diff --git a/src/display/canvas.js b/src/display/canvas.js index c5144b378..647cdc3a1 100644 --- a/src/display/canvas.js +++ b/src/display/canvas.js @@ -147,8 +147,13 @@ function mirrorContextOperations(ctx, destCtx) { }; ctx.setTransform = function (a, b, c, d, e, f) { - destCtx.setTransform(a, b, c, d, e, f); - this.__originalSetTransform(a, b, c, d, e, f); + if (b === undefined) { + destCtx.setTransform(a); + this.__originalSetTransform(a); + } else { + destCtx.setTransform(a, b, c, d, e, f); + this.__originalSetTransform(a, b, c, d, e, f); + } }; ctx.resetTransform = function () { @@ -1467,6 +1472,13 @@ class CanvasGraphics { // Graphics state is stored on the main(suspended) canvas. Restore its // state then copy it over to the temporary canvas. copyCtxState(this.suspendedCtx, this.ctx); + // The scratch canvas may have been freshly created by beginSMaskMode + // (called from checkSMaskState during a previous endGroup), in which + // case its save/restore stack is empty and ctx.restore() above was a + // no-op. Explicitly sync the CTM from the main canvas so that any CTM + // change that the mirrored restore applied to the main canvas is also + // reflected on the scratch canvas. + this.ctx.setTransform(this.suspendedCtx.getTransform()); } this.checkSMaskState(opIdx); @@ -2805,6 +2817,13 @@ class CanvasGraphics { this.restore(opIdx); if (this.dependencyTracker) { this.ctx.restore(); + // beginSMaskMode() may have been called inside restore(opIdx) above + // (via checkSMaskState), creating a fresh scratch canvas. If so, + // the mirrored ctx.restore() just synced main's CTM but left the + // scratch at the stale CTM set by beginSMaskMode(). Re-sync it. + if (this.inSMaskMode) { + this.ctx.setTransform(this.suspendedCtx.getTransform()); + } } } else { this.ctx.restore(); diff --git a/test/pdfs/issue17784.pdf.link b/test/pdfs/issue17784.pdf.link new file mode 100644 index 000000000..800f74442 --- /dev/null +++ b/test/pdfs/issue17784.pdf.link @@ -0,0 +1 @@ +https://web.archive.org/web/20240320131329/https://lp.entro.security/hubfs/Gated%20Assets/Onboarding-offboarding-checklist.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 84dc4f03c..f4ead7c85 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -14126,5 +14126,15 @@ "md5": "5a690e2303604441308f808b5fc33e22", "rounds": 1, "type": "eq" + }, + { + "id": "issue17784", + "file": "pdfs/issue17784.pdf", + "md5": "e92178bb5ca8d6cd6f79868470adbe1d", + "link": true, + "rounds": 1, + "firstPage": 3, + "lastPage": 3, + "type": "eq" } ]