duplicate method
Duplicates the page at index, inserting the copy at at — by default
right after the original.
The copy is shallow, on purpose. The new page references the same
content objects, the same /Resources, the same fonts and the same
XObjects as the original: there is no renumbering and no stream copy, and
duplicating a 4 MB page costs one dictionary. That is correct because
nothing in this library rewrites an existing content stream in place; once
that exists, duplicating will need a real deep copy.
To bring in a page from another document there is insertImported,
which reuses the deep import of PdfDocumentMerger. It would be of no use
here: source and target are the same document, and the object numbers
already hold.
The annotations are not copied: an annotation belongs to a single page
through /P, and sharing it between two would produce exactly the
inconsistency this phase exists to avoid. The loss becomes a warning in
warnings.
Implementation
PdfPage duplicate(int index, {int? at}) {
_checkIndex(index);
final source = _pages[index];
final target = at ?? index + 1;
_checkInsertIndex(target, 'at');
final before = List<PdfPage>.of(_pages);
// The constructor registers the page at the requested position; inserting
// it again afterwards would make it show up twice in `/Kids`.
final copy = PdfPage(
document,
pageFormat: source.pageFormat,
rotate: source.rotate,
index: target,
);
final box = source.mediaBoxOverride;
if (box != null) copy.mediaBoxOverride = List<double>.of(box);
for (final entry in source.params.values.entries) {
if (_notCopiedOnDuplicate.contains(entry.key)) continue;
copy.params[entry.key] = _copyValue(entry.value);
}
// The resources of a page created in this session only enter `/Resources`
// in prepare(); they have to be copied in the model, not in the dictionary.
copy.fonts.addAll(source.fonts);
copy.shading.addAll(source.shading);
copy.patterns.addAll(source.patterns);
copy.xObjects.addAll(source.xObjects);
copy.isolatedTransparency = source.isolatedTransparency;
copy.knockoutTransparency = source.knockoutTransparency;
final contents = _contentReferencesOf(source);
if (contents.isNotEmpty) {
copy.altered = true;
final list = PdfArray<PdfDataType>(contents);
list.uniq();
copy.params[PdfNameTokens.contents] =
list.values.length == 1 ? list.values.first : list;
}
if (source.params.containsKey(PdfNameTokens.annots) ||
source.annotations.isNotEmpty) {
_warn('a cópia da página ${index + 1} não leva as anotações do original: '
'uma anotação pertence a uma única página pelo /P');
}
_afterMutation(before);
return copy;
}