diff options
author | Simon Steiner <ssteiner@apache.org> | 2015-02-24 11:23:44 +0000 |
---|---|---|
committer | Simon Steiner <ssteiner@apache.org> | 2015-02-24 11:23:44 +0000 |
commit | 77e0508bb36a6c5e547857f2bea17e1def2a2abc (patch) | |
tree | 92f26caed0d59eba746b306b69a84e6895e610d8 /test/java/org/apache/fop | |
parent | c85d08c4b9adbf8135e18ad9c3f94e3469e4e12e (diff) | |
download | xmlgraphics-fop-77e0508bb36a6c5e547857f2bea17e1def2a2abc.tar.gz xmlgraphics-fop-77e0508bb36a6c5e547857f2bea17e1def2a2abc.zip |
FOP-2445: Merge PDF Linearization branch
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1661887 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'test/java/org/apache/fop')
10 files changed, 335 insertions, 19 deletions
diff --git a/test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java b/test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java index dec62c0a4..ae68cbeb7 100644 --- a/test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java +++ b/test/java/org/apache/fop/pdf/AbstractPDFStreamTestCase.java @@ -49,7 +49,7 @@ public class AbstractPDFStreamTestCase extends PDFObjectTestCase { encodedBytes[i++] = (byte) (in & 0xff); } } - private String startStream = "<< /Length 5 0 R /Filter /FlateDecode >>\n" + private String startStream = "<< /Length 1 0 R /Filter /FlateDecode >>\n" + "stream\n"; private String endStream = "endstream"; diff --git a/test/java/org/apache/fop/pdf/ObjectStreamManagerTestCase.java b/test/java/org/apache/fop/pdf/ObjectStreamManagerTestCase.java index 21eb6088f..fda1a006e 100644 --- a/test/java/org/apache/fop/pdf/ObjectStreamManagerTestCase.java +++ b/test/java/org/apache/fop/pdf/ObjectStreamManagerTestCase.java @@ -46,7 +46,7 @@ public class ObjectStreamManagerTestCase { int objectStreamNumber2 = assertSameObjectStream(expectedCapacity, expectedCapacity * 2); int objectStreamNumber3 = assertSameObjectStream(expectedCapacity * 2, numCompressedObjects); assertDifferent(objectStreamNumber1, objectStreamNumber2, objectStreamNumber3); - assertEquals(objectStreamNumber3, pdfDocument.previous.getObjectNumber()); + assertEquals(objectStreamNumber3, pdfDocument.previous.getObjectNumber().getNumber()); } private void createCompressObjectReferences(int numObjects) { @@ -82,8 +82,8 @@ public class ObjectStreamManagerTestCase { private CompressedObject createCompressedObject(final int objectNumber) { return new CompressedObject() { - public int getObjectNumber() { - return objectNumber; + public PDFObjectNumber getObjectNumber() { + return new PDFObjectNumber(objectNumber); } public int output(OutputStream outputStream) throws IOException { @@ -101,7 +101,7 @@ public class ObjectStreamManagerTestCase { } private int getObjectStreamNumber(int index) { - return compressedObjectReferences.get(index).getObjectStreamNumber(); + return compressedObjectReferences.get(index).getObjectStreamNumber().getNumber(); } private void assertDifferent(int objectStreamNumber1, int objectStreamNumber2, diff --git a/test/java/org/apache/fop/pdf/ObjectStreamTestCase.java b/test/java/org/apache/fop/pdf/ObjectStreamTestCase.java index 3512e1147..bf8fe26c8 100644 --- a/test/java/org/apache/fop/pdf/ObjectStreamTestCase.java +++ b/test/java/org/apache/fop/pdf/ObjectStreamTestCase.java @@ -86,13 +86,14 @@ public class ObjectStreamTestCase { private String getExpectedOutput() { int numObs = compressedObjects.size(); - int objectStreamNumber = objectStream.getObjectNumber(); + int objectStreamNumber = objectStream.getObjectNumber().getNumber(); 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"); + objectStreamNumber++; } expected.append(" /Type /ObjStm\n") .append(" /N ").append(numObs).append("\n") diff --git a/test/java/org/apache/fop/pdf/PDFEncryptionJCETestCase.java b/test/java/org/apache/fop/pdf/PDFEncryptionJCETestCase.java index e3f8344e0..18d15c384 100644 --- a/test/java/org/apache/fop/pdf/PDFEncryptionJCETestCase.java +++ b/test/java/org/apache/fop/pdf/PDFEncryptionJCETestCase.java @@ -286,7 +286,7 @@ public class PDFEncryptionJCETestCase { public final void testMake() { PDFEncryption testEncryptionObj = createEncryptionObject(new PDFEncryptionParams()); assertTrue(testEncryptionObj instanceof PDFEncryptionJCE); - assertEquals(1, ((PDFEncryptionJCE) testEncryptionObj).getObjectNumber()); + assertEquals(1, ((PDFEncryptionJCE) testEncryptionObj).getObjectNumber().getNumber()); } @Test @@ -608,7 +608,7 @@ public class PDFEncryptionJCETestCase { }; } }; - return (PDFEncryptionJCE) PDFEncryptionJCE.make(1, params, doc); + return (PDFEncryptionJCE) PDFEncryptionJCE.make(new PDFObjectNumber(1), params, doc); } private void runEncryptionTests() throws IOException { diff --git a/test/java/org/apache/fop/pdf/PDFLinearizationTestCase.java b/test/java/org/apache/fop/pdf/PDFLinearizationTestCase.java new file mode 100644 index 000000000..7b78c1f5b --- /dev/null +++ b/test/java/org/apache/fop/pdf/PDFLinearizationTestCase.java @@ -0,0 +1,311 @@ +/* + * 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.awt.Dimension; +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.transform.stream.StreamResult; + +import org.junit.Assert; +import org.junit.Test; + +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.fonts.FontInfo; +import org.apache.fop.render.intermediate.IFContext; +import org.apache.fop.render.pdf.PDFContentGenerator; +import org.apache.fop.render.pdf.PDFDocumentHandler; +import org.apache.fop.render.pdf.PDFPainter; + +public class PDFLinearizationTestCase { + private int objectLeast; + private int[] objects; + + @Test + public void testPDF() throws IOException { + PDFDocument doc = new PDFDocument(""); + doc.setLinearizationEnabled(true); + PDFResources resources = new PDFResources(doc); + PDFResourceContext context = new PDFResourceContext(resources); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + PDFContentGenerator gen = null; + for (int i = 0; i < 2; i++) { + gen = new PDFContentGenerator(doc, out, context); + Rectangle2D.Float f = new Rectangle2D.Float(); + PDFPage page = new PDFPage(resources, i, f, f, f, f); + doc.registerObject(page); + doc.registerObject(gen.getStream()); + page.setContents(gen.getStream()); + } + gen.flushPDFDoc(); + byte[] data = out.toByteArray(); + checkPDF(data); + } + + @Test + public void testImage() throws Exception { + String fopxconf = "<fop version=\"1.0\"><renderers>" + + "<renderer mime=\"application/pdf\">" + + "<linearization>true</linearization>" + + "</renderer></renderers></fop>"; + FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI(), + new ByteArrayInputStream(fopxconf.getBytes())); + FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); + IFContext ifContext = new IFContext(foUserAgent); + PDFDocumentHandler documentHandler = new PDFDocumentHandler(ifContext); + documentHandler.getConfigurator().configure(documentHandler); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + documentHandler.setFontInfo(new FontInfo()); + documentHandler.setResult(new StreamResult(out)); + documentHandler.startDocument(); + documentHandler.startPage(0, "", "", new Dimension()); + PDFPainter pdfPainter = new PDFPainter(documentHandler, null); + pdfPainter.drawImage("test/resources/fop/svg/logo.jpg", new Rectangle()); + documentHandler.endPage(); + Assert.assertFalse(out.toString().contains("/Subtype /Image")); + documentHandler.endDocument(); + Assert.assertTrue(out.toString().contains("/Subtype /Image")); + } + + private void checkPDF(byte[] data) throws IOException { + checkHintTable(data); + InputStream is = new ByteArrayInputStream(data); + Map<String, StringBuilder> objs = readObjs(is); + + List<String> keys = new ArrayList<String>(objs.keySet()); + int start = keys.indexOf("1 0 obj"); + Assert.assertTrue(start > 1); + int j = 1; + for (int i = start; i < keys.size(); i++) { + Assert.assertEquals(keys.get(i), j + " 0 obj"); + j++; + } + for (int i = 0; i < start; i++) { + Assert.assertEquals(keys.get(i), j + " 0 obj"); + j++; + } + + checkFirstObj(data); + checkTrailer(data); + + String firstObj = objs.values().iterator().next().toString().replace("\n", ""); + Assert.assertTrue(firstObj.startsWith("<< /Linearized 1 /L " + data.length)); + Assert.assertTrue(firstObj.endsWith("startxref0%%EOF")); + int pageObjNumber = getValue("/O", firstObj); + Assert.assertTrue(objs.get(pageObjNumber + " 0 obj").toString().contains("/Type /Page")); + Assert.assertTrue(objs.get("5 0 obj").toString().contains("/Type /Pages")); + + int total = 0; + for (int i : objects) { + total += i; + } + Assert.assertEquals(total, objs.size() - 6); + } + + private void checkFirstObj(byte[] data) throws IOException { + int firstObjPos = getValue("/E", getFirstObj(data)); + InputStream is = new ByteArrayInputStream(data); + Assert.assertEquals(is.skip(firstObjPos), firstObjPos); + byte[] obj = new byte[10]; + Assert.assertEquals(is.read(obj), obj.length); + Assert.assertTrue(new String(obj).startsWith("1 0 obj")); + } + + private void checkTrailer(byte[] data) throws IOException { + int trailerPos = getValue("/T", getFirstObj(data)); + InputStream is = new ByteArrayInputStream(data); + Assert.assertEquals(is.skip(trailerPos), trailerPos); + byte[] obj = new byte[20]; + Assert.assertEquals(is.read(obj), obj.length); + Assert.assertTrue(new String(obj).startsWith("0000000000 65535 f")); + } + + private int getValue(String name, String firstObj) throws IOException { + String[] split = firstObj.split(" "); + for (int i = 0; i < split.length; i++) { + if (split[i].equals(name)) { + return Integer.valueOf(split[i + 1].replace(">>", "")); + } + } + throw new IOException(name + " not found " + firstObj); + } + + private int[] getArrayValue(String name, String firstObj) throws IOException { + String[] split = firstObj.split(" "); + for (int i = 0; i < split.length; i++) { + if (split[i].equals(name)) { + int[] v = new int[2]; + v[0] = Integer.valueOf(split[i + 1].replace("[", "")); + v[1] = Integer.valueOf(split[i + 2].replace("]", "")); + return v; + } + } + throw new IOException(name + " not found " + firstObj); + } + + private String getFirstObj(byte[] out) throws IOException { + InputStream data = new ByteArrayInputStream(out); + Map<String, StringBuilder> objs = readObjs(data); + return objs.values().iterator().next().toString().replace("\n", ""); + } + + private void checkHintTable(byte[] out) throws IOException { + String firstObj = getFirstObj(out); + int hintPos = getArrayValue("/H", firstObj)[0]; + int hintLength = getArrayValue("/H", firstObj)[1]; + + InputStream data = new ByteArrayInputStream(out); + Assert.assertEquals(data.skip(hintPos), hintPos); + + byte[] hintTable = new byte[hintLength]; + Assert.assertEquals(data.read(hintTable), hintLength); + String hintTableStr = new String(hintTable); + + Assert.assertTrue(hintTableStr.contains("/S ")); + Assert.assertTrue(hintTableStr.contains("/C ")); + Assert.assertTrue(hintTableStr.contains("/E ")); + Assert.assertTrue(hintTableStr.contains("/L ")); + Assert.assertTrue(hintTableStr.contains("/V ")); + Assert.assertTrue(hintTableStr.contains("/O ")); + Assert.assertTrue(hintTableStr.contains("/I ")); + Assert.assertTrue(hintTableStr.contains("/Length ")); + Assert.assertTrue(hintTableStr.contains("stream")); + Assert.assertTrue(hintTableStr.contains("endstream")); + Assert.assertTrue(hintTableStr.endsWith("endobj\n")); + + data = new ByteArrayInputStream(hintTable); + readStart(data); + int pages = getValue("/N", firstObj); + readObjectsTable(data, pages); + readSharedObjectsTable(data); + Assert.assertEquals(objectLeast, 1); + } + + private void readObjectsTable(InputStream data, int pages) + throws IOException { + objectLeast = read32(data); + read32(data); + int bitsDiffObjects = read16(data); + read32(data); + int bitsDiffPageLength = read16(data); + read32(data); + read16(data); + read32(data); + read16(data); + read16(data); + read16(data); + read16(data); + read16(data); + + objects = new int[pages]; + for (int i = 0; i < pages; i++) { + objects[i] = objectLeast + readBits(bitsDiffObjects, data); + } + for (int i = 0; i < pages; i++) { + readBits(bitsDiffPageLength, data); + } + for (int i = 0; i < pages; i++) { + readBits(32, data); + } + } + + private void readSharedObjectsTable(InputStream str) throws IOException { + readBits(32, str); + readBits(32, str); + readBits(32, str); + int sharedGroups = readBits(32, str); + readBits(16, str); + readBits(32, str); + int bitsDiffGroupLength = readBits(16, str); + for (int i = 0; i < sharedGroups; i++) { + readBits(bitsDiffGroupLength, str); + } + } + + private int readBits(int bits, InputStream data) throws IOException { + if (bits == 32) { + return read32(data); + } + if (bits == 16) { + return read16(data); + } + throw new IOException("Wrong bits"); + } + + private int read32(InputStream data) throws IOException { + int ch1 = data.read(); + int ch2 = data.read(); + int ch3 = data.read(); + int ch4 = data.read(); + return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4)); + } + + private int read16(InputStream data) throws IOException { + int ch1 = data.read(); + int ch2 = data.read(); + return (ch1 << 8) + (ch2); + } + + private void readStart(InputStream inputStream) throws IOException { + StringBuilder sb = new StringBuilder(); + while (inputStream.available() > 0) { + int data = inputStream.read(); + if (data == '\n') { + if (sb.toString().equals("stream")) { + return; + } + sb.setLength(0); + } else { + sb.append((char)data); + } + } + } + + private Map<String, StringBuilder> readObjs(InputStream inputStream) throws IOException { + Map<String, StringBuilder> objs = new LinkedHashMap<String, StringBuilder>(); + StringBuilder sb = new StringBuilder(); + String key = null; + while (inputStream.available() > 0) { + int data = inputStream.read(); + if (data == '\n') { + if (sb.toString().endsWith(" 0 obj")) { + key = sb.toString().trim(); + objs.put(key, new StringBuilder()); + } else if (key != null) { + objs.get(key).append(sb).append("\n"); + } + sb.setLength(0); + } else { + sb.append((char)data); + } + } + return objs; + } +} diff --git a/test/java/org/apache/fop/pdf/PDFObjectTestCase.java b/test/java/org/apache/fop/pdf/PDFObjectTestCase.java index f35d2a15c..544352438 100644 --- a/test/java/org/apache/fop/pdf/PDFObjectTestCase.java +++ b/test/java/org/apache/fop/pdf/PDFObjectTestCase.java @@ -58,10 +58,10 @@ public class PDFObjectTestCase { @Test public void testSetObjectNumber() { pdfObjectUnderTest.setObjectNumber(1); - assertEquals(1, pdfObjectUnderTest.getObjectNumber()); + assertEquals(1, pdfObjectUnderTest.getObjectNumber().getNumber()); pdfObjectUnderTest.setObjectNumber(5); - assertEquals(5, pdfObjectUnderTest.getObjectNumber()); + assertEquals(5, pdfObjectUnderTest.getObjectNumber().getNumber()); } /** @@ -157,12 +157,12 @@ public class PDFObjectTestCase { PDFDictionary dict = new PDFDictionary(); dict.setObjectNumber(7); PDFReference ref = dict.makeReference(); - assertEquals(ref.getObjectNumber(), 7); + assertEquals(ref.getObjectNumber().getNumber(), 7); assertEquals(ref.getGeneration(), 0); assertEquals(ref.toString(), "7 0 R"); ref = new PDFReference("8 0 R"); - assertEquals(ref.getObjectNumber(), 8); + assertEquals(ref.getObjectNumber().getNumber(), 8); assertEquals(ref.getGeneration(), 0); assertEquals(ref.toString(), "8 0 R"); } diff --git a/test/java/org/apache/fop/pdf/xref/CompressedObjectReferenceTestCase.java b/test/java/org/apache/fop/pdf/xref/CompressedObjectReferenceTestCase.java index b7a326c64..b58d2f93e 100644 --- a/test/java/org/apache/fop/pdf/xref/CompressedObjectReferenceTestCase.java +++ b/test/java/org/apache/fop/pdf/xref/CompressedObjectReferenceTestCase.java @@ -27,6 +27,8 @@ import org.junit.Test; import static org.junit.Assert.assertArrayEquals; +import org.apache.fop.pdf.PDFObjectNumber; + public class CompressedObjectReferenceTestCase extends ObjectReferenceTest { @Test @@ -41,7 +43,7 @@ public class CompressedObjectReferenceTestCase extends ObjectReferenceTest { private void runTest(List<Integer> expectedObjectStreamBytes, int index) throws IOException { int objectStreamNumber = (int) computeNumberFromBytes(expectedObjectStreamBytes); - sut = new CompressedObjectReference(0, objectStreamNumber, index); + sut = new CompressedObjectReference(new PDFObjectNumber(0), new PDFObjectNumber(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 index cd55577cd..513f0d754 100644 --- a/test/java/org/apache/fop/pdf/xref/CrossReferenceObjectTest.java +++ b/test/java/org/apache/fop/pdf/xref/CrossReferenceObjectTest.java @@ -52,7 +52,7 @@ public abstract class CrossReferenceObjectTest { 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)); + PDFRoot root = new PDFRoot(pdfDocument, new PDFPages(pdfDocument)); PDFInfo info = new PDFInfo(); info.setObjectNumber(2); byte[] fileID = diff --git a/test/java/org/apache/fop/pdf/xref/CrossReferenceStreamTestCase.java b/test/java/org/apache/fop/pdf/xref/CrossReferenceStreamTestCase.java index 3e609635d..e0e8aef78 100644 --- a/test/java/org/apache/fop/pdf/xref/CrossReferenceStreamTestCase.java +++ b/test/java/org/apache/fop/pdf/xref/CrossReferenceStreamTestCase.java @@ -29,6 +29,8 @@ import java.util.List; import org.junit.Test; +import org.apache.fop.pdf.PDFObjectNumber; + public class CrossReferenceStreamTestCase extends CrossReferenceObjectTest { private List<Long> uncompressedObjectOffsets; @@ -54,7 +56,7 @@ public class CrossReferenceStreamTestCase extends CrossReferenceObjectTest { @Test public void testWithObjectStreams1() throws IOException { List<CompressedObjectReference> compressedObjectReferences = - Arrays.asList(new CompressedObjectReference(2, 1, 0)); + Arrays.asList(new CompressedObjectReference(new PDFObjectNumber(2), new PDFObjectNumber(1), 0)); test(Arrays.asList(0L, null), compressedObjectReferences); } @@ -72,8 +74,8 @@ public class CrossReferenceStreamTestCase extends CrossReferenceObjectTest { for (int index = 0; index < numCompressedObjects; index++) { indirectObjectOffsets.add(null); int obNum = numIndirectObjects + index + 1; - compressedObjectReferences.add(new CompressedObjectReference(obNum, - numIndirectObjects, index)); + compressedObjectReferences.add(new CompressedObjectReference(new PDFObjectNumber(obNum), + new PDFObjectNumber(numIndirectObjects), index)); } test(indirectObjectOffsets, compressedObjectReferences); } @@ -108,7 +110,7 @@ public class CrossReferenceStreamTestCase extends CrossReferenceObjectTest { objectReferences.add(offset == null ? null : new UncompressedObjectReference(offset)); } for (CompressedObjectReference ref : compressedObjectReferences) { - objectReferences.set(ref.getObjectNumber() - 1, ref); + objectReferences.set(ref.getObjectNumber().getNumber() - 1, ref); } int maxObjectNumber = objectReferences.size() + 1; ByteArrayOutputStream stream = new ByteArrayOutputStream(); diff --git a/test/java/org/apache/fop/pdf/xref/CrossReferenceTableTestCase.java b/test/java/org/apache/fop/pdf/xref/CrossReferenceTableTestCase.java index 12f6e3c1b..1c609e30f 100644 --- a/test/java/org/apache/fop/pdf/xref/CrossReferenceTableTestCase.java +++ b/test/java/org/apache/fop/pdf/xref/CrossReferenceTableTestCase.java @@ -53,7 +53,7 @@ public class CrossReferenceTableTestCase extends CrossReferenceObjectTest { @Override protected CrossReferenceObject createCrossReferenceObject() { - return new CrossReferenceTable(trailerDictionary, STARTXREF, offsets); + return new CrossReferenceTable(trailerDictionary, STARTXREF, offsets, 0, offsets.size(), offsets.size()); } @Override |