Merge pull request #12458 from Snuffleupagus/LocalTilingPatternCache
Add local caching of TilingPatterns in `PartialEvaluator.getOperatorList` (issue 2765 and 8473)
This commit is contained in:
commit
e59a90d8e9
@ -81,6 +81,7 @@ import {
|
|||||||
LocalColorSpaceCache,
|
LocalColorSpaceCache,
|
||||||
LocalGStateCache,
|
LocalGStateCache,
|
||||||
LocalImageCache,
|
LocalImageCache,
|
||||||
|
LocalTilingPatternCache,
|
||||||
} from "./image_utils.js";
|
} from "./image_utils.js";
|
||||||
import { bidi } from "./bidi.js";
|
import { bidi } from "./bidi.js";
|
||||||
import { ColorSpace } from "./colorspace.js";
|
import { ColorSpace } from "./colorspace.js";
|
||||||
@ -716,12 +717,14 @@ class PartialEvaluator {
|
|||||||
|
|
||||||
handleTilingType(
|
handleTilingType(
|
||||||
fn,
|
fn,
|
||||||
args,
|
color,
|
||||||
resources,
|
resources,
|
||||||
pattern,
|
pattern,
|
||||||
patternDict,
|
patternDict,
|
||||||
operatorList,
|
operatorList,
|
||||||
task
|
task,
|
||||||
|
cacheKey,
|
||||||
|
localTilingPatternCache
|
||||||
) {
|
) {
|
||||||
// Create an IR of the pattern code.
|
// Create an IR of the pattern code.
|
||||||
const tilingOpList = new OperatorList();
|
const tilingOpList = new OperatorList();
|
||||||
@ -739,38 +742,39 @@ class PartialEvaluator {
|
|||||||
operatorList: tilingOpList,
|
operatorList: tilingOpList,
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return getTilingPatternIR(
|
const operatorListIR = tilingOpList.getIR();
|
||||||
{
|
const tilingPatternIR = getTilingPatternIR(
|
||||||
fnArray: tilingOpList.fnArray,
|
operatorListIR,
|
||||||
argsArray: tilingOpList.argsArray,
|
|
||||||
},
|
|
||||||
patternDict,
|
patternDict,
|
||||||
args
|
color
|
||||||
);
|
);
|
||||||
})
|
// Add the dependencies to the parent operator list so they are
|
||||||
.then(
|
// resolved before the sub operator list is executed synchronously.
|
||||||
function (tilingPatternIR) {
|
operatorList.addDependencies(tilingOpList.dependencies);
|
||||||
// Add the dependencies to the parent operator list so they are
|
operatorList.addOp(fn, tilingPatternIR);
|
||||||
// resolved before the sub operator list is executed synchronously.
|
|
||||||
operatorList.addDependencies(tilingOpList.dependencies);
|
if (cacheKey) {
|
||||||
operatorList.addOp(fn, tilingPatternIR);
|
localTilingPatternCache.set(cacheKey, patternDict.objId, {
|
||||||
},
|
operatorListIR,
|
||||||
reason => {
|
dict: patternDict,
|
||||||
if (reason instanceof AbortException) {
|
});
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.options.ignoreErrors) {
|
|
||||||
// Error(s) in the TilingPattern -- sending unsupported feature
|
|
||||||
// notification and allow rendering to continue.
|
|
||||||
this.handler.send("UnsupportedFeature", {
|
|
||||||
featureId: UNSUPPORTED_FEATURES.errorTilingPattern,
|
|
||||||
});
|
|
||||||
warn(`handleTilingType - ignoring pattern: "${reason}".`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw reason;
|
|
||||||
}
|
}
|
||||||
);
|
})
|
||||||
|
.catch(reason => {
|
||||||
|
if (reason instanceof AbortException) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.options.ignoreErrors) {
|
||||||
|
// Error(s) in the TilingPattern -- sending unsupported feature
|
||||||
|
// notification and allow rendering to continue.
|
||||||
|
this.handler.send("UnsupportedFeature", {
|
||||||
|
featureId: UNSUPPORTED_FEATURES.errorTilingPattern,
|
||||||
|
});
|
||||||
|
warn(`handleTilingType - ignoring pattern: "${reason}".`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw reason;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSetFont(resources, fontArgs, fontRef, operatorList, task, state) {
|
handleSetFont(resources, fontArgs, fontRef, operatorList, task, state) {
|
||||||
@ -1221,7 +1225,7 @@ class PartialEvaluator {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleColorN(
|
handleColorN(
|
||||||
operatorList,
|
operatorList,
|
||||||
fn,
|
fn,
|
||||||
args,
|
args,
|
||||||
@ -1229,43 +1233,70 @@ class PartialEvaluator {
|
|||||||
patterns,
|
patterns,
|
||||||
resources,
|
resources,
|
||||||
task,
|
task,
|
||||||
localColorSpaceCache
|
localColorSpaceCache,
|
||||||
|
localTilingPatternCache
|
||||||
) {
|
) {
|
||||||
// compile tiling patterns
|
// compile tiling patterns
|
||||||
var patternName = args[args.length - 1];
|
const patternName = args[args.length - 1];
|
||||||
// SCN/scn applies patterns along with normal colors
|
// SCN/scn applies patterns along with normal colors
|
||||||
var pattern;
|
if (patternName instanceof Name) {
|
||||||
if (isName(patternName) && (pattern = patterns.get(patternName.name))) {
|
const localTilingPattern = localTilingPatternCache.getByName(patternName);
|
||||||
var dict = isStream(pattern) ? pattern.dict : pattern;
|
if (localTilingPattern) {
|
||||||
var typeNum = dict.get("PatternType");
|
try {
|
||||||
|
const color = cs.base ? cs.base.getRgb(args, 0) : null;
|
||||||
if (typeNum === PatternType.TILING) {
|
const tilingPatternIR = getTilingPatternIR(
|
||||||
var color = cs.base ? cs.base.getRgb(args, 0) : null;
|
localTilingPattern.operatorListIR,
|
||||||
return this.handleTilingType(
|
localTilingPattern.dict,
|
||||||
fn,
|
color
|
||||||
color,
|
);
|
||||||
resources,
|
operatorList.addOp(fn, tilingPatternIR);
|
||||||
pattern,
|
return undefined;
|
||||||
dict,
|
} catch (ex) {
|
||||||
operatorList,
|
if (ex instanceof MissingDataException) {
|
||||||
task
|
throw ex;
|
||||||
);
|
}
|
||||||
} else if (typeNum === PatternType.SHADING) {
|
// Handle any errors during normal TilingPattern parsing.
|
||||||
var shading = dict.get("Shading");
|
}
|
||||||
var matrix = dict.getArray("Matrix");
|
}
|
||||||
pattern = Pattern.parseShading(
|
// TODO: Attempt to lookup cached TilingPatterns by reference as well,
|
||||||
shading,
|
// if and only if there are PDF documents where doing so would
|
||||||
matrix,
|
// significantly improve performance.
|
||||||
this.xref,
|
|
||||||
resources,
|
let pattern = patterns.get(patternName.name);
|
||||||
this.handler,
|
if (pattern) {
|
||||||
this._pdfFunctionFactory,
|
var dict = isStream(pattern) ? pattern.dict : pattern;
|
||||||
localColorSpaceCache
|
var typeNum = dict.get("PatternType");
|
||||||
);
|
|
||||||
operatorList.addOp(fn, pattern.getIR());
|
if (typeNum === PatternType.TILING) {
|
||||||
return undefined;
|
const color = cs.base ? cs.base.getRgb(args, 0) : null;
|
||||||
|
return this.handleTilingType(
|
||||||
|
fn,
|
||||||
|
color,
|
||||||
|
resources,
|
||||||
|
pattern,
|
||||||
|
dict,
|
||||||
|
operatorList,
|
||||||
|
task,
|
||||||
|
patternName,
|
||||||
|
localTilingPatternCache
|
||||||
|
);
|
||||||
|
} else if (typeNum === PatternType.SHADING) {
|
||||||
|
var shading = dict.get("Shading");
|
||||||
|
var matrix = dict.getArray("Matrix");
|
||||||
|
pattern = Pattern.parseShading(
|
||||||
|
shading,
|
||||||
|
matrix,
|
||||||
|
this.xref,
|
||||||
|
resources,
|
||||||
|
this.handler,
|
||||||
|
this._pdfFunctionFactory,
|
||||||
|
localColorSpaceCache
|
||||||
|
);
|
||||||
|
operatorList.addOp(fn, pattern.getIR());
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
throw new FormatError(`Unknown PatternType: ${typeNum}`);
|
||||||
}
|
}
|
||||||
throw new FormatError(`Unknown PatternType: ${typeNum}`);
|
|
||||||
}
|
}
|
||||||
throw new FormatError(`Unknown PatternName: ${patternName}`);
|
throw new FormatError(`Unknown PatternName: ${patternName}`);
|
||||||
}
|
}
|
||||||
@ -1349,6 +1380,7 @@ class PartialEvaluator {
|
|||||||
const localImageCache = new LocalImageCache();
|
const localImageCache = new LocalImageCache();
|
||||||
const localColorSpaceCache = new LocalColorSpaceCache();
|
const localColorSpaceCache = new LocalColorSpaceCache();
|
||||||
const localGStateCache = new LocalGStateCache();
|
const localGStateCache = new LocalGStateCache();
|
||||||
|
const localTilingPatternCache = new LocalTilingPatternCache();
|
||||||
|
|
||||||
var xobjs = resources.get("XObject") || Dict.empty;
|
var xobjs = resources.get("XObject") || Dict.empty;
|
||||||
var patterns = resources.get("Pattern") || Dict.empty;
|
var patterns = resources.get("Pattern") || Dict.empty;
|
||||||
@ -1704,7 +1736,8 @@ class PartialEvaluator {
|
|||||||
patterns,
|
patterns,
|
||||||
resources,
|
resources,
|
||||||
task,
|
task,
|
||||||
localColorSpaceCache
|
localColorSpaceCache,
|
||||||
|
localTilingPatternCache
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@ -1724,7 +1757,8 @@ class PartialEvaluator {
|
|||||||
patterns,
|
patterns,
|
||||||
resources,
|
resources,
|
||||||
task,
|
task,
|
||||||
localColorSpaceCache
|
localColorSpaceCache,
|
||||||
|
localTilingPatternCache
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -133,6 +133,29 @@ class LocalGStateCache extends BaseLocalCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LocalTilingPatternCache extends BaseLocalCache {
|
||||||
|
set(name, ref = null, data) {
|
||||||
|
if (!name) {
|
||||||
|
throw new Error(
|
||||||
|
'LocalTilingPatternCache.set - expected "name" argument.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (ref) {
|
||||||
|
if (this._imageCache.has(ref)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._nameRefMap.set(name, ref);
|
||||||
|
this._imageCache.put(ref, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// name
|
||||||
|
if (this._imageMap.has(name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._imageMap.set(name, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class GlobalImageCache {
|
class GlobalImageCache {
|
||||||
static get NUM_PAGES_THRESHOLD() {
|
static get NUM_PAGES_THRESHOLD() {
|
||||||
return shadow(this, "NUM_PAGES_THRESHOLD", 2);
|
return shadow(this, "NUM_PAGES_THRESHOLD", 2);
|
||||||
@ -231,5 +254,6 @@ export {
|
|||||||
LocalColorSpaceCache,
|
LocalColorSpaceCache,
|
||||||
LocalFunctionCache,
|
LocalFunctionCache,
|
||||||
LocalGStateCache,
|
LocalGStateCache,
|
||||||
|
LocalTilingPatternCache,
|
||||||
GlobalImageCache,
|
GlobalImageCache,
|
||||||
};
|
};
|
||||||
|
@ -967,7 +967,7 @@ Shadings.Dummy = (function DummyClosure() {
|
|||||||
return Dummy;
|
return Dummy;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function getTilingPatternIR(operatorList, dict, args) {
|
function getTilingPatternIR(operatorList, dict, color) {
|
||||||
const matrix = dict.getArray("Matrix");
|
const matrix = dict.getArray("Matrix");
|
||||||
const bbox = Util.normalizeRect(dict.getArray("BBox"));
|
const bbox = Util.normalizeRect(dict.getArray("BBox"));
|
||||||
const xstep = dict.get("XStep");
|
const xstep = dict.get("XStep");
|
||||||
@ -983,7 +983,7 @@ function getTilingPatternIR(operatorList, dict, args) {
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
"TilingPattern",
|
"TilingPattern",
|
||||||
args,
|
color,
|
||||||
operatorList,
|
operatorList,
|
||||||
matrix,
|
matrix,
|
||||||
bbox,
|
bbox,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user