1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-26 01:58:06 +02:00

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

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