UNPKG

pdf-lib

Version:

Library for creating and modifying PDF files in JavaScript

94 lines (93 loc) 4.26 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; } Object.defineProperty(exports, "__esModule", { value: true }); var pdf_objects_1 = require("../pdf-objects"); var utils_1 = require("../../utils"); var decodeStream_1 = __importDefault(require("./encoding/decodeStream")); var parseObjectStream_1 = __importDefault(require("./parseObjectStream")); /** * Accepts an array of bytes and a PDFDictionary as input. Checks to see if the * first characters in the trimmed input make up a PDF Stream. * * If so, the content of the stream is extracted into a subarray. A tuple * containing this content subarray and a subarray of the input with the bytes making * up the entire stream removed is returned. * * If not, null is returned. */ var parseStream = function (input, dict, parseHandlers) { if (parseHandlers === void 0) { parseHandlers = {}; } // Check that the next bytes comprise the beginning of a stream var trimmed = utils_1.trimArrayAndRemoveComments(input); var startstreamIdx; if (utils_1.arrayToString(trimmed, 0, 7) === 'stream\n') startstreamIdx = 7; else if (utils_1.arrayToString(trimmed, 0, 8) === 'stream\r\n') startstreamIdx = 8; if (!startstreamIdx) return undefined; /* TODO: Make this more efficient by using the "Length" entry of the stream dictionary to jump to the end of the stream, instead of traversing each byte. */ // Locate the end of the stream var endstreamMatchTuple = utils_1.arrayIndexOneOf(trimmed, [ '\nendstream', '\rendstream', 'endstream', ]); if (!endstreamMatchTuple) utils_1.error('Invalid Stream!'); var _a = endstreamMatchTuple, endstreamIdx = _a[0], endstreamMatch = _a[1]; /* TODO: See if it makes sense to .slice() the stream contents, even though this would require more memory space. */ // Extract the stream content bytes var contents = trimmed.subarray(startstreamIdx, endstreamIdx); // Verify that the next characters denote the end of the stream var endobjIdx = utils_1.arrayIndexOf(trimmed, 'endobj', endstreamIdx); if (utils_1.arrayToString(trimmed, endstreamIdx, endobjIdx).trim() !== 'endstream') { utils_1.error('Invalid Stream!'); } return [contents, trimmed.subarray(endstreamIdx + endstreamMatch.length)]; }; /** * Accepts an array of bytes and a PDFDictionary as input. Checks to see if the * first characters in the trimmed input make up a PDF Stream. * * If so, returns a tuple containing (1) a PDFObjectStream if it is an * Object Stream, otherwise a PDFStream and (2) a subarray of the input wih the * characters making up the parsed stream removed. The "onParseObjectStream" will * be called with the PDFObjectStream if it is an Object Stream. Otherwise * the "onParseStream" parse hander will be called. * * If not, null is returned. */ exports.default = (function (input, dict, index, parseHandlers) { if (parseHandlers === void 0) { parseHandlers = {}; } // Parse the input bytes into the stream dictionary and content bytes var res = parseStream(input, dict, parseHandlers); if (!res) return undefined; var contents = res[0], remaining = res[1]; // If it's an Object Stream, parse it and return the indirect objects it contains if (dict.getMaybe('Type') === pdf_objects_1.PDFName.from('ObjStm')) { if (dict.getMaybe('Filter') !== pdf_objects_1.PDFName.from('FlateDecode')) { utils_1.error("Cannot decode \"" + dict.get('Filter') + "\" Object Streams"); } var decoded = decodeStream_1.default(dict, contents); var objectStream = parseObjectStream_1.default(dict, decoded, index, parseHandlers); if (parseHandlers.onParseObjectStream) { parseHandlers.onParseObjectStream(objectStream); } return [objectStream, remaining]; } // Otherwise, return a PDFStream without parsing the content bytes var stream = pdf_objects_1.PDFRawStream.from(dict, contents); if (parseHandlers.onParseStream) parseHandlers.onParseStream(stream); return [stream, remaining]; });