From 8304df2520ad414b013ae7e98444b3808156b8ff Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Mon, 6 Mar 2023 10:57:05 +0100 Subject: [PATCH] Apply transfer filters to any graphic commands --- src/display/canvas.js | 29 +++++++++++++++++++++++------ src/display/display_utils.js | 2 +- test/pdfs/issue16114.pdf.link | 2 ++ test/test_manifest.json | 8 ++++++++ 4 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 test/pdfs/issue16114.pdf.link diff --git a/src/display/canvas.js b/src/display/canvas.js index 74da9d151..5863b7528 100644 --- a/src/display/canvas.js +++ b/src/display/canvas.js @@ -38,6 +38,7 @@ import { TilingPattern, } from "./pattern_helper.js"; import { convertBlackAndWhiteToRGBA } from "../shared/image_utils.js"; +import { isNodeJS } from "../shared/is_node.js"; // contexts store most of the state we need natively. // However, PDF needs a bit more state, which we store here. @@ -837,6 +838,7 @@ function copyCtxState(sourceCtx, destCtx) { "miterLimit", "globalCompositeOperation", "font", + "filter", ]; for (const property of properties) { if (sourceCtx[property] !== undefined) { @@ -863,6 +865,9 @@ function resetCtxToDefault(ctx, foregroundColor) { ctx.setLineDash([]); ctx.lineDashOffset = 0; } + if (!isNodeJS) { + ctx.filter = "none"; + } } function composeSMaskBackdrop(bytes, r0, g0, b0) { @@ -1576,9 +1581,12 @@ class CanvasGraphics { this.checkSMaskState(); break; case "TR": - this.current.transferMaps = this.filterFactory - ? this.filterFactory.addFilter(value) - : value; + if (this.filterFactory) { + this.ctx.filter = this.current.transferMaps = + this.filterFactory.addFilter(value); + } else { + this.current.transferMaps = value; + } break; } } @@ -3025,7 +3033,7 @@ class CanvasGraphics { } applyTransferMapsToBitmap(imgData) { - if (!this.current.transferMaps) { + if (!this.current.transferMaps || this.current.transferMaps === "none") { return imgData.bitmap; } const { bitmap, width, height } = imgData; @@ -3037,7 +3045,7 @@ class CanvasGraphics { const tmpCtx = tmpCanvas.context; tmpCtx.filter = this.current.transferMaps; tmpCtx.drawImage(bitmap, 0, 0); - tmpCtx.filter = ""; + tmpCtx.filter = "none"; return tmpCanvas.canvas; } @@ -3051,6 +3059,15 @@ class CanvasGraphics { const ctx = this.ctx; this.save(); + + if (!isNodeJS) { + // The filter, if any, will be applied in applyTransferMapsToBitmap. + // It must be applied to the image before rescaling else some artifacts + // could appear. + // The final restore will reset it to its value. + ctx.filter = "none"; + } + // scale the image to the unit square ctx.scale(1 / width, -1 / height); @@ -3106,7 +3123,7 @@ class CanvasGraphics { const ctx = this.ctx; let imgToPaint; if (imgData.bitmap) { - imgToPaint = this.applyTransferMapsToBitmap(imgData); + imgToPaint = imgData.bitmap; } else { const w = imgData.width; const h = imgData.height; diff --git a/src/display/display_utils.js b/src/display/display_utils.js index 1e33b34d1..1e5ab9f6e 100644 --- a/src/display/display_utils.js +++ b/src/display/display_utils.js @@ -81,7 +81,7 @@ class FilterFactory { addFilter(maps) { if (!maps) { - return ""; + return "none"; } // When a page is zoomed the page is re-drawn but the maps are likely diff --git a/test/pdfs/issue16114.pdf.link b/test/pdfs/issue16114.pdf.link new file mode 100644 index 000000000..45692bdd8 --- /dev/null +++ b/test/pdfs/issue16114.pdf.link @@ -0,0 +1,2 @@ +https://github.com/mozilla/pdf.js/files/10896497/spider.pdf + diff --git a/test/test_manifest.json b/test/test_manifest.json index cb23055be..d91dfc659 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -7437,5 +7437,13 @@ "md5": "76d680172c969c77c9fb650b3d822ad6", "link": true, "type": "other" + }, + { + "id": "issue16114", + "file": "pdfs/issue16114.pdf", + "md5": "c04827ea33692e0f94a5e51716d9aa2e", + "rounds": 1, + "link": true, + "type": "eq" } ]