Skip to content

Commit 9799ead

Browse files
authored
Merge pull request #8236 from VANSH3104/transform/Clip
Fix transforms in clip() by using shape system for primitives using manual method
2 parents 090ae9f + ced12cd commit 9799ead

1 file changed

Lines changed: 115 additions & 37 deletions

File tree

src/core/p5.Renderer2D.js

Lines changed: 115 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ class Renderer2D extends Renderer {
306306
// Start a new path. Everything from here on out should become part of this
307307
// one path so that we can clip to the whole thing.
308308
this.clipPath = new Path2D();
309+
this._clipBaseTransform = this.drawingContext.getTransform();
309310

310311
if (this._clipInvert) {
311312
// Slight hack: draw a big rectangle over everything with reverse winding
@@ -331,7 +332,11 @@ class Renderer2D extends Renderer {
331332
}
332333

333334
endClip() {
335+
const savedTransform = this.drawingContext.getTransform();
336+
this.drawingContext.setTransform(this._clipBaseTransform);
334337
this.drawingContext.clip(this.clipPath);
338+
this.drawingContext.setTransform(savedTransform);
339+
335340
this.clipPath = null;
336341

337342
super.endClip();
@@ -652,7 +657,7 @@ class Renderer2D extends Renderer {
652657
* start <= stop < start + TWO_PI
653658
*/
654659
arc(x, y, w, h, start, stop, mode) {
655-
const ctx = this.clipPa || this.drawingContext;
660+
const ctx = this.drawingContext;
656661
const rx = w / 2.0;
657662
const ry = h / 2.0;
658663
const epsilon = 0.00001; // Smallest visible angle on displays up to 4K.
@@ -663,7 +668,15 @@ class Renderer2D extends Renderer {
663668
centerY = y + h / 2,
664669
radiusX = w / 2,
665670
radiusY = h / 2;
666-
671+
if (this._clipping) {
672+
const tempPath = new Path2D();
673+
tempPath.ellipse(centerX, centerY, radiusX, radiusY, 0, start, stop);
674+
const currentTransform = this.drawingContext.getTransform();
675+
const clipBaseTransform = this._clipBaseTransform.inverse();
676+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
677+
this.clipPath.addPath(tempPath, relativeTransform);
678+
return this;
679+
}
667680
// Determines whether to add a line to the center, which should be done
668681
// when the mode is PIE or default; as well as when the start and end
669682
// angles do not form a full circle.
@@ -675,16 +688,16 @@ class Renderer2D extends Renderer {
675688

676689
// Fill curves
677690
if (this.states.fillColor) {
678-
if (!this._clipping) ctx.beginPath();
691+
ctx.beginPath();
679692
ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, start, stop);
680693
if (createPieSlice) ctx.lineTo(centerX, centerY);
681694
ctx.closePath();
682-
if (!this._clipping) ctx.fill();
695+
ctx.fill();
683696
}
684697

685698
// Stroke curves
686699
if (this.states.strokeColor) {
687-
if (!this._clipping) ctx.beginPath();
700+
ctx.beginPath();
688701
ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, start, stop);
689702

690703
if (mode === constants.PIE && createPieSlice) {
@@ -697,16 +710,15 @@ class Renderer2D extends Renderer {
697710
// Stroke connects back to path begin for both PIE and CHORD
698711
ctx.closePath();
699712
}
700-
701-
if (!this._clipping) ctx.stroke();
713+
ctx.stroke();
702714
}
703715

704716
return this;
705717

706718
}
707719

708720
ellipse(args) {
709-
const ctx = this.clipPath || this.drawingContext;
721+
const ctx = this.drawingContext;
710722
const doFill = !!this.states.fillColor,
711723
doStroke = this.states.strokeColor;
712724
const x = parseFloat(args[0]),
@@ -726,56 +738,83 @@ class Renderer2D extends Renderer {
726738
centerY = y + h / 2,
727739
radiusX = w / 2,
728740
radiusY = h / 2;
729-
if (!this._clipping) ctx.beginPath();
730-
741+
if (this._clipping) {
742+
const tempPath = new Path2D();
743+
tempPath.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, 2 * Math.PI);
744+
const currentTransform = this.drawingContext.getTransform();
745+
const clipBaseTransform = this._clipBaseTransform.inverse();
746+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
747+
this.clipPath.addPath(tempPath, relativeTransform);
748+
return this;
749+
}
750+
ctx.beginPath();
731751
ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, 2 * Math.PI);
732752
ctx.closePath();
733-
734-
if (!this._clipping && doFill) {
753+
if (doFill) {
735754
ctx.fill();
736755
}
737-
if (!this._clipping && doStroke) {
756+
if (doStroke) {
738757
ctx.stroke();
739758
}
759+
760+
return this;
740761
}
741762

742763
line(x1, y1, x2, y2) {
743-
const ctx = this.clipPath || this.drawingContext;
764+
const ctx = this.drawingContext;
744765
if (!this.states.strokeColor) {
745766
return this;
746767
} else if (this._getStroke() === styleEmpty) {
747768
return this;
748769
}
749-
if (!this._clipping) ctx.beginPath();
770+
if (this._clipping) {
771+
const tempPath = new Path2D();
772+
tempPath.moveTo(x1, y1);
773+
tempPath.lineTo(x2, y2);
774+
const currentTransform = this.drawingContext.getTransform();
775+
const clipBaseTransform = this._clipBaseTransform.inverse();
776+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
777+
this.clipPath.addPath(tempPath, relativeTransform);
778+
return this;
779+
}
780+
ctx.beginPath();
750781
ctx.moveTo(x1, y1);
751782
ctx.lineTo(x2, y2);
752783
ctx.stroke();
784+
753785
return this;
754786
}
755787

756788
point(x, y) {
757-
const ctx = this.clipPath || this.drawingContext;
789+
const ctx = this.drawingContext;
758790
if (!this.states.strokeColor) {
759791
return this;
760792
} else if (this._getStroke() === styleEmpty) {
761793
return this;
762794
}
763795
const s = this._getStroke();
764796
const f = this._getFill();
765-
if (!this._clipping) {
766-
// swapping fill color to stroke and back after for correct point rendering
767-
this._setFill(s);
797+
if (this._clipping) {
798+
const tempPath = new Path2D();
799+
const drawingContextWidth = this.drawingContext.lineWidth;
800+
tempPath.arc(x, y, drawingContextWidth / 2, 0, constants.TWO_PI);
801+
const currentTransform = this.drawingContext.getTransform();
802+
const clipBaseTransform = this._clipBaseTransform.inverse();
803+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
804+
this.clipPath.addPath(tempPath, relativeTransform);
805+
return this;
768806
}
769-
if (!this._clipping) ctx.beginPath();
807+
this._setFill(s);
808+
ctx.beginPath();
770809
ctx.arc(x, y, ctx.lineWidth / 2, 0, constants.TWO_PI, false);
771-
if (!this._clipping) {
772-
ctx.fill();
773-
this._setFill(f);
774-
}
810+
ctx.fill();
811+
this._setFill(f);
812+
813+
return this;
775814
}
776815

777816
quad(x1, y1, x2, y2, x3, y3, x4, y4) {
778-
const ctx = this.clipPath || this.drawingContext;
817+
const ctx = this.drawingContext;
779818
const doFill = !!this.states.fillColor,
780819
doStroke = this.states.strokeColor;
781820
if (doFill && !doStroke) {
@@ -787,16 +826,29 @@ class Renderer2D extends Renderer {
787826
return this;
788827
}
789828
}
790-
if (!this._clipping) ctx.beginPath();
829+
if (this._clipping) {
830+
const tempPath = new Path2D();
831+
tempPath.moveTo(x1, y1);
832+
tempPath.lineTo(x2, y2);
833+
tempPath.lineTo(x3, y3);
834+
tempPath.lineTo(x4, y4);
835+
tempPath.closePath();
836+
const currentTransform = this.drawingContext.getTransform();
837+
const clipBaseTransform = this._clipBaseTransform.inverse();
838+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
839+
this.clipPath.addPath(tempPath, relativeTransform);
840+
return this;
841+
}
842+
ctx.beginPath();
791843
ctx.moveTo(x1, y1);
792844
ctx.lineTo(x2, y2);
793845
ctx.lineTo(x3, y3);
794846
ctx.lineTo(x4, y4);
795847
ctx.closePath();
796-
if (!this._clipping && doFill) {
848+
if (doFill) {
797849
ctx.fill();
798850
}
799-
if (!this._clipping && doStroke) {
851+
if (doStroke) {
800852
ctx.stroke();
801853
}
802854
return this;
@@ -811,7 +863,7 @@ class Renderer2D extends Renderer {
811863
let tr = args[5];
812864
let br = args[6];
813865
let bl = args[7];
814-
const ctx = this.clipPath || this.drawingContext;
866+
const ctx = this.drawingContext;
815867
const doFill = !!this.states.fillColor,
816868
doStroke = this.states.strokeColor;
817869
if (doFill && !doStroke) {
@@ -823,8 +875,20 @@ class Renderer2D extends Renderer {
823875
return this;
824876
}
825877
}
826-
if (!this._clipping) ctx.beginPath();
827-
878+
if (this._clipping) {
879+
const tempPath = new Path2D();
880+
if (typeof tl === 'undefined') {
881+
tempPath.rect(x, y, w, h);
882+
} else {
883+
tempPath.roundRect(x, y, w, h, [tl, tr, br, bl]);
884+
}
885+
const currentTransform = this.drawingContext.getTransform();
886+
const clipBaseTransform = this._clipBaseTransform.inverse();
887+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
888+
this.clipPath.addPath(tempPath, relativeTransform);
889+
return this;
890+
}
891+
ctx.beginPath();
828892
if (typeof tl === 'undefined') {
829893
// No rounded corners
830894
ctx.rect(x, y, w, h);
@@ -875,18 +939,18 @@ class Renderer2D extends Renderer {
875939

876940
ctx.roundRect(x, y, w, h, [tl, tr, br, bl]);
877941
}
878-
if (!this._clipping && this.states.fillColor) {
942+
if (doFill) {
879943
ctx.fill();
880944
}
881-
if (!this._clipping && this.states.strokeColor) {
945+
if (doStroke) {
882946
ctx.stroke();
883947
}
884948
return this;
885949
}
886950

887951

888952
triangle(args) {
889-
const ctx = this.clipPath || this.drawingContext;
953+
const ctx = this.drawingContext;
890954
const doFill = !!this.states.fillColor,
891955
doStroke = this.states.strokeColor;
892956
const x1 = args[0],
@@ -904,17 +968,31 @@ class Renderer2D extends Renderer {
904968
return this;
905969
}
906970
}
907-
if (!this._clipping) ctx.beginPath();
971+
if (this._clipping) {
972+
const tempPath = new Path2D();
973+
tempPath.moveTo(x1, y1);
974+
tempPath.lineTo(x2, y2);
975+
tempPath.lineTo(x3, y3);
976+
tempPath.closePath();
977+
const currentTransform = this.drawingContext.getTransform();
978+
const clipBaseTransform = this._clipBaseTransform.inverse();
979+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
980+
this.clipPath.addPath(tempPath, relativeTransform);
981+
return this;
982+
}
983+
ctx.beginPath();
908984
ctx.moveTo(x1, y1);
909985
ctx.lineTo(x2, y2);
910986
ctx.lineTo(x3, y3);
911987
ctx.closePath();
912-
if (!this._clipping && doFill) {
988+
if (doFill) {
913989
ctx.fill();
914990
}
915-
if (!this._clipping && doStroke) {
991+
if (doStroke) {
916992
ctx.stroke();
917993
}
994+
995+
return this;
918996
}
919997

920998
//////////////////////////////////////////////

0 commit comments

Comments
 (0)