Clear the full SMask scratch canvas in compose()

PR #21101 narrowed `compose()`'s `clearRect` from full canvas to the
caller-supplied dirty box. That leaves pixels outside the current
dirty box on the SMask scratch canvas between `compose()` calls;
subsequent draws into scratch are then source-over-blended on top of
those leftovers, so the output depends on the cumulative draw history
rather than just the current draw.
This commit is contained in:
calixteman 2026-05-14 22:59:21 +02:00
parent b708f59d04
commit 5e18cfd8f0
No known key found for this signature in database
GPG Key ID: 0C5442631EE0691F

View File

@ -1850,17 +1850,13 @@ class CanvasGraphics {
return;
}
// Whatever was drawn has been moved to the suspended canvas, now clear it
// out of the current canvas. Only the dirty box region needs clearing;
// everything outside it is already transparent.
// Clear the full scratch canvas, not just the dirty box. Pixels left
// outside dirtyBox can leak into a later compose() whose destination-in
// pass doesn't overwrite them, producing stale output -- this is what
// breaks `firefox-issue17779-partial` (issue #21276).
this.ctx.save();
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.clearRect(
dirtyBox[0],
dirtyBox[1],
dirtyBox[2] - dirtyBox[0],
dirtyBox[3] - dirtyBox[1]
);
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
this.ctx.restore();
}