aboutsummaryrefslogtreecommitdiffstats
path: root/test/java/org
diff options
context:
space:
mode:
authorVincent Hennebert <vhennebert@apache.org>2012-03-21 15:12:43 +0000
committerVincent Hennebert <vhennebert@apache.org>2012-03-21 15:12:43 +0000
commitb9fbfa6b71b5e0d67806c066ea422819de08f3b2 (patch)
treeea0b24983c14733ec584a04b79ac108634a9cef2 /test/java/org
parent54b6471e8fe27378222389de496721cc379a812d (diff)
downloadxmlgraphics-fop-b9fbfa6b71b5e0d67806c066ea422819de08f3b2.tar.gz
xmlgraphics-fop-b9fbfa6b71b5e0d67806c066ea422819de08f3b2.zip
Added support for PDF object streams.Temp_PDF_ObjectStreams
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
Diffstat (limited to 'test/java/org')
-rw-r--r--test/java/org/apache/fop/StandardTestSuite.java4
-rw-r--r--test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java8
-rw-r--r--test/java/org/apache/fop/pdf/ObjectStreamManagerTestCase.java113
-rw-r--r--test/java/org/apache/fop/pdf/ObjectStreamTestCase.java131
-rw-r--r--test/java/org/apache/fop/pdf/PDFEncryptionJCETestCase.java2
-rw-r--r--test/java/org/apache/fop/pdf/PDFFilterListTestCase.java33
-rw-r--r--test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java4
-rw-r--r--test/java/org/apache/fop/pdf/PDFObjectTestCase.java9
-rw-r--r--test/java/org/apache/fop/pdf/PDFStreamTestCase.java126
-rw-r--r--test/java/org/apache/fop/pdf/xref/CompressedObjectReferenceTestCase.java50
-rw-r--r--test/java/org/apache/fop/pdf/xref/CrossReferenceObjectTest.java106
-rw-r--r--test/java/org/apache/fop/pdf/xref/CrossReferenceStreamTestCase.java142
-rw-r--r--test/java/org/apache/fop/pdf/xref/CrossReferenceTableTestCase.java80
-rw-r--r--test/java/org/apache/fop/pdf/xref/ObjectReferenceTest.java62
-rw-r--r--test/java/org/apache/fop/pdf/xref/UncompressedObjectReferenceTestCase.java90
15 files changed, 944 insertions, 16 deletions
diff --git a/test/java/org/apache/fop/StandardTestSuite.java b/test/java/org/apache/fop/StandardTestSuite.java
index eecdeb671..8649fdfa8 100644
--- a/test/java/org/apache/fop/StandardTestSuite.java
+++ b/test/java/org/apache/fop/StandardTestSuite.java
@@ -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.
diff --git a/test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java b/test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java
index b930a8b6d..95d5c0a1d 100644
--- a/test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java
+++ b/test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java
@@ -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
index 000000000..89d980029
--- /dev/null
+++ b/test/java/org/apache/fop/pdf/ObjectStreamManagerTestCase.java
@@ -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
index 000000000..317828e4b
--- /dev/null
+++ b/test/java/org/apache/fop/pdf/ObjectStreamTestCase.java
@@ -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;
+ }
+ }
+
+}
diff --git a/test/java/org/apache/fop/pdf/PDFEncryptionJCETestCase.java b/test/java/org/apache/fop/pdf/PDFEncryptionJCETestCase.java
index 235db7045..db10e656e 100644
--- a/test/java/org/apache/fop/pdf/PDFEncryptionJCETestCase.java
+++ b/test/java/org/apache/fop/pdf/PDFEncryptionJCETestCase.java
@@ -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
index 000000000..2504d871a
--- /dev/null
+++ b/test/java/org/apache/fop/pdf/PDFFilterListTestCase.java
@@ -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());
+ }
+}
diff --git a/test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java b/test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java
index a0c4ea11f..c7a9dff89 100644
--- a/test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java
+++ b/test/java/org/apache/fop/pdf/PDFLibraryTestSuite.java
@@ -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 {
}
diff --git a/test/java/org/apache/fop/pdf/PDFObjectTestCase.java b/test/java/org/apache/fop/pdf/PDFObjectTestCase.java
index ee9512d88..10ffa3b27 100644
--- a/test/java/org/apache/fop/pdf/PDFObjectTestCase.java
+++ b/test/java/org/apache/fop/pdf/PDFObjectTestCase.java
@@ -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
index 000000000..93dcea511
--- /dev/null
+++ b/test/java/org/apache/fop/pdf/PDFStreamTestCase.java
@@ -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
index 000000000..8b103d277
--- /dev/null
+++ b/test/java/org/apache/fop/pdf/xref/CompressedObjectReferenceTestCase.java
@@ -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
index 000000000..df1b86e53
--- /dev/null
+++ b/test/java/org/apache/fop/pdf/xref/CrossReferenceObjectTest.java
@@ -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
index 000000000..3e609635d
--- /dev/null
+++ b/test/java/org/apache/fop/pdf/xref/CrossReferenceStreamTestCase.java
@@ -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
index 000000000..ceff96a91
--- /dev/null
+++ b/test/java/org/apache/fop/pdf/xref/CrossReferenceTableTestCase.java
@@ -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
index 000000000..fada2794c
--- /dev/null
+++ b/test/java/org/apache/fop/pdf/xref/ObjectReferenceTest.java
@@ -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
index 000000000..b147084e8
--- /dev/null
+++ b/test/java/org/apache/fop/pdf/xref/UncompressedObjectReferenceTestCase.java
@@ -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);
+ }
+
+}