diff --git a/src/core/evaluator.js b/src/core/evaluator.js index a768a6193..4354130dd 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -59,6 +59,7 @@ import { LocalGStateCache, LocalImageCache, LocalTilingPatternCache, + RegionalImageCache, } from "./image_utils.js"; import { NullStream, Stream } from "./stream.js"; import { BaseStream } from "./base_stream.js"; @@ -229,6 +230,7 @@ class PartialEvaluator { this.options = options || DefaultPartialEvaluatorOptions; this.parsingType3Font = false; + this._regionalImageCache = new RegionalImageCache(); this._fetchBuiltInCMapBound = this.fetchBuiltInCMap.bind(this); ImageResizer.setMaxArea(this.options.canvasMaxAreaInBytes); } @@ -635,11 +637,20 @@ class PartialEvaluator { ); if (cacheKey) { - localImageCache.set(cacheKey, imageRef, { + const cacheData = { fn: OPS.paintImageMaskXObject, args, optionalContent, - }); + }; + localImageCache.set(cacheKey, imageRef, cacheData); + + if (imageRef) { + this._regionalImageCache.set( + /* name = */ null, + imageRef, + cacheData + ); + } } return; } @@ -664,11 +675,20 @@ class PartialEvaluator { ); if (cacheKey) { - localImageCache.set(cacheKey, imageRef, { + const cacheData = { fn: OPS.paintSolidColorImageMask, args: [], optionalContent, - }); + }; + localImageCache.set(cacheKey, imageRef, cacheData); + + if (imageRef) { + this._regionalImageCache.set( + /* name = */ null, + imageRef, + cacheData + ); + } } return; } @@ -693,11 +713,16 @@ class PartialEvaluator { ); if (cacheKey) { - localImageCache.set(cacheKey, imageRef, { + const cacheData = { fn: OPS.paintImageMaskXObject, args, optionalContent, - }); + }; + localImageCache.set(cacheKey, imageRef, cacheData); + + if (imageRef) { + this._regionalImageCache.set(/* name = */ null, imageRef, cacheData); + } } return; } @@ -790,13 +815,16 @@ class PartialEvaluator { operatorList.addImageOps(OPS.paintImageXObject, args, optionalContent); if (cacheKey) { - localImageCache.set(cacheKey, imageRef, { + const cacheData = { fn: OPS.paintImageXObject, args, optionalContent, - }); + }; + localImageCache.set(cacheKey, imageRef, cacheData); if (imageRef) { + this._regionalImageCache.set(/* name = */ null, imageRef, cacheData); + assert(!isInline, "Cannot cache an inline image globally."); this.globalImageCache.addPageIndex(imageRef, this.pageIndex); @@ -1723,7 +1751,9 @@ class PartialEvaluator { let xobj = xobjs.getRaw(name); if (xobj instanceof Ref) { - const localImage = localImageCache.getByRef(xobj); + const localImage = + localImageCache.getByRef(xobj) || + self._regionalImageCache.getByRef(xobj); if (localImage) { operatorList.addImageOps( localImage.fn, diff --git a/src/core/image_utils.js b/src/core/image_utils.js index 1dfb5b740..f93729c29 100644 --- a/src/core/image_utils.js +++ b/src/core/image_utils.js @@ -156,6 +156,22 @@ class LocalTilingPatternCache extends BaseLocalCache { } } +class RegionalImageCache extends BaseLocalCache { + constructor(options) { + super({ onlyRefs: true }); + } + + set(name = null, ref, data) { + if (!ref) { + throw new Error('RegionalImageCache.set - expected "ref" argument.'); + } + if (this._imageCache.has(ref)) { + return; + } + this._imageCache.put(ref, data); + } +} + class GlobalImageCache { static get NUM_PAGES_THRESHOLD() { return shadow(this, "NUM_PAGES_THRESHOLD", 2); @@ -288,4 +304,5 @@ export { LocalGStateCache, LocalImageCache, LocalTilingPatternCache, + RegionalImageCache, }; diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index faace5c91..08047ff9b 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -225,6 +225,7 @@ !issue840.pdf !160F-2019.pdf !issue4402_reduced.pdf +!issue16263.pdf !issue845r.pdf !issue3405r.pdf !issue14130.pdf diff --git a/test/pdfs/issue16263.pdf b/test/pdfs/issue16263.pdf new file mode 100644 index 000000000..002b207f1 Binary files /dev/null and b/test/pdfs/issue16263.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index 12abd2808..e2caef285 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -4721,6 +4721,12 @@ "link": false, "type": "eq" }, + { "id": "issue16263", + "file": "pdfs/issue16263.pdf", + "md5": "93c3e7884f1f2d072442898127e0a6fd", + "rounds": 1, + "type": "eq" + }, { "id": "issue2006", "file": "pdfs/issue2006.pdf", "md5": "71ec73831ece9b508ad20efa6ff28642",