UNPKG

pdf-lib

Version:

Library for creating and modifying PDF files in JavaScript

106 lines (105 loc) 4.95 kB
import { PDFArray, PDFDictionary, PDFIndirectReference, PDFStream, } from '../pdf-objects'; import { PDFPage } from '../pdf-structures'; /** * PDFObjectCopier copies PDFObjects from a src index to a dest index. * The primary use case for this is to copy pages between PDFs. * * _Copying_ an object with a PDFObjectCopier is different from _cloning_ an * object with its [[PDFObject.clone]] method: * * ``` * const origObject = ... * const copiedObject = PDFObjectCopier.for(srcIndex, destIndex).copy(origObject); * const clonedObject = originalObject.clone(); * ``` * * Copying an object is equivalent to cloning it and then copying over any other * objects that it references. Note that only dictionaries, arrays, and streams * (or structures build from them) can contain indirect references to other * objects. Copying a PDFObject that is not a dictionary, array, or stream is * supported, but is equivalent to cloning it. */ var PDFObjectCopier = /** @class */ (function () { function PDFObjectCopier(srcIndex, destIndex) { var _this = this; this.traversedObjects = new Map(); // prettier-ignore this.copy = function (object) { return (object instanceof PDFPage ? _this.copyPDFPage(object) : object instanceof PDFDictionary ? _this.copyPDFDict(object) : object instanceof PDFArray ? _this.copyPDFArray(object) : object instanceof PDFStream ? _this.copyPDFStream(object) : object instanceof PDFIndirectReference ? _this.copyPDFIndirectObject(object) : object.clone()); }; this.copyPDFPage = function (originalPage) { var clonedPage = originalPage.clone(); // Move any entries that the originalPage is inheriting from its parent // tree nodes directly into originalPage so they are preserved during // the copy. clonedPage.Parent.ascend(function (parentNode) { PDFPage.INHERITABLE_ENTRIES.forEach(function (key) { if (!clonedPage.getMaybe(key) && parentNode.getMaybe(key)) { clonedPage.set(key, parentNode.get(key)); } }); }, true); // Remove the parent reference to prevent the whole donor document's page // tree from being copied when we only need a single page. clonedPage.delete('Parent'); return _this.copyPDFDict(clonedPage); }; this.copyPDFDict = function (originalDict) { if (_this.traversedObjects.has(originalDict)) { return _this.traversedObjects.get(originalDict); } var clonedDict = originalDict.clone(); clonedDict.index = _this.dest; _this.traversedObjects.set(originalDict, clonedDict); originalDict.map.forEach(function (value, key) { clonedDict.set(key, _this.copy(value)); }); return clonedDict; }; this.copyPDFArray = function (originalArray) { if (_this.traversedObjects.has(originalArray)) { return _this.traversedObjects.get(originalArray); } var clonedArray = originalArray.clone(); clonedArray.index = _this.dest; _this.traversedObjects.set(originalArray, clonedArray); originalArray.forEach(function (value, idx) { clonedArray.set(idx, _this.copy(value)); }); return clonedArray; }; this.copyPDFStream = function (originalStream) { if (_this.traversedObjects.has(originalStream)) { return _this.traversedObjects.get(originalStream); } var clonedStream = originalStream.clone(); clonedStream.dictionary.index = _this.dest; _this.traversedObjects.set(originalStream, clonedStream); originalStream.dictionary.map.forEach(function (value, key) { clonedStream.dictionary.set(key, _this.copy(value)); }); return clonedStream; }; this.copyPDFIndirectObject = function (ref) { var alreadyMapped = _this.traversedObjects.has(ref); if (!alreadyMapped) { var newRef = _this.dest.nextObjectNumber(); _this.traversedObjects.set(ref, newRef); var dereferencedValue = _this.src.lookup(ref); var cloned = _this.copy(dereferencedValue); _this.dest.assign(newRef, cloned); } return _this.traversedObjects.get(ref); }; this.src = srcIndex; this.dest = destIndex; } PDFObjectCopier.for = function (srcIndex, destIndex) { return new PDFObjectCopier(srcIndex, destIndex); }; return PDFObjectCopier; }()); export default PDFObjectCopier;