Re-factor the LocalTilingPatternCache
to cache by Ref rather than Name (PR 12458 follow-up, issue 13780)
This way there cannot be any *incorrect* cache hits, since Refs are guaranteed to be unique. Please note that the reason for caching by Ref rather than doing something along the lines of the `localShadingPatternCache` (which uses a `Map` directly), is that TilingPatterns are streams and those cannot be cached on the `XRef`-instance (this way we avoid unnecessary parsing).
This commit is contained in:
parent
8ee5acd85d
commit
5f25fea0fe
@ -795,7 +795,6 @@ class PartialEvaluator {
|
||||
patternDict,
|
||||
operatorList,
|
||||
task,
|
||||
cacheKey,
|
||||
localTilingPatternCache
|
||||
) {
|
||||
// Create an IR of the pattern code.
|
||||
@ -825,8 +824,8 @@ class PartialEvaluator {
|
||||
operatorList.addDependencies(tilingOpList.dependencies);
|
||||
operatorList.addOp(fn, tilingPatternIR);
|
||||
|
||||
if (cacheKey) {
|
||||
localTilingPatternCache.set(cacheKey, patternDict.objId, {
|
||||
if (patternDict.objId) {
|
||||
localTilingPatternCache.set(/* name = */ null, patternDict.objId, {
|
||||
operatorListIR,
|
||||
dict: patternDict,
|
||||
});
|
||||
@ -1356,9 +1355,11 @@ class PartialEvaluator {
|
||||
const patternName = args.pop();
|
||||
// SCN/scn applies patterns along with normal colors
|
||||
if (patternName instanceof Name) {
|
||||
const name = patternName.name;
|
||||
const rawPattern = patterns.getRaw(patternName.name);
|
||||
|
||||
const localTilingPattern = localTilingPatternCache.getByName(name);
|
||||
const localTilingPattern =
|
||||
rawPattern instanceof Ref &&
|
||||
localTilingPatternCache.getByRef(rawPattern);
|
||||
if (localTilingPattern) {
|
||||
try {
|
||||
const color = cs.base ? cs.base.getRgb(args, 0) : null;
|
||||
@ -1373,11 +1374,8 @@ class PartialEvaluator {
|
||||
// Handle any errors during normal TilingPattern parsing.
|
||||
}
|
||||
}
|
||||
// TODO: Attempt to lookup cached TilingPatterns by reference as well,
|
||||
// if and only if there are PDF documents where doing so would
|
||||
// significantly improve performance.
|
||||
|
||||
const pattern = patterns.get(name);
|
||||
const pattern = this.xref.fetchIfRef(rawPattern);
|
||||
if (pattern) {
|
||||
const dict = isStream(pattern) ? pattern.dict : pattern;
|
||||
const typeNum = dict.get("PatternType");
|
||||
@ -1392,7 +1390,6 @@ class PartialEvaluator {
|
||||
dict,
|
||||
operatorList,
|
||||
task,
|
||||
/* cacheKey = */ name,
|
||||
localTilingPatternCache
|
||||
);
|
||||
} else if (typeNum === PatternType.SHADING) {
|
||||
|
@ -135,25 +135,18 @@ class LocalGStateCache extends BaseLocalCache {
|
||||
}
|
||||
|
||||
class LocalTilingPatternCache extends BaseLocalCache {
|
||||
set(name, ref = null, data) {
|
||||
if (typeof name !== "string") {
|
||||
throw new Error(
|
||||
'LocalTilingPatternCache.set - expected "name" argument.'
|
||||
);
|
||||
constructor(options) {
|
||||
super({ onlyRefs: true });
|
||||
}
|
||||
|
||||
set(name = null, ref, data) {
|
||||
if (!ref) {
|
||||
throw new Error('LocalTilingPatternCache.set - expected "ref" argument.');
|
||||
}
|
||||
if (ref) {
|
||||
if (this._imageCache.has(ref)) {
|
||||
return;
|
||||
}
|
||||
this._nameRefMap.set(name, ref);
|
||||
this._imageCache.put(ref, data);
|
||||
if (this._imageCache.has(ref)) {
|
||||
return;
|
||||
}
|
||||
// name
|
||||
if (this._imageMap.has(name)) {
|
||||
return;
|
||||
}
|
||||
this._imageMap.set(name, data);
|
||||
this._imageCache.put(ref, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user