这是我的第一次尝试。我没有 PAC 工具(或者我找不到它),所以我需要知道出了什么问题(如果有)。我已将注释放在数组的末尾
Root/StructTreeRoot/K/[0]/K/[0]/K/[0]/K
,在另一个文件中,它是数组中的第一项。 (COSArray 显然没有“插入”)
PDStructureTreeRoot structureTreeRoot = doc.getDocumentCatalog().getStructureTreeRoot();
PDPage page = doc.getPage(0);
PDAnnotation annotation = page.getAnnotations().get(0);
COSArray aDocument = (COSArray) structureTreeRoot.getK();
COSDictionary oDocument = (COSDictionary) aDocument.getObject(0);
COSArray aPart = oDocument.getCOSArray(COSName.K);
COSDictionary oPart = (COSDictionary) aPart.getObject(0);
COSArray aSect = oPart.getCOSArray(COSName.K);
COSDictionary oSect = (COSDictionary) aSect.getObject(0);
COSArray aP = oSect.getCOSArray(COSName.K);
COSDictionary anDict = new COSDictionary(); // PDStructureElement
anDict.setItem(COSName.S, COSName.ANNOT);
anDict.setItem(COSName.P, aSect.get(0)); // assign aP but as ref
PDObjectReference objRef = new PDObjectReference();
anDict.setItem(COSName.K, objRef);
objRef.setReferencedObject(page.getAnnotations().get(0));
objRef.getCOSObject().setItem(COSName.P, anDict); //TODO check if needed in PDObjectReference API?
objRef.getCOSObject().setItem(COSName.PG, page); //TODO check if needed in PDObjectReference API?
aP.add(anDict);
int parentTreeNextKey = structureTreeRoot.getParentTreeNextKey(); // -1, ignored here
PDNumberTreeNode parentTree = structureTreeRoot.getParentTree();
Map<Integer, COSObjectable> numberTreeAsMap = getNumberTreeAsMap(parentTree);
Set<Integer> keySet = numberTreeAsMap.keySet();
int maximum = keySet.stream().reduce(Integer::max).get();
annotation.setStructParent(maximum + 1);
structureTreeRoot.setParentTreeNextKey(maximum + 2);
numberTreeAsMap.put(maximum + 1, anDict);
parentTree = new PDNumberTreeNode(PDParentTreeValue.class);
parentTree.setNumbers(numberTreeAsMap);
structureTreeRoot.setParentTree(parentTree);
getNumberTreeAsMap 是 PDFMergerUtility 中的一个便捷方法
static Map<Integer, COSObjectable> getNumberTreeAsMap(PDNumberTreeNode tree)
throws IOException
{
if (tree == null)
{
return new LinkedHashMap<>();
}
Map<Integer, COSObjectable> numbers = tree.getNumbers();
if (numbers == null)
{
numbers = new LinkedHashMap<>();
}
else
{
// must copy because the map is read only
numbers = new LinkedHashMap<>(numbers);
}
List<PDNumberTreeNode> kids = tree.getKids();
if (kids != null)
{
for (PDNumberTreeNode kid : kids)
{
numbers.putAll(getNumberTreeAsMap(kid));
}
}
return numbers;
}