]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugfix: Some string objects were not encrypted (for example in named destinations)
authorJeremias Maerki <jeremias@apache.org>
Fri, 11 Jan 2008 09:04:28 +0000 (09:04 +0000)
committerJeremias Maerki <jeremias@apache.org>
Fri, 11 Jan 2008 09:04:28 +0000 (09:04 +0000)
I had to refactor the PDF library a little bit but since it only affects the inner API it shouldn't be a problem that I removed some methods which caused trouble because a didn't think about encryption when I worked on the PDF library last year.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@611114 13f79535-47bb-0310-9956-ffa450edef68

26 files changed:
src/java/org/apache/fop/pdf/AbstractPDFStream.java
src/java/org/apache/fop/pdf/BitmapImage.java
src/java/org/apache/fop/pdf/PDFArray.java
src/java/org/apache/fop/pdf/PDFDestination.java
src/java/org/apache/fop/pdf/PDFDests.java
src/java/org/apache/fop/pdf/PDFDictionary.java
src/java/org/apache/fop/pdf/PDFDocument.java
src/java/org/apache/fop/pdf/PDFEncryptionJCE.java
src/java/org/apache/fop/pdf/PDFFactory.java
src/java/org/apache/fop/pdf/PDFFilterList.java
src/java/org/apache/fop/pdf/PDFFormXObject.java
src/java/org/apache/fop/pdf/PDFImage.java
src/java/org/apache/fop/pdf/PDFImageXObject.java
src/java/org/apache/fop/pdf/PDFName.java
src/java/org/apache/fop/pdf/PDFNameTreeNode.java
src/java/org/apache/fop/pdf/PDFNull.java
src/java/org/apache/fop/pdf/PDFNumberTreeNode.java
src/java/org/apache/fop/pdf/PDFNumsArray.java
src/java/org/apache/fop/pdf/PDFObject.java
src/java/org/apache/fop/pdf/PDFPageLabels.java
src/java/org/apache/fop/pdf/PDFReference.java
src/java/org/apache/fop/pdf/PDFRoot.java
src/java/org/apache/fop/pdf/PDFWritable.java
src/java/org/apache/fop/render/pdf/FopPDFImage.java
src/java/org/apache/fop/render/pdf/PDFRenderer.java
status.xml

index 0ade68f89d9d4ab563f83a0001553995a360b271..16190da9997bd4bf3673c2a31fb3075142e01162 100644 (file)
@@ -21,8 +21,10 @@ package org.apache.fop.pdf;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.Writer;
 
 import org.apache.commons.io.output.CountingOutputStream;
+
 import org.apache.fop.util.CloseBlockerOutputStream;
 
 /**
@@ -169,8 +171,12 @@ public abstract class AbstractPDFStream extends PDFDictionary {
      * {@inheritDoc}
      */
     protected int output(OutputStream stream) throws IOException {
-        int length = 0;
         setupFilterList();
+
+        CountingOutputStream cout = new CountingOutputStream(stream);
+        Writer writer = PDFDocument.getWriterFor(cout);
+        writer.write(getObjectID());
+        //int length = 0;
         
         StreamCache encodedStream = null;
         PDFNumber refLength = null;
@@ -184,38 +190,21 @@ public abstract class AbstractPDFStream extends PDFDictionary {
             lengthEntry = new Integer(encodedStream.getSize() + 1);
         }
         
-        byte[] p = encode(buildStreamDict(lengthEntry));
-        stream.write(p);
-        length += p.length;
+        populateStreamDict(lengthEntry);
+        writeDictionary(cout, writer);
         
         //Send encoded stream to target OutputStream
+        writer.flush();
         if (encodedStream == null) {
-            int bytesWritten = encodeAndWriteStream(stream, refLength);
-            length += bytesWritten;
+            encodeAndWriteStream(cout, refLength);
         } else {
-            length += outputStreamData(encodedStream, stream);
+            outputStreamData(encodedStream, cout);
             encodedStream.clear(); //Encoded stream can now be discarded
         }
         
-        p = encode("\nendobj\n");
-        stream.write(p);
-        length += p.length;
-        return length;
-    }
-
-    /**
-     * Constructs the dictionary for the stream. Override this method if you
-     * need additional entries.
-     * @param lengthEntry value for the /Length entry
-     * @return the newly constructed dictionary
-     */
-    protected String buildStreamDict(Object lengthEntry) {
-        StringBuffer sb = new StringBuffer();
-        sb.append(getObjectID());
-        populateStreamDict(lengthEntry);
-        
-        writeDictionary(sb);
-        return sb.toString();
+        writer.write("\nendobj\n");
+        writer.flush();
+        return cout.getCount();
     }
 
     /**
index 461ec0a64b545a9aa662ddb4daa2d47059ed4a0e..34c78ffe3137f49166844ee441f79b6095aba24a 100644 (file)
@@ -163,15 +163,6 @@ public class BitmapImage implements PDFImage {
         return null;
     }
 
-    /**
-     * Get the soft mask reference for this image.
-     *
-     * @return the soft mask reference if any
-     */
-    public String getSoftMask() {
-        return maskRef.toInlinePDFString();
-    }
-    
     /** {@inheritDoc} */
     public PDFReference getSoftMaskReference() {
         return maskRef;
index 2dd68ad8bca19b4645e5ca73cec00ab6f84aa3eb..2cb2adb1dfd4d34b8aed24b19c7242011cf150f1 100644 (file)
  
 package org.apache.fop.pdf;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
 import java.util.Collection;
 import java.util.List;
 
+import org.apache.commons.io.output.CountingOutputStream;
+
 /**
  * Class representing an array object.
  */
@@ -33,20 +38,21 @@ public class PDFArray extends PDFObject {
 
     /**
      * Create a new, empty array object
+     * @param parent the array's parent if any
      */
-    public PDFArray() {
+    public PDFArray(PDFObject parent) {
         /* generic creation of PDF object */
-        super();
+        super(parent);
     }
 
     /**
-     * Create the array object
-     *
+     * Create an array object.
+     * @param parent the array's parent if any
      * @param values the actual array wrapped by this object
      */
-    public PDFArray(int[] values) {
+    public PDFArray(PDFObject parent, int[] values) {
         /* generic creation of PDF object */
-        super();
+        super(parent);
 
         for (int i = 0, c = values.length; i < c; i++) {
             this.values.add(new Integer(values[i]));
@@ -54,25 +60,25 @@ public class PDFArray extends PDFObject {
     }
 
     /**
-     * Create the array object
-     *
+     * Create an array object.
+     * @param parent the array's parent if any
      * @param values the actual values wrapped by this object
      */
-    public PDFArray(Collection values) {
+    public PDFArray(PDFObject parent, Collection values) {
         /* generic creation of PDF object */
-        super();
+        super(parent);
         
         this.values.addAll(values);
     }
     
     /**
      * Create the array object
-     *
+     * @param parent the array's parent if any
      * @param values the actual array wrapped by this object
      */
-    public PDFArray(Object[] values) {
+    public PDFArray(PDFObject parent, Object[] values) {
         /* generic creation of PDF object */
-        super();
+        super(parent);
         
         for (int i = 0, c = values.length; i < c; i++) {
             this.values.add(values[i]);
@@ -114,6 +120,17 @@ public class PDFArray extends PDFObject {
         return this.values.get(index);
     }
     
+    /**
+     * Adds a new value to the array.
+     * @param obj the value
+     */
+    public void add(PDFObject obj) {
+        if (obj != null) {
+            obj.setParent(this);
+        }
+        this.values.add(obj);
+    }
+    
     /**
      * Adds a new value to the array.
      * @param obj the value
@@ -130,27 +147,30 @@ public class PDFArray extends PDFObject {
         this.values.add(new Double(value));
     }
     
-    /**
-     * {@inheritDoc}
-     */
-    public String toPDFString() {
-        StringBuffer p = new StringBuffer(64);
+    /** {@inheritDoc} */
+    protected int output(OutputStream stream) throws IOException {
+        CountingOutputStream cout = new CountingOutputStream(stream);
+        Writer writer = PDFDocument.getWriterFor(cout);
         if (hasObjectNumber()) {
-            p.append(getObjectID());
+            writer.write(getObjectID());
         }
-        p.append("[");
+        
+        writer.write('[');
         for (int i = 0; i < values.size(); i++) {
             if (i > 0) {
-                p.append(" ");
+                writer.write(' ');
             }
             Object obj = this.values.get(i);
-            formatObject(obj, p);
+            formatObject(obj, cout, writer);
         }
-        p.append("]");
+        writer.write(']');
+        
         if (hasObjectNumber()) {
-            p.append("\nendobj\n");
+            writer.write("\nendobj\n");
         }
-        return p.toString();
+        
+        writer.flush();
+        return cout.getCount();
     }
-
+    
 }
index c59b20cfcbd48b7b2c6ec90f0e29c9226fad33a3..eaf38449d264a24f723635a7217c76196249116d 100644 (file)
 
 package org.apache.fop.pdf;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
+import org.apache.commons.io.output.CountingOutputStream;
+
 /**
  * class representing a named destination
  */
@@ -40,30 +46,24 @@ public class PDFDestination extends PDFObject {
      * @param goToRef Object reference to the GoTo Action
      */
     public PDFDestination(String idRef, Object goToRef) {
+        super();
         this.goToReference = goToRef;
         this.idRef = idRef;
     }
 
-    /**
-     * Creates the key/value pair for this destination entry for the name tree.
-     * @return the formatted key/value pair
-     */
-    public String toKeyValuePair() {
-        StringBuffer sb = new StringBuffer();
-        sb.append("(").append(getIDRef()).append(") ");
-        if (goToReference instanceof PDFWritable) {
-            sb.append(((PDFWritable)goToReference).toInlinePDFString());
-        } else {
-            sb.append(goToReference);
-        }
-        return sb.toString();
-    }
-    
     /** {@inheritDoc} */
-    protected String toPDFString() {
-        return toKeyValuePair();
+    protected int output(OutputStream stream) throws IOException {
+        CountingOutputStream cout = new CountingOutputStream(stream);
+        Writer writer = PDFDocument.getWriterFor(cout);
+        
+        formatObject(getIDRef(), cout, writer);
+        writer.write(' ');
+        formatObject(goToReference, cout, writer);
+        
+        writer.flush();
+        return cout.getCount();
     }
-
+    
     /**
      * Sets the GoToReference in the associated DestinationData object.
      *
@@ -124,9 +124,7 @@ public class PDFDestination extends PDFObject {
         return false;
     }
 
-    /**
-     * {@inheritDoc}
-     */
+    /** {@inheritDoc} */
     public int hashCode() {
         return getIDRef().hashCode();
     }
index 463ef8d7e8d971a677cb820f7751b107dc084a59..ff2d6a237f566eea5efb023b0fe9d26143ec74f9 100644 (file)
@@ -40,7 +40,7 @@ public class PDFDests extends PDFNameTreeNode {
      */
     public PDFDests(List destinationList) {
         this();
-        setNames(new PDFArray(destinationList));
+        setNames(new PDFArray(this, destinationList));
     }
 
 }
index c183871b555f4ccbf5f533f9b047813a56f4d397..49d48312c4161926b11fd3025926c98dbc6800bf 100644 (file)
  
 package org.apache.fop.pdf;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.commons.io.output.CountingOutputStream;
+
 /**
  * Class representing a PDF dictionary object
  */
@@ -40,13 +45,20 @@ public class PDFDictionary extends PDFObject {
     protected List order = new java.util.ArrayList();
     
     /**
-     * Create the dictionary object
+     * Create a new dictionary object.
      */
     public PDFDictionary() {
-        /* generic creation of PDF object */
         super();
     }
 
+    /**
+     * Create a new dictionary object.
+     * @param parent the object's parent if any
+     */
+    public PDFDictionary(PDFObject parent) {
+        super(parent);
+    }
+
     /**
      * Puts a new name/value pair.
      * @param name the name
@@ -80,47 +92,53 @@ public class PDFDictionary extends PDFObject {
         return this.entries.get(name);
     }
     
-    /**
-     * {@inheritDoc}
-     */
-    public String toPDFString() {
-        StringBuffer p = new StringBuffer(64);
+    /** {@inheritDoc} */
+    protected int output(OutputStream stream) throws IOException {
+        CountingOutputStream cout = new CountingOutputStream(stream);
+        Writer writer = PDFDocument.getWriterFor(cout);
         if (hasObjectNumber()) {
-            p.append(getObjectID());
+            writer.write(getObjectID());
         }
-        writeDictionary(p);
+        
+        writeDictionary(cout, writer);
+
         if (hasObjectNumber()) {
-            p.append("endobj\n");
+            writer.write("\nendobj\n");
         }
-        return p.toString();
+        
+        writer.flush();
+        return cout.getCount();
     }
-
+    
     /**
      * Writes the contents of the dictionary to a StringBuffer.
-     * @param sb the target StringBuffer
+     * @param out the OutputStream (for binary content)
+     * @param writer the Writer (for text content, wraps the above OutputStream)
+     * @throws IOException if an I/O error occurs
      */
-    protected void writeDictionary(StringBuffer sb) {
-        sb.append("<<");
+    protected void writeDictionary(OutputStream out, Writer writer) throws IOException {
+        writer.write("<<");
         boolean compact = (this.order.size() <= 2);
         Iterator iter = this.order.iterator();
         while (iter.hasNext()) {
             String key = (String)iter.next();
             if (compact) {
-                sb.append(' ');
+                writer.write(' ');
             } else {
-                sb.append("\n  ");
+                writer.write("\n  ");
             }
-            sb.append('/').append(key);
-            sb.append(' ');
+            writer.write('/');
+            writer.write(key);
+            writer.write(' ');
             Object obj = this.entries.get(key);
-            formatObject(obj, sb);
+            formatObject(obj, out, writer);
         }
         if (compact) {
-            sb.append(' ');
+            writer.write(' ');
         } else {
-            sb.append('\n');
+            writer.write('\n');
         }
-        sb.append(">>\n");
+        writer.write(">>\n");
     }
 
 }
index 045d521739458755796a762e5e51788a699d6eb8..bd44595fba5cd420580ac58adfe0d1db37453c09 100644 (file)
@@ -24,15 +24,16 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
+import java.io.Writer;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Collections;
 import java.util.Date;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Iterator;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -316,6 +317,22 @@ public class PDFDocument {
         }
     }
 
+    /**
+     * Creates and returns a Writer object wrapping the given OutputStream. The Writer is
+     * 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
+     */
+    public static Writer getWriterFor(OutputStream out) {
+        try {
+            return new java.io.BufferedWriter(new java.io.OutputStreamWriter(out, ENCODING));
+        } catch (UnsupportedEncodingException uee) {
+            throw new Error("JVM doesn't support " + ENCODING + " encoding!");
+        }
+    }
+    
     /**
      * set the producer of the document
      *
index 203ca90e1ca5f4922d9a06cd76ac2cb6c01c6d25..5da37076ce060b03227fe59aaced193b11c56915 100644 (file)
 package org.apache.fop.pdf;
 
 // Java
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.IOException;
+import java.security.InvalidKeyException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
-import java.security.InvalidKeyException;
+import java.util.Random;
+
+import javax.crypto.BadPaddingException;
 import javax.crypto.Cipher;
-import javax.crypto.spec.SecretKeySpec;
 import javax.crypto.CipherOutputStream;
 import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.BadPaddingException;
 import javax.crypto.NoSuchPaddingException;
-
-import java.util.Random;
+import javax.crypto.spec.SecretKeySpec;
 
 /**
  * class representing a /Filter /Standard object.
@@ -358,17 +358,20 @@ public class PDFEncryptionJCE extends PDFObject implements PDFEncryption {
         if (this.encryptionKey == null) {
             throw new IllegalStateException("PDF Encryption has not been initialized");
         }
-        log.debug("encrypting with for " + number + " " + generation);
-
         byte[] hash = calcHash(number, generation);        
         return encryptWithHash(data, hash, hash.length);
     }
 
-    /**
-     * {@inheritDoc} 
-     */
+    /** {@inheritDoc} */
     public byte[] encrypt(byte[] data, PDFObject refObj) {
-        return encryptData(data, refObj.getObjectNumber(), refObj.getGeneration());
+        PDFObject o = refObj;
+        while (o != null && !o.hasObjectNumber()) {
+            o = o.getParent();
+        }
+        if (o == null) {
+            throw new IllegalStateException("No object number could be obtained for a PDF object");
+        }
+        return encryptData(data, o.getObjectNumber(), o.getGeneration());
     }
 
     private byte[] calcHash(int number, int generation) {
index f851abae712dab579a42f6d10e6cfed0170244f3..f3069e85efc451c21181c87d094025b2be53c793 100644 (file)
@@ -39,6 +39,9 @@ import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.output.ByteArrayOutputStream;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
+import org.apache.xmlgraphics.xmp.Metadata;
+
 import org.apache.fop.fonts.CIDFont;
 import org.apache.fop.fonts.CustomFont;
 import org.apache.fop.fonts.FontDescriptor;
@@ -51,7 +54,6 @@ import org.apache.fop.fonts.truetype.FontFileReader;
 import org.apache.fop.fonts.truetype.TTFSubSetFile;
 import org.apache.fop.fonts.type1.PFBData;
 import org.apache.fop.fonts.type1.PFBParser;
-import org.apache.xmlgraphics.xmp.Metadata;
 
 /**
  * This class provides method to create and register PDF objects.
@@ -872,7 +874,7 @@ public class PDFFactory {
         //true for a "deep" structure (one node per entry), true for a "flat" structure
         if (deep) {
             dests = new PDFDests();
-            PDFArray kids = new PDFArray();
+            PDFArray kids = new PDFArray(dests);
             Iterator iter = destinationList.iterator();
             while (iter.hasNext()) {
                 PDFDestination dest = (PDFDestination)iter.next();
@@ -880,8 +882,9 @@ public class PDFFactory {
                 getDocument().registerObject(node);
                 node.setLowerLimit(dest.getIDRef());
                 node.setUpperLimit(dest.getIDRef());
-                node.setNames(new PDFArray());
-                node.getNames().add(dest);
+                node.setNames(new PDFArray(node));
+                PDFArray names = node.getNames();
+                names.add(dest);
                 kids.add(node);
             }
             dests.setLowerLimit(((PDFNameTreeNode)kids.get(0)).getLowerLimit());
@@ -1527,7 +1530,7 @@ public class PDFFactory {
      * @return the PDF Array with the int values
      */
     public PDFArray makeArray(int[] values) {
-        PDFArray array = new PDFArray(values);
+        PDFArray array = new PDFArray(null, values);
 
         getDocument().registerObject(array);
         return array;
index e866fc88e9ac87c5b4ee7401f5541161e4416643..607ae174bc4197782ebe5d39a7f13aa0dd7d2451 100644 (file)
@@ -277,7 +277,7 @@ public class PDFFilterList {
     }
 
     private void putFilterEntries(PDFDictionary dict, List names) {
-        PDFArray array = new PDFArray();
+        PDFArray array = new PDFArray(dict);
         for (int i = 0, c = names.size(); i < c; i++) {
             final String name = (String)names.get(i);
             if (name.length() > 0) {
@@ -323,7 +323,7 @@ public class PDFFilterList {
 
     private void putDecodeParams(PDFDictionary dict, List parms) {
         boolean needParmsEntry = false;
-        PDFArray array = new PDFArray();
+        PDFArray array = new PDFArray(dict);
         for (int i = 0, c = parms.size(); i < c; i++) {
             Object obj = parms.get(i);
             if (obj != null) {
index 456419f800b28ab9dd4bbe047780be642260e9ba..6ccf76c6c1da94df1df74585a69485d3e7e98874 100644 (file)
@@ -63,7 +63,7 @@ public class PDFFormXObject extends PDFXObject {
     public void setBBox(Rectangle2D bbox) {
         PDFArray array = (PDFArray)get("BBox");
         if (array == null) {
-            array = new PDFArray();
+            array = new PDFArray(this);
             array.add(bbox.getX());
             array.add(bbox.getY());
             array.add(bbox.getWidth());
@@ -105,7 +105,7 @@ public class PDFFormXObject extends PDFXObject {
         double[] m = new double[6];
         at.getMatrix(m);
         if (array == null) {
-            array = new PDFArray();
+            array = new PDFArray(this);
             array.add(m[0]);
             array.add(m[1]);
             array.add(m[2]);
@@ -170,7 +170,7 @@ public class PDFFormXObject extends PDFXObject {
     /** {@inheritDoc} */
     protected void populateStreamDict(Object lengthEntry) {
         if (get("Matrix") == null) {
-            put("Matrix", new PDFArray(new int[] {1, 0, 0, 1, 0, 0}));
+            put("Matrix", new PDFArray(this, new int[] {1, 0, 0, 1, 0, 0}));
         }
         put("Resources", resRef);
         super.populateStreamDict(lengthEntry);
index dd24240b5fb7f301c3e3995011796c0b53e51c57..f880fa6acb4735de3c4798351c8d136f9e0bb0a6 100644 (file)
@@ -105,11 +105,8 @@ public interface PDFImage {
 
     /**
      * Get the PDF reference for a soft mask.
-     *
-     * @return the PDF reference for a soft mask image
+     * @return the PDF reference for a soft mask image (or null if there's no soft mask)
      */
-    String getSoftMask();
-    
     PDFReference getSoftMaskReference();
 
     /** @return true for CMYK images generated by Adobe Photoshop */
index 4cc1741001fcffc843abdd54c6da61b4c23c0665..35f3e543d8e2af2888fc25acc89b11ae36379fc6 100644 (file)
@@ -94,7 +94,8 @@ public class PDFImageXObject extends PDFXObject {
 
         PDFICCStream pdfICCStream = pdfimage.getICCStream();
         if (pdfICCStream != null) {
-            put("ColorSpace", new PDFArray(new Object[] {new PDFName("ICCBased"), pdfICCStream}));
+            put("ColorSpace", new PDFArray(this,
+                    new Object[] {new PDFName("ICCBased"), pdfICCStream}));
         } else {
             PDFDeviceColorSpace cs = pdfimage.getColorSpace();
             put("ColorSpace", new PDFName(cs.getName()));
@@ -107,7 +108,7 @@ public class PDFImageXObject extends PDFXObject {
              */
             final Float zero = new Float(0.0f);
             final Float one = new Float(1.0f);
-            PDFArray decode = new PDFArray();
+            PDFArray decode = new PDFArray(this);
             for (int i = 0, c = pdfimage.getColorSpace().getNumComponents(); i < c; i++) {
                 decode.add(one);
                 decode.add(zero);
@@ -117,7 +118,7 @@ public class PDFImageXObject extends PDFXObject {
 
         if (pdfimage.isTransparent()) {
             PDFColor transp = pdfimage.getTransparentColor();
-            PDFArray mask = new PDFArray();
+            PDFArray mask = new PDFArray(this);
             mask.add(new Integer(transp.red255()));
             mask.add(new Integer(transp.red255()));
             mask.add(new Integer(transp.green255()));
index 4c3c3d0037495bc0115a77c1f0078d403419a49f..8c626d53f0e705c182f0584bca8612cf7f6ef224 100644 (file)
  
 package org.apache.fop.pdf;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
 /**
  * Class representing a PDF name object.
  */
@@ -65,15 +69,14 @@ public class PDFName implements PDFWritable {
         sb.append(DIGITS[ch & 0x0F]);
     }
     
-    
     /** {@inheritDoc} */
-    public String toInlinePDFString() {
+    public String toString() {
         return this.name;
     }
-    
+
     /** {@inheritDoc} */
-    public String toString() {
-        return toInlinePDFString();
+    public void outputInline(OutputStream out, Writer writer) throws IOException {
+        writer.write(toString());
     }
     
 }
index 476cfc7a2f9bd7c2c397f007f2d0c25b262768e3..4dcf0e03ee29a8d1418fdbe79b7fecdbaad9d27d 100644 (file)
@@ -108,7 +108,7 @@ public class PDFNameTreeNode extends PDFDictionary {
     private PDFArray prepareLimitsArray() {
         PDFArray limits = (PDFArray)get(LIMITS);
         if (limits == null) {
-            limits = new PDFArray(new Object[2]);
+            limits = new PDFArray(this, new Object[2]);
             put(LIMITS, limits);
         }
         if (limits.length() != 2) {
index e3fb44a8d3215230f1c35e36d29f3ae69626528a..b1af30dc074861e2ad9d7ad6071bd4f90dee6039 100644 (file)
  
 package org.apache.fop.pdf;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
 /**
  * Class representing a PDF name object.
  */
@@ -35,13 +39,13 @@ public final class PDFNull implements PDFWritable {
     }
 
     /** {@inheritDoc} */
-    public String toInlinePDFString() {
+    public String toString() {
         return "null";
     }
     
     /** {@inheritDoc} */
-    public String toString() {
-        return toInlinePDFString();
+    public void outputInline(OutputStream out, Writer writer) throws IOException {
+        writer.write(toString());
     }
     
 }
index 4e69c01d4d5ed2c588f103561e2aa7b7a4908ba9..ef1ccb45252f1a4542bf5f0c621dbc5cc6f49cb2 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- *\r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/* $Id$ */\r
-\r
-package org.apache.fop.pdf;\r
-\r
-/**\r
- * Class representing a PDF number tree node.\r
- */\r
-public class PDFNumberTreeNode extends PDFDictionary {\r
-\r
-    private static final String KIDS = "Kids";\r
-    private static final String NUMS = "Nums";\r
-    private static final String LIMITS = "Limits";\r
-\r
-    /**\r
-     * create a named destination\r
-     */\r
-    public PDFNumberTreeNode() {\r
-        /* generic creation of PDF object */\r
-        super();\r
-    }\r
-\r
-    /**\r
-     * Sets the Kids array.\r
-     * @param kids the Kids array\r
-     */\r
-    public void setKids(PDFArray kids) {\r
-        put(KIDS, kids);\r
-    }\r
-    \r
-    /**\r
-     * Returns the Kids array.\r
-     * @return the Kids array\r
-     */\r
-    public PDFArray getKids() {\r
-        return (PDFArray)get(KIDS);\r
-    }\r
-    \r
-    /**\r
-     * Sets the Nums array.\r
-     * @param nums the Nums array\r
-     */\r
-    public void setNums(PDFNumsArray nums) {\r
-        put(NUMS, nums);\r
-    }\r
-    \r
-    /**\r
-     * Returns the Nums array.\r
-     * @return the Nums array\r
-     */\r
-    public PDFNumsArray getNums() {\r
-        return (PDFNumsArray)get(NUMS);\r
-    }\r
-    \r
-    /**\r
-     * Sets the lower limit value of the Limits array.\r
-     * @param key the lower limit value\r
-     */\r
-    public void setLowerLimit(Integer key) {\r
-        PDFArray limits = prepareLimitsArray();\r
-        limits.set(0, key);\r
-    }\r
-\r
-    /**\r
-     * Returns the lower limit value of the Limits array.\r
-     * @return the lower limit value\r
-     */\r
-    public Integer getLowerLimit() {\r
-        PDFArray limits = prepareLimitsArray();\r
-        return (Integer)limits.get(0);\r
-    }\r
-\r
-    /**\r
-     * Sets the upper limit value of the Limits array.\r
-     * @param key the upper limit value\r
-     */\r
-    public void setUpperLimit(Integer key) {\r
-        PDFArray limits = prepareLimitsArray();\r
-        limits.set(1, key);\r
-    }\r
-\r
-    /**\r
-     * Returns the upper limit value of the Limits array.\r
-     * @return the upper limit value\r
-     */\r
-    public Integer getUpperLimit() {\r
-        PDFArray limits = prepareLimitsArray();\r
-        return (Integer)limits.get(1);\r
-    }\r
-\r
-\r
-    private PDFArray prepareLimitsArray() {\r
-        PDFArray limits = (PDFArray)get(LIMITS);\r
-        if (limits == null) {\r
-            limits = new PDFArray(new Object[2]);\r
-            put(LIMITS, limits);\r
-        }\r
-        if (limits.length() != 2) {\r
-            throw new IllegalStateException("Limits array must have 2 entries");\r
-        }\r
-        return limits;\r
-    }\r
-    \r
-}\r
-\r
+/*
+ * 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 number tree node.
+ */
+public class PDFNumberTreeNode extends PDFDictionary {
+
+    private static final String KIDS = "Kids";
+    private static final String NUMS = "Nums";
+    private static final String LIMITS = "Limits";
+
+    /**
+     * create a named destination
+     */
+    public PDFNumberTreeNode() {
+        /* generic creation of PDF object */
+        super();
+    }
+
+    /**
+     * Sets the Kids array.
+     * @param kids the Kids array
+     */
+    public void setKids(PDFArray kids) {
+        put(KIDS, kids);
+    }
+    
+    /**
+     * Returns the Kids array.
+     * @return the Kids array
+     */
+    public PDFArray getKids() {
+        return (PDFArray)get(KIDS);
+    }
+    
+    /**
+     * Sets the Nums array.
+     * @param nums the Nums array
+     */
+    public void setNums(PDFNumsArray nums) {
+        put(NUMS, nums);
+    }
+    
+    /**
+     * Returns the Nums array.
+     * @return the Nums array
+     */
+    public PDFNumsArray getNums() {
+        return (PDFNumsArray)get(NUMS);
+    }
+    
+    /**
+     * Sets the lower limit value of the Limits array.
+     * @param key the lower limit value
+     */
+    public void setLowerLimit(Integer key) {
+        PDFArray limits = prepareLimitsArray();
+        limits.set(0, key);
+    }
+
+    /**
+     * Returns the lower limit value of the Limits array.
+     * @return the lower limit value
+     */
+    public Integer getLowerLimit() {
+        PDFArray limits = prepareLimitsArray();
+        return (Integer)limits.get(0);
+    }
+
+    /**
+     * Sets the upper limit value of the Limits array.
+     * @param key the upper limit value
+     */
+    public void setUpperLimit(Integer key) {
+        PDFArray limits = prepareLimitsArray();
+        limits.set(1, key);
+    }
+
+    /**
+     * Returns the upper limit value of the Limits array.
+     * @return the upper limit value
+     */
+    public Integer getUpperLimit() {
+        PDFArray limits = prepareLimitsArray();
+        return (Integer)limits.get(1);
+    }
+
+
+    private PDFArray prepareLimitsArray() {
+        PDFArray limits = (PDFArray)get(LIMITS);
+        if (limits == null) {
+            limits = new PDFArray(this, new Object[2]);
+            put(LIMITS, limits);
+        }
+        if (limits.length() != 2) {
+            throw new IllegalStateException("Limits array must have 2 entries");
+        }
+        return limits;
+    }
+    
+}
+
index 55f973ccd32ea37fb6e7df10d27024b4635acddb..0a86754e8978318d5a2368e7266381c9875d606b 100644 (file)
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/* $Id: PDFArray.java 588547 2007-10-26 07:48:14Z jeremias $ */\r
\r
-package org.apache.fop.pdf;\r
-\r
-import java.util.Iterator;\r
-import java.util.Map;\r
-import java.util.SortedMap;\r
-\r
-/**\r
- * Class representing an "Nums" array object (for Number Trees).\r
- */\r
-public class PDFNumsArray extends PDFObject {\r
-    \r
-    /** Sorted Map holding the values of this array. */\r
-    protected SortedMap map = new java.util.TreeMap();\r
-\r
-    /**\r
-     * Create a new, empty array object\r
-     */\r
-    public PDFNumsArray() {\r
-        /* generic creation of PDF object */\r
-        super();\r
-    }\r
-\r
-    /**\r
-     * Returns the length of the array\r
-     * @return the length of the array\r
-     */\r
-    public int length() {\r
-        return this.map.size();\r
-    }\r
-    \r
-    /**\r
-     * Sets an entry.\r
-     * @param key the key of the value to set\r
-     * @param obj the new value\r
-     */\r
-    public void put(int key, Object obj) {\r
-        this.map.put(new Integer(key), obj);\r
-    }\r
-    \r
-    /**\r
-     * Gets an entry.\r
-     * @param key the key of requested value\r
-     * @return the requested value\r
-     */\r
-    public Object get(int key) {\r
-        return this.map.get(new Integer(key));\r
-    }\r
-    \r
-    /** {@inheritDoc} */\r
-    public String toPDFString() {\r
-        StringBuffer p = new StringBuffer(64);\r
-        if (hasObjectNumber()) {\r
-            p.append(getObjectID());\r
-        }\r
-        p.append("[");\r
-        boolean first = true;\r
-        Iterator iter = this.map.entrySet().iterator();\r
-        while (iter.hasNext()) {\r
-            Map.Entry entry = (Map.Entry)iter.next();\r
-            if (!first) {\r
-                p.append(" ");\r
-            }\r
-            first = false;\r
-            formatObject(entry.getKey(), p);\r
-            p.append(" ");\r
-            formatObject(entry.getValue(), p);\r
-        }\r
-        p.append("]");\r
-        if (hasObjectNumber()) {\r
-            p.append("\nendobj\n");\r
-        }\r
-        return p.toString();\r
-    }\r
-\r
-}\r
+/*
+ * 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;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.SortedMap;
+
+import org.apache.commons.io.output.CountingOutputStream;
+
+/**
+ * Class representing an "Nums" array object (for Number Trees).
+ */
+public class PDFNumsArray extends PDFObject {
+    
+    /** Sorted Map holding the values of this array. */
+    protected SortedMap map = new java.util.TreeMap();
+
+    /**
+     * Create a new, empty array object.
+     * @param parent the object's parent if any
+     */
+    public PDFNumsArray(PDFObject parent) {
+        super(parent);
+    }
+
+    /**
+     * Returns the length of the array
+     * @return the length of the array
+     */
+    public int length() {
+        return this.map.size();
+    }
+    
+    /**
+     * Sets an entry.
+     * @param key the key of the value to set
+     * @param obj the new value
+     */
+    public void put(int key, Object obj) {
+        this.map.put(new Integer(key), obj);
+    }
+    
+    /**
+     * Gets an entry.
+     * @param key the key of requested value
+     * @return the requested value
+     */
+    public Object get(int key) {
+        return this.map.get(new Integer(key));
+    }
+    
+    /** {@inheritDoc} */
+    protected int output(OutputStream stream) throws IOException {
+        CountingOutputStream cout = new CountingOutputStream(stream);
+        Writer writer = PDFDocument.getWriterFor(cout);
+        if (hasObjectNumber()) {
+            writer.write(getObjectID());
+        }
+        
+        writer.write('[');
+        boolean first = true;
+        Iterator iter = this.map.entrySet().iterator();
+        while (iter.hasNext()) {
+            Map.Entry entry = (Map.Entry)iter.next();
+            if (!first) {
+                writer.write(" ");
+            }
+            first = false;
+            formatObject(entry.getKey(), cout, writer);
+            writer.write(" ");
+            formatObject(entry.getValue(), cout, writer);
+        }
+        writer.write(']');
+        
+        if (hasObjectNumber()) {
+            writer.write("\nendobj\n");
+        }
+        
+        writer.flush();
+        return cout.getCount();
+    }
+    
+}
index cab6b75f2a3c7478557a19c6813acb239ed93eee..f5318357411d310c38cfa55cd2219d3778d686c2 100644 (file)
@@ -22,6 +22,7 @@ package org.apache.fop.pdf;
 // Java
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.Writer;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
@@ -57,6 +58,9 @@ public abstract class PDFObject implements PDFWritable {
      */
     private PDFDocument document;
 
+    /** the parent PDFObject (may be null and may not always be set, needed for encryption) */
+    private PDFObject parent;
+    
     /**
      * Returns the object's number.
      * @return the PDF Object number
@@ -68,6 +72,21 @@ public abstract class PDFObject implements PDFWritable {
         return this.objnum;
     }
     
+    /**
+     * Default constructor.
+     */
+    public PDFObject() {
+        //nop
+    }
+    
+    /**
+     * Constructor for direct objects.
+     * @param parent the containing PDFObject instance
+     */
+    public PDFObject(PDFObject parent) {
+        setParent(parent);
+    }
+    
     /**
      * Indicates whether this PDFObject has already been assigned an 
      * object number.
@@ -102,7 +121,13 @@ public abstract class PDFObject implements PDFWritable {
      * has not been assigned)
      */
     public final PDFDocument getDocument() {
-        return this.document;
+        if (this.document != null) {
+            return this.document;
+        } else if (getParent() != null) {
+            return getParent().getDocument();
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -127,6 +152,22 @@ public abstract class PDFObject implements PDFWritable {
         this.document = doc;
     }
 
+    /**
+     * Returns this objects's parent. The parent is null if it is a "direct object".
+     * @return the parent or null if there's no parent (or it hasn't been set)
+     */
+    public PDFObject getParent() {
+        return this.parent;
+    }
+    
+    /**
+     * Sets the direct parent object.
+     * @param parent the direct parent
+     */
+    public void setParent(PDFObject parent) {
+        this.parent = parent;
+    }
+
     /**
      * Returns the PDF representation of the Object ID.
      * @return the Object ID
@@ -169,6 +210,16 @@ public abstract class PDFObject implements PDFWritable {
         return pdf.length;
     }
 
+    /** {@inheritDoc} */
+    public void outputInline(OutputStream out, Writer writer) throws IOException {
+        if (hasObjectNumber()) {
+            writer.write(referencePDF());
+        } else {
+            writer.flush();
+            output(out);
+        }
+    }
+    
     /**
      * Encodes the object as a byte array for output to a PDF file.
      *
@@ -184,7 +235,9 @@ public abstract class PDFObject implements PDFWritable {
      * is normally converted/encoded to a byte array by toPDF(). Only use 
      * this method to implement the serialization if the object can be fully 
      * represented as text. If the PDF representation of the object contains
-     * binary content use toPDF() or output(OutputStream) instead.
+     * binary content use toPDF() or output(OutputStream) instead. This applies
+     * to any object potentially containing a string object because string object
+     * are encrypted and therefore need to be binary.
      * @return String the String representation
      */
     protected String toPDFString() {
@@ -192,20 +245,6 @@ public abstract class PDFObject implements PDFWritable {
                     + "Use output(OutputStream) instead.");
     }
     
-    /**
-     * Returns a representation of this object for in-object placement, i.e. if the object
-     * has an object number its reference is returned. Otherwise, its PDF representation is
-     * returned.
-     * @return the String representation
-     */
-    public String toInlinePDFString() {
-        if (hasObjectNumber()) {
-            return referencePDF();
-        } else {
-            return toPDFString();
-        }
-    }
-    
     /**
      * Converts text to a byte array for writing to a PDF file.
      * @param text text to convert/encode
@@ -250,23 +289,27 @@ public abstract class PDFObject implements PDFWritable {
     /**
      * Formats an object for serialization to PDF.
      * @param obj the object
-     * @param sb the StringBuffer to write to
+     * @param out the OutputStream to write to
+     * @param writer a Writer for text content (will always be a wrapper around the above
+     *                  OutputStream. Make sure <code>flush</code> is called when mixing calls)
+     * @throws IOException If an I/O error occurs
      */
-    protected void formatObject(Object obj, StringBuffer sb) {
+    protected void formatObject(Object obj, OutputStream out, Writer writer) throws IOException {
         if (obj == null) {
-            sb.append("null");
+            writer.write("null");
         } else if (obj instanceof PDFWritable) {
-            sb.append(((PDFWritable)obj).toInlinePDFString());
+            ((PDFWritable)obj).outputInline(out, writer);
         } else if (obj instanceof Number) {
             if (obj instanceof Double || obj instanceof Float) {
-                sb.append(PDFNumber.doubleOut(((Number)obj).doubleValue()));
+                writer.write(PDFNumber.doubleOut(((Number)obj).doubleValue()));
             } else {
-                sb.append(obj);
+                writer.write(obj.toString());
             }
         } else if (obj instanceof Boolean) {
-            sb.append(obj);
+            writer.write(obj.toString());
         } else {
-            sb.append("(").append(obj).append(")");
+            writer.flush();
+            out.write(encodeText(obj.toString()));
         }
     }
     
index bb02a3c7eb36fc48514cb1e1e2e463adc14a106d..1a51c4155144689da6495fcabfa82f1c9188c069 100644 (file)
@@ -1,48 +1,48 @@
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- * \r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/* $Id$ */\r
\r
-package org.apache.fop.pdf;\r
-\r
-/**\r
- * Class representing a PDF /PageLabels dictionary.\r
- */\r
-public class PDFPageLabels extends PDFNumberTreeNode {\r
-    \r
-    /**\r
-     * Create the /PageLabels dictionary\r
-     */\r
-    public PDFPageLabels() {\r
-        super();\r
-    }\r
-\r
-    /**\r
-     * Returns the Nums object\r
-     * @return the Nums object (an empty PDFNumsArray for the "/Nums" entry is created\r
-     *       if it doesn't exist)\r
-     */\r
-    public PDFNumsArray getNums() {\r
-        PDFNumsArray nums = super.getNums();\r
-        if (nums == null) {\r
-            nums = new PDFNumsArray();\r
-            setNums(nums);\r
-        }\r
-        return nums;\r
-    }\r
-    \r
-}\r
+/*
+ * 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 /PageLabels dictionary.
+ */
+public class PDFPageLabels extends PDFNumberTreeNode {
+    
+    /**
+     * Create the /PageLabels dictionary
+     */
+    public PDFPageLabels() {
+        super();
+    }
+
+    /**
+     * Returns the Nums object
+     * @return the Nums object (an empty PDFNumsArray for the "/Nums" entry is created
+     *       if it doesn't exist)
+     */
+    public PDFNumsArray getNums() {
+        PDFNumsArray nums = super.getNums();
+        if (nums == null) {
+            nums = new PDFNumsArray(this);
+            setNums(nums);
+        }
+        return nums;
+    }
+    
+}
index ed1a8c01628019783101ac1702203e9197a6ca09..3b615735a23bd9386d2bb43444a024156bf153ca 100644 (file)
@@ -19,6 +19,9 @@
  
 package org.apache.fop.pdf;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
 import java.lang.ref.Reference;
 import java.lang.ref.SoftReference;
 
@@ -68,13 +71,13 @@ public class PDFReference implements PDFWritable {
     }
     
     /** {@inheritDoc} */
-    public String toInlinePDFString() {
+    public String toString() {
         return this.indirectReference;
     }
     
     /** {@inheritDoc} */
-    public String toString() {
-        return toInlinePDFString();
+    public void outputInline(OutputStream out, Writer writer) throws IOException {
+        writer.write(toString());
     }
     
 }
index 1a54a209ffa6e8ce9cf41a7952d896e8e158e1ae..54cadf6169dec2d7c1a4b1d121c67ec7c4be1b8e 100644 (file)
@@ -225,7 +225,7 @@ public class PDFRoot extends PDFDictionary {
         if (getDocumentSafely().getPDFVersion() >= PDFDocument.PDF_VERSION_1_4) {
             PDFArray outputIntents = getOutputIntents(); 
             if (outputIntents == null) {
-                outputIntents = new PDFArray();
+                outputIntents = new PDFArray(this);
                 put("OutputIntents", outputIntents);
             }
             outputIntents.add(outputIntent);
index 23bcf9ad876115c907c9d6934d1e96ac31357835..4f024fb922b8e4107ce4d925c17ae6d3ed4246fd 100644 (file)
  
 package org.apache.fop.pdf;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
 /**
  * This interface is implemented by classes that can be serialized to a PDF file either by
  * serializing the object or by writing a indirect reference to the actual object.
@@ -26,11 +30,13 @@ package org.apache.fop.pdf;
 public interface PDFWritable {
     
     /**
-     * Returns a representation of this object for in-object placement, i.e. if the object
-     * has an object number its reference is returned. Otherwise, its PDF representation is
-     * returned.
-     * @return the String representation
+     * Writes a "direct object" (inline object) representation to the stream. A Writer is given
+     * for optimized encoding of text content. Since the Writer is buffered, make sure
+     * <code>flush()</code> is called before any direct calls to <code>out</code> are made.
+     * @param out the OutputStream (for binary content)
+     * @param writer the Writer (for text content, wraps the above OutputStream)
+     * @throws IOException if an I/O error occurs
      */
-    String toInlinePDFString();
+    void outputInline(OutputStream out, Writer writer) throws IOException;
     
 }
index c9b0e3a7b036c6d1a36686b81e43be0a1bda53c8..e60c207d673813fd08b0cd886afa029c1d48410e 100644 (file)
@@ -25,6 +25,7 @@ import java.io.OutputStream;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+
 import org.apache.fop.image.EPSImage;
 import org.apache.fop.image.FopImage;
 import org.apache.fop.image.TIFFImage;
@@ -237,11 +238,6 @@ public class FopPDFImage implements PDFImage {
         return maskRef;
     }
 
-    /** {@inheritDoc} */
-    public String getSoftMask() {
-        return softMask.toInlinePDFString();
-    }
-
     /** {@inheritDoc} */
     public PDFReference getSoftMaskReference() {
         return softMask;
index 2d8e7d5bac06efadc90c86e7d3f833c3030c44c8..f4aa5ee904c2d1e5655427d6a96915666236f80a 100644 (file)
@@ -37,7 +37,15 @@ import java.util.Map;
 import javax.xml.transform.Source;
 import javax.xml.transform.stream.StreamSource;
 
+import org.w3c.dom.Document;
+
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.CountingOutputStream;
+
+import org.apache.xmlgraphics.xmp.Metadata;
+import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter;
+import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;
+
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.apps.FOUserAgent;
 import org.apache.fop.apps.MimeConstants;
@@ -86,6 +94,7 @@ import org.apache.fop.pdf.PDFInfo;
 import org.apache.fop.pdf.PDFLink;
 import org.apache.fop.pdf.PDFMetadata;
 import org.apache.fop.pdf.PDFNumber;
+import org.apache.fop.pdf.PDFNumsArray;
 import org.apache.fop.pdf.PDFOutline;
 import org.apache.fop.pdf.PDFOutputIntent;
 import org.apache.fop.pdf.PDFPage;
@@ -102,10 +111,6 @@ import org.apache.fop.render.Graphics2DAdapter;
 import org.apache.fop.render.RendererContext;
 import org.apache.fop.util.CharUtilities;
 import org.apache.fop.util.ColorProfileUtil;
-import org.apache.xmlgraphics.xmp.Metadata;
-import org.apache.xmlgraphics.xmp.schemas.XMPBasicAdapter;
-import org.apache.xmlgraphics.xmp.schemas.XMPBasicSchema;
-import org.w3c.dom.Document;
 
 /**
  * Renderer that renders areas to PDF.
@@ -357,7 +362,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
         this.pdfDoc.getInfo().setTitle(userAgent.getTitle());
         this.pdfDoc.getInfo().setKeywords(userAgent.getKeywords());
         this.pdfDoc.setFilterMap(filterMap);
-        this.pdfDoc.outputHeader(stream);
+        this.pdfDoc.outputHeader(ostream);
 
         //Setup encryption if necessary
         PDFEncryptionManager.setupPDFEncryption(encryptionParams, this.pdfDoc);
@@ -725,11 +730,12 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
             pageLabels = this.pdfDoc.getFactory().makePageLabels();
             this.pdfDoc.getRoot().setPageLabels(pageLabels);
         }
-        PDFDictionary dict = new PDFDictionary();
+        PDFNumsArray nums = pageLabels.getNums(); 
+        PDFDictionary dict = new PDFDictionary(nums);
         dict.put("P", page.getPageNumberString());
         //TODO If the sequence of generated page numbers were inspected, this could be
         //expressed in a more space-efficient way
-        pageLabels.getNums().put(page.getPageIndex(), dict);
+        nums.put(page.getPageIndex(), dict);
     }
     
     /**
index 829a76a6642e5a8dbe69801338d9083e2f8608c2..e666358441fdb827a4dc9b6de67e8bd01f26da97 100644 (file)
@@ -28,6 +28,9 @@
 
   <changes>
     <release version="FOP Trunk">
+      <action context="Code" dev="JM" type="fix">
+        Fixed generation of named destinations so it works when the PDF document is encrypted.
+      </action>
       <action context="Code" dev="JM" type="add">
         PostScript output now generates the bounding box DSC comments for the whole document.
       </action>