Skip to content

Commit e5f5a41

Browse files
committed
Prevent double transform application in clip() with absolute coordinates
1 parent 34c4706 commit e5f5a41

1 file changed

Lines changed: 31 additions & 19 deletions

File tree

src/core/p5.Renderer2D.js

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ class Renderer2D extends Renderer {
305305
// Start a new path. Everything from here on out should become part of this
306306
// one path so that we can clip to the whole thing.
307307
this.clipPath = new Path2D();
308-
this.initialClipTransform = this.drawingContext.getTransform().inverse();
308+
this.initialTransform = this.drawingContext.getTransform();
309309

310310
if (this._clipInvert) {
311311
// Slight hack: draw a big rectangle over everything with reverse winding
@@ -331,7 +331,10 @@ class Renderer2D extends Renderer {
331331
}
332332

333333
endClip() {
334+
const currentTransform = this.drawingContext.getTransform();
335+
this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
334336
this.drawingContext.clip(this.clipPath);
337+
this.drawingContext.setTransform(currentTransform);
335338
this.clipPath = null;
336339

337340
super.endClip();
@@ -728,25 +731,34 @@ class Renderer2D extends Renderer {
728731
radiusY = h / 2;
729732
if (this._clipping) {
730733
const tempPath = new Path2D();
731-
tempPath.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, 2 * Math.PI);
732-
733-
const currentTransform = this.drawingContext.getTransform();
734-
const initialClip = this.initialClipTransform;
735-
if (currentTransform.a < 0 || currentTransform.d < 0) {
736-
const fixedTransform = new DOMMatrix([
737-
Math.abs(currentTransform.a), currentTransform.b,
738-
currentTransform.c, Math.abs(currentTransform.d),
739-
currentTransform.e, currentTransform.f
740-
]);
741-
const relativeTransform = initialClip.multiply(fixedTransform);
742-
this.clipPath.addPath(tempPath, relativeTransform);
743-
} else {
744-
// Normal case
745-
const relativeTransform = initialClip.multiply(currentTransform);
746-
this.clipPath.addPath(tempPath, relativeTransform);
747-
}
734+
const current = this.drawingContext.getTransform();
735+
// Transform coordinates manually but preserve scale signs
736+
const transformPoint = (x, y) => {
737+
return {
738+
x: current.a * x + current.c * y + current.e,
739+
y: current.b * x + current.d * y + current.f
740+
};
741+
};
742+
const transformedCenter = transformPoint(centerX, centerY);
743+
// Calculate transformed radii WITHOUT Math.abs() to preserve negative scaling
744+
const scaleX = Math.sqrt(current.a * current.a + current.c * current.c);
745+
const scaleY = Math.sqrt(current.b * current.b + current.d * current.d);
746+
747+
// Preserve the sign of the scaling for mirroring effects
748+
const signX = current.a < 0 ? -1 : 1;
749+
const signY = current.d < 0 ? -1 : 1;
750+
751+
const transformedRadiusX = scaleX * radiusX * signX;
752+
const transformedRadiusY = scaleY * radiusY * signY;
753+
tempPath.ellipse(
754+
transformedCenter.x,
755+
transformedCenter.y,
756+
Math.abs(transformedRadiusX),
757+
Math.abs(transformedRadiusY),
758+
0, 0, 2 * Math.PI
759+
);
760+
this.clipPath.addPath(tempPath);
748761
} else {
749-
// Normal drawing (existing code)
750762
ctx.beginPath();
751763
ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, 2 * Math.PI);
752764
ctx.closePath();

0 commit comments

Comments
 (0)