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 2021/05/28 15:58:57 UTC
svn commit: r1890293 -
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java
Author: tilman
Date: Fri May 28 15:58:57 2021
New Revision: 1890293
URL: http://svn.apache.org/viewvc?rev=1890293&view=rev
Log:
PDFBOX-5198: merge the K entries so that "Document" gets grouped as "Part" below a single "Document" to align with Adobe
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java?rev=1890293&r1=1890292&r2=1890293&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/multipdf/PDFMergerUtility.java Fri May 28 15:58:57 2021
@@ -956,40 +956,120 @@ public class PDFMergerUtility
PDStructureTreeRoot srcStructTree,
PDStructureTreeRoot destStructTree) throws IOException
{
- // make new /K with array that has the input /K entries
- COSArray newKArray = new COSArray();
+ COSArray dstKArray = new COSArray();
if (destStructTree.getK() != null)
{
COSBase base = destStructTree.getK();
if (base instanceof COSArray)
{
- newKArray.addAll((COSArray) base);
+ dstKArray.addAll((COSArray) base);
}
- else
+ else if (base instanceof COSDictionary)
{
- newKArray.add(base);
+ dstKArray.add(base);
}
}
+
+ COSArray srcKArray = new COSArray();
if (srcStructTree.getK() != null)
{
COSBase base = cloner.cloneForNewDocument(srcStructTree.getK());
if (base instanceof COSArray)
{
- newKArray.addAll((COSArray) base);
+ srcKArray.addAll((COSArray) base);
}
- else
+ else if (base instanceof COSDictionary)
{
- newKArray.add(base);
+ srcKArray.add(base);
}
}
- if (newKArray.size() > 0)
+
+ if (srcKArray.size() == 0)
+ {
+ return;
+ }
+
+ if (dstKArray.size() == 1 && dstKArray.getObject(0) instanceof COSDictionary)
+ {
+ // Only one element in the destination. If it is a /Document and its children
+ // are /Document or /Part, then we can insert there
+ COSDictionary topKDict = (COSDictionary) dstKArray.getObject(0);
+ if (COSName.DOCUMENT.equals(topKDict.getCOSName(COSName.S)))
+ {
+ COSArray kLevelOneArray = topKDict.getCOSArray(COSName.K);
+ if (kLevelOneArray != null)
+ {
+ boolean onlyDocuments = hasOnlyDocumentsOrParts(kLevelOneArray);
+ if (onlyDocuments)
+ {
+ // insert src elements at level 1
+ kLevelOneArray.addAll(srcKArray);
+ updateParentEntry(kLevelOneArray, topKDict, COSName.PART);
+ return;
+ }
+ }
+ }
+ }
+
+ if (dstKArray.size() == 0)
+ {
+ updateParentEntry(srcKArray, destStructTree.getCOSObject(), null);
+ destStructTree.setK(srcKArray);
+ return;
+ }
+
+ // whatever this is, merge this under a new /Document element
+ dstKArray.addAll(srcKArray);
+ COSDictionary kLevelZeroDict = new COSDictionary();
+ // If it is all Document, then make it all Part
+ COSName newStructureType = hasOnlyDocumentsOrParts(dstKArray) ? COSName.PART : null;
+ updateParentEntry(dstKArray, kLevelZeroDict, newStructureType);
+ kLevelZeroDict.setItem(COSName.K, dstKArray);
+ kLevelZeroDict.setItem(COSName.P, destStructTree);
+ kLevelZeroDict.setItem(COSName.S, COSName.DOCUMENT);
+ destStructTree.setK(kLevelZeroDict);
+ }
+
+ private boolean hasOnlyDocumentsOrParts(COSArray kLevelOneArray)
+ {
+ for (int i = 0; i < kLevelOneArray.size(); ++i)
+ {
+ COSBase base = kLevelOneArray.getObject(i);
+ if (!(base instanceof COSDictionary))
+ {
+ return false;
+ }
+ COSDictionary dict = (COSDictionary) base;
+ if (!COSName.DOCUMENT.equals(dict.getCOSName(COSName.S)) &&
+ !COSName.PART.equals(dict.getCOSName(COSName.S)))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Update the P reference to the new parent dictionary.
+ *
+ * @param kArray the kids array
+ * @param newParent the new parent
+ * @param newStructureType the new structure type in /S or null so it doesn't get replaced
+ */
+ private void updateParentEntry(COSArray kArray, COSDictionary newParent, COSName newStructureType)
+ {
+ for (int i = 0; i < kArray.size(); i++)
{
- COSDictionary kDictLevel0 = new COSDictionary();
- updateParentEntry(newKArray, kDictLevel0);
- kDictLevel0.setItem(COSName.K, newKArray);
- kDictLevel0.setItem(COSName.P, destStructTree);
- kDictLevel0.setItem(COSName.S, COSName.DOCUMENT);
- destStructTree.setK(kDictLevel0);
+ COSBase subEntry = kArray.getObject(i);
+ if (subEntry instanceof COSDictionary)
+ {
+ COSDictionary dictEntry = (COSDictionary) subEntry;
+ dictEntry.setItem(COSName.P, newParent);
+ if (newStructureType != null)
+ {
+ dictEntry.setItem(COSName.S, newStructureType);
+ }
+ }
}
}
@@ -1383,28 +1463,6 @@ public class PDFMergerUtility
}
}
}
-
- /**
- * Update the P reference to the new parent dictionary.
- *
- * @param kArray the kids array
- * @param newParent the new parent
- */
- private void updateParentEntry(COSArray kArray, COSDictionary newParent)
- {
- for (int i = 0; i < kArray.size(); i++)
- {
- COSBase subEntry = kArray.getObject(i);
- if (subEntry instanceof COSDictionary)
- {
- COSDictionary dictEntry = (COSDictionary) subEntry;
- if (dictEntry.getDictionaryObject(COSName.P) != null)
- {
- dictEntry.setItem(COSName.P, newParent);
- }
- }
- }
- }
/**
* Update the StructParents and StructParent values in a PDPage.