UNPKG

pdfjs-dist

Version:

Generic build of Mozilla's PDF.js library.

1,286 lines (1,244 loc) • 102 kB
/** * @licstart The following is the entire license notice for the * Javascript code in this page * * Copyright 2017 Mozilla Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * @licend The above is the entire license notice for the * Javascript code in this page */ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.PartialEvaluator = undefined; var _util = require('../shared/util'); var _cmap = require('./cmap'); var _stream = require('./stream'); var _primitives = require('./primitives'); var _fonts = require('./fonts'); var _encodings = require('./encodings'); var _unicode = require('./unicode'); var _standard_fonts = require('./standard_fonts'); var _pattern = require('./pattern'); var _parser = require('./parser'); var _bidi = require('./bidi'); var _colorspace = require('./colorspace'); var _glyphlist = require('./glyphlist'); var _metrics = require('./metrics'); var _function = require('./function'); var _jpeg_stream = require('./jpeg_stream'); var _murmurhash = require('./murmurhash3'); var _operator_list = require('./operator_list'); var _image = require('./image'); var PartialEvaluator = function PartialEvaluatorClosure() { var DefaultPartialEvaluatorOptions = { forceDataSchema: false, maxImageSize: -1, disableFontFace: false, nativeImageDecoderSupport: _util.NativeImageDecoding.DECODE, ignoreErrors: false, isEvalSupported: true }; function NativeImageDecoder(_ref) { var xref = _ref.xref, resources = _ref.resources, handler = _ref.handler, _ref$forceDataSchema = _ref.forceDataSchema, forceDataSchema = _ref$forceDataSchema === undefined ? false : _ref$forceDataSchema, pdfFunctionFactory = _ref.pdfFunctionFactory; this.xref = xref; this.resources = resources; this.handler = handler; this.forceDataSchema = forceDataSchema; this.pdfFunctionFactory = pdfFunctionFactory; } NativeImageDecoder.prototype = { canDecode: function canDecode(image) { return image instanceof _jpeg_stream.JpegStream && NativeImageDecoder.isDecodable(image, this.xref, this.resources, this.pdfFunctionFactory); }, decode: function decode(image) { var dict = image.dict; var colorSpace = dict.get('ColorSpace', 'CS'); colorSpace = _colorspace.ColorSpace.parse(colorSpace, this.xref, this.resources, this.pdfFunctionFactory); return this.handler.sendWithPromise('JpegDecode', [image.getIR(this.forceDataSchema), colorSpace.numComps]).then(function (_ref2) { var data = _ref2.data, width = _ref2.width, height = _ref2.height; return new _stream.Stream(data, 0, data.length, image.dict); }); } }; NativeImageDecoder.isSupported = function (image, xref, res, pdfFunctionFactory) { var dict = image.dict; if (dict.has('DecodeParms') || dict.has('DP')) { return false; } var cs = _colorspace.ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res, pdfFunctionFactory); return (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB') && cs.isDefaultDecode(dict.getArray('Decode', 'D')); }; NativeImageDecoder.isDecodable = function (image, xref, res, pdfFunctionFactory) { var dict = image.dict; if (dict.has('DecodeParms') || dict.has('DP')) { return false; } var cs = _colorspace.ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res, pdfFunctionFactory); return (cs.numComps === 1 || cs.numComps === 3) && cs.isDefaultDecode(dict.getArray('Decode', 'D')); }; function PartialEvaluator(_ref3) { var _this = this; var pdfManager = _ref3.pdfManager, xref = _ref3.xref, handler = _ref3.handler, pageIndex = _ref3.pageIndex, idFactory = _ref3.idFactory, fontCache = _ref3.fontCache, builtInCMapCache = _ref3.builtInCMapCache, _ref3$options = _ref3.options, options = _ref3$options === undefined ? null : _ref3$options, pdfFunctionFactory = _ref3.pdfFunctionFactory; this.pdfManager = pdfManager; this.xref = xref; this.handler = handler; this.pageIndex = pageIndex; this.idFactory = idFactory; this.fontCache = fontCache; this.builtInCMapCache = builtInCMapCache; this.options = options || DefaultPartialEvaluatorOptions; this.pdfFunctionFactory = pdfFunctionFactory; this.fetchBuiltInCMap = function (name) { var cachedCMap = _this.builtInCMapCache[name]; if (cachedCMap) { return Promise.resolve(cachedCMap); } return _this.handler.sendWithPromise('FetchBuiltInCMap', { name: name }).then(function (data) { if (data.compressionType !== _util.CMapCompressionType.NONE) { _this.builtInCMapCache[name] = data; } return data; }); }; } var TIME_SLOT_DURATION_MS = 20; var CHECK_TIME_EVERY = 100; function TimeSlotManager() { this.reset(); } TimeSlotManager.prototype = { check: function TimeSlotManager_check() { if (++this.checked < CHECK_TIME_EVERY) { return false; } this.checked = 0; return this.endTime <= Date.now(); }, reset: function TimeSlotManager_reset() { this.endTime = Date.now() + TIME_SLOT_DURATION_MS; this.checked = 0; } }; function normalizeBlendMode(value) { if (!(0, _primitives.isName)(value)) { return 'source-over'; } switch (value.name) { case 'Normal': case 'Compatible': return 'source-over'; case 'Multiply': return 'multiply'; case 'Screen': return 'screen'; case 'Overlay': return 'overlay'; case 'Darken': return 'darken'; case 'Lighten': return 'lighten'; case 'ColorDodge': return 'color-dodge'; case 'ColorBurn': return 'color-burn'; case 'HardLight': return 'hard-light'; case 'SoftLight': return 'soft-light'; case 'Difference': return 'difference'; case 'Exclusion': return 'exclusion'; case 'Hue': return 'hue'; case 'Saturation': return 'saturation'; case 'Color': return 'color'; case 'Luminosity': return 'luminosity'; } (0, _util.warn)('Unsupported blend mode: ' + value.name); return 'source-over'; } var deferred = Promise.resolve(); var TILING_PATTERN = 1, SHADING_PATTERN = 2; PartialEvaluator.prototype = { clone: function clone() { var newOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DefaultPartialEvaluatorOptions; var newEvaluator = Object.create(this); newEvaluator.options = newOptions; return newEvaluator; }, hasBlendModes: function PartialEvaluator_hasBlendModes(resources) { if (!(0, _primitives.isDict)(resources)) { return false; } var processed = Object.create(null); if (resources.objId) { processed[resources.objId] = true; } var nodes = [resources], xref = this.xref; while (nodes.length) { var key, i, ii; var node = nodes.shift(); var graphicStates = node.get('ExtGState'); if ((0, _primitives.isDict)(graphicStates)) { var graphicStatesKeys = graphicStates.getKeys(); for (i = 0, ii = graphicStatesKeys.length; i < ii; i++) { key = graphicStatesKeys[i]; var graphicState = graphicStates.get(key); var bm = graphicState.get('BM'); if ((0, _primitives.isName)(bm) && bm.name !== 'Normal') { return true; } } } var xObjects = node.get('XObject'); if (!(0, _primitives.isDict)(xObjects)) { continue; } var xObjectsKeys = xObjects.getKeys(); for (i = 0, ii = xObjectsKeys.length; i < ii; i++) { key = xObjectsKeys[i]; var xObject = xObjects.getRaw(key); if ((0, _primitives.isRef)(xObject)) { if (processed[xObject.toString()]) { continue; } xObject = xref.fetch(xObject); } if (!(0, _primitives.isStream)(xObject)) { continue; } if (xObject.dict.objId) { if (processed[xObject.dict.objId]) { continue; } processed[xObject.dict.objId] = true; } var xResources = xObject.dict.get('Resources'); if ((0, _primitives.isDict)(xResources) && (!xResources.objId || !processed[xResources.objId])) { nodes.push(xResources); if (xResources.objId) { processed[xResources.objId] = true; } } } } return false; }, buildFormXObject: function PartialEvaluator_buildFormXObject(resources, xobj, smask, operatorList, task, initialState) { var dict = xobj.dict; var matrix = dict.getArray('Matrix'); var bbox = dict.getArray('BBox'); var group = dict.get('Group'); if (group) { var groupOptions = { matrix: matrix, bbox: bbox, smask: smask, isolated: false, knockout: false }; var groupSubtype = group.get('S'); var colorSpace = null; if ((0, _primitives.isName)(groupSubtype, 'Transparency')) { groupOptions.isolated = group.get('I') || false; groupOptions.knockout = group.get('K') || false; if (group.has('CS')) { colorSpace = _colorspace.ColorSpace.parse(group.get('CS'), this.xref, resources, this.pdfFunctionFactory); } } if (smask && smask.backdrop) { colorSpace = colorSpace || _colorspace.ColorSpace.singletons.rgb; smask.backdrop = colorSpace.getRgb(smask.backdrop, 0); } operatorList.addOp(_util.OPS.beginGroup, [groupOptions]); } operatorList.addOp(_util.OPS.paintFormXObjectBegin, [matrix, bbox]); return this.getOperatorList({ stream: xobj, task: task, resources: dict.get('Resources') || resources, operatorList: operatorList, initialState: initialState }).then(function () { operatorList.addOp(_util.OPS.paintFormXObjectEnd, []); if (group) { operatorList.addOp(_util.OPS.endGroup, [groupOptions]); } }); }, buildPaintImageXObject: function buildPaintImageXObject(_ref4) { var _this2 = this; var resources = _ref4.resources, image = _ref4.image, _ref4$isInline = _ref4.isInline, isInline = _ref4$isInline === undefined ? false : _ref4$isInline, operatorList = _ref4.operatorList, cacheKey = _ref4.cacheKey, imageCache = _ref4.imageCache, _ref4$forceDisableNat = _ref4.forceDisableNativeImageDecoder, forceDisableNativeImageDecoder = _ref4$forceDisableNat === undefined ? false : _ref4$forceDisableNat; var dict = image.dict; var w = dict.get('Width', 'W'); var h = dict.get('Height', 'H'); if (!(w && (0, _util.isNum)(w)) || !(h && (0, _util.isNum)(h))) { (0, _util.warn)('Image dimensions are missing, or not numbers.'); return Promise.resolve(); } var maxImageSize = this.options.maxImageSize; if (maxImageSize !== -1 && w * h > maxImageSize) { (0, _util.warn)('Image exceeded maximum allowed size and was removed.'); return Promise.resolve(); } var imageMask = dict.get('ImageMask', 'IM') || false; var imgData, args; if (imageMask) { var width = dict.get('Width', 'W'); var height = dict.get('Height', 'H'); var bitStrideLength = width + 7 >> 3; var imgArray = image.getBytes(bitStrideLength * height); var decode = dict.getArray('Decode', 'D'); imgData = _image.PDFImage.createMask({ imgArray: imgArray, width: width, height: height, imageIsFromDecodeStream: image instanceof _stream.DecodeStream, inverseDecode: !!decode && decode[0] > 0 }); imgData.cached = true; args = [imgData]; operatorList.addOp(_util.OPS.paintImageMaskXObject, args); if (cacheKey) { imageCache[cacheKey] = { fn: _util.OPS.paintImageMaskXObject, args: args }; } return Promise.resolve(); } var softMask = dict.get('SMask', 'SM') || false; var mask = dict.get('Mask') || false; var SMALL_IMAGE_DIMENSIONS = 200; if (isInline && !softMask && !mask && !(image instanceof _jpeg_stream.JpegStream) && w + h < SMALL_IMAGE_DIMENSIONS) { var imageObj = new _image.PDFImage({ xref: this.xref, res: resources, image: image, isInline: isInline, pdfFunctionFactory: this.pdfFunctionFactory }); imgData = imageObj.createImageData(true); operatorList.addOp(_util.OPS.paintInlineImageXObject, [imgData]); return Promise.resolve(); } var nativeImageDecoderSupport = forceDisableNativeImageDecoder ? _util.NativeImageDecoding.NONE : this.options.nativeImageDecoderSupport; var objId = 'img_' + this.idFactory.createObjId(); if (nativeImageDecoderSupport !== _util.NativeImageDecoding.NONE && !softMask && !mask && image instanceof _jpeg_stream.JpegStream && NativeImageDecoder.isSupported(image, this.xref, resources, this.pdfFunctionFactory)) { return this.handler.sendWithPromise('obj', [objId, this.pageIndex, 'JpegStream', image.getIR(this.options.forceDataSchema)]).then(function () { operatorList.addDependency(objId); args = [objId, w, h]; operatorList.addOp(_util.OPS.paintJpegXObject, args); if (cacheKey) { imageCache[cacheKey] = { fn: _util.OPS.paintJpegXObject, args: args }; } }, function (reason) { (0, _util.warn)('Native JPEG decoding failed -- trying to recover: ' + (reason && reason.message)); return _this2.buildPaintImageXObject({ resources: resources, image: image, isInline: isInline, operatorList: operatorList, cacheKey: cacheKey, imageCache: imageCache, forceDisableNativeImageDecoder: true }); }); } var nativeImageDecoder = null; if (nativeImageDecoderSupport === _util.NativeImageDecoding.DECODE && (image instanceof _jpeg_stream.JpegStream || mask instanceof _jpeg_stream.JpegStream || softMask instanceof _jpeg_stream.JpegStream)) { nativeImageDecoder = new NativeImageDecoder({ xref: this.xref, resources: resources, handler: this.handler, forceDataSchema: this.options.forceDataSchema, pdfFunctionFactory: this.pdfFunctionFactory }); } operatorList.addDependency(objId); args = [objId, w, h]; _image.PDFImage.buildImage({ handler: this.handler, xref: this.xref, res: resources, image: image, isInline: isInline, nativeDecoder: nativeImageDecoder, pdfFunctionFactory: this.pdfFunctionFactory }).then(function (imageObj) { var imgData = imageObj.createImageData(false); _this2.handler.send('obj', [objId, _this2.pageIndex, 'Image', imgData], [imgData.data.buffer]); }).catch(function (reason) { (0, _util.warn)('Unable to decode image: ' + reason); _this2.handler.send('obj', [objId, _this2.pageIndex, 'Image', null]); }); operatorList.addOp(_util.OPS.paintImageXObject, args); if (cacheKey) { imageCache[cacheKey] = { fn: _util.OPS.paintImageXObject, args: args }; } return Promise.resolve(); }, handleSMask: function PartialEvaluator_handleSmask(smask, resources, operatorList, task, stateManager) { var smaskContent = smask.get('G'); var smaskOptions = { subtype: smask.get('S').name, backdrop: smask.get('BC') }; var transferObj = smask.get('TR'); if ((0, _function.isPDFFunction)(transferObj)) { var transferFn = this.pdfFunctionFactory.create(transferObj); var transferMap = new Uint8Array(256); var tmp = new Float32Array(1); for (var i = 0; i < 256; i++) { tmp[0] = i / 255; transferFn(tmp, 0, tmp, 0); transferMap[i] = tmp[0] * 255 | 0; } smaskOptions.transferMap = transferMap; } return this.buildFormXObject(resources, smaskContent, smaskOptions, operatorList, task, stateManager.state.clone()); }, handleTilingType: function handleTilingType(fn, args, resources, pattern, patternDict, operatorList, task) { var _this3 = this; var tilingOpList = new _operator_list.OperatorList(); var resourcesArray = [patternDict.get('Resources'), resources]; var patternResources = _primitives.Dict.merge(this.xref, resourcesArray); return this.getOperatorList({ stream: pattern, task: task, resources: patternResources, operatorList: tilingOpList }).then(function () { return (0, _pattern.getTilingPatternIR)({ fnArray: tilingOpList.fnArray, argsArray: tilingOpList.argsArray }, patternDict, args); }).then(function (tilingPatternIR) { operatorList.addDependencies(tilingOpList.dependencies); operatorList.addOp(fn, tilingPatternIR); }, function (reason) { if (_this3.options.ignoreErrors) { _this3.handler.send('UnsupportedFeature', { featureId: _util.UNSUPPORTED_FEATURES.unknown }); (0, _util.warn)('handleTilingType - ignoring pattern: "' + reason + '".'); return; } throw reason; }); }, handleSetFont: function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef, operatorList, task, state) { var _this4 = this; var fontName; if (fontArgs) { fontArgs = fontArgs.slice(); fontName = fontArgs[0].name; } return this.loadFont(fontName, fontRef, resources).then(function (translated) { if (!translated.font.isType3Font) { return translated; } return translated.loadType3Data(_this4, resources, operatorList, task).then(function () { return translated; }).catch(function (reason) { _this4.handler.send('UnsupportedFeature', { featureId: _util.UNSUPPORTED_FEATURES.font }); return new TranslatedFont('g_font_error', new _fonts.ErrorFont('Type3 font load error: ' + reason), translated.font); }); }).then(function (translated) { state.font = translated.font; translated.send(_this4.handler); return translated.loadedName; }); }, handleText: function PartialEvaluator_handleText(chars, state) { var _this5 = this; var font = state.font; var glyphs = font.charsToGlyphs(chars); var isAddToPathSet = !!(state.textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG); if (font.data && (isAddToPathSet || this.options.disableFontFace || state.fillColorSpace.name === 'Pattern')) { var buildPath = function buildPath(fontChar) { if (!font.renderer.hasBuiltPath(fontChar)) { var path = font.renderer.getPathJs(fontChar); _this5.handler.send('commonobj', [font.loadedName + '_path_' + fontChar, 'FontPath', path]); } }; for (var i = 0, ii = glyphs.length; i < ii; i++) { var glyph = glyphs[i]; buildPath(glyph.fontChar); var accent = glyph.accent; if (accent && accent.fontChar) { buildPath(accent.fontChar); } } } return glyphs; }, setGState: function PartialEvaluator_setGState(resources, gState, operatorList, task, stateManager) { var _this6 = this; var gStateObj = []; var gStateKeys = gState.getKeys(); var promise = Promise.resolve(); var _loop = function _loop() { var key = gStateKeys[i]; var value = gState.get(key); switch (key) { case 'Type': break; case 'LW': case 'LC': case 'LJ': case 'ML': case 'D': case 'RI': case 'FL': case 'CA': case 'ca': gStateObj.push([key, value]); break; case 'Font': promise = promise.then(function () { return _this6.handleSetFont(resources, null, value[0], operatorList, task, stateManager.state).then(function (loadedName) { operatorList.addDependency(loadedName); gStateObj.push([key, [loadedName, value[1]]]); }); }); break; case 'BM': gStateObj.push([key, normalizeBlendMode(value)]); break; case 'SMask': if ((0, _primitives.isName)(value, 'None')) { gStateObj.push([key, false]); break; } if ((0, _primitives.isDict)(value)) { promise = promise.then(function () { return _this6.handleSMask(value, resources, operatorList, task, stateManager); }); gStateObj.push([key, true]); } else { (0, _util.warn)('Unsupported SMask type'); } break; case 'OP': case 'op': case 'OPM': case 'BG': case 'BG2': case 'UCR': case 'UCR2': case 'TR': case 'TR2': case 'HT': case 'SM': case 'SA': case 'AIS': case 'TK': (0, _util.info)('graphic state operator ' + key); break; default: (0, _util.info)('Unknown graphic state operator ' + key); break; } }; for (var i = 0, ii = gStateKeys.length; i < ii; i++) { _loop(); } return promise.then(function () { if (gStateObj.length > 0) { operatorList.addOp(_util.OPS.setGState, [gStateObj]); } }); }, loadFont: function PartialEvaluator_loadFont(fontName, font, resources) { var _this7 = this; function errorFont() { return Promise.resolve(new TranslatedFont('g_font_error', new _fonts.ErrorFont('Font ' + fontName + ' is not available'), font)); } var fontRef, xref = this.xref; if (font) { if (!(0, _primitives.isRef)(font)) { throw new Error('The "font" object should be a reference.'); } fontRef = font; } else { var fontRes = resources.get('Font'); if (fontRes) { fontRef = fontRes.getRaw(fontName); } else { (0, _util.warn)('fontRes not available'); return errorFont(); } } if (!fontRef) { (0, _util.warn)('fontRef not available'); return errorFont(); } if (this.fontCache.has(fontRef)) { return this.fontCache.get(fontRef); } font = xref.fetchIfRef(fontRef); if (!(0, _primitives.isDict)(font)) { return errorFont(); } if (font.translated) { return font.translated; } var fontCapability = (0, _util.createPromiseCapability)(); var preEvaluatedFont = this.preEvaluateFont(font); var descriptor = preEvaluatedFont.descriptor; var fontRefIsRef = (0, _primitives.isRef)(fontRef), fontID; if (fontRefIsRef) { fontID = fontRef.toString(); } if ((0, _primitives.isDict)(descriptor)) { if (!descriptor.fontAliases) { descriptor.fontAliases = Object.create(null); } var fontAliases = descriptor.fontAliases; var hash = preEvaluatedFont.hash; if (fontAliases[hash]) { var aliasFontRef = fontAliases[hash].aliasRef; if (fontRefIsRef && aliasFontRef && this.fontCache.has(aliasFontRef)) { this.fontCache.putAlias(fontRef, aliasFontRef); return this.fontCache.get(fontRef); } } else { fontAliases[hash] = { fontID: _fonts.Font.getFontID() }; } if (fontRefIsRef) { fontAliases[hash].aliasRef = fontRef; } fontID = fontAliases[hash].fontID; } if (fontRefIsRef) { this.fontCache.put(fontRef, fontCapability.promise); } else { if (!fontID) { fontID = this.idFactory.createObjId(); } this.fontCache.put('id_' + fontID, fontCapability.promise); } (0, _util.assert)(fontID, 'The "fontID" must be defined.'); font.loadedName = 'g_' + this.pdfManager.docId + '_f' + fontID; font.translated = fontCapability.promise; var translatedPromise; try { translatedPromise = this.translateFont(preEvaluatedFont); } catch (e) { translatedPromise = Promise.reject(e); } translatedPromise.then(function (translatedFont) { if (translatedFont.fontType !== undefined) { var xrefFontStats = xref.stats.fontTypes; xrefFontStats[translatedFont.fontType] = true; } fontCapability.resolve(new TranslatedFont(font.loadedName, translatedFont, font)); }).catch(function (reason) { _this7.handler.send('UnsupportedFeature', { featureId: _util.UNSUPPORTED_FEATURES.font }); try { var descriptor = preEvaluatedFont.descriptor; var fontFile3 = descriptor && descriptor.get('FontFile3'); var subtype = fontFile3 && fontFile3.get('Subtype'); var fontType = (0, _fonts.getFontType)(preEvaluatedFont.type, subtype && subtype.name); var xrefFontStats = xref.stats.fontTypes; xrefFontStats[fontType] = true; } catch (ex) {} fontCapability.resolve(new TranslatedFont(font.loadedName, new _fonts.ErrorFont(reason instanceof Error ? reason.message : reason), font)); }); return fontCapability.promise; }, buildPath: function PartialEvaluator_buildPath(operatorList, fn, args) { var lastIndex = operatorList.length - 1; if (!args) { args = []; } if (lastIndex < 0 || operatorList.fnArray[lastIndex] !== _util.OPS.constructPath) { operatorList.addOp(_util.OPS.constructPath, [[fn], args]); } else { var opArgs = operatorList.argsArray[lastIndex]; opArgs[0].push(fn); Array.prototype.push.apply(opArgs[1], args); } }, handleColorN: function PartialEvaluator_handleColorN(operatorList, fn, args, cs, patterns, resources, task) { var patternName = args[args.length - 1]; var pattern; if ((0, _primitives.isName)(patternName) && (pattern = patterns.get(patternName.name))) { var dict = (0, _primitives.isStream)(pattern) ? pattern.dict : pattern; var typeNum = dict.get('PatternType'); if (typeNum === TILING_PATTERN) { var color = cs.base ? cs.base.getRgb(args, 0) : null; return this.handleTilingType(fn, color, resources, pattern, dict, operatorList, task); } else if (typeNum === SHADING_PATTERN) { var shading = dict.get('Shading'); var matrix = dict.getArray('Matrix'); pattern = _pattern.Pattern.parseShading(shading, matrix, this.xref, resources, this.handler, this.pdfFunctionFactory); operatorList.addOp(fn, pattern.getIR()); return Promise.resolve(); } return Promise.reject(new Error('Unknown PatternType: ' + typeNum)); } operatorList.addOp(fn, args); return Promise.resolve(); }, getOperatorList: function getOperatorList(_ref5) { var _this8 = this; var stream = _ref5.stream, task = _ref5.task, resources = _ref5.resources, operatorList = _ref5.operatorList, _ref5$initialState = _ref5.initialState, initialState = _ref5$initialState === undefined ? null : _ref5$initialState; resources = resources || _primitives.Dict.empty; initialState = initialState || new EvalState(); if (!operatorList) { throw new Error('getOperatorList: missing "operatorList" parameter'); } var self = this; var xref = this.xref; var imageCache = Object.create(null); var xobjs = resources.get('XObject') || _primitives.Dict.empty; var patterns = resources.get('Pattern') || _primitives.Dict.empty; var stateManager = new StateManager(initialState); var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); var timeSlotManager = new TimeSlotManager(); function closePendingRestoreOPS(argument) { for (var i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) { operatorList.addOp(_util.OPS.restore, []); } } return new Promise(function promiseBody(resolve, reject) { var next = function next(promise) { promise.then(function () { try { promiseBody(resolve, reject); } catch (ex) { reject(ex); } }, reject); }; task.ensureNotTerminated(); timeSlotManager.reset(); var stop, operation = {}, i, ii, cs; while (!(stop = timeSlotManager.check())) { operation.args = null; if (!preprocessor.read(operation)) { break; } var args = operation.args; var fn = operation.fn; switch (fn | 0) { case _util.OPS.paintXObject: var name = args[0].name; if (name && imageCache[name] !== undefined) { operatorList.addOp(imageCache[name].fn, imageCache[name].args); args = null; continue; } next(new Promise(function (resolveXObject, rejectXObject) { if (!name) { throw new _util.FormatError('XObject must be referred to by name.'); } var xobj = xobjs.get(name); if (!xobj) { operatorList.addOp(fn, args); resolveXObject(); return; } if (!(0, _primitives.isStream)(xobj)) { throw new _util.FormatError('XObject should be a stream'); } var type = xobj.dict.get('Subtype'); if (!(0, _primitives.isName)(type)) { throw new _util.FormatError('XObject should have a Name subtype'); } if (type.name === 'Form') { stateManager.save(); self.buildFormXObject(resources, xobj, null, operatorList, task, stateManager.state.clone()).then(function () { stateManager.restore(); resolveXObject(); }, rejectXObject); return; } else if (type.name === 'Image') { self.buildPaintImageXObject({ resources: resources, image: xobj, operatorList: operatorList, cacheKey: name, imageCache: imageCache }).then(resolveXObject, rejectXObject); return; } else if (type.name === 'PS') { (0, _util.info)('Ignored XObject subtype PS'); } else { throw new _util.FormatError('Unhandled XObject subtype ' + type.name); } resolveXObject(); }).catch(function (reason) { if (self.options.ignoreErrors) { self.handler.send('UnsupportedFeature', { featureId: _util.UNSUPPORTED_FEATURES.unknown }); (0, _util.warn)('getOperatorList - ignoring XObject: "' + reason + '".'); return; } throw reason; })); return; case _util.OPS.setFont: var fontSize = args[1]; next(self.handleSetFont(resources, args, null, operatorList, task, stateManager.state).then(function (loadedName) { operatorList.addDependency(loadedName); operatorList.addOp(_util.OPS.setFont, [loadedName, fontSize]); })); return; case _util.OPS.endInlineImage: var cacheKey = args[0].cacheKey; if (cacheKey) { var cacheEntry = imageCache[cacheKey]; if (cacheEntry !== undefined) { operatorList.addOp(cacheEntry.fn, cacheEntry.args); args = null; continue; } } next(self.buildPaintImageXObject({ resources: resources, image: args[0], isInline: true, operatorList: operatorList, cacheKey: cacheKey, imageCache: imageCache })); return; case _util.OPS.showText: args[0] = self.handleText(args[0], stateManager.state); break; case _util.OPS.showSpacedText: var arr = args[0]; var combinedGlyphs = []; var arrLength = arr.length; var state = stateManager.state; for (i = 0; i < arrLength; ++i) { var arrItem = arr[i]; if ((0, _util.isString)(arrItem)) { Array.prototype.push.apply(combinedGlyphs, self.handleText(arrItem, state)); } else if ((0, _util.isNum)(arrItem)) { combinedGlyphs.push(arrItem); } } args[0] = combinedGlyphs; fn = _util.OPS.showText; break; case _util.OPS.nextLineShowText: operatorList.addOp(_util.OPS.nextLine); args[0] = self.handleText(args[0], stateManager.state); fn = _util.OPS.showText; break; case _util.OPS.nextLineSetSpacingShowText: operatorList.addOp(_util.OPS.nextLine); operatorList.addOp(_util.OPS.setWordSpacing, [args.shift()]); operatorList.addOp(_util.OPS.setCharSpacing, [args.shift()]); args[0] = self.handleText(args[0], stateManager.state); fn = _util.OPS.showText; break; case _util.OPS.setTextRenderingMode: stateManager.state.textRenderingMode = args[0]; break; case _util.OPS.setFillColorSpace: stateManager.state.fillColorSpace = _colorspace.ColorSpace.parse(args[0], xref, resources, self.pdfFunctionFactory); continue; case _util.OPS.setStrokeColorSpace: stateManager.state.strokeColorSpace = _colorspace.ColorSpace.parse(args[0], xref, resources, self.pdfFunctionFactory); continue; case _util.OPS.setFillColor: cs = stateManager.state.fillColorSpace; args = cs.getRgb(args, 0); fn = _util.OPS.setFillRGBColor; break; case _util.OPS.setStrokeColor: cs = stateManager.state.strokeColorSpace; args = cs.getRgb(args, 0); fn = _util.OPS.setStrokeRGBColor; break; case _util.OPS.setFillGray: stateManager.state.fillColorSpace = _colorspace.ColorSpace.singletons.gray; args = _colorspace.ColorSpace.singletons.gray.getRgb(args, 0); fn = _util.OPS.setFillRGBColor; break; case _util.OPS.setStrokeGray: stateManager.state.strokeColorSpace = _colorspace.ColorSpace.singletons.gray; args = _colorspace.ColorSpace.singletons.gray.getRgb(args, 0); fn = _util.OPS.setStrokeRGBColor; break; case _util.OPS.setFillCMYKColor: stateManager.state.fillColorSpace = _colorspace.ColorSpace.singletons.cmyk; args = _colorspace.ColorSpace.singletons.cmyk.getRgb(args, 0); fn = _util.OPS.setFillRGBColor; break; case _util.OPS.setStrokeCMYKColor: stateManager.state.strokeColorSpace = _colorspace.ColorSpace.singletons.cmyk; args = _colorspace.ColorSpace.singletons.cmyk.getRgb(args, 0); fn = _util.OPS.setStrokeRGBColor; break; case _util.OPS.setFillRGBColor: stateManager.state.fillColorSpace = _colorspace.ColorSpace.singletons.rgb; args = _colorspace.ColorSpace.singletons.rgb.getRgb(args, 0); break; case _util.OPS.setStrokeRGBColor: stateManager.state.strokeColorSpace = _colorspace.ColorSpace.singletons.rgb; args = _colorspace.ColorSpace.singletons.rgb.getRgb(args, 0); break; case _util.OPS.setFillColorN: cs = stateManager.state.fillColorSpace; if (cs.name === 'Pattern') { next(self.handleColorN(operatorList, _util.OPS.setFillColorN, args, cs, patterns, resources, task)); return; } args = cs.getRgb(args, 0); fn = _util.OPS.setFillRGBColor; break; case _util.OPS.setStrokeColorN: cs = stateManager.state.strokeColorSpace; if (cs.name === 'Pattern') { next(self.handleColorN(operatorList, _util.OPS.setStrokeColorN, args, cs, patterns, resources, task)); return; } args = cs.getRgb(args, 0); fn = _util.OPS.setStrokeRGBColor; break; case _util.OPS.shadingFill: var shadingRes = resources.get('Shading'); if (!shadingRes) { throw new _util.FormatError('No shading resource found'); } var shading = shadingRes.get(args[0].name); if (!shading) { throw new _util.FormatError('No shading object found'); } var shadingFill = _pattern.Pattern.parseShading(shading, null, xref, resources, self.handler, self.pdfFunctionFactory); var patternIR = shadingFill.getIR(); args = [patternIR]; fn = _util.OPS.shadingFill; break; case _util.OPS.setGState: var dictName = args[0]; var extGState = resources.get('ExtGState'); if (!(0, _primitives.isDict)(extGState) || !extGState.has(dictName.name)) { break; } var gState = extGState.get(dictName.name); next(self.setGState(resources, gState, operatorList, task, stateManager)); return; case _util.OPS.moveTo: case _util.OPS.lineTo: case _util.OPS.curveTo: case _util.OPS.curveTo2: case _util.OPS.curveTo3: case _util.OPS.closePath: self.buildPath(operatorList, fn, args); continue; case _util.OPS.rectangle: self.buildPath(operatorList, fn, args); continue; case _util.OPS.markPoint: case _util.OPS.markPointProps: case _util.OPS.beginMarkedContent: case _util.OPS.beginMarkedContentProps: case _util.OPS.endMarkedContent: case _util.OPS.beginCompat: case _util.OPS.endCompat: continue; default: if (args !== null) { for (i = 0, ii = args.length; i < ii; i++) { if (args[i] instanceof _primitives.Dict) { break; } } if (i < ii) { (0, _util.warn)('getOperatorList - ignoring operator: ' + fn); continue; } } } operatorList.addOp(fn, args); } if (stop) { next(deferred); return; } closePendingRestoreOPS(); resolve(); }).catch(function (reason) { if (_this8.options.ignoreErrors) { _this8.handler.send('UnsupportedFeature', { featureId: _util.UNSUPPORTED_FEATURES.unknown }); (0, _util.warn)('getOperatorList - ignoring errors during task: ' + task.name); closePendingRestoreOPS(); return; } throw reason; }); }, getTextContent: function getTextContent(_ref6) { var _this9 = this; var stream = _ref6.stream, task = _ref6.task, resources = _ref6.resources, _ref6$stateManager = _ref6.stateManager, stateManager = _ref6$stateManager === undefined ? null : _ref6$stateManager, _ref6$normalizeWhites = _ref6.normalizeWhitespace, normalizeWhitespace = _ref6$normalizeWhites === undefined ? false : _ref6$normalizeWhites, _ref6$combineTextItem = _ref6.combineTextItems, combineTextItems = _ref6$combineTextItem === undefined ? false : _ref6$combineTextItem, sink = _ref6.sink, _ref6$seenStyles = _ref6.seenStyles, seenStyles = _ref6$seenStyles === undefined ? Object.create(null) : _ref6$seenStyles; resources = resources || _primitives.Dict.empty; stateManager = stateManager || new StateManager(new TextState()); var WhitespaceRegexp = /\s/g; var textContent = { items: [], styles: Object.create(null) }; var textContentItem = { initialized: false, str: [], width: 0, height: 0, vertical: false, lastAdvanceWidth: 0, lastAdvanceHeight: 0, textAdvanceScale: 0, spaceWidth: 0, fakeSpaceMin: Infinity, fakeMultiSpaceMin: Infinity, fakeMultiSpaceMax: -0, textRunBreakAllowed: false, transform: null, fontName: null }; var SPACE_FACTOR = 0.3; var MULTI_SPACE_FACTOR = 1.5; var MULTI_SPACE_FACTOR_MAX = 4; var self = this; var xref = this.xref; var xobjs = null; var skipEmptyXObjs = Object.create(null); var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); var textState; function ensureTextContentItem() { if (textContentItem.initialized) { return textContentItem; } var font = textState.font; if (!(font.loadedName in seenStyles)) { seenStyles[font.loadedName] = true; textContent.styles[font.loadedName] = { fontFamily: font.fallbackName, ascent: font.ascent, descent: font.descent, vertical: font.vertical }; } textContentItem.fontName = font.loadedName; var tsm = [textState.fontSize * textState.textHScale, 0, 0, textState.fontSize, 0, textState.textRise]; if (font.isType3Font && textState.fontMatrix !== _util.FONT_IDENTITY_MATRIX && textState.fontSize === 1) { var glyphHeight = font.bbox[3] - font.bbox[1]; if (glyphHeight > 0) { glyphHeight = glyphHeight * textState.fontMatrix[3]; tsm[3] *= glyphHeight; } } var trm = _util.Util.transform(textState.ctm, _util.Util.transform(textState.textMatrix, tsm)); textContentItem.transform = trm; if (!font.vertical) { textContentItem.width = 0; textContentItem.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]); textContentItem.vertical = false; } else { textContentItem.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]); textContentItem.height = 0; textContentItem.vertical = true; } var a = textState.textLineMatrix[0]; var b = textState.textLineMatrix[1]; var scaleLineX = Math.sqrt(a * a + b * b); a = textState.ctm[0]; b = textState.ctm[1]; var scaleCtmX = Math.sqrt(a * a + b * b); textContentItem.textAdvanceScale = scaleCtmX * scaleLineX; textContentItem.lastAdvanceWidth = 0; textContentItem.lastAdvanceHeight = 0; var spaceWidth = font.spaceWidth / 1000 * textState.fontSize; if (spaceWidth) { textContentItem.spaceWidth = spaceWidth; textContentItem.fakeSpaceMin = spaceWidth * SPACE_FACTOR; textContentItem.fakeMultiSpaceMin = spaceWidth * MULTI_SPACE_FACTOR; textContentItem.fakeMultiSpaceMax = spaceWidth * MULTI_SPACE_FACTOR_MAX; textContentItem.textRunBreakAllowed = !font.isMonospace; } else { textContentItem.spaceWidth = 0; textContentItem.fakeSpaceMin = Infinity; textContentItem.fakeMultiSpaceMin = Infinity; textContentItem.fakeMultiSpaceMax = 0; textContentItem.textRunBreakAllowed = false; } textContentItem.initialized = true; return textContentItem; } function replaceWhitespace(str) { var i = 0, ii = str.length, code; while (i < ii && (code = str.charCodeAt(i)) >= 0x20 && code <= 0x7F) { i++; } return i < ii ? str.replace(WhitespaceRegexp, ' ') : str; } function runBidiTransform(textChunk) { var str = textChunk.str.join(''); var bidiResult = (0, _bidi.bidi)(str, -1, textChunk.vertical); return { str: normalizeWhitespace ? replaceWhitespace(bidiResult.str) : bidiResult.str, dir: bidiResult.dir, width: textChunk.width, height: textChunk.height, transform: textChunk.transform, fontName: textChunk.fontName }; } function handleSetFont(fontName, fontRef) { return self.loadFont(fontName, fontRef, resources).then(function (translated) { textState.font = translated.font; textState.fontMatrix = translated.font.fontMatrix || _util.FONT_IDENTITY_MATRIX; }); } function buildTextContentItem(chars) { var font = textState.font; var textChunk = ensureTextContentItem(); var width = 0; var height = 0; var glyphs = font.charsToGlyphs(chars); for (var i = 0; i < glyphs.length; i++) { var glyph = glyphs[i]; var glyphWidth = null; if (font.vertical && glyph.vmetric) { glyphWidth = glyph.vmetric[0]; } else { glyphWidth = glyph.width; } var glyphUnicode = glyph.unicode; var NormalizedUnicodes = (0, _unicode.getNormalizedUnicodes)(); if (NormalizedUnicodes[glyphUnicode] !== undefined) { glyphUnicode = NormalizedUnicodes[glyphUnicode]; } glyphUnicode = (0, _unicode.reverseIfRtl)(glyphUnicode); var charSpacing = textState.charSpacing; if (glyph.isSpace) { var wordSpacing = textState.wordSpacing; charSpacing += wordSpacing; if (wordSpacing > 0) { addFakeSpaces(wordSpacing, textChunk.str); } } var tx = 0; var ty = 0; if (!font.vertical) { var w0 = glyphWidth * textState.fontMatrix[0]; tx = (w0 * textState.fontSize + charSpacing) * textState.textHScale; width += tx; } else { var w1 = glyphWidth * textState.fontMatrix[0]; ty = w1 * textState.fontSize + charSpacing; height += ty; } textState.translateTextMatrix(tx, ty); textChunk.str.push(glyphUnicode); } if (!font.vertical) { textChunk.lastAdvanceWidth = width; textChunk.width += width; } else { textChunk.lastAdvanceHeight = height; textChunk.height += Math.abs(height); } return textChunk; } function addFakeSpaces(width, strBuf) { if (width < textContentItem.fakeSpaceMin) { return; } if (width < textContentItem.fakeMultiSpaceMin) { strBuf.push(' '); return; } var fakeSpaces = Math.round(width / textContentItem.spaceWidth); while (fakeSpaces-- > 0) { strBuf.push(' '); } } function flushTextContentItem() { if (!textContentItem.initialized) { return; } textContentItem.width *= textContentItem.textAdvanceScale; textContentItem.height *= textContentItem.textAdvanceScale; textContent.items.push(runBidiTransform(textContentItem)); textContentItem.initialized = false; textContentItem.str.length = 0; } function