private static void CloneParents(PdfDictionary structElem, StructureTreeCopier.LastClonedAncestor lastCloned , PdfDocument document) { if (lastCloned.ancestor != structElem) { PdfDictionary structElemClone = (PdfDictionary)structElem.Clone(ignoreKeysForClone).MakeIndirect(document); PdfDictionary currClone = structElemClone; PdfDictionary currElem = structElem; while (currElem.Get(PdfName.P) != lastCloned.ancestor) { PdfDictionary parent = currElem.GetAsDictionary(PdfName.P); PdfDictionary parentClone = (PdfDictionary)parent.Clone(ignoreKeysForClone).MakeIndirect(document); currClone.Put(PdfName.P, parentClone); parentClone.Put(PdfName.K, currClone); currClone = parentClone; currElem = parent; } PdfStructElem.AddKidObject(lastCloned.clone, -1, currClone); lastCloned.clone = structElemClone; lastCloned.ancestor = structElem; } }
private static void SeparateKids(PdfDictionary structElem, ICollection <PdfObject> firstPartElems, StructureTreeCopier.LastClonedAncestor lastCloned) { PdfObject k = structElem.Get(PdfName.K); // If /K entry is not a PdfArray - it would be a kid which we won't clone at the moment, because it won't contain // kids from both parts at the same time. It would either be cloned as an ancestor later, or not cloned at all. // If it's kid is struct elem - it would definitely be structElem from the first part, so we simply call separateKids for it. if (!k.IsArray()) { if (k.IsDictionary() && PdfStructElem.IsStructElem((PdfDictionary)k)) { SeparateKids((PdfDictionary)k, firstPartElems, lastCloned); } } else { PdfDocument document = structElem.GetIndirectReference().GetDocument(); PdfArray kids = (PdfArray)k; for (int i = 0; i < kids.Size(); ++i) { PdfObject kid = kids.Get(i); PdfDictionary dictKid = null; if (kid.IsDictionary()) { dictKid = (PdfDictionary)kid; } if (dictKid != null && PdfStructElem.IsStructElem(dictKid)) { if (firstPartElems.Contains(kid)) { SeparateKids((PdfDictionary)kid, firstPartElems, lastCloned); } else { if (dictKid.IsFlushed()) { throw new PdfException(PdfException.TagFromTheExistingTagStructureIsFlushedCannotAddCopiedPageTags); } // elems with no kids will not be marked as from the first part, // but nonetheless we don't want to move all of them to the second part; we just leave them as is if (dictKid.ContainsKey(PdfName.K)) { CloneParents(structElem, lastCloned, document); kids.Remove(i--); PdfStructElem.AddKidObject(lastCloned.clone, -1, kid); } } } else { if (!firstPartElems.Contains(kid)) { CloneParents(structElem, lastCloned, document); PdfMcr mcr; if (dictKid != null) { if (dictKid.Get(PdfName.Type).Equals(PdfName.MCR)) { mcr = new PdfMcrDictionary(dictKid, new PdfStructElem(lastCloned.clone)); } else { mcr = new PdfObjRef(dictKid, new PdfStructElem(lastCloned.clone)); } } else { mcr = new PdfMcrNumber((PdfNumber)kid, new PdfStructElem(lastCloned.clone)); } kids.Remove(i--); PdfStructElem.AddKidObject(lastCloned.clone, -1, kid); document.GetStructTreeRoot().GetParentTreeHandler().RegisterMcr(mcr); } } } } // re-register mcr if (lastCloned.ancestor == structElem) { lastCloned.ancestor = lastCloned.ancestor.GetAsDictionary(PdfName.P); lastCloned.clone = lastCloned.clone.GetAsDictionary(PdfName.P); } }