You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by cb...@apache.org on 2012/01/06 17:03:45 UTC

svn commit: r1228243 [1/2] - in /xmlgraphics/fop/trunk: ./ src/java/org/apache/fop/pdf/ test/java/org/apache/fop/ test/java/org/apache/fop/pdf/ test/java/org/apache/fop/util/

Author: cbowditch
Date: Fri Jan  6 16:03:44 2012
New Revision: 1228243

URL: http://svn.apache.org/viewvc?rev=1228243&view=rev
Log:
Bugzilla #51644:
Tagged PDF performance improvement + tests
Submitted by: Mehdi Houshmand

Added:
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFArrayTestCase.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDestsTestCase.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDictionaryTestCase.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDocumentTestCase.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNameTestCase.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNullTestCase.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNumberTestCase.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNumsArrayTestCase.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFRectangleTestCase.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFReferenceTestCase.java
Removed:
    xmlgraphics/fop/trunk/test/java/org/apache/fop/util/PDFNumberTestCase.java
Modified:
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/AbstractPDFStream.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFArray.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDestination.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDictionary.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDocument.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEmbeddedFiles.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFName.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNull.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNumsArray.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRectangle.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFReference.java
    xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFWritable.java
    xmlgraphics/fop/trunk/status.xml
    xmlgraphics/fop/trunk/test/java/org/apache/fop/StandardTestSuite.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/UtilityCodeTestSuite.java
    xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFObjectTestCase.java

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/AbstractPDFStream.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/AbstractPDFStream.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/AbstractPDFStream.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/AbstractPDFStream.java Fri Jan  6 16:03:44 2012
@@ -21,7 +21,6 @@ package org.apache.fop.pdf;
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.Writer;
 
 import org.apache.commons.io.output.CountingOutputStream;
 
@@ -164,7 +163,7 @@ public abstract class AbstractPDFStream 
         OutputStream filteredOutput = getFilterList().applyFilters(cout);
         outputRawStreamData(filteredOutput);
         filteredOutput.close();
-        refLength.setNumber(new Integer(cout.getCount()));
+        refLength.setNumber(Integer.valueOf(cout.getCount()));
         bytesWritten += cout.getCount();
 
         //Stream trailer
@@ -180,13 +179,13 @@ public abstract class AbstractPDFStream 
      * byte arrays around so much
      * {@inheritDoc}
      */
+    @Override
     protected int output(OutputStream stream) throws IOException {
         setupFilterList();
 
         CountingOutputStream cout = new CountingOutputStream(stream);
-        Writer writer = PDFDocument.getWriterFor(cout);
-        writer.write(getObjectID());
-        //int length = 0;
+        StringBuilder textBuffer = new StringBuilder(64);
+        textBuffer.append(getObjectID());
 
         StreamCache encodedStream = null;
         PDFNumber refLength = null;
@@ -197,14 +196,14 @@ public abstract class AbstractPDFStream 
             lengthEntry = refLength;
         } else {
             encodedStream = encodeStream();
-            lengthEntry = new Integer(encodedStream.getSize() + 1);
+            lengthEntry = Integer.valueOf(encodedStream.getSize() + 1);
         }
 
         populateStreamDict(lengthEntry);
-        writeDictionary(cout, writer);
+        writeDictionary(cout, textBuffer);
 
         //Send encoded stream to target OutputStream
-        writer.flush();
+        PDFDocument.flushTextBuffer(textBuffer, cout);
         if (encodedStream == null) {
             encodeAndWriteStream(cout, refLength);
         } else {
@@ -212,8 +211,8 @@ public abstract class AbstractPDFStream 
             encodedStream.clear(); //Encoded stream can now be discarded
         }
 
-        writer.write("\nendobj\n");
-        writer.flush();
+        textBuffer.append("\nendobj\n");
+        PDFDocument.flushTextBuffer(textBuffer, cout);
         return cout.getCount();
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFArray.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFArray.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFArray.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFArray.java Fri Jan  6 16:03:44 2012
@@ -21,7 +21,6 @@ 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;
 
@@ -34,7 +33,7 @@ public class PDFArray extends PDFObject 
     /**
      * List holding the values of this array
      */
-    protected List values = new java.util.ArrayList();
+    protected List<Object> values = new java.util.ArrayList<Object>();
 
     /**
      * Create a new, empty array object
@@ -62,7 +61,7 @@ public class PDFArray extends PDFObject 
         super(parent);
 
         for (int i = 0, c = values.length; i < c; i++) {
-            this.values.add(new Integer(values[i]));
+            this.values.add(Integer.valueOf(values[i]));
         }
     }
 
@@ -85,7 +84,7 @@ public class PDFArray extends PDFObject 
      * @param parent the array's parent if any
      * @param values the actual values wrapped by this object
      */
-    public PDFArray(PDFObject parent, Collection values) {
+    public PDFArray(PDFObject parent, Collection<Object> values) {
         /* generic creation of PDF object */
         super(parent);
 
@@ -180,28 +179,29 @@ public class PDFArray extends PDFObject 
     }
 
     /** {@inheritDoc} */
+    @Override
     protected int output(OutputStream stream) throws IOException {
         CountingOutputStream cout = new CountingOutputStream(stream);
-        Writer writer = PDFDocument.getWriterFor(cout);
+        StringBuilder textBuffer = new StringBuilder(64);
         if (hasObjectNumber()) {
-            writer.write(getObjectID());
+            textBuffer.append(getObjectID());
         }
 
-        writer.write('[');
+        textBuffer.append('[');
         for (int i = 0; i < values.size(); i++) {
             if (i > 0) {
-                writer.write(' ');
+                textBuffer.append(' ');
             }
             Object obj = this.values.get(i);
-            formatObject(obj, cout, writer);
+            formatObject(obj, cout, textBuffer);
         }
-        writer.write(']');
+        textBuffer.append(']');
 
         if (hasObjectNumber()) {
-            writer.write("\nendobj\n");
+            textBuffer.append("\nendobj\n");
         }
 
-        writer.flush();
+        PDFDocument.flushTextBuffer(textBuffer, cout);
         return cout.getCount();
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDestination.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDestination.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDestination.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDestination.java Fri Jan  6 16:03:44 2012
@@ -21,7 +21,6 @@ package org.apache.fop.pdf;
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.Writer;
 
 import org.apache.commons.io.output.CountingOutputStream;
 
@@ -52,15 +51,16 @@ public class PDFDestination extends PDFO
     }
 
     /** {@inheritDoc} */
+    @Override
     protected int output(OutputStream stream) throws IOException {
         CountingOutputStream cout = new CountingOutputStream(stream);
-        Writer writer = PDFDocument.getWriterFor(cout);
+        StringBuilder textBuffer = new StringBuilder(64);
 
-        formatObject(getIDRef(), cout, writer);
-        writer.write(' ');
-        formatObject(goToReference, cout, writer);
+        formatObject(getIDRef(), cout, textBuffer);
+        textBuffer.append(' ');
+        formatObject(goToReference, cout, textBuffer);
 
-        writer.flush();
+        PDFDocument.flushTextBuffer(textBuffer, cout);
         return cout.getCount();
     }
 
@@ -70,6 +70,7 @@ public class PDFDestination extends PDFO
      * @param goToReference the reference to set in the associated DestinationData object.
      * @deprecated use setGoToReference(Object) instead
      */
+    @Deprecated
     public void setGoToReference(String goToReference) {
         this.goToReference = goToReference;
     }
@@ -107,6 +108,7 @@ public class PDFDestination extends PDFO
      * @param obj the object to compare
      * @return true if this equals other object
      */
+    @Override
     public boolean equals(Object obj) {
         if (this == obj) {
             return true;
@@ -125,6 +127,7 @@ public class PDFDestination extends PDFO
     }
 
     /** {@inheritDoc} */
+    @Override
     public int hashCode() {
         return getIDRef().hashCode();
     }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDictionary.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDictionary.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDictionary.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDictionary.java Fri Jan  6 16:03:44 2012
@@ -21,8 +21,6 @@ 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;
 
@@ -36,13 +34,13 @@ public class PDFDictionary extends PDFOb
     /**
      * the entry map
      */
-    protected Map entries = new java.util.HashMap();
+    protected Map<String, Object> entries = new java.util.HashMap<String, Object>();
 
     /**
      * maintains the order of the entries added to the entry map. Whenever you modify
      * "entries", always make sure you adjust this list accordingly.
      */
-    protected List order = new java.util.ArrayList();
+    protected List<String> order = new java.util.ArrayList<String>();
 
     /**
      * Create a new dictionary object.
@@ -86,7 +84,7 @@ public class PDFDictionary extends PDFOb
         if (!entries.containsKey(name)) {
             this.order.add(name);
         }
-        this.entries.put(name, new Integer(value));
+        this.entries.put(name, Integer.valueOf(value));
     }
 
     /**
@@ -99,51 +97,50 @@ public class PDFDictionary extends PDFOb
     }
 
     /** {@inheritDoc} */
+    @Override
     protected int output(OutputStream stream) throws IOException {
         CountingOutputStream cout = new CountingOutputStream(stream);
-        Writer writer = PDFDocument.getWriterFor(cout);
+        StringBuilder textBuffer = new StringBuilder(64);
         if (hasObjectNumber()) {
-            writer.write(getObjectID());
+            textBuffer.append(getObjectID());
         }
 
-        writeDictionary(cout, writer);
+        writeDictionary(cout, textBuffer);
 
         if (hasObjectNumber()) {
-            writer.write("\nendobj\n");
+            textBuffer.append("\nendobj\n");
         }
 
-        writer.flush();
+        PDFDocument.flushTextBuffer(textBuffer, cout);
         return cout.getCount();
     }
 
     /**
      * Writes the contents of the dictionary to a StringBuffer.
      * @param out the OutputStream (for binary content)
-     * @param writer the Writer (for text content, wraps the above OutputStream)
+     * @param textBuffer the text buffer for text output
      * @throws IOException if an I/O error occurs
      */
-    protected void writeDictionary(OutputStream out, Writer writer) throws IOException {
-        writer.write("<<");
+    protected void writeDictionary(OutputStream out, StringBuilder textBuffer) throws IOException {
+        textBuffer.append("<<");
         boolean compact = (this.order.size() <= 2);
-        Iterator iter = this.order.iterator();
-        while (iter.hasNext()) {
-            String key = (String)iter.next();
+        for (String key : this.order) {
             if (compact) {
-                writer.write(' ');
+                textBuffer.append(' ');
             } else {
-                writer.write("\n  ");
+                textBuffer.append("\n  ");
             }
-            writer.write(PDFName.escapeName(key));
-            writer.write(' ');
+            textBuffer.append(PDFName.escapeName(key));
+            textBuffer.append(' ');
             Object obj = this.entries.get(key);
-            formatObject(obj, out, writer);
+            formatObject(obj, out, textBuffer);
         }
         if (compact) {
-            writer.write(' ');
+            textBuffer.append(' ');
         } else {
-            writer.write('\n');
+            textBuffer.append('\n');
         }
-        writer.write(">>\n");
+        textBuffer.append(">>\n");
     }
 
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDocument.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDocument.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDocument.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFDocument.java Fri Jan  6 16:03:44 2012
@@ -24,7 +24,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
-import java.io.Writer;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -274,20 +273,17 @@ 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!");
-        }
+     * Flushes the given text buffer to an output stream with the right encoding and resets
+     * the text buffer. This is used to efficiently switch between outputting text and binary
+     * content.
+     * @param textBuffer the text buffer
+     * @param out the output stream to flush the text content to
+     * @throws IOException if an I/O error occurs while writing to the output stream
+     */
+    public static void flushTextBuffer(StringBuilder textBuffer, OutputStream out)
+            throws IOException {
+        out.write(encode(textBuffer.toString()));
+        textBuffer.setLength(0);
     }
 
     /**

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEmbeddedFiles.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEmbeddedFiles.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEmbeddedFiles.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFEmbeddedFiles.java Fri Jan  6 16:03:44 2012
@@ -21,7 +21,6 @@ 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;
@@ -39,9 +38,9 @@ public class PDFEmbeddedFiles extends PD
     }
 
     /** {@inheritDoc} */
-    protected void writeDictionary(OutputStream out, Writer writer) throws IOException {
+    protected void writeDictionary(OutputStream out, StringBuilder textBuffer) throws IOException {
         sortNames(); //Sort the names before writing them out
-        super.writeDictionary(out, writer);
+        super.writeDictionary(out, textBuffer);
     }
 
     private void sortNames() {

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFName.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFName.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFName.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFName.java Fri Jan  6 16:03:44 2012
@@ -21,7 +21,6 @@ package org.apache.fop.pdf;
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.Writer;
 
 import org.apache.commons.io.output.CountingOutputStream;
 
@@ -49,7 +48,7 @@ public class PDFName extends PDFObject {
      * @return the escaped name
      */
     static String escapeName(String name) {
-        StringBuffer sb = new StringBuffer(Math.min(16, name.length() + 4));
+        StringBuilder sb = new StringBuilder(Math.min(16, name.length() + 4));
         boolean skipFirst = false;
         sb.append('/');
         if (name.startsWith("/")) {
@@ -72,7 +71,7 @@ public class PDFName extends PDFObject {
         = {'0', '1', '2', '3', '4', '5', '6', '7',
            '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
 
-    private static void toHex(char ch, StringBuffer sb) {
+    private static void toHex(char ch, StringBuilder sb) {
         if (ch >= 256) {
             throw new IllegalArgumentException(
                     "Only 8-bit characters allowed by this implementation");
@@ -82,6 +81,7 @@ public class PDFName extends PDFObject {
     }
 
     /** {@inheritDoc} */
+    @Override
     public String toString() {
         return this.name;
     }
@@ -110,29 +110,30 @@ public class PDFName extends PDFObject {
 
 
     /** {@inheritDoc} */
+    @Override
     protected int output(OutputStream stream) throws IOException {
         CountingOutputStream cout = new CountingOutputStream(stream);
-        Writer writer = PDFDocument.getWriterFor(cout);
+        StringBuilder textBuffer = new StringBuilder(64);
         if (hasObjectNumber()) {
-            writer.write(getObjectID());
+            textBuffer.append(getObjectID());
         }
 
-        writer.write(toString());
+        textBuffer.append(toString());
 
         if (hasObjectNumber()) {
-            writer.write("\nendobj\n");
+            textBuffer.append("\nendobj\n");
         }
 
-        writer.flush();
+        PDFDocument.flushTextBuffer(textBuffer, cout);
         return cout.getCount();
     }
 
-    /** {@inheritDoc} */
-    public void outputInline(OutputStream out, Writer writer) throws IOException {
+    @Override
+    public void outputInline(OutputStream out, StringBuilder textBuffer) throws IOException {
         if (hasObjectNumber()) {
-            writer.write(referencePDF());
+            textBuffer.append(referencePDF());
         } else {
-            writer.write(toString());
+            textBuffer.append(toString());
         }
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNull.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNull.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNull.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNull.java Fri Jan  6 16:03:44 2012
@@ -21,7 +21,6 @@ package org.apache.fop.pdf;
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.Writer;
 
 /**
  * Class representing a PDF name object.
@@ -38,13 +37,14 @@ public final class PDFNull implements PD
     }
 
     /** {@inheritDoc} */
+    @Override
     public String toString() {
         return "null";
     }
 
     /** {@inheritDoc} */
-    public void outputInline(OutputStream out, Writer writer) throws IOException {
-        writer.write(toString());
+    public void outputInline(OutputStream out, StringBuilder textBuffer) throws IOException {
+        textBuffer.append(toString());
     }
 
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNumsArray.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNumsArray.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNumsArray.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFNumsArray.java Fri Jan  6 16:03:44 2012
@@ -21,8 +21,6 @@ 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;
 
@@ -34,7 +32,7 @@ import org.apache.commons.io.output.Coun
 public class PDFNumsArray extends PDFObject {
 
     /** Sorted Map holding the values of this array. */
-    protected SortedMap map = new java.util.TreeMap();
+    protected SortedMap<Integer, Object> map = new java.util.TreeMap<Integer, Object>();
 
     /**
      * Create a new, empty array object.
@@ -67,7 +65,7 @@ public class PDFNumsArray extends PDFObj
      * @param obj the new value
      */
     public void put(int key, Object obj) {
-        put(new Integer(key), obj);
+        put(Integer.valueOf(key), obj);
     }
 
     /**
@@ -85,37 +83,36 @@ public class PDFNumsArray extends PDFObj
      * @return the requested value
      */
     public Object get(int key) {
-        return get(new Integer(key));
+        return get(Integer.valueOf(key));
     }
 
     /** {@inheritDoc} */
+    @Override
     protected int output(OutputStream stream) throws IOException {
         CountingOutputStream cout = new CountingOutputStream(stream);
-        Writer writer = PDFDocument.getWriterFor(cout);
+        StringBuilder textBuffer = new StringBuilder(64);
         if (hasObjectNumber()) {
-            writer.write(getObjectID());
+            textBuffer.append(getObjectID());
         }
 
-        writer.write('[');
+        textBuffer.append('[');
         boolean first = true;
-        Iterator iter = this.map.entrySet().iterator();
-        while (iter.hasNext()) {
-            Map.Entry entry = (Map.Entry)iter.next();
+        for (Map.Entry<Integer, Object> entry : this.map.entrySet()) {
             if (!first) {
-                writer.write(" ");
+                textBuffer.append(" ");
             }
             first = false;
-            formatObject(entry.getKey(), cout, writer);
-            writer.write(" ");
-            formatObject(entry.getValue(), cout, writer);
+            formatObject(entry.getKey(), cout, textBuffer);
+            textBuffer.append(" ");
+            formatObject(entry.getValue(), cout, textBuffer);
         }
-        writer.write(']');
+        textBuffer.append(']');
 
         if (hasObjectNumber()) {
-            writer.write("\nendobj\n");
+            textBuffer.append("\nendobj\n");
         }
 
-        writer.flush();
+        PDFDocument.flushTextBuffer(textBuffer, cout);
         return cout.getCount();
     }
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFObject.java Fri Jan  6 16:03:44 2012
@@ -217,10 +217,15 @@ public abstract class PDFObject implemen
 
     /** {@inheritDoc} */
     public void outputInline(OutputStream out, Writer writer) throws IOException {
+        throw new UnsupportedOperationException("Don't use anymore: " + getClass().getName());
+    }
+
+    /** {@inheritDoc} */
+    public void outputInline(OutputStream out, StringBuilder textBuffer) throws IOException {
         if (hasObjectNumber()) {
-            writer.write(referencePDF());
+            textBuffer.append(referencePDF());
         } else {
-            writer.flush();
+            PDFDocument.flushTextBuffer(textBuffer, out);
             output(out);
         }
     }
@@ -302,40 +307,46 @@ public abstract class PDFObject implemen
 
     /**
      * Formats an object for serialization to PDF.
+     * <p>
+     * IMPORTANT: If you need to write out binary output, call
+     * {@link PDFDocument#flushTextBuffer(StringBuilder, OutputStream)} before writing any content
+     * to the {@link OutputStream}!
      * @param obj the object
      * @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)
+     * @param textBuffer a text buffer for text output
      * @throws IOException If an I/O error occurs
      */
-    protected void formatObject(Object obj, OutputStream out, Writer writer) throws IOException {
+    protected void formatObject(Object obj, OutputStream out, StringBuilder textBuffer)
+                throws IOException {
         if (obj == null) {
-            writer.write("null");
+            textBuffer.append("null");
         } else if (obj instanceof PDFWritable) {
-            ((PDFWritable)obj).outputInline(out, writer);
+            ((PDFWritable)obj).outputInline(out, textBuffer);
         } else if (obj instanceof Number) {
             if (obj instanceof Double || obj instanceof Float) {
-                writer.write(PDFNumber.doubleOut(((Number)obj).doubleValue()));
+                textBuffer.append(PDFNumber.doubleOut(((Number)obj).doubleValue()));
             } else {
-                writer.write(obj.toString());
+                textBuffer.append(obj.toString());
             }
         } else if (obj instanceof Boolean) {
-            writer.write(obj.toString());
+            textBuffer.append(obj.toString());
         } else if (obj instanceof byte[]) {
-            writer.flush();
+            PDFDocument.flushTextBuffer(textBuffer, out);
             encodeBinaryToHexString((byte[])obj, out);
         } else {
-            writer.flush();
+            PDFDocument.flushTextBuffer(textBuffer, out);
             out.write(encodeText(obj.toString()));
         }
     }
 
-    /** Formatting pattern for PDF date */
-    protected static final SimpleDateFormat DATE_FORMAT;
-
-    static {
-        DATE_FORMAT = new SimpleDateFormat("'D:'yyyyMMddHHmmss", Locale.ENGLISH);
-        DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));
+    /**
+     * Returns a SimpleDateFormat instance for formatting PDF date-times.
+     * @return a new SimpleDateFormat instance
+     */
+    protected SimpleDateFormat getPDFDateFormat() {
+        SimpleDateFormat df = new SimpleDateFormat("'D:'yyyyMMddHHmmss", Locale.ENGLISH);
+        df.setTimeZone(TimeZone.getTimeZone("GMT"));
+        return df;
     }
 
     /**
@@ -355,7 +366,7 @@ public abstract class PDFObject implemen
         //DateFormat is operating on GMT so adjust for time zone offset
         Date dt1 = new Date(time.getTime() + offset);
         StringBuffer sb = new StringBuffer();
-        sb.append(DATE_FORMAT.format(dt1));
+        sb.append(getPDFDateFormat().format(dt1));
 
         offset /= (1000 * 60); //Convert to minutes
 

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRectangle.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRectangle.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRectangle.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFRectangle.java Fri Jan  6 16:03:44 2012
@@ -21,7 +21,6 @@ package org.apache.fop.pdf;
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.Writer;
 
 /**
  * class representing a rectangle
@@ -78,16 +77,26 @@ public class PDFRectangle implements PDF
     }
 
     private String format() {
-        return "[" + llx + " " + lly + " " + urx + " " + ury + "]";
+        StringBuilder textBuffer = new StringBuilder(32);
+        format(textBuffer);
+        return textBuffer.toString();
+    }
+
+    private void format(StringBuilder textBuffer) {
+        textBuffer.append('[').append(llx)
+                  .append(' ').append(lly)
+                  .append(' ').append(urx)
+                  .append(' ').append(ury).append(']');
     }
 
     /** {@inheritDoc} */
+    @Override
     public String toString() {
         return "PDFRectangle" + format();
     }
 
     /** {@inheritDoc} */
-    public void outputInline(OutputStream out, Writer writer) throws IOException {
-        writer.write(format());
+    public void outputInline(OutputStream out, StringBuilder textBuffer) throws IOException {
+        format(textBuffer);
     }
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFReference.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFReference.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFReference.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFReference.java Fri Jan  6 16:03:44 2012
@@ -19,9 +19,7 @@
 
 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;
 
@@ -36,7 +34,7 @@ public class PDFReference implements PDF
     private int objectNumber;
     private int generation;
 
-    private Reference objReference;
+    private Reference<PDFObject> objReference;
 
     /**
      * Creates a new PDF reference.
@@ -45,7 +43,7 @@ public class PDFReference implements PDF
     public PDFReference(PDFObject obj) {
         this.objectNumber = obj.getObjectNumber();
         this.generation = obj.getGeneration();
-        this.objReference = new SoftReference(obj);
+        this.objReference = new SoftReference<PDFObject>(obj);
     }
 
     /**
@@ -69,7 +67,7 @@ public class PDFReference implements PDF
      */
     public PDFObject getObject() {
         if (this.objReference != null) {
-            PDFObject obj = (PDFObject)this.objReference.get();
+            PDFObject obj = this.objReference.get();
             if (obj == null) {
                 this.objReference = null;
             }
@@ -96,13 +94,16 @@ public class PDFReference implements PDF
     }
 
     /** {@inheritDoc} */
+    @Override
     public String toString() {
-        return getObjectNumber() + " " + getGeneration() + " R";
+        StringBuilder textBuffer = new StringBuilder();
+        outputInline(null, textBuffer);
+        return textBuffer.toString();
     }
 
     /** {@inheritDoc} */
-    public void outputInline(OutputStream out, Writer writer) throws IOException {
-        writer.write(toString());
+    public void outputInline(OutputStream out, StringBuilder textBuffer) {
+        textBuffer.append(getObjectNumber()).append(' ').append(getGeneration()).append(" R");
     }
 
 }

Modified: xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFWritable.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFWritable.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFWritable.java (original)
+++ xmlgraphics/fop/trunk/src/java/org/apache/fop/pdf/PDFWritable.java Fri Jan  6 16:03:44 2012
@@ -21,7 +21,6 @@ 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
@@ -30,13 +29,16 @@ import java.io.Writer;
 public interface PDFWritable {
 
     /**
-     * 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.
+     * Writes a "direct object" (inline object) representation to the stream. A text buffer is given
+     * for optimized encoding of text content.
+     * <p>
+     * IMPORTANT: If you need to write out binary output, call
+     * {@link PDFDocument#flushTextBuffer(StringBuilder, OutputStream)} before writing any content
+     * to the {@link OutputStream}!
      * @param out the OutputStream (for binary content)
-     * @param writer the Writer (for text content, wraps the above OutputStream)
+     * @param textBuffer the text buffer for text content
      * @throws IOException if an I/O error occurs
      */
-    void outputInline(OutputStream out, Writer writer) throws IOException;
+    void outputInline(OutputStream out, StringBuilder textBuffer) throws IOException;
 
 }

Modified: xmlgraphics/fop/trunk/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/status.xml?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/status.xml (original)
+++ xmlgraphics/fop/trunk/status.xml Fri Jan  6 16:03:44 2012
@@ -61,6 +61,9 @@
       documents. Example: the fix of marks layering will be such a case when it's done.
     -->
     <release version="FOP Trunk" date="TBD">
+      <action context="Code" dev="CB" type="add" fixes-bug="51664" due-to="Mehdi Houshmand">
+        Tagged PDF performance improvement plus tests
+      </action>	
       <action context="Code" dev="MH" type="add" fixes-bug="52197">
         Improved AdobeStandardEncoding support in AFM files for type1 fonts
       </action>

Modified: xmlgraphics/fop/trunk/test/java/org/apache/fop/StandardTestSuite.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/StandardTestSuite.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/StandardTestSuite.java (original)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/StandardTestSuite.java Fri Jan  6 16:03:44 2012
@@ -44,6 +44,7 @@ import org.apache.fop.render.pdf.RenderP
 import org.apache.fop.render.ps.PSTestSuite;
 import org.apache.fop.render.rtf.RichTextFormatTestSuite;
 import org.apache.fop.traits.MinOptMaxTestCase;
+import org.apache.fop.pdf.PDFLibraryTestSuite;
 
 /**
  * Test suite for basic functionality of FOP.
@@ -70,6 +71,7 @@ import org.apache.fop.traits.MinOptMaxTe
         MODCAParserTestCase.class,
         CharactersetEncoderTestCase.class,
         org.apache.fop.render.afp.AFPTestSuite.class,
+        PDFLibraryTestSuite.class,
         PSTestSuite.class,
         MinOptMaxTestCase.class,
         AdobeStandardEncodingTestCase.class,

Modified: xmlgraphics/fop/trunk/test/java/org/apache/fop/UtilityCodeTestSuite.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/UtilityCodeTestSuite.java?rev=1228243&r1=1228242&r2=1228243&view=diff
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/UtilityCodeTestSuite.java (original)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/UtilityCodeTestSuite.java Fri Jan  6 16:03:44 2012
@@ -28,12 +28,10 @@ import org.apache.fop.pdf.FileIDGenerato
 import org.apache.fop.pdf.PDFDocumentGraphics2DTestCase;
 import org.apache.fop.pdf.PDFEncryptionJCETestCase;
 import org.apache.fop.pdf.PDFFactoryTestCase;
-import org.apache.fop.pdf.PDFObjectTestCase;
 import org.apache.fop.traits.BorderPropsTestCase;
 import org.apache.fop.util.BitmapImageUtilTestCase;
 import org.apache.fop.util.ColorUtilTestCase;
 import org.apache.fop.util.ElementListUtilsTestCase;
-import org.apache.fop.util.PDFNumberTestCase;
 import org.apache.fop.util.XMLResourceBundleTestCase;
 
 /**
@@ -41,8 +39,6 @@ import org.apache.fop.util.XMLResourceBu
  */
 @RunWith(Suite.class)
 @SuiteClasses({
-    PDFNumberTestCase.class,
-    PDFObjectTestCase.class,
     ColorUtilTestCase.class,
     BorderPropsTestCase.class,
     ElementListUtilsTestCase.class,

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java?rev=1228243&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java (added)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java Fri Jan  6 16:03:44 2012
@@ -0,0 +1,92 @@
+/*
+ * 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.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test case for {@link AbstractPDFStream}.
+ */
+public class AbstractPDFStreamTestCase extends PDFObjectTestCase {
+
+    private AbstractPDFStream abstractStream;
+
+    private String textData = "This is an arbitrary string for testing.";
+
+    private static byte[] encodedBytes;
+    static {
+        int[] encoded = { 0x78, 0x9c, 0x0b, 0xc9, 0xc8, 0x2c, 0x56, 0x00, 0xa2, 0xc4, 0x3c, 0x85,
+                0xc4, 0xa2, 0xa4, 0xcc, 0x92, 0xa2, 0xc4, 0xa2, 0x4a, 0x85, 0xe2, 0x92, 0xa2, 0xcc,
+                0xbc, 0x74, 0x85, 0xb4, 0xfc, 0x22, 0x85, 0x92, 0xd4, 0xe2, 0x12, 0x20, 0x5b, 0x0f,
+                0x00, 0x2d, 0x2b, 0x0e, 0xde, 0x0a };
+        encodedBytes = new byte[encoded.length];
+        int i = 0;
+        for (int in : encoded) {
+            encodedBytes[i++] = (byte) (in & 0xff);
+        }
+    }
+    private String startStream = "1 0 obj\n" +
+                                "<< /Length 5 0 R /Filter /FlateDecode >>\n" +
+                                "stream\n";
+    private String endStream = "endstream\nendobj\n";
+
+    @Before
+    public void setUp() {
+        abstractStream = new AbstractPDFStream() {
+
+            @Override
+            protected void outputRawStreamData(OutputStream out) throws IOException {
+                out.write(textData.getBytes());
+            }
+
+            @Override
+            protected int getSizeHint() throws IOException {
+                return textData.length();
+            }
+        };
+        abstractStream.setDocument(doc);
+        abstractStream.setParent(parent);
+
+        pdfObjectUnderTest = abstractStream;
+    }
+
+    /**
+     * Tests output() - ensure that this object is correctly formatted to the output stream.
+     * @throws IOException if an I/O error occurs
+     */
+    @Test
+    public void testOutput() throws IOException {
+        // This differs from most other objects, if the object number = 0 an exception is thrown
+        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+        abstractStream.setObjectNumber(1);
+        ByteArrayOutputStream expectedStream = new ByteArrayOutputStream();
+        expectedStream.write(startStream.getBytes());
+        expectedStream.write(encodedBytes);
+        expectedStream.write(endStream.getBytes());
+        assertEquals(expectedStream.size(), abstractStream.output(outStream));
+        assertEquals(expectedStream.toString(), outStream.toString());
+    }
+}

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFArrayTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFArrayTestCase.java?rev=1228243&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFArrayTestCase.java (added)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFArrayTestCase.java Fri Jan  6 16:03:44 2012
@@ -0,0 +1,237 @@
+/*
+ * 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 static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test case for {@link PDFArray}.
+ */
+public class PDFArrayTestCase extends PDFObjectTestCase {
+    private PDFArray intArray;
+    private String intArrayOutput;
+    private PDFArray doubleArray;
+    private String doubleArrayOutput;
+    private PDFArray collectionArray;
+    private String collectionArrayOutput;
+    private PDFArray objArray;
+    private String objArrayOutput;
+
+    /** A PDF object used solely for testing */
+    private PDFNumber num;
+
+    @Before
+    public void setUp() {
+        intArray = new PDFArray(parent, new int[] {1, 2, 3, 4, 5});
+        intArrayOutput = "[1 2 3 4 5]";
+
+        doubleArray = new PDFArray(parent, new double[] {1.1, 2.2, 3.3, 4.4, 5.5});
+        doubleArrayOutput = "[1.1 2.2 3.3 4.4 5.5]";
+
+        List<Object> strList = new ArrayList<Object>();
+        strList.add("one");
+        strList.add("two");
+        strList.add("three");
+        collectionArray = new PDFArray(parent, strList);
+        collectionArrayOutput = "[(one) (two) (three)]";
+
+        // Set arbitrary values here
+        num = new PDFNumber();
+        num.setNumber(20);
+        num.setObjectNumber(4);
+        objArray = new PDFArray(parent, new Object[] {"one", 2, 3.0f, num});
+        objArrayOutput = "[(one) 2 3 4 0 R]";
+
+        // set the document
+        intArray.setDocument(doc);
+        doubleArray.setDocument(doc);
+        collectionArray.setDocument(doc);
+        objArray.setDocument(doc);
+
+        // Test the progenitor in the inheritance stack
+        objArray.setParent(parent);
+        pdfObjectUnderTest = objArray;
+    }
+
+    private void intArrayContainsTests() {
+        for (int i = 1; i <= 5; i++) {
+            assertTrue(intArray.contains(i));
+        }
+        assertFalse(intArray.contains(6));
+        assertFalse(intArray.contains(0));
+    }
+
+    private void doubleArrayContainsTests() {
+        assertTrue(doubleArray.contains(1.1));
+        assertTrue(doubleArray.contains(2.2));
+        assertTrue(doubleArray.contains(3.3));
+        assertTrue(doubleArray.contains(4.4));
+        assertTrue(doubleArray.contains(5.5));
+        assertFalse(doubleArray.contains(10.0));
+        assertFalse(doubleArray.contains(0.0));
+    }
+
+    private void collectionArrayContainsTests() {
+        assertTrue(collectionArray.contains("one"));
+        assertTrue(collectionArray.contains("two"));
+        assertTrue(collectionArray.contains("three"));
+        assertFalse(collectionArray.contains("zero"));
+        assertFalse(collectionArray.contains("four"));
+    }
+
+    private void objectArrayContainsTests() {
+        assertTrue(objArray.contains("one"));
+        assertTrue(objArray.contains(2));
+        assertTrue(objArray.contains(3.0f));
+        assertTrue(objArray.contains(num));
+        assertFalse(objArray.contains("four"));
+        assertFalse(objArray.contains(0.0));
+    }
+
+    /**
+     * Test contains() - test whether this PDFArray contains an object.
+     */
+    @Test
+    public void testContains() {
+        // Test some arbitrary values
+        intArrayContainsTests();
+        doubleArrayContainsTests();
+        collectionArrayContainsTests();
+        objectArrayContainsTests();
+    }
+
+    /**
+     * Test length() - tests the length of an array.
+     */
+    @Test
+    public void testLength() {
+        assertEquals(5, intArray.length());
+        assertEquals(5, doubleArray.length());
+        assertEquals(3, collectionArray.length());
+        assertEquals(4, objArray.length());
+
+        // Test the count is incremented when an object is added (this only
+        // needs to be tested once)
+        intArray.add(6);
+        assertEquals(6, intArray.length());
+    }
+
+    /**
+     * Test set() - tests that a particular point has been properly set.
+     */
+    @Test
+    public void testSet() {
+        PDFName name = new PDFName("zero test");
+        objArray.set(0, name);
+        assertEquals(name, objArray.get(0));
+
+        objArray.set(1, "test");
+        assertEquals("test", objArray.get(1));
+        // This goes through the set(int, double) code path rather than set(int, Object)
+        objArray.set(2, 5);
+        assertEquals(5.0, objArray.get(2));
+        try {
+            objArray.set(4, 2);
+            fail("out of bounds");
+        } catch (IndexOutOfBoundsException e) {
+            // Pass
+        }
+    }
+
+    /**
+     * Test get() - gets the object stored at a given index.
+     */
+    @Test
+    public void testGet() {
+        // Test some arbitrary values
+        for (int i = 1; i <= 5; i++) {
+            assertEquals(i, intArray.get(i - 1));
+        }
+
+        assertEquals(1.1, doubleArray.get(0));
+        assertEquals(2.2, doubleArray.get(1));
+        assertEquals(3.3, doubleArray.get(2));
+        assertEquals(4.4, doubleArray.get(3));
+        assertEquals(5.5, doubleArray.get(4));
+
+        assertEquals("one", collectionArray.get(0));
+        assertEquals("two", collectionArray.get(1));
+        assertEquals("three", collectionArray.get(2));
+
+        assertEquals("one", objArray.get(0));
+        assertEquals(2, objArray.get(1));
+        assertEquals(0, Double.compare(3.0, (Float) objArray.get(2)));
+        assertEquals(num, objArray.get(3));
+    }
+
+    /**
+     * Tests add() - tests that objects are appended to the end of the array as expected.
+     */
+    @Test
+    public void testAdd() {
+        intArray.add(new Integer(6));
+        doubleArray.add(6.6);
+        // Test some arbitrary values
+        for (int i = 1; i <= 6; i++) {
+            assertEquals(i, intArray.get(i - 1));
+        }
+
+        assertEquals(1.1, doubleArray.get(0));
+        assertEquals(2.2, doubleArray.get(1));
+        assertEquals(3.3, doubleArray.get(2));
+        assertEquals(4.4, doubleArray.get(3));
+        assertEquals(5.5, doubleArray.get(4));
+        assertEquals(6.6, doubleArray.get(5));
+
+        collectionArray.add(1);
+        assertEquals("one", collectionArray.get(0));
+        assertEquals("two", collectionArray.get(1));
+        assertEquals("three", collectionArray.get(2));
+        assertEquals(1.0, collectionArray.get(3));
+
+        objArray.add("four");
+        assertEquals("one", objArray.get(0));
+        assertEquals(2, objArray.get(1));
+        assertEquals(0, Double.compare(3.0, (Float) objArray.get(2)));
+        assertEquals("four", objArray.get(4));
+    }
+
+    /**
+     * Tests output() - tests that this object is properly streamed to the PDF document.
+     * @throws IOException error caused by I/O
+     */
+    @Test
+    public void testOutput() throws IOException {
+        testOutputStreams(intArrayOutput, intArray);
+        testOutputStreams(doubleArrayOutput, doubleArray);
+        testOutputStreams(collectionArrayOutput, collectionArray);
+        testOutputStreams(objArrayOutput, objArray);
+    }
+}

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDestsTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDestsTestCase.java?rev=1228243&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDestsTestCase.java (added)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDestsTestCase.java Fri Jan  6 16:03:44 2012
@@ -0,0 +1,64 @@
+/*
+ * 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 org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test case for {@link PDFDests}.
+ */
+public class PDFDestsTestCase extends PDFObjectTestCase {
+
+    private PDFDests dests = new PDFDests();
+    private String expectedString = "<< /Names [(number) 10 (name) /Test#20name] >>\n";
+
+    @Before
+    public void setUp() {
+        List<PDFDestination> destinations = new ArrayList<PDFDestination>();
+        PDFNumber number = new PDFNumber();
+        number.setNumber(10);
+        PDFDestination testNumber = new PDFDestination("number", number);
+        testNumber.setDocument(doc);
+        destinations.add(testNumber);
+        PDFDestination testName = new PDFDestination("name", new PDFName("Test name"));
+        testName.setDocument(doc);
+        destinations.add(testName);
+
+        dests = new PDFDests(destinations);
+        dests.setDocument(doc);
+        dests.setParent(parent);
+        pdfObjectUnderTest = dests;
+    }
+
+    /**
+     * Populate the object with some arbitrary values and ensure they are wrapped properly.
+     * @throws IOException if an I/O error occurs
+     */
+    @Test
+    public void testConstructor() throws IOException {
+        // Seems the only way to test this is by testing the output
+        testOutputStreams(expectedString, dests);
+    }
+}

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDictionaryTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDictionaryTestCase.java?rev=1228243&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDictionaryTestCase.java (added)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDictionaryTestCase.java Fri Jan  6 16:03:44 2012
@@ -0,0 +1,135 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.apache.commons.io.output.CountingOutputStream;
+import org.junit.Before;
+import org.junit.Test;
+
+
+/**
+ * Test case for {@link PDFDictionary}.
+ */
+public class PDFDictionaryTestCase extends PDFObjectTestCase {
+    /** The test subject */
+    private PDFDictionary pdfDictUnderTest;
+    private PDFArray testArray;
+    private PDFNumber testNumber;
+    /** The order in which these objects are put into the dictionary MUST be maintained. */
+    private String expectedOutput = "<<\n"
+                                  + "  /String (TestValue)\n"
+                                  + "  /int 10\n"
+                                  + "  /double 3.1\n"
+                                  + "  /array [1 (two) 20]\n"
+                                  + "  /number 20\n"
+                                  + "  /null null\n"
+                                  + ">>\n";
+
+    @Before
+    public void setUp() {
+        // A PDFNumber for testing, this DOES have a parent
+        testNumber = new PDFNumber();
+        testNumber.setParent(parent);
+        testNumber.setNumber(20);
+        // An array for testing, this DOES NOT have a parent
+        testArray = new PDFArray();
+        testArray.add(1);
+        testArray.add("two");
+        testArray.add(testNumber);
+        // Populating the dictionary with a parent, document and the various objects
+        pdfDictUnderTest = new PDFDictionary(parent);
+        pdfDictUnderTest.setDocument(doc);
+        pdfDictUnderTest.put("String", "TestValue");
+        pdfDictUnderTest.put("int", 10);
+        pdfDictUnderTest.put("double", Double.valueOf(3.1));
+        pdfDictUnderTest.put("array", testArray);
+        pdfDictUnderTest.put("number", testNumber);
+        // null is a valid PDF object
+        pdfDictUnderTest.put("null", null);
+        // test that the interface is maintained
+        pdfObjectUnderTest = pdfDictUnderTest;
+    }
+
+    /**
+     * Tests put() - tests that the object is put into the dictionary and it is handled if it is a
+     * {@link PDFObject}.
+     */
+    @Test
+    public void testPut() {
+        // The "put()" commands have already been done in setUp(), so just test them.
+        assertEquals("TestValue", pdfDictUnderTest.get("String"));
+        assertEquals(10, pdfDictUnderTest.get("int"));
+        assertEquals(3.1, pdfDictUnderTest.get("double"));
+        // With PDFObjects, if they DO NOT have a parent, the dict becomes their parent.
+        assertEquals(testArray, pdfDictUnderTest.get("array"));
+        assertEquals(pdfDictUnderTest, testArray.getParent());
+        // With PDFObjects, if they DO have a parent, the dict DOES NOT change the parent object.
+        assertEquals(testNumber, pdfDictUnderTest.get("number"));
+        // Test it doesn't explode when we try to get a non-existent entry
+        assertNull(pdfDictUnderTest.get("Not in dictionary"));
+        // Tests that we can over-write objects
+        pdfDictUnderTest.put("array", 10);
+        assertEquals(10, pdfDictUnderTest.get("array"));
+        // Test that nulls are handled appropriately
+        assertNull(pdfDictUnderTest.get("null"));
+    }
+
+    /**
+     * Tests get() - tests that objects can be properly retrieved from the dictionary.
+     */
+    @Test
+    public void testGet() {
+        // Tested fairly comprehensively in testPut().
+    }
+
+    /**
+     * Tests writeDictionary() - tests that the dictionary is properly written to the output-stream.
+     */
+    @Test
+    public void testWriteDictionary() {
+        // Ensure that the objects stored in the dictionary are streamed in the correct format.
+        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+        CountingOutputStream cout = new CountingOutputStream(outStream);
+        StringBuilder textBuffer = new StringBuilder();
+        try {
+            pdfDictUnderTest.writeDictionary(cout, textBuffer);
+            PDFDocument.flushTextBuffer(textBuffer, cout);
+            assertEquals(expectedOutput, outStream.toString());
+        } catch (IOException e) {
+            fail("IOException: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Tests output() - test that this object can write itself to an output stream.
+     * @throws IOException error caused by I/O
+     */
+    @Test
+    public void testOutput() throws IOException {
+        testOutputStreams(expectedOutput, pdfDictUnderTest);
+    }
+}

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDocumentTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDocumentTestCase.java?rev=1228243&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDocumentTestCase.java (added)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFDocumentTestCase.java Fri Jan  6 16:03:44 2012
@@ -0,0 +1,62 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Test case for {@link PDFDocument}
+ */
+public class PDFDocumentTestCase {
+
+    /**
+     * Test flushTextBuffer() - ensure that the text given will stream to the PDF document as
+     * expected.
+     * @throws IOException when an I/O error occurs
+     */
+    @Test
+    public void testFlushTextBuffer() throws IOException {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        StringBuilder textBuffer = new StringBuilder();
+        String testString = "This is a test string, just some arbitrary data.";
+        textBuffer.append(testString);
+        
+        PDFDocument.flushTextBuffer(textBuffer, out);
+        assertEquals(testString, out.toString());
+        
+        // Should reset the textBuffer
+        assertEquals(0, textBuffer.length());
+        assertEquals("", textBuffer.toString());
+        out.reset();
+
+        String[] strArray = { "Try ", "with ", "multiple ", "strings." };
+        for (String str : strArray) {
+            textBuffer.append(str);
+        }
+        String fullString = textBuffer.toString();
+        PDFDocument.flushTextBuffer(textBuffer, out);
+        assertEquals(fullString, out.toString());
+    }
+}

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java?rev=1228243&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java (added)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java Fri Jan  6 16:03:44 2012
@@ -0,0 +1,54 @@
+/*
+ * 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 junit.framework.Test;
+import junit.framework.TestSuite;
+
+
+/**
+ * Test suite for FOP's utility classes.
+ */
+public class PDFLibraryTestSuite {
+
+    /**
+     * Builds the test suite
+     * @return the test suite
+     */
+    public static Test suite() {
+        TestSuite suite = new TestSuite(
+            "Test suite for FOP's utility classes");
+        //$JUnit-BEGIN$
+        suite.addTest(new TestSuite(PDFArrayTestCase.class));
+        suite.addTest(new TestSuite(PDFDictionaryTestCase.class));
+        suite.addTest(new TestSuite(PDFNumberTestCase.class));
+        suite.addTest(new TestSuite(PDFObjectTestCase.class));
+        suite.addTest(new TestSuite(PDFNameTestCase.class));
+        suite.addTest(new TestSuite(AbstractPDFStreamTestCase.class));
+        suite.addTest(new TestSuite(PDFDestsTestCase.class));
+        suite.addTest(new TestSuite(PDFDocumentTestCase.class));
+        suite.addTest(new TestSuite(PDFNullTestCase.class));
+        suite.addTest(new TestSuite(PDFNumsArrayTestCase.class));
+        suite.addTest(new TestSuite(PDFRectangleTestCase.class));
+        suite.addTest(new TestSuite(PDFReferenceTestCase.class));
+        //$JUnit-END$
+        return suite;
+    }
+}

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNameTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNameTestCase.java?rev=1228243&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNameTestCase.java (added)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNameTestCase.java Fri Jan  6 16:03:44 2012
@@ -0,0 +1,169 @@
+/*
+ * 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.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.apache.commons.io.output.CountingOutputStream;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test class for {@link PDFName}.
+ */
+public class PDFNameTestCase extends PDFObjectTestCase {
+    private PDFName pdfName;
+
+    /**
+     * Sets up the local variables
+     */
+    @Before
+    public void setUp() {
+        pdfName = new PDFName("TestName");
+        pdfName.setParent(parent);
+        pdfName.setDocument(doc);
+
+        pdfObjectUnderTest = pdfName;
+    }
+
+    /**
+     * Tests escapeName() - tests that this method escapes the necessary characters.
+     */
+    @Test
+    public void testEscapeName() {
+        try {
+            // Test for null, this is a programming error thus the NPE
+            PDFName.escapeName(null);
+            fail("NPE not thrown when null object given to escapeName()");
+        } catch (NullPointerException e) {
+            // PASS
+        }
+        // All names are prefixed by "/", check the PDF spec for further details.
+        assertEquals("/Test", PDFName.escapeName("Test"));
+        // Check that if the name is already prefixed with "/" it doens't do it twice
+        assertEquals("/Test", PDFName.escapeName("/Test"));
+        // Test with a space in the middle
+        assertEquals("/Test#20test", PDFName.escapeName("Test test"));
+        // Test that all chars apart from ASCII '!' --> '~' are escaped
+        nonEscapedCharactersTests();
+        escapedCharactersTests();
+    }
+
+    private void escapedCharactersTests() {
+        for (char i = 0; i < '!'; i++) {
+            String str = Integer.toHexString(i >>> 4 & 0x0f).toUpperCase();
+            str += Integer.toHexString(i & 0x0f).toUpperCase();
+            assertEquals("/#" + str, PDFName.escapeName(String.valueOf(i)));
+        }
+        for (char i = '~' + 1; i < 256; i++) {
+            String str = Integer.toHexString(i >>> 4 & 0x0f).toUpperCase();
+            str += Integer.toHexString(i & 0x0f).toUpperCase();
+            assertEquals("/#" + str, PDFName.escapeName(String.valueOf(i)));
+        }
+        checkCharacterIsEscaped('#');
+        checkCharacterIsEscaped('%');
+        checkCharacterIsEscaped('(');
+        checkCharacterIsEscaped(')');
+        checkCharacterIsEscaped('<');
+        checkCharacterIsEscaped('>');
+        checkCharacterIsEscaped('[');
+        checkCharacterIsEscaped(']');
+        checkCharacterIsEscaped('>');
+    }
+
+    private void checkCharacterIsEscaped(char c) {
+        String str = Integer.toHexString(c >>> 4 & 0x0f).toUpperCase();
+        str += Integer.toHexString(c & 0x0f).toUpperCase();
+        assertEquals("/#" + str, PDFName.escapeName(String.valueOf(c)));
+    }
+
+    private void nonEscapedCharactersTests() {
+        charactersNotEscapedBetween('!', '"');
+        charactersNotEscapedBetween('*', ';');
+        charactersNotEscapedBetween('?', 'Z');
+        charactersNotEscapedBetween('^', '~');
+    }
+
+    private void charactersNotEscapedBetween(char c1, char c2) {
+        for (char i = c1; i <= c2; i++) {
+            String str = String.valueOf(i);
+            String expected = !str.equals("/") ? "/" + str : str;
+            assertEquals(expected, PDFName.escapeName(str));
+        }
+    }
+
+    /**
+     * Tests toString() - this has been overridden to return the String that PDFName wraps.
+     */
+    @Test
+    public void testToString() {
+        // The escape characters have already been tested in testEscapeName() so this doesn't need
+        // to be done twice.
+        PDFName test1 = new PDFName("test1");
+        assertEquals("/test1", test1.toString());
+        PDFName test2 = new PDFName("another test");
+        assertEquals("/another#20test", test2.toString());
+        try {
+            new PDFName(null);
+            fail("NPE not thrown when null passed to constructor");
+        } catch (NullPointerException e) {
+            // PASS
+        }
+    }
+
+    /**
+     * Tests output() - check that this object can stream itself in the correct format.
+     * @throws IOException error caused by I/O
+     */
+    @Test
+    public void testOutput() throws IOException {
+        testOutputStreams("/TestName", pdfName);
+        testOutputStreams("/test#20test", new PDFName("test test"));
+    }
+
+    /**
+     * Test outputInline() - this writes the object reference if it is a direct object (has an
+     * object number), or writes the String representation if there is no object number.
+     */
+    @Test
+    public void testOutputInline() {
+        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+        CountingOutputStream cout = new CountingOutputStream(outStream);
+        StringBuilder textBuffer = new StringBuilder();
+        try {
+            // test with no object number set.
+            pdfName.outputInline(outStream, textBuffer);
+            PDFDocument.flushTextBuffer(textBuffer, cout);
+            assertEquals("/TestName", outStream.toString());
+
+            outStream.reset();
+            // test with object number set
+            pdfName.setObjectNumber(1);
+            pdfName.outputInline(outStream, textBuffer);
+            PDFDocument.flushTextBuffer(textBuffer, cout);
+            assertEquals("1 0 R", outStream.toString());
+        } catch (IOException e) {
+            fail("IOException: " + e.getMessage());
+        }
+    }
+}

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNullTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNullTestCase.java?rev=1228243&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNullTestCase.java (added)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNullTestCase.java Fri Jan  6 16:03:44 2012
@@ -0,0 +1,49 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Test case for {@link PDFNull}.
+ */
+public class PDFNullTestCase extends PDFObjectTestCase {
+
+    /**
+     * Test outputInline() - test that "null" is printed to the output stream.
+     */
+    @Test
+    public void testOutputInline() throws IOException {
+        PDFNull obj = PDFNull.INSTANCE;
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        StringBuilder text = new StringBuilder();
+        obj.outputInline(out, text);
+        assertEquals("null", text.toString());
+
+        // Ensure previously written text is not discarded
+        obj.outputInline(out, text);
+        assertEquals("nullnull", text.toString());
+    }
+}

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNumberTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNumberTestCase.java?rev=1228243&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNumberTestCase.java (added)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNumberTestCase.java Fri Jan  6 16:03:44 2012
@@ -0,0 +1,162 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+
+/**
+ * This test tests PDFNumber's doubleOut() methods.
+ */
+public class PDFNumberTestCase extends PDFObjectTestCase {
+    /**
+     * Sets up the local variables, most of these are inherited from PDFObjectTestCase
+     */
+    @Before
+    public void setUp() {
+        pdfObjectUnderTest = new PDFNumber();
+        pdfObjectUnderTest.setParent(parent);
+        pdfObjectUnderTest.setDocument(doc);
+    }
+
+    /**
+     * Tests PDFNumber.doubleOut().
+     * @throws Exception if the test fails
+     */
+    @Test
+    public void testDoubleOut1() throws Exception {
+        //Default is 6 decimal digits
+        assertEquals("0", PDFNumber.doubleOut(0.0f));
+        assertEquals("0", PDFNumber.doubleOut(0.0000000000000000000123f));
+        assertEquals("0.1", PDFNumber.doubleOut(0.1f));
+        assertEquals("100", PDFNumber.doubleOut(100.0f));
+        assertEquals("100", PDFNumber.doubleOut(99.99999999999999999999999f));
+
+        //You'd expect 100.123456 here but DecimalFormat uses the BigDecimal.ROUND_HALF_EVEN
+        //strategy. I don't know if that's a problem. The strange thing testDoubleOut2
+        //seems to return the normally expected value. Weird.
+        assertEquals("100.123459", PDFNumber.doubleOut(100.12345611111111f));
+        assertEquals("-100.123459", PDFNumber.doubleOut(-100.12345611111111f));
+    }
+
+    /**
+     * Tests PDFNumber.doubleOut().
+     * @throws Exception if the test fails
+     */
+    public void testDoubleOut2() throws Exception {
+        //4 decimal digits in this case
+        assertEquals("0", PDFNumber.doubleOut(0.0f, 4));
+        assertEquals("0", PDFNumber.doubleOut(0.0000000000000000000123f, 4));
+        assertEquals("0.1", PDFNumber.doubleOut(0.1f, 4));
+        assertEquals("100", PDFNumber.doubleOut(100.0f, 4));
+        assertEquals("100", PDFNumber.doubleOut(99.99999999999999999999999f, 4));
+        assertEquals("100.1234", PDFNumber.doubleOut(100.12341111111111f, 4));
+        assertEquals("-100.1234", PDFNumber.doubleOut(-100.12341111111111f, 4));
+    }
+
+    /**
+     * Tests PDFNumber.doubleOut().
+     * @throws Exception if the test fails
+     */
+    public void testDoubleOut3() throws Exception {
+        //0 decimal digits in this case
+        assertEquals("0", PDFNumber.doubleOut(0.0f, 0));
+        assertEquals("0", PDFNumber.doubleOut(0.1f, 0));
+        assertEquals("1", PDFNumber.doubleOut(0.6f, 0));
+        assertEquals("100", PDFNumber.doubleOut(100.1234f, 0));
+        assertEquals("-100", PDFNumber.doubleOut(-100.1234f, 0));
+    }
+
+    /**
+     * Tests PDFNumber.doubleOut(). Special cases (former bugs).
+     * @throws Exception if the test fails
+     */
+    public void testDoubleOut4() throws Exception {
+        double d = Double.parseDouble("5.7220458984375E-6");
+        assertEquals("0.000006", PDFNumber.doubleOut(d));
+        assertEquals("0", PDFNumber.doubleOut(d, 4));
+        assertEquals("0.00000572", PDFNumber.doubleOut(d, 8));
+    }
+
+    /**
+     * Tests PDFNumber.doubleOut(). Tests for wrong parameters.
+     * @throws Exception if the test fails
+     */
+    public void testDoubleOutWrongParameters() throws Exception {
+        try {
+            PDFNumber.doubleOut(0.1f, -1);
+            fail("IllegalArgument expected!");
+        } catch (IllegalArgumentException iae) {
+            //we want that
+        }
+        try {
+            PDFNumber.doubleOut(0.1f, 17); //We support max 16 decimal digits
+            fail("IllegalArgument expected!");
+        } catch (IllegalArgumentException iae) {
+            //we want that
+        }
+        try {
+            PDFNumber.doubleOut(0.1f, 98274659);
+            fail("IllegalArgument expected!");
+        } catch (IllegalArgumentException iae) {
+            //we want that
+        }
+        try {
+            PDFNumber.doubleOut(null);
+            fail("NullPointer expected!");
+        } catch (NullPointerException e) {
+            // PASS
+        }
+    }
+
+    /**
+     * Tests both getNumber() and setNumber() - basic getter/setter methods... Why there isn't a
+     * constructor is beyond me...
+     */
+    public void testGetSetNumber() {
+        PDFNumber pdfNum = new PDFNumber();
+        // Check with a floating point number
+        pdfNum.setNumber(1.111f);
+        assertEquals(1.111f, pdfNum.getNumber());
+        // try with an int
+        pdfNum.setNumber(2);
+        assertEquals(2, pdfNum.getNumber());
+        // See what happens with a null... make sure it doesn't explode
+        pdfNum.setNumber(null);
+        assertEquals(null, pdfNum.getNumber());
+    }
+
+    /**
+     * Tests toPDFString() - this serializes PDFNumber to PDF format.
+     * @throws IOException error caused by I/O
+     */
+    public void testToPDFString() throws IOException {
+        PDFNumber testSubject = new PDFNumber();
+        testSubject.setNumber(1.0001);
+        testOutputStreams("1.0001", testSubject);
+        testSubject.setNumber(999);
+        testOutputStreams("999", testSubject);
+    }
+}

Added: xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNumsArrayTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNumsArrayTestCase.java?rev=1228243&view=auto
==============================================================================
--- xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNumsArrayTestCase.java (added)
+++ xmlgraphics/fop/trunk/test/java/org/apache/fop/pdf/PDFNumsArrayTestCase.java Fri Jan  6 16:03:44 2012
@@ -0,0 +1,54 @@
+/*
+ * 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 org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+
+/**
+ * Test case for {@link PDFNumsArray}.
+ */
+public class PDFNumsArrayTestCase extends PDFObjectTestCase {
+    private PDFNumsArray numsArray;
+    private String expectedString = "[0 /Test#20name 1 10]";
+
+    @Before
+    public void setUp() {
+        numsArray = new PDFNumsArray(parent);
+        numsArray.put(0, new PDFName("Test name"));
+        PDFNumber num = new PDFNumber();
+        num.setNumber(10);
+        numsArray.put(1, num);
+        numsArray.setDocument(doc);
+
+        pdfObjectUnderTest = numsArray;
+    }
+
+    /**
+     * Test output() - ensure that this object is properly outputted to the PDF document.
+     * @throws IOException if an I/O error occurs
+     */
+    @Test
+    public void testOutput() throws IOException {
+        testOutputStreams(expectedString, numsArray);
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org