]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Added support for PDF object streams. Temp_PDF_ObjectStreams Temp_PDF_ObjectStreams
authorVincent Hennebert <vhennebert@apache.org>
Wed, 21 Mar 2012 15:12:43 +0000 (15:12 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Wed, 21 Mar 2012 15:12:43 +0000 (15:12 +0000)
When accessibility is enabled and PDF version 1.5 selected, the structure tree will be stored in object streams in order to reduce the size of the final PDF.
This can lead to file reductions by up to 75%

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

151 files changed:
src/java/org/apache/fop/pdf/AbstractPDFStream.java
src/java/org/apache/fop/pdf/CompressedObject.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/ObjectStream.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/ObjectStreamManager.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/PDFAnnotList.java
src/java/org/apache/fop/pdf/PDFArray.java
src/java/org/apache/fop/pdf/PDFCIDFont.java
src/java/org/apache/fop/pdf/PDFCMap.java
src/java/org/apache/fop/pdf/PDFDestination.java
src/java/org/apache/fop/pdf/PDFDictionary.java
src/java/org/apache/fop/pdf/PDFDocument.java
src/java/org/apache/fop/pdf/PDFEncryption.java
src/java/org/apache/fop/pdf/PDFEncryptionJCE.java
src/java/org/apache/fop/pdf/PDFFactory.java
src/java/org/apache/fop/pdf/PDFFilterList.java
src/java/org/apache/fop/pdf/PDFFont.java
src/java/org/apache/fop/pdf/PDFFormXObject.java
src/java/org/apache/fop/pdf/PDFFunction.java
src/java/org/apache/fop/pdf/PDFGState.java
src/java/org/apache/fop/pdf/PDFGoTo.java
src/java/org/apache/fop/pdf/PDFGoToRemote.java
src/java/org/apache/fop/pdf/PDFICCBasedColorSpace.java
src/java/org/apache/fop/pdf/PDFICCStream.java
src/java/org/apache/fop/pdf/PDFImageXObject.java
src/java/org/apache/fop/pdf/PDFInfo.java
src/java/org/apache/fop/pdf/PDFLaunch.java
src/java/org/apache/fop/pdf/PDFLink.java
src/java/org/apache/fop/pdf/PDFMetadata.java
src/java/org/apache/fop/pdf/PDFName.java
src/java/org/apache/fop/pdf/PDFNumber.java
src/java/org/apache/fop/pdf/PDFNumsArray.java
src/java/org/apache/fop/pdf/PDFObject.java
src/java/org/apache/fop/pdf/PDFOutline.java
src/java/org/apache/fop/pdf/PDFOutputIntent.java
src/java/org/apache/fop/pdf/PDFPages.java
src/java/org/apache/fop/pdf/PDFPattern.java
src/java/org/apache/fop/pdf/PDFResources.java
src/java/org/apache/fop/pdf/PDFRoot.java
src/java/org/apache/fop/pdf/PDFShading.java
src/java/org/apache/fop/pdf/PDFStream.java
src/java/org/apache/fop/pdf/PDFStructElem.java
src/java/org/apache/fop/pdf/PDFT1Stream.java
src/java/org/apache/fop/pdf/PDFTTFStream.java
src/java/org/apache/fop/pdf/PDFText.java
src/java/org/apache/fop/pdf/PDFUri.java
src/java/org/apache/fop/pdf/PDFXObject.java
src/java/org/apache/fop/pdf/Version.java
src/java/org/apache/fop/pdf/xref/CompressedObjectReference.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/xref/CrossReferenceObject.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/xref/CrossReferenceStream.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/xref/CrossReferenceTable.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/xref/ObjectReference.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/xref/TrailerDictionary.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/xref/UncompressedObjectReference.java [new file with mode: 0644]
src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
src/java/org/apache/fop/render/pdf/PDFRenderingUtil.java
src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java
test/accessibility/README [deleted file]
test/accessibility/background-image_jpg_repeat.fo [deleted file]
test/accessibility/background-image_jpg_single.fo [deleted file]
test/accessibility/background-image_png_repeat.fo [deleted file]
test/accessibility/background-image_png_single.fo [deleted file]
test/accessibility/background-image_svg_repeat.fo [deleted file]
test/accessibility/background-image_svg_single.fo [deleted file]
test/accessibility/complete.fo [deleted file]
test/accessibility/fop.xconf [deleted file]
test/accessibility/image_jpg.fo [deleted file]
test/accessibility/image_png.fo [deleted file]
test/accessibility/image_svg.fo [deleted file]
test/accessibility/image_wmf.fo [deleted file]
test/accessibility/leader.fo [deleted file]
test/accessibility/links.fo [deleted file]
test/accessibility/pdf/background-image_jpg_repeat.pdf [deleted file]
test/accessibility/pdf/background-image_jpg_single.pdf [deleted file]
test/accessibility/pdf/background-image_png_repeat.pdf [deleted file]
test/accessibility/pdf/background-image_png_single.pdf [deleted file]
test/accessibility/pdf/background-image_svg_repeat.pdf [deleted file]
test/accessibility/pdf/background-image_svg_single.pdf [deleted file]
test/accessibility/pdf/complete.pdf [deleted file]
test/accessibility/pdf/image_jpg.pdf [deleted file]
test/accessibility/pdf/image_png.pdf [deleted file]
test/accessibility/pdf/image_svg.pdf [deleted file]
test/accessibility/pdf/image_wmf.pdf [deleted file]
test/accessibility/pdf/leader.pdf [deleted file]
test/accessibility/pdf/links.pdf [deleted file]
test/accessibility/pdf/role.pdf [deleted file]
test/accessibility/pdf/role_non-standard.pdf [deleted file]
test/accessibility/pdf/text_1.pdf [deleted file]
test/accessibility/pdf/text_2.pdf [deleted file]
test/accessibility/pdf/text_font-embedding.pdf [deleted file]
test/accessibility/role.fo [deleted file]
test/accessibility/role_non-standard.fo [deleted file]
test/accessibility/text_1.fo [deleted file]
test/accessibility/text_2.fo [deleted file]
test/accessibility/text_font-embedding.fo [deleted file]
test/java/org/apache/fop/StandardTestSuite.java
test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java
test/java/org/apache/fop/pdf/ObjectStreamManagerTestCase.java [new file with mode: 0644]
test/java/org/apache/fop/pdf/ObjectStreamTestCase.java [new file with mode: 0644]
test/java/org/apache/fop/pdf/PDFEncryptionJCETestCase.java
test/java/org/apache/fop/pdf/PDFFilterListTestCase.java [new file with mode: 0644]
test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java
test/java/org/apache/fop/pdf/PDFObjectTestCase.java
test/java/org/apache/fop/pdf/PDFStreamTestCase.java [new file with mode: 0644]
test/java/org/apache/fop/pdf/xref/CompressedObjectReferenceTestCase.java [new file with mode: 0644]
test/java/org/apache/fop/pdf/xref/CrossReferenceObjectTest.java [new file with mode: 0644]
test/java/org/apache/fop/pdf/xref/CrossReferenceStreamTestCase.java [new file with mode: 0644]
test/java/org/apache/fop/pdf/xref/CrossReferenceTableTestCase.java [new file with mode: 0644]
test/java/org/apache/fop/pdf/xref/ObjectReferenceTest.java [new file with mode: 0644]
test/java/org/apache/fop/pdf/xref/UncompressedObjectReferenceTestCase.java [new file with mode: 0644]
test/pdf/1.5/fop.xconf [new file with mode: 0644]
test/pdf/1.5/test.fo [new file with mode: 0644]
test/pdf/1.5/test.pdf [new file with mode: 0644]
test/pdf/accessibility/README [new file with mode: 0644]
test/pdf/accessibility/background-image_jpg_repeat.fo [new file with mode: 0644]
test/pdf/accessibility/background-image_jpg_single.fo [new file with mode: 0644]
test/pdf/accessibility/background-image_png_repeat.fo [new file with mode: 0644]
test/pdf/accessibility/background-image_png_single.fo [new file with mode: 0644]
test/pdf/accessibility/background-image_svg_repeat.fo [new file with mode: 0644]
test/pdf/accessibility/background-image_svg_single.fo [new file with mode: 0644]
test/pdf/accessibility/complete.fo [new file with mode: 0644]
test/pdf/accessibility/fop.xconf [new file with mode: 0644]
test/pdf/accessibility/image_jpg.fo [new file with mode: 0644]
test/pdf/accessibility/image_png.fo [new file with mode: 0644]
test/pdf/accessibility/image_svg.fo [new file with mode: 0644]
test/pdf/accessibility/image_wmf.fo [new file with mode: 0644]
test/pdf/accessibility/leader.fo [new file with mode: 0644]
test/pdf/accessibility/links.fo [new file with mode: 0644]
test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/background-image_jpg_single.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/background-image_png_repeat.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/background-image_png_single.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/background-image_svg_repeat.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/background-image_svg_single.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/complete.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/image_jpg.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/image_png.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/image_svg.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/image_wmf.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/leader.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/links.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/role.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/role_non-standard.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/text_1.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/text_2.pdf [new file with mode: 0644]
test/pdf/accessibility/pdf/text_font-embedding.pdf [new file with mode: 0644]
test/pdf/accessibility/role.fo [new file with mode: 0644]
test/pdf/accessibility/role_non-standard.fo [new file with mode: 0644]
test/pdf/accessibility/text_1.fo [new file with mode: 0644]
test/pdf/accessibility/text_2.fo [new file with mode: 0644]
test/pdf/accessibility/text_font-embedding.fo [new file with mode: 0644]

index 1b25c113fb5190c13f2c92b052caaf8aa8492962..0181728b8ba0bcd107d9d7cdf37a4002be0088f9 100644 (file)
@@ -29,16 +29,48 @@ import org.apache.fop.util.CloseBlockerOutputStream;
 /**
  * This is an abstract base class for PDF streams.
  */
-public abstract class AbstractPDFStream extends PDFDictionary {
+public abstract class AbstractPDFStream extends PDFObject {
+
+    private final PDFDictionary dictionary;
 
     /** The filters that should be applied */
     private PDFFilterList filters;
 
+    private final boolean encodeOnTheFly;
+
+    protected AbstractPDFStream() {
+        this(true);
+    }
+
+    protected AbstractPDFStream(PDFDictionary dictionary) {
+        this(dictionary, true);
+    }
+
+    protected AbstractPDFStream(boolean encodeOnTheFly) {
+        this(new PDFDictionary(), encodeOnTheFly);
+    }
+
+    protected AbstractPDFStream(PDFDictionary dictionary, boolean encodeOnTheFly) {
+        this.dictionary = dictionary;
+        this.encodeOnTheFly = encodeOnTheFly;
+    }
+
+    protected final PDFDictionary getDictionary() {
+        return dictionary;
+    }
+
+    protected Object get(String key) {
+        return dictionary.get(key);
+    }
+
     /**
-     * Constructor for AbstractPDFStream.
+     * Puts the given object in the dictionary associated to this stream.
+     *
+     * @param key the key in the dictionary
+     * @param value the value to store
      */
-    public AbstractPDFStream() {
-        super();
+    public void put(String key, Object value) {
+        dictionary.put(key, value);
     }
 
     /**
@@ -180,17 +212,16 @@ public abstract class AbstractPDFStream extends PDFDictionary {
      * {@inheritDoc}
      */
     @Override
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
         setupFilterList();
 
         CountingOutputStream cout = new CountingOutputStream(stream);
         StringBuilder textBuffer = new StringBuilder(64);
-        textBuffer.append(getObjectID());
 
         StreamCache encodedStream = null;
         PDFNumber refLength = null;
         final Object lengthEntry;
-        if (isEncodingOnTheFly()) {
+        if (encodeOnTheFly) {
             refLength = new PDFNumber();
             getDocumentSafely().registerObject(refLength);
             lengthEntry = refLength;
@@ -200,7 +231,7 @@ public abstract class AbstractPDFStream extends PDFDictionary {
         }
 
         populateStreamDict(lengthEntry);
-        writeDictionary(cout, textBuffer);
+        dictionary.writeDictionary(cout, textBuffer);
 
         //Send encoded stream to target OutputStream
         PDFDocument.flushTextBuffer(textBuffer, cout);
@@ -211,18 +242,14 @@ public abstract class AbstractPDFStream extends PDFDictionary {
             encodedStream.clear(); //Encoded stream can now be discarded
         }
 
-        textBuffer.append("\nendobj\n");
         PDFDocument.flushTextBuffer(textBuffer, cout);
         return cout.getCount();
     }
 
-    /**
-     * Indicates whether encoding may happen without buffering the encoded data. If this method
-     * returns true, the /Length entry will be an indirect object, a direct object otherwise.
-     * @return true if encoding should happen "on the fly"
-     */
-    protected boolean isEncodingOnTheFly() {
-        return getDocument().isEncodingOnTheFly();
+    @Override
+    public void setDocument(PDFDocument doc) {
+        dictionary.setDocument(doc);
+        super.setDocument(doc);
     }
 
     /**
@@ -233,7 +260,7 @@ public abstract class AbstractPDFStream extends PDFDictionary {
     protected void populateStreamDict(Object lengthEntry) {
         put("Length", lengthEntry);
         if (!getFilterList().isDisableAllFilters()) {
-            getFilterList().putFilterDictEntries(this);
+            getFilterList().putFilterDictEntries(dictionary);
         }
     }
 
diff --git a/src/java/org/apache/fop/pdf/CompressedObject.java b/src/java/org/apache/fop/pdf/CompressedObject.java
new file mode 100644 (file)
index 0000000..55d9c29
--- /dev/null
@@ -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 java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Represents a PDF object that may appear in an object stream. An object stream is a PDF
+ * stream whose content is a sequence of PDF objects. See Section 3.4.6 of the PDF 1.5
+ * Reference.
+ */
+interface CompressedObject {
+
+    /**
+     * Returns the object number of this indirect object. Note that a compressed object
+     * must have a generation number of 0.
+     *
+     * @return the object number.
+     */
+    int getObjectNumber();
+
+    /**
+     * Outputs this object's content into the given stream.
+     *
+     * @param outputStream a stream, likely to be provided by the containing object stream
+     * @return the number of bytes written to the stream
+     * @throws IOException
+     */
+    int output(OutputStream outputStream) throws IOException;
+
+}
diff --git a/src/java/org/apache/fop/pdf/ObjectStream.java b/src/java/org/apache/fop/pdf/ObjectStream.java
new file mode 100644 (file)
index 0000000..e9335bc
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+import org.apache.fop.pdf.xref.CompressedObjectReference;
+
+/**
+ * An object stream, as described in section 3.4.6 of the PDF 1.5 Reference.
+ */
+public class ObjectStream extends PDFStream {
+
+    private static final PDFName OBJ_STM = new PDFName("ObjStm");
+
+    private List<CompressedObject> objects = new ArrayList<CompressedObject>();
+
+    private int firstObjectOffset;
+
+    ObjectStream() {
+        super(false);
+    }
+
+    ObjectStream(ObjectStream previous) {
+        this();
+        put("Extends", previous);
+    }
+
+    CompressedObjectReference addObject(CompressedObject obj) {
+        if (obj == null) {
+            throw new NullPointerException("obj must not be null");
+        }
+        CompressedObjectReference reference = new CompressedObjectReference(obj.getObjectNumber(),
+                getObjectNumber(), objects.size());
+        objects.add(obj);
+        return reference;
+    }
+
+    @Override
+    protected void outputRawStreamData(OutputStream out) throws IOException {
+        int currentOffset = 0;
+        StringBuilder offsetsPart = new StringBuilder();
+        ByteArrayOutputStream streamContent = new ByteArrayOutputStream();
+        for (CompressedObject object : objects) {
+            offsetsPart.append(object.getObjectNumber())
+                    .append(' ')
+                    .append(currentOffset)
+                    .append('\n');
+            currentOffset += object.output(streamContent);
+        }
+        byte[] offsets = PDFDocument.encode(offsetsPart.toString());
+        firstObjectOffset = offsets.length;
+        out.write(offsets);
+        streamContent.writeTo(out);
+    }
+
+    @Override
+    protected void populateStreamDict(Object lengthEntry) {
+        put("Type", OBJ_STM);
+        put("N", objects.size());
+        put("First", firstObjectOffset);
+        super.populateStreamDict(lengthEntry);
+    }
+}
diff --git a/src/java/org/apache/fop/pdf/ObjectStreamManager.java b/src/java/org/apache/fop/pdf/ObjectStreamManager.java
new file mode 100644 (file)
index 0000000..723facd
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+
+import org.apache.fop.pdf.xref.CompressedObjectReference;
+
+/**
+ * Manages a collection of object streams, creating new streams as necessary to keep the
+ * number of objects in each stream at the recommended value. Streams are related to each
+ * other through the use of the Extends entry in the stream dictionary.
+ */
+class ObjectStreamManager {
+
+    private static final int OBJECT_STREAM_CAPACITY = 100;
+
+    private final PDFDocument pdfDocument;
+
+    private final List<CompressedObjectReference> compressedObjectReferences;
+
+    private int numObjectsInStream;
+
+    private ObjectStream currentObjectStream;
+
+    ObjectStreamManager(PDFDocument pdfDocument) {
+        this.pdfDocument = pdfDocument;
+        createObjectStream();
+        compressedObjectReferences = new ArrayList<CompressedObjectReference>();
+    }
+
+    void add(CompressedObject compressedObject) {
+        if (numObjectsInStream++ == OBJECT_STREAM_CAPACITY) {
+            createObjectStream();
+            numObjectsInStream = 1;
+        }
+        compressedObjectReferences.add(currentObjectStream.addObject(compressedObject));
+    }
+
+    private void createObjectStream() {
+        currentObjectStream = currentObjectStream == null
+                ? new ObjectStream()
+                : new ObjectStream(currentObjectStream);
+        pdfDocument.assignObjectNumber(currentObjectStream);
+        pdfDocument.addTrailerObject(currentObjectStream);
+    }
+
+    List<CompressedObjectReference> getCompressedObjectReferences() {
+        return compressedObjectReferences;
+    }
+}
index 0a87106273f38385eb65a9b5139f50bcfc553e2d..65b327e3108cfc81982d4a4598f15994514bbefc 100644 (file)
@@ -58,22 +58,19 @@ public class PDFAnnotList extends PDFObject {
      */
     public String toPDFString() {
         StringBuffer p = new StringBuffer(128);
-        p.append(getObjectID());
         p.append("[\n");
         for (int i = 0; i < getCount(); i++) {
             p.append(((PDFObject)links.get(i)).referencePDF());
             p.append("\n");
         }
-        p.append("]\nendobj\n");
+        p.append("]");
         return p.toString();
     }
 
     /*
      * example
-     * 20 0 obj
      * [
      * 19 0 R
      * ]
-     * endobj
      */
 }
index 78eba3bb9bb7267b1070537283504692b2aaf94d..13183032845613b4e9e5b5b91b5332faa3d7bba2 100644 (file)
@@ -21,7 +21,6 @@ package org.apache.fop.pdf;
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.Collection;
 import java.util.List;
 
 import org.apache.commons.io.output.CountingOutputStream;
@@ -48,7 +47,7 @@ public class PDFArray extends PDFObject {
      * Create a new, empty array object with no parent.
      */
     public PDFArray() {
-        this(null);
+        this((PDFObject) null);
     }
 
     /**
@@ -84,13 +83,22 @@ 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<Object> values) {
+    public PDFArray(PDFObject parent, List<?> values) {
         /* generic creation of PDF object */
         super(parent);
 
         this.values.addAll(values);
     }
 
+    /**
+     * Creates an array object made of the given elements.
+     *
+     * @param elements the array content
+     */
+    public PDFArray(Object... elements) {
+        this(null, elements);
+    }
+
     /**
      * Create the array object
      * @param parent the array's parent if any
@@ -180,13 +188,9 @@ public class PDFArray extends PDFObject {
 
     /** {@inheritDoc} */
     @Override
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
         CountingOutputStream cout = new CountingOutputStream(stream);
         StringBuilder textBuffer = new StringBuilder(64);
-        if (hasObjectNumber()) {
-            textBuffer.append(getObjectID());
-        }
-
         textBuffer.append('[');
         for (int i = 0; i < values.size(); i++) {
             if (i > 0) {
@@ -196,11 +200,6 @@ public class PDFArray extends PDFObject {
             formatObject(obj, cout, textBuffer);
         }
         textBuffer.append(']');
-
-        if (hasObjectNumber()) {
-            textBuffer.append("\nendobj\n");
-        }
-
         PDFDocument.flushTextBuffer(textBuffer, cout);
         return cout.getCount();
     }
index 459fe25843169b3ecfa2408691c2c9032120b0de..46374d8692c7fe4ba38496add5406897aa02f6a9 100644 (file)
@@ -200,7 +200,6 @@ public class PDFCIDFont extends PDFObject {
      */
     public String toPDFString() {
         StringBuffer p = new StringBuffer(128);
-        p.append(getObjectID());
         p.append("<< /Type /Font");
         p.append("\n/BaseFont /");
         p.append(this.basefont);
@@ -234,14 +233,13 @@ public class PDFCIDFont extends PDFObject {
             p.append("\n/DW2 [");    // always two values, see p 211
             p.append(this.dw2[0]);
             p.append(this.dw2[1]);
-            p.append("] \n>>\nendobj\n");
+            p.append("]");
         }
         if (w2 != null) {
             p.append("\n/W2 ");
             p.append(w2.toPDFString());
-            p.append(" \n>>\nendobj\n");
         }
-        p.append(" \n>>\nendobj\n");
+        p.append("\n>>");
         return p.toString();
     }
 
index 57d148fc2ff005e60bbc5299a26a494ea47ea744..34bc0f9523825af859c63b1131e87fe778f82f7a 100644 (file)
@@ -423,7 +423,7 @@ public class PDFCMap extends PDFStream {
     }
 
     /** {@inheritDoc} */
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
         CMapBuilder builder = createCMapBuilder(getBufferWriter());
         builder.writeCMap();
         return super.output(stream);
index 400c4a4b6614497789ccfc153e401b6d0de27b2b..21c6558320e185af2dac0c953d24ce1ee21b1fc5 100644 (file)
@@ -50,9 +50,8 @@ public class PDFDestination extends PDFObject {
         this.idRef = idRef;
     }
 
-    /** {@inheritDoc} */
     @Override
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
         CountingOutputStream cout = new CountingOutputStream(stream);
         StringBuilder textBuffer = new StringBuilder(64);
 
index 5a67243047af4e2b70756943bce893e63d510fda..6bacd31a3410e00e0944667695e64155e4b93e5b 100644 (file)
@@ -98,19 +98,10 @@ public class PDFDictionary extends PDFObject {
 
     /** {@inheritDoc} */
     @Override
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
         CountingOutputStream cout = new CountingOutputStream(stream);
         StringBuilder textBuffer = new StringBuilder(64);
-        if (hasObjectNumber()) {
-            textBuffer.append(getObjectID());
-        }
-
         writeDictionary(cout, textBuffer);
-
-        if (hasObjectNumber()) {
-            textBuffer.append("\nendobj\n");
-        }
-
         PDFDocument.flushTextBuffer(textBuffer, cout);
         return cout.getCount();
     }
index e9886fc372c477a412042aac6cfe9b5303676e5e..9850c605e3c2056fc57d4c95b97eb7e732fbbc85 100644 (file)
@@ -26,6 +26,7 @@ import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
@@ -37,6 +38,10 @@ import java.util.Map;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import org.apache.fop.pdf.xref.CrossReferenceStream;
+import org.apache.fop.pdf.xref.CrossReferenceTable;
+import org.apache.fop.pdf.xref.TrailerDictionary;
+
 /* image support modified from work of BoBoGi */
 /* font support based on work by Takayuki Takeuchi */
 
@@ -63,31 +68,28 @@ import org.apache.commons.logging.LogFactory;
  */
 public class PDFDocument {
 
-    private static final Long LOCATION_PLACEHOLDER = new Long(0);
-
     /** the encoding to use when converting strings to PDF commands */
     public static final String ENCODING = "ISO-8859-1";
 
     /** the counter for object numbering */
-    protected int objectcount = 0;
+    protected int objectcount;
 
     /** the logger instance */
     private Log log = LogFactory.getLog("org.apache.fop.pdf");
 
     /** the current character position */
-    private long position = 0;
-
-    /** character position of xref table */
-    private long xref;
+    private long position;
 
     /** the character position of each object */
-    private List<Long> location = new ArrayList<Long>();
+    private List<Long> indirectObjectOffsets = new ArrayList<Long>();
+
+    private Collection<PDFStructElem> structureTreeElements;
 
     /** List of objects to write in the trailer */
-    private List trailerObjects = new ArrayList();
+    private List<PDFObject> trailerObjects = new ArrayList<PDFObject>();
 
     /** the objects themselves */
-    private List objects = new LinkedList();
+    private List<PDFObject> objects = new LinkedList<PDFObject>();
 
     /** Controls the PDF version of this document */
     private VersionController versionController;
@@ -99,7 +101,7 @@ public class PDFDocument {
     private PDFRoot root;
 
     /** The root outline object */
-    private PDFOutline outlineRoot = null;
+    private PDFOutline outlineRoot;
 
     /** The /Pages object (mark-fop@inomial.com) */
     private PDFPages pages;
@@ -118,66 +120,47 @@ public class PDFDocument {
         = new PDFDeviceColorSpace(PDFDeviceColorSpace.DEVICE_RGB);
 
     /** the counter for Pattern name numbering (e.g. 'Pattern1') */
-    private int patternCount = 0;
+    private int patternCount;
 
     /** the counter for Shading name numbering */
-    private int shadingCount = 0;
+    private int shadingCount;
 
     /** the counter for XObject numbering */
-    private int xObjectCount = 0;
+    private int xObjectCount;
 
-    /** the {@link PDFXObject}s map */
     /* TODO: Should be modified (works only for image subtype) */
-    private Map xObjectsMap = new HashMap();
-
-    /** The {@link PDFFont} map */
-    private Map fontMap = new HashMap();
+    private Map<String, PDFXObject> xObjectsMap = new HashMap<String, PDFXObject>();
 
-    /** The {@link PDFFilter} map */
-    private Map filterMap = new HashMap();
+    private Map<String, PDFFont> fontMap = new HashMap<String, PDFFont>();
 
-    /** List of {@link PDFGState}s. */
-    private List gstates = new ArrayList();
+    private Map<String, List<String>> filterMap = new HashMap<String, List<String>>();
 
-    /** List of {@link PDFFunction}s. */
-    private List functions = new ArrayList();
+    private List<PDFGState> gstates = new ArrayList<PDFGState>();
 
-    /** List of {@link PDFShading}s. */
-    private List shadings = new ArrayList();
+    private List<PDFFunction> functions = new ArrayList<PDFFunction>();
 
-    /** List of {@link PDFPattern}s. */
-    private List patterns = new ArrayList();
+    private List<PDFShading> shadings = new ArrayList<PDFShading>();
 
-    /** List of {@link PDFLink}s. */
-    private List links = new ArrayList();
+    private List<PDFPattern> patterns = new ArrayList<PDFPattern>();
 
-    /** List of {@link PDFDestination}s. */
-    private List destinations;
+    private List<PDFLink> links = new ArrayList<PDFLink>();
 
-    /** List of {@link PDFFileSpec}s. */
-    private List filespecs = new ArrayList();
+    private List<PDFDestination> destinations;
 
-    /** List of {@link PDFGoToRemote}s. */
-    private List gotoremotes = new ArrayList();
+    private List<PDFFileSpec> filespecs = new ArrayList<PDFFileSpec>();
 
-    /** List of {@link PDFGoTo}s. */
-    private List gotos = new ArrayList();
+    private List<PDFGoToRemote> gotoremotes = new ArrayList<PDFGoToRemote>();
 
-    /** List of {@link PDFLaunch}es. */
-    private List launches = new ArrayList();
+    private List<PDFGoTo> gotos = new ArrayList<PDFGoTo>();
 
-    /**
-     * The PDFDests object for the name dictionary.
-     * Note: This object is not a list.
-     */
-    private PDFDests dests;
+    private List<PDFLaunch> launches = new ArrayList<PDFLaunch>();
 
     private PDFFactory factory;
 
-    private boolean encodingOnTheFly = true;
-
     private FileIDGenerator fileIDGenerator;
 
+    private boolean accessibilityEnabled;
+
     /**
      * Creates an empty PDF document.
      *
@@ -265,17 +248,6 @@ public class PDFDocument {
         return this.factory;
     }
 
-    /**
-     * Indicates whether stream encoding on-the-fly is enabled. If enabled
-     * stream can be serialized without the need for a buffer to merely
-     * calculate the stream length.
-     *
-     * @return <code>true</code> if on-the-fly encoding is enabled
-     */
-    public boolean isEncodingOnTheFly() {
-        return this.encodingOnTheFly;
-    }
-
     /**
      * Converts text to a byte array for writing to a PDF file.
      *
@@ -336,7 +308,7 @@ public class PDFDocument {
      *
      * @param map the map of filter lists for each stream type
      */
-    public void setFilterMap(Map map) {
+    public void setFilterMap(Map<String, List<String>> map) {
         this.filterMap = map;
     }
 
@@ -345,7 +317,7 @@ public class PDFDocument {
      *
      * @return the map of filters being used
      */
-    public Map getFilterMap() {
+    public Map<String, List<String>> getFilterMap() {
         return this.filterMap;
     }
 
@@ -367,6 +339,37 @@ public class PDFDocument {
         return this.root;
     }
 
+    /**
+     * Creates and returns a StructTreeRoot object.
+     *
+     * @param parentTree the value of the ParenTree entry
+     * @return the structure tree root
+     */
+    public PDFStructTreeRoot makeStructTreeRoot(PDFParentTree parentTree) {
+        PDFStructTreeRoot structTreeRoot = new PDFStructTreeRoot(parentTree);
+        assignObjectNumber(structTreeRoot);
+        addTrailerObject(structTreeRoot);
+        root.setStructTreeRoot(structTreeRoot);
+        structureTreeElements = new ArrayList<PDFStructElem>();
+        return structTreeRoot;
+    }
+
+    /**
+     * Creates and returns a structure element.
+     *
+     * @param structureType the structure type of the new element (value for the
+     * S entry)
+     * @param parent the parent of the new structure element in the structure
+     * hierarchy
+     * @return a dictionary of type StructElem
+     */
+    public PDFStructElem makeStructureElement(PDFName structureType, PDFObject parent) {
+        PDFStructElem structElem = new PDFStructElem(parent, structureType);
+        assignObjectNumber(structElem);
+        structureTreeElements.add(structElem);
+        return structElem;
+    }
+
     /**
      * Get the {@link PDFInfo} object for this document.
      *
@@ -439,39 +442,39 @@ public class PDFDocument {
 
         //Add object to special lists where necessary
         if (obj instanceof PDFFunction) {
-            this.functions.add(obj);
+            this.functions.add((PDFFunction) obj);
         }
         if (obj instanceof PDFShading) {
             final String shadingName = "Sh" + (++this.shadingCount);
             ((PDFShading)obj).setName(shadingName);
-            this.shadings.add(obj);
+            this.shadings.add((PDFShading) obj);
         }
         if (obj instanceof PDFPattern) {
             final String patternName = "Pa" + (++this.patternCount);
             ((PDFPattern)obj).setName(patternName);
-            this.patterns.add(obj);
+            this.patterns.add((PDFPattern) obj);
         }
         if (obj instanceof PDFFont) {
             final PDFFont font = (PDFFont)obj;
             this.fontMap.put(font.getName(), font);
         }
         if (obj instanceof PDFGState) {
-            this.gstates.add(obj);
+            this.gstates.add((PDFGState) obj);
         }
         if (obj instanceof PDFPage) {
             this.pages.notifyKidRegistered((PDFPage)obj);
         }
         if (obj instanceof PDFLaunch) {
-            this.launches.add(obj);
+            this.launches.add((PDFLaunch) obj);
         }
         if (obj instanceof PDFLink) {
-            this.links.add(obj);
+            this.links.add((PDFLink) obj);
         }
         if (obj instanceof PDFFileSpec) {
-            this.filespecs.add(obj);
+            this.filespecs.add((PDFFileSpec) obj);
         }
         if (obj instanceof PDFGoToRemote) {
-            this.gotoremotes.add(obj);
+            this.gotoremotes.add((PDFGoToRemote) obj);
         }
     }
 
@@ -485,7 +488,7 @@ public class PDFDocument {
         this.trailerObjects.add(obj);
 
         if (obj instanceof PDFGoTo) {
-            this.gotos.add(obj);
+            this.gotos.add((PDFGoTo) obj);
         }
     }
 
@@ -537,9 +540,8 @@ public class PDFDocument {
         return this.encryption;
     }
 
-    private Object findPDFObject(List list, PDFObject compare) {
-        for (Iterator iter = list.iterator(); iter.hasNext();) {
-            PDFObject obj = (PDFObject) iter.next();
+    private Object findPDFObject(List<? extends PDFObject> list, PDFObject compare) {
+        for (PDFObject obj : list) {
             if (compare.contentEquals(obj)) {
                 return obj;
             }
@@ -589,7 +591,7 @@ public class PDFDocument {
      * @return PDFFont the requested font, null if it wasn't found
      */
     protected PDFFont findFont(String fontname) {
-        return (PDFFont)this.fontMap.get(fontname);
+        return this.fontMap.get(fontname);
     }
 
     /**
@@ -601,7 +603,7 @@ public class PDFDocument {
     protected PDFDestination findDestination(PDFDestination compare) {
         int index = getDestinationList().indexOf(compare);
         if (index >= 0) {
-            return (PDFDestination)getDestinationList().get(index);
+            return getDestinationList().get(index);
         } else {
             return null;
         }
@@ -666,9 +668,9 @@ public class PDFDocument {
      */
     protected PDFGState findGState(PDFGState wanted, PDFGState current) {
         PDFGState poss;
-        Iterator iter = this.gstates.iterator();
+        Iterator<PDFGState> iter = this.gstates.iterator();
         while (iter.hasNext()) {
-            PDFGState avail = (PDFGState)iter.next();
+            PDFGState avail = iter.next();
             poss = new PDFGState();
             poss.addValues(current);
             poss.addValues(avail);
@@ -712,7 +714,7 @@ public class PDFDocument {
      *
      * @return the map of fonts used in this document
      */
-    public Map getFontMap() {
+    public Map<String, PDFFont> getFontMap() {
         return this.fontMap;
     }
 
@@ -753,16 +755,7 @@ public class PDFDocument {
      * @return the PDFXObject for the key if found
      */
     public PDFXObject getXObject(String key) {
-        return (PDFXObject)this.xObjectsMap.get(key);
-    }
-
-    /**
-     * Gets the PDFDests object (which represents the /Dests entry).
-     *
-     * @return the PDFDests object (which represents the /Dests entry).
-     */
-    public PDFDests getDests() {
-        return this.dests;
+        return this.xObjectsMap.get(key);
     }
 
     /**
@@ -771,7 +764,7 @@ public class PDFDocument {
      */
     public void addDestination(PDFDestination destination) {
         if (this.destinations == null) {
-            this.destinations = new ArrayList();
+            this.destinations = new ArrayList<PDFDestination>();
         }
         this.destinations.add(destination);
     }
@@ -781,11 +774,11 @@ public class PDFDocument {
      *
      * @return the list of named destinations.
      */
-    public List getDestinationList() {
+    public List<PDFDestination> getDestinationList() {
         if (hasDestinations()) {
             return this.destinations;
         } else {
-            return Collections.EMPTY_LIST;
+            return Collections.emptyList();
         }
     }
 
@@ -900,17 +893,8 @@ public class PDFDocument {
         return this.resources;
     }
 
-    /**
-     * Ensure there is room in the locations xref for the number of
-     * objects that have been created.
-     * @param objidx    the object's index
-     * @param position  the position
-     */
-    private void setLocation(int objidx, long position) {
-        while (this.location.size() <= objidx) {
-            this.location.add(LOCATION_PLACEHOLDER);
-        }
-        this.location.set(objidx, position);
+    public void enableAccessibility(boolean enableAccessibility) {
+        this.accessibilityEnabled = enableAccessibility;
     }
 
     /**
@@ -924,23 +908,50 @@ public class PDFDocument {
         //LinkedList) allows for output() methods to create and register objects
         //on the fly even during serialization.
         while (this.objects.size() > 0) {
-            /* Retrieve first */
-            PDFObject object = (PDFObject)this.objects.remove(0);
-            /*
-             * add the position of this object to the list of object
-             * locations
-             */
-            setLocation(object.getObjectNumber() - 1, this.position);
-
-            /*
-             * output the object and increment the character position
-             * by the object's length
-             */
-            this.position += object.output(stream);
+            PDFObject object = this.objects.remove(0);
+            streamIndirectObject(object, stream);
         }
+    }
 
-        //Clear all objects written to the file
-        //this.objects.clear();
+    private void streamIndirectObject(PDFObject o, OutputStream stream) throws IOException {
+        recordObjectOffset(o);
+        this.position += outputIndirectObject(o, stream);
+    }
+
+    private void streamIndirectObjects(Collection<? extends PDFObject> objects, OutputStream stream)
+            throws IOException {
+        for (PDFObject o : objects) {
+            streamIndirectObject(o, stream);
+        }
+    }
+
+    private void recordObjectOffset(PDFObject object) {
+        int index = object.getObjectNumber() - 1;
+        while (indirectObjectOffsets.size() <= index) {
+            indirectObjectOffsets.add(null);
+        }
+        indirectObjectOffsets.set(index, position);
+    }
+
+    /**
+     * Outputs the given object, wrapped by obj/endobj, to the given stream.
+     *
+     * @param object an indirect object, as described in Section 3.2.9 of the PDF 1.5
+     * Reference.
+     * @param stream the stream to which the object must be output
+     * @throws IllegalArgumentException if the object is not an indirect object
+     */
+    public static int outputIndirectObject(PDFObject object, OutputStream stream)
+            throws IOException {
+        if (!object.hasObjectNumber()) {
+            throw new IllegalArgumentException("Not an indirect object");
+        }
+        byte[] obj = encode(object.getObjectID());
+        stream.write(obj);
+        int length = object.output(stream);
+        byte[] endobj = encode("\nendobj\n");
+        stream.write(endobj);
+        return obj.length + length + endobj.length;
     }
 
     /**
@@ -980,89 +991,102 @@ public class PDFDocument {
      * @throws IOException if there is an exception writing to the output stream
      */
     public void outputTrailer(OutputStream stream) throws IOException {
+        createDestinations();
+        output(stream);
+        outputTrailerObjectsAndXref(stream);
+    }
+
+    private void createDestinations() {
         if (hasDestinations()) {
             Collections.sort(this.destinations, new DestinationComparator());
-            this.dests = getFactory().makeDests(this.destinations);
+            PDFDests dests = getFactory().makeDests(this.destinations);
             if (this.root.getNames() == null) {
                 this.root.setNames(getFactory().makeNames());
             }
             this.root.getNames().setDests(dests);
         }
-        output(stream);
-        for (int count = 0; count < this.trailerObjects.size(); count++) {
-            PDFObject o = (PDFObject)this.trailerObjects.get(count);
-            setLocation(o.getObjectNumber() - 1, this.position);
-            this.position += o.output(stream);
+    }
+
+    private void outputTrailerObjectsAndXref(OutputStream stream) throws IOException {
+        TrailerOutputHelper trailerOutputHelper = mayCompressStructureTreeElements()
+                ? new CompressedTrailerOutputHelper()
+                : new UncompressedTrailerOutputHelper();
+        if (structureTreeElements != null) {
+            trailerOutputHelper.outputStructureTreeElements(stream);
         }
-        /* output the xref table and increment the character position
-          by the table's length */
-        this.position += outputXref(stream);
-
-        /* construct the trailer */
-        StringBuffer pdf = new StringBuffer(128);
-        pdf.append("trailer\n<<\n/Size ")
-                .append(this.objectcount + 1)
-                .append("\n/Root ")
-                .append(this.root.referencePDF())
-                .append("\n/Info ")
-                .append(this.info.referencePDF())
-                .append('\n');
-
-        if (this.isEncryptionActive()) {
-            pdf.append(this.encryption.getTrailerEntry());
-        } else {
-            byte[] fileID = getFileIDGenerator().getOriginalFileID();
-            String fileIDAsString = PDFText.toHex(fileID);
-            pdf.append("/ID [" + fileIDAsString + " " + fileIDAsString + "]");
+        streamIndirectObjects(trailerObjects, stream);
+        TrailerDictionary trailerDictionary = createTrailerDictionary();
+        long startxref = trailerOutputHelper.outputCrossReferenceObject(stream, trailerDictionary);
+        String trailer = "startxref\n" + startxref + "\n%%EOF\n";
+        stream.write(encode(trailer));
+    }
+
+    private boolean mayCompressStructureTreeElements() {
+        return accessibilityEnabled
+                && versionController.getPDFVersion().compareTo(Version.V1_5) >= 0;
+    }
+
+    private TrailerDictionary createTrailerDictionary() {
+        FileIDGenerator gen = getFileIDGenerator();
+        TrailerDictionary trailerDictionary = new TrailerDictionary(this)
+                .setRoot(root)
+                .setInfo(info)
+                .setFileID(gen.getOriginalFileID(), gen.getUpdatedFileID());
+        if (isEncryptionActive()) {
+            trailerDictionary.setEncryption(encryption);
         }
+        return trailerDictionary;
+    }
 
-        pdf.append("\n>>\nstartxref\n")
-                .append(this.xref)
-                .append("\n%%EOF\n");
+    private interface TrailerOutputHelper {
 
-        /* write the trailer */
-        stream.write(encode(pdf.toString()));
+        void outputStructureTreeElements(OutputStream stream) throws IOException;
+
+        /**
+         * @return the offset of the cross-reference object (the value of startxref)
+         */
+        long outputCrossReferenceObject(OutputStream stream, TrailerDictionary trailerDictionary)
+                throws IOException;
     }
 
-    /**
-     * Write the xref table
-     *
-     * @param stream the OutputStream to write the xref table to
-     * @return the number of characters written
-     * @throws IOException in case of an error writing the result to
-     *          the parameter stream
-     */
-    private int outputXref(OutputStream stream) throws IOException {
-
-        /* remember position of xref table */
-        this.xref = this.position;
-
-        /* construct initial part of xref */
-        StringBuffer pdf = new StringBuffer(128);
-        pdf.append("xref\n0 ");
-        pdf.append(this.objectcount + 1);
-        pdf.append("\n0000000000 65535 f \n");
-
-        String s;
-        String loc;
-        for (int count = 0; count < this.location.size(); count++) {
-            final String padding = "0000000000";
-            s = this.location.get(count).toString();
-            if (s.length() > 10) {
-                throw new IOException("PDF file too large. PDF cannot grow beyond approx. 9.3GB.");
-            }
+    private class UncompressedTrailerOutputHelper implements TrailerOutputHelper {
 
-            /* contruct xref entry for object */
-            loc = padding.substring(s.length()) + s;
+        public void outputStructureTreeElements(OutputStream stream)
+                throws IOException {
+            streamIndirectObjects(structureTreeElements, stream);
+        }
 
-            /* append to xref table */
-            pdf = pdf.append(loc).append(" 00000 n \n");
+        public long outputCrossReferenceObject(OutputStream stream,
+                TrailerDictionary trailerDictionary) throws IOException {
+            new CrossReferenceTable(trailerDictionary, position,
+                    indirectObjectOffsets).output(stream);
+            return position;
         }
+    }
+
+    private class CompressedTrailerOutputHelper implements TrailerOutputHelper {
+
+        private ObjectStreamManager structureTreeObjectStreams;
 
-        /* write the xref table and return the character length */
-        byte[] pdfBytes = encode(pdf.toString());
-        stream.write(pdfBytes);
-        return pdfBytes.length;
+        public void outputStructureTreeElements(OutputStream stream)
+                throws IOException {
+            assert structureTreeElements.size() > 0;
+            structureTreeObjectStreams = new ObjectStreamManager(PDFDocument.this);
+            for (PDFStructElem structElem : structureTreeElements) {
+                structureTreeObjectStreams.add(structElem);
+            }
+        }
+
+        public long outputCrossReferenceObject(OutputStream stream,
+                TrailerDictionary trailerDictionary) throws IOException {
+            // Outputting the object streams should not have created new indirect objects
+            assert objects.isEmpty();
+            new CrossReferenceStream(PDFDocument.this, ++objectcount, trailerDictionary, position,
+                    indirectObjectOffsets,
+                    structureTreeObjectStreams.getCompressedObjectReferences())
+                    .output(stream);
+            return position;
+        }
     }
 
     long getCurrentFileSize() {
index 277cf0a94e79e24e38382e7cd299bfc4b8f90b64..fcb56e50b73f0af3b21114fd44e58e35f4977435 100644 (file)
@@ -40,8 +40,10 @@ public interface PDFEncryption {
     byte[] encrypt(byte[] data, PDFObject refObj);
 
     /**
-     * Returns the trailer entry for encryption.
-     * @return the trailer entry
+     * Returns the /Encrypt entry in the file trailer dictionary.
+     *
+     * @return the string "/Encrypt n g R\n" where n and g are the number and generation
+     * of the document's encryption dictionary
      */
     String getTrailerEntry();
 }
index c9b9c58baf5c0faab6d5ab0f32f1224f62bc88fa..2ef3b93da242345b9a04b344c2c068aa3948d592 100644 (file)
@@ -69,8 +69,9 @@ public final class PDFEncryptionJCE extends PDFObject implements PDFEncryption {
                     ? new Rev2Engine(encryptionSettings)
                     : new Rev3Engine(encryptionSettings);
             initializationEngine.run();
-            encryptionDictionary = createEncryptionDictionary(getObjectID(), permissions,
-                    initializationEngine.oValue, initializationEngine.uValue);
+            encryptionDictionary = createEncryptionDictionary(permissions,
+                    initializationEngine.oValue,
+                    initializationEngine.uValue);
         }
 
         private void determineEncryptionAlgorithm() {
@@ -91,18 +92,16 @@ public final class PDFEncryptionJCE extends PDFObject implements PDFEncryption {
                     && encryptionParams.isAllowPrintHq();
         }
 
-        private String createEncryptionDictionary(final String objectId, final int permissions,
-                final byte[] oValue, final byte[] uValue) {
-            return objectId
-                    + "<< /Filter /Standard\n"
+        private String createEncryptionDictionary(final int permissions, final byte[] oValue,
+                final byte[] uValue) {
+            return "<< /Filter /Standard\n"
                     + "/V " + version + "\n"
                     + "/R " + revision + "\n"
                     + "/Length " + encryptionLength + "\n"
                     + "/P "  + permissions + "\n"
                     + "/O " + PDFText.toHex(oValue) + "\n"
                     + "/U " + PDFText.toHex(uValue) + "\n"
-                    + ">>\n"
-                    + "endobj\n";
+                    + ">>";
         }
 
     }
@@ -488,14 +487,7 @@ public final class PDFEncryptionJCE extends PDFObject implements PDFEncryption {
 
     /** {@inheritDoc} */
     public String getTrailerEntry() {
-        PDFDocument doc = getDocumentSafely();
-        FileIDGenerator gen = doc.getFileIDGenerator();
-        return "/Encrypt " + getObjectNumber() + " "
-                    + getGeneration() + " R\n"
-                    + "/ID["
-                    + PDFText.toHex(gen.getOriginalFileID())
-                    + PDFText.toHex(gen.getUpdatedFileID())
-                    + "]\n";
+        return "/Encrypt " + getObjectNumber() + " " + getGeneration() + " R\n";
     }
 
     private static byte[] encryptWithKey(byte[] key, byte[] data) {
index a981dae88cede9be11ee196cb3d4203b561c6166..2c347031f71abb75bcb9b38513dcb80f7ca07478 100644 (file)
@@ -912,35 +912,6 @@ public class PDFFactory {
         return pageLabels;
     }
 
-    /**
-     * Creates and returns a StructTreeRoot object. Used for accessibility.
-     * @param parentTree the value of the ParenTree entry
-     * @return structure Tree Root element
-     */
-    public PDFStructTreeRoot makeStructTreeRoot(PDFParentTree parentTree) {
-        PDFStructTreeRoot structTreeRoot = new PDFStructTreeRoot(parentTree);
-        getDocument().assignObjectNumber(structTreeRoot);
-        getDocument().addTrailerObject(structTreeRoot);
-        getDocument().getRoot().setStructTreeRoot(structTreeRoot);
-        return structTreeRoot;
-    }
-
-    /**
-     * Creates and returns a StructElem object.
-     *
-     * @param structureType the structure type of the new element (value for the
-     * S entry)
-     * @param parent the parent of the new structure element in the structure
-     * hierarchy
-     * @return the newly created element
-     */
-    public PDFStructElem makeStructureElement(PDFName structureType, PDFObject parent) {
-        PDFStructElem structElem = new PDFStructElem(parent, structureType);
-        getDocument().assignObjectNumber(structElem);
-        getDocument().addTrailerObject(structElem);
-        return structElem;
-    }
-
     /**
      * Make a the head object of the name dictionary (the /Dests object).
      *
index 3025b878890b3cc257b87c43b3630f9f65d3e10c..3f26f454cbb6a074398ee44656ee967359228762 100644 (file)
@@ -21,6 +21,7 @@ package org.apache.fop.pdf;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -47,7 +48,7 @@ public class PDFFilterList {
     /** Key for the filter used for metadata */
     public static final String METADATA_FILTER = "metadata";
 
-    private List filters = new java.util.ArrayList();
+    private List<PDFFilter> filters = new java.util.ArrayList<PDFFilter>();
 
     private boolean ignoreASCIIFilters = false;
 
@@ -197,6 +198,10 @@ public class PDFFilterList {
         }
     }
 
+    List<PDFFilter> getFilters() {
+        return Collections.unmodifiableList(filters);
+    }
+
     /**
      * Apply the filters to the data
      * in the order given and return the /Filter and /DecodeParms
@@ -206,7 +211,7 @@ public class PDFFilterList {
      * @return a String representing the filter list
      */
     protected String buildFilterDictEntries() {
-        if (filters != null && filters.size() > 0) {
+        if (filters.size() > 0) {
             List names = new java.util.ArrayList();
             List parms = new java.util.ArrayList();
 
@@ -229,7 +234,7 @@ public class PDFFilterList {
      * @param dict the PDFDictionary to set the entries on
      */
     protected void putFilterDictEntries(PDFDictionary dict) {
-        if (filters != null && filters.size() > 0) {
+        if (filters.size() > 0) {
             List names = new java.util.ArrayList();
             List parms = new java.util.ArrayList();
 
@@ -358,7 +363,7 @@ public class PDFFilterList {
      */
     public OutputStream applyFilters(OutputStream stream) throws IOException {
         OutputStream out = stream;
-        if (filters != null && !isDisableAllFilters()) {
+        if (!isDisableAllFilters()) {
             for (int count = filters.size() - 1; count >= 0; count--) {
                 PDFFilter filter = (PDFFilter)filters.get(count);
                 out = filter.applyFilter(out);
index 2808e5ba7ae7ae2908d1301889013c42ee137d48..191fd223e3e2f02a3e60682519042818a1aa7467 100644 (file)
@@ -174,7 +174,7 @@ public class PDFFont extends PDFDictionary {
     }
 
     /** {@inheritDoc} */
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
         validate();
         return super.output(stream);
     }
index 2ccc170860302b9ee97a79a1281db69e517468e4..bc81a0a353d8e99c8d5bf485cb8ba982d3b4a1db 100644 (file)
@@ -44,7 +44,7 @@ public class PDFFormXObject extends PDFXObject {
      * @param resources the resource PDF reference
      */
     public PDFFormXObject(int xnumber, PDFStream contents, PDFReference resources) {
-        super();
+        super(contents.getDictionary());
         put("Name", new PDFName("Form" + xnumber));
         this.contents = contents;
 
@@ -160,7 +160,7 @@ public class PDFFormXObject extends PDFXObject {
     }
 
     /** {@inheritDoc} */
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
         final int len = super.output(stream);
 
         //Now that the data has been written, it can be discarded.
index 9e93ebee8c9e70bd70e37c2daf092b9f1dde112c..44198105b10ed97db90b991647bfd12aff2c5d63 100644 (file)
@@ -380,8 +380,7 @@ public class PDFFunction extends PDFObject {
         int numberOfFunctions = 0;
         int tempInt = 0;
         StringBuffer p = new StringBuffer(256);
-        p.append(getObjectID()
-                + "<< \n/FunctionType " + this.functionType + " \n");
+        p.append("<< \n/FunctionType " + this.functionType + " \n");
 
         // FunctionType 0
         if (this.functionType == 0) {
@@ -482,15 +481,14 @@ public class PDFFunction extends PDFObject {
                     p.append("] \n");
                 }
             }
-            p.append(">> \n");
+            p.append(">>");
 
             // stream representing the function
             if (this.functionDataStream != null) {
-                p.append("stream\n" + this.functionDataStream
-                         + "\nendstream\n");
+                p.append("\nstream\n" + this.functionDataStream
+                         + "\nendstream");
             }
 
-            p.append("endobj\n");
             // end of if FunctionType 0
 
         } else if (this.functionType == 2) {
@@ -550,7 +548,7 @@ public class PDFFunction extends PDFObject {
                      + PDFNumber.doubleOut(new Double(this.interpolationExponentN))
                      + " \n");
 
-            p.append(">> \nendobj\n");
+            p.append(">>");
 
         } else if (this.functionType
                    == 3) {                       // fix this up when my eyes uncross
@@ -643,10 +641,7 @@ public class PDFFunction extends PDFObject {
                 }
 
             }
-            p.append("] \n");
-
-
-            p.append(">> \nendobj\n");
+            p.append("]\n>>");
         } else if (this.functionType
                    == 4) {                       // fix this up when my eyes uncross
             // DOMAIN
@@ -681,15 +676,14 @@ public class PDFFunction extends PDFObject {
                          + " \n");
             }
 
-            p.append(">> \n");
+            p.append(">>");
 
             // stream representing the function
             if (this.functionDataStream != null) {
-                p.append("stream\n{ " + this.functionDataStream
-                         + " } \nendstream\n");
+                p.append("\nstream\n{ " + this.functionDataStream
+                         + " }\nendstream");
             }
 
-            p.append("endobj\n");
 
         }
 
index fe57e39c2ace14747fb48ecc1f7ea3a4c033b4f0..7306218aeda7cc27f8e9577f3ff9edfaee47faf7 100644 (file)
@@ -149,12 +149,10 @@ public class PDFGState extends PDFObject {
      */
     public String toPDFString() {
         StringBuffer sb = new StringBuffer(64);
-        sb.append(getObjectID());
         sb.append("<<\n/Type /ExtGState\n");
         appendVal(sb, GSTATE_ALPHA_NONSTROKE);
         appendVal(sb, GSTATE_ALPHA_STROKE);
-
-        sb.append(">>\nendobj\n");
+        sb.append(">>");
         return sb.toString();
     }
 
index 0626f0fcd73c2fab26a3228ffb7ad2a34dee7637..784aa4f953dfcd3c660684cab1656e2f4d064232 100644 (file)
@@ -124,9 +124,7 @@ public class PDFGoTo extends PDFAction {
         } else {
             dest = "/D [" + this.pageReference + " " + destination + "]\n";
         }
-        return getObjectID()
-                    + "<< /Type /Action\n/S /GoTo\n" + dest
-                    + ">>\nendobj\n";
+        return "<< /Type /Action\n/S /GoTo\n" + dest + ">>";
     }
 
     /*
index 93fbe47de82f975734f188ad95768f80c100ab84..2dccdafceb256cc086166620b800eebf5206f38b 100644 (file)
@@ -106,7 +106,6 @@ public class PDFGoToRemote extends PDFAction {
      */
     public String toPDFString() {
         StringBuffer sb = new StringBuffer(64);
-        sb.append(getObjectID());
         sb.append("<<\n/S /GoToR\n/F ");
         sb.append(pdfFileSpec.toString());
         sb.append("\n");
@@ -121,7 +120,7 @@ public class PDFGoToRemote extends PDFAction {
             sb.append("/NewWindow true");
         }
 
-        sb.append(" \n>>\nendobj\n");
+        sb.append("\n>>");
 
         return sb.toString();
     }
index 87e8f5475dd14086ce1687cefc0c58d65956f465..b86ba29f5453af54f87988997c67910fa35e03fe 100644 (file)
@@ -99,9 +99,7 @@ public class PDFICCBasedColorSpace extends PDFObject implements PDFColorSpace {
     @Override
     protected String toPDFString() {
         StringBuffer sb = new StringBuffer(64);
-        sb.append(getObjectID());
         sb.append("[/ICCBased ").append(getICCStream().referencePDF()).append("]");
-        sb.append("\nendobj\n");
         return sb.toString();
     }
 
index 9002fcc94816026627e68dee5d1e689d4d481106..33b81307b633441b9cc1619a9ed3d064b0d6e583 100644 (file)
@@ -64,7 +64,7 @@ public class PDFICCStream extends PDFStream {
      * {@inheritDoc}
      */
     @Override
-    protected int output(java.io.OutputStream stream)
+    public int output(java.io.OutputStream stream)
                 throws java.io.IOException {
         int length = super.output(stream);
         this.cp = null; //Free ICC stream when it's not used anymore
index 9ec8f1595c31eedb81711233147eb71a343dcc74..acab4c19c3d5e0d076967f44be5e7ad22d935bb6 100644 (file)
@@ -61,7 +61,7 @@ public class PDFImageXObject extends PDFXObject {
      * @throws IOException if there is an error writing the data
      * @return the length of the data written
      */
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
         int length = super.output(stream);
 
         // let it gc
@@ -137,7 +137,7 @@ public class PDFImageXObject extends PDFXObject {
             put("SMask", ref);
         }
         //Important: do this at the end so previous values can be overwritten.
-        pdfimage.populateXObjectDictionary(this);
+        pdfimage.populateXObjectDictionary(getDictionary());
     }
 
     /** {@inheritDoc} */
index 3f3fb3b46d981cf64f435900fc97ff70a5ed209b..d457c288841b5ec6a7d9bf3ba9c7cf6bdd89efcd 100644 (file)
@@ -169,7 +169,6 @@ public class PDFInfo extends PDFObject {
         PDFProfile profile = getDocumentSafely().getProfile();
         ByteArrayOutputStream bout = new ByteArrayOutputStream(128);
         try {
-            bout.write(encode(getObjectID()));
             bout.write(encode("<<\n"));
             if (title != null && title.length() > 0) {
                 bout.write(encode("/Title "));
@@ -229,7 +228,7 @@ public class PDFInfo extends PDFObject {
                 bout.write(encode("/Trapped /False\n"));
             }
 
-            bout.write(encode(">>\nendobj\n"));
+            bout.write(encode(">>"));
         } catch (IOException ioe) {
             log.error("Ignored I/O exception", ioe);
         }
index e62da5279c039000c86a6c3b3efcd5f4eb9ca7d5..7d80ddb4356f6e4c8b1d589cc762d8adb49b4cbc 100644 (file)
@@ -54,10 +54,9 @@ public class PDFLaunch extends PDFAction {
     /** {@inheritDoc} */
     public String toPDFString() {
         StringBuffer sb = new StringBuffer(64);
-        sb.append(getObjectID());
         sb.append("<<\n/S /Launch\n/F ");
         sb.append(externalFileSpec.toString());
-        sb.append(" \n>>\nendobj\n");
+        sb.append("\n>>");
 
         return sb.toString();
     }
index 934932648da98f1ffb62aff5a177361791f23702..ffec6f09c6fbdb4657947fdf5060035d1e3a7cf2 100644 (file)
@@ -92,15 +92,14 @@ public class PDFLink extends PDFObject {
             f |= 1 << (5 - 1); //NoRotate, bit 5
             fFlag = "/F " + f;
         }
-        String s = getObjectID()
-                   + "<< /Type /Annot\n" + "/Subtype /Link\n" + "/Rect [ "
+        String s = "<< /Type /Annot\n" + "/Subtype /Link\n" + "/Rect [ "
                    + (ulx) + " " + (uly) + " "
                    + (brx) + " " + (bry) + " ]\n" + "/C [ "
                    + this.color + " ]\n" + "/Border [ 0 0 0 ]\n" + "/A "
                    + this.action.getAction() + "\n" + "/H /I\n"
                    + (this.structParent != null
                            ? "/StructParent " + this.structParent.toString() + "\n" : "")
-                   + fFlag + "\n>>\nendobj\n";
+                   + fFlag + "\n>>";
         return s;
     }
 
index b9612d11bbb0e6e3a7c31a6626bd50a84a202380..9b1b8165b2e806151eab2ecdfad387498e7e2435 100644 (file)
@@ -79,7 +79,7 @@ public class PDFMetadata extends PDFStream {
      * byte arrays around so much
      * {@inheritDoc}
      */
-    protected int output(java.io.OutputStream stream)
+    public int output(java.io.OutputStream stream)
                 throws java.io.IOException {
         int length = super.output(stream);
         this.xmpMetadata = null; //Release DOM when it's not used anymore
index 7fa6842fa58e5ea68fd69710851f84175d0f6bf1..23294cc54edcae547be953cf9ccc01dd9f6ca9dd 100644 (file)
@@ -108,22 +108,11 @@ public class PDFName extends PDFObject {
         return name.hashCode();
     }
 
-
-    /** {@inheritDoc} */
     @Override
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
         CountingOutputStream cout = new CountingOutputStream(stream);
         StringBuilder textBuffer = new StringBuilder(64);
-        if (hasObjectNumber()) {
-            textBuffer.append(getObjectID());
-        }
-
         textBuffer.append(toString());
-
-        if (hasObjectNumber()) {
-            textBuffer.append("\nendobj\n");
-        }
-
         PDFDocument.flushTextBuffer(textBuffer, cout);
         return cout.getCount();
     }
index 5bc648ced1cefe085b6c1506832365ff55a5d970..95242305c44917f5cd522c26707da0ca7450d2a5 100644 (file)
@@ -85,13 +85,7 @@ public class PDFNumber extends PDFObject {
                 "The number of this PDFNumber must not be empty");
         }
         StringBuffer sb = new StringBuffer(64);
-        if (hasObjectNumber()) {
-            sb.append(getObjectID());
-        }
         sb.append(doubleOut(getNumber().doubleValue(), 10));
-        if (hasObjectNumber()) {
-            sb.append("\nendobj\n");
-        }
         return sb.toString();
     }
 
index ecd3016477705adf235069336bda672017e04a80..e9e1855b0a29041d0c7d8f9a0ed83429edf52c7f 100644 (file)
@@ -88,13 +88,9 @@ public class PDFNumsArray extends PDFObject {
 
     /** {@inheritDoc} */
     @Override
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
         CountingOutputStream cout = new CountingOutputStream(stream);
         StringBuilder textBuffer = new StringBuilder(64);
-        if (hasObjectNumber()) {
-            textBuffer.append(getObjectID());
-        }
-
         textBuffer.append('[');
         boolean first = true;
         for (Map.Entry<Integer, Object> entry : this.map.entrySet()) {
@@ -107,11 +103,6 @@ public class PDFNumsArray extends PDFObject {
             formatObject(entry.getValue(), cout, textBuffer);
         }
         textBuffer.append(']');
-
-        if (hasObjectNumber()) {
-            textBuffer.append("\nendobj\n");
-        }
-
         PDFDocument.flushTextBuffer(textBuffer, cout);
         return cout.getCount();
     }
index 5abb5a142ab5360300f214a6359ba814dac0daf9..1b9c4eea754bf4bc3c4333f50346c282bfed45d4 100644 (file)
@@ -204,7 +204,7 @@ public abstract class PDFObject implements PDFWritable {
      * @throws IOException if there is an error writing to the stream
      * @return the number of bytes written
      */
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
         byte[] pdf = this.toPDF();
         stream.write(pdf);
         return pdf.length;
index 66116c681122774e85f28aaec9ea67de611a09da..61c5625481d4ed2c84e095003307137ce1b65c44 100644 (file)
@@ -131,7 +131,6 @@ public class PDFOutline extends PDFObject {
     protected byte[] toPDF() {
         ByteArrayOutputStream bout = new ByteArrayOutputStream(128);
         try {
-            bout.write(encode(getObjectID()));
             bout.write(encode("<<"));
             if (parent == null) {
                 // root Outlines object
@@ -164,7 +163,7 @@ public class PDFOutline extends PDFObject {
                     bout.write(encode(" /A " + actionRef + "\n"));
                 }
             }
-            bout.write(encode(">> endobj\n"));
+            bout.write(encode(">>"));
         } catch (IOException ioe) {
             log.error("Ignored I/O exception", ioe);
         }
index ea073829bf33b1684123f550c661bba011b75b24..1c03739446a93ba61d4223b21396d6b5c3b71079 100644 (file)
@@ -130,7 +130,6 @@ public class PDFOutputIntent extends PDFObject {
     public byte[] toPDF() {
         ByteArrayOutputStream bout = new ByteArrayOutputStream(128);
         try {
-            bout.write(encode(getObjectID()));
             bout.write(encode("<<\n"));
             bout.write(encode("/Type /OutputIntent\n"));
 
@@ -164,7 +163,7 @@ public class PDFOutputIntent extends PDFObject {
                 bout.write(encode("/DestOutputProfile " + destOutputProfile.referencePDF() + "\n"));
             }
 
-            bout.write(encode(">>\nendobj\n"));
+            bout.write(encode(">>"));
         } catch (IOException ioe) {
             log.error("Ignored I/O exception", ioe);
         }
index 61d860eaa0e97a58d92c02c42a9a4ca18aed54f2..98c293a9791c52c30511d7c39679afd91ba52ca5 100644 (file)
@@ -109,10 +109,9 @@ public class PDFPages extends PDFObject {
      */
     public String toPDFString() {
         StringBuffer sb = new StringBuffer(64);
-        sb.append(getObjectID())
-            .append("<< /Type /Pages\n/Count ")
-            .append(this.getCount())
-            .append("\n/Kids [");
+        sb.append("<< /Type /Pages\n/Count ")
+                .append(this.getCount())
+                .append("\n/Kids [");
         for (int i = 0; i < kids.size(); i++) {
             Object kid = kids.get(i);
             if (kid == null) {
@@ -120,7 +119,7 @@ public class PDFPages extends PDFObject {
             }
             sb.append(kid).append(" ");
         }
-        sb.append("] >>\nendobj\n");
+        sb.append("] >>");
         return sb.toString();
     }
 
index 378b1cf8b9cd34b9c799194b826c31d40f679efb..88a2ff4925ad3789f74baf2120f71bc0d6e3f03c 100644 (file)
@@ -210,13 +210,12 @@ public class PDFPattern extends PDFPathPaint {
      * @throws IOException if there is an error writing to the stream
      * @return the PDF string.
      */
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
 
         int vectorSize = 0;
         int tempInt = 0;
         byte[] buffer;
         StringBuffer p = new StringBuffer(64);
-        p.append(getObjectID());
         p.append("<< \n/Type /Pattern \n");
 
         if (this.resources != null) {
@@ -323,10 +322,6 @@ public class PDFPattern extends PDFPathPaint {
             length += pdfStream.outputStreamData(encodedStream, stream);
         }
 
-        buffer = encode("\nendobj\n");
-        stream.write(buffer);
-        length += buffer.length;
-
         return length;
     }
 
index 70f9af50477882c6c6078219bc21d4971b8ca0fe..df8647bf41c3463a5867389c40bf948d2c4ca81b 100644 (file)
@@ -192,8 +192,8 @@ public class PDFResources extends PDFDictionary {
         return cs;
     }
 
-    /** {@inheritDoc} */
-    protected int output(OutputStream stream) throws IOException {
+    @Override
+    public int output(OutputStream stream) throws IOException {
         populateDictionary();
         return super.output(stream);
     }
index 81b93b159f767b29f17a62202d8dae1e79f0c019..e74c7747802c3549a5ef29dfbd8ec814f902b2b7 100644 (file)
@@ -76,7 +76,7 @@ public class PDFRoot extends PDFDictionary {
     }
 
     /** {@inheritDoc} */
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
         getDocument().getProfile().verifyTaggedPDF();
         return super.output(stream);
     }
index 2f955b8504b18249e3ef7e781532871291195956..90953968c5850af279793ae3ad01e136af09f079 100644 (file)
@@ -342,8 +342,7 @@ public class PDFShading extends PDFObject {
         int vectorSize;
         int tempInt;
         StringBuffer p = new StringBuffer(128);
-        p.append(getObjectID()
-            + "<< \n/ShadingType " + this.shadingType + " \n");
+        p.append("<<\n/ShadingType " + this.shadingType + " \n");
         if (this.colorSpace != null) {
             p.append("/ColorSpace /"
                      + this.colorSpace.getName() + " \n");
@@ -528,7 +527,7 @@ public class PDFShading extends PDFObject {
 
         }
 
-        p.append(">> \nendobj\n");
+        p.append(">>");
 
         return (p.toString());
     }
index 5f74a2613e92f70ecd5f5219fcb9ed8d0a017783..a0b990ec5a18746a13d4cf1f74f2d9dd75deda16 100644 (file)
@@ -21,6 +21,7 @@ package org.apache.fop.pdf;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.io.Writer;
 
 /**
@@ -44,16 +45,33 @@ public class PDFStream extends AbstractPDFStream {
      * Create an empty stream object
      */
     public PDFStream() {
-        super();
+        setUp();
+    }
+
+    public PDFStream(PDFDictionary dictionary) {
+        super(dictionary);
+        setUp();
+    }
+
+    public PDFStream(PDFDictionary dictionary, boolean encodeOnTheFly) {
+        super(dictionary, encodeOnTheFly);
+        setUp();
+    }
+
+    public PDFStream(boolean encodeOnTheFly) {
+        super(encodeOnTheFly);
+        setUp();
+    }
+
+    private void setUp() {
         try {
             data = StreamCacheFactory.getInstance().createStreamCache();
-            this.streamWriter = new java.io.OutputStreamWriter(
+            this.streamWriter = new OutputStreamWriter(
                     getBufferOutputStream(), PDFDocument.ENCODING);
             //Buffer to minimize calls to the converter
             this.streamWriter = new java.io.BufferedWriter(this.streamWriter);
-        } catch (IOException ex) {
-            //TODO throw the exception and catch it elsewhere
-            ex.printStackTrace();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
         }
     }
 
@@ -136,7 +154,7 @@ public class PDFStream extends AbstractPDFStream {
     /**
      * {@inheritDoc}
      */
-    protected int output(OutputStream stream) throws IOException {
+    public int output(OutputStream stream) throws IOException {
         final int len = super.output(stream);
 
         //Now that the data has been written, it can be discarded.
index e35a860d97322a82272eb23d3b24207736cd5bba..90a41fb7275d5623fd2d7d7936f1b9cc44cac633 100644 (file)
@@ -31,7 +31,7 @@ import org.apache.fop.util.LanguageTags;
 /**
  * Class representing a PDF Structure Element.
  */
-public class PDFStructElem extends PDFDictionary implements StructureTreeElement {
+public class PDFStructElem extends PDFDictionary implements StructureTreeElement, CompressedObject {
 
     private PDFStructElem parentElement;
 
index d723625ebe845f85ed49e9df15aae367340c9fbb..2bae5dca3425208186879db1718db06a0b3b60f9 100644 (file)
@@ -46,7 +46,7 @@ public class PDFT1Stream extends AbstractPDFFontStream {
      * byte arrays around so much
      * {@inheritDoc}
      */
-    protected int output(java.io.OutputStream stream)
+    public int output(java.io.OutputStream stream)
             throws java.io.IOException {
         if (pfb == null) {
             throw new IllegalStateException("pfb must not be null at this point");
index 643ddb1e857b8f06f0a3d2f207291f6672b61c35..998e14f28f9a40803ca0b12ede26c4e5c13e49e0 100644 (file)
@@ -53,7 +53,7 @@ public class PDFTTFStream extends AbstractPDFFontStream {
      * byte arrays around so much
      * {@inheritDoc}
      */
-    protected int output(java.io.OutputStream stream)
+    public int output(java.io.OutputStream stream)
             throws java.io.IOException {
         if (log.isDebugEnabled()) {
             log.debug("Writing " + origLength + " bytes of TTF font data");
index 9566f60da50387e9dc3c4f99db60406c00501ee9..3cddfe4267f0b53bd901ed22522c0619fa84c246 100644 (file)
@@ -60,11 +60,9 @@ public class PDFText extends PDFObject {
                 "The text of this PDFText must not be empty");
         }
         StringBuffer sb = new StringBuffer(64);
-        sb.append(getObjectID());
         sb.append("(");
         sb.append(escapeText(getText()));
         sb.append(")");
-        sb.append("\nendobj\n");
         return sb.toString();
     }
 
index a6124ec0355fa57f6b3cf953c6925844fe219262..b3d377ff15efdf306ff4bcd9be329d56e3d93f11 100644 (file)
@@ -55,8 +55,7 @@ public class PDFUri extends PDFAction {
     /** {@inheritDoc} */
     public String toPDFString() {
         //TODO Convert this class into a dictionary
-        return getObjectID() + getDictString() + "\nendobj\n";
-        //throw new UnsupportedOperationException("This method should not be called");
+        return getDictString();
     }
 
 }
index d1ce6d75e2b607d199b8f2f1339cbd96c0e196a5..c2b70265097dc47e38a7e36e53195d6dd24fb192 100644 (file)
@@ -41,6 +41,10 @@ public abstract class PDFXObject extends AbstractPDFStream {
         super();
     }
 
+    protected PDFXObject(PDFDictionary dictionary) {
+        super(dictionary);
+    }
+
     /**
      * Returns the XObject's name.
      * @return the name of the XObject
index 0df63d312e3bbd57ec0792440d257008f46aef17..4bdc7a1b431d983fa686c994e80be90a46d7d417 100644 (file)
@@ -48,12 +48,13 @@ public enum Version {
     }
 
     /**
-     * Given the PDF version as a String, returns the corresponding enumerated type. The String
-     * should be in the format "1.x" for PDF v1.x.
+     * Given the PDF version as a String, returns the corresponding enumerated type. The
+     * String should be in the format "1.x" for PDF v1.x.
      *
      * @param version a version number
      * @return the corresponding Version instance
-     * @throws IllegalArgumentException if the argument does not correspond to any existing PDF version
+     * @throws IllegalArgumentException if the argument does not correspond to any
+     * existing PDF version
      */
     public static Version getValueOf(String version) {
         for (Version pdfVersion : Version.values()) {
diff --git a/src/java/org/apache/fop/pdf/xref/CompressedObjectReference.java b/src/java/org/apache/fop/pdf/xref/CompressedObjectReference.java
new file mode 100644 (file)
index 0000000..eb619fc
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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.xref;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * A reference to an indirect object stored in an object stream. Contains the relevant
+ * information to add to a cross-reference stream.
+ */
+public class CompressedObjectReference implements ObjectReference {
+
+    private final int objectNumber;
+
+    private final int objectStreamNumber;
+
+    private final int index;
+
+    /**
+     * Creates a new reference.
+     *
+     * @param objectNumber the number of the compressed object being referenced
+     * @param objectStreamNumber the number of the object stream in which the compressed
+     * object is to be found
+     * @param index the index of the compressed object in the object stream
+     */
+    public CompressedObjectReference(int objectNumber, int objectStreamNumber, int index) {
+        this.objectNumber = objectNumber;
+        this.objectStreamNumber = objectStreamNumber;
+        this.index = index;
+    }
+
+    public void output(DataOutputStream out) throws IOException {
+        out.write(2);
+        out.writeLong(objectStreamNumber);
+        out.write(0);
+        out.write(index);
+    }
+
+    public int getObjectNumber() {
+        return objectNumber;
+    }
+
+    public int getObjectStreamNumber() {
+        return objectStreamNumber;
+    }
+
+}
diff --git a/src/java/org/apache/fop/pdf/xref/CrossReferenceObject.java b/src/java/org/apache/fop/pdf/xref/CrossReferenceObject.java
new file mode 100644 (file)
index 0000000..3db50ec
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.xref;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * A representation of the cross-reference data to be output at the end of a PDF file.
+ */
+public abstract class CrossReferenceObject {
+
+    protected final TrailerDictionary trailerDictionary;
+
+    protected final long startxref;
+
+    CrossReferenceObject(TrailerDictionary trailerDictionary, long startxref) {
+        this.trailerDictionary = trailerDictionary;
+        this.startxref = startxref;
+    }
+
+    /**
+     * Writes the cross reference data to a PDF stream
+     *
+     * @param stream the stream to write the cross reference to
+     * @throws IOException if an I/O exception occurs while writing the data
+     */
+    public abstract void output(OutputStream stream) throws IOException;
+}
diff --git a/src/java/org/apache/fop/pdf/xref/CrossReferenceStream.java b/src/java/org/apache/fop/pdf/xref/CrossReferenceStream.java
new file mode 100644 (file)
index 0000000..32c3157
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * 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.xref;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.fop.pdf.PDFArray;
+import org.apache.fop.pdf.PDFDictionary;
+import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFFilterList;
+import org.apache.fop.pdf.PDFName;
+import org.apache.fop.pdf.PDFStream;
+
+/**
+ * A cross-reference stream, as described in Section 3.4.7 of the PDF 1.5 Reference.
+ */
+public class CrossReferenceStream extends CrossReferenceObject {
+
+    private static final PDFName XREF = new PDFName("XRef");
+
+    private final PDFDocument document;
+
+    private final int objectNumber;
+
+    private final List<ObjectReference> objectReferences;
+
+    public CrossReferenceStream(PDFDocument document,
+            int objectNumber,
+            TrailerDictionary trailerDictionary,
+            long startxref,
+            List<Long> uncompressedObjectReferences,
+            List<CompressedObjectReference> compressedObjectReferences) {
+        super(trailerDictionary, startxref);
+        this.document = document;
+        this.objectNumber = objectNumber;
+        this.objectReferences = new ArrayList<ObjectReference>(uncompressedObjectReferences.size());
+        for (Long offset : uncompressedObjectReferences) {
+            objectReferences.add(offset == null ? null : new UncompressedObjectReference(offset));
+        }
+        for (CompressedObjectReference ref : compressedObjectReferences) {
+            this.objectReferences.set(ref.getObjectNumber() - 1, ref);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public void output(OutputStream stream) throws IOException {
+        populateDictionary();
+        PDFStream helperStream = new PDFStream(trailerDictionary.getDictionary(), false) {
+
+            @Override
+            protected void setupFilterList() {
+                PDFFilterList filterList = getFilterList();
+                assert !filterList.isInitialized();
+                filterList.addDefaultFilters(document.getFilterMap(), getDefaultFilterName());
+            }
+
+        };
+        helperStream.setObjectNumber(objectNumber);
+        helperStream.setDocument(document);
+        ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
+        DataOutputStream data = new DataOutputStream(byteArray);
+        addFreeEntryForObject0(data);
+        for (ObjectReference objectReference : objectReferences) {
+            assert objectReference != null;
+            objectReference.output(data);
+        }
+        new UncompressedObjectReference(startxref).output(data);
+        data.close();
+        helperStream.setData(byteArray.toByteArray());
+        PDFDocument.outputIndirectObject(helperStream, stream);
+    }
+
+    private void populateDictionary() throws IOException {
+        int objectCount = objectReferences.size() + 1;
+        PDFDictionary dictionary = trailerDictionary.getDictionary();
+        dictionary.put("/Type", XREF);
+        dictionary.put("/Size", objectCount + 1);
+        dictionary.put("/W", new PDFArray(1, 8, 2));
+    }
+
+    private void addFreeEntryForObject0(DataOutputStream data) throws IOException {
+        data.write(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xff, (byte) 0xff});
+    }
+
+}
diff --git a/src/java/org/apache/fop/pdf/xref/CrossReferenceTable.java b/src/java/org/apache/fop/pdf/xref/CrossReferenceTable.java
new file mode 100644 (file)
index 0000000..41a1146
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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.xref;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+import org.apache.fop.pdf.PDFDictionary;
+import org.apache.fop.pdf.PDFDocument;
+
+/**
+ * A cross-reference table, as described in Section 3.4.3 of the PDF 1.5 Reference.
+ */
+public class CrossReferenceTable extends CrossReferenceObject {
+
+    private final List<Long> objectReferences;
+
+    private final StringBuilder pdf = new StringBuilder(256);
+
+    public CrossReferenceTable(TrailerDictionary trailerDictionary, long startxref,
+            List<Long> location) {
+        super(trailerDictionary, startxref);
+        this.objectReferences = location;
+    }
+
+    public void output(OutputStream stream) throws IOException {
+        outputXref();
+        writeTrailer(stream);
+    }
+
+    private void outputXref() throws IOException {
+        pdf.append("xref\n0 ");
+        pdf.append(objectReferences.size() + 1);
+        pdf.append("\n0000000000 65535 f \n");
+        for (Long objectReference : objectReferences) {
+            final String padding = "0000000000";
+            String s = String.valueOf(objectReference);
+            if (s.length() > 10) {
+                throw new IOException("PDF file too large."
+                        + " PDF 1.4 cannot grow beyond approx. 9.3GB.");
+            }
+            String loc = padding.substring(s.length()) + s;
+            pdf.append(loc).append(" 00000 n \n");
+        }
+    }
+
+    private void writeTrailer(OutputStream stream) throws IOException {
+        pdf.append("trailer\n");
+        stream.write(PDFDocument.encode(pdf.toString()));
+        PDFDictionary dictionary = trailerDictionary.getDictionary();
+        dictionary.put("/Size", objectReferences.size() + 1);
+        dictionary.output(stream);
+    }
+
+}
diff --git a/src/java/org/apache/fop/pdf/xref/ObjectReference.java b/src/java/org/apache/fop/pdf/xref/ObjectReference.java
new file mode 100644 (file)
index 0000000..894a66c
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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.xref;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * A reference to an indirect object.
+ */
+interface ObjectReference {
+
+    /**
+     * Outputs this reference to the given stream, in the cross-reference stream format.
+     * For example, a object may output the bytes 01 00 00 00 00 00 00 01 ff 00 to
+     * indicate a non-compressed object (01), at offset 511 from the beginning of the file
+     * (00 00 00 00 00 00 01 ff), of generation number 0 (00).
+     *
+     * @param out the stream to which to output the reference
+     */
+    void output(DataOutputStream out) throws IOException;
+}
diff --git a/src/java/org/apache/fop/pdf/xref/TrailerDictionary.java b/src/java/org/apache/fop/pdf/xref/TrailerDictionary.java
new file mode 100644 (file)
index 0000000..d5d6252
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * 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.xref;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.fop.pdf.PDFArray;
+import org.apache.fop.pdf.PDFDictionary;
+import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFEncryption;
+import org.apache.fop.pdf.PDFInfo;
+import org.apache.fop.pdf.PDFRoot;
+import org.apache.fop.pdf.PDFText;
+import org.apache.fop.pdf.PDFWritable;
+
+/**
+ * A data class representing entries of the file trailer dictionary.
+ */
+public class TrailerDictionary {
+
+    private final PDFDictionary dictionary;
+
+    public TrailerDictionary(PDFDocument pdfDocument) {
+        this.dictionary = new PDFDictionary();
+        this.dictionary.setDocument(pdfDocument);
+    }
+
+    /** Sets the value of the Root entry. */
+    public TrailerDictionary setRoot(PDFRoot root) {
+        dictionary.put("/Root", root);
+        return this;
+    }
+
+    /** Sets the value of the Info entry. */
+    public TrailerDictionary setInfo(PDFInfo info) {
+        dictionary.put("/Info", info);
+        return this;
+    }
+
+    /** Sets the value of the Encrypt entry. */
+    public TrailerDictionary setEncryption(PDFEncryption encryption) {
+        dictionary.put("/Encrypt", encryption);
+        return this;
+    }
+
+    /** Sets the value of the ID entry. */
+    public TrailerDictionary setFileID(byte[] originalFileID, byte[] updatedFileID) {
+        // TODO this is ugly! Used to circumvent the fact that the file ID will be
+        // encrypted if directly stored as a byte array
+        class FileID implements PDFWritable {
+
+            private final byte[] fileID;
+
+            FileID(byte[] id) {
+                fileID = id;
+            }
+
+            public void outputInline(OutputStream out, StringBuilder textBuffer)
+                    throws IOException {
+                PDFDocument.flushTextBuffer(textBuffer, out);
+                String hex = PDFText.toHex(fileID, true);
+                byte[] encoded = hex.getBytes("US-ASCII");
+                out.write(encoded);
+            }
+
+        }
+        PDFArray fileID = new PDFArray(new FileID(originalFileID), new FileID(updatedFileID));
+        dictionary.put("/ID", fileID);
+        return this;
+    }
+
+    PDFDictionary getDictionary() {
+        return dictionary;
+    }
+
+}
diff --git a/src/java/org/apache/fop/pdf/xref/UncompressedObjectReference.java b/src/java/org/apache/fop/pdf/xref/UncompressedObjectReference.java
new file mode 100644 (file)
index 0000000..a54ec62
--- /dev/null
@@ -0,0 +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.xref;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+/**
+ * A reference to an indirect object that is not stored in an object stream.
+ */
+class UncompressedObjectReference implements ObjectReference {
+
+    final long offset;
+
+    /**
+     * Creates a new reference.
+     *
+     * @param offset offset of the object from the beginning of the PDF file
+     */
+    UncompressedObjectReference(long offset) {
+        this.offset = offset;
+    }
+
+    public void output(DataOutputStream out) throws IOException {
+        out.write(1);
+        out.writeLong(offset);
+        out.write(0);
+        out.write(0);
+    }
+
+}
index 88a6e9c22fbdede26ede586e5de52619498c8ab1..1c9f9b49d05f46a7d5c6f0bc45bf59b10abb2657 100644 (file)
@@ -95,15 +95,15 @@ class PDFLogicalStructureHandler {
      */
     PDFLogicalStructureHandler(PDFDocument pdfDoc) {
         this.pdfDoc = pdfDoc;
-        PDFStructTreeRoot structTreeRoot = pdfDoc.getFactory().makeStructTreeRoot(parentTree);
-        rootStructureElement = pdfDoc.getFactory().makeStructureElement(
+        PDFStructTreeRoot structTreeRoot = pdfDoc.makeStructTreeRoot(parentTree);
+        rootStructureElement = pdfDoc.makeStructureElement(
                 FOToPDFRoleMap.mapFormattingObject("root", structTreeRoot), structTreeRoot);
         structTreeRoot.addKid(rootStructureElement);
     }
 
 
     PDFStructElem createPageSequence(Locale language) {
-        PDFStructElem structElemPart = pdfDoc.getFactory().makeStructureElement(
+        PDFStructElem structElemPart = pdfDoc.makeStructureElement(
                 FOToPDFRoleMap.mapFormattingObject("page-sequence", rootStructureElement),
                 rootStructureElement);
         rootStructureElement.addKid(structElemPart);
index 83f6ccab67b1bb3ea188ea7dc5fb280473e293be..53d2596772056d0e0b95f814f3e9d7770c2c7f6f 100644 (file)
@@ -385,8 +385,8 @@ class PDFRenderingUtil implements PDFConfigurationConstants {
         if (maxPDFVersion == null) {
             this.pdfDoc = new PDFDocument(producer);
         } else {
-            VersionController controller =
-                    VersionController.getFixedVersionController(maxPDFVersion);
+            VersionController controller
+                    VersionController.getFixedVersionController(maxPDFVersion);
             this.pdfDoc = new PDFDocument(producer, controller);
         }
         updateInfo();
@@ -411,6 +411,9 @@ class PDFRenderingUtil implements PDFConfigurationConstants {
             log.debug("PDF/A is active. Conformance Level: " + pdfAMode);
             addPDFA1OutputIntent();
         }
+
+        this.pdfDoc.enableAccessibility(userAgent.isAccessibilityEnabled());
+
         return this.pdfDoc;
     }
 
index 11eba4ea45a3200a97d86a1a36ae275b3c084fb4..2a2a4a392e0b523edcc9e192b7603e3f0c2ec579 100644 (file)
@@ -65,7 +65,7 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler {
         PDFStructElem parent = ancestors.getFirst();
         String role = attributes.getValue("role");
         PDFStructElem created;
-        created = pdfFactory.makeStructureElement(
+        created = pdfFactory.getDocument().makeStructureElement(
                 FOToPDFRoleMap.mapFormattingObject(name, role, parent, eventBroadcaster), parent);
         parent.addKid(created);
         ancestors.addFirst(created);
@@ -84,7 +84,7 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler {
         PDFStructElem parent = ancestors.getFirst();
         String role = attributes.getValue("role");
         PDFStructElem created;
-        created = pdfFactory.makeStructureElement(
+        created = pdfFactory.getDocument().makeStructureElement(
                 FOToPDFRoleMap.mapFormattingObject(name, role, parent, eventBroadcaster), parent);
         parent.addKid(created);
         String altTextNode = attributes.getValue(ExtensionElementMapping.URI, "alt-text");
@@ -104,7 +104,7 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler {
         if ("#PCDATA".equals(name)) {
             created = new PDFStructElem.Placeholder(parent, name);
         } else {
-            created = pdfFactory.makeStructureElement(
+            created = pdfFactory.getDocument().makeStructureElement(
                     FOToPDFRoleMap.mapFormattingObject(name, role, parent,
                             eventBroadcaster), parent);
         }
diff --git a/test/accessibility/README b/test/accessibility/README
deleted file mode 100644 (file)
index 1d2e043..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-This directory contains sample FO files for testing the accessibility features
-of FOP.
-
-Every FO file in this directory has a corresponding PDF file in the pdf/
-sub-directory. The fop.xconf configuration file was used.
-
-The PDF files have been checked with Adobe Acrobat Professional 9, using both 
-the full accessibility checker and the read-aloud feature. The checker reports 
-no error /and/ the entire document can be read aloud.
-
-
-!! DO NOT MODIFY THOSE FILES, NEITHER THE FO NOR THE PDF !!
-
-
-... Or at least, know what you are doing
-If the FO files are modified, the resulting PDFs must be checked again, both 
-with the checker and the read-aloud feature. (Sometimes the checker reports no 
-problem yet part or all of the document cannot be read aloud.)
-
-The purpose of this infrastructure is to be able to quickly re-test the 
-accessibility processing chain when any change has been made to it. The 
-configuration file disables the compression of the PDF streams, so it is 
-possible to compare a re-generated PDF with the original one by using a simple 
-diff tool. The files will not be identical because of the different creation 
-dates (and the ID key in the trailer), but apart from that there should be no 
-difference.
-
-The rationale is that using a diff tool is much quicker and less tedious than 
-running Acrobat's accessibility checker and read-aloud feature every time.
-
-
-To re-generate the PDF files:
-    ../../fop -c fop.xconf text_1.fo pdf/text_1.new.pdf
-    diff pdf/text_1_painter.pdf pdf/text_1.new.pdf
-Or, going through the intermediate format:
-    ../../fop -c fop.xconf text_1.fo -if application/pdf text_1_if.xml
-    ../../fop -c fop.xconf -ifin text_1_if.xml pdf/text_1.new.pdf
-    diff pdf/text_1.pdf pdf/text_1.new.pdf
-
-
-$Id$
diff --git a/test/accessibility/background-image_jpg_repeat.fo b/test/accessibility/background-image_jpg_repeat.fo
deleted file mode 100644 (file)
index 727162e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body background-image="../resources/images/bgimg72dpi.jpg"/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
-        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
-        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
-        output.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/background-image_jpg_single.fo b/test/accessibility/background-image_jpg_single.fo
deleted file mode 100644 (file)
index 335353e..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body background-image="../resources/images/bgimg72dpi.jpg" 
-        background-repeat="no-repeat" background-position-horizontal="50%" 
-        background-position-vertical="50%"/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
-        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
-        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
-        output.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/background-image_png_repeat.fo b/test/accessibility/background-image_png_repeat.fo
deleted file mode 100644 (file)
index 5e4a8ba..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body background-image="../resources/images/bgimg72dpi.png"/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
-        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
-        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
-        output.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/background-image_png_single.fo b/test/accessibility/background-image_png_single.fo
deleted file mode 100644 (file)
index 90067ec..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body background-image="../resources/images/fop-logo-color-24bit.png" 
-        background-repeat="no-repeat" background-position-horizontal="50%" 
-        background-position-vertical="50%"/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
-        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
-        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
-        output.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/background-image_svg_repeat.fo b/test/accessibility/background-image_svg_repeat.fo
deleted file mode 100644 (file)
index 02520b6..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body background-image="../resources/images/rgb-circles.svg"/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
-        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
-        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
-        output.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/background-image_svg_single.fo b/test/accessibility/background-image_svg_single.fo
deleted file mode 100644 (file)
index 3029f32..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body background-image="../resources/images/rgb-circles.svg" 
-        background-repeat="no-repeat" background-position-horizontal="50%" 
-        background-position-vertical="50%"/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
-        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
-        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
-        output.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/complete.fo b/test/accessibility/complete.fo
deleted file mode 100644 (file)
index 7568475..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
-  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body column-count="2" margin-top="15pt"/>
-      <fo:region-before extent="12pt"/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:static-content flow-name="xsl-region-before">
-      <fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page 
-        <fo:page-number/></fo:block>
-    </fo:static-content>
-    <fo:static-content flow-name="xsl-footnote-separator">
-      <fo:block><fo:leader leader-length="100pt" leader-pattern="rule"/></fo:block>
-    </fo:static-content>
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>(There’s another page sequence <fo:wrapper color="blue"><fo:basic-link 
-            internal-destination="second">below</fo:basic-link></fo:wrapper>.)</fo:block>
-      <fo:block font-family="sans-serif" font-weight="bold" space-before="1em" space-after="0.2em" 
-        role="H1"><fo:block>About Apache FOP</fo:block></fo:block>
-      <fo:block>It is a print formatter driven by XSL formatting objects (XSL-FO) and an output 
-        independent formatter<fo:footnote><fo:inline baseline-shift="super" 
-            font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the <fo:wrapper 
-                color="blue"><fo:basic-link 
-                  external-destination="http://xmlgraphics.apache.org/fop/">FOP 
-                  website</fo:basic-link></fo:wrapper> for more 
-              information</fo:block></fo:footnote-body></fo:footnote>. FOP has a nice logo: 
-        <fo:external-graphic src="../resources/images/fop-logo-color-24bit.png" 
-          inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
-          fox:alt-text="FOP Logo"/></fo:block>
-      <fo:table space-before="10pt" space-after="10pt" width="100%" table-layout="fixed">
-        <fo:table-header>
-          <fo:table-row>
-            <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
-              <fo:block>Header 1.1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
-              <fo:block>Header 1.2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-        </fo:table-header>
-        <fo:table-body>
-          <fo:table-row>
-            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
-              <fo:block>Cell 1.1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
-              <fo:block>Cell 1.2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-          <fo:table-row>
-            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
-              <fo:block>Cell 2.1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
-              <fo:block>Cell 2.2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-        </fo:table-body>
-      </fo:table>
-      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
-        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
-        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
-        output.</fo:block>
-      <fo:block span="all" border-top="1pt solid black" border-bottom="1pt solid black" 
-        padding-before="2pt" padding-after="2pt">This fo:block element spans all the columns of the 
-        document. This is intended to test the abilities of the text-to-speech program.</fo:block>
-      <fo:block>And now we are back to normal content flowing in two columns. Let’s start a numbered 
-        list:</fo:block>
-      <fo:list-block provisional-distance-between-starts="15pt" provisional-label-separation="0mm" 
-        keep-with-previous="auto">
-        <fo:list-item keep-with-previous="always">
-          <fo:list-item-label end-indent="label-end()">
-            <fo:block>1.</fo:block>
-          </fo:list-item-label>
-          <fo:list-item-body start-indent="body-start()">
-            <fo:block>
-              <fo:block>Line 1 of item 1</fo:block>
-              <fo:block>Line 2 of item 1</fo:block>
-              <fo:block>Line 3 of item 1</fo:block>
-            </fo:block>
-          </fo:list-item-body>
-        </fo:list-item>
-        <fo:list-item keep-with-previous="always">
-          <fo:list-item-label end-indent="label-end()">
-            <fo:block>2.</fo:block>
-          </fo:list-item-label>
-          <fo:list-item-body start-indent="body-start()">
-            <fo:block>
-              <fo:block>Line 1 of item 2</fo:block>
-              <fo:block>Line 2 of item 2</fo:block>
-              <fo:block>Line 3 of item 2</fo:block>
-            </fo:block>
-          </fo:list-item-body>
-        </fo:list-item>
-      </fo:list-block>
-      <fo:block>And now we are going to see how a second page sequence is handled.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-  <fo:page-sequence master-reference="page">
-    <fo:static-content flow-name="xsl-region-before">
-      <fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page 
-        <fo:page-number/></fo:block>
-    </fo:static-content>
-    <fo:static-content flow-name="xsl-footnote-separator">
-      <fo:block><fo:leader leader-length="100pt" leader-pattern="rule"/></fo:block>
-    </fo:static-content>
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block id="second">Apache FOP (Formatting Objects Processor) is a print formatter driven by 
-        XSL formatting objects (XSL-FO) and an output independent formatter<fo:footnote><fo:inline 
-            baseline-shift="super" font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the 
-              <fo:wrapper color="blue"><fo:basic-link 
-                  external-destination="http://xmlgraphics.apache.org/fop/">FOP 
-                  website</fo:basic-link></fo:wrapper> for more 
-              information</fo:block></fo:footnote-body></fo:footnote>. It is a Java application that 
-        reads a formatting object (FO) tree and renders the resulting pages to a specified 
-        output.</fo:block>
-      <fo:table space-before="10pt" space-after="10pt" width="100%" table-layout="fixed">
-        <fo:table-header>
-          <fo:table-row>
-            <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
-              <fo:block>Header 1.1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
-              <fo:block>Header 1.2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-        </fo:table-header>
-        <fo:table-body>
-          <fo:table-row>
-            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
-              <fo:block>Cell 1.1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
-              <fo:block>Cell 1.2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-          <fo:table-row>
-            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
-              <fo:block>Cell 2.1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
-              <fo:block>Cell 2.2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-        </fo:table-body>
-      </fo:table>
-      <fo:block language="fr" country="FR">Apache FOP (Formatting Objects Processor) est une 
-        application de mise en page de documents respectant le standard XSL-FO. À partir d’un 
-        document au format XSL-FO, cette application écrite en Java effectue une mise en page et 
-        renvoie un document prêt pour impression.</fo:block>
-      <fo:block span="all" border-top="1pt solid black" border-bottom="1pt solid black" 
-        padding-before="2pt" padding-after="2pt">This fo:block element spans all the columns of the 
-        document. This is intended to test the abilities of the text-to-speech program.</fo:block>
-      <fo:block>And now we are back to normal content flowing in two columns. Let’s start a numbered 
-        list:</fo:block>
-      <fo:list-block provisional-distance-between-starts="15pt" provisional-label-separation="0mm" 
-        keep-with-previous="auto">
-        <fo:list-item keep-with-previous="always">
-          <fo:list-item-label end-indent="label-end()">
-            <fo:block>1.</fo:block>
-          </fo:list-item-label>
-          <fo:list-item-body start-indent="body-start()">
-            <fo:block>
-              <fo:block>Line 1 of item 1</fo:block>
-              <fo:block>Line 2 of item 1</fo:block>
-              <fo:block>Line 3 of item 1</fo:block>
-            </fo:block>
-          </fo:list-item-body>
-        </fo:list-item>
-        <fo:list-item keep-with-previous="always">
-          <fo:list-item-label end-indent="label-end()">
-            <fo:block>2.</fo:block>
-          </fo:list-item-label>
-          <fo:list-item-body start-indent="body-start()">
-            <fo:block>
-              <fo:block>Line 1 of item 2</fo:block>
-              <fo:block>Line 2 of item 2</fo:block>
-              <fo:block>Line 3 of item 2</fo:block>
-            </fo:block>
-          </fo:list-item-body>
-        </fo:list-item>
-      </fo:list-block>
-      <fo:block>The end of the document has now been reached.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/fop.xconf b/test/accessibility/fop.xconf
deleted file mode 100644 (file)
index 8c5dc2b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<fop version="1.0">
-  <accessibility>true</accessibility>
-  <source-resolution>144</source-resolution>
-  <use-cache>false</use-cache>
-  <font-base>../resources/fonts/</font-base>
-  <renderers>
-    <renderer mime="application/pdf">
-      <filterList>
-        <value>null</value>
-      </filterList>
-      <filterList type="image">
-        <value>flate</value>
-        <value>ascii-85</value>
-      </filterList>
-      <fonts>
-        <font embed-url="DejaVuLGCSerif.ttf">
-          <font-triplet name="DejaVu" style="normal" weight="normal"/>
-        </font>
-      </fonts>
-    </renderer>
-  </renderers>
-</fop>
diff --git a/test/accessibility/image_jpg.fo b/test/accessibility/image_jpg.fo
deleted file mode 100644 (file)
index 5fe36f6..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" 
-  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>This document contains an image in the JPEG format: <fo:external-graphic 
-          src="../resources/images/cmyk.jpg"
-          inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
-          fox:alt-text="CMYK colours"/>. Here is the end of the text.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/image_png.fo b/test/accessibility/image_png.fo
deleted file mode 100644 (file)
index b529aa8..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" 
-  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>This document contains an image in the PNG format: <fo:external-graphic 
-          src="../resources/images/fop-logo-color-24bit.png"
-          inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
-          fox:alt-text="FOP Logo"/>. Here is the end of the text.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/image_svg.fo b/test/accessibility/image_svg.fo
deleted file mode 100644 (file)
index bbc77fe..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" 
-  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>This document contains an image in the SVG format: <fo:external-graphic 
-          src="../resources/images/circles.svg"
-          inline-progression-dimension.maximum="75pt" content-width="scale-to-fit"
-          fox:alt-text="Nice circles"/>. And here is the same image as an instream-foreign-object: 
-        <fo:instream-foreign-object inline-progression-dimension.maximum="75pt" 
-          content-width="scale-down-to-fit" fox:alt-text="The same nice circles">
-<svg xmlns="http://www.w3.org/2000/svg" width="12cm" height="12cm">
-  <g style="fill-opacity:0.7; stroke:black; stroke-width:0.1cm;">
-    <circle cx="6cm" cy="2cm" r="100" style="fill:red;" transform="translate(0,50)" />
-    <circle cx="6cm" cy="2cm" r="100" style="fill:blue;" transform="translate(70,150)" />
-    <circle cx="6cm" cy="2cm" r="100" style="fill:green;" transform="translate(-70,150)"/>
-  </g>
-</svg>
-      </fo:instream-foreign-object>.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/image_wmf.fo b/test/accessibility/image_wmf.fo
deleted file mode 100644 (file)
index 1a4de77..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" 
-  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="320pt" page-width="320pt" margin="10pt">
-      <fo:region-body/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>This document contains an image in the WMF format: <fo:external-graphic 
-          src="../resources/images/testChart.wmf"
-          inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
-          fox:alt-text="Metafile Companion Test Chart"/> Here is the end of the text.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/leader.fo b/test/accessibility/leader.fo
deleted file mode 100644 (file)
index ffd7680..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify" 
-      text-align-last="justify">
-      <fo:block>This is a text followed by a leader with leader-pattern=​"use-content", the 
-        content being text:<fo:leader leader-pattern="use-content"><fo:inline> • 
-      </fo:inline></fo:leader>1</fo:block>
-      <fo:block space-before="10pt">This is a text followed by a leader with 
-        leader-pattern=​"use-content", the content being images:<fo:leader 
-          leader-pattern="use-content"><fo:external-graphic 
-            src="../resources/images/list-item.png"/></fo:leader>1</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/links.fo b/test/accessibility/links.fo
deleted file mode 100644 (file)
index 36250e3..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" 
-  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>This is a <fo:wrapper color="blue"><fo:basic-link 
-            internal-destination="FOP">link</fo:basic-link></fo:wrapper> to the next 
-        paragraph.</fo:block>
-      <fo:block id="FOP">Apache FOP (Formatting Objects Processor) is a print formatter driven by 
-        XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
-        application that reads a formatting object (FO) tree and renders the resulting pages to a 
-        specified output.</fo:block>
-      <fo:block>For more information, see the <fo:wrapper color="blue"><fo:basic-link 
-            external-destination="http://xmlgraphics.apache.org/fop/">FOP 
-            website</fo:basic-link></fo:wrapper>.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/pdf/background-image_jpg_repeat.pdf b/test/accessibility/pdf/background-image_jpg_repeat.pdf
deleted file mode 100644 (file)
index 2217617..0000000
Binary files a/test/accessibility/pdf/background-image_jpg_repeat.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/background-image_jpg_single.pdf b/test/accessibility/pdf/background-image_jpg_single.pdf
deleted file mode 100644 (file)
index 232afdd..0000000
Binary files a/test/accessibility/pdf/background-image_jpg_single.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/background-image_png_repeat.pdf b/test/accessibility/pdf/background-image_png_repeat.pdf
deleted file mode 100644 (file)
index 52da402..0000000
Binary files a/test/accessibility/pdf/background-image_png_repeat.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/background-image_png_single.pdf b/test/accessibility/pdf/background-image_png_single.pdf
deleted file mode 100644 (file)
index 356e488..0000000
Binary files a/test/accessibility/pdf/background-image_png_single.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/background-image_svg_repeat.pdf b/test/accessibility/pdf/background-image_svg_repeat.pdf
deleted file mode 100644 (file)
index 0bce240..0000000
Binary files a/test/accessibility/pdf/background-image_svg_repeat.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/background-image_svg_single.pdf b/test/accessibility/pdf/background-image_svg_single.pdf
deleted file mode 100644 (file)
index 3e4afcd..0000000
Binary files a/test/accessibility/pdf/background-image_svg_single.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/complete.pdf b/test/accessibility/pdf/complete.pdf
deleted file mode 100644 (file)
index cffb9e2..0000000
Binary files a/test/accessibility/pdf/complete.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/image_jpg.pdf b/test/accessibility/pdf/image_jpg.pdf
deleted file mode 100644 (file)
index cb004bb..0000000
Binary files a/test/accessibility/pdf/image_jpg.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/image_png.pdf b/test/accessibility/pdf/image_png.pdf
deleted file mode 100644 (file)
index c328937..0000000
Binary files a/test/accessibility/pdf/image_png.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/image_svg.pdf b/test/accessibility/pdf/image_svg.pdf
deleted file mode 100644 (file)
index c3fce5b..0000000
Binary files a/test/accessibility/pdf/image_svg.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/image_wmf.pdf b/test/accessibility/pdf/image_wmf.pdf
deleted file mode 100644 (file)
index b9ec8c5..0000000
Binary files a/test/accessibility/pdf/image_wmf.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/leader.pdf b/test/accessibility/pdf/leader.pdf
deleted file mode 100644 (file)
index c7432e7..0000000
Binary files a/test/accessibility/pdf/leader.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/links.pdf b/test/accessibility/pdf/links.pdf
deleted file mode 100644 (file)
index 91d7c25..0000000
Binary files a/test/accessibility/pdf/links.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/role.pdf b/test/accessibility/pdf/role.pdf
deleted file mode 100644 (file)
index acb4350..0000000
Binary files a/test/accessibility/pdf/role.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/role_non-standard.pdf b/test/accessibility/pdf/role_non-standard.pdf
deleted file mode 100644 (file)
index fcf614e..0000000
Binary files a/test/accessibility/pdf/role_non-standard.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/text_1.pdf b/test/accessibility/pdf/text_1.pdf
deleted file mode 100644 (file)
index 596419c..0000000
Binary files a/test/accessibility/pdf/text_1.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/text_2.pdf b/test/accessibility/pdf/text_2.pdf
deleted file mode 100644 (file)
index 19fff21..0000000
Binary files a/test/accessibility/pdf/text_2.pdf and /dev/null differ
diff --git a/test/accessibility/pdf/text_font-embedding.pdf b/test/accessibility/pdf/text_font-embedding.pdf
deleted file mode 100644 (file)
index 0288449..0000000
Binary files a/test/accessibility/pdf/text_font-embedding.pdf and /dev/null differ
diff --git a/test/accessibility/role.fo b/test/accessibility/role.fo
deleted file mode 100644 (file)
index ced8a4d..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" font-family="sans-serif">
-      <fo:block role="H1" font-weight="bold" font-size="150%"
-        space-before.minimum="1.5em"
-        space-before.optimum="2em"
-        space-before.maximum="3em"
-        space-before.precedence="1000"
-        space-after.minimum="0.2em"
-        space-after.optimum="0.2em"
-        space-after.maximum="0.5em"
-        space-after.precedence="1000">Title 1: To Start With</fo:block>
-      <fo:block role="H2" font-weight="bold" font-size="120%"
-        space-before.minimum="1.2em"
-        space-before.optimum="1.5em"
-        space-before.maximum="2em"
-        space-before.precedence="900"
-        space-after.minimum="0.2em"
-        space-after.optimum="0.2em"
-        space-after.maximum="0.5em"
-        space-after.precedence="900">Title 2: A Sub-Title</fo:block>
-      <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter 
-        driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
-        application that reads a formatting object (FO) tree and renders the resulting pages to a 
-        specified output.</fo:block>
-      <fo:block role="H2" font-weight="bold" font-size="120%"
-        space-before.minimum="1.2em"
-        space-before.optimum="1.5em"
-        space-before.maximum="2em"
-        space-before.precedence="900"
-        space-after.minimum="0.2em"
-        space-after.optimum="0.2em"
-        space-after.maximum="0.5em"
-        space-after.precedence="900">Title 2: Another Sub-Title</fo:block>
-      <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter 
-        driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
-        application that reads a formatting object (FO) tree and renders the resulting pages to a 
-        specified output.</fo:block>
-      <fo:block role="H1" font-weight="bold" font-size="150%"
-        space-before.minimum="1.5em"
-        space-before.optimum="2em"
-        space-before.maximum="3em"
-        space-before.precedence="1000"
-        space-after.minimum="0.2em"
-        space-after.optimum="0.2em"
-        space-after.maximum="0.5em"
-        space-after.precedence="1000">Title 1: Second Title</fo:block>
-      <fo:block role="H2" font-weight="bold" font-size="120%"
-        space-before.minimum="1.2em"
-        space-before.optimum="1.5em"
-        space-before.maximum="2em"
-        space-before.precedence="900"
-        space-after.minimum="0.2em"
-        space-after.optimum="0.2em"
-        space-after.maximum="0.5em"
-        space-after.precedence="900">Title 2: A Sample Table</fo:block>
-      <fo:block>See data below:</fo:block>
-      <fo:table table-layout="fixed" width="70%" start-indent="15%" border="0.5pt solid black">
-        <fo:table-header start-indent="0" font-weight="bold">
-          <fo:table-row>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Header 1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Header 2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-        </fo:table-header>
-        <fo:table-footer start-indent="0" font-weight="bold">
-          <fo:table-row>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Footer 1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Footer 2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-        </fo:table-footer>
-        <fo:table-body start-indent="0">
-          <fo:table-row>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Cell 1.1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Cell 1.2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-          <fo:table-row>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Cell 2.1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Cell 2.2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-        </fo:table-body>
-      </fo:table>
-      <fo:block text-align="justify" space-before="0.5em">That’s all folks.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/role_non-standard.fo b/test/accessibility/role_non-standard.fo
deleted file mode 100644 (file)
index d3e1a98..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" font-family="sans-serif">
-      <fo:block role="H1" font-weight="bold" font-size="150%"
-        space-before.minimum="1.5em"
-        space-before.optimum="2em"
-        space-before.maximum="3em"
-        space-before.precedence="1000"
-        space-after.minimum="0.2em"
-        space-after.optimum="0.2em"
-        space-after.maximum="0.5em"
-        space-after.precedence="1000">Title 1: To Start With</fo:block>
-      <fo:block role="Header2" font-weight="bold" font-size="120%"
-        space-before.minimum="1.2em"
-        space-before.optimum="1.5em"
-        space-before.maximum="2em"
-        space-before.precedence="900"
-        space-after.minimum="0.2em"
-        space-after.optimum="0.2em"
-        space-after.maximum="0.5em"
-        space-after.precedence="900">A Sub-Title With a Non-Standard Role</fo:block>
-      <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter 
-        driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
-        application that reads a formatting object (FO) tree and renders the resulting pages to a 
-        specified output.</fo:block>
-      <fo:block role="H2" font-weight="bold" font-size="120%"
-        space-before.minimum="1.2em"
-        space-before.optimum="1.5em"
-        space-before.maximum="2em"
-        space-before.precedence="900"
-        space-after.minimum="0.2em"
-        space-after.optimum="0.2em"
-        space-after.maximum="0.5em"
-        space-after.precedence="900">Title 2: Another Sub-Title</fo:block>
-      <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter 
-        driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
-        application that reads a formatting object (FO) tree and renders the resulting pages to a 
-        specified output.</fo:block>
-      <fo:block role="H1" font-weight="bold" font-size="150%"
-        space-before.minimum="1.5em"
-        space-before.optimum="2em"
-        space-before.maximum="3em"
-        space-before.precedence="1000"
-        space-after.minimum="0.2em"
-        space-after.optimum="0.2em"
-        space-after.maximum="0.5em"
-        space-after.precedence="1000">Title 1: Second Title</fo:block>
-      <fo:block role="H2" font-weight="bold" font-size="120%"
-        space-before.minimum="1.2em"
-        space-before.optimum="1.5em"
-        space-before.maximum="2em"
-        space-before.precedence="900"
-        space-after.minimum="0.2em"
-        space-after.optimum="0.2em"
-        space-after.maximum="0.5em"
-        space-after.precedence="900">Title 2: A Sample Table</fo:block>
-      <fo:block>See data below:</fo:block>
-      <fo:table table-layout="fixed" width="70%" start-indent="15%" border="0.5pt solid black">
-        <fo:table-header start-indent="0" font-weight="bold" role="TableHeader">
-          <fo:table-row>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Header 1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Header 2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-        </fo:table-header>
-        <fo:table-footer start-indent="0" font-weight="bold">
-          <fo:table-row>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Footer 1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Footer 2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-        </fo:table-footer>
-        <fo:table-body start-indent="0">
-          <fo:table-row>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Cell 1.1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Cell 1.2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-          <fo:table-row>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Cell 2.1</fo:block>
-            </fo:table-cell>
-            <fo:table-cell border="0.5pt solid black" padding="2pt">
-              <fo:block>Cell 2.2</fo:block>
-            </fo:table-cell>
-          </fo:table-row>
-        </fo:table-body>
-      </fo:table>
-      <fo:block text-align="justify" space-before="0.5em">That’s all folks.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/text_1.fo b/test/accessibility/text_1.fo
deleted file mode 100644 (file)
index 31ad315..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
-        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
-        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
-        output.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/text_2.fo b/test/accessibility/text_2.fo
deleted file mode 100644 (file)
index f569311..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
-      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
-        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
-        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
-        output.</fo:block>
-      <fo:block language="fr" country="FR">Apache FOP (Formatting Objects Processor) est une 
-        application de mise en page de documents respectant le standard XSL-FO. À partir d’un 
-        document au format XSL-FO, cette application écrite en Java effectue une mise en page et 
-        renvoie un document prêt pour impression.</fo:block>
-      <fo:block>Back to English and let’s say it again: Apache FOP (Formatting Objects Processor) is 
-        a print formatter driven by XSL formatting objects (XSL-FO) and an output independent 
-        formatter.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
diff --git a/test/accessibility/text_font-embedding.fo b/test/accessibility/text_font-embedding.fo
deleted file mode 100644 (file)
index 10c1c99..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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$ -->
-<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
-  <fo:layout-master-set>
-    <fo:simple-page-master master-name="page"
-      page-height="220pt" page-width="320pt" margin="10pt">
-      <fo:region-body/>
-    </fo:simple-page-master>
-  </fo:layout-master-set>
-  <fo:page-sequence master-reference="page">
-    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify" font-family="DejaVu">
-      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
-        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
-        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
-        output.</fo:block>
-    </fo:flow>
-  </fo:page-sequence>
-</fo:root>
index eecdeb671f3c091c1855059f571215ff44b4eff6..8649fdfa874b09fd62404de3a074716d47b00239 100644 (file)
@@ -34,9 +34,10 @@ import org.apache.fop.fonts.type1.AdobeStandardEncodingTestCase;
 import org.apache.fop.image.loader.batik.ImageLoaderTestCase;
 import org.apache.fop.image.loader.batik.ImagePreloaderTestCase;
 import org.apache.fop.intermediate.IFMimickingTestCase;
+import org.apache.fop.layoutmgr.PageSequenceLayoutManagerTestCase;
+import org.apache.fop.pdf.PDFLibraryTestSuite;
 import org.apache.fop.render.extensions.prepress.PageBoundariesTestCase;
 import org.apache.fop.render.extensions.prepress.PageScaleTestCase;
-import org.apache.fop.layoutmgr.PageSequenceLayoutManagerTestCase;
 import org.apache.fop.render.pdf.PDFAConformanceTestCase;
 import org.apache.fop.render.pdf.PDFCMapTestCase;
 import org.apache.fop.render.pdf.PDFEncodingTestCase;
@@ -45,7 +46,6 @@ import org.apache.fop.render.pdf.RenderPDFTestSuite;
 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.
index b930a8b6da7860ba8d1b05eb758500798a989786..95d5c0a1d9c3c565a68e69c3eb4674d42748dd3a 100644 (file)
@@ -48,10 +48,10 @@ public class AbstractPDFStreamTestCase extends PDFObjectTestCase {
             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";
+    private String startStream = "<< /Length 5 0 R /Filter /FlateDecode >>\n"
+                + "stream\n";
+
+    private String endStream = "endstream";
 
     @Before
     public void setUp() {
diff --git a/test/java/org/apache/fop/pdf/ObjectStreamManagerTestCase.java b/test/java/org/apache/fop/pdf/ObjectStreamManagerTestCase.java
new file mode 100644 (file)
index 0000000..89d9800
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * 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.assertTrue;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.apache.fop.pdf.xref.CompressedObjectReference;
+
+public class ObjectStreamManagerTestCase {
+
+    private List<CompressedObjectReference> compressedObjectReferences;
+
+    private MockPdfDocument pdfDocument;
+
+    @Test
+    public void add() {
+        final int expectedCapacity = 100;
+        final int numCompressedObjects = expectedCapacity * 2 + 1;
+        createCompressObjectReferences(numCompressedObjects);
+        assertEquals(numCompressedObjects, compressedObjectReferences.size());
+        int objectStreamNumber1 = assertSameObjectStream(0, expectedCapacity);
+        int objectStreamNumber2 = assertSameObjectStream(expectedCapacity, expectedCapacity * 2);
+        int objectStreamNumber3 = assertSameObjectStream(expectedCapacity * 2, numCompressedObjects);
+        assertDifferent(objectStreamNumber1, objectStreamNumber2, objectStreamNumber3);
+        assertEquals(objectStreamNumber3, pdfDocument.previous.getObjectNumber());
+    }
+
+    private void createCompressObjectReferences(int numObjects) {
+        pdfDocument = new MockPdfDocument();
+        ObjectStreamManager sut = new ObjectStreamManager(pdfDocument);
+        for (int obNum = 1; obNum <= numObjects; obNum++) {
+            sut.add(createCompressedObject(obNum));
+        }
+        compressedObjectReferences = sut.getCompressedObjectReferences();
+    }
+
+    private static class MockPdfDocument extends PDFDocument {
+
+        private ObjectStream previous;
+
+        public MockPdfDocument() {
+            super("");
+        }
+
+        public void assignObjectNumber(PDFObject obj) {
+            super.assignObjectNumber(obj);
+            if (obj instanceof ObjectStream) {
+                ObjectStream  objStream = (ObjectStream) obj;
+                ObjectStream previous = (ObjectStream) objStream.get("Extends");
+                if (previous == null) {
+                    assertEquals(this.previous, previous);
+                }
+                this.previous = objStream;
+            }
+        }
+    }
+
+    private CompressedObject createCompressedObject(final int objectNumber) {
+        return new CompressedObject() {
+
+            public int getObjectNumber() {
+                return objectNumber;
+            }
+
+            public int output(OutputStream outputStream) throws IOException {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+
+    private int assertSameObjectStream(int from, int to) {
+        int objectStreamNumber = getObjectStreamNumber(from);
+        for (int i = from + 1; i < to; i++) {
+            assertEquals(objectStreamNumber, getObjectStreamNumber(i));
+        }
+        return objectStreamNumber;
+    }
+
+    private int getObjectStreamNumber(int index) {
+        return compressedObjectReferences.get(index).getObjectStreamNumber();
+    }
+
+    private void assertDifferent(int objectStreamNumber1, int objectStreamNumber2,
+            int objectStreamNumber3) {
+        assertTrue(objectStreamNumber1 != objectStreamNumber2);
+        assertTrue(objectStreamNumber1 != objectStreamNumber3);
+        assertTrue(objectStreamNumber2 != objectStreamNumber3);
+    }
+}
diff --git a/test/java/org/apache/fop/pdf/ObjectStreamTestCase.java b/test/java/org/apache/fop/pdf/ObjectStreamTestCase.java
new file mode 100644 (file)
index 0000000..317828e
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * 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 java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class ObjectStreamTestCase {
+
+    private static final String OBJECT_CONTENT = "<<\n  /Foo True\n  /Bar False\n>>\n";
+
+    private PDFDocument pdfDocument;
+
+    private ObjectStream objectStream;
+
+    private List<MockCompressedObject> compressedObjects;
+
+    @Before
+    public void setUp() throws Exception {
+        pdfDocument = new PDFDocument("PDFObjectStreamTestCase");
+        objectStream = new ObjectStream();
+        pdfDocument.assignObjectNumber(objectStream);
+        compressedObjects = Arrays.asList(new MockCompressedObject(), new MockCompressedObject());
+    }
+
+    @Test
+    public void testSingleObjectStream() throws IOException {
+        populateObjectStream();
+        testOutput();
+    }
+
+    @Test
+    public void testObjectStreamCollection() throws IOException {
+        objectStream = new ObjectStream(objectStream);
+        pdfDocument.assignObjectNumber(objectStream);
+        populateObjectStream();
+        testOutput();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void directObjectsAreNotAllowed() throws Exception {
+        objectStream.addObject(new MockCompressedObject());
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void nullObjectsAreNotAllowed() throws Exception {
+        objectStream.addObject(null);
+    }
+
+    private void testOutput() throws IOException {
+        String expected = getExpectedOutput();
+        String actual = getActualOutput();
+        assertEquals(expected, actual);
+    }
+
+    private void populateObjectStream() {
+        for (MockCompressedObject obj : compressedObjects) {
+            pdfDocument.assignObjectNumber(obj);
+            objectStream.addObject(obj);
+        }
+    }
+
+    private String getExpectedOutput() {
+        int numObs = compressedObjects.size();
+        int objectStreamNumber = objectStream.getObjectNumber();
+        int offsetsLength = 9;
+        StringBuilder expected = new StringBuilder();
+        expected.append("<<\n");
+        ObjectStream previous = (ObjectStream) objectStream.get("Extends");
+        if (previous != null) {
+            expected.append("  /Extends ").append(previous.getObjectNumber()).append(" 0 R\n");
+        }
+        expected.append("  /Type /ObjStm\n")
+                .append("  /N ").append(numObs).append("\n")
+                .append("  /First ").append(offsetsLength).append('\n')
+                .append("  /Length ").append(OBJECT_CONTENT.length() * 2 + offsetsLength + 1).append('\n')
+                .append(">>\n")
+                .append("stream\n");
+        int offset = 0;
+        int num = 1;
+        for (PDFObject ob : compressedObjects) {
+            expected.append(objectStreamNumber + num++).append(' ').append(offset).append('\n');
+            offset += ob.toPDFString().length();
+        }
+        for (PDFObject ob : compressedObjects) {
+            expected.append(ob.toPDFString());
+        }
+        expected.append("\nendstream");
+        return expected.toString();
+    }
+
+    private String getActualOutput() throws IOException {
+        ByteArrayOutputStream actual = new ByteArrayOutputStream();
+        objectStream.getFilterList().setDisableAllFilters(true);
+        objectStream.output(actual);
+        return actual.toString("US-ASCII");
+    }
+
+    private static class MockCompressedObject extends PDFObject implements CompressedObject {
+
+        @Override
+        protected String toPDFString() {
+            return OBJECT_CONTENT;
+        }
+    }
+
+}
index 235db704505a4b4981ab00b0f2eaeb5ffe13c7d1..db10e656eacd5354343a38b998d1faeb7b92ea66 100644 (file)
@@ -223,8 +223,6 @@ public class PDFEncryptionJCETestCase {
             final String digits = "\\d+";
             final String hexDigits = "\\p{XDigit}+";
 
-            dictionary.mustContain("1" + whitespace + "0" + whitespace + "obj");
-
             dictionary.mustContain("/Filter" + whitespace + "/Standard\\b");
 
             dictionary.mustContain("/V" + whitespace + "(" + digits + ")")
diff --git a/test/java/org/apache/fop/pdf/PDFFilterListTestCase.java b/test/java/org/apache/fop/pdf/PDFFilterListTestCase.java
new file mode 100644 (file)
index 0000000..2504d87
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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 org.junit.Test;
+
+public class PDFFilterListTestCase {
+
+    @Test
+    public void testFilterList() {
+        PDFFilterList filterList = new PDFFilterList();
+        assertFalse(filterList.isInitialized());
+    }
+}
index a0c4ea11f16c9e0e99e8f68c39a230ba499876f2..c7a9dff89a5f74e528d186cd99e9fd1d49035191 100644 (file)
@@ -40,7 +40,9 @@ import org.junit.runners.Suite.SuiteClasses;
         PDFNullTestCase.class,
         PDFNumsArrayTestCase.class,
         PDFRectangleTestCase.class,
-        PDFReferenceTestCase.class
+        PDFReferenceTestCase.class,
+        VersionTestCase.class,
+        VersionControllerTestCase.class
 })
 public class PDFLibraryTestSuite {
 }
index ee9512d88ebf44ddf768d19ea242e2adf0dfd183..10ffa3b27fe7311ea46861325cc6153672eccf9a 100644 (file)
@@ -40,10 +40,6 @@ public class PDFObjectTestCase {
     protected final PDFObject parent = new DummyPDFObject();
     /** The test subject */
     protected PDFObject pdfObjectUnderTest;
-    /** The string to begin describing the object <code>"1 0 obj\n"</code> */
-    protected final String beginObj = "1 0 obj\n";
-    /** The string to end describing the object <code>"\nendobj\n"</code> */
-    protected final String endObj = "\nendobj\n";
 
     private static class DummyPDFObject extends PDFObject {
 
@@ -195,8 +191,7 @@ public class PDFObjectTestCase {
         outStream.reset();
         object.setObjectNumber(1);
         // Test the length of the output string is returned correctly.
-        String string = beginObj + expectedString + endObj;
-        assertEquals(string.length(), object.output(outStream));
-        assertEquals(string, outStream.toString());
+        assertEquals(expectedString.length(), object.output(outStream));
+        assertEquals(expectedString, outStream.toString());
     }
 }
diff --git a/test/java/org/apache/fop/pdf/PDFStreamTestCase.java b/test/java/org/apache/fop/pdf/PDFStreamTestCase.java
new file mode 100644 (file)
index 0000000..93dcea5
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * 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.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class PDFStreamTestCase {
+
+    private PDFStream stream;
+
+    @Before
+    public void createStream() {
+        stream = new PDFStream();
+        stream.setObjectNumber(1);
+        PDFDocument pdfDocument = new PDFDocument("Apache FOP");
+        stream.setDocument(pdfDocument);
+    }
+
+    @Test
+    public void testFilterSetup() {
+        testGetFilterList();
+        testSetupFilterList();
+    }
+
+    private void testGetFilterList() {
+        PDFFilterList filterList = stream.getFilterList();
+        assertFalse(filterList.isInitialized());
+        assertEquals(0, filterList.getFilters().size());
+    }
+
+    private void testSetupFilterList() {
+        stream.setupFilterList();
+        PDFFilterList filterList = stream.getFilterList();
+        assertTrue(filterList.isInitialized());
+        assertEquals(1, filterList.getFilters().size());
+        PDFFilter filter = filterList.getFilters().get(0);
+        assertEquals("/FlateDecode", filter.getName());
+    }
+
+    @Test
+    public void customFilter() {
+        PDFFilterList filters = stream.getFilterList();
+        filters.addFilter("null");
+        assertTrue(filters.isInitialized());
+        assertEquals(1, filters.getFilters().size());
+        PDFFilter filter = filters.getFilters().get(0);
+        assertEquals("", filter.getName());
+    }
+
+    @Test
+    public void testStream() throws IOException {
+        PDFFilterList filters = stream.getFilterList();
+        filters.addFilter("null");
+        byte[] bytes = createSampleData();
+        stream.setData(bytes);
+        ByteArrayOutputStream actual = new ByteArrayOutputStream();
+        stream.outputRawStreamData(actual);
+        assertArrayEquals(bytes, actual.toByteArray());
+    }
+
+    @Test
+    public void testEncodeStream() throws IOException {
+        PDFFilterList filters = stream.getFilterList();
+        filters.addFilter("null");
+        byte[] bytes = createSampleData();
+        stream.setData(bytes);
+        ByteArrayOutputStream actual = new ByteArrayOutputStream();
+        StreamCache streamCache = stream.encodeStream();
+        streamCache.outputContents(actual);
+        assertArrayEquals(bytes, actual.toByteArray());
+    }
+
+    @Test
+    public void testEncodeAndWriteStream() throws IOException {
+        PDFFilterList filters = stream.getFilterList();
+        filters.addFilter("null");
+        byte[] bytes = createSampleData();
+        stream.setData(bytes);
+        ByteArrayOutputStream actual = new ByteArrayOutputStream();
+        PDFNumber number = new PDFNumber();
+        stream.encodeAndWriteStream(actual, number);
+        assertArrayEquals(createSampleStreamData(), actual.toByteArray());
+    }
+
+    private byte[] createSampleData() {
+        byte[] bytes = new byte[10];
+        for (int i = 0; i < 10; i++) {
+            bytes[i] = (byte) i;
+        }
+        return bytes;
+    }
+
+    private byte[] createSampleStreamData() throws IOException {
+        ByteArrayOutputStream stream = new ByteArrayOutputStream();
+        stream.write("stream\n".getBytes("US-ASCII"));
+        stream.write(createSampleData());
+        stream.write("\nendstream".getBytes("US-ASCII"));
+        return stream.toByteArray();
+    }
+}
diff --git a/test/java/org/apache/fop/pdf/xref/CompressedObjectReferenceTestCase.java b/test/java/org/apache/fop/pdf/xref/CompressedObjectReferenceTestCase.java
new file mode 100644 (file)
index 0000000..8b103d2
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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.xref;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+public class CompressedObjectReferenceTestCase extends ObjectReferenceTest {
+
+    @Test
+    public void testOutput() throws IOException {
+        runTest(Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0), 0);
+        runTest(Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0x1), 4);
+        runTest(Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0xf3), 16);
+        runTest(Arrays.asList(0, 0, 0, 0, 0, 0, 0x5, 0xf7), 128);
+        runTest(Arrays.asList(0, 0, 0, 0, 0, 0x9, 0xfb, 0xd), 0xae);
+        runTest(Arrays.asList(0, 0, 0, 0, 0x11, 0xff, 0x15, 0xe9), 0xff);
+    }
+
+    private void runTest(List<Integer> expectedObjectStreamBytes, int index) throws IOException {
+        int objectStreamNumber = (int) computeNumberFromBytes(expectedObjectStreamBytes);
+        sut = new CompressedObjectReference(0, objectStreamNumber, index);
+        byte[] expected = createExpectedOutput((byte) 2, expectedObjectStreamBytes, index);
+        byte[] actual = getActualOutput();
+        assertArrayEquals(expected, actual);
+    }
+
+}
diff --git a/test/java/org/apache/fop/pdf/xref/CrossReferenceObjectTest.java b/test/java/org/apache/fop/pdf/xref/CrossReferenceObjectTest.java
new file mode 100644 (file)
index 0000000..df1b86e
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * 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.xref;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+
+import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFInfo;
+import org.apache.fop.pdf.PDFPages;
+import org.apache.fop.pdf.PDFRoot;
+
+public abstract class CrossReferenceObjectTest {
+
+    protected static final int STARTXREF = 12345;
+
+    protected PDFDocument pdfDocument;
+
+    protected TrailerDictionary trailerDictionary;
+
+    private CrossReferenceObject crossReferenceObject;
+
+    @Before
+    public void setUp() throws UnsupportedEncodingException {
+        pdfDocument = new PDFDocument("Apache FOP");
+        Map<String, List<String>> filterMap = pdfDocument.getFilterMap();
+        filterMap.put("default", Arrays.asList("null"));
+        PDFRoot root = new PDFRoot(1, new PDFPages(10));
+        PDFInfo info = new PDFInfo();
+        info.setObjectNumber(2);
+        byte[] fileID =
+                new byte[] {0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xab, (byte) 0xcd, (byte) 0xef};
+        trailerDictionary = new TrailerDictionary(pdfDocument)
+                .setRoot(root)
+                .setInfo(info)
+                .setFileID(fileID, fileID);
+    }
+
+    protected void runTest() throws IOException {
+        crossReferenceObject = createCrossReferenceObject();
+        byte[] expected = createExpectedCrossReferenceData();
+        byte[] actual = createActualCrossReferenceData();
+        assertArrayEquals(expected, actual);
+    }
+
+    protected abstract CrossReferenceObject createCrossReferenceObject();
+
+    protected abstract byte[] createExpectedCrossReferenceData() throws IOException;
+
+    protected byte[] createActualCrossReferenceData() throws IOException {
+        ByteArrayOutputStream pdf = new ByteArrayOutputStream();
+        crossReferenceObject.output(pdf);
+        pdf.close();
+        return pdf.toByteArray();
+    }
+
+    protected byte[] getBytes(StringBuilder stringBuilder) {
+        return getBytes(stringBuilder.toString());
+    }
+
+    protected byte[] getBytes(String string) {
+        try {
+            return string.getBytes("US-ASCII");
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Outputs the given byte array to a file with the given name. Use for debugging
+     * purpose.
+     */
+    protected void streamToFile(byte[] bytes, String filename) throws IOException {
+        OutputStream output = new FileOutputStream(filename);
+        output.write(bytes);
+        output.close();
+    }
+
+}
diff --git a/test/java/org/apache/fop/pdf/xref/CrossReferenceStreamTestCase.java b/test/java/org/apache/fop/pdf/xref/CrossReferenceStreamTestCase.java
new file mode 100644 (file)
index 0000000..3e60963
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * 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.xref;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Test;
+
+public class CrossReferenceStreamTestCase extends CrossReferenceObjectTest {
+
+    private List<Long> uncompressedObjectOffsets;
+
+    private List<CompressedObjectReference> compressedObjectReferences;
+
+    @Test
+    public void testWithNoOffset() throws IOException {
+        List<Long> emptyList = Collections.emptyList();
+        test(emptyList);
+    }
+
+    @Test
+    public void testWithOffsets() throws IOException {
+        test(new ArrayList<Long>(Arrays.asList(0L, 1L, 2L, 3L, 4L)));
+    }
+
+    @Test
+    public void testWithBigOffsets() throws IOException {
+        test(new ArrayList<Long>(Arrays.asList(0xffL, 0xffffL, 0xffffffffL, 0xffffffffffffffffL)));
+    }
+
+    @Test
+    public void testWithObjectStreams1() throws IOException {
+        List<CompressedObjectReference> compressedObjectReferences =
+                Arrays.asList(new CompressedObjectReference(2, 1, 0));
+        test(Arrays.asList(0L, null), compressedObjectReferences);
+    }
+
+    @Test
+    public void testWithObjectStreams2() throws IOException {
+        int numIndirectObjects = 2;
+        int numCompressedObjects = 1;
+        List<Long> indirectObjectOffsets
+                = new ArrayList<Long>(numIndirectObjects + numCompressedObjects);
+        for (long i = 0; i < numIndirectObjects; i++) {
+            indirectObjectOffsets.add(i);
+        }
+        List<CompressedObjectReference> compressedObjectReferences
+                = new ArrayList<CompressedObjectReference>();
+        for (int index = 0; index < numCompressedObjects; index++) {
+            indirectObjectOffsets.add(null);
+            int obNum = numIndirectObjects + index + 1;
+            compressedObjectReferences.add(new CompressedObjectReference(obNum,
+                    numIndirectObjects, index));
+        }
+        test(indirectObjectOffsets, compressedObjectReferences);
+    }
+
+    private void test(List<Long> indirectObjectOffsets) throws IOException {
+        List<CompressedObjectReference> compressedObjectReferences = Collections.emptyList();
+        test(indirectObjectOffsets, compressedObjectReferences);
+    }
+
+    private void test(List<Long> indirectObjectOffsets,
+            List<CompressedObjectReference> compressedObjectReferences) throws IOException {
+        this.uncompressedObjectOffsets = indirectObjectOffsets;
+        this.compressedObjectReferences = compressedObjectReferences;
+        runTest();
+    }
+
+    @Override
+    protected CrossReferenceObject createCrossReferenceObject() {
+        return new CrossReferenceStream(pdfDocument,
+                uncompressedObjectOffsets.size() + 1,
+                trailerDictionary,
+                STARTXREF,
+                uncompressedObjectOffsets,
+                compressedObjectReferences);
+    }
+
+    @Override
+    protected byte[] createExpectedCrossReferenceData() throws IOException {
+        List<ObjectReference> objectReferences
+                = new ArrayList<ObjectReference>(uncompressedObjectOffsets.size());
+        for (Long offset : uncompressedObjectOffsets) {
+            objectReferences.add(offset == null ? null : new UncompressedObjectReference(offset));
+        }
+        for (CompressedObjectReference ref : compressedObjectReferences) {
+            objectReferences.set(ref.getObjectNumber() - 1, ref);
+        }
+        int maxObjectNumber = objectReferences.size() + 1;
+        ByteArrayOutputStream stream = new ByteArrayOutputStream();
+        StringBuilder expected = new StringBuilder(256);
+        expected.append(maxObjectNumber + " 0 obj\n")
+                .append("<<\n")
+                .append("  /Root 1 0 R\n")
+                .append("  /Info 2 0 R\n")
+                .append("  /ID [<0123456789ABCDEF> <0123456789ABCDEF>]\n")
+                .append("  /Type /XRef\n")
+                .append("  /Size ").append(Integer.toString(maxObjectNumber + 1)).append('\n')
+                .append("  /W [1 8 2]\n")
+                .append("  /Length ").append(Integer.toString((maxObjectNumber + 1) * 11 + 1)).append('\n')
+                .append(">>\n")
+                .append("stream\n");
+        stream.write(getBytes(expected));
+        DataOutputStream data = new DataOutputStream(stream);
+        data.write(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xff, (byte) 0xff});
+        for (ObjectReference objectReference : objectReferences) {
+            objectReference.output(data);
+        }
+        data.write(1);
+        data.writeLong(STARTXREF);
+        data.write(0);
+        data.write(0);
+        data.close();
+        stream.write(getBytes("\nendstream\nendobj\n"));
+        return stream.toByteArray();
+    }
+
+}
diff --git a/test/java/org/apache/fop/pdf/xref/CrossReferenceTableTestCase.java b/test/java/org/apache/fop/pdf/xref/CrossReferenceTableTestCase.java
new file mode 100644 (file)
index 0000000..ceff96a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * 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.xref;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Test;
+
+public class CrossReferenceTableTestCase extends CrossReferenceObjectTest {
+
+    private List<Long> offsets;
+
+    @Test
+    public void testWithNoOffset() throws IOException {
+        List<Long> emptyList = Collections.emptyList();
+        runTest(emptyList);
+    }
+
+    @Test
+    public void testWithOffsets() throws IOException {
+        runTest(Arrays.asList(0L, 1L, 2L, 3L, 4L));
+    }
+
+    @Test
+    public void testWithBigOffsets() throws IOException {
+        runTest(Arrays.asList(0xffL, 0xffffL, 0x7fffffffL));
+    }
+
+    private void runTest(List<Long> offsets) throws IOException {
+        this.offsets = offsets;
+        runTest();
+    }
+
+    @Override
+    protected CrossReferenceObject createCrossReferenceObject() {
+        return new CrossReferenceTable(trailerDictionary, STARTXREF, offsets);
+    }
+
+    @Override
+    protected byte[] createExpectedCrossReferenceData() throws IOException {
+        StringBuilder expected = new StringBuilder(256);
+        expected.append("xref\n0 ")
+                .append(offsets.size() + 1)
+                .append("\n0000000000 65535 f \n");
+        for (Long objectReference : offsets) {
+            final String padding = "0000000000";
+            String s = String.valueOf(objectReference).toString();
+            String loc = padding.substring(s.length()) + s;
+            expected.append(loc).append(" 00000 n \n");
+        }
+        expected.append("trailer\n<<\n")
+                .append("  /Root 1 0 R\n")
+                .append("  /Info 2 0 R\n")
+                .append("  /ID [<0123456789ABCDEF> <0123456789ABCDEF>]\n")
+                .append("  /Size ").append(Integer.toString(offsets.size() + 1)).append('\n')
+                .append(">>\n");
+        return getBytes(expected);
+    }
+
+}
diff --git a/test/java/org/apache/fop/pdf/xref/ObjectReferenceTest.java b/test/java/org/apache/fop/pdf/xref/ObjectReferenceTest.java
new file mode 100644 (file)
index 0000000..fada279
--- /dev/null
@@ -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.xref;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+abstract class ObjectReferenceTest {
+
+    protected ObjectReference sut;
+
+    protected long computeNumberFromBytes(List<Integer> expectedOffsetBytes) {
+        assert expectedOffsetBytes.size() <= 8;
+        long offset = 0;
+        for (int b : expectedOffsetBytes) {
+            offset = offset << 8 | b;
+        }
+        return offset;
+    }
+
+    protected byte[] createExpectedOutput(byte field1, List<Integer> field2, int field3) {
+        assert field2.size() == 8;
+        assert (field3 & 0xffff) == field3;
+        byte[] expected = new byte[11];
+        int index = 0;
+        expected[index++] = field1;
+        for (Integer b : field2) {
+            expected[index++] = b.byteValue();
+        }
+        expected[index++] = (byte) ((field3 & 0xff00) >> 8);
+        expected[index++] = (byte) (field3 & 0xff);
+        return expected;
+    }
+
+    protected byte[] getActualOutput() throws IOException {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        DataOutputStream dataOutputStream = new DataOutputStream(out);
+        sut.output(dataOutputStream);
+        dataOutputStream.close();
+        return out.toByteArray();
+    }
+
+}
diff --git a/test/java/org/apache/fop/pdf/xref/UncompressedObjectReferenceTestCase.java b/test/java/org/apache/fop/pdf/xref/UncompressedObjectReferenceTestCase.java
new file mode 100644 (file)
index 0000000..b147084
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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.xref;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+
+public class UncompressedObjectReferenceTestCase extends ObjectReferenceTest {
+
+    @Test
+    public void test1ByteOffsets() throws IOException {
+        run1ByteOffsetTest(0x0);
+        run1ByteOffsetTest(0xf);
+        run1ByteOffsetTest(0x10);
+        run1ByteOffsetTest(0xff);
+    }
+
+    private void run1ByteOffsetTest(int offset) throws IOException {
+        runIntegerOffsetTest(Arrays.asList(0, 0, 0, offset));
+    }
+
+    @Test
+    public void test2ByteOffsets() throws IOException {
+        runIntegerOffsetTest(Arrays.asList(0, 0, 1, 0xff));
+        runIntegerOffsetTest(Arrays.asList(0, 0, 0xa0, 0xff));
+    }
+
+    @Test
+    public void test3ByteOffsets() throws IOException {
+        runIntegerOffsetTest(Arrays.asList(0, 2, 0x12, 0x34));
+        runIntegerOffsetTest(Arrays.asList(0, 0xee, 0x56, 0x78));
+    }
+
+    @Test
+    public void test4ByteOffsets() throws IOException {
+        runIntegerOffsetTest(Arrays.asList(0x6, 0x12, 0x34, 0x56));
+        runIntegerOffsetTest(Arrays.asList(0xf1, 0x9a, 0xbc, 0xde));
+    }
+
+    @Test
+    public void test5ByteOffsets() throws IOException {
+        runTest(Arrays.asList(0, 0, 0, 0x7, 0x78, 0x9a, 0xbc, 0xde));
+        runTest(Arrays.asList(0, 0, 0, 0xbf, 0xf0, 0, 0x1, 0x2));
+    }
+
+    @Test
+    public void test8ByteOffsets() throws IOException {
+        runTest(Arrays.asList(0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8));
+        runTest(Arrays.asList(0xf9, 0xe8, 0xd7, 0xc6, 0xb5, 0xa4, 0x93, 0x82));
+    }
+
+    private void runIntegerOffsetTest(List<Integer> expectedOffsetBytes) throws IOException {
+        List<Integer> expectedLongOffset = new ArrayList<Integer>(8);
+        expectedLongOffset.addAll(Arrays.asList(0, 0, 0, 0));
+        expectedLongOffset.addAll(expectedOffsetBytes);
+        runTest(expectedLongOffset);
+    }
+
+    private void runTest(List<Integer> expectedOffsetBytes) throws IOException {
+        long offset = computeNumberFromBytes(expectedOffsetBytes);
+        sut = new UncompressedObjectReference(offset);
+        byte[] expected = createExpectedOutput((byte) 1, expectedOffsetBytes, (byte) 0);
+        byte[] actual = getActualOutput();
+        assertArrayEquals(expected, actual);
+    }
+
+}
diff --git a/test/pdf/1.5/fop.xconf b/test/pdf/1.5/fop.xconf
new file mode 100644 (file)
index 0000000..ab8bc7c
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<fop version="1.0">
+  <accessibility>true</accessibility>
+  <source-resolution>144</source-resolution>
+  <use-cache>false</use-cache>
+  <font-base>../../resources/fonts/ttf/</font-base>
+  <renderers>
+    <renderer mime="application/pdf">
+      <version>1.5</version>
+      <filterList>
+        <value>null</value>
+      </filterList>
+      <filterList type="image">
+        <value>flate</value>
+        <value>ascii-85</value>
+      </filterList>
+      <fonts>
+        <font embed-url="DejaVuLGCSerif.ttf">
+          <font-triplet name="DejaVu" style="normal" weight="normal"/>
+        </font>
+      </fonts>
+    </renderer>
+  </renderers>
+</fop>
diff --git a/test/pdf/1.5/test.fo b/test/pdf/1.5/test.fo
new file mode 100644 (file)
index 0000000..23e8405
--- /dev/null
@@ -0,0 +1,207 @@
+<?xml version="1.0" standalone="no"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body column-count="2" margin-top="15pt"/>
+      <fo:region-before extent="12pt"/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:static-content flow-name="xsl-region-before">
+      <fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page 
+        <fo:page-number/></fo:block>
+    </fo:static-content>
+    <fo:static-content flow-name="xsl-footnote-separator">
+      <fo:block><fo:leader leader-length="100pt" leader-pattern="rule"/></fo:block>
+    </fo:static-content>
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>(There’s another page sequence <fo:wrapper color="blue"><fo:basic-link 
+            internal-destination="second">below</fo:basic-link></fo:wrapper>.)</fo:block>
+      <fo:block font-family="sans-serif" font-weight="bold" space-before="1em" space-after="0.2em" 
+        role="H1"><fo:block>About Apache FOP</fo:block></fo:block>
+      <fo:block>It is a print formatter driven by XSL formatting objects (XSL-FO) and an output 
+        independent formatter<fo:footnote><fo:inline baseline-shift="super" 
+            font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the <fo:wrapper 
+                color="blue"><fo:basic-link 
+                  external-destination="http://xmlgraphics.apache.org/fop/">FOP 
+                  website</fo:basic-link></fo:wrapper> for more 
+              information</fo:block></fo:footnote-body></fo:footnote>. FOP has a nice logo: 
+        <fo:external-graphic src="../../resources/images/fop-logo-color-24bit.png" 
+          inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
+          fox:alt-text="FOP Logo"/></fo:block>
+      <fo:table space-before="10pt" space-after="10pt" width="100%" table-layout="fixed">
+        <fo:table-header>
+          <fo:table-row>
+            <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+              <fo:block>Header 1.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+              <fo:block>Header 1.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-header>
+        <fo:table-body>
+          <fo:table-row>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 1.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 1.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+          <fo:table-row>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 2.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 2.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-body>
+      </fo:table>
+      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
+        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
+        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
+        output.</fo:block>
+      <fo:block span="all" border-top="1pt solid black" border-bottom="1pt solid black" 
+        padding-before="2pt" padding-after="2pt">This fo:block element spans all the columns of the 
+        document. This is intended to test the abilities of the text-to-speech program.</fo:block>
+      <fo:block>And now we are back to normal content flowing in two columns. Let’s start a numbered 
+        list:</fo:block>
+      <fo:list-block provisional-distance-between-starts="15pt" provisional-label-separation="0mm" 
+        keep-with-previous="auto">
+        <fo:list-item keep-with-previous="always">
+          <fo:list-item-label end-indent="label-end()">
+            <fo:block>1.</fo:block>
+          </fo:list-item-label>
+          <fo:list-item-body start-indent="body-start()">
+            <fo:block>
+              <fo:block>Line 1 of item 1</fo:block>
+              <fo:block>Line 2 of item 1</fo:block>
+              <fo:block>Line 3 of item 1</fo:block>
+            </fo:block>
+          </fo:list-item-body>
+        </fo:list-item>
+        <fo:list-item keep-with-previous="always">
+          <fo:list-item-label end-indent="label-end()">
+            <fo:block>2.</fo:block>
+          </fo:list-item-label>
+          <fo:list-item-body start-indent="body-start()">
+            <fo:block>
+              <fo:block>Line 1 of item 2</fo:block>
+              <fo:block>Line 2 of item 2</fo:block>
+              <fo:block>Line 3 of item 2</fo:block>
+            </fo:block>
+          </fo:list-item-body>
+        </fo:list-item>
+      </fo:list-block>
+      <fo:block>And now we are going to see how a second page sequence is handled.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+  <fo:page-sequence master-reference="page">
+    <fo:static-content flow-name="xsl-region-before">
+      <fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page 
+        <fo:page-number/></fo:block>
+    </fo:static-content>
+    <fo:static-content flow-name="xsl-footnote-separator">
+      <fo:block><fo:leader leader-length="100pt" leader-pattern="rule"/></fo:block>
+    </fo:static-content>
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block id="second">Apache FOP (Formatting Objects Processor) is a print formatter driven by 
+        XSL formatting objects (XSL-FO) and an output independent formatter<fo:footnote><fo:inline 
+            baseline-shift="super" font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the 
+              <fo:wrapper color="blue"><fo:basic-link 
+                  external-destination="http://xmlgraphics.apache.org/fop/">FOP 
+                  website</fo:basic-link></fo:wrapper> for more 
+              information</fo:block></fo:footnote-body></fo:footnote>. It is a Java application that 
+        reads a formatting object (FO) tree and renders the resulting pages to a specified 
+        output.</fo:block>
+      <fo:table space-before="10pt" space-after="10pt" width="100%" table-layout="fixed">
+        <fo:table-header>
+          <fo:table-row>
+            <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+              <fo:block>Header 1.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+              <fo:block>Header 1.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-header>
+        <fo:table-body>
+          <fo:table-row>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 1.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 1.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+          <fo:table-row>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 2.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 2.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-body>
+      </fo:table>
+      <fo:block language="fr" country="FR">Apache FOP (Formatting Objects Processor) est une 
+        application de mise en page de documents respectant le standard XSL-FO. À partir d’un 
+        document au format XSL-FO, cette application écrite en Java effectue une mise en page et 
+        renvoie un document prêt pour impression.</fo:block>
+      <fo:block span="all" border-top="1pt solid black" border-bottom="1pt solid black" 
+        padding-before="2pt" padding-after="2pt">This fo:block element spans all the columns of the 
+        document. This is intended to test the abilities of the text-to-speech program.</fo:block>
+      <fo:block>And now we are back to normal content flowing in two columns. Let’s start a numbered 
+        list:</fo:block>
+      <fo:list-block provisional-distance-between-starts="15pt" provisional-label-separation="0mm" 
+        keep-with-previous="auto">
+        <fo:list-item keep-with-previous="always">
+          <fo:list-item-label end-indent="label-end()">
+            <fo:block>1.</fo:block>
+          </fo:list-item-label>
+          <fo:list-item-body start-indent="body-start()">
+            <fo:block>
+              <fo:block>Line 1 of item 1</fo:block>
+              <fo:block>Line 2 of item 1</fo:block>
+              <fo:block>Line 3 of item 1</fo:block>
+            </fo:block>
+          </fo:list-item-body>
+        </fo:list-item>
+        <fo:list-item keep-with-previous="always">
+          <fo:list-item-label end-indent="label-end()">
+            <fo:block>2.</fo:block>
+          </fo:list-item-label>
+          <fo:list-item-body start-indent="body-start()">
+            <fo:block>
+              <fo:block>Line 1 of item 2</fo:block>
+              <fo:block>Line 2 of item 2</fo:block>
+              <fo:block>Line 3 of item 2</fo:block>
+            </fo:block>
+          </fo:list-item-body>
+        </fo:list-item>
+      </fo:list-block>
+      <fo:block>The end of the document has now been reached.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/1.5/test.pdf b/test/pdf/1.5/test.pdf
new file mode 100644 (file)
index 0000000..4c25c08
Binary files /dev/null and b/test/pdf/1.5/test.pdf differ
diff --git a/test/pdf/accessibility/README b/test/pdf/accessibility/README
new file mode 100644 (file)
index 0000000..1d2e043
--- /dev/null
@@ -0,0 +1,41 @@
+This directory contains sample FO files for testing the accessibility features
+of FOP.
+
+Every FO file in this directory has a corresponding PDF file in the pdf/
+sub-directory. The fop.xconf configuration file was used.
+
+The PDF files have been checked with Adobe Acrobat Professional 9, using both 
+the full accessibility checker and the read-aloud feature. The checker reports 
+no error /and/ the entire document can be read aloud.
+
+
+!! DO NOT MODIFY THOSE FILES, NEITHER THE FO NOR THE PDF !!
+
+
+... Or at least, know what you are doing
+If the FO files are modified, the resulting PDFs must be checked again, both 
+with the checker and the read-aloud feature. (Sometimes the checker reports no 
+problem yet part or all of the document cannot be read aloud.)
+
+The purpose of this infrastructure is to be able to quickly re-test the 
+accessibility processing chain when any change has been made to it. The 
+configuration file disables the compression of the PDF streams, so it is 
+possible to compare a re-generated PDF with the original one by using a simple 
+diff tool. The files will not be identical because of the different creation 
+dates (and the ID key in the trailer), but apart from that there should be no 
+difference.
+
+The rationale is that using a diff tool is much quicker and less tedious than 
+running Acrobat's accessibility checker and read-aloud feature every time.
+
+
+To re-generate the PDF files:
+    ../../fop -c fop.xconf text_1.fo pdf/text_1.new.pdf
+    diff pdf/text_1_painter.pdf pdf/text_1.new.pdf
+Or, going through the intermediate format:
+    ../../fop -c fop.xconf text_1.fo -if application/pdf text_1_if.xml
+    ../../fop -c fop.xconf -ifin text_1_if.xml pdf/text_1.new.pdf
+    diff pdf/text_1.pdf pdf/text_1.new.pdf
+
+
+$Id$
diff --git a/test/pdf/accessibility/background-image_jpg_repeat.fo b/test/pdf/accessibility/background-image_jpg_repeat.fo
new file mode 100644 (file)
index 0000000..12af7d7
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body background-image="../../resources/images/bgimg72dpi.jpg"/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
+        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
+        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
+        output.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/background-image_jpg_single.fo b/test/pdf/accessibility/background-image_jpg_single.fo
new file mode 100644 (file)
index 0000000..1efd10d
--- /dev/null
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body background-image="../../resources/images/bgimg72dpi.jpg" 
+        background-repeat="no-repeat" background-position-horizontal="50%" 
+        background-position-vertical="50%"/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
+        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
+        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
+        output.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/background-image_png_repeat.fo b/test/pdf/accessibility/background-image_png_repeat.fo
new file mode 100644 (file)
index 0000000..9bbc3e4
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body background-image="../../resources/images/bgimg72dpi.png"/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
+        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
+        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
+        output.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/background-image_png_single.fo b/test/pdf/accessibility/background-image_png_single.fo
new file mode 100644 (file)
index 0000000..0cff427
--- /dev/null
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body background-image="../../resources/images/fop-logo-color-24bit.png" 
+        background-repeat="no-repeat" background-position-horizontal="50%" 
+        background-position-vertical="50%"/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
+        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
+        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
+        output.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/background-image_svg_repeat.fo b/test/pdf/accessibility/background-image_svg_repeat.fo
new file mode 100644 (file)
index 0000000..ba69947
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body background-image="../../resources/images/rgb-circles.svg"/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
+        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
+        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
+        output.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/background-image_svg_single.fo b/test/pdf/accessibility/background-image_svg_single.fo
new file mode 100644 (file)
index 0000000..efe91c6
--- /dev/null
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body background-image="../../resources/images/rgb-circles.svg" 
+        background-repeat="no-repeat" background-position-horizontal="50%" 
+        background-position-vertical="50%"/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
+        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
+        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
+        output.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/complete.fo b/test/pdf/accessibility/complete.fo
new file mode 100644 (file)
index 0000000..23e8405
--- /dev/null
@@ -0,0 +1,207 @@
+<?xml version="1.0" standalone="no"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
+  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body column-count="2" margin-top="15pt"/>
+      <fo:region-before extent="12pt"/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:static-content flow-name="xsl-region-before">
+      <fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page 
+        <fo:page-number/></fo:block>
+    </fo:static-content>
+    <fo:static-content flow-name="xsl-footnote-separator">
+      <fo:block><fo:leader leader-length="100pt" leader-pattern="rule"/></fo:block>
+    </fo:static-content>
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>(There’s another page sequence <fo:wrapper color="blue"><fo:basic-link 
+            internal-destination="second">below</fo:basic-link></fo:wrapper>.)</fo:block>
+      <fo:block font-family="sans-serif" font-weight="bold" space-before="1em" space-after="0.2em" 
+        role="H1"><fo:block>About Apache FOP</fo:block></fo:block>
+      <fo:block>It is a print formatter driven by XSL formatting objects (XSL-FO) and an output 
+        independent formatter<fo:footnote><fo:inline baseline-shift="super" 
+            font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the <fo:wrapper 
+                color="blue"><fo:basic-link 
+                  external-destination="http://xmlgraphics.apache.org/fop/">FOP 
+                  website</fo:basic-link></fo:wrapper> for more 
+              information</fo:block></fo:footnote-body></fo:footnote>. FOP has a nice logo: 
+        <fo:external-graphic src="../../resources/images/fop-logo-color-24bit.png" 
+          inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
+          fox:alt-text="FOP Logo"/></fo:block>
+      <fo:table space-before="10pt" space-after="10pt" width="100%" table-layout="fixed">
+        <fo:table-header>
+          <fo:table-row>
+            <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+              <fo:block>Header 1.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+              <fo:block>Header 1.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-header>
+        <fo:table-body>
+          <fo:table-row>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 1.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 1.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+          <fo:table-row>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 2.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 2.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-body>
+      </fo:table>
+      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
+        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
+        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
+        output.</fo:block>
+      <fo:block span="all" border-top="1pt solid black" border-bottom="1pt solid black" 
+        padding-before="2pt" padding-after="2pt">This fo:block element spans all the columns of the 
+        document. This is intended to test the abilities of the text-to-speech program.</fo:block>
+      <fo:block>And now we are back to normal content flowing in two columns. Let’s start a numbered 
+        list:</fo:block>
+      <fo:list-block provisional-distance-between-starts="15pt" provisional-label-separation="0mm" 
+        keep-with-previous="auto">
+        <fo:list-item keep-with-previous="always">
+          <fo:list-item-label end-indent="label-end()">
+            <fo:block>1.</fo:block>
+          </fo:list-item-label>
+          <fo:list-item-body start-indent="body-start()">
+            <fo:block>
+              <fo:block>Line 1 of item 1</fo:block>
+              <fo:block>Line 2 of item 1</fo:block>
+              <fo:block>Line 3 of item 1</fo:block>
+            </fo:block>
+          </fo:list-item-body>
+        </fo:list-item>
+        <fo:list-item keep-with-previous="always">
+          <fo:list-item-label end-indent="label-end()">
+            <fo:block>2.</fo:block>
+          </fo:list-item-label>
+          <fo:list-item-body start-indent="body-start()">
+            <fo:block>
+              <fo:block>Line 1 of item 2</fo:block>
+              <fo:block>Line 2 of item 2</fo:block>
+              <fo:block>Line 3 of item 2</fo:block>
+            </fo:block>
+          </fo:list-item-body>
+        </fo:list-item>
+      </fo:list-block>
+      <fo:block>And now we are going to see how a second page sequence is handled.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+  <fo:page-sequence master-reference="page">
+    <fo:static-content flow-name="xsl-region-before">
+      <fo:block font-size="8pt" text-align-last="justify">This is the page header<fo:leader/>Page 
+        <fo:page-number/></fo:block>
+    </fo:static-content>
+    <fo:static-content flow-name="xsl-footnote-separator">
+      <fo:block><fo:leader leader-length="100pt" leader-pattern="rule"/></fo:block>
+    </fo:static-content>
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block id="second">Apache FOP (Formatting Objects Processor) is a print formatter driven by 
+        XSL formatting objects (XSL-FO) and an output independent formatter<fo:footnote><fo:inline 
+            baseline-shift="super" font-size="70%">1</fo:inline><fo:footnote-body><fo:block>See the 
+              <fo:wrapper color="blue"><fo:basic-link 
+                  external-destination="http://xmlgraphics.apache.org/fop/">FOP 
+                  website</fo:basic-link></fo:wrapper> for more 
+              information</fo:block></fo:footnote-body></fo:footnote>. It is a Java application that 
+        reads a formatting object (FO) tree and renders the resulting pages to a specified 
+        output.</fo:block>
+      <fo:table space-before="10pt" space-after="10pt" width="100%" table-layout="fixed">
+        <fo:table-header>
+          <fo:table-row>
+            <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+              <fo:block>Header 1.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="2pt solid black" padding="2pt 2pt 0">
+              <fo:block>Header 1.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-header>
+        <fo:table-body>
+          <fo:table-row>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 1.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 1.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+          <fo:table-row>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 2.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="1pt solid black" padding="2pt 2pt 0">
+              <fo:block>Cell 2.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-body>
+      </fo:table>
+      <fo:block language="fr" country="FR">Apache FOP (Formatting Objects Processor) est une 
+        application de mise en page de documents respectant le standard XSL-FO. À partir d’un 
+        document au format XSL-FO, cette application écrite en Java effectue une mise en page et 
+        renvoie un document prêt pour impression.</fo:block>
+      <fo:block span="all" border-top="1pt solid black" border-bottom="1pt solid black" 
+        padding-before="2pt" padding-after="2pt">This fo:block element spans all the columns of the 
+        document. This is intended to test the abilities of the text-to-speech program.</fo:block>
+      <fo:block>And now we are back to normal content flowing in two columns. Let’s start a numbered 
+        list:</fo:block>
+      <fo:list-block provisional-distance-between-starts="15pt" provisional-label-separation="0mm" 
+        keep-with-previous="auto">
+        <fo:list-item keep-with-previous="always">
+          <fo:list-item-label end-indent="label-end()">
+            <fo:block>1.</fo:block>
+          </fo:list-item-label>
+          <fo:list-item-body start-indent="body-start()">
+            <fo:block>
+              <fo:block>Line 1 of item 1</fo:block>
+              <fo:block>Line 2 of item 1</fo:block>
+              <fo:block>Line 3 of item 1</fo:block>
+            </fo:block>
+          </fo:list-item-body>
+        </fo:list-item>
+        <fo:list-item keep-with-previous="always">
+          <fo:list-item-label end-indent="label-end()">
+            <fo:block>2.</fo:block>
+          </fo:list-item-label>
+          <fo:list-item-body start-indent="body-start()">
+            <fo:block>
+              <fo:block>Line 1 of item 2</fo:block>
+              <fo:block>Line 2 of item 2</fo:block>
+              <fo:block>Line 3 of item 2</fo:block>
+            </fo:block>
+          </fo:list-item-body>
+        </fo:list-item>
+      </fo:list-block>
+      <fo:block>The end of the document has now been reached.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/fop.xconf b/test/pdf/accessibility/fop.xconf
new file mode 100644 (file)
index 0000000..adfccd2
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<fop version="1.0">
+  <accessibility>true</accessibility>
+  <source-resolution>144</source-resolution>
+  <use-cache>false</use-cache>
+  <font-base>../../resources/fonts/ttf/</font-base>
+  <renderers>
+    <renderer mime="application/pdf">
+      <filterList>
+        <value>null</value>
+      </filterList>
+      <filterList type="image">
+        <value>flate</value>
+        <value>ascii-85</value>
+      </filterList>
+      <fonts>
+        <font embed-url="DejaVuLGCSerif.ttf">
+          <font-triplet name="DejaVu" style="normal" weight="normal"/>
+        </font>
+      </fonts>
+    </renderer>
+  </renderers>
+</fop>
diff --git a/test/pdf/accessibility/image_jpg.fo b/test/pdf/accessibility/image_jpg.fo
new file mode 100644 (file)
index 0000000..2a2b600
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" 
+  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>This document contains an image in the JPEG format: <fo:external-graphic 
+          src="../../resources/images/cmyk.jpg"
+          inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
+          fox:alt-text="CMYK colours"/>. Here is the end of the text.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/image_png.fo b/test/pdf/accessibility/image_png.fo
new file mode 100644 (file)
index 0000000..52ee80a
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" 
+  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>This document contains an image in the PNG format: <fo:external-graphic 
+          src="../../resources/images/fop-logo-color-24bit.png"
+          inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
+          fox:alt-text="FOP Logo"/>. Here is the end of the text.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/image_svg.fo b/test/pdf/accessibility/image_svg.fo
new file mode 100644 (file)
index 0000000..96cfede
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" standalone="no"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" 
+  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>This document contains an image in the SVG format: <fo:external-graphic 
+          src="../../resources/images/circles.svg"
+          inline-progression-dimension.maximum="75pt" content-width="scale-to-fit"
+          fox:alt-text="Nice circles"/>. And here is the same image as an instream-foreign-object: 
+        <fo:instream-foreign-object inline-progression-dimension.maximum="75pt" 
+          content-width="scale-down-to-fit" fox:alt-text="The same nice circles">
+<svg xmlns="http://www.w3.org/2000/svg" width="12cm" height="12cm">
+  <g style="fill-opacity:0.7; stroke:black; stroke-width:0.1cm;">
+    <circle cx="6cm" cy="2cm" r="100" style="fill:red;" transform="translate(0,50)" />
+    <circle cx="6cm" cy="2cm" r="100" style="fill:blue;" transform="translate(70,150)" />
+    <circle cx="6cm" cy="2cm" r="100" style="fill:green;" transform="translate(-70,150)"/>
+  </g>
+</svg>
+      </fo:instream-foreign-object>.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/image_wmf.fo b/test/pdf/accessibility/image_wmf.fo
new file mode 100644 (file)
index 0000000..43112db
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" standalone="no"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" 
+  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="320pt" page-width="320pt" margin="10pt">
+      <fo:region-body/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>This document contains an image in the WMF format: <fo:external-graphic 
+          src="../../resources/images/testChart.wmf"
+          inline-progression-dimension.maximum="100%" content-width="scale-to-fit"
+          fox:alt-text="Metafile Companion Test Chart"/> Here is the end of the text.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/leader.fo b/test/pdf/accessibility/leader.fo
new file mode 100644 (file)
index 0000000..4b395cc
--- /dev/null
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify" 
+      text-align-last="justify">
+      <fo:block>This is a text followed by a leader with leader-pattern=​"use-content", the 
+        content being text:<fo:leader leader-pattern="use-content"><fo:inline> • 
+      </fo:inline></fo:leader>1</fo:block>
+      <fo:block space-before="10pt">This is a text followed by a leader with 
+        leader-pattern=​"use-content", the content being images:<fo:leader 
+          leader-pattern="use-content"><fo:external-graphic 
+            src="../../resources/images/list-item.png"/></fo:leader>1</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/links.fo b/test/pdf/accessibility/links.fo
new file mode 100644 (file)
index 0000000..36250e3
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0" standalone="no"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" 
+  xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>This is a <fo:wrapper color="blue"><fo:basic-link 
+            internal-destination="FOP">link</fo:basic-link></fo:wrapper> to the next 
+        paragraph.</fo:block>
+      <fo:block id="FOP">Apache FOP (Formatting Objects Processor) is a print formatter driven by 
+        XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
+        application that reads a formatting object (FO) tree and renders the resulting pages to a 
+        specified output.</fo:block>
+      <fo:block>For more information, see the <fo:wrapper color="blue"><fo:basic-link 
+            external-destination="http://xmlgraphics.apache.org/fop/">FOP 
+            website</fo:basic-link></fo:wrapper>.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf b/test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf
new file mode 100644 (file)
index 0000000..9b4a7fc
Binary files /dev/null and b/test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf differ
diff --git a/test/pdf/accessibility/pdf/background-image_jpg_single.pdf b/test/pdf/accessibility/pdf/background-image_jpg_single.pdf
new file mode 100644 (file)
index 0000000..d1d0ecb
Binary files /dev/null and b/test/pdf/accessibility/pdf/background-image_jpg_single.pdf differ
diff --git a/test/pdf/accessibility/pdf/background-image_png_repeat.pdf b/test/pdf/accessibility/pdf/background-image_png_repeat.pdf
new file mode 100644 (file)
index 0000000..ccb2cf0
Binary files /dev/null and b/test/pdf/accessibility/pdf/background-image_png_repeat.pdf differ
diff --git a/test/pdf/accessibility/pdf/background-image_png_single.pdf b/test/pdf/accessibility/pdf/background-image_png_single.pdf
new file mode 100644 (file)
index 0000000..902520b
Binary files /dev/null and b/test/pdf/accessibility/pdf/background-image_png_single.pdf differ
diff --git a/test/pdf/accessibility/pdf/background-image_svg_repeat.pdf b/test/pdf/accessibility/pdf/background-image_svg_repeat.pdf
new file mode 100644 (file)
index 0000000..a720a5b
Binary files /dev/null and b/test/pdf/accessibility/pdf/background-image_svg_repeat.pdf differ
diff --git a/test/pdf/accessibility/pdf/background-image_svg_single.pdf b/test/pdf/accessibility/pdf/background-image_svg_single.pdf
new file mode 100644 (file)
index 0000000..7e6e3e9
Binary files /dev/null and b/test/pdf/accessibility/pdf/background-image_svg_single.pdf differ
diff --git a/test/pdf/accessibility/pdf/complete.pdf b/test/pdf/accessibility/pdf/complete.pdf
new file mode 100644 (file)
index 0000000..f1dc105
Binary files /dev/null and b/test/pdf/accessibility/pdf/complete.pdf differ
diff --git a/test/pdf/accessibility/pdf/image_jpg.pdf b/test/pdf/accessibility/pdf/image_jpg.pdf
new file mode 100644 (file)
index 0000000..e943c83
Binary files /dev/null and b/test/pdf/accessibility/pdf/image_jpg.pdf differ
diff --git a/test/pdf/accessibility/pdf/image_png.pdf b/test/pdf/accessibility/pdf/image_png.pdf
new file mode 100644 (file)
index 0000000..5ea4467
Binary files /dev/null and b/test/pdf/accessibility/pdf/image_png.pdf differ
diff --git a/test/pdf/accessibility/pdf/image_svg.pdf b/test/pdf/accessibility/pdf/image_svg.pdf
new file mode 100644 (file)
index 0000000..db1e061
Binary files /dev/null and b/test/pdf/accessibility/pdf/image_svg.pdf differ
diff --git a/test/pdf/accessibility/pdf/image_wmf.pdf b/test/pdf/accessibility/pdf/image_wmf.pdf
new file mode 100644 (file)
index 0000000..65c46d1
Binary files /dev/null and b/test/pdf/accessibility/pdf/image_wmf.pdf differ
diff --git a/test/pdf/accessibility/pdf/leader.pdf b/test/pdf/accessibility/pdf/leader.pdf
new file mode 100644 (file)
index 0000000..d270c25
Binary files /dev/null and b/test/pdf/accessibility/pdf/leader.pdf differ
diff --git a/test/pdf/accessibility/pdf/links.pdf b/test/pdf/accessibility/pdf/links.pdf
new file mode 100644 (file)
index 0000000..b2a5a42
Binary files /dev/null and b/test/pdf/accessibility/pdf/links.pdf differ
diff --git a/test/pdf/accessibility/pdf/role.pdf b/test/pdf/accessibility/pdf/role.pdf
new file mode 100644 (file)
index 0000000..329925b
Binary files /dev/null and b/test/pdf/accessibility/pdf/role.pdf differ
diff --git a/test/pdf/accessibility/pdf/role_non-standard.pdf b/test/pdf/accessibility/pdf/role_non-standard.pdf
new file mode 100644 (file)
index 0000000..84daea7
Binary files /dev/null and b/test/pdf/accessibility/pdf/role_non-standard.pdf differ
diff --git a/test/pdf/accessibility/pdf/text_1.pdf b/test/pdf/accessibility/pdf/text_1.pdf
new file mode 100644 (file)
index 0000000..13f0171
Binary files /dev/null and b/test/pdf/accessibility/pdf/text_1.pdf differ
diff --git a/test/pdf/accessibility/pdf/text_2.pdf b/test/pdf/accessibility/pdf/text_2.pdf
new file mode 100644 (file)
index 0000000..9432639
Binary files /dev/null and b/test/pdf/accessibility/pdf/text_2.pdf differ
diff --git a/test/pdf/accessibility/pdf/text_font-embedding.pdf b/test/pdf/accessibility/pdf/text_font-embedding.pdf
new file mode 100644 (file)
index 0000000..7ffb40a
Binary files /dev/null and b/test/pdf/accessibility/pdf/text_font-embedding.pdf differ
diff --git a/test/pdf/accessibility/role.fo b/test/pdf/accessibility/role.fo
new file mode 100644 (file)
index 0000000..ced8a4d
--- /dev/null
@@ -0,0 +1,125 @@
+<?xml version="1.0"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" font-family="sans-serif">
+      <fo:block role="H1" font-weight="bold" font-size="150%"
+        space-before.minimum="1.5em"
+        space-before.optimum="2em"
+        space-before.maximum="3em"
+        space-before.precedence="1000"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="1000">Title 1: To Start With</fo:block>
+      <fo:block role="H2" font-weight="bold" font-size="120%"
+        space-before.minimum="1.2em"
+        space-before.optimum="1.5em"
+        space-before.maximum="2em"
+        space-before.precedence="900"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="900">Title 2: A Sub-Title</fo:block>
+      <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter 
+        driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
+        application that reads a formatting object (FO) tree and renders the resulting pages to a 
+        specified output.</fo:block>
+      <fo:block role="H2" font-weight="bold" font-size="120%"
+        space-before.minimum="1.2em"
+        space-before.optimum="1.5em"
+        space-before.maximum="2em"
+        space-before.precedence="900"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="900">Title 2: Another Sub-Title</fo:block>
+      <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter 
+        driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
+        application that reads a formatting object (FO) tree and renders the resulting pages to a 
+        specified output.</fo:block>
+      <fo:block role="H1" font-weight="bold" font-size="150%"
+        space-before.minimum="1.5em"
+        space-before.optimum="2em"
+        space-before.maximum="3em"
+        space-before.precedence="1000"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="1000">Title 1: Second Title</fo:block>
+      <fo:block role="H2" font-weight="bold" font-size="120%"
+        space-before.minimum="1.2em"
+        space-before.optimum="1.5em"
+        space-before.maximum="2em"
+        space-before.precedence="900"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="900">Title 2: A Sample Table</fo:block>
+      <fo:block>See data below:</fo:block>
+      <fo:table table-layout="fixed" width="70%" start-indent="15%" border="0.5pt solid black">
+        <fo:table-header start-indent="0" font-weight="bold">
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Header 1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Header 2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-header>
+        <fo:table-footer start-indent="0" font-weight="bold">
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Footer 1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Footer 2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-footer>
+        <fo:table-body start-indent="0">
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 1.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 1.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 2.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 2.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-body>
+      </fo:table>
+      <fo:block text-align="justify" space-before="0.5em">That’s all folks.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/role_non-standard.fo b/test/pdf/accessibility/role_non-standard.fo
new file mode 100644 (file)
index 0000000..d3e1a98
--- /dev/null
@@ -0,0 +1,125 @@
+<?xml version="1.0"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" font-family="sans-serif">
+      <fo:block role="H1" font-weight="bold" font-size="150%"
+        space-before.minimum="1.5em"
+        space-before.optimum="2em"
+        space-before.maximum="3em"
+        space-before.precedence="1000"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="1000">Title 1: To Start With</fo:block>
+      <fo:block role="Header2" font-weight="bold" font-size="120%"
+        space-before.minimum="1.2em"
+        space-before.optimum="1.5em"
+        space-before.maximum="2em"
+        space-before.precedence="900"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="900">A Sub-Title With a Non-Standard Role</fo:block>
+      <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter 
+        driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
+        application that reads a formatting object (FO) tree and renders the resulting pages to a 
+        specified output.</fo:block>
+      <fo:block role="H2" font-weight="bold" font-size="120%"
+        space-before.minimum="1.2em"
+        space-before.optimum="1.5em"
+        space-before.maximum="2em"
+        space-before.precedence="900"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="900">Title 2: Another Sub-Title</fo:block>
+      <fo:block text-align="justify">Apache FOP (Formatting Objects Processor) is a print formatter 
+        driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java 
+        application that reads a formatting object (FO) tree and renders the resulting pages to a 
+        specified output.</fo:block>
+      <fo:block role="H1" font-weight="bold" font-size="150%"
+        space-before.minimum="1.5em"
+        space-before.optimum="2em"
+        space-before.maximum="3em"
+        space-before.precedence="1000"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="1000">Title 1: Second Title</fo:block>
+      <fo:block role="H2" font-weight="bold" font-size="120%"
+        space-before.minimum="1.2em"
+        space-before.optimum="1.5em"
+        space-before.maximum="2em"
+        space-before.precedence="900"
+        space-after.minimum="0.2em"
+        space-after.optimum="0.2em"
+        space-after.maximum="0.5em"
+        space-after.precedence="900">Title 2: A Sample Table</fo:block>
+      <fo:block>See data below:</fo:block>
+      <fo:table table-layout="fixed" width="70%" start-indent="15%" border="0.5pt solid black">
+        <fo:table-header start-indent="0" font-weight="bold" role="TableHeader">
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Header 1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Header 2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-header>
+        <fo:table-footer start-indent="0" font-weight="bold">
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Footer 1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Footer 2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-footer>
+        <fo:table-body start-indent="0">
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 1.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 1.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+          <fo:table-row>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 2.1</fo:block>
+            </fo:table-cell>
+            <fo:table-cell border="0.5pt solid black" padding="2pt">
+              <fo:block>Cell 2.2</fo:block>
+            </fo:table-cell>
+          </fo:table-row>
+        </fo:table-body>
+      </fo:table>
+      <fo:block text-align="justify" space-before="0.5em">That’s all folks.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/text_1.fo b/test/pdf/accessibility/text_1.fo
new file mode 100644 (file)
index 0000000..31ad315
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
+        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
+        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
+        output.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/text_2.fo b/test/pdf/accessibility/text_2.fo
new file mode 100644 (file)
index 0000000..f569311
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify">
+      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
+        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
+        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
+        output.</fo:block>
+      <fo:block language="fr" country="FR">Apache FOP (Formatting Objects Processor) est une 
+        application de mise en page de documents respectant le standard XSL-FO. À partir d’un 
+        document au format XSL-FO, cette application écrite en Java effectue une mise en page et 
+        renvoie un document prêt pour impression.</fo:block>
+      <fo:block>Back to English and let’s say it again: Apache FOP (Formatting Objects Processor) is 
+        a print formatter driven by XSL formatting objects (XSL-FO) and an output independent 
+        formatter.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>
diff --git a/test/pdf/accessibility/text_font-embedding.fo b/test/pdf/accessibility/text_font-embedding.fo
new file mode 100644 (file)
index 0000000..10c1c99
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!--
+  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$ -->
+<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="en" country="GB">
+  <fo:layout-master-set>
+    <fo:simple-page-master master-name="page"
+      page-height="220pt" page-width="320pt" margin="10pt">
+      <fo:region-body/>
+    </fo:simple-page-master>
+  </fo:layout-master-set>
+  <fo:page-sequence master-reference="page">
+    <fo:flow flow-name="xsl-region-body" hyphenate="true" text-align="justify" font-family="DejaVu">
+      <fo:block>Apache FOP (Formatting Objects Processor) is a print formatter driven by XSL 
+        formatting objects (XSL-FO) and an output independent formatter. It is a Java application 
+        that reads a formatting object (FO) tree and renders the resulting pages to a specified 
+        output.</fo:block>
+    </fo:flow>
+  </fo:page-sequence>
+</fo:root>