diff options
Diffstat (limited to 'src/java/org/apache/fop/pdf')
30 files changed, 740 insertions, 345 deletions
diff --git a/src/java/org/apache/fop/pdf/ASCII85Filter.java b/src/java/org/apache/fop/pdf/ASCII85Filter.java index ef50bae93..2114ea540 100644 --- a/src/java/org/apache/fop/pdf/ASCII85Filter.java +++ b/src/java/org/apache/fop/pdf/ASCII85Filter.java @@ -52,7 +52,7 @@ public class ASCII85Filter extends PDFFilter { * * @return always null */ - public String getDecodeParms() { + public PDFObject getDecodeParms() { return null; } @@ -60,7 +60,11 @@ public class ASCII85Filter extends PDFFilter { * {@inheritDoc} */ public OutputStream applyFilter(OutputStream out) throws IOException { - return new ASCII85OutputStream(out); + if (isApplied()) { + return out; + } else { + return new ASCII85OutputStream(out); + } } } diff --git a/src/java/org/apache/fop/pdf/ASCIIHexFilter.java b/src/java/org/apache/fop/pdf/ASCIIHexFilter.java index ba5f15882..41c428998 100644 --- a/src/java/org/apache/fop/pdf/ASCIIHexFilter.java +++ b/src/java/org/apache/fop/pdf/ASCIIHexFilter.java @@ -51,7 +51,7 @@ public class ASCIIHexFilter extends PDFFilter { * * @return always null */ - public String getDecodeParms() { + public PDFObject getDecodeParms() { return null; } @@ -59,7 +59,11 @@ public class ASCIIHexFilter extends PDFFilter { * {@inheritDoc} */ public OutputStream applyFilter(OutputStream out) throws IOException { - return new ASCIIHexOutputStream(out); + if (isApplied()) { + return out; + } else { + return new ASCIIHexOutputStream(out); + } } } diff --git a/src/java/org/apache/fop/pdf/AbstractPDFStream.java b/src/java/org/apache/fop/pdf/AbstractPDFStream.java index 364b42d66..e208a3916 100644 --- a/src/java/org/apache/fop/pdf/AbstractPDFStream.java +++ b/src/java/org/apache/fop/pdf/AbstractPDFStream.java @@ -28,7 +28,7 @@ import org.apache.fop.util.CloseBlockerOutputStream; /** * This is an abstract base class for PDF streams. */ -public abstract class AbstractPDFStream extends PDFObject { +public abstract class AbstractPDFStream extends PDFDictionary { /** The filters that should be applied */ private PDFFilterList filters; @@ -64,7 +64,10 @@ public abstract class AbstractPDFStream extends PDFObject { this.filters = new PDFFilterList(); } else { this.filters = new PDFFilterList(getDocument().isEncryptionActive()); - //this.filters = new PDFFilterList(false); + } + boolean hasFilterEntries = (get("Filter") != null); + if (hasFilterEntries) { + this.filters.setDisableAllFilters(true); } } return this.filters; @@ -118,8 +121,8 @@ public abstract class AbstractPDFStream extends PDFObject { //Allocate a temporary buffer to find out the size of the encoded stream final StreamCache encodedStream = StreamCacheFactory.getInstance(). createStreamCache(getSizeHint()); - OutputStream filteredOutput = - getFilterList().applyFilters(encodedStream.getOutputStream()); + OutputStream filteredOutput + = getFilterList().applyFilters(encodedStream.getOutputStream()); outputRawStreamData(filteredOutput); filteredOutput.flush(); filteredOutput.close(); @@ -146,8 +149,7 @@ public abstract class AbstractPDFStream extends PDFObject { //Stream contents CloseBlockerOutputStream cbout = new CloseBlockerOutputStream(out); CountingOutputStream cout = new CountingOutputStream(cbout); - OutputStream filteredOutput = - getFilterList().applyFilters(cout); + OutputStream filteredOutput = getFilterList().applyFilters(cout); outputRawStreamData(filteredOutput); filteredOutput.close(); refLength.setNumber(new Integer(cout.getCount())); @@ -172,19 +174,17 @@ public abstract class AbstractPDFStream extends PDFObject { StreamCache encodedStream = null; PDFNumber refLength = null; - final String lengthEntry; + final Object lengthEntry; if (getDocument().isEncodingOnTheFly()) { refLength = new PDFNumber(); getDocumentSafely().registerObject(refLength); - lengthEntry = refLength.referencePDF(); + lengthEntry = refLength; } else { encodedStream = encodeStream(); - lengthEntry = Integer.toString(encodedStream.getSize() + 1); + lengthEntry = new Integer(encodedStream.getSize() + 1); } - String filterEntry = getFilterList().buildFilterDictEntries(); byte[] p = encode(buildStreamDict(lengthEntry)); - stream.write(p); length += p.length; @@ -209,12 +209,23 @@ public abstract class AbstractPDFStream extends PDFObject { * @param lengthEntry value for the /Length entry * @return the newly constructed dictionary */ - protected String buildStreamDict(String lengthEntry) { - final String filterEntry = getFilterList().buildFilterDictEntries(); - return (getObjectID() - + "<< /Length " + lengthEntry + "\n" - + filterEntry - + "\n>>\n"); + protected String buildStreamDict(Object lengthEntry) { + StringBuffer sb = new StringBuffer(); + sb.append(getObjectID()); + populateStreamDict(lengthEntry); + + writeDictionary(sb); + return sb.toString(); + } + + /** + * Populates the dictionary with all necessary entries for the stream. + * Override this method if you need additional entries. + * @param lengthEntry value for the /Length entry + */ + protected void populateStreamDict(Object lengthEntry) { + put("Length", lengthEntry); + getFilterList().putFilterDictEntries(this); } /** diff --git a/src/java/org/apache/fop/pdf/BitmapImage.java b/src/java/org/apache/fop/pdf/BitmapImage.java index e855dc61a..461ec0a64 100644 --- a/src/java/org/apache/fop/pdf/BitmapImage.java +++ b/src/java/org/apache/fop/pdf/BitmapImage.java @@ -21,7 +21,6 @@ package org.apache.fop.pdf; import java.io.IOException; import java.io.OutputStream; -//import java.util.Map; /** * Bitmap image. @@ -34,7 +33,7 @@ public class BitmapImage implements PDFImage { private int bitsPerPixel; private PDFDeviceColorSpace colorSpace; private byte[] bitmaps; - private String maskRef; + private PDFReference maskRef; private PDFColor transparent = null; private String key; private PDFDocument pdfDoc; @@ -47,7 +46,7 @@ public class BitmapImage implements PDFImage { * @param width the width of the image * @param height the height of the image * @param data the bitmap data - * @param mask the transparancy mask reference if any + * @param mask the transparency mask reference if any */ public BitmapImage(String k, int width, int height, byte[] data, String mask) { @@ -57,7 +56,7 @@ public class BitmapImage implements PDFImage { this.bitsPerPixel = 8; this.colorSpace = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB); this.bitmaps = data; - maskRef = mask; + maskRef = new PDFReference(mask); } /** @@ -170,6 +169,11 @@ public class BitmapImage implements PDFImage { * @return the soft mask reference if any */ public String getSoftMask() { + return maskRef.toInlinePDFString(); + } + + /** {@inheritDoc} */ + public PDFReference getSoftMaskReference() { return maskRef; } diff --git a/src/java/org/apache/fop/pdf/CCFFilter.java b/src/java/org/apache/fop/pdf/CCFFilter.java index 98d23d25e..03561629c 100644 --- a/src/java/org/apache/fop/pdf/CCFFilter.java +++ b/src/java/org/apache/fop/pdf/CCFFilter.java @@ -28,7 +28,7 @@ package org.apache.fop.pdf; */ public class CCFFilter extends NullFilter { - private String decodeParms; + private PDFObject decodeParms; /** * {@inheritDoc} @@ -40,7 +40,7 @@ public class CCFFilter extends NullFilter { /** * {@inheritDoc} */ - public String getDecodeParms() { + public PDFObject getDecodeParms() { return this.decodeParms; } @@ -48,7 +48,7 @@ public class CCFFilter extends NullFilter { * Sets the CCF decoding parameters * @param decodeParms The decoding parameters */ - public void setDecodeParms(String decodeParms) { + public void setDecodeParms(PDFObject decodeParms) { this.decodeParms = decodeParms; } diff --git a/src/java/org/apache/fop/pdf/DCTFilter.java b/src/java/org/apache/fop/pdf/DCTFilter.java index 08eca9738..92809d927 100644 --- a/src/java/org/apache/fop/pdf/DCTFilter.java +++ b/src/java/org/apache/fop/pdf/DCTFilter.java @@ -41,7 +41,7 @@ public class DCTFilter extends NullFilter { * Get the decode params for this filter. * @return the DCT filter has no decode params */ - public String getDecodeParms() { + public PDFObject getDecodeParms() { return null; } diff --git a/src/java/org/apache/fop/pdf/FlateFilter.java b/src/java/org/apache/fop/pdf/FlateFilter.java index 83eb1ac08..d7dc81d1f 100644 --- a/src/java/org/apache/fop/pdf/FlateFilter.java +++ b/src/java/org/apache/fop/pdf/FlateFilter.java @@ -94,22 +94,20 @@ public class FlateFilter extends PDFFilter { * * @return a string containing the decode params for this filter */ - public String getDecodeParms() { + public PDFObject getDecodeParms() { if (predictor > PREDICTION_NONE) { - StringBuffer sb = new StringBuffer(); - sb.append("<< /Predictor "); - sb.append(predictor); + PDFDictionary dict = new PDFDictionary(); + dict.put("Predictor", predictor); if (colors > 0) { - sb.append(" /Colors " + colors); + dict.put("Colors", colors); } if (bitsPerComponent > 0) { - sb.append(" /BitsPerComponent " + bitsPerComponent); + dict.put("BitsPerComponent", bitsPerComponent); } if (columns > 0) { - sb.append(" /Columns " + columns); + dict.put("Columns", columns); } - sb.append(" >> "); - return sb.toString(); + return dict; } return null; } @@ -210,11 +208,13 @@ public class FlateFilter extends PDFFilter { } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public OutputStream applyFilter(OutputStream out) throws IOException { - return new FlateEncodeOutputStream(out); + if (isApplied()) { + return out; + } else { + return new FlateEncodeOutputStream(out); + } } } diff --git a/src/java/org/apache/fop/pdf/NullFilter.java b/src/java/org/apache/fop/pdf/NullFilter.java index 7c7f54b68..6f2e7f069 100644 --- a/src/java/org/apache/fop/pdf/NullFilter.java +++ b/src/java/org/apache/fop/pdf/NullFilter.java @@ -38,7 +38,7 @@ public class NullFilter extends PDFFilter { /** * {@inheritDoc} */ - public String getDecodeParms() { + public PDFObject getDecodeParms() { return null; } diff --git a/src/java/org/apache/fop/pdf/PDFArray.java b/src/java/org/apache/fop/pdf/PDFArray.java index 1140363ec..2dd68ad8b 100644 --- a/src/java/org/apache/fop/pdf/PDFArray.java +++ b/src/java/org/apache/fop/pdf/PDFArray.java @@ -97,6 +97,15 @@ public class PDFArray extends PDFObject { } /** + * Sets an entry at a given location. + * @param index the index of the value to set + * @param value the new value + */ + public void set(int index, double value) { + this.values.set(index, new Double(value)); + } + + /** * Gets an entry at a given location. * @param index the index of the value to set * @return the requested value @@ -114,6 +123,14 @@ public class PDFArray extends PDFObject { } /** + * Adds a new value to the array. + * @param value the value + */ + public void add(double value) { + this.values.add(new Double(value)); + } + + /** * {@inheritDoc} */ public String toPDFString() { diff --git a/src/java/org/apache/fop/pdf/PDFDictionary.java b/src/java/org/apache/fop/pdf/PDFDictionary.java index 73878bdc6..71393cace 100644 --- a/src/java/org/apache/fop/pdf/PDFDictionary.java +++ b/src/java/org/apache/fop/pdf/PDFDictionary.java @@ -60,6 +60,18 @@ public class PDFDictionary extends PDFObject { } /** + * Puts a new name/value pair. + * @param name the name + * @param value the value + */ + public void put(String name, int value) { + if (!entries.containsKey(name)) { + this.order.add(name); + } + this.entries.put(name, new Integer(value)); + } + + /** * Returns the value given a name. * @param name the name of the value * @return the value or null, if there's no value with the given name. @@ -76,21 +88,29 @@ public class PDFDictionary extends PDFObject { if (hasObjectNumber()) { p.append(getObjectID()); } - p.append("<<"); + writeDictionary(p); + if (hasObjectNumber()) { + p.append("endobj\n"); + } + return p.toString(); + } + + /** + * Writes the contents of the dictionary to a StringBuffer. + * @param sb the target StringBuffer + */ + protected void writeDictionary(StringBuffer sb) { + sb.append("<<"); Iterator iter = this.order.iterator(); while (iter.hasNext()) { String key = (String)iter.next(); - p.append("\n /"); - p.append(key); - p.append(" "); + sb.append("\n /"); + sb.append(key); + sb.append(" "); Object obj = this.entries.get(key); - formatObject(obj, p); + formatObject(obj, sb); } - p.append("\n>>\n"); - if (hasObjectNumber()) { - p.append("endobj\n"); - } - return p.toString(); + sb.append("\n>>\n"); } } diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java index 748c6b3a8..045d52173 100644 --- a/src/java/org/apache/fop/pdf/PDFDocument.java +++ b/src/java/org/apache/fop/pdf/PDFDocument.java @@ -721,8 +721,20 @@ public class PDFDocument { * * @param key the image key to look for * @return the image or PDFXObject for the key if found + * @deprecated Use getXObject instead (so forms are treated in the same way) */ - public PDFXObject getImage(String key) { + public PDFImageXObject getImage(String key) { + PDFImageXObject xObject = (PDFImageXObject)xObjectsMap.get(key); + return xObject; + } + + /** + * Get an XObject from the image map. + * + * @param key the XObject key to look for + * @return the PDFXObject for the key if found + */ + public PDFXObject getXObject(String key) { PDFXObject xObject = (PDFXObject)xObjectsMap.get(key); return xObject; } @@ -779,10 +791,10 @@ public class PDFDocument { * @param img the PDF image to add * @return the PDF XObject that references the PDF image data */ - public PDFXObject addImage(PDFResourceContext res, PDFImage img) { + public PDFImageXObject addImage(PDFResourceContext res, PDFImage img) { // check if already created String key = img.getKey(); - PDFXObject xObject = (PDFXObject)xObjectsMap.get(key); + PDFImageXObject xObject = (PDFImageXObject)xObjectsMap.get(key); if (xObject != null) { if (res != null) { res.getPDFResources().addXObject(xObject); @@ -793,7 +805,7 @@ public class PDFDocument { // setup image img.setup(this); // create a new XObject - xObject = new PDFXObject(++this.xObjectCount, img); + xObject = new PDFImageXObject(++this.xObjectCount, img); registerObject(xObject); this.resources.addXObject(xObject); if (res != null) { @@ -811,26 +823,35 @@ public class PDFDocument { * * @param res the PDF resource context to add to, may be null * @param cont the PDF Stream contents of the Form XObject - * @param formres the PDF Resources for the Form XObject data + * @param formres a reference to the PDF Resources for the Form XObject data * @param key the key for the object * @return the PDF Form XObject that references the PDF data */ public PDFFormXObject addFormXObject( PDFResourceContext res, PDFStream cont, - PDFResources formres, + PDFReference formres, String key) { - PDFFormXObject xObject; - xObject = - new PDFFormXObject( + + // check if already created + PDFFormXObject xObject = (PDFFormXObject)xObjectsMap.get(key); + if (xObject != null) { + if (res != null) { + res.getPDFResources().addXObject(xObject); + } + return xObject; + } + + xObject = new PDFFormXObject( ++this.xObjectCount, cont, - formres.referencePDF()); + formres); registerObject(xObject); this.resources.addXObject(xObject); if (res != null) { res.getPDFResources().addXObject(xObject); } + this.xObjectsMap.put(key, xObject); return xObject; } diff --git a/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java b/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java index 099948864..203ca90e1 100644 --- a/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java +++ b/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java @@ -75,7 +75,7 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption { * Return a parameter dictionary for this filter, or null * @return The parameter dictionary. In this case, null. */ - public String getDecodeParms() { + public PDFObject getDecodeParms() { return null; } diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index d1e81647a..f2fe97139 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -1471,7 +1471,7 @@ public class PDFFactory { /** * Create a PDFICCStream - * @see PDFXObject + * @see PDFImageXObject * @see org.apache.fop.image.JpegImage * @see org.apache.fop.pdf.PDFDeviceColorSpace * @return the new PDF ICC stream object diff --git a/src/java/org/apache/fop/pdf/PDFFilter.java b/src/java/org/apache/fop/pdf/PDFFilter.java index 82efc4c46..ae99ed31c 100644 --- a/src/java/org/apache/fop/pdf/PDFFilter.java +++ b/src/java/org/apache/fop/pdf/PDFFilter.java @@ -92,7 +92,7 @@ public abstract class PDFFilter { * * @return the decode params for the filter */ - public abstract String getDecodeParms(); + public abstract PDFObject getDecodeParms(); /** * Applies a filter to an OutputStream. diff --git a/src/java/org/apache/fop/pdf/PDFFilterList.java b/src/java/org/apache/fop/pdf/PDFFilterList.java index e0ee7eb4b..8004e1e60 100644 --- a/src/java/org/apache/fop/pdf/PDFFilterList.java +++ b/src/java/org/apache/fop/pdf/PDFFilterList.java @@ -48,6 +48,8 @@ public class PDFFilterList { private List filters = new java.util.ArrayList(); private boolean ignoreASCIIFilters = false; + + private boolean disableAllFilters = false; /** * Default constructor. @@ -68,6 +70,22 @@ public class PDFFilterList { } /** + * Used to disable all filters. + * @param value true if all filters shall be disabled + */ + public void setDisableAllFilters(boolean value) { + this.disableAllFilters = value; + } + + /** + * Returns true if all filters are disabled. + * @return true if all filters are disabled + */ + public boolean isDisableAllFilters() { + return this.disableAllFilters; + } + + /** * Indicates whether the filter list is already initialized. * @return true if more there are filters present */ @@ -185,21 +203,7 @@ public class PDFFilterList { List names = new java.util.ArrayList(); List parms = new java.util.ArrayList(); - // run the filters - int nonNullParams = 0; - for (int count = 0; count < filters.size(); count++) { - PDFFilter filter = (PDFFilter)filters.get(count); - // place the names in our local vector in reverse order - if (filter.getName().length() > 0) { - names.add(0, filter.getName()); - if (filter.getDecodeParms() != null) { - parms.add(0, filter.getDecodeParms()); - nonNullParams++; - } else { - parms.add(0, null); - } - } - } + int nonNullParams = populateNamesAndParms(names, parms); // now build up the filter entries for the dictionary return buildFilterEntries(names) @@ -209,6 +213,47 @@ public class PDFFilterList { } + /** + * Apply the filters to the data + * in the order given and add the /Filter and /DecodeParms + * entries to the stream dictionary. If the filters have already + * been applied to the data (either externally, or internally) + * then the dictionary entries added. + * @param dict the PDFDictionary to set the entries on + */ + protected void putFilterDictEntries(PDFDictionary dict) { + if (filters != null && filters.size() > 0) { + List names = new java.util.ArrayList(); + List parms = new java.util.ArrayList(); + + populateNamesAndParms(names, parms); + + // now build up the filter entries for the dictionary + putFilterEntries(dict, names); + putDecodeParams(dict, parms); + } + } + + private int populateNamesAndParms(List names, List parms) { + // run the filters + int nonNullParams = 0; + for (int count = 0; count < filters.size(); count++) { + PDFFilter filter = (PDFFilter)filters.get(count); + // place the names in our local vector in reverse order + if (filter.getName().length() > 0) { + names.add(0, filter.getName()); + PDFObject param = filter.getDecodeParms(); + if (param != null) { + parms.add(0, param); + nonNullParams++; + } else { + parms.add(0, null); + } + } + } + return nonNullParams; + } + private String buildFilterEntries(List names) { int filterCount = 0; StringBuffer sb = new StringBuffer(64); @@ -231,6 +276,23 @@ public class PDFFilterList { } } + private void putFilterEntries(PDFDictionary dict, List names) { + PDFArray array = new PDFArray(); + for (int i = 0, c = names.size(); i < c; i++) { + final String name = (String)names.get(i); + if (name.length() > 0) { + array.add(new PDFName(name)); + } + } + if (array.length() > 0) { + if (array.length() > 1) { + dict.put("Filter", array); + } else { + dict.put("Filter", array.get(0)); + } + } + } + private String buildDecodeParms(List parms) { StringBuffer sb = new StringBuffer(); boolean needParmsEntry = false; @@ -259,6 +321,26 @@ public class PDFFilterList { } } + private void putDecodeParams(PDFDictionary dict, List parms) { + boolean needParmsEntry = false; + PDFArray array = new PDFArray(); + for (int i = 0, c = parms.size(); i < c; i++) { + Object obj = parms.get(i); + if (obj != null) { + array.add(obj); + needParmsEntry = true; + } else { + array.add(null); + } + } + if (array.length() > 0 & needParmsEntry) { + if (array.length() > 1) { + dict.put("DecodeParams", array); + } else { + dict.put("DecodeParams", array.get(0)); + } + } + } /** * Applies all registered filters as necessary. The method returns an @@ -269,7 +351,7 @@ public class PDFFilterList { */ public OutputStream applyFilters(OutputStream stream) throws IOException { OutputStream out = stream; - if (filters != null) { + if (filters != null && !isDisableAllFilters()) { for (int count = filters.size() - 1; count >= 0; count--) { PDFFilter filter = (PDFFilter)filters.get(count); out = filter.applyFilter(out); diff --git a/src/java/org/apache/fop/pdf/PDFFormXObject.java b/src/java/org/apache/fop/pdf/PDFFormXObject.java index 519bae47a..456419f80 100644 --- a/src/java/org/apache/fop/pdf/PDFFormXObject.java +++ b/src/java/org/apache/fop/pdf/PDFFormXObject.java @@ -20,6 +20,8 @@ package org.apache.fop.pdf; // Java +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; import java.io.IOException; import java.io.OutputStream; @@ -30,79 +32,149 @@ import java.io.OutputStream; * dictionary but a stream of image data. */ public class PDFFormXObject extends PDFXObject { + private PDFStream contents; - private String resRef; + private PDFReference resRef; /** * create a FormXObject with the given number and name and load the * image in the object * * @param xnumber the pdf object X number - * @param cont the pdf stream contents - * @param ref the resource PDF reference + * @param contents the form's contents + * @param resources the resource PDF reference */ - public PDFFormXObject(int xnumber, PDFStream cont, String ref) { - super(xnumber, null); - contents = cont; - resRef = ref; + public PDFFormXObject(int xnumber, PDFStream contents, PDFReference resources) { + super(); + put("Name", new PDFName("Form" + xnumber)); + this.resRef = resources; + this.contents = contents; + + put("Type", new PDFName("XObject")); + put("Subtype", new PDFName("Form")); + put("FormType", new Integer(1)); + setMatrix(new AffineTransform()); } /** - * Output the form stream as PDF. - * This sets up the form XObject dictionary and adds the content - * data stream. - * - * @param stream the output stream to write the data - * @throws IOException if there is an error writing the data - * @return the length of the data written + * Sets the bounding box of the Form XObject. + * @param bbox the bounding box */ - protected int output(OutputStream stream) throws IOException { - int length = 0; - - String dictEntries = getFilterList().buildFilterDictEntries(); - - final StreamCache encodedStream = encodeStream(); - - StringBuffer sb = new StringBuffer(128); - sb.append(getObjectID()); - sb.append("<</Type /XObject\n"); - sb.append("/Subtype /Form\n"); - sb.append("/FormType 1\n"); - sb.append("/BBox [0 0 1000 1000]\n"); - sb.append("/Matrix [1 0 0 1 0 0]\n"); - sb.append("/Resources " + resRef + "\n"); - sb.append("/Length " + (encodedStream.getSize() + 1) + "\n"); - - sb.append(dictEntries); - sb.append(">>\n"); - - // push the pdf dictionary on the writer - byte[] pdfBytes = encode(sb.toString()); - stream.write(pdfBytes); - length += pdfBytes.length; - - //Send encoded stream to target OutputStream - length += outputStreamData(encodedStream, stream); - encodedStream.clear(); //Encoded stream can now be discarded - - pdfBytes = encode("endobj\n"); - stream.write(pdfBytes); - length += pdfBytes.length; - - // let it gc - // this object is retained as a reference to inserting - // the same image but the image data is no longer needed - contents = null; - return length; + public void setBBox(Rectangle2D bbox) { + PDFArray array = (PDFArray)get("BBox"); + if (array == null) { + array = new PDFArray(); + array.add(bbox.getX()); + array.add(bbox.getY()); + array.add(bbox.getWidth()); + array.add(bbox.getHeight()); + put("BBox", array); + } else { + array.set(0, bbox.getX()); + array.set(1, bbox.getY()); + array.set(2, bbox.getWidth()); + array.set(3, bbox.getHeight()); + } + } + + /** + * Returns the bounding box. + * @return the BBox value + */ + public Rectangle2D getBBox() { + PDFArray array = (PDFArray)get("BBox"); + if (array != null) { + Rectangle2D rect = new Rectangle2D.Double(); + double x = ((Number)array.get(0)).doubleValue(); + double y = ((Number)array.get(1)).doubleValue(); + double w = ((Number)array.get(2)).doubleValue(); + double h = ((Number)array.get(3)).doubleValue(); + rect.setFrame(x, y, w, h); + return rect; + } else { + return null; + } } /** - * {@inheritDoc} + * Sets the Matrix value + * @param at the AffineTransform defining the transformation matrix */ + public void setMatrix(AffineTransform at) { + PDFArray array = (PDFArray)get("Matrix"); + double[] m = new double[6]; + at.getMatrix(m); + if (array == null) { + array = new PDFArray(); + array.add(m[0]); + array.add(m[1]); + array.add(m[2]); + array.add(m[3]); + array.add(m[4]); + array.add(m[5]); + put("Matrix", array); + } else { + array.set(0, m[0]); + array.set(1, m[1]); + array.set(2, m[2]); + array.set(3, m[3]); + array.set(4, m[4]); + array.set(5, m[5]); + } + } + + /** + * Returns the Matrix value. + * @return the Matrix + */ + public AffineTransform getMatrix() { + PDFArray array = (PDFArray)get("Matrix"); + if (array != null) { + AffineTransform at = new AffineTransform(); + double m00 = ((Number)array.get(0)).doubleValue(); + double m10 = ((Number)array.get(1)).doubleValue(); + double m01 = ((Number)array.get(2)).doubleValue(); + double m11 = ((Number)array.get(3)).doubleValue(); + double m02 = ((Number)array.get(4)).doubleValue(); + double m12 = ((Number)array.get(5)).doubleValue(); + at.setTransform(m00, m10, m01, m11, m02, m12); + return at; + } else { + return null; + } + } + + /** + * Used to set the contents of the PDF stream. + * @param data the contents as a byte array + * @throws IOException in case of an I/O problem + */ + public void setData(byte[] data) throws IOException { + this.contents.setData(data); + } + + /** {@inheritDoc} */ protected void outputRawStreamData(OutputStream out) throws IOException { contents.outputRawStreamData(out); } + /** {@inheritDoc} */ + protected int output(OutputStream stream) throws IOException { + final int len = super.output(stream); + + //Now that the data has been written, it can be discarded. + this.contents = null; + return len; + } + + /** {@inheritDoc} */ + protected void populateStreamDict(Object lengthEntry) { + if (get("Matrix") == null) { + put("Matrix", new PDFArray(new int[] {1, 0, 0, 1, 0, 0})); + } + put("Resources", resRef); + super.populateStreamDict(lengthEntry); + } } diff --git a/src/java/org/apache/fop/pdf/PDFICCStream.java b/src/java/org/apache/fop/pdf/PDFICCStream.java index 6c08953cb..da1e8353c 100644 --- a/src/java/org/apache/fop/pdf/PDFICCStream.java +++ b/src/java/org/apache/fop/pdf/PDFICCStream.java @@ -73,24 +73,13 @@ public class PDFICCStream extends PDFStream { cp.write(out); } - /** - * {@inheritDoc} - */ - protected String buildStreamDict(String lengthEntry) { - final String filterEntry = getFilterList().buildFilterDictEntries(); - final StringBuffer sb = new StringBuffer(128); - sb.append(getObjectID()); - sb.append("<< "); - sb.append("/N " + cp.getNumComponents()); - + /** {@inheritDoc} */ + protected void populateStreamDict(Object lengthEntry) { + put("N", cp.getNumComponents()); if (pdfColorSpace != null) { - sb.append("\n/Alternate /" + pdfColorSpace.getName() + " "); + put("Alternate", new PDFName(pdfColorSpace.getName())); } - - sb.append("\n/Length " + lengthEntry); - sb.append("\n" + filterEntry); - sb.append("\n>>\n"); - return sb.toString(); + super.populateStreamDict(lengthEntry); } } diff --git a/src/java/org/apache/fop/pdf/PDFImage.java b/src/java/org/apache/fop/pdf/PDFImage.java index db233d1d4..dd24240b5 100644 --- a/src/java/org/apache/fop/pdf/PDFImage.java +++ b/src/java/org/apache/fop/pdf/PDFImage.java @@ -109,6 +109,8 @@ public interface PDFImage { * @return the PDF reference for a soft mask image */ String getSoftMask(); + + PDFReference getSoftMaskReference(); /** @return true for CMYK images generated by Adobe Photoshop */ boolean isInverted(); diff --git a/src/java/org/apache/fop/pdf/PDFImageXObject.java b/src/java/org/apache/fop/pdf/PDFImageXObject.java new file mode 100644 index 000000000..4cc174100 --- /dev/null +++ b/src/java/org/apache/fop/pdf/PDFImageXObject.java @@ -0,0 +1,168 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.pdf; + +// Java +import java.io.IOException; +import java.io.OutputStream; + +/* modified by JKT to integrate with 0.12.0 */ +/* modified by Eric SCHAEFFER to integrate with 0.13.0 */ + +/** + * PDF XObject + * + * A derivative of the PDF Object, is a PDF Stream that has not only a + * dictionary but a stream of image data. + * The dictionary just provides information like the stream length. + * This outputs the image dictionary and the image data. + * This is used as a reference for inserting the same image in the + * document in another place. + */ +public class PDFImageXObject extends PDFXObject { + + private PDFImage pdfimage; + + /** + * create an XObject with the given number and name and load the + * image in the object + * + * @param xnumber the pdf object X number + * @param img the pdf image that contains the image data + */ + public PDFImageXObject(int xnumber, PDFImage img) { + super(); + put("Name", new PDFName("Im" + xnumber)); + pdfimage = img; + } + + /** + * Output the image as PDF. + * This sets up the image dictionary and adds the image data stream. + * + * @param stream the output stream to write the data + * @throws IOException if there is an error writing the data + * @return the length of the data written + */ + protected int output(OutputStream stream) throws IOException { + int length = super.output(stream); + + // let it gc + // this object is retained as a reference to inserting + // the same image but the image data is no longer needed + pdfimage = null; + return length; + } + + /** {@inheritDoc} */ + protected void populateStreamDict(Object lengthEntry) { + super.populateStreamDict(lengthEntry); + if (pdfimage.isPS()) { + populateDictionaryFromPS(); + } else { + populateDictionaryFromImage(); + } + } + + private void populateDictionaryFromPS() { + getDocumentSafely().getProfile().verifyPSXObjectsAllowed(); + put("Subtype", new PDFName("PS")); + } + + private void populateDictionaryFromImage() { + put("Subtype", new PDFName("Image")); + put("Width", new Integer(pdfimage.getWidth())); + put("Height", new Integer(pdfimage.getHeight())); + put("BitsPerComponent", new Integer(pdfimage.getBitsPerPixel())); + + PDFICCStream pdfICCStream = pdfimage.getICCStream(); + if (pdfICCStream != null) { + put("ColorSpace", new PDFArray(new Object[] {new PDFName("ICCBased"), pdfICCStream})); + } else { + PDFDeviceColorSpace cs = pdfimage.getColorSpace(); + put("ColorSpace", new PDFName(cs.getName())); + } + + if (pdfimage.isInverted()) { + /* PhotoShop generates CMYK values that's inverse, + * this will invert the values - too bad if it's not + * a PhotoShop image... + */ + final Float zero = new Float(0.0f); + final Float one = new Float(1.0f); + PDFArray decode = new PDFArray(); + for (int i = 0, c = pdfimage.getColorSpace().getNumComponents(); i < c; i++) { + decode.add(one); + decode.add(zero); + } + put("Decode", decode); + } + + if (pdfimage.isTransparent()) { + PDFColor transp = pdfimage.getTransparentColor(); + PDFArray mask = new PDFArray(); + mask.add(new Integer(transp.red255())); + mask.add(new Integer(transp.red255())); + mask.add(new Integer(transp.green255())); + mask.add(new Integer(transp.green255())); + mask.add(new Integer(transp.blue255())); + mask.add(new Integer(transp.blue255())); + put("Mask", mask); + } + PDFReference ref = pdfimage.getSoftMaskReference(); + if (ref != null) { + put("SMask", ref); + } + } + + /** {@inheritDoc} */ + protected void outputRawStreamData(OutputStream out) throws IOException { + pdfimage.outputContents(out); + } + + /** {@inheritDoc} */ + protected int getSizeHint() throws IOException { + return 0; + } + + /** {@inheritDoc} */ + protected void prepareImplicitFilters() { + PDFFilter pdfFilter = pdfimage.getPDFFilter(); + if (pdfFilter != null) { + getFilterList().ensureFilterInPlace(pdfFilter); + } + } + + /** + * This sets up the default filters for XObjects. It uses the PDFImage + * instance to determine what default filters to apply. + * {@inheritDoc} + */ + protected void setupFilterList() { + if (!getFilterList().isInitialized()) { + getFilterList().addDefaultFilters( + getDocumentSafely().getFilterMap(), + pdfimage.getFilterHint()); + } + super.setupFilterList(); + } + + +} diff --git a/src/java/org/apache/fop/pdf/PDFMetadata.java b/src/java/org/apache/fop/pdf/PDFMetadata.java index 74ffb1580..067502986 100644 --- a/src/java/org/apache/fop/pdf/PDFMetadata.java +++ b/src/java/org/apache/fop/pdf/PDFMetadata.java @@ -101,24 +101,18 @@ public class PDFMetadata extends PDFStream { } /** {@inheritDoc} */ - protected String buildStreamDict(String lengthEntry) { + protected void populateStreamDict(Object lengthEntry) { final String filterEntry = getFilterList().buildFilterDictEntries(); if (getDocumentSafely().getProfile().getPDFAMode().isPDFA1LevelB() && filterEntry != null && filterEntry.length() > 0) { throw new PDFConformanceException( "The Filter key is prohibited when PDF/A-1 is active"); } - final StringBuffer sb = new StringBuffer(128); - sb.append(getObjectID()); - sb.append("<< "); - sb.append("/Type /Metadata"); - sb.append("\n/Subtype /XML"); - sb.append("\n/Length " + lengthEntry); - sb.append("\n" + filterEntry); - sb.append("\n>>\n"); - return sb.toString(); + put("Type", new PDFName("Metadata")); + put("Subtype", new PDFName("XML")); + super.populateStreamDict(lengthEntry); } - + /** * Creates an XMP document based on the settings on the PDF Document. * @param pdfDoc the PDF Document diff --git a/src/java/org/apache/fop/pdf/PDFName.java b/src/java/org/apache/fop/pdf/PDFName.java new file mode 100644 index 000000000..4c3c3d003 --- /dev/null +++ b/src/java/org/apache/fop/pdf/PDFName.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.pdf; + +/** + * Class representing a PDF name object. + */ +public class PDFName implements PDFWritable { + + private String name; + + /** + * Creates a new PDF name object. + * @param name the name value + */ + public PDFName(String name) { + this.name = escapeName(name); + } + + + private static String escapeName(String name) { + StringBuffer sb = new StringBuffer(Math.min(16, name.length() + 4)); + if (!name.startsWith("/")) { + sb.append('/'); + } + for (int i = 0, c = name.length(); i < c; i++) { + char ch = name.charAt(i); + if (ch >= 33 && ch <= 126) { + sb.append(ch); + } else { + sb.append('#'); + toHex(ch, sb); + } + } + return sb.toString(); + } + + private static final char[] DIGITS + = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + private static void toHex(char ch, StringBuffer sb) { + if (ch >= 256) { + throw new IllegalArgumentException( + "Only 8-bit characters allowed by this implementation"); + } + sb.append(DIGITS[ch >>> 4 & 0x0F]); + sb.append(DIGITS[ch & 0x0F]); + } + + + /** {@inheritDoc} */ + public String toInlinePDFString() { + return this.name; + } + + /** {@inheritDoc} */ + public String toString() { + return toInlinePDFString(); + } + +} diff --git a/src/java/org/apache/fop/pdf/PDFNull.java b/src/java/org/apache/fop/pdf/PDFNull.java new file mode 100644 index 000000000..e3fb44a8d --- /dev/null +++ b/src/java/org/apache/fop/pdf/PDFNull.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* $Id$ */ + +package org.apache.fop.pdf; + +/** + * Class representing a PDF name object. + */ +public final class PDFNull implements PDFWritable { + + /** Instance for the "null" object. */ + public static final PDFNull INSTANCE = new PDFNull(); + + /** + * Creates a new PDF name object. + * @param name the name value + */ + private PDFNull() { + } + + /** {@inheritDoc} */ + public String toInlinePDFString() { + return "null"; + } + + /** {@inheritDoc} */ + public String toString() { + return toInlinePDFString(); + } + +} diff --git a/src/java/org/apache/fop/pdf/PDFNumber.java b/src/java/org/apache/fop/pdf/PDFNumber.java index 6da28f9be..2a8d6c472 100644 --- a/src/java/org/apache/fop/pdf/PDFNumber.java +++ b/src/java/org/apache/fop/pdf/PDFNumber.java @@ -111,9 +111,13 @@ public class PDFNumber extends PDFObject { "The number of this PDFNumber must not be empty"); } StringBuffer sb = new StringBuffer(64); - sb.append(getObjectID()); + if (hasObjectNumber()) { + sb.append(getObjectID()); + } sb.append(getNumber().toString()); - sb.append("\nendobj\n"); + if (hasObjectNumber()) { + sb.append("\nendobj\n"); + } return sb.toString(); } diff --git a/src/java/org/apache/fop/pdf/PDFObject.java b/src/java/org/apache/fop/pdf/PDFObject.java index 544a30cc4..8152fcd83 100644 --- a/src/java/org/apache/fop/pdf/PDFObject.java +++ b/src/java/org/apache/fop/pdf/PDFObject.java @@ -251,9 +251,17 @@ public abstract class PDFObject implements PDFWritable { * @param sb the StringBuffer to write to */ protected void formatObject(Object obj, StringBuffer sb) { - if (obj instanceof PDFWritable) { + if (obj == null) { + sb.append("null"); + } else if (obj instanceof PDFWritable) { sb.append(((PDFWritable)obj).toInlinePDFString()); } else if (obj instanceof Number) { + if (obj instanceof Double || obj instanceof Float) { + sb.append(PDFNumber.doubleOut(((Number)obj).doubleValue())); + } else { + sb.append(obj); + } + } else if (obj instanceof Boolean) { sb.append(obj); } else { sb.append("(").append(obj).append(")"); diff --git a/src/java/org/apache/fop/pdf/PDFReference.java b/src/java/org/apache/fop/pdf/PDFReference.java index a1b776a81..ed1a8c016 100644 --- a/src/java/org/apache/fop/pdf/PDFReference.java +++ b/src/java/org/apache/fop/pdf/PDFReference.java @@ -42,6 +42,14 @@ public class PDFReference implements PDFWritable { this.indirectReference = obj.referencePDF(); this.objReference = new SoftReference(obj); } + + /** + * Creates a new PDF reference, but without a reference to the original object. + * @param ref an object reference + */ + public PDFReference(String ref) { + this.indirectReference = ref; + } /** * Returns the PDF object @@ -64,4 +72,9 @@ public class PDFReference implements PDFWritable { return this.indirectReference; } + /** {@inheritDoc} */ + public String toString() { + return toInlinePDFString(); + } + } diff --git a/src/java/org/apache/fop/pdf/PDFResources.java b/src/java/org/apache/fop/pdf/PDFResources.java index 70e809aaa..310f8d8d0 100644 --- a/src/java/org/apache/fop/pdf/PDFResources.java +++ b/src/java/org/apache/fop/pdf/PDFResources.java @@ -240,7 +240,7 @@ public class PDFResources extends PDFObject { p = p.append("/XObject <<\n"); for (Iterator iter = xObjects.iterator(); iter.hasNext();) { PDFXObject xobj = (PDFXObject)iter.next(); - p = p.append(" /Im" + xobj.getXNumber() + " " + p = p.append(" " + xobj.getName() + " " + xobj.referencePDF() + "\n"); } diff --git a/src/java/org/apache/fop/pdf/PDFStream.java b/src/java/org/apache/fop/pdf/PDFStream.java index ac025da87..59a8336c5 100644 --- a/src/java/org/apache/fop/pdf/PDFStream.java +++ b/src/java/org/apache/fop/pdf/PDFStream.java @@ -64,7 +64,17 @@ public class PDFStream extends AbstractPDFStream { } } - + + /** + * Returns an OutputStream that can be used to write to the buffer which is used + * to build up the PDF stream. + * @return the OutputStream + * @throws IOException In case of an I/O problem + */ + public OutputStream getBufferOutputStream() throws IOException { + return this.data.getOutputStream(); + } + /** * Used to set the contents of the PDF stream. * @param data the contents as a byte array diff --git a/src/java/org/apache/fop/pdf/PDFT1Stream.java b/src/java/org/apache/fop/pdf/PDFT1Stream.java index aca7e4f60..08a626009 100644 --- a/src/java/org/apache/fop/pdf/PDFT1Stream.java +++ b/src/java/org/apache/fop/pdf/PDFT1Stream.java @@ -61,18 +61,12 @@ public class PDFT1Stream extends AbstractPDFStream { return length; } - /** - * {@inheritDoc} - */ - protected String buildStreamDict(String lengthEntry) { - final String filterEntry = getFilterList().buildFilterDictEntries(); - return (getObjectID() - + "<< /Length " + lengthEntry - + " /Length1 " + pfb.getLength1() - + " /Length2 " + pfb.getLength2() - + " /Length3 " + pfb.getLength3() - + "\n" + filterEntry - + "\n>>\n"); + /** {@inheritDoc} */ + protected void populateStreamDict(Object lengthEntry) { + super.populateStreamDict(lengthEntry); + put("Length1", new Integer(pfb.getLength1())); + put("Length2", new Integer(pfb.getLength2())); + put("Length3", new Integer(pfb.getLength3())); } /** diff --git a/src/java/org/apache/fop/pdf/PDFTTFStream.java b/src/java/org/apache/fop/pdf/PDFTTFStream.java index 5176fac66..9f4c543ad 100644 --- a/src/java/org/apache/fop/pdf/PDFTTFStream.java +++ b/src/java/org/apache/fop/pdf/PDFTTFStream.java @@ -51,18 +51,12 @@ public class PDFTTFStream extends PDFStream { return length; } - /** - * {@inheritDoc} - */ - protected String buildStreamDict(String lengthEntry) { - final String filterEntry = getFilterList().buildFilterDictEntries(); - return (getObjectID() - + "<< /Length " + lengthEntry - + " /Length1 " + origLength - + "\n" + filterEntry - + "\n>>\n"); + /** {@inheritDoc} */ + protected void populateStreamDict(Object lengthEntry) { + put("Length1", origLength); + super.populateStreamDict(lengthEntry); } - + /** * Sets the TrueType font data. * @param data the font payload diff --git a/src/java/org/apache/fop/pdf/PDFXObject.java b/src/java/org/apache/fop/pdf/PDFXObject.java index 3e70e20c5..d0115fe66 100644 --- a/src/java/org/apache/fop/pdf/PDFXObject.java +++ b/src/java/org/apache/fop/pdf/PDFXObject.java @@ -21,13 +21,9 @@ package org.apache.fop.pdf; // Java import java.io.IOException; -import java.io.OutputStream; - -/* modified by JKT to integrate with 0.12.0 */ -/* modified by Eric SCHAEFFER to integrate with 0.13.0 */ /** - * PDF XObject + * Abstract base class of PDF XObjects. * * A derivative of the PDF Object, is a PDF Stream that has not only a * dictionary but a stream of image data. @@ -36,170 +32,32 @@ import java.io.OutputStream; * This is used as a reference for inserting the same image in the * document in another place. */ -public class PDFXObject extends AbstractPDFStream { +public abstract class PDFXObject extends AbstractPDFStream { - private PDFImage pdfimage; - private int xnum; - /** - * create an XObject with the given number and name and load the - * image in the object - * - * @param xnumber the pdf object X number - * @param img the pdf image that contains the image data + * Create an XObject with the given number. */ - public PDFXObject(int xnumber, PDFImage img) { + public PDFXObject() { super(); - this.xnum = xnumber; - pdfimage = img; - } - - /** - * Get the xnumber for this pdf object. - * - * @return the PDF XObject number - */ - public int getXNumber() { - return this.xnum; - } - - /** - * Output the image as PDF. - * This sets up the image dictionary and adds the image data stream. - * - * @param stream the output stream to write the data - * @throws IOException if there is an error writing the data - * @return the length of the data written - */ - protected int output(OutputStream stream) throws IOException { - int length = super.output(stream); - - // let it gc - // this object is retained as a reference to inserting - // the same image but the image data is no longer needed - pdfimage = null; - return length; } /** - * {@inheritDoc} + * Returns the XObject's name. + * @return the name of the XObject */ - protected String buildStreamDict(String lengthEntry) { - String dictEntries = getFilterList().buildFilterDictEntries(); - if (pdfimage.isPS()) { - return buildDictionaryFromPS(lengthEntry, dictEntries); - } else { - return buildDictionaryFromImage(lengthEntry, dictEntries); - } + public PDFName getName() { + return (PDFName)get("Name"); } - private String buildDictionaryFromPS(String lengthEntry, - String dictEntries) { - getDocumentSafely().getProfile().verifyPSXObjectsAllowed(); - StringBuffer sb = new StringBuffer(128); - sb.append(getObjectID()); - sb.append("<</Type /XObject\n"); - sb.append("/Subtype /PS\n"); - sb.append("/Length " + lengthEntry); - - sb.append(dictEntries); - sb.append("\n>>\n"); - return sb.toString(); - } - - private String buildDictionaryFromImage(String lengthEntry, - String dictEntries) { - StringBuffer sb = new StringBuffer(128); - sb.append(getObjectID()); - sb.append("<</Type /XObject\n"); - sb.append("/Subtype /Image\n"); - sb.append("/Name /Im" + xnum + "\n"); - sb.append("/Length " + lengthEntry + "\n"); - sb.append("/Width " + pdfimage.getWidth() + "\n"); - sb.append("/Height " + pdfimage.getHeight() + "\n"); - sb.append("/BitsPerComponent " + pdfimage.getBitsPerPixel() + "\n"); - - PDFICCStream pdfICCStream = pdfimage.getICCStream(); - if (pdfICCStream != null) { - sb.append("/ColorSpace [/ICCBased " - + pdfICCStream.referencePDF() + "]\n"); - } else { - PDFDeviceColorSpace cs = pdfimage.getColorSpace(); - sb.append("/ColorSpace /" + cs.getName() - + "\n"); - } - - if (pdfimage.isInverted()) { - /* PhotoShop generates CMYK values that's inverse, - * this will invert the values - too bad if it's not - * a PhotoShop image... - */ - if (pdfimage.getColorSpace().getColorSpace() == PDFDeviceColorSpace.DEVICE_CMYK) { - sb.append("/Decode [ 1.0 0.0 1.0 0.0 1.0 0.0 1.0 0.0 ]\n"); - } else if (pdfimage.getColorSpace().getColorSpace() == PDFDeviceColorSpace.DEVICE_RGB) { - sb.append("/Decode [ 1.0 0.0 1.0 0.0 1.0 0.0 ]\n"); - } else if (pdfimage.getColorSpace().getColorSpace() == PDFDeviceColorSpace.DEVICE_GRAY) { - sb.append("/Decode [ 1.0 0.0 ]\n"); - } - } - - if (pdfimage.isTransparent()) { - PDFColor transp = pdfimage.getTransparentColor(); - sb.append("/Mask [" - + transp.red255() + " " - + transp.red255() + " " - + transp.green255() + " " - + transp.green255() + " " - + transp.blue255() + " " - + transp.blue255() + "]\n"); - } - String ref = pdfimage.getSoftMask(); - if (ref != null) { - sb.append("/SMask " + ref + "\n"); - } - - sb.append(dictEntries); - sb.append("\n>>\n"); - return sb.toString(); + /** {@inheritDoc} */ + protected void populateStreamDict(Object lengthEntry) { + put("Type", new PDFName("XObject")); + super.populateStreamDict(lengthEntry); } - /** - * {@inheritDoc} - */ - protected void outputRawStreamData(OutputStream out) throws IOException { - pdfimage.outputContents(out); - } - - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ protected int getSizeHint() throws IOException { return 0; } - /** - * {@inheritDoc} - */ - protected void prepareImplicitFilters() { - PDFFilter pdfFilter = pdfimage.getPDFFilter(); - if (pdfFilter != null) { - getFilterList().ensureFilterInPlace(pdfFilter); - } - } - - /** - * This sets up the default filters for XObjects. It uses the PDFImage - * instance to determine what default filters to apply. - * {@inheritDoc} - */ - protected void setupFilterList() { - if (!getFilterList().isInitialized()) { - getFilterList().addDefaultFilters( - getDocumentSafely().getFilterMap(), - pdfimage.getFilterHint()); - } - super.setupFilterList(); - } - - } |