pdfjs-dist
Version:
Generic build of Mozilla's PDF.js library.
1,286 lines (1,244 loc) • 102 kB
JavaScript
/**
* @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