]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugzilla #54169: Split the parent tree (the number tree corresponding to the ParentTr...
authorVincent Hennebert <vhennebert@apache.org>
Mon, 19 Nov 2012 18:53:11 +0000 (18:53 +0000)
committerVincent Hennebert <vhennebert@apache.org>
Mon, 19 Nov 2012 18:53:11 +0000 (18:53 +0000)
Patch submitted by Robert Meyer

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

30 files changed:
src/java/org/apache/fop/pdf/PDFNumberTreeNode.java
src/java/org/apache/fop/pdf/PDFPageLabels.java
src/java/org/apache/fop/pdf/PDFParentTree.java
src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java
status.xml
test/java/org/apache/fop/pdf/PDFParentTreeTestCase.java [new file with mode: 0644]
test/pdf/1.5/test.pdf
test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf
test/pdf/accessibility/pdf/background-image_jpg_single.pdf
test/pdf/accessibility/pdf/background-image_png_repeat.pdf
test/pdf/accessibility/pdf/background-image_png_single.pdf
test/pdf/accessibility/pdf/background-image_svg_repeat.pdf
test/pdf/accessibility/pdf/background-image_svg_single.pdf
test/pdf/accessibility/pdf/complete.pdf
test/pdf/accessibility/pdf/hyphenation.pdf
test/pdf/accessibility/pdf/image_jpg.pdf
test/pdf/accessibility/pdf/image_png.pdf
test/pdf/accessibility/pdf/image_svg.pdf
test/pdf/accessibility/pdf/image_wmf.pdf
test/pdf/accessibility/pdf/language.pdf
test/pdf/accessibility/pdf/leader.pdf
test/pdf/accessibility/pdf/links.pdf
test/pdf/accessibility/pdf/role.pdf
test/pdf/accessibility/pdf/role_non-standard.pdf
test/pdf/accessibility/pdf/side-regions.pdf
test/pdf/accessibility/pdf/table_row-col-span.pdf
test/pdf/accessibility/pdf/text_1.pdf
test/pdf/accessibility/pdf/text_2.pdf
test/pdf/accessibility/pdf/text_font-embedding.pdf
test/pdf/accessibility/pdf/th_scope.pdf

index 72fbcd1c6bea02928f7bf43c232c72b330b744ff..599530439d574a01ad0d6d22501a1ba5746757da 100644 (file)
@@ -49,7 +49,7 @@ public class PDFNumberTreeNode extends PDFDictionary {
      * @return the Kids array
      */
     public PDFArray getKids() {
-        return (PDFArray)get(KIDS);
+        return (PDFArray) get(KIDS);
     }
 
     /**
@@ -65,7 +65,12 @@ public class PDFNumberTreeNode extends PDFDictionary {
      * @return the Nums array
      */
     public PDFNumsArray getNums() {
-        return (PDFNumsArray)get(NUMS);
+        PDFNumsArray nums = (PDFNumsArray) get(NUMS);
+        if (nums == null) {
+            nums = new PDFNumsArray(this);
+            setNums(nums);
+        }
+        return nums;
     }
 
     /**
@@ -83,7 +88,7 @@ public class PDFNumberTreeNode extends PDFDictionary {
      */
     public Integer getLowerLimit() {
         PDFArray limits = prepareLimitsArray();
-        return (Integer)limits.get(0);
+        return (Integer) limits.get(0);
     }
 
     /**
@@ -101,12 +106,25 @@ public class PDFNumberTreeNode extends PDFDictionary {
      */
     public Integer getUpperLimit() {
         PDFArray limits = prepareLimitsArray();
-        return (Integer)limits.get(1);
+        return (Integer) limits.get(1);
+    }
+
+    /**
+     * Adds a number and object to the nums array and increases the
+     * upper limit should it be required.
+     * @param num The unique number identifying the object in the array
+     * @param object The object being added
+     */
+    protected void addToNums(int num, Object object) {
+        getNums().put(num, object);
+        if (getUpperLimit() < num) {
+            setUpperLimit(num);
+        }
     }
 
 
     private PDFArray prepareLimitsArray() {
-        PDFArray limits = (PDFArray)get(LIMITS);
+        PDFArray limits = (PDFArray) get(LIMITS);
         if (limits == null) {
             limits = new PDFArray(this, new Object[2]);
             put(LIMITS, limits);
index e95c97a25a72cb2a0b285eaf0a972802367b618c..e7b90ec4e2bdab8fe657664b71b322789de92701 100644 (file)
@@ -56,20 +56,6 @@ public class PDFPageLabels extends PDFNumberTreeNode {
         super();
     }
 
-    /**
-     * Returns the Nums object
-     * @return the Nums object (an empty PDFNumsArray for the "/Nums" entry is created
-     *       if it doesn't exist)
-     */
-    public PDFNumsArray getNums() {
-        PDFNumsArray nums = super.getNums();
-        if (nums == null) {
-            nums = new PDFNumsArray(this);
-            setNums(nums);
-        }
-        return nums;
-    }
-
     /**
      * Adds a new entry, if necessary, to the /PageLabels dictionary.
      * @param index the page index (0 for page 1)
index 7876bbc0c4e339b42c5de0f37a89fb3303b1a13e..e03545568b49fab9473c1d5b779b43b4e5ab95e8 100644 (file)
@@ -24,18 +24,44 @@ package org.apache.fop.pdf;
  */
 public class PDFParentTree extends PDFNumberTreeNode {
 
+    private static final int MAX_NUMS_ARRAY_SIZE = 50;
+
+    public PDFParentTree() {
+        put("Kids", new PDFArray());
+    }
+
+    @Override
+    public void addToNums(int num, Object object) {
+        int arrayIndex = num / MAX_NUMS_ARRAY_SIZE;
+        setNumOfKidsArrays(arrayIndex + 1);
+        insertItemToNumsArray(arrayIndex, num, object);
+    }
+
+    private void setNumOfKidsArrays(int numKids) {
+        for (int i = getKids().length(); i < numKids; i++) {
+            PDFNumberTreeNode newArray = new PDFNumberTreeNode();
+            newArray.setNums(new PDFNumsArray(newArray));
+            newArray.setLowerLimit(i * MAX_NUMS_ARRAY_SIZE);
+            newArray.setUpperLimit(i * MAX_NUMS_ARRAY_SIZE);
+            addKid(newArray);
+        }
+    }
+
     /**
-     * Returns the number tree corresponding to this parent tree.
-     *
-     * @return the number tree
+     * Registers a child object and adds it to the Kids array.
+     * @param kid The child PDF object to be added
      */
-    public PDFNumsArray getNums() {
-        PDFNumsArray nums = super.getNums();
-        if (nums == null) {
-            nums = new PDFNumsArray(this);
-            setNums(nums);
-        }
-        return nums;
+    private void addKid(PDFObject kid) {
+        assert getDocument() != null;
+        getDocument().assignObjectNumber(kid);
+        getDocument().addTrailerObject(kid);
+        ((PDFArray) get("Kids")).add(kid);
+    }
+
+    private void insertItemToNumsArray(int array, int num, Object object) {
+        assert getKids().get(array) instanceof PDFNumberTreeNode;
+        PDFNumberTreeNode numsArray = (PDFNumberTreeNode) getKids().get(array);
+        numsArray.addToNums(num, object);
     }
 }
 
index ee00d2401e40cd912a26707453d71c6029e9fde4..c532a05a4f4e95a43a144b20c39770db88e126f6 100644 (file)
@@ -124,7 +124,7 @@ class PDFLogicalStructureHandler {
         // being output to the PDF.
         // This should really be handled by PDFNumsArray
         pdfDoc.registerObject(pageParentTreeArray);
-        parentTree.getNums().put(currentPage.getStructParents(), pageParentTreeArray);
+        parentTree.addToNums(currentPage.getStructParents(), pageParentTreeArray);
     }
 
     private MarkedContentInfo addToParentTree(PDFStructElem structureTreeElement) {
@@ -198,7 +198,7 @@ class PDFLogicalStructureHandler {
         contentItem.put("Type", OBJR);
         contentItem.put("Pg", this.currentPage);
         contentItem.put("Obj", link);
-        parentTree.getNums().put(structParent, structureTreeElement);
+        parentTree.addToNums(structParent, structureTreeElement);
         structureTreeElement.addKid(contentItem);
     }
 
index 990a15f5e6b0a2f111ff2ac6ef4058d91c6c63b9..9362983b2326c246a9831493538103602a891607 100644 (file)
       documents. Example: the fix of marks layering will be such a case when it's done.
     -->
     <release version="FOP Trunk" date="TBD">
+      <action context="Renderers" dev="VH" type="fix" fixes-bug="54169" due-to="Robert Meyer">
+        Split the parent tree (the number tree corresponding to the ParentTree entry in the 
+        structure tree root) to avoid reaching the internal limits of Acrobat Pro, that would 
+        otherwise split it at the wrong place when saving the document.
+      </action>
       <action context="Fonts" dev="MH" type="add" fixes-bug="54120">
         Created a simple mechanism to avoid NPEs when AWT fonts are requested from Batik
         for AFP output.
diff --git a/test/java/org/apache/fop/pdf/PDFParentTreeTestCase.java b/test/java/org/apache/fop/pdf/PDFParentTreeTestCase.java
new file mode 100644 (file)
index 0000000..6fa5d6a
--- /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;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+/**
+ * Tests that the nums array in the ParentTree dictionary is correctly being split into
+ * separate arrays if the elements number exceeds the set limit.
+ */
+public class PDFParentTreeTestCase {
+
+    private PDFParentTree parentTree;
+
+    @Before
+    public void initializeStructureTree() {
+        parentTree = new PDFParentTree();
+        PDFDocument pdfDocument = new PDFDocument("test");
+        pdfDocument.makeStructTreeRoot(parentTree);
+    }
+
+    /**
+     * Adds less structured items than the imposed limit which should result
+     * in only one nums array being created.
+     * @throws Exception
+     */
+    @Test
+    public void testNoSplit() throws Exception {
+        assertEquals(getArrayNumber(45), 1);
+    }
+
+    /**
+     * Adds more than the imposed array limit to test that it splits the
+     * nums array into two objects.
+     * @throws Exception
+     */
+    @Test
+    public void testSingleSplit() throws Exception {
+        assertEquals(getArrayNumber(70), 2);
+    }
+
+    /**
+     * Adds items to the nums array to cause and test that multiple splits occur
+     * @throws Exception
+     */
+    @Test
+    public void testMultipleSplit() throws Exception {
+        assertEquals(getArrayNumber(165), 4);
+    }
+
+    /**
+     * Ensures that items added out of order get added to the correct nums array
+     * @throws Exception
+     */
+    @Test
+    public void testOutOfOrderSplit() throws Exception {
+        PDFStructElem structElem = mock(PDFStructElem.class);
+        for (int num = 50; num < 53; num++) {
+            parentTree.addToNums(num, structElem);
+        }
+        assertEquals(getArrayNumber(50), 2);
+        PDFNumberTreeNode treeNode = (PDFNumberTreeNode) parentTree.getKids().get(0);
+        for (int num = 0; num < 50; num++) {
+            assertTrue(treeNode.getNums().map.containsKey(num));
+        }
+        treeNode = (PDFNumberTreeNode) parentTree.getKids().get(1);
+        for (int num = 50; num < 53; num++) {
+            assertTrue(treeNode.getNums().map.containsKey(num));
+        }
+    }
+
+    /**
+     * Gets the number of arrays created for a given number of elements
+     * @param elementNumber The number of elements to be added to the nums array
+     * @return Returns the number of array objects
+     * @throws Exception
+     */
+    private int getArrayNumber(int elementNumber) throws Exception {
+        PDFStructElem structElem = mock(PDFStructElem.class);
+        for (int structParent = 0; structParent < elementNumber; structParent++) {
+            parentTree.addToNums(structParent, structElem);
+        }
+        return parentTree.getKids().length();
+    }
+}
index d97648e1edca50f561957fa6a1b04593adb0e8e0..e937afd583ea69ef477531c3ff56519d8b1bf944 100644 (file)
Binary files a/test/pdf/1.5/test.pdf and b/test/pdf/1.5/test.pdf differ
index 65f04cdef6dc79ca4b12c60c7db7bb3323155dd5..4c2fe46873d7e191bcbe7e0039b8edc4da1b4422 100644 (file)
Binary files a/test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf and b/test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf differ
index 6803ba999f339884d61a81c5b120db5ce25d0851..74b17c33762a761fe33c5c93ee4ca6805d4e6602 100644 (file)
Binary files a/test/pdf/accessibility/pdf/background-image_jpg_single.pdf and b/test/pdf/accessibility/pdf/background-image_jpg_single.pdf differ
index d42d935aa1165ba42966e62c8cf4c3059334374d..f69e373bcfc11c684f739f7e41c232ba9685403d 100644 (file)
Binary files a/test/pdf/accessibility/pdf/background-image_png_repeat.pdf and b/test/pdf/accessibility/pdf/background-image_png_repeat.pdf differ
index ba39a2b31f7322877d196b3b81b00fecfca48fcf..cdba6192e9c9a5484e1b4563431975c0de73c8c4 100644 (file)
Binary files a/test/pdf/accessibility/pdf/background-image_png_single.pdf and b/test/pdf/accessibility/pdf/background-image_png_single.pdf differ
index 1de4c98a147cc2d44497463a42c376a7879db78e..ed74244b33192f13ddd55e464bb8780dd1de3e0b 100644 (file)
Binary files a/test/pdf/accessibility/pdf/background-image_svg_repeat.pdf and b/test/pdf/accessibility/pdf/background-image_svg_repeat.pdf differ
index b89ea182ae1e95d94159ce5ed59cea90b692e2a4..d2245e349172ae465fa108f257dd55a0f1ae38b1 100644 (file)
Binary files a/test/pdf/accessibility/pdf/background-image_svg_single.pdf and b/test/pdf/accessibility/pdf/background-image_svg_single.pdf differ
index 9b4df8c400b712a05b624133baa0c09546acf2cc..844106f2324908d329ee6927ac2d2752258724d5 100644 (file)
Binary files a/test/pdf/accessibility/pdf/complete.pdf and b/test/pdf/accessibility/pdf/complete.pdf differ
index d8552f63a45d570a4b433e1ef8c575a7b3867e26..401fbf3568bda01a591ce0883aaece4202a71391 100644 (file)
Binary files a/test/pdf/accessibility/pdf/hyphenation.pdf and b/test/pdf/accessibility/pdf/hyphenation.pdf differ
index e35768d8ae6a3d9b93c35c08986a187cfe56486a..76f5509c861af8a5d2e91d286d7c65abdfe49ce7 100644 (file)
Binary files a/test/pdf/accessibility/pdf/image_jpg.pdf and b/test/pdf/accessibility/pdf/image_jpg.pdf differ
index a33d2ed3f4746be7e2ba8b05012d81779335a8f7..0a5641aaa81ddba42300360305fd4c34eef9ff8f 100644 (file)
Binary files a/test/pdf/accessibility/pdf/image_png.pdf and b/test/pdf/accessibility/pdf/image_png.pdf differ
index 1184ddef9954858234c43282422152fb4652642c..eaf6d56c4ec724bbb4c0e68aea920785b9ff69fc 100644 (file)
Binary files a/test/pdf/accessibility/pdf/image_svg.pdf and b/test/pdf/accessibility/pdf/image_svg.pdf differ
index 43c15d9ea6e1f6c3911619aa56ea965dfb7d562b..819f385a6613eb24a387f2beff7020cf8f497b98 100644 (file)
Binary files a/test/pdf/accessibility/pdf/image_wmf.pdf and b/test/pdf/accessibility/pdf/image_wmf.pdf differ
index 48a5f9f52b16f2a3347e9142f8b57e54bf57145a..e32f4f7e961125af382237436f9501276b79e303 100644 (file)
Binary files a/test/pdf/accessibility/pdf/language.pdf and b/test/pdf/accessibility/pdf/language.pdf differ
index e277699e5c50d2eeae1a0abe1d2a879b37084c37..869a47d7616661dcb2416f21e8fe3999441bdb19 100644 (file)
Binary files a/test/pdf/accessibility/pdf/leader.pdf and b/test/pdf/accessibility/pdf/leader.pdf differ
index 896620bfb393b63c30412a361e2db884db46fea2..5c63a25744abbbc972da290cc1ae87a7637f7377 100644 (file)
Binary files a/test/pdf/accessibility/pdf/links.pdf and b/test/pdf/accessibility/pdf/links.pdf differ
index 6e26032ff1920a6cf31106b559ce97e30209c47f..a91e8b98306a98823ee30f47a79b26ba5b1596a2 100644 (file)
Binary files a/test/pdf/accessibility/pdf/role.pdf and b/test/pdf/accessibility/pdf/role.pdf differ
index edf7541df069d1b873f61c01f57b1876bf3c8be9..c7a55233cef31610075a9e2674fc6a3c48beeebc 100644 (file)
Binary files a/test/pdf/accessibility/pdf/role_non-standard.pdf and b/test/pdf/accessibility/pdf/role_non-standard.pdf differ
index 22364c2c827e854fa6cebc37e51df63799fae94a..650e962b35d41e449f4011feb91b530037e59cad 100644 (file)
Binary files a/test/pdf/accessibility/pdf/side-regions.pdf and b/test/pdf/accessibility/pdf/side-regions.pdf differ
index eec14fa3d8d7fa6166b4a2d9af831d707b564f6e..9a05c1892a6fadcf5abba0a03fa1120c278ebf10 100644 (file)
Binary files a/test/pdf/accessibility/pdf/table_row-col-span.pdf and b/test/pdf/accessibility/pdf/table_row-col-span.pdf differ
index f3daa44b0baeaff71e6ae03f5b2263ad63dec91d..71b32f80c5f6209b50eb14e04ade016bbcaad816 100644 (file)
Binary files a/test/pdf/accessibility/pdf/text_1.pdf and b/test/pdf/accessibility/pdf/text_1.pdf differ
index 5a2abcf2f8a8926801efa9cdedd1409d680109c6..ac16626596c4bb9cd1589c488d297f851cf93ea0 100644 (file)
Binary files a/test/pdf/accessibility/pdf/text_2.pdf and b/test/pdf/accessibility/pdf/text_2.pdf differ
index e7f75b5a3da0f3aa17298be245048176db6475a6..d724af9e97d1a6816c52b478dccdd366a6603f53 100644 (file)
Binary files a/test/pdf/accessibility/pdf/text_font-embedding.pdf and b/test/pdf/accessibility/pdf/text_font-embedding.pdf differ
index 9d19548d7ce6ff42262d00f445b766a72cd2d8b5..68a98987b77291d877d8cd1a978845360702262f 100644 (file)
Binary files a/test/pdf/accessibility/pdf/th_scope.pdf and b/test/pdf/accessibility/pdf/th_scope.pdf differ