import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/* font support based on work by Takayuki Takeuchi */
/**
- * class representing a PDF document.
+ * Class representing a PDF document.
*
* The document is built up by calling various methods and then finally
* output to given filehandle using output method.
/** Integer constant to represent PDF 1.4 */
public static final int PDF_VERSION_1_4 = 4;
- /**
- * the encoding to use when converting strings to PDF commandos.
- */
+ /** the encoding to use when converting strings to PDF commands */
public static final String ENCODING = "ISO-8859-1";
+ /** the counter for object numbering */
+ protected int objectcount = 0;
+
+ /** the logger instance */
private Log log = LogFactory.getLog("org.apache.fop.pdf");
- /**
- * the current character position
- */
- protected int position = 0;
+ /** the current character position */
+ private int position = 0;
- /**
- * the character position of each object
- */
- protected List location = new java.util.ArrayList();
-
- /** List of objects to write in the trailer */
- private List trailerObjects = new java.util.ArrayList();
+ /** character position of xref table */
+ private int xref;
- /**
- * the counter for object numbering
- */
- protected int objectcount = 0;
+ /** the character position of each object */
+ private List location = new ArrayList();
- /**
- * the objects themselves
- */
- protected List objects = new java.util.LinkedList();
+ /** List of objects to write in the trailer */
+ private List trailerObjects = new ArrayList();
- /**
- * character position of xref table
- */
- protected int xref;
+ /** the objects themselves */
+ private List objects = new LinkedList();
/** Indicates what PDF version is active */
- protected int pdfVersion = PDF_VERSION_1_4;
+ private int pdfVersion = PDF_VERSION_1_4;
- /**
- * Indicates which PDF profiles are active (PDF/A, PDF/X etc.)
- */
- protected PDFProfile pdfProfile = new PDFProfile(this);
+ /** Indicates which PDF profiles are active (PDF/A, PDF/X etc.) */
+ private PDFProfile pdfProfile = new PDFProfile(this);
- /**
- * the /Root object
- */
- protected PDFRoot root;
+ /** the /Root object */
+ private PDFRoot root;
/** The root outline object */
private PDFOutline outlineRoot = null;
/** The /Pages object (mark-fop@inomial.com) */
private PDFPages pages;
- /**
- * the /Info object
- */
- protected PDFInfo info;
+ /** the /Info object */
+ private PDFInfo info;
- /**
- * the /Resources object
- */
- protected PDFResources resources;
+ /** the /Resources object */
+ private PDFResources resources;
- /**
- * the documents encryption, if exists
- */
- protected PDFEncryption encryption;
+ /** the document's encryption, if it exists */
+ private PDFEncryption encryption;
- /**
- * the colorspace (0=RGB, 1=CMYK)
- */
- protected PDFDeviceColorSpace colorspace =
+ /** the colorspace (0=RGB, 1=CMYK) */
+ private PDFDeviceColorSpace colorspace =
new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB);
- /**
- * the counter for Pattern name numbering (e.g. 'Pattern1')
- */
- protected int patternCount = 0;
+ /** the counter for Pattern name numbering (e.g. 'Pattern1') */
+ private int patternCount = 0;
- /**
- * the counter for Shading name numbering
- */
- protected int shadingCount = 0;
+ /** the counter for Shading name numbering */
+ private int shadingCount = 0;
- /**
- * the counter for XObject numbering
- */
- protected int xObjectCount = 0;
+ /** the counter for XObject numbering */
+ private int xObjectCount = 0;
- /**
- * the XObjects Map.
- * Should be modified (works only for image subtype)
- */
- protected Map xObjectsMap = new java.util.HashMap();
+ /** the {@link PDFXObject}s map */
+ /* TODO: Should be modified (works only for image subtype) */
+ private Map xObjectsMap = new HashMap();
- /**
- * the Font Map.
- */
- protected Map fontMap = new java.util.HashMap();
+ /** The {@link PDFFont} map */
+ private Map fontMap = new HashMap();
- /**
- * The filter map.
- */
- protected Map filterMap = new java.util.HashMap();
+ /** The {@link PDFFilter} map */
+ private Map filterMap = new HashMap();
- /**
- * List of PDFGState objects.
- */
- protected List gstates = new java.util.ArrayList();
+ /** List of {@link PDFGState}s. */
+ private List gstates = new ArrayList();
- /**
- * List of functions.
- */
- protected List functions = new java.util.ArrayList();
+ /** List of {@link PDFFunction}s. */
+ private List functions = new ArrayList();
- /**
- * List of shadings.
- */
- protected List shadings = new java.util.ArrayList();
+ /** List of {@link PDFShading}s. */
+ private List shadings = new ArrayList();
- /**
- * List of patterns.
- */
- protected List patterns = new java.util.ArrayList();
+ /** List of {@link PDFPattern}s. */
+ private List patterns = new ArrayList();
- /**
- * List of Links.
- */
- protected List links = new java.util.ArrayList();
+ /** List of {@link PDFLink}s. */
+ private List links = new ArrayList();
- /**
- * List of Destinations.
- */
- protected List destinations;
+ /** List of {@link PDFDestination}s. */
+ private List destinations;
- /**
- * List of FileSpecs.
- */
- protected List filespecs = new java.util.ArrayList();
+ /** List of {@link PDFFileSpec}s. */
+ private List filespecs = new ArrayList();
- /**
- * List of GoToRemotes.
- */
- protected List gotoremotes = new java.util.ArrayList();
+ /** List of {@link PDFGoToRemote}s. */
+ private List gotoremotes = new ArrayList();
- /**
- * List of GoTos.
- */
- protected List gotos = new java.util.ArrayList();
+ /** List of {@link PDFGoTo}s. */
+ private List gotos = new ArrayList();
- /**
- * List of PDFLaunch objects.
- */
- protected List launches = new java.util.ArrayList();
+ /** List of {@link PDFLaunch}es. */
+ private List launches = new ArrayList();
/**
* The PDFDests object for the name dictionary.
this.pages = getFactory().makePages();
// Create the Root object
- this.root = getFactory().makeRoot(pages);
+ this.root = getFactory().makeRoot(this.pages);
// Create the Resources object
this.resources = getFactory().makeResources();
}
/**
- * @return the integer representing the active PDF version (one of PDFDocument.PDF_VERSION_*)
+ * @return the integer representing the active PDF version
+ * (one of PDFDocument.PDF_VERSION_*)
*/
public int getPDFVersion() {
return this.pdfVersion;
/**
* Returns the factory for PDF objects.
- * @return PDFFactory the factory
+ *
+ * @return the {@link PDFFactory} object
*/
public PDFFactory getFactory() {
return this.factory;
* Indicates whether stream encoding on-the-fly is enabled. If enabled
* stream can be serialized without the need for a buffer to merely
* calculate the stream length.
- * @return boolean true if on-the-fly encoding is enabled
+ *
+ * @return <code>true</code> if on-the-fly encoding is enabled
*/
public boolean isEncodingOnTheFly() {
return this.encodingOnTheFly;
/**
* Converts text to a byte array for writing to a PDF file.
+ *
* @param text text to convert/encode
- * @return byte[] the resulting byte array
+ * @return the resulting <code>byte</code> array
*/
public static byte[] encode(String text) {
try {
* buffered to reduce the number of calls to the encoding converter so don't forget
* to <code>flush()</code> the Writer after use or before writing directly to the
* underlying OutputStream.
+ *
* @param out the OutputStream to write to
* @return the requested Writer
*/
}
/**
- * set the producer of the document
+ * Sets the producer of the document.
*
* @param producer string indicating application producing the PDF
*/
}
/**
- * Set the creation date of the document.
+ * Sets the creation date of the document.
*
* @param date Date to be stored as creation date in the PDF.
*/
public void setCreationDate(Date date) {
- info.setCreationDate(date);
+ this.info.setCreationDate(date);
}
/**
- * Set the creator of the document.
+ * Sets the creator of the document.
*
* @param creator string indicating application creating the document
*/
}
/**
- * Set the filter map to use for filters in this document.
+ * Sets the filter map to use for filters in this document.
*
* @param map the map of filter lists for each stream type
*/
}
/**
- * Get the filter map used for filters in this document.
+ * Returns the {@link PDFFilter}s map used for filters in this document.
*
* @return the map of filters being used
*/
}
/**
- * Returns the PDFPages object associated with the root object.
- * @return the PDFPages object
+ * Returns the {@link PDFPages} object associated with the root object.
+ *
+ * @return the {@link PDFPages} object
*/
public PDFPages getPages() {
return this.pages;
}
/**
- * Get the PDF root object.
+ * Get the {@link PDFRoot} object for this document.
*
- * @return the PDFRoot object
+ * @return the {@link PDFRoot} object
*/
public PDFRoot getRoot() {
return this.root;
}
/**
- * Get the pdf info object for this document.
+ * Get the {@link PDFInfo} object for this document.
*
- * @return the PDF Info object for this document
+ * @return the {@link PDFInfo} object
*/
public PDFInfo getInfo() {
- return info;
+ return this.info;
}
/**
- * Registers a PDFObject in this PDF document. The PDF is assigned a new
- * object number.
- * @param obj PDFObject to add
- * @return PDFObject the PDFObject added (its object number set)
+ * Registers a {@link PDFObject} in this PDF document.
+ * The object is assigned a new object number.
+ *
+ * @param obj {@link PDFObject} to add
+ * @return the added {@link PDFObject} added (with its object number set)
*/
public PDFObject registerObject(PDFObject obj) {
assignObjectNumber(obj);
}
/**
- * Assigns the PDFObject a object number and sets the parent of the
- * PDFObject to this PDFDocument.
- * @param obj PDFObject to assign a number to
+ * Assigns the {@link PDFObject} an object number,
+ * and sets the parent of the {@link PDFObject} to this document.
+ *
+ * @param obj {@link PDFObject} to assign a number to
*/
public void assignObjectNumber(PDFObject obj) {
if (obj == null) {
}
/**
- * Adds an PDFObject to this document. The object must have a object number
- * assigned.
- * @param obj PDFObject to add
+ * Adds a {@link PDFObject} to this document.
+ * The object <em>MUST</em> have an object number assigned.
+ *
+ * @param obj {@link PDFObject} to add
*/
public void addObject(PDFObject obj) {
if (obj == null) {
/**
* Apply the encryption filter to a PDFStream if encryption is enabled.
+ *
* @param stream PDFStream to encrypt
*/
public void applyEncryption(AbstractPDFStream stream) {
/**
* Enables PDF encryption.
+ *
* @param params The encryption parameters for the pdf file
*/
public void setEncryption(PDFEncryptionParams params) {
getProfile().verifyEncryptionAllowed();
this.encryption = PDFEncryptionManager.newInstance(++this.objectcount, params);
- if (encryption != null) {
- PDFObject pdfObject = (PDFObject)encryption;
+ if (this.encryption != null) {
+ PDFObject pdfObject = (PDFObject)this.encryption;
pdfObject.setDocument(this);
addTrailerObject(pdfObject);
} else {
/**
* Indicates whether encryption is active for this PDF or not.
+ *
* @return boolean True if encryption is active
*/
public boolean isEncryptionActive() {
/**
* Returns the active Encryption object.
+ *
* @return the Encryption object
*/
public PDFEncryption getEncryption() {
- return encryption;
+ return this.encryption;
}
private Object findPDFObject(List list, PDFObject compare) {
/**
* Looks through the registered functions to see if one that is equal to
* a reference object exists
+ *
* @param compare reference object
* @return the function if it was found, null otherwise
*/
protected PDFFunction findFunction(PDFFunction compare) {
- return (PDFFunction)findPDFObject(functions, compare);
+ return (PDFFunction)findPDFObject(this.functions, compare);
}
/**
* Looks through the registered shadings to see if one that is equal to
* a reference object exists
+ *
* @param compare reference object
* @return the shading if it was found, null otherwise
*/
protected PDFShading findShading(PDFShading compare) {
- return (PDFShading)findPDFObject(shadings, compare);
+ return (PDFShading)findPDFObject(this.shadings, compare);
}
/**
* The problem with this is for tiling patterns the pattern
* data stream is stored and may use up memory, usually this
* would only be a small amount of data.
+ *
* @param compare reference object
* @return the shading if it was found, null otherwise
*/
protected PDFPattern findPattern(PDFPattern compare) {
- return (PDFPattern)findPDFObject(patterns, compare);
+ return (PDFPattern)findPDFObject(this.patterns, compare);
}
/**
* Finds a font.
+ *
* @param fontname name of the font
* @return PDFFont the requested font, null if it wasn't found
*/
protected PDFFont findFont(String fontname) {
- return (PDFFont)fontMap.get(fontname);
+ return (PDFFont)this.fontMap.get(fontname);
}
/**
* Finds a named destination.
+ *
* @param compare reference object to use as search template
* @return the link if found, null otherwise
*/
/**
* Finds a link.
+ *
* @param compare reference object to use as search template
* @return the link if found, null otherwise
*/
protected PDFLink findLink(PDFLink compare) {
- return (PDFLink)findPDFObject(links, compare);
+ return (PDFLink)findPDFObject(this.links, compare);
}
/**
* Finds a file spec.
+ *
* @param compare reference object to use as search template
* @return the file spec if found, null otherwise
*/
protected PDFFileSpec findFileSpec(PDFFileSpec compare) {
- return (PDFFileSpec)findPDFObject(filespecs, compare);
+ return (PDFFileSpec)findPDFObject(this.filespecs, compare);
}
/**
* Finds a goto remote.
+ *
* @param compare reference object to use as search template
* @return the goto remote if found, null otherwise
*/
protected PDFGoToRemote findGoToRemote(PDFGoToRemote compare) {
- return (PDFGoToRemote)findPDFObject(gotoremotes, compare);
+ return (PDFGoToRemote)findPDFObject(this.gotoremotes, compare);
}
/**
* Finds a goto.
+ *
* @param compare reference object to use as search template
* @return the goto if found, null otherwise
*/
protected PDFGoTo findGoTo(PDFGoTo compare) {
- return (PDFGoTo)findPDFObject(gotos, compare);
+ return (PDFGoTo)findPDFObject(this.gotos, compare);
}
/**
* Finds a launch.
+ *
* @param compare reference object to use as search template
* @return the launch if found, null otherwise
*/
protected PDFLaunch findLaunch(PDFLaunch compare) {
- return (PDFLaunch) findPDFObject(launches, compare);
+ return (PDFLaunch) findPDFObject(this.launches, compare);
+ }
+
+ /**
+ * Finds a uri.
+ *
+ * @param compare reference object to use as search template
+ * @return the launch if found, null otherwise
+ */
+ protected PDFUri findURI(PDFUri compare) {
+ return (PDFUri) findPDFObject(this.uris, compare);
}
/**
* Looks for an existing GState to use
+ *
* @param wanted requested features
* @param current currently active features
- * @return PDFGState the GState if found, null otherwise
+ * @return the GState if found, null otherwise
*/
protected PDFGState findGState(PDFGState wanted, PDFGState current) {
PDFGState poss;
- Iterator iter = gstates.iterator();
+ Iterator iter = this.gstates.iterator();
while (iter.hasNext()) {
PDFGState avail = (PDFGState)iter.next();
poss = new PDFGState();
}
/**
- * Get the PDF color space object.
+ * Returns the PDF color space object.
*
* @return the color space
*/
}
/**
- * Get the color space.
+ * Returns the color space.
*
* @return the color space
*/
}
/**
- * Get the font map for this document.
+ * Returns the font map for this document.
*
* @return the map of fonts used in this document
*/
public Map getFontMap() {
- return fontMap;
+ return this.fontMap;
}
/**
protected InputStream resolveURI(String uri)
throws java.io.FileNotFoundException {
try {
- /**@todo Temporary hack to compile, improve later */
+ /* TODO: Temporary hack to compile, improve later */
return new java.net.URL(uri).openStream();
} catch (Exception e) {
throw new java.io.FileNotFoundException(
* @deprecated Use getXObject instead (so forms are treated in the same way)
*/
public PDFImageXObject getImage(String key) {
- PDFImageXObject xObject = (PDFImageXObject)xObjectsMap.get(key);
- return xObject;
+ return (PDFImageXObject)this.xObjectsMap.get(key);
}
/**
* @return the PDFXObject for the key if found
*/
public PDFXObject getXObject(String key) {
- PDFXObject xObject = (PDFXObject)xObjectsMap.get(key);
- return xObject;
+ return (PDFXObject)this.xObjectsMap.get(key);
}
/**
* @return the PDFDests object (which represents the /Dests entry).
*/
public PDFDests getDests() {
- return dests;
+ return this.dests;
}
/**
*/
public void addDestination(PDFDestination destination) {
if (this.destinations == null) {
- this.destinations = new java.util.ArrayList();
+ this.destinations = new ArrayList();
}
this.destinations.add(destination);
}
*/
public List getDestinationList() {
if (hasDestinations()) {
- return destinations;
+ return this.destinations;
} else {
return Collections.EMPTY_LIST;
}
* Add an image to the PDF document.
* This adds an image to the PDF objects.
* If an image with the same key already exists it will return the
- * old PDFXObject.
+ * old {@link PDFXObject}.
*
* @param res the PDF resource context to add to, may be null
* @param img the PDF image to add
public PDFImageXObject addImage(PDFResourceContext res, PDFImage img) {
// check if already created
String key = img.getKey();
- PDFImageXObject xObject = (PDFImageXObject)xObjectsMap.get(key);
+ PDFImageXObject xObject = (PDFImageXObject)this.xObjectsMap.get(key);
if (xObject != null) {
if (res != null) {
res.getPDFResources().addXObject(xObject);
* Add a form XObject to the PDF document.
* This adds a Form XObject to the PDF objects.
* If a Form XObject with the same key already exists it will return the
- * old PDFFormXObject.
+ * old {@link PDFFormXObject}.
*
* @param res the PDF resource context to add to, may be null
* @param cont the PDF Stream contents of the Form XObject
* @return the PDF Outline root object
*/
public PDFOutline getOutlineRoot() {
- if (outlineRoot != null) {
- return outlineRoot;
+ if (this.outlineRoot != null) {
+ return this.outlineRoot;
}
- outlineRoot = new PDFOutline(null, null, true);
- assignObjectNumber(outlineRoot);
- addTrailerObject(outlineRoot);
- root.setRootOutline(outlineRoot);
- return outlineRoot;
+ this.outlineRoot = new PDFOutline(null, null, true);
+ assignObjectNumber(this.outlineRoot);
+ addTrailerObject(this.outlineRoot);
+ this.root.setRootOutline(this.outlineRoot);
+ return this.outlineRoot;
}
/**
- * get the /Resources object for the document
+ * Get the /Resources object for the document
*
* @return the /Resources object
*/
/**
* Ensure there is room in the locations xref for the number of
* objects that have been created.
+ * @param objidx the object's index
+ * @param position the position
*/
private void setLocation(int objidx, int position) {
- while (location.size() <= objidx) {
- location.add(LOCATION_PLACEHOLDER);
+ while (this.location.size() <= objidx) {
+ this.location.add(LOCATION_PLACEHOLDER);
}
- location.set(objidx, new Integer(position));
+ this.location.set(objidx, new Integer(position));
}
/**
- * write the entire document out
+ * Writes out the entire document
*
* @param stream the OutputStream to output the document to
* @throws IOException if there is an exception writing to the output stream
}
/**
- * write the trailer
+ * Write the trailer
*
* @param stream the OutputStream to write the trailer to
* @throws IOException if there is an exception writing to the output stream
*/
public void outputTrailer(OutputStream stream) throws IOException {
if (hasDestinations()) {
- Collections.sort(destinations, new DestinationComparator());
- dests = getFactory().makeDests(destinations);
+ Collections.sort(this.destinations, new DestinationComparator());
+ this.dests = getFactory().makeDests(this.destinations);
if (this.root.getNames() == null) {
this.root.setNames(getFactory().makeNames());
}
this.root.getNames().setDests(dests);
}
output(stream);
- for (int count = 0; count < trailerObjects.size(); count++) {
- PDFObject o = (PDFObject)trailerObjects.get(count);
+ for (int count = 0; count < this.trailerObjects.size(); count++) {
+ PDFObject o = (PDFObject)this.trailerObjects.get(count);
this.location.set(
o.getObjectNumber() - 1,
new Integer(this.position));
this.position += outputXref(stream);
/* construct the trailer */
- String pdf =
- "trailer\n"
- + "<<\n"
- + "/Size "
- + (this.objectcount + 1)
- + "\n"
- + "/Root "
- + this.root.referencePDF()
- + "\n"
- + "/Info "
- + this.info.referencePDF()
- + "\n";
- if (this.encryption != null) {
- pdf += this.encryption.getTrailerEntry();
+ StringBuffer pdf = new StringBuffer(128);
+ pdf.append("trailer\n<<\n/Size ")
+ .append(this.objectcount + 1)
+ .append("\n/Root ")
+ .append(this.root.referencePDF())
+ .append("\n/Info ")
+ .append(this.info.referencePDF())
+ .append('\n');
+
+ if (this.isEncryptionActive()) {
+ pdf.append(this.encryption.getTrailerEntry());
} else {
- pdf += getIDEntry();
+ pdf.append(this.getIDEntry());
}
- pdf += "\n"
- + ">>\n"
- + "startxref\n"
- + this.xref
- + "\n"
- + "%%EOF\n";
+
+ pdf.append("\n>>\nstartxref\n")
+ .append(this.xref)
+ .append("\n%%EOF\n");
/* write the trailer */
- stream.write(encode(pdf));
+ stream.write(encode(pdf.toString()));
}
/**
- * write the xref table
+ * Write the xref table
*
* @param stream the OutputStream to write the xref table to
* @return the number of characters written
+ * @throws IOException in case of an error writing the result to
+ * the parameter stream
*/
private int outputXref(OutputStream stream) throws IOException {
/* construct initial part of xref */
StringBuffer pdf = new StringBuffer(128);
- pdf.append(
- "xref\n0 " + (this.objectcount + 1) + "\n0000000000 65535 f \n");
+ pdf.append("xref\n0 ");
+ pdf.append(this.objectcount + 1);
+ pdf.append("\n0000000000 65535 f \n");
+ String s, loc;
for (int count = 0; count < this.location.size(); count++) {
- String x = this.location.get(count).toString();
+ final String padding = "0000000000";
+ s = this.location.get(count).toString();
/* contruct xref entry for object */
- String padding = "0000000000";
- String loc = padding.substring(x.length()) + x;
+ loc = padding.substring(s.length()) + s;
/* append to xref table */
- pdf = pdf.append(loc + " 00000 n \n");
+ pdf = pdf.append(loc).append(" 00000 n \n");
}
/* write the xref table and return the character length */