diff --git a/src/core/colorspace.js b/src/core/colorspace.js index 05860ab7b..3651418e0 100644 --- a/src/core/colorspace.js +++ b/src/core/colorspace.js @@ -15,7 +15,6 @@ import { FormatError, info, isString, shadow, warn } from '../shared/util'; import { isDict, isName, isStream } from './primitives'; -import { PDFFunction } from './function'; var ColorSpace = (function ColorSpaceClosure() { /** @@ -200,12 +199,12 @@ var ColorSpace = (function ColorSpaceClosure() { usesZeroToOneRange: true, }; - ColorSpace.parse = function ColorSpace_parse(cs, xref, res) { - let IR = ColorSpace.parseToIR(cs, xref, res); - return ColorSpace.fromIR(IR); + ColorSpace.parse = function(cs, xref, res, pdfFunctionFactory) { + let IR = ColorSpace.parseToIR(cs, xref, res, pdfFunctionFactory); + return ColorSpace.fromIR(IR, pdfFunctionFactory); }; - ColorSpace.fromIR = function ColorSpace_fromIR(IR) { + ColorSpace.fromIR = function(IR, pdfFunctionFactory) { var name = Array.isArray(IR) ? IR[0] : IR; var whitePoint, blackPoint, gamma; @@ -230,21 +229,23 @@ var ColorSpace = (function ColorSpaceClosure() { case 'PatternCS': var basePatternCS = IR[1]; if (basePatternCS) { - basePatternCS = ColorSpace.fromIR(basePatternCS); + basePatternCS = ColorSpace.fromIR(basePatternCS, pdfFunctionFactory); } return new PatternCS(basePatternCS); case 'IndexedCS': var baseIndexedCS = IR[1]; var hiVal = IR[2]; var lookup = IR[3]; - return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), hiVal, lookup); + return new IndexedCS(ColorSpace.fromIR(baseIndexedCS, + pdfFunctionFactory), + hiVal, lookup); case 'AlternateCS': var numComps = IR[1]; var alt = IR[2]; var tintFnIR = IR[3]; - - return new AlternateCS(numComps, ColorSpace.fromIR(alt), - PDFFunction.fromIR(tintFnIR)); + return new AlternateCS(numComps, ColorSpace.fromIR(alt, + pdfFunctionFactory), + pdfFunctionFactory.createFromIR(tintFnIR)); case 'LabCS': whitePoint = IR[1]; blackPoint = IR[2]; @@ -255,7 +256,7 @@ var ColorSpace = (function ColorSpaceClosure() { } }; - ColorSpace.parseToIR = function ColorSpace_parseToIR(cs, xref, res) { + ColorSpace.parseToIR = function(cs, xref, res, pdfFunctionFactory) { if (isName(cs)) { var colorSpaces = res.get('ColorSpace'); if (isDict(colorSpaces)) { @@ -317,10 +318,11 @@ var ColorSpace = (function ColorSpaceClosure() { numComps = dict.get('N'); alt = dict.get('Alternate'); if (alt) { - var altIR = ColorSpace.parseToIR(alt, xref, res); + var altIR = ColorSpace.parseToIR(alt, xref, res, + pdfFunctionFactory); // Parse the /Alternate CS to ensure that the number of components // are correct, and also (indirectly) that it is not a PatternCS. - var altCS = ColorSpace.fromIR(altIR); + var altCS = ColorSpace.fromIR(altIR, pdfFunctionFactory); if (altCS.numComps === numComps) { return altIR; } @@ -337,12 +339,14 @@ var ColorSpace = (function ColorSpaceClosure() { case 'Pattern': var basePatternCS = cs[1] || null; if (basePatternCS) { - basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res); + basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res, + pdfFunctionFactory); } return ['PatternCS', basePatternCS]; case 'Indexed': case 'I': - var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res); + var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res, + pdfFunctionFactory); var hiVal = xref.fetchIfRef(cs[2]) + 1; var lookup = xref.fetchIfRef(cs[3]); if (isStream(lookup)) { @@ -353,8 +357,8 @@ var ColorSpace = (function ColorSpaceClosure() { case 'DeviceN': var name = xref.fetchIfRef(cs[1]); numComps = Array.isArray(name) ? name.length : 1; - alt = ColorSpace.parseToIR(cs[2], xref, res); - var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3])); + alt = ColorSpace.parseToIR(cs[2], xref, res, pdfFunctionFactory); + let tintFnIR = pdfFunctionFactory.createIR(xref.fetchIfRef(cs[3])); return ['AlternateCS', numComps, alt, tintFnIR]; case 'Lab': params = xref.fetchIfRef(cs[1]); diff --git a/src/core/document.js b/src/core/document.js index 4d8b066fe..19fdb6a65 100644 --- a/src/core/document.js +++ b/src/core/document.js @@ -24,7 +24,7 @@ import { OperatorList, PartialEvaluator } from './evaluator'; import { AnnotationFactory } from './annotation'; import { calculateMD5 } from './crypto'; import { Linearization } from './parser'; -import { PDFFunction } from './function'; +import { PDFFunctionFactory } from './function'; var Page = (function PageClosure() { @@ -36,8 +36,8 @@ var Page = (function PageClosure() { (intent === 'print' && annotation.printable); } - function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache, - builtInCMapCache) { + function Page({ pdfManager, xref, pageIndex, pageDict, ref, fontCache, + builtInCMapCache, pdfFunctionFactory, }) { this.pdfManager = pdfManager; this.pageIndex = pageIndex; this.pageDict = pageDict; @@ -45,6 +45,7 @@ var Page = (function PageClosure() { this.ref = ref; this.fontCache = fontCache; this.builtInCMapCache = builtInCMapCache; + this.pdfFunctionFactory = pdfFunctionFactory; this.evaluatorOptions = pdfManager.evaluatorOptions; this.resourcesPromise = null; @@ -215,6 +216,7 @@ var Page = (function PageClosure() { fontCache: this.fontCache, builtInCMapCache: this.builtInCMapCache, options: this.evaluatorOptions, + pdfFunctionFactory: this.pdfFunctionFactory, }); var dataPromises = Promise.all([contentStreamPromise, resourcesPromise]); @@ -290,6 +292,7 @@ var Page = (function PageClosure() { fontCache: this.fontCache, builtInCMapCache: this.builtInCMapCache, options: this.evaluatorOptions, + pdfFunctionFactory: this.pdfFunctionFactory, }); return partialEvaluator.getTextContent({ @@ -361,6 +364,12 @@ var PDFDocument = (function PDFDocumentClosure() { this.pdfManager = pdfManager; this.stream = stream; this.xref = new XRef(stream, pdfManager); + + let evaluatorOptions = pdfManager.evaluatorOptions; + this.pdfFunctionFactory = new PDFFunctionFactory({ + xref: this.xref, + isEvalSupported: evaluatorOptions.isEvalSupported, + }); } function find(stream, needle, limit, backwards) { @@ -528,14 +537,19 @@ var PDFDocument = (function PDFDocumentClosure() { this.xref.parse(recoveryMode); var pageFactory = { createPage: (pageIndex, dict, ref, fontCache, builtInCMapCache) => { - return new Page(this.pdfManager, this.xref, pageIndex, dict, ref, - fontCache, builtInCMapCache); + return new Page({ + pdfManager: this.pdfManager, + xref: this.xref, + pageIndex, + pageDict: dict, + ref, + fontCache, + builtInCMapCache, + pdfFunctionFactory: this.pdfFunctionFactory, + }); }, }; this.catalog = new Catalog(this.pdfManager, this.xref, pageFactory); - - let evaluatorOptions = this.pdfManager.evaluatorOptions; - PDFFunction.setIsEvalSupported(evaluatorOptions.isEvalSupported); }, get numPages() { var linearization = this.linearization; diff --git a/src/core/evaluator.js b/src/core/evaluator.js index 5db338ab0..73672b51f 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -38,12 +38,12 @@ import { getSerifFonts, getStdFontMap, getSymbolsFonts } from './standard_fonts'; import { getTilingPatternIR, Pattern } from './pattern'; -import { isPDFFunction, PDFFunction } from './function'; import { Lexer, Parser } from './parser'; import { bidi } from './bidi'; import { ColorSpace } from './colorspace'; import { getGlyphsUnicode } from './glyphlist'; import { getMetrics } from './metrics'; +import { isPDFFunction } from './function'; import { MurmurHash3_64 } from './murmurhash3'; import { PDFImage } from './image'; @@ -58,22 +58,26 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { }; function NativeImageDecoder({ xref, resources, handler, - forceDataSchema = false, }) { + forceDataSchema = false, + pdfFunctionFactory, }) { this.xref = xref; this.resources = resources; this.handler = handler; this.forceDataSchema = forceDataSchema; + this.pdfFunctionFactory = pdfFunctionFactory; } NativeImageDecoder.prototype = { canDecode(image) { return image instanceof JpegStream && - NativeImageDecoder.isDecodable(image, this.xref, this.resources); + NativeImageDecoder.isDecodable(image, this.xref, this.resources, + this.pdfFunctionFactory); }, decode(image) { // For natively supported JPEGs send them to the main thread for decoding. var dict = image.dict; var colorSpace = dict.get('ColorSpace', 'CS'); - colorSpace = ColorSpace.parse(colorSpace, this.xref, this.resources); + colorSpace = ColorSpace.parse(colorSpace, this.xref, this.resources, + this.pdfFunctionFactory); var numComps = colorSpace.numComps; var decodePromise = this.handler.sendWithPromise('JpegDecode', [image.getIR(this.forceDataSchema), numComps]); @@ -87,30 +91,35 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { * Checks if the image can be decoded and displayed by the browser without any * further processing such as color space conversions. */ - NativeImageDecoder.isSupported = function(image, xref, res) { + NativeImageDecoder.isSupported = function(image, xref, res, + pdfFunctionFactory) { var dict = image.dict; if (dict.has('DecodeParms') || dict.has('DP')) { return false; } - var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res); + var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res, + pdfFunctionFactory); return (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB') && cs.isDefaultDecode(dict.getArray('Decode', 'D')); }; /** * Checks if the image can be decoded by the browser. */ - NativeImageDecoder.isDecodable = function(image, xref, res) { + NativeImageDecoder.isDecodable = function(image, xref, res, + pdfFunctionFactory) { var dict = image.dict; if (dict.has('DecodeParms') || dict.has('DP')) { return false; } - var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res); + var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res, + pdfFunctionFactory); return (cs.numComps === 1 || cs.numComps === 3) && cs.isDefaultDecode(dict.getArray('Decode', 'D')); }; function PartialEvaluator({ pdfManager, xref, handler, pageIndex, idFactory, - fontCache, builtInCMapCache, options = null, }) { + fontCache, builtInCMapCache, options = null, + pdfFunctionFactory, }) { this.pdfManager = pdfManager; this.xref = xref; this.handler = handler; @@ -119,6 +128,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { this.fontCache = fontCache; this.builtInCMapCache = builtInCMapCache; this.options = options || DefaultPartialEvaluatorOptions; + this.pdfFunctionFactory = pdfFunctionFactory; this.fetchBuiltInCMap = (name) => { var cachedCMap = this.builtInCMapCache[name]; @@ -302,12 +312,14 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { }; var groupSubtype = group.get('S'); - var colorSpace; + var colorSpace = null; if (isName(groupSubtype, 'Transparency')) { groupOptions.isolated = (group.get('I') || false); groupOptions.knockout = (group.get('K') || false); - colorSpace = (group.has('CS') ? - ColorSpace.parse(group.get('CS'), this.xref, resources) : null); + if (group.has('CS')) { + colorSpace = ColorSpace.parse(group.get('CS'), this.xref, resources, + this.pdfFunctionFactory); + } } if (smask && smask.backdrop) { @@ -398,6 +410,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { xref: this.xref, res: resources, image, + pdfFunctionFactory: this.pdfFunctionFactory, }); // We force the use of RGBA_32BPP images here, because we can't handle // any other kind. @@ -415,7 +428,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { if (nativeImageDecoderSupport !== NativeImageDecoding.NONE && !softMask && !mask && image instanceof JpegStream && - NativeImageDecoder.isSupported(image, this.xref, resources)) { + NativeImageDecoder.isSupported(image, this.xref, resources, + this.pdfFunctionFactory)) { // These JPEGs don't need any more processing so we can just send it. operatorList.addOp(OPS.paintJpegXObject, args); this.handler.send('obj', [objId, this.pageIndex, 'JpegStream', @@ -439,6 +453,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { resources, handler: this.handler, forceDataSchema: this.options.forceDataSchema, + pdfFunctionFactory: this.pdfFunctionFactory, }); } @@ -448,6 +463,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { res: resources, image, nativeDecoder: nativeImageDecoder, + pdfFunctionFactory: this.pdfFunctionFactory, }).then((imageObj) => { var imgData = imageObj.createImageData(/* forceRGBA = */ false); this.handler.send('obj', [objId, this.pageIndex, 'Image', imgData], @@ -479,7 +495,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { // we will build a map of integer values in range 0..255 to be fast. var transferObj = smask.get('TR'); if (isPDFFunction(transferObj)) { - var transferFn = PDFFunction.parse(this.xref, transferObj); + let transferFn = this.pdfFunctionFactory.create(transferObj); var transferMap = new Uint8Array(256); var tmp = new Float32Array(1); for (var i = 0; i < 256; i++) { @@ -865,7 +881,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { var shading = dict.get('Shading'); var matrix = dict.getArray('Matrix'); pattern = Pattern.parseShading(shading, matrix, this.xref, resources, - this.handler); + this.handler, this.pdfFunctionFactory); operatorList.addOp(fn, pattern.getIR()); return Promise.resolve(); } @@ -1040,11 +1056,13 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { case OPS.setFillColorSpace: stateManager.state.fillColorSpace = - ColorSpace.parse(args[0], xref, resources); + ColorSpace.parse(args[0], xref, resources, + self.pdfFunctionFactory); continue; case OPS.setStrokeColorSpace: stateManager.state.strokeColorSpace = - ColorSpace.parse(args[0], xref, resources); + ColorSpace.parse(args[0], xref, resources, + self.pdfFunctionFactory); continue; case OPS.setFillColor: cs = stateManager.state.fillColorSpace; @@ -1117,7 +1135,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { } var shadingFill = Pattern.parseShading(shading, null, xref, - resources, self.handler); + resources, self.handler, self.pdfFunctionFactory); var patternIR = shadingFill.getIR(); args = [patternIR]; fn = OPS.shadingFill; diff --git a/src/core/function.js b/src/core/function.js index a07f4c27a..5ad151206 100644 --- a/src/core/function.js +++ b/src/core/function.js @@ -25,21 +25,53 @@ let IsEvalSupportedCached = { }, }; -var PDFFunction = (function PDFFunctionClosure() { - var CONSTRUCT_SAMPLED = 0; - var CONSTRUCT_INTERPOLATED = 2; - var CONSTRUCT_STICHED = 3; - var CONSTRUCT_POSTSCRIPT = 4; +class PDFFunctionFactory { + constructor({ xref, isEvalSupported = true, }) { + this.xref = xref; + this.isEvalSupported = isEvalSupported !== false; + } - let isEvalSupported = true; + create(fn) { + return PDFFunction.parse({ + xref: this.xref, + isEvalSupported: this.isEvalSupported, + fn, + }); + } + + createFromArray(fnObj) { + return PDFFunction.parseArray({ + xref: this.xref, + isEvalSupported: this.isEvalSupported, + fnObj, + }); + } + + createFromIR(IR) { + return PDFFunction.fromIR({ + xref: this.xref, + isEvalSupported: this.isEvalSupported, + IR, + }); + } + + createIR(fn) { + return PDFFunction.getIR({ + xref: this.xref, + isEvalSupported: this.isEvalSupported, + fn, + }); + } +} + +var PDFFunction = (function PDFFunctionClosure() { + const CONSTRUCT_SAMPLED = 0; + const CONSTRUCT_INTERPOLATED = 2; + const CONSTRUCT_STICHED = 3; + const CONSTRUCT_POSTSCRIPT = 4; return { - setIsEvalSupported(support = true) { - isEvalSupported = support !== false; - }, - - getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps, - str) { + getSampleArray(size, outputSize, bps, stream) { var i, ii; var length = 1; for (i = 0, ii = size.length; i < ii; i++) { @@ -53,7 +85,7 @@ var PDFFunction = (function PDFFunctionClosure() { // 32 is a valid bps so shifting won't work var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1); - var strBytes = str.getBytes((length * bps + 7) / 8); + var strBytes = stream.getBytes((length * bps + 7) / 8); var strIdx = 0; for (i = 0; i < length; i++) { while (codeSize < bps) { @@ -68,7 +100,7 @@ var PDFFunction = (function PDFFunctionClosure() { return array; }, - getIR: function PDFFunction_getIR(xref, fn) { + getIR({ xref, isEvalSupported, fn, }) { var dict = fn.dict; if (!dict) { dict = fn; @@ -86,48 +118,49 @@ var PDFFunction = (function PDFFunctionClosure() { throw new FormatError('Unknown type of function'); } - return typeFn.call(this, fn, dict, xref); + return typeFn.call(this, { xref, isEvalSupported, fn, dict, }); }, - fromIR: function PDFFunction_fromIR(IR) { + fromIR({ xref, isEvalSupported, IR, }) { var type = IR[0]; switch (type) { case CONSTRUCT_SAMPLED: - return this.constructSampledFromIR(IR); + return this.constructSampledFromIR({ xref, isEvalSupported, IR, }); case CONSTRUCT_INTERPOLATED: - return this.constructInterpolatedFromIR(IR); + return this.constructInterpolatedFromIR({ xref, isEvalSupported, + IR, }); case CONSTRUCT_STICHED: - return this.constructStichedFromIR(IR); + return this.constructStichedFromIR({ xref, isEvalSupported, IR, }); // case CONSTRUCT_POSTSCRIPT: default: - return this.constructPostScriptFromIR(IR); + return this.constructPostScriptFromIR({ xref, isEvalSupported, IR, }); } }, - parse: function PDFFunction_parse(xref, fn) { - var IR = this.getIR(xref, fn); - return this.fromIR(IR); + parse({ xref, isEvalSupported, fn, }) { + let IR = this.getIR({ xref, isEvalSupported, fn, }); + return this.fromIR({ xref, isEvalSupported, IR, }); }, - parseArray: function PDFFunction_parseArray(xref, fnObj) { + parseArray({ xref, isEvalSupported, fnObj, }) { if (!Array.isArray(fnObj)) { // not an array -- parsing as regular function - return this.parse(xref, fnObj); + return this.parse({ xref, isEvalSupported, fn: fnObj, }); } var fnArray = []; for (var j = 0, jj = fnObj.length; j < jj; j++) { - var obj = xref.fetchIfRef(fnObj[j]); - fnArray.push(PDFFunction.parse(xref, obj)); + fnArray.push(this.parse({ xref, isEvalSupported, + fn: xref.fetchIfRef(fnObj[j]), })); } - return function (src, srcOffset, dest, destOffset) { + return function(src, srcOffset, dest, destOffset) { for (var i = 0, ii = fnArray.length; i < ii; i++) { fnArray[i](src, srcOffset, dest, destOffset + i); } }; }, - constructSampled: function PDFFunction_constructSampled(str, dict) { + constructSampled({ xref, isEvalSupported, fn, dict, }) { function toMultiArray(arr) { var inputLength = arr.length; var out = []; @@ -177,7 +210,7 @@ var PDFFunction = (function PDFFunctionClosure() { decode = toMultiArray(decode); } - var samples = this.getSampleArray(size, outputSize, bps, str); + var samples = this.getSampleArray(size, outputSize, bps, fn); return [ CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size, @@ -185,7 +218,7 @@ var PDFFunction = (function PDFFunctionClosure() { ]; }, - constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) { + constructSampledFromIR({ xref, isEvalSupported, IR, }) { // See chapter 3, page 109 of the PDF reference function interpolate(x, xmin, xmax, ymin, ymax) { return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin))); @@ -270,8 +303,7 @@ var PDFFunction = (function PDFFunctionClosure() { }; }, - constructInterpolated: function PDFFunction_constructInterpolated(str, - dict) { + constructInterpolated({ xref, isEvalSupported, fn, dict, }) { var c0 = dict.getArray('C0') || [0]; var c1 = dict.getArray('C1') || [1]; var n = dict.get('N'); @@ -290,8 +322,7 @@ var PDFFunction = (function PDFFunctionClosure() { return [CONSTRUCT_INTERPOLATED, c0, diff, n]; }, - constructInterpolatedFromIR: - function PDFFunction_constructInterpolatedFromIR(IR) { + constructInterpolatedFromIR({ xref, isEvalSupported, IR, }) { var c0 = IR[1]; var diff = IR[2]; var n = IR[3]; @@ -308,7 +339,7 @@ var PDFFunction = (function PDFFunctionClosure() { }; }, - constructStiched: function PDFFunction_constructStiched(fn, dict, xref) { + constructStiched({ xref, isEvalSupported, fn, dict, }) { var domain = dict.getArray('Domain'); if (!domain) { @@ -323,7 +354,8 @@ var PDFFunction = (function PDFFunctionClosure() { var fnRefs = dict.get('Functions'); var fns = []; for (var i = 0, ii = fnRefs.length; i < ii; ++i) { - fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i]))); + fns.push(this.getIR({ xref, isEvalSupported, + fn: xref.fetchIfRef(fnRefs[i]), })); } var bounds = dict.getArray('Bounds'); @@ -332,7 +364,7 @@ var PDFFunction = (function PDFFunctionClosure() { return [CONSTRUCT_STICHED, domain, bounds, encode, fns]; }, - constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) { + constructStichedFromIR({ xref, isEvalSupported, IR, }) { var domain = IR[1]; var bounds = IR[2]; var encode = IR[3]; @@ -341,7 +373,7 @@ var PDFFunction = (function PDFFunctionClosure() { var tmpBuf = new Float32Array(1); for (var i = 0, ii = fnsIR.length; i < ii; i++) { - fns.push(PDFFunction.fromIR(fnsIR[i])); + fns.push(this.fromIR({ xref, isEvalSupported, IR: fnsIR[i], })); } return function constructStichedFromIRResult(src, srcOffset, @@ -387,8 +419,7 @@ var PDFFunction = (function PDFFunctionClosure() { }; }, - constructPostScript: function PDFFunction_constructPostScript(fn, dict, - xref) { + constructPostScript({ xref, isEvalSupported, fn, dict, }) { var domain = dict.getArray('Domain'); var range = dict.getArray('Range'); @@ -407,8 +438,7 @@ var PDFFunction = (function PDFFunctionClosure() { return [CONSTRUCT_POSTSCRIPT, domain, range, code]; }, - constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR( - IR) { + constructPostScriptFromIR({ xref, isEvalSupported, IR, }) { var domain = IR[1]; var range = IR[2]; var code = IR[3]; @@ -1151,7 +1181,7 @@ var PostScriptCompiler = (function PostScriptCompilerClosure() { export { isPDFFunction, - PDFFunction, + PDFFunctionFactory, PostScriptEvaluator, PostScriptCompiler, }; diff --git a/src/core/image.js b/src/core/image.js index 9408315d7..9010bf970 100644 --- a/src/core/image.js +++ b/src/core/image.js @@ -75,7 +75,7 @@ var PDFImage = (function PDFImageClosure() { } function PDFImage({ xref, res, image, smask = null, mask = null, - isMask = false, }) { + isMask = false, pdfFunctionFactory, }) { this.image = image; var dict = image.dict; if (dict.has('Filter')) { @@ -138,7 +138,8 @@ var PDFImage = (function PDFImageClosure() { 'color components not supported.'); } } - this.colorSpace = ColorSpace.parse(colorSpace, xref, res); + this.colorSpace = ColorSpace.parse(colorSpace, xref, res, + pdfFunctionFactory); this.numComps = this.colorSpace.numComps; } @@ -165,6 +166,7 @@ var PDFImage = (function PDFImageClosure() { xref, res, image: smask, + pdfFunctionFactory, }); } else if (mask) { if (isStream(mask)) { @@ -177,6 +179,7 @@ var PDFImage = (function PDFImageClosure() { res, image: mask, isMask: true, + pdfFunctionFactory, }); } } else { @@ -190,7 +193,8 @@ var PDFImage = (function PDFImageClosure() { * with a PDFImage when the image is ready to be used. */ PDFImage.buildImage = function({ handler, xref, res, image, - nativeDecoder = null, }) { + nativeDecoder = null, + pdfFunctionFactory, }) { var imagePromise = handleImageData(image, nativeDecoder); var smaskPromise; var maskPromise; @@ -224,13 +228,13 @@ var PDFImage = (function PDFImageClosure() { image: imageData, smask: smaskData, mask: maskData, + pdfFunctionFactory, }); }); }; PDFImage.createMask = function({ imgArray, width, height, imageIsFromDecodeStream, inverseDecode, }) { - // |imgArray| might not contain full data for every pixel of the mask, so // we need to distinguish between |computedLength| and |actualLength|. // In particular, if inverseDecode is true, then the array we return must diff --git a/src/core/pattern.js b/src/core/pattern.js index c20fda95d..a8df287b7 100644 --- a/src/core/pattern.js +++ b/src/core/pattern.js @@ -20,7 +20,6 @@ import { } from '../shared/util'; import { ColorSpace } from './colorspace'; import { isStream } from './primitives'; -import { PDFFunction } from './function'; var ShadingType = { FUNCTION_BASED: 1, @@ -46,9 +45,8 @@ var Pattern = (function PatternClosure() { }, }; - Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref, - res, handler) { - + Pattern.parseShading = function(shading, matrix, xref, res, handler, + pdfFunctionFactory) { var dict = isStream(shading) ? shading.dict : shading; var type = dict.get('ShadingType'); @@ -57,12 +55,14 @@ var Pattern = (function PatternClosure() { case ShadingType.AXIAL: case ShadingType.RADIAL: // Both radial and axial shadings are handled by RadialAxial shading. - return new Shadings.RadialAxial(dict, matrix, xref, res); + return new Shadings.RadialAxial(dict, matrix, xref, res, + pdfFunctionFactory); case ShadingType.FREE_FORM_MESH: case ShadingType.LATTICE_FORM_MESH: case ShadingType.COONS_PATCH_MESH: case ShadingType.TENSOR_PATCH_MESH: - return new Shadings.Mesh(shading, matrix, xref, res); + return new Shadings.Mesh(shading, matrix, xref, res, + pdfFunctionFactory); default: throw new FormatError('Unsupported ShadingType: ' + type); } @@ -88,13 +88,13 @@ Shadings.SMALL_NUMBER = 1e-6; // Radial and axial shading have very similar implementations // If needed, the implementations can be broken into two classes Shadings.RadialAxial = (function RadialAxialClosure() { - function RadialAxial(dict, matrix, xref, res) { + function RadialAxial(dict, matrix, xref, res, pdfFunctionFactory) { this.matrix = matrix; this.coordsArr = dict.getArray('Coords'); this.shadingType = dict.get('ShadingType'); this.type = 'Pattern'; var cs = dict.get('ColorSpace', 'CS'); - cs = ColorSpace.parse(cs, xref, res); + cs = ColorSpace.parse(cs, xref, res, pdfFunctionFactory); this.cs = cs; var t0 = 0.0, t1 = 1.0; @@ -132,7 +132,7 @@ Shadings.RadialAxial = (function RadialAxialClosure() { this.extendEnd = extendEnd; var fnObj = dict.get('Function'); - var fn = PDFFunction.parseArray(xref, fnObj); + var fn = pdfFunctionFactory.createFromArray(fnObj); // 10 samples seems good enough for now, but probably won't work // if there are sharp color changes. Ideally, we would implement @@ -711,7 +711,7 @@ Shadings.Mesh = (function MeshClosure() { } } - function Mesh(stream, matrix, xref, res) { + function Mesh(stream, matrix, xref, res, pdfFunctionFactory) { if (!isStream(stream)) { throw new FormatError('Mesh data is not a stream'); } @@ -721,13 +721,13 @@ Shadings.Mesh = (function MeshClosure() { this.type = 'Pattern'; this.bbox = dict.getArray('BBox'); var cs = dict.get('ColorSpace', 'CS'); - cs = ColorSpace.parse(cs, xref, res); + cs = ColorSpace.parse(cs, xref, res, pdfFunctionFactory); this.cs = cs; this.background = dict.has('Background') ? cs.getRgb(dict.get('Background'), 0) : null; var fnObj = dict.get('Function'); - var fn = fnObj ? PDFFunction.parseArray(xref, fnObj) : null; + var fn = fnObj ? pdfFunctionFactory.createFromArray(fnObj) : null; this.coords = []; this.colors = []; diff --git a/test/unit/colorspace_spec.js b/test/unit/colorspace_spec.js index 2c37f0fb3..63c0db66f 100644 --- a/test/unit/colorspace_spec.js +++ b/test/unit/colorspace_spec.js @@ -16,6 +16,7 @@ import { Dict, Name, Ref } from '../../src/core/primitives'; import { Stream, StringStream } from '../../src/core/stream'; import { ColorSpace } from '../../src/core/colorspace'; +import { PDFFunctionFactory } from '../../src/core/function'; import { XRefMock } from './test_utils'; describe('colorspace', function () { @@ -54,7 +55,10 @@ describe('colorspace', function () { }]); let res = new Dict(); - let colorSpace = ColorSpace.parse(cs, xref, res); + let pdfFunctionFactory = new PDFFunctionFactory({ + xref, + }); + let colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory); let testSrc = new Uint8Array([27, 125, 250, 131]); let testDest = new Uint8Array(4 * 4 * 3); @@ -92,7 +96,10 @@ describe('colorspace', function () { }]); let res = new Dict(); - let colorSpace = ColorSpace.parse(cs, xref, res); + let pdfFunctionFactory = new PDFFunctionFactory({ + xref, + }); + let colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory); let testSrc = new Uint8Array([27, 125, 250, 131]); let testDest = new Uint8Array(3 * 3 * 3); @@ -126,7 +133,10 @@ describe('colorspace', function () { }]); let res = new Dict(); - let colorSpace = ColorSpace.parse(cs, xref, res); + let pdfFunctionFactory = new PDFFunctionFactory({ + xref, + }); + let colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory); let testSrc = new Uint8Array([ 27, 125, 250, @@ -169,7 +179,10 @@ describe('colorspace', function () { }]); let res = new Dict(); - let colorSpace = ColorSpace.parse(cs, xref, res); + let pdfFunctionFactory = new PDFFunctionFactory({ + xref, + }); + let colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory); let testSrc = new Uint8Array([ 27, 125, 250, @@ -208,7 +221,10 @@ describe('colorspace', function () { }]); let res = new Dict(); - let colorSpace = ColorSpace.parse(cs, xref, res); + let pdfFunctionFactory = new PDFFunctionFactory({ + xref, + }); + let colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory); let testSrc = new Uint8Array([ 27, 125, 250, 128, @@ -251,7 +267,10 @@ describe('colorspace', function () { }]); let res = new Dict(); - let colorSpace = ColorSpace.parse(cs, xref, res); + let pdfFunctionFactory = new PDFFunctionFactory({ + xref, + }); + let colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory); let testSrc = new Uint8Array([ 27, 125, 250, 128, @@ -298,7 +317,10 @@ describe('colorspace', function () { }]); let res = new Dict(); - let colorSpace = ColorSpace.parse(cs, xref, res); + let pdfFunctionFactory = new PDFFunctionFactory({ + xref, + }); + let colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory); let testSrc = new Uint8Array([27, 125, 250, 131]); let testDest = new Uint8Array(4 * 4 * 3); @@ -348,7 +370,10 @@ describe('colorspace', function () { }]); let res = new Dict(); - let colorSpace = ColorSpace.parse(cs, xref, res); + let pdfFunctionFactory = new PDFFunctionFactory({ + xref, + }); + let colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory); let testSrc = new Uint8Array([ 27, 125, 250, @@ -395,7 +420,10 @@ describe('colorspace', function () { }]); let res = new Dict(); - let colorSpace = ColorSpace.parse(cs, xref, res); + let pdfFunctionFactory = new PDFFunctionFactory({ + xref, + }); + let colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory); let testSrc = new Uint8Array([ 27, 25, 50, @@ -445,7 +473,10 @@ describe('colorspace', function () { }]); let res = new Dict(); - let colorSpace = ColorSpace.parse(cs, xref, res); + let pdfFunctionFactory = new PDFFunctionFactory({ + xref, + }); + let colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory); let testSrc = new Uint8Array([2, 2, 0, 1]); let testDest = new Uint8Array(3 * 3 * 3); @@ -497,7 +528,10 @@ describe('colorspace', function () { }]); let res = new Dict(); - let colorSpace = ColorSpace.parse(cs, xref, res); + let pdfFunctionFactory = new PDFFunctionFactory({ + xref, + }); + let colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory); let testSrc = new Uint8Array([27, 25, 50, 31]); let testDest = new Uint8Array(3 * 3 * 3); diff --git a/test/unit/document_spec.js b/test/unit/document_spec.js index 3fac13476..bb6a84875 100644 --- a/test/unit/document_spec.js +++ b/test/unit/document_spec.js @@ -18,16 +18,14 @@ import { Page } from '../../src/core/document'; describe('document', function () { describe('Page', function () { it('should create correct objId using the idFactory', function () { - var page1 = new Page(/* pdfManager = */ { }, /* xref = */ null, - /* pageIndex = */ 0, - /* pageDict = */ null, /* ref = */ null, - /* fontCache = */ null, - /* builtInCMapCache = */ null); - var page2 = new Page(/* pdfManager = */ { }, /* xref = */ null, - /* pageIndex = */ 1, - /* pageDict = */ null, /* ref = */ null, - /* fontCache = */ null, - /* builtInCMapCache = */ null); + var page1 = new Page({ + pdfManager: { }, + pageIndex: 0, + }); + var page2 = new Page({ + pdfManager: { }, + pageIndex: 1, + }); var idFactory1 = page1.idFactory, idFactory2 = page2.idFactory;