q5 3.8.0 → 3.8.1
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/deno.json +1 -1
- package/package.json +1 -1
- package/q5.js +5 -4
- package/q5.min.js +1 -1
package/deno.json
CHANGED
package/package.json
CHANGED
package/q5.js
CHANGED
|
@@ -912,6 +912,7 @@ Q5.renderers.c2d.canvas = ($, q) => {
|
|
|
912
912
|
|
|
913
913
|
$.strokeWeight = (n) => {
|
|
914
914
|
if (!n) $._doStroke = false;
|
|
915
|
+
else $._doStroke = true;
|
|
915
916
|
$.ctx.lineWidth = $._strokeWeight = n || 0.0001;
|
|
916
917
|
};
|
|
917
918
|
|
|
@@ -5575,10 +5576,10 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5575
5576
|
|
|
5576
5577
|
$.strokeWeight = (v) => {
|
|
5577
5578
|
if (v === undefined) return sw;
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5579
|
+
|
|
5580
|
+
if (!v) return (doStroke = false);
|
|
5581
|
+
else doStroke = true;
|
|
5582
|
+
|
|
5582
5583
|
v = Math.abs(v);
|
|
5583
5584
|
sw = v;
|
|
5584
5585
|
hsw = v / 2;
|
package/q5.min.js
CHANGED
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
* @license LGPL-3.0
|
|
7
7
|
* @class Q5
|
|
8
8
|
*/
|
|
9
|
-
function Q5(e,t,r){let n,a=this;a._isQ5=a._q5=!0,a._parent=t,a.ready=new Promise((e=>{n=e})),"webgpu-fallback"==r?(a._renderer="c2d",a._webgpu=a._webgpuFallback=!0):(a._renderer=r||"c2d",a["_"+a._renderer]=!0);let i,o="auto"==e;if(e??="global","auto"==e){if(!(window.setup||window.update||Q5.update||window.draw||Q5.draw))return;e="global"}"global"==e&&(Q5._hasGlobal=a._isGlobal=!0,i=Q5._esm?globalThis:Q5._server?global:window),"graphics"==e&&(a._isGraphics=!0),"image"==e&&(a._isImage=!0);let s=new Proxy(a,{set:(e,t,r)=>(a[t]=r,a._isGlobal&&(i[t]=r),!0)});a.canvas=a.ctx=a.drawingContext=null,a.pixels=[];let l=null,d=!0;async function c(e){for(let t of Q5.hooks[e])await t.call(a,s)}a.frameCount=0,a.deltaTime=16,a._targetFrameRate=0,a._targetFrameDuration=16.666666666666668,a._frameRate=a._fps=60,a._loop=!0;let u=0;a.millis=()=>performance.now()-u,a.noCanvas=()=>{a.canvas?.remove&&a.canvas.remove(),a.canvas=0,s.ctx=s.drawingContext=0},window&&(a.windowWidth=window.innerWidth,a.windowHeight=window.innerHeight,a.deviceOrientation=window.screen?.orientation?.type),a._loaders=[],a.loadAll=()=>{let e=[...a._loaders];return a._loaders=[],a._g&&(e=e.concat(a._g._loaders),a._g._loaders=[]),Promise.all(e)},a.isPreloadSupported=()=>!0,a.disablePreload=()=>a._disablePreload=!0;const h=[];async function f(e){let t=e||performance.now();if(a._didResize&&(a.windowResized(),a._didResize=!1),a._loop)if(d)l=g(f);else{let e=t+a._targetFrameDuration,r=e-performance.now();for(;r<0;)r+=a._targetFrameDuration;l=setTimeout((()=>f(e)),r)}else if(a.frameCount&&!a._redraw)return;if(a.frameCount&&d&&!a._redraw){if(t-a._lastFrameTime<a._targetFrameDuration-4)return}s.deltaTime=t-a._lastFrameTime,a._frameRate=1e3/a.deltaTime,s.frameCount++;let r=performance.now();a.resetMatrix(),a._beginRender&&a._beginRender(),await c("predraw");try{await a.draw()}catch(e){throw Q5.errorTolerant||a.noLoop(),a._fes&&a._fes(e),e}await c("postdraw"),await a.postProcess(),a._render&&a._render(),a._finishRender&&a._finishRender(),s.pmouseX=a.mouseX,s.pmouseY=a.mouseY,s.moveX=s.moveY=0,a._lastFrameTime=t;let n=performance.now();a._fps=Math.round(1e3/(n-r))}a._incrementPreload=()=>{a._loaders.push(new Promise((e=>h.push(e))))},a._decrementPreload=()=>{h.length&&h.pop()()},a.noLoop=()=>{a._loop=!1,null!=l&&(d&&window.cancelAnimationFrame?cancelAnimationFrame(l):clearTimeout(l)),l=null},a.loop=()=>{a._loop=!0,a._setupDone&&null==l&&f()},a.isLooping=()=>a._loop,a.redraw=async(e=1)=>{a._redraw=!0;for(let t=0;t<e;t++)await f();a._redraw=!1},a.remove=async()=>{a.noLoop(),a.canvas.remove(),await c("remove")},a.frameRate=e=>(e&&e!=a._targetFrameRate&&(a._targetFrameRate=e,a._targetFrameDuration=1e3/e,a._loop&&null!=l&&(d&&window.cancelAnimationFrame?cancelAnimationFrame(l):clearTimeout(l),l=null),d=e<=60,a._setupDone&&(l=d?g(f):setTimeout((()=>f()),a._targetFrameDuration))),a._frameRate),a.getTargetFrameRate=()=>a._targetFrameRate||60,a.getFPS=()=>a._fps,a.Element=function(e){this.elt=e},a._elements=[],a.describe=()=>{},a.log=a.print=console.log;for(let e in Q5.modules)Q5.modules[e](a,s);let p=Q5.renderers[a._renderer];for(let e in p)p[e](a,s);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(a[e]=Q5[e]);if(a._isGraphics)return;if(a._isGlobal){let e=Object.assign({},a);delete e.Color,Object.assign(Q5,e),delete Q5.Q5}for(let e of Q5.hooks.init)e.call(a,s);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof a[e]&&(a[e]=t.bind(a));for(let[e,t]of Object.entries(Q5.preloadMethods))a[e]=function(){return a._incrementPreload(),t.apply(a,arguments)};if(a._isGlobal){let e=Object.getOwnPropertyNames(a);for(let t of e)"_"!=t[0]&&(i[t]=a[t]);for(let e of["_incrementPreload","_decrementPreload"])i[e]=a[e]}"function"==typeof e&&e(a),Q5._instanceCount++;let g=window.requestAnimationFrame||function(e){const t=a._lastFrameTime+a._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},m=i||a,x=Q5._userFns.slice(0,15);for(let e of x)a[e]??=()=>{};if(a._isGlobal){let e=Q5._userFns.slice(0,19);for(let t of e)Q5[t]?a[t]=Q5[t]:Object.defineProperty(Q5,t,{get:()=>a[t],set:e=>a[t]=e})}function _(e){const t=m[e]||a[e];a[e]=e=>{try{return t(e)}catch(e){throw a._fes&&a._fes(e),e}}}async function v(){await c("presetup"),n(),(m.preload||a.preload)&&(_("preload"),a.preload()),await Promise.race([new Promise((e=>{!function t(){a.setup||a.update||a.draw||m.setup||m.update||m.draw?e():a._setupDone||(a.canvas?.ready&&a._render&&(a._beginRender(),a._render(),a._finishRender()),g(t))}()})),new Promise((e=>{setTimeout((()=>{a._loaders.length||e()}),500)}))]),a._disablePreload||await a.loadAll(),a.setup??=m.setup||(()=>{}),_("setup");for(let e of x)_(e);a.draw??=m.draw||(()=>{}),u=performance.now(),await a.setup(),a._setupDone=!0,null===a.ctx&&a.createCanvas(200,200),await c("postsetup"),a.frameCount||(a._lastFrameTime=performance.now()-15,g(f))}Q5.instances.push(a),o||Q5._esm?v():setTimeout(v,32)}function createCanvas(e,t,r){if(Q5._hasGlobal)return;if("c2d"==e||"c2d"==t||"c2d"==r||"c2d"==r?.renderer||!Q5._esm){let n=new Q5,a=n.createCanvas(e,t,r);return n.ready.then((()=>a))}return Q5.WebGPU().then((n=>n.createCanvas(e,t,r)))}Q5.renderers={},Q5.modules={},Q5._server="object"==typeof process,Q5._esm=void 0===this,Q5._instanceCount=0,Q5.instances=[],Q5._friendlyError=(e,t)=>{Q5.disableFriendlyErrors||console.error(t+": "+e)},Q5._validateParameters=()=>!0,Q5._userFns=["postProcess","mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","doubleClicked","mouseWheel","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized","preload","setup","update","draw"],Q5.hooks={init:[],presetup:[],postsetup:[],predraw:[],postdraw:[],remove:[]},Q5.addHook=(e,t)=>Q5.hooks[e].push(t),Q5.registerAddon=e=>{let t={};e(Q5,Q5.prototype,t);for(let e in t)Q5.hooks[e].push(t[e])},Q5.prototype.registerMethod=(e,t)=>{("beforeSetup"==e||e.includes("Preload"))&&(e="presetup"),"afterSetup"==e&&(e="postsetup"),"pre"==e&&(e="predraw"),"post"==e&&(e="postdraw"),Q5.hooks[e].push(t)},Q5.preloadMethods={},Q5.prototype.registerPreloadMethod=(e,t)=>Q5.preloadMethods[e]=t[e],Q5._server&&(global.q5=global.Q5=Q5,global.p5??=Q5),"object"==typeof window?(window.q5=window.Q5=Q5,window.p5??=Q5,window.createCanvas=createCanvas,window.C2D="c2d",window.WEBGPU="webgpu"):global.window=0,Q5.version=Q5.VERSION="3.8","object"==typeof document&&document.addEventListener("DOMContentLoaded",(()=>{Q5._hasGlobal||(Q5.update||Q5.draw?Q5.WebGPU():new Q5("auto"))})),Q5.modules.canvas=(e,t)=>{e._Canvas=window.OffscreenCanvas||function(){return document.createElement("canvas")},Q5._server?Q5._createServerCanvas&&(t.canvas=Q5._createServerCanvas(200,200)):(e._isImage||e._isGraphics)&&(t.canvas=new e._Canvas(200,200)),e.canvas||("object"==typeof document?(t.canvas=document.createElement("canvas"),e.canvas.id="q5Canvas"+Q5._instanceCount,e.canvas.classList.add("q5Canvas")):e.noCanvas()),e.displayDensity=()=>window.devicePixelRatio||1,e.width=200,e.height=200,e._pixelDensity=1;let r=e.canvas;if(r&&(r.width=200,r.height=200,r.colorSpace=Q5.canvasOptions.colorSpace,e._isImage||(r.renderer=e._renderer,r[e._renderer]=!0,e._pixelDensity=Math.ceil(e.displayDensity()))),e._adjustDisplay=e=>{let t=r.style;t&&e&&(t.width=r.w+"px",t.height=r.h+"px")},e.createCanvas=function(t,a,i){(isNaN(t)||"string"==typeof t&&!t.includes(":"))&&(i=t,t=null),"number"!=typeof a&&(i=a,a=null),i??=arguments[3],"string"==typeof i&&(i={renderer:i});let o=Object.assign({},Q5.canvasOptions);if("object"==typeof i&&Object.assign(o,i),!e._isImage)if(e._isGraphics)e._pixelDensity=this._pixelDensity;else if(Q5._server)r.visible=!0;else{let t=r,a=document.body||document.documentElement;for(;t&&t.parentElement!=a;)t=t.parentElement;if(t||(document.getElementById(r.id)?.remove(),n()),window.IntersectionObserver){let t=!1;new IntersectionObserver((n=>{if(n[0].isIntersecting)r.visible=!0;else{let e=r.getBoundingClientRect();r.visible=e.top<window.innerHeight&&e.bottom>0&&e.left<window.innerWidth&&e.right>0}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 s=e._createCanvas(r.w,r.h,o);return e._addEventMethods&&e._addEventMethods(r),e.canvas.ready=!0,s},e.createGraphics=function(t,r,n={}){"string"==typeof n&&(n={renderer:n});let a=new Q5("graphics",void 0,n.renderer||(e._webgpuFallback?"webgpu-fallback":e._renderer));n.alpha??=!0,n.colorSpace??=e.canvas.colorSpace,n.pixelDensity??=e._pixelDensity,a._defaultImageScale=e._defaultImageScale,a.createCanvas.call(e,t,r,n);let i=a._pixelDensity*e._defaultImageScale;return a.defaultWidth=t*i,a.defaultHeight=r*i,a},e._setCanvasSize=(n,a)=>{a??=n??window.innerHeight,n??=window.innerWidth,r.w=n=Math.ceil(n),r.h=a=Math.ceil(a),r.width=Math.ceil(n*e._pixelDensity),r.height=Math.ceil(a*e._pixelDensity),t.width=n,t.height=a,t.halfWidth=r.hw=n/2,t.halfHeight=r.hh=a/2;let i=Q5._libMap;i.width&&(t[i.width]=n,t[i.height]=a,t[i.halfWidth]=t.halfWidth,t[i.halfHeight]=t.halfHeight),e.displayMode&&!r.displayMode?e.displayMode():e._adjustDisplay(!0)},e._setImageSize=(n,a)=>{t.width=r.w=n,t.height=r.h=a,t.halfWidth=r.hw=n/2,t.halfHeight=r.hh=a/2,r.width=Math.ceil(n*e._pixelDensity),r.height=Math.ceil(a*e._pixelDensity)},e.defaultImageScale=t=>t?(e._g&&(e._g._defaultImageScale=t),e._defaultImageScale=t):e._defaultImageScale,e.defaultImageScale(.5),!e._isImage){if(r&&!e._isGraphics){function n(){let t=e._parent;if(t??=document.getElementsByTagName("main")[0],!t){t=document.createElement("main"),(document.body||document.documentElement).appendChild(t)}r.parent(t),document.body||document.addEventListener("DOMContentLoaded",(()=>{document.body&&document.body.appendChild(t)}))}r.parent=t=>{function n(){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(n),e._ro.observe(t)):e.frameCount||window.addEventListener("resize",n)},n()}e.resizeCanvas=(t,n)=>{if(!e.ctx)return e.createCanvas(t,n);t==r.w&&n==r.h||e._resizeCanvas(t,n)},r&&!Q5._createServerCanvas&&(r.resize=e.resizeCanvas),e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._resizeCanvas(r.w,r.h),e._g&&e._g.pixelDensity(t),t):e._pixelDensity,window&&!e._isGraphics&&window.addEventListener("resize",(()=>{e._didResize=!0,t.windowWidth=window.innerWidth,t.windowHeight=window.innerHeight,t.deviceOrientation=window.screen?.orientation?.type}))}},Q5.CENTER="center",Q5.LEFT="left",Q5.RIGHT="right",Q5.TOP="top",Q5.BOTTOM="bottom",Q5.BASELINE="alphabetic",Q5.MIDDLE="middle",Q5.NORMAL="normal",Q5.ITALIC="italic",Q5.BOLD="bold",Q5.BOLDITALIC="italic bold",Q5.ROUND="round",Q5.SQUARE="butt",Q5.PROJECT="square",Q5.MITER="miter",Q5.BEVEL="bevel",Q5.NONE="none",Q5.SIMPLE="simple",Q5.CHORD_OPEN=0,Q5.PIE_OPEN=1,Q5.PIE=2,Q5.CHORD=3,Q5.RADIUS="radius",Q5.CORNER="corner",Q5.CORNERS="corners",Q5.OPEN=0,Q5.CLOSE=1,Q5.VIDEO="video",Q5.AUDIO="audio",Q5.LANDSCAPE="landscape",Q5.PORTRAIT="portrait",Q5.BLEND="source-over",Q5.REMOVE="destination-out",Q5.ADD="lighter",Q5.DARKEST="darken",Q5.LIGHTEST="lighten",Q5.DIFFERENCE="difference",Q5.SUBTRACT="subtract",Q5.EXCLUSION="exclusion",Q5.MULTIPLY="multiply",Q5.SCREEN="screen",Q5.REPLACE="copy",Q5.OVERLAY="overlay",Q5.HARD_LIGHT="hard-light",Q5.SOFT_LIGHT="soft-light",Q5.DODGE="color-dodge",Q5.BURN="color-burn",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.SEPIA=9,Q5.BRIGHTNESS=10,Q5.SATURATION=11,Q5.CONTRAST=12,Q5.HUE_ROTATE=13,Q5.C2D=Q5.P2D=Q5.P2DHDR="c2d",Q5.WEBGL="webgl",Q5.GPU=Q5.WEBGPU="webgpu",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.c2d={},Q5.renderers.c2d.canvas=(e,t)=>{let r=e.canvas;function n(){let t=e._styles.pop();for(let r of e._styleNames)e[r]=t[r]}e.colorMode&&e.colorMode("rgb",e._webgpu?1:255),e._createCanvas=function(n,a,i){if(r)return t.ctx=t.drawingContext=r.getContext("2d",i),e._isImage||(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._strokeWeight=1),e.ctx.scale(e._pixelDensity,e._pixelDensity),e.ctx.save(),r;console.error("q5 canvas could not be created. skia-canvas and jsdom packages not found.")},e.clear=()=>{e.ctx.save(),e.ctx.resetTransform(),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.restore()},e._isImage||(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._isColor&&(t=e.color(...arguments)),e.ctx.fillStyle=t.toString(),e.ctx.fillRect(0,0,e.canvas.width,e.canvas.height)),e.ctx.restore()},e._resizeCanvas=(t,n)=>{let a,i={};for(let t in e.ctx)"function"!=typeof e.ctx[t]&&(i[t]=e.ctx[t]);if(delete i.canvas,e.frameCount>1){a=new e._Canvas(r.width,r.height),a.w=r.w,a.h=r.h,a.getContext("2d").drawImage(r,0,0)}e._setCanvasSize(t,n);for(let t in i)e.ctx[t]=i[t];e.scale(e._pixelDensity),a&&e.ctx.drawImage(a,0,0,a.w,a.h)},e.fill=function(t){if(e._doFill=e._fillSet=!0,Q5.Color&&(t._isColor||"string"==typeof t&&!e._namedColors[t]||(t=e.color(...arguments)),t.a<=0))return e._doFill=!1;e.ctx.fillStyle=e._fill=t.toString()},e.stroke=function(t){if(e._doStroke=e._strokeSet=!0,Q5.Color&&(t._isColor||"string"==typeof t&&!e._namedColors[t]||(t=e.color(...arguments)),t.a<=0))return e._doStroke=!1;e.ctx.strokeStyle=e._stroke=t.toString()},e.strokeWeight=t=>{t||(e._doStroke=!1),e.ctx.lineWidth=e._strokeWeight=t||1e-4},e.noFill=()=>e._doFill=!1,e.noStroke=()=>e._doStroke=!1,e.opacity=t=>e.ctx.globalAlpha=t,e._getFillIdx=()=>e._fill,e._setFillIdx=t=>e._fill=t,e._getStrokeIdx=()=>e._stroke,e._setStrokeIdx=t=>e._stroke=t,e._doShadow=!1,e._shadowOffsetX=e._shadowOffsetY=e._shadowBlur=10,e.shadow=function(t){if(Q5.Color&&(t._isColor||"string"==typeof t&&!e._namedColors[t]||(t=e.color(...arguments)),t.a<=0))return e._doShadow=!1;e.ctx.shadowColor=e._shadow=t.toString(),e._doShadow=!0,e.ctx.shadowOffsetX||=e._shadowOffsetX,e.ctx.shadowOffsetY||=e._shadowOffsetY,e.ctx.shadowBlur||=e._shadowBlur},e.shadowBox=(t,r,n)=>{e.ctx.shadowOffsetX=e._shadowOffsetX=t,e.ctx.shadowOffsetY=e._shadowOffsetY=r||t,e.ctx.shadowBlur=e._shadowBlur=n||0},e.noShadow=()=>{e._doShadow=!1,e.ctx.shadowOffsetX=e.ctx.shadowOffsetY=e.ctx.shadowBlur=0},e.translate=(t,r)=>{t.x&&(r=t.y,t=t.x),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,n,a,i,o)=>e.ctx.transform(t,r,n,a,i,o),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._webgpu&&e.translate(e.halfWidth,e.halfHeight))},e._styleNames=["_fill","_stroke","_strokeWeight","_doFill","_doStroke","_fillSet","_strokeSet","_shadow","_doShadow","_shadowOffsetX","_shadowOffsetY","_shadowBlur","_tint","_textSize","_textAlign","_textBaseline","_imageMode","_rectMode","_ellipseMode","_colorMode","_colorFormat","Color"],e._styles=[],e.pushStyles=()=>{let t={};for(let r of e._styleNames)t[r]=e[r];e._styles.push(t),e._fontMod&&e._updateFont()},e.popStyles=()=>{n(),e.ctx.fillStyle=e._fill,e.ctx.strokeStyle=e._stroke,e.ctx.lineWidth=e._strokeWeight,e.ctx.shadowColor=e._shadow,e.ctx.shadowOffsetX=e._doShadow?e._shadowOffsetX:0,e.ctx.shadowOffsetY=e._doShadow?e._shadowOffsetY:0,e.ctx.shadowBlur=e._doShadow?e._shadowBlur:0},e.pushMatrix=()=>e.ctx.save(),e.popMatrix=()=>e.ctx.restore(),e.push=()=>{e.pushStyles(),e.ctx.save()},e.pop=()=>{e.ctx.restore(),n()})},Q5.renderers.c2d.shapes=e=>{e._doStroke=!0,e._doFill=!0,e._strokeSet=!1,e._fillSet=!1,e._ellipseMode=Q5.CENTER,e._rectMode=Q5.CORNER;let t=!0,r=[];function n(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}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=()=>{},e.line=(t,r,n,a)=>{e._doStroke&&(e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(n,a),e.ctx.stroke())};const a=2*Math.PI;function i(t,r,n,i,o,s,l){if(e._angleMode&&(o=e.radians(o),s=e.radians(s)),(o%=a)<0&&(o+=a),(s%=a)<0&&(s+=a),o>s&&(s+=a),o==s)return e.ellipse(t,r,n,i);if(n/=2,i/=2,n=Math.abs(n),i=Math.abs(i),e._doFill||l!=e.PIE_OPEN||(l=e.CHORD_OPEN),e.ctx.beginPath(),e.ctx.ellipse(t,r,n,i,0,o,s),l!=e.PIE&&l!=e.PIE_OPEN||e.ctx.lineTo(t,r),e._doFill&&e.ctx.fill(),e._doStroke){if(l!=e.PIE&&l!=e.CHORD||e.ctx.closePath(),l!=e.PIE_OPEN)return e.ctx.stroke();e.ctx.beginPath(),e.ctx.ellipse(t,r,n,i,0,o,s),e.ctx.stroke()}}function o(t,r,i,o){e.ctx.beginPath(),e.ctx.ellipse(t,r,Math.abs(i/2),Math.abs(o/2),0,0,a),n()}function s(t,r,a,i,o,l,d,c){return void 0===o?function(t,r,a,i){e.ctx.beginPath(),e.ctx.rect(t,r,a,i),n()}(t,r,a,i):void 0===l?s(t,r,a,i,o,o,o,o):(e.ctx.beginPath(),e.ctx.roundRect(t,r,a,i,[o,l,d,c]),void n())}e.arc=(t,r,n,a,o,s,l)=>{if(o==s)return e.ellipse(t,r,n,a);l??=e.PIE_OPEN,e._ellipseMode==e.CENTER?i(t,r,n,a,o,s,l):e._ellipseMode==e.RADIUS?i(t,r,2*n,2*a,o,s,l):e._ellipseMode==e.CORNER?i(t+n/2,r+a/2,n,a,o,s,l):e._ellipseMode==e.CORNERS&&i((t+n)/2,(r+a)/2,n-t,a-r,o,s,l)},e.ellipse=(t,r,n,a)=>{a??=n,e._ellipseMode==e.CENTER?o(t,r,n,a):e._ellipseMode==e.RADIUS?o(t,r,2*n,2*a):e._ellipseMode==e.CORNER?o(t+n/2,r+a/2,n,a):e._ellipseMode==e.CORNERS&&o((t+n)/2,(r+a)/2,n-t,a-r)},e.circle=(t,r,i)=>{e._ellipseMode==e.CENTER?(e.ctx.beginPath(),e.ctx.arc(t,r,Math.abs(i/2),0,a),n()):e.ellipse(t,r,i,i)},e.point=(t,r)=>{e._doStroke&&(t.x&&(r=t.y,t=t.x),e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(t,r),e.ctx.stroke())},e.rect=(t,r,n,a=n,i,o,l,d)=>{e._rectMode==e.CENTER?s(t-n/2,r-a/2,n,a,i,o,l,d):e._rectMode==e.RADIUS?s(t-n,r-a,2*n,2*a,i,o,l,d):e._rectMode==e.CORNER?s(t,r,n,a,i,o,l,d):e._rectMode==e.CORNERS&&s(t,r,n-t,a-r,i,o,l,d)},e.square=(t,r,n,a,i,o,s)=>e.rect(t,r,n,n,a,i,o,s),e.capsule=(t,r,a,i,o)=>{const s=a-t,l=i-r,d=Math.hypot(s,l);if(0===d)return e.circle(t,r,2*o);const c=Math.atan2(l,s),u=-l/d*o,h=s/d*o;e.ctx.beginPath(),e.ctx.moveTo(t-u,r-h),e.ctx.arc(t,r,o,c-e.HALF_PI,c+e.HALF_PI,!0),e.ctx.lineTo(a+u,i+h),e.ctx.arc(a,i,o,c+e.HALF_PI,c-e.HALF_PI,!0),e.ctx.closePath(),n()},e.beginShape=()=>{r=[],e.ctx.beginPath(),t=!0},e.beginContour=()=>{e.ctx.closePath(),r=[],t=!0},e.endContour=()=>{r=[],t=!0},e.vertex=(n,a)=>{r=[],t?e.ctx.moveTo(n,a):e.ctx.lineTo(n,a),t=!1},e.bezierVertex=(t,n,a,i,o,s)=>{r=[],e.ctx.bezierCurveTo(t,n,a,i,o,s)},e.quadraticVertex=(t,n,a,i)=>{r=[],e.ctx.quadraticCurveTo(t,n,a,i)},e.bezier=(t,r,n,a,i,o,s,l)=>{e.beginShape(),e.vertex(t,r),e.bezierVertex(n,a,i,o,s,l),e.endShape()},e.triangle=(t,r,n,a,i,o)=>{e.beginShape(),e.vertex(t,r),e.vertex(n,a),e.vertex(i,o),e.endShape(e.CLOSE)},e.quad=(t,r,n,a,i,o,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(n,a),e.vertex(i,o),e.vertex(s,l),e.endShape(e.CLOSE)},e.endShape=t=>{r=[],t&&e.ctx.closePath(),n()},e.curveVertex=(n,a)=>{if(r.push([n,a]),r.length<4)return;let i=r.at(-4),o=r.at(-3),s=r.at(-2),l=r.at(-1),d=o[0]+(s[0]-i[0])/6,c=o[1]+(s[1]-i[1])/6,u=s[0]-(l[0]-o[0])/6,h=s[1]-(l[1]-o[1])/6;t&&(e.ctx.moveTo(o[0],o[1]),t=!1),e.ctx.bezierCurveTo(d,c,u,h,s[0],s[1])},e.curve=(t,r,n,a,i,o,s,l)=>{e.beginShape(),e.curveVertex(t,r),e.curveVertex(n,a),e.curveVertex(i,o),e.curveVertex(s,l),e.endShape()},e.curvePoint=(e,t,r,n,a)=>{const i=a*a*a,o=a*a;return e*(-.5*i+o-.5*a)+t*(1.5*i-2.5*o+1)+r*(-1.5*i+2*o+.5*a)+n*(.5*i-.5*o)},e.bezierPoint=(e,t,r,n,a)=>{const i=1-a;return Math.pow(i,3)*e+3*Math.pow(i,2)*a*t+3*i*Math.pow(a,2)*r+Math.pow(a,3)*n},e.curveTangent=(e,t,r,n,a)=>{const i=a*a;return e*(-3*i/2+2*a-.5)+t*(9*i/2-5*a)+r*(-9*i/2+4*a+.5)+n*(3*i/2-a)},e.bezierTangent=(e,t,r,n,a)=>{const i=1-a;return 3*n*Math.pow(a,2)-3*r*Math.pow(a,2)+6*r*i*a-6*t*i*a+3*t*Math.pow(i,2)-3*e*Math.pow(i,2)},e.erase=function(t,r){255==e._colorFormat&&(t&&(t/=255),r&&(r/=255)),e.ctx.save(),e.ctx.globalCompositeOperation="destination-out",e.ctx.fillStyle=`rgb(0 0 0 / ${t||1})`,e.ctx.strokeStyle=`rgb(0 0 0 / ${r||1})`},e.noErase=function(){e.ctx.globalCompositeOperation="source-over",e.ctx.restore()},e.inFill=(t,r)=>{const n=e._pixelDensity;return e.ctx.isPointInPath(t*n,r*n)},e.inStroke=(t,r)=>{const n=e._pixelDensity;return e.ctx.isPointInStroke(t*n,r*n)}},Q5.renderers.c2d.image=(e,t)=>{const r=e.canvas;r&&(r.convertToBlob??=e=>new Promise((t=>{r.toBlob((e=>t(e)),e.type,e.quality)}))),e._tint=null;let n=null,a=null;e.createImage=(t,r,n={})=>(n.colorSpace??=e.canvas.colorSpace,n.defaultImageScale??=e._defaultImageScale,new Q5.Image(t,r,n)),e.loadImage=function(t,r,n){if(t.canvas)return t;if("gif"==t.slice(-3).toLowerCase())throw new Error("q5 doesn't support GIFs. Use a video or p5play animation instead. https://github.com/q5js/q5.js/issues/84");let a=[...arguments].at(-1);"object"==typeof a?(n=a,r=null):n=void 0;let i=e.createImage(1,1,n),o=i._pixelDensity,s=new window.Image;return s.crossOrigin="Anonymous",i.promise=new Promise(((t,a)=>{s.onload=()=>{delete i.then,i._usedAwait&&(i=e.createImage(1,1,n)),s._pixelDensity=o,i.defaultWidth=s.width*e._defaultImageScale,i.defaultHeight=s.height*e._defaultImageScale,i.naturalWidth=s.naturalWidth||s.width,i.naturalHeight=s.naturalHeight||s.height,i._setImageSize(Math.ceil(i.naturalWidth/o),Math.ceil(i.naturalHeight/o)),i.ctx.drawImage(s,0,0),r&&r(i),t(i)},s.onerror=a})),e._loaders.push(i.promise),i.then=(e,t)=>(i._usedAwait=!0,i.promise.then(e,t)),i.src=s.src=t,i},e._imageMode=Q5.CORNER,e.imageMode=t=>e._imageMode=t,e.image=(t,r,n,a,i,o=0,s=0,l,d)=>{if(!t)return;let c=t.canvas||t;a??=t.defaultWidth||c.width||t.videoWidth,i??=t.defaultHeight||c.height||t.videoHeight,"center"==e._imageMode&&(r-=.5*a,n-=.5*i);let u=t._pixelDensity||1;if(l?l*=u:l=c.width||c.videoWidth,d?d*=u:d=c.height||c.videoHeight,e._tint){if(t._retint||t._tint!=e._tint){t._tintImg??=e.createImage(t.w,t.h,{pixelDensity:u}),t._tintImg.width==t.width&&t._tintImg.height==t.height||t._tintImg.resize(t.w,t.h);let r=t._tintImg.ctx;r.globalCompositeOperation="copy",r.fillStyle=e._tint,r.fillRect(0,0,t.width,t.height),t?.canvas?.alpha&&(r.globalCompositeOperation="destination-in",r.drawImage(c,0,0,t.width,t.height)),r.globalCompositeOperation="multiply",r.drawImage(c,0,0,t.width,t.height),t._tint=e._tint,t._retint=!1}c=t._tintImg.canvas}t.flipped&&(e.ctx.save(),e.ctx.translate(r+a,0),e.ctx.scale(-1,1),r=0),e.ctx.drawImage(c,o*u,s*u,l,d,r,n,a,i),t.flipped&&e.ctx.restore()},e.filter=(t,n)=>{e.ctx.save();let a="";if(e.ctx.filter){if("string"==typeof t)a=t;else if(t==Q5.GRAY)a="saturate(0%)";else if(t==Q5.INVERT)a="invert(100%)";else if(t==Q5.BLUR){a=`blur(${Math.ceil(n*e._pixelDensity)||1}px)`}else if(t==Q5.THRESHOLD){n??=.5,a=`saturate(0%) brightness(${Math.floor(.5/Math.max(n,1e-5)*100)}%) contrast(1000000%)`}else if(t==Q5.SEPIA)a=`sepia(${n??1})`;else if(t==Q5.BRIGHTNESS)a=`brightness(${n??1})`;else if(t==Q5.SATURATION)a=`saturate(${n??1})`;else if(t==Q5.CONTRAST)a=`contrast(${n??1})`;else if(t==Q5.HUE_ROTATE){a=`hue-rotate(${n}${0==e._angleMode?"rad":"deg"})`}if(a&&(e.ctx.filter=a,"none"==e.ctx.filter))throw new Error(`Invalid filter format: ${t}`)}a||e._softFilter(t,n),e.ctx.globalCompositeOperation="source-over",e.ctx.drawImage(r,0,0,r.w,r.h),e.ctx.restore(),e.modified=e._retint=!0},e._isImage&&(e.resize=(t,n)=>{let a=new e._Canvas(r.width,r.height);a.getContext("2d",{colorSpace:r.colorSpace}).drawImage(r,0,0),e._setImageSize(t,n),e.defaultWidth=r.width*e._defaultImageScale,e.defaultHeight=r.height*e._defaultImageScale,e.ctx.clearRect(0,0,r.width,r.height),e.ctx.drawImage(a,0,0,r.width,r.height),e._retint=!0,e._owner?._makeDrawable&&(e._texture.destroy(),delete e._texture,e._owner._makeDrawable(e))}),e._getImageData=(t,n,a,i)=>e.ctx.getImageData(t,n,a,i,{colorSpace:r.colorSpace}),e.trim=()=>{let t=e._pixelDensity||1,n=r.width,a=r.height,i=e._getImageData(0,0,n,a).data,o=n,s=0,l=a,d=0,c=3;for(let e=0;e<a;e++)for(let t=0;t<n;t++)0!==i[c]&&(t<o&&(o=t),t>s&&(s=t),e<l&&(l=e),e>d&&(d=e)),c+=4;return l=Math.floor(l/t),d=Math.floor(d/t),o=Math.floor(o/t),s=Math.floor(s/t),e.get(o,l,s-o+1,d-l+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.modified=e._retint=!0},e.inset=(t,n,a,i,o,s,l,d)=>{let c=e._pixelDensity||1;e.ctx.drawImage(r,t*c,n*c,a*c,i*c,o,s,l,d),e.modified=e._retint=!0},e.copy=()=>{let t=e.get();for(let r in e)"function"==typeof e[r]||/(canvas|ctx|texture)/.test(r)||(t[r]=e[r]);return t},e.get=(t,n,i,o)=>{let s=e._pixelDensity||1;if(void 0!==t&&void 0===i){a||e.loadPixels();let i=Math.floor(t*s),o=4*(Math.floor(n*s)*r.width+i);return[a[o],a[o+1],a[o+2],a[o+3]]}t=Math.floor(t||0)*s,n=Math.floor(n||0)*s,i??=e.width,o??=e.height;let l=e.createImage(i,o,{pixelDensity:s});return l.ctx.drawImage(r,t,n,i*s,o*s,0,0,i,o),l.width=i,l.height=o,e._owner?._makeDrawable&&e._owner._makeDrawable(l),l},e.set=(t,n,i)=>{if(t=Math.floor(t),n=Math.floor(n),e.modified=e._retint=!0,i.canvas){let r=e._tint;return e._tint=null,e.image(i,t,n),void(e._tint=r)}a||e.loadPixels();let o=e._pixelDensity||1,s=i.r,l=i.g,d=i.b,c=i.a;1==(e._colorFormat||e._owner?._colorFormat)&&(s*=255,l*=255,d*=255,c*=255);for(let e=0;e<o;e++)for(let i=0;i<o;i++){let u=4*((n*o+e)*r.width+t*o+i);a[u]=s,a[u+1]=l,a[u+2]=d,a[u+3]=c}},e.loadPixels=()=>{n=e._getImageData(0,0,r.width,r.height),t.pixels=a=n.data},e.updatePixels=()=>{null!=n&&(e.ctx.putImageData(n,0,0),e.modified=e._retint=!0)},e.smooth=()=>e.ctx.imageSmoothingEnabled=!0,e.noSmooth=()=>e.ctx.imageSmoothingEnabled=!1,e._isImage||(e.tint=function(t){e._tint=(t._isColor?t:e.color(...arguments)).toString()},e.noTint=()=>e._tint=null)},Q5.Image=class{constructor(e,t,r={}){r.alpha??=!0,r.colorSpace??=Q5.canvasOptions.colorSpace;let n=this;n._isImage=!0,n.canvas=n.ctx=n.drawingContext=null,n.pixels=[],Q5.modules.canvas(n,n);let a=Q5.renderers.c2d;for(let e of["canvas","image","softFilters"])a[e]&&a[e](n,n);n._pixelDensity=r.pixelDensity||1,n._defaultImageScale=r.defaultImageScale||2,n.createCanvas(e,t,r);let i=n._pixelDensity*n._defaultImageScale;n.defaultWidth=e*i,n.defaultHeight=t*i,delete n.createCanvas,n._loop=!1;let o=Q5._libMap,s=["copy","filter","get","set","resize","mask","trim","inset","pixels","loadPixels","updatePixels","smooth","noSmooth"];for(let e of s)o[e]&&(n[o[e]]=n[e])}get w(){return this.width}get h(){return this.height}},Q5.renderers.c2d.softFilters=e=>{let t=null;function r(){let r=e.canvas.width*e.canvas.height*4;t&&t.length==r||(t=new Uint8ClampedArray(r))}e._softFilter=(n,a)=>{e._filters||(e._filters=[],e._filters[Q5.THRESHOLD]=(e,t)=>{void 0===t?t=127.5:t*=255;for(let r=0;r<e.length;r+=4){const n=.2126*e[r]+.7152*e[r+1]+.0722*e[r+2];e[r]=e[r+1]=e[r+2]=n>=t?255:0}},e._filters[Q5.GRAY]=e=>{for(let t=0;t<e.length;t+=4){const r=.2126*e[t]+.7152*e[t+1]+.0722*e[t+2];e[t]=e[t+1]=e[t+2]=r}},e._filters[Q5.OPAQUE]=e=>{for(let t=0;t<e.length;t+=4)e[t+3]=255},e._filters[Q5.INVERT]=e=>{for(let t=0;t<e.length;t+=4)e[t]=255-e[t],e[t+1]=255-e[t+1],e[t+2]=255-e[t+2]},e._filters[Q5.POSTERIZE]=(e,t=4)=>{let r=t-1;for(let n=0;n<e.length;n+=4)e[n]=255*(e[n]*t>>8)/r,e[n+1]=255*(e[n+1]*t>>8)/r,e[n+2]=255*(e[n+2]*t>>8)/r},e._filters[Q5.DILATE]=(n,a)=>{a??=Math.max,r(),t.set(n);let[i,o]=[e.canvas.width,e.canvas.height];for(let e=0;e<o;e++)for(let r=0;r<i;r++){let s=4*Math.max(r-1,0),l=4*Math.min(r+1,i-1),d=4*Math.max(e-1,0)*i,c=4*Math.min(e+1,o-1)*i,u=4*e*i,h=4*r;for(let e=0;e<4;e++){let r=e+d,i=e+c,o=e+u;n[u+h+e]=a(t[r+h],t[o+s],t[o+h],t[o+l],t[i+h])}}},e._filters[Q5.ERODE]=t=>{e._filters[Q5.DILATE](t,Math.min)},e._filters[Q5.BLUR]=(n,a)=>{a=a||1,a=Math.floor(a*e._pixelDensity),r(),t.set(n);let i=2*a+1,o=function(e){let t=new Float32Array(e),r=.3*a+.8,n=r*r*2;for(let a=0;a<e;a++){let i=a-e/2,o=Math.exp(-i*i/n)/(2.5066282746*r);t[a]=o}return t}(i),[s,l]=[e.canvas.width,e.canvas.height];for(let e=0;e<l;e++)for(let r=0;r<s;r++){let l=0,d=0,c=0,u=0;for(let n=0;n<i;n++){let i=4*(e*s+Math.min(Math.max(r-a+n,0),s-1));l+=t[i]*o[n],d+=t[i+1]*o[n],c+=t[i+2]*o[n],u+=t[i+3]*o[n]}let h=4*(e*s+r);n[h]=l,n[h+1]=d,n[h+2]=c,n[h+3]=u}t.set(n);for(let e=0;e<l;e++)for(let r=0;r<s;r++){let d=0,c=0,u=0,h=0;for(let n=0;n<i;n++){let i=4*(Math.min(Math.max(e-a+n,0),l-1)*s+r);d+=t[i]*o[n],c+=t[i+1]*o[n],u+=t[i+2]*o[n],h+=t[i+3]*o[n]}let f=4*(e*s+r);n[f]=d,n[f+1]=c,n[f+2]=u,n[f+3]=h}});let i=e._getImageData(0,0,e.canvas.width,e.canvas.height);e._filters[n](i.data,a),e.ctx.putImageData(i,0,0)}},Q5.renderers.c2d.text=(e,t)=>{e._textAlign="left",e._textBaseline="alphabetic",e._textSize=12;let r="sans-serif",n=!1,a=15,i=3,o="normal",s="normal",l=0,d=!1,c=0;e._fontMod=!1;let u=e._textCache={};e.loadFont=(t,r)=>{let n;if(t.includes("fonts.googleapis.com/css"))n=function(e,t){e.startsWith("http")||(e="https://"+e);const r=new URL(e).searchParams,n=r.get("family");if(!n)return console.error("Invalid Google Fonts URL: missing family parameter"),null;const a=n.split(":")[0];let i={family:a};return i.promise=(async()=>{try{const r=await fetch(e);if(!r.ok)throw new Error(`Failed to fetch Google Font: ${r.status} ${r.statusText}`);let n,o=await r.text(),s=/@font-face\s*{([^}]*)}/g,l=/src:\s*url\(([^)]+)\)[^;]*;/,d=/font-family:\s*['"]([^'"]+)['"]/,c=/font-weight:\s*([^;]+);/,u=/font-style:\s*([^;]+);/,h=[];for(;null!==(n=s.exec(o));){let e=n[1],t=l.exec(e);if(!t)continue;let r=t[1],a=d.exec(e);if(!a)continue;let i=a[1],o=c.exec(e),s=o?o[1]:"400",f=u.exec(e),p=f?f[1]:"normal",g=`${i}-${s}-${p}`.replace(/\s+/g,"-"),m=new FontFace(i,`url(${r})`,{weight:s,style:p});document.fonts.add(m);try{await m.load(),h.push(m)}catch(e){console.error(`Failed to load font face: ${g}`,e)}}return i._usedAwait&&(i={family:a}),i.faces=h,delete i.then,t&&t(i),i}catch(e){throw console.error("Error loading Google Font:",e),e}})(),i}(t,r);else{let e=t.split("/").pop().split(".")[0].replace(" ","");n={family:e};let a=new FontFace(e,`url(${encodeURI(t)})`);document.fonts.add(a),n.promise=new Promise(((e,t)=>{a.load().then((()=>{delete n.then,r&&r(a),e(a)})).catch((e=>{t(e)}))}))}return e._loaders.push(n.promise),e.textFont(n.family),n.then=(e,t)=>(n._usedAwait=!0,n.promise.then(e,t)),n},e.textFont=t=>{if(t&&"string"!=typeof t&&(t=t.family),!t||t==r)return r;r=t,e._fontMod=!0,l=-1},e.textSize=t=>{if(null==t)return e._textSize;e._textSize=t,e._fontMod=!0,l=-1,n||(a=1.25*t,i=a-t)},e.textStyle=t=>{if(!t)return o;o=t,e._fontMod=!0,l=-1},e.textWeight=t=>{if(!t)return s;s=t,e._fontMod=!0,l=-1},e.textLeading=t=>null==t?a||1.25*e._textSize:(n=!0,t==a?a:(a=t,i=t-e._textSize,void(l=-1))),e.textAlign=(t,r)=>{e.ctx.textAlign=e._textAlign=t,r&&(e.ctx.textBaseline=e._textBaseline=r==e.CENTER?"middle":r)},e._updateFont=()=>{e.ctx.font=`${o} ${s} ${e._textSize}px ${r}`,e._fontMod=!1},e.textWidth=t=>(e._fontMod&&e._updateFont(),e.ctx.measureText(t).width),e.textAscent=t=>(e._fontMod&&e._updateFont(),e.ctx.measureText(t).actualBoundingBoxAscent),e.textDescent=t=>(e._fontMod&&e._updateFont(),e.ctx.measureText(t).actualBoundingBoxDescent),e.textFill=e.fill,e.textStroke=e.stroke;e.createTextImage=(t,r,n)=>{d=!0;let a=e.text(t,0,0,r,n);return d=!1,a};let h=[];e.text=(t,n,s,f,p)=>{if(void 0===t||!e._doFill&&!e._doStroke)return;t=t.toString();let g,m,x,_,v,b,y,S,w=e.ctx;if(e._fontMod&&e._updateFont(),d)if(-1==l&&(()=>{let t=r+e._textSize+o+a,n=5381;for(let e=0;e<t.length;e++)n=33*n^t.charCodeAt(e);l=n>>>0})(),m=e._fill+e._stroke+e._strokeWeight,x=u[t],x?_=x[l]:x=u[t]={},_){if(g=_[m],g)return g;if(_.size>=4){for(let e in _){g=_[e],delete _[e];break}v=!0}}else _=x[l]={};if(-1==t.indexOf("\n")?h[0]=t:h=t.split("\n"),t.length>f){let e=[];for(let t of h){let r=0;for(;r<t.length;){let n=r+f;if(n>=t.length){e.push(t.slice(r));break}let a=t.lastIndexOf(" ",n);(-1===a||a<r)&&(a=n),e.push(t.slice(r,a)),r=a+1}}h=e}if(d){if(b=0,y=a,g){let e=g.canvas;g.ctx.clearRect(0,0,e.width,e.height),g.modified=!0}else{let t=e.ctx.textBaseline;e.ctx.textBaseline="alphabetic";let r=w.measureText(" "),n=r.fontBoundingBoxAscent,o=r.fontBoundingBoxDescent;e.ctx.textBaseline=t;let s=0;for(let e of h){let t=w.measureText(e).width;t>s&&(s=t)}let l=Math.ceil(s),d=Math.ceil(a*h.length+o);g=e.createImage.call(e,l,d,{pixelDensity:e._pixelDensity,defaultImageScale:1/e._pixelDensity}),g._ascent=n,g._descent=o,g._top=o+i,g._middle=g._top+.5*n+a*(h.length-1)*.5,g._bottom=g._top+n+a*(h.length-1),g._leading=a}w=g.ctx,w.font=e.ctx.font,w.fillStyle=e._fill,w.strokeStyle=e._stroke,w.lineWidth=e.ctx.lineWidth}else b=n,y=s,"middle"==e._textBaseline?y-=a*(h.length-1)*.5:"bottom"==e._textBaseline&&(y-=a*(h.length-1));e._fillSet||(S=w.fillStyle,w.fillStyle="black");let C=0;for(let t of h)if(e._doStroke&&e._strokeSet&&w.strokeText(t,b,y),e._doFill&&w.fillText(t,b,y),y+=a,C++,C>=p)break;if(h=[],e._fillSet||(w.fillStyle=S),d){if(_[m]=g,v||(_.size||(Object.defineProperty(_,"size",{writable:!0,enumerable:!1}),_.size=0),_.size++,c++),c>Q5.MAX_TEXT_IMAGES){for(const e in u){x=u[e];for(const e in x){_=x[e];for(let e in _){let t=_[e];t._texture&&t._texture.destroy(),delete _[e]}}}c=0}return g}},e.textImage=(t,r,n)=>{"string"==typeof t&&(t=e.createTextImage(t));let a=e._imageMode;e._imageMode="corner";let i=e._textAlign;"center"==i?r-=t.canvas.hw:"right"==i&&(r-=t.width);let o=e._textBaseline;"alphabetic"==o?n-=t._leading:"middle"==o?n-=t._middle:"bottom"==o?n-=t._bottom:"top"==o&&(n-=t._top),e.image(t,r,n),e._imageMode=a}},Q5.fonts=[],Q5.MAX_TEXT_IMAGES=5e3,Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e.RGBHDR=e._colorMode="rgb",e.HSL="hsl",e.HSB="hsb",e.OKLCH="oklch",e.SRGB="srgb",e.DISPLAY_P3="display-p3",e.colorMode=(r,n,a)=>{e._colorMode=r;let i="srgb"==e.canvas.colorSpace||"srgb"==a;e._srgb=i,n??="rgb"==r&&(e._c2d||i)?255:1,e._colorFormat="integer"==n||255==n?255:1,"oklch"==r?t.Color=Q5.ColorOKLCH:"hsl"==r?t.Color=i?Q5.ColorHSL:Q5.ColorHSL_P3:"hsb"==r?t.Color=i?Q5.ColorHSB:Q5.ColorHSB_P3:(255==e._colorFormat?t.Color=i?Q5.ColorRGB_8:Q5.ColorRGB_P3_8:t.Color=i?Q5.ColorRGB:Q5.ColorRGB_P3,e._colorMode="rgb")},e._namedColors={aqua:[0,255,255],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],coral:[255,127,80],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],silver:[192,192,192],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,n,a)=>{let i=e.Color;if(t._isColor)return new i(...t.levels);if(null==r){if("string"==typeof t){if("#"==t[0])t.length<=5?(t.length>4&&(a=parseInt(t[4]+t[4],16)),n=parseInt(t[3]+t[3],16),r=parseInt(t[2]+t[2],16),t=parseInt(t[1]+t[1],16)):(t.length>7&&(a=parseInt(t.slice(7,9),16)),n=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]){let e=new i(0,0,0);return e._css=t,e.toString=function(){return this._css},e}if([t,r,n,a]=e._namedColors[t],"rgb"!=e._colorMode)return i=e._srgb?Q5.ColorRGB_8:Q5.ColorRGB_P3_8,new i(t,r,n,a)}1==e._colorFormat&&(t/=255,r&&(r/=255),n&&(n/=255),a&&(a/=255))}(Array.isArray(t)||t.constructor==Float32Array)&&([t,r,n,a]=t)}return null==n?e._colorMode==Q5.OKLCH?new i(t,0,0,r):new i(t,t,t,r):new i(t,r,n,a)},e.red=e=>e.r,e.green=e=>e.g,e.blue=e=>e.b,e.alpha=e=>e.a,e.lightness=t=>{if(t.l)return t.l;let r=100*(.2126*t.r+.7152*t.g+.0722*t.b);return 255==e._colorFormat?r/255:r},e.hue=t=>{if(t.h)return t.h;let r=t.r,n=t.g,a=t.b;255==e._colorFormat&&(r/=255,n/=255,a/=255);let i,o=Math.max(r,n,a),s=Math.min(r,n,a);return i=o==s?0:o==r?60*(n-a)/(o-s):o==n?60*(a-r)/(o-s)+120:60*(r-n)/(o-s)+240,i<0&&(i+=360),i},e.lerpColor=(t,r,n)=>{if(n=Math.max(0,Math.min(1,n)),"rgb"==e._colorMode)return new e.Color(e.lerp(t.r,r.r,n),e.lerp(t.g,r.g,n),e.lerp(t.b,r.b,n),e.lerp(t.a,r.a,n));{let a=r.h-t.h;a>180&&(a-=360),a<-180&&(a+=360);let i=t.h+n*a;return i<0&&(i+=360),i>360&&(i-=360),new e.Color(e.lerp(t.l,r.l,n),e.lerp(t.c,r.c,n),i,e.lerp(t.a,r.a,n))}}},Q5.Color=class{constructor(){this._isColor=!0,this._q5Color=!0}get alpha(){return this.a}set alpha(e){this.a=e}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,r,n){super(),this.l=e,this.c=t,this.h=r,this.a=n??1}get levels(){return[this.l,this.c,this.h,this.a]}equals(e){return e&&this.l==e.l&&this.c==e.c&&this.h==e.h&&this.a==e.a}isSameColor(e){return e&&this.l==e.l&&this.c==e.c&&this.h==e.h}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}get lightness(){return this.l}set lightness(e){this.l=e}get chroma(){return this.c}set chroma(e){this.c=e}get hue(){return this.h}set hue(e){this.h=e}},Q5.ColorRGB=class extends Q5.Color{constructor(e,t,r,n){super(),this.r=e,this.g=t,this.b=r,this.a=n??1}get levels(){return[this.r,this.g,this.b,this.a]}equals(e){return e&&this.r==e.r&&this.g==e.g&&this.b==e.b&&this.a==e.a}isSameColor(e){return e&&this.r==e.r&&this.g==e.g&&this.b==e.b}toString(){return`color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`}get red(){return this.r}set red(e){this.r=e}get green(){return this.g}set green(e){this.g=e}get blue(){return this.b}set blue(e){this.b=e}},Q5.ColorRGB_P3=class extends Q5.ColorRGB{toString(){return`color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGB_8=class extends Q5.ColorRGB{constructor(e,t,r,n){super(e,t,r,n??255)}setRed(e){this.r=e}setGreen(e){this.g=e}setBlue(e){this.b=e}setAlpha(e){this.a=e}toString(){return`rgb(${this.r} ${this.g} ${this.b} / ${this.a/255})`}},Q5.ColorRGB_P3_8=class extends Q5.ColorRGB_8{constructor(e,t,r,n){super(e,t,r,n??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),n=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${r} / ${n})`,this._edited=!1}return this._css}},Q5.ColorHSL=class extends Q5.Color{constructor(e,t,r,n){super(),this.h=e,this.s=t,this.l=r,this.a=n??1}get levels(){return[this.h,this.s,this.l,this.a]}equals(e){return e&&this.h==e.h&&this.s==e.s&&this.l==e.l&&this.a==e.a}isSameColor(e){return e&&this.h==e.h&&this.s==e.s&&this.l==e.l}toString(){return`hsl(${this.h} ${this.s} ${this.l} / ${this.a})`}get hue(){return this.h}set hue(e){this.h=e}get saturation(){return this.s}set saturation(e){this.s=e}get lightness(){return this.l}set lightness(e){this.l=e}},Q5.ColorHSL_P3=class extends Q5.ColorHSL{toString(){return`color(display-p3 ${Q5.HSLtoRGB(this.h,this.s,this.l).join(" ")} / ${this.a})`}},Q5.ColorHSB=class extends Q5.ColorHSL{constructor(e,t,r,n){super(e,t,r,n),delete this.l,this.b=r}get levels(){return[this.h,this.s,this.b,this.a]}equals(e){return e&&this.h==e.h&&this.s==e.s&&this.b==e.b&&this.a==e.a}isSameColor(e){return e&&this.h==e.h&&this.s==e.s&&this.b==e.b}toString(){return`hsl(${Q5.HSBtoHSL(this.h,this.s,this.b).join(" ")} / ${this.a})`}get v(){return this.b}set v(e){this.b=e}get brightness(){return this.b}set brightness(e){this.b=e}get value(){return this.b}set value(e){this.b=e}},Q5.ColorHSB_P3=class extends Q5.ColorHSB{toString(){return`color(display-p3 ${Q5.HSLtoRGB(...Q5.HSBtoHSL(this.h,this.s,this.b)).join(" ")} / ${this.a})`}},Q5.HSLtoRGB=(e,t,r)=>{r/=100;let n=t/100*Math.min(r,1-r),a=(t,a=(t+e/30)%12)=>r-n*Math.max(Math.min(a-3,9-a,1),-1);return[a(0),a(8),a(4)]},Q5.HSBtoHSL=(e,t,r,n=r*(1-t/200))=>[e,n&&100!=n?(r-n)/Math.min(n,100-n)*100:0,n];{const e=(e,t)=>[e[0]*t[0]+e[1]*t[1]+e[2]*t[2],e[3]*t[0]+e[4]*t[1]+e[5]*t[2],e[6]*t[0]+e[7]*t[1]+e[8]*t[2]],t=(e,t,r)=>[e,isNaN(r)?0:t*Math.cos(r*Math.PI/180),isNaN(r)?0:t*Math.sin(r*Math.PI/180)],r=e=>e.map((e=>Math.max(0,Math.min(1,Math.abs(e)>.0031308?(e<0?-1:1)*(1.055*Math.abs(e)**(1/2.4)-.055):12.92*e)))),n=t=>{const r=e([1,.3963377773761749,.2158037573099136,1,-.1055613458156586,-.0638541728258133,1,-.0894841775298119,-1.2914855480194092],t);return e([1.2268798758459243,-.5578149944602171,.2813910456659647,-.0405757452148008,1.112286803280317,-.0717110580655164,-.0763729366746601,-.4214933324022432,1.5869240198367816],r.map((e=>e**3)))},a=t=>e([3.2409699419045226,-1.537383177570094,-.4986107602930034,-.9692436362808796,1.8759675015077202,.04155505740717559,.05563007969699366,-.20397695888897652,1.0569715142428786],t);Q5.OKLCHtoRGB=(e,i,o)=>r(a(n(t(e,i,o))))}Q5.modules.display=e=>{if(!e.canvas||e._isGraphics)return;let t=e.canvas;e.MAXED="maxed",e.SMOOTH="smooth",e.PIXELATED="pixelated",0!=Q5._instanceCount||Q5._server||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 display: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\nmain.q5-centered,\nmain.q5-maxed {\n\theight: 100vh;\n}\nmain {\n\toverscroll-behavior: none;\n}\n</style>"),e._adjustDisplay=e=>{let r=t.style;if(r)if("normal"==t.displayMode){if(!e)return;r.width=t.w*t.displayScale+"px",r.height=t.h*t.displayScale+"px"}else{let e=t.parentElement.getBoundingClientRect();t.w/t.h>e.width/e.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",n="smooth",a=1)=>{Q5._server||("string"==typeof a&&(a=parseFloat(a.slice(1))),"fullscreen"==r&&(r="maxed"),"center"==r&&(r="centered"),t.displayMode&&(t.parentElement.classList.remove("q5-"+t.displayMode),t.classList.remove("q5-pixelated")),t.parentElement.classList.add("q5-"+r),"pixelated"==n&&(t.classList.add("q5-pixelated"),e.pixelDensity(1),e.defaultImageScale(1),e.noSmooth&&e.noSmooth(),e.textFont&&e.textFont("monospace")),Object.assign(t,{displayMode:r,renderQuality:n,displayScale:a}),e.ctx&&e.pushStyles(),e._adjustDisplay(!0),e.ctx&&e.popStyles())},e.fullscreen=e=>{if(null==e)return document.fullscreenElement;e?document.body.requestFullscreen():document.exitFullscreen()}},Q5.modules.dom=(e,t)=>{e.elementMode=t=>e._elementMode=t,e.createElement=(t,r)=>{let n=document.createElement(t);return"center"==e._elementMode&&(n.style.transform="translate(-50%, -50%)"),r&&(n.innerHTML=r),Object.defineProperty(n,"x",{get:()=>n._x,set:t=>{let r=n.style.position;r&&"relative"!=r||(n.style.position="absolute");let a=e.canvas.offsetLeft+t;n.style.left=a+"px",n._x=a}}),Object.defineProperty(n,"y",{get:()=>n._y,set:t=>{let r=n.style.position;r&&"relative"!=r||(n.style.position="absolute");let a=e.canvas.offsetTop+t;n.style.top=a+"px",n._y=a}}),Object.defineProperty(n,"width",{get:()=>parseFloat(n.style.width||0),set:e=>n.style.width=e+"px"}),Object.defineProperty(n,"height",{get:()=>parseFloat(n.style.height||0),set:e=>n.style.height=e+"px"}),n.position=(e,t,r)=>(r&&(n.style.position=r),n.x=e,n.y=t,n),Object.defineProperty(n,"size",{writable:!0}),n.size=(e,t)=>(n.width=e,n.height=t,n),n.center=()=>(n.style.position="absolute",n.x=e.canvas.hw,n.y=e.canvas.hh,n),n.show=()=>(n.style.display="",n),n.hide=()=>(n.style.display="none",n),n.parent=e=>(e.append(n),n),e._addEventMethods(n),e._elements.push(n),e.canvas?e.canvas.parentElement.append(n):document.body.append(n),n.elt=n,n},e.createEl=e.createElement,e._addEventMethods=e=>{let t=e.addEventListener;e.mousePressed=e=>t("mousedown",e),e.mouseReleased=e=>t("mouseup",e),e.mouseClicked=e=>t("click",e),e.mouseMoved=e=>t("mousemove",e),e.mouseWheel=e=>t("wheel",e)},e.createA=(t,r,n)=>{let a=e.createEl("a",r);return a.href=t,a.target=n?"_blank":"_self",a},e.createButton=t=>e.createEl("button",t),e.createCheckbox=(t="",r=!1)=>{let n=e.createEl("input");n.type="checkbox",n.checked=r;let a=e.createEl("label",t);return a.addEventListener("click",(()=>{n.checked=!n.checked,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))})),n.insertAdjacentElement("afterend",a),n.label=a,n},e.createColorPicker=(t="#ffffff")=>{let r=e.createEl("input");return r.type="color",r.value=t.toString(),r},e.createDiv=t=>e.createEl("div",t),e.createImg=t=>{let r=e.createEl("img");return r.crossOrigin="anonymous",r.src=t,r},e.createInput=(t="",r="text")=>{let n=e.createEl("input");return n.value=t,n.type=r,n.style.boxSizing="border-box",n},e.createP=t=>e.createEl("p",t);let r=0;function n(t){t.width||=t.videoWidth,t.height||=t.videoHeight,t.defaultWidth=t.width*e._defaultImageScale,t.defaultHeight=t.height*e._defaultImageScale,t.ready=!0}e.createRadio=t=>{let n=e.createEl("div");return n.name=t||"radio"+r++,n.buttons=[],Object.defineProperty(n,"value",{get:()=>n.selected?.value,set:e=>{let t=n.buttons.find((t=>t.value==e));t&&(t.checked=!0,n.selected=t)}}),n.option=(t,r)=>{let a=e.createEl("input");a.type="radio",a.name=n.name,a.value=r||t,a.addEventListener("input",(()=>n.selected=a));let i=e.createEl("label",t);return i.addEventListener("click",(()=>{a.checked=!0,n.selected=a,a.dispatchEvent(new Event("input",{bubbles:!0})),a.dispatchEvent(new Event("change",{bubbles:!0}))})),a.label=i,n.append(a),n.append(i),n.buttons.push(a),n},n},e.createSelect=t=>{let r=e.createEl("select");if(t){let n=e.createEl("option",t);n.disabled=!0,n.selected=!0,r.append(n)}return Object.defineProperty(r,"selected",{get:()=>r.multiple?Array.from(r.selectedOptions).map((e=>e.textContent)):r.selectedOptions[0]?.textContent,set:e=>{if(r.multiple)Array.from(r.options).forEach((t=>{t.selected=e.includes(t.textContent)}));else{const t=Array.from(r.options).find((t=>t.textContent===e));t&&(t.selected=!0)}}}),Object.defineProperty(r,"value",{get:()=>r.multiple?Array.from(r.selectedOptions).map((e=>e.value)):r.selectedOptions[0]?.value,set:e=>{if(r.multiple)r.options.forEach((t=>t.selected=e.includes(t.value)));else{let t;for(let n=0;n<r.options.length;n++)if(r.options[n].value==e){t=r.options[n];break}t&&(t.selected=!0)}}}),r.option=(t,n)=>{let a=e.createEl("option",t);return a.value=n||t,r.append(a),r},r},e.createSlider=(t,r,n,a)=>{let i=e.createEl("input");return i.type="range",i.min=t,i.max=r,i.step=a,i.value=n,i.val=()=>parseFloat(i.value),i},e.createSpan=t=>e.createEl("span",t),e.createVideo=t=>{let r=e.createEl("video");return r.crossOrigin="anonymous",t&&(r.promise=new Promise((a=>{r.addEventListener("loadeddata",(()=>{delete r.then,r._usedAwait&&(r=e.createEl("video"),r.crossOrigin="anonymous",r.src=t),n(r),a(r)})),r.src=t})),e._loaders.push(r.promise),r.then=(e,t)=>(r._usedAwait=!0,r.promise.then(e,t))),r},e.createCapture=function(t,r=!0,a){let i="string"==typeof t?{[t]:!0}:t||{video:!0,audio:!0};!0===i.video&&(i.video={width:3840,height:2160}),i.video.facingMode??="user";let o=e.createVideo();return o.promise=(async()=>{let t;try{t=await navigator.mediaDevices.getUserMedia(i)}catch(e){throw e}return delete o.then,o._usedAwait&&(o=e.createVideo()),function(t){t.playsinline=t.autoplay=!0,r&&(t.flipped=!0,t.style.transform="scale(-1, 1)"),t.loadPixels=()=>{let r=e.createGraphics(t.videoWidth,t.videoHeight,{renderer:"c2d"});r.image(t,0,0),r.loadPixels(),t.pixels=r.pixels,r.remove()}}(o),o.srcObject=t,await new Promise((e=>o.addEventListener("loadeddata",e))),n(o),a&&a(o),o})(),e._loaders.push(o.promise),o.then=(e,t)=>(o._usedAwait=!0,o.promise.then(e,t)),o},e.findElement=e=>document.querySelector(e),e.findElements=e=>document.querySelectorAll(e)},Q5.modules.fes=e=>{if(e._fes=async t=>{if(Q5.disableFriendlyErrors)return;t._handledByFES=!0;let r=t.stack?.split("\n");if(!r?.length)return;let n=1,a="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(n=0,a="@");r[n].indexOf("q5")>=0;)n++;let i=r[n].split(a).at(-1);i.startsWith("blob:")&&(i=i.slice(5)),i=i.split(")")[0];let o=i.split(":"),s=parseInt(o.at(-2));o[o.length-1]=o.at(-1).split(")")[0];let l=t.file||o.slice(0,-2).join(":"),d=l.split("/").at(-1);try{let t=(await(await fetch(l)).text()).split("\n"),r=t[s-1]?.trim()??"",n=["🐛","🐞","🐜","🦗","🦋","🪲"][Math.floor(6*Math.random())],a=window.self!==window.top,i=`q5.js ${n}`,o=` Error in ${d} on line ${s}:\n\n${r}`;a?e.log(i+o):e.log(`%c${i}%c${o}`,"background: #b7ebff; color: #000;","")}catch(e){}},"undefined"!=typeof window&&window.addEventListener){let t=new Error,r=t.stack?.split("\n")||"";for(let t of r){let r=t.match(/(https?:\/\/[^\s)]+\.js|\b\/[^\s)]+\.js)/);if(r){let t=r[1];if(!/q5|p5play/i.test(t)){e._sketchFile=t;break}}}e._sketchFile&&(window.addEventListener("error",(t=>{let r=t.error;t.filename!==e._sketchFile||r?._handledByFES||(r.file=t.filename,e._fes(r))})),window.addEventListener("unhandledrejection",(t=>{let r=t.reason;r?.stack?.includes(e._sketchFile)&&!r?._handledByFES&&e._fes(r)})))}if(e._isGlobal&&0!=Q5.online&&null!=typeof navigator&&navigator.onLine){!async function(){try{let e=await fetch("https://data.jsdelivr.com/v1/package/npm/q5");if(!e.ok)return;let t=(await e.json()).tags.latest;t=t.slice(0,t.lastIndexOf(".")),t!=Q5.version&&console.warn(`q5.js v${t} is now available! Consider updating from v${Q5.version}.`)}catch(e){}}()}},Q5.modules.input=(e,t)=>{if(e._isGraphics)return;e.mouseX=0,e.mouseY=0,e.pmouseX=0,e.pmouseY=0,e.touches=[],e.pointers={},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={},n=[Q5.LEFT,Q5.CENTER,Q5.RIGHT],a=e.canvas;e._startAudio=()=>{Q5.aud&&"running"==Q5.aud?.state||e.userStartAudio()},e._updatePointer=r=>{let n=r.pointerId;e.pointers[n]??={event:r};let i,o,s=e.pointers[n];if(s.event=r,a){let t=a.getBoundingClientRect(),n=a.scrollWidth/e.width||1,s=a.scrollHeight/e.height||1;i=(r.clientX-t.left)/n,o=(r.clientY-t.top)/s,e._webgpu&&(i-=a.hw,o-=a.hh)}else i=r.clientX,o=r.clientY;s.x=i,s.y=o,!r.isPrimary&&r.pointerId||(document.pointerLockElement?(t.mouseX+=r.movementX,t.mouseY+=r.movementY):(t.mouseX=i,t.mouseY=o),t.moveX=r.movementX,t.moveY=r.movementY)};let i=0;function o(t){const r=e.canvas.getBoundingClientRect(),n=e.canvas.scrollWidth/e.width||1,a=e.canvas.scrollHeight/e.height||1;let i=0,o=0;return e._webgpu&&(i=e.halfWidth,o=e.halfHeight),{x:(t.clientX-r.left)/n-i,y:(t.clientY-r.top)/a-o,id:t.identifier}}if(e._onpointerdown=r=>{i++,e._startAudio(),e._updatePointer(r),t.mouseIsPressed=!0,t.mouseButton=n[r.button],e.mousePressed(r)},e._onpointermove=t=>{a&&!a.visible||(e._updatePointer(t),e.mouseIsPressed?e.mouseDragged(t):e.mouseMoved(t))},e._onpointerup=r=>{t.mouseIsPressed=!1,i>0&&(i--,e._updatePointer(r),delete e.pointers[r.pointerId],e.mouseReleased(r))},e._onclick=r=>{e._updatePointer(r),t.mouseIsPressed=!0,e.mouseClicked(r),t.mouseIsPressed=!1},e._ondblclick=r=>{e._updatePointer(r),t.mouseIsPressed=!0,e.doubleClicked(r),t.mouseIsPressed=!1},e._onwheel=t=>{e._updatePointer(t),t.delta=t.deltaY;let r=e.mouseWheel(t);(e._isGlobal&&!r||0==r)&&t.preventDefault()},e.cursor=(t,r,n)=>{let a="";t.includes(".")&&(t=`url("${t}")`,a=", auto"),void 0!==r&&(t+=" "+r+" "+n),e.canvas.style.cursor=t+a},e.noCursor=()=>e.canvas.style.cursor="none",e.pointerLock=(e=!1)=>{document.body?.requestPointerLock({unadjustedMovement:e})},e._onkeydown=n=>{n.repeat||(e._startAudio(),t.keyIsPressed=!0,t.key=n.key,t.keyCode=n.keyCode,r[e.keyCode]=r[e.key.toLowerCase()]=!0,e.keyPressed(n),1==n.key.length&&e.keyTyped(n))},e._onkeyup=n=>{t.keyIsPressed=!1,t.key=n.key,t.keyCode=n.keyCode,r[e.keyCode]=r[e.key.toLowerCase()]=!1,e.keyReleased(n)},e.keyIsDown=e=>!!r["string"==typeof e?e.toLowerCase():e],e._updateTouches=t=>{if(a&&!a.visible)return;let r=[...t.changedTouches].map(o);for(let t of r){let r=e.touches.find((e=>e.id==t.id));r?(r.x=t.x,r.y=t.y):e.touches.push(t)}for(let r=e.touches.length-1;r>=0;r--){let n=e.touches[r],a=!1;for(let e=0;e<t.touches.length;e++)if(t.touches[e].identifier===n.id){a=!0;break}a||e.touches.splice(r,1)}},e._ontouchstart=t=>{e._startAudio(),e.touchStarted(t)||t.preventDefault()},e._ontouchmove=t=>{e.touchMoved(t)||t.preventDefault()},e._ontouchend=t=>{e.touchEnded(t)||t.preventDefault()},window){let t=window.addEventListener;t("keydown",(t=>e._onkeydown(t)),!1),t("keyup",(t=>e._onkeyup(t)),!1);let r=window.PointerEvent?"pointer":"mouse";t(r+"move",(t=>e._onpointermove(t)),!1),t(r+"up",(t=>e._onpointerup(t))),t(r+"cancel",(t=>e._onpointerup(t))),t("touchstart",(t=>e._updateTouches(t))),t("touchmove",(t=>e._updateTouches(t))),t("touchend",(t=>e._updateTouches(t))),t("touchcancel",(t=>e._updateTouches(t))),a&&a.addEventListener("wheel",(t=>e._onwheel(t))),!e._isGlobal&&a&&(t=a.addEventListener.bind(a)),t(r+"down",(t=>e._onpointerdown(t))),t("click",(t=>e._onclick(t))),t("dblclick",(t=>e._ondblclick(t))),a&&(t=a.addEventListener.bind(a)),t("touchstart",(t=>e._ontouchstart(t))),t("touchmove",(t=>e._ontouchmove(t))),t("touchend",(t=>e._ontouchend(t))),t("touchcancel",(t=>e._ontouchend(t)))}},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.TWO_PI=e.TAU=2*Math.PI,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.pow=Math.pow,e.sqrt=Math.sqrt,e.SHR3=1,e.LCG=2,e.round=(e,t=0)=>{let r=10**t;return Math.round(e*r)/r};let r=e._angleMode=0;e.angleMode=t=>(r=e._angleMode=0==t||"radians"==t?0:1,r?"degrees":"radians");let n=e._DEGTORAD=Math.PI/180,a=e._RADTODEG=180/Math.PI;function i(){let e,t,r=4294967295;return{setSeed(n){e=t=(n??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,n,a,i)=>{let o=n+1*(e-t)/(r-t)*(a-n);return i?n<a?Math.min(Math.max(o,n),a):Math.min(Math.max(o,a),n):o},e.dist=function(){let e=arguments;return 2==e.length?Math.hypot(e[0].x-e[1].x,e[0].y-e[1].y):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.lerp=(e,t,r)=>e*(1-r)+t*r,e.constrain=(e,t,r)=>Math.min(Math.max(e,t),r),e.norm=(t,r,n)=>e.map(t,r,n,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e),e.sin=e=>Math.sin(r?e*n:e),e.cos=e=>Math.cos(r?e*n:e),e.tan=e=>Math.tan(r?e*n:e),e.asin=e=>{let t=Math.asin(e);return r?t*a:t},e.acos=e=>{let t=Math.acos(e);return r?t*a:t},e.atan=e=>{let t=Math.atan(e);return r?t*a:t},e.atan2=(e,t)=>{let n=Math.atan2(e,t);return r?n*a:n};let o=i();o.setSeed(),e.randomSeed=e=>o.setSeed(e),e.random=(e,t)=>void 0===e?o.rand():"number"==typeof e?void 0!==t?o.rand()*(t-e)+e:o.rand()*e:e[Math.trunc(e.length*o.rand())],e.jit=(t=1)=>e.random(-t,t),e.randomGenerator=t=>{t==e.LCG?o=function(){const e=4294967296;let t,r;return{setSeed(n){r=t=(n??Math.random()*e)>>>0},getSeed:()=>t,rand:()=>(r=(1664525*r+1013904223)%e,r/e)}}():t==e.SHR3&&(o=i()),o.setSeed()};var s=new function(){var e,t,r,n=new Array(128),a=new Array(256),i=new Array(128),s=new Array(128),l=new Array(256),d=new Array(256),c=()=>4294967296*o.rand()-2147483648,u=()=>.5+2.328306e-10*(c()|0),h=()=>{for(var t,a,o,l,d=3.44262;;){if(t=r*i[e],0==e){do{o=u(),l=u(),t=.2904764*-Math.log(o),a=-Math.log(l)}while(a+a<t*t);return r>0?d+t:-d-t}if(s[e]+u()*(s[e-1]-s[e])<Math.exp(-.5*t*t))return t;if(r=c(),e=127&r,Math.abs(r)<n[e])return r*i[e]}},f=()=>{for(var r;;){if(0==e)return 7.69711-Math.log(u());if(r=t*l[e],d[e]+u()*(d[e-1]-d[e])<Math.exp(-r))return r;if((t=c())<a[e=255&t])return t*l[e]}};this.SHR3=c,this.UNI=u,this.RNOR=()=>(r=c(),e=127&r,Math.abs(r)<n[e]?r*i[e]:h()),this.REXP=()=>(t=c()>>>0)<n[e=255&t]?t*l[e]:f(),this.zigset=()=>{var e,t,r=2147483648,o=4294967296,c=3.442619855899,u=c,h=.00991256303526217,f=7.697117470131487,p=f,g=.003949659822581572;for(e=h/Math.exp(-.5*c*c),n[0]=Math.floor(c/e*r),n[1]=0,i[0]=e/r,i[127]=c/r,s[0]=1,s[127]=Math.exp(-.5*c*c),t=126;t>=1;t--)c=Math.sqrt(-2*Math.log(h/c+Math.exp(-.5*c*c))),n[t+1]=Math.floor(c/u*r),u=c,s[t]=Math.exp(-.5*c*c),i[t]=c/r;for(e=g/Math.exp(-f),a[0]=Math.floor(f/e*o),a[1]=0,l[0]=e/o,l[255]=f/o,d[0]=1,d[255]=Math.exp(-f),t=254;t>=1;t--)f=-Math.log(g/f+Math.exp(-f)),a[t+1]=Math.floor(f/p*o),p=f,d[t]=Math.exp(-f),l[t]=f/o}};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.NoiseGenerator=Q5.PerlinNoise,e.noiseMode=e=>{t.NoiseGenerator=Q5[e[0].toUpperCase()+e.slice(1)+"Noise"],l=null},e.noiseSeed=t=>{l=new e.NoiseGenerator(t)},e.noise=(t=0,r=0,n=0)=>(l??=new e.NoiseGenerator,l.noise(t,r,n)),e.noiseDetail=(t,r)=>{l??=new e.NoiseGenerator,t>0&&(l.octaves=t),r>0&&(l.falloff=r)}},Q5.NoiseGenerator=class{},Q5.PerlinNoise=class extends Q5.NoiseGenerator{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,n=[];for(let e=0;e<256;e++)n[e]=e;for(let a=255;a>0;a--)t=(e=16807*e%2147483647)%(a+1),r=n[a],n[a]=n[t],n[t]=r;return n}dot(e,t,r,n){return e[0]*t+e[1]*r+e[2]*n}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 n=this,a=0,i=1,o=1,s=0;for(let l=0;l<n.octaves;l++){const l=255&Math.floor(e*i),d=255&Math.floor(t*i),c=255&Math.floor(r*i),u=e*i-Math.floor(e*i),h=t*i-Math.floor(t*i),f=r*i-Math.floor(r*i),p=n.fade(u),g=n.fade(h),m=n.fade(f),x=n.p[l]+d,_=n.p[x]+c,v=n.p[x+1]+c,b=n.p[l+1]+d,y=n.p[b]+c,S=n.p[b+1]+c,w=n.mix(n.dot(n.grad3[n.p[_]%12],u,h,f),n.dot(n.grad3[n.p[y]%12],u-1,h,f),p),C=n.mix(n.dot(n.grad3[n.p[v]%12],u,h-1,f),n.dot(n.grad3[n.p[S]%12],u-1,h-1,f),p),Q=n.mix(n.dot(n.grad3[n.p[_+1]%12],u,h,f-1),n.dot(n.grad3[n.p[y+1]%12],u-1,h,f-1),p),M=n.mix(n.dot(n.grad3[n.p[v+1]%12],u,h-1,f-1),n.dot(n.grad3[n.p[S+1]%12],u-1,h-1,f-1),p),P=n.mix(w,C,g),E=n.mix(Q,M,g);a+=n.mix(P,E,m)*o,s+=o,o*=n.falloff,i*=2}return(a/s+1)/2}},Q5.modules.record=(e,t)=>{let r,n,a,i,o,s,l;function d(t={}){document.head.insertAdjacentHTML("beforeend","<style>\n.rec {\n\tdisplay: flex;\n\tz-index: 1000;\n\tgap: 6px;\n\tbackground: #1a1b1d;\n\tpadding: 6px 8px;\n\tborder-radius: 21px;\n\tbox-shadow: #0000001a 0px 4px 12px;\n\tborder: 2px solid transparent; \n\topacity: 0.6;\n\ttransition: all 0.3s;\n\twidth: 134px;\n\toverflow: hidden;\n}\n\n.rec:hover {\n\twidth: unset;\n\topacity: 0.96;\n}\n\n.rec.recording { border-color: #cc3e44; }\n\n.rec button,\n.rec select { cursor: pointer; }\n\n.rec button,\n.rec select,\n.rec input,\n.rec span {\n\tfont-family: sans-serif;\n\tfont-size: 14px;\n\tpadding: 2px 10px;\n\tborder-radius: 18px;\n\toutline: none;\n\tbackground: #232529;\n\tcolor: #d4dae6;\n\tbox-shadow: #0000001a 0px 4px 12px;\n\tborder: 1px solid #46494e;\n\tvertical-align: middle;\n\tline-height: 18px;\n\ttransition: all 0.3s;\n}\n\n.rec .audio-toggle {\n\tfont-size: 16px;\n\tpadding: 2px 10px;\n}\n\n.rec .bitrate input {\n\tborder-radius: 18px 0 0 18px;\n\tborder-right: 0;\n\twidth: 40px;\n\tpadding: 2px 5px 2px 10px;\n\ttext-align: right;\n}\n\n.rec .bitrate span {\n\tborder-radius: 0 18px 18px 0;\n\tborder-left: 0;\n\tpadding: 2px 10px 2px 5px;\n\tbackground: #333;\n}\n\n.rec .record-button { \n\tcolor: #cc3e44;\n\tfont-size: 18px;\n}\n\n.rec select:hover,\n.rec button:hover { background: #32343b; }\n\n.rec button:disabled {\n\topacity: 0.5;\n\tcolor: #969ba5;\n\tcursor: not-allowed;\n}\n</style>"),r=e.createEl("div"),r.className="rec",r.innerHTML='\n<button class="record-button"></button>\n<span class="record-timer"></span>\n<button></button>\n',[n,i,a]=r.children,r.x=r.y=8,r.resetTimer=()=>r.time={hours:0,minutes:0,seconds:0,frames:0},r.resetTimer();let d="video/mp4; codecs=";r.formats={"H.264":d+'"avc1.42E01E"',VP9:d+"vp9"};let h=d+'"avc1.640034"';e.canvas.width*e.canvas.height>32e5&&MediaRecorder.isTypeSupported(h)&&(r.formats["H.264"]=h),Object.assign(r.formats,t.formats),o=e.createSelect("format");for(const e in r.formats)o.option(e,r.formats[e]);o.title="Video Format",r.append(o);let g=e.createEl("div");g.className="bitrate",g.style.display="flex",r.append(g),s=e.createInput();let m=document.createElement("span");function x(){r.encoderSettings.mimeType=o.value}function _(){r.encoderSettings.videoBitsPerSecond=1e6*s.value}m.textContent="mbps",s.title=m.title="Video Bitrate",g.append(s),g.append(m),l=e.createEl("button"),l.className="audio-toggle active",l.textContent="🔊",l.title="Toggle Audio Recording",r.append(l),r.captureAudio=!0,l.addEventListener("click",(()=>{r.captureAudio=!r.captureAudio,l.textContent=r.captureAudio?"🔊":"🔇",l.classList.toggle("active",r.captureAudio)})),r.encoderSettings={},o.addEventListener("change",x),s.addEventListener("change",_),Object.defineProperty(r,"bitrate",{get:()=>s.value,set:e=>{s.value=e,_()}}),Object.defineProperty(r,"format",{get:()=>o.selected,set:e=>{e=e.toUpperCase(),r.formats[e]&&(o.selected=e,x())}}),r.format="H.264";let v=e.canvas.height;r.bitrate=v>=4320?96:v>=2160?64:v>=1440?48:v>=1080?32:v>=720?26:16,n.addEventListener("click",(()=>{e.recording?r.paused?u():e.pauseRecording():c()})),a.addEventListener("click",(()=>{r.paused?e.saveRecording():e.deleteRecording()})),f(),e.registerMethod("post",p)}function c(){if(!e.recording){if(e.userStartAudio(),!r.stream){r.frameRate??=e.getTargetFrameRate();let t=e.canvas.captureStream(r.frameRate);if(r.videoTrack=t.getVideoTracks()[0],r.captureAudio&&e.getAudioContext){let t=e.getAudioContext(),n=t.createMediaStreamDestination();t.destination.input?t.destination.input.connect(n):Q5.soundOut.connect(n),r.audioTrack=n.stream.getAudioTracks()[0],r.stream=new MediaStream([r.videoTrack,r.audioTrack])}else r.stream=t}r.mediaRecorder=new MediaRecorder(r.stream,r.encoderSettings),r.chunks=[],r.mediaRecorder.addEventListener("dataavailable",(e=>{e.data.size>0&&r.chunks.push(e.data)})),r.mediaRecorder.start(),t.recording=!0,r.paused=!1,r.classList.add("recording"),r.resetTimer(),f(!0)}}function u(){e.recording&&r.paused&&(r.mediaRecorder.resume(),r.paused=!1,f(!0))}function h(){e.recording&&(r.resetTimer(),r.mediaRecorder.stop(),t.recording=!1,r.paused=!1,r.classList.remove("recording"))}function f(e){n.textContent=e?"⏸":"⏺",n.title=(e?"Pause":"Start")+" Recording",a.textContent=e?"🗑️":"💾",a.title=(e?"Delete":"Save")+" Recording",a.disabled=!e}function p(){if(e.recording&&!r.paused){r.time.frames++;let t=e.getTargetFrameRate();r.time.frames>=t&&(r.time.seconds+=Math.floor(r.time.frames/t),r.time.frames%=t,r.time.seconds>=60&&(r.time.minutes+=Math.floor(r.time.seconds/60),r.time.seconds%=60,r.time.minutes>=60&&(r.time.hours+=Math.floor(r.time.minutes/60),r.time.minutes%=60)))}i.textContent=function(){let{hours:e,minutes:t,seconds:n,frames:a}=r.time;return`${String(e).padStart(2,"0")}:${String(t).padStart(2,"0")}:${String(n).padStart(2,"0")}:${String(a).padStart(2,"0")}`}()}e.recording=!1,e.createRecorder=e=>(r||d(e),r),e.record=t=>{r||(d(t),r.hide()),e.recording?r.paused&&u():c()},e.pauseRecording=()=>{e.recording&&!r.paused&&(r.mediaRecorder.pause(),r.paused=!0,f(),n.title="Resume Recording",a.disabled=!1)},e.deleteRecording=()=>{h(),f(),t.recording=!1},e.saveRecording=async n=>{if(!e.recording)return;await new Promise((e=>{r.mediaRecorder.onstop=e,h()}));let a=r.encoderSettings.mimeType,i=a.slice(6,a.indexOf(";")),o=URL.createObjectURL(new Blob(r.chunks,{type:a})),s=document.createElement("iframe"),l=document.createElement("a");s.style.display="none",s.name="download_"+Date.now(),document.body.append(s),l.target=s.name,l.href=o,n??=document.title+" "+(new Date).toLocaleString(void 0,{hour12:!1}).replace(","," at").replaceAll("/","-").replaceAll(":","_"),l.download=`${n}.${i}`,await new Promise((e=>{s.onload=()=>{document.body.removeChild(s),e()},l.click()})),setTimeout((()=>URL.revokeObjectURL(o)),1e3),f(),t.recording=!1}},Q5.modules.sound=(e,t)=>{e.Sound=Q5.Sound;let r=[];e.loadSound=(t,n)=>{let a=new Q5.Sound;return r.push(a),a.promise=(async()=>{let e;a._usedAwait&&(r.splice(r.indexOf(a),1),a=new Q5.Sound,r.push(a));try{await a.load(t)}catch(t){e=t}if(delete a.then,e)throw e;return n&&n(a),a})(),e._loaders.push(a.promise),a.then=(e,t)=>(a._usedAwait=!0,a.promise.then(e,t)),a},e.loadAudio=(t,r)=>{let n=new Audio(t);return n._isAudio=!0,n.crossOrigin="Anonymous",n.promise=new Promise(((e,a)=>{function i(){n.loaded||(delete n.then,n._usedAwait&&(n=new Audio(t),n._isAudio=!0,n.crossOrigin="Anonymous"),n.loaded=!0,r&&r(n),e(n))}n.addEventListener("canplay",i),n.addEventListener("suspend",i),n.addEventListener("error",a)})),e._loaders.push(n.promise),n.then=(e,t)=>(n._usedAwait=!0,n.promise.then(e,t)),n},e.getAudioContext=()=>Q5.aud,e.userStartAudio=()=>{if(window.AudioContext){if(Q5._offlineAudio){Q5._offlineAudio=!1,Q5.aud=new window.AudioContext,Q5.soundOut=Q5.aud.createGain(),Q5.soundOut.connect(Q5.aud.destination);for(let e of Q5.instances)e._userAudioStarted()}return Q5.aud.resume()}},e._userAudioStarted=()=>{for(let e of r)e.init()},e.outputVolume=e=>{Q5.soundOut&&(Q5.soundOut.gain.value=e)}},window.OfflineAudioContext&&(Q5.aud=new window.OfflineAudioContext(2,1,44100),Q5._offlineAudio=!0,Q5.soundOut=Q5.aud.createGain(),Q5.soundOut.connect(Q5.aud.destination)),Q5.Sound=class{constructor(){this._isSound=!0,this.sources=new Set,this.loaded=this.paused=!1}async load(e){this.url=e;let t=await fetch(e);this.buffer=await t.arrayBuffer(),this.buffer=await Q5.aud.decodeAudioData(this.buffer),Q5.aud&&this.init()}init(){this.buffer.length&&(this.gainNode=Q5.aud.createGain(),this.pannerNode=Q5.aud.createStereoPanner(),this.gainNode.connect(this.pannerNode),this.pannerNode.connect(Q5.soundOut),this.loaded=!0,this._volume&&(this.volume=this._volume),this._pan&&(this.pan=this._pan))}_newSource(e,t){let r=Q5.aud.createBufferSource();return r.buffer=this.buffer,r.connect(this.gainNode),r.loop=this._loop,r._startedAt=Q5.aud.currentTime,r._offset=e,r._duration=t,r.start(0,r._offset,r._duration),this.sources.add(r),r.promise=new Promise((e=>{r.onended=()=>{this.paused||(this.ended=!0,this._onended&&this._onended(),this.sources.delete(r),e())}})),r}play(e=0,t){if(!this.loaded)return;let r;if(this.paused){let e=[];for(let t of this.sources)e.push({offset:t._offset,duration:t._duration}),this.sources.delete(t);e.sort(((e,t)=>(e.duration??this.buffer.duration-e.offset)-(t.duration??this.buffer.duration-t.offset)));for(let t of e)r=this._newSource(t.offset,t.duration)}else r=this._newSource(e,t);return this.paused=this.ended=!1,r.promise}pause(){if(this.isPlaying()){for(let e of this.sources){e.stop();let t=Q5.aud.currentTime-e._startedAt;e._offset+=t,e._duration&&(e._duration-=t)}this.paused=!0}}stop(){for(let e of this.sources)e.stop(),this.sources.delete(e);this.paused=!1,this.ended=!0}get volume(){return this._volume}set volume(e){this.loaded&&(this.gainNode.gain.value=e),this._volume=e}get pan(){return this._pan}set pan(e){this.loaded&&(this.pannerNode.pan.value=e),this._pan=e}get loop(){return this._loop}set loop(e){this.sources.forEach((t=>t.loop=e)),this._loop=e}get playing(){return!this.paused&&this.sources.size>0}setVolume(e){this.volume=e}setPan(e){this.pan=e}setLoop(e){this.loop=e}isLoaded(){return this.loaded}isPlaying(){return this.playing}isPaused(){return this.paused}isLooping(){return this._loop}onended(e){this._onended=e}},Q5.modules.util=(e,t)=>{e._loadFile=(t,r,n)=>{let a={};return a.promise=fetch(t).then((e=>e.ok?"json"==n?e.json():e.text():(reject("error loading file"),null))).then((e=>("csv"==n&&(e=Q5.CSV.parse(e)),"string"==typeof e?a.text=e:Object.assign(a,e),delete a.then,r&&r(e),e))),e._loaders.push(a.promise),a.then=(e,t)=>a.promise.then(e,t),a},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.loadXML=(t,r)=>{let n={};return n.promise=fetch(t).then((e=>e.text())).then((e=>{let t=(new DOMParser).parseFromString(e,"application/xml");return n.DOM=t,delete n.then,r&&r(t),t})),e._loaders.push(n.promise),n.then=(e,t)=>n.promise.then(e,t),n};const r=/(jpe?g|png|gif|webp|avif|svg)/i,n=/(ttf|otf|woff2?|eot|json)/i,a=/(serif|sans-serif|monospace|cursive|fantasy)/i,i=/(wav|flac|mp3|ogg|m4a|aac|aiff|weba)/i;async function o(e,t,n){let a;if(t=t||"untitled",n=n||"png",r.test(n)){let t=e.canvas||e;a=await t.convertToBlob({type:"image/"+n})}else{let t="text/plain";"json"==n&&("string"!=typeof e&&(e=JSON.stringify(e)),t="text/json"),a=new Blob([e],{type:t})}let i=document.createElement("a");i.href=URL.createObjectURL(a),i.download=t+"."+n,i.click(),setTimeout((()=>URL.revokeObjectURL(i.href)),1e3)}e.load=function(...t){Array.isArray(t[0])&&(t=t[0]);let o=[];for(let s of t){let t,l=s.split(".").pop().toLowerCase();t="json"!=l||s.includes("-msdf.")?"csv"==l?e.loadCSV(s):r.test(l)?e.loadImage(s):n.test(l)||a.test(s)?e.loadFont(s):i.test(l)?e.loadSound(s):"xml"==l?e.loadXML(s):e.loadText(s):e.loadJSON(s),o.push(t)}return 1==t.length?o[0]:Promise.all(o)},e.save=(t,r,n)=>{if((!t||"string"==typeof t&&(!r||!n&&r.length<5))&&(n=r,r=t,t=e),n)o(t,r,n);else if(r){let e=r.lastIndexOf(".");o(t,r.slice(0,e),r.slice(e+1))}else o(t)},e.canvas&&!Q5._createServerCanvas&&(e.canvas.save=e.saveCanvas=e.save),"object"==typeof localStorage&&(e.storeItem=(e,t)=>localStorage.setItem(e,t),e.getItem=e=>localStorage.getItem(e),e.removeItem=e=>localStorage.removeItem(e),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(),e.nf=(e,t,r)=>{let n=e<0,a=(e=Math.abs(e)).toFixed(r).split(".");a[0]=a[0].padStart(t,"0");let i=a.join(".");return n&&(i="-"+i),i},e.shuffle=(t,r)=>{r||(t=[...t]);for(let r=t.length-1;r>0;r--){let n=Math.floor(e.random()*(r+1));[t[r],t[n]]=[t[n],t[r]]}return t}},Q5.CSV={},Q5.CSV.parse=(e,t=",",r="\n")=>{if(!e.length)return[];let n=[],a=e.split(r),i=a[0].split(t).map((e=>e.replaceAll('"',"")));for(let e=1;e<a.length;e++){let r={},o=a[e].split(t);i.forEach(((e,t)=>r[e]=JSON.parse(o[t]))),n.push(r)}return n},Q5.modules.vector=e=>{e.Vector=Q5.Vector,e.createVector=(t,r,n)=>new e.Vector(t,r,n,e)},Q5.Vector=class{constructor(e,t,r,n){this.x=e||0,this.y=t||0,this.z=r||0,this._isVector=!0,this._$=n||window,this._useCache=!1,this._mag=0,this._magCached=!1,this._direction=0,this._directionCached=!1}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}}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}_calcMag(){const e=this.x,t=this.y,r=this.z;this._mag=Math.sqrt(e*e+t*t+r*r),this._magCached=this._useCache}mag(){return this._magCached||this._calcMag(),this._mag}magSq(){if(this._magCached)return this._mag*this._mag;const e=this.x,t=this.y,r=this.z;return e*e+t*t+r*r}setMag(e){this._magCached||this._calcMag();let t=this._mag;if(0==t){const t=this.direction();this.x=e*this._$.cos(t),this.y=e*this._$.sin(t)}else{let r=e/t;this.x*=r,this.y*=r,this.z*=r}return this._mag=e,this._magCached=this._useCache,this}direction(){if(!this._directionCached){const e=this.x,t=this.y;(e||t)&&(this._direction=this._$.atan2(this.y,this.x)),this._directionCached=this._useCache}return this._direction}setDirection(e){let t=this.mag();return t&&(this.x=t*this._$.cos(e),this.y=t*this._$.sin(e)),this._direction=e,this._directionCached=this._useCache,this}heading(){return this.direction()}setHeading(e){return this.setDirection(e)}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,n=this.z-e.z;return Math.sqrt(t*t+r*r+n*n)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,r=this.z*e.x-this.x*e.z,n=this.x*e.y-this.y*e.x;return this.x=t,this.y=r,this.z=n,this}normalize(){this._magCached||this._calcMag();let e=this._mag;return 0!=e&&(this.x/=e,this.y/=e,this.z/=e),this._mag=1,this._magCached=this._useCache,this}limit(e){this._magCached||this._calcMag();let t=this._mag;if(t>e){let r=e/t;this.x*=r,this.y*=r,this.z*=r,this._mag=e,this._magCached=this._useCache}return this}rotate(e){let t=this._$.cos(e),r=this._$.sin(e),n=this.x*t-this.y*r,a=this.x*r+this.y*t;return this.x=n,this.y=a,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 n=this.mag(),a=r.mag();if(0==n||0==a)return this.mult(1-t).add(r.mult(t));let i=Q5.Vector.cross(this,r),o=i.mag(),s=Math.atan2(o,this.dot(r));if(o>0)i.div(o);else{if(s<this._$.HALF_PI)return this.mult(1-t).add(r.mult(t));0==this.z&&0==r.z?i.set(0,0,1):0!=this.x?i.set(this.y,-this.x,0).normalize():i.set(1,0,0)}let l=i.cross(this),d=1-t+t*a/n,c=d*Math.cos(t*s),u=d*Math.sin(t*s);return this.x=this.x*c+l.x*u,this.y=this.y*c+l.y*u,this.z=this.z*c+l.z*u,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._mag=t,this._magCached=this._useCache,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._mag=r,this._magCached=this._useCache;const n=this._$.cos(t),a=this._$.sin(t),i=this._$.cos(e),o=this._$.sin(e);return this.x=r*o*a,this.y=-r*i,this.z=r*o*n,this}random2D(){return this._mag=1,this._magCached=this._useCache,this.fromAngle(Math.random()*Math.PI*2)}random3D(){return this._mag=1,this._magCached=this._useCache,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.direction=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),Q5.Vector.reflect=(e,t)=>e.copy().reflect(t),Q5.Vector.random2D=()=>(new Q5.Vector).random2D(),Q5.Vector.random3D=()=>(new Q5.Vector).random3D(),Q5.Vector.fromAngle=(e,t)=>(new Q5.Vector).fromAngle(e,t),Q5.Vector.fromAngles=(e,t,r)=>(new Q5.Vector).fromAngles(e,t,r),Q5.renderers.webgpu={},Q5.renderers.webgpu.canvas=(e,t)=>{const r=e.canvas;e.colorMode&&e.colorMode("rgb",1),e._baseShaderCode="\nstruct Q5 {\n\twidth: f32,\n\theight: f32,\n\thalfWidth: f32,\n\thalfHeight: f32,\n\tpixelDensity: f32,\n\tframeCount: f32,\n\ttime: f32,\n\tdeltaTime: f32,\n\tmouseX: f32,\n\tmouseY: f32,\n\tmouseIsPressed: f32,\n\tkeyCode: f32,\n\tkeyIsPressed: f32\n}",e._g=e.createGraphics(1,1,"c2d"),e._g.colorMode&&e._g.colorMode(e.RGB,1);let n,a,i,o,s,l,d,c,u,h,f=2,p=12,g=0,m=0;e._pipelineConfigs=[],e._pipelines=[],e._buffers=[];let x=[],_=new Float32Array(1e6);_.set([0,0,0,0,0,0,0,1,1,1,1,1]);let v=Q5.device.createBindGroupLayout({label:"mainLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]});e._bindGroupLayouts=[v];let b=Q5.device.createBuffer({size:64,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),y=()=>{let t=[e.canvas.width,e.canvas.height],r="bgra8unorm";i=Q5.device.createTexture({size:t,sampleCount:4,format:r,usage:GPUTextureUsage.RENDER_ATTACHMENT}).createView();let n=GPUTextureUsage.COPY_SRC|GPUTextureUsage.COPY_DST|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT;e._frameA=s=Q5.device.createTexture({label:"frameA",size:t,format:r,usage:n}),e._frameB=o=Q5.device.createTexture({label:"frameB",size:t,format:r,usage:n}),e._frameShaderCode=e._baseShaderCode+"\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex: u32\n}\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) texCoord: vec2f\n}\n\nconst ndc = array(vec2f(-1,-1), vec2f(1,-1), vec2f(-1,1), vec2f(1,1));\nconst quad = array(vec2f(0,1), vec2f(1,1), vec2f(0,0), vec2f(1,0));\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var samp: sampler;\n@group(0) @binding(2) var tex: texture_2d<f32>;\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tvar f: FragParams;\n\tf.position = vec4f(ndc[v.vertexIndex], 0.0, 1.0);\n\tf.texCoord = quad[v.vertexIndex];\n\treturn f;\n}\n\n@fragment\nfn fragMain(f: FragParams ) -> @location(0) vec4f {\n\treturn textureSample(tex, samp, f.texCoord);\n}";let a=Q5.device.createShaderModule({label:"frameShader",code:e._frameShaderCode});d=Q5.device.createSampler({magFilter:"linear",minFilter:"linear"}),l=Q5.device.createBindGroupLayout({label:"frameLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]});let c=Q5.device.createPipelineLayout({bindGroupLayouts:[l]});e._pipelineConfigs[0]={layout:c,vertex:{module:a,entryPoint:"vertexMain"},fragment:{module:a,entryPoint:"fragMain",targets:[{format:r}]},primitive:{topology:"triangle-strip"},multisample:{count:4}},e._pipelines[0]=Q5.device.createRenderPipeline(e._pipelineConfigs[0]),u=Q5.device.createBindGroup({layout:l,entries:[{binding:0,resource:{buffer:b}},{binding:1,resource:d},{binding:2,resource:o.createView()}]}),h=Q5.device.createBindGroup({layout:l,entries:[{binding:0,resource:{buffer:b}},{binding:1,resource:d},{binding:2,resource:s.createView()}]})};e._createCanvas=(n,a,i)=>(t.ctx=t.drawingContext=r.getContext("webgpu"),i.format??=navigator.gpu.getPreferredCanvasFormat(),i.device??=Q5.device,i.alpha&&(i.alphaMode="premultiplied"),e.ctx.configure(i),y(),r),e._resizeCanvas=(t,r)=>{e._setCanvasSize(t,r),y()};let S=!0,w="rgb",C=1;if(e.colorMode){let t=e.colorMode;e.colorMode=function(){t(...arguments),w=e._colorMode,S="rgb"==w,C=e._colorFormat}}const Q=(t,r,n,a)=>{if(!1===S||void 0===r&&!t._isColor&&"number"!=typeof t?!1!==S&&"string"!=typeof t&&Array.isArray(t)?[t,r,n,a]=t:t=e.color(t,r,n,a):void 0===n&&(a=r??C,r=n=t),a??=C,t._isColor){let e=t;S?({r:t,g:r,b:n,a:a}=e):(a=e.a,e=null!=e.c?Q5.OKLCHtoRGB(e.l,e.c,e.h):null!=e.l?Q5.HSLtoRGB(e.h,e.s,e.l):Q5.HSLtoRGB(...Q5.HSBtoHSL(e.h,e.s,e.b)),[t,r,n]=e)}255===C&&(t/=255,r/=255,n/=255,a/=255);let i=_,o=p;i[o++]=t,i[o++]=r,i[o++]=n,i[o++]=a,p=o,f++};let M=!0,P=!0,E=!1,I=!1,R=1,A=2,T=2,k=1,O=1,G=.5,L=.25,D=.5;e.fill=(e,t,r,n)=>{Q(e,t,r,n),M=E=!0,A=f},e.stroke=(e,t,r,n)=>{Q(e,t,r,n),P=I=!0,R=f},e.tint=(e,t,r,n)=>{Q(e,t,r,n),T=f},e.opacity=e=>k=e,e.noFill=()=>M=!1,e.noStroke=()=>P=!1,e.noTint=()=>T=2,e.strokeWeight=e=>{if(void 0===e)return O;e?(e=Math.abs(e),O=e,G=e/2,L=e/4,D=G*W):P=!1},e._getStrokeWeight=()=>[O,G,L,D],e._setStrokeWeight=e=>{[O,G,L,D]=e},e._getFillIdx=()=>A,e._setFillIdx=e=>A=e,e._doFill=()=>M=!0,e._getStrokeIdx=()=>R,e._setStrokeIdx=e=>R=e,e._doStroke=()=>P=!0;const B=e._isGraphics?1e3:Q5.MAX_TRANSFORMS,F=16*B*4,z=new Float32Array(16*B);let U,V=[],N=[],H=0,q=!1;V.push([1,0,0,0,0,-1,0,0,0,0,1,0,0,0,0,1]),z.set(V[0]),e.translate=(e,t)=>{if(!e&&!t)return;let r=U;r[12]+=e*r[0]+t*r[4],r[13]+=e*r[1]+t*r[5],q=!0},e.rotate=e.rotateZ=(t,r)=>{if(!t)return;let n,a;void 0===r?(e._angleMode&&(t*=e._DEGTORAD),n=Math.cos(t),a=Math.sin(t)):(n=t,a=r);let i=U,o=i[0],s=i[1],l=i[4],d=i[5];1!=o||s||l||1!=d?(i[0]=o*n+s*a,i[1]=s*n-o*a,i[4]=l*n+d*a,i[5]=d*n-l*a):(i[0]=n,i[1]=-a,i[4]=a,i[5]=n),q=!0};let W=1;e.scale=(e=1,t,r=1)=>{t??=e,W=Math.max(Math.abs(e),Math.abs(t)),D=G*W;let n=U;n[0]*=e,n[1]*=e,n[2]*=e,n[3]*=e,n[4]*=t,n[5]*=t,n[6]*=t,n[7]*=t,n[8]*=r,n[9]*=r,n[10]*=r,n[11]*=r,q=!0},e.shearX=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.tan(t),n=U,a=n[0],i=n[1],o=n[4],s=n[5];n[4]=o+a*r,n[5]=s+i*r,q=!0},e.shearY=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.tan(t),n=U,a=n[0],i=n[1],o=n[4],s=n[5];n[0]=a+o*r,n[1]=i+s*r,q=!0},e.applyMatrix=(...e)=>{let t;if(t=1==e.length?e[0]:e,t.length<=6){t=[t[0],t[1],0,t[2],t[3],0,t[4]||0,t[5]||0,1]}if(t.length<=9)t=[t[0],t[1],0,t[2],t[3],t[4],0,t[5],0,0,1,0,t[6],t[7],0,t[8]];else if(16!=t.length)throw new Error("Matrix must be a 3x3 or 4x4 array.");U=t.slice(),q=!0};const j=()=>{z.set(U,16*V.length),H=V.length,V.push(U.slice()),q=!1};let $=[];e.pushMatrix=()=>{q&&j(),N.push(H),$.push(W)},e.popMatrix=()=>{if(!N.length)return console.warn("Matrix index stack is empty!");let e=N.pop();U=V[e].slice(),H=e,q=!1,W=$.pop(),D=G*W},e.resetMatrix=()=>{U=V[0].slice(),H=0,W=1,D=G},e.resetMatrix();let X=[];e.pushStyles=()=>{X.push([A,R,O,G,W,D,M,P,E,I,k,T,Et,It,Rt,mt,Fe,Ke,S,w,C,e.Color])},e.popStyles=()=>{let t=X.pop();[A,R,O,G,W,D,M,P,E,I,k,T,Et,It,Rt,mt,Fe,Ke,S,w,C]=t,e._colorFormat=C,e._colorMode=w,e.Color=t.at(-1)},e.push=()=>{e.pushMatrix(),e.pushStyles()},e.pop=()=>{e.popMatrix(),e.popStyles()};let Y=[0,0,0,0];const J=(e,t,r,n,a)=>{let i,o,s,l;if(a&&"corner"!=a)if("center"==a){let a=r/2,d=n/2;i=e-a,o=e+a,s=t-d,l=t+d}else i=e,o=r,s=t,l=n;else i=e,o=e+r,s=t,l=t+n;return Y[0]=i,Y[1]=o,Y[2]=s,Y[3]=l,Y};let K=["zero","one","src-alpha","one-minus-src-alpha","dst","dst-alpha","one-minus-dst-alpha","one-minus-src"],Z=["add","subtract","reverse-subtract","min","max"];const ee={"source-over":[2,3,0,2,3,0],"destination-over":[6,1,0,6,1,0],"source-in":[5,0,0,5,0,0],"destination-in":[0,2,0,0,2,0],"source-out":[6,0,0,6,0,0],"destination-out":[0,3,0,0,3,0],"source-atop":[5,3,0,5,3,0],"destination-atop":[6,2,0,6,2,0],lighter:[1,1,0,1,1,0],darken:[1,1,3,3,5,0],lighten:[1,1,4,3,5,0],replace:[1,0,0,1,0,0]};let te=Object.keys(ee);e.blendConfigs={};for(const[t,r]of Object.entries(ee))e.blendConfigs[t]={color:{srcFactor:K[r[0]],dstFactor:K[r[1]],operation:Z[r[2]]},alpha:{srcFactor:K[r[3]],dstFactor:K[r[4]],operation:Z[r[5]]}};let re,ne,ae,ie,oe,se,le,de,ce,ue,he="source-over";e.blendMode=e=>{if(e==he)return;he=e;let t=te.indexOf(e);-1!=t?x.push(0,t):console.error(`Blend mode "${e}" not supported in q5.js WebGPU.`)},e.clear=()=>{re=!0},e.background=(t,n,a,i)=>{if(t.canvas){e.push(),e.resetMatrix();let n=t;mt="corner",e.image(n,-r.hw,-r.hh,r.w,r.h),e.pop()}else{Q(t,n,a,i);let e=-r.hw,o=r.hw,s=-r.hh,l=r.hh;Pe(e,s,o,s,o,l,e,l,f,0)}},e._beginRender=()=>{const t=o;o=s,s=t;const r=u;u=h,h=r,n=Q5.device.createCommandEncoder(),e._pass=a=n.beginRenderPass({label:"q5-webgpu",colorAttachments:[{view:i,resolveTarget:o.createView(),loadOp:"clear",storeOp:"store",clearValue:[0,0,0,0]}]}),c=h,re||(a.setPipeline(e._pipelines[g]),a.setBindGroup(0,c),a.draw(4)),re=!1},e._render=()=>{let t=16*V.length*4;(!ne||ne.size<t)&&(ne&&ne.destroy(),ne=Q5.device.createBuffer({size:Math.min(2*t,F),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),Q5.device.queue.writeBuffer(ne,0,z.subarray(0,16*V.length));let r=4*p;(!ae||ae.size<r)&&(ae&&ae.destroy(),ae=Q5.device.createBuffer({size:2*r,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),Q5.device.queue.writeBuffer(ae,0,_.subarray(0,p)),e._uniforms[0]=e.width,e._uniforms[1]=e.height,e._uniforms[2]=e.halfWidth,e._uniforms[3]=e.halfHeight,e._uniforms[4]=e._pixelDensity,e._uniforms[5]=e.frameCount,e._uniforms[6]=performance.now(),e._uniforms[7]=e.deltaTime,e._uniforms[8]=e.mouseX,e._uniforms[9]=e.mouseY,e._uniforms[10]=e.mouseIsPressed?1:0,e._uniforms[11]=e.keyCode,e._uniforms[12]=e.keyIsPressed?1:0,Q5.device.queue.writeBuffer(b,0,e._uniforms),de&&ce===ne&&ue===ae||(de=Q5.device.createBindGroup({layout:v,entries:[{binding:0,resource:{buffer:b}},{binding:1,resource:{buffer:ne}},{binding:2,resource:{buffer:ae}}]}),ce=ne,ue=ae),a.setBindGroup(0,de),e._pass.setPipeline(e._pipelines[1]);let n=4*me;if((!ie||ie.size<n)&&(ie&&ie.destroy(),ie=Q5.device.createBuffer({size:2*n,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})),Q5.device.queue.writeBuffer(ie,0,ge.subarray(0,me)),e._pass.setVertexBuffer(0,ie),ot){e._pass.setPipeline(e._pipelines[2]);let t=4*ot;(!oe||oe.size<t)&&(oe&&oe.destroy(),oe=Q5.device.createBuffer({size:2*t,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})),Q5.device.queue.writeBuffer(oe,0,it.subarray(0,ot)),e._pass.setVertexBuffer(1,oe),pt&&(e._pass.setPipeline(e._pipelines[3]),e._pass.setVertexBuffer(1,oe))}if(Bt.length){let t=0;for(let e of Bt)Ut.set(e,t),t+=e.length;let r=4*t;(!se||se.size<r)&&(se&&se.destroy(),se=Q5.device.createBuffer({size:2*r,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),Q5.device.queue.writeBuffer(se,0,Ut.buffer,0,r);let n=0;for(let e of Ft)Vt.set(e,n),n+=e.length;let a=4*n;(!le||le.size<a)&&(le&&le.destroy(),le=Q5.device.createBuffer({label:"textBuffer",size:2*a,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),Q5.device.queue.writeBuffer(le,0,Vt.buffer,0,a),e._textBindGroup=Q5.device.createBindGroup({label:"textBindGroup",layout:bt,entries:[{binding:0,resource:{buffer:se}},{binding:1,resource:{buffer:le}}]})}Q5.device.queue.writeBuffer(Le,0,Oe.buffer,Oe.byteOffset,4*Ge),Q5.device.queue.writeBuffer(Xe,0,je.buffer,je.byteOffset,4*$e);let i=0,o=0,s=0,l=0,d=0,c=-1;for(let t=0;t<x.length;t+=2){let r=x[t+1];if(x[t]!=c){if(0==x[t]){let t=te[r];for(let r=1;r<e._pipelines.length;r++)e._pipelineConfigs[r].fragment.targets[0].blend=e.blendConfigs[t],e._pipelines[r]=Q5.device.createRenderPipeline(e._pipelineConfigs[r]);continue}c=x[t],a.setPipeline(e._pipelines[c]),5==c?(a.setIndexBuffer(Ae,"uint16"),a.setBindGroup(1,De)):6==c&&(a.setIndexBuffer(He,"uint16"),a.setBindGroup(1,Ye))}if(6==c)a.drawIndexed(18,r,0,0,d),d+=r;else if(5==c)a.drawIndexed(6,r,0,0,l),l+=r;else if(4==c||c>=4e3){let n=x[t+2];a.setBindGroup(1,Mt[n].bindGroup),a.setBindGroup(2,e._textBindGroup),a.draw(4,r,0,s),s+=r,t++}else 2==c||3==c||c>=2e3?(a.setBindGroup(1,e._textureBindGroups[r]),a.draw(4,1,o),o+=4):(a.draw(r,1,i),i+=r)}},e._finishRender=()=>{a.end(),a=n.beginRenderPass({colorAttachments:[{view:i,resolveTarget:e.ctx.getCurrentTexture().createView(),loadOp:"clear",storeOp:"store",clearValue:[0,0,0,0]}]}),c=u,a.setPipeline(e._pipelines[m]),a.setBindGroup(0,c),a.draw(4),a.end(),Q5.device.queue.submit([n.finish()]),e._pass=a=n=null,x.length=0,f=2,p=12,V.length=1,N.length=0,e._texture=o,me=0,ot=0,pt>0&&(e._textureBindGroups.length=ft),pt=0,Bt.length=0,Ft.length=0,Ge=0,$e=0,Q5.device.queue.onSubmittedWorkDone().then((()=>{for(let t of e._buffers)t.destroy();e._buffers=[]}))};let fe=1;e._shapesShaderCode=e._baseShaderCode+"\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex : u32,\n\t@location(0) pos: vec2f,\n\t@location(1) colorIndex: f32,\n\t@location(2) matrixIndex: f32\n}\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) color: vec4f\n}\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tvar vert = transformVertex(v.pos, v.matrixIndex);\n\n\tvar f: FragParams;\n\tf.position = vert;\n\tf.color = colors[i32(v.colorIndex)];\n\treturn f;\n}\n\n@fragment\nfn fragMain(f: FragParams) -> @location(0) vec4f {\n\treturn f.color;\n}\n";let pe=Q5.device.createShaderModule({label:"shapesShader",code:e._shapesShaderCode}),ge=new Float32Array(e._isGraphics?1e3:1e7),me=0;const xe=2*Math.PI;Math.PI;let _e=Q5.device.createPipelineLayout({label:"shapesPipelineLayout",bindGroupLayouts:e._bindGroupLayouts});e._pipelineConfigs[1]={label:"shapesPipeline",layout:_e,vertex:{module:pe,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:pe,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs["source-over"]}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[1]=Q5.device.createRenderPipeline(e._pipelineConfigs[1]);const ve=(e,t,r,n)=>{let a=ge,i=me;a[i++]=e,a[i++]=t,a[i++]=r,a[i++]=n,me=i};let be="round",ye="round";e.strokeCap=e=>be=e,e.strokeJoin=e=>ye=e,e.lineMode=()=>{be="square",ye="none"};let Se=20;e.curveDetail=e=>Se=e;let we,Ce=20;e.bezierDetail=e=>Ce=e;let Qe=[],Me=[];function Pe(e,t,r,n,a,i,o,s,l,d){ve(e,t,l,d),ve(r,n,l,d),ve(o,s,l,d),ve(a,i,l,d),x.push(fe,4)}e.beginShape=()=>{we=0,Qe=[],Me=[]},e.vertex=(e,t)=>{q&&j(),Qe.push(e,t,A,H),we++},e.curveVertex=(e,t)=>{q&&j(),Me.push({x:e,y:t})},e.bezierVertex=function(e,t,r,n,a,i){if(0===we)throw new Error("Shape needs a vertex()");q&&j();let o,s,l=4*(we-1),d=Qe[l],c=Qe[l+1],u=1/Ce,h=4==arguments.length;h&&(a=r,i=n);let f=1+u;for(let l=u;l<=f;l+=u){let u=l*l,f=1-l,p=f*f;if(h)o=p*d+2*f*l*e+u*a,s=p*c+2*f*l*t+u*i;else{let h=u*l,g=p*f;o=g*d+3*p*l*e+3*f*u*r+h*a,s=g*c+3*p*l*t+3*f*u*n+h*i}Qe.push(o,s,A,H),we++}},e.quadraticVertex=(t,r,n,a)=>e.bezierVertex(t,r,n,a),e.endShape=t=>{if(Me.length>0){let e=[...Me];if(e.length<4)for(;e.length<4;)e.unshift(e[0]),e.push(e[e.length-1]);let t=1/Se;for(let r=0;r<e.length-3;r++){let n=e[r],a=e[r+1],i=e[r+2],o=e[r+3];for(let e=0;e<=1;e+=t){let t=e*e,r=t*e,s=.5*(2*a.x+(-n.x+i.x)*e+(2*n.x-5*a.x+4*i.x-o.x)*t+(-n.x+3*a.x-3*i.x+o.x)*r),l=.5*(2*a.y+(-n.y+i.y)*e+(2*n.y-5*a.y+4*i.y-o.y)*t+(-n.y+3*a.y-3*i.y+o.y)*r);Qe.push(s,l,A,H),we++}}}if(we){if(1==we)return e.point(Qe[0],Qe[1]);if(2==we)return e.line(Qe[0],Qe[1],Qe[4],Qe[5]);if(t){let e=0,t=4*(we-1),r=Qe[e],n=Qe[e+1],a=Qe[t],i=Qe[t+1];r===a&&n===i||(Qe.push(r,n,Qe[e+2],Qe[e+3]),we++)}if(M)if(5==we)ve(Qe[0],Qe[1],Qe[2],Qe[3]),ve(Qe[4],Qe[5],Qe[6],Qe[7]),ve(Qe[12],Qe[13],Qe[14],Qe[15]),ve(Qe[8],Qe[9],Qe[10],Qe[11]),x.push(fe,4);else{for(let e=1;e<we-1;e++){let t=0,r=4*e,n=4*(e+1);ve(Qe[t],Qe[t+1],Qe[t+2],Qe[t+3]),ve(Qe[r],Qe[r+1],Qe[r+2],Qe[r+3]),ve(Qe[n],Qe[n+1],Qe[n+2],Qe[n+3])}x.push(fe,3*(we-2))}if(P){for(let t=0;t<we-1;t++){let r=4*t,n=4*(t+1);e.line(Qe[r],Qe[r+1],Qe[n],Qe[n+1])}let r=4*(we-1),n=0;t&&e.line(Qe[r],Qe[r+1],Qe[n],Qe[n+1])}we=0,Qe=[],Me=[]}},e.curve=(t,r,n,a,i,o,s,l)=>{e.beginShape(),e.curveVertex(t,r),e.curveVertex(n,a),e.curveVertex(i,o),e.curveVertex(s,l),e.endShape()},e.bezier=(t,r,n,a,i,o,s,l)=>{e.beginShape(),e.vertex(t,r),e.bezierVertex(n,a,i,o,s,l),e.endShape()},e.triangle=(t,r,n,a,i,o)=>{e.beginShape(),e.vertex(t,r),e.vertex(n,a),e.vertex(i,o),e.endShape(!0)},e.quad=(t,r,n,a,i,o,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(n,a),e.vertex(i,o),e.vertex(s,l),e.endShape(!0)},e.plane=(e,t,r,n)=>{n??=r;let[a,i,o,s]=J(e,t,r,n,"center");q&&j(),Pe(a,o,i,o,i,s,a,s,A,H)};let Ee=5;e._rectShaderCode=e._baseShaderCode+"\nstruct Rect {\n\tcenter: vec2f,\n\textents: vec2f,\n\troundedRadius: f32,\n\tstrokeWeight: f32,\n\tfillIndex: f32,\n\tstrokeIndex: f32,\n\tmatrixIndex: f32,\n\tpadding0: f32, // can't use vec3f for alignment\n\tpadding1: vec2f,\n\tpadding2: vec4f\n};\n\nstruct VertexParams {\n\t@builtin(vertex_index) vertIndex: u32,\n\t@builtin(instance_index) instIndex: u32\n};\n\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) local: vec2f,\n\t@location(1) extents: vec2f,\n\t@location(2) roundedRadius: f32,\n\t@location(3) strokeWeight: f32,\n\t@location(4) fill: vec4f,\n\t@location(5) stroke: vec4f,\n\t@location(6) blend: vec4f\n};\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\n@group(1) @binding(0) var<storage, read> rects: array<Rect>;\n\nconst quad = array(\n\tvec2f(-1.0, -1.0),\n\tvec2f( 1.0, -1.0),\n\tvec2f(-1.0, 1.0),\n\tvec2f( 1.0, 1.0)\n);\nconst transparent = vec4f(0.0);\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tlet rect = rects[v.instIndex];\n\n\tlet halfStrokeSize = vec2f(rect.strokeWeight * 0.5);\n\tlet quadSize = rect.extents + halfStrokeSize;\n\tlet pos = (quad[v.vertIndex] * quadSize) + rect.center;\n\n\tlet local = pos - rect.center;\n\n\tvar f: FragParams;\n\tf.position = transformVertex(pos, rect.matrixIndex);\n\n\tf.local = local;\n\tf.extents = rect.extents;\n\tf.roundedRadius = rect.roundedRadius;\n\tf.strokeWeight = rect.strokeWeight;\n\n\tlet fill = colors[i32(rect.fillIndex)];\n\tlet stroke = colors[i32(rect.strokeIndex)];\n\tf.fill = fill;\n\tf.stroke = stroke;\n\n\t// Source-over blend: stroke over fill (pre-multiplied alpha)\n\tif (fill.a != 0.0 && stroke.a != 1.0) {\n\t\tlet outAlpha = stroke.a + fill.a * (1.0 - stroke.a);\n\t\tlet outColor = stroke.rgb * stroke.a + fill.rgb * fill.a * (1.0 - stroke.a);\n\t\tf.blend = vec4f(outColor / max(outAlpha, 1e-5), outAlpha);\n\t}\n\treturn f;\n}\n\nfn sdRoundRect(p: vec2f, extents: vec2f, radius: f32) -> f32 {\n\tlet q = abs(p) - extents + vec2f(radius);\n\treturn length(max(q, vec2f(0.0))) - radius + min(max(q.x, q.y), 0.0);\n}\n\n@fragment\nfn fragMain(f: FragParams) -> @location(0) vec4f {\n\tlet dist = select(\n\t\tmax(abs(f.local.x) - f.extents.x, abs(f.local.y) - f.extents.y), // sharp\n\t\tsdRoundRect(f.local, f.extents, f.roundedRadius), // rounded\n\t\tf.roundedRadius > 0.0\n\t);\n\n\t// fill only\n\tif (f.fill.a != 0.0 && f.strokeWeight == 0.0) {\n\t\tif (dist <= 0.0) {\n\t\t\treturn f.fill;\n\t\t}\n\t\treturn transparent;\n\t}\n\n\tlet halfStroke = f.strokeWeight * 0.5;\n\tlet inner = dist + halfStroke;\n\n\tif (f.fill.a != 0.0) {\n\t\tif (inner <= 0.0) {\n\t\t\treturn f.fill;\n\t\t}\n\t\tif (dist <= 0.0 && f.stroke.a != 1.0) {\n\t\t\treturn f.blend;\n\t\t}\n\t}\n\n\tlet outer = dist - halfStroke;\n\n\tif (outer <= 0.0 && inner >= 0.0) {\n\t\treturn f.stroke;\n\t}\n\n\treturn transparent;\n}\n\t";let Ie=Q5.device.createShaderModule({label:"rectShader",code:e._rectShaderCode}),Re=new Uint16Array([0,1,2,2,1,3]),Ae=Q5.device.createBuffer({size:Re.byteLength,usage:GPUBufferUsage.INDEX,mappedAtCreation:!0});new Uint16Array(Ae.getMappedRange()).set(Re),Ae.unmap();let Te=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}}]}),ke=Q5.device.createPipelineLayout({label:"rectPipelineLayout",bindGroupLayouts:[...e._bindGroupLayouts,Te]});e._pipelineConfigs[5]={label:"rectPipeline",layout:ke,vertex:{module:Ie,entryPoint:"vertexMain",buffers:[]},fragment:{module:Ie,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs["source-over"]}]},primitive:{topology:"triangle-list"},multisample:{count:4}},e._pipelines[5]=Q5.device.createRenderPipeline(e._pipelineConfigs[5]);let Oe=new Float32Array(16*Q5.MAX_RECTS),Ge=0,Le=Q5.device.createBuffer({size:Oe.byteLength,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),De=Q5.device.createBindGroup({layout:Te,entries:[{binding:0,resource:{buffer:Le}}]});function Be(e,t,r,n,a,i,o){let s=Oe,l=Ge;s[l]=e,s[l+1]=t,s[l+2]=r,s[l+3]=n,s[l+4]=a,s[l+5]=i,s[l+6]=o,s[l+7]=R,s[l+8]=H,Ge+=16,x.push(Ee,1)}let Fe="corner";e.rectMode=e=>Fe=e,e._getRectMode=()=>Fe;let ze=[0,0,0,0];function Ue(t,r,n,a,i,o,s){let l=n-t,d=a-r,c=Math.hypot(l,d);if(0===c)return;let u=Math.atan2(d,l),h=(t+n)/2,f=(r+a)/2;e._angleMode&&(u*=e._RADTODEG),e.pushMatrix(),e.translate(h,f),e.rotate(u),q&&j(),Be(0,0,c/2+i,i,i,o,s),e.popMatrix()}e.rect=(e,t,r,n,a=0)=>{let i,o;q&&j(),[e,t,i,o]=function(e,t,r,n){let a=r/2,i=n/2;return"center"!=Fe&&("corner"==Fe?(e+=a,t+=i,a=Math.abs(a),i=Math.abs(i)):"radius"==Fe?(a=r,i=n):"corners"==Fe&&(a=Math.abs((r-e)/2),i=Math.abs((n-t)/2),e=(e+r)/2,t=(t+n)/2)),ze[0]=e,ze[1]=t,ze[2]=a,ze[3]=i,ze}(e,t,r,n),Be(e,t,i,o,a,P?O:0,M?A:0)},e.square=(t,r,n,a)=>e.rect(t,r,n,n,a),e.capsule=(e,t,r,n,a)=>{Ue(e,t,r,n,a,P?O:0,M?A:0)},e.line=(e,t,r,n)=>{P&&Ue(e,t,r,n,L,G,0)};e._ellipseShaderCode=e._baseShaderCode+"\nstruct Ellipse {\n\tcenter: vec2f,\n\tsize: vec2f,\n\tstartAngle: f32,\n\tendAngle: f32,\n\tstrokeWeight: f32,\n\tfillIndex: f32,\n\tstrokeIndex: f32,\n\tmatrixIndex: f32,\n\tpadding0: vec2f,\n\tpadding1: vec4f\n};\n\nstruct VertexParams {\n\t@builtin(vertex_index) vertIndex: u32,\n\t@builtin(instance_index) instIndex: u32\n};\n\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) outerEdge: vec2f,\n\t@location(1) fillEdge: vec2f,\n\t@location(2) innerEdge: vec2f,\n\t@location(3) strokeWeight: f32,\n\t@location(4) fill: vec4f,\n\t@location(5) stroke: vec4f,\n\t@location(6) blend: vec4f\n};\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\n@group(1) @binding(0) var<storage, read> ellipses: array<Ellipse>;\n\nconst PI = 3.141592653589793;\nconst segments = 6.0;\nconst expansion = 1.0 / cos(PI / segments);\nconst antiAlias = 0.015625; // 1/64\nconst transparent = vec4f(0.0);\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tlet ellipse = ellipses[v.instIndex];\n\tvar pos = ellipse.center;\n\tvar local = vec2f(0.0);\n\tlet start = ellipse.startAngle;\n\tlet end = ellipse.endAngle;\n\tlet arc = end - start;\n\tlet halfStrokeSize = vec2f(ellipse.strokeWeight * 0.5);\n\n\tlet fanSize = (ellipse.size + halfStrokeSize) * expansion;\n\n\tif (v.vertIndex != 0) {\n\t\tlet theta = start + (f32(v.vertIndex - 1) / segments) * arc;\n\t\tlocal = vec2f(cos(theta), sin(theta));\n\t\tpos = ellipse.center + local * fanSize;\n\t}\n\n\tlet dist = pos - ellipse.center;\n\n\tvar f: FragParams;\n\tf.position = transformVertex(pos, ellipse.matrixIndex);\n\tf.outerEdge = dist / (ellipse.size + halfStrokeSize);\n\tf.fillEdge = dist / ellipse.size;\n\tf.innerEdge = dist / (ellipse.size - halfStrokeSize);\n\tf.strokeWeight = ellipse.strokeWeight;\n\n\tlet fill = colors[i32(ellipse.fillIndex)];\n\tlet stroke = colors[i32(ellipse.strokeIndex)];\n\tf.fill = fill;\n\tf.stroke = stroke;\n\n\t// Source-over blend: stroke over fill (pre-multiplied alpha)\n\tif (fill.a != 0.0 && stroke.a != 1.0) {\n\t\tlet outAlpha = stroke.a + fill.a * (1.0 - stroke.a);\n\t\tlet outColor = stroke.rgb * stroke.a + fill.rgb * fill.a * (1.0 - stroke.a);\n\t\tf.blend = vec4f(outColor / max(outAlpha, 1e-5), outAlpha);\n\t}\n\treturn f;\n}\n\n@fragment\nfn fragMain(f: FragParams) -> @location(0) vec4f {\n\tlet fillEdge = length(f.fillEdge);\n\n\t// disable AA for very thin strokes\n\tlet aa = select(antiAlias, 0.0, f.strokeWeight <= 1.0);\n\n\tif (f.fill.a != 0.0 && f.strokeWeight == 0.0) {\n\t\tif (fillEdge > 1.0) {\n\t\t\treturn transparent;\n\t\t}\n\t\tlet fillAlpha = 1.0 - smoothstep(1.0 - aa, 1.0, fillEdge);\n\t\treturn vec4f(f.fill.rgb, f.fill.a * fillAlpha);\n\t}\n\n\tlet innerEdge = length(f.innerEdge);\n\t\n\tif (f.fill.a != 0.0 && fillEdge < 1.0) {\n\t\tif (innerEdge < 1.0) {\n\t\t\treturn f.fill;\n\t\t}\n\t\tlet tInner = smoothstep(1.0, 1.0 + aa, innerEdge);\n\t\tlet tOuter = smoothstep(1.0 - aa, 1.0, fillEdge);\n\t\tif (f.stroke.a != 1.0) {\n\t\t\tlet fillBlend = mix(f.fill, f.blend, tInner);\n\t\t\treturn mix(fillBlend, f.stroke, tOuter);\n\t\t} else {\n\t\t\tlet fillBlend = mix(f.fill, f.stroke, tInner);\n\t\t\treturn mix(fillBlend, f.stroke, tOuter);\n\t\t}\n\t}\n\t\n\tif (innerEdge < 1.0) {\n\t\treturn transparent;\n\t}\n\n\tlet outerEdge = length(f.outerEdge);\n\tlet outerAlpha = 1.0 - smoothstep(1.0 - aa, 1.0, outerEdge);\n\tlet innerAlpha = smoothstep(1.0, 1.0 + aa, innerEdge);\n\tlet strokeAlpha = innerAlpha * outerAlpha;\n\treturn vec4f(f.stroke.rgb, f.stroke.a * strokeAlpha);\n}\n\t\t";let Ve=Q5.device.createShaderModule({label:"ellipseShader",code:e._ellipseShaderCode}),Ne=new Uint16Array([0,1,2,0,2,3,0,3,4,0,4,5,0,5,6,0,6,7]),He=Q5.device.createBuffer({size:Ne.byteLength,usage:GPUBufferUsage.INDEX,mappedAtCreation:!0});new Uint16Array(He.getMappedRange()).set(Ne),He.unmap();let qe=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}}]}),We=Q5.device.createPipelineLayout({label:"ellipsePipelineLayout",bindGroupLayouts:[...e._bindGroupLayouts,qe]});e._pipelineConfigs[6]={label:"ellipsePipeline",layout:We,vertex:{module:Ve,entryPoint:"vertexMain",buffers:[]},fragment:{module:Ve,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs["source-over"]}]},primitive:{topology:"triangle-list"},multisample:{count:4}},e._pipelines[6]=Q5.device.createRenderPipeline(e._pipelineConfigs[6]);let je=new Float32Array(16*Q5.MAX_ELLIPSES),$e=0,Xe=Q5.device.createBuffer({size:je.byteLength,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),Ye=Q5.device.createBindGroup({layout:qe,entries:[{binding:0,resource:{buffer:Xe}}]});function Je(e,t,r,n,a,i,o,s){let l=je,d=$e;l[d]=e,l[d+1]=t,l[d+2]=r,l[d+3]=n,l[d+4]=a,l[d+5]=i,l[d+6]=o,l[d+7]=s?A:0,l[d+8]=R,l[d+9]=H,$e+=16,x.push(6,1)}let Ke="center";e.ellipseMode=e=>Ke=e,e._getEllipseMode=()=>Ke;let Ze=[0,0,0,0];function et(e,t,r,n){let a,i;return n??=r,"center"==Ke?(a=r/2,i=n/2):"radius"==Ke?(a=r,i=n):"corner"==Ke?(e+=r/2,t+=n/2,a=r/2,i=n/2):"corners"==Ke&&(a=r-(e=(e+r)/2),i=n-(t=(t+n)/2)),Ze[0]=e,Ze[1]=t,Ze[2]=a,Ze[3]=i,Ze}e.ellipse=(e,t,r,n)=>{let a,i;[e,t,a,i]=et(e,t,r,n),q&&j(),Je(e,t,a,i,0,xe,P?O:0,M)},e.circle=(t,r,n)=>e.ellipse(t,r,n,n),e.arc=(t,r,n,a,i,o)=>{if(i===o)return e.ellipse(t,r,n,a);if(e._angleMode&&(i=e.radians(i),o=e.radians(o)),(i%=xe)<0&&(i+=xe),(o%=xe)<0&&(o+=xe),i>o&&(o+=xe),i==o)return e.ellipse(t,r,n,a);let s,l;[t,r,s,l]=et(t,r,n,a),q&&j(),Je(t,r,s,l,i,o,P?O:0,M)},e.point=(e,t)=>{q&&j(),D<=.5?Be(e,t,G,G,0,O,0):Je(e,t,G,G,0,xe,O,0)};let tt=2,rt=3;e._imageShaderCode=e._baseShaderCode+"\n\tstruct VertexParams {\n\t\t@builtin(vertex_index) vertexIndex : u32,\n\t\t@location(0) pos: vec2f,\n\t\t@location(1) texCoord: vec2f,\n\t\t@location(2) tintIndex: f32,\n\t\t@location(3) matrixIndex: f32,\n\t\t@location(4) imageAlpha: f32\n\t}\n\tstruct FragParams {\n\t\t@builtin(position) position: vec4f,\n\t\t@location(0) texCoord: vec2f,\n\t\t@location(1) tintColor: vec4f,\n\t\t@location(2) imageAlpha: f32\n\t}\n\t\n\t@group(0) @binding(0) var<uniform> q: Q5;\n\t@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n\t@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\t\n\t@group(1) @binding(0) var samp: sampler;\n\t@group(1) @binding(1) var tex: texture_2d<f32>;\n\t\n\tfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\t\tvar vert = vec4f(pos, 0f, 1f);\n\t\tvert = transforms[i32(matrixIndex)] * vert;\n\t\tvert.x /= q.halfWidth;\n\t\tvert.y /= q.halfHeight;\n\t\treturn vert;\n\t}\n\t\n\tfn applyTint(texColor: vec4f, tintColor: vec4f) -> vec4f {\n\t\t// apply the tint color to the sampled texture color at full strength\n\t\tlet tinted = vec4f(texColor.rgb * tintColor.rgb, texColor.a);\n\t\t// mix in the tint using the tint alpha as the blend strength\n\t\treturn mix(texColor, tinted, tintColor.a);\n\t}\n\t\n\t@vertex\n\tfn vertexMain(v: VertexParams) -> FragParams {\n\t\tvar vert = transformVertex(v.pos, v.matrixIndex);\n\t\n\t\tvar f: FragParams;\n\t\tf.position = vert;\n\t\tf.texCoord = v.texCoord;\n\t\tf.tintColor = colors[i32(v.tintIndex)];\n\t\tf.imageAlpha = v.imageAlpha;\n\t\treturn f;\n\t}\n\t\n\t@fragment\n\tfn fragMain(f: FragParams) -> @location(0) vec4f {\n\t\tvar texColor = textureSample(tex, samp, f.texCoord);\n\t\ttexColor.a *= f.imageAlpha;\n\t\treturn applyTint(texColor, f.tintColor);\n\t}\n\t";let nt=Q5.device.createShaderModule({label:"imageShader",code:e._imageShaderCode});e._videoShaderCode=e._imageShaderCode.replace("texture_2d<f32>","texture_external").replace("textureSample","textureSampleBaseClampToEdge");let at=Q5.device.createShaderModule({label:"videoShader",code:e._videoShaderCode}),it=new Float32Array(e._isGraphics?1e3:1e7),ot=0,st={arrayStride:28,attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"},{shaderLocation:2,offset:16,format:"float32"},{shaderLocation:3,offset:20,format:"float32"},{shaderLocation:4,offset:24,format:"float32"}]},lt=Q5.device.createBindGroupLayout({label:"textureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]}),dt=Q5.device.createBindGroupLayout({label:"videoTextureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,externalTexture:{}}]}),ct=Q5.device.createPipelineLayout({label:"imagePipelineLayout",bindGroupLayouts:[...e._bindGroupLayouts,lt]}),ut=Q5.device.createPipelineLayout({label:"videoPipelineLayout",bindGroupLayouts:[...e._bindGroupLayouts,dt]});e._pipelineConfigs[2]={label:"imagePipeline",layout:ct,vertex:{module:nt,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},st]},fragment:{module:nt,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs["source-over"]}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[2]=Q5.device.createRenderPipeline(e._pipelineConfigs[2]),e._pipelineConfigs[3]={label:"videoPipeline",layout:ut,vertex:{module:at,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},st]},fragment:{module:at,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs["source-over"]}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[3]=Q5.device.createRenderPipeline(e._pipelineConfigs[3]),e._textureBindGroups=[],r&&(r.convertToBlob=async t=>{let r=e._drawStack?.length;r&&(e._render(),e._finishRender());let n=e._texture;r&&e._beginRender();let a=n.width,i=n.height,o=256*Math.ceil(4*a/256),s=Q5.device.createBuffer({size:o*i,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),l=Q5.device.createCommandEncoder();l.copyTextureToBuffer({texture:n},{buffer:s,bytesPerRow:o,rowsPerImage:i},{width:a,height:i}),Q5.device.queue.submit([l.finish()]),await s.mapAsync(GPUMapMode.READ);let d=new Uint8Array(s.getMappedRange()),c=new Uint8Array(a*i*4);for(let e=0;e<i;e++){const t=e*o,r=e*a*4;for(let e=0;e<a;e++){const n=t+4*e,a=r+4*e;c[a+0]=d[n+2],c[a+1]=d[n+1],c[a+2]=d[n+0],c[a+3]=d[n+3]}}s.unmap();let u=e.canvas.colorSpace;c=new Uint8ClampedArray(c.buffer),c=new ImageData(c,a,i,{colorSpace:u});let h=new OffscreenCanvas(a,i);return h.getContext("2d",{colorSpace:u}).putImageData(c,0,0),e._buffers.push(s),await h.convertToBlob(t)});let ht=t=>{e._imageSampler=Q5.device.createSampler({magFilter:t,minFilter:t})};e.smooth=()=>ht("linear"),e.noSmooth=()=>ht("nearest"),e.smooth();let ft=0,pt=0;e._addTexture=(t,r)=>{let n=t.canvas||t;if(!r){if(t._texture)return;let a=[n.width,n.height,1];r=Q5.device.createTexture({size:a,format:"bgra8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_SRC|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),Q5.device.queue.copyExternalImageToTexture({source:n},{texture:r,colorSpace:e.canvas.colorSpace},a)}r.index=ft+pt,t._texture=r,e._textureBindGroups[r.index]=Q5.device.createBindGroup({label:t.src||r.label||"canvas",layout:lt,entries:[{binding:0,resource:e._imageSampler},{binding:1,resource:r.createView()}]}),ft++},e.loadImage=(t,r)=>e._g.loadImage(t,(t=>{e._makeDrawable(t),r&&r(t)})),e._makeDrawable=t=>{e._addTexture(t),t._owner=e},e.createImage=(t,r,n)=>{let a=e._g.createImage(t,r,n);return e._makeDrawable(a),a.modified=!0,a};let gt=e.createGraphics;e.createGraphics=(t,r,n={})=>{if(!Q5.experimental)throw new Error("createGraphics is disabled by default in q5 WebGPU. See issue https://github.com/q5js/q5.js/issues/104 for details.");"string"==typeof n&&(n={renderer:n}),n.renderer??="c2d";let a=gt(t,r,n);return a.canvas.webgpu?(e._addTexture(a,a._frameA),e._addTexture(a,a._frameB),a._beginRender()):(e._makeDrawable(a),a.modified=!0),a};let mt="corner";e.imageMode=e=>mt=e,e._getImageMode=()=>mt,e._uniforms=new Float32Array(13);const xt=(e,t,r,n,a,i,o)=>{let s=it,l=ot;s[l++]=e,s[l++]=t,s[l++]=r,s[l++]=n,s[l++]=a,s[l++]=i,s[l++]=o,ot=l};e.image=(t,r=0,n=0,a,i,o=0,s=0,l,d)=>{if(!t)return;let c;if(null==t._texture){if(c="VIDEO"==t.tagName,!t.width||c&&!t.currentTime)return;t.flipped&&e.scale(-1,1)}q&&j();let u=t.canvas||t,h=u.width,f=u.height,p=t._pixelDensity||1,g=t._isGraphics&&t._drawStack?.length;g&&(t._render(),t._finishRender()),t.modified&&(Q5.device.queue.copyExternalImageToTexture({source:u},{texture:t._texture,colorSpace:e.canvas.colorSpace},[h,f,1]),t.frameCount++,t.modified=!1),a??=t.defaultWidth||t.videoWidth,i??=t.defaultHeight||t.videoHeight,l??=h,d??=f,o*=p,s*=p;let[m,_,v,b]=J(r,n,a,i,mt),y=o/h,S=s/f,w=(o+l)/h,C=(s+d)/f,Q=H,M=T,P=k;if(xt(m,v,y,S,M,Q,P),xt(_,v,w,S,M,Q,P),xt(m,b,y,C,M,Q,P),xt(_,b,w,C,M,Q,P),c){let r=Q5.device.importExternalTexture({source:t});e._textureBindGroups.push(Q5.device.createBindGroup({layout:dt,entries:[{binding:0,resource:e._imageSampler},{binding:1,resource:r}]})),x.push(rt,e._textureBindGroups.length-1),t.flipped&&e.scale(-1,1)}else x.push(tt,t._texture.index),g&&(t.resetMatrix(),t._beginRender(),t.frameCount++)};let _t=4;e._textShaderCode=e._baseShaderCode+"\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex : u32,\n\t@builtin(instance_index) instanceIndex : u32\n}\nstruct FragParams {\n\t@builtin(position) position : vec4f,\n\t@location(0) texCoord : vec2f,\n\t@location(1) fillColor : vec4f,\n\t@location(2) strokeColor : vec4f,\n\t@location(3) strokeWeight : f32,\n\t@location(4) edge : f32\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\tmatrixIndex: f32,\n\tfillIndex: f32,\n\tstrokeIndex: f32,\n\tstrokeWeight: f32,\n\tedge: f32\n}\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\n@group(1) @binding(0) var fontTexture: texture_2d<f32>;\n@group(1) @binding(1) var fontSampler: sampler;\n@group(1) @binding(2) var<storage> fontChars: array<Char>;\n\n@group(2) @binding(0) var<storage> textChars: array<vec4f>;\n@group(2) @binding(1) var<storage> textMetadata: array<Text>;\n\nconst quad = array(vec2f(0, 1), vec2f(1, 1), vec2f(0, 0), vec2f(1, 0));\nconst uvs = array(vec2f(0, 1), vec2f(1, 1), vec2f(0, 0), vec2f(1, 0));\n\nfn calcPos(i: u32, char: vec4f, fontChar: Char, text: Text) -> vec2f {\n\treturn ((quad[i] * fontChar.size + char.xy + fontChar.offset) *\n\t\ttext.scale) + text.pos;\n}\n\nfn calcUV(i: u32, fontChar: Char) -> vec2f {\n\treturn uvs[i] * fontChar.texExtent + fontChar.texOffset;\n}\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\nfn calcDist(texCoord: vec2f, edgeWidth: f32) -> f32 {\n\tlet c = textureSample(fontTexture, fontSampler, texCoord);\n\tlet sigDist = max(min(c.r, c.g), min(max(c.r, c.g), c.b)) - edgeWidth;\n\n\tlet pxRange = 4.0;\n\tlet sz = vec2f(textureDimensions(fontTexture, 0));\n\tlet dx = sz.x * length(vec2f(dpdxFine(texCoord.x), dpdyFine(texCoord.x)));\n\tlet dy = sz.y * length(vec2f(dpdxFine(texCoord.y), dpdyFine(texCoord.y)));\n\tlet toPixels = pxRange * inverseSqrt(dx * dx + dy * dy);\n\treturn sigDist * toPixels;\n}\n\n@vertex\nfn vertexMain(v : VertexParams) -> FragParams {\n\tlet char = textChars[v.instanceIndex];\n\tlet text = textMetadata[i32(char.w)];\n\tlet fontChar = fontChars[i32(char.z)];\n\tlet pos = calcPos(v.vertexIndex, char, fontChar, text);\n\n\tvar vert = transformVertex(pos, text.matrixIndex);\n\n\tvar f : FragParams;\n\tf.position = vert;\n\tf.texCoord = calcUV(v.vertexIndex, fontChar);\n\tf.fillColor = colors[i32(text.fillIndex)];\n\tf.strokeColor = colors[i32(text.strokeIndex)];\n\tf.strokeWeight = text.strokeWeight;\n\tf.edge = text.edge;\n\treturn f;\n}\n\n@fragment\nfn fragMain(f : FragParams) -> @location(0) vec4f {\n\tlet edge = f.edge;\n\tlet dist = calcDist(f.texCoord, edge);\n\n\tif (f.strokeWeight == 0.0) {\n\t\tlet fillAlpha = smoothstep(-edge, edge, dist);\n\t\tlet color = vec4f(f.fillColor.rgb, f.fillColor.a * fillAlpha);\n\t\tif (color.a < 0.01) {\n\t\t\tdiscard;\n\t\t}\n\t\treturn color;\n\t}\n\n\tlet halfStroke = f.strokeWeight / 2.0;\n\tlet fillAlpha = smoothstep(-edge, edge, dist - halfStroke);\n\tlet strokeAlpha = smoothstep(-edge, edge, dist + halfStroke);\n\tvar color = mix(f.strokeColor, f.fillColor, fillAlpha);\n\tcolor = vec4f(color.rgb, color.a * strokeAlpha);\n\tif (color.a < 0.01) {\n\t\tdiscard;\n\t}\n\treturn color;\n}\n";let vt=Q5.device.createShaderModule({label:"textShader",code:e._textShaderCode}),bt=Q5.device.createBindGroupLayout({label:"textBindGroupLayout",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"}}]}),yt=Q5.device.createSampler({minFilter:"linear",magFilter:"linear",mipmapFilter:"linear",maxAnisotropy:16}),St=Q5.device.createBindGroupLayout({label:"fontBindGroupLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,texture:{}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{}},{binding:2,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}}]}),wt=Q5.device.createPipelineLayout({bindGroupLayouts:[...e._bindGroupLayouts,St,bt]});e._pipelineConfigs[4]={label:"textPipeline",layout:wt,vertex:{module:vt,entryPoint:"vertexMain"},fragment:{module:vt,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs["source-over"]}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[4]=Q5.device.createRenderPipeline(e._pipelineConfigs[4]);class Ct{constructor(e,t,r,n){this.bindGroup=e,this.lineHeight=t,this.chars=r,this.kernings=n;let a=Object.values(r);this.charCount=a.length,this.defaultChar=a[0]}getChar(e){return this.chars[e]??this.defaultChar}getXAdvance(e,t=-1){let r=this.getChar(e);if(t>=0){let n=this.kernings.get(e);if(n)return r.xadvance+(n.get(t)??0)}return r.xadvance}}let Qt,Mt=[],Pt={};e.loadFont=(t="sans-serif",r)=>{if(Qt=!0,t.startsWith("https://fonts.googleapis.com/css"))return e._g.loadFont(t,r);let n=t.slice(t.lastIndexOf(".")+1);if(t==n){let e=t;Pt[e]=null,t=`https://q5js.org/fonts/${e}-msdf.json`,0!=Q5.online&&navigator.onLine||(t=`/node_modules/q5/builtinFonts/${e}-msdf.json`),n="json"}if("json"!=n)return e._g.loadFont(t,r);let a=t.slice(t.lastIndexOf("/")+1,t.lastIndexOf("-")),i={family:a};return i.promise=async function(t,r,n){let a,i,o=t.substring(0,t.lastIndexOf("-"));try{[a,i]=await Promise.all([fetch(t).then((e=>{if(404==e.status)throw new Error("404");return e.json()})),fetch(o+".png").then((e=>e.blob())).then((e=>createImageBitmap(e)))])}catch(e){return console.error("Error loading font:",e),""}let s=[i.width,i.height,1],l=Q5.device.createTexture({label:`MSDF ${r}`,size:s,format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:i},{texture:l},s),"string"==typeof a.chars&&(a.chars=Q5.CSV.parse(a.chars," "),a.kernings=Q5.CSV.parse(a.kernings," "));let d=a.chars.length,c=Q5.device.createBuffer({size:32*d,usage:GPUBufferUsage.STORAGE,mappedAtCreation:!0}),u=new Float32Array(c.getMappedRange()),h=1/a.common.scaleW,f=1/a.common.scaleH,p={},g=0;for(let[e,t]of a.chars.entries())p[t.id]=t,p[t.id].charIndex=e,u[g]=t.x*h,u[g+1]=t.y*f,u[g+2]=t.width*h,u[g+3]=t.height*f,u[g+4]=t.width,u[g+5]=t.height,u[g+6]=t.xoffset,u[g+7]=t.yoffset,g+=8;c.unmap();let m=Q5.device.createBindGroup({label:"fontBindGroup",layout:St,entries:[{binding:0,resource:l.createView()},{binding:1,resource:yt},{binding:2,resource:{buffer:c}}]}),x=new Map;if(a.kernings)for(let e of a.kernings){let t=x.get(e.first);t||(t=new Map,x.set(e.first,t)),t.set(e.second,e.amount)}let _=new Ct(m,a.common.lineHeight,p,x);return _.index=Mt.length,Mt.push(_),Pt[r]=_,e._font=_,n&&n(r),{family:r}}(t,a,(()=>{delete i.then,i._usedAwait&&(i={family:a}),r&&r(i)})),e._loaders.push(i.promise),i.then=(e,t)=>(i._usedAwait=!0,i.promise.then(e,t)),i};let Et=18,It="left",Rt="alphabetic",At=!1,Tt=22.5,kt=4.5,Ot=1.25,Gt=["serif","sans-serif","monospace","cursive","fantasy","system-ui"];e.textFont=t=>{if(!t)return e._font;Qt=!0,"string"!=typeof t&&(t=t.family);let r=Pt[t];r?e._font=r:(Gt[t]||void 0===r)&&e._g.textFont(t)},e.textSize=t=>{if(e._font||e._g.textSize(t),null==t)return Et;Et=t,At||(Tt=t*Ot,kt=Tt-t)};let Lt={thin:100,extralight:200,light:300,normal:400,regular:400,medium:500,semibold:600,bold:700,bolder:800,extrabold:800,black:900,heavy:900},Dt=.5;e.textWeight=t=>{if(!t)return e._textWeight;if("string"==typeof t&&!(t=Lt[t.toLowerCase().replace(/[ _-]/g,"")]))throw new Error(`Invalid font weight: ${t}`);Dt=.6875-375e-6*t},e.textLeading=t=>e._font?t?(e._font.lineHeight=Tt=t,kt=Tt-Et,Ot=Tt/Et,void(At=!0)):Tt:e._g.textLeading(t),e.textAlign=(e,t)=>{It=e,t&&(Rt=t)},e.textStyle=e=>{};let Bt=[],Ft=[],zt=new Array(100),Ut=new Float32Array(4*Q5.MAX_CHARS),Vt=new Float32Array(8*Q5.MAX_TEXTS),Nt=(e,t,r)=>{let n=0,a=0,i=0,o=0,s=0,l=zt,d=t.charCodeAt(0);for(let c=0;c<t.length;++c){let u=d;switch(d=c<t.length-1?t.charCodeAt(c+1):-1,u){case 10:l.push(a),o++,n=Math.max(n,a),a=0,i-=e.lineHeight*Ot;break;case 13:break;case 32:a+=e.getXAdvance(u);break;case 9:a+=2*e.getXAdvance(u);break;default:r&&r(a,i,o,e.getChar(u)),a+=e.getXAdvance(u,d),s++}}l[o]=a,n=Math.max(n,a);let c=o+1;return{width:n,height:c*e.lineHeight*Ot,lineWidths:l,lineCount:c,printedCharCount:s}};e.text=(t,r,n,a,i)=>{if(Et<1)return;let o,s=typeof t;if("string"!=s)"object"==s?t=t.toString():t+="";else if(!t.length)return;if(!e._font){Qt||e.loadFont();let o=e.createTextImage(t,a,i);return e.textImage(o,r,n)}if(t.length>a){let e=[],r=0;for(;r<t.length&&e.length<i;){let n=r+a;if(n>=t.length){e.push(t.slice(r));break}let i=t.lastIndexOf(" ",n);(-1==i||i<r)&&(i=n),e.push(t.slice(r,i)),r=i+1}t=e.join("\n"),o=!0}o??=t.includes("\n");let l,d=[],c=It,u=Rt,h=Ft.length,f=0;if("left"!=c||o){l=Nt(e._font,t);let r=0;"alphabetic"==u?n-=Et:"center"==u?r=.5*l.height:"bottom"==u&&(r=l.height),Nt(e._font,t,((e,t,n,a)=>{let i=0;"center"==c?i=-.5*l.width- -.5*(l.width-l.lineWidths[n]):"right"==c&&(i=-l.lineWidths[n]),d[f]=e+i,d[f+1]=-(t+r),d[f+2]=a.charIndex,d[f+3]=h,f+=4}))}else l=Nt(e._font,t,((e,t,r,n)=>{d[f]=e,d[f+1]=-t,d[f+2]=n.charIndex,d[f+3]=h,f+=4})),"alphabetic"==u?n-=Et:"center"==u?n-=.5*Et:"bottom"==u&&(n-=Tt);Bt.push(d);let p=[];q&&j(),p[0]=r,p[1]=n,p[2]=Et/42,p[3]=H,p[4]=M&&E?A:1,p[5]=R,p[6]=P&&I?O:0,p[7]=Dt,Ft.push(p),x.push(_t,l.printedCharCount,e._font.index)},e.textWidth=t=>e._font?Nt(e._font,t).width*Et/42:(e._g.textSize(Et),e._g.textWidth(t)),e.textAscent=t=>e._font?Tt-kt:(e._g.textSize(Et),e._g.textAscent(t)),e.textDescent=t=>e._font?kt:(e._g.textSize(Et),e._g.textDescent(t)),e.createTextImage=(t,r,n)=>{if(e._g.textSize(Et),M&&E){let t=4*A;e._g.fill(_.slice(t,t+4))}if(P&&I){let t=4*R;e._g.stroke(_.slice(t,t+4))}let a=e._g.createTextImage(t,r,n);return e._makeDrawable(a),a},e.textImage=(t,r,n)=>{"string"==typeof t&&(t=e.createTextImage(t));let a=mt;mt="corner";let i=It;"center"==i?r-=t.canvas.hw:"right"==i&&(r-=t.width);let o=Rt;"alphabetic"==o?n-=t._leading:"center"==o?n-=t._middle:"bottom"==o?n-=t._bottom:"top"==o&&(n-=t._top),e.image(t,r,n),mt=a};let Ht=["frame","shapes","image","video","text"],qt={frame:10,shapes:1e3,image:2e3,video:3e3,text:4e3};e._createShader=(t,r="shapes")=>{t=t.trim();let n=e["_"+r+"ShaderCode"],a=n.indexOf("@vertex"),i=n.indexOf("@fragment");t=t.includes("@fragment")?t.includes("@vertex")?n.slice(0,a)+t:n.slice(0,i)+t:n.slice(0,a)+t+"\n\n"+n.slice(i);let o=Q5.device.createShaderModule({label:r+"Shader",code:t});o.type=r;let s=Ht.indexOf(r),l=Object.assign({},e._pipelineConfigs[s]);l.vertex.module=l.fragment.module=o;let d=qt[r];return e._pipelines[d]=Q5.device.createRenderPipeline(l),e._pipelines[d].shader=o,o.pipelineIndex=d,qt[r]++,o},e.createShader=e.createShapesShader=e._createShader,e.createFrameShader=t=>e._createShader(t,"frame"),e.createImageShader=t=>e._createShader(t,"image"),e.createVideoShader=t=>e._createShader(t,"video"),e.createTextShader=t=>e._createShader(t,"text"),e.shader=e=>{let t=e.type,r=e.pipelineIndex;"frame"==t?e.applyBeforeDraw?g=r:m=r:"shapes"==t?fe=r:"image"==t?tt=r:"video"==t?rt=r:"text"==t&&(_t=r)},e.resetShader=e.resetShapesShader=()=>fe=1,e.resetFrameShader=()=>g=m=0,e.resetImageShader=()=>tt=2,e.resetVideoShader=()=>rt=3,e.resetTextShader=()=>_t=4,e.resetShaders=()=>{g=m=0,fe=1,tt=2,rt=3,_t=4}},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.MAX_TRANSFORMS=1e7,Q5.MAX_RECTS=200200,Q5.MAX_ELLIPSES=200200,Q5.MAX_CHARS=1e5,Q5.MAX_TEXTS=1e4,Q5.initWebGPU=async()=>{if(!navigator.gpu)return console.warn("q5 WebGPU not supported on this browser! Use Google Chrome or Edge."),!1;if(!Q5.requestedGPU){Q5.requestedGPU=!0;let e=await navigator.gpu.requestAdapter();if(!e)return console.warn("q5 WebGPU could not start! No appropriate GPUAdapter found, Vulkan may need to be enabled."),!1;Q5.device=await e.requestDevice(),Q5.device.lost.then((e=>{console.error("WebGPU crashed!"),console.error(e)}))}return!0},Q5.WebGPU=async function(e,t){let r;return e&&"global"!=e||(Q5._hasGlobal=!0),await Q5.initWebGPU()||(r=new Q5(e,t,"webgpu-fallback")),r=new Q5(e,t,"webgpu"),await r.ready,r};const libLangs="\n# core\ncreateCanvas -> es:crearLienzo ja:キャンバスを作成する\nlog -> es:log\n\n# color\nbackground -> es:fondo ja:背景\nfill -> es:relleno\nstroke -> es:trazo\nnoFill -> es:sinRelleno\nnoStroke -> es:sinTrazo\ncolor -> es:color\ncolorMode -> es:modoColor\n\n# display\nwindowWidth -> es:anchoVentana\nwindowHeight -> es:altoVentana\nwidth -> es:ancho\nheight -> es:alto\nframeCount -> es:cuadroActual\nnoLoop -> es:pausar\nredraw -> es:redibujar\nloop -> es:reanudar\nframeRate -> es:frecuenciaRefresco\ngetTargetFrameRate -> es:obtenerTasaFotogramasObjetivo\ngetFPS -> es:obtenerFPS\ndeltaTime -> es:deltaTiempo\npixelDensity -> es:densidadPíxeles\ndisplayDensity -> es:densidadVisualización\nfullscreen -> es:pantallaCompleta\ndisplayMode -> es:modoVisualización\nhalfWidth -> es:medioAncho\nhalfHeight -> es:medioAlto\ncanvas -> es:lienzo\nresizeCanvas -> es:redimensionarLienzo\ndrawingContext -> es:contextoDibujo\n\n# shape\ncircle -> es:círculo\nellipse -> es:elipse\nrect -> es:rect\nsquare -> es:cuadrado\npoint -> es:punto\nline -> es:línea\ncapsule -> es:cápsula\nrectMode -> es:modoRect\nellipseMode -> es:modoEliptico\narc -> es:arco\ncurve -> es:curva\nbeginShape -> es:empezarForma\nendShape -> es:terminarForma\nvertex -> es:vértice\nbezier -> es:bezier\ntriangle -> es:triángulo\nquad -> es:quad\ncurveDetail -> es:detalleCurva\nbeginContour -> es:empezarContorno\nendContour -> es:terminarContorno\nbezierVertex -> es:vérticeBezier\nquadraticVertex -> es:vérticeCuadrático\n\n# image\nloadImage -> es:cargarImagen\nimage -> es:imagen\nimageMode -> es:modoImagen\nnoTint -> es:noTeñir\ntint -> es:teñir\nfilter -> es:filtro\ncreateImage -> es:crearImagen\ncreateGraphics -> es:crearGráficos\ndefaultImageScale -> es:escalaImagenPorDefecto\nresize -> es:redimensionar\ntrim -> es:recortar\nsmooth -> es:suavizar\nnoSmooth -> es:noSuavizar\nmask -> es:enmascarar\ncopy -> es:copiar\ninset -> es:insertado\nget -> es:obtener\nset -> es:establecer\npixels -> es:píxeles\nloadPixels -> es:cargarPíxeles\nupdatePixels -> es:actualizarPíxeles\n\n# text\ntext -> es:texto\nloadFont -> es:cargarFuente\ntextFont -> es:fuenteTexto\ntextSize -> es:tamañoTexto\ntextLeading -> es:interlineado\ntextStyle -> es:estiloTexto\ntextAlign -> es:alineaciónTexto\ntextWidth -> es:anchoTexto\ntextWeight -> es:pesoTexto\ntextAscent -> es:ascensoTexto\ntextDescent -> es:descensoTexto\ncreateTextImage -> es:crearImagenTexto\ntextImage -> es:imagenTexto\nnf -> es:nf\n\n# input\nmouseX -> es:ratónX\nmouseY -> es:ratónY\npmouseX -> es:pRatónX\npmouseY -> es:pRatónY\nmouseIsPressed -> es:ratónPresionado\nmouseButton -> es:botónRatón\nkey -> es:tecla\nkeyIsPressed -> es:teclaPresionada\nkeyIsDown -> es:teclaEstaPresionada\ntouches -> es:toques\npointers -> es:punteros\ncursor -> es:cursor\nnoCursor -> es:sinCursor\npointerLock -> es:bloqueoPuntero\n\n# style\nstrokeWeight -> es:grosorTrazo\nopacity -> es:opacidad\nshadow -> es:sombra\nnoShadow -> es:sinSombra\nshadowBox -> es:cajaSombra\nblendMode -> es:modoMezcla\nstrokeCap -> es:terminaciónTrazo\nstrokeJoin -> es:uniónTrazo\nerase -> es:borrar\nnoErase -> es:noBorrar\nclear -> es:limpiar\npushStyles -> es:guardarEstilos\npopStyles -> es:recuperarEstilos\ninFill -> es:enRelleno\ninStroke -> es:enTrazo\n\n# transform\ntranslate -> es:trasladar\nrotate -> es:rotar\nscale -> es:escalar\nshearX -> es:cizallarX\nshearY -> es:cizallarY\napplyMatrix -> es:aplicarMatriz\nresetMatrix -> es:reiniciarMatriz\npush -> es:apilar\npop -> es:desapilar\npushMatrix -> es:guardarMatriz\npopMatrix -> es:recuperarMatriz\n\n# math\nrandom -> es:aleatorio\nnoise -> es:ruido\ndist -> es:dist\nmap -> es:mapa\nangleMode -> es:modoÁngulo\nradians -> es:radianes\ndegrees -> es:grados\nlerp -> es:interpolar\nconstrain -> es:constreñir\nnorm -> es:norm\nabs -> es:abs\nround -> es:redondear\nceil -> es:techo\nfloor -> es:piso\nmin -> es:min\nmax -> es:max\npow -> es:pot\nsq -> es:cuad\nsqrt -> es:raiz\nexp -> es:exp\nrandomSeed -> es:semillaAleatoria\nrandomGaussian -> es:aleatorioGaussiano\nnoiseMode -> es:modoRuido\nnoiseSeed -> es:semillaRuido\nnoiseDetail -> es:detalleRuido\njit -> es:flu\nrandomGenerator -> es:generadorAleatorio\nrandomExponential -> es:aleatorioExponencial\n\n# sound\nloadSound -> es:cargarSonido\nloadAudio -> es:cargarAudio\ngetAudioContext -> es:obtenerContextoAudio\nuserStartAudio -> es:iniciarAudioUsuario\n\n# dom\ncreateElement -> es:crearElemento\ncreateA -> es:crearA\ncreateButton -> es:crearBotón\ncreateCheckbox -> es:crearCasilla\ncreateColorPicker -> es:crearSelectorColor\ncreateImg -> es:crearImg\ncreateInput -> es:crearEntrada\ncreateP -> es:crearP\ncreateRadio -> es:crearOpciónes\ncreateSelect -> es:crearSelección\ncreateSlider -> es:crearDeslizador\ncreateVideo -> es:crearVideo\ncreateCapture -> es:crearCaptura\nfindElement -> es:encontrarElemento\nfindElements -> es:encontrarElementos\n\n# record\ncreateRecorder -> es:crearGrabadora\nrecord -> es:grabar\npauseRecording -> es:pausarGrabación\ndeleteRecording -> es:borrarGrabación\nsaveRecording -> es:guardarGrabación\nrecording -> es:grabando\n\n# io\nload -> es:cargar\nsave -> es:guardar\nloadJSON -> es:cargarJSON\nloadStrings -> es:cargarTexto\nyear -> es:año\nday -> es:día\nhour -> es:hora\nminute -> es:minuto\nsecond -> es:segundo\nloadCSV -> es:cargarCSV\nloadXML -> es:cargarXML\nloadAll -> es:cargarTodo\ndisablePreload -> es:deshabilitarPrecarga\nshuffle -> es:barajar\nstoreItem -> es:guardarItem\ngetItem -> es:obtenerItem\nremoveItem -> es:eliminarItem\nclearStorage -> es:limpiarAlmacenamiento\n\n# shaders\ncreateShader -> es:crearShader\nplane -> es:plano\nshader -> es:shader\nresetShader -> es:reiniciarShader\nresetFrameShader -> es:reiniciarShaderFotograma\nresetImageShader -> es:reiniciarShaderImagen\nresetVideoShader -> es:reiniciarShaderVideo\nresetTextShader -> es:reiniciarShaderTexto\nresetShaders -> es:reiniciarShaders\ncreateFrameShader -> es:crearShaderFotograma\ncreateImageShader -> es:crearShaderImagen\ncreateVideoShader -> es:crearShaderVideo\ncreateTextShader -> es:crearShaderTexto\n\n# constants\nCORNER -> es:ESQUINA\nRADIUS -> es:RADIO\nCORNERS -> es:ESQUINAS\nTHRESHOLD -> es:UMBRAL\nGRAY -> es:GRIS\nOPAQUE -> es:OPACO\nINVERT -> es:INVERTIR\nPOSTERIZE -> es:POSTERIZAR\nDILATE -> es:DILATAR\nERODE -> es:EROSIONAR\nBLUR -> es:DESENFOCAR\nNORMAL -> es:NORMAL\nITALIC -> es:CURSIVA\nBOLD -> es:NEGRILLA\nBOLDITALIC -> es:NEGRILLA_CURSIVA\nLEFT -> es:IZQUIERDA\nCENTER -> es:CENTRO\nRIGHT -> es:DERECHA\nTOP -> es:ARRIBA\nBOTTOM -> es:ABAJO\nBASELINE -> es:LINEA_BASE\nMIDDLE -> es:MEDIO\nRGB -> es:RGB\nOKLCH -> es:OKLCH\nHSL -> es:HSL\nHSB -> es:HSB\nSRGB -> es:SRGB\nDISPLAY_P3 -> es:DISPLAY_P3\nMAXED -> es:MAXIMIZADO\nSMOOTH -> es:SUAVE\nPIXELATED -> es:PIXELADO\nTWO_PI -> es:DOS_PI\nHALF_PI -> es:MEDIO_PI\nQUARTER_PI -> es:CUARTO_PI\n\n# vector\ncreateVector -> es:crearVector\n",userLangs="\nupdate -> es:actualizar\ndraw -> es:dibujar\npostProcess -> es:postProcesar\nmousePressed -> es:alPresionarRatón\nmouseReleased -> es:alSoltarRatón\nmouseMoved -> es:alMoverRatón\nmouseDragged -> es:alArrastrarRatón\ndoubleClicked -> es:dobleClic\nkeyPressed -> es:alPresionarTecla\nkeyReleased -> es:alSoltarTecla\ntouchStarted -> es:alEmpezarToque\ntouchEnded -> es:alTerminarToque\ntouchMoved -> es:alMoverToque\nmouseWheel -> es:ruedaRatón\n",classLangs={Vector:"\nadd -> es:sumar\nsub -> es:restar\nmult -> es:multiplicar\ndiv -> es:dividir\nmag -> es:magnitud\nmagSq -> es:magnitudCuad\ndist -> es:distancia\nnormalize -> es:normalizar\nlimit -> es:limitar\nsetMag -> es:establecerMagnitud\nheading -> es:rumbo\nrotate -> es:rotar\nlerp -> es:interpolar\narray -> es:arreglo\ncopy -> es:copiar\ndot -> es:punto\ncross -> es:cruz\nangleBetween -> es:anguloEntre\nreflect -> es:reflejar\n",Sound:"\nload -> es:cargar\nplay -> es:reproducir\nstop -> es:parar\npause -> es:pausar\nloop -> es:bucle\nsetVolume -> es:establecerVolumen\nsetPan -> es:establecerPan\nsetLoop -> es:establecerBucle\nisLoaded -> es:estaCargado\nisPlaying -> es:estaReproduciendo\nisPaused -> es:estaPausado\nisLooping -> es:estaEnBucle\nonended -> es:alTerminar\n"},parseLangs=function(e,t){let r={};for(let n of e.split("\n")){let e=n.indexOf(" "+t+":");e>0&&"#"!=n[0]&&(r[n.split(" ")[0]]=n.slice(e+4).split(" ")[0])}return r};Object.defineProperty(Q5,"lang",{get:()=>Q5._lang,set:e=>{if(e==Q5._lang)return;if(Q5._lang=e,"en"==e)return Q5._userFns=Q5._userFns.slice(0,19),void(Q5._libMap=Q5._userFnsMap={});let t=parseLangs(libLangs,e);"object"==typeof window&&(window[t.createCanvas]=createCanvas);let r=parseLangs(userLangs,e);for(let e in r){let t=r[e];Q5.hasOwnProperty(t)||Object.defineProperty(Q5,t,{get:()=>Q5[e],set:t=>Q5[e]=t})}for(let t in classLangs)if(Q5[t]){let r=parseLangs(classLangs[t],e),n=Q5[t].prototype;for(let e in r){let t=r[e];n.hasOwnProperty(t)||Object.defineProperty(n,t,{get:function(){return this[e]},set:function(t){this[e]=t}})}}Q5._libMap=t,Q5._userFnsMap=r,Q5._userFns.push(...Object.values(r))}}),Q5.lang="en",Q5.modules.lang=e=>{let t=Q5._userFnsMap;for(let r in t){let n=t[r];Object.defineProperty(e,n,{get:()=>e[r],set:t=>e[r]=t})}let r=Q5._libMap;r.createCanvas&&(e[r.createCanvas]=e.createCanvas)},Q5.addHook("init",(e=>{let t=Q5._libMap;for(let r in t){e[t[r]]=e[r]}})),Q5.addHook("predraw",(e=>{let t=Q5._libMap;t.mouseX&&(e[t.frameCount]=e.frameCount,e[t.mouseX]=e.mouseX,e[t.mouseY]=e.mouseY,e[t.mouseIsPressed]=e.mouseIsPressed,e[t.mouseButton]=e.mouseButton,e[t.key]=e.key,e[t.keyIsPressed]=e.keyIsPressed,e[t.touches]=e.touches,e[t.pointers]=e.pointers)}));
|
|
9
|
+
function Q5(e,t,r){let n,a=this;a._isQ5=a._q5=!0,a._parent=t,a.ready=new Promise((e=>{n=e})),"webgpu-fallback"==r?(a._renderer="c2d",a._webgpu=a._webgpuFallback=!0):(a._renderer=r||"c2d",a["_"+a._renderer]=!0);let i,o="auto"==e;if(e??="global","auto"==e){if(!(window.setup||window.update||Q5.update||window.draw||Q5.draw))return;e="global"}"global"==e&&(Q5._hasGlobal=a._isGlobal=!0,i=Q5._esm?globalThis:Q5._server?global:window),"graphics"==e&&(a._isGraphics=!0),"image"==e&&(a._isImage=!0);let s=new Proxy(a,{set:(e,t,r)=>(a[t]=r,a._isGlobal&&(i[t]=r),!0)});a.canvas=a.ctx=a.drawingContext=null,a.pixels=[];let l=null,d=!0;async function c(e){for(let t of Q5.hooks[e])await t.call(a,s)}a.frameCount=0,a.deltaTime=16,a._targetFrameRate=0,a._targetFrameDuration=16.666666666666668,a._frameRate=a._fps=60,a._loop=!0;let u=0;a.millis=()=>performance.now()-u,a.noCanvas=()=>{a.canvas?.remove&&a.canvas.remove(),a.canvas=0,s.ctx=s.drawingContext=0},window&&(a.windowWidth=window.innerWidth,a.windowHeight=window.innerHeight,a.deviceOrientation=window.screen?.orientation?.type),a._loaders=[],a.loadAll=()=>{let e=[...a._loaders];return a._loaders=[],a._g&&(e=e.concat(a._g._loaders),a._g._loaders=[]),Promise.all(e)},a.isPreloadSupported=()=>!0,a.disablePreload=()=>a._disablePreload=!0;const h=[];async function f(e){let t=e||performance.now();if(a._didResize&&(a.windowResized(),a._didResize=!1),a._loop)if(d)l=g(f);else{let e=t+a._targetFrameDuration,r=e-performance.now();for(;r<0;)r+=a._targetFrameDuration;l=setTimeout((()=>f(e)),r)}else if(a.frameCount&&!a._redraw)return;if(a.frameCount&&d&&!a._redraw){if(t-a._lastFrameTime<a._targetFrameDuration-4)return}s.deltaTime=t-a._lastFrameTime,a._frameRate=1e3/a.deltaTime,s.frameCount++;let r=performance.now();a.resetMatrix(),a._beginRender&&a._beginRender(),await c("predraw");try{await a.draw()}catch(e){throw Q5.errorTolerant||a.noLoop(),a._fes&&a._fes(e),e}await c("postdraw"),await a.postProcess(),a._render&&a._render(),a._finishRender&&a._finishRender(),s.pmouseX=a.mouseX,s.pmouseY=a.mouseY,s.moveX=s.moveY=0,a._lastFrameTime=t;let n=performance.now();a._fps=Math.round(1e3/(n-r))}a._incrementPreload=()=>{a._loaders.push(new Promise((e=>h.push(e))))},a._decrementPreload=()=>{h.length&&h.pop()()},a.noLoop=()=>{a._loop=!1,null!=l&&(d&&window.cancelAnimationFrame?cancelAnimationFrame(l):clearTimeout(l)),l=null},a.loop=()=>{a._loop=!0,a._setupDone&&null==l&&f()},a.isLooping=()=>a._loop,a.redraw=async(e=1)=>{a._redraw=!0;for(let t=0;t<e;t++)await f();a._redraw=!1},a.remove=async()=>{a.noLoop(),a.canvas.remove(),await c("remove")},a.frameRate=e=>(e&&e!=a._targetFrameRate&&(a._targetFrameRate=e,a._targetFrameDuration=1e3/e,a._loop&&null!=l&&(d&&window.cancelAnimationFrame?cancelAnimationFrame(l):clearTimeout(l),l=null),d=e<=60,a._setupDone&&(l=d?g(f):setTimeout((()=>f()),a._targetFrameDuration))),a._frameRate),a.getTargetFrameRate=()=>a._targetFrameRate||60,a.getFPS=()=>a._fps,a.Element=function(e){this.elt=e},a._elements=[],a.describe=()=>{},a.log=a.print=console.log;for(let e in Q5.modules)Q5.modules[e](a,s);let p=Q5.renderers[a._renderer];for(let e in p)p[e](a,s);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(a[e]=Q5[e]);if(a._isGraphics)return;if(a._isGlobal){let e=Object.assign({},a);delete e.Color,Object.assign(Q5,e),delete Q5.Q5}for(let e of Q5.hooks.init)e.call(a,s);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof a[e]&&(a[e]=t.bind(a));for(let[e,t]of Object.entries(Q5.preloadMethods))a[e]=function(){return a._incrementPreload(),t.apply(a,arguments)};if(a._isGlobal){let e=Object.getOwnPropertyNames(a);for(let t of e)"_"!=t[0]&&(i[t]=a[t]);for(let e of["_incrementPreload","_decrementPreload"])i[e]=a[e]}"function"==typeof e&&e(a),Q5._instanceCount++;let g=window.requestAnimationFrame||function(e){const t=a._lastFrameTime+a._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},m=i||a,x=Q5._userFns.slice(0,15);for(let e of x)a[e]??=()=>{};if(a._isGlobal){let e=Q5._userFns.slice(0,19);for(let t of e)Q5[t]?a[t]=Q5[t]:Object.defineProperty(Q5,t,{get:()=>a[t],set:e=>a[t]=e})}function _(e){const t=m[e]||a[e];a[e]=e=>{try{return t(e)}catch(e){throw a._fes&&a._fes(e),e}}}async function v(){await c("presetup"),n(),(m.preload||a.preload)&&(_("preload"),a.preload()),await Promise.race([new Promise((e=>{!function t(){a.setup||a.update||a.draw||m.setup||m.update||m.draw?e():a._setupDone||(a.canvas?.ready&&a._render&&(a._beginRender(),a._render(),a._finishRender()),g(t))}()})),new Promise((e=>{setTimeout((()=>{a._loaders.length||e()}),500)}))]),a._disablePreload||await a.loadAll(),a.setup??=m.setup||(()=>{}),_("setup");for(let e of x)_(e);a.draw??=m.draw||(()=>{}),u=performance.now(),await a.setup(),a._setupDone=!0,null===a.ctx&&a.createCanvas(200,200),await c("postsetup"),a.frameCount||(a._lastFrameTime=performance.now()-15,g(f))}Q5.instances.push(a),o||Q5._esm?v():setTimeout(v,32)}function createCanvas(e,t,r){if(Q5._hasGlobal)return;if("c2d"==e||"c2d"==t||"c2d"==r||"c2d"==r?.renderer||!Q5._esm){let n=new Q5,a=n.createCanvas(e,t,r);return n.ready.then((()=>a))}return Q5.WebGPU().then((n=>n.createCanvas(e,t,r)))}Q5.renderers={},Q5.modules={},Q5._server="object"==typeof process,Q5._esm=void 0===this,Q5._instanceCount=0,Q5.instances=[],Q5._friendlyError=(e,t)=>{Q5.disableFriendlyErrors||console.error(t+": "+e)},Q5._validateParameters=()=>!0,Q5._userFns=["postProcess","mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","doubleClicked","mouseWheel","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized","preload","setup","update","draw"],Q5.hooks={init:[],presetup:[],postsetup:[],predraw:[],postdraw:[],remove:[]},Q5.addHook=(e,t)=>Q5.hooks[e].push(t),Q5.registerAddon=e=>{let t={};e(Q5,Q5.prototype,t);for(let e in t)Q5.hooks[e].push(t[e])},Q5.prototype.registerMethod=(e,t)=>{("beforeSetup"==e||e.includes("Preload"))&&(e="presetup"),"afterSetup"==e&&(e="postsetup"),"pre"==e&&(e="predraw"),"post"==e&&(e="postdraw"),Q5.hooks[e].push(t)},Q5.preloadMethods={},Q5.prototype.registerPreloadMethod=(e,t)=>Q5.preloadMethods[e]=t[e],Q5._server&&(global.q5=global.Q5=Q5,global.p5??=Q5),"object"==typeof window?(window.q5=window.Q5=Q5,window.p5??=Q5,window.createCanvas=createCanvas,window.C2D="c2d",window.WEBGPU="webgpu"):global.window=0,Q5.version=Q5.VERSION="3.8","object"==typeof document&&document.addEventListener("DOMContentLoaded",(()=>{Q5._hasGlobal||(Q5.update||Q5.draw?Q5.WebGPU():new Q5("auto"))})),Q5.modules.canvas=(e,t)=>{e._Canvas=window.OffscreenCanvas||function(){return document.createElement("canvas")},Q5._server?Q5._createServerCanvas&&(t.canvas=Q5._createServerCanvas(200,200)):(e._isImage||e._isGraphics)&&(t.canvas=new e._Canvas(200,200)),e.canvas||("object"==typeof document?(t.canvas=document.createElement("canvas"),e.canvas.id="q5Canvas"+Q5._instanceCount,e.canvas.classList.add("q5Canvas")):e.noCanvas()),e.displayDensity=()=>window.devicePixelRatio||1,e.width=200,e.height=200,e._pixelDensity=1;let r=e.canvas;if(r&&(r.width=200,r.height=200,r.colorSpace=Q5.canvasOptions.colorSpace,e._isImage||(r.renderer=e._renderer,r[e._renderer]=!0,e._pixelDensity=Math.ceil(e.displayDensity()))),e._adjustDisplay=e=>{let t=r.style;t&&e&&(t.width=r.w+"px",t.height=r.h+"px")},e.createCanvas=function(t,a,i){(isNaN(t)||"string"==typeof t&&!t.includes(":"))&&(i=t,t=null),"number"!=typeof a&&(i=a,a=null),i??=arguments[3],"string"==typeof i&&(i={renderer:i});let o=Object.assign({},Q5.canvasOptions);if("object"==typeof i&&Object.assign(o,i),!e._isImage)if(e._isGraphics)e._pixelDensity=this._pixelDensity;else if(Q5._server)r.visible=!0;else{let t=r,a=document.body||document.documentElement;for(;t&&t.parentElement!=a;)t=t.parentElement;if(t||(document.getElementById(r.id)?.remove(),n()),window.IntersectionObserver){let t=!1;new IntersectionObserver((n=>{if(n[0].isIntersecting)r.visible=!0;else{let e=r.getBoundingClientRect();r.visible=e.top<window.innerHeight&&e.bottom>0&&e.left<window.innerWidth&&e.right>0}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 s=e._createCanvas(r.w,r.h,o);return e._addEventMethods&&e._addEventMethods(r),e.canvas.ready=!0,s},e.createGraphics=function(t,r,n={}){"string"==typeof n&&(n={renderer:n});let a=new Q5("graphics",void 0,n.renderer||(e._webgpuFallback?"webgpu-fallback":e._renderer));n.alpha??=!0,n.colorSpace??=e.canvas.colorSpace,n.pixelDensity??=e._pixelDensity,a._defaultImageScale=e._defaultImageScale,a.createCanvas.call(e,t,r,n);let i=a._pixelDensity*e._defaultImageScale;return a.defaultWidth=t*i,a.defaultHeight=r*i,a},e._setCanvasSize=(n,a)=>{a??=n??window.innerHeight,n??=window.innerWidth,r.w=n=Math.ceil(n),r.h=a=Math.ceil(a),r.width=Math.ceil(n*e._pixelDensity),r.height=Math.ceil(a*e._pixelDensity),t.width=n,t.height=a,t.halfWidth=r.hw=n/2,t.halfHeight=r.hh=a/2;let i=Q5._libMap;i.width&&(t[i.width]=n,t[i.height]=a,t[i.halfWidth]=t.halfWidth,t[i.halfHeight]=t.halfHeight),e.displayMode&&!r.displayMode?e.displayMode():e._adjustDisplay(!0)},e._setImageSize=(n,a)=>{t.width=r.w=n,t.height=r.h=a,t.halfWidth=r.hw=n/2,t.halfHeight=r.hh=a/2,r.width=Math.ceil(n*e._pixelDensity),r.height=Math.ceil(a*e._pixelDensity)},e.defaultImageScale=t=>t?(e._g&&(e._g._defaultImageScale=t),e._defaultImageScale=t):e._defaultImageScale,e.defaultImageScale(.5),!e._isImage){if(r&&!e._isGraphics){function n(){let t=e._parent;if(t??=document.getElementsByTagName("main")[0],!t){t=document.createElement("main"),(document.body||document.documentElement).appendChild(t)}r.parent(t),document.body||document.addEventListener("DOMContentLoaded",(()=>{document.body&&document.body.appendChild(t)}))}r.parent=t=>{function n(){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(n),e._ro.observe(t)):e.frameCount||window.addEventListener("resize",n)},n()}e.resizeCanvas=(t,n)=>{if(!e.ctx)return e.createCanvas(t,n);t==r.w&&n==r.h||e._resizeCanvas(t,n)},r&&!Q5._createServerCanvas&&(r.resize=e.resizeCanvas),e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._resizeCanvas(r.w,r.h),e._g&&e._g.pixelDensity(t),t):e._pixelDensity,window&&!e._isGraphics&&window.addEventListener("resize",(()=>{e._didResize=!0,t.windowWidth=window.innerWidth,t.windowHeight=window.innerHeight,t.deviceOrientation=window.screen?.orientation?.type}))}},Q5.CENTER="center",Q5.LEFT="left",Q5.RIGHT="right",Q5.TOP="top",Q5.BOTTOM="bottom",Q5.BASELINE="alphabetic",Q5.MIDDLE="middle",Q5.NORMAL="normal",Q5.ITALIC="italic",Q5.BOLD="bold",Q5.BOLDITALIC="italic bold",Q5.ROUND="round",Q5.SQUARE="butt",Q5.PROJECT="square",Q5.MITER="miter",Q5.BEVEL="bevel",Q5.NONE="none",Q5.SIMPLE="simple",Q5.CHORD_OPEN=0,Q5.PIE_OPEN=1,Q5.PIE=2,Q5.CHORD=3,Q5.RADIUS="radius",Q5.CORNER="corner",Q5.CORNERS="corners",Q5.OPEN=0,Q5.CLOSE=1,Q5.VIDEO="video",Q5.AUDIO="audio",Q5.LANDSCAPE="landscape",Q5.PORTRAIT="portrait",Q5.BLEND="source-over",Q5.REMOVE="destination-out",Q5.ADD="lighter",Q5.DARKEST="darken",Q5.LIGHTEST="lighten",Q5.DIFFERENCE="difference",Q5.SUBTRACT="subtract",Q5.EXCLUSION="exclusion",Q5.MULTIPLY="multiply",Q5.SCREEN="screen",Q5.REPLACE="copy",Q5.OVERLAY="overlay",Q5.HARD_LIGHT="hard-light",Q5.SOFT_LIGHT="soft-light",Q5.DODGE="color-dodge",Q5.BURN="color-burn",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.SEPIA=9,Q5.BRIGHTNESS=10,Q5.SATURATION=11,Q5.CONTRAST=12,Q5.HUE_ROTATE=13,Q5.C2D=Q5.P2D=Q5.P2DHDR="c2d",Q5.WEBGL="webgl",Q5.GPU=Q5.WEBGPU="webgpu",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.c2d={},Q5.renderers.c2d.canvas=(e,t)=>{let r=e.canvas;function n(){let t=e._styles.pop();for(let r of e._styleNames)e[r]=t[r]}e.colorMode&&e.colorMode("rgb",e._webgpu?1:255),e._createCanvas=function(n,a,i){if(r)return t.ctx=t.drawingContext=r.getContext("2d",i),e._isImage||(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._strokeWeight=1),e.ctx.scale(e._pixelDensity,e._pixelDensity),e.ctx.save(),r;console.error("q5 canvas could not be created. skia-canvas and jsdom packages not found.")},e.clear=()=>{e.ctx.save(),e.ctx.resetTransform(),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.restore()},e._isImage||(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._isColor&&(t=e.color(...arguments)),e.ctx.fillStyle=t.toString(),e.ctx.fillRect(0,0,e.canvas.width,e.canvas.height)),e.ctx.restore()},e._resizeCanvas=(t,n)=>{let a,i={};for(let t in e.ctx)"function"!=typeof e.ctx[t]&&(i[t]=e.ctx[t]);if(delete i.canvas,e.frameCount>1){a=new e._Canvas(r.width,r.height),a.w=r.w,a.h=r.h,a.getContext("2d").drawImage(r,0,0)}e._setCanvasSize(t,n);for(let t in i)e.ctx[t]=i[t];e.scale(e._pixelDensity),a&&e.ctx.drawImage(a,0,0,a.w,a.h)},e.fill=function(t){if(e._doFill=e._fillSet=!0,Q5.Color&&(t._isColor||"string"==typeof t&&!e._namedColors[t]||(t=e.color(...arguments)),t.a<=0))return e._doFill=!1;e.ctx.fillStyle=e._fill=t.toString()},e.stroke=function(t){if(e._doStroke=e._strokeSet=!0,Q5.Color&&(t._isColor||"string"==typeof t&&!e._namedColors[t]||(t=e.color(...arguments)),t.a<=0))return e._doStroke=!1;e.ctx.strokeStyle=e._stroke=t.toString()},e.strokeWeight=t=>{e._doStroke=!!t,e.ctx.lineWidth=e._strokeWeight=t||1e-4},e.noFill=()=>e._doFill=!1,e.noStroke=()=>e._doStroke=!1,e.opacity=t=>e.ctx.globalAlpha=t,e._getFillIdx=()=>e._fill,e._setFillIdx=t=>e._fill=t,e._getStrokeIdx=()=>e._stroke,e._setStrokeIdx=t=>e._stroke=t,e._doShadow=!1,e._shadowOffsetX=e._shadowOffsetY=e._shadowBlur=10,e.shadow=function(t){if(Q5.Color&&(t._isColor||"string"==typeof t&&!e._namedColors[t]||(t=e.color(...arguments)),t.a<=0))return e._doShadow=!1;e.ctx.shadowColor=e._shadow=t.toString(),e._doShadow=!0,e.ctx.shadowOffsetX||=e._shadowOffsetX,e.ctx.shadowOffsetY||=e._shadowOffsetY,e.ctx.shadowBlur||=e._shadowBlur},e.shadowBox=(t,r,n)=>{e.ctx.shadowOffsetX=e._shadowOffsetX=t,e.ctx.shadowOffsetY=e._shadowOffsetY=r||t,e.ctx.shadowBlur=e._shadowBlur=n||0},e.noShadow=()=>{e._doShadow=!1,e.ctx.shadowOffsetX=e.ctx.shadowOffsetY=e.ctx.shadowBlur=0},e.translate=(t,r)=>{t.x&&(r=t.y,t=t.x),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,n,a,i,o)=>e.ctx.transform(t,r,n,a,i,o),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._webgpu&&e.translate(e.halfWidth,e.halfHeight))},e._styleNames=["_fill","_stroke","_strokeWeight","_doFill","_doStroke","_fillSet","_strokeSet","_shadow","_doShadow","_shadowOffsetX","_shadowOffsetY","_shadowBlur","_tint","_textSize","_textAlign","_textBaseline","_imageMode","_rectMode","_ellipseMode","_colorMode","_colorFormat","Color"],e._styles=[],e.pushStyles=()=>{let t={};for(let r of e._styleNames)t[r]=e[r];e._styles.push(t),e._fontMod&&e._updateFont()},e.popStyles=()=>{n(),e.ctx.fillStyle=e._fill,e.ctx.strokeStyle=e._stroke,e.ctx.lineWidth=e._strokeWeight,e.ctx.shadowColor=e._shadow,e.ctx.shadowOffsetX=e._doShadow?e._shadowOffsetX:0,e.ctx.shadowOffsetY=e._doShadow?e._shadowOffsetY:0,e.ctx.shadowBlur=e._doShadow?e._shadowBlur:0},e.pushMatrix=()=>e.ctx.save(),e.popMatrix=()=>e.ctx.restore(),e.push=()=>{e.pushStyles(),e.ctx.save()},e.pop=()=>{e.ctx.restore(),n()})},Q5.renderers.c2d.shapes=e=>{e._doStroke=!0,e._doFill=!0,e._strokeSet=!1,e._fillSet=!1,e._ellipseMode=Q5.CENTER,e._rectMode=Q5.CORNER;let t=!0,r=[];function n(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}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=()=>{},e.line=(t,r,n,a)=>{e._doStroke&&(e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(n,a),e.ctx.stroke())};const a=2*Math.PI;function i(t,r,n,i,o,s,l){if(e._angleMode&&(o=e.radians(o),s=e.radians(s)),(o%=a)<0&&(o+=a),(s%=a)<0&&(s+=a),o>s&&(s+=a),o==s)return e.ellipse(t,r,n,i);if(n/=2,i/=2,n=Math.abs(n),i=Math.abs(i),e._doFill||l!=e.PIE_OPEN||(l=e.CHORD_OPEN),e.ctx.beginPath(),e.ctx.ellipse(t,r,n,i,0,o,s),l!=e.PIE&&l!=e.PIE_OPEN||e.ctx.lineTo(t,r),e._doFill&&e.ctx.fill(),e._doStroke){if(l!=e.PIE&&l!=e.CHORD||e.ctx.closePath(),l!=e.PIE_OPEN)return e.ctx.stroke();e.ctx.beginPath(),e.ctx.ellipse(t,r,n,i,0,o,s),e.ctx.stroke()}}function o(t,r,i,o){e.ctx.beginPath(),e.ctx.ellipse(t,r,Math.abs(i/2),Math.abs(o/2),0,0,a),n()}function s(t,r,a,i,o,l,d,c){return void 0===o?function(t,r,a,i){e.ctx.beginPath(),e.ctx.rect(t,r,a,i),n()}(t,r,a,i):void 0===l?s(t,r,a,i,o,o,o,o):(e.ctx.beginPath(),e.ctx.roundRect(t,r,a,i,[o,l,d,c]),void n())}e.arc=(t,r,n,a,o,s,l)=>{if(o==s)return e.ellipse(t,r,n,a);l??=e.PIE_OPEN,e._ellipseMode==e.CENTER?i(t,r,n,a,o,s,l):e._ellipseMode==e.RADIUS?i(t,r,2*n,2*a,o,s,l):e._ellipseMode==e.CORNER?i(t+n/2,r+a/2,n,a,o,s,l):e._ellipseMode==e.CORNERS&&i((t+n)/2,(r+a)/2,n-t,a-r,o,s,l)},e.ellipse=(t,r,n,a)=>{a??=n,e._ellipseMode==e.CENTER?o(t,r,n,a):e._ellipseMode==e.RADIUS?o(t,r,2*n,2*a):e._ellipseMode==e.CORNER?o(t+n/2,r+a/2,n,a):e._ellipseMode==e.CORNERS&&o((t+n)/2,(r+a)/2,n-t,a-r)},e.circle=(t,r,i)=>{e._ellipseMode==e.CENTER?(e.ctx.beginPath(),e.ctx.arc(t,r,Math.abs(i/2),0,a),n()):e.ellipse(t,r,i,i)},e.point=(t,r)=>{e._doStroke&&(t.x&&(r=t.y,t=t.x),e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(t,r),e.ctx.stroke())},e.rect=(t,r,n,a=n,i,o,l,d)=>{e._rectMode==e.CENTER?s(t-n/2,r-a/2,n,a,i,o,l,d):e._rectMode==e.RADIUS?s(t-n,r-a,2*n,2*a,i,o,l,d):e._rectMode==e.CORNER?s(t,r,n,a,i,o,l,d):e._rectMode==e.CORNERS&&s(t,r,n-t,a-r,i,o,l,d)},e.square=(t,r,n,a,i,o,s)=>e.rect(t,r,n,n,a,i,o,s),e.capsule=(t,r,a,i,o)=>{const s=a-t,l=i-r,d=Math.hypot(s,l);if(0===d)return e.circle(t,r,2*o);const c=Math.atan2(l,s),u=-l/d*o,h=s/d*o;e.ctx.beginPath(),e.ctx.moveTo(t-u,r-h),e.ctx.arc(t,r,o,c-e.HALF_PI,c+e.HALF_PI,!0),e.ctx.lineTo(a+u,i+h),e.ctx.arc(a,i,o,c+e.HALF_PI,c-e.HALF_PI,!0),e.ctx.closePath(),n()},e.beginShape=()=>{r=[],e.ctx.beginPath(),t=!0},e.beginContour=()=>{e.ctx.closePath(),r=[],t=!0},e.endContour=()=>{r=[],t=!0},e.vertex=(n,a)=>{r=[],t?e.ctx.moveTo(n,a):e.ctx.lineTo(n,a),t=!1},e.bezierVertex=(t,n,a,i,o,s)=>{r=[],e.ctx.bezierCurveTo(t,n,a,i,o,s)},e.quadraticVertex=(t,n,a,i)=>{r=[],e.ctx.quadraticCurveTo(t,n,a,i)},e.bezier=(t,r,n,a,i,o,s,l)=>{e.beginShape(),e.vertex(t,r),e.bezierVertex(n,a,i,o,s,l),e.endShape()},e.triangle=(t,r,n,a,i,o)=>{e.beginShape(),e.vertex(t,r),e.vertex(n,a),e.vertex(i,o),e.endShape(e.CLOSE)},e.quad=(t,r,n,a,i,o,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(n,a),e.vertex(i,o),e.vertex(s,l),e.endShape(e.CLOSE)},e.endShape=t=>{r=[],t&&e.ctx.closePath(),n()},e.curveVertex=(n,a)=>{if(r.push([n,a]),r.length<4)return;let i=r.at(-4),o=r.at(-3),s=r.at(-2),l=r.at(-1),d=o[0]+(s[0]-i[0])/6,c=o[1]+(s[1]-i[1])/6,u=s[0]-(l[0]-o[0])/6,h=s[1]-(l[1]-o[1])/6;t&&(e.ctx.moveTo(o[0],o[1]),t=!1),e.ctx.bezierCurveTo(d,c,u,h,s[0],s[1])},e.curve=(t,r,n,a,i,o,s,l)=>{e.beginShape(),e.curveVertex(t,r),e.curveVertex(n,a),e.curveVertex(i,o),e.curveVertex(s,l),e.endShape()},e.curvePoint=(e,t,r,n,a)=>{const i=a*a*a,o=a*a;return e*(-.5*i+o-.5*a)+t*(1.5*i-2.5*o+1)+r*(-1.5*i+2*o+.5*a)+n*(.5*i-.5*o)},e.bezierPoint=(e,t,r,n,a)=>{const i=1-a;return Math.pow(i,3)*e+3*Math.pow(i,2)*a*t+3*i*Math.pow(a,2)*r+Math.pow(a,3)*n},e.curveTangent=(e,t,r,n,a)=>{const i=a*a;return e*(-3*i/2+2*a-.5)+t*(9*i/2-5*a)+r*(-9*i/2+4*a+.5)+n*(3*i/2-a)},e.bezierTangent=(e,t,r,n,a)=>{const i=1-a;return 3*n*Math.pow(a,2)-3*r*Math.pow(a,2)+6*r*i*a-6*t*i*a+3*t*Math.pow(i,2)-3*e*Math.pow(i,2)},e.erase=function(t,r){255==e._colorFormat&&(t&&(t/=255),r&&(r/=255)),e.ctx.save(),e.ctx.globalCompositeOperation="destination-out",e.ctx.fillStyle=`rgb(0 0 0 / ${t||1})`,e.ctx.strokeStyle=`rgb(0 0 0 / ${r||1})`},e.noErase=function(){e.ctx.globalCompositeOperation="source-over",e.ctx.restore()},e.inFill=(t,r)=>{const n=e._pixelDensity;return e.ctx.isPointInPath(t*n,r*n)},e.inStroke=(t,r)=>{const n=e._pixelDensity;return e.ctx.isPointInStroke(t*n,r*n)}},Q5.renderers.c2d.image=(e,t)=>{const r=e.canvas;r&&(r.convertToBlob??=e=>new Promise((t=>{r.toBlob((e=>t(e)),e.type,e.quality)}))),e._tint=null;let n=null,a=null;e.createImage=(t,r,n={})=>(n.colorSpace??=e.canvas.colorSpace,n.defaultImageScale??=e._defaultImageScale,new Q5.Image(t,r,n)),e.loadImage=function(t,r,n){if(t.canvas)return t;if("gif"==t.slice(-3).toLowerCase())throw new Error("q5 doesn't support GIFs. Use a video or p5play animation instead. https://github.com/q5js/q5.js/issues/84");let a=[...arguments].at(-1);"object"==typeof a?(n=a,r=null):n=void 0;let i=e.createImage(1,1,n),o=i._pixelDensity,s=new window.Image;return s.crossOrigin="Anonymous",i.promise=new Promise(((t,a)=>{s.onload=()=>{delete i.then,i._usedAwait&&(i=e.createImage(1,1,n)),s._pixelDensity=o,i.defaultWidth=s.width*e._defaultImageScale,i.defaultHeight=s.height*e._defaultImageScale,i.naturalWidth=s.naturalWidth||s.width,i.naturalHeight=s.naturalHeight||s.height,i._setImageSize(Math.ceil(i.naturalWidth/o),Math.ceil(i.naturalHeight/o)),i.ctx.drawImage(s,0,0),r&&r(i),t(i)},s.onerror=a})),e._loaders.push(i.promise),i.then=(e,t)=>(i._usedAwait=!0,i.promise.then(e,t)),i.src=s.src=t,i},e._imageMode=Q5.CORNER,e.imageMode=t=>e._imageMode=t,e.image=(t,r,n,a,i,o=0,s=0,l,d)=>{if(!t)return;let c=t.canvas||t;a??=t.defaultWidth||c.width||t.videoWidth,i??=t.defaultHeight||c.height||t.videoHeight,"center"==e._imageMode&&(r-=.5*a,n-=.5*i);let u=t._pixelDensity||1;if(l?l*=u:l=c.width||c.videoWidth,d?d*=u:d=c.height||c.videoHeight,e._tint){if(t._retint||t._tint!=e._tint){t._tintImg??=e.createImage(t.w,t.h,{pixelDensity:u}),t._tintImg.width==t.width&&t._tintImg.height==t.height||t._tintImg.resize(t.w,t.h);let r=t._tintImg.ctx;r.globalCompositeOperation="copy",r.fillStyle=e._tint,r.fillRect(0,0,t.width,t.height),t?.canvas?.alpha&&(r.globalCompositeOperation="destination-in",r.drawImage(c,0,0,t.width,t.height)),r.globalCompositeOperation="multiply",r.drawImage(c,0,0,t.width,t.height),t._tint=e._tint,t._retint=!1}c=t._tintImg.canvas}t.flipped&&(e.ctx.save(),e.ctx.translate(r+a,0),e.ctx.scale(-1,1),r=0),e.ctx.drawImage(c,o*u,s*u,l,d,r,n,a,i),t.flipped&&e.ctx.restore()},e.filter=(t,n)=>{e.ctx.save();let a="";if(e.ctx.filter){if("string"==typeof t)a=t;else if(t==Q5.GRAY)a="saturate(0%)";else if(t==Q5.INVERT)a="invert(100%)";else if(t==Q5.BLUR){a=`blur(${Math.ceil(n*e._pixelDensity)||1}px)`}else if(t==Q5.THRESHOLD){n??=.5,a=`saturate(0%) brightness(${Math.floor(.5/Math.max(n,1e-5)*100)}%) contrast(1000000%)`}else if(t==Q5.SEPIA)a=`sepia(${n??1})`;else if(t==Q5.BRIGHTNESS)a=`brightness(${n??1})`;else if(t==Q5.SATURATION)a=`saturate(${n??1})`;else if(t==Q5.CONTRAST)a=`contrast(${n??1})`;else if(t==Q5.HUE_ROTATE){a=`hue-rotate(${n}${0==e._angleMode?"rad":"deg"})`}if(a&&(e.ctx.filter=a,"none"==e.ctx.filter))throw new Error(`Invalid filter format: ${t}`)}a||e._softFilter(t,n),e.ctx.globalCompositeOperation="source-over",e.ctx.drawImage(r,0,0,r.w,r.h),e.ctx.restore(),e.modified=e._retint=!0},e._isImage&&(e.resize=(t,n)=>{let a=new e._Canvas(r.width,r.height);a.getContext("2d",{colorSpace:r.colorSpace}).drawImage(r,0,0),e._setImageSize(t,n),e.defaultWidth=r.width*e._defaultImageScale,e.defaultHeight=r.height*e._defaultImageScale,e.ctx.clearRect(0,0,r.width,r.height),e.ctx.drawImage(a,0,0,r.width,r.height),e._retint=!0,e._owner?._makeDrawable&&(e._texture.destroy(),delete e._texture,e._owner._makeDrawable(e))}),e._getImageData=(t,n,a,i)=>e.ctx.getImageData(t,n,a,i,{colorSpace:r.colorSpace}),e.trim=()=>{let t=e._pixelDensity||1,n=r.width,a=r.height,i=e._getImageData(0,0,n,a).data,o=n,s=0,l=a,d=0,c=3;for(let e=0;e<a;e++)for(let t=0;t<n;t++)0!==i[c]&&(t<o&&(o=t),t>s&&(s=t),e<l&&(l=e),e>d&&(d=e)),c+=4;return l=Math.floor(l/t),d=Math.floor(d/t),o=Math.floor(o/t),s=Math.floor(s/t),e.get(o,l,s-o+1,d-l+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.modified=e._retint=!0},e.inset=(t,n,a,i,o,s,l,d)=>{let c=e._pixelDensity||1;e.ctx.drawImage(r,t*c,n*c,a*c,i*c,o,s,l,d),e.modified=e._retint=!0},e.copy=()=>{let t=e.get();for(let r in e)"function"==typeof e[r]||/(canvas|ctx|texture)/.test(r)||(t[r]=e[r]);return t},e.get=(t,n,i,o)=>{let s=e._pixelDensity||1;if(void 0!==t&&void 0===i){a||e.loadPixels();let i=Math.floor(t*s),o=4*(Math.floor(n*s)*r.width+i);return[a[o],a[o+1],a[o+2],a[o+3]]}t=Math.floor(t||0)*s,n=Math.floor(n||0)*s,i??=e.width,o??=e.height;let l=e.createImage(i,o,{pixelDensity:s});return l.ctx.drawImage(r,t,n,i*s,o*s,0,0,i,o),l.width=i,l.height=o,e._owner?._makeDrawable&&e._owner._makeDrawable(l),l},e.set=(t,n,i)=>{if(t=Math.floor(t),n=Math.floor(n),e.modified=e._retint=!0,i.canvas){let r=e._tint;return e._tint=null,e.image(i,t,n),void(e._tint=r)}a||e.loadPixels();let o=e._pixelDensity||1,s=i.r,l=i.g,d=i.b,c=i.a;1==(e._colorFormat||e._owner?._colorFormat)&&(s*=255,l*=255,d*=255,c*=255);for(let e=0;e<o;e++)for(let i=0;i<o;i++){let u=4*((n*o+e)*r.width+t*o+i);a[u]=s,a[u+1]=l,a[u+2]=d,a[u+3]=c}},e.loadPixels=()=>{n=e._getImageData(0,0,r.width,r.height),t.pixels=a=n.data},e.updatePixels=()=>{null!=n&&(e.ctx.putImageData(n,0,0),e.modified=e._retint=!0)},e.smooth=()=>e.ctx.imageSmoothingEnabled=!0,e.noSmooth=()=>e.ctx.imageSmoothingEnabled=!1,e._isImage||(e.tint=function(t){e._tint=(t._isColor?t:e.color(...arguments)).toString()},e.noTint=()=>e._tint=null)},Q5.Image=class{constructor(e,t,r={}){r.alpha??=!0,r.colorSpace??=Q5.canvasOptions.colorSpace;let n=this;n._isImage=!0,n.canvas=n.ctx=n.drawingContext=null,n.pixels=[],Q5.modules.canvas(n,n);let a=Q5.renderers.c2d;for(let e of["canvas","image","softFilters"])a[e]&&a[e](n,n);n._pixelDensity=r.pixelDensity||1,n._defaultImageScale=r.defaultImageScale||2,n.createCanvas(e,t,r);let i=n._pixelDensity*n._defaultImageScale;n.defaultWidth=e*i,n.defaultHeight=t*i,delete n.createCanvas,n._loop=!1;let o=Q5._libMap,s=["copy","filter","get","set","resize","mask","trim","inset","pixels","loadPixels","updatePixels","smooth","noSmooth"];for(let e of s)o[e]&&(n[o[e]]=n[e])}get w(){return this.width}get h(){return this.height}},Q5.renderers.c2d.softFilters=e=>{let t=null;function r(){let r=e.canvas.width*e.canvas.height*4;t&&t.length==r||(t=new Uint8ClampedArray(r))}e._softFilter=(n,a)=>{e._filters||(e._filters=[],e._filters[Q5.THRESHOLD]=(e,t)=>{void 0===t?t=127.5:t*=255;for(let r=0;r<e.length;r+=4){const n=.2126*e[r]+.7152*e[r+1]+.0722*e[r+2];e[r]=e[r+1]=e[r+2]=n>=t?255:0}},e._filters[Q5.GRAY]=e=>{for(let t=0;t<e.length;t+=4){const r=.2126*e[t]+.7152*e[t+1]+.0722*e[t+2];e[t]=e[t+1]=e[t+2]=r}},e._filters[Q5.OPAQUE]=e=>{for(let t=0;t<e.length;t+=4)e[t+3]=255},e._filters[Q5.INVERT]=e=>{for(let t=0;t<e.length;t+=4)e[t]=255-e[t],e[t+1]=255-e[t+1],e[t+2]=255-e[t+2]},e._filters[Q5.POSTERIZE]=(e,t=4)=>{let r=t-1;for(let n=0;n<e.length;n+=4)e[n]=255*(e[n]*t>>8)/r,e[n+1]=255*(e[n+1]*t>>8)/r,e[n+2]=255*(e[n+2]*t>>8)/r},e._filters[Q5.DILATE]=(n,a)=>{a??=Math.max,r(),t.set(n);let[i,o]=[e.canvas.width,e.canvas.height];for(let e=0;e<o;e++)for(let r=0;r<i;r++){let s=4*Math.max(r-1,0),l=4*Math.min(r+1,i-1),d=4*Math.max(e-1,0)*i,c=4*Math.min(e+1,o-1)*i,u=4*e*i,h=4*r;for(let e=0;e<4;e++){let r=e+d,i=e+c,o=e+u;n[u+h+e]=a(t[r+h],t[o+s],t[o+h],t[o+l],t[i+h])}}},e._filters[Q5.ERODE]=t=>{e._filters[Q5.DILATE](t,Math.min)},e._filters[Q5.BLUR]=(n,a)=>{a=a||1,a=Math.floor(a*e._pixelDensity),r(),t.set(n);let i=2*a+1,o=function(e){let t=new Float32Array(e),r=.3*a+.8,n=r*r*2;for(let a=0;a<e;a++){let i=a-e/2,o=Math.exp(-i*i/n)/(2.5066282746*r);t[a]=o}return t}(i),[s,l]=[e.canvas.width,e.canvas.height];for(let e=0;e<l;e++)for(let r=0;r<s;r++){let l=0,d=0,c=0,u=0;for(let n=0;n<i;n++){let i=4*(e*s+Math.min(Math.max(r-a+n,0),s-1));l+=t[i]*o[n],d+=t[i+1]*o[n],c+=t[i+2]*o[n],u+=t[i+3]*o[n]}let h=4*(e*s+r);n[h]=l,n[h+1]=d,n[h+2]=c,n[h+3]=u}t.set(n);for(let e=0;e<l;e++)for(let r=0;r<s;r++){let d=0,c=0,u=0,h=0;for(let n=0;n<i;n++){let i=4*(Math.min(Math.max(e-a+n,0),l-1)*s+r);d+=t[i]*o[n],c+=t[i+1]*o[n],u+=t[i+2]*o[n],h+=t[i+3]*o[n]}let f=4*(e*s+r);n[f]=d,n[f+1]=c,n[f+2]=u,n[f+3]=h}});let i=e._getImageData(0,0,e.canvas.width,e.canvas.height);e._filters[n](i.data,a),e.ctx.putImageData(i,0,0)}},Q5.renderers.c2d.text=(e,t)=>{e._textAlign="left",e._textBaseline="alphabetic",e._textSize=12;let r="sans-serif",n=!1,a=15,i=3,o="normal",s="normal",l=0,d=!1,c=0;e._fontMod=!1;let u=e._textCache={};e.loadFont=(t,r)=>{let n;if(t.includes("fonts.googleapis.com/css"))n=function(e,t){e.startsWith("http")||(e="https://"+e);const r=new URL(e).searchParams,n=r.get("family");if(!n)return console.error("Invalid Google Fonts URL: missing family parameter"),null;const a=n.split(":")[0];let i={family:a};return i.promise=(async()=>{try{const r=await fetch(e);if(!r.ok)throw new Error(`Failed to fetch Google Font: ${r.status} ${r.statusText}`);let n,o=await r.text(),s=/@font-face\s*{([^}]*)}/g,l=/src:\s*url\(([^)]+)\)[^;]*;/,d=/font-family:\s*['"]([^'"]+)['"]/,c=/font-weight:\s*([^;]+);/,u=/font-style:\s*([^;]+);/,h=[];for(;null!==(n=s.exec(o));){let e=n[1],t=l.exec(e);if(!t)continue;let r=t[1],a=d.exec(e);if(!a)continue;let i=a[1],o=c.exec(e),s=o?o[1]:"400",f=u.exec(e),p=f?f[1]:"normal",g=`${i}-${s}-${p}`.replace(/\s+/g,"-"),m=new FontFace(i,`url(${r})`,{weight:s,style:p});document.fonts.add(m);try{await m.load(),h.push(m)}catch(e){console.error(`Failed to load font face: ${g}`,e)}}return i._usedAwait&&(i={family:a}),i.faces=h,delete i.then,t&&t(i),i}catch(e){throw console.error("Error loading Google Font:",e),e}})(),i}(t,r);else{let e=t.split("/").pop().split(".")[0].replace(" ","");n={family:e};let a=new FontFace(e,`url(${encodeURI(t)})`);document.fonts.add(a),n.promise=new Promise(((e,t)=>{a.load().then((()=>{delete n.then,r&&r(a),e(a)})).catch((e=>{t(e)}))}))}return e._loaders.push(n.promise),e.textFont(n.family),n.then=(e,t)=>(n._usedAwait=!0,n.promise.then(e,t)),n},e.textFont=t=>{if(t&&"string"!=typeof t&&(t=t.family),!t||t==r)return r;r=t,e._fontMod=!0,l=-1},e.textSize=t=>{if(null==t)return e._textSize;e._textSize=t,e._fontMod=!0,l=-1,n||(a=1.25*t,i=a-t)},e.textStyle=t=>{if(!t)return o;o=t,e._fontMod=!0,l=-1},e.textWeight=t=>{if(!t)return s;s=t,e._fontMod=!0,l=-1},e.textLeading=t=>null==t?a||1.25*e._textSize:(n=!0,t==a?a:(a=t,i=t-e._textSize,void(l=-1))),e.textAlign=(t,r)=>{e.ctx.textAlign=e._textAlign=t,r&&(e.ctx.textBaseline=e._textBaseline=r==e.CENTER?"middle":r)},e._updateFont=()=>{e.ctx.font=`${o} ${s} ${e._textSize}px ${r}`,e._fontMod=!1},e.textWidth=t=>(e._fontMod&&e._updateFont(),e.ctx.measureText(t).width),e.textAscent=t=>(e._fontMod&&e._updateFont(),e.ctx.measureText(t).actualBoundingBoxAscent),e.textDescent=t=>(e._fontMod&&e._updateFont(),e.ctx.measureText(t).actualBoundingBoxDescent),e.textFill=e.fill,e.textStroke=e.stroke;e.createTextImage=(t,r,n)=>{d=!0;let a=e.text(t,0,0,r,n);return d=!1,a};let h=[];e.text=(t,n,s,f,p)=>{if(void 0===t||!e._doFill&&!e._doStroke)return;t=t.toString();let g,m,x,_,v,b,y,S,w=e.ctx;if(e._fontMod&&e._updateFont(),d)if(-1==l&&(()=>{let t=r+e._textSize+o+a,n=5381;for(let e=0;e<t.length;e++)n=33*n^t.charCodeAt(e);l=n>>>0})(),m=e._fill+e._stroke+e._strokeWeight,x=u[t],x?_=x[l]:x=u[t]={},_){if(g=_[m],g)return g;if(_.size>=4){for(let e in _){g=_[e],delete _[e];break}v=!0}}else _=x[l]={};if(-1==t.indexOf("\n")?h[0]=t:h=t.split("\n"),t.length>f){let e=[];for(let t of h){let r=0;for(;r<t.length;){let n=r+f;if(n>=t.length){e.push(t.slice(r));break}let a=t.lastIndexOf(" ",n);(-1===a||a<r)&&(a=n),e.push(t.slice(r,a)),r=a+1}}h=e}if(d){if(b=0,y=a,g){let e=g.canvas;g.ctx.clearRect(0,0,e.width,e.height),g.modified=!0}else{let t=e.ctx.textBaseline;e.ctx.textBaseline="alphabetic";let r=w.measureText(" "),n=r.fontBoundingBoxAscent,o=r.fontBoundingBoxDescent;e.ctx.textBaseline=t;let s=0;for(let e of h){let t=w.measureText(e).width;t>s&&(s=t)}let l=Math.ceil(s),d=Math.ceil(a*h.length+o);g=e.createImage.call(e,l,d,{pixelDensity:e._pixelDensity,defaultImageScale:1/e._pixelDensity}),g._ascent=n,g._descent=o,g._top=o+i,g._middle=g._top+.5*n+a*(h.length-1)*.5,g._bottom=g._top+n+a*(h.length-1),g._leading=a}w=g.ctx,w.font=e.ctx.font,w.fillStyle=e._fill,w.strokeStyle=e._stroke,w.lineWidth=e.ctx.lineWidth}else b=n,y=s,"middle"==e._textBaseline?y-=a*(h.length-1)*.5:"bottom"==e._textBaseline&&(y-=a*(h.length-1));e._fillSet||(S=w.fillStyle,w.fillStyle="black");let C=0;for(let t of h)if(e._doStroke&&e._strokeSet&&w.strokeText(t,b,y),e._doFill&&w.fillText(t,b,y),y+=a,C++,C>=p)break;if(h=[],e._fillSet||(w.fillStyle=S),d){if(_[m]=g,v||(_.size||(Object.defineProperty(_,"size",{writable:!0,enumerable:!1}),_.size=0),_.size++,c++),c>Q5.MAX_TEXT_IMAGES){for(const e in u){x=u[e];for(const e in x){_=x[e];for(let e in _){let t=_[e];t._texture&&t._texture.destroy(),delete _[e]}}}c=0}return g}},e.textImage=(t,r,n)=>{"string"==typeof t&&(t=e.createTextImage(t));let a=e._imageMode;e._imageMode="corner";let i=e._textAlign;"center"==i?r-=t.canvas.hw:"right"==i&&(r-=t.width);let o=e._textBaseline;"alphabetic"==o?n-=t._leading:"middle"==o?n-=t._middle:"bottom"==o?n-=t._bottom:"top"==o&&(n-=t._top),e.image(t,r,n),e._imageMode=a}},Q5.fonts=[],Q5.MAX_TEXT_IMAGES=5e3,Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e.RGBHDR=e._colorMode="rgb",e.HSL="hsl",e.HSB="hsb",e.OKLCH="oklch",e.SRGB="srgb",e.DISPLAY_P3="display-p3",e.colorMode=(r,n,a)=>{e._colorMode=r;let i="srgb"==e.canvas.colorSpace||"srgb"==a;e._srgb=i,n??="rgb"==r&&(e._c2d||i)?255:1,e._colorFormat="integer"==n||255==n?255:1,"oklch"==r?t.Color=Q5.ColorOKLCH:"hsl"==r?t.Color=i?Q5.ColorHSL:Q5.ColorHSL_P3:"hsb"==r?t.Color=i?Q5.ColorHSB:Q5.ColorHSB_P3:(255==e._colorFormat?t.Color=i?Q5.ColorRGB_8:Q5.ColorRGB_P3_8:t.Color=i?Q5.ColorRGB:Q5.ColorRGB_P3,e._colorMode="rgb")},e._namedColors={aqua:[0,255,255],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],coral:[255,127,80],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],silver:[192,192,192],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,n,a)=>{let i=e.Color;if(t._isColor)return new i(...t.levels);if(null==r){if("string"==typeof t){if("#"==t[0])t.length<=5?(t.length>4&&(a=parseInt(t[4]+t[4],16)),n=parseInt(t[3]+t[3],16),r=parseInt(t[2]+t[2],16),t=parseInt(t[1]+t[1],16)):(t.length>7&&(a=parseInt(t.slice(7,9),16)),n=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]){let e=new i(0,0,0);return e._css=t,e.toString=function(){return this._css},e}if([t,r,n,a]=e._namedColors[t],"rgb"!=e._colorMode)return i=e._srgb?Q5.ColorRGB_8:Q5.ColorRGB_P3_8,new i(t,r,n,a)}1==e._colorFormat&&(t/=255,r&&(r/=255),n&&(n/=255),a&&(a/=255))}(Array.isArray(t)||t.constructor==Float32Array)&&([t,r,n,a]=t)}return null==n?e._colorMode==Q5.OKLCH?new i(t,0,0,r):new i(t,t,t,r):new i(t,r,n,a)},e.red=e=>e.r,e.green=e=>e.g,e.blue=e=>e.b,e.alpha=e=>e.a,e.lightness=t=>{if(t.l)return t.l;let r=100*(.2126*t.r+.7152*t.g+.0722*t.b);return 255==e._colorFormat?r/255:r},e.hue=t=>{if(t.h)return t.h;let r=t.r,n=t.g,a=t.b;255==e._colorFormat&&(r/=255,n/=255,a/=255);let i,o=Math.max(r,n,a),s=Math.min(r,n,a);return i=o==s?0:o==r?60*(n-a)/(o-s):o==n?60*(a-r)/(o-s)+120:60*(r-n)/(o-s)+240,i<0&&(i+=360),i},e.lerpColor=(t,r,n)=>{if(n=Math.max(0,Math.min(1,n)),"rgb"==e._colorMode)return new e.Color(e.lerp(t.r,r.r,n),e.lerp(t.g,r.g,n),e.lerp(t.b,r.b,n),e.lerp(t.a,r.a,n));{let a=r.h-t.h;a>180&&(a-=360),a<-180&&(a+=360);let i=t.h+n*a;return i<0&&(i+=360),i>360&&(i-=360),new e.Color(e.lerp(t.l,r.l,n),e.lerp(t.c,r.c,n),i,e.lerp(t.a,r.a,n))}}},Q5.Color=class{constructor(){this._isColor=!0,this._q5Color=!0}get alpha(){return this.a}set alpha(e){this.a=e}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,r,n){super(),this.l=e,this.c=t,this.h=r,this.a=n??1}get levels(){return[this.l,this.c,this.h,this.a]}equals(e){return e&&this.l==e.l&&this.c==e.c&&this.h==e.h&&this.a==e.a}isSameColor(e){return e&&this.l==e.l&&this.c==e.c&&this.h==e.h}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}get lightness(){return this.l}set lightness(e){this.l=e}get chroma(){return this.c}set chroma(e){this.c=e}get hue(){return this.h}set hue(e){this.h=e}},Q5.ColorRGB=class extends Q5.Color{constructor(e,t,r,n){super(),this.r=e,this.g=t,this.b=r,this.a=n??1}get levels(){return[this.r,this.g,this.b,this.a]}equals(e){return e&&this.r==e.r&&this.g==e.g&&this.b==e.b&&this.a==e.a}isSameColor(e){return e&&this.r==e.r&&this.g==e.g&&this.b==e.b}toString(){return`color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`}get red(){return this.r}set red(e){this.r=e}get green(){return this.g}set green(e){this.g=e}get blue(){return this.b}set blue(e){this.b=e}},Q5.ColorRGB_P3=class extends Q5.ColorRGB{toString(){return`color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGB_8=class extends Q5.ColorRGB{constructor(e,t,r,n){super(e,t,r,n??255)}setRed(e){this.r=e}setGreen(e){this.g=e}setBlue(e){this.b=e}setAlpha(e){this.a=e}toString(){return`rgb(${this.r} ${this.g} ${this.b} / ${this.a/255})`}},Q5.ColorRGB_P3_8=class extends Q5.ColorRGB_8{constructor(e,t,r,n){super(e,t,r,n??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),n=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${r} / ${n})`,this._edited=!1}return this._css}},Q5.ColorHSL=class extends Q5.Color{constructor(e,t,r,n){super(),this.h=e,this.s=t,this.l=r,this.a=n??1}get levels(){return[this.h,this.s,this.l,this.a]}equals(e){return e&&this.h==e.h&&this.s==e.s&&this.l==e.l&&this.a==e.a}isSameColor(e){return e&&this.h==e.h&&this.s==e.s&&this.l==e.l}toString(){return`hsl(${this.h} ${this.s} ${this.l} / ${this.a})`}get hue(){return this.h}set hue(e){this.h=e}get saturation(){return this.s}set saturation(e){this.s=e}get lightness(){return this.l}set lightness(e){this.l=e}},Q5.ColorHSL_P3=class extends Q5.ColorHSL{toString(){return`color(display-p3 ${Q5.HSLtoRGB(this.h,this.s,this.l).join(" ")} / ${this.a})`}},Q5.ColorHSB=class extends Q5.ColorHSL{constructor(e,t,r,n){super(e,t,r,n),delete this.l,this.b=r}get levels(){return[this.h,this.s,this.b,this.a]}equals(e){return e&&this.h==e.h&&this.s==e.s&&this.b==e.b&&this.a==e.a}isSameColor(e){return e&&this.h==e.h&&this.s==e.s&&this.b==e.b}toString(){return`hsl(${Q5.HSBtoHSL(this.h,this.s,this.b).join(" ")} / ${this.a})`}get v(){return this.b}set v(e){this.b=e}get brightness(){return this.b}set brightness(e){this.b=e}get value(){return this.b}set value(e){this.b=e}},Q5.ColorHSB_P3=class extends Q5.ColorHSB{toString(){return`color(display-p3 ${Q5.HSLtoRGB(...Q5.HSBtoHSL(this.h,this.s,this.b)).join(" ")} / ${this.a})`}},Q5.HSLtoRGB=(e,t,r)=>{r/=100;let n=t/100*Math.min(r,1-r),a=(t,a=(t+e/30)%12)=>r-n*Math.max(Math.min(a-3,9-a,1),-1);return[a(0),a(8),a(4)]},Q5.HSBtoHSL=(e,t,r,n=r*(1-t/200))=>[e,n&&100!=n?(r-n)/Math.min(n,100-n)*100:0,n];{const e=(e,t)=>[e[0]*t[0]+e[1]*t[1]+e[2]*t[2],e[3]*t[0]+e[4]*t[1]+e[5]*t[2],e[6]*t[0]+e[7]*t[1]+e[8]*t[2]],t=(e,t,r)=>[e,isNaN(r)?0:t*Math.cos(r*Math.PI/180),isNaN(r)?0:t*Math.sin(r*Math.PI/180)],r=e=>e.map((e=>Math.max(0,Math.min(1,Math.abs(e)>.0031308?(e<0?-1:1)*(1.055*Math.abs(e)**(1/2.4)-.055):12.92*e)))),n=t=>{const r=e([1,.3963377773761749,.2158037573099136,1,-.1055613458156586,-.0638541728258133,1,-.0894841775298119,-1.2914855480194092],t);return e([1.2268798758459243,-.5578149944602171,.2813910456659647,-.0405757452148008,1.112286803280317,-.0717110580655164,-.0763729366746601,-.4214933324022432,1.5869240198367816],r.map((e=>e**3)))},a=t=>e([3.2409699419045226,-1.537383177570094,-.4986107602930034,-.9692436362808796,1.8759675015077202,.04155505740717559,.05563007969699366,-.20397695888897652,1.0569715142428786],t);Q5.OKLCHtoRGB=(e,i,o)=>r(a(n(t(e,i,o))))}Q5.modules.display=e=>{if(!e.canvas||e._isGraphics)return;let t=e.canvas;e.MAXED="maxed",e.SMOOTH="smooth",e.PIXELATED="pixelated",0!=Q5._instanceCount||Q5._server||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 display: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\nmain.q5-centered,\nmain.q5-maxed {\n\theight: 100vh;\n}\nmain {\n\toverscroll-behavior: none;\n}\n</style>"),e._adjustDisplay=e=>{let r=t.style;if(r)if("normal"==t.displayMode){if(!e)return;r.width=t.w*t.displayScale+"px",r.height=t.h*t.displayScale+"px"}else{let e=t.parentElement.getBoundingClientRect();t.w/t.h>e.width/e.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",n="smooth",a=1)=>{Q5._server||("string"==typeof a&&(a=parseFloat(a.slice(1))),"fullscreen"==r&&(r="maxed"),"center"==r&&(r="centered"),t.displayMode&&(t.parentElement.classList.remove("q5-"+t.displayMode),t.classList.remove("q5-pixelated")),t.parentElement.classList.add("q5-"+r),"pixelated"==n&&(t.classList.add("q5-pixelated"),e.pixelDensity(1),e.defaultImageScale(1),e.noSmooth&&e.noSmooth(),e.textFont&&e.textFont("monospace")),Object.assign(t,{displayMode:r,renderQuality:n,displayScale:a}),e.ctx&&e.pushStyles(),e._adjustDisplay(!0),e.ctx&&e.popStyles())},e.fullscreen=e=>{if(null==e)return document.fullscreenElement;e?document.body.requestFullscreen():document.exitFullscreen()}},Q5.modules.dom=(e,t)=>{e.elementMode=t=>e._elementMode=t,e.createElement=(t,r)=>{let n=document.createElement(t);return"center"==e._elementMode&&(n.style.transform="translate(-50%, -50%)"),r&&(n.innerHTML=r),Object.defineProperty(n,"x",{get:()=>n._x,set:t=>{let r=n.style.position;r&&"relative"!=r||(n.style.position="absolute");let a=e.canvas.offsetLeft+t;n.style.left=a+"px",n._x=a}}),Object.defineProperty(n,"y",{get:()=>n._y,set:t=>{let r=n.style.position;r&&"relative"!=r||(n.style.position="absolute");let a=e.canvas.offsetTop+t;n.style.top=a+"px",n._y=a}}),Object.defineProperty(n,"width",{get:()=>parseFloat(n.style.width||0),set:e=>n.style.width=e+"px"}),Object.defineProperty(n,"height",{get:()=>parseFloat(n.style.height||0),set:e=>n.style.height=e+"px"}),n.position=(e,t,r)=>(r&&(n.style.position=r),n.x=e,n.y=t,n),Object.defineProperty(n,"size",{writable:!0}),n.size=(e,t)=>(n.width=e,n.height=t,n),n.center=()=>(n.style.position="absolute",n.x=e.canvas.hw,n.y=e.canvas.hh,n),n.show=()=>(n.style.display="",n),n.hide=()=>(n.style.display="none",n),n.parent=e=>(e.append(n),n),e._addEventMethods(n),e._elements.push(n),e.canvas?e.canvas.parentElement.append(n):document.body.append(n),n.elt=n,n},e.createEl=e.createElement,e._addEventMethods=e=>{let t=e.addEventListener;e.mousePressed=e=>t("mousedown",e),e.mouseReleased=e=>t("mouseup",e),e.mouseClicked=e=>t("click",e),e.mouseMoved=e=>t("mousemove",e),e.mouseWheel=e=>t("wheel",e)},e.createA=(t,r,n)=>{let a=e.createEl("a",r);return a.href=t,a.target=n?"_blank":"_self",a},e.createButton=t=>e.createEl("button",t),e.createCheckbox=(t="",r=!1)=>{let n=e.createEl("input");n.type="checkbox",n.checked=r;let a=e.createEl("label",t);return a.addEventListener("click",(()=>{n.checked=!n.checked,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))})),n.insertAdjacentElement("afterend",a),n.label=a,n},e.createColorPicker=(t="#ffffff")=>{let r=e.createEl("input");return r.type="color",r.value=t.toString(),r},e.createDiv=t=>e.createEl("div",t),e.createImg=t=>{let r=e.createEl("img");return r.crossOrigin="anonymous",r.src=t,r},e.createInput=(t="",r="text")=>{let n=e.createEl("input");return n.value=t,n.type=r,n.style.boxSizing="border-box",n},e.createP=t=>e.createEl("p",t);let r=0;function n(t){t.width||=t.videoWidth,t.height||=t.videoHeight,t.defaultWidth=t.width*e._defaultImageScale,t.defaultHeight=t.height*e._defaultImageScale,t.ready=!0}e.createRadio=t=>{let n=e.createEl("div");return n.name=t||"radio"+r++,n.buttons=[],Object.defineProperty(n,"value",{get:()=>n.selected?.value,set:e=>{let t=n.buttons.find((t=>t.value==e));t&&(t.checked=!0,n.selected=t)}}),n.option=(t,r)=>{let a=e.createEl("input");a.type="radio",a.name=n.name,a.value=r||t,a.addEventListener("input",(()=>n.selected=a));let i=e.createEl("label",t);return i.addEventListener("click",(()=>{a.checked=!0,n.selected=a,a.dispatchEvent(new Event("input",{bubbles:!0})),a.dispatchEvent(new Event("change",{bubbles:!0}))})),a.label=i,n.append(a),n.append(i),n.buttons.push(a),n},n},e.createSelect=t=>{let r=e.createEl("select");if(t){let n=e.createEl("option",t);n.disabled=!0,n.selected=!0,r.append(n)}return Object.defineProperty(r,"selected",{get:()=>r.multiple?Array.from(r.selectedOptions).map((e=>e.textContent)):r.selectedOptions[0]?.textContent,set:e=>{if(r.multiple)Array.from(r.options).forEach((t=>{t.selected=e.includes(t.textContent)}));else{const t=Array.from(r.options).find((t=>t.textContent===e));t&&(t.selected=!0)}}}),Object.defineProperty(r,"value",{get:()=>r.multiple?Array.from(r.selectedOptions).map((e=>e.value)):r.selectedOptions[0]?.value,set:e=>{if(r.multiple)r.options.forEach((t=>t.selected=e.includes(t.value)));else{let t;for(let n=0;n<r.options.length;n++)if(r.options[n].value==e){t=r.options[n];break}t&&(t.selected=!0)}}}),r.option=(t,n)=>{let a=e.createEl("option",t);return a.value=n||t,r.append(a),r},r},e.createSlider=(t,r,n,a)=>{let i=e.createEl("input");return i.type="range",i.min=t,i.max=r,i.step=a,i.value=n,i.val=()=>parseFloat(i.value),i},e.createSpan=t=>e.createEl("span",t),e.createVideo=t=>{let r=e.createEl("video");return r.crossOrigin="anonymous",t&&(r.promise=new Promise((a=>{r.addEventListener("loadeddata",(()=>{delete r.then,r._usedAwait&&(r=e.createEl("video"),r.crossOrigin="anonymous",r.src=t),n(r),a(r)})),r.src=t})),e._loaders.push(r.promise),r.then=(e,t)=>(r._usedAwait=!0,r.promise.then(e,t))),r},e.createCapture=function(t,r=!0,a){let i="string"==typeof t?{[t]:!0}:t||{video:!0,audio:!0};!0===i.video&&(i.video={width:3840,height:2160}),i.video.facingMode??="user";let o=e.createVideo();return o.promise=(async()=>{let t;try{t=await navigator.mediaDevices.getUserMedia(i)}catch(e){throw e}return delete o.then,o._usedAwait&&(o=e.createVideo()),function(t){t.playsinline=t.autoplay=!0,r&&(t.flipped=!0,t.style.transform="scale(-1, 1)"),t.loadPixels=()=>{let r=e.createGraphics(t.videoWidth,t.videoHeight,{renderer:"c2d"});r.image(t,0,0),r.loadPixels(),t.pixels=r.pixels,r.remove()}}(o),o.srcObject=t,await new Promise((e=>o.addEventListener("loadeddata",e))),n(o),a&&a(o),o})(),e._loaders.push(o.promise),o.then=(e,t)=>(o._usedAwait=!0,o.promise.then(e,t)),o},e.findElement=e=>document.querySelector(e),e.findElements=e=>document.querySelectorAll(e)},Q5.modules.fes=e=>{if(e._fes=async t=>{if(Q5.disableFriendlyErrors)return;t._handledByFES=!0;let r=t.stack?.split("\n");if(!r?.length)return;let n=1,a="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(n=0,a="@");r[n].indexOf("q5")>=0;)n++;let i=r[n].split(a).at(-1);i.startsWith("blob:")&&(i=i.slice(5)),i=i.split(")")[0];let o=i.split(":"),s=parseInt(o.at(-2));o[o.length-1]=o.at(-1).split(")")[0];let l=t.file||o.slice(0,-2).join(":"),d=l.split("/").at(-1);try{let t=(await(await fetch(l)).text()).split("\n"),r=t[s-1]?.trim()??"",n=["🐛","🐞","🐜","🦗","🦋","🪲"][Math.floor(6*Math.random())],a=window.self!==window.top,i=`q5.js ${n}`,o=` Error in ${d} on line ${s}:\n\n${r}`;a?e.log(i+o):e.log(`%c${i}%c${o}`,"background: #b7ebff; color: #000;","")}catch(e){}},"undefined"!=typeof window&&window.addEventListener){let t=new Error,r=t.stack?.split("\n")||"";for(let t of r){let r=t.match(/(https?:\/\/[^\s)]+\.js|\b\/[^\s)]+\.js)/);if(r){let t=r[1];if(!/q5|p5play/i.test(t)){e._sketchFile=t;break}}}e._sketchFile&&(window.addEventListener("error",(t=>{let r=t.error;t.filename!==e._sketchFile||r?._handledByFES||(r.file=t.filename,e._fes(r))})),window.addEventListener("unhandledrejection",(t=>{let r=t.reason;r?.stack?.includes(e._sketchFile)&&!r?._handledByFES&&e._fes(r)})))}if(e._isGlobal&&0!=Q5.online&&null!=typeof navigator&&navigator.onLine){!async function(){try{let e=await fetch("https://data.jsdelivr.com/v1/package/npm/q5");if(!e.ok)return;let t=(await e.json()).tags.latest;t=t.slice(0,t.lastIndexOf(".")),t!=Q5.version&&console.warn(`q5.js v${t} is now available! Consider updating from v${Q5.version}.`)}catch(e){}}()}},Q5.modules.input=(e,t)=>{if(e._isGraphics)return;e.mouseX=0,e.mouseY=0,e.pmouseX=0,e.pmouseY=0,e.touches=[],e.pointers={},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={},n=[Q5.LEFT,Q5.CENTER,Q5.RIGHT],a=e.canvas;e._startAudio=()=>{Q5.aud&&"running"==Q5.aud?.state||e.userStartAudio()},e._updatePointer=r=>{let n=r.pointerId;e.pointers[n]??={event:r};let i,o,s=e.pointers[n];if(s.event=r,a){let t=a.getBoundingClientRect(),n=a.scrollWidth/e.width||1,s=a.scrollHeight/e.height||1;i=(r.clientX-t.left)/n,o=(r.clientY-t.top)/s,e._webgpu&&(i-=a.hw,o-=a.hh)}else i=r.clientX,o=r.clientY;s.x=i,s.y=o,!r.isPrimary&&r.pointerId||(document.pointerLockElement?(t.mouseX+=r.movementX,t.mouseY+=r.movementY):(t.mouseX=i,t.mouseY=o),t.moveX=r.movementX,t.moveY=r.movementY)};let i=0;function o(t){const r=e.canvas.getBoundingClientRect(),n=e.canvas.scrollWidth/e.width||1,a=e.canvas.scrollHeight/e.height||1;let i=0,o=0;return e._webgpu&&(i=e.halfWidth,o=e.halfHeight),{x:(t.clientX-r.left)/n-i,y:(t.clientY-r.top)/a-o,id:t.identifier}}if(e._onpointerdown=r=>{i++,e._startAudio(),e._updatePointer(r),t.mouseIsPressed=!0,t.mouseButton=n[r.button],e.mousePressed(r)},e._onpointermove=t=>{a&&!a.visible||(e._updatePointer(t),e.mouseIsPressed?e.mouseDragged(t):e.mouseMoved(t))},e._onpointerup=r=>{t.mouseIsPressed=!1,i>0&&(i--,e._updatePointer(r),delete e.pointers[r.pointerId],e.mouseReleased(r))},e._onclick=r=>{e._updatePointer(r),t.mouseIsPressed=!0,e.mouseClicked(r),t.mouseIsPressed=!1},e._ondblclick=r=>{e._updatePointer(r),t.mouseIsPressed=!0,e.doubleClicked(r),t.mouseIsPressed=!1},e._onwheel=t=>{e._updatePointer(t),t.delta=t.deltaY;let r=e.mouseWheel(t);(e._isGlobal&&!r||0==r)&&t.preventDefault()},e.cursor=(t,r,n)=>{let a="";t.includes(".")&&(t=`url("${t}")`,a=", auto"),void 0!==r&&(t+=" "+r+" "+n),e.canvas.style.cursor=t+a},e.noCursor=()=>e.canvas.style.cursor="none",e.pointerLock=(e=!1)=>{document.body?.requestPointerLock({unadjustedMovement:e})},e._onkeydown=n=>{n.repeat||(e._startAudio(),t.keyIsPressed=!0,t.key=n.key,t.keyCode=n.keyCode,r[e.keyCode]=r[e.key.toLowerCase()]=!0,e.keyPressed(n),1==n.key.length&&e.keyTyped(n))},e._onkeyup=n=>{t.keyIsPressed=!1,t.key=n.key,t.keyCode=n.keyCode,r[e.keyCode]=r[e.key.toLowerCase()]=!1,e.keyReleased(n)},e.keyIsDown=e=>!!r["string"==typeof e?e.toLowerCase():e],e._updateTouches=t=>{if(a&&!a.visible)return;let r=[...t.changedTouches].map(o);for(let t of r){let r=e.touches.find((e=>e.id==t.id));r?(r.x=t.x,r.y=t.y):e.touches.push(t)}for(let r=e.touches.length-1;r>=0;r--){let n=e.touches[r],a=!1;for(let e=0;e<t.touches.length;e++)if(t.touches[e].identifier===n.id){a=!0;break}a||e.touches.splice(r,1)}},e._ontouchstart=t=>{e._startAudio(),e.touchStarted(t)||t.preventDefault()},e._ontouchmove=t=>{e.touchMoved(t)||t.preventDefault()},e._ontouchend=t=>{e.touchEnded(t)||t.preventDefault()},window){let t=window.addEventListener;t("keydown",(t=>e._onkeydown(t)),!1),t("keyup",(t=>e._onkeyup(t)),!1);let r=window.PointerEvent?"pointer":"mouse";t(r+"move",(t=>e._onpointermove(t)),!1),t(r+"up",(t=>e._onpointerup(t))),t(r+"cancel",(t=>e._onpointerup(t))),t("touchstart",(t=>e._updateTouches(t))),t("touchmove",(t=>e._updateTouches(t))),t("touchend",(t=>e._updateTouches(t))),t("touchcancel",(t=>e._updateTouches(t))),a&&a.addEventListener("wheel",(t=>e._onwheel(t))),!e._isGlobal&&a&&(t=a.addEventListener.bind(a)),t(r+"down",(t=>e._onpointerdown(t))),t("click",(t=>e._onclick(t))),t("dblclick",(t=>e._ondblclick(t))),a&&(t=a.addEventListener.bind(a)),t("touchstart",(t=>e._ontouchstart(t))),t("touchmove",(t=>e._ontouchmove(t))),t("touchend",(t=>e._ontouchend(t))),t("touchcancel",(t=>e._ontouchend(t)))}},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.TWO_PI=e.TAU=2*Math.PI,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.pow=Math.pow,e.sqrt=Math.sqrt,e.SHR3=1,e.LCG=2,e.round=(e,t=0)=>{let r=10**t;return Math.round(e*r)/r};let r=e._angleMode=0;e.angleMode=t=>(r=e._angleMode=0==t||"radians"==t?0:1,r?"degrees":"radians");let n=e._DEGTORAD=Math.PI/180,a=e._RADTODEG=180/Math.PI;function i(){let e,t,r=4294967295;return{setSeed(n){e=t=(n??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,n,a,i)=>{let o=n+1*(e-t)/(r-t)*(a-n);return i?n<a?Math.min(Math.max(o,n),a):Math.min(Math.max(o,a),n):o},e.dist=function(){let e=arguments;return 2==e.length?Math.hypot(e[0].x-e[1].x,e[0].y-e[1].y):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.lerp=(e,t,r)=>e*(1-r)+t*r,e.constrain=(e,t,r)=>Math.min(Math.max(e,t),r),e.norm=(t,r,n)=>e.map(t,r,n,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e),e.sin=e=>Math.sin(r?e*n:e),e.cos=e=>Math.cos(r?e*n:e),e.tan=e=>Math.tan(r?e*n:e),e.asin=e=>{let t=Math.asin(e);return r?t*a:t},e.acos=e=>{let t=Math.acos(e);return r?t*a:t},e.atan=e=>{let t=Math.atan(e);return r?t*a:t},e.atan2=(e,t)=>{let n=Math.atan2(e,t);return r?n*a:n};let o=i();o.setSeed(),e.randomSeed=e=>o.setSeed(e),e.random=(e,t)=>void 0===e?o.rand():"number"==typeof e?void 0!==t?o.rand()*(t-e)+e:o.rand()*e:e[Math.trunc(e.length*o.rand())],e.jit=(t=1)=>e.random(-t,t),e.randomGenerator=t=>{t==e.LCG?o=function(){const e=4294967296;let t,r;return{setSeed(n){r=t=(n??Math.random()*e)>>>0},getSeed:()=>t,rand:()=>(r=(1664525*r+1013904223)%e,r/e)}}():t==e.SHR3&&(o=i()),o.setSeed()};var s=new function(){var e,t,r,n=new Array(128),a=new Array(256),i=new Array(128),s=new Array(128),l=new Array(256),d=new Array(256),c=()=>4294967296*o.rand()-2147483648,u=()=>.5+2.328306e-10*(c()|0),h=()=>{for(var t,a,o,l,d=3.44262;;){if(t=r*i[e],0==e){do{o=u(),l=u(),t=.2904764*-Math.log(o),a=-Math.log(l)}while(a+a<t*t);return r>0?d+t:-d-t}if(s[e]+u()*(s[e-1]-s[e])<Math.exp(-.5*t*t))return t;if(r=c(),e=127&r,Math.abs(r)<n[e])return r*i[e]}},f=()=>{for(var r;;){if(0==e)return 7.69711-Math.log(u());if(r=t*l[e],d[e]+u()*(d[e-1]-d[e])<Math.exp(-r))return r;if((t=c())<a[e=255&t])return t*l[e]}};this.SHR3=c,this.UNI=u,this.RNOR=()=>(r=c(),e=127&r,Math.abs(r)<n[e]?r*i[e]:h()),this.REXP=()=>(t=c()>>>0)<n[e=255&t]?t*l[e]:f(),this.zigset=()=>{var e,t,r=2147483648,o=4294967296,c=3.442619855899,u=c,h=.00991256303526217,f=7.697117470131487,p=f,g=.003949659822581572;for(e=h/Math.exp(-.5*c*c),n[0]=Math.floor(c/e*r),n[1]=0,i[0]=e/r,i[127]=c/r,s[0]=1,s[127]=Math.exp(-.5*c*c),t=126;t>=1;t--)c=Math.sqrt(-2*Math.log(h/c+Math.exp(-.5*c*c))),n[t+1]=Math.floor(c/u*r),u=c,s[t]=Math.exp(-.5*c*c),i[t]=c/r;for(e=g/Math.exp(-f),a[0]=Math.floor(f/e*o),a[1]=0,l[0]=e/o,l[255]=f/o,d[0]=1,d[255]=Math.exp(-f),t=254;t>=1;t--)f=-Math.log(g/f+Math.exp(-f)),a[t+1]=Math.floor(f/p*o),p=f,d[t]=Math.exp(-f),l[t]=f/o}};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.NoiseGenerator=Q5.PerlinNoise,e.noiseMode=e=>{t.NoiseGenerator=Q5[e[0].toUpperCase()+e.slice(1)+"Noise"],l=null},e.noiseSeed=t=>{l=new e.NoiseGenerator(t)},e.noise=(t=0,r=0,n=0)=>(l??=new e.NoiseGenerator,l.noise(t,r,n)),e.noiseDetail=(t,r)=>{l??=new e.NoiseGenerator,t>0&&(l.octaves=t),r>0&&(l.falloff=r)}},Q5.NoiseGenerator=class{},Q5.PerlinNoise=class extends Q5.NoiseGenerator{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,n=[];for(let e=0;e<256;e++)n[e]=e;for(let a=255;a>0;a--)t=(e=16807*e%2147483647)%(a+1),r=n[a],n[a]=n[t],n[t]=r;return n}dot(e,t,r,n){return e[0]*t+e[1]*r+e[2]*n}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 n=this,a=0,i=1,o=1,s=0;for(let l=0;l<n.octaves;l++){const l=255&Math.floor(e*i),d=255&Math.floor(t*i),c=255&Math.floor(r*i),u=e*i-Math.floor(e*i),h=t*i-Math.floor(t*i),f=r*i-Math.floor(r*i),p=n.fade(u),g=n.fade(h),m=n.fade(f),x=n.p[l]+d,_=n.p[x]+c,v=n.p[x+1]+c,b=n.p[l+1]+d,y=n.p[b]+c,S=n.p[b+1]+c,w=n.mix(n.dot(n.grad3[n.p[_]%12],u,h,f),n.dot(n.grad3[n.p[y]%12],u-1,h,f),p),C=n.mix(n.dot(n.grad3[n.p[v]%12],u,h-1,f),n.dot(n.grad3[n.p[S]%12],u-1,h-1,f),p),Q=n.mix(n.dot(n.grad3[n.p[_+1]%12],u,h,f-1),n.dot(n.grad3[n.p[y+1]%12],u-1,h,f-1),p),M=n.mix(n.dot(n.grad3[n.p[v+1]%12],u,h-1,f-1),n.dot(n.grad3[n.p[S+1]%12],u-1,h-1,f-1),p),P=n.mix(w,C,g),E=n.mix(Q,M,g);a+=n.mix(P,E,m)*o,s+=o,o*=n.falloff,i*=2}return(a/s+1)/2}},Q5.modules.record=(e,t)=>{let r,n,a,i,o,s,l;function d(t={}){document.head.insertAdjacentHTML("beforeend","<style>\n.rec {\n\tdisplay: flex;\n\tz-index: 1000;\n\tgap: 6px;\n\tbackground: #1a1b1d;\n\tpadding: 6px 8px;\n\tborder-radius: 21px;\n\tbox-shadow: #0000001a 0px 4px 12px;\n\tborder: 2px solid transparent; \n\topacity: 0.6;\n\ttransition: all 0.3s;\n\twidth: 134px;\n\toverflow: hidden;\n}\n\n.rec:hover {\n\twidth: unset;\n\topacity: 0.96;\n}\n\n.rec.recording { border-color: #cc3e44; }\n\n.rec button,\n.rec select { cursor: pointer; }\n\n.rec button,\n.rec select,\n.rec input,\n.rec span {\n\tfont-family: sans-serif;\n\tfont-size: 14px;\n\tpadding: 2px 10px;\n\tborder-radius: 18px;\n\toutline: none;\n\tbackground: #232529;\n\tcolor: #d4dae6;\n\tbox-shadow: #0000001a 0px 4px 12px;\n\tborder: 1px solid #46494e;\n\tvertical-align: middle;\n\tline-height: 18px;\n\ttransition: all 0.3s;\n}\n\n.rec .audio-toggle {\n\tfont-size: 16px;\n\tpadding: 2px 10px;\n}\n\n.rec .bitrate input {\n\tborder-radius: 18px 0 0 18px;\n\tborder-right: 0;\n\twidth: 40px;\n\tpadding: 2px 5px 2px 10px;\n\ttext-align: right;\n}\n\n.rec .bitrate span {\n\tborder-radius: 0 18px 18px 0;\n\tborder-left: 0;\n\tpadding: 2px 10px 2px 5px;\n\tbackground: #333;\n}\n\n.rec .record-button { \n\tcolor: #cc3e44;\n\tfont-size: 18px;\n}\n\n.rec select:hover,\n.rec button:hover { background: #32343b; }\n\n.rec button:disabled {\n\topacity: 0.5;\n\tcolor: #969ba5;\n\tcursor: not-allowed;\n}\n</style>"),r=e.createEl("div"),r.className="rec",r.innerHTML='\n<button class="record-button"></button>\n<span class="record-timer"></span>\n<button></button>\n',[n,i,a]=r.children,r.x=r.y=8,r.resetTimer=()=>r.time={hours:0,minutes:0,seconds:0,frames:0},r.resetTimer();let d="video/mp4; codecs=";r.formats={"H.264":d+'"avc1.42E01E"',VP9:d+"vp9"};let h=d+'"avc1.640034"';e.canvas.width*e.canvas.height>32e5&&MediaRecorder.isTypeSupported(h)&&(r.formats["H.264"]=h),Object.assign(r.formats,t.formats),o=e.createSelect("format");for(const e in r.formats)o.option(e,r.formats[e]);o.title="Video Format",r.append(o);let g=e.createEl("div");g.className="bitrate",g.style.display="flex",r.append(g),s=e.createInput();let m=document.createElement("span");function x(){r.encoderSettings.mimeType=o.value}function _(){r.encoderSettings.videoBitsPerSecond=1e6*s.value}m.textContent="mbps",s.title=m.title="Video Bitrate",g.append(s),g.append(m),l=e.createEl("button"),l.className="audio-toggle active",l.textContent="🔊",l.title="Toggle Audio Recording",r.append(l),r.captureAudio=!0,l.addEventListener("click",(()=>{r.captureAudio=!r.captureAudio,l.textContent=r.captureAudio?"🔊":"🔇",l.classList.toggle("active",r.captureAudio)})),r.encoderSettings={},o.addEventListener("change",x),s.addEventListener("change",_),Object.defineProperty(r,"bitrate",{get:()=>s.value,set:e=>{s.value=e,_()}}),Object.defineProperty(r,"format",{get:()=>o.selected,set:e=>{e=e.toUpperCase(),r.formats[e]&&(o.selected=e,x())}}),r.format="H.264";let v=e.canvas.height;r.bitrate=v>=4320?96:v>=2160?64:v>=1440?48:v>=1080?32:v>=720?26:16,n.addEventListener("click",(()=>{e.recording?r.paused?u():e.pauseRecording():c()})),a.addEventListener("click",(()=>{r.paused?e.saveRecording():e.deleteRecording()})),f(),e.registerMethod("post",p)}function c(){if(!e.recording){if(e.userStartAudio(),!r.stream){r.frameRate??=e.getTargetFrameRate();let t=e.canvas.captureStream(r.frameRate);if(r.videoTrack=t.getVideoTracks()[0],r.captureAudio&&e.getAudioContext){let t=e.getAudioContext(),n=t.createMediaStreamDestination();t.destination.input?t.destination.input.connect(n):Q5.soundOut.connect(n),r.audioTrack=n.stream.getAudioTracks()[0],r.stream=new MediaStream([r.videoTrack,r.audioTrack])}else r.stream=t}r.mediaRecorder=new MediaRecorder(r.stream,r.encoderSettings),r.chunks=[],r.mediaRecorder.addEventListener("dataavailable",(e=>{e.data.size>0&&r.chunks.push(e.data)})),r.mediaRecorder.start(),t.recording=!0,r.paused=!1,r.classList.add("recording"),r.resetTimer(),f(!0)}}function u(){e.recording&&r.paused&&(r.mediaRecorder.resume(),r.paused=!1,f(!0))}function h(){e.recording&&(r.resetTimer(),r.mediaRecorder.stop(),t.recording=!1,r.paused=!1,r.classList.remove("recording"))}function f(e){n.textContent=e?"⏸":"⏺",n.title=(e?"Pause":"Start")+" Recording",a.textContent=e?"🗑️":"💾",a.title=(e?"Delete":"Save")+" Recording",a.disabled=!e}function p(){if(e.recording&&!r.paused){r.time.frames++;let t=e.getTargetFrameRate();r.time.frames>=t&&(r.time.seconds+=Math.floor(r.time.frames/t),r.time.frames%=t,r.time.seconds>=60&&(r.time.minutes+=Math.floor(r.time.seconds/60),r.time.seconds%=60,r.time.minutes>=60&&(r.time.hours+=Math.floor(r.time.minutes/60),r.time.minutes%=60)))}i.textContent=function(){let{hours:e,minutes:t,seconds:n,frames:a}=r.time;return`${String(e).padStart(2,"0")}:${String(t).padStart(2,"0")}:${String(n).padStart(2,"0")}:${String(a).padStart(2,"0")}`}()}e.recording=!1,e.createRecorder=e=>(r||d(e),r),e.record=t=>{r||(d(t),r.hide()),e.recording?r.paused&&u():c()},e.pauseRecording=()=>{e.recording&&!r.paused&&(r.mediaRecorder.pause(),r.paused=!0,f(),n.title="Resume Recording",a.disabled=!1)},e.deleteRecording=()=>{h(),f(),t.recording=!1},e.saveRecording=async n=>{if(!e.recording)return;await new Promise((e=>{r.mediaRecorder.onstop=e,h()}));let a=r.encoderSettings.mimeType,i=a.slice(6,a.indexOf(";")),o=URL.createObjectURL(new Blob(r.chunks,{type:a})),s=document.createElement("iframe"),l=document.createElement("a");s.style.display="none",s.name="download_"+Date.now(),document.body.append(s),l.target=s.name,l.href=o,n??=document.title+" "+(new Date).toLocaleString(void 0,{hour12:!1}).replace(","," at").replaceAll("/","-").replaceAll(":","_"),l.download=`${n}.${i}`,await new Promise((e=>{s.onload=()=>{document.body.removeChild(s),e()},l.click()})),setTimeout((()=>URL.revokeObjectURL(o)),1e3),f(),t.recording=!1}},Q5.modules.sound=(e,t)=>{e.Sound=Q5.Sound;let r=[];e.loadSound=(t,n)=>{let a=new Q5.Sound;return r.push(a),a.promise=(async()=>{let e;a._usedAwait&&(r.splice(r.indexOf(a),1),a=new Q5.Sound,r.push(a));try{await a.load(t)}catch(t){e=t}if(delete a.then,e)throw e;return n&&n(a),a})(),e._loaders.push(a.promise),a.then=(e,t)=>(a._usedAwait=!0,a.promise.then(e,t)),a},e.loadAudio=(t,r)=>{let n=new Audio(t);return n._isAudio=!0,n.crossOrigin="Anonymous",n.promise=new Promise(((e,a)=>{function i(){n.loaded||(delete n.then,n._usedAwait&&(n=new Audio(t),n._isAudio=!0,n.crossOrigin="Anonymous"),n.loaded=!0,r&&r(n),e(n))}n.addEventListener("canplay",i),n.addEventListener("suspend",i),n.addEventListener("error",a)})),e._loaders.push(n.promise),n.then=(e,t)=>(n._usedAwait=!0,n.promise.then(e,t)),n},e.getAudioContext=()=>Q5.aud,e.userStartAudio=()=>{if(window.AudioContext){if(Q5._offlineAudio){Q5._offlineAudio=!1,Q5.aud=new window.AudioContext,Q5.soundOut=Q5.aud.createGain(),Q5.soundOut.connect(Q5.aud.destination);for(let e of Q5.instances)e._userAudioStarted()}return Q5.aud.resume()}},e._userAudioStarted=()=>{for(let e of r)e.init()},e.outputVolume=e=>{Q5.soundOut&&(Q5.soundOut.gain.value=e)}},window.OfflineAudioContext&&(Q5.aud=new window.OfflineAudioContext(2,1,44100),Q5._offlineAudio=!0,Q5.soundOut=Q5.aud.createGain(),Q5.soundOut.connect(Q5.aud.destination)),Q5.Sound=class{constructor(){this._isSound=!0,this.sources=new Set,this.loaded=this.paused=!1}async load(e){this.url=e;let t=await fetch(e);this.buffer=await t.arrayBuffer(),this.buffer=await Q5.aud.decodeAudioData(this.buffer),Q5.aud&&this.init()}init(){this.buffer.length&&(this.gainNode=Q5.aud.createGain(),this.pannerNode=Q5.aud.createStereoPanner(),this.gainNode.connect(this.pannerNode),this.pannerNode.connect(Q5.soundOut),this.loaded=!0,this._volume&&(this.volume=this._volume),this._pan&&(this.pan=this._pan))}_newSource(e,t){let r=Q5.aud.createBufferSource();return r.buffer=this.buffer,r.connect(this.gainNode),r.loop=this._loop,r._startedAt=Q5.aud.currentTime,r._offset=e,r._duration=t,r.start(0,r._offset,r._duration),this.sources.add(r),r.promise=new Promise((e=>{r.onended=()=>{this.paused||(this.ended=!0,this._onended&&this._onended(),this.sources.delete(r),e())}})),r}play(e=0,t){if(!this.loaded)return;let r;if(this.paused){let e=[];for(let t of this.sources)e.push({offset:t._offset,duration:t._duration}),this.sources.delete(t);e.sort(((e,t)=>(e.duration??this.buffer.duration-e.offset)-(t.duration??this.buffer.duration-t.offset)));for(let t of e)r=this._newSource(t.offset,t.duration)}else r=this._newSource(e,t);return this.paused=this.ended=!1,r.promise}pause(){if(this.isPlaying()){for(let e of this.sources){e.stop();let t=Q5.aud.currentTime-e._startedAt;e._offset+=t,e._duration&&(e._duration-=t)}this.paused=!0}}stop(){for(let e of this.sources)e.stop(),this.sources.delete(e);this.paused=!1,this.ended=!0}get volume(){return this._volume}set volume(e){this.loaded&&(this.gainNode.gain.value=e),this._volume=e}get pan(){return this._pan}set pan(e){this.loaded&&(this.pannerNode.pan.value=e),this._pan=e}get loop(){return this._loop}set loop(e){this.sources.forEach((t=>t.loop=e)),this._loop=e}get playing(){return!this.paused&&this.sources.size>0}setVolume(e){this.volume=e}setPan(e){this.pan=e}setLoop(e){this.loop=e}isLoaded(){return this.loaded}isPlaying(){return this.playing}isPaused(){return this.paused}isLooping(){return this._loop}onended(e){this._onended=e}},Q5.modules.util=(e,t)=>{e._loadFile=(t,r,n)=>{let a={};return a.promise=fetch(t).then((e=>e.ok?"json"==n?e.json():e.text():(reject("error loading file"),null))).then((e=>("csv"==n&&(e=Q5.CSV.parse(e)),"string"==typeof e?a.text=e:Object.assign(a,e),delete a.then,r&&r(e),e))),e._loaders.push(a.promise),a.then=(e,t)=>a.promise.then(e,t),a},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.loadXML=(t,r)=>{let n={};return n.promise=fetch(t).then((e=>e.text())).then((e=>{let t=(new DOMParser).parseFromString(e,"application/xml");return n.DOM=t,delete n.then,r&&r(t),t})),e._loaders.push(n.promise),n.then=(e,t)=>n.promise.then(e,t),n};const r=/(jpe?g|png|gif|webp|avif|svg)/i,n=/(ttf|otf|woff2?|eot|json)/i,a=/(serif|sans-serif|monospace|cursive|fantasy)/i,i=/(wav|flac|mp3|ogg|m4a|aac|aiff|weba)/i;async function o(e,t,n){let a;if(t=t||"untitled",n=n||"png",r.test(n)){let t=e.canvas||e;a=await t.convertToBlob({type:"image/"+n})}else{let t="text/plain";"json"==n&&("string"!=typeof e&&(e=JSON.stringify(e)),t="text/json"),a=new Blob([e],{type:t})}let i=document.createElement("a");i.href=URL.createObjectURL(a),i.download=t+"."+n,i.click(),setTimeout((()=>URL.revokeObjectURL(i.href)),1e3)}e.load=function(...t){Array.isArray(t[0])&&(t=t[0]);let o=[];for(let s of t){let t,l=s.split(".").pop().toLowerCase();t="json"!=l||s.includes("-msdf.")?"csv"==l?e.loadCSV(s):r.test(l)?e.loadImage(s):n.test(l)||a.test(s)?e.loadFont(s):i.test(l)?e.loadSound(s):"xml"==l?e.loadXML(s):e.loadText(s):e.loadJSON(s),o.push(t)}return 1==t.length?o[0]:Promise.all(o)},e.save=(t,r,n)=>{if((!t||"string"==typeof t&&(!r||!n&&r.length<5))&&(n=r,r=t,t=e),n)o(t,r,n);else if(r){let e=r.lastIndexOf(".");o(t,r.slice(0,e),r.slice(e+1))}else o(t)},e.canvas&&!Q5._createServerCanvas&&(e.canvas.save=e.saveCanvas=e.save),"object"==typeof localStorage&&(e.storeItem=(e,t)=>localStorage.setItem(e,t),e.getItem=e=>localStorage.getItem(e),e.removeItem=e=>localStorage.removeItem(e),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(),e.nf=(e,t,r)=>{let n=e<0,a=(e=Math.abs(e)).toFixed(r).split(".");a[0]=a[0].padStart(t,"0");let i=a.join(".");return n&&(i="-"+i),i},e.shuffle=(t,r)=>{r||(t=[...t]);for(let r=t.length-1;r>0;r--){let n=Math.floor(e.random()*(r+1));[t[r],t[n]]=[t[n],t[r]]}return t}},Q5.CSV={},Q5.CSV.parse=(e,t=",",r="\n")=>{if(!e.length)return[];let n=[],a=e.split(r),i=a[0].split(t).map((e=>e.replaceAll('"',"")));for(let e=1;e<a.length;e++){let r={},o=a[e].split(t);i.forEach(((e,t)=>r[e]=JSON.parse(o[t]))),n.push(r)}return n},Q5.modules.vector=e=>{e.Vector=Q5.Vector,e.createVector=(t,r,n)=>new e.Vector(t,r,n,e)},Q5.Vector=class{constructor(e,t,r,n){this.x=e||0,this.y=t||0,this.z=r||0,this._isVector=!0,this._$=n||window,this._useCache=!1,this._mag=0,this._magCached=!1,this._direction=0,this._directionCached=!1}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}}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}_calcMag(){const e=this.x,t=this.y,r=this.z;this._mag=Math.sqrt(e*e+t*t+r*r),this._magCached=this._useCache}mag(){return this._magCached||this._calcMag(),this._mag}magSq(){if(this._magCached)return this._mag*this._mag;const e=this.x,t=this.y,r=this.z;return e*e+t*t+r*r}setMag(e){this._magCached||this._calcMag();let t=this._mag;if(0==t){const t=this.direction();this.x=e*this._$.cos(t),this.y=e*this._$.sin(t)}else{let r=e/t;this.x*=r,this.y*=r,this.z*=r}return this._mag=e,this._magCached=this._useCache,this}direction(){if(!this._directionCached){const e=this.x,t=this.y;(e||t)&&(this._direction=this._$.atan2(this.y,this.x)),this._directionCached=this._useCache}return this._direction}setDirection(e){let t=this.mag();return t&&(this.x=t*this._$.cos(e),this.y=t*this._$.sin(e)),this._direction=e,this._directionCached=this._useCache,this}heading(){return this.direction()}setHeading(e){return this.setDirection(e)}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,n=this.z-e.z;return Math.sqrt(t*t+r*r+n*n)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,r=this.z*e.x-this.x*e.z,n=this.x*e.y-this.y*e.x;return this.x=t,this.y=r,this.z=n,this}normalize(){this._magCached||this._calcMag();let e=this._mag;return 0!=e&&(this.x/=e,this.y/=e,this.z/=e),this._mag=1,this._magCached=this._useCache,this}limit(e){this._magCached||this._calcMag();let t=this._mag;if(t>e){let r=e/t;this.x*=r,this.y*=r,this.z*=r,this._mag=e,this._magCached=this._useCache}return this}rotate(e){let t=this._$.cos(e),r=this._$.sin(e),n=this.x*t-this.y*r,a=this.x*r+this.y*t;return this.x=n,this.y=a,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 n=this.mag(),a=r.mag();if(0==n||0==a)return this.mult(1-t).add(r.mult(t));let i=Q5.Vector.cross(this,r),o=i.mag(),s=Math.atan2(o,this.dot(r));if(o>0)i.div(o);else{if(s<this._$.HALF_PI)return this.mult(1-t).add(r.mult(t));0==this.z&&0==r.z?i.set(0,0,1):0!=this.x?i.set(this.y,-this.x,0).normalize():i.set(1,0,0)}let l=i.cross(this),d=1-t+t*a/n,c=d*Math.cos(t*s),u=d*Math.sin(t*s);return this.x=this.x*c+l.x*u,this.y=this.y*c+l.y*u,this.z=this.z*c+l.z*u,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._mag=t,this._magCached=this._useCache,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._mag=r,this._magCached=this._useCache;const n=this._$.cos(t),a=this._$.sin(t),i=this._$.cos(e),o=this._$.sin(e);return this.x=r*o*a,this.y=-r*i,this.z=r*o*n,this}random2D(){return this._mag=1,this._magCached=this._useCache,this.fromAngle(Math.random()*Math.PI*2)}random3D(){return this._mag=1,this._magCached=this._useCache,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.direction=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),Q5.Vector.reflect=(e,t)=>e.copy().reflect(t),Q5.Vector.random2D=()=>(new Q5.Vector).random2D(),Q5.Vector.random3D=()=>(new Q5.Vector).random3D(),Q5.Vector.fromAngle=(e,t)=>(new Q5.Vector).fromAngle(e,t),Q5.Vector.fromAngles=(e,t,r)=>(new Q5.Vector).fromAngles(e,t,r),Q5.renderers.webgpu={},Q5.renderers.webgpu.canvas=(e,t)=>{const r=e.canvas;e.colorMode&&e.colorMode("rgb",1),e._baseShaderCode="\nstruct Q5 {\n\twidth: f32,\n\theight: f32,\n\thalfWidth: f32,\n\thalfHeight: f32,\n\tpixelDensity: f32,\n\tframeCount: f32,\n\ttime: f32,\n\tdeltaTime: f32,\n\tmouseX: f32,\n\tmouseY: f32,\n\tmouseIsPressed: f32,\n\tkeyCode: f32,\n\tkeyIsPressed: f32\n}",e._g=e.createGraphics(1,1,"c2d"),e._g.colorMode&&e._g.colorMode(e.RGB,1);let n,a,i,o,s,l,d,c,u,h,f=2,p=12,g=0,m=0;e._pipelineConfigs=[],e._pipelines=[],e._buffers=[];let x=[],_=new Float32Array(1e6);_.set([0,0,0,0,0,0,0,1,1,1,1,1]);let v=Q5.device.createBindGroupLayout({label:"mainLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]});e._bindGroupLayouts=[v];let b=Q5.device.createBuffer({size:64,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),y=()=>{let t=[e.canvas.width,e.canvas.height],r="bgra8unorm";i=Q5.device.createTexture({size:t,sampleCount:4,format:r,usage:GPUTextureUsage.RENDER_ATTACHMENT}).createView();let n=GPUTextureUsage.COPY_SRC|GPUTextureUsage.COPY_DST|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT;e._frameA=s=Q5.device.createTexture({label:"frameA",size:t,format:r,usage:n}),e._frameB=o=Q5.device.createTexture({label:"frameB",size:t,format:r,usage:n}),e._frameShaderCode=e._baseShaderCode+"\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex: u32\n}\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) texCoord: vec2f\n}\n\nconst ndc = array(vec2f(-1,-1), vec2f(1,-1), vec2f(-1,1), vec2f(1,1));\nconst quad = array(vec2f(0,1), vec2f(1,1), vec2f(0,0), vec2f(1,0));\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var samp: sampler;\n@group(0) @binding(2) var tex: texture_2d<f32>;\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tvar f: FragParams;\n\tf.position = vec4f(ndc[v.vertexIndex], 0.0, 1.0);\n\tf.texCoord = quad[v.vertexIndex];\n\treturn f;\n}\n\n@fragment\nfn fragMain(f: FragParams ) -> @location(0) vec4f {\n\treturn textureSample(tex, samp, f.texCoord);\n}";let a=Q5.device.createShaderModule({label:"frameShader",code:e._frameShaderCode});d=Q5.device.createSampler({magFilter:"linear",minFilter:"linear"}),l=Q5.device.createBindGroupLayout({label:"frameLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]});let c=Q5.device.createPipelineLayout({bindGroupLayouts:[l]});e._pipelineConfigs[0]={layout:c,vertex:{module:a,entryPoint:"vertexMain"},fragment:{module:a,entryPoint:"fragMain",targets:[{format:r}]},primitive:{topology:"triangle-strip"},multisample:{count:4}},e._pipelines[0]=Q5.device.createRenderPipeline(e._pipelineConfigs[0]),u=Q5.device.createBindGroup({layout:l,entries:[{binding:0,resource:{buffer:b}},{binding:1,resource:d},{binding:2,resource:o.createView()}]}),h=Q5.device.createBindGroup({layout:l,entries:[{binding:0,resource:{buffer:b}},{binding:1,resource:d},{binding:2,resource:s.createView()}]})};e._createCanvas=(n,a,i)=>(t.ctx=t.drawingContext=r.getContext("webgpu"),i.format??=navigator.gpu.getPreferredCanvasFormat(),i.device??=Q5.device,i.alpha&&(i.alphaMode="premultiplied"),e.ctx.configure(i),y(),r),e._resizeCanvas=(t,r)=>{e._setCanvasSize(t,r),y()};let S=!0,w="rgb",C=1;if(e.colorMode){let t=e.colorMode;e.colorMode=function(){t(...arguments),w=e._colorMode,S="rgb"==w,C=e._colorFormat}}const Q=(t,r,n,a)=>{if(!1===S||void 0===r&&!t._isColor&&"number"!=typeof t?!1!==S&&"string"!=typeof t&&Array.isArray(t)?[t,r,n,a]=t:t=e.color(t,r,n,a):void 0===n&&(a=r??C,r=n=t),a??=C,t._isColor){let e=t;S?({r:t,g:r,b:n,a:a}=e):(a=e.a,e=null!=e.c?Q5.OKLCHtoRGB(e.l,e.c,e.h):null!=e.l?Q5.HSLtoRGB(e.h,e.s,e.l):Q5.HSLtoRGB(...Q5.HSBtoHSL(e.h,e.s,e.b)),[t,r,n]=e)}255===C&&(t/=255,r/=255,n/=255,a/=255);let i=_,o=p;i[o++]=t,i[o++]=r,i[o++]=n,i[o++]=a,p=o,f++};let M=!0,P=!0,E=!1,I=!1,R=1,A=2,T=2,k=1,O=1,G=.5,L=.25,D=.5;e.fill=(e,t,r,n)=>{Q(e,t,r,n),M=E=!0,A=f},e.stroke=(e,t,r,n)=>{Q(e,t,r,n),P=I=!0,R=f},e.tint=(e,t,r,n)=>{Q(e,t,r,n),T=f},e.opacity=e=>k=e,e.noFill=()=>M=!1,e.noStroke=()=>P=!1,e.noTint=()=>T=2,e.strokeWeight=e=>void 0===e?O:e?(P=!0,e=Math.abs(e),O=e,G=e/2,L=e/4,void(D=G*W)):P=!1,e._getStrokeWeight=()=>[O,G,L,D],e._setStrokeWeight=e=>{[O,G,L,D]=e},e._getFillIdx=()=>A,e._setFillIdx=e=>A=e,e._doFill=()=>M=!0,e._getStrokeIdx=()=>R,e._setStrokeIdx=e=>R=e,e._doStroke=()=>P=!0;const B=e._isGraphics?1e3:Q5.MAX_TRANSFORMS,F=16*B*4,z=new Float32Array(16*B);let U,V=[],N=[],H=0,q=!1;V.push([1,0,0,0,0,-1,0,0,0,0,1,0,0,0,0,1]),z.set(V[0]),e.translate=(e,t)=>{if(!e&&!t)return;let r=U;r[12]+=e*r[0]+t*r[4],r[13]+=e*r[1]+t*r[5],q=!0},e.rotate=e.rotateZ=(t,r)=>{if(!t)return;let n,a;void 0===r?(e._angleMode&&(t*=e._DEGTORAD),n=Math.cos(t),a=Math.sin(t)):(n=t,a=r);let i=U,o=i[0],s=i[1],l=i[4],d=i[5];1!=o||s||l||1!=d?(i[0]=o*n+s*a,i[1]=s*n-o*a,i[4]=l*n+d*a,i[5]=d*n-l*a):(i[0]=n,i[1]=-a,i[4]=a,i[5]=n),q=!0};let W=1;e.scale=(e=1,t,r=1)=>{t??=e,W=Math.max(Math.abs(e),Math.abs(t)),D=G*W;let n=U;n[0]*=e,n[1]*=e,n[2]*=e,n[3]*=e,n[4]*=t,n[5]*=t,n[6]*=t,n[7]*=t,n[8]*=r,n[9]*=r,n[10]*=r,n[11]*=r,q=!0},e.shearX=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.tan(t),n=U,a=n[0],i=n[1],o=n[4],s=n[5];n[4]=o+a*r,n[5]=s+i*r,q=!0},e.shearY=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.tan(t),n=U,a=n[0],i=n[1],o=n[4],s=n[5];n[0]=a+o*r,n[1]=i+s*r,q=!0},e.applyMatrix=(...e)=>{let t;if(t=1==e.length?e[0]:e,t.length<=6){t=[t[0],t[1],0,t[2],t[3],0,t[4]||0,t[5]||0,1]}if(t.length<=9)t=[t[0],t[1],0,t[2],t[3],t[4],0,t[5],0,0,1,0,t[6],t[7],0,t[8]];else if(16!=t.length)throw new Error("Matrix must be a 3x3 or 4x4 array.");U=t.slice(),q=!0};const j=()=>{z.set(U,16*V.length),H=V.length,V.push(U.slice()),q=!1};let $=[];e.pushMatrix=()=>{q&&j(),N.push(H),$.push(W)},e.popMatrix=()=>{if(!N.length)return console.warn("Matrix index stack is empty!");let e=N.pop();U=V[e].slice(),H=e,q=!1,W=$.pop(),D=G*W},e.resetMatrix=()=>{U=V[0].slice(),H=0,W=1,D=G},e.resetMatrix();let X=[];e.pushStyles=()=>{X.push([A,R,O,G,W,D,M,P,E,I,k,T,Et,It,Rt,mt,Fe,Ke,S,w,C,e.Color])},e.popStyles=()=>{let t=X.pop();[A,R,O,G,W,D,M,P,E,I,k,T,Et,It,Rt,mt,Fe,Ke,S,w,C]=t,e._colorFormat=C,e._colorMode=w,e.Color=t.at(-1)},e.push=()=>{e.pushMatrix(),e.pushStyles()},e.pop=()=>{e.popMatrix(),e.popStyles()};let Y=[0,0,0,0];const J=(e,t,r,n,a)=>{let i,o,s,l;if(a&&"corner"!=a)if("center"==a){let a=r/2,d=n/2;i=e-a,o=e+a,s=t-d,l=t+d}else i=e,o=r,s=t,l=n;else i=e,o=e+r,s=t,l=t+n;return Y[0]=i,Y[1]=o,Y[2]=s,Y[3]=l,Y};let K=["zero","one","src-alpha","one-minus-src-alpha","dst","dst-alpha","one-minus-dst-alpha","one-minus-src"],Z=["add","subtract","reverse-subtract","min","max"];const ee={"source-over":[2,3,0,2,3,0],"destination-over":[6,1,0,6,1,0],"source-in":[5,0,0,5,0,0],"destination-in":[0,2,0,0,2,0],"source-out":[6,0,0,6,0,0],"destination-out":[0,3,0,0,3,0],"source-atop":[5,3,0,5,3,0],"destination-atop":[6,2,0,6,2,0],lighter:[1,1,0,1,1,0],darken:[1,1,3,3,5,0],lighten:[1,1,4,3,5,0],replace:[1,0,0,1,0,0]};let te=Object.keys(ee);e.blendConfigs={};for(const[t,r]of Object.entries(ee))e.blendConfigs[t]={color:{srcFactor:K[r[0]],dstFactor:K[r[1]],operation:Z[r[2]]},alpha:{srcFactor:K[r[3]],dstFactor:K[r[4]],operation:Z[r[5]]}};let re,ne,ae,ie,oe,se,le,de,ce,ue,he="source-over";e.blendMode=e=>{if(e==he)return;he=e;let t=te.indexOf(e);-1!=t?x.push(0,t):console.error(`Blend mode "${e}" not supported in q5.js WebGPU.`)},e.clear=()=>{re=!0},e.background=(t,n,a,i)=>{if(t.canvas){e.push(),e.resetMatrix();let n=t;mt="corner",e.image(n,-r.hw,-r.hh,r.w,r.h),e.pop()}else{Q(t,n,a,i);let e=-r.hw,o=r.hw,s=-r.hh,l=r.hh;Pe(e,s,o,s,o,l,e,l,f,0)}},e._beginRender=()=>{const t=o;o=s,s=t;const r=u;u=h,h=r,n=Q5.device.createCommandEncoder(),e._pass=a=n.beginRenderPass({label:"q5-webgpu",colorAttachments:[{view:i,resolveTarget:o.createView(),loadOp:"clear",storeOp:"store",clearValue:[0,0,0,0]}]}),c=h,re||(a.setPipeline(e._pipelines[g]),a.setBindGroup(0,c),a.draw(4)),re=!1},e._render=()=>{let t=16*V.length*4;(!ne||ne.size<t)&&(ne&&ne.destroy(),ne=Q5.device.createBuffer({size:Math.min(2*t,F),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),Q5.device.queue.writeBuffer(ne,0,z.subarray(0,16*V.length));let r=4*p;(!ae||ae.size<r)&&(ae&&ae.destroy(),ae=Q5.device.createBuffer({size:2*r,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),Q5.device.queue.writeBuffer(ae,0,_.subarray(0,p)),e._uniforms[0]=e.width,e._uniforms[1]=e.height,e._uniforms[2]=e.halfWidth,e._uniforms[3]=e.halfHeight,e._uniforms[4]=e._pixelDensity,e._uniforms[5]=e.frameCount,e._uniforms[6]=performance.now(),e._uniforms[7]=e.deltaTime,e._uniforms[8]=e.mouseX,e._uniforms[9]=e.mouseY,e._uniforms[10]=e.mouseIsPressed?1:0,e._uniforms[11]=e.keyCode,e._uniforms[12]=e.keyIsPressed?1:0,Q5.device.queue.writeBuffer(b,0,e._uniforms),de&&ce===ne&&ue===ae||(de=Q5.device.createBindGroup({layout:v,entries:[{binding:0,resource:{buffer:b}},{binding:1,resource:{buffer:ne}},{binding:2,resource:{buffer:ae}}]}),ce=ne,ue=ae),a.setBindGroup(0,de),e._pass.setPipeline(e._pipelines[1]);let n=4*me;if((!ie||ie.size<n)&&(ie&&ie.destroy(),ie=Q5.device.createBuffer({size:2*n,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})),Q5.device.queue.writeBuffer(ie,0,ge.subarray(0,me)),e._pass.setVertexBuffer(0,ie),ot){e._pass.setPipeline(e._pipelines[2]);let t=4*ot;(!oe||oe.size<t)&&(oe&&oe.destroy(),oe=Q5.device.createBuffer({size:2*t,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})),Q5.device.queue.writeBuffer(oe,0,it.subarray(0,ot)),e._pass.setVertexBuffer(1,oe),pt&&(e._pass.setPipeline(e._pipelines[3]),e._pass.setVertexBuffer(1,oe))}if(Bt.length){let t=0;for(let e of Bt)Ut.set(e,t),t+=e.length;let r=4*t;(!se||se.size<r)&&(se&&se.destroy(),se=Q5.device.createBuffer({size:2*r,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),Q5.device.queue.writeBuffer(se,0,Ut.buffer,0,r);let n=0;for(let e of Ft)Vt.set(e,n),n+=e.length;let a=4*n;(!le||le.size<a)&&(le&&le.destroy(),le=Q5.device.createBuffer({label:"textBuffer",size:2*a,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})),Q5.device.queue.writeBuffer(le,0,Vt.buffer,0,a),e._textBindGroup=Q5.device.createBindGroup({label:"textBindGroup",layout:bt,entries:[{binding:0,resource:{buffer:se}},{binding:1,resource:{buffer:le}}]})}Q5.device.queue.writeBuffer(Le,0,Oe.buffer,Oe.byteOffset,4*Ge),Q5.device.queue.writeBuffer(Xe,0,je.buffer,je.byteOffset,4*$e);let i=0,o=0,s=0,l=0,d=0,c=-1;for(let t=0;t<x.length;t+=2){let r=x[t+1];if(x[t]!=c){if(0==x[t]){let t=te[r];for(let r=1;r<e._pipelines.length;r++)e._pipelineConfigs[r].fragment.targets[0].blend=e.blendConfigs[t],e._pipelines[r]=Q5.device.createRenderPipeline(e._pipelineConfigs[r]);continue}c=x[t],a.setPipeline(e._pipelines[c]),5==c?(a.setIndexBuffer(Ae,"uint16"),a.setBindGroup(1,De)):6==c&&(a.setIndexBuffer(He,"uint16"),a.setBindGroup(1,Ye))}if(6==c)a.drawIndexed(18,r,0,0,d),d+=r;else if(5==c)a.drawIndexed(6,r,0,0,l),l+=r;else if(4==c||c>=4e3){let n=x[t+2];a.setBindGroup(1,Mt[n].bindGroup),a.setBindGroup(2,e._textBindGroup),a.draw(4,r,0,s),s+=r,t++}else 2==c||3==c||c>=2e3?(a.setBindGroup(1,e._textureBindGroups[r]),a.draw(4,1,o),o+=4):(a.draw(r,1,i),i+=r)}},e._finishRender=()=>{a.end(),a=n.beginRenderPass({colorAttachments:[{view:i,resolveTarget:e.ctx.getCurrentTexture().createView(),loadOp:"clear",storeOp:"store",clearValue:[0,0,0,0]}]}),c=u,a.setPipeline(e._pipelines[m]),a.setBindGroup(0,c),a.draw(4),a.end(),Q5.device.queue.submit([n.finish()]),e._pass=a=n=null,x.length=0,f=2,p=12,V.length=1,N.length=0,e._texture=o,me=0,ot=0,pt>0&&(e._textureBindGroups.length=ft),pt=0,Bt.length=0,Ft.length=0,Ge=0,$e=0,Q5.device.queue.onSubmittedWorkDone().then((()=>{for(let t of e._buffers)t.destroy();e._buffers=[]}))};let fe=1;e._shapesShaderCode=e._baseShaderCode+"\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex : u32,\n\t@location(0) pos: vec2f,\n\t@location(1) colorIndex: f32,\n\t@location(2) matrixIndex: f32\n}\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) color: vec4f\n}\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tvar vert = transformVertex(v.pos, v.matrixIndex);\n\n\tvar f: FragParams;\n\tf.position = vert;\n\tf.color = colors[i32(v.colorIndex)];\n\treturn f;\n}\n\n@fragment\nfn fragMain(f: FragParams) -> @location(0) vec4f {\n\treturn f.color;\n}\n";let pe=Q5.device.createShaderModule({label:"shapesShader",code:e._shapesShaderCode}),ge=new Float32Array(e._isGraphics?1e3:1e7),me=0;const xe=2*Math.PI;Math.PI;let _e=Q5.device.createPipelineLayout({label:"shapesPipelineLayout",bindGroupLayouts:e._bindGroupLayouts});e._pipelineConfigs[1]={label:"shapesPipeline",layout:_e,vertex:{module:pe,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:pe,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs["source-over"]}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[1]=Q5.device.createRenderPipeline(e._pipelineConfigs[1]);const ve=(e,t,r,n)=>{let a=ge,i=me;a[i++]=e,a[i++]=t,a[i++]=r,a[i++]=n,me=i};let be="round",ye="round";e.strokeCap=e=>be=e,e.strokeJoin=e=>ye=e,e.lineMode=()=>{be="square",ye="none"};let Se=20;e.curveDetail=e=>Se=e;let we,Ce=20;e.bezierDetail=e=>Ce=e;let Qe=[],Me=[];function Pe(e,t,r,n,a,i,o,s,l,d){ve(e,t,l,d),ve(r,n,l,d),ve(o,s,l,d),ve(a,i,l,d),x.push(fe,4)}e.beginShape=()=>{we=0,Qe=[],Me=[]},e.vertex=(e,t)=>{q&&j(),Qe.push(e,t,A,H),we++},e.curveVertex=(e,t)=>{q&&j(),Me.push({x:e,y:t})},e.bezierVertex=function(e,t,r,n,a,i){if(0===we)throw new Error("Shape needs a vertex()");q&&j();let o,s,l=4*(we-1),d=Qe[l],c=Qe[l+1],u=1/Ce,h=4==arguments.length;h&&(a=r,i=n);let f=1+u;for(let l=u;l<=f;l+=u){let u=l*l,f=1-l,p=f*f;if(h)o=p*d+2*f*l*e+u*a,s=p*c+2*f*l*t+u*i;else{let h=u*l,g=p*f;o=g*d+3*p*l*e+3*f*u*r+h*a,s=g*c+3*p*l*t+3*f*u*n+h*i}Qe.push(o,s,A,H),we++}},e.quadraticVertex=(t,r,n,a)=>e.bezierVertex(t,r,n,a),e.endShape=t=>{if(Me.length>0){let e=[...Me];if(e.length<4)for(;e.length<4;)e.unshift(e[0]),e.push(e[e.length-1]);let t=1/Se;for(let r=0;r<e.length-3;r++){let n=e[r],a=e[r+1],i=e[r+2],o=e[r+3];for(let e=0;e<=1;e+=t){let t=e*e,r=t*e,s=.5*(2*a.x+(-n.x+i.x)*e+(2*n.x-5*a.x+4*i.x-o.x)*t+(-n.x+3*a.x-3*i.x+o.x)*r),l=.5*(2*a.y+(-n.y+i.y)*e+(2*n.y-5*a.y+4*i.y-o.y)*t+(-n.y+3*a.y-3*i.y+o.y)*r);Qe.push(s,l,A,H),we++}}}if(we){if(1==we)return e.point(Qe[0],Qe[1]);if(2==we)return e.line(Qe[0],Qe[1],Qe[4],Qe[5]);if(t){let e=0,t=4*(we-1),r=Qe[e],n=Qe[e+1],a=Qe[t],i=Qe[t+1];r===a&&n===i||(Qe.push(r,n,Qe[e+2],Qe[e+3]),we++)}if(M)if(5==we)ve(Qe[0],Qe[1],Qe[2],Qe[3]),ve(Qe[4],Qe[5],Qe[6],Qe[7]),ve(Qe[12],Qe[13],Qe[14],Qe[15]),ve(Qe[8],Qe[9],Qe[10],Qe[11]),x.push(fe,4);else{for(let e=1;e<we-1;e++){let t=0,r=4*e,n=4*(e+1);ve(Qe[t],Qe[t+1],Qe[t+2],Qe[t+3]),ve(Qe[r],Qe[r+1],Qe[r+2],Qe[r+3]),ve(Qe[n],Qe[n+1],Qe[n+2],Qe[n+3])}x.push(fe,3*(we-2))}if(P){for(let t=0;t<we-1;t++){let r=4*t,n=4*(t+1);e.line(Qe[r],Qe[r+1],Qe[n],Qe[n+1])}let r=4*(we-1),n=0;t&&e.line(Qe[r],Qe[r+1],Qe[n],Qe[n+1])}we=0,Qe=[],Me=[]}},e.curve=(t,r,n,a,i,o,s,l)=>{e.beginShape(),e.curveVertex(t,r),e.curveVertex(n,a),e.curveVertex(i,o),e.curveVertex(s,l),e.endShape()},e.bezier=(t,r,n,a,i,o,s,l)=>{e.beginShape(),e.vertex(t,r),e.bezierVertex(n,a,i,o,s,l),e.endShape()},e.triangle=(t,r,n,a,i,o)=>{e.beginShape(),e.vertex(t,r),e.vertex(n,a),e.vertex(i,o),e.endShape(!0)},e.quad=(t,r,n,a,i,o,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(n,a),e.vertex(i,o),e.vertex(s,l),e.endShape(!0)},e.plane=(e,t,r,n)=>{n??=r;let[a,i,o,s]=J(e,t,r,n,"center");q&&j(),Pe(a,o,i,o,i,s,a,s,A,H)};let Ee=5;e._rectShaderCode=e._baseShaderCode+"\nstruct Rect {\n\tcenter: vec2f,\n\textents: vec2f,\n\troundedRadius: f32,\n\tstrokeWeight: f32,\n\tfillIndex: f32,\n\tstrokeIndex: f32,\n\tmatrixIndex: f32,\n\tpadding0: f32, // can't use vec3f for alignment\n\tpadding1: vec2f,\n\tpadding2: vec4f\n};\n\nstruct VertexParams {\n\t@builtin(vertex_index) vertIndex: u32,\n\t@builtin(instance_index) instIndex: u32\n};\n\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) local: vec2f,\n\t@location(1) extents: vec2f,\n\t@location(2) roundedRadius: f32,\n\t@location(3) strokeWeight: f32,\n\t@location(4) fill: vec4f,\n\t@location(5) stroke: vec4f,\n\t@location(6) blend: vec4f\n};\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\n@group(1) @binding(0) var<storage, read> rects: array<Rect>;\n\nconst quad = array(\n\tvec2f(-1.0, -1.0),\n\tvec2f( 1.0, -1.0),\n\tvec2f(-1.0, 1.0),\n\tvec2f( 1.0, 1.0)\n);\nconst transparent = vec4f(0.0);\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tlet rect = rects[v.instIndex];\n\n\tlet halfStrokeSize = vec2f(rect.strokeWeight * 0.5);\n\tlet quadSize = rect.extents + halfStrokeSize;\n\tlet pos = (quad[v.vertIndex] * quadSize) + rect.center;\n\n\tlet local = pos - rect.center;\n\n\tvar f: FragParams;\n\tf.position = transformVertex(pos, rect.matrixIndex);\n\n\tf.local = local;\n\tf.extents = rect.extents;\n\tf.roundedRadius = rect.roundedRadius;\n\tf.strokeWeight = rect.strokeWeight;\n\n\tlet fill = colors[i32(rect.fillIndex)];\n\tlet stroke = colors[i32(rect.strokeIndex)];\n\tf.fill = fill;\n\tf.stroke = stroke;\n\n\t// Source-over blend: stroke over fill (pre-multiplied alpha)\n\tif (fill.a != 0.0 && stroke.a != 1.0) {\n\t\tlet outAlpha = stroke.a + fill.a * (1.0 - stroke.a);\n\t\tlet outColor = stroke.rgb * stroke.a + fill.rgb * fill.a * (1.0 - stroke.a);\n\t\tf.blend = vec4f(outColor / max(outAlpha, 1e-5), outAlpha);\n\t}\n\treturn f;\n}\n\nfn sdRoundRect(p: vec2f, extents: vec2f, radius: f32) -> f32 {\n\tlet q = abs(p) - extents + vec2f(radius);\n\treturn length(max(q, vec2f(0.0))) - radius + min(max(q.x, q.y), 0.0);\n}\n\n@fragment\nfn fragMain(f: FragParams) -> @location(0) vec4f {\n\tlet dist = select(\n\t\tmax(abs(f.local.x) - f.extents.x, abs(f.local.y) - f.extents.y), // sharp\n\t\tsdRoundRect(f.local, f.extents, f.roundedRadius), // rounded\n\t\tf.roundedRadius > 0.0\n\t);\n\n\t// fill only\n\tif (f.fill.a != 0.0 && f.strokeWeight == 0.0) {\n\t\tif (dist <= 0.0) {\n\t\t\treturn f.fill;\n\t\t}\n\t\treturn transparent;\n\t}\n\n\tlet halfStroke = f.strokeWeight * 0.5;\n\tlet inner = dist + halfStroke;\n\n\tif (f.fill.a != 0.0) {\n\t\tif (inner <= 0.0) {\n\t\t\treturn f.fill;\n\t\t}\n\t\tif (dist <= 0.0 && f.stroke.a != 1.0) {\n\t\t\treturn f.blend;\n\t\t}\n\t}\n\n\tlet outer = dist - halfStroke;\n\n\tif (outer <= 0.0 && inner >= 0.0) {\n\t\treturn f.stroke;\n\t}\n\n\treturn transparent;\n}\n\t";let Ie=Q5.device.createShaderModule({label:"rectShader",code:e._rectShaderCode}),Re=new Uint16Array([0,1,2,2,1,3]),Ae=Q5.device.createBuffer({size:Re.byteLength,usage:GPUBufferUsage.INDEX,mappedAtCreation:!0});new Uint16Array(Ae.getMappedRange()).set(Re),Ae.unmap();let Te=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}}]}),ke=Q5.device.createPipelineLayout({label:"rectPipelineLayout",bindGroupLayouts:[...e._bindGroupLayouts,Te]});e._pipelineConfigs[5]={label:"rectPipeline",layout:ke,vertex:{module:Ie,entryPoint:"vertexMain",buffers:[]},fragment:{module:Ie,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs["source-over"]}]},primitive:{topology:"triangle-list"},multisample:{count:4}},e._pipelines[5]=Q5.device.createRenderPipeline(e._pipelineConfigs[5]);let Oe=new Float32Array(16*Q5.MAX_RECTS),Ge=0,Le=Q5.device.createBuffer({size:Oe.byteLength,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),De=Q5.device.createBindGroup({layout:Te,entries:[{binding:0,resource:{buffer:Le}}]});function Be(e,t,r,n,a,i,o){let s=Oe,l=Ge;s[l]=e,s[l+1]=t,s[l+2]=r,s[l+3]=n,s[l+4]=a,s[l+5]=i,s[l+6]=o,s[l+7]=R,s[l+8]=H,Ge+=16,x.push(Ee,1)}let Fe="corner";e.rectMode=e=>Fe=e,e._getRectMode=()=>Fe;let ze=[0,0,0,0];function Ue(t,r,n,a,i,o,s){let l=n-t,d=a-r,c=Math.hypot(l,d);if(0===c)return;let u=Math.atan2(d,l),h=(t+n)/2,f=(r+a)/2;e._angleMode&&(u*=e._RADTODEG),e.pushMatrix(),e.translate(h,f),e.rotate(u),q&&j(),Be(0,0,c/2+i,i,i,o,s),e.popMatrix()}e.rect=(e,t,r,n,a=0)=>{let i,o;q&&j(),[e,t,i,o]=function(e,t,r,n){let a=r/2,i=n/2;return"center"!=Fe&&("corner"==Fe?(e+=a,t+=i,a=Math.abs(a),i=Math.abs(i)):"radius"==Fe?(a=r,i=n):"corners"==Fe&&(a=Math.abs((r-e)/2),i=Math.abs((n-t)/2),e=(e+r)/2,t=(t+n)/2)),ze[0]=e,ze[1]=t,ze[2]=a,ze[3]=i,ze}(e,t,r,n),Be(e,t,i,o,a,P?O:0,M?A:0)},e.square=(t,r,n,a)=>e.rect(t,r,n,n,a),e.capsule=(e,t,r,n,a)=>{Ue(e,t,r,n,a,P?O:0,M?A:0)},e.line=(e,t,r,n)=>{P&&Ue(e,t,r,n,L,G,0)};e._ellipseShaderCode=e._baseShaderCode+"\nstruct Ellipse {\n\tcenter: vec2f,\n\tsize: vec2f,\n\tstartAngle: f32,\n\tendAngle: f32,\n\tstrokeWeight: f32,\n\tfillIndex: f32,\n\tstrokeIndex: f32,\n\tmatrixIndex: f32,\n\tpadding0: vec2f,\n\tpadding1: vec4f\n};\n\nstruct VertexParams {\n\t@builtin(vertex_index) vertIndex: u32,\n\t@builtin(instance_index) instIndex: u32\n};\n\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) outerEdge: vec2f,\n\t@location(1) fillEdge: vec2f,\n\t@location(2) innerEdge: vec2f,\n\t@location(3) strokeWeight: f32,\n\t@location(4) fill: vec4f,\n\t@location(5) stroke: vec4f,\n\t@location(6) blend: vec4f\n};\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\n@group(1) @binding(0) var<storage, read> ellipses: array<Ellipse>;\n\nconst PI = 3.141592653589793;\nconst segments = 6.0;\nconst expansion = 1.0 / cos(PI / segments);\nconst antiAlias = 0.015625; // 1/64\nconst transparent = vec4f(0.0);\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tlet ellipse = ellipses[v.instIndex];\n\tvar pos = ellipse.center;\n\tvar local = vec2f(0.0);\n\tlet start = ellipse.startAngle;\n\tlet end = ellipse.endAngle;\n\tlet arc = end - start;\n\tlet halfStrokeSize = vec2f(ellipse.strokeWeight * 0.5);\n\n\tlet fanSize = (ellipse.size + halfStrokeSize) * expansion;\n\n\tif (v.vertIndex != 0) {\n\t\tlet theta = start + (f32(v.vertIndex - 1) / segments) * arc;\n\t\tlocal = vec2f(cos(theta), sin(theta));\n\t\tpos = ellipse.center + local * fanSize;\n\t}\n\n\tlet dist = pos - ellipse.center;\n\n\tvar f: FragParams;\n\tf.position = transformVertex(pos, ellipse.matrixIndex);\n\tf.outerEdge = dist / (ellipse.size + halfStrokeSize);\n\tf.fillEdge = dist / ellipse.size;\n\tf.innerEdge = dist / (ellipse.size - halfStrokeSize);\n\tf.strokeWeight = ellipse.strokeWeight;\n\n\tlet fill = colors[i32(ellipse.fillIndex)];\n\tlet stroke = colors[i32(ellipse.strokeIndex)];\n\tf.fill = fill;\n\tf.stroke = stroke;\n\n\t// Source-over blend: stroke over fill (pre-multiplied alpha)\n\tif (fill.a != 0.0 && stroke.a != 1.0) {\n\t\tlet outAlpha = stroke.a + fill.a * (1.0 - stroke.a);\n\t\tlet outColor = stroke.rgb * stroke.a + fill.rgb * fill.a * (1.0 - stroke.a);\n\t\tf.blend = vec4f(outColor / max(outAlpha, 1e-5), outAlpha);\n\t}\n\treturn f;\n}\n\n@fragment\nfn fragMain(f: FragParams) -> @location(0) vec4f {\n\tlet fillEdge = length(f.fillEdge);\n\n\t// disable AA for very thin strokes\n\tlet aa = select(antiAlias, 0.0, f.strokeWeight <= 1.0);\n\n\tif (f.fill.a != 0.0 && f.strokeWeight == 0.0) {\n\t\tif (fillEdge > 1.0) {\n\t\t\treturn transparent;\n\t\t}\n\t\tlet fillAlpha = 1.0 - smoothstep(1.0 - aa, 1.0, fillEdge);\n\t\treturn vec4f(f.fill.rgb, f.fill.a * fillAlpha);\n\t}\n\n\tlet innerEdge = length(f.innerEdge);\n\t\n\tif (f.fill.a != 0.0 && fillEdge < 1.0) {\n\t\tif (innerEdge < 1.0) {\n\t\t\treturn f.fill;\n\t\t}\n\t\tlet tInner = smoothstep(1.0, 1.0 + aa, innerEdge);\n\t\tlet tOuter = smoothstep(1.0 - aa, 1.0, fillEdge);\n\t\tif (f.stroke.a != 1.0) {\n\t\t\tlet fillBlend = mix(f.fill, f.blend, tInner);\n\t\t\treturn mix(fillBlend, f.stroke, tOuter);\n\t\t} else {\n\t\t\tlet fillBlend = mix(f.fill, f.stroke, tInner);\n\t\t\treturn mix(fillBlend, f.stroke, tOuter);\n\t\t}\n\t}\n\t\n\tif (innerEdge < 1.0) {\n\t\treturn transparent;\n\t}\n\n\tlet outerEdge = length(f.outerEdge);\n\tlet outerAlpha = 1.0 - smoothstep(1.0 - aa, 1.0, outerEdge);\n\tlet innerAlpha = smoothstep(1.0, 1.0 + aa, innerEdge);\n\tlet strokeAlpha = innerAlpha * outerAlpha;\n\treturn vec4f(f.stroke.rgb, f.stroke.a * strokeAlpha);\n}\n\t\t";let Ve=Q5.device.createShaderModule({label:"ellipseShader",code:e._ellipseShaderCode}),Ne=new Uint16Array([0,1,2,0,2,3,0,3,4,0,4,5,0,5,6,0,6,7]),He=Q5.device.createBuffer({size:Ne.byteLength,usage:GPUBufferUsage.INDEX,mappedAtCreation:!0});new Uint16Array(He.getMappedRange()).set(Ne),He.unmap();let qe=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}}]}),We=Q5.device.createPipelineLayout({label:"ellipsePipelineLayout",bindGroupLayouts:[...e._bindGroupLayouts,qe]});e._pipelineConfigs[6]={label:"ellipsePipeline",layout:We,vertex:{module:Ve,entryPoint:"vertexMain",buffers:[]},fragment:{module:Ve,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs["source-over"]}]},primitive:{topology:"triangle-list"},multisample:{count:4}},e._pipelines[6]=Q5.device.createRenderPipeline(e._pipelineConfigs[6]);let je=new Float32Array(16*Q5.MAX_ELLIPSES),$e=0,Xe=Q5.device.createBuffer({size:je.byteLength,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),Ye=Q5.device.createBindGroup({layout:qe,entries:[{binding:0,resource:{buffer:Xe}}]});function Je(e,t,r,n,a,i,o,s){let l=je,d=$e;l[d]=e,l[d+1]=t,l[d+2]=r,l[d+3]=n,l[d+4]=a,l[d+5]=i,l[d+6]=o,l[d+7]=s?A:0,l[d+8]=R,l[d+9]=H,$e+=16,x.push(6,1)}let Ke="center";e.ellipseMode=e=>Ke=e,e._getEllipseMode=()=>Ke;let Ze=[0,0,0,0];function et(e,t,r,n){let a,i;return n??=r,"center"==Ke?(a=r/2,i=n/2):"radius"==Ke?(a=r,i=n):"corner"==Ke?(e+=r/2,t+=n/2,a=r/2,i=n/2):"corners"==Ke&&(a=r-(e=(e+r)/2),i=n-(t=(t+n)/2)),Ze[0]=e,Ze[1]=t,Ze[2]=a,Ze[3]=i,Ze}e.ellipse=(e,t,r,n)=>{let a,i;[e,t,a,i]=et(e,t,r,n),q&&j(),Je(e,t,a,i,0,xe,P?O:0,M)},e.circle=(t,r,n)=>e.ellipse(t,r,n,n),e.arc=(t,r,n,a,i,o)=>{if(i===o)return e.ellipse(t,r,n,a);if(e._angleMode&&(i=e.radians(i),o=e.radians(o)),(i%=xe)<0&&(i+=xe),(o%=xe)<0&&(o+=xe),i>o&&(o+=xe),i==o)return e.ellipse(t,r,n,a);let s,l;[t,r,s,l]=et(t,r,n,a),q&&j(),Je(t,r,s,l,i,o,P?O:0,M)},e.point=(e,t)=>{q&&j(),D<=.5?Be(e,t,G,G,0,O,0):Je(e,t,G,G,0,xe,O,0)};let tt=2,rt=3;e._imageShaderCode=e._baseShaderCode+"\n\tstruct VertexParams {\n\t\t@builtin(vertex_index) vertexIndex : u32,\n\t\t@location(0) pos: vec2f,\n\t\t@location(1) texCoord: vec2f,\n\t\t@location(2) tintIndex: f32,\n\t\t@location(3) matrixIndex: f32,\n\t\t@location(4) imageAlpha: f32\n\t}\n\tstruct FragParams {\n\t\t@builtin(position) position: vec4f,\n\t\t@location(0) texCoord: vec2f,\n\t\t@location(1) tintColor: vec4f,\n\t\t@location(2) imageAlpha: f32\n\t}\n\t\n\t@group(0) @binding(0) var<uniform> q: Q5;\n\t@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n\t@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\t\n\t@group(1) @binding(0) var samp: sampler;\n\t@group(1) @binding(1) var tex: texture_2d<f32>;\n\t\n\tfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\t\tvar vert = vec4f(pos, 0f, 1f);\n\t\tvert = transforms[i32(matrixIndex)] * vert;\n\t\tvert.x /= q.halfWidth;\n\t\tvert.y /= q.halfHeight;\n\t\treturn vert;\n\t}\n\t\n\tfn applyTint(texColor: vec4f, tintColor: vec4f) -> vec4f {\n\t\t// apply the tint color to the sampled texture color at full strength\n\t\tlet tinted = vec4f(texColor.rgb * tintColor.rgb, texColor.a);\n\t\t// mix in the tint using the tint alpha as the blend strength\n\t\treturn mix(texColor, tinted, tintColor.a);\n\t}\n\t\n\t@vertex\n\tfn vertexMain(v: VertexParams) -> FragParams {\n\t\tvar vert = transformVertex(v.pos, v.matrixIndex);\n\t\n\t\tvar f: FragParams;\n\t\tf.position = vert;\n\t\tf.texCoord = v.texCoord;\n\t\tf.tintColor = colors[i32(v.tintIndex)];\n\t\tf.imageAlpha = v.imageAlpha;\n\t\treturn f;\n\t}\n\t\n\t@fragment\n\tfn fragMain(f: FragParams) -> @location(0) vec4f {\n\t\tvar texColor = textureSample(tex, samp, f.texCoord);\n\t\ttexColor.a *= f.imageAlpha;\n\t\treturn applyTint(texColor, f.tintColor);\n\t}\n\t";let nt=Q5.device.createShaderModule({label:"imageShader",code:e._imageShaderCode});e._videoShaderCode=e._imageShaderCode.replace("texture_2d<f32>","texture_external").replace("textureSample","textureSampleBaseClampToEdge");let at=Q5.device.createShaderModule({label:"videoShader",code:e._videoShaderCode}),it=new Float32Array(e._isGraphics?1e3:1e7),ot=0,st={arrayStride:28,attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"},{shaderLocation:2,offset:16,format:"float32"},{shaderLocation:3,offset:20,format:"float32"},{shaderLocation:4,offset:24,format:"float32"}]},lt=Q5.device.createBindGroupLayout({label:"textureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]}),dt=Q5.device.createBindGroupLayout({label:"videoTextureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,externalTexture:{}}]}),ct=Q5.device.createPipelineLayout({label:"imagePipelineLayout",bindGroupLayouts:[...e._bindGroupLayouts,lt]}),ut=Q5.device.createPipelineLayout({label:"videoPipelineLayout",bindGroupLayouts:[...e._bindGroupLayouts,dt]});e._pipelineConfigs[2]={label:"imagePipeline",layout:ct,vertex:{module:nt,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},st]},fragment:{module:nt,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs["source-over"]}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[2]=Q5.device.createRenderPipeline(e._pipelineConfigs[2]),e._pipelineConfigs[3]={label:"videoPipeline",layout:ut,vertex:{module:at,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},st]},fragment:{module:at,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs["source-over"]}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[3]=Q5.device.createRenderPipeline(e._pipelineConfigs[3]),e._textureBindGroups=[],r&&(r.convertToBlob=async t=>{let r=e._drawStack?.length;r&&(e._render(),e._finishRender());let n=e._texture;r&&e._beginRender();let a=n.width,i=n.height,o=256*Math.ceil(4*a/256),s=Q5.device.createBuffer({size:o*i,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),l=Q5.device.createCommandEncoder();l.copyTextureToBuffer({texture:n},{buffer:s,bytesPerRow:o,rowsPerImage:i},{width:a,height:i}),Q5.device.queue.submit([l.finish()]),await s.mapAsync(GPUMapMode.READ);let d=new Uint8Array(s.getMappedRange()),c=new Uint8Array(a*i*4);for(let e=0;e<i;e++){const t=e*o,r=e*a*4;for(let e=0;e<a;e++){const n=t+4*e,a=r+4*e;c[a+0]=d[n+2],c[a+1]=d[n+1],c[a+2]=d[n+0],c[a+3]=d[n+3]}}s.unmap();let u=e.canvas.colorSpace;c=new Uint8ClampedArray(c.buffer),c=new ImageData(c,a,i,{colorSpace:u});let h=new OffscreenCanvas(a,i);return h.getContext("2d",{colorSpace:u}).putImageData(c,0,0),e._buffers.push(s),await h.convertToBlob(t)});let ht=t=>{e._imageSampler=Q5.device.createSampler({magFilter:t,minFilter:t})};e.smooth=()=>ht("linear"),e.noSmooth=()=>ht("nearest"),e.smooth();let ft=0,pt=0;e._addTexture=(t,r)=>{let n=t.canvas||t;if(!r){if(t._texture)return;let a=[n.width,n.height,1];r=Q5.device.createTexture({size:a,format:"bgra8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_SRC|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),Q5.device.queue.copyExternalImageToTexture({source:n},{texture:r,colorSpace:e.canvas.colorSpace},a)}r.index=ft+pt,t._texture=r,e._textureBindGroups[r.index]=Q5.device.createBindGroup({label:t.src||r.label||"canvas",layout:lt,entries:[{binding:0,resource:e._imageSampler},{binding:1,resource:r.createView()}]}),ft++},e.loadImage=(t,r)=>e._g.loadImage(t,(t=>{e._makeDrawable(t),r&&r(t)})),e._makeDrawable=t=>{e._addTexture(t),t._owner=e},e.createImage=(t,r,n)=>{let a=e._g.createImage(t,r,n);return e._makeDrawable(a),a.modified=!0,a};let gt=e.createGraphics;e.createGraphics=(t,r,n={})=>{if(!Q5.experimental)throw new Error("createGraphics is disabled by default in q5 WebGPU. See issue https://github.com/q5js/q5.js/issues/104 for details.");"string"==typeof n&&(n={renderer:n}),n.renderer??="c2d";let a=gt(t,r,n);return a.canvas.webgpu?(e._addTexture(a,a._frameA),e._addTexture(a,a._frameB),a._beginRender()):(e._makeDrawable(a),a.modified=!0),a};let mt="corner";e.imageMode=e=>mt=e,e._getImageMode=()=>mt,e._uniforms=new Float32Array(13);const xt=(e,t,r,n,a,i,o)=>{let s=it,l=ot;s[l++]=e,s[l++]=t,s[l++]=r,s[l++]=n,s[l++]=a,s[l++]=i,s[l++]=o,ot=l};e.image=(t,r=0,n=0,a,i,o=0,s=0,l,d)=>{if(!t)return;let c;if(null==t._texture){if(c="VIDEO"==t.tagName,!t.width||c&&!t.currentTime)return;t.flipped&&e.scale(-1,1)}q&&j();let u=t.canvas||t,h=u.width,f=u.height,p=t._pixelDensity||1,g=t._isGraphics&&t._drawStack?.length;g&&(t._render(),t._finishRender()),t.modified&&(Q5.device.queue.copyExternalImageToTexture({source:u},{texture:t._texture,colorSpace:e.canvas.colorSpace},[h,f,1]),t.frameCount++,t.modified=!1),a??=t.defaultWidth||t.videoWidth,i??=t.defaultHeight||t.videoHeight,l??=h,d??=f,o*=p,s*=p;let[m,_,v,b]=J(r,n,a,i,mt),y=o/h,S=s/f,w=(o+l)/h,C=(s+d)/f,Q=H,M=T,P=k;if(xt(m,v,y,S,M,Q,P),xt(_,v,w,S,M,Q,P),xt(m,b,y,C,M,Q,P),xt(_,b,w,C,M,Q,P),c){let r=Q5.device.importExternalTexture({source:t});e._textureBindGroups.push(Q5.device.createBindGroup({layout:dt,entries:[{binding:0,resource:e._imageSampler},{binding:1,resource:r}]})),x.push(rt,e._textureBindGroups.length-1),t.flipped&&e.scale(-1,1)}else x.push(tt,t._texture.index),g&&(t.resetMatrix(),t._beginRender(),t.frameCount++)};let _t=4;e._textShaderCode=e._baseShaderCode+"\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex : u32,\n\t@builtin(instance_index) instanceIndex : u32\n}\nstruct FragParams {\n\t@builtin(position) position : vec4f,\n\t@location(0) texCoord : vec2f,\n\t@location(1) fillColor : vec4f,\n\t@location(2) strokeColor : vec4f,\n\t@location(3) strokeWeight : f32,\n\t@location(4) edge : f32\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\tmatrixIndex: f32,\n\tfillIndex: f32,\n\tstrokeIndex: f32,\n\tstrokeWeight: f32,\n\tedge: f32\n}\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\n@group(1) @binding(0) var fontTexture: texture_2d<f32>;\n@group(1) @binding(1) var fontSampler: sampler;\n@group(1) @binding(2) var<storage> fontChars: array<Char>;\n\n@group(2) @binding(0) var<storage> textChars: array<vec4f>;\n@group(2) @binding(1) var<storage> textMetadata: array<Text>;\n\nconst quad = array(vec2f(0, 1), vec2f(1, 1), vec2f(0, 0), vec2f(1, 0));\nconst uvs = array(vec2f(0, 1), vec2f(1, 1), vec2f(0, 0), vec2f(1, 0));\n\nfn calcPos(i: u32, char: vec4f, fontChar: Char, text: Text) -> vec2f {\n\treturn ((quad[i] * fontChar.size + char.xy + fontChar.offset) *\n\t\ttext.scale) + text.pos;\n}\n\nfn calcUV(i: u32, fontChar: Char) -> vec2f {\n\treturn uvs[i] * fontChar.texExtent + fontChar.texOffset;\n}\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\nfn calcDist(texCoord: vec2f, edgeWidth: f32) -> f32 {\n\tlet c = textureSample(fontTexture, fontSampler, texCoord);\n\tlet sigDist = max(min(c.r, c.g), min(max(c.r, c.g), c.b)) - edgeWidth;\n\n\tlet pxRange = 4.0;\n\tlet sz = vec2f(textureDimensions(fontTexture, 0));\n\tlet dx = sz.x * length(vec2f(dpdxFine(texCoord.x), dpdyFine(texCoord.x)));\n\tlet dy = sz.y * length(vec2f(dpdxFine(texCoord.y), dpdyFine(texCoord.y)));\n\tlet toPixels = pxRange * inverseSqrt(dx * dx + dy * dy);\n\treturn sigDist * toPixels;\n}\n\n@vertex\nfn vertexMain(v : VertexParams) -> FragParams {\n\tlet char = textChars[v.instanceIndex];\n\tlet text = textMetadata[i32(char.w)];\n\tlet fontChar = fontChars[i32(char.z)];\n\tlet pos = calcPos(v.vertexIndex, char, fontChar, text);\n\n\tvar vert = transformVertex(pos, text.matrixIndex);\n\n\tvar f : FragParams;\n\tf.position = vert;\n\tf.texCoord = calcUV(v.vertexIndex, fontChar);\n\tf.fillColor = colors[i32(text.fillIndex)];\n\tf.strokeColor = colors[i32(text.strokeIndex)];\n\tf.strokeWeight = text.strokeWeight;\n\tf.edge = text.edge;\n\treturn f;\n}\n\n@fragment\nfn fragMain(f : FragParams) -> @location(0) vec4f {\n\tlet edge = f.edge;\n\tlet dist = calcDist(f.texCoord, edge);\n\n\tif (f.strokeWeight == 0.0) {\n\t\tlet fillAlpha = smoothstep(-edge, edge, dist);\n\t\tlet color = vec4f(f.fillColor.rgb, f.fillColor.a * fillAlpha);\n\t\tif (color.a < 0.01) {\n\t\t\tdiscard;\n\t\t}\n\t\treturn color;\n\t}\n\n\tlet halfStroke = f.strokeWeight / 2.0;\n\tlet fillAlpha = smoothstep(-edge, edge, dist - halfStroke);\n\tlet strokeAlpha = smoothstep(-edge, edge, dist + halfStroke);\n\tvar color = mix(f.strokeColor, f.fillColor, fillAlpha);\n\tcolor = vec4f(color.rgb, color.a * strokeAlpha);\n\tif (color.a < 0.01) {\n\t\tdiscard;\n\t}\n\treturn color;\n}\n";let vt=Q5.device.createShaderModule({label:"textShader",code:e._textShaderCode}),bt=Q5.device.createBindGroupLayout({label:"textBindGroupLayout",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"}}]}),yt=Q5.device.createSampler({minFilter:"linear",magFilter:"linear",mipmapFilter:"linear",maxAnisotropy:16}),St=Q5.device.createBindGroupLayout({label:"fontBindGroupLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,texture:{}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{}},{binding:2,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}}]}),wt=Q5.device.createPipelineLayout({bindGroupLayouts:[...e._bindGroupLayouts,St,bt]});e._pipelineConfigs[4]={label:"textPipeline",layout:wt,vertex:{module:vt,entryPoint:"vertexMain"},fragment:{module:vt,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs["source-over"]}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[4]=Q5.device.createRenderPipeline(e._pipelineConfigs[4]);class Ct{constructor(e,t,r,n){this.bindGroup=e,this.lineHeight=t,this.chars=r,this.kernings=n;let a=Object.values(r);this.charCount=a.length,this.defaultChar=a[0]}getChar(e){return this.chars[e]??this.defaultChar}getXAdvance(e,t=-1){let r=this.getChar(e);if(t>=0){let n=this.kernings.get(e);if(n)return r.xadvance+(n.get(t)??0)}return r.xadvance}}let Qt,Mt=[],Pt={};e.loadFont=(t="sans-serif",r)=>{if(Qt=!0,t.startsWith("https://fonts.googleapis.com/css"))return e._g.loadFont(t,r);let n=t.slice(t.lastIndexOf(".")+1);if(t==n){let e=t;Pt[e]=null,t=`https://q5js.org/fonts/${e}-msdf.json`,0!=Q5.online&&navigator.onLine||(t=`/node_modules/q5/builtinFonts/${e}-msdf.json`),n="json"}if("json"!=n)return e._g.loadFont(t,r);let a=t.slice(t.lastIndexOf("/")+1,t.lastIndexOf("-")),i={family:a};return i.promise=async function(t,r,n){let a,i,o=t.substring(0,t.lastIndexOf("-"));try{[a,i]=await Promise.all([fetch(t).then((e=>{if(404==e.status)throw new Error("404");return e.json()})),fetch(o+".png").then((e=>e.blob())).then((e=>createImageBitmap(e)))])}catch(e){return console.error("Error loading font:",e),""}let s=[i.width,i.height,1],l=Q5.device.createTexture({label:`MSDF ${r}`,size:s,format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:i},{texture:l},s),"string"==typeof a.chars&&(a.chars=Q5.CSV.parse(a.chars," "),a.kernings=Q5.CSV.parse(a.kernings," "));let d=a.chars.length,c=Q5.device.createBuffer({size:32*d,usage:GPUBufferUsage.STORAGE,mappedAtCreation:!0}),u=new Float32Array(c.getMappedRange()),h=1/a.common.scaleW,f=1/a.common.scaleH,p={},g=0;for(let[e,t]of a.chars.entries())p[t.id]=t,p[t.id].charIndex=e,u[g]=t.x*h,u[g+1]=t.y*f,u[g+2]=t.width*h,u[g+3]=t.height*f,u[g+4]=t.width,u[g+5]=t.height,u[g+6]=t.xoffset,u[g+7]=t.yoffset,g+=8;c.unmap();let m=Q5.device.createBindGroup({label:"fontBindGroup",layout:St,entries:[{binding:0,resource:l.createView()},{binding:1,resource:yt},{binding:2,resource:{buffer:c}}]}),x=new Map;if(a.kernings)for(let e of a.kernings){let t=x.get(e.first);t||(t=new Map,x.set(e.first,t)),t.set(e.second,e.amount)}let _=new Ct(m,a.common.lineHeight,p,x);return _.index=Mt.length,Mt.push(_),Pt[r]=_,e._font=_,n&&n(r),{family:r}}(t,a,(()=>{delete i.then,i._usedAwait&&(i={family:a}),r&&r(i)})),e._loaders.push(i.promise),i.then=(e,t)=>(i._usedAwait=!0,i.promise.then(e,t)),i};let Et=18,It="left",Rt="alphabetic",At=!1,Tt=22.5,kt=4.5,Ot=1.25,Gt=["serif","sans-serif","monospace","cursive","fantasy","system-ui"];e.textFont=t=>{if(!t)return e._font;Qt=!0,"string"!=typeof t&&(t=t.family);let r=Pt[t];r?e._font=r:(Gt[t]||void 0===r)&&e._g.textFont(t)},e.textSize=t=>{if(e._font||e._g.textSize(t),null==t)return Et;Et=t,At||(Tt=t*Ot,kt=Tt-t)};let Lt={thin:100,extralight:200,light:300,normal:400,regular:400,medium:500,semibold:600,bold:700,bolder:800,extrabold:800,black:900,heavy:900},Dt=.5;e.textWeight=t=>{if(!t)return e._textWeight;if("string"==typeof t&&!(t=Lt[t.toLowerCase().replace(/[ _-]/g,"")]))throw new Error(`Invalid font weight: ${t}`);Dt=.6875-375e-6*t},e.textLeading=t=>e._font?t?(e._font.lineHeight=Tt=t,kt=Tt-Et,Ot=Tt/Et,void(At=!0)):Tt:e._g.textLeading(t),e.textAlign=(e,t)=>{It=e,t&&(Rt=t)},e.textStyle=e=>{};let Bt=[],Ft=[],zt=new Array(100),Ut=new Float32Array(4*Q5.MAX_CHARS),Vt=new Float32Array(8*Q5.MAX_TEXTS),Nt=(e,t,r)=>{let n=0,a=0,i=0,o=0,s=0,l=zt,d=t.charCodeAt(0);for(let c=0;c<t.length;++c){let u=d;switch(d=c<t.length-1?t.charCodeAt(c+1):-1,u){case 10:l.push(a),o++,n=Math.max(n,a),a=0,i-=e.lineHeight*Ot;break;case 13:break;case 32:a+=e.getXAdvance(u);break;case 9:a+=2*e.getXAdvance(u);break;default:r&&r(a,i,o,e.getChar(u)),a+=e.getXAdvance(u,d),s++}}l[o]=a,n=Math.max(n,a);let c=o+1;return{width:n,height:c*e.lineHeight*Ot,lineWidths:l,lineCount:c,printedCharCount:s}};e.text=(t,r,n,a,i)=>{if(Et<1)return;let o,s=typeof t;if("string"!=s)"object"==s?t=t.toString():t+="";else if(!t.length)return;if(!e._font){Qt||e.loadFont();let o=e.createTextImage(t,a,i);return e.textImage(o,r,n)}if(t.length>a){let e=[],r=0;for(;r<t.length&&e.length<i;){let n=r+a;if(n>=t.length){e.push(t.slice(r));break}let i=t.lastIndexOf(" ",n);(-1==i||i<r)&&(i=n),e.push(t.slice(r,i)),r=i+1}t=e.join("\n"),o=!0}o??=t.includes("\n");let l,d=[],c=It,u=Rt,h=Ft.length,f=0;if("left"!=c||o){l=Nt(e._font,t);let r=0;"alphabetic"==u?n-=Et:"center"==u?r=.5*l.height:"bottom"==u&&(r=l.height),Nt(e._font,t,((e,t,n,a)=>{let i=0;"center"==c?i=-.5*l.width- -.5*(l.width-l.lineWidths[n]):"right"==c&&(i=-l.lineWidths[n]),d[f]=e+i,d[f+1]=-(t+r),d[f+2]=a.charIndex,d[f+3]=h,f+=4}))}else l=Nt(e._font,t,((e,t,r,n)=>{d[f]=e,d[f+1]=-t,d[f+2]=n.charIndex,d[f+3]=h,f+=4})),"alphabetic"==u?n-=Et:"center"==u?n-=.5*Et:"bottom"==u&&(n-=Tt);Bt.push(d);let p=[];q&&j(),p[0]=r,p[1]=n,p[2]=Et/42,p[3]=H,p[4]=M&&E?A:1,p[5]=R,p[6]=P&&I?O:0,p[7]=Dt,Ft.push(p),x.push(_t,l.printedCharCount,e._font.index)},e.textWidth=t=>e._font?Nt(e._font,t).width*Et/42:(e._g.textSize(Et),e._g.textWidth(t)),e.textAscent=t=>e._font?Tt-kt:(e._g.textSize(Et),e._g.textAscent(t)),e.textDescent=t=>e._font?kt:(e._g.textSize(Et),e._g.textDescent(t)),e.createTextImage=(t,r,n)=>{if(e._g.textSize(Et),M&&E){let t=4*A;e._g.fill(_.slice(t,t+4))}if(P&&I){let t=4*R;e._g.stroke(_.slice(t,t+4))}let a=e._g.createTextImage(t,r,n);return e._makeDrawable(a),a},e.textImage=(t,r,n)=>{"string"==typeof t&&(t=e.createTextImage(t));let a=mt;mt="corner";let i=It;"center"==i?r-=t.canvas.hw:"right"==i&&(r-=t.width);let o=Rt;"alphabetic"==o?n-=t._leading:"center"==o?n-=t._middle:"bottom"==o?n-=t._bottom:"top"==o&&(n-=t._top),e.image(t,r,n),mt=a};let Ht=["frame","shapes","image","video","text"],qt={frame:10,shapes:1e3,image:2e3,video:3e3,text:4e3};e._createShader=(t,r="shapes")=>{t=t.trim();let n=e["_"+r+"ShaderCode"],a=n.indexOf("@vertex"),i=n.indexOf("@fragment");t=t.includes("@fragment")?t.includes("@vertex")?n.slice(0,a)+t:n.slice(0,i)+t:n.slice(0,a)+t+"\n\n"+n.slice(i);let o=Q5.device.createShaderModule({label:r+"Shader",code:t});o.type=r;let s=Ht.indexOf(r),l=Object.assign({},e._pipelineConfigs[s]);l.vertex.module=l.fragment.module=o;let d=qt[r];return e._pipelines[d]=Q5.device.createRenderPipeline(l),e._pipelines[d].shader=o,o.pipelineIndex=d,qt[r]++,o},e.createShader=e.createShapesShader=e._createShader,e.createFrameShader=t=>e._createShader(t,"frame"),e.createImageShader=t=>e._createShader(t,"image"),e.createVideoShader=t=>e._createShader(t,"video"),e.createTextShader=t=>e._createShader(t,"text"),e.shader=e=>{let t=e.type,r=e.pipelineIndex;"frame"==t?e.applyBeforeDraw?g=r:m=r:"shapes"==t?fe=r:"image"==t?tt=r:"video"==t?rt=r:"text"==t&&(_t=r)},e.resetShader=e.resetShapesShader=()=>fe=1,e.resetFrameShader=()=>g=m=0,e.resetImageShader=()=>tt=2,e.resetVideoShader=()=>rt=3,e.resetTextShader=()=>_t=4,e.resetShaders=()=>{g=m=0,fe=1,tt=2,rt=3,_t=4}},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.MAX_TRANSFORMS=1e7,Q5.MAX_RECTS=200200,Q5.MAX_ELLIPSES=200200,Q5.MAX_CHARS=1e5,Q5.MAX_TEXTS=1e4,Q5.initWebGPU=async()=>{if(!navigator.gpu)return console.warn("q5 WebGPU not supported on this browser! Use Google Chrome or Edge."),!1;if(!Q5.requestedGPU){Q5.requestedGPU=!0;let e=await navigator.gpu.requestAdapter();if(!e)return console.warn("q5 WebGPU could not start! No appropriate GPUAdapter found, Vulkan may need to be enabled."),!1;Q5.device=await e.requestDevice(),Q5.device.lost.then((e=>{console.error("WebGPU crashed!"),console.error(e)}))}return!0},Q5.WebGPU=async function(e,t){let r;return e&&"global"!=e||(Q5._hasGlobal=!0),await Q5.initWebGPU()||(r=new Q5(e,t,"webgpu-fallback")),r=new Q5(e,t,"webgpu"),await r.ready,r};const libLangs="\n# core\ncreateCanvas -> es:crearLienzo ja:キャンバスを作成する\nlog -> es:log\n\n# color\nbackground -> es:fondo ja:背景\nfill -> es:relleno\nstroke -> es:trazo\nnoFill -> es:sinRelleno\nnoStroke -> es:sinTrazo\ncolor -> es:color\ncolorMode -> es:modoColor\n\n# display\nwindowWidth -> es:anchoVentana\nwindowHeight -> es:altoVentana\nwidth -> es:ancho\nheight -> es:alto\nframeCount -> es:cuadroActual\nnoLoop -> es:pausar\nredraw -> es:redibujar\nloop -> es:reanudar\nframeRate -> es:frecuenciaRefresco\ngetTargetFrameRate -> es:obtenerTasaFotogramasObjetivo\ngetFPS -> es:obtenerFPS\ndeltaTime -> es:deltaTiempo\npixelDensity -> es:densidadPíxeles\ndisplayDensity -> es:densidadVisualización\nfullscreen -> es:pantallaCompleta\ndisplayMode -> es:modoVisualización\nhalfWidth -> es:medioAncho\nhalfHeight -> es:medioAlto\ncanvas -> es:lienzo\nresizeCanvas -> es:redimensionarLienzo\ndrawingContext -> es:contextoDibujo\n\n# shape\ncircle -> es:círculo\nellipse -> es:elipse\nrect -> es:rect\nsquare -> es:cuadrado\npoint -> es:punto\nline -> es:línea\ncapsule -> es:cápsula\nrectMode -> es:modoRect\nellipseMode -> es:modoEliptico\narc -> es:arco\ncurve -> es:curva\nbeginShape -> es:empezarForma\nendShape -> es:terminarForma\nvertex -> es:vértice\nbezier -> es:bezier\ntriangle -> es:triángulo\nquad -> es:quad\ncurveDetail -> es:detalleCurva\nbeginContour -> es:empezarContorno\nendContour -> es:terminarContorno\nbezierVertex -> es:vérticeBezier\nquadraticVertex -> es:vérticeCuadrático\n\n# image\nloadImage -> es:cargarImagen\nimage -> es:imagen\nimageMode -> es:modoImagen\nnoTint -> es:noTeñir\ntint -> es:teñir\nfilter -> es:filtro\ncreateImage -> es:crearImagen\ncreateGraphics -> es:crearGráficos\ndefaultImageScale -> es:escalaImagenPorDefecto\nresize -> es:redimensionar\ntrim -> es:recortar\nsmooth -> es:suavizar\nnoSmooth -> es:noSuavizar\nmask -> es:enmascarar\ncopy -> es:copiar\ninset -> es:insertado\nget -> es:obtener\nset -> es:establecer\npixels -> es:píxeles\nloadPixels -> es:cargarPíxeles\nupdatePixels -> es:actualizarPíxeles\n\n# text\ntext -> es:texto\nloadFont -> es:cargarFuente\ntextFont -> es:fuenteTexto\ntextSize -> es:tamañoTexto\ntextLeading -> es:interlineado\ntextStyle -> es:estiloTexto\ntextAlign -> es:alineaciónTexto\ntextWidth -> es:anchoTexto\ntextWeight -> es:pesoTexto\ntextAscent -> es:ascensoTexto\ntextDescent -> es:descensoTexto\ncreateTextImage -> es:crearImagenTexto\ntextImage -> es:imagenTexto\nnf -> es:nf\n\n# input\nmouseX -> es:ratónX\nmouseY -> es:ratónY\npmouseX -> es:pRatónX\npmouseY -> es:pRatónY\nmouseIsPressed -> es:ratónPresionado\nmouseButton -> es:botónRatón\nkey -> es:tecla\nkeyIsPressed -> es:teclaPresionada\nkeyIsDown -> es:teclaEstaPresionada\ntouches -> es:toques\npointers -> es:punteros\ncursor -> es:cursor\nnoCursor -> es:sinCursor\npointerLock -> es:bloqueoPuntero\n\n# style\nstrokeWeight -> es:grosorTrazo\nopacity -> es:opacidad\nshadow -> es:sombra\nnoShadow -> es:sinSombra\nshadowBox -> es:cajaSombra\nblendMode -> es:modoMezcla\nstrokeCap -> es:terminaciónTrazo\nstrokeJoin -> es:uniónTrazo\nerase -> es:borrar\nnoErase -> es:noBorrar\nclear -> es:limpiar\npushStyles -> es:guardarEstilos\npopStyles -> es:recuperarEstilos\ninFill -> es:enRelleno\ninStroke -> es:enTrazo\n\n# transform\ntranslate -> es:trasladar\nrotate -> es:rotar\nscale -> es:escalar\nshearX -> es:cizallarX\nshearY -> es:cizallarY\napplyMatrix -> es:aplicarMatriz\nresetMatrix -> es:reiniciarMatriz\npush -> es:apilar\npop -> es:desapilar\npushMatrix -> es:guardarMatriz\npopMatrix -> es:recuperarMatriz\n\n# math\nrandom -> es:aleatorio\nnoise -> es:ruido\ndist -> es:dist\nmap -> es:mapa\nangleMode -> es:modoÁngulo\nradians -> es:radianes\ndegrees -> es:grados\nlerp -> es:interpolar\nconstrain -> es:constreñir\nnorm -> es:norm\nabs -> es:abs\nround -> es:redondear\nceil -> es:techo\nfloor -> es:piso\nmin -> es:min\nmax -> es:max\npow -> es:pot\nsq -> es:cuad\nsqrt -> es:raiz\nexp -> es:exp\nrandomSeed -> es:semillaAleatoria\nrandomGaussian -> es:aleatorioGaussiano\nnoiseMode -> es:modoRuido\nnoiseSeed -> es:semillaRuido\nnoiseDetail -> es:detalleRuido\njit -> es:flu\nrandomGenerator -> es:generadorAleatorio\nrandomExponential -> es:aleatorioExponencial\n\n# sound\nloadSound -> es:cargarSonido\nloadAudio -> es:cargarAudio\ngetAudioContext -> es:obtenerContextoAudio\nuserStartAudio -> es:iniciarAudioUsuario\n\n# dom\ncreateElement -> es:crearElemento\ncreateA -> es:crearA\ncreateButton -> es:crearBotón\ncreateCheckbox -> es:crearCasilla\ncreateColorPicker -> es:crearSelectorColor\ncreateImg -> es:crearImg\ncreateInput -> es:crearEntrada\ncreateP -> es:crearP\ncreateRadio -> es:crearOpciónes\ncreateSelect -> es:crearSelección\ncreateSlider -> es:crearDeslizador\ncreateVideo -> es:crearVideo\ncreateCapture -> es:crearCaptura\nfindElement -> es:encontrarElemento\nfindElements -> es:encontrarElementos\n\n# record\ncreateRecorder -> es:crearGrabadora\nrecord -> es:grabar\npauseRecording -> es:pausarGrabación\ndeleteRecording -> es:borrarGrabación\nsaveRecording -> es:guardarGrabación\nrecording -> es:grabando\n\n# io\nload -> es:cargar\nsave -> es:guardar\nloadJSON -> es:cargarJSON\nloadStrings -> es:cargarTexto\nyear -> es:año\nday -> es:día\nhour -> es:hora\nminute -> es:minuto\nsecond -> es:segundo\nloadCSV -> es:cargarCSV\nloadXML -> es:cargarXML\nloadAll -> es:cargarTodo\ndisablePreload -> es:deshabilitarPrecarga\nshuffle -> es:barajar\nstoreItem -> es:guardarItem\ngetItem -> es:obtenerItem\nremoveItem -> es:eliminarItem\nclearStorage -> es:limpiarAlmacenamiento\n\n# shaders\ncreateShader -> es:crearShader\nplane -> es:plano\nshader -> es:shader\nresetShader -> es:reiniciarShader\nresetFrameShader -> es:reiniciarShaderFotograma\nresetImageShader -> es:reiniciarShaderImagen\nresetVideoShader -> es:reiniciarShaderVideo\nresetTextShader -> es:reiniciarShaderTexto\nresetShaders -> es:reiniciarShaders\ncreateFrameShader -> es:crearShaderFotograma\ncreateImageShader -> es:crearShaderImagen\ncreateVideoShader -> es:crearShaderVideo\ncreateTextShader -> es:crearShaderTexto\n\n# constants\nCORNER -> es:ESQUINA\nRADIUS -> es:RADIO\nCORNERS -> es:ESQUINAS\nTHRESHOLD -> es:UMBRAL\nGRAY -> es:GRIS\nOPAQUE -> es:OPACO\nINVERT -> es:INVERTIR\nPOSTERIZE -> es:POSTERIZAR\nDILATE -> es:DILATAR\nERODE -> es:EROSIONAR\nBLUR -> es:DESENFOCAR\nNORMAL -> es:NORMAL\nITALIC -> es:CURSIVA\nBOLD -> es:NEGRILLA\nBOLDITALIC -> es:NEGRILLA_CURSIVA\nLEFT -> es:IZQUIERDA\nCENTER -> es:CENTRO\nRIGHT -> es:DERECHA\nTOP -> es:ARRIBA\nBOTTOM -> es:ABAJO\nBASELINE -> es:LINEA_BASE\nMIDDLE -> es:MEDIO\nRGB -> es:RGB\nOKLCH -> es:OKLCH\nHSL -> es:HSL\nHSB -> es:HSB\nSRGB -> es:SRGB\nDISPLAY_P3 -> es:DISPLAY_P3\nMAXED -> es:MAXIMIZADO\nSMOOTH -> es:SUAVE\nPIXELATED -> es:PIXELADO\nTWO_PI -> es:DOS_PI\nHALF_PI -> es:MEDIO_PI\nQUARTER_PI -> es:CUARTO_PI\n\n# vector\ncreateVector -> es:crearVector\n",userLangs="\nupdate -> es:actualizar\ndraw -> es:dibujar\npostProcess -> es:postProcesar\nmousePressed -> es:alPresionarRatón\nmouseReleased -> es:alSoltarRatón\nmouseMoved -> es:alMoverRatón\nmouseDragged -> es:alArrastrarRatón\ndoubleClicked -> es:dobleClic\nkeyPressed -> es:alPresionarTecla\nkeyReleased -> es:alSoltarTecla\ntouchStarted -> es:alEmpezarToque\ntouchEnded -> es:alTerminarToque\ntouchMoved -> es:alMoverToque\nmouseWheel -> es:ruedaRatón\n",classLangs={Vector:"\nadd -> es:sumar\nsub -> es:restar\nmult -> es:multiplicar\ndiv -> es:dividir\nmag -> es:magnitud\nmagSq -> es:magnitudCuad\ndist -> es:distancia\nnormalize -> es:normalizar\nlimit -> es:limitar\nsetMag -> es:establecerMagnitud\nheading -> es:rumbo\nrotate -> es:rotar\nlerp -> es:interpolar\narray -> es:arreglo\ncopy -> es:copiar\ndot -> es:punto\ncross -> es:cruz\nangleBetween -> es:anguloEntre\nreflect -> es:reflejar\n",Sound:"\nload -> es:cargar\nplay -> es:reproducir\nstop -> es:parar\npause -> es:pausar\nloop -> es:bucle\nsetVolume -> es:establecerVolumen\nsetPan -> es:establecerPan\nsetLoop -> es:establecerBucle\nisLoaded -> es:estaCargado\nisPlaying -> es:estaReproduciendo\nisPaused -> es:estaPausado\nisLooping -> es:estaEnBucle\nonended -> es:alTerminar\n"},parseLangs=function(e,t){let r={};for(let n of e.split("\n")){let e=n.indexOf(" "+t+":");e>0&&"#"!=n[0]&&(r[n.split(" ")[0]]=n.slice(e+4).split(" ")[0])}return r};Object.defineProperty(Q5,"lang",{get:()=>Q5._lang,set:e=>{if(e==Q5._lang)return;if(Q5._lang=e,"en"==e)return Q5._userFns=Q5._userFns.slice(0,19),void(Q5._libMap=Q5._userFnsMap={});let t=parseLangs(libLangs,e);"object"==typeof window&&(window[t.createCanvas]=createCanvas);let r=parseLangs(userLangs,e);for(let e in r){let t=r[e];Q5.hasOwnProperty(t)||Object.defineProperty(Q5,t,{get:()=>Q5[e],set:t=>Q5[e]=t})}for(let t in classLangs)if(Q5[t]){let r=parseLangs(classLangs[t],e),n=Q5[t].prototype;for(let e in r){let t=r[e];n.hasOwnProperty(t)||Object.defineProperty(n,t,{get:function(){return this[e]},set:function(t){this[e]=t}})}}Q5._libMap=t,Q5._userFnsMap=r,Q5._userFns.push(...Object.values(r))}}),Q5.lang="en",Q5.modules.lang=e=>{let t=Q5._userFnsMap;for(let r in t){let n=t[r];Object.defineProperty(e,n,{get:()=>e[r],set:t=>e[r]=t})}let r=Q5._libMap;r.createCanvas&&(e[r.createCanvas]=e.createCanvas)},Q5.addHook("init",(e=>{let t=Q5._libMap;for(let r in t){e[t[r]]=e[r]}})),Q5.addHook("predraw",(e=>{let t=Q5._libMap;t.mouseX&&(e[t.frameCount]=e.frameCount,e[t.mouseX]=e.mouseX,e[t.mouseY]=e.mouseY,e[t.mouseIsPressed]=e.mouseIsPressed,e[t.mouseButton]=e.mouseButton,e[t.key]=e.key,e[t.keyIsPressed]=e.keyIsPressed,e[t.touches]=e.touches,e[t.pointers]=e.pointers)}));
|