diff --git a/src/core/colorspace.js b/src/core/colorspace.js index 287b6cb0b..e06019043 100644 --- a/src/core/colorspace.js +++ b/src/core/colorspace.js @@ -379,24 +379,46 @@ class AlternateCS extends ColorSpace { : new Uint8ClampedArray(baseNumComps * count); const numComps = this.numComps; + const tintCache = new Map(); + // Use an integer cache-key when possible, since that's a lot faster than + // string concatenation. + const int32Key = + numComps <= 4 && + (src instanceof Uint8Array || src instanceof Uint8ClampedArray); + const scaled = new Float32Array(numComps); const tinted = new Float32Array(baseNumComps); - let i, j; + let i, j, key, val; for (i = 0; i < count; i++) { + key = int32Key ? 0 : ""; + for (j = 0; j < numComps; j++) { - scaled[j] = src[srcOffset++] * scale; + val = src[srcOffset++]; + scaled[j] = val * scale; + + key += int32Key ? val << (8 * j) : val + "_"; } - tintFn(scaled, 0, tinted, 0); - if (usesZeroToOneRange) { - for (j = 0; j < baseNumComps; j++) { - baseBuf[pos++] = tinted[j] * 255; - } - } else { - base.getRgbItem(tinted, 0, baseBuf, pos); + + const cached = tintCache.get(key); + if (cached) { + baseBuf.set(cached, pos); pos += baseNumComps; + } else { + tintFn(scaled, 0, tinted, 0); + + if (usesZeroToOneRange) { + for (j = 0; j < baseNumComps; j++) { + baseBuf[pos++] = tinted[j] * 255; + } + } else { + base.getRgbItem(tinted, 0, baseBuf, pos); + pos += baseNumComps; + } + tintCache.set(key, baseBuf.slice(pos - baseNumComps, pos)); } } + tintCache.clear(); if (!isPassthrough) { base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01); diff --git a/src/core/function.js b/src/core/function.js index f426f15bf..702e36b3e 100644 --- a/src/core/function.js +++ b/src/core/function.js @@ -392,12 +392,11 @@ class PDFFunction { // seen in our tests. const MAX_CACHE_SIZE = 2048 * 4; let cache_available = MAX_CACHE_SIZE; - const tmpBuf = new Float32Array(numInputs); + const input = new Float32Array(numInputs); return function constructPostScriptFn(src, srcOffset, dest, destOffset) { let i, value; let key = ""; - const input = tmpBuf; for (i = 0; i < numInputs; i++) { value = src[srcOffset + i]; input[i] = value; diff --git a/test/pdfs/pr5134.pdf.link b/test/pdfs/pr5134.pdf.link new file mode 100644 index 000000000..721dc2fdc --- /dev/null +++ b/test/pdfs/pr5134.pdf.link @@ -0,0 +1 @@ +https://web.archive.org/web/20140211020222/http://www.coachusa.com/CoachUsaAssets/files/97/route45.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index bfa914535..394c60a6a 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -2254,6 +2254,15 @@ "lastPage": 1, "type": "eq" }, + { + "id": "pr5134", + "file": "pdfs/pr5134.pdf", + "md5": "6a701a163472e071a2519348b55cbac1", + "rounds": 1, + "link": true, + "firstPage": 2, + "type": "eq" + }, { "id": "issue5599", "file": "pdfs/issue5599.pdf",