Split the existing PDFFunction in two classes, a private PDFFunction and a public PDFFunctionFactory, and utilize the latter in PDFDocument to allow various code to access the methods of PDFFunction`

*Follow-up to PR 8909.*

This requires us to pass around `pdfFunctionFactory` to quite a lot of existing code, however I don't see another way of handling this while still guaranteeing that we can access `PDFFunction` as freely as in the old code.

Please note that the patch passes all tests locally (unit, font, reference), and I *very* much hope that we have sufficient test-coverage for the code in question to catch any typos/mistakes in the re-factoring.
This commit is contained in:
Jonas Jenwald 2017-09-19 13:49:30 +02:00
parent 5c961c76bb
commit b8ec518a1e
8 changed files with 226 additions and 124 deletions

View File

@ -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]);

View File

@ -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;

View File

@ -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;

View File

@ -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,
};

View File

@ -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

View File

@ -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 = [];

View File

@ -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);

View File

@ -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;