UNPKG

q5

Version:

Beginner friendly graphics powered by WebGPU and optimized for interactive art!

9 lines 120 kB
/** * q5.js * @version 3.3 * @author quinton-ashley * @contributors evanalulu, Tezumie, ormaq, Dukemz, LingDong- * @license LGPL-3.0 * @class Q5 */ function Q5(e,t,r){let n=this;n._isQ5=n._q5=!0,n._parent=t,"webgpu-fallback"==r?(n._renderer="c2d",n._webgpu=n._webgpuFallback=!0):(n._renderer=r||"c2d",n["_"+n._renderer]=!0);let i,a="auto"==e;if(e??="global","auto"==e){if(!(window.setup||window.update||window.draw))return;e="global"}"global"==e&&(Q5._hasGlobal=n._isGlobal=!0,i=Q5._esm?globalThis:Q5._server?global:window),"graphics"==e&&(n._isGraphics=!0),"image"==e&&(n._isImage=!0);let o=new Proxy(n,{set:(e,t,r)=>(n[t]=r,n._isGlobal&&(i[t]=r),!0)});n.canvas=n.ctx=n.drawingContext=null,n.pixels=[];let s=null,l=!0;async function d(e){for(let t of Q5.hooks[e])await t.call(n,o)}n.frameCount=0,n.deltaTime=16,n._targetFrameRate=0,n._targetFrameDuration=16.666666666666668,n._frameRate=n._fps=60,n._loop=!0;let c=0;n.millis=()=>performance.now()-c,n.noCanvas=()=>{n.canvas?.remove&&n.canvas.remove(),n.canvas=0,o.ctx=o.drawingContext=0},window&&(n.windowWidth=window.innerWidth,n.windowHeight=window.innerHeight,n.deviceOrientation=window.screen?.orientation?.type),n._preloadPromises=[],n._usePreload=!0,n.usePromiseLoading=(e=!0)=>n._usePreload=!e,n.usePreloadSystem=(e=!0)=>n._usePreload=e,n.isPreloadSupported=()=>n._usePreload;const u=[];async function h(e){let t=e||performance.now();if(n._didResize&&(n.windowResized(),n._didResize=!1),n._loop)if(l)s=p(h);else{let e=t+n._targetFrameDuration,r=e-performance.now();for(;r<0;)r+=n._targetFrameDuration;s=setTimeout((()=>h(e)),r)}else if(n.frameCount&&!n._redraw)return;if(n.frameCount&&l&&!n._redraw){if(t-n._lastFrameTime<n._targetFrameDuration-4)return}o.deltaTime=t-n._lastFrameTime,n._frameRate=1e3/n.deltaTime,o.frameCount++;let r=performance.now();n.resetMatrix(),n._beginRender&&n._beginRender(),await d("predraw");try{await n.draw()}catch(e){throw Q5.errorTolerant||n.noLoop(),n._fes&&n._fes(e),e}await d("postdraw"),await n.postProcess(),n._render&&n._render(),n._finishRender&&n._finishRender(),o.pmouseX=n.mouseX,o.pmouseY=n.mouseY,o.moveX=o.moveY=0,n._lastFrameTime=t;let i=performance.now();n._fps=Math.round(1e3/(i-r))}n._incrementPreload=()=>{n._preloadPromises.push(new Promise((e=>u.push(e))))},n._decrementPreload=()=>{u.length&&u.pop()()},n.noLoop=()=>{n._loop=!1,null!=s&&(l&&window.cancelAnimationFrame?cancelAnimationFrame(s):clearTimeout(s)),s=null},n.loop=()=>{n._loop=!0,n._setupDone&&null==s&&h()},n.isLooping=()=>n._loop,n.redraw=async(e=1)=>{n._redraw=!0;for(let t=0;t<e;t++)await h();n._redraw=!1},n.remove=async()=>{n.noLoop(),n.canvas.remove(),await d("remove")},n.frameRate=e=>(e&&e!=n._targetFrameRate&&(n._targetFrameRate=e,n._targetFrameDuration=1e3/e,n._loop&&null!=s&&(l&&window.cancelAnimationFrame?cancelAnimationFrame(s):clearTimeout(s),s=null),l=e<=60,n._setupDone&&(s=l?p(h):setTimeout((()=>h()),n._targetFrameDuration))),n._frameRate),n.getTargetFrameRate=()=>n._targetFrameRate||60,n.getFPS=()=>n._fps,n.Element=function(e){this.elt=e},n._elements=[],n.describe=()=>{},n.log=n.print=console.log;for(let e in Q5.modules)Q5.modules[e](n,o);let f=Q5.renderers[n._renderer];for(let e in f)f[e](n,o);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(n[e]=Q5[e]);if(n._isGraphics)return;if(n._isGlobal){let e=Object.assign({},n);delete e.Color,Object.assign(Q5,e),delete Q5.Q5}for(let e of Q5.hooks.init)e.call(n,o);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof n[e]&&(n[e]=t.bind(n));for(let[e,t]of Object.entries(Q5.preloadMethods))n[e]=function(){return n._incrementPreload(),t.apply(n,arguments)};if(n._isGlobal){let e=Object.getOwnPropertyNames(n);for(let t of e)"_"!=t[0]&&(i[t]=n[t]);for(let e of["_incrementPreload","_decrementPreload"])i[e]=n[e]}"function"==typeof e&&e(n),Q5._instanceCount++;let p=window.requestAnimationFrame||function(e){const t=n._lastFrameTime+n._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},g=i||n,m=["preload","postProcess","mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","doubleClicked","mouseWheel","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of m)n[e]??=()=>{};function x(e){const t=g[e]||n[e];n[e]=e=>{try{return t(e)}catch(e){throw n._fes&&n._fes(e),e}}}async function _(){x("preload"),n.preload(),await Promise.race([new Promise((e=>{!function t(){n.setup||n.update||n.draw||g.setup||g.update||g.draw?e():n._setupDone||(n._render&&(n._beginRender(),n._render(),n._finishRender()),p(t))}()})),new Promise((e=>{setTimeout((()=>{n._preloadPromises.length||e()}),500)}))]),await Promise.all(n._preloadPromises),n._g&&await Promise.all(n._g._preloadPromises),"AsyncFunction"==g.setup?.constructor.name&&n.usePromiseLoading(),n.setup??=g.setup||(()=>{}),x("setup");for(let e of m)x(e);n.draw??=g.draw||(()=>{}),await d("presetup"),c=performance.now(),await n.setup(),n._setupDone=!0,null===n.ctx&&n.createCanvas(200,200),await d("postsetup"),n.frameCount||(n._lastFrameTime=performance.now()-15,p(h))}Q5.instances.push(n),a?_():setTimeout(_,32)}function createCanvas(e,t,r){if(!Q5._hasGlobal){(new Q5).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.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.p5??=global.Q5=Q5),"object"==typeof window?window.p5??=window.Q5=Q5:global.window=0,Q5.version=Q5.VERSION="3.3","object"==typeof document&&document.addEventListener("DOMContentLoaded",(()=>{Q5._hasGlobal||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,i,a){"object"==typeof t&&(a=t,t=null),a??=arguments[3],"string"==typeof a&&(a={renderer:a});let o=Object.assign({},Q5.canvasOptions);if("object"==typeof a&&Object.assign(o,a),!e._isImage)if(e._isGraphics)e._pixelDensity=this._pixelDensity;else if(Q5._server)r.visible=!0;else{let t=r,i=document.body||document.documentElement;for(;t&&t.parentElement!=i;)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,i),Object.assign(r,o);let s=e._createCanvas(r.w,r.h,o);return e._addEventMethods&&e._addEventMethods(r),s},e.createGraphics=function(t,r,n={}){"string"==typeof n&&(n={renderer:n});let i=new Q5("graphics",void 0,n.renderer||(e._webgpuFallback?"webgpu-fallback":e._renderer));n.alpha??=!0,n.colorSpace??=e.canvas.colorSpace,i.createCanvas.call(e,t,r,n);let a=i._pixelDensity*e._defaultImageScale;return i.defaultWidth=t*a,i.defaultHeight=r*a,i},e._setCanvasSize=(n,i)=>{i??=n??window.innerHeight,n??=window.innerWidth,r.w=n=Math.ceil(n),r.h=i=Math.ceil(i),t.halfWidth=r.hw=n/2,t.halfHeight=r.hh=i/2,r.width=Math.ceil(n*e._pixelDensity),r.height=Math.ceil(i*e._pixelDensity),t.width=n,t.height=i,e.displayMode&&!r.displayMode?e.displayMode():e._adjustDisplay(!0)},e._setImageSize=(n,i)=>{t.width=r.w=n,t.height=r.h=i,t.halfWidth=r.hw=n/2,t.halfHeight=r.hh=i/2,r.width=Math.ceil(n*e._pixelDensity),r.height=Math.ceil(i*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._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.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,i,a){if(r)return t.ctx=t.drawingContext=r.getContext("2d",a),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 i,a={};for(let t in e.ctx)"function"!=typeof e.ctx[t]&&(a[t]=e.ctx[t]);if(delete a.canvas,e.frameCount>1){i=new e._Canvas(r.width,r.height),i.w=r.w,i.h=r.h,i.getContext("2d").drawImage(r,0,0)}e._setCanvasSize(t,n);for(let t in a)e.ctx[t]=a[t];e.scale(e._pixelDensity),i&&e.ctx.drawImage(i,0,0,i.w,i.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,i,a,o)=>e.ctx.transform(t,r,n,i,a,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,i)=>{e._doStroke&&(e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(n,i),e.ctx.stroke())};const i=2*Math.PI;function a(t,r,n,a,o,s,l){if(e._angleMode&&(o=e.radians(o),s=e.radians(s)),(o%=i)<0&&(o+=i),(s%=i)<0&&(s+=i),o>s&&(s+=i),o==s)return e.ellipse(t,r,n,a);if(n/=2,a/=2,n=Math.abs(n),a=Math.abs(a),e._doFill||l!=e.PIE_OPEN||(l=e.CHORD_OPEN),e.ctx.beginPath(),e.ctx.ellipse(t,r,n,a,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,a,0,o,s),e.ctx.stroke()}}function o(t,r,a,o){e.ctx.beginPath(),e.ctx.ellipse(t,r,Math.abs(a/2),Math.abs(o/2),0,0,i),n()}function s(t,r,i,a,o,l,d,c){return void 0===o?function(t,r,i,a){e.ctx.beginPath(),e.ctx.rect(t,r,i,a),n()}(t,r,i,a):void 0===l?s(t,r,i,a,o,o,o,o):(e.ctx.beginPath(),e.ctx.roundRect(t,r,i,a,[o,l,d,c]),void n())}e.arc=(t,r,n,i,o,s,l)=>{if(o==s)return e.ellipse(t,r,n,i);l??=e.PIE_OPEN,e._ellipseMode==e.CENTER?a(t,r,n,i,o,s,l):e._ellipseMode==e.RADIUS?a(t,r,2*n,2*i,o,s,l):e._ellipseMode==e.CORNER?a(t+n/2,r+i/2,n,i,o,s,l):e._ellipseMode==e.CORNERS&&a((t+n)/2,(r+i)/2,n-t,i-r,o,s,l)},e.ellipse=(t,r,n,i)=>{i??=n,e._ellipseMode==e.CENTER?o(t,r,n,i):e._ellipseMode==e.RADIUS?o(t,r,2*n,2*i):e._ellipseMode==e.CORNER?o(t+n/2,r+i/2,n,i):e._ellipseMode==e.CORNERS&&o((t+n)/2,(r+i)/2,n-t,i-r)},e.circle=(t,r,a)=>{e._ellipseMode==e.CENTER?(e.ctx.beginPath(),e.ctx.arc(t,r,Math.abs(a/2),0,i),n()):e.ellipse(t,r,a,a)},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,i=n,a,o,l,d)=>{e._rectMode==e.CENTER?s(t-n/2,r-i/2,n,i,a,o,l,d):e._rectMode==e.RADIUS?s(t-n,r-i,2*n,2*i,a,o,l,d):e._rectMode==e.CORNER?s(t,r,n,i,a,o,l,d):e._rectMode==e.CORNERS&&s(t,r,n-t,i-r,a,o,l,d)},e.square=(t,r,n,i,a,o,s)=>e.rect(t,r,n,n,i,a,o,s),e.capsule=(t,r,i,a,o)=>{const s=i-t,l=a-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(i+u,a+h),e.ctx.arc(i,a,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,i)=>{r=[],t?e.ctx.moveTo(n,i):e.ctx.lineTo(n,i),t=!1},e.bezierVertex=(t,n,i,a,o,s)=>{r=[],e.ctx.bezierCurveTo(t,n,i,a,o,s)},e.quadraticVertex=(t,n,i,a)=>{r=[],e.ctx.quadraticCurveTo(t,n,i,a)},e.bezier=(t,r,n,i,a,o,s,l)=>{e.beginShape(),e.vertex(t,r),e.bezierVertex(n,i,a,o,s,l),e.endShape()},e.triangle=(t,r,n,i,a,o)=>{e.beginShape(),e.vertex(t,r),e.vertex(n,i),e.vertex(a,o),e.endShape(e.CLOSE)},e.quad=(t,r,n,i,a,o,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(n,i),e.vertex(a,o),e.vertex(s,l),e.endShape(e.CLOSE)},e.endShape=t=>{r=[],t&&e.ctx.closePath(),n()},e.curveVertex=(n,i)=>{if(r.push([n,i]),r.length<4)return;let a=r.at(-4),o=r.at(-3),s=r.at(-2),l=r.at(-1),d=o[0]+(s[0]-a[0])/6,c=o[1]+(s[1]-a[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,i,a,o,s,l)=>{e.beginShape(),e.curveVertex(t,r),e.curveVertex(n,i),e.curveVertex(a,o),e.curveVertex(s,l),e.endShape()},e.curvePoint=(e,t,r,n,i)=>{const a=i*i*i,o=i*i;return e*(-.5*a+o-.5*i)+t*(1.5*a-2.5*o+1)+r*(-1.5*a+2*o+.5*i)+n*(.5*a-.5*o)},e.bezierPoint=(e,t,r,n,i)=>{const a=1-i;return Math.pow(a,3)*e+3*Math.pow(a,2)*i*t+3*a*Math.pow(i,2)*r+Math.pow(i,3)*n},e.curveTangent=(e,t,r,n,i)=>{const a=i*i;return e*(-3*a/2+2*i-.5)+t*(9*a/2-5*i)+r*(-9*a/2+4*i+.5)+n*(3*a/2-i)},e.bezierTangent=(e,t,r,n,i)=>{const a=1-i;return 3*n*Math.pow(i,2)-3*r*Math.pow(i,2)+6*r*a*i-6*t*a*i+3*t*Math.pow(a,2)-3*e*Math.pow(a,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,i=null;e.createImage=(t,n,i)=>(i??={},i.alpha??=!0,i.colorSpace??=r.colorSpace||Q5.canvasOptions.colorSpace,new Q5.Image(e,t,n,i)),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 i=[...arguments].at(-1);"object"==typeof i?(n=i,r=null):n=null;let a=e.createImage(1,1,n),o=a._pixelDensity,s=new window.Image;return s.crossOrigin="Anonymous",a.promise=new Promise(((t,n)=>{s.onload=()=>{s._pixelDensity=o,a.defaultWidth=s.width*e._defaultImageScale,a.defaultHeight=s.height*e._defaultImageScale,a.naturalWidth=s.naturalWidth||s.width,a.naturalHeight=s.naturalHeight||s.height,a._setImageSize(Math.ceil(a.naturalWidth/o),Math.ceil(a.naturalHeight/o)),a.ctx.drawImage(s,0,0),r&&r(a),delete a.promise,t(a)},s.onerror=n})),e._preloadPromises.push(a.promise),a.src=s.src=t,e._usePreload?a:a.promise},e._imageMode=Q5.CORNER,e.imageMode=t=>e._imageMode=t,e.image=(t,r,n,i,a,o=0,s=0,l,d)=>{if(!t)return;let c=t.canvas||t;i??=t.defaultWidth||c.width||t.videoWidth,a??=t.defaultHeight||c.height||t.videoHeight,"center"==e._imageMode&&(r-=.5*i,n-=.5*a);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+i,0),e.ctx.scale(-1,1),r=0),e.ctx.drawImage(c,o*u,s*u,l,d,r,n,i,a),t.flipped&&e.ctx.restore()},e.filter=(t,n)=>{e.ctx.save();let i="";if(e.ctx.filter){if("string"==typeof t)i=t;else if(t==Q5.GRAY)i="saturate(0%)";else if(t==Q5.INVERT)i="invert(100%)";else if(t==Q5.BLUR){i=`blur(${Math.ceil(n*e._pixelDensity)||1}px)`}else if(t==Q5.THRESHOLD){n??=.5,i=`saturate(0%) brightness(${Math.floor(.5/Math.max(n,1e-5)*100)}%) contrast(1000000%)`}else if(t==Q5.SEPIA)i=`sepia(${n??1})`;else if(t==Q5.BRIGHTNESS)i=`brightness(${n??1})`;else if(t==Q5.SATURATION)i=`saturate(${n??1})`;else if(t==Q5.CONTRAST)i=`contrast(${n??1})`;else if(t==Q5.HUE_ROTATE){i=`hue-rotate(${n}${0==e._angleMode?"rad":"deg"})`}if(i&&(e.ctx.filter=i,"none"==e.ctx.filter))throw new Error(`Invalid filter format: ${t}`)}i||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 i=new e._Canvas(r.width,r.height);i.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(i,0,0,r.width,r.height),e.modified=e._retint=!0}),e._getImageData=(t,n,i,a)=>e.ctx.getImageData(t,n,i,a,{colorSpace:r.colorSpace}),e.trim=()=>{let t=e._pixelDensity||1,n=r.width,i=r.height,a=e._getImageData(0,0,n,i).data,o=n,s=0,l=i,d=0,c=3;for(let e=0;e<i;e++)for(let t=0;t<n;t++)0!==a[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,i,a,o,s,l,d)=>{let c=e._pixelDensity||1;e.ctx.drawImage(r,t*c,n*c,i*c,a*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,a,o)=>{let s=e._pixelDensity||1;if(void 0!==t&&void 0===a){i||e.loadPixels();let a=Math.floor(t*s),o=4*(Math.floor(n*s)*r.width+a);return[i[o],i[o+1],i[o+2],i[o+3]]}t=Math.floor(t||0)*s,n=Math.floor(n||0)*s,a??=e.width,o??=e.height;let l=e.createImage(a,o,{pixelDensity:s});return l.ctx.drawImage(r,t,n,a*s,o*s,0,0,a,o),l.width=a,l.height=o,e._webgpuInst&&e._webgpuInst._makeDrawable(l),l},e.set=(t,n,a)=>{if(t=Math.floor(t),n=Math.floor(n),e.modified=e._retint=!0,a.canvas){let r=e._tint;return e._tint=null,e.image(a,t,n),void(e._tint=r)}i||e.loadPixels();let o=e._pixelDensity||1;for(let e=0;e<o;e++)for(let s=0;s<o;s++){let l=4*((n*o+e)*r.width+t*o+s);i[l]=a.r,i[l+1]=a.g,i[l+2]=a.b,i[l+3]=a.a}},e.loadPixels=()=>{n=e._getImageData(0,0,r.width,r.height),t.pixels=i=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,n={}){let i=this;i._isImage=!0,i.canvas=i.ctx=i.drawingContext=null,i.pixels=[],Q5.modules.canvas(i,i);let a=Q5.renderers.c2d;for(let e of["canvas","image","softFilters"])a[e]&&a[e](i,i);i._pixelDensity=n.pixelDensity||1,i._defaultImageScale=e._defaultImageScale,i.createCanvas(t,r,n);let o=i._pixelDensity*e._defaultImageScale;i.defaultWidth=t*o,i.defaultHeight=r*o,delete i.createCanvas,i._loop=!1}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,i)=>{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,i)=>{i??=Math.max,r(),t.set(n);let[a,o]=[e.canvas.width,e.canvas.height];for(let e=0;e<o;e++)for(let r=0;r<a;r++){let s=4*Math.max(r-1,0),l=4*Math.min(r+1,a-1),d=4*Math.max(e-1,0)*a,c=4*Math.min(e+1,o-1)*a,u=4*e*a,h=4*r;for(let e=0;e<4;e++){let r=e+d,a=e+c,o=e+u;n[u+h+e]=i(t[r+h],t[o+s],t[o+h],t[o+l],t[a+h])}}},e._filters[Q5.ERODE]=t=>{e._filters[Q5.DILATE](t,Math.min)},e._filters[Q5.BLUR]=(n,i)=>{i=i||1,i=Math.floor(i*e._pixelDensity),r(),t.set(n);let a=2*i+1,o=function(e){let t=new Float32Array(e),r=.3*i+.8,n=r*r*2;for(let i=0;i<e;i++){let a=i-e/2,o=Math.exp(-a*a/n)/(2.5066282746*r);t[i]=o}return t}(a),[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<a;n++){let a=4*(e*s+Math.min(Math.max(r-i+n,0),s-1));l+=t[a]*o[n],d+=t[a+1]*o[n],c+=t[a+2]*o[n],u+=t[a+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<a;n++){let a=4*(Math.min(Math.max(e-i+n,0),l-1)*s+r);d+=t[a]*o[n],c+=t[a+1]*o[n],u+=t[a+2]*o[n],h+=t[a+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 a=e._getImageData(0,0,e.canvas.width,e.canvas.height);e._filters[n](a.data,i),e.ctx.putImageData(a,0,0)}},Q5.renderers.c2d.text=(e,t)=>{e._textAlign="left",e._textBaseline="alphabetic",e._textSize=12;let r="sans-serif",n=!1,i=15,a=3,o="normal",s="normal",l=0,d=[],c=!1,u=0;e._fontMod=!1;let h=e._textCache={};e._textCacheMaxSize=12e3,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;let i={family:n.split(":")[0]};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,a=await r.text(),o=/@font-face\s*{([^}]*)}/g,s=/src:\s*url\(([^)]+)\)[^;]*;/,l=/font-family:\s*['"]([^'"]+)['"]/,d=/font-weight:\s*([^;]+);/,c=/font-style:\s*([^;]+);/,u=[];for(;null!==(n=o.exec(a));){let e=n[1],t=s.exec(e);if(!t)continue;let r=t[1],i=l.exec(e);if(!i)continue;let a=i[1],o=d.exec(e),h=o?o[1]:"400",f=c.exec(e),p=f?f[1]:"normal",g=`${a}-${h}-${p}`.replace(/\s+/g,"-"),m=new FontFace(a,`url(${r})`,{weight:h,style:p});document.fonts.add(m);try{await m.load(),u.push(m)}catch(e){console.error(`Failed to load font face: ${g}`,e)}}return i.faces=u,delete i.promise,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=new FontFace(e,`url(${encodeURI(t)})`),document.fonts.add(n),n.promise=(async()=>{let e;try{await n.load()}catch(t){e=t}if(delete n.promise,e)throw e;return r&&r(n),n})()}return e._preloadPromises.push(n.promise),e.textFont(n.family),e._usePreload?n:n.promise},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||(i=1.25*t,a=i-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?i||1.25*e._textSize:(n=!0,t==i?i:(i=t,a=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)=>{c=!0;let i=e.text(t,0,0,r,n);return c=!1,i};let f=[];e.text=(t,n,s,p,g)=>{if(void 0===t||!e._doFill&&!e._doStroke)return;t=t.toString();let m,x,_,v,b,y=e.ctx;if(e._fontMod&&e._updateFont(),c){-1==l&&(()=>{let t=r+e._textSize+o+i,n=5381;for(let e=0;e<t.length;e++)n=33*n^t.charCodeAt(e);l=n>>>0})(),v=e._fill+e._stroke+e._strokeWeight;let n,a=h[t];if(a&&(n=a[l]),n&&(m=n[v],m))return m}if(-1==t.indexOf("\n")?f[0]=t:f=t.split("\n"),t.length>p){let e=[];for(let t of f){let r=0;for(;r<t.length;){let n=r+p;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}}f=e}if(c){if(x=0,_=i,m)m.modified=!0;else{let t=e.ctx.textBaseline;e.ctx.textBaseline="alphabetic";let r=y.measureText(" "),n=r.fontBoundingBoxAscent,o=r.fontBoundingBoxDescent;e.ctx.textBaseline=t;let s=0;for(let e of f){let t=y.measureText(e).width;t>s&&(s=t)}let l=Math.ceil(s),d=Math.ceil(i*f.length+o);m=e.createImage.call(e,l,d,{pixelDensity:e._pixelDensity}),m._ascent=n,m._descent=o,m._top=o+a,m._middle=m._top+.5*n+i*(f.length-1)*.5,m._bottom=m._top+n+i*(f.length-1),m._leading=i}y=m.ctx,y.font=e.ctx.font,y.fillStyle=e._fill,y.strokeStyle=e._stroke,y.lineWidth=e.ctx.lineWidth}else x=n,_=s,"middle"==e._textBaseline?_-=i*(f.length-1)*.5:"bottom"==e._textBaseline&&(_-=i*(f.length-1));e._fillSet||(b=y.fillStyle,y.fillStyle="black");let w=0;for(let t of f)if(e._doStroke&&e._strokeSet&&y.strokeText(t,x,_),e._doFill&&y.fillText(t,x,_),_+=i,w++,w>=g)break;if(f=[],e._fillSet||(y.fillStyle=b),c){if(d.push(l),(h[t]??={})[l]??={},h[t][l][v]=m,u++,u>e._textCacheMaxSize){let e=Math.ceil(u/2),t=d.splice(0,e);for(let e in h){e=h[e];for(let r of t)delete e[r]}u-=e}return m}},e.textImage=(t,r,n)=>{"string"==typeof t&&(t=e.createTextImage(t));let i=e._imageMode;e._imageMode="corner";let a=e._textAlign;"center"==a?r-=t.canvas.hw:"right"==a&&(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=i}},Q5.fonts=[],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,i)=>{e._colorMode=r;let a="srgb"==e.canvas.colorSpace||"srgb"==i;e._srgb=a,n??="rgb"==r&&(e._c2d||a)?255:1,e._colorFormat="integer"==n||255==n?255:1,"oklch"==r?t.Color=Q5.ColorOKLCH:"hsl"==r?t.Color=a?Q5.ColorHSL:Q5.ColorHSL_P3:"hsb"==r?t.Color=a?Q5.ColorHSB:Q5.ColorHSB_P3:(255==e._colorFormat?t.Color=a?Q5.ColorRGB_8:Q5.ColorRGB_P3_8:t.Color=a?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],crimson:[220,20,60],cyan:[0,255,255],darkviolet:[148,0,211],gold:[255,215,0],green:[0,128,0],gray:[128,128,128],grey:[128,128,128],hotpink:[255,105,180],indigo:[75,0,130],khaki:[240,230,140],lightgreen:[144,238,144],lime:[0,255,0],magenta:[255,0,255],navy:[0,0,128],orange:[255,165,0],olive:[128,128,0],peachpuff:[255,218,185],pink:[255,192,203],purple:[128,0,128],red:[255,0,0],skyblue:[135,206,235],tan:[210,180,140],turquoise:[64,224,208],transparent:[0,0,0,0],white:[255,255,255],violet:[238,130,238],yellow:[255,255,0]},e.color=(t,r,n,i)=>{let a=e.Color;if(t._isColor)return new a(...t.levels);if(null==r){if("string"==typeof t){if("#"==t[0])t.length<=5?(t.length>4&&(i=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&&(i=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 a(0,0,0);return e._css=t,e.toString=function(){return this._css},e}if([t,r,n,i]=e._namedColors[t],"rgb"!=e._colorMode)return a=e._srgb?Q5.ColorRGB_8:Q5.ColorRGB_P3_8,new a(t,r,n,i)}1==e._colorFormat&&(t/=255,r&&(r/=255),n&&(n/=255),i&&(i/=255))}(Array.isArray(t)||t.constructor==Float32Array)&&([t,r,n,i]=t)}return null==n?e._colorMode==Q5.OKLCH?new a(t,0,0,r):new a(t,t,t,r):new a(t,r,n,i)},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,i=t.b;255==e._colorFormat&&(r/=255,n/=255,i/=255);let a,o=Math.max(r,n,i),s=Math.min(r,n,i);return a=o==s?0:o==r?60*(n-i)/(o-s):o==n?60*(i-r)/(o-s)+120:60*(r-n)/(o-s)+240,a<0&&(a+=360),a},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 i=r.h-t.h;i>180&&(i-=360),i<-180&&(i+=360);let a=t.h+n*i;return a<0&&(a+=360),a>360&&(a-=360),new e.Color(e.lerp(t.l,r.l,n),e.lerp(t.c,r.c,n),a,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),i=(t,i=(t+e/30)%12)=>r-n*Math.max(Math.min(i-3,9-i,1),-1);return[i(0),i(8),i(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)))},i=t=>e([3.2409699419045226,-1.537383177570094,-.4986107602930034,-.9692436362808796,1.8759675015077202,.04155505740717559,.05563007969699366,-.20397695888897652,1.0569715142428786],t);Q5.OKLCHtoRGB=(e,a,o)=>r(i(n(t(e,a,o))))}if(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",i=1)=>{Q5._server||("string"==typeof i&&(i=parseFloat(i.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:i}),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 i=e.canvas.offsetLeft+t;n.style.left=i+"px",n._x=i}}),Object.defineProperty(n,"y",{get:()=>n._y,set:t=>{let r=n.style.position;r&&"relative"!=r||(n.style.position="absolute");let i=e.canvas.offsetTop+t;n.style.top=i+"px",n._y=i}}),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 i=e.createEl("a",r);return i.href=t,i.target=n?"_blank":"_self",i},e.createButton=t=>e.createEl("button",t),e.createCheckbox=(t="",r=!1)=>{let n=e.createEl("input");n.type="checkbox",n.checked=r;let i=e.createEl("label",t);return i.addEventListener("click",(()=>{n.checked=!n.checked,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))})),n.insertAdjacentElement("afterend",i),n.label=i,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;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 i=e.createEl("input");i.type="radio",i.name=n.name,i.value=r||t,i.addEventListener("input",(()=>n.selected=i));let a=e.createEl("label",t);return a.addEventListener("click",(()=>{i.checked=!0,n.selected=i,i.dispatchEvent(new Event("input",{bubbles:!0})),i.dispatchEvent(new Event("change",{bubbles:!0}))})),i.label=a,n.append(i),n.append(a),n.buttons.push(i),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 i=e.createEl("option",t);return i.value=n||t,r.append(i),r},r},e.createSlider=(t,r,n,i)=>{let a=e.createEl("input");return a.type="range",a.min=t,a.max=r,a.value=n,a.step=i,a.val=()=>parseFloat(a.value),a},e.createSpan=t=>e.createEl("span",t),e.createVideo=t=>{let r=e.createEl("video");return r.crossOrigin="anonymous",r._load=()=>{r.width||=r.videoWidth,r.height||=r.videoHeight,r.defaultWidth=r.width*e._defaultImageScale,r.defaultHeight=r.height*e._defaultImageScale,r.ready=!0},t&&(r.promise=new Promise((e=>{r.addEventListener("loadeddata",(()=>{r._load(),e(r)})),r.src=t})),e._preloadPromises.push(r.promise),!e._usePreload)?r.promise:r},e.createCapture=function(t,r=!0,n){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 a=e.createVideo();return a.playsinline=a.autoplay=!0,r&&(a.flipped=!0,a.style.transform="scale(-1, 1)"),a.loadPixels=()=>{let t=e.createGraphics(a.videoWidth,a.videoHeight,{renderer:"c2d"});t.image(a,0,0),t.loadPixels(),a.pixels=t.pixels,t.remove()},a.promise=(async()=>{let e;try{e=await navigator.mediaDevices.getUserMedia(i)}catch(e){throw e}return a.srcObject=e,await new Promise((e=>a.addEventListener("loadeddata",e))),a._load(),n&&n(a),a})(),e._preloadPromises.push(a.promise),e._usePreload?a:a.promise},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,i="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(n=0,i="@");r[n].indexOf("q5")>=0;)n++;let a=r[n].split(i).at(-1);a.startsWith("blob:")&&(a=a.slice(5));let o=a.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())],i=window.self!==window.top,a=`q5.js ${n}`,o=` Error in ${d} on line ${s}:\n\n${r}`;i?e.log(a+o):e.log(`%c${a}%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)})))}},null!=typeof navigator&&navigator.onLine){async function checkLatestVersion(){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){}}checkLatestVersion()}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],i=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 a,o,s=e.pointers[n];if(s.event=r,i){let t=i.getBoundingClientRect(),n=i.scrollWidth/e.width||1,s=i.scrollHeight/e.height||1;a=(r.clientX-t.left)/n,o=(r.clientY-t.top)/s,e._webgpu&&(a-=i.hw,o-=i.hh)}else a=r.clientX,o=r.clientY;s.x=a,s.y=o,!r.isPrimary&&r.pointerId||(document.pointerLockElement?(t.mouseX+=r.movementX,t.mouseY+=r.movementY):(t.mouseX=a,t.mouseY=o),t.moveX=r.movementX,t.moveY=r.movementY)};let a=0;function o(t){const r=e.canvas.getBoundingClientRect(),n=e.canvas.scrollWidth/e.width||1,i=e.canvas.scrollHeight/e.height||1;let a=0,o=0;return e._webgpu&&(a=e.halfWidth,o=e.halfHeight),{x:(t.clientX-r.left)/n-a,y:(t.clientY-r.top)/i-o,id:t.identifier}}if(e._onpointerdown=r=>{a++,e._startAudio(),e._updatePointer(r),t.mouseIsPressed=!0,t.mouseButton=n[r.button],e.mousePressed(r)},e._onpointermove=t=>{i&&!i.visible||(e._updatePointer(t),e.mouseIsPressed?e.mouseDragged(t):e.mouseMoved(t))},e._onpointerup=r=>{t.mouseIsPressed=!1,a>0&&(a--,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.doub