You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2017/10/21 17:08:34 UTC

svn commit: r1812834 - in /pdfbox/branches/2.0/pdfbox/src: main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java

Author: tilman
Date: Sat Oct 21 17:08:34 2017
New Revision: 1812834

URL: http://svn.apache.org/viewvc?rev=1812834&view=rev
Log:
PDFBOX-3972: keep local destination page index to update page reference after cloning; add test

Modified:
    pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java
    pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java

Modified: pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java?rev=1812834&r1=1812833&r2=1812834&view=diff
==============================================================================
--- pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java (original)
+++ pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java Sat Oct 21 17:08:34 2017
@@ -48,13 +48,17 @@ import org.apache.pdfbox.pdmodel.PDDocum
 import org.apache.pdfbox.pdmodel.PDPage;
 import org.apache.pdfbox.pdmodel.PDResources;
 import org.apache.pdfbox.pdmodel.PageMode;
+import org.apache.pdfbox.pdmodel.common.PDDestinationOrAction;
 import org.apache.pdfbox.pdmodel.common.PDMetadata;
 import org.apache.pdfbox.pdmodel.common.PDNumberTreeNode;
 import org.apache.pdfbox.pdmodel.common.PDStream;
 import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDMarkInfo;
 import org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDStructureTreeRoot;
 import org.apache.pdfbox.pdmodel.graphics.color.PDOutputIntent;
+import org.apache.pdfbox.pdmodel.interactive.action.PDActionGoTo;
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation;
+import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDDestination;
+import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageDestination;
 import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
 import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
 import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
@@ -340,8 +344,29 @@ public class PDFMergerUtility
             destination.setVersion(srcVersion);
         }
 
+        int pageIndexOpenActionDest = -1;
         if (destCatalog.getOpenAction() == null)
         {
+            // PDFBOX-3972: get local dest page index, it must be reassigned after the page cloning
+            PDDestinationOrAction openAction = srcCatalog.getOpenAction();
+            PDDestination openActionDestination;
+            if (openAction instanceof PDActionGoTo)
+            {
+                openActionDestination = ((PDActionGoTo) openAction).getDestination();
+            }
+            else
+            {
+                openActionDestination = (PDDestination) openAction;
+            }
+            if (openActionDestination instanceof PDPageDestination)
+            {
+                PDPage page = ((PDPageDestination) openActionDestination).getPage();
+                if (page != null)
+                {
+                    pageIndexOpenActionDest = srcCatalog.getPages().indexOf(page);
+                }
+            }
+
             destCatalog.setOpenAction(srcCatalog.getOpenAction());
         }
 
@@ -556,6 +581,7 @@ public class PDFMergerUtility
         }
 
         Map<COSDictionary, COSDictionary> objMapping = new HashMap<COSDictionary, COSDictionary>();
+        int pageIndex = 0;
         for (PDPage page : srcCatalog.getPages())
         {
             PDPage newPage = new PDPage((COSDictionary) cloner.cloneForNewDocument(page.getCOSObject()));
@@ -585,6 +611,24 @@ public class PDFMergerUtility
                 // TODO update mapping for XObjects
             }
             destination.addPage(newPage);
+
+            if (pageIndex == pageIndexOpenActionDest)
+            {
+                // PDFBOX-3972: reassign the page.
+                // The openAction is either a PDActionGoTo or a PDPageDestination
+                PDDestinationOrAction openAction = destCatalog.getOpenAction();
+                PDPageDestination pageDestination;
+                if (destCatalog.getOpenAction() instanceof PDActionGoTo)
+                {
+                    pageDestination = (PDPageDestination) ((PDActionGoTo) openAction).getDestination();
+                }
+                else
+                {
+                    pageDestination = (PDPageDestination) openAction;
+                }
+                pageDestination.setPage(newPage);
+            }
+            ++pageIndex;
         }
         if (mergeStructTree)
         {

Modified: pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java
URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java?rev=1812834&r1=1812833&r2=1812834&view=diff
==============================================================================
--- pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java (original)
+++ pdfbox/branches/2.0/pdfbox/src/test/java/org/apache/pdfbox/multipdf/PDFMergerUtilityTest.java Sat Oct 21 17:08:34 2017
@@ -23,6 +23,10 @@ import junit.framework.TestCase;
 
 import org.apache.pdfbox.io.MemoryUsageSetting;
 import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageDestination;
+import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageFitDestination;
 import org.apache.pdfbox.rendering.PDFRenderer;
 
 /**
@@ -111,6 +115,43 @@ public class PDFMergerUtilityTest extend
                 MemoryUsageSetting.setupTempFileOnly());
     }
 
+    /**
+     * PDFBOX-3972: Test that OpenAction page destination isn't lost after merge.
+     * 
+     * @throws IOException 
+     */
+    public void testPDFMergerOpenAction() throws IOException
+    {
+        PDDocument doc1 = new PDDocument();
+        doc1.addPage(new PDPage());
+        doc1.addPage(new PDPage());
+        doc1.addPage(new PDPage());
+        doc1.save(new File(TARGETTESTDIR,"MergerOpenActionTest1.pdf"));
+        doc1.close();
+
+        PDDocument doc2 = new PDDocument();
+        doc2.addPage(new PDPage());
+        doc2.addPage(new PDPage());
+        doc2.addPage(new PDPage());
+        PDPageDestination dest = new PDPageFitDestination();
+        dest.setPage(doc2.getPage(1));
+        doc2.getDocumentCatalog().setOpenAction(dest);
+        doc2.save(new File(TARGETTESTDIR,"MergerOpenActionTest2.pdf"));
+        doc2.close();
+
+        PDFMergerUtility pdfMergerUtility = new PDFMergerUtility();
+        pdfMergerUtility.addSource(new File(TARGETTESTDIR, "MergerOpenActionTest1.pdf"));
+        pdfMergerUtility.addSource(new File(TARGETTESTDIR, "MergerOpenActionTest2.pdf"));
+        pdfMergerUtility.setDestinationFileName(TARGETTESTDIR + "MergerOpenActionTestResult.pdf");
+        pdfMergerUtility.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
+
+        PDDocument mergedDoc = PDDocument.load(new File(TARGETTESTDIR, "MergerOpenActionTestResult.pdf"));
+        PDDocumentCatalog documentCatalog = mergedDoc.getDocumentCatalog();
+        dest = (PDPageDestination) documentCatalog.getOpenAction();
+        assertEquals(4, documentCatalog.getPages().indexOf(dest.getPage()));
+        mergedDoc.close();
+    }
+
     // checks that the result file of a merge has the same rendering as the two
     // source files
     private void checkMergeIdentical(String filename1, String filename2, String mergeFilename,