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:
parent
5c961c76bb
commit
b8ec518a1e
@ -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]);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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 = [];
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user