q5 2.9.8 → 2.9.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/q5.d.ts +95 -1
- package/q5.js +48 -21
- package/q5.min.js +1 -1
- package/src/q5-2d-canvas.js +11 -2
- package/src/q5-2d-drawing.js +17 -2
- package/src/q5-canvas.js +4 -2
- package/src/q5-webgpu-canvas.js +3 -3
- package/src/q5-webgpu-drawing.js +9 -8
- package/src/q5-webgpu-text.js +4 -4
- package/src/readme.md +1 -1
package/package.json
CHANGED
package/q5.d.ts
CHANGED
|
@@ -402,31 +402,74 @@ function draw() {
|
|
|
402
402
|
* Translates the origin of the drawing context.
|
|
403
403
|
* @param {number} x - translation along the x-axis
|
|
404
404
|
* @param {number} y - translation along the y-axis
|
|
405
|
+
* @example
|
|
406
|
+
function draw() {
|
|
407
|
+
background(200);
|
|
408
|
+
|
|
409
|
+
translate(100, 100);
|
|
410
|
+
circle(0, 0, 80);
|
|
411
|
+
}
|
|
405
412
|
*/
|
|
406
413
|
function translate(x: number, y: number): void;
|
|
407
414
|
|
|
408
415
|
/** ⬜️
|
|
409
416
|
* Rotates the drawing context.
|
|
410
417
|
* @param {number} angle - rotation angle in radians
|
|
418
|
+
* @example
|
|
419
|
+
function draw() {
|
|
420
|
+
background(200);
|
|
421
|
+
|
|
422
|
+
translate(100, 100);
|
|
423
|
+
rotate(QUARTER_PI);
|
|
424
|
+
|
|
425
|
+
// drawn from its top-left corner by default
|
|
426
|
+
square(0, 0, 50);
|
|
427
|
+
}
|
|
411
428
|
*/
|
|
412
429
|
function rotate(angle: number): void;
|
|
413
430
|
|
|
414
431
|
/** ⬜️
|
|
415
432
|
* Scales the drawing context.
|
|
433
|
+
*
|
|
434
|
+
* If only one input parameter is provided,
|
|
435
|
+
* the drawing context will be scaled uniformly.
|
|
416
436
|
* @param {number} x - scaling factor along the x-axis
|
|
417
437
|
* @param {number} [y] - scaling factor along the y-axis
|
|
438
|
+
* @example
|
|
439
|
+
function draw() {
|
|
440
|
+
background(200);
|
|
441
|
+
|
|
442
|
+
scale(4);
|
|
443
|
+
circle(0, 0, 80);
|
|
444
|
+
}
|
|
418
445
|
*/
|
|
419
446
|
function scale(x: number, y?: number): void;
|
|
420
447
|
|
|
421
448
|
/** ⬜️
|
|
422
449
|
* Shears the drawing context along the x-axis.
|
|
423
450
|
* @param {number} angle - shear angle in radians
|
|
451
|
+
* @example
|
|
452
|
+
function draw() {
|
|
453
|
+
background(200);
|
|
454
|
+
|
|
455
|
+
translate(25, 60);
|
|
456
|
+
shearX(QUARTER_PI);
|
|
457
|
+
square(0, 0, 80);
|
|
458
|
+
}
|
|
424
459
|
*/
|
|
425
460
|
function shearX(angle: number): void;
|
|
426
461
|
|
|
427
462
|
/** ⬜️
|
|
428
463
|
* Shears the drawing context along the y-axis.
|
|
429
464
|
* @param {number} angle - shear angle in radians
|
|
465
|
+
* @example
|
|
466
|
+
function draw() {
|
|
467
|
+
background(200);
|
|
468
|
+
|
|
469
|
+
translate(25, 60);
|
|
470
|
+
shearY(QUARTER_PI);
|
|
471
|
+
square(0, 0, 80);
|
|
472
|
+
}
|
|
430
473
|
*/
|
|
431
474
|
function shearY(angle: number): void;
|
|
432
475
|
|
|
@@ -440,16 +483,46 @@ function draw() {
|
|
|
440
483
|
* @param {number} d - vertical scaling
|
|
441
484
|
* @param {number} e - horizontal moving
|
|
442
485
|
* @param {number} f - vertical moving
|
|
486
|
+
* @example
|
|
487
|
+
function draw() {
|
|
488
|
+
background(200);
|
|
489
|
+
|
|
490
|
+
applyMatrix(2, 1, 1, 1, 100, 100);
|
|
491
|
+
circle(0, 0, 80);
|
|
492
|
+
}
|
|
443
493
|
*/
|
|
444
494
|
function applyMatrix(a: number, b: number, c: number, d: number, e: number, f: number): void;
|
|
445
495
|
|
|
446
496
|
/** ⬜️
|
|
447
497
|
* Resets the transformation matrix.
|
|
498
|
+
*
|
|
499
|
+
* q5 runs this function before every time the `draw` function is run,
|
|
500
|
+
* so that transformations don't carry over to the next frame.
|
|
501
|
+
* @example
|
|
502
|
+
function draw() {
|
|
503
|
+
background(200);
|
|
504
|
+
|
|
505
|
+
translate(100, 100);
|
|
506
|
+
circle(0, 0, 80);
|
|
507
|
+
|
|
508
|
+
resetMatrix();
|
|
509
|
+
square(0, 0, 50);
|
|
510
|
+
}
|
|
448
511
|
*/
|
|
449
512
|
function resetMatrix(): void;
|
|
450
513
|
|
|
451
514
|
/** ⬜️
|
|
452
515
|
* Saves the current transformation matrix.
|
|
516
|
+
* @example
|
|
517
|
+
function draw() {
|
|
518
|
+
background(200);
|
|
519
|
+
translate(100, 100);
|
|
520
|
+
pushMatrix();
|
|
521
|
+
rotate(QUARTER_PI);
|
|
522
|
+
ellipse(0, 0, 120, 40);
|
|
523
|
+
popMatrix();
|
|
524
|
+
ellipse(0, 0, 120, 40);
|
|
525
|
+
}
|
|
453
526
|
*/
|
|
454
527
|
function pushMatrix(): void;
|
|
455
528
|
|
|
@@ -461,7 +534,18 @@ function draw() {
|
|
|
461
534
|
/** ⬜️
|
|
462
535
|
* Saves the current drawing style settings.
|
|
463
536
|
*
|
|
464
|
-
* This includes the fill, stroke, stroke weight, tint, image mode,
|
|
537
|
+
* This includes the fill, stroke, stroke weight, tint, image mode,
|
|
538
|
+
* rect mode, ellipse mode, text size, text align, and text baseline.
|
|
539
|
+
* @example
|
|
540
|
+
function draw() {
|
|
541
|
+
background(200);
|
|
542
|
+
|
|
543
|
+
pushStyles();
|
|
544
|
+
fill('blue');
|
|
545
|
+
circle(50, 50, 80);
|
|
546
|
+
popStyles();
|
|
547
|
+
circle(150, 150, 80);
|
|
548
|
+
}
|
|
465
549
|
*/
|
|
466
550
|
function pushStyles(): void;
|
|
467
551
|
|
|
@@ -472,6 +556,16 @@ function draw() {
|
|
|
472
556
|
|
|
473
557
|
/** ⬜️
|
|
474
558
|
* Saves the current drawing style settings and transformations.
|
|
559
|
+
* @example
|
|
560
|
+
createCanvas(200, 200);
|
|
561
|
+
|
|
562
|
+
push();
|
|
563
|
+
fill('blue');
|
|
564
|
+
translate(100, 100);
|
|
565
|
+
circle(0, 0, 80);
|
|
566
|
+
pop();
|
|
567
|
+
|
|
568
|
+
square(0, 0, 50);
|
|
475
569
|
*/
|
|
476
570
|
function push(): void;
|
|
477
571
|
|
package/q5.js
CHANGED
|
@@ -445,8 +445,8 @@ Q5.modules.canvas = ($, q) => {
|
|
|
445
445
|
opt.alpha ??= true;
|
|
446
446
|
opt.colorSpace ??= $.canvas.colorSpace;
|
|
447
447
|
g.createCanvas.call($, w, h, opt);
|
|
448
|
-
g.defaultWidth = w
|
|
449
|
-
g.defaultHeight = h
|
|
448
|
+
g.defaultWidth = w;
|
|
449
|
+
g.defaultHeight = h;
|
|
450
450
|
return g;
|
|
451
451
|
};
|
|
452
452
|
|
|
@@ -593,6 +593,8 @@ Q5.modules.canvas = ($, q) => {
|
|
|
593
593
|
};
|
|
594
594
|
|
|
595
595
|
$._styleNames = [
|
|
596
|
+
'_fill',
|
|
597
|
+
'_stroke',
|
|
596
598
|
'_doStroke',
|
|
597
599
|
'_doFill',
|
|
598
600
|
'_strokeSet',
|
|
@@ -647,8 +649,8 @@ Q5.renderers.q2d.canvas = ($, q) => {
|
|
|
647
649
|
|
|
648
650
|
if ($._scope != 'image') {
|
|
649
651
|
// default styles
|
|
650
|
-
$.ctx.fillStyle = 'white';
|
|
651
|
-
$.ctx.strokeStyle = 'black';
|
|
652
|
+
$.ctx.fillStyle = $._fill = 'white';
|
|
653
|
+
$.ctx.strokeStyle = $._stroke = 'black';
|
|
652
654
|
$.ctx.lineCap = 'round';
|
|
653
655
|
$.ctx.lineJoin = 'miter';
|
|
654
656
|
$.ctx.textAlign = 'left';
|
|
@@ -757,6 +759,15 @@ Q5.renderers.q2d.canvas = ($, q) => {
|
|
|
757
759
|
$.pushMatrix = () => $.ctx.save();
|
|
758
760
|
$.popMatrix = () => $.ctx.restore();
|
|
759
761
|
|
|
762
|
+
$.popStyles = () => {
|
|
763
|
+
let styles = $._styles.pop();
|
|
764
|
+
for (let s of $._styleNames) $[s] = styles[s];
|
|
765
|
+
|
|
766
|
+
$.ctx.fillStyle = $._fill;
|
|
767
|
+
$.ctx.strokeStyle = $._stroke;
|
|
768
|
+
$.ctx.lineWidth = $._strokeWeight;
|
|
769
|
+
};
|
|
770
|
+
|
|
760
771
|
$.push = () => {
|
|
761
772
|
$.ctx.save();
|
|
762
773
|
$.pushStyles();
|
|
@@ -844,14 +855,15 @@ Q5.renderers.q2d.drawing = ($) => {
|
|
|
844
855
|
|
|
845
856
|
function arc(x, y, w, h, lo, hi, mode, detail) {
|
|
846
857
|
if (!$._doFill && !$._doStroke) return;
|
|
858
|
+
|
|
847
859
|
let d = $._angleMode;
|
|
848
860
|
let full = d ? 360 : $.TAU;
|
|
849
861
|
lo %= full;
|
|
850
862
|
hi %= full;
|
|
851
863
|
if (lo < 0) lo += full;
|
|
852
864
|
if (hi < 0) hi += full;
|
|
853
|
-
if (lo
|
|
854
|
-
|
|
865
|
+
if (lo > hi) hi += full;
|
|
866
|
+
|
|
855
867
|
$.ctx.beginPath();
|
|
856
868
|
if (w == h) {
|
|
857
869
|
if (d) {
|
|
@@ -859,6 +871,15 @@ Q5.renderers.q2d.drawing = ($) => {
|
|
|
859
871
|
hi = $.radians(hi);
|
|
860
872
|
}
|
|
861
873
|
$.ctx.arc(x, y, w / 2, lo, hi);
|
|
874
|
+
|
|
875
|
+
if (mode == $.CHORD) {
|
|
876
|
+
$.ctx.lineTo(x + (Math.cos(hi) * w) / 2, y + (Math.sin(hi) * h) / 2);
|
|
877
|
+
$.ctx.lineTo(x + (Math.cos(lo) * w) / 2, y + (Math.sin(lo) * h) / 2);
|
|
878
|
+
$.ctx.closePath();
|
|
879
|
+
} else if (mode == $.PIE) {
|
|
880
|
+
$.ctx.lineTo(x, y);
|
|
881
|
+
$.ctx.closePath();
|
|
882
|
+
}
|
|
862
883
|
} else {
|
|
863
884
|
for (let i = 0; i < detail + 1; i++) {
|
|
864
885
|
let t = i / detail;
|
|
@@ -867,7 +888,10 @@ Q5.renderers.q2d.drawing = ($) => {
|
|
|
867
888
|
let dy = ($.sin(a) * h) / 2;
|
|
868
889
|
$.ctx[i ? 'lineTo' : 'moveTo'](x + dx, y + dy);
|
|
869
890
|
}
|
|
891
|
+
|
|
870
892
|
if (mode == $.CHORD) {
|
|
893
|
+
$.ctx.lineTo(x + ($.cos(hi) * w) / 2, y + ($.sin(hi) * h) / 2);
|
|
894
|
+
$.ctx.lineTo(x + ($.cos(lo) * w) / 2, y + ($.sin(lo) * h) / 2);
|
|
871
895
|
$.ctx.closePath();
|
|
872
896
|
} else if (mode == $.PIE) {
|
|
873
897
|
$.ctx.lineTo(x, y);
|
|
@@ -926,6 +950,7 @@ Q5.renderers.q2d.drawing = ($) => {
|
|
|
926
950
|
ink();
|
|
927
951
|
} else $.ellipse(x, y, d, d);
|
|
928
952
|
};
|
|
953
|
+
|
|
929
954
|
$.point = (x, y) => {
|
|
930
955
|
if ($._doStroke) {
|
|
931
956
|
if (x.x) {
|
|
@@ -942,6 +967,7 @@ Q5.renderers.q2d.drawing = ($) => {
|
|
|
942
967
|
$.ctx.stroke();
|
|
943
968
|
}
|
|
944
969
|
};
|
|
970
|
+
|
|
945
971
|
function rect(x, y, w, h) {
|
|
946
972
|
if ($._da) {
|
|
947
973
|
x *= $._da;
|
|
@@ -3288,18 +3314,18 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3288
3314
|
colorIndex++;
|
|
3289
3315
|
};
|
|
3290
3316
|
|
|
3291
|
-
$.
|
|
3317
|
+
$._fill = $._stroke = 0;
|
|
3292
3318
|
$._doFill = $._doStroke = true;
|
|
3293
3319
|
|
|
3294
3320
|
$.fill = (r, g, b, a) => {
|
|
3295
3321
|
addColor(r, g, b, a);
|
|
3296
3322
|
$._doFill = $._fillSet = true;
|
|
3297
|
-
$.
|
|
3323
|
+
$._fill = colorIndex;
|
|
3298
3324
|
};
|
|
3299
3325
|
$.stroke = (r, g, b, a) => {
|
|
3300
3326
|
addColor(r, g, b, a);
|
|
3301
3327
|
$._doStroke = $._strokeSet = true;
|
|
3302
|
-
$.
|
|
3328
|
+
$._stroke = colorIndex;
|
|
3303
3329
|
};
|
|
3304
3330
|
|
|
3305
3331
|
$.noFill = () => ($._doFill = false);
|
|
@@ -3828,6 +3854,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
3828
3854
|
};
|
|
3829
3855
|
|
|
3830
3856
|
const addEllipse = (x, y, a, b, n, ci, ti) => {
|
|
3857
|
+
y = -y;
|
|
3831
3858
|
let t = 0,
|
|
3832
3859
|
angleIncrement = $.TAU / n;
|
|
3833
3860
|
|
|
@@ -3880,7 +3907,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
3880
3907
|
ti = $._transformIndex;
|
|
3881
3908
|
|
|
3882
3909
|
if ($._doStroke) {
|
|
3883
|
-
ci = $.
|
|
3910
|
+
ci = $._stroke;
|
|
3884
3911
|
|
|
3885
3912
|
// stroke weight adjustment
|
|
3886
3913
|
let sw = $._strokeWeight / 2;
|
|
@@ -3919,7 +3946,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
3919
3946
|
}
|
|
3920
3947
|
|
|
3921
3948
|
if ($._doFill) {
|
|
3922
|
-
ci = colorIndex ?? $.
|
|
3949
|
+
ci = colorIndex ?? $._fill;
|
|
3923
3950
|
addRect(l, t, r, t, r, b, l, b, ci, ti);
|
|
3924
3951
|
}
|
|
3925
3952
|
};
|
|
@@ -3968,19 +3995,19 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
3968
3995
|
let ti = $._transformIndex;
|
|
3969
3996
|
if ($._doStroke) {
|
|
3970
3997
|
let sw = $._strokeWeight / 2;
|
|
3971
|
-
addEllipse(x, y, a + sw, b + sw, n, $.
|
|
3998
|
+
addEllipse(x, y, a + sw, b + sw, n, $._stroke, ti);
|
|
3972
3999
|
a -= sw;
|
|
3973
4000
|
b -= sw;
|
|
3974
4001
|
}
|
|
3975
4002
|
if ($._doFill) {
|
|
3976
|
-
addEllipse(x, y, a, b, n, colorIndex ?? $.
|
|
4003
|
+
addEllipse(x, y, a, b, n, colorIndex ?? $._fill, ti);
|
|
3977
4004
|
}
|
|
3978
4005
|
};
|
|
3979
4006
|
|
|
3980
4007
|
$.circle = (x, y, d) => $.ellipse(x, y, d, d);
|
|
3981
4008
|
|
|
3982
4009
|
$.point = (x, y) => {
|
|
3983
|
-
colorIndex = $.
|
|
4010
|
+
colorIndex = $._stroke;
|
|
3984
4011
|
$._doStroke = false;
|
|
3985
4012
|
let sw = $._strokeWeight;
|
|
3986
4013
|
if (sw < 2) {
|
|
@@ -3992,7 +4019,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
3992
4019
|
};
|
|
3993
4020
|
|
|
3994
4021
|
$.line = (x1, y1, x2, y2) => {
|
|
3995
|
-
colorIndex = $.
|
|
4022
|
+
colorIndex = $._stroke;
|
|
3996
4023
|
|
|
3997
4024
|
$.push();
|
|
3998
4025
|
$._doStroke = false;
|
|
@@ -4026,7 +4053,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
4026
4053
|
|
|
4027
4054
|
$.vertex = (x, y) => {
|
|
4028
4055
|
if ($._matrixDirty) $._saveMatrix();
|
|
4029
|
-
sv.push(x, -y, $.
|
|
4056
|
+
sv.push(x, -y, $._fill, $._transformIndex);
|
|
4030
4057
|
shapeVertCount++;
|
|
4031
4058
|
};
|
|
4032
4059
|
|
|
@@ -4119,7 +4146,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
4119
4146
|
$._rectMode = og;
|
|
4120
4147
|
}
|
|
4121
4148
|
$.pop();
|
|
4122
|
-
if (!$._fillSet) $.
|
|
4149
|
+
if (!$._fillSet) $._fill = 1;
|
|
4123
4150
|
};
|
|
4124
4151
|
|
|
4125
4152
|
$._hooks.preRender.push(() => {
|
|
@@ -4839,8 +4866,8 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
|
|
|
4839
4866
|
text[1] = -y;
|
|
4840
4867
|
text[2] = $._textSize / 44;
|
|
4841
4868
|
text[3] = $._transformIndex;
|
|
4842
|
-
text[4] = $._fillSet ? $.
|
|
4843
|
-
text[5] = $.
|
|
4869
|
+
text[4] = $._fillSet ? $._fill : 0;
|
|
4870
|
+
text[5] = $._stroke;
|
|
4844
4871
|
|
|
4845
4872
|
$._textStack.push(text);
|
|
4846
4873
|
$.drawStack.push(2, measurements.printedCharCount, $._font.index);
|
|
@@ -4855,11 +4882,11 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
|
|
|
4855
4882
|
g.textSize($._textSize);
|
|
4856
4883
|
|
|
4857
4884
|
if ($._doFill) {
|
|
4858
|
-
let fi = $.
|
|
4885
|
+
let fi = $._fill * 4;
|
|
4859
4886
|
g.fill(colorStack.slice(fi, fi + 4));
|
|
4860
4887
|
}
|
|
4861
4888
|
if ($._doStroke) {
|
|
4862
|
-
let si = $.
|
|
4889
|
+
let si = $._stroke * 4;
|
|
4863
4890
|
g.stroke(colorStack.slice(si, si + 4));
|
|
4864
4891
|
}
|
|
4865
4892
|
|
package/q5.min.js
CHANGED
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
* @license LGPL-3.0
|
|
6
6
|
* @class Q5
|
|
7
7
|
*/
|
|
8
|
-
function Q5(e,t,r){let a=this;a._q5=!0,a._parent=t,a._renderer=r||"q2d",a._preloadCount=0;let n,o="auto"==e;if(e??="global","auto"==e){if(!window.setup&&!window.draw)return;e="global"}a._scope=e,"global"==e&&(Q5._hasGlobal=a._isGlobal=!0,n=Q5._nodejs?global:window);let i=new Proxy(a,{set:(e,t,r)=>(a[t]=r,a._isGlobal&&(n[t]=r),!0)});a.canvas=a.ctx=a.drawingContext=null,a.pixels=[];let s=null;a.frameCount=0,a.deltaTime=16,a._targetFrameRate=0,a._targetFrameDuration=16.666666666666668,a._frameRate=a._fps=60,a._loop=!0,a._hooks={postCanvas:[],preRender:[],postRender:[]};let l=0;a.millis=()=>performance.now()-l,a.noCanvas=()=>{a.canvas?.remove&&a.canvas.remove(),a.canvas=0,i.ctx=i.drawingContext=0},window&&(a.windowWidth=window.innerWidth,a.windowHeight=window.innerHeight,a.deviceOrientation=window.screen?.orientation?.type),a._incrementPreload=()=>i._preloadCount++,a._decrementPreload=()=>i._preloadCount--,a._draw=e=>{let t=e||performance.now();if(a._lastFrameTime??=t-a._targetFrameDuration,a._didResize&&(a.windowResized(),a._didResize=!1),a._loop)s=c(a._draw);else if(a.frameCount&&!a._redraw)return;if(s&&a.frameCount){if(t-a._lastFrameTime<a._targetFrameDuration-4)return}i.deltaTime=t-a._lastFrameTime,a._frameRate=1e3/a.deltaTime,i.frameCount++;let r=performance.now();a.resetMatrix(),a._beginRender&&a._beginRender();for(let e of Q5.methods.pre)e.call(a);try{a.draw()}catch(e){throw!Q5.disableFriendlyErrors&&a._askAI&&a._askAI(e),Q5.errorTolerant||a.noLoop(),e}for(let e of Q5.methods.post)e.call(a);a._render&&a._render(),a._finishRender&&a._finishRender(),i.pmouseX=a.mouseX,i.pmouseY=a.mouseY,i.moveX=i.moveY=0,a._lastFrameTime=t;let n=performance.now();a._fps=Math.round(1e3/(n-r))},a.noLoop=()=>{a._loop=!1,s=null},a.loop=()=>{a._loop=!0,null==s&&a._draw()},a.isLooping=()=>a._loop,a.redraw=(e=1)=>{a._redraw=!0;for(let t=0;t<e;t++)a._draw();a._redraw=!1},a.remove=()=>{a.noLoop(),a.canvas.remove()},a.frameRate=e=>(e&&(a._targetFrameRate=e,a._targetFrameDuration=1e3/e),a._frameRate),a.getTargetFrameRate=()=>a._targetFrameRate||60,a.getFPS=()=>a._fps,a.Element=function(e){this.elt=e},a._elements=[],a.TWO_PI=a.TAU=2*Math.PI,a.log=a.print=console.log,a.describe=()=>{};for(let e in Q5.modules)Q5.modules[e](a,i);let d=Q5.renderers[a._renderer];for(let e in d)d[e](a,i);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(a[e]=Q5[e]);if("graphics"==e)return;"global"==e&&(Object.assign(Q5,a),delete Q5.Q5);for(let e of Q5.methods.init)e.call(a);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof a[e]&&(a[e]=t.bind(a));if("global"==e){let e=Object.getOwnPropertyNames(a);for(let t of e)"_"!=t[0]&&(n[t]=a[t])}"function"==typeof e&&e(a),Q5._instanceCount++;let c=window.requestAnimationFrame||function(e){const t=a._lastFrameTime+a._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},h=n||a;a._isTouchAware=h.touchStarted||h.touchMoved||h.mouseReleased,a._isGlobal&&(a.preload=h.preload,a.setup=h.setup,a.draw=h.draw),a.preload??=()=>{},a.setup??=()=>{},a.draw??=()=>{};let u=["mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","mouseWheel","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of u)h[e]?a._isGlobal&&(a[e]=t=>{try{return h[e](t)}catch(e){throw a._askAI&&a._askAI(e),e}}):a[e]=()=>{};async function p(){if(a._startDone=!0,a._preloadCount>0)return c(p);l=performance.now(),await a.setup(),a._setupDone=!0,a.frameCount||(null===a.ctx&&a.createCanvas(200,200),a.ctx&&a.resetMatrix(),c(a._draw))}function f(){try{a.preload(),a._startDone||p()}catch(e){throw a._askAI&&a._askAI(e),e}}o?f():setTimeout(f,32)}function createCanvas(e,t,r){if(!Q5._hasGlobal){(new Q5).createCanvas(e,t,r)}}Q5.renderers={},Q5.modules={},Q5._nodejs="object"==typeof process,Q5._instanceCount=0,Q5._friendlyError=(e,t)=>{Q5.disableFriendlyErrors||console.error(t+": "+e)},Q5._validateParameters=()=>!0,Q5.methods={init:[],pre:[],post:[],remove:[]},Q5.prototype.registerMethod=(e,t)=>Q5.methods[e].push(t),Q5.prototype.registerPreloadMethod=(e,t)=>Q5.prototype[e]=t[e],Q5._nodejs&&(global.p5??=global.Q5=Q5),"object"==typeof window?window.p5??=window.Q5=Q5:global.window=0,"object"==typeof document&&document.addEventListener("DOMContentLoaded",(()=>{Q5._hasGlobal||new Q5("auto")})),Q5.modules.canvas=(e,t)=>{e.CENTER="center",e.LEFT="left",e.RIGHT="right",e.TOP="top",e.BOTTOM="bottom",e.BASELINE="alphabetic",e.NORMAL="normal",e.ITALIC="italic",e.BOLD="bold",e.BOLDITALIC="italic bold",e.ROUND="round",e.SQUARE="butt",e.PROJECT="square",e.MITER="miter",e.BEVEL="bevel",e.CHORD=0,e.PIE=1,e.OPEN=2,e.RADIUS="radius",e.CORNER="corner",e.CORNERS="corners",e.CLOSE=1,e.LANDSCAPE="landscape",e.PORTRAIT="portrait",e.BLEND="source-over",e.REMOVE="destination-out",e.ADD="lighter",e.DARKEST="darken",e.LIGHTEST="lighten",e.DIFFERENCE="difference",e.SUBTRACT="subtract",e.EXCLUSION="exclusion",e.MULTIPLY="multiply",e.SCREEN="screen",e.REPLACE="copy",e.OVERLAY="overlay",e.HARD_LIGHT="hard-light",e.SOFT_LIGHT="soft-light",e.DODGE="color-dodge",e.BURN="color-burn",e.P2D="2d",e.WEBGL="webgl",e._OffscreenCanvas=window.OffscreenCanvas||function(){return document.createElement("canvas")},Q5._nodejs?Q5._createNodeJSCanvas&&(t.canvas=Q5._createNodeJSCanvas(100,100)):"image"!=e._scope&&"graphics"!=e._scope||(t.canvas=new e._OffscreenCanvas(100,100)),e.canvas||("object"==typeof document?(t.canvas=document.createElement("canvas"),e.canvas.id="q5Canvas"+Q5._instanceCount,e.canvas.classList.add("q5Canvas")):e.noCanvas());let r=e.canvas;if(r.width=e.width=100,r.height=e.height=100,e._pixelDensity=1,e.displayDensity=()=>window.devicePixelRatio||1,"image"!=e._scope&&(r.renderer=e._renderer,r[e._renderer]=!0,e._pixelDensity=Math.ceil(e.displayDensity())),e._adjustDisplay=()=>{r.style&&(r.style.width=r.w+"px",r.style.height=r.h+"px")},e.createCanvas=function(t,a,n){n??=arguments[3];let o=Object.assign({},Q5.canvasOptions);if("object"==typeof n&&Object.assign(o,n),"image"!=e._scope)if("graphics"==e._scope)e._pixelDensity=this._pixelDensity;else if(window.IntersectionObserver){let t=!1;new IntersectionObserver((a=>{r.visible=a[0].isIntersecting,t||(e._wasLooping=e._loop,t=!0),r.visible?e._wasLooping&&!e._loop&&e.loop():(e._wasLooping=e._loop,e.noLoop())})).observe(r)}e._setCanvasSize(t,a),Object.assign(r,o);let i=e._createCanvas(r.w,r.h,o);if(e._hooks)for(let t of e._hooks.postCanvas)t();return e._beginRender&&e._beginRender(),i},e.createGraphics=function(t,r,a){let n=new Q5("graphics");return a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace,n.createCanvas.call(e,t,r,a),n.defaultWidth=t*e._defaultImageScale,n.defaultHeight=r*e._defaultImageScale,n},e._save=async(e,t,r)=>{if(t=t||"untitled","jpg"==(r=r||"png")||"png"==r||"webp"==r)if(e instanceof OffscreenCanvas){const t=await e.convertToBlob({type:"image/"+r});e=await new Promise((e=>{const r=new FileReader;r.onloadend=()=>e(r.result),r.readAsDataURL(t)}))}else e=e.toDataURL("image/"+r);else{let t="text/plain";"json"==r&&("string"!=typeof e&&(e=JSON.stringify(e)),t="text/json"),e=new Blob([e],{type:t}),e=URL.createObjectURL(e)}let a=document.createElement("a");a.href=e,a.download=t+"."+r,a.click(),URL.revokeObjectURL(a.href)},e.save=(t,r,a)=>{if((!t||"string"==typeof t&&(!r||!a&&r.length<5))&&(a=r,r=t,t=e.canvas),a)return e._save(t,r,a);r?(r=r.split("."),e._save(t,r[0],r.at(-1))):e._save(t)},e._setCanvasSize=(a,n)=>{a??=window.innerWidth,n??=window.innerHeight,r.w=a=Math.ceil(a),r.h=n=Math.ceil(n),r.hw=a/2,r.hh=n/2,r.width=Math.ceil(a*e._pixelDensity),r.height=Math.ceil(n*e._pixelDensity),e._da?e.flexibleCanvas(e._dau):(t.width=a,t.height=n),e.displayMode&&!r.displayMode?e.displayMode():e._adjustDisplay()},e._setImageSize=(a,n)=>{t.width=r.w=a,t.height=r.h=n,r.hw=a/2,r.hh=n/2,r.width=Math.ceil(a*e._pixelDensity),r.height=Math.ceil(n*e._pixelDensity)},"image"!=e._scope){if(r&&"graphics"!=e._scope){function a(){let t=e._parent;t??=document.getElementsByTagName("main")[0],t||(t=document.createElement("main"),document.body.append(t)),r.parent(t)}r.parent=t=>{function a(){e.frameCount>1&&(e._didResize=!0,e._adjustDisplay())}r.parentElement&&r.parentElement.removeChild(r),"string"==typeof t&&(t=document.getElementById(t)),t.append(r),"function"==typeof ResizeObserver?(e._ro&&e._ro.disconnect(),e._ro=new ResizeObserver(a),e._ro.observe(t)):e.frameCount||window.addEventListener("resize",a)},document.body?a():document.addEventListener("DOMContentLoaded",a)}e.resizeCanvas=(t,a)=>{if(!e.ctx)return e.createCanvas(t,a);t==r.w&&a==r.h||e._resizeCanvas(t,a)},e.canvas.resize=e.resizeCanvas,e.canvas.save=e.saveCanvas=e.save,e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(r.w,r.h),t):e._pixelDensity,e.defaultImageScale=t=>t?e._defaultImageScale=t:e._defaultImageScale,e.defaultImageScale(.5),e.flexibleCanvas=(a=400)=>{a?(e._da=r.width/(a*e._pixelDensity),t.width=e._dau=a,t.height=r.h/r.w*a):e._da=0},e._styleNames=["_doStroke","_doFill","_strokeSet","_fillSet","_tint","_imageMode","_rectMode","_ellipseMode","_textSize","_textAlign","_textBaseline"],e._styles=[],e.pushStyles=()=>{let t={};for(let r of e._styleNames)t[r]=e[r];e._styles.push(t)},e.popStyles=()=>{let t=e._styles.pop();for(let r of e._styleNames)e[r]=t[r]},window&&"graphics"!=e._scope&&window.addEventListener("resize",(()=>{e._didResize=!0,t.windowWidth=window.innerWidth,t.windowHeight=window.innerHeight,t.deviceOrientation=window.screen?.orientation?.type}))}},Q5.canvasOptions={alpha:!1,colorSpace:"display-p3"},window.matchMedia&&matchMedia("(dynamic-range: high) and (color-gamut: p3)").matches?Q5.supportsHDR=!0:Q5.canvasOptions.colorSpace="srgb",Q5.renderers.q2d={},Q5.renderers.q2d.canvas=(e,t)=>{let r=e.canvas;e.colorMode&&e.colorMode("rgb","integer"),e._createCanvas=function(a,n,o){return t.ctx=t.drawingContext=r.getContext("2d",o),"image"!=e._scope&&(e.ctx.fillStyle="white",e.ctx.strokeStyle="black",e.ctx.lineCap="round",e.ctx.lineJoin="miter",e.ctx.textAlign="left"),e.ctx.scale(e._pixelDensity,e._pixelDensity),e.ctx.save(),r},e.clear=()=>{e.ctx.save(),e.ctx.resetTransform(),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.restore()},"image"!=e._scope&&(e._resizeCanvas=(t,a)=>{let n,o={};for(let t in e.ctx)"function"!=typeof e.ctx[t]&&(o[t]=e.ctx[t]);if(delete o.canvas,e.frameCount>1){n=new e._OffscreenCanvas(r.width,r.height),n.w=r.w,n.h=r.h,n.getContext("2d").drawImage(r,0,0)}e._setCanvasSize(t,a);for(let t in o)e.ctx[t]=o[t];e.scale(e._pixelDensity),n&&e.ctx.drawImage(n,0,0,n.w,n.h)},e.fill=function(t){if(e._doFill=e._fillSet=!0,Q5.Color&&(t._q5Color||("string"!=typeof t?t=e.color(...arguments):e._namedColors[t]&&(t=e.color(...e._namedColors[t]))),t.a<=0))return e._doFill=!1;e.ctx.fillStyle=e._fill=t.toString()},e.noFill=()=>e._doFill=!1,e.stroke=function(t){if(e._doStroke=e._strokeSet=!0,Q5.Color&&(t._q5Color||("string"!=typeof t?t=e.color(...arguments):e._namedColors[t]&&(t=e.color(...e._namedColors[t]))),t.a<=0))return e._doStroke=!1;e.ctx.strokeStyle=e._stroke=t.toString()},e.strokeWeight=t=>{t||(e._doStroke=!1),e._da&&(t*=e._da),e.ctx.lineWidth=e._strokeWeight=t||1e-4},e.noStroke=()=>e._doStroke=!1,e.opacity=t=>e.ctx.globalAlpha=t,e.translate=(t,r)=>{e._da&&(t*=e._da,r*=e._da),e.ctx.translate(t,r)},e.rotate=t=>{e._angleMode&&(t=e.radians(t)),e.ctx.rotate(t)},e.scale=(t,r)=>{t.x&&(r=t.y,t=t.x),r??=t,e.ctx.scale(t,r)},e.applyMatrix=(t,r,a,n,o,i)=>e.ctx.transform(t,r,a,n,o,i),e.shearX=t=>e.ctx.transform(1,0,e.tan(t),1,0,0),e.shearY=t=>e.ctx.transform(1,e.tan(t),0,1,0,0),e.resetMatrix=()=>{e.ctx&&(e.ctx.resetTransform(),e.scale(e._pixelDensity))},e.pushMatrix=()=>e.ctx.save(),e.popMatrix=()=>e.ctx.restore(),e.push=()=>{e.ctx.save(),e.pushStyles()},e.pop=()=>{e.ctx.restore(),e.popStyles()},e.createCapture=e=>{var t=document.createElement("video");return t.playsinline="playsinline",t.autoplay="autoplay",navigator.mediaDevices.getUserMedia(e).then((e=>{t.srcObject=e})),t.style.position="absolute",t.style.opacity=1e-5,t.style.zIndex=-1e3,document.body.append(t),t})},Q5.renderers.q2d.drawing=e=>{e._doStroke=!0,e._doFill=!0,e._strokeSet=!1,e._fillSet=!1,e._ellipseMode=e.CENTER,e._rectMode=e.CORNER,e._curveDetail=20,e._curveAlpha=0;let t=!0,r=[];function a(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}function n(t,r,n,o,i,s,l,d){if(!e._doFill&&!e._doStroke)return;let c=e._angleMode,h=c?360:e.TAU;if((i%=h)<0&&(i+=h),(s%=h)<0&&(s+=h),0!=i||0!=s){if(i>s&&([i,s]=[s,i]),e.ctx.beginPath(),n==o)c&&(i=e.radians(i),s=e.radians(s)),e.ctx.arc(t,r,n/2,i,s);else{for(let a=0;a<d+1;a++){let l=a/d,c=e.lerp(i,s,l),h=e.cos(c)*n/2,u=e.sin(c)*o/2;e.ctx[a?"lineTo":"moveTo"](t+h,r+u)}l==e.CHORD?e.ctx.closePath():l==e.PIE&&(e.ctx.lineTo(t,r),e.ctx.closePath())}a()}}function o(t,r,n,o){(e._doFill||e._doStroke)&&(e._da&&(t*=e._da,r*=e._da,n*=e._da,o*=e._da),e.ctx.beginPath(),e.ctx.ellipse(t,r,n/2,o/2,0,0,e.TAU),a())}function i(t,r,n,o,s,l,d,c){if(e._doFill||e._doStroke){if(void 0===s)return function(t,r,n,o){e._da&&(t*=e._da,r*=e._da,n*=e._da,o*=e._da),e.ctx.beginPath(),e.ctx.rect(t,r,n,o),a()}(t,r,n,o);if(void 0===l)return i(t,r,n,o,s,s,s,s);e._da&&(t*=e._da,r*=e._da,n*=e._da,o*=e._da,s*=e._da,l*=e._da,c*=e._da,d*=e._da),e.ctx.roundRect(t,r,n,o,[s,l,d,c]),a()}}e.blendMode=t=>e.ctx.globalCompositeOperation=t,e.strokeCap=t=>e.ctx.lineCap=t,e.strokeJoin=t=>e.ctx.lineJoin=t,e.ellipseMode=t=>e._ellipseMode=t,e.rectMode=t=>e._rectMode=t,e.curveDetail=t=>e._curveDetail=t,e.curveAlpha=t=>e._curveAlpha=t,e.curveTightness=t=>e._curveAlpha=t,e.background=function(t){e.ctx.save(),e.ctx.resetTransform(),e.ctx.globalAlpha=1,t.canvas?e.image(t,0,0,e.canvas.width,e.canvas.height):(Q5.Color&&!t._q5Color&&("string"!=typeof t?t=e.color(...arguments):e._namedColors[t]&&(t=e.color(...e._namedColors[t]))),e.ctx.fillStyle=t.toString(),e.ctx.fillRect(0,0,e.canvas.width,e.canvas.height)),e.ctx.restore()},e.line=(t,r,a,n)=>{e._doStroke&&(e._da&&(t*=e._da,r*=e._da,a*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(a,n),e.ctx.stroke())},e.arc=(t,r,a,o,i,s,l,d=25)=>{if(i==s)return e.ellipse(t,r,a,o);l??=e.PIE,e._ellipseMode==e.CENTER?n(t,r,a,o,i,s,l,d):e._ellipseMode==e.RADIUS?n(t,r,2*a,2*o,i,s,l,d):e._ellipseMode==e.CORNER?n(t+a/2,r+o/2,a,o,i,s,l,d):e._ellipseMode==e.CORNERS&&n((t+a)/2,(r+o)/2,a-t,o-r,i,s,l,d)},e.ellipse=(t,r,a,n)=>{n??=a,e._ellipseMode==e.CENTER?o(t,r,a,n):e._ellipseMode==e.RADIUS?o(t,r,2*a,2*n):e._ellipseMode==e.CORNER?o(t+a/2,r+n/2,a,n):e._ellipseMode==e.CORNERS&&o((t+a)/2,(r+n)/2,a-t,n-r)},e.circle=(t,r,n)=>{e._ellipseMode==e.CENTER?(e._da&&(t*=e._da,r*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.arc(t,r,n/2,0,e.TAU),a()):e.ellipse(t,r,n,n)},e.point=(t,r)=>{e._doStroke&&(t.x&&(r=t.y,t=t.x),e._da&&(t*=e._da,r*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(t,r),e.ctx.stroke())},e.rect=(t,r,a,n=a,o,s,l,d)=>{e._rectMode==e.CENTER?i(t-a/2,r-n/2,a,n,o,s,l,d):e._rectMode==e.RADIUS?i(t-a,r-n,2*a,2*n,o,s,l,d):e._rectMode==e.CORNER?i(t,r,a,n,o,s,l,d):e._rectMode==e.CORNERS&&i(t,r,a-t,n-r,o,s,l,d)},e.square=(t,r,a,n,o,i,s)=>e.rect(t,r,a,a,n,o,i,s),e.beginShape=()=>{r=[],e.ctx.beginPath(),t=!0},e.beginContour=()=>{e.ctx.closePath(),r=[],t=!0},e.endContour=()=>{r=[],t=!0},e.vertex=(a,n)=>{e._da&&(a*=e._da,n*=e._da),r=[],t?e.ctx.moveTo(a,n):e.ctx.lineTo(a,n),t=!1},e.bezierVertex=(t,a,n,o,i,s)=>{e._da&&(t*=e._da,a*=e._da,n*=e._da,o*=e._da,i*=e._da,s*=e._da),r=[],e.ctx.bezierCurveTo(t,a,n,o,i,s)},e.quadraticVertex=(t,a,n,o)=>{e._da&&(t*=e._da,a*=e._da,n*=e._da,o*=e._da),r=[],e.ctx.quadraticCurveTo(t,a,n,o)},e.bezier=(t,r,a,n,o,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.bezierVertex(a,n,o,i,s,l),e.endShape()},e.triangle=(t,r,a,n,o,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,n),e.vertex(o,i),e.endShape(e.CLOSE)},e.quad=(t,r,a,n,o,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,n),e.vertex(o,i),e.vertex(s,l),e.endShape(e.CLOSE)},e.endShape=t=>{r=[],t&&e.ctx.closePath(),a()},e.curveVertex=(a,n)=>{if(e._da&&(a*=e._da,n*=e._da),r.push([a,n]),r.length<4)return;let o=function(e,t,r,a,n,o,i,s,l,d){function c(e,t,r,a,n,o){let i=Math.pow(a-t,2)+Math.pow(n-r,2);return Math.pow(i,.5*o)+e}let h=[],u=c(0,e,t,r,a,d),p=c(u,r,a,n,o,d),f=c(p,n,o,i,s,d);for(let d=0;d<l;d++){let c=u+d/(l-1)*(p-u),_=[(u-c)/(u-0),(c-0)/(u-0),(p-c)/(p-u),(c-u)/(p-u),(f-c)/(f-p),(c-p)/(f-p),(p-c)/(p-0),(c-0)/(p-0),(f-c)/(f-u),(c-u)/(f-u)];for(let e=0;e<_.length;e+=2)isNaN(_[e])&&(_[e]=1,_[e+1]=0),isFinite(_[e])||(_[e]>0?(_[e]=1,_[e+1]=0):(_[e]=0,_[e+1]=1));let g=e*_[0]+r*_[1],m=t*_[0]+a*_[1],x=r*_[2]+n*_[3],v=a*_[2]+o*_[3],y=n*_[4]+i*_[5],w=o*_[4]+s*_[5],b=g*_[6]+x*_[7],S=m*_[6]+v*_[7],M=x*_[8]+y*_[9],C=v*_[8]+w*_[9],I=b*_[2]+M*_[3],R=S*_[2]+C*_[3];h.push([I,R])}return h}(...r.at(-4),...r.at(-3),...r.at(-2),...r.at(-1),e._curveDetail,e._curveAlpha);for(let r=0;r<o.length;r++)t?e.ctx.moveTo(...o[r]):e.ctx.lineTo(...o[r]),t=!1},e.curve=(t,r,a,n,o,i,s,l)=>{e.beginShape(),e.curveVertex(t,r),e.curveVertex(a,n),e.curveVertex(o,i),e.curveVertex(s,l),e.endShape()},e.curvePoint=(e,t,r,a,n)=>{const o=n*n*n,i=n*n;return e*(-.5*o+i-.5*n)+t*(1.5*o-2.5*i+1)+r*(-1.5*o+2*i+.5*n)+a*(.5*o-.5*i)},e.bezierPoint=(e,t,r,a,n)=>{const o=1-n;return Math.pow(o,3)*e+3*Math.pow(o,2)*n*t+3*o*Math.pow(n,2)*r+Math.pow(n,3)*a},e.curveTangent=(e,t,r,a,n)=>{const o=n*n;return e*(-3*o/2+2*n-.5)+t*(9*o/2-5*n)+r*(-9*o/2+4*n+.5)+a*(3*o/2-n)},e.bezierTangent=(e,t,r,a,n)=>{const o=1-n;return 3*a*Math.pow(n,2)-3*r*Math.pow(n,2)+6*r*o*n-6*t*o*n+3*t*Math.pow(o,2)-3*e*Math.pow(o,2)},e.erase=function(t=255,r=255){e.ctx.save(),e.ctx.globalCompositeOperation="destination-out",e.ctx.fillStyle=`rgba(0, 0, 0, ${t/255})`,e.ctx.strokeStyle=`rgba(0, 0, 0, ${r/255})`},e.noErase=function(){e.ctx.globalCompositeOperation="source-over",e.ctx.restore()},e.inFill=(t,r)=>{const a=e._pixelDensity;return e.ctx.isPointInPath(t*a,r*a)},e.inStroke=(t,r)=>{const a=e._pixelDensity;return e.ctx.isPointInStroke(t*a,r*a)}},Q5.renderers.q2d.image=(e,t)=>{Q5.Image??=class{constructor(e,t,r){let a=this;a._scope="image",a.canvas=a.ctx=a.drawingContext=null,a.pixels=[],Q5.modules.canvas(a,a);let n=Q5.renderers.q2d;for(let e of["canvas","image","soft_filters"])n[e]&&n[e](a,a);a._pixelDensity=r.pixelDensity||1,a.createCanvas(e,t,r),delete a.createCanvas,a._loop=!1}get w(){return this.width}get h(){return this.height}},e.createImage=(t,r,a)=>{a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace||Q5.canvasOptions.colorSpace;let n=new Q5.Image(t,r,a);return n.defaultWidth=t*e._defaultImageScale,n.defaultHeight=r*e._defaultImageScale,n},e.loadImage=function(r,a,n){if(r.canvas)return r;if("gif"==r.slice(-3).toLowerCase())throw new Error("q5 doesn't support GIFs due to their impact on performance. Use a video or animation instead.");t._preloadCount++;let o=[...arguments].at(-1);n="object"==typeof o?o:null;let i=e.createImage(1,1,n),s=i._pixelDensity=n?.pixelDensity||1;function l(r){i.defaultWidth=r.width*e._defaultImageScale,i.defaultHeight=r.height*e._defaultImageScale,i.naturalWidth=r.naturalWidth,i.naturalHeight=r.naturalHeight,i._setImageSize(Math.ceil(i.naturalWidth/s),Math.ceil(i.naturalHeight/s)),i.ctx.drawImage(r,0,0),t._preloadCount--,a&&a(i)}if(Q5._nodejs&&global.CairoCanvas)global.CairoCanvas.loadImage(r).then(l).catch((e=>{throw t._preloadCount--,e}));else{let e=new window.Image;e.src=r,e.crossOrigin="Anonymous",e._pixelDensity=s,e.onload=()=>l(e),e.onerror=e=>{throw t._preloadCount--,e}}return i},e.imageMode=t=>e._imageMode=t,e.image=(t,r,a,n,o,i=0,s=0,l,d)=>{if(!t)return;let c=t?.canvas||t;Q5._createNodeJSCanvas&&(c=c.context.canvas),n??=t.defaultWidth||c.width||t.videoWidth,o??=t.defaultHeight||c.height||t.videoHeight,"center"==e._imageMode&&(r-=.5*n,a-=.5*o),e._da&&(r*=e._da,a*=e._da,n*=e._da,o*=e._da,i*=e._da,s*=e._da,l*=e._da,d*=e._da);let h=t._pixelDensity||1;l?l*=h:l=c.width||c.videoWidth,d?d*=h:d=c.height||c.videoHeight,e.ctx.drawImage(c,i*h,s*h,l,d,r,a,n,o),e._tint&&(e.ctx.globalCompositeOperation="multiply",e.ctx.fillStyle=e._tint.toString(),e.ctx.fillRect(r,a,n,o),e.ctx.globalCompositeOperation="source-over")},e._tint=null;let r=null;e._softFilter=()=>{throw new Error("Load q5-2d-soft-filters.js to use software filters.")},e.filter=(t,r)=>{if(!e.ctx.filter)return e._softFilter(t,r);if("string"==typeof t)f=t;else if(t==Q5.GRAY)f="saturate(0%)";else if(t==Q5.INVERT)f="invert(100%)";else if(t==Q5.BLUR){let t=Math.ceil(r*e._pixelDensity)||1;f=`blur(${t}px)`}else{if(t!=Q5.THRESHOLD)return e._softFilter(t,r);{r??=.5;let e=Math.floor(.5/Math.max(r,1e-5)*100);f=`saturate(0%) brightness(${e}%) contrast(1000000%)`}}e.ctx.filter=f,e.ctx.drawImage(e.canvas,0,0,e.canvas.w,e.canvas.h),e.ctx.filter="none"},"image"==e._scope&&(e.resize=(t,r)=>{let a=e.canvas,n=new e._OffscreenCanvas(a.width,a.height);n.getContext("2d",{colorSpace:a.colorSpace}).drawImage(a,0,0),e._setImageSize(t,r),e.ctx.clearRect(0,0,a.width,a.height),e.ctx.drawImage(n,0,0,a.width,a.height)}),e._getImageData=(t,r,a,n)=>e.ctx.getImageData(t,r,a,n,{colorSpace:e.canvas.colorSpace}),e.trim=()=>{let t=e._pixelDensity||1,r=e.canvas.width,a=e.canvas.height,n=e._getImageData(0,0,r,a).data,o=r,i=0,s=a,l=0,d=3;for(let e=0;e<a;e++)for(let t=0;t<r;t++)0!==n[d]&&(t<o&&(o=t),t>i&&(i=t),e<s&&(s=e),e>l&&(l=e)),d+=4;return s=Math.floor(s/t),l=Math.floor(l/t),o=Math.floor(o/t),i=Math.floor(i/t),e.get(o,s,i-o+1,l-s+1)},e.mask=t=>{e.ctx.save(),e.ctx.resetTransform();let r=e.ctx.globalCompositeOperation;e.ctx.globalCompositeOperation="destination-in",e.ctx.drawImage(t.canvas,0,0),e.ctx.globalCompositeOperation=r,e.ctx.restore()},e.inset=(t,r,a,n,o,i,s,l)=>{let d=e._pixelDensity||1;e.ctx.drawImage(e.canvas,t*d,r*d,a*d,n*d,o,i,s,l)},e.copy=()=>e.get(),e.get=(t,r,a,n)=>{let o=e._pixelDensity||1;if(void 0!==t&&void 0===a){let a=e._getImageData(t*o,r*o,1,1).data;return[a[0],a[1],a[2],a[3]/255]}t=(t||0)*o,r=(r||0)*o;let i=a=a||e.width,s=n=n||e.height;a*=o,n*=o;let l=e.createImage(a,n);return l.ctx.drawImage(e.canvas,t,r,a,n,0,0,a,n),l._pixelDensity=o,l.width=i,l.height=s,l},e.set=(t,r,a)=>{if(a.canvas){let n=e._tint;return e._tint=null,e.image(a,t,r),void(e._tint=n)}e.pixels.length||e.loadPixels();let n=e._pixelDensity||1;for(let o=0;o<n;o++)for(let i=0;i<n;i++){let s=4*((r*n+o)*e.canvas.width+t*n+i);e.pixels[s]=a.r,e.pixels[s+1]=a.g,e.pixels[s+2]=a.b,e.pixels[s+3]=a.a}},e.loadPixels=()=>{r=e._getImageData(0,0,e.canvas.width,e.canvas.height),t.pixels=r.data},e.updatePixels=()=>{null!=r&&e.ctx.putImageData(r,0,0)},e.smooth=()=>e.ctx.imageSmoothingEnabled=!0,e.noSmooth=()=>e.ctx.imageSmoothingEnabled=!1,"image"!=e._scope&&(e.tint=function(t){e._tint=t._q5Color?t:e.color(...arguments)},e.noTint=()=>e._tint=null)},Q5.THRESHOLD=1,Q5.GRAY=2,Q5.OPAQUE=3,Q5.INVERT=4,Q5.POSTERIZE=5,Q5.DILATE=6,Q5.ERODE=7,Q5.BLUR=8,Q5.renderers.q2d.text=(e,t)=>{e._textAlign="left",e._textBaseline="alphabetic",e._textSize=12;let r="sans-serif",a=!1,n=15,o=3,i="normal",s=!1,l=0,d=[],c=!1,h=!1,u=0,p=12e3,f=e._textCache={};e.loadFont=(e,r)=>{t._preloadCount++;let a=e.split("/").pop().split(".")[0].replace(" ",""),n=new FontFace(a,`url(${e})`);return document.fonts.add(n),n.load().then((()=>{t._preloadCount--,r&&r(a)})),a},e.textFont=e=>{if(!e||e==r)return r;r=e,s=!0,l=-1},e.textSize=t=>{if(null==t||t==e._textSize)return e._textSize;e._da&&(t*=e._da),e._textSize=t,s=!0,l=-1,a||(n=1.25*t,o=n-t)},e.textStyle=e=>{if(!e||e==i)return i;i=e,s=!0,l=-1},e.textLeading=t=>{if(a=!0,null==t||t==n)return n;e._da&&(t*=e._da),n=t,o=t-e._textSize,l=-1},e.textAlign=(t,r)=>{e.ctx.textAlign=e._textAlign=t,r&&(e.ctx.textBaseline=e._textBaseline=r==e.CENTER?"middle":r)},e.textWidth=t=>e.ctx.measureText(t).width,e.textAscent=t=>e.ctx.measureText(t).actualBoundingBoxAscent,e.textDescent=t=>e.ctx.measureText(t).actualBoundingBoxDescent,e.textFill=e.fill,e.textStroke=e.stroke;e.textCache=(e,t)=>(t&&(p=t),void 0!==e&&(c=e),c),e.createTextImage=(t,r,a)=>(h=!0,img=e.text(t,0,0,r,a),h=!1,img);let _=[];e.text=(t,a,g,m,x)=>{if(void 0===t||!e._doFill&&!e._doStroke)return;t=t.toString(),e._da&&(a*=e._da,g*=e._da);let v,y,w,b,S=e.ctx;if(s&&(S.font=`${i} ${e._textSize}px ${r}`,s=!1),(c||h)&&(-1==l&&(()=>{let t=r+e._textSize+i+n,a=5381;for(let e=0;e<t.length;e++)a=33*a^t.charCodeAt(e);l=a>>>0})(),v=f[t],v&&(v=v[l]),v)){if(v._fill==e._fill&&v._stroke==e._stroke&&v._strokeWeight==e._strokeWeight)return h?v:e.textImage(v,a,g);v.clear()}if(-1==t.indexOf("\n")?_[0]=t:_=t.split("\n"),t.length>m){let e=[];for(let t of _){let r=0;for(;r<t.length;){let a=r+m;if(a>=t.length){e.push(t.slice(r));break}let n=t.lastIndexOf(" ",a);(-1===n||n<r)&&(n=a),e.push(t.slice(r,n)),r=n+1}}_=e}if(c||h){if(y=0,w=n*_.length,!v){let r=S.measureText(" "),a=r.fontBoundingBoxAscent,i=r.fontBoundingBoxDescent;x??=w+i,v=e.createImage.call(e,Math.ceil(S.measureText(t).width),Math.ceil(x),{pixelDensity:e._pixelDensity}),v._ascent=a,v._descent=i,v._top=i+o,v._middle=v._top+.5*a,v._bottom=v._top+a,v._leading=n}v._fill=e._fill,v._stroke=e._stroke,v._strokeWeight=e._strokeWeight,v.modified=!0,S=v.ctx,S.font=e.ctx.font,S.fillStyle=e._fill,S.strokeStyle=e._stroke,S.lineWidth=e.ctx.lineWidth}else y=a,w=g;e._fillSet||(b=S.fillStyle,S.fillStyle="black");for(let t of _)if(e._doStroke&&e._strokeSet&&S.strokeText(t,y,w),e._doFill&&S.fillText(t,y,w),w+=n,w>x)break;if(_.length=0,e._fillSet||(S.fillStyle=b),c||h){if(d.push(l),(f[t]??={})[l]=v,u++,u>p){let e=Math.ceil(u/2),t=d.splice(0,e);for(let e in f){e=f[e];for(let r of t)delete e[r]}u-=e}if(h)return v;e.textImage(v,a,g)}},e.textImage=(t,r,a)=>{"string"==typeof t&&(t=e.createTextImage(t));let n=e._imageMode;e._imageMode="corner";let o=e._textAlign;"center"==o?r-=t.canvas.hw:"right"==o&&(r-=t.width);let i=e._textBaseline;"alphabetic"==i?a-=t._leading:"middle"==i?a-=t._middle:"bottom"==i?a-=t._bottom:"top"==i&&(a-=t._top),e.image(t,r,a),e._imageMode=n},e.nf=(e,t,r)=>{let a=e<0,n=(e=Math.abs(e)).toFixed(r).split(".");n[0]=n[0].padStart(t,"0");let o=n.join(".");return a&&(o="-"+o),o}},Q5.modules.ai=e=>{e.askAI=(e="")=>{throw Q5.disableFriendlyErrors=!1,Error("Ask AI ✨ "+e)},e._askAI=async e=>{let t=e.message?.includes("Ask AI ✨"),r=e.stack?.split("\n");if(!e.stack||r.length<=1)return;let a=1,n="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(a=0,n="@");r[a].indexOf("q5")>=0;)a++;let o=r[a].split(n).at(-1);o.startsWith("blob:")&&(o=o.slice(5));let i=o.split(":"),s=parseInt(i.at(-2));t&&s++,i[3]=i[3].split(")")[0];let l=i.slice(0,2).join(":"),d=l.split("/").at(-1);try{let r=(await(await fetch(l)).text()).split("\n"),a=r[s-1].trim(),n="",o=1;for(;n.length<1600&&(s-o>=0&&(n=r[s-o].trim()+"\n"+n),s+o<r.length);)n+=r[s+o].trim()+"\n",o++;let i="https://chatgpt.com/?q=q5.js+"+(t&&e.message.length>10?e.message.slice(10):"Whats+wrong+with+this+line%3F+short+answer")+(t?"":"%0A%0A"+encodeURIComponent(e.name+": "+e.message))+"%0A%0ALine%3A+"+encodeURIComponent(a)+"%0A%0AExcerpt+for+context%3A%0A%0A"+encodeURIComponent(n);if(console.warn("Error in "+d+" on line "+s+":\n\n"+a),console.warn("Ask AI ✨ "+i),t)return window.open(i,"_blank")}catch(e){}}},Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e._colorMode="rgb",e.OKLCH="oklch",e.colorMode=(r,a)=>{e._colorMode=r;let n="srgb"==e.canvas.colorSpace||"srgb"==r;if(a??=n?"integer":"float",e._colorFormat="float"==a||1==a?1:255,"oklch"==r)t.Color=Q5.ColorOKLCH;else{let r="srgb"==e.canvas.colorSpace;255==e._colorFormat?t.Color=r?Q5.ColorRGBA_8:Q5.ColorRGBA_P3_8:t.Color=r?Q5.ColorRGBA:Q5.ColorRGBA_P3,e._colorMode="rgb"}},e._namedColors={aqua:[0,255,255],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],crimson:[220,20,60],cyan:[0,255,255],darkviolet:[148,0,211],gold:[255,215,0],green:[0,128,0],gray:[128,128,128],grey:[128,128,128],hotpink:[255,105,180],indigo:[75,0,130],khaki:[240,230,140],lightgreen:[144,238,144],lime:[0,255,0],magenta:[255,0,255],navy:[0,0,128],orange:[255,165,0],olive:[128,128,0],peachpuff:[255,218,185],pink:[255,192,203],purple:[128,0,128],red:[255,0,0],skyblue:[135,206,235],tan:[210,180,140],turquoise:[64,224,208],transparent:[0,0,0,0],white:[255,255,255],violet:[238,130,238],yellow:[255,255,0]},e.color=(t,r,a,n)=>{let o=e.Color;if(t._q5Color)return new o(...t.levels);if(null==r){if("string"==typeof t){if("#"==t[0])t.length<=5?(t.length>4&&(n=parseInt(t[4]+t[4],16)),a=parseInt(t[3]+t[3],16),r=parseInt(t[2]+t[2],16),t=parseInt(t[1]+t[1],16)):(t.length>7&&(n=parseInt(t.slice(7,9),16)),a=parseInt(t.slice(5,7),16),r=parseInt(t.slice(3,5),16),t=parseInt(t.slice(1,3),16));else{if(!e._namedColors[t])return console.error("q5 can't parse color: "+t+"\nOnly numeric input, hex, and common named colors are supported."),new o(0,0,0);[t,r,a,n]=e._namedColors[t]}1==e._colorFormat&&(t/=255,r&&(r/=255),a&&(a/=255),n&&(n/=255))}Array.isArray(t)&&([t,r,a,n]=t)}return null==a?new o(t,t,t,r):new o(t,r,a,n)},e.red=e=>e.r,e.green=e=>e.g,e.blue=e=>e.b,e.alpha=e=>e.a,e.lightness=e=>e.l?e.l:100*(.2126*e.r+.7152*e.g+.0722*e.b)/255,e.hue=t=>{if(t.h)return t.h;let r=t.r,a=t.g,n=t.b;255==e._colorFormat&&(r/=255,a/=255,n/=255);let o,i=Math.max(r,a,n),s=Math.min(r,a,n);return o=i==s?0:i==r?60*(a-n)/(i-s):i==a?60*(n-r)/(i-s)+120:60*(r-a)/(i-s)+240,o<0&&(o+=360),o},e.lerpColor=(t,r,a)=>{if(a=Math.max(0,Math.min(1,a)),"rgb"==e._colorMode)return new e.Color(e.lerp(t.r,r.r,a),e.lerp(t.g,r.g,a),e.lerp(t.b,r.b,a),e.lerp(t.a,r.a,a));{let n=r.h-t.h;n>180&&(n-=360),n<-180&&(n+=360);let o=t.h+a*n;return o<0&&(o+=360),o>360&&(o-=360),new e.Color(e.lerp(t.l,r.l,a),e.lerp(t.c,r.c,a),o,e.lerp(t.a,r.a,a))}}},Q5.Color=class{constructor(){this._q5Color=!0}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,r,a){super(),this.l=e,this.c=t,this.h=r,this.a=a??1}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}},Q5.ColorRGBA=class extends Q5.Color{constructor(e,t,r,a){super(),this.r=e,this.g=t,this.b=r,this.a=a??1}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_P3=class extends Q5.ColorRGBA{toString(){return`color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_8=class extends Q5.ColorRGBA{constructor(e,t,r,a){super(e,t,r,a??255)}setRed(e){this.r=e}setGreen(e){this.g=e}setBlue(e){this.b=e}setAlpha(e){this.a=e}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`rgb(${this.r} ${this.g} ${this.b} / ${this.a/255})`}},Q5.ColorRGBA_P3_8=class extends Q5.ColorRGBA{constructor(e,t,r,a){super(e,t,r,a??255),this._edited=!0}get r(){return this._r}set r(e){this._r=e,this._edited=!0}get g(){return this._g}set g(e){this._g=e,this._edited=!0}get b(){return this._b}set b(e){this._b=e,this._edited=!0}get a(){return this._a}set a(e){this._a=e,this._edited=!0}toString(){if(this._edited){let e=(this._r/255).toFixed(3),t=(this._g/255).toFixed(3),r=(this._b/255).toFixed(3),a=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${r} / ${a})`,this._edited=!1}return this._css}},Q5.modules.display=e=>{if(!e.canvas||"graphics"==e._scope)return;let t=e.canvas;e.CENTERED="centered",e.FULLSCREEN="fullscreen",e.MAXED="maxed",e.PIXELATED="pixelated",0!=Q5._instanceCount||Q5._nodejs||document.head.insertAdjacentHTML("beforeend","<style>\nhtml, body {\n\tmargin: 0;\n\tpadding: 0;\n}\n.q5Canvas {\n\toutline: none;\n\t-webkit-touch-callout: none;\n\t-webkit-text-size-adjust: none;\n\t-webkit-user-select: none;\n\toverscroll-behavior: none;\n}\n.q5-pixelated {\n\timage-rendering: pixelated;\n\tfont-smooth: never;\n\t-webkit-font-smoothing: none;\n}\n.q5-centered,\n.q5-maxed,\n.q5-fullscreen {\n display: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\nmain.q5-centered,\nmain.q5-maxed,\n.q5-fullscreen {\n\theight: 100vh;\n}\nmain {\n\toverscroll-behavior: none;\n}\n</style>"),e._adjustDisplay=()=>{let r=t.style,a=t.parentElement;r&&a&&t.displayMode&&("pixelated"==t.renderQuality&&(t.classList.add("q5-pixelated"),e.pixelDensity(1),e.defaultImageScale(1),e.noSmooth&&e.noSmooth(),e.textFont&&e.textFont("monospace")),"default"==t.displayMode||"normal"==t.displayMode?(a.classList.remove("q5-centered","q5-maxed","q5-fullscreen"),r.width=t.w*t.displayScale+"px",r.height=t.h*t.displayScale+"px"):(a.classList.add("q5-"+t.displayMode),a=a.getBoundingClientRect(),t.w/t.h>a.width/a.height?("centered"==t.displayMode?(r.width=t.w*t.displayScale+"px",r.maxWidth="100%"):r.width="100%",r.height="auto",r.maxHeight=""):(r.width="auto",r.maxWidth="","centered"==t.displayMode?(r.height=t.h*t.displayScale+"px",r.maxHeight="100%"):r.height="100%")))},e.displayMode=(r="normal",a="smooth",n=1)=>{"string"==typeof n&&(n=parseFloat(n.slice(1))),Object.assign(t,{displayMode:r,renderQuality:a,displayScale:n}),e._adjustDisplay()},e.fullscreen=e=>{if(void 0===e)return document.fullscreenElement;e?document.body.requestFullscreen():document.body.exitFullscreen()}},Q5.modules.input=(e,t)=>{if("graphics"==e._scope)return;e.mouseX=0,e.mouseY=0,e.pmouseX=0,e.pmouseY=0,e.touches=[],e.mouseButton="",e.keyIsPressed=!1,e.mouseIsPressed=!1,e.key="",e.keyCode=0,e.UP_ARROW=38,e.DOWN_ARROW=40,e.LEFT_ARROW=37,e.RIGHT_ARROW=39,e.SHIFT=16,e.TAB=9,e.BACKSPACE=8,e.ENTER=e.RETURN=13,e.ALT=e.OPTION=18,e.CONTROL=17,e.DELETE=46,e.ESCAPE=27,e.ARROW="default",e.CROSS="crosshair",e.HAND="pointer",e.MOVE="move",e.TEXT="text";let r={},a=[e.LEFT,e.CENTER,e.RIGHT],n=e.canvas;function o(t){const r=e.canvas.getBoundingClientRect(),a=e.canvas.scrollWidth/e.width||1,n=e.canvas.scrollHeight/e.height||1;return{x:(t.clientX-r.left)/a,y:(t.clientY-r.top)/n,id:t.identifier}}if(e._startAudio=()=>{e.getAudioContext&&"suspended"==e.getAudioContext()?.state&&e.userStartAudio()},e._updateMouse=r=>{if(!r.changedTouches){if(n){let a=n.getBoundingClientRect(),o=n.scrollWidth/e.width||1,i=n.scrollHeight/e.height||1;t.mouseX=(r.clientX-a.left)/o,t.mouseY=(r.clientY-a.top)/i,"webgpu"==n.renderer&&(t.mouseX-=n.hw,t.mouseY-=n.hh)}else t.mouseX=r.clientX,t.mouseY=r.clientY;t.moveX=r.movementX,t.moveY=r.movementY}},e._onmousedown=r=>{e._startAudio(),e._updateMouse(r),t.mouseIsPressed=!0,t.mouseButton=a[r.button],e.mousePressed(r)},e._onmousemove=t=>{e._updateMouse(t),e.mouseIsPressed?e.mouseDragged(t):e.mouseMoved(t)},e._onmouseup=r=>{e._updateMouse(r),t.mouseIsPressed=!1,e.mouseReleased(r)},e._onclick=r=>{e._updateMouse(r),t.mouseIsPressed=!0,e.mouseClicked(r),t.mouseIsPressed=!1},e._onwheel=t=>{e._updateMouse(t),t.delta=t.deltaY,0==e.mouseWheel(t)&&t.preventDefault()},e.cursor=(t,r,a)=>{let n="";t.includes(".")&&(t=`url("${t}")`,n=", auto"),void 0!==r&&(t+=" "+r+" "+a),e.canvas.style.cursor=t+n},e.noCursor=()=>{e.canvas.style.cursor="none"},window&&(e.requestPointerLock=document.body?.requestPointerLock,e.exitPointerLock=document.exitPointerLock),e._onkeydown=a=>{a.repeat||(e._startAudio(),t.keyIsPressed=!0,t.key=a.key,t.keyCode=a.keyCode,r[e.keyCode]=r[e.key.toLowerCase()]=!0,e.keyPressed(a),1==a.key.length&&e.keyTyped(a))},e._onkeyup=a=>{t.keyIsPressed=!1,t.key=a.key,t.keyCode=a.keyCode,r[e.keyCode]=r[e.key.toLowerCase()]=!1,e.keyReleased(a)},e.keyIsDown=e=>!!r["string"==typeof e?e.toLowerCase():e],e._ontouchstart=r=>{e._startAudio(),t.touches=[...r.touches].map(o),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,t.mouseIsPressed=!0,t.mouseButton=e.LEFT,e.mousePressed(r)||r.preventDefault()),e.touchStarted(r)||r.preventDefault()},e._ontouchmove=r=>{t.touches=[...r.touches].map(o),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,e.mouseDragged(r)||r.preventDefault()),e.touchMoved(r)||r.preventDefault()},e._ontouchend=r=>{t.touches=[...r.touches].map(o),e._isTouchAware||e.touches.length||(t.mouseIsPressed=!1,e.mouseReleased(r)||r.preventDefault()),e.touchEnded(r)||r.preventDefault()},n&&(n.addEventListener("mousedown",(t=>e._onmousedown(t))),n.addEventListener("mouseup",(t=>e._onmouseup(t))),n.addEventListener("wheel",(t=>e._onwheel(t))),n.addEventListener("click",(t=>e._onclick(t))),n.addEventListener("touchstart",(t=>e._ontouchstart(t))),n.addEventListener("touchmove",(t=>e._ontouchmove(t))),n.addEventListener("touchcancel",(t=>e._ontouchend(t))),n.addEventListener("touchend",(t=>e._ontouchend(t)))),window){let t=window.addEventListener;t("mousemove",(t=>e._onmousemove(t)),!1),t("keydown",(t=>e._onkeydown(t)),!1),t("keyup",(t=>e._onkeyup(t)),!1)}},Q5.modules.math=(e,t)=>{e.RADIANS=0,e.DEGREES=1,e.PI=Math.PI,e.HALF_PI=Math.PI/2,e.QUARTER_PI=Math.PI/4,e.abs=Math.abs,e.ceil=Math.ceil,e.exp=Math.exp,e.floor=e.int=Math.floor,e.loge=Math.log,e.mag=Math.hypot,e.max=Math.max,e.min=Math.min,e.round=Math.round,e.pow=Math.pow,e.sqrt=Math.sqrt,e.SHR3=1,e.LCG=2;let r=0;e.angleMode=t=>{"radians"==t&&(t=0),r=e._angleMode=t};let a=e._DEGTORAD=Math.PI/180,n=e._RADTODEG=180/Math.PI;function o(){let e,t,r=4294967295;return{setSeed(a){e=t=(a??Math.random()*r)>>>0},getSeed:()=>t,rand:()=>(e^=e<<17,e^=e>>13,e^=e<<5,(e>>>0)/r)}}e.degrees=t=>t*e._RADTODEG,e.radians=t=>t*e._DEGTORAD,e.map=Q5.prototype.map=(e,t,r,a,n,o)=>{let i=a+1*(e-t)/(r-t)*(n-a);return o?a<n?Math.min(Math.max(i,a),n):Math.min(Math.max(i,n),a):i},e.lerp=(e,t,r)=>e*(1-r)+t*r,e.constrain=(e,t,r)=>Math.min(Math.max(e,t),r),e.dist=function(){let e=arguments;return 4==e.length?Math.hypot(e[0]-e[2],e[1]-e[3]):Math.hypot(e[0]-e[3],e[1]-e[4],e[2]-e[5])},e.norm=(t,r,a)=>e.map(t,r,a,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e),e.sin=e=>Math.sin(r?e*a:e),e.cos=e=>Math.cos(r?e*a:e),e.tan=e=>Math.tan(r?e*a:e),e.asin=e=>{let t=Math.asin(e);return r?t*n:t},e.acos=e=>{let t=Math.acos(e);return r?t*n:t},e.atan=e=>{let t=Math.atan(e);return r?t*n:t},e.atan2=(e,t)=>{let a=Math.atan2(e,t);return r?a*n:a};let i=o();i.setSeed(),e.randomSeed=e=>i.setSeed(e),e.random=(e,t)=>void 0===e?i.rand():"number"==typeof e?void 0!==t?i.rand()*(t-e)+e:i.rand()*e:e[Math.trunc(e.length*i.rand())],e.randomGenerator=t=>{t==e.LCG?i=function(){const e=4294967296;let t,r;return{setSeed(a){r=t=(a??Math.random()*e)>>>0},getSeed:()=>t,rand:()=>(r=(1664525*r+1013904223)%e,r/e)}}():t==e.SHR3&&(i=o()),i.setSeed()};var s=new function(){var e,t,r,a=new Array(128),n=new Array(256),o=new Array(128),s=new Array(128),l=new Array(256),d=new Array(256),c=()=>4294967296*i.rand()-2147483648,h=()=>.5+2.328306e-10*(c()|0),u=()=>{for(var t,n,i,l,d=3.44262;;){if(t=r*o[e],0==e){do{i=h(),l=h(),t=.2904764*-Math.log(i),n=-Math.log(l)}while(n+n<t*t);return r>0?d+t:-d-t}if(s[e]+h()*(s[e-1]-s[e])<Math.exp(-.5*t*t))return t;if(r=c(),e=127&r,Math.abs(r)<a[e])return r*o[e]}},p=()=>{for(var r;;){if(0==e)return 7.69711-Math.log(h());if(r=t*l[e],d[e]+h()*(d[e-1]-d[e])<Math.exp(-r))return r;if((t=c())<n[e=255&t])return t*l[e]}};this.SHR3=c,this.UNI=h,this.RNOR=()=>(r=c(),e=127&r,Math.abs(r)<a[e]?r*o[e]:u()),this.REXP=()=>(t=c()>>>0)<a[e=255&t]?t*l[e]:p(),this.zigset=()=>{var e,t,r=2147483648,i=4294967296,c=3.442619855899,h=c,u=.00991256303526217,p=7.697117470131487,f=p,_=.003949659822581572;for(e=u/Math.exp(-.5*c*c),a[0]=Math.floor(c/e*r),a[1]=0,o[0]=e/r,o[127]=c/r,s[0]=1,s[127]=Math.exp(-.5*c*c),t=126;t>=1;t--)c=Math.sqrt(-2*Math.log(u/c+Math.exp(-.5*c*c))),a[t+1]=Math.floor(c/h*r),h=c,s[t]=Math.exp(-.5*c*c),o[t]=c/r;for(e=_/Math.exp(-p),n[0]=Math.floor(p/e*i),n[1]=0,l[0]=e/i,l[255]=p/i,d[0]=1,d[255]=Math.exp(-p),t=254;t>=1;t--)p=-Math.log(_/p+Math.exp(-p)),n[t+1]=Math.floor(p/f*i),f=p,d[t]=Math.exp(-p),l[t]=p/i}};let l;s.hasInit=!1,e.randomGaussian=(e,t)=>(s.hasInit||(s.zigset(),s.hasInit=!0),s.RNOR()*t+e),e.randomExponential=()=>(s.hasInit||(s.zigset(),s.hasInit=!0),s.REXP()),e.PERLIN="perlin",e.SIMPLEX="simplex",e.BLOCKY="blocky",e.Noise=Q5.PerlinNoise,e.noiseMode=e=>{t.Noise=Q5[e[0].toUpperCase()+e.slice(1)+"Noise"],l=null},e.noiseSeed=t=>{l=new e.Noise(t)},e.noise=(t=0,r=0,a=0)=>(l??=new e.Noise,l.noise(t,r,a)),e.noiseDetail=(t,r)=>{l??=new e.Noise,t>0&&(l.octaves=t),r>0&&(l.falloff=r)}},Q5.Noise=class{},Q5.PerlinNoise=class extends Q5.Noise{constructor(e){super(),this.grad3=[[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]],this.octaves=1,this.falloff=.5,this.p=null==e?Array.from({length:256},(()=>Math.floor(256*Math.random()))):this.seedPermutation(e),this.p=this.p.concat(this.p)}seedPermutation(e){let t,r,a=[];for(let e=0;e<256;e++)a[e]=e;for(let n=255;n>0;n--)t=(e=16807*e%2147483647)%(n+1),r=a[n],a[n]=a[t],a[t]=r;return a}dot(e,t,r,a){return e[0]*t+e[1]*r+e[2]*a}mix(e,t,r){return(1-r)*e+r*t}fade(e){return e*e*e*(e*(6*e-15)+10)}noise(e,t,r){let a=this,n=0,o=1,i=1,s=0;for(let l=0;l<a.octaves;l++){const l=255&Math.floor(e*o),d=255&Math.floor(t*o),c=255&Math.floor(r*o),h=e*o-Math.floor(e*o),u=t*o-Math.floor(t*o),p=r*o-Math.floor(r*o),f=a.fade(h),_=a.fade(u),g=a.fade(p),m=a.p[l]+d,x=a.p[m]+c,v=a.p[m+1]+c,y=a.p[l+1]+d,w=a.p[y]+c,b=a.p[y+1]+c,S=a.mix(a.dot(a.grad3[a.p[x]%12],h,u,p),a.dot(a.grad3[a.p[w]%12],h-1,u,p),f),M=a.mix(a.dot(a.grad3[a.p[v]%12],h,u-1,p),a.dot(a.grad3[a.p[b]%12],h-1,u-1,p),f),C=a.mix(a.dot(a.grad3[a.p[x+1]%12],h,u,p-1),a.dot(a.grad3[a.p[w+1]%12],h-1,u,p-1),f),I=a.mix(a.dot(a.grad3[a.p[v+1]%12],h,u-1,p-1),a.dot(a.grad3[a.p[b+1]%12],h-1,u-1,p-1),f),R=a.mix(S,M,_),Q=a.mix(C,I,_);n+=a.mix(R,Q,g)*i,s+=i,i*=a.falloff,o*=2}return(n/s+1)/2}},Q5.modules.sound=(e,t)=>{e.Sound=Q5.Sound,e.loadSound=(e,r)=>{t._preloadCount++,Q5.aud??=new window.AudioContext;let a=new Q5.Sound(e,r);return a.crossOrigin="Anonymous",a.addEventListener("canplaythrough",(()=>{t._preloadCount--,a.loaded=!0,r&&r(a)})),a},e.getAudioContext=()=>Q5.aud,e.userStartAudio=()=>Q5.aud.resume()},window.Audio&&(Q5.Sound=class extends Audio{constructor(e){super(e);let t=this;t.load(),t.panner=Q5.aud.createStereoPanner(),t.source=Q5.aud.createMediaElementSource(t),t.source.connect(t.panner),t.panner.connect(Q5.aud.destination),Object.defineProperty(t,"pan",{get:()=>t.panner.pan.value,set:e=>t.panner.pan.value=e})}setVolume(e){this.volume=e}setLoop(e){this.loop=e}setPan(e){this.pan=e}isLoaded(){return this.loaded}isPlaying(){return!this.paused}}),Q5.modules.util=(e,t)=>{e._loadFile=(r,a,n)=>{t._preloadCount++;let o={};return fetch(r).then((e=>"json"==n?e.json():e.text())).then((r=>{t._preloadCount--,"csv"==n&&(r=e.CSV.parse(r)),Object.assign(o,r),a&&a(r)})),o},e.loadText=(t,r)=>e._loadFile(t,r,"text"),e.loadJSON=(t,r)=>e._loadFile(t,r,"json"),e.loadCSV=(t,r)=>e._loadFile(t,r,"csv"),e.CSV={},e.CSV.parse=(e,t=",",r="\n")=>{let a=[],n=e.split(r),o=n[0].split(t);for(let e=1;e<n.length;e++){let r={},i=n[e].split(t);o.forEach(((e,t)=>r[e]=JSON.parse(i[t]))),a.push(r)}return a},"object"==typeof localStorage&&(e.storeItem=localStorage.setItem,e.getItem=localStorage.getItem,e.removeItem=localStorage.removeItem,e.clearStorage=localStorage.clear),e.year=()=>(new Date).getFullYear(),e.day=()=>(new Date).getDay(),e.hour=()=>(new Date).getHours(),e.minute=()=>(new Date).getMinutes(),e.second=()=>(new Date).getSeconds()},Q5.modules.vector=e=>{e.createVector=(t,r,a)=>new Q5.Vector(t,r,a,e)},Q5.Vector=class{constructor(e,t,r,a){this.x=e||0,this.y=t||0,this.z=r||0,this._$=a||window,this._cn=null,this._cnsq=null}set(e,t,r){return this.x=e?.x||e||0,this.y=e?.y||t||0,this.z=e?.z||r||0,this}copy(){return new Q5.Vector(this.x,this.y,this.z)}_arg2v(e,t,r){return void 0!==e?.x?e:void 0!==t?{x:e,y:t,z:r||0}:{x:e,y:e,z:e}}_calcNorm(){this._cnsq=this.x*this.x+this.y*this.y+this.z*this.z,this._cn=Math.sqrt(this._cnsq)}add(){let e=this._arg2v(...arguments);return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}rem(){let e=this._arg2v(...arguments);return this.x%=e.x,this.y%=e.y,this.z%=e.z,this}sub(){let e=this._arg2v(...arguments);return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}mult(){let e=this._arg2v(...arguments);return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}div(){let e=this._arg2v(...arguments);return e.x?this.x/=e.x:this.x=0,e.y?this.y/=e.y:this.y=0,e.z?this.z/=e.z:this.z=0,this}mag(){return this._calcNorm(),this._cn}magSq(){return this._calcNorm(),this._cnsq}dot(){let e=this._arg2v(...arguments);return this.x*e.x+this.y*e.y+this.z*e.z}dist(){let e=this._arg2v(...arguments),t=this.x-e.x,r=this.y-e.y,a=this.z-e.z;return Math.sqrt(t*t+r*r+a*a)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,r=this.z*e.x-this.x*e.z,a=this.x*e.y-this.y*e.x;return this.x=t,this.y=r,this.z=a,this}normalize(){this._calcNorm();let e=this._cn;return 0!=e&&(this.x/=e,this.y/=e,this.z/=e),this._cn=1,this._cnsq=1,this}limit(e){this._calcNorm();let t=this._cn;if(t>e){let r=e/t;this.x*=r,this.y*=r,this.z*=r,this._cn=e,this._cnsq=e*e}return this}setMag(e){this._calcNorm();let t=e/this._cn;return this.x*=t,this.y*=t,this.z*=t,this._cn=e,this._cnsq=e*e,this}heading(){return this._$.atan2(this.y,this.x)}setHeading(e){let t=this.mag();return this.x=t*this._$.cos(e),this.y=t*this._$.sin(e),this}rotate(e){let t=this._$.cos(e),r=this._$.sin(e),a=this.x*t-this.y*r,n=this.x*r+this.y*t;return this.x=a,this.y=n,this}angleBetween(){let e=this._arg2v(...arguments),t=Q5.Vector.cross(this,e);return this._$.atan2(t.mag(),this.dot(e))*Math.sign(t.z||1)}lerp(){let e=[...arguments],t=e.at(-1);if(0==t)return this;let r=this._arg2v(...e.slice(0,-1));return this.x+=(r.x-this.x)*t,this.y+=(r.y-this.y)*t,this.z+=(r.z-this.z)*t,this}slerp(){let e=[...arguments],t=e.at(-1);if(0==t)return this;let r=this._arg2v(...e.slice(0,-1));if(1==t)return this.set(r);let a=this.mag(),n=r.mag();if(0==a||0==n)return this.mult(1-t).add(r.mult(t));let o=Q5.Vector.cross(this,r),i=o.mag(),s=Math.atan2(i,this.dot(r));if(i>0)o.div(i);else{if(s<this._$.HALF_PI)return this.mult(1-t).add(r.mult(t));0==this.z&&0==r.z?o.set(0,0,1):0!=this.x?o.set(this.y,-this.x,0).normalize():o.set(1,0,0)}let l=o.cross(this),d=1-t+t*n/a,c=d*Math.cos(t*s),h=d*Math.sin(t*s);return this.x=this.x*c+l.x*h,this.y=this.y*c+l.y*h,this.z=this.z*c+l.z*h,this}reflect(e){return e.normalize(),this.sub(e.mult(2*this.dot(e)))}array(){return[this.x,this.y,this.z]}equals(e,t){return t??=Number.EPSILON||0,Math.abs(e.x-this.x)<t&&Math.abs(e.y-this.y)<t&&Math.abs(e.z-this.z)<t}fromAngle(e,t){return void 0===t&&(t=1),this._cn=t,this._cnsq=t*t,this.x=t*this._$.cos(e),this.y=t*this._$.sin(e),this.z=0,this}fromAngles(e,t,r){void 0===r&&(r=1),this._cn=r,this._cnsq=r*r;const a=this._$.cos(t),n=this._$.sin(t),o=this._$.cos(e),i=this._$.sin(e);return this.x=r*i*n,this.y=-r*o,this.z=r*i*a,this}random2D(){return this._cn=this._cnsq=1,this.fromAngle(Math.random()*Math.PI*2)}random3D(){return this._cn=this._cnsq=1,this.fromAngles(Math.random()*Math.PI*2,Math.random()*Math.PI*2)}toString(){return`[${this.x}, ${this.y}, ${this.z}]`}},Q5.Vector.add=(e,t)=>e.copy().add(t),Q5.Vector.cross=(e,t)=>e.copy().cross(t),Q5.Vector.dist=(e,t)=>Math.hypot(e.x-t.x,e.y-t.y,e.z-t.z),Q5.Vector.div=(e,t)=>e.copy().div(t),Q5.Vector.dot=(e,t)=>e.copy().dot(t),Q5.Vector.equals=(e,t,r)=>e.equals(t,r),Q5.Vector.lerp=(e,t,r)=>e.copy().lerp(t,r),Q5.Vector.slerp=(e,t,r)=>e.copy().slerp(t,r),Q5.Vector.limit=(e,t)=>e.copy().limit(t),Q5.Vector.heading=e=>this._$.atan2(e.y,e.x),Q5.Vector.magSq=e=>e.x*e.x+e.y*e.y+e.z*e.z,Q5.Vector.mag=e=>Math.sqrt(Q5.Vector.magSq(e)),Q5.Vector.mult=(e,t)=>e.copy().mult(t),Q5.Vector.normalize=e=>e.copy().normalize(),Q5.Vector.rem=(e,t)=>e.copy().rem(t),Q5.Vector.sub=(e,t)=>e.copy().sub(t);for(let e of["fromAngle","fromAngles","random2D","random3D"])Q5.Vector[e]=(t,r,a)=>(new Q5.Vector)[e](t,r,a);Q5.renderers.webgpu={},Q5.renderers.webgpu.canvas=(e,t)=>{let r=e.canvas;r.width=e.width=500,r.height=e.height=500,e.colorMode&&e.colorMode("rgb",1);let a,n,o,i=1,s=8;e._pipelineConfigs=[],e._pipelines=[];let l=e.drawStack=[],d=e.colorStack=new Float32Array(1e6);d.set([0,0,0,1,1,1,1,1]),e._transformLayout=Q5.device.createBindGroupLayout({label:"transformLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform",hasDynamicOffset:!1}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]}),o=Q5.device.createBindGroupLayout({label:"colorsLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]}),e.bindGroupLayouts=[e._transformLayout,o];let c=Q5.device.createBuffer({size:8,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),h=()=>{n=Q5.device.createTexture({size:[e.canvas.width,e.canvas.height],sampleCount:4,format:"bgra8unorm",usage:GPUTextureUsage.RENDER_ATTACHMENT}).createView()};e._createCanvas=(a,n,o)=>(t.ctx=t.drawingContext=r.getContext("webgpu"),o.format??=navigator.gpu.getPreferredCanvasFormat(),o.device??=Q5.device,e.ctx.configure(o),Q5.device.queue.writeBuffer(c,0,new Float32Array([e.canvas.hw,e.canvas.hh])),h(),r),e._resizeCanvas=(t,r)=>{e._setCanvasSize(t,r),h()},e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(r.w,r.h),h(),t):e._pixelDensity;let u=(t,r,a,n=1)=>{"string"==typeof t?t=e.color(t):null==a&&(n=r??1,r=a=t),t._q5Color&&(n=t.a,a=t.b,r=t.g,t=t.r);let o=d,l=s;o[l++]=t,o[l++]=r,o[l++]=a,o[l++]=n,s=l,i++};e._fillIndex=e._strokeIndex=0,e._doFill=e._doStroke=!0,e.fill=(t,r,a,n)=>{u(t,r,a,n),e._doFill=e._fillSet=!0,e._fillIndex=i},e.stroke=(t,r,a,n)=>{u(t,r,a,n),e._doStroke=e._strokeSet=!0,e._strokeIndex=i},e.noFill=()=>e._doFill=!1,e.noStroke=()=>e._doStroke=!1,e._strokeWeight=1,e.strokeWeight=t=>e._strokeWeight=Math.abs(t),e.resetMatrix=()=>{e._matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],e._transformIndex=0},e.resetMatrix(),e._matrixDirty=!1;let p=[e._matrix.slice()];e._transformIndexStack=[],e.translate=(t,r,a)=>{(t||r||a)&&(e._matrix[12]+=t,e._matrix[13]-=r,e._matrix[14]+=a||0,e._matrixDirty=!0)},e.rotate=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.cos(t),a=Math.sin(t),n=e._matrix,o=n[0],i=n[1],s=n[4],l=n[5];o||i||s||l?(n[0]=o*r+s*a,n[1]=i*r+l*a,n[4]=s*r-o*a,n[5]=l*r-i*a):(n[0]=r,n[1]=a,n[4]=-a,n[5]=r),e._matrixDirty=!0},e.scale=(t=1,r,a=1)=>{r??=t;let n=e._matrix;n[0]*=t,n[1]*=t,n[2]*=t,n[3]*=t,n[4]*=r,n[5]*=r,n[6]*=r,n[7]*=r,n[8]*=a,n[9]*=a,n[10]*=a,n[11]*=a,e._matrixDirty=!0},e.shearX=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.tan(t),a=e._matrix[0],n=e._matrix[1],o=e._matrix[4],i=e._matrix[5];e._matrix[0]=a+o*r,e._matrix[1]=n+i*r,e._matrixDirty=!0},e.shearY=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.tan(t),a=e._matrix[0],n=e._matrix[1],o=e._matrix[4],i=e._matrix[5];e._matrix[4]=o+a*r,e._matrix[5]=i+n*r,e._matrixDirty=!0},e.applyMatrix=(...t)=>{let r;if(r=1==t.length?t[0]:t,9==r.length)r=[r[0],r[1],0,r[2],r[3],r[4],0,r[5],0,0,1,0,r[6],r[7],0,r[8]];else if(16!=r.length)throw new Error("Matrix must be a 3x3 or 4x4 array.");e._matrix=r.slice(),e._matrixDirty=!0},e._saveMatrix=()=>{p.push(e._matrix.slice()),e._transformIndex=p.length-1,e._matrixDirty=!1},e.pushMatrix=()=>{e._matrixDirty&&e._saveMatrix(),e._transformIndexStack.push(e._transformIndex)},e.popMatrix=()=>{if(!e._transformIndexStack.length)return console.warn("Matrix index stack is empty!");let t=e._transformIndexStack.pop();e._matrix=p[t].slice(),e._transformIndex=t,e._matrixDirty=!1},e.push=()=>{e.pushMatrix(),e.pushStyles()},e.pop=()=>{e.popMatrix(),e.popStyles()},e._calcBox=(e,t,r,a,n)=>{let o,i,s,l,d=r/2,c=a/2;return n&&"corner"!=n?"center"==n?(o=e-d,i=e+d,s=-(t-c),l=-(t+c)):(o=e,i=r,s=-t,l=-a):(o=e,i=e+r,s=-t,l=-(t+a)),[o,i,s,l]};let f=["zero","one","src-alpha","one-minus-src-alpha","dst","dst-alpha","one-minus-dst-alpha","one-minus-src"],_=["add","subtract","reverse-subtract","min","max"];const g={normal:[2,3,0,2,3,0],additive:[1,1,0,1,1,0]};e.blendConfigs={};for(const[t,r]of Object.entries(g))e.blendConfigs[t]={color:{srcFactor:f[r[0]],dstFactor:f[r[1]],operation:_[r[2]]},alpha:{srcFactor:f[r[3]],dstFactor:f[r[4]],operation:_[r[5]]}};e._blendMode="normal",e.blendMode=t=>{if(t!=e._blendMode){"source-over"==t&&(t="normal"),"lighter"==t&&(t="additive"),t=t.toLowerCase().replace(/[ -]/g,"_"),e._blendMode=t;for(let r=0;r<e._pipelines.length;r++)e._pipelineConfigs[r].fragment.targets[0].blend=e.blendConfigs[t],e._pipelines[r]=Q5.device.createRenderPipeline(e._pipelineConfigs[r])}},e.clear=()=>{},e._beginRender=()=>{e.encoder=Q5.device.createCommandEncoder(),a=t.pass=e.encoder.beginRenderPass({label:"q5-webgpu",colorAttachments:[{view:n,resolveTarget:e.ctx.getCurrentTexture().createView(),loadOp:"clear",storeOp:"store"}]})},e._render=()=>{if(p.length>1||!e._transformBindGroup){let t=Q5.device.createBuffer({size:64*p.length,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(p.flat()),t.unmap(),e._transformBindGroup=Q5.device.createBindGroup({layout:e._transformLayout,entries:[{binding:0,resource:{buffer:c}},{binding:1,resource:{buffer:t}}]})}a.setBindGroup(0,e._transformBindGroup);let t=Q5.device.createBuffer({size:4*s,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(d.slice(0,s)),t.unmap(),e._colorsBindGroup=Q5.device.createBindGroup({layout:o,entries:[{binding:0,resource:{buffer:t}}]}),e.pass.setBindGroup(1,e._colorsBindGroup);for(let t of e._hooks.preRender)t();let r=0,n=0,i=0,h=-1;for(let t=0;t<l.length;t+=2){let o=l[t+1];if(h!=l[t]&&(h=l[t],a.setPipeline(e._pipelines[h])),0==h)a.draw(o,1,r),r+=o;else if(1==h)-1!=o&&a.setBindGroup(2,e._textureBindGroups[o]),a.draw(4,1,n),n+=4;else if(2==h){let r=l[t+2];a.setBindGroup(2,e._fonts[r].bindGroup),a.setBindGroup(3,e._textBindGroup),a.draw(4,o,0,i),i+=o,t++}}for(let t of e._hooks.postRender)t()},e._finishRender=()=>{a.end();let r=e.encoder.finish();Q5.device.queue.submit([r]),t.pass=e.encoder=null,e.drawStack.length=0,i=1,s=8,rotation=0,p.length=1,e._transformIndexStack.length=0}},Q5.initWebGPU=async()=>{if(!navigator.gpu)return console.warn("q5 WebGPU not supported on this browser!"),!1;if(!Q5.device){let e=await navigator.gpu.requestAdapter();if(!e)throw new Error("No appropriate GPUAdapter found.");Q5.device=await e.requestDevice()}return!0},Q5.webgpu=async function(e,t){if(e&&"global"!=e||(Q5._hasGlobal=!0),!await Q5.initWebGPU()){let r=new Q5(e,t);return r.colorMode("rgb",1),r._beginRender=()=>r.translate(r.canvas.hw,r.canvas.hh),r}return new Q5(e,t,"webgpu")},Q5.renderers.webgpu.drawing=(e,t)=>{let r,a=e.canvas,n=e.drawStack,o=new Float32Array(1e7),i=0,s=Q5.device.createShaderModule({label:"drawingVertexShader",code:"\nstruct VertexInput {\n\t@location(0) pos: vec2f,\n\t@location(1) colorIndex: f32,\n\t@location(2) transformIndex: f32\n}\nstruct VertexOutput {\n\t@builtin(position) position: vec4f,\n\t@location(0) color: vec4f\n}\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n}\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n\n@group(1) @binding(0) var<storage> colors : array<vec4f>;\n\n@vertex\nfn vertexMain(input: VertexInput) -> VertexOutput {\n\tvar vert = vec4f(input.pos, 0.0, 1.0);\n\tvert = transforms[i32(input.transformIndex)] * vert;\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output: VertexOutput;\n\toutput.position = vert;\n\toutput.color = colors[i32(input.colorIndex)];\n\treturn output;\n}\n"}),l=Q5.device.createShaderModule({label:"drawingFragmentShader",code:"\n@fragment\nfn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {\n\treturn color;\n}\n"}),d=Q5.device.createPipelineLayout({label:"drawingPipelineLayout",bindGroupLayouts:e.bindGroupLayouts});e._pipelineConfigs[0]={label:"drawingPipeline",layout:d,vertex:{module:s,entryPoint:"vertexMain",buffers:[{arrayStride:16,attributes:[{format:"float32x2",offset:0,shaderLocation:0},{format:"float32",offset:8,shaderLocation:1},{format:"float32",offset:12,shaderLocation:2}]}]},fragment:{module:l,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[0]=Q5.device.createRenderPipeline(e._pipelineConfigs[0]);const c=(e,t,r,a)=>{let n=o,s=i;n[s++]=e,n[s++]=t,n[s++]=r,n[s++]=a,i=s},h=(e,t,r,a,s,l,d,c,h,u)=>{let p=o,f=i;p[f++]=e,p[f++]=t,p[f++]=h,p[f++]=u,p[f++]=r,p[f++]=a,p[f++]=h,p[f++]=u,p[f++]=d,p[f++]=c,p[f++]=h,p[f++]=u,p[f++]=s,p[f++]=l,p[f++]=h,p[f++]=u,i=f,n.push(0,4)},u=(t,r,a,s,l,d,c)=>{let h=0,u=e.TAU/l,p=o,f=i;for(let e=0;e<=l;e++){p[f++]=t,p[f++]=r,p[f++]=d,p[f++]=c;let e=t+a*Math.cos(h),n=r+s*Math.sin(h);p[f++]=e,p[f++]=n,p[f++]=d,p[f++]=c,h+=u}p[f++]=t,p[f++]=r,p[f++]=d,p[f++]=c,p[f++]=t+a,p[f++]=r,p[f++]=d,p[f++]=c,i=f,n.push(0,2*(l+1)+2)};e.rectMode=t=>e._rectMode=t,e.rect=(t,a,n,o)=>{let i,s,[l,d,c,u]=e._calcBox(t,a,n,o,e._rectMode);if(e._matrixDirty&&e._saveMatrix(),s=e._transformIndex,e._doStroke){i=e._strokeIndex;let t=e._strokeWeight/2;if(e._doFill){let e=c+t,r=u-t,a=l-t,n=d+t;h(a,e,n,e,n,r,a,r,i,s),c-=t,u+=t,l+=t,d-=t}else{let e=l-t,r=d+t,a=c+t,n=u-t,o=l+t,p=d-t,f=c-t,_=u+t;h(e,f,r,f,r,a,e,a,i,s),h(e,n,r,n,r,_,e,_,i,s),h(e,a,o,a,o,n,e,n,i,s),h(p,a,r,a,r,n,p,n,i,s)}}e._doFill&&(i=r??e._fillIndex,h(l,c,d,c,d,u,l,u,i,s))},e.square=(t,r,a)=>e.rect(t,r,a,a);let p;e.ellipseMode=t=>e._ellipseMode=t,e.ellipse=(t,a,n,o)=>{let i=(s=n==o?n:Math.max(n,o))<4?6:s<6?8:s<10?10:s<16?12:s<20?14:s<22?16:s<24?18:s<28?20:s<34?22:s<42?24:s<48?26:s<56?28:s<64?30:s<72?32:s<84?34:s<96?36:s<98?38:s<113?40:s<149?44:s<199?48:s<261?52:s<353?56:s<461?60:s<585?64:s<1200?70:s<1800?80:s<2400?90:100;var s;let l=Math.max(n,1)/2,d=n==o?l:Math.max(o,1)/2;e._matrixDirty&&e._saveMatrix();let c=e._transformIndex;if(e._doStroke){let r=e._strokeWeight/2;u(t,a,l+r,d+r,i,e._strokeIndex,c),l-=r,d-=r}e._doFill&&u(t,a,l,d,i,r??e._fillIndex,c)},e.circle=(t,r,a)=>e.ellipse(t,r,a,a),e.point=(t,a)=>{r=e._strokeIndex,e._doStroke=!1;let n=e._strokeWeight;n<2?(n=Math.round(n),e.rect(t,a,n,n)):e.ellipse(t,a,n,n),e._doStroke=!0,r=null},e.line=(t,a,n,o)=>{r=e._strokeIndex,e.push(),e._doStroke=!1,e.translate(t,-a),e.rotate(e.atan2(o-a,n-t));let i=Math.sqrt((n-t)**2+(o-a)**2),s=e._strokeWeight,l=s/2;e._rectMode="corner",s<4?e.rect(-l,-l,i+l,s):(e._ellipseMode="center",e.ellipse(0,0,s,s),e.ellipse(i,0,s,s),e.rect(0,-l,i,s)),e.pop(),r=null};let f=[];e.beginShape=()=>{p=0,f=[]},e.vertex=(t,r)=>{e._matrixDirty&&e._saveMatrix(),f.push(t,-r,e._fillIndex,e._transformIndex),p++},e.endShape=t=>{if(p<3)throw new Error("A shape must have at least 3 vertices.");if(t){let e=0,t=4*(p-1),r=f[e],a=f[e+1],n=f[t],o=f[t+1];r===n&&a===o||(f.push(r,a,f[e+2],f[e+3]),p++)}if(e._doFill){for(let e=1;e<p-1;e++){let t=0,r=4*e,a=4*(e+1);c(f[t],f[t+1],f[t+2],f[t+3]),c(f[r],f[r+1],f[r+2],f[r+3]),c(f[a],f[a+1],f[a+2],f[a+3])}n.push(0,3*(p-2))}if(e._doStroke){for(let t=0;t<p-1;t++){let r=4*t,a=4*(t+1);e.line(f[r],f[r+1],f[a],f[a+1])}if(t){let t=4*(p-1),r=0;e.line(f[t],f[t+1],f[r],f[r+1])}}p=0,f=[]},e.triangle=(t,r,a,n,o,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,n),e.vertex(o,i),e.endShape(!0)},e.quad=(t,r,a,n,o,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,n),e.vertex(o,i),e.vertex(s,l),e.endShape(!0)},e.background=(t,r,n,o)=>{if(e.push(),e.resetMatrix(),e._doStroke=!1,t.src){let r=e._imageMode;e._imageMode="corner",e.image(t,-a.hw,-a.hh,a.w,a.h),e._imageMode=r}else{let i=e._rectMode;e._rectMode="corner",e.fill(t,r,n,o),e.rect(-a.hw,-a.hh,a.w,a.h),e._rectMode=i}e.pop(),e._fillSet||(e._fillIndex=1)},e._hooks.preRender.push((()=>{e.pass.setPipeline(e._pipelines[0]);let t=Q5.device.createBuffer({size:4*i,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(o.slice(0,i)),t.unmap(),e.pass.setVertexBuffer(0,t)})),e._hooks.postRender.push((()=>{i=0}))},Q5.renderers.webgpu.image=(e,t)=>{e._textureBindGroups=[];let r=[],a=Q5.device.createShaderModule({label:"imageVertexShader",code:"\nstruct VertexOutput {\n\t@builtin(position) position: vec4f,\n\t@location(0) texCoord: vec2f\n}\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n}\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n\n@vertex\nfn vertexMain(@location(0) pos: vec2f, @location(1) texCoord: vec2f, @location(2) transformIndex: f32) -> VertexOutput {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(transformIndex)] * vert;\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output: VertexOutput;\n\toutput.position = vert;\n\toutput.texCoord = texCoord;\n\treturn output;\n}\n\t"}),n=Q5.device.createShaderModule({label:"imageFragmentShader",code:"\n@group(2) @binding(0) var samp: sampler;\n@group(2) @binding(1) var texture: texture_2d<f32>;\n\n@fragment\nfn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {\n\t// Sample the texture using the interpolated texture coordinate\n\treturn textureSample(texture, samp, texCoord);\n}\n\t"}),o=Q5.device.createBindGroupLayout({label:"textureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]});const i=Q5.device.createPipelineLayout({label:"imagePipelineLayout",bindGroupLayouts:[...e.bindGroupLayouts,o]});e._pipelineConfigs[1]={label:"imagePipeline",layout:i,vertex:{module:a,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},{arrayStride:20,attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"},{shaderLocation:2,offset:16,format:"float32"}]}]},fragment:{module:n,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[1]=Q5.device.createRenderPipeline(e._pipelineConfigs[1]);let s=Q5.device.createSampler({magFilter:"linear",minFilter:"linear"});e._textures=[];let l=0;e._createTexture=t=>{t.canvas&&(t=t.canvas);let r=[t.width,t.height,1],a=Q5.device.createTexture({size:r,format:"bgra8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:t},{texture:a,colorSpace:e.canvas.colorSpace},r),e._textures[l]=a,t.textureIndex=l;const n=Q5.device.createBindGroup({layout:o,entries:[{binding:0,resource:s},{binding:1,resource:a.createView()}]});e._textureBindGroups[l]=n,l=(l+1)%12e3,e._textures[l]&&(e._textures[l].destroy(),delete e._textures[l],delete e._textureBindGroups[l])},e.loadImage=e.loadTexture=r=>{t._preloadCount++;const a=new Image;return a.crossOrigin="Anonymous",a.onload=()=>{a.defaultWidth=a.width*e._defaultImageScale,a.defaultHeight=a.height*e._defaultImageScale,e._createTexture(a),t._preloadCount--},a.src=r,a},e.imageMode=t=>e._imageMode=t,e.image=(t,a,n,o,i,s=0,l=0,d,c)=>{if(t.canvas&&(t=t.canvas),null==t.textureIndex)return;e._matrixDirty&&e._saveMatrix();let h=e._transformIndex,u=t.defaultWidth,p=t.defaultHeight;o??=u,i??=p,d??=u,c??=p;let[f,_,g,m]=e._calcBox(a,n,o,i,e._imageMode),x=s/u,v=l/p,y=(s+d)/u,w=(l+c)/p;r.push(f,g,x,v,h,_,g,y,v,h,f,m,x,w,h,_,m,y,w,h),e.drawStack.push(1,t.textureIndex)},e._hooks.preRender.push((()=>{if(!e._textureBindGroups.length)return;e.pass.setPipeline(e._pipelines[1]);const t=Q5.device.createBuffer({size:4*r.length,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(r),t.unmap(),e.pass.setVertexBuffer(1,t)})),e._hooks.postRender.push((()=>{r.length=0}))},Q5.THRESHOLD=1,Q5.GRAY=2,Q5.OPAQUE=3,Q5.INVERT=4,Q5.POSTERIZE=5,Q5.DILATE=6,Q5.ERODE=7,Q5.BLUR=8,Q5.renderers.webgpu.text=(e,t)=>{let r=Q5.device.createShaderModule({label:"MSDF text shader",code:"\n// Positions for simple quad geometry\nconst pos = array(vec2f(0, -1), vec2f(1, -1), vec2f(0, 0), vec2f(1, 0));\n\nstruct VertexInput {\n\t@builtin(vertex_index) vertex : u32,\n\t@builtin(instance_index) instance : u32\n}\nstruct VertexOutput {\n\t@builtin(position) position : vec4f,\n\t@location(0) texCoord : vec2f,\n\t@location(1) fillColor : vec4f\n}\nstruct Char {\n\ttexOffset: vec2f,\n\ttexExtent: vec2f,\n\tsize: vec2f,\n\toffset: vec2f,\n}\nstruct Text {\n\tpos: vec2f,\n\tscale: f32,\n\ttransformIndex: f32,\n\tfillIndex: f32,\n\tstrokeIndex: f32\n}\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n}\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n\n@group(1) @binding(0) var<storage> colors : array<vec4f>;\n\n@group(2) @binding(0) var fontTexture: texture_2d<f32>;\n@group(2) @binding(1) var fontSampler: sampler;\n@group(2) @binding(2) var<storage> fontChars: array<Char>;\n\n@group(3) @binding(0) var<storage> textChars: array<vec4f>;\n@group(3) @binding(1) var<storage> textMetadata: array<Text>;\n\n@vertex\nfn vertexMain(input : VertexInput) -> VertexOutput {\n\tlet char = textChars[input.instance];\n\n\tlet text = textMetadata[i32(char.w)];\n\n\tlet fontChar = fontChars[i32(char.z)];\n\n\tlet charPos = ((pos[input.vertex] * fontChar.size + char.xy + fontChar.offset) * text.scale) + text.pos;\n\n\tvar vert = vec4f(charPos, 0.0, 1.0);\n\tvert = transforms[i32(text.transformIndex)] * vert;\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output : VertexOutput;\n\toutput.position = vert;\n\toutput.texCoord = (pos[input.vertex] * vec2f(1, -1)) * fontChar.texExtent + fontChar.texOffset;\n\toutput.fillColor = colors[i32(text.fillIndex)];\n\treturn output;\n}\n\nfn sampleMsdf(texCoord: vec2f) -> f32 {\n\tlet c = textureSample(fontTexture, fontSampler, texCoord);\n\treturn max(min(c.r, c.g), min(max(c.r, c.g), c.b));\n}\n\n@fragment\nfn fragmentMain(input : VertexOutput) -> @location(0) vec4f {\n\t// pxRange (AKA distanceRange) comes from the msdfgen tool,\n\t// uses the default which is 4.\n\tlet pxRange = 4.0;\n\tlet sz = vec2f(textureDimensions(fontTexture, 0));\n\tlet dx = sz.x*length(vec2f(dpdxFine(input.texCoord.x), dpdyFine(input.texCoord.x)));\n\tlet dy = sz.y*length(vec2f(dpdxFine(input.texCoord.y), dpdyFine(input.texCoord.y)));\n\tlet toPixels = pxRange * inverseSqrt(dx * dx + dy * dy);\n\tlet sigDist = sampleMsdf(input.texCoord) - 0.5;\n\tlet pxDist = sigDist * toPixels;\n\tlet edgeWidth = 0.5;\n\tlet alpha = smoothstep(-edgeWidth, edgeWidth, pxDist);\n\tif (alpha < 0.001) {\n\t\tdiscard;\n\t}\n\treturn vec4f(input.fillColor.rgb, input.fillColor.a * alpha);\n}\n"}),a=Q5.device.createBindGroupLayout({label:"MSDF text group layout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:1,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]}),n=Q5.device.createSampler({minFilter:"linear",magFilter:"linear",mipmapFilter:"linear",maxAnisotropy:16}),o=Q5.device.createBindGroupLayout({label:"MSDF font group layout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,texture:{}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{}},{binding:2,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}}]}),i=Q5.device.createPipelineLayout({bindGroupLayouts:[...e.bindGroupLayouts,o,a]});e._pipelineConfigs[2]={label:"msdf font pipeline",layout:i,vertex:{module:r,entryPoint:"vertexMain"},fragment:{module:r,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[2]=Q5.device.createRenderPipeline(e._pipelineConfigs[2]);class s{constructor(e,t,r,a){this.bindGroup=e,this.lineHeight=t,this.chars=r,this.kernings=a;let n=Object.values(r);this.charCount=n.length,this.defaultChar=n[0]}getChar(e){return this.chars[e]??this.defaultChar}getXAdvance(e,t=-1){let r=this.getChar(e);if(t>=0){let a=this.kernings.get(e);if(a)return r.xadvance+(a.get(t)??0)}return r.xadvance}}e._fonts=[];let l={},d=e.createGraphics(1,1);d.colorMode(e.RGB,1),e.loadFont=(r,a)=>{if("json"!=r.slice(r.lastIndexOf(".")+1))return d.loadFont(r,a);let i=r.slice(r.lastIndexOf("/")+1,r.lastIndexOf("-"));return(async(r,a,i)=>{t._preloadCount++;let d=await fetch(r);if(404==d.status)return t._preloadCount--,"";let c=await d.json(),h=r.lastIndexOf("/"),u=-1!=h?r.substring(0,h+1):"";d=await fetch(u+c.pages[0]);let p=await createImageBitmap(await d.blob()),f=[p.width,p.height,1],_=Q5.device.createTexture({label:`MSDF ${a}`,size:f,format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:p},{texture:_},f),"string"==typeof c.chars&&(c.chars=e.CSV.parse(c.chars," "),c.kernings=e.CSV.parse(c.kernings," "));let g=c.chars.length,m=Q5.device.createBuffer({size:32*g,usage:GPUBufferUsage.STORAGE,mappedAtCreation:!0}),x=new Float32Array(m.getMappedRange()),v=1/c.common.scaleW,y=1/c.common.scaleH,w={},b=0;for(let[e,t]of c.chars.entries())w[t.id]=t,w[t.id].charIndex=e,x[b]=t.x*v,x[b+1]=t.y*y,x[b+2]=t.width*v,x[b+3]=t.height*y,x[b+4]=t.width,x[b+5]=t.height,x[b+6]=t.xoffset,x[b+7]=-t.yoffset,b+=8;m.unmap();let S=Q5.device.createBindGroup({label:"msdf font bind group",layout:o,entries:[{binding:0,resource:_.createView()},{binding:1,resource:n},{binding:2,resource:{buffer:m}}]}),M=new Map;if(c.kernings)for(let e of c.kernings){let t=M.get(e.first);t||(t=new Map,M.set(e.first,t)),t.set(e.second,e.amount)}e._font=new s(S,c.common.lineHeight,w,M),e._font.index=e._fonts.length,e._fonts.push(e._font),l[a]=e._font,t._preloadCount--,i&&i(a)})(r,i,a),i},e._textSize=18,e._textAlign="left",e._textBaseline="alphabetic";let c=!1,h=22.5,u=4.5,p=1.25;e.textFont=t=>{e._font=l[t]},e.textSize=t=>{e._textSize=t,c||(h=t*p,u=h-t)},e.textLeading=t=>{e._font.lineHeight=h=t,u=h-e._textSize,p=h/e._textSize,c=!0},e.textAlign=(t,r)=>{e._textAlign=t,r&&(e._textBaseline=r)},e._charStack=[],e._textStack=[];let f,_=(e,t,r)=>{let a=0,n=0,o=0,i=0,s=0,l=[],d=t.charCodeAt(0);for(let c=0;c<t.length;++c){let h=d;switch(d=c<t.length-1?t.charCodeAt(c+1):-1,h){case 10:l.push(n),i++,a=Math.max(a,n),n=0,o-=e.lineHeight*p;break;case 13:break;case 32:n+=e.getXAdvance(h);break;case 9:n+=2*e.getXAdvance(h);break;default:r&&r(n,o,i,e.getChar(h)),n+=e.getXAdvance(h,d),s++}}return l.push(n),a=Math.max(a,n),{width:a,height:l.length*e.lineHeight*p,lineWidths:l,printedCharCount:s}};e.text=(t,r,a,n,o)=>{if(!e._font)return void(navigator.onLine&&!f&&(f=!0,e.loadFont("https://q5js.org/fonts/YaHei-msdf.json")));if(t.length>n){let e=[],r=0;for(;r<t.length;){let a=r+n;if(a>=t.length){e.push(t.slice(r));break}let o=t.lastIndexOf(" ",a);(-1==o||o<r)&&(o=a),e.push(t.slice(r,o)),r=o+1}t=e.join("\n")}let i;for(let e=0;e<t.length;e++){switch(t[e]){case"\n":i=!0;case"\r":case"\t":case" ":0}}let s,l=[],d=e._textAlign,c=e._textBaseline,u=e._textStack.length,p=0;if("left"!=d||i){s=_(e._font,t);let r=0;"alphabetic"==c?a-=e._textSize:"center"==c?r=.5*s.height:"bottom"==c&&(r=s.height),_(e._font,t,((e,t,a,n)=>{let o=0;"center"==d?o=-.5*s.width- -.5*(s.width-s.lineWidths[a]):"right"==d&&(o=s.width-s.lineWidths[a]),l[p]=e+o,l[p+1]=t+r,l[p+2]=n.charIndex,l[p+3]=u,p+=4}))}else s=_(e._font,t,((e,t,r,a)=>{l[p]=e,l[p+1]=t,l[p+2]=a.charIndex,l[p+3]=u,p+=4})),"alphabetic"==c?a-=e._textSize:"center"==c?a-=.5*e._textSize:"bottom"==c&&(a-=h);e._charStack.push(l);let g=[];e._matrixDirty&&e._saveMatrix(),g[0]=r,g[1]=-a,g[2]=e._textSize/44,g[3]=e._transformIndex,g[4]=e._fillSet?e._fillIndex:0,g[5]=e._strokeIndex,e._textStack.push(g),e.drawStack.push(2,s.printedCharCount,e._font.index)},e.textWidth=t=>e._font?_(e._font,t).width:0,e.createTextImage=(t,r,a)=>{if(d.textSize(e._textSize),e._doFill){let t=4*e._fillIndex;d.fill(colorStack.slice(t,t+4))}if(e._doStroke){let t=4*e._strokeIndex;d.stroke(colorStack.slice(t,t+4))}let n=d.createTextImage(t,r,a);if(null==n.canvas.textureIndex)e._createTexture(n);else if(n.modified){let t=n.canvas,r=[t.width,t.height,1],a=e._textures[t.textureIndex];Q5.device.queue.copyExternalImageToTexture({source:t},{texture:a,colorSpace:e.canvas.colorSpace},r),n.modified=!1}return n},e.textImage=(t,r,a)=>{"string"==typeof t&&(t=e.createTextImage(t));let n=e._imageMode;e._imageMode="corner";let o=e._textAlign;"center"==o?r-=t.canvas.hw:"right"==o&&(r-=t.width);let i=e._textBaseline;"alphabetic"==i?a-=t._leading:"center"==i?a-=t._middle:"bottom"==i?a-=t._bottom:"top"==i&&(a-=t._top),e.image(t,r,a),e._imageMode=n},e._hooks.preRender.push((()=>{if(!e._charStack.length)return;let t=0;for(let r of e._charStack)t+=4*r.length;let r=Q5.device.createBuffer({size:t,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(r.getMappedRange()).set(e._charStack.flat()),r.unmap();let n=6*e._textStack.length*4,o=Q5.device.createBuffer({label:"textBuffer",size:n,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(o.getMappedRange()).set(e._textStack.flat()),o.unmap(),e._textBindGroup=Q5.device.createBindGroup({label:"msdf text bind group",layout:a,entries:[{binding:0,resource:{buffer:r}},{binding:1,resource:{buffer:o}}]})})),e._hooks.postRender.push((()=>{e._charStack.length=0,e._textStack.length=0}))};
|
|
8
|
+
function Q5(e,t,r){let a=this;a._q5=!0,a._parent=t,a._renderer=r||"q2d",a._preloadCount=0;let n,o="auto"==e;if(e??="global","auto"==e){if(!window.setup&&!window.draw)return;e="global"}a._scope=e,"global"==e&&(Q5._hasGlobal=a._isGlobal=!0,n=Q5._nodejs?global:window);let i=new Proxy(a,{set:(e,t,r)=>(a[t]=r,a._isGlobal&&(n[t]=r),!0)});a.canvas=a.ctx=a.drawingContext=null,a.pixels=[];let s=null;a.frameCount=0,a.deltaTime=16,a._targetFrameRate=0,a._targetFrameDuration=16.666666666666668,a._frameRate=a._fps=60,a._loop=!0,a._hooks={postCanvas:[],preRender:[],postRender:[]};let l=0;a.millis=()=>performance.now()-l,a.noCanvas=()=>{a.canvas?.remove&&a.canvas.remove(),a.canvas=0,i.ctx=i.drawingContext=0},window&&(a.windowWidth=window.innerWidth,a.windowHeight=window.innerHeight,a.deviceOrientation=window.screen?.orientation?.type),a._incrementPreload=()=>i._preloadCount++,a._decrementPreload=()=>i._preloadCount--,a._draw=e=>{let t=e||performance.now();if(a._lastFrameTime??=t-a._targetFrameDuration,a._didResize&&(a.windowResized(),a._didResize=!1),a._loop)s=c(a._draw);else if(a.frameCount&&!a._redraw)return;if(s&&a.frameCount){if(t-a._lastFrameTime<a._targetFrameDuration-4)return}i.deltaTime=t-a._lastFrameTime,a._frameRate=1e3/a.deltaTime,i.frameCount++;let r=performance.now();a.resetMatrix(),a._beginRender&&a._beginRender();for(let e of Q5.methods.pre)e.call(a);try{a.draw()}catch(e){throw!Q5.disableFriendlyErrors&&a._askAI&&a._askAI(e),Q5.errorTolerant||a.noLoop(),e}for(let e of Q5.methods.post)e.call(a);a._render&&a._render(),a._finishRender&&a._finishRender(),i.pmouseX=a.mouseX,i.pmouseY=a.mouseY,i.moveX=i.moveY=0,a._lastFrameTime=t;let n=performance.now();a._fps=Math.round(1e3/(n-r))},a.noLoop=()=>{a._loop=!1,s=null},a.loop=()=>{a._loop=!0,null==s&&a._draw()},a.isLooping=()=>a._loop,a.redraw=(e=1)=>{a._redraw=!0;for(let t=0;t<e;t++)a._draw();a._redraw=!1},a.remove=()=>{a.noLoop(),a.canvas.remove()},a.frameRate=e=>(e&&(a._targetFrameRate=e,a._targetFrameDuration=1e3/e),a._frameRate),a.getTargetFrameRate=()=>a._targetFrameRate||60,a.getFPS=()=>a._fps,a.Element=function(e){this.elt=e},a._elements=[],a.TWO_PI=a.TAU=2*Math.PI,a.log=a.print=console.log,a.describe=()=>{};for(let e in Q5.modules)Q5.modules[e](a,i);let d=Q5.renderers[a._renderer];for(let e in d)d[e](a,i);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(a[e]=Q5[e]);if("graphics"==e)return;"global"==e&&(Object.assign(Q5,a),delete Q5.Q5);for(let e of Q5.methods.init)e.call(a);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof a[e]&&(a[e]=t.bind(a));if("global"==e){let e=Object.getOwnPropertyNames(a);for(let t of e)"_"!=t[0]&&(n[t]=a[t])}"function"==typeof e&&e(a),Q5._instanceCount++;let c=window.requestAnimationFrame||function(e){const t=a._lastFrameTime+a._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},h=n||a;a._isTouchAware=h.touchStarted||h.touchMoved||h.mouseReleased,a._isGlobal&&(a.preload=h.preload,a.setup=h.setup,a.draw=h.draw),a.preload??=()=>{},a.setup??=()=>{},a.draw??=()=>{};let u=["mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","mouseWheel","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of u)h[e]?a._isGlobal&&(a[e]=t=>{try{return h[e](t)}catch(e){throw a._askAI&&a._askAI(e),e}}):a[e]=()=>{};async function p(){if(a._startDone=!0,a._preloadCount>0)return c(p);l=performance.now(),await a.setup(),a._setupDone=!0,a.frameCount||(null===a.ctx&&a.createCanvas(200,200),a.ctx&&a.resetMatrix(),c(a._draw))}function f(){try{a.preload(),a._startDone||p()}catch(e){throw a._askAI&&a._askAI(e),e}}o?f():setTimeout(f,32)}function createCanvas(e,t,r){if(!Q5._hasGlobal){(new Q5).createCanvas(e,t,r)}}Q5.renderers={},Q5.modules={},Q5._nodejs="object"==typeof process,Q5._instanceCount=0,Q5._friendlyError=(e,t)=>{Q5.disableFriendlyErrors||console.error(t+": "+e)},Q5._validateParameters=()=>!0,Q5.methods={init:[],pre:[],post:[],remove:[]},Q5.prototype.registerMethod=(e,t)=>Q5.methods[e].push(t),Q5.prototype.registerPreloadMethod=(e,t)=>Q5.prototype[e]=t[e],Q5._nodejs&&(global.p5??=global.Q5=Q5),"object"==typeof window?window.p5??=window.Q5=Q5:global.window=0,"object"==typeof document&&document.addEventListener("DOMContentLoaded",(()=>{Q5._hasGlobal||new Q5("auto")})),Q5.modules.canvas=(e,t)=>{e.CENTER="center",e.LEFT="left",e.RIGHT="right",e.TOP="top",e.BOTTOM="bottom",e.BASELINE="alphabetic",e.NORMAL="normal",e.ITALIC="italic",e.BOLD="bold",e.BOLDITALIC="italic bold",e.ROUND="round",e.SQUARE="butt",e.PROJECT="square",e.MITER="miter",e.BEVEL="bevel",e.CHORD=0,e.PIE=1,e.OPEN=2,e.RADIUS="radius",e.CORNER="corner",e.CORNERS="corners",e.CLOSE=1,e.LANDSCAPE="landscape",e.PORTRAIT="portrait",e.BLEND="source-over",e.REMOVE="destination-out",e.ADD="lighter",e.DARKEST="darken",e.LIGHTEST="lighten",e.DIFFERENCE="difference",e.SUBTRACT="subtract",e.EXCLUSION="exclusion",e.MULTIPLY="multiply",e.SCREEN="screen",e.REPLACE="copy",e.OVERLAY="overlay",e.HARD_LIGHT="hard-light",e.SOFT_LIGHT="soft-light",e.DODGE="color-dodge",e.BURN="color-burn",e.P2D="2d",e.WEBGL="webgl",e._OffscreenCanvas=window.OffscreenCanvas||function(){return document.createElement("canvas")},Q5._nodejs?Q5._createNodeJSCanvas&&(t.canvas=Q5._createNodeJSCanvas(100,100)):"image"!=e._scope&&"graphics"!=e._scope||(t.canvas=new e._OffscreenCanvas(100,100)),e.canvas||("object"==typeof document?(t.canvas=document.createElement("canvas"),e.canvas.id="q5Canvas"+Q5._instanceCount,e.canvas.classList.add("q5Canvas")):e.noCanvas());let r=e.canvas;if(r.width=e.width=100,r.height=e.height=100,e._pixelDensity=1,e.displayDensity=()=>window.devicePixelRatio||1,"image"!=e._scope&&(r.renderer=e._renderer,r[e._renderer]=!0,e._pixelDensity=Math.ceil(e.displayDensity())),e._adjustDisplay=()=>{r.style&&(r.style.width=r.w+"px",r.style.height=r.h+"px")},e.createCanvas=function(t,a,n){n??=arguments[3];let o=Object.assign({},Q5.canvasOptions);if("object"==typeof n&&Object.assign(o,n),"image"!=e._scope)if("graphics"==e._scope)e._pixelDensity=this._pixelDensity;else if(window.IntersectionObserver){let t=!1;new IntersectionObserver((a=>{r.visible=a[0].isIntersecting,t||(e._wasLooping=e._loop,t=!0),r.visible?e._wasLooping&&!e._loop&&e.loop():(e._wasLooping=e._loop,e.noLoop())})).observe(r)}e._setCanvasSize(t,a),Object.assign(r,o);let i=e._createCanvas(r.w,r.h,o);if(e._hooks)for(let t of e._hooks.postCanvas)t();return e._beginRender&&e._beginRender(),i},e.createGraphics=function(t,r,a){let n=new Q5("graphics");return a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace,n.createCanvas.call(e,t,r,a),n.defaultWidth=t,n.defaultHeight=r,n},e._save=async(e,t,r)=>{if(t=t||"untitled","jpg"==(r=r||"png")||"png"==r||"webp"==r)if(e instanceof OffscreenCanvas){const t=await e.convertToBlob({type:"image/"+r});e=await new Promise((e=>{const r=new FileReader;r.onloadend=()=>e(r.result),r.readAsDataURL(t)}))}else e=e.toDataURL("image/"+r);else{let t="text/plain";"json"==r&&("string"!=typeof e&&(e=JSON.stringify(e)),t="text/json"),e=new Blob([e],{type:t}),e=URL.createObjectURL(e)}let a=document.createElement("a");a.href=e,a.download=t+"."+r,a.click(),URL.revokeObjectURL(a.href)},e.save=(t,r,a)=>{if((!t||"string"==typeof t&&(!r||!a&&r.length<5))&&(a=r,r=t,t=e.canvas),a)return e._save(t,r,a);r?(r=r.split("."),e._save(t,r[0],r.at(-1))):e._save(t)},e._setCanvasSize=(a,n)=>{a??=window.innerWidth,n??=window.innerHeight,r.w=a=Math.ceil(a),r.h=n=Math.ceil(n),r.hw=a/2,r.hh=n/2,r.width=Math.ceil(a*e._pixelDensity),r.height=Math.ceil(n*e._pixelDensity),e._da?e.flexibleCanvas(e._dau):(t.width=a,t.height=n),e.displayMode&&!r.displayMode?e.displayMode():e._adjustDisplay()},e._setImageSize=(a,n)=>{t.width=r.w=a,t.height=r.h=n,r.hw=a/2,r.hh=n/2,r.width=Math.ceil(a*e._pixelDensity),r.height=Math.ceil(n*e._pixelDensity)},"image"!=e._scope){if(r&&"graphics"!=e._scope){function a(){let t=e._parent;t??=document.getElementsByTagName("main")[0],t||(t=document.createElement("main"),document.body.append(t)),r.parent(t)}r.parent=t=>{function a(){e.frameCount>1&&(e._didResize=!0,e._adjustDisplay())}r.parentElement&&r.parentElement.removeChild(r),"string"==typeof t&&(t=document.getElementById(t)),t.append(r),"function"==typeof ResizeObserver?(e._ro&&e._ro.disconnect(),e._ro=new ResizeObserver(a),e._ro.observe(t)):e.frameCount||window.addEventListener("resize",a)},document.body?a():document.addEventListener("DOMContentLoaded",a)}e.resizeCanvas=(t,a)=>{if(!e.ctx)return e.createCanvas(t,a);t==r.w&&a==r.h||e._resizeCanvas(t,a)},e.canvas.resize=e.resizeCanvas,e.canvas.save=e.saveCanvas=e.save,e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(r.w,r.h),t):e._pixelDensity,e.defaultImageScale=t=>t?e._defaultImageScale=t:e._defaultImageScale,e.defaultImageScale(.5),e.flexibleCanvas=(a=400)=>{a?(e._da=r.width/(a*e._pixelDensity),t.width=e._dau=a,t.height=r.h/r.w*a):e._da=0},e._styleNames=["_fill","_stroke","_doStroke","_doFill","_strokeSet","_fillSet","_tint","_imageMode","_rectMode","_ellipseMode","_textSize","_textAlign","_textBaseline"],e._styles=[],e.pushStyles=()=>{let t={};for(let r of e._styleNames)t[r]=e[r];e._styles.push(t)},e.popStyles=()=>{let t=e._styles.pop();for(let r of e._styleNames)e[r]=t[r]},window&&"graphics"!=e._scope&&window.addEventListener("resize",(()=>{e._didResize=!0,t.windowWidth=window.innerWidth,t.windowHeight=window.innerHeight,t.deviceOrientation=window.screen?.orientation?.type}))}},Q5.canvasOptions={alpha:!1,colorSpace:"display-p3"},window.matchMedia&&matchMedia("(dynamic-range: high) and (color-gamut: p3)").matches?Q5.supportsHDR=!0:Q5.canvasOptions.colorSpace="srgb",Q5.renderers.q2d={},Q5.renderers.q2d.canvas=(e,t)=>{let r=e.canvas;e.colorMode&&e.colorMode("rgb","integer"),e._createCanvas=function(a,n,o){return t.ctx=t.drawingContext=r.getContext("2d",o),"image"!=e._scope&&(e.ctx.fillStyle=e._fill="white",e.ctx.strokeStyle=e._stroke="black",e.ctx.lineCap="round",e.ctx.lineJoin="miter",e.ctx.textAlign="left"),e.ctx.scale(e._pixelDensity,e._pixelDensity),e.ctx.save(),r},e.clear=()=>{e.ctx.save(),e.ctx.resetTransform(),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.restore()},"image"!=e._scope&&(e._resizeCanvas=(t,a)=>{let n,o={};for(let t in e.ctx)"function"!=typeof e.ctx[t]&&(o[t]=e.ctx[t]);if(delete o.canvas,e.frameCount>1){n=new e._OffscreenCanvas(r.width,r.height),n.w=r.w,n.h=r.h,n.getContext("2d").drawImage(r,0,0)}e._setCanvasSize(t,a);for(let t in o)e.ctx[t]=o[t];e.scale(e._pixelDensity),n&&e.ctx.drawImage(n,0,0,n.w,n.h)},e.fill=function(t){if(e._doFill=e._fillSet=!0,Q5.Color&&(t._q5Color||("string"!=typeof t?t=e.color(...arguments):e._namedColors[t]&&(t=e.color(...e._namedColors[t]))),t.a<=0))return e._doFill=!1;e.ctx.fillStyle=e._fill=t.toString()},e.noFill=()=>e._doFill=!1,e.stroke=function(t){if(e._doStroke=e._strokeSet=!0,Q5.Color&&(t._q5Color||("string"!=typeof t?t=e.color(...arguments):e._namedColors[t]&&(t=e.color(...e._namedColors[t]))),t.a<=0))return e._doStroke=!1;e.ctx.strokeStyle=e._stroke=t.toString()},e.strokeWeight=t=>{t||(e._doStroke=!1),e._da&&(t*=e._da),e.ctx.lineWidth=e._strokeWeight=t||1e-4},e.noStroke=()=>e._doStroke=!1,e.opacity=t=>e.ctx.globalAlpha=t,e.translate=(t,r)=>{e._da&&(t*=e._da,r*=e._da),e.ctx.translate(t,r)},e.rotate=t=>{e._angleMode&&(t=e.radians(t)),e.ctx.rotate(t)},e.scale=(t,r)=>{t.x&&(r=t.y,t=t.x),r??=t,e.ctx.scale(t,r)},e.applyMatrix=(t,r,a,n,o,i)=>e.ctx.transform(t,r,a,n,o,i),e.shearX=t=>e.ctx.transform(1,0,e.tan(t),1,0,0),e.shearY=t=>e.ctx.transform(1,e.tan(t),0,1,0,0),e.resetMatrix=()=>{e.ctx&&(e.ctx.resetTransform(),e.scale(e._pixelDensity))},e.pushMatrix=()=>e.ctx.save(),e.popMatrix=()=>e.ctx.restore(),e.popStyles=()=>{let t=e._styles.pop();for(let r of e._styleNames)e[r]=t[r];e.ctx.fillStyle=e._fill,e.ctx.strokeStyle=e._stroke,e.ctx.lineWidth=e._strokeWeight},e.push=()=>{e.ctx.save(),e.pushStyles()},e.pop=()=>{e.ctx.restore(),e.popStyles()},e.createCapture=e=>{var t=document.createElement("video");return t.playsinline="playsinline",t.autoplay="autoplay",navigator.mediaDevices.getUserMedia(e).then((e=>{t.srcObject=e})),t.style.position="absolute",t.style.opacity=1e-5,t.style.zIndex=-1e3,document.body.append(t),t})},Q5.renderers.q2d.drawing=e=>{e._doStroke=!0,e._doFill=!0,e._strokeSet=!1,e._fillSet=!1,e._ellipseMode=e.CENTER,e._rectMode=e.CORNER,e._curveDetail=20,e._curveAlpha=0;let t=!0,r=[];function a(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}function n(t,r,n,o,i,s,l,d){if(!e._doFill&&!e._doStroke)return;let c=e._angleMode,h=c?360:e.TAU;if((i%=h)<0&&(i+=h),(s%=h)<0&&(s+=h),i>s&&(s+=h),e.ctx.beginPath(),n==o)c&&(i=e.radians(i),s=e.radians(s)),e.ctx.arc(t,r,n/2,i,s),l==e.CHORD?(e.ctx.lineTo(t+Math.cos(s)*n/2,r+Math.sin(s)*o/2),e.ctx.lineTo(t+Math.cos(i)*n/2,r+Math.sin(i)*o/2),e.ctx.closePath()):l==e.PIE&&(e.ctx.lineTo(t,r),e.ctx.closePath());else{for(let a=0;a<d+1;a++){let l=a/d,c=e.lerp(i,s,l),h=e.cos(c)*n/2,u=e.sin(c)*o/2;e.ctx[a?"lineTo":"moveTo"](t+h,r+u)}l==e.CHORD?(e.ctx.lineTo(t+e.cos(s)*n/2,r+e.sin(s)*o/2),e.ctx.lineTo(t+e.cos(i)*n/2,r+e.sin(i)*o/2),e.ctx.closePath()):l==e.PIE&&(e.ctx.lineTo(t,r),e.ctx.closePath())}a()}function o(t,r,n,o){(e._doFill||e._doStroke)&&(e._da&&(t*=e._da,r*=e._da,n*=e._da,o*=e._da),e.ctx.beginPath(),e.ctx.ellipse(t,r,n/2,o/2,0,0,e.TAU),a())}function i(t,r,n,o,s,l,d,c){if(e._doFill||e._doStroke){if(void 0===s)return function(t,r,n,o){e._da&&(t*=e._da,r*=e._da,n*=e._da,o*=e._da),e.ctx.beginPath(),e.ctx.rect(t,r,n,o),a()}(t,r,n,o);if(void 0===l)return i(t,r,n,o,s,s,s,s);e._da&&(t*=e._da,r*=e._da,n*=e._da,o*=e._da,s*=e._da,l*=e._da,c*=e._da,d*=e._da),e.ctx.roundRect(t,r,n,o,[s,l,d,c]),a()}}e.blendMode=t=>e.ctx.globalCompositeOperation=t,e.strokeCap=t=>e.ctx.lineCap=t,e.strokeJoin=t=>e.ctx.lineJoin=t,e.ellipseMode=t=>e._ellipseMode=t,e.rectMode=t=>e._rectMode=t,e.curveDetail=t=>e._curveDetail=t,e.curveAlpha=t=>e._curveAlpha=t,e.curveTightness=t=>e._curveAlpha=t,e.background=function(t){e.ctx.save(),e.ctx.resetTransform(),e.ctx.globalAlpha=1,t.canvas?e.image(t,0,0,e.canvas.width,e.canvas.height):(Q5.Color&&!t._q5Color&&("string"!=typeof t?t=e.color(...arguments):e._namedColors[t]&&(t=e.color(...e._namedColors[t]))),e.ctx.fillStyle=t.toString(),e.ctx.fillRect(0,0,e.canvas.width,e.canvas.height)),e.ctx.restore()},e.line=(t,r,a,n)=>{e._doStroke&&(e._da&&(t*=e._da,r*=e._da,a*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(a,n),e.ctx.stroke())},e.arc=(t,r,a,o,i,s,l,d=25)=>{if(i==s)return e.ellipse(t,r,a,o);l??=e.PIE,e._ellipseMode==e.CENTER?n(t,r,a,o,i,s,l,d):e._ellipseMode==e.RADIUS?n(t,r,2*a,2*o,i,s,l,d):e._ellipseMode==e.CORNER?n(t+a/2,r+o/2,a,o,i,s,l,d):e._ellipseMode==e.CORNERS&&n((t+a)/2,(r+o)/2,a-t,o-r,i,s,l,d)},e.ellipse=(t,r,a,n)=>{n??=a,e._ellipseMode==e.CENTER?o(t,r,a,n):e._ellipseMode==e.RADIUS?o(t,r,2*a,2*n):e._ellipseMode==e.CORNER?o(t+a/2,r+n/2,a,n):e._ellipseMode==e.CORNERS&&o((t+a)/2,(r+n)/2,a-t,n-r)},e.circle=(t,r,n)=>{e._ellipseMode==e.CENTER?(e._da&&(t*=e._da,r*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.arc(t,r,n/2,0,e.TAU),a()):e.ellipse(t,r,n,n)},e.point=(t,r)=>{e._doStroke&&(t.x&&(r=t.y,t=t.x),e._da&&(t*=e._da,r*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(t,r),e.ctx.stroke())},e.rect=(t,r,a,n=a,o,s,l,d)=>{e._rectMode==e.CENTER?i(t-a/2,r-n/2,a,n,o,s,l,d):e._rectMode==e.RADIUS?i(t-a,r-n,2*a,2*n,o,s,l,d):e._rectMode==e.CORNER?i(t,r,a,n,o,s,l,d):e._rectMode==e.CORNERS&&i(t,r,a-t,n-r,o,s,l,d)},e.square=(t,r,a,n,o,i,s)=>e.rect(t,r,a,a,n,o,i,s),e.beginShape=()=>{r=[],e.ctx.beginPath(),t=!0},e.beginContour=()=>{e.ctx.closePath(),r=[],t=!0},e.endContour=()=>{r=[],t=!0},e.vertex=(a,n)=>{e._da&&(a*=e._da,n*=e._da),r=[],t?e.ctx.moveTo(a,n):e.ctx.lineTo(a,n),t=!1},e.bezierVertex=(t,a,n,o,i,s)=>{e._da&&(t*=e._da,a*=e._da,n*=e._da,o*=e._da,i*=e._da,s*=e._da),r=[],e.ctx.bezierCurveTo(t,a,n,o,i,s)},e.quadraticVertex=(t,a,n,o)=>{e._da&&(t*=e._da,a*=e._da,n*=e._da,o*=e._da),r=[],e.ctx.quadraticCurveTo(t,a,n,o)},e.bezier=(t,r,a,n,o,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.bezierVertex(a,n,o,i,s,l),e.endShape()},e.triangle=(t,r,a,n,o,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,n),e.vertex(o,i),e.endShape(e.CLOSE)},e.quad=(t,r,a,n,o,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,n),e.vertex(o,i),e.vertex(s,l),e.endShape(e.CLOSE)},e.endShape=t=>{r=[],t&&e.ctx.closePath(),a()},e.curveVertex=(a,n)=>{if(e._da&&(a*=e._da,n*=e._da),r.push([a,n]),r.length<4)return;let o=function(e,t,r,a,n,o,i,s,l,d){function c(e,t,r,a,n,o){let i=Math.pow(a-t,2)+Math.pow(n-r,2);return Math.pow(i,.5*o)+e}let h=[],u=c(0,e,t,r,a,d),p=c(u,r,a,n,o,d),f=c(p,n,o,i,s,d);for(let d=0;d<l;d++){let c=u+d/(l-1)*(p-u),_=[(u-c)/(u-0),(c-0)/(u-0),(p-c)/(p-u),(c-u)/(p-u),(f-c)/(f-p),(c-p)/(f-p),(p-c)/(p-0),(c-0)/(p-0),(f-c)/(f-u),(c-u)/(f-u)];for(let e=0;e<_.length;e+=2)isNaN(_[e])&&(_[e]=1,_[e+1]=0),isFinite(_[e])||(_[e]>0?(_[e]=1,_[e+1]=0):(_[e]=0,_[e+1]=1));let g=e*_[0]+r*_[1],m=t*_[0]+a*_[1],x=r*_[2]+n*_[3],v=a*_[2]+o*_[3],y=n*_[4]+i*_[5],w=o*_[4]+s*_[5],b=g*_[6]+x*_[7],S=m*_[6]+v*_[7],M=x*_[8]+y*_[9],C=v*_[8]+w*_[9],R=b*_[2]+M*_[3],I=S*_[2]+C*_[3];h.push([R,I])}return h}(...r.at(-4),...r.at(-3),...r.at(-2),...r.at(-1),e._curveDetail,e._curveAlpha);for(let r=0;r<o.length;r++)t?e.ctx.moveTo(...o[r]):e.ctx.lineTo(...o[r]),t=!1},e.curve=(t,r,a,n,o,i,s,l)=>{e.beginShape(),e.curveVertex(t,r),e.curveVertex(a,n),e.curveVertex(o,i),e.curveVertex(s,l),e.endShape()},e.curvePoint=(e,t,r,a,n)=>{const o=n*n*n,i=n*n;return e*(-.5*o+i-.5*n)+t*(1.5*o-2.5*i+1)+r*(-1.5*o+2*i+.5*n)+a*(.5*o-.5*i)},e.bezierPoint=(e,t,r,a,n)=>{const o=1-n;return Math.pow(o,3)*e+3*Math.pow(o,2)*n*t+3*o*Math.pow(n,2)*r+Math.pow(n,3)*a},e.curveTangent=(e,t,r,a,n)=>{const o=n*n;return e*(-3*o/2+2*n-.5)+t*(9*o/2-5*n)+r*(-9*o/2+4*n+.5)+a*(3*o/2-n)},e.bezierTangent=(e,t,r,a,n)=>{const o=1-n;return 3*a*Math.pow(n,2)-3*r*Math.pow(n,2)+6*r*o*n-6*t*o*n+3*t*Math.pow(o,2)-3*e*Math.pow(o,2)},e.erase=function(t=255,r=255){e.ctx.save(),e.ctx.globalCompositeOperation="destination-out",e.ctx.fillStyle=`rgba(0, 0, 0, ${t/255})`,e.ctx.strokeStyle=`rgba(0, 0, 0, ${r/255})`},e.noErase=function(){e.ctx.globalCompositeOperation="source-over",e.ctx.restore()},e.inFill=(t,r)=>{const a=e._pixelDensity;return e.ctx.isPointInPath(t*a,r*a)},e.inStroke=(t,r)=>{const a=e._pixelDensity;return e.ctx.isPointInStroke(t*a,r*a)}},Q5.renderers.q2d.image=(e,t)=>{Q5.Image??=class{constructor(e,t,r){let a=this;a._scope="image",a.canvas=a.ctx=a.drawingContext=null,a.pixels=[],Q5.modules.canvas(a,a);let n=Q5.renderers.q2d;for(let e of["canvas","image","soft_filters"])n[e]&&n[e](a,a);a._pixelDensity=r.pixelDensity||1,a.createCanvas(e,t,r),delete a.createCanvas,a._loop=!1}get w(){return this.width}get h(){return this.height}},e.createImage=(t,r,a)=>{a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace||Q5.canvasOptions.colorSpace;let n=new Q5.Image(t,r,a);return n.defaultWidth=t*e._defaultImageScale,n.defaultHeight=r*e._defaultImageScale,n},e.loadImage=function(r,a,n){if(r.canvas)return r;if("gif"==r.slice(-3).toLowerCase())throw new Error("q5 doesn't support GIFs due to their impact on performance. Use a video or animation instead.");t._preloadCount++;let o=[...arguments].at(-1);n="object"==typeof o?o:null;let i=e.createImage(1,1,n),s=i._pixelDensity=n?.pixelDensity||1;function l(r){i.defaultWidth=r.width*e._defaultImageScale,i.defaultHeight=r.height*e._defaultImageScale,i.naturalWidth=r.naturalWidth,i.naturalHeight=r.naturalHeight,i._setImageSize(Math.ceil(i.naturalWidth/s),Math.ceil(i.naturalHeight/s)),i.ctx.drawImage(r,0,0),t._preloadCount--,a&&a(i)}if(Q5._nodejs&&global.CairoCanvas)global.CairoCanvas.loadImage(r).then(l).catch((e=>{throw t._preloadCount--,e}));else{let e=new window.Image;e.src=r,e.crossOrigin="Anonymous",e._pixelDensity=s,e.onload=()=>l(e),e.onerror=e=>{throw t._preloadCount--,e}}return i},e.imageMode=t=>e._imageMode=t,e.image=(t,r,a,n,o,i=0,s=0,l,d)=>{if(!t)return;let c=t?.canvas||t;Q5._createNodeJSCanvas&&(c=c.context.canvas),n??=t.defaultWidth||c.width||t.videoWidth,o??=t.defaultHeight||c.height||t.videoHeight,"center"==e._imageMode&&(r-=.5*n,a-=.5*o),e._da&&(r*=e._da,a*=e._da,n*=e._da,o*=e._da,i*=e._da,s*=e._da,l*=e._da,d*=e._da);let h=t._pixelDensity||1;l?l*=h:l=c.width||c.videoWidth,d?d*=h:d=c.height||c.videoHeight,e.ctx.drawImage(c,i*h,s*h,l,d,r,a,n,o),e._tint&&(e.ctx.globalCompositeOperation="multiply",e.ctx.fillStyle=e._tint.toString(),e.ctx.fillRect(r,a,n,o),e.ctx.globalCompositeOperation="source-over")},e._tint=null;let r=null;e._softFilter=()=>{throw new Error("Load q5-2d-soft-filters.js to use software filters.")},e.filter=(t,r)=>{if(!e.ctx.filter)return e._softFilter(t,r);if("string"==typeof t)f=t;else if(t==Q5.GRAY)f="saturate(0%)";else if(t==Q5.INVERT)f="invert(100%)";else if(t==Q5.BLUR){let t=Math.ceil(r*e._pixelDensity)||1;f=`blur(${t}px)`}else{if(t!=Q5.THRESHOLD)return e._softFilter(t,r);{r??=.5;let e=Math.floor(.5/Math.max(r,1e-5)*100);f=`saturate(0%) brightness(${e}%) contrast(1000000%)`}}e.ctx.filter=f,e.ctx.drawImage(e.canvas,0,0,e.canvas.w,e.canvas.h),e.ctx.filter="none"},"image"==e._scope&&(e.resize=(t,r)=>{let a=e.canvas,n=new e._OffscreenCanvas(a.width,a.height);n.getContext("2d",{colorSpace:a.colorSpace}).drawImage(a,0,0),e._setImageSize(t,r),e.ctx.clearRect(0,0,a.width,a.height),e.ctx.drawImage(n,0,0,a.width,a.height)}),e._getImageData=(t,r,a,n)=>e.ctx.getImageData(t,r,a,n,{colorSpace:e.canvas.colorSpace}),e.trim=()=>{let t=e._pixelDensity||1,r=e.canvas.width,a=e.canvas.height,n=e._getImageData(0,0,r,a).data,o=r,i=0,s=a,l=0,d=3;for(let e=0;e<a;e++)for(let t=0;t<r;t++)0!==n[d]&&(t<o&&(o=t),t>i&&(i=t),e<s&&(s=e),e>l&&(l=e)),d+=4;return s=Math.floor(s/t),l=Math.floor(l/t),o=Math.floor(o/t),i=Math.floor(i/t),e.get(o,s,i-o+1,l-s+1)},e.mask=t=>{e.ctx.save(),e.ctx.resetTransform();let r=e.ctx.globalCompositeOperation;e.ctx.globalCompositeOperation="destination-in",e.ctx.drawImage(t.canvas,0,0),e.ctx.globalCompositeOperation=r,e.ctx.restore()},e.inset=(t,r,a,n,o,i,s,l)=>{let d=e._pixelDensity||1;e.ctx.drawImage(e.canvas,t*d,r*d,a*d,n*d,o,i,s,l)},e.copy=()=>e.get(),e.get=(t,r,a,n)=>{let o=e._pixelDensity||1;if(void 0!==t&&void 0===a){let a=e._getImageData(t*o,r*o,1,1).data;return[a[0],a[1],a[2],a[3]/255]}t=(t||0)*o,r=(r||0)*o;let i=a=a||e.width,s=n=n||e.height;a*=o,n*=o;let l=e.createImage(a,n);return l.ctx.drawImage(e.canvas,t,r,a,n,0,0,a,n),l._pixelDensity=o,l.width=i,l.height=s,l},e.set=(t,r,a)=>{if(a.canvas){let n=e._tint;return e._tint=null,e.image(a,t,r),void(e._tint=n)}e.pixels.length||e.loadPixels();let n=e._pixelDensity||1;for(let o=0;o<n;o++)for(let i=0;i<n;i++){let s=4*((r*n+o)*e.canvas.width+t*n+i);e.pixels[s]=a.r,e.pixels[s+1]=a.g,e.pixels[s+2]=a.b,e.pixels[s+3]=a.a}},e.loadPixels=()=>{r=e._getImageData(0,0,e.canvas.width,e.canvas.height),t.pixels=r.data},e.updatePixels=()=>{null!=r&&e.ctx.putImageData(r,0,0)},e.smooth=()=>e.ctx.imageSmoothingEnabled=!0,e.noSmooth=()=>e.ctx.imageSmoothingEnabled=!1,"image"!=e._scope&&(e.tint=function(t){e._tint=t._q5Color?t:e.color(...arguments)},e.noTint=()=>e._tint=null)},Q5.THRESHOLD=1,Q5.GRAY=2,Q5.OPAQUE=3,Q5.INVERT=4,Q5.POSTERIZE=5,Q5.DILATE=6,Q5.ERODE=7,Q5.BLUR=8,Q5.renderers.q2d.text=(e,t)=>{e._textAlign="left",e._textBaseline="alphabetic",e._textSize=12;let r="sans-serif",a=!1,n=15,o=3,i="normal",s=!1,l=0,d=[],c=!1,h=!1,u=0,p=12e3,f=e._textCache={};e.loadFont=(e,r)=>{t._preloadCount++;let a=e.split("/").pop().split(".")[0].replace(" ",""),n=new FontFace(a,`url(${e})`);return document.fonts.add(n),n.load().then((()=>{t._preloadCount--,r&&r(a)})),a},e.textFont=e=>{if(!e||e==r)return r;r=e,s=!0,l=-1},e.textSize=t=>{if(null==t||t==e._textSize)return e._textSize;e._da&&(t*=e._da),e._textSize=t,s=!0,l=-1,a||(n=1.25*t,o=n-t)},e.textStyle=e=>{if(!e||e==i)return i;i=e,s=!0,l=-1},e.textLeading=t=>{if(a=!0,null==t||t==n)return n;e._da&&(t*=e._da),n=t,o=t-e._textSize,l=-1},e.textAlign=(t,r)=>{e.ctx.textAlign=e._textAlign=t,r&&(e.ctx.textBaseline=e._textBaseline=r==e.CENTER?"middle":r)},e.textWidth=t=>e.ctx.measureText(t).width,e.textAscent=t=>e.ctx.measureText(t).actualBoundingBoxAscent,e.textDescent=t=>e.ctx.measureText(t).actualBoundingBoxDescent,e.textFill=e.fill,e.textStroke=e.stroke;e.textCache=(e,t)=>(t&&(p=t),void 0!==e&&(c=e),c),e.createTextImage=(t,r,a)=>(h=!0,img=e.text(t,0,0,r,a),h=!1,img);let _=[];e.text=(t,a,g,m,x)=>{if(void 0===t||!e._doFill&&!e._doStroke)return;t=t.toString(),e._da&&(a*=e._da,g*=e._da);let v,y,w,b,S=e.ctx;if(s&&(S.font=`${i} ${e._textSize}px ${r}`,s=!1),(c||h)&&(-1==l&&(()=>{let t=r+e._textSize+i+n,a=5381;for(let e=0;e<t.length;e++)a=33*a^t.charCodeAt(e);l=a>>>0})(),v=f[t],v&&(v=v[l]),v)){if(v._fill==e._fill&&v._stroke==e._stroke&&v._strokeWeight==e._strokeWeight)return h?v:e.textImage(v,a,g);v.clear()}if(-1==t.indexOf("\n")?_[0]=t:_=t.split("\n"),t.length>m){let e=[];for(let t of _){let r=0;for(;r<t.length;){let a=r+m;if(a>=t.length){e.push(t.slice(r));break}let n=t.lastIndexOf(" ",a);(-1===n||n<r)&&(n=a),e.push(t.slice(r,n)),r=n+1}}_=e}if(c||h){if(y=0,w=n*_.length,!v){let r=S.measureText(" "),a=r.fontBoundingBoxAscent,i=r.fontBoundingBoxDescent;x??=w+i,v=e.createImage.call(e,Math.ceil(S.measureText(t).width),Math.ceil(x),{pixelDensity:e._pixelDensity}),v._ascent=a,v._descent=i,v._top=i+o,v._middle=v._top+.5*a,v._bottom=v._top+a,v._leading=n}v._fill=e._fill,v._stroke=e._stroke,v._strokeWeight=e._strokeWeight,v.modified=!0,S=v.ctx,S.font=e.ctx.font,S.fillStyle=e._fill,S.strokeStyle=e._stroke,S.lineWidth=e.ctx.lineWidth}else y=a,w=g;e._fillSet||(b=S.fillStyle,S.fillStyle="black");for(let t of _)if(e._doStroke&&e._strokeSet&&S.strokeText(t,y,w),e._doFill&&S.fillText(t,y,w),w+=n,w>x)break;if(_.length=0,e._fillSet||(S.fillStyle=b),c||h){if(d.push(l),(f[t]??={})[l]=v,u++,u>p){let e=Math.ceil(u/2),t=d.splice(0,e);for(let e in f){e=f[e];for(let r of t)delete e[r]}u-=e}if(h)return v;e.textImage(v,a,g)}},e.textImage=(t,r,a)=>{"string"==typeof t&&(t=e.createTextImage(t));let n=e._imageMode;e._imageMode="corner";let o=e._textAlign;"center"==o?r-=t.canvas.hw:"right"==o&&(r-=t.width);let i=e._textBaseline;"alphabetic"==i?a-=t._leading:"middle"==i?a-=t._middle:"bottom"==i?a-=t._bottom:"top"==i&&(a-=t._top),e.image(t,r,a),e._imageMode=n},e.nf=(e,t,r)=>{let a=e<0,n=(e=Math.abs(e)).toFixed(r).split(".");n[0]=n[0].padStart(t,"0");let o=n.join(".");return a&&(o="-"+o),o}},Q5.modules.ai=e=>{e.askAI=(e="")=>{throw Q5.disableFriendlyErrors=!1,Error("Ask AI ✨ "+e)},e._askAI=async e=>{let t=e.message?.includes("Ask AI ✨"),r=e.stack?.split("\n");if(!e.stack||r.length<=1)return;let a=1,n="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(a=0,n="@");r[a].indexOf("q5")>=0;)a++;let o=r[a].split(n).at(-1);o.startsWith("blob:")&&(o=o.slice(5));let i=o.split(":"),s=parseInt(i.at(-2));t&&s++,i[3]=i[3].split(")")[0];let l=i.slice(0,2).join(":"),d=l.split("/").at(-1);try{let r=(await(await fetch(l)).text()).split("\n"),a=r[s-1].trim(),n="",o=1;for(;n.length<1600&&(s-o>=0&&(n=r[s-o].trim()+"\n"+n),s+o<r.length);)n+=r[s+o].trim()+"\n",o++;let i="https://chatgpt.com/?q=q5.js+"+(t&&e.message.length>10?e.message.slice(10):"Whats+wrong+with+this+line%3F+short+answer")+(t?"":"%0A%0A"+encodeURIComponent(e.name+": "+e.message))+"%0A%0ALine%3A+"+encodeURIComponent(a)+"%0A%0AExcerpt+for+context%3A%0A%0A"+encodeURIComponent(n);if(console.warn("Error in "+d+" on line "+s+":\n\n"+a),console.warn("Ask AI ✨ "+i),t)return window.open(i,"_blank")}catch(e){}}},Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e._colorMode="rgb",e.OKLCH="oklch",e.colorMode=(r,a)=>{e._colorMode=r;let n="srgb"==e.canvas.colorSpace||"srgb"==r;if(a??=n?"integer":"float",e._colorFormat="float"==a||1==a?1:255,"oklch"==r)t.Color=Q5.ColorOKLCH;else{let r="srgb"==e.canvas.colorSpace;255==e._colorFormat?t.Color=r?Q5.ColorRGBA_8:Q5.ColorRGBA_P3_8:t.Color=r?Q5.ColorRGBA:Q5.ColorRGBA_P3,e._colorMode="rgb"}},e._namedColors={aqua:[0,255,255],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],crimson:[220,20,60],cyan:[0,255,255],darkviolet:[148,0,211],gold:[255,215,0],green:[0,128,0],gray:[128,128,128],grey:[128,128,128],hotpink:[255,105,180],indigo:[75,0,130],khaki:[240,230,140],lightgreen:[144,238,144],lime:[0,255,0],magenta:[255,0,255],navy:[0,0,128],orange:[255,165,0],olive:[128,128,0],peachpuff:[255,218,185],pink:[255,192,203],purple:[128,0,128],red:[255,0,0],skyblue:[135,206,235],tan:[210,180,140],turquoise:[64,224,208],transparent:[0,0,0,0],white:[255,255,255],violet:[238,130,238],yellow:[255,255,0]},e.color=(t,r,a,n)=>{let o=e.Color;if(t._q5Color)return new o(...t.levels);if(null==r){if("string"==typeof t){if("#"==t[0])t.length<=5?(t.length>4&&(n=parseInt(t[4]+t[4],16)),a=parseInt(t[3]+t[3],16),r=parseInt(t[2]+t[2],16),t=parseInt(t[1]+t[1],16)):(t.length>7&&(n=parseInt(t.slice(7,9),16)),a=parseInt(t.slice(5,7),16),r=parseInt(t.slice(3,5),16),t=parseInt(t.slice(1,3),16));else{if(!e._namedColors[t])return console.error("q5 can't parse color: "+t+"\nOnly numeric input, hex, and common named colors are supported."),new o(0,0,0);[t,r,a,n]=e._namedColors[t]}1==e._colorFormat&&(t/=255,r&&(r/=255),a&&(a/=255),n&&(n/=255))}Array.isArray(t)&&([t,r,a,n]=t)}return null==a?new o(t,t,t,r):new o(t,r,a,n)},e.red=e=>e.r,e.green=e=>e.g,e.blue=e=>e.b,e.alpha=e=>e.a,e.lightness=e=>e.l?e.l:100*(.2126*e.r+.7152*e.g+.0722*e.b)/255,e.hue=t=>{if(t.h)return t.h;let r=t.r,a=t.g,n=t.b;255==e._colorFormat&&(r/=255,a/=255,n/=255);let o,i=Math.max(r,a,n),s=Math.min(r,a,n);return o=i==s?0:i==r?60*(a-n)/(i-s):i==a?60*(n-r)/(i-s)+120:60*(r-a)/(i-s)+240,o<0&&(o+=360),o},e.lerpColor=(t,r,a)=>{if(a=Math.max(0,Math.min(1,a)),"rgb"==e._colorMode)return new e.Color(e.lerp(t.r,r.r,a),e.lerp(t.g,r.g,a),e.lerp(t.b,r.b,a),e.lerp(t.a,r.a,a));{let n=r.h-t.h;n>180&&(n-=360),n<-180&&(n+=360);let o=t.h+a*n;return o<0&&(o+=360),o>360&&(o-=360),new e.Color(e.lerp(t.l,r.l,a),e.lerp(t.c,r.c,a),o,e.lerp(t.a,r.a,a))}}},Q5.Color=class{constructor(){this._q5Color=!0}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,r,a){super(),this.l=e,this.c=t,this.h=r,this.a=a??1}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}},Q5.ColorRGBA=class extends Q5.Color{constructor(e,t,r,a){super(),this.r=e,this.g=t,this.b=r,this.a=a??1}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_P3=class extends Q5.ColorRGBA{toString(){return`color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_8=class extends Q5.ColorRGBA{constructor(e,t,r,a){super(e,t,r,a??255)}setRed(e){this.r=e}setGreen(e){this.g=e}setBlue(e){this.b=e}setAlpha(e){this.a=e}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`rgb(${this.r} ${this.g} ${this.b} / ${this.a/255})`}},Q5.ColorRGBA_P3_8=class extends Q5.ColorRGBA{constructor(e,t,r,a){super(e,t,r,a??255),this._edited=!0}get r(){return this._r}set r(e){this._r=e,this._edited=!0}get g(){return this._g}set g(e){this._g=e,this._edited=!0}get b(){return this._b}set b(e){this._b=e,this._edited=!0}get a(){return this._a}set a(e){this._a=e,this._edited=!0}toString(){if(this._edited){let e=(this._r/255).toFixed(3),t=(this._g/255).toFixed(3),r=(this._b/255).toFixed(3),a=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${r} / ${a})`,this._edited=!1}return this._css}},Q5.modules.display=e=>{if(!e.canvas||"graphics"==e._scope)return;let t=e.canvas;e.CENTERED="centered",e.FULLSCREEN="fullscreen",e.MAXED="maxed",e.PIXELATED="pixelated",0!=Q5._instanceCount||Q5._nodejs||document.head.insertAdjacentHTML("beforeend","<style>\nhtml, body {\n\tmargin: 0;\n\tpadding: 0;\n}\n.q5Canvas {\n\toutline: none;\n\t-webkit-touch-callout: none;\n\t-webkit-text-size-adjust: none;\n\t-webkit-user-select: none;\n\toverscroll-behavior: none;\n}\n.q5-pixelated {\n\timage-rendering: pixelated;\n\tfont-smooth: never;\n\t-webkit-font-smoothing: none;\n}\n.q5-centered,\n.q5-maxed,\n.q5-fullscreen {\n display: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\nmain.q5-centered,\nmain.q5-maxed,\n.q5-fullscreen {\n\theight: 100vh;\n}\nmain {\n\toverscroll-behavior: none;\n}\n</style>"),e._adjustDisplay=()=>{let r=t.style,a=t.parentElement;r&&a&&t.displayMode&&("pixelated"==t.renderQuality&&(t.classList.add("q5-pixelated"),e.pixelDensity(1),e.defaultImageScale(1),e.noSmooth&&e.noSmooth(),e.textFont&&e.textFont("monospace")),"default"==t.displayMode||"normal"==t.displayMode?(a.classList.remove("q5-centered","q5-maxed","q5-fullscreen"),r.width=t.w*t.displayScale+"px",r.height=t.h*t.displayScale+"px"):(a.classList.add("q5-"+t.displayMode),a=a.getBoundingClientRect(),t.w/t.h>a.width/a.height?("centered"==t.displayMode?(r.width=t.w*t.displayScale+"px",r.maxWidth="100%"):r.width="100%",r.height="auto",r.maxHeight=""):(r.width="auto",r.maxWidth="","centered"==t.displayMode?(r.height=t.h*t.displayScale+"px",r.maxHeight="100%"):r.height="100%")))},e.displayMode=(r="normal",a="smooth",n=1)=>{"string"==typeof n&&(n=parseFloat(n.slice(1))),Object.assign(t,{displayMode:r,renderQuality:a,displayScale:n}),e._adjustDisplay()},e.fullscreen=e=>{if(void 0===e)return document.fullscreenElement;e?document.body.requestFullscreen():document.body.exitFullscreen()}},Q5.modules.input=(e,t)=>{if("graphics"==e._scope)return;e.mouseX=0,e.mouseY=0,e.pmouseX=0,e.pmouseY=0,e.touches=[],e.mouseButton="",e.keyIsPressed=!1,e.mouseIsPressed=!1,e.key="",e.keyCode=0,e.UP_ARROW=38,e.DOWN_ARROW=40,e.LEFT_ARROW=37,e.RIGHT_ARROW=39,e.SHIFT=16,e.TAB=9,e.BACKSPACE=8,e.ENTER=e.RETURN=13,e.ALT=e.OPTION=18,e.CONTROL=17,e.DELETE=46,e.ESCAPE=27,e.ARROW="default",e.CROSS="crosshair",e.HAND="pointer",e.MOVE="move",e.TEXT="text";let r={},a=[e.LEFT,e.CENTER,e.RIGHT],n=e.canvas;function o(t){const r=e.canvas.getBoundingClientRect(),a=e.canvas.scrollWidth/e.width||1,n=e.canvas.scrollHeight/e.height||1;return{x:(t.clientX-r.left)/a,y:(t.clientY-r.top)/n,id:t.identifier}}if(e._startAudio=()=>{e.getAudioContext&&"suspended"==e.getAudioContext()?.state&&e.userStartAudio()},e._updateMouse=r=>{if(!r.changedTouches){if(n){let a=n.getBoundingClientRect(),o=n.scrollWidth/e.width||1,i=n.scrollHeight/e.height||1;t.mouseX=(r.clientX-a.left)/o,t.mouseY=(r.clientY-a.top)/i,"webgpu"==n.renderer&&(t.mouseX-=n.hw,t.mouseY-=n.hh)}else t.mouseX=r.clientX,t.mouseY=r.clientY;t.moveX=r.movementX,t.moveY=r.movementY}},e._onmousedown=r=>{e._startAudio(),e._updateMouse(r),t.mouseIsPressed=!0,t.mouseButton=a[r.button],e.mousePressed(r)},e._onmousemove=t=>{e._updateMouse(t),e.mouseIsPressed?e.mouseDragged(t):e.mouseMoved(t)},e._onmouseup=r=>{e._updateMouse(r),t.mouseIsPressed=!1,e.mouseReleased(r)},e._onclick=r=>{e._updateMouse(r),t.mouseIsPressed=!0,e.mouseClicked(r),t.mouseIsPressed=!1},e._onwheel=t=>{e._updateMouse(t),t.delta=t.deltaY,0==e.mouseWheel(t)&&t.preventDefault()},e.cursor=(t,r,a)=>{let n="";t.includes(".")&&(t=`url("${t}")`,n=", auto"),void 0!==r&&(t+=" "+r+" "+a),e.canvas.style.cursor=t+n},e.noCursor=()=>{e.canvas.style.cursor="none"},window&&(e.requestPointerLock=document.body?.requestPointerLock,e.exitPointerLock=document.exitPointerLock),e._onkeydown=a=>{a.repeat||(e._startAudio(),t.keyIsPressed=!0,t.key=a.key,t.keyCode=a.keyCode,r[e.keyCode]=r[e.key.toLowerCase()]=!0,e.keyPressed(a),1==a.key.length&&e.keyTyped(a))},e._onkeyup=a=>{t.keyIsPressed=!1,t.key=a.key,t.keyCode=a.keyCode,r[e.keyCode]=r[e.key.toLowerCase()]=!1,e.keyReleased(a)},e.keyIsDown=e=>!!r["string"==typeof e?e.toLowerCase():e],e._ontouchstart=r=>{e._startAudio(),t.touches=[...r.touches].map(o),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,t.mouseIsPressed=!0,t.mouseButton=e.LEFT,e.mousePressed(r)||r.preventDefault()),e.touchStarted(r)||r.preventDefault()},e._ontouchmove=r=>{t.touches=[...r.touches].map(o),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,e.mouseDragged(r)||r.preventDefault()),e.touchMoved(r)||r.preventDefault()},e._ontouchend=r=>{t.touches=[...r.touches].map(o),e._isTouchAware||e.touches.length||(t.mouseIsPressed=!1,e.mouseReleased(r)||r.preventDefault()),e.touchEnded(r)||r.preventDefault()},n&&(n.addEventListener("mousedown",(t=>e._onmousedown(t))),n.addEventListener("mouseup",(t=>e._onmouseup(t))),n.addEventListener("wheel",(t=>e._onwheel(t))),n.addEventListener("click",(t=>e._onclick(t))),n.addEventListener("touchstart",(t=>e._ontouchstart(t))),n.addEventListener("touchmove",(t=>e._ontouchmove(t))),n.addEventListener("touchcancel",(t=>e._ontouchend(t))),n.addEventListener("touchend",(t=>e._ontouchend(t)))),window){let t=window.addEventListener;t("mousemove",(t=>e._onmousemove(t)),!1),t("keydown",(t=>e._onkeydown(t)),!1),t("keyup",(t=>e._onkeyup(t)),!1)}},Q5.modules.math=(e,t)=>{e.RADIANS=0,e.DEGREES=1,e.PI=Math.PI,e.HALF_PI=Math.PI/2,e.QUARTER_PI=Math.PI/4,e.abs=Math.abs,e.ceil=Math.ceil,e.exp=Math.exp,e.floor=e.int=Math.floor,e.loge=Math.log,e.mag=Math.hypot,e.max=Math.max,e.min=Math.min,e.round=Math.round,e.pow=Math.pow,e.sqrt=Math.sqrt,e.SHR3=1,e.LCG=2;let r=0;e.angleMode=t=>{"radians"==t&&(t=0),r=e._angleMode=t};let a=e._DEGTORAD=Math.PI/180,n=e._RADTODEG=180/Math.PI;function o(){let e,t,r=4294967295;return{setSeed(a){e=t=(a??Math.random()*r)>>>0},getSeed:()=>t,rand:()=>(e^=e<<17,e^=e>>13,e^=e<<5,(e>>>0)/r)}}e.degrees=t=>t*e._RADTODEG,e.radians=t=>t*e._DEGTORAD,e.map=Q5.prototype.map=(e,t,r,a,n,o)=>{let i=a+1*(e-t)/(r-t)*(n-a);return o?a<n?Math.min(Math.max(i,a),n):Math.min(Math.max(i,n),a):i},e.lerp=(e,t,r)=>e*(1-r)+t*r,e.constrain=(e,t,r)=>Math.min(Math.max(e,t),r),e.dist=function(){let e=arguments;return 4==e.length?Math.hypot(e[0]-e[2],e[1]-e[3]):Math.hypot(e[0]-e[3],e[1]-e[4],e[2]-e[5])},e.norm=(t,r,a)=>e.map(t,r,a,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e),e.sin=e=>Math.sin(r?e*a:e),e.cos=e=>Math.cos(r?e*a:e),e.tan=e=>Math.tan(r?e*a:e),e.asin=e=>{let t=Math.asin(e);return r?t*n:t},e.acos=e=>{let t=Math.acos(e);return r?t*n:t},e.atan=e=>{let t=Math.atan(e);return r?t*n:t},e.atan2=(e,t)=>{let a=Math.atan2(e,t);return r?a*n:a};let i=o();i.setSeed(),e.randomSeed=e=>i.setSeed(e),e.random=(e,t)=>void 0===e?i.rand():"number"==typeof e?void 0!==t?i.rand()*(t-e)+e:i.rand()*e:e[Math.trunc(e.length*i.rand())],e.randomGenerator=t=>{t==e.LCG?i=function(){const e=4294967296;let t,r;return{setSeed(a){r=t=(a??Math.random()*e)>>>0},getSeed:()=>t,rand:()=>(r=(1664525*r+1013904223)%e,r/e)}}():t==e.SHR3&&(i=o()),i.setSeed()};var s=new function(){var e,t,r,a=new Array(128),n=new Array(256),o=new Array(128),s=new Array(128),l=new Array(256),d=new Array(256),c=()=>4294967296*i.rand()-2147483648,h=()=>.5+2.328306e-10*(c()|0),u=()=>{for(var t,n,i,l,d=3.44262;;){if(t=r*o[e],0==e){do{i=h(),l=h(),t=.2904764*-Math.log(i),n=-Math.log(l)}while(n+n<t*t);return r>0?d+t:-d-t}if(s[e]+h()*(s[e-1]-s[e])<Math.exp(-.5*t*t))return t;if(r=c(),e=127&r,Math.abs(r)<a[e])return r*o[e]}},p=()=>{for(var r;;){if(0==e)return 7.69711-Math.log(h());if(r=t*l[e],d[e]+h()*(d[e-1]-d[e])<Math.exp(-r))return r;if((t=c())<n[e=255&t])return t*l[e]}};this.SHR3=c,this.UNI=h,this.RNOR=()=>(r=c(),e=127&r,Math.abs(r)<a[e]?r*o[e]:u()),this.REXP=()=>(t=c()>>>0)<a[e=255&t]?t*l[e]:p(),this.zigset=()=>{var e,t,r=2147483648,i=4294967296,c=3.442619855899,h=c,u=.00991256303526217,p=7.697117470131487,f=p,_=.003949659822581572;for(e=u/Math.exp(-.5*c*c),a[0]=Math.floor(c/e*r),a[1]=0,o[0]=e/r,o[127]=c/r,s[0]=1,s[127]=Math.exp(-.5*c*c),t=126;t>=1;t--)c=Math.sqrt(-2*Math.log(u/c+Math.exp(-.5*c*c))),a[t+1]=Math.floor(c/h*r),h=c,s[t]=Math.exp(-.5*c*c),o[t]=c/r;for(e=_/Math.exp(-p),n[0]=Math.floor(p/e*i),n[1]=0,l[0]=e/i,l[255]=p/i,d[0]=1,d[255]=Math.exp(-p),t=254;t>=1;t--)p=-Math.log(_/p+Math.exp(-p)),n[t+1]=Math.floor(p/f*i),f=p,d[t]=Math.exp(-p),l[t]=p/i}};let l;s.hasInit=!1,e.randomGaussian=(e,t)=>(s.hasInit||(s.zigset(),s.hasInit=!0),s.RNOR()*t+e),e.randomExponential=()=>(s.hasInit||(s.zigset(),s.hasInit=!0),s.REXP()),e.PERLIN="perlin",e.SIMPLEX="simplex",e.BLOCKY="blocky",e.Noise=Q5.PerlinNoise,e.noiseMode=e=>{t.Noise=Q5[e[0].toUpperCase()+e.slice(1)+"Noise"],l=null},e.noiseSeed=t=>{l=new e.Noise(t)},e.noise=(t=0,r=0,a=0)=>(l??=new e.Noise,l.noise(t,r,a)),e.noiseDetail=(t,r)=>{l??=new e.Noise,t>0&&(l.octaves=t),r>0&&(l.falloff=r)}},Q5.Noise=class{},Q5.PerlinNoise=class extends Q5.Noise{constructor(e){super(),this.grad3=[[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]],this.octaves=1,this.falloff=.5,this.p=null==e?Array.from({length:256},(()=>Math.floor(256*Math.random()))):this.seedPermutation(e),this.p=this.p.concat(this.p)}seedPermutation(e){let t,r,a=[];for(let e=0;e<256;e++)a[e]=e;for(let n=255;n>0;n--)t=(e=16807*e%2147483647)%(n+1),r=a[n],a[n]=a[t],a[t]=r;return a}dot(e,t,r,a){return e[0]*t+e[1]*r+e[2]*a}mix(e,t,r){return(1-r)*e+r*t}fade(e){return e*e*e*(e*(6*e-15)+10)}noise(e,t,r){let a=this,n=0,o=1,i=1,s=0;for(let l=0;l<a.octaves;l++){const l=255&Math.floor(e*o),d=255&Math.floor(t*o),c=255&Math.floor(r*o),h=e*o-Math.floor(e*o),u=t*o-Math.floor(t*o),p=r*o-Math.floor(r*o),f=a.fade(h),_=a.fade(u),g=a.fade(p),m=a.p[l]+d,x=a.p[m]+c,v=a.p[m+1]+c,y=a.p[l+1]+d,w=a.p[y]+c,b=a.p[y+1]+c,S=a.mix(a.dot(a.grad3[a.p[x]%12],h,u,p),a.dot(a.grad3[a.p[w]%12],h-1,u,p),f),M=a.mix(a.dot(a.grad3[a.p[v]%12],h,u-1,p),a.dot(a.grad3[a.p[b]%12],h-1,u-1,p),f),C=a.mix(a.dot(a.grad3[a.p[x+1]%12],h,u,p-1),a.dot(a.grad3[a.p[w+1]%12],h-1,u,p-1),f),R=a.mix(a.dot(a.grad3[a.p[v+1]%12],h,u-1,p-1),a.dot(a.grad3[a.p[b+1]%12],h-1,u-1,p-1),f),I=a.mix(S,M,_),Q=a.mix(C,R,_);n+=a.mix(I,Q,g)*i,s+=i,i*=a.falloff,o*=2}return(n/s+1)/2}},Q5.modules.sound=(e,t)=>{e.Sound=Q5.Sound,e.loadSound=(e,r)=>{t._preloadCount++,Q5.aud??=new window.AudioContext;let a=new Q5.Sound(e,r);return a.crossOrigin="Anonymous",a.addEventListener("canplaythrough",(()=>{t._preloadCount--,a.loaded=!0,r&&r(a)})),a},e.getAudioContext=()=>Q5.aud,e.userStartAudio=()=>Q5.aud.resume()},window.Audio&&(Q5.Sound=class extends Audio{constructor(e){super(e);let t=this;t.load(),t.panner=Q5.aud.createStereoPanner(),t.source=Q5.aud.createMediaElementSource(t),t.source.connect(t.panner),t.panner.connect(Q5.aud.destination),Object.defineProperty(t,"pan",{get:()=>t.panner.pan.value,set:e=>t.panner.pan.value=e})}setVolume(e){this.volume=e}setLoop(e){this.loop=e}setPan(e){this.pan=e}isLoaded(){return this.loaded}isPlaying(){return!this.paused}}),Q5.modules.util=(e,t)=>{e._loadFile=(r,a,n)=>{t._preloadCount++;let o={};return fetch(r).then((e=>"json"==n?e.json():e.text())).then((r=>{t._preloadCount--,"csv"==n&&(r=e.CSV.parse(r)),Object.assign(o,r),a&&a(r)})),o},e.loadText=(t,r)=>e._loadFile(t,r,"text"),e.loadJSON=(t,r)=>e._loadFile(t,r,"json"),e.loadCSV=(t,r)=>e._loadFile(t,r,"csv"),e.CSV={},e.CSV.parse=(e,t=",",r="\n")=>{let a=[],n=e.split(r),o=n[0].split(t);for(let e=1;e<n.length;e++){let r={},i=n[e].split(t);o.forEach(((e,t)=>r[e]=JSON.parse(i[t]))),a.push(r)}return a},"object"==typeof localStorage&&(e.storeItem=localStorage.setItem,e.getItem=localStorage.getItem,e.removeItem=localStorage.removeItem,e.clearStorage=localStorage.clear),e.year=()=>(new Date).getFullYear(),e.day=()=>(new Date).getDay(),e.hour=()=>(new Date).getHours(),e.minute=()=>(new Date).getMinutes(),e.second=()=>(new Date).getSeconds()},Q5.modules.vector=e=>{e.createVector=(t,r,a)=>new Q5.Vector(t,r,a,e)},Q5.Vector=class{constructor(e,t,r,a){this.x=e||0,this.y=t||0,this.z=r||0,this._$=a||window,this._cn=null,this._cnsq=null}set(e,t,r){return this.x=e?.x||e||0,this.y=e?.y||t||0,this.z=e?.z||r||0,this}copy(){return new Q5.Vector(this.x,this.y,this.z)}_arg2v(e,t,r){return void 0!==e?.x?e:void 0!==t?{x:e,y:t,z:r||0}:{x:e,y:e,z:e}}_calcNorm(){this._cnsq=this.x*this.x+this.y*this.y+this.z*this.z,this._cn=Math.sqrt(this._cnsq)}add(){let e=this._arg2v(...arguments);return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}rem(){let e=this._arg2v(...arguments);return this.x%=e.x,this.y%=e.y,this.z%=e.z,this}sub(){let e=this._arg2v(...arguments);return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}mult(){let e=this._arg2v(...arguments);return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}div(){let e=this._arg2v(...arguments);return e.x?this.x/=e.x:this.x=0,e.y?this.y/=e.y:this.y=0,e.z?this.z/=e.z:this.z=0,this}mag(){return this._calcNorm(),this._cn}magSq(){return this._calcNorm(),this._cnsq}dot(){let e=this._arg2v(...arguments);return this.x*e.x+this.y*e.y+this.z*e.z}dist(){let e=this._arg2v(...arguments),t=this.x-e.x,r=this.y-e.y,a=this.z-e.z;return Math.sqrt(t*t+r*r+a*a)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,r=this.z*e.x-this.x*e.z,a=this.x*e.y-this.y*e.x;return this.x=t,this.y=r,this.z=a,this}normalize(){this._calcNorm();let e=this._cn;return 0!=e&&(this.x/=e,this.y/=e,this.z/=e),this._cn=1,this._cnsq=1,this}limit(e){this._calcNorm();let t=this._cn;if(t>e){let r=e/t;this.x*=r,this.y*=r,this.z*=r,this._cn=e,this._cnsq=e*e}return this}setMag(e){this._calcNorm();let t=e/this._cn;return this.x*=t,this.y*=t,this.z*=t,this._cn=e,this._cnsq=e*e,this}heading(){return this._$.atan2(this.y,this.x)}setHeading(e){let t=this.mag();return this.x=t*this._$.cos(e),this.y=t*this._$.sin(e),this}rotate(e){let t=this._$.cos(e),r=this._$.sin(e),a=this.x*t-this.y*r,n=this.x*r+this.y*t;return this.x=a,this.y=n,this}angleBetween(){let e=this._arg2v(...arguments),t=Q5.Vector.cross(this,e);return this._$.atan2(t.mag(),this.dot(e))*Math.sign(t.z||1)}lerp(){let e=[...arguments],t=e.at(-1);if(0==t)return this;let r=this._arg2v(...e.slice(0,-1));return this.x+=(r.x-this.x)*t,this.y+=(r.y-this.y)*t,this.z+=(r.z-this.z)*t,this}slerp(){let e=[...arguments],t=e.at(-1);if(0==t)return this;let r=this._arg2v(...e.slice(0,-1));if(1==t)return this.set(r);let a=this.mag(),n=r.mag();if(0==a||0==n)return this.mult(1-t).add(r.mult(t));let o=Q5.Vector.cross(this,r),i=o.mag(),s=Math.atan2(i,this.dot(r));if(i>0)o.div(i);else{if(s<this._$.HALF_PI)return this.mult(1-t).add(r.mult(t));0==this.z&&0==r.z?o.set(0,0,1):0!=this.x?o.set(this.y,-this.x,0).normalize():o.set(1,0,0)}let l=o.cross(this),d=1-t+t*n/a,c=d*Math.cos(t*s),h=d*Math.sin(t*s);return this.x=this.x*c+l.x*h,this.y=this.y*c+l.y*h,this.z=this.z*c+l.z*h,this}reflect(e){return e.normalize(),this.sub(e.mult(2*this.dot(e)))}array(){return[this.x,this.y,this.z]}equals(e,t){return t??=Number.EPSILON||0,Math.abs(e.x-this.x)<t&&Math.abs(e.y-this.y)<t&&Math.abs(e.z-this.z)<t}fromAngle(e,t){return void 0===t&&(t=1),this._cn=t,this._cnsq=t*t,this.x=t*this._$.cos(e),this.y=t*this._$.sin(e),this.z=0,this}fromAngles(e,t,r){void 0===r&&(r=1),this._cn=r,this._cnsq=r*r;const a=this._$.cos(t),n=this._$.sin(t),o=this._$.cos(e),i=this._$.sin(e);return this.x=r*i*n,this.y=-r*o,this.z=r*i*a,this}random2D(){return this._cn=this._cnsq=1,this.fromAngle(Math.random()*Math.PI*2)}random3D(){return this._cn=this._cnsq=1,this.fromAngles(Math.random()*Math.PI*2,Math.random()*Math.PI*2)}toString(){return`[${this.x}, ${this.y}, ${this.z}]`}},Q5.Vector.add=(e,t)=>e.copy().add(t),Q5.Vector.cross=(e,t)=>e.copy().cross(t),Q5.Vector.dist=(e,t)=>Math.hypot(e.x-t.x,e.y-t.y,e.z-t.z),Q5.Vector.div=(e,t)=>e.copy().div(t),Q5.Vector.dot=(e,t)=>e.copy().dot(t),Q5.Vector.equals=(e,t,r)=>e.equals(t,r),Q5.Vector.lerp=(e,t,r)=>e.copy().lerp(t,r),Q5.Vector.slerp=(e,t,r)=>e.copy().slerp(t,r),Q5.Vector.limit=(e,t)=>e.copy().limit(t),Q5.Vector.heading=e=>this._$.atan2(e.y,e.x),Q5.Vector.magSq=e=>e.x*e.x+e.y*e.y+e.z*e.z,Q5.Vector.mag=e=>Math.sqrt(Q5.Vector.magSq(e)),Q5.Vector.mult=(e,t)=>e.copy().mult(t),Q5.Vector.normalize=e=>e.copy().normalize(),Q5.Vector.rem=(e,t)=>e.copy().rem(t),Q5.Vector.sub=(e,t)=>e.copy().sub(t);for(let e of["fromAngle","fromAngles","random2D","random3D"])Q5.Vector[e]=(t,r,a)=>(new Q5.Vector)[e](t,r,a);Q5.renderers.webgpu={},Q5.renderers.webgpu.canvas=(e,t)=>{let r=e.canvas;r.width=e.width=500,r.height=e.height=500,e.colorMode&&e.colorMode("rgb",1);let a,n,o,i=1,s=8;e._pipelineConfigs=[],e._pipelines=[];let l=e.drawStack=[],d=e.colorStack=new Float32Array(1e6);d.set([0,0,0,1,1,1,1,1]),e._transformLayout=Q5.device.createBindGroupLayout({label:"transformLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform",hasDynamicOffset:!1}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]}),o=Q5.device.createBindGroupLayout({label:"colorsLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]}),e.bindGroupLayouts=[e._transformLayout,o];let c=Q5.device.createBuffer({size:8,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),h=()=>{n=Q5.device.createTexture({size:[e.canvas.width,e.canvas.height],sampleCount:4,format:"bgra8unorm",usage:GPUTextureUsage.RENDER_ATTACHMENT}).createView()};e._createCanvas=(a,n,o)=>(t.ctx=t.drawingContext=r.getContext("webgpu"),o.format??=navigator.gpu.getPreferredCanvasFormat(),o.device??=Q5.device,e.ctx.configure(o),Q5.device.queue.writeBuffer(c,0,new Float32Array([e.canvas.hw,e.canvas.hh])),h(),r),e._resizeCanvas=(t,r)=>{e._setCanvasSize(t,r),h()},e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(r.w,r.h),h(),t):e._pixelDensity;let u=(t,r,a,n=1)=>{"string"==typeof t?t=e.color(t):null==a&&(n=r??1,r=a=t),t._q5Color&&(n=t.a,a=t.b,r=t.g,t=t.r);let o=d,l=s;o[l++]=t,o[l++]=r,o[l++]=a,o[l++]=n,s=l,i++};e._fill=e._stroke=0,e._doFill=e._doStroke=!0,e.fill=(t,r,a,n)=>{u(t,r,a,n),e._doFill=e._fillSet=!0,e._fill=i},e.stroke=(t,r,a,n)=>{u(t,r,a,n),e._doStroke=e._strokeSet=!0,e._stroke=i},e.noFill=()=>e._doFill=!1,e.noStroke=()=>e._doStroke=!1,e._strokeWeight=1,e.strokeWeight=t=>e._strokeWeight=Math.abs(t),e.resetMatrix=()=>{e._matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],e._transformIndex=0},e.resetMatrix(),e._matrixDirty=!1;let p=[e._matrix.slice()];e._transformIndexStack=[],e.translate=(t,r,a)=>{(t||r||a)&&(e._matrix[12]+=t,e._matrix[13]-=r,e._matrix[14]+=a||0,e._matrixDirty=!0)},e.rotate=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.cos(t),a=Math.sin(t),n=e._matrix,o=n[0],i=n[1],s=n[4],l=n[5];o||i||s||l?(n[0]=o*r+s*a,n[1]=i*r+l*a,n[4]=s*r-o*a,n[5]=l*r-i*a):(n[0]=r,n[1]=a,n[4]=-a,n[5]=r),e._matrixDirty=!0},e.scale=(t=1,r,a=1)=>{r??=t;let n=e._matrix;n[0]*=t,n[1]*=t,n[2]*=t,n[3]*=t,n[4]*=r,n[5]*=r,n[6]*=r,n[7]*=r,n[8]*=a,n[9]*=a,n[10]*=a,n[11]*=a,e._matrixDirty=!0},e.shearX=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.tan(t),a=e._matrix[0],n=e._matrix[1],o=e._matrix[4],i=e._matrix[5];e._matrix[0]=a+o*r,e._matrix[1]=n+i*r,e._matrixDirty=!0},e.shearY=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.tan(t),a=e._matrix[0],n=e._matrix[1],o=e._matrix[4],i=e._matrix[5];e._matrix[4]=o+a*r,e._matrix[5]=i+n*r,e._matrixDirty=!0},e.applyMatrix=(...t)=>{let r;if(r=1==t.length?t[0]:t,9==r.length)r=[r[0],r[1],0,r[2],r[3],r[4],0,r[5],0,0,1,0,r[6],r[7],0,r[8]];else if(16!=r.length)throw new Error("Matrix must be a 3x3 or 4x4 array.");e._matrix=r.slice(),e._matrixDirty=!0},e._saveMatrix=()=>{p.push(e._matrix.slice()),e._transformIndex=p.length-1,e._matrixDirty=!1},e.pushMatrix=()=>{e._matrixDirty&&e._saveMatrix(),e._transformIndexStack.push(e._transformIndex)},e.popMatrix=()=>{if(!e._transformIndexStack.length)return console.warn("Matrix index stack is empty!");let t=e._transformIndexStack.pop();e._matrix=p[t].slice(),e._transformIndex=t,e._matrixDirty=!1},e.push=()=>{e.pushMatrix(),e.pushStyles()},e.pop=()=>{e.popMatrix(),e.popStyles()},e._calcBox=(e,t,r,a,n)=>{let o,i,s,l,d=r/2,c=a/2;return n&&"corner"!=n?"center"==n?(o=e-d,i=e+d,s=-(t-c),l=-(t+c)):(o=e,i=r,s=-t,l=-a):(o=e,i=e+r,s=-t,l=-(t+a)),[o,i,s,l]};let f=["zero","one","src-alpha","one-minus-src-alpha","dst","dst-alpha","one-minus-dst-alpha","one-minus-src"],_=["add","subtract","reverse-subtract","min","max"];const g={normal:[2,3,0,2,3,0],additive:[1,1,0,1,1,0]};e.blendConfigs={};for(const[t,r]of Object.entries(g))e.blendConfigs[t]={color:{srcFactor:f[r[0]],dstFactor:f[r[1]],operation:_[r[2]]},alpha:{srcFactor:f[r[3]],dstFactor:f[r[4]],operation:_[r[5]]}};e._blendMode="normal",e.blendMode=t=>{if(t!=e._blendMode){"source-over"==t&&(t="normal"),"lighter"==t&&(t="additive"),t=t.toLowerCase().replace(/[ -]/g,"_"),e._blendMode=t;for(let r=0;r<e._pipelines.length;r++)e._pipelineConfigs[r].fragment.targets[0].blend=e.blendConfigs[t],e._pipelines[r]=Q5.device.createRenderPipeline(e._pipelineConfigs[r])}},e.clear=()=>{},e._beginRender=()=>{e.encoder=Q5.device.createCommandEncoder(),a=t.pass=e.encoder.beginRenderPass({label:"q5-webgpu",colorAttachments:[{view:n,resolveTarget:e.ctx.getCurrentTexture().createView(),loadOp:"clear",storeOp:"store"}]})},e._render=()=>{if(p.length>1||!e._transformBindGroup){let t=Q5.device.createBuffer({size:64*p.length,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(p.flat()),t.unmap(),e._transformBindGroup=Q5.device.createBindGroup({layout:e._transformLayout,entries:[{binding:0,resource:{buffer:c}},{binding:1,resource:{buffer:t}}]})}a.setBindGroup(0,e._transformBindGroup);let t=Q5.device.createBuffer({size:4*s,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(d.slice(0,s)),t.unmap(),e._colorsBindGroup=Q5.device.createBindGroup({layout:o,entries:[{binding:0,resource:{buffer:t}}]}),e.pass.setBindGroup(1,e._colorsBindGroup);for(let t of e._hooks.preRender)t();let r=0,n=0,i=0,h=-1;for(let t=0;t<l.length;t+=2){let o=l[t+1];if(h!=l[t]&&(h=l[t],a.setPipeline(e._pipelines[h])),0==h)a.draw(o,1,r),r+=o;else if(1==h)-1!=o&&a.setBindGroup(2,e._textureBindGroups[o]),a.draw(4,1,n),n+=4;else if(2==h){let r=l[t+2];a.setBindGroup(2,e._fonts[r].bindGroup),a.setBindGroup(3,e._textBindGroup),a.draw(4,o,0,i),i+=o,t++}}for(let t of e._hooks.postRender)t()},e._finishRender=()=>{a.end();let r=e.encoder.finish();Q5.device.queue.submit([r]),t.pass=e.encoder=null,e.drawStack.length=0,i=1,s=8,rotation=0,p.length=1,e._transformIndexStack.length=0}},Q5.initWebGPU=async()=>{if(!navigator.gpu)return console.warn("q5 WebGPU not supported on this browser!"),!1;if(!Q5.device){let e=await navigator.gpu.requestAdapter();if(!e)throw new Error("No appropriate GPUAdapter found.");Q5.device=await e.requestDevice()}return!0},Q5.webgpu=async function(e,t){if(e&&"global"!=e||(Q5._hasGlobal=!0),!await Q5.initWebGPU()){let r=new Q5(e,t);return r.colorMode("rgb",1),r._beginRender=()=>r.translate(r.canvas.hw,r.canvas.hh),r}return new Q5(e,t,"webgpu")},Q5.renderers.webgpu.drawing=(e,t)=>{let r,a=e.canvas,n=e.drawStack,o=new Float32Array(1e7),i=0,s=Q5.device.createShaderModule({label:"drawingVertexShader",code:"\nstruct VertexInput {\n\t@location(0) pos: vec2f,\n\t@location(1) colorIndex: f32,\n\t@location(2) transformIndex: f32\n}\nstruct VertexOutput {\n\t@builtin(position) position: vec4f,\n\t@location(0) color: vec4f\n}\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n}\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n\n@group(1) @binding(0) var<storage> colors : array<vec4f>;\n\n@vertex\nfn vertexMain(input: VertexInput) -> VertexOutput {\n\tvar vert = vec4f(input.pos, 0.0, 1.0);\n\tvert = transforms[i32(input.transformIndex)] * vert;\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output: VertexOutput;\n\toutput.position = vert;\n\toutput.color = colors[i32(input.colorIndex)];\n\treturn output;\n}\n"}),l=Q5.device.createShaderModule({label:"drawingFragmentShader",code:"\n@fragment\nfn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {\n\treturn color;\n}\n"}),d=Q5.device.createPipelineLayout({label:"drawingPipelineLayout",bindGroupLayouts:e.bindGroupLayouts});e._pipelineConfigs[0]={label:"drawingPipeline",layout:d,vertex:{module:s,entryPoint:"vertexMain",buffers:[{arrayStride:16,attributes:[{format:"float32x2",offset:0,shaderLocation:0},{format:"float32",offset:8,shaderLocation:1},{format:"float32",offset:12,shaderLocation:2}]}]},fragment:{module:l,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[0]=Q5.device.createRenderPipeline(e._pipelineConfigs[0]);const c=(e,t,r,a)=>{let n=o,s=i;n[s++]=e,n[s++]=t,n[s++]=r,n[s++]=a,i=s},h=(e,t,r,a,s,l,d,c,h,u)=>{let p=o,f=i;p[f++]=e,p[f++]=t,p[f++]=h,p[f++]=u,p[f++]=r,p[f++]=a,p[f++]=h,p[f++]=u,p[f++]=d,p[f++]=c,p[f++]=h,p[f++]=u,p[f++]=s,p[f++]=l,p[f++]=h,p[f++]=u,i=f,n.push(0,4)},u=(t,r,a,s,l,d,c)=>{r=-r;let h=0,u=e.TAU/l,p=o,f=i;for(let e=0;e<=l;e++){p[f++]=t,p[f++]=r,p[f++]=d,p[f++]=c;let e=t+a*Math.cos(h),n=r+s*Math.sin(h);p[f++]=e,p[f++]=n,p[f++]=d,p[f++]=c,h+=u}p[f++]=t,p[f++]=r,p[f++]=d,p[f++]=c,p[f++]=t+a,p[f++]=r,p[f++]=d,p[f++]=c,i=f,n.push(0,2*(l+1)+2)};e.rectMode=t=>e._rectMode=t,e.rect=(t,a,n,o)=>{let i,s,[l,d,c,u]=e._calcBox(t,a,n,o,e._rectMode);if(e._matrixDirty&&e._saveMatrix(),s=e._transformIndex,e._doStroke){i=e._stroke;let t=e._strokeWeight/2;if(e._doFill){let e=c+t,r=u-t,a=l-t,n=d+t;h(a,e,n,e,n,r,a,r,i,s),c-=t,u+=t,l+=t,d-=t}else{let e=l-t,r=d+t,a=c+t,n=u-t,o=l+t,p=d-t,f=c-t,_=u+t;h(e,f,r,f,r,a,e,a,i,s),h(e,n,r,n,r,_,e,_,i,s),h(e,a,o,a,o,n,e,n,i,s),h(p,a,r,a,r,n,p,n,i,s)}}e._doFill&&(i=r??e._fill,h(l,c,d,c,d,u,l,u,i,s))},e.square=(t,r,a)=>e.rect(t,r,a,a);let p;e.ellipseMode=t=>e._ellipseMode=t,e.ellipse=(t,a,n,o)=>{let i=(s=n==o?n:Math.max(n,o))<4?6:s<6?8:s<10?10:s<16?12:s<20?14:s<22?16:s<24?18:s<28?20:s<34?22:s<42?24:s<48?26:s<56?28:s<64?30:s<72?32:s<84?34:s<96?36:s<98?38:s<113?40:s<149?44:s<199?48:s<261?52:s<353?56:s<461?60:s<585?64:s<1200?70:s<1800?80:s<2400?90:100;var s;let l=Math.max(n,1)/2,d=n==o?l:Math.max(o,1)/2;e._matrixDirty&&e._saveMatrix();let c=e._transformIndex;if(e._doStroke){let r=e._strokeWeight/2;u(t,a,l+r,d+r,i,e._stroke,c),l-=r,d-=r}e._doFill&&u(t,a,l,d,i,r??e._fill,c)},e.circle=(t,r,a)=>e.ellipse(t,r,a,a),e.point=(t,a)=>{r=e._stroke,e._doStroke=!1;let n=e._strokeWeight;n<2?(n=Math.round(n),e.rect(t,a,n,n)):e.ellipse(t,a,n,n),e._doStroke=!0,r=null},e.line=(t,a,n,o)=>{r=e._stroke,e.push(),e._doStroke=!1,e.translate(t,-a),e.rotate(e.atan2(o-a,n-t));let i=Math.sqrt((n-t)**2+(o-a)**2),s=e._strokeWeight,l=s/2;e._rectMode="corner",s<4?e.rect(-l,-l,i+l,s):(e._ellipseMode="center",e.ellipse(0,0,s,s),e.ellipse(i,0,s,s),e.rect(0,-l,i,s)),e.pop(),r=null};let f=[];e.beginShape=()=>{p=0,f=[]},e.vertex=(t,r)=>{e._matrixDirty&&e._saveMatrix(),f.push(t,-r,e._fill,e._transformIndex),p++},e.endShape=t=>{if(p<3)throw new Error("A shape must have at least 3 vertices.");if(t){let e=0,t=4*(p-1),r=f[e],a=f[e+1],n=f[t],o=f[t+1];r===n&&a===o||(f.push(r,a,f[e+2],f[e+3]),p++)}if(e._doFill){for(let e=1;e<p-1;e++){let t=0,r=4*e,a=4*(e+1);c(f[t],f[t+1],f[t+2],f[t+3]),c(f[r],f[r+1],f[r+2],f[r+3]),c(f[a],f[a+1],f[a+2],f[a+3])}n.push(0,3*(p-2))}if(e._doStroke){for(let t=0;t<p-1;t++){let r=4*t,a=4*(t+1);e.line(f[r],f[r+1],f[a],f[a+1])}if(t){let t=4*(p-1),r=0;e.line(f[t],f[t+1],f[r],f[r+1])}}p=0,f=[]},e.triangle=(t,r,a,n,o,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,n),e.vertex(o,i),e.endShape(!0)},e.quad=(t,r,a,n,o,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,n),e.vertex(o,i),e.vertex(s,l),e.endShape(!0)},e.background=(t,r,n,o)=>{if(e.push(),e.resetMatrix(),e._doStroke=!1,t.src){let r=e._imageMode;e._imageMode="corner",e.image(t,-a.hw,-a.hh,a.w,a.h),e._imageMode=r}else{let i=e._rectMode;e._rectMode="corner",e.fill(t,r,n,o),e.rect(-a.hw,-a.hh,a.w,a.h),e._rectMode=i}e.pop(),e._fillSet||(e._fill=1)},e._hooks.preRender.push((()=>{e.pass.setPipeline(e._pipelines[0]);let t=Q5.device.createBuffer({size:4*i,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(o.slice(0,i)),t.unmap(),e.pass.setVertexBuffer(0,t)})),e._hooks.postRender.push((()=>{i=0}))},Q5.renderers.webgpu.image=(e,t)=>{e._textureBindGroups=[];let r=[],a=Q5.device.createShaderModule({label:"imageVertexShader",code:"\nstruct VertexOutput {\n\t@builtin(position) position: vec4f,\n\t@location(0) texCoord: vec2f\n}\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n}\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n\n@vertex\nfn vertexMain(@location(0) pos: vec2f, @location(1) texCoord: vec2f, @location(2) transformIndex: f32) -> VertexOutput {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(transformIndex)] * vert;\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output: VertexOutput;\n\toutput.position = vert;\n\toutput.texCoord = texCoord;\n\treturn output;\n}\n\t"}),n=Q5.device.createShaderModule({label:"imageFragmentShader",code:"\n@group(2) @binding(0) var samp: sampler;\n@group(2) @binding(1) var texture: texture_2d<f32>;\n\n@fragment\nfn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {\n\t// Sample the texture using the interpolated texture coordinate\n\treturn textureSample(texture, samp, texCoord);\n}\n\t"}),o=Q5.device.createBindGroupLayout({label:"textureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]});const i=Q5.device.createPipelineLayout({label:"imagePipelineLayout",bindGroupLayouts:[...e.bindGroupLayouts,o]});e._pipelineConfigs[1]={label:"imagePipeline",layout:i,vertex:{module:a,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},{arrayStride:20,attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"},{shaderLocation:2,offset:16,format:"float32"}]}]},fragment:{module:n,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[1]=Q5.device.createRenderPipeline(e._pipelineConfigs[1]);let s=Q5.device.createSampler({magFilter:"linear",minFilter:"linear"});e._textures=[];let l=0;e._createTexture=t=>{t.canvas&&(t=t.canvas);let r=[t.width,t.height,1],a=Q5.device.createTexture({size:r,format:"bgra8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:t},{texture:a,colorSpace:e.canvas.colorSpace},r),e._textures[l]=a,t.textureIndex=l;const n=Q5.device.createBindGroup({layout:o,entries:[{binding:0,resource:s},{binding:1,resource:a.createView()}]});e._textureBindGroups[l]=n,l=(l+1)%12e3,e._textures[l]&&(e._textures[l].destroy(),delete e._textures[l],delete e._textureBindGroups[l])},e.loadImage=e.loadTexture=r=>{t._preloadCount++;const a=new Image;return a.crossOrigin="Anonymous",a.onload=()=>{a.defaultWidth=a.width*e._defaultImageScale,a.defaultHeight=a.height*e._defaultImageScale,e._createTexture(a),t._preloadCount--},a.src=r,a},e.imageMode=t=>e._imageMode=t,e.image=(t,a,n,o,i,s=0,l=0,d,c)=>{if(t.canvas&&(t=t.canvas),null==t.textureIndex)return;e._matrixDirty&&e._saveMatrix();let h=e._transformIndex,u=t.defaultWidth,p=t.defaultHeight;o??=u,i??=p,d??=u,c??=p;let[f,_,g,m]=e._calcBox(a,n,o,i,e._imageMode),x=s/u,v=l/p,y=(s+d)/u,w=(l+c)/p;r.push(f,g,x,v,h,_,g,y,v,h,f,m,x,w,h,_,m,y,w,h),e.drawStack.push(1,t.textureIndex)},e._hooks.preRender.push((()=>{if(!e._textureBindGroups.length)return;e.pass.setPipeline(e._pipelines[1]);const t=Q5.device.createBuffer({size:4*r.length,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(r),t.unmap(),e.pass.setVertexBuffer(1,t)})),e._hooks.postRender.push((()=>{r.length=0}))},Q5.THRESHOLD=1,Q5.GRAY=2,Q5.OPAQUE=3,Q5.INVERT=4,Q5.POSTERIZE=5,Q5.DILATE=6,Q5.ERODE=7,Q5.BLUR=8,Q5.renderers.webgpu.text=(e,t)=>{let r=Q5.device.createShaderModule({label:"MSDF text shader",code:"\n// Positions for simple quad geometry\nconst pos = array(vec2f(0, -1), vec2f(1, -1), vec2f(0, 0), vec2f(1, 0));\n\nstruct VertexInput {\n\t@builtin(vertex_index) vertex : u32,\n\t@builtin(instance_index) instance : u32\n}\nstruct VertexOutput {\n\t@builtin(position) position : vec4f,\n\t@location(0) texCoord : vec2f,\n\t@location(1) fillColor : vec4f\n}\nstruct Char {\n\ttexOffset: vec2f,\n\ttexExtent: vec2f,\n\tsize: vec2f,\n\toffset: vec2f,\n}\nstruct Text {\n\tpos: vec2f,\n\tscale: f32,\n\ttransformIndex: f32,\n\tfillIndex: f32,\n\tstrokeIndex: f32\n}\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n}\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n\n@group(1) @binding(0) var<storage> colors : array<vec4f>;\n\n@group(2) @binding(0) var fontTexture: texture_2d<f32>;\n@group(2) @binding(1) var fontSampler: sampler;\n@group(2) @binding(2) var<storage> fontChars: array<Char>;\n\n@group(3) @binding(0) var<storage> textChars: array<vec4f>;\n@group(3) @binding(1) var<storage> textMetadata: array<Text>;\n\n@vertex\nfn vertexMain(input : VertexInput) -> VertexOutput {\n\tlet char = textChars[input.instance];\n\n\tlet text = textMetadata[i32(char.w)];\n\n\tlet fontChar = fontChars[i32(char.z)];\n\n\tlet charPos = ((pos[input.vertex] * fontChar.size + char.xy + fontChar.offset) * text.scale) + text.pos;\n\n\tvar vert = vec4f(charPos, 0.0, 1.0);\n\tvert = transforms[i32(text.transformIndex)] * vert;\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output : VertexOutput;\n\toutput.position = vert;\n\toutput.texCoord = (pos[input.vertex] * vec2f(1, -1)) * fontChar.texExtent + fontChar.texOffset;\n\toutput.fillColor = colors[i32(text.fillIndex)];\n\treturn output;\n}\n\nfn sampleMsdf(texCoord: vec2f) -> f32 {\n\tlet c = textureSample(fontTexture, fontSampler, texCoord);\n\treturn max(min(c.r, c.g), min(max(c.r, c.g), c.b));\n}\n\n@fragment\nfn fragmentMain(input : VertexOutput) -> @location(0) vec4f {\n\t// pxRange (AKA distanceRange) comes from the msdfgen tool,\n\t// uses the default which is 4.\n\tlet pxRange = 4.0;\n\tlet sz = vec2f(textureDimensions(fontTexture, 0));\n\tlet dx = sz.x*length(vec2f(dpdxFine(input.texCoord.x), dpdyFine(input.texCoord.x)));\n\tlet dy = sz.y*length(vec2f(dpdxFine(input.texCoord.y), dpdyFine(input.texCoord.y)));\n\tlet toPixels = pxRange * inverseSqrt(dx * dx + dy * dy);\n\tlet sigDist = sampleMsdf(input.texCoord) - 0.5;\n\tlet pxDist = sigDist * toPixels;\n\tlet edgeWidth = 0.5;\n\tlet alpha = smoothstep(-edgeWidth, edgeWidth, pxDist);\n\tif (alpha < 0.001) {\n\t\tdiscard;\n\t}\n\treturn vec4f(input.fillColor.rgb, input.fillColor.a * alpha);\n}\n"}),a=Q5.device.createBindGroupLayout({label:"MSDF text group layout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:1,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]}),n=Q5.device.createSampler({minFilter:"linear",magFilter:"linear",mipmapFilter:"linear",maxAnisotropy:16}),o=Q5.device.createBindGroupLayout({label:"MSDF font group layout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,texture:{}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{}},{binding:2,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}}]}),i=Q5.device.createPipelineLayout({bindGroupLayouts:[...e.bindGroupLayouts,o,a]});e._pipelineConfigs[2]={label:"msdf font pipeline",layout:i,vertex:{module:r,entryPoint:"vertexMain"},fragment:{module:r,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[2]=Q5.device.createRenderPipeline(e._pipelineConfigs[2]);class s{constructor(e,t,r,a){this.bindGroup=e,this.lineHeight=t,this.chars=r,this.kernings=a;let n=Object.values(r);this.charCount=n.length,this.defaultChar=n[0]}getChar(e){return this.chars[e]??this.defaultChar}getXAdvance(e,t=-1){let r=this.getChar(e);if(t>=0){let a=this.kernings.get(e);if(a)return r.xadvance+(a.get(t)??0)}return r.xadvance}}e._fonts=[];let l={},d=e.createGraphics(1,1);d.colorMode(e.RGB,1),e.loadFont=(r,a)=>{if("json"!=r.slice(r.lastIndexOf(".")+1))return d.loadFont(r,a);let i=r.slice(r.lastIndexOf("/")+1,r.lastIndexOf("-"));return(async(r,a,i)=>{t._preloadCount++;let d=await fetch(r);if(404==d.status)return t._preloadCount--,"";let c=await d.json(),h=r.lastIndexOf("/"),u=-1!=h?r.substring(0,h+1):"";d=await fetch(u+c.pages[0]);let p=await createImageBitmap(await d.blob()),f=[p.width,p.height,1],_=Q5.device.createTexture({label:`MSDF ${a}`,size:f,format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:p},{texture:_},f),"string"==typeof c.chars&&(c.chars=e.CSV.parse(c.chars," "),c.kernings=e.CSV.parse(c.kernings," "));let g=c.chars.length,m=Q5.device.createBuffer({size:32*g,usage:GPUBufferUsage.STORAGE,mappedAtCreation:!0}),x=new Float32Array(m.getMappedRange()),v=1/c.common.scaleW,y=1/c.common.scaleH,w={},b=0;for(let[e,t]of c.chars.entries())w[t.id]=t,w[t.id].charIndex=e,x[b]=t.x*v,x[b+1]=t.y*y,x[b+2]=t.width*v,x[b+3]=t.height*y,x[b+4]=t.width,x[b+5]=t.height,x[b+6]=t.xoffset,x[b+7]=-t.yoffset,b+=8;m.unmap();let S=Q5.device.createBindGroup({label:"msdf font bind group",layout:o,entries:[{binding:0,resource:_.createView()},{binding:1,resource:n},{binding:2,resource:{buffer:m}}]}),M=new Map;if(c.kernings)for(let e of c.kernings){let t=M.get(e.first);t||(t=new Map,M.set(e.first,t)),t.set(e.second,e.amount)}e._font=new s(S,c.common.lineHeight,w,M),e._font.index=e._fonts.length,e._fonts.push(e._font),l[a]=e._font,t._preloadCount--,i&&i(a)})(r,i,a),i},e._textSize=18,e._textAlign="left",e._textBaseline="alphabetic";let c=!1,h=22.5,u=4.5,p=1.25;e.textFont=t=>{e._font=l[t]},e.textSize=t=>{e._textSize=t,c||(h=t*p,u=h-t)},e.textLeading=t=>{e._font.lineHeight=h=t,u=h-e._textSize,p=h/e._textSize,c=!0},e.textAlign=(t,r)=>{e._textAlign=t,r&&(e._textBaseline=r)},e._charStack=[],e._textStack=[];let f,_=(e,t,r)=>{let a=0,n=0,o=0,i=0,s=0,l=[],d=t.charCodeAt(0);for(let c=0;c<t.length;++c){let h=d;switch(d=c<t.length-1?t.charCodeAt(c+1):-1,h){case 10:l.push(n),i++,a=Math.max(a,n),n=0,o-=e.lineHeight*p;break;case 13:break;case 32:n+=e.getXAdvance(h);break;case 9:n+=2*e.getXAdvance(h);break;default:r&&r(n,o,i,e.getChar(h)),n+=e.getXAdvance(h,d),s++}}return l.push(n),a=Math.max(a,n),{width:a,height:l.length*e.lineHeight*p,lineWidths:l,printedCharCount:s}};e.text=(t,r,a,n,o)=>{if(!e._font)return void(navigator.onLine&&!f&&(f=!0,e.loadFont("https://q5js.org/fonts/YaHei-msdf.json")));if(t.length>n){let e=[],r=0;for(;r<t.length;){let a=r+n;if(a>=t.length){e.push(t.slice(r));break}let o=t.lastIndexOf(" ",a);(-1==o||o<r)&&(o=a),e.push(t.slice(r,o)),r=o+1}t=e.join("\n")}let i;for(let e=0;e<t.length;e++){switch(t[e]){case"\n":i=!0;case"\r":case"\t":case" ":0}}let s,l=[],d=e._textAlign,c=e._textBaseline,u=e._textStack.length,p=0;if("left"!=d||i){s=_(e._font,t);let r=0;"alphabetic"==c?a-=e._textSize:"center"==c?r=.5*s.height:"bottom"==c&&(r=s.height),_(e._font,t,((e,t,a,n)=>{let o=0;"center"==d?o=-.5*s.width- -.5*(s.width-s.lineWidths[a]):"right"==d&&(o=s.width-s.lineWidths[a]),l[p]=e+o,l[p+1]=t+r,l[p+2]=n.charIndex,l[p+3]=u,p+=4}))}else s=_(e._font,t,((e,t,r,a)=>{l[p]=e,l[p+1]=t,l[p+2]=a.charIndex,l[p+3]=u,p+=4})),"alphabetic"==c?a-=e._textSize:"center"==c?a-=.5*e._textSize:"bottom"==c&&(a-=h);e._charStack.push(l);let g=[];e._matrixDirty&&e._saveMatrix(),g[0]=r,g[1]=-a,g[2]=e._textSize/44,g[3]=e._transformIndex,g[4]=e._fillSet?e._fill:0,g[5]=e._stroke,e._textStack.push(g),e.drawStack.push(2,s.printedCharCount,e._font.index)},e.textWidth=t=>e._font?_(e._font,t).width:0,e.createTextImage=(t,r,a)=>{if(d.textSize(e._textSize),e._doFill){let t=4*e._fill;d.fill(colorStack.slice(t,t+4))}if(e._doStroke){let t=4*e._stroke;d.stroke(colorStack.slice(t,t+4))}let n=d.createTextImage(t,r,a);if(null==n.canvas.textureIndex)e._createTexture(n);else if(n.modified){let t=n.canvas,r=[t.width,t.height,1],a=e._textures[t.textureIndex];Q5.device.queue.copyExternalImageToTexture({source:t},{texture:a,colorSpace:e.canvas.colorSpace},r),n.modified=!1}return n},e.textImage=(t,r,a)=>{"string"==typeof t&&(t=e.createTextImage(t));let n=e._imageMode;e._imageMode="corner";let o=e._textAlign;"center"==o?r-=t.canvas.hw:"right"==o&&(r-=t.width);let i=e._textBaseline;"alphabetic"==i?a-=t._leading:"center"==i?a-=t._middle:"bottom"==i?a-=t._bottom:"top"==i&&(a-=t._top),e.image(t,r,a),e._imageMode=n},e._hooks.preRender.push((()=>{if(!e._charStack.length)return;let t=0;for(let r of e._charStack)t+=4*r.length;let r=Q5.device.createBuffer({size:t,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(r.getMappedRange()).set(e._charStack.flat()),r.unmap();let n=6*e._textStack.length*4,o=Q5.device.createBuffer({label:"textBuffer",size:n,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(o.getMappedRange()).set(e._textStack.flat()),o.unmap(),e._textBindGroup=Q5.device.createBindGroup({label:"msdf text bind group",layout:a,entries:[{binding:0,resource:{buffer:r}},{binding:1,resource:{buffer:o}}]})})),e._hooks.postRender.push((()=>{e._charStack.length=0,e._textStack.length=0}))};
|
package/src/q5-2d-canvas.js
CHANGED
|
@@ -10,8 +10,8 @@ Q5.renderers.q2d.canvas = ($, q) => {
|
|
|
10
10
|
|
|
11
11
|
if ($._scope != 'image') {
|
|
12
12
|
// default styles
|
|
13
|
-
$.ctx.fillStyle = 'white';
|
|
14
|
-
$.ctx.strokeStyle = 'black';
|
|
13
|
+
$.ctx.fillStyle = $._fill = 'white';
|
|
14
|
+
$.ctx.strokeStyle = $._stroke = 'black';
|
|
15
15
|
$.ctx.lineCap = 'round';
|
|
16
16
|
$.ctx.lineJoin = 'miter';
|
|
17
17
|
$.ctx.textAlign = 'left';
|
|
@@ -120,6 +120,15 @@ Q5.renderers.q2d.canvas = ($, q) => {
|
|
|
120
120
|
$.pushMatrix = () => $.ctx.save();
|
|
121
121
|
$.popMatrix = () => $.ctx.restore();
|
|
122
122
|
|
|
123
|
+
$.popStyles = () => {
|
|
124
|
+
let styles = $._styles.pop();
|
|
125
|
+
for (let s of $._styleNames) $[s] = styles[s];
|
|
126
|
+
|
|
127
|
+
$.ctx.fillStyle = $._fill;
|
|
128
|
+
$.ctx.strokeStyle = $._stroke;
|
|
129
|
+
$.ctx.lineWidth = $._strokeWeight;
|
|
130
|
+
};
|
|
131
|
+
|
|
123
132
|
$.push = () => {
|
|
124
133
|
$.ctx.save();
|
|
125
134
|
$.pushStyles();
|
package/src/q5-2d-drawing.js
CHANGED
|
@@ -62,14 +62,15 @@ Q5.renderers.q2d.drawing = ($) => {
|
|
|
62
62
|
|
|
63
63
|
function arc(x, y, w, h, lo, hi, mode, detail) {
|
|
64
64
|
if (!$._doFill && !$._doStroke) return;
|
|
65
|
+
|
|
65
66
|
let d = $._angleMode;
|
|
66
67
|
let full = d ? 360 : $.TAU;
|
|
67
68
|
lo %= full;
|
|
68
69
|
hi %= full;
|
|
69
70
|
if (lo < 0) lo += full;
|
|
70
71
|
if (hi < 0) hi += full;
|
|
71
|
-
if (lo
|
|
72
|
-
|
|
72
|
+
if (lo > hi) hi += full;
|
|
73
|
+
|
|
73
74
|
$.ctx.beginPath();
|
|
74
75
|
if (w == h) {
|
|
75
76
|
if (d) {
|
|
@@ -77,6 +78,15 @@ Q5.renderers.q2d.drawing = ($) => {
|
|
|
77
78
|
hi = $.radians(hi);
|
|
78
79
|
}
|
|
79
80
|
$.ctx.arc(x, y, w / 2, lo, hi);
|
|
81
|
+
|
|
82
|
+
if (mode == $.CHORD) {
|
|
83
|
+
$.ctx.lineTo(x + (Math.cos(hi) * w) / 2, y + (Math.sin(hi) * h) / 2);
|
|
84
|
+
$.ctx.lineTo(x + (Math.cos(lo) * w) / 2, y + (Math.sin(lo) * h) / 2);
|
|
85
|
+
$.ctx.closePath();
|
|
86
|
+
} else if (mode == $.PIE) {
|
|
87
|
+
$.ctx.lineTo(x, y);
|
|
88
|
+
$.ctx.closePath();
|
|
89
|
+
}
|
|
80
90
|
} else {
|
|
81
91
|
for (let i = 0; i < detail + 1; i++) {
|
|
82
92
|
let t = i / detail;
|
|
@@ -85,7 +95,10 @@ Q5.renderers.q2d.drawing = ($) => {
|
|
|
85
95
|
let dy = ($.sin(a) * h) / 2;
|
|
86
96
|
$.ctx[i ? 'lineTo' : 'moveTo'](x + dx, y + dy);
|
|
87
97
|
}
|
|
98
|
+
|
|
88
99
|
if (mode == $.CHORD) {
|
|
100
|
+
$.ctx.lineTo(x + ($.cos(hi) * w) / 2, y + ($.sin(hi) * h) / 2);
|
|
101
|
+
$.ctx.lineTo(x + ($.cos(lo) * w) / 2, y + ($.sin(lo) * h) / 2);
|
|
89
102
|
$.ctx.closePath();
|
|
90
103
|
} else if (mode == $.PIE) {
|
|
91
104
|
$.ctx.lineTo(x, y);
|
|
@@ -144,6 +157,7 @@ Q5.renderers.q2d.drawing = ($) => {
|
|
|
144
157
|
ink();
|
|
145
158
|
} else $.ellipse(x, y, d, d);
|
|
146
159
|
};
|
|
160
|
+
|
|
147
161
|
$.point = (x, y) => {
|
|
148
162
|
if ($._doStroke) {
|
|
149
163
|
if (x.x) {
|
|
@@ -160,6 +174,7 @@ Q5.renderers.q2d.drawing = ($) => {
|
|
|
160
174
|
$.ctx.stroke();
|
|
161
175
|
}
|
|
162
176
|
};
|
|
177
|
+
|
|
163
178
|
function rect(x, y, w, h) {
|
|
164
179
|
if ($._da) {
|
|
165
180
|
x *= $._da;
|
package/src/q5-canvas.js
CHANGED
|
@@ -139,8 +139,8 @@ Q5.modules.canvas = ($, q) => {
|
|
|
139
139
|
opt.alpha ??= true;
|
|
140
140
|
opt.colorSpace ??= $.canvas.colorSpace;
|
|
141
141
|
g.createCanvas.call($, w, h, opt);
|
|
142
|
-
g.defaultWidth = w
|
|
143
|
-
g.defaultHeight = h
|
|
142
|
+
g.defaultWidth = w;
|
|
143
|
+
g.defaultHeight = h;
|
|
144
144
|
return g;
|
|
145
145
|
};
|
|
146
146
|
|
|
@@ -287,6 +287,8 @@ Q5.modules.canvas = ($, q) => {
|
|
|
287
287
|
};
|
|
288
288
|
|
|
289
289
|
$._styleNames = [
|
|
290
|
+
'_fill',
|
|
291
|
+
'_stroke',
|
|
290
292
|
'_doStroke',
|
|
291
293
|
'_doFill',
|
|
292
294
|
'_strokeSet',
|
package/src/q5-webgpu-canvas.js
CHANGED
|
@@ -147,18 +147,18 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
147
147
|
colorIndex++;
|
|
148
148
|
};
|
|
149
149
|
|
|
150
|
-
$.
|
|
150
|
+
$._fill = $._stroke = 0;
|
|
151
151
|
$._doFill = $._doStroke = true;
|
|
152
152
|
|
|
153
153
|
$.fill = (r, g, b, a) => {
|
|
154
154
|
addColor(r, g, b, a);
|
|
155
155
|
$._doFill = $._fillSet = true;
|
|
156
|
-
$.
|
|
156
|
+
$._fill = colorIndex;
|
|
157
157
|
};
|
|
158
158
|
$.stroke = (r, g, b, a) => {
|
|
159
159
|
addColor(r, g, b, a);
|
|
160
160
|
$._doStroke = $._strokeSet = true;
|
|
161
|
-
$.
|
|
161
|
+
$._stroke = colorIndex;
|
|
162
162
|
};
|
|
163
163
|
|
|
164
164
|
$.noFill = () => ($._doFill = false);
|
package/src/q5-webgpu-drawing.js
CHANGED
|
@@ -126,6 +126,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
126
126
|
};
|
|
127
127
|
|
|
128
128
|
const addEllipse = (x, y, a, b, n, ci, ti) => {
|
|
129
|
+
y = -y;
|
|
129
130
|
let t = 0,
|
|
130
131
|
angleIncrement = $.TAU / n;
|
|
131
132
|
|
|
@@ -178,7 +179,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
178
179
|
ti = $._transformIndex;
|
|
179
180
|
|
|
180
181
|
if ($._doStroke) {
|
|
181
|
-
ci = $.
|
|
182
|
+
ci = $._stroke;
|
|
182
183
|
|
|
183
184
|
// stroke weight adjustment
|
|
184
185
|
let sw = $._strokeWeight / 2;
|
|
@@ -217,7 +218,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
217
218
|
}
|
|
218
219
|
|
|
219
220
|
if ($._doFill) {
|
|
220
|
-
ci = colorIndex ?? $.
|
|
221
|
+
ci = colorIndex ?? $._fill;
|
|
221
222
|
addRect(l, t, r, t, r, b, l, b, ci, ti);
|
|
222
223
|
}
|
|
223
224
|
};
|
|
@@ -266,19 +267,19 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
266
267
|
let ti = $._transformIndex;
|
|
267
268
|
if ($._doStroke) {
|
|
268
269
|
let sw = $._strokeWeight / 2;
|
|
269
|
-
addEllipse(x, y, a + sw, b + sw, n, $.
|
|
270
|
+
addEllipse(x, y, a + sw, b + sw, n, $._stroke, ti);
|
|
270
271
|
a -= sw;
|
|
271
272
|
b -= sw;
|
|
272
273
|
}
|
|
273
274
|
if ($._doFill) {
|
|
274
|
-
addEllipse(x, y, a, b, n, colorIndex ?? $.
|
|
275
|
+
addEllipse(x, y, a, b, n, colorIndex ?? $._fill, ti);
|
|
275
276
|
}
|
|
276
277
|
};
|
|
277
278
|
|
|
278
279
|
$.circle = (x, y, d) => $.ellipse(x, y, d, d);
|
|
279
280
|
|
|
280
281
|
$.point = (x, y) => {
|
|
281
|
-
colorIndex = $.
|
|
282
|
+
colorIndex = $._stroke;
|
|
282
283
|
$._doStroke = false;
|
|
283
284
|
let sw = $._strokeWeight;
|
|
284
285
|
if (sw < 2) {
|
|
@@ -290,7 +291,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
290
291
|
};
|
|
291
292
|
|
|
292
293
|
$.line = (x1, y1, x2, y2) => {
|
|
293
|
-
colorIndex = $.
|
|
294
|
+
colorIndex = $._stroke;
|
|
294
295
|
|
|
295
296
|
$.push();
|
|
296
297
|
$._doStroke = false;
|
|
@@ -324,7 +325,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
324
325
|
|
|
325
326
|
$.vertex = (x, y) => {
|
|
326
327
|
if ($._matrixDirty) $._saveMatrix();
|
|
327
|
-
sv.push(x, -y, $.
|
|
328
|
+
sv.push(x, -y, $._fill, $._transformIndex);
|
|
328
329
|
shapeVertCount++;
|
|
329
330
|
};
|
|
330
331
|
|
|
@@ -417,7 +418,7 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
|
|
|
417
418
|
$._rectMode = og;
|
|
418
419
|
}
|
|
419
420
|
$.pop();
|
|
420
|
-
if (!$._fillSet) $.
|
|
421
|
+
if (!$._fillSet) $._fill = 1;
|
|
421
422
|
};
|
|
422
423
|
|
|
423
424
|
$._hooks.preRender.push(() => {
|
package/src/q5-webgpu-text.js
CHANGED
|
@@ -464,8 +464,8 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
|
|
|
464
464
|
text[1] = -y;
|
|
465
465
|
text[2] = $._textSize / 44;
|
|
466
466
|
text[3] = $._transformIndex;
|
|
467
|
-
text[4] = $._fillSet ? $.
|
|
468
|
-
text[5] = $.
|
|
467
|
+
text[4] = $._fillSet ? $._fill : 0;
|
|
468
|
+
text[5] = $._stroke;
|
|
469
469
|
|
|
470
470
|
$._textStack.push(text);
|
|
471
471
|
$.drawStack.push(2, measurements.printedCharCount, $._font.index);
|
|
@@ -480,11 +480,11 @@ fn fragmentMain(input : VertexOutput) -> @location(0) vec4f {
|
|
|
480
480
|
g.textSize($._textSize);
|
|
481
481
|
|
|
482
482
|
if ($._doFill) {
|
|
483
|
-
let fi = $.
|
|
483
|
+
let fi = $._fill * 4;
|
|
484
484
|
g.fill(colorStack.slice(fi, fi + 4));
|
|
485
485
|
}
|
|
486
486
|
if ($._doStroke) {
|
|
487
|
-
let si = $.
|
|
487
|
+
let si = $._stroke * 4;
|
|
488
488
|
g.stroke(colorStack.slice(si, si + 4));
|
|
489
489
|
}
|
|
490
490
|
|
package/src/readme.md
CHANGED
|
@@ -137,7 +137,7 @@ WebGPU has different default settings compared to q5's q2d renderer and p5's P2D
|
|
|
137
137
|
- The origin of the canvas (0, 0) is in the center, not the top left.
|
|
138
138
|
- Mouse and touch coordinates correspond to canvas pixels (unlike in p5 WEBGL mode).
|
|
139
139
|
|
|
140
|
-
The sketches you create with the q5-webgpu renderer will still display
|
|
140
|
+
The sketches you create with the q5-webgpu renderer will still display if WebGPU is not supported on a viewer's browser. q5 will put a warning in the console and apply a compatibility layer to display sketches with the fallback q2d renderer.
|
|
141
141
|
|
|
142
142
|
## webgpu-drawing
|
|
143
143
|
|