package uk.co.mmscomputing.imageio.pdf;
import java.io.*;
import java.util.*;
import java.awt.image.*;
public class PDFPage extends PDFDictionary{
private PDFBody body;
private PDFDocument.PDFPages parent;
private PDFIndirectReference ref;
private PDFArray contents;
public PDFPage(PDFBody body, PDFDocument.PDFPages parent){
this.body = body;
this.parent = parent;
this.ref = body.getIndirectReference(this);
this.contents = null;
put("Type",new PDFObject.PDFName("Page"));
setMediaBox(0,0,613,793);
put("Parent",parent.getReference());
}
public PDFIndirectReference getReference(){return ref;}
public PDFDocument.PDFPages getParent(){return parent;}
// All pages from <parent> will inherit: MediaBox, CropBox, Resources and Rotate !
public void setMediaBox(int x,int y,int width,int height){
PDFArray mediaBox;
mediaBox = new PDFArray();
mediaBox.add(new PDFObject.PDFInteger(x)); // lower-left (x,y)
mediaBox.add(new PDFObject.PDFInteger(y));
mediaBox.add(new PDFObject.PDFInteger(x+width/*-1*/)); // upper-right (x,y)
mediaBox.add(new PDFObject.PDFInteger(y+height/*-1*/));
put("MediaBox",mediaBox);
}
public void addResource(String name,PDFObject object){
PDFDictionary resources=(PDFDictionary)get("Resources");
if(resources==null){
resources=new PDFDictionary();
put("Resources",resources);
}
resources.put(name,object);
}
public void addResource(String name,PDFIndirectObject object){
PDFDictionary resources=(PDFDictionary)get("Resources");
if(resources==null){
resources=new PDFDictionary();
put("Resources",resources);
}
resources.put(name,new PDFIndirectReference(object));
}
public boolean haveResource(String name){
PDFDictionary resources=(PDFDictionary)get("Resources");
if(resources==null){ return false;}
return resources.get(name)!=null;
}
// "If contents is absent, the page is empty" [1] p.53
public void setContents(PDFIndirectObject content){
if(contents==null){
contents = new PDFArray();
put("Contents",contents);
}
contents.add(content);
}
public void setCropBox(int x,int y,int width,int height){
PDFArray cropBox;
cropBox = new PDFArray();
cropBox.add(new PDFObject.PDFInteger(x)); // lower-left (x,y)
cropBox.add(new PDFObject.PDFInteger(y));
cropBox.add(new PDFObject.PDFInteger(x+width/*-1*/)); // upper-right (x,y)
cropBox.add(new PDFObject.PDFInteger(y+height/*-1*/));
put("CropBox",cropBox);
}
public void addDefaultFont(){
PDFIndirectReference defaultFont = body.getDefaultFont();
PDFDictionary font = new PDFDictionary();
font.put("defaultFont",defaultFont);
addResource("Font",font);
}
public void addPostScript(byte[] data){
if(!haveResource("Font")){addDefaultFont();}
PDFStream stream = new PDFStream();
PDFIndirectObject obj = body.getIndirectObject(stream);
stream.setInputStream(new ByteArrayInputStream(data));
setContents(obj);
}
public void addText(int x,int y, int size, String text){
String data="BT\n";
data+="/defaultFont "+size+" Tf\n";
data+=""+x+" "+y+" Td("+text+") Tj\n";
data+="ET";
addPostScript(data.getBytes());
}
public void addImage(String name, BufferedImage image)throws IOException{
PDFIndirectObject obj;
PDFDictionary resources=(PDFDictionary)get("Resources");
if(resources==null){
resources=new PDFDictionary();
put("Resources",resources);
}
PDFArray procset = new PDFArray();
procset.add(new PDFObject.PDFName("PDF"));
procset.add(new PDFObject.PDFName("Text"));
procset.add(new PDFObject.PDFName("ImageB"));
procset.add(new PDFObject.PDFName("ImageC"));
obj = body.getIndirectObject(procset);
resources.put("ProcSet",new PDFIndirectReference(obj));
PDFDictionary xobject=(PDFDictionary)resources.get("XObject");
if(xobject==null){
xobject=new PDFDictionary();
resources.put("XObject",xobject);
}
int width = image.getWidth();
int height = image.getHeight();
setMediaBox(0,0,width,height);
PDFImage pdfimage = new PDFImage(name, image);
obj = body.getIndirectObject(pdfimage);
xobject.put(name,new PDFIndirectReference(obj));
PDFStream stream = new PDFStream();
obj = body.getIndirectObject(stream);
/*
Images are only 1 by 1 pixels in user space.
CTM is transformation matrix from user space to device space.
We need to scale the image to its original width and height
*/
String data="q\n"; // q : save current graphics state
// cm: concat CTM with following matrix
data +=Integer.toString(width)+" 0 0 "+Integer.toString(height)+" 0 0 cm\n";
data +="/"+name+" Do\n"; // paint image with name: /name
// data +=Double.toString(1.0/width)+" 0 0 "+Double.toString(1.0/height)+" 0 0 cm\n";
data +="Q\n"; // Q : restore the graphics state to the last saved state
stream.setInputStream(new ByteArrayInputStream(data.getBytes()));
setContents(obj);
}
}
/*
[1] Portable Document Format Reference Manual
ISBN 0-201-62628-4
1996
*/