UNPKG

pdf-lib

Version:

Library for creating and modifying PDF files in JavaScript

88 lines (87 loc) 4.33 kB
import PDFDocument from '../pdf-document/PDFDocument'; import PDFObjectIndex from '../pdf-document/PDFObjectIndex'; import { PDFArray, PDFDictionary, PDFIndirectReference, PDFName, PDFStream, } from '../pdf-objects'; import QOps from '../pdf-operators/graphics/graphics-state/QOps'; import PDFParser from '../pdf-parser/PDFParser'; import { PDFCatalog, PDFContentStream, PDFObjectStream, PDFPageTree, } from '../pdf-structures'; import { isInstance, validate } from '../../utils/validate'; var PDFDocumentFactory = /** @class */ (function () { function PDFDocumentFactory() { } /** * Creates a new [[PDFDocument]] object. Useful for creating new PDF documents. * * @returns The new [[PDFDocument]] object. */ PDFDocumentFactory.create = function () { var index = PDFObjectIndex.create(); var refs = { catalog: PDFIndirectReference.forNumbers(1, 0), pageTree: PDFIndirectReference.forNumbers(2, 0), }; var catalog = PDFCatalog.create(refs.pageTree, index); var pageTree = PDFPageTree.createRootNode(PDFArray.fromArray([], index), index); index.assign(refs.catalog, catalog); index.assign(refs.pageTree, pageTree); return PDFDocument.from(catalog, index); }; /** * Loads an existing PDF document contained from the specified `Uint8Array` * into a [[PDFDocument]] object. Useful for modifying existing PDF documents. * * @param data A `Uint8Array` containing the raw bytes of a PDF document. * * @returns A [[PDFDocument]] object initialized from the provided document. */ PDFDocumentFactory.load = function (data) { validate(data, isInstance(Uint8Array), '"PDFDocumentFactory.load()" must be called with an argument of type Uint8Array.'); var index = PDFObjectIndex.create(); var pdfParser = new PDFParser(); var parsedPdf = pdfParser.parse(data, index); var indexMap = PDFDocumentFactory.normalize(parsedPdf); index.index = indexMap; var pushGraphicsStateContentStream = PDFContentStream.of(PDFDictionary.from({}, index), QOps.q.operator); var popGraphicsStateContentStream = PDFContentStream.of(PDFDictionary.from({}, index), QOps.Q.operator); var maxObjectNumber = parsedPdf.maxObjectNumber; var ref1 = PDFIndirectReference.forNumbers(maxObjectNumber + 1, 0); var ref2 = PDFIndirectReference.forNumbers(maxObjectNumber + 2, 0); index.assign(ref1, pushGraphicsStateContentStream); index.assign(ref2, popGraphicsStateContentStream); index.pushGraphicsStateContentStream = ref1; index.popGraphicsStateContentStream = ref2; return PDFDocument.from(parsedPdf.catalog, index); }; // TODO: Need to throw out objects with "free" obj numbers... /** @hidden */ PDFDocumentFactory.normalize = function (_a) { var dictionaries = _a.dictionaries, arrays = _a.arrays, body = _a.original.body, updates = _a.updates; var index = new Map(); // Remove Object Streams and Cross Reference Streams, because we've already // parsed the Object Streams into PDFIndirectObjects, and will just write // them as such and use normal xref tables to reference them. var shouldKeep = function (object) { return !(object instanceof PDFObjectStream) && !(object instanceof PDFStream && object.dictionary.getMaybe('Type') === PDFName.from('XRef')); }; // Initialize index with objects in the original body body.forEach(function (_a, ref) { var pdfObject = _a.pdfObject; if (shouldKeep(pdfObject)) index.set(ref, pdfObject); }); // Update index with most recent version of each object // TODO: This could be omitted to recover a previous version of the document... updates.forEach(function (_a) { var updateBody = _a.body; updateBody.forEach(function (_a, ref) { var pdfObject = _a.pdfObject; if (shouldKeep(pdfObject)) index.set(ref, pdfObject); }); }); return index; }; return PDFDocumentFactory; }()); export default PDFDocumentFactory;