Skip to content

Commit 8a4422d

Browse files
authored
Merge branch 'dev-2.0' into color-perf
2 parents 279e180 + 2adc450 commit 8a4422d

34 files changed

Lines changed: 985 additions & 323 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"test/**/*.js": "eslint",
2020
"utils/**/*.{js,mjs}": "eslint"
2121
},
22-
"version": "2.2.0-rc.4",
22+
"version": "2.2.0",
2323
"dependencies": {
2424
"@davepagurek/bezier-path": "^0.0.2",
2525
"@japont/unicode-range": "^1.0.0",

preview/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107

108108
p.draw = function () {
109109
p.clear();
110+
p.rotateY(p.millis() * 0.001);
110111
p.push();
111112
//p.clip(() => p.rect(-50, -50, 200, 200));
112113
/*p.orbitControl();

src/core/p5.Renderer2D.js

Lines changed: 120 additions & 41 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();
@@ -546,16 +551,17 @@ class Renderer2D extends Renderer {
546551
// round down to get integer numbers
547552
x = Math.floor(x);
548553
y = Math.floor(y);
549-
if (imgOrCol instanceof Image) {
554+
if (imgOrCol instanceof Graphics || imgOrCol instanceof Image) {
550555
this.drawingContext.save();
551556
this.drawingContext.setTransform(1, 0, 0, 1, 0, 0);
552557
this.drawingContext.scale(
553558
this._pixelDensity,
554559
this._pixelDensity
555560
);
556-
this.drawingContext.clearRect(x, y, imgOrCol.width, imgOrCol.height);
557-
this.drawingContext.drawImage(imgOrCol.canvas, x, y);
558-
this.drawingContext.restore();
561+
const width = imgOrCol.width;
562+
const height = imgOrCol.height;
563+
this.drawingContext.clearRect(x, y, width, height);
564+
this.drawingContext.drawImage(imgOrCol.canvas, x, y, width, height);
559565
} else {
560566
let r = 0,
561567
g = 0,
@@ -652,7 +658,7 @@ class Renderer2D extends Renderer {
652658
* start <= stop < start + TWO_PI
653659
*/
654660
arc(x, y, w, h, start, stop, mode) {
655-
const ctx = this.clipPa || this.drawingContext;
661+
const ctx = this.drawingContext;
656662
const rx = w / 2.0;
657663
const ry = h / 2.0;
658664
const epsilon = 0.00001; // Smallest visible angle on displays up to 4K.
@@ -663,7 +669,15 @@ class Renderer2D extends Renderer {
663669
centerY = y + h / 2,
664670
radiusX = w / 2,
665671
radiusY = h / 2;
666-
672+
if (this._clipping) {
673+
const tempPath = new Path2D();
674+
tempPath.ellipse(centerX, centerY, radiusX, radiusY, 0, start, stop);
675+
const currentTransform = this.drawingContext.getTransform();
676+
const clipBaseTransform = this._clipBaseTransform.inverse();
677+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
678+
this.clipPath.addPath(tempPath, relativeTransform);
679+
return this;
680+
}
667681
// Determines whether to add a line to the center, which should be done
668682
// when the mode is PIE or default; as well as when the start and end
669683
// angles do not form a full circle.
@@ -675,16 +689,16 @@ class Renderer2D extends Renderer {
675689

676690
// Fill curves
677691
if (this.states.fillColor) {
678-
if (!this._clipping) ctx.beginPath();
692+
ctx.beginPath();
679693
ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, start, stop);
680694
if (createPieSlice) ctx.lineTo(centerX, centerY);
681695
ctx.closePath();
682-
if (!this._clipping) ctx.fill();
696+
ctx.fill();
683697
}
684698

685699
// Stroke curves
686700
if (this.states.strokeColor) {
687-
if (!this._clipping) ctx.beginPath();
701+
ctx.beginPath();
688702
ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, start, stop);
689703

690704
if (mode === constants.PIE && createPieSlice) {
@@ -697,16 +711,15 @@ class Renderer2D extends Renderer {
697711
// Stroke connects back to path begin for both PIE and CHORD
698712
ctx.closePath();
699713
}
700-
701-
if (!this._clipping) ctx.stroke();
714+
ctx.stroke();
702715
}
703716

704717
return this;
705718

706719
}
707720

708721
ellipse(args) {
709-
const ctx = this.clipPath || this.drawingContext;
722+
const ctx = this.drawingContext;
710723
const doFill = !!this.states.fillColor,
711724
doStroke = this.states.strokeColor;
712725
const x = parseFloat(args[0]),
@@ -726,56 +739,83 @@ class Renderer2D extends Renderer {
726739
centerY = y + h / 2,
727740
radiusX = w / 2,
728741
radiusY = h / 2;
729-
if (!this._clipping) ctx.beginPath();
730-
742+
if (this._clipping) {
743+
const tempPath = new Path2D();
744+
tempPath.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, 2 * Math.PI);
745+
const currentTransform = this.drawingContext.getTransform();
746+
const clipBaseTransform = this._clipBaseTransform.inverse();
747+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
748+
this.clipPath.addPath(tempPath, relativeTransform);
749+
return this;
750+
}
751+
ctx.beginPath();
731752
ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, 2 * Math.PI);
732753
ctx.closePath();
733-
734-
if (!this._clipping && doFill) {
754+
if (doFill) {
735755
ctx.fill();
736756
}
737-
if (!this._clipping && doStroke) {
757+
if (doStroke) {
738758
ctx.stroke();
739759
}
760+
761+
return this;
740762
}
741763

742764
line(x1, y1, x2, y2) {
743-
const ctx = this.clipPath || this.drawingContext;
765+
const ctx = this.drawingContext;
744766
if (!this.states.strokeColor) {
745767
return this;
746768
} else if (this._getStroke() === styleEmpty) {
747769
return this;
748770
}
749-
if (!this._clipping) ctx.beginPath();
771+
if (this._clipping) {
772+
const tempPath = new Path2D();
773+
tempPath.moveTo(x1, y1);
774+
tempPath.lineTo(x2, y2);
775+
const currentTransform = this.drawingContext.getTransform();
776+
const clipBaseTransform = this._clipBaseTransform.inverse();
777+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
778+
this.clipPath.addPath(tempPath, relativeTransform);
779+
return this;
780+
}
781+
ctx.beginPath();
750782
ctx.moveTo(x1, y1);
751783
ctx.lineTo(x2, y2);
752784
ctx.stroke();
785+
753786
return this;
754787
}
755788

756789
point(x, y) {
757-
const ctx = this.clipPath || this.drawingContext;
790+
const ctx = this.drawingContext;
758791
if (!this.states.strokeColor) {
759792
return this;
760793
} else if (this._getStroke() === styleEmpty) {
761794
return this;
762795
}
763796
const s = this._getStroke();
764797
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);
798+
if (this._clipping) {
799+
const tempPath = new Path2D();
800+
const drawingContextWidth = this.drawingContext.lineWidth;
801+
tempPath.arc(x, y, drawingContextWidth / 2, 0, constants.TWO_PI);
802+
const currentTransform = this.drawingContext.getTransform();
803+
const clipBaseTransform = this._clipBaseTransform.inverse();
804+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
805+
this.clipPath.addPath(tempPath, relativeTransform);
806+
return this;
768807
}
769-
if (!this._clipping) ctx.beginPath();
808+
this._setFill(s);
809+
ctx.beginPath();
770810
ctx.arc(x, y, ctx.lineWidth / 2, 0, constants.TWO_PI, false);
771-
if (!this._clipping) {
772-
ctx.fill();
773-
this._setFill(f);
774-
}
811+
ctx.fill();
812+
this._setFill(f);
813+
814+
return this;
775815
}
776816

777817
quad(x1, y1, x2, y2, x3, y3, x4, y4) {
778-
const ctx = this.clipPath || this.drawingContext;
818+
const ctx = this.drawingContext;
779819
const doFill = !!this.states.fillColor,
780820
doStroke = this.states.strokeColor;
781821
if (doFill && !doStroke) {
@@ -787,16 +827,29 @@ class Renderer2D extends Renderer {
787827
return this;
788828
}
789829
}
790-
if (!this._clipping) ctx.beginPath();
830+
if (this._clipping) {
831+
const tempPath = new Path2D();
832+
tempPath.moveTo(x1, y1);
833+
tempPath.lineTo(x2, y2);
834+
tempPath.lineTo(x3, y3);
835+
tempPath.lineTo(x4, y4);
836+
tempPath.closePath();
837+
const currentTransform = this.drawingContext.getTransform();
838+
const clipBaseTransform = this._clipBaseTransform.inverse();
839+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
840+
this.clipPath.addPath(tempPath, relativeTransform);
841+
return this;
842+
}
843+
ctx.beginPath();
791844
ctx.moveTo(x1, y1);
792845
ctx.lineTo(x2, y2);
793846
ctx.lineTo(x3, y3);
794847
ctx.lineTo(x4, y4);
795848
ctx.closePath();
796-
if (!this._clipping && doFill) {
849+
if (doFill) {
797850
ctx.fill();
798851
}
799-
if (!this._clipping && doStroke) {
852+
if (doStroke) {
800853
ctx.stroke();
801854
}
802855
return this;
@@ -811,7 +864,7 @@ class Renderer2D extends Renderer {
811864
let tr = args[5];
812865
let br = args[6];
813866
let bl = args[7];
814-
const ctx = this.clipPath || this.drawingContext;
867+
const ctx = this.drawingContext;
815868
const doFill = !!this.states.fillColor,
816869
doStroke = this.states.strokeColor;
817870
if (doFill && !doStroke) {
@@ -823,8 +876,20 @@ class Renderer2D extends Renderer {
823876
return this;
824877
}
825878
}
826-
if (!this._clipping) ctx.beginPath();
827-
879+
if (this._clipping) {
880+
const tempPath = new Path2D();
881+
if (typeof tl === 'undefined') {
882+
tempPath.rect(x, y, w, h);
883+
} else {
884+
tempPath.roundRect(x, y, w, h, [tl, tr, br, bl]);
885+
}
886+
const currentTransform = this.drawingContext.getTransform();
887+
const clipBaseTransform = this._clipBaseTransform.inverse();
888+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
889+
this.clipPath.addPath(tempPath, relativeTransform);
890+
return this;
891+
}
892+
ctx.beginPath();
828893
if (typeof tl === 'undefined') {
829894
// No rounded corners
830895
ctx.rect(x, y, w, h);
@@ -875,18 +940,18 @@ class Renderer2D extends Renderer {
875940

876941
ctx.roundRect(x, y, w, h, [tl, tr, br, bl]);
877942
}
878-
if (!this._clipping && this.states.fillColor) {
943+
if (doFill) {
879944
ctx.fill();
880945
}
881-
if (!this._clipping && this.states.strokeColor) {
946+
if (doStroke) {
882947
ctx.stroke();
883948
}
884949
return this;
885950
}
886951

887952

888953
triangle(args) {
889-
const ctx = this.clipPath || this.drawingContext;
954+
const ctx = this.drawingContext;
890955
const doFill = !!this.states.fillColor,
891956
doStroke = this.states.strokeColor;
892957
const x1 = args[0],
@@ -904,17 +969,31 @@ class Renderer2D extends Renderer {
904969
return this;
905970
}
906971
}
907-
if (!this._clipping) ctx.beginPath();
972+
if (this._clipping) {
973+
const tempPath = new Path2D();
974+
tempPath.moveTo(x1, y1);
975+
tempPath.lineTo(x2, y2);
976+
tempPath.lineTo(x3, y3);
977+
tempPath.closePath();
978+
const currentTransform = this.drawingContext.getTransform();
979+
const clipBaseTransform = this._clipBaseTransform.inverse();
980+
const relativeTransform = clipBaseTransform.multiply(currentTransform);
981+
this.clipPath.addPath(tempPath, relativeTransform);
982+
return this;
983+
}
984+
ctx.beginPath();
908985
ctx.moveTo(x1, y1);
909986
ctx.lineTo(x2, y2);
910987
ctx.lineTo(x3, y3);
911988
ctx.closePath();
912-
if (!this._clipping && doFill) {
989+
if (doFill) {
913990
ctx.fill();
914991
}
915-
if (!this._clipping && doStroke) {
992+
if (doStroke) {
916993
ctx.stroke();
917994
}
995+
996+
return this;
918997
}
919998

920999
//////////////////////////////////////////////

src/strands/ir_types.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const NodeTypeRequiredFields = {
2727
export const StatementType = {
2828
DISCARD: 'discard',
2929
BREAK: 'break',
30+
EARLY_RETURN: 'early_return',
3031
EXPRESSION: 'expression', // Used when we want to output a single expression as a statement, e.g. a for loop condition
3132
EMPTY: 'empty', // Used for empty statements like ; in for loops
3233
};

0 commit comments

Comments
 (0)