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 { FormatError, info, isString, shadow, warn } from '../shared/util';
import { isDict, isName, isStream } from './primitives'; import { isDict, isName, isStream } from './primitives';
import { PDFFunction } from './function';
var ColorSpace = (function ColorSpaceClosure() { var ColorSpace = (function ColorSpaceClosure() {
/** /**
@ -200,12 +199,12 @@ var ColorSpace = (function ColorSpaceClosure() {
usesZeroToOneRange: true, usesZeroToOneRange: true,
}; };
ColorSpace.parse = function ColorSpace_parse(cs, xref, res) { ColorSpace.parse = function(cs, xref, res, pdfFunctionFactory) {
let IR = ColorSpace.parseToIR(cs, xref, res); let IR = ColorSpace.parseToIR(cs, xref, res, pdfFunctionFactory);
return ColorSpace.fromIR(IR); 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 name = Array.isArray(IR) ? IR[0] : IR;
var whitePoint, blackPoint, gamma; var whitePoint, blackPoint, gamma;
@ -230,21 +229,23 @@ var ColorSpace = (function ColorSpaceClosure() {
case 'PatternCS': case 'PatternCS':
var basePatternCS = IR[1]; var basePatternCS = IR[1];
if (basePatternCS) { if (basePatternCS) {
basePatternCS = ColorSpace.fromIR(basePatternCS); basePatternCS = ColorSpace.fromIR(basePatternCS, pdfFunctionFactory);
} }
return new PatternCS(basePatternCS); return new PatternCS(basePatternCS);
case 'IndexedCS': case 'IndexedCS':
var baseIndexedCS = IR[1]; var baseIndexedCS = IR[1];
var hiVal = IR[2]; var hiVal = IR[2];
var lookup = IR[3]; var lookup = IR[3];
return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), hiVal, lookup); return new IndexedCS(ColorSpace.fromIR(baseIndexedCS,
pdfFunctionFactory),
hiVal, lookup);
case 'AlternateCS': case 'AlternateCS':
var numComps = IR[1]; var numComps = IR[1];
var alt = IR[2]; var alt = IR[2];
var tintFnIR = IR[3]; var tintFnIR = IR[3];
return new AlternateCS(numComps, ColorSpace.fromIR(alt,
return new AlternateCS(numComps, ColorSpace.fromIR(alt), pdfFunctionFactory),
PDFFunction.fromIR(tintFnIR)); pdfFunctionFactory.createFromIR(tintFnIR));
case 'LabCS': case 'LabCS':
whitePoint = IR[1]; whitePoint = IR[1];
blackPoint = IR[2]; 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)) { if (isName(cs)) {
var colorSpaces = res.get('ColorSpace'); var colorSpaces = res.get('ColorSpace');
if (isDict(colorSpaces)) { if (isDict(colorSpaces)) {
@ -317,10 +318,11 @@ var ColorSpace = (function ColorSpaceClosure() {
numComps = dict.get('N'); numComps = dict.get('N');
alt = dict.get('Alternate'); alt = dict.get('Alternate');
if (alt) { 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 // Parse the /Alternate CS to ensure that the number of components
// are correct, and also (indirectly) that it is not a PatternCS. // 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) { if (altCS.numComps === numComps) {
return altIR; return altIR;
} }
@ -337,12 +339,14 @@ var ColorSpace = (function ColorSpaceClosure() {
case 'Pattern': case 'Pattern':
var basePatternCS = cs[1] || null; var basePatternCS = cs[1] || null;
if (basePatternCS) { if (basePatternCS) {
basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res); basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res,
pdfFunctionFactory);
} }
return ['PatternCS', basePatternCS]; return ['PatternCS', basePatternCS];
case 'Indexed': case 'Indexed':
case 'I': 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 hiVal = xref.fetchIfRef(cs[2]) + 1;
var lookup = xref.fetchIfRef(cs[3]); var lookup = xref.fetchIfRef(cs[3]);
if (isStream(lookup)) { if (isStream(lookup)) {
@ -353,8 +357,8 @@ var ColorSpace = (function ColorSpaceClosure() {
case 'DeviceN': case 'DeviceN':
var name = xref.fetchIfRef(cs[1]); var name = xref.fetchIfRef(cs[1]);
numComps = Array.isArray(name) ? name.length : 1; numComps = Array.isArray(name) ? name.length : 1;
alt = ColorSpace.parseToIR(cs[2], xref, res); alt = ColorSpace.parseToIR(cs[2], xref, res, pdfFunctionFactory);
var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3])); let tintFnIR = pdfFunctionFactory.createIR(xref.fetchIfRef(cs[3]));
return ['AlternateCS', numComps, alt, tintFnIR]; return ['AlternateCS', numComps, alt, tintFnIR];
case 'Lab': case 'Lab':
params = xref.fetchIfRef(cs[1]); params = xref.fetchIfRef(cs[1]);

View File

@ -24,7 +24,7 @@ import { OperatorList, PartialEvaluator } from './evaluator';
import { AnnotationFactory } from './annotation'; import { AnnotationFactory } from './annotation';
import { calculateMD5 } from './crypto'; import { calculateMD5 } from './crypto';
import { Linearization } from './parser'; import { Linearization } from './parser';
import { PDFFunction } from './function'; import { PDFFunctionFactory } from './function';
var Page = (function PageClosure() { var Page = (function PageClosure() {
@ -36,8 +36,8 @@ var Page = (function PageClosure() {
(intent === 'print' && annotation.printable); (intent === 'print' && annotation.printable);
} }
function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache, function Page({ pdfManager, xref, pageIndex, pageDict, ref, fontCache,
builtInCMapCache) { builtInCMapCache, pdfFunctionFactory, }) {
this.pdfManager = pdfManager; this.pdfManager = pdfManager;
this.pageIndex = pageIndex; this.pageIndex = pageIndex;
this.pageDict = pageDict; this.pageDict = pageDict;
@ -45,6 +45,7 @@ var Page = (function PageClosure() {
this.ref = ref; this.ref = ref;
this.fontCache = fontCache; this.fontCache = fontCache;
this.builtInCMapCache = builtInCMapCache; this.builtInCMapCache = builtInCMapCache;
this.pdfFunctionFactory = pdfFunctionFactory;
this.evaluatorOptions = pdfManager.evaluatorOptions; this.evaluatorOptions = pdfManager.evaluatorOptions;
this.resourcesPromise = null; this.resourcesPromise = null;
@ -215,6 +216,7 @@ var Page = (function PageClosure() {
fontCache: this.fontCache, fontCache: this.fontCache,
builtInCMapCache: this.builtInCMapCache, builtInCMapCache: this.builtInCMapCache,
options: this.evaluatorOptions, options: this.evaluatorOptions,
pdfFunctionFactory: this.pdfFunctionFactory,
}); });
var dataPromises = Promise.all([contentStreamPromise, resourcesPromise]); var dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
@ -290,6 +292,7 @@ var Page = (function PageClosure() {
fontCache: this.fontCache, fontCache: this.fontCache,
builtInCMapCache: this.builtInCMapCache, builtInCMapCache: this.builtInCMapCache,
options: this.evaluatorOptions, options: this.evaluatorOptions,
pdfFunctionFactory: this.pdfFunctionFactory,
}); });
return partialEvaluator.getTextContent({ return partialEvaluator.getTextContent({
@ -361,6 +364,12 @@ var PDFDocument = (function PDFDocumentClosure() {
this.pdfManager = pdfManager; this.pdfManager = pdfManager;
this.stream = stream; this.stream = stream;
this.xref = new XRef(stream, pdfManager); 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) { function find(stream, needle, limit, backwards) {
@ -528,14 +537,19 @@ var PDFDocument = (function PDFDocumentClosure() {
this.xref.parse(recoveryMode); this.xref.parse(recoveryMode);
var pageFactory = { var pageFactory = {
createPage: (pageIndex, dict, ref, fontCache, builtInCMapCache) => { createPage: (pageIndex, dict, ref, fontCache, builtInCMapCache) => {
return new Page(this.pdfManager, this.xref, pageIndex, dict, ref, return new Page({
fontCache, builtInCMapCache); pdfManager: this.pdfManager,
xref: this.xref,
pageIndex,
pageDict: dict,
ref,
fontCache,
builtInCMapCache,
pdfFunctionFactory: this.pdfFunctionFactory,
});
}, },
}; };
this.catalog = new Catalog(this.pdfManager, this.xref, pageFactory); this.catalog = new Catalog(this.pdfManager, this.xref, pageFactory);
let evaluatorOptions = this.pdfManager.evaluatorOptions;
PDFFunction.setIsEvalSupported(evaluatorOptions.isEvalSupported);
}, },
get numPages() { get numPages() {
var linearization = this.linearization; var linearization = this.linearization;

View File

@ -38,12 +38,12 @@ import {
getSerifFonts, getStdFontMap, getSymbolsFonts getSerifFonts, getStdFontMap, getSymbolsFonts
} from './standard_fonts'; } from './standard_fonts';
import { getTilingPatternIR, Pattern } from './pattern'; import { getTilingPatternIR, Pattern } from './pattern';
import { isPDFFunction, PDFFunction } from './function';
import { Lexer, Parser } from './parser'; import { Lexer, Parser } from './parser';
import { bidi } from './bidi'; import { bidi } from './bidi';
import { ColorSpace } from './colorspace'; import { ColorSpace } from './colorspace';
import { getGlyphsUnicode } from './glyphlist'; import { getGlyphsUnicode } from './glyphlist';
import { getMetrics } from './metrics'; import { getMetrics } from './metrics';
import { isPDFFunction } from './function';
import { MurmurHash3_64 } from './murmurhash3'; import { MurmurHash3_64 } from './murmurhash3';
import { PDFImage } from './image'; import { PDFImage } from './image';
@ -58,22 +58,26 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
}; };
function NativeImageDecoder({ xref, resources, handler, function NativeImageDecoder({ xref, resources, handler,
forceDataSchema = false, }) { forceDataSchema = false,
pdfFunctionFactory, }) {
this.xref = xref; this.xref = xref;
this.resources = resources; this.resources = resources;
this.handler = handler; this.handler = handler;
this.forceDataSchema = forceDataSchema; this.forceDataSchema = forceDataSchema;
this.pdfFunctionFactory = pdfFunctionFactory;
} }
NativeImageDecoder.prototype = { NativeImageDecoder.prototype = {
canDecode(image) { canDecode(image) {
return image instanceof JpegStream && return image instanceof JpegStream &&
NativeImageDecoder.isDecodable(image, this.xref, this.resources); NativeImageDecoder.isDecodable(image, this.xref, this.resources,
this.pdfFunctionFactory);
}, },
decode(image) { decode(image) {
// For natively supported JPEGs send them to the main thread for decoding. // For natively supported JPEGs send them to the main thread for decoding.
var dict = image.dict; var dict = image.dict;
var colorSpace = dict.get('ColorSpace', 'CS'); 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 numComps = colorSpace.numComps;
var decodePromise = this.handler.sendWithPromise('JpegDecode', var decodePromise = this.handler.sendWithPromise('JpegDecode',
[image.getIR(this.forceDataSchema), numComps]); [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 * Checks if the image can be decoded and displayed by the browser without any
* further processing such as color space conversions. * further processing such as color space conversions.
*/ */
NativeImageDecoder.isSupported = function(image, xref, res) { NativeImageDecoder.isSupported = function(image, xref, res,
pdfFunctionFactory) {
var dict = image.dict; var dict = image.dict;
if (dict.has('DecodeParms') || dict.has('DP')) { if (dict.has('DecodeParms') || dict.has('DP')) {
return false; 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') && return (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB') &&
cs.isDefaultDecode(dict.getArray('Decode', 'D')); cs.isDefaultDecode(dict.getArray('Decode', 'D'));
}; };
/** /**
* Checks if the image can be decoded by the browser. * 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; var dict = image.dict;
if (dict.has('DecodeParms') || dict.has('DP')) { if (dict.has('DecodeParms') || dict.has('DP')) {
return false; 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) && return (cs.numComps === 1 || cs.numComps === 3) &&
cs.isDefaultDecode(dict.getArray('Decode', 'D')); cs.isDefaultDecode(dict.getArray('Decode', 'D'));
}; };
function PartialEvaluator({ pdfManager, xref, handler, pageIndex, idFactory, function PartialEvaluator({ pdfManager, xref, handler, pageIndex, idFactory,
fontCache, builtInCMapCache, options = null, }) { fontCache, builtInCMapCache, options = null,
pdfFunctionFactory, }) {
this.pdfManager = pdfManager; this.pdfManager = pdfManager;
this.xref = xref; this.xref = xref;
this.handler = handler; this.handler = handler;
@ -119,6 +128,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
this.fontCache = fontCache; this.fontCache = fontCache;
this.builtInCMapCache = builtInCMapCache; this.builtInCMapCache = builtInCMapCache;
this.options = options || DefaultPartialEvaluatorOptions; this.options = options || DefaultPartialEvaluatorOptions;
this.pdfFunctionFactory = pdfFunctionFactory;
this.fetchBuiltInCMap = (name) => { this.fetchBuiltInCMap = (name) => {
var cachedCMap = this.builtInCMapCache[name]; var cachedCMap = this.builtInCMapCache[name];
@ -302,12 +312,14 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
}; };
var groupSubtype = group.get('S'); var groupSubtype = group.get('S');
var colorSpace; var colorSpace = null;
if (isName(groupSubtype, 'Transparency')) { if (isName(groupSubtype, 'Transparency')) {
groupOptions.isolated = (group.get('I') || false); groupOptions.isolated = (group.get('I') || false);
groupOptions.knockout = (group.get('K') || false); groupOptions.knockout = (group.get('K') || false);
colorSpace = (group.has('CS') ? if (group.has('CS')) {
ColorSpace.parse(group.get('CS'), this.xref, resources) : null); colorSpace = ColorSpace.parse(group.get('CS'), this.xref, resources,
this.pdfFunctionFactory);
}
} }
if (smask && smask.backdrop) { if (smask && smask.backdrop) {
@ -398,6 +410,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
xref: this.xref, xref: this.xref,
res: resources, res: resources,
image, image,
pdfFunctionFactory: this.pdfFunctionFactory,
}); });
// We force the use of RGBA_32BPP images here, because we can't handle // We force the use of RGBA_32BPP images here, because we can't handle
// any other kind. // any other kind.
@ -415,7 +428,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
if (nativeImageDecoderSupport !== NativeImageDecoding.NONE && if (nativeImageDecoderSupport !== NativeImageDecoding.NONE &&
!softMask && !mask && image instanceof JpegStream && !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. // These JPEGs don't need any more processing so we can just send it.
operatorList.addOp(OPS.paintJpegXObject, args); operatorList.addOp(OPS.paintJpegXObject, args);
this.handler.send('obj', [objId, this.pageIndex, 'JpegStream', this.handler.send('obj', [objId, this.pageIndex, 'JpegStream',
@ -439,6 +453,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
resources, resources,
handler: this.handler, handler: this.handler,
forceDataSchema: this.options.forceDataSchema, forceDataSchema: this.options.forceDataSchema,
pdfFunctionFactory: this.pdfFunctionFactory,
}); });
} }
@ -448,6 +463,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
res: resources, res: resources,
image, image,
nativeDecoder: nativeImageDecoder, nativeDecoder: nativeImageDecoder,
pdfFunctionFactory: this.pdfFunctionFactory,
}).then((imageObj) => { }).then((imageObj) => {
var imgData = imageObj.createImageData(/* forceRGBA = */ false); var imgData = imageObj.createImageData(/* forceRGBA = */ false);
this.handler.send('obj', [objId, this.pageIndex, 'Image', imgData], 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. // we will build a map of integer values in range 0..255 to be fast.
var transferObj = smask.get('TR'); var transferObj = smask.get('TR');
if (isPDFFunction(transferObj)) { if (isPDFFunction(transferObj)) {
var transferFn = PDFFunction.parse(this.xref, transferObj); let transferFn = this.pdfFunctionFactory.create(transferObj);
var transferMap = new Uint8Array(256); var transferMap = new Uint8Array(256);
var tmp = new Float32Array(1); var tmp = new Float32Array(1);
for (var i = 0; i < 256; i++) { for (var i = 0; i < 256; i++) {
@ -865,7 +881,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var shading = dict.get('Shading'); var shading = dict.get('Shading');
var matrix = dict.getArray('Matrix'); var matrix = dict.getArray('Matrix');
pattern = Pattern.parseShading(shading, matrix, this.xref, resources, pattern = Pattern.parseShading(shading, matrix, this.xref, resources,
this.handler); this.handler, this.pdfFunctionFactory);
operatorList.addOp(fn, pattern.getIR()); operatorList.addOp(fn, pattern.getIR());
return Promise.resolve(); return Promise.resolve();
} }
@ -1040,11 +1056,13 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
case OPS.setFillColorSpace: case OPS.setFillColorSpace:
stateManager.state.fillColorSpace = stateManager.state.fillColorSpace =
ColorSpace.parse(args[0], xref, resources); ColorSpace.parse(args[0], xref, resources,
self.pdfFunctionFactory);
continue; continue;
case OPS.setStrokeColorSpace: case OPS.setStrokeColorSpace:
stateManager.state.strokeColorSpace = stateManager.state.strokeColorSpace =
ColorSpace.parse(args[0], xref, resources); ColorSpace.parse(args[0], xref, resources,
self.pdfFunctionFactory);
continue; continue;
case OPS.setFillColor: case OPS.setFillColor:
cs = stateManager.state.fillColorSpace; cs = stateManager.state.fillColorSpace;
@ -1117,7 +1135,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
} }
var shadingFill = Pattern.parseShading(shading, null, xref, var shadingFill = Pattern.parseShading(shading, null, xref,
resources, self.handler); resources, self.handler, self.pdfFunctionFactory);
var patternIR = shadingFill.getIR(); var patternIR = shadingFill.getIR();
args = [patternIR]; args = [patternIR];
fn = OPS.shadingFill; fn = OPS.shadingFill;

View File

@ -25,21 +25,53 @@ let IsEvalSupportedCached = {
}, },
}; };
var PDFFunction = (function PDFFunctionClosure() { class PDFFunctionFactory {
var CONSTRUCT_SAMPLED = 0; constructor({ xref, isEvalSupported = true, }) {
var CONSTRUCT_INTERPOLATED = 2; this.xref = xref;
var CONSTRUCT_STICHED = 3; this.isEvalSupported = isEvalSupported !== false;
var CONSTRUCT_POSTSCRIPT = 4; }
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 { return {
setIsEvalSupported(support = true) { getSampleArray(size, outputSize, bps, stream) {
isEvalSupported = support !== false;
},
getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps,
str) {
var i, ii; var i, ii;
var length = 1; var length = 1;
for (i = 0, ii = size.length; i < ii; i++) { 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 // 32 is a valid bps so shifting won't work
var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1); 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; var strIdx = 0;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
while (codeSize < bps) { while (codeSize < bps) {
@ -68,7 +100,7 @@ var PDFFunction = (function PDFFunctionClosure() {
return array; return array;
}, },
getIR: function PDFFunction_getIR(xref, fn) { getIR({ xref, isEvalSupported, fn, }) {
var dict = fn.dict; var dict = fn.dict;
if (!dict) { if (!dict) {
dict = fn; dict = fn;
@ -86,48 +118,49 @@ var PDFFunction = (function PDFFunctionClosure() {
throw new FormatError('Unknown type of function'); 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]; var type = IR[0];
switch (type) { switch (type) {
case CONSTRUCT_SAMPLED: case CONSTRUCT_SAMPLED:
return this.constructSampledFromIR(IR); return this.constructSampledFromIR({ xref, isEvalSupported, IR, });
case CONSTRUCT_INTERPOLATED: case CONSTRUCT_INTERPOLATED:
return this.constructInterpolatedFromIR(IR); return this.constructInterpolatedFromIR({ xref, isEvalSupported,
IR, });
case CONSTRUCT_STICHED: case CONSTRUCT_STICHED:
return this.constructStichedFromIR(IR); return this.constructStichedFromIR({ xref, isEvalSupported, IR, });
// case CONSTRUCT_POSTSCRIPT: // case CONSTRUCT_POSTSCRIPT:
default: default:
return this.constructPostScriptFromIR(IR); return this.constructPostScriptFromIR({ xref, isEvalSupported, IR, });
} }
}, },
parse: function PDFFunction_parse(xref, fn) { parse({ xref, isEvalSupported, fn, }) {
var IR = this.getIR(xref, fn); let IR = this.getIR({ xref, isEvalSupported, fn, });
return this.fromIR(IR); return this.fromIR({ xref, isEvalSupported, IR, });
}, },
parseArray: function PDFFunction_parseArray(xref, fnObj) { parseArray({ xref, isEvalSupported, fnObj, }) {
if (!Array.isArray(fnObj)) { if (!Array.isArray(fnObj)) {
// not an array -- parsing as regular function // not an array -- parsing as regular function
return this.parse(xref, fnObj); return this.parse({ xref, isEvalSupported, fn: fnObj, });
} }
var fnArray = []; var fnArray = [];
for (var j = 0, jj = fnObj.length; j < jj; j++) { for (var j = 0, jj = fnObj.length; j < jj; j++) {
var obj = xref.fetchIfRef(fnObj[j]); fnArray.push(this.parse({ xref, isEvalSupported,
fnArray.push(PDFFunction.parse(xref, obj)); 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++) { for (var i = 0, ii = fnArray.length; i < ii; i++) {
fnArray[i](src, srcOffset, dest, destOffset + i); fnArray[i](src, srcOffset, dest, destOffset + i);
} }
}; };
}, },
constructSampled: function PDFFunction_constructSampled(str, dict) { constructSampled({ xref, isEvalSupported, fn, dict, }) {
function toMultiArray(arr) { function toMultiArray(arr) {
var inputLength = arr.length; var inputLength = arr.length;
var out = []; var out = [];
@ -177,7 +210,7 @@ var PDFFunction = (function PDFFunctionClosure() {
decode = toMultiArray(decode); decode = toMultiArray(decode);
} }
var samples = this.getSampleArray(size, outputSize, bps, str); var samples = this.getSampleArray(size, outputSize, bps, fn);
return [ return [
CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size, 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 // See chapter 3, page 109 of the PDF reference
function interpolate(x, xmin, xmax, ymin, ymax) { function interpolate(x, xmin, xmax, ymin, ymax) {
return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin))); return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin)));
@ -270,8 +303,7 @@ var PDFFunction = (function PDFFunctionClosure() {
}; };
}, },
constructInterpolated: function PDFFunction_constructInterpolated(str, constructInterpolated({ xref, isEvalSupported, fn, dict, }) {
dict) {
var c0 = dict.getArray('C0') || [0]; var c0 = dict.getArray('C0') || [0];
var c1 = dict.getArray('C1') || [1]; var c1 = dict.getArray('C1') || [1];
var n = dict.get('N'); var n = dict.get('N');
@ -290,8 +322,7 @@ var PDFFunction = (function PDFFunctionClosure() {
return [CONSTRUCT_INTERPOLATED, c0, diff, n]; return [CONSTRUCT_INTERPOLATED, c0, diff, n];
}, },
constructInterpolatedFromIR: constructInterpolatedFromIR({ xref, isEvalSupported, IR, }) {
function PDFFunction_constructInterpolatedFromIR(IR) {
var c0 = IR[1]; var c0 = IR[1];
var diff = IR[2]; var diff = IR[2];
var n = IR[3]; 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'); var domain = dict.getArray('Domain');
if (!domain) { if (!domain) {
@ -323,7 +354,8 @@ var PDFFunction = (function PDFFunctionClosure() {
var fnRefs = dict.get('Functions'); var fnRefs = dict.get('Functions');
var fns = []; var fns = [];
for (var i = 0, ii = fnRefs.length; i < ii; ++i) { 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'); var bounds = dict.getArray('Bounds');
@ -332,7 +364,7 @@ var PDFFunction = (function PDFFunctionClosure() {
return [CONSTRUCT_STICHED, domain, bounds, encode, fns]; return [CONSTRUCT_STICHED, domain, bounds, encode, fns];
}, },
constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) { constructStichedFromIR({ xref, isEvalSupported, IR, }) {
var domain = IR[1]; var domain = IR[1];
var bounds = IR[2]; var bounds = IR[2];
var encode = IR[3]; var encode = IR[3];
@ -341,7 +373,7 @@ var PDFFunction = (function PDFFunctionClosure() {
var tmpBuf = new Float32Array(1); var tmpBuf = new Float32Array(1);
for (var i = 0, ii = fnsIR.length; i < ii; i++) { 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, return function constructStichedFromIRResult(src, srcOffset,
@ -387,8 +419,7 @@ var PDFFunction = (function PDFFunctionClosure() {
}; };
}, },
constructPostScript: function PDFFunction_constructPostScript(fn, dict, constructPostScript({ xref, isEvalSupported, fn, dict, }) {
xref) {
var domain = dict.getArray('Domain'); var domain = dict.getArray('Domain');
var range = dict.getArray('Range'); var range = dict.getArray('Range');
@ -407,8 +438,7 @@ var PDFFunction = (function PDFFunctionClosure() {
return [CONSTRUCT_POSTSCRIPT, domain, range, code]; return [CONSTRUCT_POSTSCRIPT, domain, range, code];
}, },
constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR( constructPostScriptFromIR({ xref, isEvalSupported, IR, }) {
IR) {
var domain = IR[1]; var domain = IR[1];
var range = IR[2]; var range = IR[2];
var code = IR[3]; var code = IR[3];
@ -1151,7 +1181,7 @@ var PostScriptCompiler = (function PostScriptCompilerClosure() {
export { export {
isPDFFunction, isPDFFunction,
PDFFunction, PDFFunctionFactory,
PostScriptEvaluator, PostScriptEvaluator,
PostScriptCompiler, PostScriptCompiler,
}; };

View File

@ -75,7 +75,7 @@ var PDFImage = (function PDFImageClosure() {
} }
function PDFImage({ xref, res, image, smask = null, mask = null, function PDFImage({ xref, res, image, smask = null, mask = null,
isMask = false, }) { isMask = false, pdfFunctionFactory, }) {
this.image = image; this.image = image;
var dict = image.dict; var dict = image.dict;
if (dict.has('Filter')) { if (dict.has('Filter')) {
@ -138,7 +138,8 @@ var PDFImage = (function PDFImageClosure() {
'color components not supported.'); 'color components not supported.');
} }
} }
this.colorSpace = ColorSpace.parse(colorSpace, xref, res); this.colorSpace = ColorSpace.parse(colorSpace, xref, res,
pdfFunctionFactory);
this.numComps = this.colorSpace.numComps; this.numComps = this.colorSpace.numComps;
} }
@ -165,6 +166,7 @@ var PDFImage = (function PDFImageClosure() {
xref, xref,
res, res,
image: smask, image: smask,
pdfFunctionFactory,
}); });
} else if (mask) { } else if (mask) {
if (isStream(mask)) { if (isStream(mask)) {
@ -177,6 +179,7 @@ var PDFImage = (function PDFImageClosure() {
res, res,
image: mask, image: mask,
isMask: true, isMask: true,
pdfFunctionFactory,
}); });
} }
} else { } else {
@ -190,7 +193,8 @@ var PDFImage = (function PDFImageClosure() {
* with a PDFImage when the image is ready to be used. * with a PDFImage when the image is ready to be used.
*/ */
PDFImage.buildImage = function({ handler, xref, res, image, PDFImage.buildImage = function({ handler, xref, res, image,
nativeDecoder = null, }) { nativeDecoder = null,
pdfFunctionFactory, }) {
var imagePromise = handleImageData(image, nativeDecoder); var imagePromise = handleImageData(image, nativeDecoder);
var smaskPromise; var smaskPromise;
var maskPromise; var maskPromise;
@ -224,13 +228,13 @@ var PDFImage = (function PDFImageClosure() {
image: imageData, image: imageData,
smask: smaskData, smask: smaskData,
mask: maskData, mask: maskData,
pdfFunctionFactory,
}); });
}); });
}; };
PDFImage.createMask = function({ imgArray, width, height, PDFImage.createMask = function({ imgArray, width, height,
imageIsFromDecodeStream, inverseDecode, }) { imageIsFromDecodeStream, inverseDecode, }) {
// |imgArray| might not contain full data for every pixel of the mask, so // |imgArray| might not contain full data for every pixel of the mask, so
// we need to distinguish between |computedLength| and |actualLength|. // we need to distinguish between |computedLength| and |actualLength|.
// In particular, if inverseDecode is true, then the array we return must // In particular, if inverseDecode is true, then the array we return must

View File

@ -20,7 +20,6 @@ import {
} from '../shared/util'; } from '../shared/util';
import { ColorSpace } from './colorspace'; import { ColorSpace } from './colorspace';
import { isStream } from './primitives'; import { isStream } from './primitives';
import { PDFFunction } from './function';
var ShadingType = { var ShadingType = {
FUNCTION_BASED: 1, FUNCTION_BASED: 1,
@ -46,9 +45,8 @@ var Pattern = (function PatternClosure() {
}, },
}; };
Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref, Pattern.parseShading = function(shading, matrix, xref, res, handler,
res, handler) { pdfFunctionFactory) {
var dict = isStream(shading) ? shading.dict : shading; var dict = isStream(shading) ? shading.dict : shading;
var type = dict.get('ShadingType'); var type = dict.get('ShadingType');
@ -57,12 +55,14 @@ var Pattern = (function PatternClosure() {
case ShadingType.AXIAL: case ShadingType.AXIAL:
case ShadingType.RADIAL: case ShadingType.RADIAL:
// Both radial and axial shadings are handled by RadialAxial shading. // 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.FREE_FORM_MESH:
case ShadingType.LATTICE_FORM_MESH: case ShadingType.LATTICE_FORM_MESH:
case ShadingType.COONS_PATCH_MESH: case ShadingType.COONS_PATCH_MESH:
case ShadingType.TENSOR_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: default:
throw new FormatError('Unsupported ShadingType: ' + type); throw new FormatError('Unsupported ShadingType: ' + type);
} }
@ -88,13 +88,13 @@ Shadings.SMALL_NUMBER = 1e-6;
// Radial and axial shading have very similar implementations // Radial and axial shading have very similar implementations
// If needed, the implementations can be broken into two classes // If needed, the implementations can be broken into two classes
Shadings.RadialAxial = (function RadialAxialClosure() { Shadings.RadialAxial = (function RadialAxialClosure() {
function RadialAxial(dict, matrix, xref, res) { function RadialAxial(dict, matrix, xref, res, pdfFunctionFactory) {
this.matrix = matrix; this.matrix = matrix;
this.coordsArr = dict.getArray('Coords'); this.coordsArr = dict.getArray('Coords');
this.shadingType = dict.get('ShadingType'); this.shadingType = dict.get('ShadingType');
this.type = 'Pattern'; this.type = 'Pattern';
var cs = dict.get('ColorSpace', 'CS'); var cs = dict.get('ColorSpace', 'CS');
cs = ColorSpace.parse(cs, xref, res); cs = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
this.cs = cs; this.cs = cs;
var t0 = 0.0, t1 = 1.0; var t0 = 0.0, t1 = 1.0;
@ -132,7 +132,7 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
this.extendEnd = extendEnd; this.extendEnd = extendEnd;
var fnObj = dict.get('Function'); 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 // 10 samples seems good enough for now, but probably won't work
// if there are sharp color changes. Ideally, we would implement // 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)) { if (!isStream(stream)) {
throw new FormatError('Mesh data is not a stream'); throw new FormatError('Mesh data is not a stream');
} }
@ -721,13 +721,13 @@ Shadings.Mesh = (function MeshClosure() {
this.type = 'Pattern'; this.type = 'Pattern';
this.bbox = dict.getArray('BBox'); this.bbox = dict.getArray('BBox');
var cs = dict.get('ColorSpace', 'CS'); var cs = dict.get('ColorSpace', 'CS');
cs = ColorSpace.parse(cs, xref, res); cs = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
this.cs = cs; this.cs = cs;
this.background = dict.has('Background') ? this.background = dict.has('Background') ?
cs.getRgb(dict.get('Background'), 0) : null; cs.getRgb(dict.get('Background'), 0) : null;
var fnObj = dict.get('Function'); var fnObj = dict.get('Function');
var fn = fnObj ? PDFFunction.parseArray(xref, fnObj) : null; var fn = fnObj ? pdfFunctionFactory.createFromArray(fnObj) : null;
this.coords = []; this.coords = [];
this.colors = []; this.colors = [];

View File

@ -16,6 +16,7 @@
import { Dict, Name, Ref } from '../../src/core/primitives'; import { Dict, Name, Ref } from '../../src/core/primitives';
import { Stream, StringStream } from '../../src/core/stream'; import { Stream, StringStream } from '../../src/core/stream';
import { ColorSpace } from '../../src/core/colorspace'; import { ColorSpace } from '../../src/core/colorspace';
import { PDFFunctionFactory } from '../../src/core/function';
import { XRefMock } from './test_utils'; import { XRefMock } from './test_utils';
describe('colorspace', function () { describe('colorspace', function () {
@ -54,7 +55,10 @@ describe('colorspace', function () {
}]); }]);
let res = new Dict(); 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 testSrc = new Uint8Array([27, 125, 250, 131]);
let testDest = new Uint8Array(4 * 4 * 3); let testDest = new Uint8Array(4 * 4 * 3);
@ -92,7 +96,10 @@ describe('colorspace', function () {
}]); }]);
let res = new Dict(); 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 testSrc = new Uint8Array([27, 125, 250, 131]);
let testDest = new Uint8Array(3 * 3 * 3); let testDest = new Uint8Array(3 * 3 * 3);
@ -126,7 +133,10 @@ describe('colorspace', function () {
}]); }]);
let res = new Dict(); 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([ let testSrc = new Uint8Array([
27, 125, 250, 27, 125, 250,
@ -169,7 +179,10 @@ describe('colorspace', function () {
}]); }]);
let res = new Dict(); 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([ let testSrc = new Uint8Array([
27, 125, 250, 27, 125, 250,
@ -208,7 +221,10 @@ describe('colorspace', function () {
}]); }]);
let res = new Dict(); 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([ let testSrc = new Uint8Array([
27, 125, 250, 128, 27, 125, 250, 128,
@ -251,7 +267,10 @@ describe('colorspace', function () {
}]); }]);
let res = new Dict(); 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([ let testSrc = new Uint8Array([
27, 125, 250, 128, 27, 125, 250, 128,
@ -298,7 +317,10 @@ describe('colorspace', function () {
}]); }]);
let res = new Dict(); 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 testSrc = new Uint8Array([27, 125, 250, 131]);
let testDest = new Uint8Array(4 * 4 * 3); let testDest = new Uint8Array(4 * 4 * 3);
@ -348,7 +370,10 @@ describe('colorspace', function () {
}]); }]);
let res = new Dict(); 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([ let testSrc = new Uint8Array([
27, 125, 250, 27, 125, 250,
@ -395,7 +420,10 @@ describe('colorspace', function () {
}]); }]);
let res = new Dict(); 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([ let testSrc = new Uint8Array([
27, 25, 50, 27, 25, 50,
@ -445,7 +473,10 @@ describe('colorspace', function () {
}]); }]);
let res = new Dict(); 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 testSrc = new Uint8Array([2, 2, 0, 1]);
let testDest = new Uint8Array(3 * 3 * 3); let testDest = new Uint8Array(3 * 3 * 3);
@ -497,7 +528,10 @@ describe('colorspace', function () {
}]); }]);
let res = new Dict(); 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 testSrc = new Uint8Array([27, 25, 50, 31]);
let testDest = new Uint8Array(3 * 3 * 3); let testDest = new Uint8Array(3 * 3 * 3);

View File

@ -18,16 +18,14 @@ import { Page } from '../../src/core/document';
describe('document', function () { describe('document', function () {
describe('Page', function () { describe('Page', function () {
it('should create correct objId using the idFactory', function () { it('should create correct objId using the idFactory', function () {
var page1 = new Page(/* pdfManager = */ { }, /* xref = */ null, var page1 = new Page({
/* pageIndex = */ 0, pdfManager: { },
/* pageDict = */ null, /* ref = */ null, pageIndex: 0,
/* fontCache = */ null, });
/* builtInCMapCache = */ null); var page2 = new Page({
var page2 = new Page(/* pdfManager = */ { }, /* xref = */ null, pdfManager: { },
/* pageIndex = */ 1, pageIndex: 1,
/* pageDict = */ null, /* ref = */ null, });
/* fontCache = */ null,
/* builtInCMapCache = */ null);
var idFactory1 = page1.idFactory, idFactory2 = page2.idFactory; var idFactory1 = page1.idFactory, idFactory2 = page2.idFactory;