pdf-lib
Version:
Library for creating and modifying PDF files in JavaScript
88 lines (87 loc) • 4.33 kB
JavaScript
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;