From 96d0d22d66cfbab6d0f5b213251db9a2653c7745 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Mon, 6 Jun 2022 17:24:38 +0200 Subject: [PATCH] Reset all the canvas states after rendering each annotations (#14105) - each annotation must be rendered independently of the others. So after having rendered each annotation, the canvas states are reset in order to have something clean to render the next one. --- src/display/canvas.js | 32 ++++++++++++++++++++------------ test/pdfs/issue14105.pdf.link | 2 ++ test/test_manifest.json | 8 ++++++++ 3 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 test/pdfs/issue14105.pdf.link diff --git a/src/display/canvas.js b/src/display/canvas.js index d7f7fd93f27b7..42e7d244ab75c 100644 --- a/src/display/canvas.js +++ b/src/display/canvas.js @@ -1453,7 +1453,7 @@ class CanvasGraphics { } } - endDrawing() { + #restoreInitialState() { // Finishing all opened operations such as SMask group painting. while (this.stateStack.length || this.inSMaskMode) { this.restore(); @@ -1469,6 +1469,10 @@ class CanvasGraphics { this.ctx.restore(); this.transparentCanvas = null; } + } + + endDrawing() { + this.#restoreInitialState(); this.cachedCanvases.clear(); this.cachedPatterns.clear(); @@ -2972,20 +2976,25 @@ class CanvasGraphics { } } - beginAnnotations() { - this.save(); - if (this.baseTransform) { - this.ctx.setTransform.apply(this.ctx, this.baseTransform); - } - } + beginAnnotations() {} - endAnnotations() { - this.restore(); - } + endAnnotations() {} beginAnnotation(id, rect, transform, matrix, hasOwnCanvas) { + // The annotations are drawn just after the page content. + // The page content drawing can potentially have set a transform, + // a clipping path, whatever... + // So in order to have something clean, we restore the initial state. + this.#restoreInitialState(); + resetCtxToDefault(this.ctx, this.foregroundColor); + + this.ctx.save(); this.save(); + if (this.baseTransform) { + this.ctx.setTransform.apply(this.ctx, this.baseTransform); + } + if (Array.isArray(rect) && rect.length === 4) { const width = rect[2] - rect[0]; const height = rect[3] - rect[1]; @@ -3022,8 +3031,8 @@ class CanvasGraphics { this.annotationCanvasMap.set(id, canvas); this.annotationCanvas.savedCtx = this.ctx; this.ctx = context; - this.ctx.setTransform(scaleX, 0, 0, -scaleY, 0, height * scaleY); addContextCurrentTransform(this.ctx); + this.ctx.setTransform(scaleX, 0, 0, -scaleY, 0, height * scaleY); resetCtxToDefault(this.ctx, this.foregroundColor); } else { @@ -3050,7 +3059,6 @@ class CanvasGraphics { delete this.annotationCanvas.savedCtx; delete this.annotationCanvas; } - this.restore(); } paintImageMaskXObject(img) { diff --git a/test/pdfs/issue14105.pdf.link b/test/pdfs/issue14105.pdf.link new file mode 100644 index 0000000000000..249723974d10a --- /dev/null +++ b/test/pdfs/issue14105.pdf.link @@ -0,0 +1,2 @@ +https://github.com/mozilla/pdf.js/files/7291567/Stamp_Problem.pdf + diff --git a/test/test_manifest.json b/test/test_manifest.json index d429af59be822..8215e0966dbcb 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -6545,5 +6545,13 @@ "link": true, "type": "eq", "annotations": true + }, + { "id": "issue14105", + "file": "pdfs/issue14105.pdf", + "md5": "554174cd461180cbe46c137e846dd527", + "rounds": 1, + "link": true, + "type": "eq", + "annotations": true } ]