aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/java/org/apache/fop/pdf/AbstractPDFStream.java41
-rw-r--r--src/java/org/apache/fop/pdf/BitmapImage.java9
-rw-r--r--src/java/org/apache/fop/pdf/PDFArray.java72
-rw-r--r--src/java/org/apache/fop/pdf/PDFDestination.java40
-rw-r--r--src/java/org/apache/fop/pdf/PDFDests.java2
-rw-r--r--src/java/org/apache/fop/pdf/PDFDictionary.java64
-rw-r--r--src/java/org/apache/fop/pdf/PDFDocument.java19
-rw-r--r--src/java/org/apache/fop/pdf/PDFEncryptionJCE.java27
-rw-r--r--src/java/org/apache/fop/pdf/PDFFactory.java13
-rw-r--r--src/java/org/apache/fop/pdf/PDFFilterList.java4
-rw-r--r--src/java/org/apache/fop/pdf/PDFFormXObject.java6
-rw-r--r--src/java/org/apache/fop/pdf/PDFImage.java5
-rw-r--r--src/java/org/apache/fop/pdf/PDFImageXObject.java7
-rw-r--r--src/java/org/apache/fop/pdf/PDFName.java13
-rw-r--r--src/java/org/apache/fop/pdf/PDFNameTreeNode.java2
-rw-r--r--src/java/org/apache/fop/pdf/PDFNull.java10
-rw-r--r--src/java/org/apache/fop/pdf/PDFNumberTreeNode.java242
-rw-r--r--src/java/org/apache/fop/pdf/PDFNumsArray.java198
-rw-r--r--src/java/org/apache/fop/pdf/PDFObject.java91
-rw-r--r--src/java/org/apache/fop/pdf/PDFPageLabels.java96
-rw-r--r--src/java/org/apache/fop/pdf/PDFReference.java9
-rw-r--r--src/java/org/apache/fop/pdf/PDFRoot.java2
-rw-r--r--src/java/org/apache/fop/pdf/PDFWritable.java16
-rw-r--r--src/java/org/apache/fop/render/pdf/FopPDFImage.java6
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFRenderer.java20
25 files changed, 561 insertions, 453 deletions
diff --git a/src/java/org/apache/fop/pdf/AbstractPDFStream.java b/src/java/org/apache/fop/pdf/AbstractPDFStream.java
index 0ade68f89..16190da99 100644
--- a/src/java/org/apache/fop/pdf/AbstractPDFStream.java
+++ b/src/java/org/apache/fop/pdf/AbstractPDFStream.java
@@ -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();
}
/**
diff --git a/src/java/org/apache/fop/pdf/BitmapImage.java b/src/java/org/apache/fop/pdf/BitmapImage.java
index 461ec0a64..34c78ffe3 100644
--- a/src/java/org/apache/fop/pdf/BitmapImage.java
+++ b/src/java/org/apache/fop/pdf/BitmapImage.java
@@ -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;
diff --git a/src/java/org/apache/fop/pdf/PDFArray.java b/src/java/org/apache/fop/pdf/PDFArray.java
index 2dd68ad8b..2cb2adb1d 100644
--- a/src/java/org/apache/fop/pdf/PDFArray.java
+++ b/src/java/org/apache/fop/pdf/PDFArray.java
@@ -19,9 +19,14 @@
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]);
@@ -118,6 +124,17 @@ public class PDFArray extends PDFObject {
* 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
+ */
public void add(Object obj) {
this.values.add(obj);
}
@@ -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();
}
-
+
}
diff --git a/src/java/org/apache/fop/pdf/PDFDestination.java b/src/java/org/apache/fop/pdf/PDFDestination.java
index c59b20cfc..eaf38449d 100644
--- a/src/java/org/apache/fop/pdf/PDFDestination.java
+++ b/src/java/org/apache/fop/pdf/PDFDestination.java
@@ -19,6 +19,12 @@
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();
}
diff --git a/src/java/org/apache/fop/pdf/PDFDests.java b/src/java/org/apache/fop/pdf/PDFDests.java
index 463ef8d7e..ff2d6a237 100644
--- a/src/java/org/apache/fop/pdf/PDFDests.java
+++ b/src/java/org/apache/fop/pdf/PDFDests.java
@@ -40,7 +40,7 @@ public class PDFDests extends PDFNameTreeNode {
*/
public PDFDests(List destinationList) {
this();
- setNames(new PDFArray(destinationList));
+ setNames(new PDFArray(this, destinationList));
}
}
diff --git a/src/java/org/apache/fop/pdf/PDFDictionary.java b/src/java/org/apache/fop/pdf/PDFDictionary.java
index c183871b5..49d48312c 100644
--- a/src/java/org/apache/fop/pdf/PDFDictionary.java
+++ b/src/java/org/apache/fop/pdf/PDFDictionary.java
@@ -19,10 +19,15 @@
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,14 +45,21 @@ 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
* @param value the value
@@ -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");
}
}
diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java
index 045d52173..bd44595fb 100644
--- a/src/java/org/apache/fop/pdf/PDFDocument.java
+++ b/src/java/org/apache/fop/pdf/PDFDocument.java
@@ -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;
@@ -317,6 +318,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
*
* @param producer string indicating application producing the PDF
diff --git a/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java b/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java
index 203ca90e1..5da37076c 100644
--- a/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java
+++ b/src/java/org/apache/fop/pdf/PDFEncryptionJCE.java
@@ -20,20 +20,20 @@
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) {
diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java
index f851abae7..f3069e85e 100644
--- a/src/java/org/apache/fop/pdf/PDFFactory.java
+++ b/src/java/org/apache/fop/pdf/PDFFactory.java
@@ -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;
diff --git a/src/java/org/apache/fop/pdf/PDFFilterList.java b/src/java/org/apache/fop/pdf/PDFFilterList.java
index e866fc88e..607ae174b 100644
--- a/src/java/org/apache/fop/pdf/PDFFilterList.java
+++ b/src/java/org/apache/fop/pdf/PDFFilterList.java
@@ -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) {
diff --git a/src/java/org/apache/fop/pdf/PDFFormXObject.java b/src/java/org/apache/fop/pdf/PDFFormXObject.java
index 456419f80..6ccf76c6c 100644
--- a/src/java/org/apache/fop/pdf/PDFFormXObject.java
+++ b/src/java/org/apache/fop/pdf/PDFFormXObject.java
@@ -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);
diff --git a/src/java/org/apache/fop/pdf/PDFImage.java b/src/java/org/apache/fop/pdf/PDFImage.java
index dd24240b5..f880fa6ac 100644
--- a/src/java/org/apache/fop/pdf/PDFImage.java
+++ b/src/java/org/apache/fop/pdf/PDFImage.java
@@ -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 */
diff --git a/src/java/org/apache/fop/pdf/PDFImageXObject.java b/src/java/org/apache/fop/pdf/PDFImageXObject.java
index 4cc174100..35f3e543d 100644
--- a/src/java/org/apache/fop/pdf/PDFImageXObject.java
+++ b/src/java/org/apache/fop/pdf/PDFImageXObject.java
@@ -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()));
diff --git a/src/java/org/apache/fop/pdf/PDFName.java b/src/java/org/apache/fop/pdf/PDFName.java
index 4c3c3d003..8c626d53f 100644
--- a/src/java/org/apache/fop/pdf/PDFName.java
+++ b/src/java/org/apache/fop/pdf/PDFName.java
@@ -19,6 +19,10 @@
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());
}
}
diff --git a/src/java/org/apache/fop/pdf/PDFNameTreeNode.java b/src/java/org/apache/fop/pdf/PDFNameTreeNode.java
index 476cfc7a2..4dcf0e03e 100644
--- a/src/java/org/apache/fop/pdf/PDFNameTreeNode.java
+++ b/src/java/org/apache/fop/pdf/PDFNameTreeNode.java
@@ -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) {
diff --git a/src/java/org/apache/fop/pdf/PDFNull.java b/src/java/org/apache/fop/pdf/PDFNull.java
index e3fb44a8d..b1af30dc0 100644
--- a/src/java/org/apache/fop/pdf/PDFNull.java
+++ b/src/java/org/apache/fop/pdf/PDFNull.java
@@ -19,6 +19,10 @@
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());
}
}
diff --git a/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java b/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java
index 4e69c01d4..ef1ccb452 100644
--- a/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java
+++ b/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java
@@ -1,121 +1,121 @@
-/*
- * 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(new Object[2]);
- put(LIMITS, limits);
- }
- if (limits.length() != 2) {
- throw new IllegalStateException("Limits array must have 2 entries");
- }
- return limits;
- }
-
-}
-
+/*
+ * 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;
+ }
+
+}
+
diff --git a/src/java/org/apache/fop/pdf/PDFNumsArray.java b/src/java/org/apache/fop/pdf/PDFNumsArray.java
index 55f973ccd..0a86754e8 100644
--- a/src/java/org/apache/fop/pdf/PDFNumsArray.java
+++ b/src/java/org/apache/fop/pdf/PDFNumsArray.java
@@ -1,94 +1,104 @@
-/*
- * 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: PDFArray.java 588547 2007-10-26 07:48:14Z jeremias $ */
-
-package org.apache.fop.pdf;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.SortedMap;
-
-/**
- * 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
- */
- public PDFNumsArray() {
- /* generic creation of PDF object */
- super();
- }
-
- /**
- * 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} */
- public String toPDFString() {
- StringBuffer p = new StringBuffer(64);
- if (hasObjectNumber()) {
- p.append(getObjectID());
- }
- p.append("[");
- boolean first = true;
- Iterator iter = this.map.entrySet().iterator();
- while (iter.hasNext()) {
- Map.Entry entry = (Map.Entry)iter.next();
- if (!first) {
- p.append(" ");
- }
- first = false;
- formatObject(entry.getKey(), p);
- p.append(" ");
- formatObject(entry.getValue(), p);
- }
- p.append("]");
- if (hasObjectNumber()) {
- p.append("\nendobj\n");
- }
- return p.toString();
- }
-
-}
+/*
+ * 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();
+ }
+
+}
diff --git a/src/java/org/apache/fop/pdf/PDFObject.java b/src/java/org/apache/fop/pdf/PDFObject.java
index cab6b75f2..f53183574 100644
--- a/src/java/org/apache/fop/pdf/PDFObject.java
+++ b/src/java/org/apache/fop/pdf/PDFObject.java
@@ -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
@@ -69,6 +73,21 @@ public abstract class PDFObject implements PDFWritable {
}
/**
+ * 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.
* @return True if it has 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;
+ }
}
/**
@@ -128,6 +153,22 @@ public abstract class PDFObject implements PDFWritable {
}
/**
+ * 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() {
@@ -193,20 +246,6 @@ public abstract class PDFObject implements 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
- */
- 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
* @return byte[] the resulting byte array
@@ -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()));
}
}
diff --git a/src/java/org/apache/fop/pdf/PDFPageLabels.java b/src/java/org/apache/fop/pdf/PDFPageLabels.java
index bb02a3c7e..1a51c4155 100644
--- a/src/java/org/apache/fop/pdf/PDFPageLabels.java
+++ b/src/java/org/apache/fop/pdf/PDFPageLabels.java
@@ -1,48 +1,48 @@
-/*
- * 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();
- setNums(nums);
- }
- return nums;
- }
-
-}
+/*
+ * 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;
+ }
+
+}
diff --git a/src/java/org/apache/fop/pdf/PDFReference.java b/src/java/org/apache/fop/pdf/PDFReference.java
index ed1a8c016..3b615735a 100644
--- a/src/java/org/apache/fop/pdf/PDFReference.java
+++ b/src/java/org/apache/fop/pdf/PDFReference.java
@@ -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());
}
}
diff --git a/src/java/org/apache/fop/pdf/PDFRoot.java b/src/java/org/apache/fop/pdf/PDFRoot.java
index 1a54a209f..54cadf616 100644
--- a/src/java/org/apache/fop/pdf/PDFRoot.java
+++ b/src/java/org/apache/fop/pdf/PDFRoot.java
@@ -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);
diff --git a/src/java/org/apache/fop/pdf/PDFWritable.java b/src/java/org/apache/fop/pdf/PDFWritable.java
index 23bcf9ad8..4f024fb92 100644
--- a/src/java/org/apache/fop/pdf/PDFWritable.java
+++ b/src/java/org/apache/fop/pdf/PDFWritable.java
@@ -19,6 +19,10 @@
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;
}
diff --git a/src/java/org/apache/fop/render/pdf/FopPDFImage.java b/src/java/org/apache/fop/render/pdf/FopPDFImage.java
index c9b0e3a7b..e60c207d6 100644
--- a/src/java/org/apache/fop/render/pdf/FopPDFImage.java
+++ b/src/java/org/apache/fop/render/pdf/FopPDFImage.java
@@ -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;
@@ -238,11 +239,6 @@ public class FopPDFImage implements PDFImage {
}
/** {@inheritDoc} */
- public String getSoftMask() {
- return softMask.toInlinePDFString();
- }
-
- /** {@inheritDoc} */
public PDFReference getSoftMaskReference() {
return softMask;
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
index 2d8e7d5ba..f4aa5ee90 100644
--- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java
+++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
@@ -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);
}
/**