From: Vincent Hennebert Date: Mon, 19 Nov 2012 18:53:11 +0000 (+0000) Subject: Bugzilla #54169: Split the parent tree (the number tree corresponding to the ParentTr... X-Git-Tag: fop-2_0~264 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=638ea00309ef225858fdc2b5ab2889e1236d783d;p=xmlgraphics-fop.git Bugzilla #54169: 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. Patch submitted by Robert Meyer git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1411352 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java b/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java index 72fbcd1c6..599530439 100644 --- a/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java +++ b/src/java/org/apache/fop/pdf/PDFNumberTreeNode.java @@ -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); diff --git a/src/java/org/apache/fop/pdf/PDFPageLabels.java b/src/java/org/apache/fop/pdf/PDFPageLabels.java index e95c97a25..e7b90ec4e 100644 --- a/src/java/org/apache/fop/pdf/PDFPageLabels.java +++ b/src/java/org/apache/fop/pdf/PDFPageLabels.java @@ -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) diff --git a/src/java/org/apache/fop/pdf/PDFParentTree.java b/src/java/org/apache/fop/pdf/PDFParentTree.java index 7876bbc0c..e03545568 100644 --- a/src/java/org/apache/fop/pdf/PDFParentTree.java +++ b/src/java/org/apache/fop/pdf/PDFParentTree.java @@ -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); } } diff --git a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java index ee00d2401..c532a05a4 100644 --- a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java +++ b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java @@ -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); } diff --git a/status.xml b/status.xml index 990a15f5e..9362983b2 100644 --- a/status.xml +++ b/status.xml @@ -59,6 +59,11 @@ documents. Example: the fix of marks layering will be such a case when it's done. --> + + 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. + 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 index 000000000..6fa5d6a42 --- /dev/null +++ b/test/java/org/apache/fop/pdf/PDFParentTreeTestCase.java @@ -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(); + } +} diff --git a/test/pdf/1.5/test.pdf b/test/pdf/1.5/test.pdf index d97648e1e..e937afd58 100644 Binary files a/test/pdf/1.5/test.pdf and b/test/pdf/1.5/test.pdf differ diff --git a/test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf b/test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf index 65f04cdef..4c2fe4687 100644 Binary files a/test/pdf/accessibility/pdf/background-image_jpg_repeat.pdf 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 index 6803ba999..74b17c337 100644 Binary files a/test/pdf/accessibility/pdf/background-image_jpg_single.pdf 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 index d42d935aa..f69e373bc 100644 Binary files a/test/pdf/accessibility/pdf/background-image_png_repeat.pdf 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 index ba39a2b31..cdba6192e 100644 Binary files a/test/pdf/accessibility/pdf/background-image_png_single.pdf 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 index 1de4c98a1..ed74244b3 100644 Binary files a/test/pdf/accessibility/pdf/background-image_svg_repeat.pdf 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 index b89ea182a..d2245e349 100644 Binary files a/test/pdf/accessibility/pdf/background-image_svg_single.pdf 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 index 9b4df8c40..844106f23 100644 Binary files a/test/pdf/accessibility/pdf/complete.pdf and b/test/pdf/accessibility/pdf/complete.pdf differ diff --git a/test/pdf/accessibility/pdf/hyphenation.pdf b/test/pdf/accessibility/pdf/hyphenation.pdf index d8552f63a..401fbf356 100644 Binary files a/test/pdf/accessibility/pdf/hyphenation.pdf and b/test/pdf/accessibility/pdf/hyphenation.pdf differ diff --git a/test/pdf/accessibility/pdf/image_jpg.pdf b/test/pdf/accessibility/pdf/image_jpg.pdf index e35768d8a..76f5509c8 100644 Binary files a/test/pdf/accessibility/pdf/image_jpg.pdf 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 index a33d2ed3f..0a5641aaa 100644 Binary files a/test/pdf/accessibility/pdf/image_png.pdf 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 index 1184ddef9..eaf6d56c4 100644 Binary files a/test/pdf/accessibility/pdf/image_svg.pdf 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 index 43c15d9ea..819f385a6 100644 Binary files a/test/pdf/accessibility/pdf/image_wmf.pdf and b/test/pdf/accessibility/pdf/image_wmf.pdf differ diff --git a/test/pdf/accessibility/pdf/language.pdf b/test/pdf/accessibility/pdf/language.pdf index 48a5f9f52..e32f4f7e9 100644 Binary files a/test/pdf/accessibility/pdf/language.pdf and b/test/pdf/accessibility/pdf/language.pdf differ diff --git a/test/pdf/accessibility/pdf/leader.pdf b/test/pdf/accessibility/pdf/leader.pdf index e277699e5..869a47d76 100644 Binary files a/test/pdf/accessibility/pdf/leader.pdf 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 index 896620bfb..5c63a2574 100644 Binary files a/test/pdf/accessibility/pdf/links.pdf 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 index 6e26032ff..a91e8b983 100644 Binary files a/test/pdf/accessibility/pdf/role.pdf 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 index edf7541df..c7a55233c 100644 Binary files a/test/pdf/accessibility/pdf/role_non-standard.pdf and b/test/pdf/accessibility/pdf/role_non-standard.pdf differ diff --git a/test/pdf/accessibility/pdf/side-regions.pdf b/test/pdf/accessibility/pdf/side-regions.pdf index 22364c2c8..650e962b3 100644 Binary files a/test/pdf/accessibility/pdf/side-regions.pdf and b/test/pdf/accessibility/pdf/side-regions.pdf differ diff --git a/test/pdf/accessibility/pdf/table_row-col-span.pdf b/test/pdf/accessibility/pdf/table_row-col-span.pdf index eec14fa3d..9a05c1892 100644 Binary files a/test/pdf/accessibility/pdf/table_row-col-span.pdf and b/test/pdf/accessibility/pdf/table_row-col-span.pdf differ diff --git a/test/pdf/accessibility/pdf/text_1.pdf b/test/pdf/accessibility/pdf/text_1.pdf index f3daa44b0..71b32f80c 100644 Binary files a/test/pdf/accessibility/pdf/text_1.pdf 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 index 5a2abcf2f..ac1662659 100644 Binary files a/test/pdf/accessibility/pdf/text_2.pdf 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 index e7f75b5a3..d724af9e9 100644 Binary files a/test/pdf/accessibility/pdf/text_font-embedding.pdf and b/test/pdf/accessibility/pdf/text_font-embedding.pdf differ diff --git a/test/pdf/accessibility/pdf/th_scope.pdf b/test/pdf/accessibility/pdf/th_scope.pdf index 9d19548d7..68a98987b 100644 Binary files a/test/pdf/accessibility/pdf/th_scope.pdf and b/test/pdf/accessibility/pdf/th_scope.pdf differ