pdf-lib
Version:
Library for creating and modifying PDF files in JavaScript
94 lines (93 loc) • 4.26 kB
JavaScript
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];
});
;