textmode.js 0.1.9-beta.6 → 0.1.9

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.
Files changed (31) hide show
  1. package/README.md +14 -13
  2. package/dist/textmode.esm.js +1038 -1000
  3. package/dist/textmode.esm.min.js +910 -872
  4. package/dist/textmode.umd.js +14 -14
  5. package/dist/textmode.umd.min.js +14 -14
  6. package/dist/types/ColorPalette.d.ts +2 -5
  7. package/dist/types/export/txt/TXTDataExtractor.d.ts +3 -3
  8. package/dist/types/export/txt/types.d.ts +5 -3
  9. package/dist/types/index.d.ts +2 -1
  10. package/dist/types/rendering/core/Framebuffer.d.ts +140 -0
  11. package/dist/types/rendering/core/Shader.d.ts +59 -0
  12. package/dist/types/rendering/core/index.d.ts +2 -0
  13. package/dist/types/rendering/index.d.ts +3 -2
  14. package/dist/types/rendering/webgl/Framebuffer.d.ts +5 -20
  15. package/dist/types/rendering/webgl/Renderer.d.ts +9 -7
  16. package/dist/types/rendering/webgl/Shader.d.ts +23 -7
  17. package/dist/types/textmode/ConversionPipeline.d.ts +1 -1
  18. package/dist/types/textmode/Textmodifier.d.ts +4 -4
  19. package/dist/types/textmode/converters/BrightnessConverter.d.ts +25 -25
  20. package/dist/types/textmode/converters/Converter.d.ts +12 -5
  21. package/dist/types/textmode/converters/FeatureConverter.d.ts +27 -5
  22. package/dist/types/textmode/converters/index.d.ts +3 -3
  23. package/dist/types/textmode/font/TextmodeFont.d.ts +2 -2
  24. package/dist/types/textmode/font/TextureAtlas.d.ts +2 -2
  25. package/dist/types/textmode/mixins/RenderingMixin.d.ts +3 -3
  26. package/package.json +1 -1
  27. package/dist/types/rendering/core/AbstractFramebuffer.d.ts +0 -1
  28. package/dist/types/rendering/core/AbstractGeometry.d.ts +0 -1
  29. package/dist/types/rendering/core/AbstractShader.d.ts +0 -1
  30. package/dist/types/rendering/core/AbstractTexture.d.ts +0 -1
  31. package/dist/types/rendering/core/GraphicsContext.d.ts +0 -1
@@ -1,11 +1,11 @@
1
- var Wt=Object.defineProperty;var jt=(w,b,D)=>b in w?Wt(w,b,{enumerable:!0,configurable:!0,writable:!0,value:D}):w[b]=D;var c=(w,b,D)=>jt(w,typeof b!="symbol"?b+"":b,D);var t,e;t=this,e=function(w){class b extends Error{constructor(r,s={}){super(b.i(r,s)),this.name="TextmodeError"}static i(r,s){let i=r;if(s&&Object.keys(s).length>0){i+=`
1
+ var jt=Object.defineProperty;var Zt=(w,v,M)=>v in w?jt(w,v,{enumerable:!0,configurable:!0,writable:!0,value:M}):w[v]=M;var c=(w,v,M)=>Zt(w,typeof v!="symbol"?v+"":v,M);var t,e;t=this,e=function(w){class v extends Error{constructor(r,s={}){super(v.i(r,s)),this.name="TextmodeError"}static i(r,s){let i=r;if(s&&Object.keys(s).length>0){i+=`
2
2
 
3
3
  📋 Context:`;for(const[o,n]of Object.entries(s))i+=`
4
- - ${o}: ${b.o(n)}`}return i+=`
4
+ - ${o}: ${v.o(n)}`}return i+=`
5
5
 
6
6
  `,i+="↓".repeat(24)+`
7
- `,i}static o(r){if(r===null)return"null";if(r===void 0)return"undefined";if(typeof r=="string")return`"${r}"`;if(typeof r=="number"||typeof r=="boolean")return r+"";if(Array.isArray(r))return r.length===0?"[]":r.length<=5?`[${r.map(s=>b.o(s)).join(", ")}]`:`[${r.slice(0,3).map(s=>b.o(s)).join(", ")}, ... +${r.length-3} more]`;if(typeof r=="object"){const s=Object.keys(r);return s.length===0?"{}":s.length<=3?`{ ${s.map(i=>`${i}: ${b.o(r[i])}`).join(", ")} }`:`{ ${s.slice(0,2).map(i=>`${i}: ${b.o(r[i])}`).join(", ")}, ... +${s.length-2} more }`}return r+""}}var D=(l=>(l[l.SILENT=0]="SILENT",l[l.WARNING=1]="WARNING",l[l.ERROR=2]="ERROR",l[l.THROW=3]="THROW",l))(D||{});const S=class S{constructor(){c(this,"l",{globalLevel:3})}static u(){return S.h||(S.h=new S),S.h}p(r,s){const i="%c[textmode.js] Oops! (╯°□°)╯︵ Something went wrong in your code.",o="color: #f44336; font-weight: bold; background: #ffebee; padding: 2px 6px; border-radius: 3px;";switch(this.l.globalLevel){case 0:return!1;case 1:return console.group(i,o),console.warn(b.i(r,s)),console.groupEnd(),!1;case 2:return console.group(i,o),console.error(b.i(r,s)),console.groupEnd(),!1;default:throw new b(r,s)}}m(r,s,i){return!!r||(this.p(s,i),!1)}_(r){this.l.globalLevel=r}};c(S,"h",null);let O=S;const C=O.u(),X=new WeakMap;function Y(l,r){X.set(l,r)}function q(l){return X.get(l)}class Z{constructor(r,s,i=s,o={}){c(this,"v");c(this,"C");c(this,"$");c(this,"F");c(this,"M");c(this,"l");c(this,"S",null);c(this,"D",null);this.v=r,this.F=s,this.M=i,this.l={filter:"nearest",wrap:"clamp",format:"rgba",type:"unsigned_byte",...o},this.$=this.R(),this.C=r.createFramebuffer(),this.V()}k(r){const{v:s}=this,i=s.getParameter(s.FRAMEBUFFER_BINDING);s.bindFramebuffer(s.FRAMEBUFFER,this.C);try{return r()}finally{s.bindFramebuffer(s.FRAMEBUFFER,i)}}R(){const{v:r}=this,s=r.createTexture();r.bindTexture(r.TEXTURE_2D,s);const i=this.l.filter==="linear"?r.LINEAR:r.NEAREST,o=this.l.wrap==="repeat"?r.REPEAT:r.CLAMP_TO_EDGE;return r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MIN_FILTER,i),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_MAG_FILTER,i),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_S,o),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_T,o),this.I(),s}I(){const{v:r}=this,s=this.l.type==="float"?r.FLOAT:r.UNSIGNED_BYTE;r.texImage2D(r.TEXTURE_2D,0,r.RGBA,this.F,this.M,0,r.RGBA,s,null)}V(){const{v:r}=this;r.bindFramebuffer(r.FRAMEBUFFER,this.C),r.framebufferTexture2D(r.FRAMEBUFFER,r.COLOR_ATTACHMENT0,r.TEXTURE_2D,this.$,0),r.bindFramebuffer(r.FRAMEBUFFER,null)}update(r){const{v:s}=this;s.bindTexture(s.TEXTURE_2D,this.$),s.pixelStorei(s.UNPACK_FLIP_Y_WEBGL,1),s.texImage2D(s.TEXTURE_2D,0,s.RGBA,s.RGBA,s.UNSIGNED_BYTE,r),s.bindTexture(s.TEXTURE_2D,null)}updatePixels(r,s,i){const{v:o}=this;o.bindTexture(o.TEXTURE_2D,this.$),o.texImage2D(o.TEXTURE_2D,0,o.RGBA,s,i,0,o.RGBA,o.UNSIGNED_BYTE,r),o.bindTexture(o.TEXTURE_2D,null)}resize(r,s){const{v:i}=this;this.F=r,this.M=s,this.D=null,i.bindTexture(i.TEXTURE_2D,this.$),this.I(),i.bindTexture(i.TEXTURE_2D,null)}begin(){const{v:r}=this;this.S={framebuffer:r.getParameter(r.FRAMEBUFFER_BINDING),viewport:r.getParameter(r.VIEWPORT)},r.bindFramebuffer(r.FRAMEBUFFER,this.C),r.viewport(0,0,this.F,this.M),Y(r,[0,0,this.F,this.M])}end(){if(!this.S)return;const{v:r}=this;r.bindFramebuffer(r.FRAMEBUFFER,this.S.framebuffer),r.viewport(...this.S.viewport),Y(r,this.S.viewport),this.S=null}loadPixels(){const{v:r}=this;this.D||(this.D=new Uint8Array(this.F*this.M*4)),this.k(()=>{r.readPixels(0,0,this.F,this.M,r.RGBA,r.UNSIGNED_BYTE,this.D)})}get(r,s,i,o){const{v:n}=this;if(r===void 0&&s===void 0){const a=new Uint8Array(this.F*this.M*4);return this.k(()=>(n.readPixels(0,0,this.F,this.M,n.RGBA,n.UNSIGNED_BYTE,a),a))}if(i===void 0&&o===void 0){(r<0||s<0||r>=this.F||s>=this.M)&&(console.warn("The x and y values passed to Framebuffer.get are outside of its range and will be clamped."),r=Math.max(0,Math.min(r,this.F-1)),s=Math.max(0,Math.min(s,this.M-1)));const a=new Uint8Array(4);return this.k(()=>(n.readPixels(r,s,1,1,n.RGBA,n.UNSIGNED_BYTE,a),[a[0],a[1],a[2],a[3]]))}{r=Math.max(0,Math.min(r,this.F-1)),s=Math.max(0,Math.min(s,this.M-1)),i=Math.max(1,Math.min(i,this.F-r)),o=Math.max(1,Math.min(o,this.M-s));const a=new Uint8Array(i*o*4);return this.k(()=>(n.readPixels(r,s,i,o,n.RGBA,n.UNSIGNED_BYTE,a),a))}}P(){this.C&&this.v.deleteFramebuffer(this.C),this.$&&this.v.deleteTexture(this.$)}get framebuffer(){return this.C}get texture(){return this.$}get width(){return this.F}get height(){return this.M}get pixels(){return this.D}}class M{constructor(r,s,i){c(this,"v");c(this,"G");c(this,"A",new Map);c(this,"U",new Map);c(this,"L",0);c(this,"j");this.v=r,this.G=this.H(s,i),this.j=r.getParameter(r.MAX_TEXTURE_IMAGE_UNITS),this.O()}O(){const r=this.v.getProgramParameter(this.G,this.v.ACTIVE_UNIFORMS);for(let s=0;s<r;s++){const i=this.v.getActiveUniform(this.G,s);if(i){const o=this.v.getUniformLocation(this.G,i.name);o&&(this.A.set(i.name,o),this.U.set(i.name,i.type))}}}H(r,s){const i=this.W(this.v.VERTEX_SHADER,r),o=this.W(this.v.FRAGMENT_SHADER,s),n=this.v.createProgram();if(this.v.attachShader(n,i),this.v.attachShader(n,o),this.v.linkProgram(n),!this.v.getProgramParameter(n,this.v.LINK_STATUS)){const a=this.v.getProgramInfoLog(n);throw Error("Shader program link error: "+a)}return this.v.deleteShader(i),this.v.deleteShader(o),n}W(r,s){const i=this.v.createShader(r);if(this.v.shaderSource(i,s),this.v.compileShader(i),!this.v.getShaderParameter(i,this.v.COMPILE_STATUS)){const o=this.v.getShaderInfoLog(i);throw this.v.deleteShader(i),Error("Shader compilation error: "+o)}return i}N(){this.v.useProgram(this.G),this.X()}setUniform(r,s){const i=this.A.get(r);if(i)if(typeof s=="number")this.q(r)?this.v.uniform1i(i,Math.floor(s)):this.v.uniform1f(i,s);else if(typeof s=="boolean")this.v.uniform1i(i,s?1:0);else if(Array.isArray(s))switch(s.length){case 2:this.v.uniform2f(i,s[0],s[1]);break;case 3:this.v.uniform3f(i,s[0],s[1],s[2]);break;case 4:this.v.uniform4f(i,s[0],s[1],s[2],s[3]);break;default:console.warn(`Unsupported array length ${s.length} for uniform '${r}'`)}else if(s instanceof WebGLTexture){const o=this.Y();this.v.uniform1i(i,o),this.v.activeTexture(this.v.TEXTURE0+o),this.v.bindTexture(this.v.TEXTURE_2D,s)}else if(s instanceof Z){const o=this.Y();this.v.uniform1i(i,o),this.v.activeTexture(this.v.TEXTURE0+o),this.v.bindTexture(this.v.TEXTURE_2D,s.texture)}else console.warn(`Unsupported uniform type for '${r}':`,typeof s)}Y(){return this.L>=this.j&&console.warn(`Exceeded maximum texture units (${this.j}). Texture may not render correctly.`),this.L++}q(r){const s=this.U.get(r);return!!s&&(s===this.v.INT||s===this.v.INT_VEC2||s===this.v.INT_VEC3||s===this.v.INT_VEC4||s===this.v.SAMPLER_2D||s===this.v.SAMPLER_CUBE)}get glProgram(){return this.G}P(){this.v.deleteProgram(this.G)}X(){this.L=0}}class Q{constructor(r){c(this,"v");c(this,"Z",null);c(this,"J",16);c(this,"K",new Map);this.v=r}tt(){if(this.Z)return;const r=this.v;this.Z=r.createBuffer(),r.bindBuffer(r.ARRAY_BUFFER,this.Z)}et(){const r=this.v,s=r.getParameter(r.CURRENT_PROGRAM);let i=this.K.get(s);return i||(i={a_position:r.getAttribLocation(s,"a_position"),a_texCoord:r.getAttribLocation(s,"a_texCoord")},this.K.set(s,i)),r.enableVertexAttribArray(i.a_position),r.vertexAttribPointer(i.a_position,2,r.FLOAT,!1,this.J,0),r.enableVertexAttribArray(i.a_texCoord),r.vertexAttribPointer(i.a_texCoord,2,r.FLOAT,!1,this.J,8),{positionLoc:i.a_position,texLoc:i.a_texCoord}}st(r,s){const i=this.v;i.disableVertexAttribArray(r),i.disableVertexAttribArray(s)}rt(r,s){const i=this.v,o=q(i)||[0,0,i.canvas.width,i.canvas.height];return{nx:r/o[2]*2-1,ny:1-s/o[3]*2}}it(r,s,i,o){const n=this.v;this.tt(),n.bindBuffer(n.ARRAY_BUFFER,this.Z);const a=new Float32Array([r,o,0,0,i,o,1,0,r,s,0,1,r,s,0,1,i,o,1,0,i,s,1,1]);n.bufferData(n.ARRAY_BUFFER,a,n.DYNAMIC_DRAW)}P(){this.Z&&this.v.deleteBuffer(this.Z)}}class ht extends Q{constructor(r){super(r)}ot(r,s,i,o){const n=this.rt(r,s),a=this.rt(r+i,s+o);this.it(n.nx,n.ny,a.nx,a.ny);const h=this.et();this.v.drawArrays(this.v.TRIANGLES,0,6),this.st(h.positionLoc,h.texLoc)}nt(r,s,i,o,n){this.ot(r,s,i,n),this.ot(r+i-n,s,n,o),this.ot(r,s+o-n,i,n),this.ot(r,s,n,o)}}class lt extends Q{constructor(r){super(r)}ht(r,s,i,o,n){const a=i-r,h=o-s,u=Math.hypot(a,h);if(u===0){const f=n/2,p=this.rt(r-f,s-f),g=this.rt(r+f,s+f);this.it(p.nx,p.ny,g.nx,g.ny)}else{const f=-h/u,p=a/u,g=n/2,x=r+f*g,m=s+p*g,v=r-f*g,T=s-p*g,y=i+f*g,_=o+p*g,F=i-f*g,A=o-p*g,$=this.rt(x,m),P=this.rt(v,T),I=this.rt(y,_),at=this.rt(F,A),k=this.v;this.tt(),k.bindBuffer(k.ARRAY_BUFFER,this.Z);const zt=new Float32Array([$.nx,$.ny,0,0,P.nx,P.ny,0,1,I.nx,I.ny,1,0,P.nx,P.ny,0,1,at.nx,at.ny,1,1,I.nx,I.ny,1,0]);k.bufferData(k.ARRAY_BUFFER,zt,k.DYNAMIC_DRAW)}const d=this.et();this.v.drawArrays(this.v.TRIANGLES,0,6),this.st(d.positionLoc,d.texLoc)}}var B="attribute vec2 a_position;attribute vec2 a_texCoord;varying vec2 v_uv;uniform float u_rotation;uniform vec2 u_center;uniform float u_aspectRatio;mat2 rotate2D(float angle){float s=sin(angle);float c=cos(angle);return mat2(c,-s,s,c);}void main(){v_uv=a_texCoord;vec2 pos=a_position;pos-=u_center;pos.x*=u_aspectRatio;pos=rotate2D(-u_rotation)*pos;pos.x/=u_aspectRatio;pos+=u_center;gl_Position=vec4(pos,0.0,1.0);}";class ct{constructor(r){c(this,"v");c(this,"lt");c(this,"ct");c(this,"ut",null);c(this,"ft");c(this,"dt");c(this,"gt",[1,1,1,1]);c(this,"_t",!0);c(this,"vt",[0,0,0,1]);c(this,"xt",1);c(this,"bt",!0);c(this,"wt",0);c(this,"Ct",[]);this.v=r,this.lt=new M(this.v,B,"precision lowp float;uniform sampler2D u_texture;varying vec2 v_uv;void main(){gl_FragColor=texture2D(u_texture,v_uv);}"),this.ct=new M(this.v,B,"precision lowp float;uniform vec4 u_color;void main(){gl_FragColor=u_color;}"),this.ft=new ht(this.v),this.dt=new lt(this.v),this.v.enable(this.v.BLEND),this.v.blendEquation(this.v.FUNC_ADD),this.v.blendFunc(this.v.ONE,this.v.ONE_MINUS_SRC_ALPHA),Y(this.v,[0,0,this.v.canvas.width,this.v.canvas.height])}yt(r){this.ut!==r&&(this.ut=r,r.N())}$t(r,s,i,o){if(this._t=!0,s===void 0&&i===void 0&&o===void 0){const n=r/255;this.gt=[n,n,n,1]}else if(i!==void 0&&o===void 0)this.gt=[r/255,s/255,i/255,1];else{if(i===void 0||o===void 0)throw Error("Invalid fill parameters. Use fill(gray), fill(r,g,b), or fill(r,g,b,a)");this.gt=[r/255,s/255,i/255,o/255]}}Ft(r,s,i,o){if(this.bt=!0,s===void 0&&i===void 0&&o===void 0){const n=r/255;this.vt=[n,n,n,1]}else if(i!==void 0&&o===void 0)this.vt=[r/255,s/255,i/255,1];else{if(i===void 0||o===void 0)throw Error("Invalid stroke parameters. Use stroke(gray), stroke(r,g,b), or stroke(r,g,b,a)");this.vt=[r/255,s/255,i/255,o/255]}}Tt(r){if(r<0)throw Error("Stroke weight must be non-negative");this.xt=r}Mt(){this.bt=!1}St(){this._t=!1}Dt(r){this.wt=r}Rt(){this.Ct.push({fillColor:[...this.gt],fillMode:this._t,strokeColor:[...this.vt],strokeWeight:this.xt,strokeMode:this.bt,rotation:this.wt})}Vt(){const r=this.Ct.pop();r?(this.gt=r.fillColor,this._t=r.fillMode,this.vt=r.strokeColor,this.xt=r.strokeWeight,this.bt=r.strokeMode,this.wt=r.rotation):console.warn("pop() called without matching push()")}kt(){this.ut=null,this.Ct=[],this.wt=0}It(r){const s=r.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"").trim().match(/^#version\s+(\d+)\s+(es)?/i);return!!s&&parseInt(s[1],10)>=300}Pt(r,s){return new M(this.v,r,s)}zt(r){const s=this.It(r)?`#version 300 es
8
- in vec2 a_position;in vec2 a_texCoord;out vec2 v_uv;uniform float u_rotation;uniform vec2 u_center;uniform float u_aspectRatio;mat2 rotate2D(float angle){float s=sin(angle);float c=cos(angle);return mat2(c,-s,s,c);}void main(){v_uv=a_texCoord;vec2 pos=a_position;pos-=u_center;pos.x*=u_aspectRatio;pos=rotate2D(-u_rotation)*pos;pos.x/=u_aspectRatio;pos+=u_center;gl_Position=vec4(pos,0.0,1.0);}`:B;return new M(this.v,s,r)}Et(r,s){this.ut.setUniform(r,s)}Gt(r,s,i,o){if(this.ut!==null){const{centerX:p,centerY:g,radians:x,aspectRatio:m}=this.At(r,s,i,o);return this.Et("u_rotation",x),this.Et("u_center",[p,g]),this.Et("u_aspectRatio",m),this.ft.ot(r,s,i,o),void(this.ut=null)}const n=this.ct;let a=0,h=0,u=0,d=1;const f=this.At(r,s,i,o);a=f.centerX,h=f.centerY,u=f.radians,d=f.aspectRatio,this._t&&(this.yt(n),this.Et("u_color",this.gt),this.Et("u_rotation",u),this.Et("u_center",[a,h]),this.Et("u_aspectRatio",d),this.ft.ot(r,s,i,o)),this.bt&&this.xt>0&&(this.yt(n),this.Et("u_color",this.vt),this.Et("u_rotation",u),this.Et("u_center",[a,h]),this.Et("u_aspectRatio",d),this.ft.nt(r,s,i,o,this.xt)),this.ut=null}Ut(r,s,i,o){if(this.ut!==null){const v=(r+i)/2,T=(s+o)/2,y=Math.abs(i-r)||1,_=Math.abs(o-s)||1,{centerX:F,centerY:A,radians:$,aspectRatio:P}=this.At(v-y/2,T-_/2,y,_);this.Et("u_rotation",$),this.Et("u_center",[F,A]),this.Et("u_aspectRatio",P);const I=this.xt>0?this.xt:1;return this.dt.ht(r,s,i,o,I),void(this.ut=null)}if(!this.bt||this.xt<=0)return;const n=this.ct,a=(r+i)/2,h=(s+o)/2,u=Math.abs(i-r)||1,d=Math.abs(o-s)||1,f=this.wt!==0;let p=0,g=0,x=0,m=1;if(f){const v=this.At(a-u/2,h-d/2,u,d);p=v.centerX,g=v.centerY,x=v.radians,m=v.aspectRatio}this.yt(n),this.Et("u_color",this.vt),f&&(this.Et("u_rotation",x),this.Et("u_center",[p,g]),this.Et("u_aspectRatio",m)),this.dt.ht(r,s,i,o,this.xt)}At(r,s,i,o){const n=q(this.v)||[0,0,this.v.canvas.width,this.v.canvas.height],a=n[2],h=n[3],u=a/h;return{centerX:(r+i/2)/a*2-1,centerY:1-(s+o/2)/h*2,radians:this.wt*Math.PI/180,aspectRatio:u}}Lt(r,s,i={}){return new Z(this.v,r,s,i)}jt(r,s=r,i=r,o=255){this.Ht(r/255,s/255,i/255,o/255)}Ht(r=0,s=0,i=0,o=0){this.v.clearColor(r,s,i,o),this.v.clear(this.v.COLOR_BUFFER_BIT)}Ot(){this.v.viewport(0,0,this.v.canvas.width,this.v.canvas.height),Y(this.v,[0,0,this.v.canvas.width,this.v.canvas.height])}get context(){return this.v}P(){this.lt.P(),this.ct.P(),this.ft.P(),this.dt.P()}Bt(r,s,i,o,n){const a=this.v,h=o??r.width,u=n??r.height;this.yt(this.lt),this.Et("u_texture",r.texture);const d=this.At(s,i,h,u);this.Et("u_rotation",d.radians),this.Et("u_center",[d.centerX,d.centerY]),this.Et("u_aspectRatio",d.aspectRatio),this.ft.ot(s,i,h,u),a.bindTexture(a.TEXTURE_2D,null),this.ut=null}}const E={readShort:(l,r)=>(E.t.uint16[0]=l[r]<<8|l[r+1],E.t.int16[0]),readUshort:(l,r)=>l[r]<<8|l[r+1],readUshorts(l,r,s){const i=[];for(let o=0;o<s;o++)i.push(E.readUshort(l,r+2*o));return i},readUint(l,r){const s=E.t.uint8;return s[3]=l[r],s[2]=l[r+1],s[1]=l[r+2],s[0]=l[r+3],E.t.uint32[0]},readASCII(l,r,s){let i="";for(let o=0;o<s;o++)i+=String.fromCharCode(l[r+o]);return i},t:(()=>{const l=new ArrayBuffer(8);return{uint8:new Uint8Array(l),int16:new Int16Array(l),uint16:new Uint16Array(l),uint32:new Uint32Array(l)}})()},ut={parseTab(l,r,s){const i={tables:[],ids:{},off:r};l=new Uint8Array(l.buffer,r,s),r=0;const o=E,n=o.readUshort,a=n(l,r+=2);r+=2;const h=[];for(let u=0;u<a;u++){const d=n(l,r),f=n(l,r+=2);r+=2;const p=o.readUint(l,r);r+=4;const g=`p${d}e${f}`;let x=h.indexOf(p);if(x===-1){let m;x=i.tables.length,h.push(p);const v=n(l,p);m=v===4?this.parse4(l,p):v===12?this.parse12(l,p):{format:v},i.tables.push(m)}i.ids[g]!=null&&console.warn("Multiple tables for one platform+encoding: "+g),i.ids[g]=x}return i},parse4(l,r){const s=E,i=s.readUshort,o=s.readUshorts,n=r,a=i(l,r+=2);r+=2;const h=i(l,r+=2)>>>1,u={format:4,searchRange:i(l,r+=2),entrySelector:0,rangeShift:0,endCount:[],startCount:[],idDelta:[],idRangeOffset:[],glyphIdArray:[]};r+=2,u.entrySelector=i(l,r),r+=2,u.rangeShift=i(l,r),r+=2,u.endCount=o(l,r,h),r+=2*h,r+=2,u.startCount=o(l,r,h),r+=2*h;for(let d=0;d<h;d++)u.idDelta.push(s.readShort(l,r)),r+=2;return u.idRangeOffset=o(l,r,h),r+=2*h,u.glyphIdArray=o(l,r,n+a-r>>1),u},parse12(l,r){const s=E.readUint;s(l,r+=4),s(l,r+=4);const i=s(l,r+=4);r+=4;const o=new Uint32Array(3*i);for(let n=0;n<3*i;n+=3)o[n]=s(l,r+(n<<2)),o[n+1]=s(l,r+(n<<2)+4),o[n+2]=s(l,r+(n<<2)+8);return{format:12,groups:o}}},dt={parseTab(l,r,s){const i=E;r+=18;const o=i.readUshort(l,r);r+=2,r+=16;const n=i.readShort(l,r);r+=2;const a=i.readShort(l,r);r+=2;const h=i.readShort(l,r);r+=2;const u=i.readShort(l,r);return r+=2,r+=6,{unitsPerEm:o,xMin:n,yMin:a,xMax:h,yMax:u,indexToLocFormat:i.readShort(l,r)}}},ft={parseTab(l,r,s){const i=E;r+=4;const o=["ascender","descender","lineGap","advanceWidthMax","minLeftSideBearing","minRightSideBearing","xMaxExtent","caretSlopeRise","caretSlopeRun","caretOffset","res0","res1","res2","res3","metricDataFormat","numberOfHMetrics"],n={};for(let a=0;a<o.length;a++){const h=o[a],u=h==="advanceWidthMax"||h==="numberOfHMetrics"?i.readUshort:i.readShort;n[h]=u(l,r+2*a)}return n}},gt={parseTab(l,r,s,i){if(!i)throw Error("Font object required for hmtx parsing");const o=E,n=[],a=[],h=i.maxp.numGlyphs,u=i.hhea.numberOfHMetrics;let d=0,f=0,p=0;for(;p<u;)d=o.readUshort(l,r+(p<<2)),f=o.readShort(l,r+(p<<2)+2),n.push(d),a.push(f),p++;for(;p<h;)n.push(d),a.push(f),p++;return{aWidth:n,lsBearing:a}}},J={cmap:ut,head:dt,hhea:ft,maxp:{parseTab(l,r,s){const i=E;return i.readUint(l,r),r+=4,{numGlyphs:i.readUshort(l,r)}}},hmtx:gt,loca:{parseTab(l,r,s,i){if(!i)throw Error("Font object required for loca parsing");const o=E,n=[],a=i.head.indexToLocFormat,h=i.maxp.numGlyphs+1;if(a===0)for(let u=0;u<h;u++)n.push(o.readUshort(l,r+(u<<1))<<1);else if(a===1)for(let u=0;u<h;u++)n.push(o.readUint(l,r+(u<<2)));return n}},glyf:{parseTab(l,r,s,i){if(!i)throw Error("Font object required for glyf parsing");const o=[],n=i.maxp.numGlyphs;for(let a=0;a<n;a++)o.push(null);return o},Wt(l,r){const s=E,i=l.Nt,o=l.loca;if(o[r]===o[r+1])return null;const n=R.findTable(i,"glyf",l.Xt);if(!n)return null;let a=n[0]+o[r];const h={};if(h.noc=s.readShort(i,a),a+=2,h.xMin=s.readShort(i,a),a+=2,h.yMin=s.readShort(i,a),a+=2,h.xMax=s.readShort(i,a),a+=2,h.yMax=s.readShort(i,a),a+=2,h.xMin>=h.xMax||h.yMin>=h.yMax)return null;if(h.noc>0){h.endPts=[];for(let g=0;g<h.noc;g++)h.endPts.push(s.readUshort(i,a)),a+=2;const u=s.readUshort(i,a);if(a+=2,i.length-a<u)return null;a+=u;const d=h.endPts[h.noc-1]+1;h.flags=[];for(let g=0;g<d;g++){const x=i[a];if(a++,h.flags.push(x),8&x){const m=i[a];a++;for(let v=0;v<m;v++)h.flags.push(x),g++}}h.xs=[];for(let g=0;g<d;g++){const x=h.flags[g],m=!!(16&x);2&x?(h.xs.push(m?i[a]:-i[a]),a++):m?h.xs.push(0):(h.xs.push(s.readShort(i,a)),a+=2)}h.ys=[];for(let g=0;g<d;g++){const x=h.flags[g],m=!!(32&x);4&x?(h.ys.push(m?i[a]:-i[a]),a++):m?h.ys.push(0):(h.ys.push(s.readShort(i,a)),a+=2)}let f=0,p=0;for(let g=0;g<d;g++)f+=h.xs[g],p+=h.ys[g],h.xs[g]=f,h.ys[g]=p}else h.parts=[],h.endPts=[],h.flags=[],h.xs=[],h.ys=[];return h}}},R={parse:l=>[((r,s,i,o)=>{const n=J,a={Nt:r,qt:s,Xt:i};for(const h in n){const u=h,d=R.findTable(r,u,i);if(d){const[f,p]=d;let g=o[f];g==null&&(g=n[u].parseTab(r,f,p,a),o[f]=g),a[u]=g}}return a})(new Uint8Array(l),0,0,{})],findTable(l,r,s){const i=E,o=i.readUshort(l,s+4);let n=s+12;for(let a=0;a<o;a++){const h=i.readASCII(l,n,4);i.readUint(l,n+4);const u=i.readUint(l,n+8),d=i.readUint(l,n+12);if(h===r)return[u,d];n+=16}return null},T:J,B:E};class V{constructor(){c(this,"Yt",new Map);c(this,"Qt",new Map)}Zt(r,s){const i=`${this.Jt(r)}_${s}`;if(this.Yt.has(i))return this.Yt.get(i);const o=r.cmap;if(!o||!o.tables)return this.Yt.set(i,0),0;let n=0;for(const a of o.tables)if(a.format===4?n=this.Kt(s,a):a.format===12&&(n=this.te(s,a)),n>0)break;return this.Yt.set(i,n),n}ee(r,s){const i=s.codePointAt(0);return i===void 0?0:this.Zt(r,i)}se(r,s){const i=r.hmtx;return i&&i.aWidth&&i.aWidth.length!==0?s<i.aWidth.length?i.aWidth[s]:i.aWidth[i.aWidth.length-1]:0}re(r,s){const i=s/r.head.unitsPerEm,o=r.hhea.ascender*i,n=r.hhea.descender*i,a=r.hhea.lineGap*i;return{ascender:o,descender:n,lineGap:a,lineHeight:o-n+a,unitsPerEm:r.head.unitsPerEm,scale:i}}ie(){this.Yt.clear(),this.Qt.clear()}Jt(r){return`${r.Xt}_${r.Nt.length}`}Kt(r,s){const i=s.endCount.length;let o=-1;for(let n=0;n<i;n++)if(r<=s.endCount[n]){o=n;break}if(o===-1||r<s.startCount[o])return 0;if(s.idRangeOffset[o]===0)return r+s.idDelta[o]&65535;{const n=s.idRangeOffset[o]/2+(r-s.startCount[o])-(i-o);if(n>=0&&n<s.glyphIdArray.length){const a=s.glyphIdArray[n];return a===0?0:a+s.idDelta[o]&65535}}return 0}te(r,s){const i=s.groups.length/3;for(let o=0;o<i;o++){const n=s.groups[3*o],a=s.groups[3*o+1],h=s.groups[3*o+2];if(r>=n&&r<=a)return h+(r-n)}return 0}}class pt{constructor(r){c(this,"oe");this.oe=r}ne(r){var i;const s=[];return(i=r==null?void 0:r.cmap)!=null&&i.tables?(r.cmap.tables.forEach(o=>{if(o.format===4){const n=this.ae(o);s.push(...n)}else if(o.format===12){const n=this.he(o);s.push(...n)}}),[...new Set(s)]):[]}le(r,s){return this.oe.ee(r,s)>0}ce(r,s){for(const i of s)if(!this.le(r,i))return!1;return!0}ue(r,s){return s.filter(i=>this.le(r,i))}fe(r){return r.filter(s=>this.de(s))}ae(r){const s=[];if(!(r.startCount&&r.endCount&&r.idRangeOffset&&r.idDelta))return s;for(let i=0;i<r.startCount.length;i++){const o=r.startCount[i],n=r.endCount[i];if(o!==65535||n!==65535){for(let a=o;a<=n;a++)if(this.pe(r,a,i)>0)try{const h=String.fromCodePoint(a);s.push(h)}catch{}}}return s}he(r){const s=[];if(!r.groups)return s;for(let i=0;i<r.groups.length;i+=3){const o=r.groups[i],n=r.groups[i+1],a=r.groups[i+2];for(let h=o;h<=n;h++)if(a+(h-o)>0)try{const u=String.fromCodePoint(h);s.push(u)}catch{}}return s}pe(r,s,i){if(r.idRangeOffset[i]===0)return s+r.idDelta[i]&65535;{const o=r.idRangeOffset[i]/2+(s-r.startCount[i])-(r.startCount.length-i);if(o>=0&&r.glyphIdArray&&o<r.glyphIdArray.length){const n=r.glyphIdArray[o];if(n!==0)return n+r.idDelta[i]&65535}}return 0}de(r){const s=r.codePointAt(0)||0;return!(s>=0&&s<=31&&s!==9&&s!==10&&s!==13||s>=127&&s<=159)}}class vt{constructor(){c(this,"me");const r=new V;this.me=new pt(r)}extractCharacters(r){return this.me.ne(r)}filterProblematicCharacters(r){return this.me.fe(r)}characterExists(r,s){return this.me.le(r,s)}allCharactersExist(r,s){return this.me.ce(r,s)}}class mt{constructor(r){c(this,"ge");c(this,"_e");c(this,"ve");c(this,"xe");this.ve=r,this.xe=new V,this.ge=document.createElement("canvas"),this._e=this.ge.getContext("2d",{willReadFrequently:!0,alpha:!1})}createTextureAtlas(r,s,i,o){const n=r.length,a=Math.ceil(Math.sqrt(n)),h=Math.ceil(n/a),u=s.width*a,d=s.height*h,f=typeof o=="object"?o:null;this.be(u,d),this.we(r,s,a,i,f);const p=this.ve.Lt(u,d,{filter:"nearest"});return p.update(this.ge),{framebuffer:p,columns:a,rows:h}}be(r,s){this.ge.width=r,this.ge.height=s,this.ge.style.width=r+"px",this.ge.style.height=r+"px",this._e.imageSmoothingEnabled=!1,this.ge.style.imageRendering="pixelated",this._e.fillStyle="black",this._e.fillRect(0,0,r,s),this._e.textBaseline="top",this._e.textAlign="left",this._e.fillStyle="white"}we(r,s,i,o,n){const a=o/n.head.unitsPerEm;for(let h=0;h<r.length;h++){const u=h%i,d=Math.floor(h/i),f=r[h].character,p=this.Ce(n,f);if(!p)continue;const g=f.codePointAt(0)||0,x=this.xe.Zt(n,g),m=this.ye(n,x)*a,v=u*s.width,T=d*s.height,y=v+.5*s.width,_=T+.5*s.height,F=Math.round(y-.5*s.width),A=Math.round(_-.5*o),$=F+.5*(s.width-m),P=A+n.hhea.ascender*a;this.$e(p,$,P,a)}}Ce(r,s){const i=s.codePointAt(0)||0,o=this.xe.Zt(r,i);if(o===0)return null;if(r.glyf&&r.glyf[o]!==null)return r.glyf[o];if(R&&R.T&&R.T.glyf&&R.T.glyf.Wt){const n=R.T.glyf.Wt(r,o);return r.glyf&&n&&(r.glyf[o]=n),n}return null}ye(r,s){const i=r.hmtx;return i&&i.aWidth?s<i.aWidth.length?i.aWidth[s]:i.aWidth[i.aWidth.length-1]:0}$e(r,s,i,o){if(!r||!r.xs||r.noc===0)return;const{xs:n,ys:a,endPts:h,flags:u}=r;if(!(n&&a&&h&&u))return;this._e.beginPath();let d=0;for(let f=0;f<h.length;f++){const p=h[f];if(!(p<d)){if(p>=d){const g=s+n[d]*o,x=i-a[d]*o;this._e.moveTo(g,x);let m=d+1;for(;m<=p;)if(1&u[m]){const v=s+n[m]*o,T=i-a[m]*o;this._e.lineTo(v,T),m++}else{const v=s+n[m]*o,T=i-a[m]*o;let y=m+1>p?d:m+1;if(1&u[y]){const _=s+n[y]*o,F=i-a[y]*o;this._e.quadraticCurveTo(v,T,_,F),m=y+1}else{const _=(v+(s+n[y]*o))/2,F=(T+(i-a[y]*o))/2;this._e.quadraticCurveTo(v,T,_,F),m=y}}this._e.closePath()}d=p+1}}this._e.fill()}}class xt{constructor(){c(this,"oe");this.oe=new V}calculateMaxGlyphDimensions(r,s,i){let o=0;const n=this.oe.re(i,s),a=n.lineHeight;for(const h of r){const u=this.oe.ee(i,h);if(u===0)continue;const d=this.oe.se(i,u)*n.scale;o=Math.max(o,d)}return{width:Math.ceil(o),height:Math.ceil(a)}}getCharacterAdvanceWidth(r,s,i){const o=this.oe.re(i,s),n=this.oe.ee(i,r);return this.oe.se(i,n)*o.scale}getFontMetrics(r,s){return this.oe.re(s,r)}ie(){this.oe.ie()}}class bt{constructor(){c(this,"xe");this.xe=new V}createCharacterObjects(r,s){return r.map((i,o)=>{const n=i.codePointAt(0)||0,a=this.Fe(o);let h=0;if(s.hmtx&&s.hmtx.aWidth){const u=this.xe.Zt(s,n);u>0&&s.hmtx.aWidth[u]!==void 0&&(h=s.hmtx.aWidth[u])}return{character:i,unicode:n,color:a,advanceWidth:h}})}Fe(r){return[r%256,Math.floor(r/256)%256,Math.floor(r/65536)%256]}getCharacterColor(r,s){if(!C.m(typeof r=="string","Character must be a string.",{method:"getCharacterColor",providedValue:r}))return[0,0,0];const i=s.find(o=>o.character===r);return i?i.color:[0,0,0]}getCharacterColors(r,s){return C.m(typeof r=="string"&&r.length>0,"Characters must be a string with at least one character.",{method:"getCharacterColors",providedValue:r})?Array.from(r).map(i=>this.getCharacterColor(i,s)||[0,0,0]):[[0,0,0]]}}class K{constructor(r,s=16){c(this,"Te");c(this,"Me",[]);c(this,"Se");c(this,"De",16);c(this,"Re",0);c(this,"Ve",0);c(this,"ke",{width:0,height:0});c(this,"Ie");c(this,"Pe","UrsaFont");c(this,"ze");c(this,"Ee");c(this,"Ge");c(this,"Ae");this.De=s,this.ze=new vt,this.Ee=new mt(r),this.Ge=new xt,this.Ae=new bt}async Ue(r){let s;if(!r)throw new b("Embedded font not available. This appears to be a minified build - please provide `fontSource`.");{const i=await fetch(r);if(!i.ok)throw new b(`Failed to load font file: ${i.status} ${i.statusText}`);s=await i.arrayBuffer()}await this.Le(s),this.Te=R.parse(s)[0],await this.je()}He(r){if(r===void 0)return this.De;this.De=r,this.ke=this.Ge.calculateMaxGlyphDimensions(this.Me.map(i=>i.character),this.De,this.Te);const s=this.Ee.createTextureAtlas(this.Me,this.ke,this.De,this.Te);this.Se=s.framebuffer,this.Re=s.columns,this.Ve=s.rows}async Oe(r){try{const s=await fetch(r);if(!s.ok)throw new b(`Failed to load font file: ${s.status} ${s.statusText}`);const i=await s.arrayBuffer();await this.Le(i);const o=R.parse(i);if(!o||o.length===0)throw Error("Failed to parse font file");this.Te=o[0],await this.je()}catch(s){throw new b("Failed to load font: "+(s instanceof Error?s.message:"Unknown error"),s)}}async Le(r){const s=Date.now();this.Pe=this.Pe==="UrsaFont"?"UrsaFont":"CustomFont_"+s,this.Ie=new FontFace(this.Pe,r),await this.Ie.load(),document.fonts.add(this.Ie)}async je(){const r=this.ze.extractCharacters(this.Te),s=this.ze.filterProblematicCharacters(r);this.Me=this.Ae.createCharacterObjects(s,this.Te),this.ke=this.Ge.calculateMaxGlyphDimensions(s,this.De,this.Te);const i=this.Ee.createTextureAtlas(this.Me,this.ke,this.De,this.Te);this.Se=i.framebuffer,this.Re=i.columns,this.Ve=i.rows}getCharacterColor(r){return this.Ae.getCharacterColor(r,this.Me)}getCharacterColors(r){return this.Ae.getCharacterColors(r,this.Me)}hasAllCharacters(r){if(typeof r!="string"||r.length===0)return!1;const s=new Set(this.Me.map(i=>i.character));for(const i of r)if(!s.has(i))return!1;return!0}P(){this.Se.P(),document.fonts.delete(this.Ie)}get fontFramebuffer(){return this.Se}get characters(){return this.Me}get textureColumns(){return this.Re}get textureRows(){return this.Ve}get maxGlyphDimensions(){return this.ke}get fontSize(){return this.De}get font(){return this.Te}}class tt{constructor(r,s,i){c(this,"Be");c(this,"We");c(this,"F");c(this,"M");c(this,"Ne");c(this,"Xe");c(this,"qe",!1);c(this,"Ye");c(this,"Qe");c(this,"Ze");this.Ye=r,this.Qe=s,this.Ze=i,this.kt()}kt(){this.qe||(this.Be=Math.floor(this.Ye.width/this.Qe),this.We=Math.floor(this.Ye.height/this.Ze)),this.Je()}Je(){this.F=this.Be*this.Qe,this.M=this.We*this.Ze,this.Ne=Math.floor((this.Ye.width-this.F)/2),this.Xe=Math.floor((this.Ye.height-this.M)/2)}Ke(r,s){this.Qe=r,this.Ze=s,this.kt()}ts(r,s){this.qe=!0,this.Be=r,this.We=s,this.Je()}es(){this.qe=!1,this.kt()}ss(){this.qe?this.Je():this.kt()}rs(r){if(r===void 0)return this.qe;this.qe=r}get cellWidth(){return this.Qe}get cellHeight(){return this.Ze}get cols(){return this.Be}get rows(){return this.We}get width(){return this.F}get height(){return this.M}get offsetX(){return this.Ne}get offsetY(){return this.Xe}}class et{constructor(r,s=!1,i={}){c(this,"Ye");c(this,"ns");c(this,"hs");c(this,"ls");c(this,"onTransformChange");this.ns=r,this.hs=s,this.Ye=this.cs(i.width,i.height),s&&this.setupTransformObserver()}cs(r,s){var o;const i=document.createElement("canvas");if(i.className="textmodeCanvas",i.style.imageRendering="pixelated",this.hs)i.width=r||800,i.height=s||600,document.body.appendChild(i);else{const n=this.ns.getBoundingClientRect();let a=Math.round(n.width),h=Math.round(n.height);if(this.ns instanceof HTMLVideoElement){const f=this.ns;(a===0||h===0)&&f.videoWidth>0&&f.videoHeight>0&&(a=f.videoWidth,h=f.videoHeight)}i.width=a,i.height=h,i.style.position="absolute",i.style.pointerEvents="none";const u=window.getComputedStyle(this.ns);let d=parseInt(u.zIndex||"0",10);isNaN(d)&&(d=0),i.style.zIndex=""+(d+1),this.us(i),(o=this.ns.parentNode)==null||o.insertBefore(i,this.ns.nextSibling)}return i}us(r){const s=this.ns.getBoundingClientRect();let i=this.ns.offsetParent;if(i&&i!==document.body){const o=i.getBoundingClientRect();r.style.top=s.top-o.top+"px",r.style.left=s.left-o.left+"px"}else r.style.top=s.top+window.scrollY+"px",r.style.left=s.left+window.scrollX+"px"}ss(r,s){if(this.hs)this.Ye.width=r??this.Ye.width,this.Ye.height=s??this.Ye.height;else{const i=this.ns.getBoundingClientRect();let o=Math.round(i.width),n=Math.round(i.height);if(this.ns instanceof HTMLVideoElement){const a=this.ns;(o===0||n===0)&&a.videoWidth>0&&a.videoHeight>0&&(o=a.videoWidth,n=a.videoHeight)}this.Ye.width=o,this.Ye.height=n,this.us(this.Ye)}}fs(){const r={alpha:!1,premultipliedAlpha:!1,preserveDrawingBuffer:!0,antialias:!1,depth:!1,stencil:!1,powerPreference:"high-performance"},s=this.Ye.getContext("webgl2",r)||this.Ye.getContext("webgl",r);if(!s)throw new b("WebGL context could not be created. Ensure your browser supports WebGL.");return s}setupTransformObserver(){this.ls=new ResizeObserver(r=>{for(const s of r){const i=s.contentRect;!this.onTransformChange||Math.round(i.width)===this.Ye.width&&Math.round(i.height)===this.Ye.height||this.onTransformChange()}}),this.ls.observe(this.Ye)}P(){this.ls&&this.ls.disconnect();const r=this.Ye.getContext("webgl")||this.Ye.getContext("webgl2");if(r){const s=r.getExtension("WEBGL_lose_context");s&&s.loseContext()}this.Ye.parentNode&&this.Ye.parentNode.removeChild(this.Ye)}get canvas(){return this.Ye}get width(){return this.Ye.width}get height(){return this.Ye.height}}class U{constructor(r,s,i,o={}){c(this,"ve");c(this,"ds");c(this,"ps");c(this,"gs");c(this,"_s");c(this,"vs");c(this,"bs");c(this,"ws");c(this,"l");this.ve=r,this.ds=s,this.ps=i,this.l=o;const n=this.ps.cols,a=this.ps.rows;this.gs=this.ve.Lt(n,a),this._s=this.ve.Lt(n,a),this.vs=this.ve.Lt(n,a),this.bs=this.ve.Lt(n,a),this.ws=this.ve.Lt(n,a)}ss(){const r=this.ps.cols,s=this.ps.rows;this.gs.resize(r,s),this._s.resize(r,s),this.vs.resize(r,s),this.bs.resize(r,s),this.ws.resize(r,s)}enabled(r){C.m(typeof r=="boolean"||typeof r=="number"&&Number.isInteger(r),"Enabled must be a boolean value or an integer (0 for false, any other number for true).",{method:"enabled",providedValue:r})&&(this.l.enabled=!!r)}enable(){this.enabled(!0)}disable(){this.enabled(!1)}P(){this.gs.P(),this._s.P(),this.vs.P(),this.bs.P(),this.ws.P()}get characterFramebuffer(){return this.gs}get primaryColorFramebuffer(){return this._s}get secondaryColorFramebuffer(){return this.vs}get rotationFramebuffer(){return this.bs}get transformFramebuffer(){return this.ws}get options(){return this.l}}class rt{constructor(r,s){c(this,"C");c(this,"ve");c(this,"Cs");this.ve=r,this.Cs=s;const i=Math.max(this.Cs.length,1);this.C=this.ve.Lt(i,1),this.$s()}$s(){const r=this.Cs.length;this.C.width!==r&&this.C.resize(r,1);const s=new Uint8Array(1*r*4);for(let i=0;i<r;i++){const o=this.Cs[i],n=4*i;s[n]=o[0],s[n+1]=o[1],s[n+2]=o[2],s[n+3]=255}this.C.updatePixels(s,r,1)}setColors(r){this.Cs=r,this.$s()}get colors(){return this.Cs}get framebuffer(){return this.C}get texture(){return this.C.texture}}class z extends U{constructor(s,i,o,n={}){super(s,i,o,n);c(this,"Fs");this.Fs=new rt(this.ve,this.ds.getCharacterColors(" .:-=+*%@#"))}characters(s){C.m(this.ds.hasAllCharacters(s),"One or more characters do not exist in the current font.",{method:"characters",providedValue:s})&&(this.l.characters=s,this.Fs.setColors(this.ds.getCharacterColors(s)))}characterColor(s,i,o,n=255){const a=this.Ts(s,"characterColor",i,o,n);a&&(this.l.characterColor=a)}characterColorMode(s){this.Ms(s,"characterColorMode")}cellColor(s,i,o,n=255){const a=this.Ts(s,"cellColor",i,o,n);a&&(this.l.cellColor=a)}cellColorMode(s){this.Ms(s,"cellColorMode")}invert(s){this.Ss(s,"invert","Invert")}rotation(s){if(!C.m(typeof s=="number","Rotation angle must be a number.",{method:"rotation",providedValue:s}))return;(s%=360)<0&&(s+=360);const i=255*s/360,o=Math.floor(i)/255,n=Math.round(i-o);this.l.rotation=[o,n,0,1]}flipHorizontally(s){this.Ss(s,"flipHorizontally","Flip horizontally")}flipVertically(s){this.Ss(s,"flipVertically","Flip vertically")}Ts(s,i,o,n,a=255){let h,u,d,f;if(typeof s=="string"){const p=this.Ds(s);if(!p)return C.m(!1,"Invalid hex color format. Use '#FF0000', '#F00', 'FF0000', or 'F00'.",{method:i,providedValue:s}),null;[h,u,d,f]=p}else if(h=s,u=o!==void 0?o:s,d=n!==void 0?n:s,f=a,!C.m([h,u,d,f].every(p=>p>=0&&p<=255),i.charAt(0).toUpperCase()+i.slice(1)+" color values must be between 0 and 255",{method:i,providedValues:{r:h,g:u,b:d,a:f}}))return null;return[h/255,u/255,d/255,f/255]}Ms(s,i){C.m(["sampled","fixed"].includes(s),"Invalid color mode. Must be 'sampled' or 'fixed'.",{method:i,providedValue:s})&&(this.l[i]=s)}Ss(s,i,o){C.m(typeof s=="boolean"||typeof s=="number"&&Number.isInteger(s),o+" must be a boolean value or an integer (0 for false, any other number for true).",{method:i,providedValue:s})&&(this.l[i]=!!s)}Ds(s){return s=s.replace(/^#/,""),/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(s)?(s.length===3&&(s=s.split("").map(i=>i+i).join("")),[parseInt(s.slice(0,2),16),parseInt(s.slice(2,4),16),parseInt(s.slice(4,6),16),255]):null}}const L=`attribute vec2 a_position;\r
7
+ `,i}static o(r){if(r===null)return"null";if(r===void 0)return"undefined";if(typeof r=="string")return`"${r}"`;if(typeof r=="number"||typeof r=="boolean")return r+"";if(Array.isArray(r))return r.length===0?"[]":r.length<=5?`[${r.map(s=>v.o(s)).join(", ")}]`:`[${r.slice(0,3).map(s=>v.o(s)).join(", ")}, ... +${r.length-3} more]`;if(typeof r=="object"){const s=Object.keys(r);return s.length===0?"{}":s.length<=3?`{ ${s.map(i=>`${i}: ${v.o(r[i])}`).join(", ")} }`:`{ ${s.slice(0,2).map(i=>`${i}: ${v.o(r[i])}`).join(", ")}, ... +${s.length-2} more }`}return r+""}}var M=(l=>(l[l.SILENT=0]="SILENT",l[l.WARNING=1]="WARNING",l[l.ERROR=2]="ERROR",l[l.THROW=3]="THROW",l))(M||{});const D=class D{constructor(){c(this,"l",{globalLevel:3})}static u(){return D.h||(D.h=new D),D.h}p(r,s){const i="%c[textmode.js] Oops! (╯°□°)╯︵ Something went wrong in your code.",o="color: #f44336; font-weight: bold; background: #ffebee; padding: 2px 6px; border-radius: 3px;";switch(this.l.globalLevel){case 0:return!1;case 1:return console.group(i,o),console.warn(v.i(r,s)),console.groupEnd(),!1;case 2:return console.group(i,o),console.error(v.i(r,s)),console.groupEnd(),!1;default:throw new v(r,s)}}m(r,s,i){return!!r||(this.p(s,i),!1)}_(r){this.l.globalLevel=r}};c(D,"h",null);let z=D;const _=z.u(),Z=new WeakMap;function O(l,r){Z.set(l,r)}function Y(l){return Z.get(l)}class q{constructor(r,s=r,i={}){c(this,"v");c(this,"C");c(this,"l");c(this,"$",null);this.v=r,this.C=s,this.l={filter:"nearest",wrap:"clamp",format:"rgba",type:"unsigned_byte",...i}}get width(){return this.v}get height(){return this.C}get pixels(){return this.$}get options(){return{...this.l}}validateCoordinates(r,s,i=!0){return(r<0||s<0||r>=this.v||s>=this.C)&&i&&console.warn("The x and y values passed to Framebuffer.get are outside of its range and will be clamped."),[Math.max(0,Math.min(r,this.v-1)),Math.max(0,Math.min(s,this.C-1))]}validateRegion(r,s,i,o){return[r=Math.max(0,Math.min(r,this.v-1)),s=Math.max(0,Math.min(s,this.C-1)),i=Math.max(1,Math.min(i,this.v-r)),o=Math.max(1,Math.min(o,this.C-s))]}updateDimensions(r,s){this.v=r,this.C=s,this.$=null}}class K extends q{constructor(s,i,o=i,n={}){super(i,o,n);c(this,"F");c(this,"M");c(this,"S");c(this,"D",null);this.F=s,this.S=this.R(),this.M=s.createFramebuffer(),this.V()}I(s){const{F:i}=this,o=i.getParameter(i.FRAMEBUFFER_BINDING);i.bindFramebuffer(i.FRAMEBUFFER,this.M);try{return s()}finally{i.bindFramebuffer(i.FRAMEBUFFER,o)}}R(){const{F:s}=this,i=s.createTexture();s.bindTexture(s.TEXTURE_2D,i);const o=this.l.filter==="linear"?s.LINEAR:s.NEAREST,n=this.l.wrap==="repeat"?s.REPEAT:s.CLAMP_TO_EDGE;return s.texParameteri(s.TEXTURE_2D,s.TEXTURE_MIN_FILTER,o),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_MAG_FILTER,o),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_WRAP_S,n),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_WRAP_T,n),this.k(),i}k(){const{F:s}=this,i=this.l.type==="float"?s.FLOAT:s.UNSIGNED_BYTE;s.texImage2D(s.TEXTURE_2D,0,s.RGBA,this.v,this.C,0,s.RGBA,i,null)}V(){const{F:s}=this;s.bindFramebuffer(s.FRAMEBUFFER,this.M),s.framebufferTexture2D(s.FRAMEBUFFER,s.COLOR_ATTACHMENT0,s.TEXTURE_2D,this.S,0),s.bindFramebuffer(s.FRAMEBUFFER,null)}P(s){const{F:i}=this;i.bindTexture(i.TEXTURE_2D,this.S),i.pixelStorei(i.UNPACK_FLIP_Y_WEBGL,1),i.texImage2D(i.TEXTURE_2D,0,i.RGBA,i.RGBA,i.UNSIGNED_BYTE,s),i.bindTexture(i.TEXTURE_2D,null)}updatePixels(s,i,o){const{F:n}=this;n.bindTexture(n.TEXTURE_2D,this.S),n.texImage2D(n.TEXTURE_2D,0,n.RGBA,i,o,0,n.RGBA,n.UNSIGNED_BYTE,s),n.bindTexture(n.TEXTURE_2D,null)}resize(s,i){const{F:o}=this;this.updateDimensions(s,i),o.bindTexture(o.TEXTURE_2D,this.S),this.k(),o.bindTexture(o.TEXTURE_2D,null)}begin(){const{F:s}=this;this.D={framebuffer:s.getParameter(s.FRAMEBUFFER_BINDING),viewport:s.getParameter(s.VIEWPORT)},s.bindFramebuffer(s.FRAMEBUFFER,this.M),s.viewport(0,0,this.v,this.C),O(s,[0,0,this.v,this.C])}end(){if(!this.D)return;const{F:s}=this;s.bindFramebuffer(s.FRAMEBUFFER,this.D.framebuffer),s.viewport(...this.D.viewport),O(s,this.D.viewport),this.D=null}loadPixels(){const{F:s}=this;this.$||(this.$=new Uint8Array(this.v*this.C*4)),this.I(()=>{s.readPixels(0,0,this.v,this.C,s.RGBA,s.UNSIGNED_BYTE,this.$)})}get(s,i,o,n){const{F:a}=this;if(s===void 0&&i===void 0){const h=new Uint8Array(this.v*this.C*4);return this.I(()=>(a.readPixels(0,0,this.v,this.C,a.RGBA,a.UNSIGNED_BYTE,h),h))}if(o===void 0&&n===void 0){const[h,u]=this.validateCoordinates(s,i),d=new Uint8Array(4);return this.I(()=>(a.readPixels(h,u,1,1,a.RGBA,a.UNSIGNED_BYTE,d),[d[0],d[1],d[2],d[3]]))}{const[h,u,d,f]=this.validateRegion(s,i,o,n),p=new Uint8Array(d*f*4);return this.I(()=>(a.readPixels(h,u,d,f,a.RGBA,a.UNSIGNED_BYTE,p),p))}}A(){this.M&&this.F.deleteFramebuffer(this.M),this.S&&this.F.deleteTexture(this.S)}get framebuffer(){return this.M}get texture(){return this.S}}class Q{constructor(){c(this,"G",!1)}get isReady(){return this.G}setUniforms(r){for(const[s,i]of Object.entries(r))this.setUniform(s,i)}}class R extends Q{constructor(s,i,o){super();c(this,"F");c(this,"U");c(this,"L",new Map);c(this,"j",new Map);c(this,"O",0);c(this,"H");this.F=s,this.U=this.W(i,o),this.H=s.getParameter(s.MAX_TEXTURE_IMAGE_UNITS),this.N(),this.G=!0}static fromSource(s,i){return new R(s,i.vertex,i.fragment)}N(){const s=this.F.getProgramParameter(this.U,this.F.ACTIVE_UNIFORMS);for(let i=0;i<s;i++){const o=this.F.getActiveUniform(this.U,i);if(o){const n=this.F.getUniformLocation(this.U,o.name);n&&(this.L.set(o.name,n),this.j.set(o.name,o.type))}}}W(s,i){const o=this.X(this.F.VERTEX_SHADER,s),n=this.X(this.F.FRAGMENT_SHADER,i),a=this.F.createProgram();if(this.F.attachShader(a,o),this.F.attachShader(a,n),this.F.linkProgram(a),!this.F.getProgramParameter(a,this.F.LINK_STATUS)){const h=this.F.getProgramInfoLog(a);throw Error("Shader program link error: "+h)}return this.F.deleteShader(o),this.F.deleteShader(n),a}X(s,i){const o=this.F.createShader(s);if(this.F.shaderSource(o,i),this.F.compileShader(o),!this.F.getShaderParameter(o,this.F.COMPILE_STATUS)){const n=this.F.getShaderInfoLog(o);throw this.F.deleteShader(o),Error("Shader compilation error: "+n)}return o}q(){this.F.useProgram(this.U),this.Y()}Y(){this.O=0}setUniform(s,i){const o=this.L.get(s);if(o)if(typeof i=="number")this.Z(s)?this.F.uniform1i(o,Math.floor(i)):this.F.uniform1f(o,i);else if(typeof i=="boolean")this.F.uniform1i(o,i?1:0);else if(Array.isArray(i))switch(i.length){case 2:this.F.uniform2f(o,i[0],i[1]);break;case 3:this.F.uniform3f(o,i[0],i[1],i[2]);break;case 4:this.F.uniform4f(o,i[0],i[1],i[2],i[3]);break;default:console.warn(`Unsupported array length ${i.length} for uniform '${s}'`)}else if(i instanceof WebGLTexture){const n=this.J();this.F.uniform1i(o,n),this.F.activeTexture(this.F.TEXTURE0+n),this.F.bindTexture(this.F.TEXTURE_2D,i)}else if(i instanceof K){const n=this.J();this.F.uniform1i(o,n),this.F.activeTexture(this.F.TEXTURE0+n),this.F.bindTexture(this.F.TEXTURE_2D,i.texture)}else if(typeof i=="object"&&"texture"in i){const n=this.J();this.F.uniform1i(o,n),this.F.activeTexture(this.F.TEXTURE0+n),this.F.bindTexture(this.F.TEXTURE_2D,i.texture)}else console.warn(`Unsupported uniform type for '${s}':`,typeof i)}J(){return this.O>=this.H&&console.warn(`Exceeded maximum texture units (${this.H}). Texture may not render correctly.`),this.O++}Z(s){const i=this.j.get(s);return!!i&&(i===this.F.INT||i===this.F.INT_VEC2||i===this.F.INT_VEC3||i===this.F.INT_VEC4||i===this.F.SAMPLER_2D||i===this.F.SAMPLER_CUBE)}get glProgram(){return this.U}A(){this.F.deleteProgram(this.U)}}class J{constructor(r){c(this,"F");c(this,"K",null);c(this,"tt",16);c(this,"et",new Map);this.F=r}st(){if(this.K)return;const r=this.F;this.K=r.createBuffer(),r.bindBuffer(r.ARRAY_BUFFER,this.K)}rt(){const r=this.F,s=r.getParameter(r.CURRENT_PROGRAM);let i=this.et.get(s);return i||(i={a_position:r.getAttribLocation(s,"a_position"),a_texCoord:r.getAttribLocation(s,"a_texCoord")},this.et.set(s,i)),r.enableVertexAttribArray(i.a_position),r.vertexAttribPointer(i.a_position,2,r.FLOAT,!1,this.tt,0),r.enableVertexAttribArray(i.a_texCoord),r.vertexAttribPointer(i.a_texCoord,2,r.FLOAT,!1,this.tt,8),{positionLoc:i.a_position,texLoc:i.a_texCoord}}it(r,s){const i=this.F;i.disableVertexAttribArray(r),i.disableVertexAttribArray(s)}ot(r,s){const i=this.F,o=Y(i)||[0,0,i.canvas.width,i.canvas.height];return{nx:r/o[2]*2-1,ny:1-s/o[3]*2}}nt(r,s,i,o){const n=this.F;this.st(),n.bindBuffer(n.ARRAY_BUFFER,this.K);const a=new Float32Array([r,o,0,0,i,o,1,0,r,s,0,1,r,s,0,1,i,o,1,0,i,s,1,1]);n.bufferData(n.ARRAY_BUFFER,a,n.DYNAMIC_DRAW)}A(){this.K&&this.F.deleteBuffer(this.K)}}class ut extends J{constructor(r){super(r)}ht(r,s,i,o){const n=this.ot(r,s),a=this.ot(r+i,s+o);this.nt(n.nx,n.ny,a.nx,a.ny);const h=this.rt();this.F.drawArrays(this.F.TRIANGLES,0,6),this.it(h.positionLoc,h.texLoc)}lt(r,s,i,o,n){this.ht(r,s,i,n),this.ht(r+i-n,s,n,o),this.ht(r,s+o-n,i,n),this.ht(r,s,n,o)}}class dt extends J{constructor(r){super(r)}ct(r,s,i,o,n){const a=i-r,h=o-s,u=Math.hypot(a,h);if(u===0){const f=n/2,p=this.ot(r-f,s-f),g=this.ot(r+f,s+f);this.nt(p.nx,p.ny,g.nx,g.ny)}else{const f=-h/u,p=a/u,g=n/2,x=r+f*g,b=s+p*g,m=r-f*g,y=s-p*g,C=i+f*g,F=o+p*g,E=i-f*g,S=o-p*g,$=this.ot(x,b),U=this.ot(m,y),G=this.ot(C,F),ct=this.ot(E,S),B=this.F;this.st(),B.bindBuffer(B.ARRAY_BUFFER,this.K);const Xt=new Float32Array([$.nx,$.ny,0,0,U.nx,U.ny,0,1,G.nx,G.ny,1,0,U.nx,U.ny,0,1,ct.nx,ct.ny,1,1,G.nx,G.ny,1,0]);B.bufferData(B.ARRAY_BUFFER,Xt,B.DYNAMIC_DRAW)}const d=this.rt();this.F.drawArrays(this.F.TRIANGLES,0,6),this.it(d.positionLoc,d.texLoc)}}var L="attribute vec2 a_position;attribute vec2 a_texCoord;varying vec2 v_uv;uniform float u_rotation;uniform vec2 u_center;uniform float u_aspectRatio;mat2 rotate2D(float angle){float s=sin(angle);float c=cos(angle);return mat2(c,-s,s,c);}void main(){v_uv=a_texCoord;vec2 pos=a_position;pos-=u_center;pos.x*=u_aspectRatio;pos=rotate2D(-u_rotation)*pos;pos.x/=u_aspectRatio;pos+=u_center;gl_Position=vec4(pos,0.0,1.0);}";class ft{constructor(r){c(this,"F");c(this,"ut");c(this,"ft");c(this,"dt",null);c(this,"gt");c(this,"_t");c(this,"vt",[1,1,1,1]);c(this,"xt",!0);c(this,"bt",[0,0,0,1]);c(this,"wt",1);c(this,"Ct",!0);c(this,"yt",0);c(this,"$t",[]);this.F=r,this.ut=new R(this.F,L,"precision lowp float;uniform sampler2D u_texture;varying vec2 v_uv;void main(){gl_FragColor=texture2D(u_texture,v_uv);}"),this.ft=new R(this.F,L,"precision lowp float;uniform vec4 u_color;void main(){gl_FragColor=u_color;}"),this.gt=new ut(this.F),this._t=new dt(this.F),this.F.enable(this.F.BLEND),this.F.blendEquation(this.F.FUNC_ADD),this.F.blendFunc(this.F.ONE,this.F.ONE_MINUS_SRC_ALPHA),O(this.F,[0,0,this.F.canvas.width,this.F.canvas.height])}Ft(r){this.dt!==r&&(this.dt=r,r.q())}Tt(r,s,i,o){if(this.xt=!0,s===void 0&&i===void 0&&o===void 0){const n=r/255;this.vt=[n,n,n,1]}else if(i!==void 0&&o===void 0)this.vt=[r/255,s/255,i/255,1];else{if(i===void 0||o===void 0)throw Error("Invalid fill parameters. Use fill(gray), fill(r,g,b), or fill(r,g,b,a)");this.vt=[r/255,s/255,i/255,o/255]}}Mt(r,s,i,o){if(this.Ct=!0,s===void 0&&i===void 0&&o===void 0){const n=r/255;this.bt=[n,n,n,1]}else if(i!==void 0&&o===void 0)this.bt=[r/255,s/255,i/255,1];else{if(i===void 0||o===void 0)throw Error("Invalid stroke parameters. Use stroke(gray), stroke(r,g,b), or stroke(r,g,b,a)");this.bt=[r/255,s/255,i/255,o/255]}}St(r){if(r<0)throw Error("Stroke weight must be non-negative");this.wt=r}Dt(){this.Ct=!1}Rt(){this.xt=!1}Vt(r){this.yt=r}It(){this.$t.push({fillColor:[...this.vt],fillMode:this.xt,strokeColor:[...this.bt],strokeWeight:this.wt,strokeMode:this.Ct,rotation:this.yt})}kt(){const r=this.$t.pop();r?(this.vt=r.fillColor,this.xt=r.fillMode,this.bt=r.strokeColor,this.wt=r.strokeWeight,this.Ct=r.strokeMode,this.yt=r.rotation):console.warn("pop() called without matching push()")}Et(){this.dt=null,this.$t=[],this.yt=0}Pt(r){const s=r.replace(/\/\*[\s\S]*?\*\//g,"").replace(/\/\/.*$/gm,"").trim().match(/^#version\s+(\d+)\s+(es)?/i);return!!s&&parseInt(s[1],10)>=300}At(r,s){return new R(this.F,r,s)}zt(r){const s=this.Pt(r)?`#version 300 es
8
+ in vec2 a_position;in vec2 a_texCoord;out vec2 v_uv;uniform float u_rotation;uniform vec2 u_center;uniform float u_aspectRatio;mat2 rotate2D(float angle){float s=sin(angle);float c=cos(angle);return mat2(c,-s,s,c);}void main(){v_uv=a_texCoord;vec2 pos=a_position;pos-=u_center;pos.x*=u_aspectRatio;pos=rotate2D(-u_rotation)*pos;pos.x/=u_aspectRatio;pos+=u_center;gl_Position=vec4(pos,0.0,1.0);}`:L;return new R(this.F,s,r)}Gt(r,s){this.dt.setUniform(r,s)}Ut(r,s,i,o){if(this.dt!==null){const{centerX:p,centerY:g,radians:x,aspectRatio:b}=this.Lt(r,s,i,o);return this.Gt("u_rotation",x),this.Gt("u_center",[p,g]),this.Gt("u_aspectRatio",b),this.gt.ht(r,s,i,o),void(this.dt=null)}const n=this.ft;let a=0,h=0,u=0,d=1;const f=this.Lt(r,s,i,o);a=f.centerX,h=f.centerY,u=f.radians,d=f.aspectRatio,this.xt&&(this.Ft(n),this.Gt("u_color",this.vt),this.Gt("u_rotation",u),this.Gt("u_center",[a,h]),this.Gt("u_aspectRatio",d),this.gt.ht(r,s,i,o)),this.Ct&&this.wt>0&&(this.Ft(n),this.Gt("u_color",this.bt),this.Gt("u_rotation",u),this.Gt("u_center",[a,h]),this.Gt("u_aspectRatio",d),this.gt.lt(r,s,i,o,this.wt)),this.dt=null}jt(r,s,i,o){if(this.dt!==null){const m=(r+i)/2,y=(s+o)/2,C=Math.abs(i-r)||1,F=Math.abs(o-s)||1,{centerX:E,centerY:S,radians:$,aspectRatio:U}=this.Lt(m-C/2,y-F/2,C,F);this.Gt("u_rotation",$),this.Gt("u_center",[E,S]),this.Gt("u_aspectRatio",U);const G=this.wt>0?this.wt:1;return this._t.ct(r,s,i,o,G),void(this.dt=null)}if(!this.Ct||this.wt<=0)return;const n=this.ft,a=(r+i)/2,h=(s+o)/2,u=Math.abs(i-r)||1,d=Math.abs(o-s)||1,f=this.yt!==0;let p=0,g=0,x=0,b=1;if(f){const m=this.Lt(a-u/2,h-d/2,u,d);p=m.centerX,g=m.centerY,x=m.radians,b=m.aspectRatio}this.Ft(n),this.Gt("u_color",this.bt),f&&(this.Gt("u_rotation",x),this.Gt("u_center",[p,g]),this.Gt("u_aspectRatio",b)),this._t.ct(r,s,i,o,this.wt)}Lt(r,s,i,o){const n=Y(this.F)||[0,0,this.F.canvas.width,this.F.canvas.height],a=n[2],h=n[3],u=a/h;return{centerX:(r+i/2)/a*2-1,centerY:1-(s+o/2)/h*2,radians:this.yt*Math.PI/180,aspectRatio:u}}Ot(r,s,i={}){return new K(this.F,r,s,i)}Ht(r,s=r,i=r,o=255){this.Bt(r/255,s/255,i/255,o/255)}Bt(r=0,s=0,i=0,o=0){this.F.clearColor(r,s,i,o),this.F.clear(this.F.COLOR_BUFFER_BIT)}Wt(){this.F.viewport(0,0,this.F.canvas.width,this.F.canvas.height),O(this.F,[0,0,this.F.canvas.width,this.F.canvas.height])}get context(){return this.F}A(){this.ut.A(),this.ft.A(),this.gt.A(),this._t.A()}Nt(r,s,i,o,n){const a=this.F,h=o??r.width,u=n??r.height;this.Ft(this.ut),this.Gt("u_texture",r);const d=this.Lt(s,i,h,u);this.Gt("u_rotation",d.radians),this.Gt("u_center",[d.centerX,d.centerY]),this.Gt("u_aspectRatio",d.aspectRatio),this.gt.ht(s,i,h,u),a.bindTexture(a.TEXTURE_2D,null),this.dt=null}}const T={readShort:(l,r)=>(T.t.uint16[0]=l[r]<<8|l[r+1],T.t.int16[0]),readUshort:(l,r)=>l[r]<<8|l[r+1],readUshorts(l,r,s){const i=[];for(let o=0;o<s;o++)i.push(T.readUshort(l,r+2*o));return i},readUint(l,r){const s=T.t.uint8;return s[3]=l[r],s[2]=l[r+1],s[1]=l[r+2],s[0]=l[r+3],T.t.uint32[0]},readASCII(l,r,s){let i="";for(let o=0;o<s;o++)i+=String.fromCharCode(l[r+o]);return i},t:(()=>{const l=new ArrayBuffer(8);return{uint8:new Uint8Array(l),int16:new Int16Array(l),uint16:new Uint16Array(l),uint32:new Uint32Array(l)}})()},gt={parseTab(l,r,s){const i={tables:[],ids:{},off:r};l=new Uint8Array(l.buffer,r,s),r=0;const o=T,n=o.readUshort,a=n(l,r+=2);r+=2;const h=[];for(let u=0;u<a;u++){const d=n(l,r),f=n(l,r+=2);r+=2;const p=o.readUint(l,r);r+=4;const g=`p${d}e${f}`;let x=h.indexOf(p);if(x===-1){let b;x=i.tables.length,h.push(p);const m=n(l,p);b=m===4?this.parse4(l,p):m===12?this.parse12(l,p):{format:m},i.tables.push(b)}i.ids[g]!=null&&console.warn("Multiple tables for one platform+encoding: "+g),i.ids[g]=x}return i},parse4(l,r){const s=T,i=s.readUshort,o=s.readUshorts,n=r,a=i(l,r+=2);r+=2;const h=i(l,r+=2)>>>1,u={format:4,searchRange:i(l,r+=2),entrySelector:0,rangeShift:0,endCount:[],startCount:[],idDelta:[],idRangeOffset:[],glyphIdArray:[]};r+=2,u.entrySelector=i(l,r),r+=2,u.rangeShift=i(l,r),r+=2,u.endCount=o(l,r,h),r+=2*h,r+=2,u.startCount=o(l,r,h),r+=2*h;for(let d=0;d<h;d++)u.idDelta.push(s.readShort(l,r)),r+=2;return u.idRangeOffset=o(l,r,h),r+=2*h,u.glyphIdArray=o(l,r,n+a-r>>1),u},parse12(l,r){const s=T.readUint;s(l,r+=4),s(l,r+=4);const i=s(l,r+=4);r+=4;const o=new Uint32Array(3*i);for(let n=0;n<3*i;n+=3)o[n]=s(l,r+(n<<2)),o[n+1]=s(l,r+(n<<2)+4),o[n+2]=s(l,r+(n<<2)+8);return{format:12,groups:o}}},pt={parseTab(l,r,s){const i=T;r+=18;const o=i.readUshort(l,r);r+=2,r+=16;const n=i.readShort(l,r);r+=2;const a=i.readShort(l,r);r+=2;const h=i.readShort(l,r);r+=2;const u=i.readShort(l,r);return r+=2,r+=6,{unitsPerEm:o,xMin:n,yMin:a,xMax:h,yMax:u,indexToLocFormat:i.readShort(l,r)}}},mt={parseTab(l,r,s){const i=T;r+=4;const o=["ascender","descender","lineGap","advanceWidthMax","minLeftSideBearing","minRightSideBearing","xMaxExtent","caretSlopeRise","caretSlopeRun","caretOffset","res0","res1","res2","res3","metricDataFormat","numberOfHMetrics"],n={};for(let a=0;a<o.length;a++){const h=o[a],u=h==="advanceWidthMax"||h==="numberOfHMetrics"?i.readUshort:i.readShort;n[h]=u(l,r+2*a)}return n}},bt={parseTab(l,r,s,i){if(!i)throw Error("Font object required for hmtx parsing");const o=T,n=[],a=[],h=i.maxp.numGlyphs,u=i.hhea.numberOfHMetrics;let d=0,f=0,p=0;for(;p<u;)d=o.readUshort(l,r+(p<<2)),f=o.readShort(l,r+(p<<2)+2),n.push(d),a.push(f),p++;for(;p<h;)n.push(d),a.push(f),p++;return{aWidth:n,lsBearing:a}}},tt={cmap:gt,head:pt,hhea:mt,maxp:{parseTab(l,r,s){const i=T;return i.readUint(l,r),r+=4,{numGlyphs:i.readUshort(l,r)}}},hmtx:bt,loca:{parseTab(l,r,s,i){if(!i)throw Error("Font object required for loca parsing");const o=T,n=[],a=i.head.indexToLocFormat,h=i.maxp.numGlyphs+1;if(a===0)for(let u=0;u<h;u++)n.push(o.readUshort(l,r+(u<<1))<<1);else if(a===1)for(let u=0;u<h;u++)n.push(o.readUint(l,r+(u<<2)));return n}},glyf:{parseTab(l,r,s,i){if(!i)throw Error("Font object required for glyf parsing");const o=[],n=i.maxp.numGlyphs;for(let a=0;a<n;a++)o.push(null);return o},Xt(l,r){const s=T,i=l.qt,o=l.loca;if(o[r]===o[r+1])return null;const n=A.findTable(i,"glyf",l.Yt);if(!n)return null;let a=n[0]+o[r];const h={};if(h.noc=s.readShort(i,a),a+=2,h.xMin=s.readShort(i,a),a+=2,h.yMin=s.readShort(i,a),a+=2,h.xMax=s.readShort(i,a),a+=2,h.yMax=s.readShort(i,a),a+=2,h.xMin>=h.xMax||h.yMin>=h.yMax)return null;if(h.noc>0){h.endPts=[];for(let g=0;g<h.noc;g++)h.endPts.push(s.readUshort(i,a)),a+=2;const u=s.readUshort(i,a);if(a+=2,i.length-a<u)return null;a+=u;const d=h.endPts[h.noc-1]+1;h.flags=[];for(let g=0;g<d;g++){const x=i[a];if(a++,h.flags.push(x),8&x){const b=i[a];a++;for(let m=0;m<b;m++)h.flags.push(x),g++}}h.xs=[];for(let g=0;g<d;g++){const x=h.flags[g],b=!!(16&x);2&x?(h.xs.push(b?i[a]:-i[a]),a++):b?h.xs.push(0):(h.xs.push(s.readShort(i,a)),a+=2)}h.ys=[];for(let g=0;g<d;g++){const x=h.flags[g],b=!!(32&x);4&x?(h.ys.push(b?i[a]:-i[a]),a++):b?h.ys.push(0):(h.ys.push(s.readShort(i,a)),a+=2)}let f=0,p=0;for(let g=0;g<d;g++)f+=h.xs[g],p+=h.ys[g],h.xs[g]=f,h.ys[g]=p}else h.parts=[],h.endPts=[],h.flags=[],h.xs=[],h.ys=[];return h}}},A={parse:l=>[((r,s,i,o)=>{const n=tt,a={qt:r,Qt:s,Yt:i};for(const h in n){const u=h,d=A.findTable(r,u,i);if(d){const[f,p]=d;let g=o[f];g==null&&(g=n[u].parseTab(r,f,p,a),o[f]=g),a[u]=g}}return a})(new Uint8Array(l),0,0,{})],findTable(l,r,s){const i=T,o=i.readUshort(l,s+4);let n=s+12;for(let a=0;a<o;a++){const h=i.readASCII(l,n,4);i.readUint(l,n+4);const u=i.readUint(l,n+8),d=i.readUint(l,n+12);if(h===r)return[u,d];n+=16}return null},T:tt,B:T};class k{constructor(){c(this,"Zt",new Map);c(this,"Jt",new Map)}Kt(r,s){const i=`${this.te(r)}_${s}`;if(this.Zt.has(i))return this.Zt.get(i);const o=r.cmap;if(!o||!o.tables)return this.Zt.set(i,0),0;let n=0;for(const a of o.tables)if(a.format===4?n=this.ee(s,a):a.format===12&&(n=this.se(s,a)),n>0)break;return this.Zt.set(i,n),n}re(r,s){const i=s.codePointAt(0);return i===void 0?0:this.Kt(r,i)}ie(r,s){const i=r.hmtx;return i&&i.aWidth&&i.aWidth.length!==0?s<i.aWidth.length?i.aWidth[s]:i.aWidth[i.aWidth.length-1]:0}oe(r,s){const i=s/r.head.unitsPerEm,o=r.hhea.ascender*i,n=r.hhea.descender*i,a=r.hhea.lineGap*i;return{ascender:o,descender:n,lineGap:a,lineHeight:o-n+a,unitsPerEm:r.head.unitsPerEm,scale:i}}ne(){this.Zt.clear(),this.Jt.clear()}te(r){return`${r.Yt}_${r.qt.length}`}ee(r,s){const i=s.endCount.length;let o=-1;for(let n=0;n<i;n++)if(r<=s.endCount[n]){o=n;break}if(o===-1||r<s.startCount[o])return 0;if(s.idRangeOffset[o]===0)return r+s.idDelta[o]&65535;{const n=s.idRangeOffset[o]/2+(r-s.startCount[o])-(i-o);if(n>=0&&n<s.glyphIdArray.length){const a=s.glyphIdArray[n];return a===0?0:a+s.idDelta[o]&65535}}return 0}se(r,s){const i=s.groups.length/3;for(let o=0;o<i;o++){const n=s.groups[3*o],a=s.groups[3*o+1],h=s.groups[3*o+2];if(r>=n&&r<=a)return h+(r-n)}return 0}}class xt{constructor(r){c(this,"ae");this.ae=r}he(r){var i;const s=[];return(i=r==null?void 0:r.cmap)!=null&&i.tables?(r.cmap.tables.forEach(o=>{if(o.format===4){const n=this.le(o);s.push(...n)}else if(o.format===12){const n=this.ce(o);s.push(...n)}}),[...new Set(s)]):[]}ue(r,s){return this.ae.re(r,s)>0}fe(r,s){for(const i of s)if(!this.ue(r,i))return!1;return!0}de(r,s){return s.filter(i=>this.ue(r,i))}pe(r){return r.filter(s=>this.me(s))}le(r){const s=[];if(!(r.startCount&&r.endCount&&r.idRangeOffset&&r.idDelta))return s;for(let i=0;i<r.startCount.length;i++){const o=r.startCount[i],n=r.endCount[i];if(o!==65535||n!==65535){for(let a=o;a<=n;a++)if(this.ge(r,a,i)>0)try{const h=String.fromCodePoint(a);s.push(h)}catch{}}}return s}ce(r){const s=[];if(!r.groups)return s;for(let i=0;i<r.groups.length;i+=3){const o=r.groups[i],n=r.groups[i+1],a=r.groups[i+2];for(let h=o;h<=n;h++)if(a+(h-o)>0)try{const u=String.fromCodePoint(h);s.push(u)}catch{}}return s}ge(r,s,i){if(r.idRangeOffset[i]===0)return s+r.idDelta[i]&65535;{const o=r.idRangeOffset[i]/2+(s-r.startCount[i])-(r.startCount.length-i);if(o>=0&&r.glyphIdArray&&o<r.glyphIdArray.length){const n=r.glyphIdArray[o];if(n!==0)return n+r.idDelta[i]&65535}}return 0}me(r){const s=r.codePointAt(0)||0;return!(s>=0&&s<=31&&s!==9&&s!==10&&s!==13||s>=127&&s<=159)}}class vt{constructor(){c(this,"_e");const r=new k;this._e=new xt(r)}extractCharacters(r){return this._e.he(r)}filterProblematicCharacters(r){return this._e.pe(r)}characterExists(r,s){return this._e.ue(r,s)}allCharactersExist(r,s){return this._e.fe(r,s)}}class wt{constructor(r){c(this,"ve");c(this,"xe");c(this,"be");c(this,"we");this.be=r,this.we=new k,this.ve=document.createElement("canvas"),this.xe=this.ve.getContext("2d",{willReadFrequently:!0,alpha:!1})}createTextureAtlas(r,s,i,o){const n=r.length,a=Math.ceil(Math.sqrt(n)),h=Math.ceil(n/a),u=s.width*a,d=s.height*h,f=typeof o=="object"?o:null;this.Ce(u,d),this.ye(r,s,a,i,f);const p=this.be.Ot(u,d,{filter:"nearest"});return p.P(this.ve),{framebuffer:p,columns:a,rows:h}}Ce(r,s){this.ve.width=r,this.ve.height=s,this.ve.style.width=r+"px",this.ve.style.height=r+"px",this.xe.imageSmoothingEnabled=!1,this.ve.style.imageRendering="pixelated",this.xe.fillStyle="black",this.xe.fillRect(0,0,r,s),this.xe.textBaseline="top",this.xe.textAlign="left",this.xe.fillStyle="white"}ye(r,s,i,o,n){const a=o/n.head.unitsPerEm;for(let h=0;h<r.length;h++){const u=h%i,d=Math.floor(h/i),f=r[h].character,p=this.$e(n,f);if(!p)continue;const g=f.codePointAt(0)||0,x=this.we.Kt(n,g),b=this.Fe(n,x)*a,m=u*s.width,y=d*s.height,C=m+.5*s.width,F=y+.5*s.height,E=Math.round(C-.5*s.width),S=Math.round(F-.5*o),$=E+.5*(s.width-b),U=S+n.hhea.ascender*a;this.Te(p,$,U,a)}}$e(r,s){const i=s.codePointAt(0)||0,o=this.we.Kt(r,i);if(o===0)return null;if(r.glyf&&r.glyf[o]!==null)return r.glyf[o];if(A&&A.T&&A.T.glyf){const n=A.T.glyf.Xt(r,o);return r.glyf&&n&&(r.glyf[o]=n),n}return null}Fe(r,s){const i=r.hmtx;return i&&i.aWidth?s<i.aWidth.length?i.aWidth[s]:i.aWidth[i.aWidth.length-1]:0}Te(r,s,i,o){if(!r||!r.xs||r.noc===0)return;const{xs:n,ys:a,endPts:h,flags:u}=r;if(!(n&&a&&h&&u))return;this.xe.beginPath();let d=0;for(let f=0;f<h.length;f++){const p=h[f];if(!(p<d)){if(p>=d){const g=s+n[d]*o,x=i-a[d]*o;this.xe.moveTo(g,x);let b=d+1;for(;b<=p;)if(1&u[b]){const m=s+n[b]*o,y=i-a[b]*o;this.xe.lineTo(m,y),b++}else{const m=s+n[b]*o,y=i-a[b]*o;let C=b+1>p?d:b+1;if(1&u[C]){const F=s+n[C]*o,E=i-a[C]*o;this.xe.quadraticCurveTo(m,y,F,E),b=C+1}else{const F=(m+(s+n[C]*o))/2,E=(y+(i-a[C]*o))/2;this.xe.quadraticCurveTo(m,y,F,E),b=C}}this.xe.closePath()}d=p+1}}this.xe.fill()}}class _t{constructor(){c(this,"ae");this.ae=new k}calculateMaxGlyphDimensions(r,s,i){let o=0;const n=this.ae.oe(i,s),a=n.lineHeight;for(const h of r){const u=this.ae.re(i,h);if(u===0)continue;const d=this.ae.ie(i,u)*n.scale;o=Math.max(o,d)}return{width:Math.ceil(o),height:Math.ceil(a)}}getCharacterAdvanceWidth(r,s,i){const o=this.ae.oe(i,s),n=this.ae.re(i,r);return this.ae.ie(i,n)*o.scale}getFontMetrics(r,s){return this.ae.oe(s,r)}ne(){this.ae.ne()}}class Ct{constructor(){c(this,"we");this.we=new k}createCharacterObjects(r,s){return r.map((i,o)=>{const n=i.codePointAt(0)||0,a=this.Me(o);let h=0;if(s.hmtx&&s.hmtx.aWidth){const u=this.we.Kt(s,n);u>0&&s.hmtx.aWidth[u]!==void 0&&(h=s.hmtx.aWidth[u])}return{character:i,unicode:n,color:a,advanceWidth:h}})}Me(r){return[r%256,Math.floor(r/256)%256,Math.floor(r/65536)%256]}getCharacterColor(r,s){if(!_.m(typeof r=="string","Character must be a string.",{method:"getCharacterColor",providedValue:r}))return[0,0,0];const i=s.find(o=>o.character===r);return i?i.color:[0,0,0]}getCharacterColors(r,s){return _.m(typeof r=="string"&&r.length>0,"Characters must be a string with at least one character.",{method:"getCharacterColors",providedValue:r})?Array.from(r).map(i=>this.getCharacterColor(i,s)||[0,0,0]):[[0,0,0]]}}class et{constructor(r,s=16){c(this,"Se");c(this,"De",[]);c(this,"Re");c(this,"Ve",16);c(this,"Ie",0);c(this,"ke",0);c(this,"Ee",{width:0,height:0});c(this,"Pe");c(this,"Ae","UrsaFont");c(this,"ze");c(this,"Ge");c(this,"Ue");c(this,"Le");this.Ve=s,this.ze=new vt,this.Ge=new wt(r),this.Ue=new _t,this.Le=new Ct}async je(r){let s;if(!r)throw new v("Embedded font not available. This appears to be a minified build - please provide `fontSource`.");{const i=await fetch(r);if(!i.ok)throw new v(`Failed to load font file: ${i.status} ${i.statusText}`);s=await i.arrayBuffer()}await this.Oe(s),this.Se=A.parse(s)[0],await this.He()}Be(r){if(r===void 0)return this.Ve;this.Ve=r,this.Ee=this.Ue.calculateMaxGlyphDimensions(this.De.map(i=>i.character),this.Ve,this.Se);const s=this.Ge.createTextureAtlas(this.De,this.Ee,this.Ve,this.Se);this.Re=s.framebuffer,this.Ie=s.columns,this.ke=s.rows}async We(r){try{const s=await fetch(r);if(!s.ok)throw new v(`Failed to load font file: ${s.status} ${s.statusText}`);const i=await s.arrayBuffer();await this.Oe(i);const o=A.parse(i);if(!o||o.length===0)throw Error("Failed to parse font file");this.Se=o[0],await this.He()}catch(s){throw new v("Failed to load font: "+(s instanceof Error?s.message:"Unknown error"),s)}}async Oe(r){const s=Date.now();this.Ae=this.Ae==="UrsaFont"?"UrsaFont":"CustomFont_"+s,this.Pe=new FontFace(this.Ae,r),await this.Pe.load(),document.fonts.add(this.Pe)}async He(){const r=this.ze.extractCharacters(this.Se),s=this.ze.filterProblematicCharacters(r);this.De=this.Le.createCharacterObjects(s,this.Se),this.Ee=this.Ue.calculateMaxGlyphDimensions(s,this.Ve,this.Se);const i=this.Ge.createTextureAtlas(this.De,this.Ee,this.Ve,this.Se);this.Re=i.framebuffer,this.Ie=i.columns,this.ke=i.rows}getCharacterColor(r){return this.Le.getCharacterColor(r,this.De)}getCharacterColors(r){return this.Le.getCharacterColors(r,this.De)}hasAllCharacters(r){if(typeof r!="string"||r.length===0)return!1;const s=new Set(this.De.map(i=>i.character));for(const i of r)if(!s.has(i))return!1;return!0}A(){this.Re.A(),document.fonts.delete(this.Pe)}get fontFramebuffer(){return this.Re}get characters(){return this.De}get textureColumns(){return this.Ie}get textureRows(){return this.ke}get maxGlyphDimensions(){return this.Ee}get fontSize(){return this.Ve}get font(){return this.Se}}class rt{constructor(r,s,i){c(this,"Ne");c(this,"Xe");c(this,"v");c(this,"C");c(this,"qe");c(this,"Ye");c(this,"Qe",!1);c(this,"Ze");c(this,"Je");c(this,"Ke");this.Ze=r,this.Je=s,this.Ke=i,this.Et()}Et(){this.Qe||(this.Ne=Math.floor(this.Ze.width/this.Je),this.Xe=Math.floor(this.Ze.height/this.Ke)),this.ts()}ts(){this.v=this.Ne*this.Je,this.C=this.Xe*this.Ke,this.qe=Math.floor((this.Ze.width-this.v)/2),this.Ye=Math.floor((this.Ze.height-this.C)/2)}es(r,s){this.Je=r,this.Ke=s,this.Et()}ss(r,s){this.Qe=!0,this.Ne=r,this.Xe=s,this.ts()}rs(){this.Qe=!1,this.Et()}ns(){this.Qe?this.ts():this.Et()}hs(r){if(r===void 0)return this.Qe;this.Qe=r}get cellWidth(){return this.Je}get cellHeight(){return this.Ke}get cols(){return this.Ne}get rows(){return this.Xe}get width(){return this.v}get height(){return this.C}get offsetX(){return this.qe}get offsetY(){return this.Ye}}class st{constructor(r,s=!1,i={}){c(this,"Ze");c(this,"ls");c(this,"cs");c(this,"us");c(this,"onTransformChange");this.ls=r,this.cs=s,this.Ze=this.fs(i.width,i.height),s&&this.setupTransformObserver()}fs(r,s){var o;const i=document.createElement("canvas");if(i.className="textmodeCanvas",i.style.imageRendering="pixelated",this.cs)i.width=r||800,i.height=s||600,document.body.appendChild(i);else{const n=this.ls.getBoundingClientRect();let a=Math.round(n.width),h=Math.round(n.height);if(this.ls instanceof HTMLVideoElement){const f=this.ls;(a===0||h===0)&&f.videoWidth>0&&f.videoHeight>0&&(a=f.videoWidth,h=f.videoHeight)}i.width=a,i.height=h,i.style.position="absolute",i.style.pointerEvents="none";const u=window.getComputedStyle(this.ls);let d=parseInt(u.zIndex||"0",10);isNaN(d)&&(d=0),i.style.zIndex=""+(d+1),this.ds(i),(o=this.ls.parentNode)==null||o.insertBefore(i,this.ls.nextSibling)}return i}ds(r){const s=this.ls.getBoundingClientRect();let i=this.ls.offsetParent;if(i&&i!==document.body){const o=i.getBoundingClientRect();r.style.top=s.top-o.top+"px",r.style.left=s.left-o.left+"px"}else r.style.top=s.top+window.scrollY+"px",r.style.left=s.left+window.scrollX+"px"}ns(r,s){if(this.cs)this.Ze.width=r??this.Ze.width,this.Ze.height=s??this.Ze.height;else{const i=this.ls.getBoundingClientRect();let o=Math.round(i.width),n=Math.round(i.height);if(this.ls instanceof HTMLVideoElement){const a=this.ls;(o===0||n===0)&&a.videoWidth>0&&a.videoHeight>0&&(o=a.videoWidth,n=a.videoHeight)}this.Ze.width=o,this.Ze.height=n,this.ds(this.Ze)}}ps(){const r={alpha:!1,premultipliedAlpha:!1,preserveDrawingBuffer:!0,antialias:!1,depth:!1,stencil:!1,powerPreference:"high-performance"},s=this.Ze.getContext("webgl2",r)||this.Ze.getContext("webgl",r);if(!s)throw new v("WebGL context could not be created. Ensure your browser supports WebGL.");return s}setupTransformObserver(){this.us=new ResizeObserver(r=>{for(const s of r){const i=s.contentRect;!this.onTransformChange||Math.round(i.width)===this.Ze.width&&Math.round(i.height)===this.Ze.height||this.onTransformChange()}}),this.us.observe(this.Ze)}A(){this.us&&this.us.disconnect();const r=this.Ze.getContext("webgl")||this.Ze.getContext("webgl2");if(r){const s=r.getExtension("WEBGL_lose_context");s&&s.loseContext()}this.Ze.parentNode&&this.Ze.parentNode.removeChild(this.Ze)}get canvas(){return this.Ze}get width(){return this.Ze.width}get height(){return this.Ze.height}}class P{constructor(r,s,i,o={}){c(this,"be");c(this,"gs");c(this,"_s");c(this,"vs");c(this,"bs");c(this,"ws");c(this,"Cs");c(this,"$s");c(this,"l");this.be=r,this.gs=s,this._s=i,this.l={enabled:!0,...o};const n=this._s.cols,a=this._s.rows;this.vs=this.be.Ot(n,a),this.bs=this.be.Ot(n,a),this.ws=this.be.Ot(n,a),this.Cs=this.be.Ot(n,a),this.$s=this.be.Ot(n,a)}ns(){const r=this._s.cols,s=this._s.rows;this.vs.resize(r,s),this.bs.resize(r,s),this.ws.resize(r,s),this.Cs.resize(r,s),this.$s.resize(r,s)}enabled(r){_.m(typeof r=="boolean"||typeof r=="number"&&Number.isInteger(r),"Enabled must be a boolean value or an integer (0 for false, any other number for true).",{method:"enabled",providedValue:r})&&(this.l.enabled=!!r)}enable(){this.enabled(!0)}disable(){this.enabled(!1)}A(){this.vs.A(),this.bs.A(),this.ws.A(),this.Cs.A(),this.$s.A()}get characterFramebuffer(){return this.vs}get primaryColorFramebuffer(){return this.bs}get secondaryColorFramebuffer(){return this.ws}get rotationFramebuffer(){return this.Cs}get transformFramebuffer(){return this.$s}get options(){return this.l}}class it{constructor(r,s){c(this,"M");c(this,"be");c(this,"Fs");this.be=r,this.Fs=s;const i=Math.max(this.Fs.length,1);this.M=this.be.Ot(i,1),this.Ts()}Ts(){const r=this.Fs.length;this.M.width!==r&&this.M.resize(r,1);const s=new Uint8Array(1*r*4);for(let i=0;i<r;i++){const o=this.Fs[i],n=4*i;s[n]=o[0],s[n+1]=o[1],s[n+2]=o[2],s[n+3]=255}this.M.updatePixels(s,r,1)}setColors(r){this.Fs=r,this.Ts()}get colors(){return this.Fs}get framebuffer(){return this.M}}class N extends P{constructor(s,i,o,n={}){super(s,i,o,{enabled:!0,characters:" .:-=+*%@#",characterColor:[1,1,1,1],characterColorMode:"sampled",cellColor:[0,0,0,1],cellColorMode:"fixed",invert:!1,rotation:[0,0,0,1],flipHorizontally:!1,flipVertically:!1,...n});c(this,"Ms");this.Ms=new it(this.be,this.gs.getCharacterColors(" .:-=+*%@#"))}characters(s){_.m(this.gs.hasAllCharacters(s),"One or more characters do not exist in the current font.",{method:"characters",providedValue:s})&&(this.l.characters=s,this.Ms.setColors(this.gs.getCharacterColors(s)))}characterColor(s,i,o,n=255){const a=this.Ss(s,"characterColor",i,o,n);a&&(this.l.characterColor=a)}characterColorMode(s){this.Ds(s,"characterColorMode")}cellColor(s,i,o,n=255){const a=this.Ss(s,"cellColor",i,o,n);a&&(this.l.cellColor=a)}cellColorMode(s){this.Ds(s,"cellColorMode")}invert(s){this.Rs(s,"invert","Invert")}rotation(s){if(!_.m(typeof s=="number","Rotation angle must be a number.",{method:"rotation",providedValue:s}))return;(s%=360)<0&&(s+=360);const i=255*s/360,o=Math.floor(i)/255,n=Math.round(i-o);this.l.rotation=[o,n,0,1]}flipHorizontally(s){this.Rs(s,"flipHorizontally","Flip horizontally")}flipVertically(s){this.Rs(s,"flipVertically","Flip vertically")}Ss(s,i,o,n,a=255){let h,u,d,f;if(typeof s=="string"){const p=this.Vs(s);if(!p)return _.m(!1,"Invalid hex color format. Use '#FF0000', '#F00', 'FF0000', or 'F00'.",{method:i,providedValue:s}),null;[h,u,d,f]=p}else if(h=s,u=o!==void 0?o:s,d=n!==void 0?n:s,f=a,!_.m([h,u,d,f].every(p=>p>=0&&p<=255),i.charAt(0).toUpperCase()+i.slice(1)+" color values must be between 0 and 255",{method:i,providedValues:{r:h,g:u,b:d,a:f}}))return null;return[h/255,u/255,d/255,f/255]}Ds(s,i){_.m(["sampled","fixed"].includes(s),"Invalid color mode. Must be 'sampled' or 'fixed'.",{method:i,providedValue:s})&&(this.l[i]=s)}Rs(s,i,o){_.m(typeof s=="boolean"||typeof s=="number"&&Number.isInteger(s),o+" must be a boolean value or an integer (0 for false, any other number for true).",{method:i,providedValue:s})&&(this.l[i]=!!s)}Vs(s){return s=s.replace(/^#/,""),/^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$/.test(s)?(s.length===3&&(s=s.split("").map(i=>i+i).join("")),[parseInt(s.slice(0,2),16),parseInt(s.slice(2,4),16),parseInt(s.slice(4,6),16),255]):null}}const I=`attribute vec2 a_position;\r
9
9
  attribute vec2 a_texCoord;\r
10
10
  varying vec2 v_uv;\r
11
11
  \r
@@ -43,22 +43,22 @@ void main() {\r
43
43
  \r
44
44
  gl_Position = vec4(pos, 0.0, 1.0);\r
45
45
  }\r
46
- `,wt={enabled:!0,characters:" .:-=+*%@#",characterColor:[1,1,1,1],characterColorMode:"sampled",cellColor:[0,0,0,1],cellColorMode:"fixed",invert:!1,rotation:[0,0,0,255],flipHorizontally:!1,flipVertically:!1,brightnessRange:[0,255]};class W extends z{constructor(s,i,o){super(s,i,o,{...wt});c(this,"Rs");c(this,"Vs");c(this,"ks");c(this,"Is");c(this,"Ps");c(this,"zs");this.Rs=new M(s.context,L,"precision lowp float;uniform sampler2D u_sketchTexture;uniform vec2 u_gridCellDimensions;uniform vec2 u_brightnessRange;varying vec2 v_uv;void main(){vec2 cellCenter=(floor(v_uv*u_gridCellDimensions)+vec2(0.5))/u_gridCellDimensions;vec4 color=texture2D(u_sketchTexture,cellCenter);float brightness=dot(color.rgb,vec3(0.299,0.587,0.114));float brightnessValue=brightness*255.0;if(brightnessValue>=u_brightnessRange.x&&brightnessValue<=u_brightnessRange.y){gl_FragColor=color;}else{gl_FragColor=vec4(0.0);}}"),this.Vs=new M(s.context,L,"precision lowp float;uniform sampler2D u_sampleTexture;uniform vec4 u_fillColor;uniform bool u_useFixedColor;varying vec2 v_uv;void main(){vec4 sampleColor=texture2D(u_sampleTexture,v_uv);if(sampleColor.a>0.0){if(u_useFixedColor){gl_FragColor=u_fillColor;}else{gl_FragColor=sampleColor;}}else{gl_FragColor=vec4(0.0);}}"),this.Is=new M(s.context,L,"precision lowp float;uniform sampler2D u_sampleTexture;uniform bool u_invert;uniform bool u_flipHorizontally;uniform bool u_flipVertically;varying vec2 v_uv;void main(){vec4 sampleColor=texture2D(u_sampleTexture,v_uv);if(sampleColor.a>0.0){float invertValue=u_invert ? 1.0 : 0.0;float flipHValue=u_flipHorizontally ? 1.0 : 0.0;float flipVValue=u_flipVertically ? 1.0 : 0.0;gl_FragColor=vec4(invertValue,flipHValue,flipVValue,1.0);}else{gl_FragColor=vec4(0.0);}}"),this.Ps=new M(s.context,L,"precision lowp float;uniform sampler2D u_sampleTexture;uniform vec4 u_rotationColor;varying vec2 v_uv;void main(){vec4 sampleColor=texture2D(u_sampleTexture,v_uv);if(sampleColor.a>0.0){gl_FragColor=u_rotationColor;}else{gl_FragColor=vec4(0.0);}}"),this.ks=new M(s.context,L,"precision lowp float;uniform sampler2D u_colorSampleFramebuffer;uniform sampler2D u_charPaletteTexture;uniform vec2 u_charPaletteSize;uniform vec2 u_brightnessRange;varying vec2 v_uv;void main(){vec4 color=texture2D(u_colorSampleFramebuffer,v_uv);if(color.a==0.0){gl_FragColor=vec4(0.0);return;}float brightness=dot(color.rgb,vec3(0.299,0.587,0.114))*255.0;vec2 range=u_brightnessRange;if(brightness<range.x||brightness>range.y){gl_FragColor=vec4(0.0);return;}float t=(brightness-range.x)/(range.y-range.x);float idx=clamp(floor(t*u_charPaletteSize.x),0.0,u_charPaletteSize.x-1.0);vec3 charColor=texture2D(u_charPaletteTexture,vec2((idx+0.5)/u_charPaletteSize.x,0.0)).rgb;gl_FragColor=vec4(charColor,1.0);}"),this.zs=this.ve.Lt(this.ps.cols,this.ps.rows)}Es(s){const i=this.ps.cols,o=this.ps.rows;this.zs.begin(),this.ve.Ht(),this.ve.yt(this.Rs),this.ve.Et("u_sketchTexture",s),this.ve.Et("u_gridCellDimensions",[i,o]),this.ve.Et("u_brightnessRange",this.l.brightnessRange),this.ve.Gt(0,0,i,o),this.zs.end(),this._s.begin(),this.ve.Ht(),this.ve.yt(this.Vs),this.ve.Et("u_sampleTexture",this.zs),this.ve.Et("u_fillColor",this.l.characterColor),this.ve.Et("u_useFixedColor",this.l.characterColorMode==="fixed"),this.ve.Gt(0,0,i,o),this._s.end(),this.vs.begin(),this.ve.Ht(),this.ve.yt(this.Vs),this.ve.Et("u_sampleTexture",this.zs),this.ve.Et("u_fillColor",this.l.cellColor),this.ve.Et("u_useFixedColor",this.l.cellColorMode==="fixed"),this.ve.Gt(0,0,i,o),this.vs.end(),this.ws.begin(),this.ve.Ht(),this.ve.yt(this.Is),this.ve.Et("u_sampleTexture",this.zs),this.ve.Et("u_invert",this.l.invert),this.ve.Et("u_flipHorizontally",this.l.flipHorizontally),this.ve.Et("u_flipVertically",this.l.flipVertically),this.ve.Gt(0,0,i,o),this.ws.end(),this.bs.begin(),this.ve.Ht(),this.ve.yt(this.Ps),this.ve.Et("u_sampleTexture",this.zs),this.ve.Et("u_rotationColor",this.l.rotation),this.ve.Gt(0,0,i,o),this.bs.end(),this.gs.begin(),this.ve.Ht(),this.ve.yt(this.ks),this.ve.Et("u_colorSampleFramebuffer",this.zs),this.ve.Et("u_charPaletteTexture",this.Fs.texture),this.ve.Et("u_charPaletteSize",[this.Fs.colors.length,1]),this.ve.Et("u_brightnessRange",this.l.brightnessRange),this.ve.Gt(0,0,i,o),this.gs.end()}ss(){super.ss(),this.zs.resize(this.ps.cols,this.ps.rows)}brightnessRange(s){C.m(Array.isArray(s)&&s.length===2&&s.every(i=>typeof i=="number"&&i>=0&&i<=255),"Brightness range must be an array of two numbers between 0 and 255.",{method:"brightnessRange",providedValue:s})&&(this.l.brightnessRange=s)}}const Ct=Object.freeze(Object.defineProperty({__proto__:null,TextmodeBrightnessConverter:W,TextmodeConverter:U,TextmodeFeatureConverter:z},Symbol.toStringTag,{value:"Module"}));class st{constructor(r,s,i){c(this,"ve");c(this,"Te");c(this,"ps");c(this,"Gs");c(this,"As");c(this,"Us");c(this,"Ls");c(this,"js");c(this,"gs");c(this,"_s");c(this,"vs");c(this,"bs");c(this,"ws");this.ve=r,this.Te=s,this.ps=i,this.js=this.ve.Pt(B,"precision mediump float;uniform sampler2D u_characterTexture;uniform vec2 u_charsetDimensions;uniform sampler2D u_primaryColorTexture;uniform sampler2D u_secondaryColorTexture;uniform sampler2D u_transformTexture;uniform sampler2D u_asciiCharacterTexture;uniform sampler2D u_rotationTexture;uniform sampler2D u_captureTexture;uniform vec2 u_captureDimensions;uniform int u_backgroundMode;uniform vec2 u_gridCellDimensions;uniform vec2 u_gridPixelDimensions;mat2 rotate2D(float angle){float s=sin(angle);float c=cos(angle);return mat2(c,-s,s,c);}void main(){vec2 adjustedCoord=gl_FragCoord.xy/u_gridPixelDimensions;vec2 gridCoord=adjustedCoord*u_gridCellDimensions;vec2 cellCoord=floor(gridCoord);vec2 charIndexTexCoord=(cellCoord+0.5)/u_gridCellDimensions;vec4 primaryColor=texture2D(u_primaryColorTexture,charIndexTexCoord);vec4 secondaryColor=texture2D(u_secondaryColorTexture,charIndexTexCoord);vec4 transformColor=texture2D(u_transformTexture,charIndexTexCoord);bool isInverted=transformColor.r>0.5;bool flipHorizontal=transformColor.g>0.5;bool flipVertical=transformColor.b>0.5;vec4 encodedIndexVec=texture2D(u_asciiCharacterTexture,charIndexTexCoord);if(encodedIndexVec.a<0.01){gl_FragColor=(u_backgroundMode==0)? vec4(0.0):texture2D(u_captureTexture,gl_FragCoord.xy/u_captureDimensions);return;}int charIndex=int(encodedIndexVec.r*255.0+0.5)+int(encodedIndexVec.g*255.0+0.5)*256;int charCol=int(mod(float(charIndex),u_charsetDimensions.x));int charRow=charIndex/int(u_charsetDimensions.x);float flippedRow=(u_charsetDimensions.y-1.0)-float(charRow);vec2 charCoord=vec2(float(charCol),flippedRow)/u_charsetDimensions;vec4 rotationColor=texture2D(u_rotationTexture,charIndexTexCoord);float scaledAngle=rotationColor.r*255.0+rotationColor.g;float rotationAngle=(scaledAngle*360.0/255.0)*0.017453292;vec2 fractionalPart=fract(gridCoord)-0.5;if(flipHorizontal)fractionalPart.x=-fractionalPart.x;if(flipVertical)fractionalPart.y=-fractionalPart.y;fractionalPart=rotate2D(rotationAngle)*fractionalPart+0.5;vec2 cellSize=1.0/u_charsetDimensions;vec2 texCoord=charCoord+fractionalPart*cellSize;vec2 cellMax=charCoord+cellSize;if(any(lessThan(texCoord,charCoord))||any(greaterThan(texCoord,cellMax))){gl_FragColor=isInverted ? primaryColor : secondaryColor;return;}vec4 charTexel=texture2D(u_characterTexture,texCoord);if(isInverted)charTexel.rgb=1.0-charTexel.rgb;gl_FragColor=mix(secondaryColor,primaryColor,charTexel);}"),this.As=new W(r,s,i),this.Us=new U(r,s,i),this.Gs=[this.As,this.Us],this.gs=this.ve.Lt(i.cols,i.rows),this._s=this.ve.Lt(i.cols,i.rows),this.vs=this.ve.Lt(i.cols,i.rows),this.bs=this.ve.Lt(i.cols,i.rows),this.ws=this.ve.Lt(i.cols,i.rows),this.Ls=this.ve.Lt(this.ps.width,this.ps.height)}Hs(r){for(const i of this.Gs)i.options.enabled&&i instanceof z&&i.Es(r);const s=(i,o)=>{i.begin(),this.ve.Ht();for(const n of this.Gs)n.options.enabled&&this.ve.Bt(o(n),0,0);i.end()};s(this.gs,i=>i.characterFramebuffer),s(this._s,i=>i.primaryColorFramebuffer),s(this.vs,i=>i.secondaryColorFramebuffer),s(this.bs,i=>i.rotationFramebuffer),s(this.ws,i=>i.transformFramebuffer),this.Ls.begin(),this.ve.Ht(),this.ve.yt(this.js),this.ve.Et("u_characterTexture",this.Te.fontFramebuffer),this.ve.Et("u_charsetDimensions",[this.Te.textureColumns,this.Te.textureRows]),this.ve.Et("u_asciiCharacterTexture",this.gs.texture),this.ve.Et("u_primaryColorTexture",this._s.texture),this.ve.Et("u_secondaryColorTexture",this.vs.texture),this.ve.Et("u_transformTexture",this.ws.texture),this.ve.Et("u_rotationTexture",this.bs.texture),this.ve.Et("u_captureTexture",r.texture),this.ve.Et("u_backgroundMode",!1),this.ve.Et("u_captureDimensions",[r.width,r.height]),this.ve.Et("u_gridCellDimensions",[this.ps.cols,this.ps.rows]),this.ve.Et("u_gridPixelDimensions",[this.ps.width,this.ps.height]),this.ve.Gt(0,0,this.Ls.width,this.Ls.height),this.Ls.end()}add(r){if(!C.m(r==="brightness"||r==="custom",'Converter type must be either "brightness" or "custom".',{method:"add",providedValue:r}))return;let s;return s=r==="brightness"?new W(this.ve,this.Te,this.ps):new U(this.ve,this.Te,this.ps),this.Gs.push(s),s}remove(r){if(!C.m(r instanceof U,"Parameter must be a TextmodeConverter instance.",{method:"remove",providedValue:r}))return;const s=this.Gs.indexOf(r);C.m(s!==-1,"Converter instance not found in pipeline.",{method:"remove",providedValue:r,convertersCount:this.Gs.length})&&this.Gs.splice(s,1)}swap(r,s){const i=(h,u)=>{if(typeof h=="number")return C.m(Number.isInteger(h)&&h>=0&&h<this.Gs.length,u+" index must be a valid integer within the converter array bounds.",{method:"swap",providedValue:h,convertersCount:this.Gs.length})?h:null;if(h instanceof U){const d=this.Gs.indexOf(h);return C.m(d!==-1,u+" converter instance not found in pipeline.",{method:"swap",providedValue:h,convertersCount:this.Gs.length})?d:null}return C.m(!1,u+" parameter must be either an integer index or a TextmodeConverter instance.",{method:"swap",providedValue:h}),null},o=i(r,"First"),n=i(s,"Second");if(o===null||n===null||!C.m(o!==n,"Cannot swap a converter with itself.",{method:"swap",firstIndex:o,secondIndex:n}))return;const a=this.Gs[o];this.Gs[o]=this.Gs[n],this.Gs[n]=a}ss(){this.Ls.resize(this.ps.width,this.ps.height);const r=this.ps.cols,s=this.ps.rows;this.gs.resize(r,s),this._s.resize(r,s),this.vs.resize(r,s),this.bs.resize(r,s),this.ws.resize(r,s);for(const i of this.Gs)i.ss()}hasEnabledConverters(){return this.Gs.some(r=>r.options.enabled)}disable(){for(const r of this.Gs)r.disable()}enable(){for(const r of this.Gs)r.enable()}P(){for(const r of this.Gs)r.P();this.gs.P(),this._s.P(),this.vs.P(),this.bs.P(),this.ws.P(),this.Ls.P(),this.js.P()}get texture(){return this.Ls}get characterFramebuffer(){return this.gs}get primaryColorFramebuffer(){return this._s}get secondaryColorFramebuffer(){return this.vs}get rotationFramebuffer(){return this.bs}get transformFramebuffer(){return this.ws}get brightness(){return this.As}get custom(){return this.Us}}const yt=l=>class extends l{fill(r,s,i,o){this.ve.$t(r,s,i,o)}stroke(r,s,i,o){this.ve.Ft(r,s,i,o)}strokeWeight(r){this.ve.Tt(r)}noStroke(){this.ve.Mt()}noFill(){this.ve.St()}rotate(r){this.ve.Dt(r)}push(){this.ve.Rt()}pop(){this.ve.Vt()}rect(r,s,i=1,o=1){this.ve.Gt(r,s,i,o)}line(r,s,i,o){this.ve.Ut(r,s,i,o)}background(r,s=r,i=r,o=255){this.ve.jt(r,s,i,o)}createShader(r,s){return this.ve.Pt(r,s)}createFilterShader(r){return this.ve.zt(r)}shader(r){this.ve.yt(r)}setUniform(r,s){this.ve.Et(r,s)}image(r,s,i,o,n){this.ve.Bt(r,s,i,o,n)}clear(){this.ve.Ht()}createFramebuffer(r,s,i={}){return this.ve.Lt(r,s,i)}};class j{Os(r){const s=r.characterFramebuffer,i=r.primaryColorFramebuffer,o=r.secondaryColorFramebuffer,n=r.transformFramebuffer,a=r.rotationFramebuffer;return s==null||s.loadPixels(),i==null||i.loadPixels(),o==null||o.loadPixels(),n==null||n.loadPixels(),a==null||a.loadPixels(),{characterPixels:(s==null?void 0:s.pixels)||new Uint8Array(0),primaryColorPixels:(i==null?void 0:i.pixels)||new Uint8Array(0),secondaryColorPixels:(o==null?void 0:o.pixels)||new Uint8Array(0),transformPixels:(n==null?void 0:n.pixels)||new Uint8Array(0),rotationPixels:(a==null?void 0:a.pixels)||new Uint8Array(0)}}Bs(r,s){return r[s]+(r[s+1]<<8)}Ws(r,s){return{r:r[s],g:r[s+1],b:r[s+2],a:r[s+3]}}}class N{Ns(r,s){return new Blob([r],{type:s})}Xs(r,s,i){try{const o=this.Ns(r,i),n=URL.createObjectURL(o),a=document.createElement("a");a.href=n,a.download=s,a.style.display="none",a.rel="noopener",document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(n)}catch(o){throw console.error("Failed to download file:",o),Error("File download failed: "+(o instanceof Error?o.message:"Unknown error"))}}qs(){return new Date().toISOString().slice(0,19).replace(/:/g,"-")}Ys(){const r=new Date;return{date:r.toISOString().split("T")[0],time:r.toTimeString().split(" ")[0].replace(/:/g,"-")}}Qs(r){return r.replace(/[<>:"/\\|?*]/g,"_").replace(/\s+/g,"_").replace(/_{2,}/g,"_").replace(/^_+|_+$/g,"").substring(0,255)}Zs(){return"'textmode-export'-"+this.qs()}}class _t extends j{Js(r,s,i){const o=r[i]===255,n=r[i+1]===255,a=r[i+2]===255,h=s[i],u=s[i+1];return{isInverted:o,flipHorizontal:n,flipVertical:a,rotation:Math.round(360*(h+u/255)/255*100)/100}}Ks(r,s,i){return{x:r,y:s,cellX:r*i.cellWidth,cellY:s*i.cellHeight}}tr(r,s){const i=[];let o=0;for(let n=0;n<s.rows;n++)for(let a=0;a<s.cols;a++){const h=4*o,u=this.Bs(r.characterPixels,h);let d=this.Ws(r.primaryColorPixels,h),f=this.Ws(r.secondaryColorPixels,h);const p=this.Js(r.transformPixels,r.rotationPixels,h);if(p.isInverted){const x=d;d=f,f=x}const g=this.Ks(a,n,s);i.push({charIndex:u,primaryColor:d,secondaryColor:f,transform:p,position:g}),o++}return i}}class Tt{er(r,s){const i=r.cmap;for(const o of i.tables)if(o.format===4){for(let n=0;n<o.startCount.length;n++)if(s>=o.startCount[n]&&s<=o.endCount[n]){if(o.idRangeOffset[n]===0)return s+o.idDelta[n]&65535;{const a=o.idRangeOffset[n]/2+(s-o.startCount[n])-(o.startCount.length-n);if(a>=0&&a<o.glyphIdArray.length){const h=o.glyphIdArray[a];if(h!==0)return h+o.idDelta[n]&65535}}}}return 0}sr(r,s,i,o,n){const a=n/r.head.unitsPerEm;return{getBoundingBox:()=>({x1:i+s.xMin*a,y1:o+-s.yMax*a,x2:i+s.xMax*a,y2:o+-s.yMin*a}),toSVG:()=>this.rr(s,i,o,a)}}rr(r,s,i,o){if(!r||!r.xs)return"";const{xs:n,ys:a,endPts:h,flags:u}=r;if(!(n&&a&&h&&u))return"";let d="",f=0;for(let p=0;p<h.length;p++){const g=h[p];if(!(g<f)){if(g>=f){const x=s+n[f]*o,m=i-a[f]*o;d+=`M${x.toFixed(2)},${m.toFixed(2)}`;let v=f+1;for(;v<=g;)if(1&u[v]){const T=s+n[v]*o,y=i-a[v]*o;d+=`L${T.toFixed(2)},${y.toFixed(2)}`,v++}else{const T=s+n[v]*o,y=i-a[v]*o;let _=v+1>g?f:v+1;if(1&u[_]){const F=s+n[_]*o,A=i-a[_]*o;d+=`Q${T.toFixed(2)},${y.toFixed(2)} ${F.toFixed(2)},${A.toFixed(2)}`,v=_+1}else{const F=(T+(s+n[_]*o))/2,A=(y+(i-a[_]*o))/2;d+=`Q${T.toFixed(2)},${y.toFixed(2)} ${F.toFixed(2)},${A.toFixed(2)}`,v=_}}d+="Z"}f=g+1}}return d}ir(r,s,i,o,n){const a=r.codePointAt(0)||0,h=this.er(s,a);let u=null;return s.glyf&&s.glyf[h]!==null?u=s.glyf[h]:R&&R.T&&R.T.glyf&&R.T.glyf.Wt&&(u=R.T.glyf.Wt(s,h),s.glyf&&u&&(s.glyf[h]=u)),this.sr(s,u,i,o,n)}nr(r,s,i,o,n,a,h,u){const d=i+(n-u*(h/s.head.unitsPerEm))/2,f=o+(a+.7*h)/2;return this.ir(r,s,d,f,h).toSVG()||null}}class Et{constructor(){c(this,"ar");this.ar=new Tt}hr(r){return`<?xml version="1.0" encoding="UTF-8" standalone="no"?>
46
+ `,ot={enabled:!0,characters:" .:-=+*%@#",characterColor:[1,1,1,1],characterColorMode:"sampled",cellColor:[0,0,0,1],cellColorMode:"fixed",invert:!1,rotation:[0,0,0,255],flipHorizontally:!1,flipVertically:!1,brightnessRange:[0,255]};class H extends N{constructor(s,i,o){super(s,i,o,ot);c(this,"Is");c(this,"ks");c(this,"Es");c(this,"Ps");c(this,"As");c(this,"zs");this.Is=new R(s.context,I,"precision lowp float;uniform sampler2D u_sketchTexture;uniform vec2 u_gridCellDimensions;uniform vec2 u_brightnessRange;varying vec2 v_uv;void main(){vec2 cellCenter=(floor(v_uv*u_gridCellDimensions)+vec2(0.5))/u_gridCellDimensions;vec4 color=texture2D(u_sketchTexture,cellCenter);float brightness=dot(color.rgb,vec3(0.299,0.587,0.114));float brightnessValue=brightness*255.0;if(brightnessValue>=u_brightnessRange.x&&brightnessValue<=u_brightnessRange.y){gl_FragColor=color;}else{gl_FragColor=vec4(0.0);}}"),this.ks=new R(s.context,I,"precision lowp float;uniform sampler2D u_sampleTexture;uniform vec4 u_fillColor;uniform bool u_useFixedColor;varying vec2 v_uv;void main(){vec4 sampleColor=texture2D(u_sampleTexture,v_uv);if(sampleColor.a>0.0){if(u_useFixedColor){gl_FragColor=u_fillColor;}else{gl_FragColor=sampleColor;}}else{gl_FragColor=vec4(0.0);}}"),this.Ps=new R(s.context,I,"precision lowp float;uniform sampler2D u_sampleTexture;uniform bool u_invert;uniform bool u_flipHorizontally;uniform bool u_flipVertically;varying vec2 v_uv;void main(){vec4 sampleColor=texture2D(u_sampleTexture,v_uv);if(sampleColor.a>0.0){float invertValue=u_invert ? 1.0 : 0.0;float flipHValue=u_flipHorizontally ? 1.0 : 0.0;float flipVValue=u_flipVertically ? 1.0 : 0.0;gl_FragColor=vec4(invertValue,flipHValue,flipVValue,1.0);}else{gl_FragColor=vec4(0.0);}}"),this.As=new R(s.context,I,"precision lowp float;uniform sampler2D u_sampleTexture;uniform vec4 u_rotationColor;varying vec2 v_uv;void main(){vec4 sampleColor=texture2D(u_sampleTexture,v_uv);if(sampleColor.a>0.0){gl_FragColor=u_rotationColor;}else{gl_FragColor=vec4(0.0);}}"),this.Es=new R(s.context,I,"precision lowp float;uniform sampler2D u_colorSampleFramebuffer;uniform sampler2D u_charPaletteTexture;uniform vec2 u_charPaletteSize;uniform vec2 u_brightnessRange;varying vec2 v_uv;void main(){vec4 color=texture2D(u_colorSampleFramebuffer,v_uv);if(color.a==0.0){gl_FragColor=vec4(0.0);return;}float brightness=dot(color.rgb,vec3(0.299,0.587,0.114))*255.0;vec2 range=u_brightnessRange;if(brightness<range.x||brightness>range.y){gl_FragColor=vec4(0.0);return;}float t=(brightness-range.x)/(range.y-range.x);float idx=clamp(floor(t*u_charPaletteSize.x),0.0,u_charPaletteSize.x-1.0);vec3 charColor=texture2D(u_charPaletteTexture,vec2((idx+0.5)/u_charPaletteSize.x,0.0)).rgb;gl_FragColor=vec4(charColor,1.0);}"),this.zs=this.be.Ot(this._s.cols,this._s.rows)}Gs(s){const i=this._s.cols,o=this._s.rows;this.zs.begin(),this.be.Bt(),this.be.Ft(this.Is),this.be.Gt("u_sketchTexture",s),this.be.Gt("u_gridCellDimensions",[i,o]),this.be.Gt("u_brightnessRange",this.l.brightnessRange),this.be.Ut(0,0,i,o),this.zs.end(),this.bs.begin(),this.be.Bt(),this.be.Ft(this.ks),this.be.Gt("u_sampleTexture",this.zs),this.be.Gt("u_fillColor",this.l.characterColor),this.be.Gt("u_useFixedColor",this.l.characterColorMode==="fixed"),this.be.Ut(0,0,i,o),this.bs.end(),this.ws.begin(),this.be.Bt(),this.be.Ft(this.ks),this.be.Gt("u_sampleTexture",this.zs),this.be.Gt("u_fillColor",this.l.cellColor),this.be.Gt("u_useFixedColor",this.l.cellColorMode==="fixed"),this.be.Ut(0,0,i,o),this.ws.end(),this.$s.begin(),this.be.Bt(),this.be.Ft(this.Ps),this.be.Gt("u_sampleTexture",this.zs),this.be.Gt("u_invert",this.l.invert),this.be.Gt("u_flipHorizontally",this.l.flipHorizontally),this.be.Gt("u_flipVertically",this.l.flipVertically),this.be.Ut(0,0,i,o),this.$s.end(),this.Cs.begin(),this.be.Bt(),this.be.Ft(this.As),this.be.Gt("u_sampleTexture",this.zs),this.be.Gt("u_rotationColor",this.l.rotation),this.be.Ut(0,0,i,o),this.Cs.end(),this.vs.begin(),this.be.Bt(),this.be.Ft(this.Es),this.be.Gt("u_colorSampleFramebuffer",this.zs),this.be.Gt("u_charPaletteTexture",this.Ms.framebuffer),this.be.Gt("u_charPaletteSize",[this.Ms.colors.length,1]),this.be.Gt("u_brightnessRange",this.l.brightnessRange),this.be.Ut(0,0,i,o),this.vs.end()}ns(){super.ns(),this.zs.resize(this._s.cols,this._s.rows)}brightnessRange(s){_.m(Array.isArray(s)&&s.length===2&&s.every(i=>typeof i=="number"&&i>=0&&i<=255),"Brightness range must be an array of two numbers between 0 and 255.",{method:"brightnessRange",providedValue:s})&&(this.l.brightnessRange=s)}}const Ft=Object.freeze(Object.defineProperty({__proto__:null,BRIGHTNESS_DEFAULT_OPTIONS:ot,TextmodeBrightnessConverter:H,TextmodeConverter:P,TextmodeFeatureConverter:N},Symbol.toStringTag,{value:"Module"}));class nt{constructor(r,s,i){c(this,"be");c(this,"Se");c(this,"_s");c(this,"Us");c(this,"Ls");c(this,"js");c(this,"Os");c(this,"Hs");c(this,"vs");c(this,"bs");c(this,"ws");c(this,"Cs");c(this,"$s");this.be=r,this.Se=s,this._s=i,this.Hs=this.be.At(L,"precision mediump float;uniform sampler2D u_characterTexture;uniform vec2 u_charsetDimensions;uniform sampler2D u_primaryColorTexture;uniform sampler2D u_secondaryColorTexture;uniform sampler2D u_transformTexture;uniform sampler2D u_asciiCharacterTexture;uniform sampler2D u_rotationTexture;uniform sampler2D u_captureTexture;uniform vec2 u_captureDimensions;uniform int u_backgroundMode;uniform vec2 u_gridCellDimensions;uniform vec2 u_gridPixelDimensions;mat2 rotate2D(float angle){float s=sin(angle);float c=cos(angle);return mat2(c,-s,s,c);}void main(){vec2 adjustedCoord=gl_FragCoord.xy/u_gridPixelDimensions;vec2 gridCoord=adjustedCoord*u_gridCellDimensions;vec2 cellCoord=floor(gridCoord);vec2 charIndexTexCoord=(cellCoord+0.5)/u_gridCellDimensions;vec4 primaryColor=texture2D(u_primaryColorTexture,charIndexTexCoord);vec4 secondaryColor=texture2D(u_secondaryColorTexture,charIndexTexCoord);vec4 transformColor=texture2D(u_transformTexture,charIndexTexCoord);bool isInverted=transformColor.r>0.5;bool flipHorizontal=transformColor.g>0.5;bool flipVertical=transformColor.b>0.5;vec4 encodedIndexVec=texture2D(u_asciiCharacterTexture,charIndexTexCoord);if(encodedIndexVec.a<0.01){gl_FragColor=(u_backgroundMode==0)? vec4(0.0):texture2D(u_captureTexture,gl_FragCoord.xy/u_captureDimensions);return;}int charIndex=int(encodedIndexVec.r*255.0+0.5)+int(encodedIndexVec.g*255.0+0.5)*256;int charCol=int(mod(float(charIndex),u_charsetDimensions.x));int charRow=charIndex/int(u_charsetDimensions.x);float flippedRow=(u_charsetDimensions.y-1.0)-float(charRow);vec2 charCoord=vec2(float(charCol),flippedRow)/u_charsetDimensions;vec4 rotationColor=texture2D(u_rotationTexture,charIndexTexCoord);float scaledAngle=rotationColor.r*255.0+rotationColor.g;float rotationAngle=(scaledAngle*360.0/255.0)*0.017453292;vec2 fractionalPart=fract(gridCoord)-0.5;if(flipHorizontal)fractionalPart.x=-fractionalPart.x;if(flipVertical)fractionalPart.y=-fractionalPart.y;fractionalPart=rotate2D(rotationAngle)*fractionalPart+0.5;vec2 cellSize=1.0/u_charsetDimensions;vec2 texCoord=charCoord+fractionalPart*cellSize;vec2 cellMax=charCoord+cellSize;if(any(lessThan(texCoord,charCoord))||any(greaterThan(texCoord,cellMax))){gl_FragColor=isInverted ? primaryColor : secondaryColor;return;}vec4 charTexel=texture2D(u_characterTexture,texCoord);if(isInverted)charTexel.rgb=1.0-charTexel.rgb;gl_FragColor=mix(secondaryColor,primaryColor,charTexel);}"),this.Ls=new H(r,s,i),this.js=new P(r,s,i),this.Us=[this.Ls,this.js],this.vs=this.be.Ot(i.cols,i.rows),this.bs=this.be.Ot(i.cols,i.rows),this.ws=this.be.Ot(i.cols,i.rows),this.Cs=this.be.Ot(i.cols,i.rows),this.$s=this.be.Ot(i.cols,i.rows),this.Os=this.be.Ot(this._s.width,this._s.height)}Bs(r){for(const i of this.Us)i.options.enabled&&i instanceof N&&i.Gs(r);const s=(i,o)=>{i.begin(),this.be.Bt();for(const n of this.Us)n.options.enabled&&this.be.Nt(o(n),0,0);i.end()};s(this.vs,i=>i.characterFramebuffer),s(this.bs,i=>i.primaryColorFramebuffer),s(this.ws,i=>i.secondaryColorFramebuffer),s(this.Cs,i=>i.rotationFramebuffer),s(this.$s,i=>i.transformFramebuffer),this.Os.begin(),this.be.Bt(),this.be.Ft(this.Hs),this.be.Gt("u_characterTexture",this.Se.fontFramebuffer),this.be.Gt("u_charsetDimensions",[this.Se.textureColumns,this.Se.textureRows]),this.be.Gt("u_asciiCharacterTexture",this.vs),this.be.Gt("u_primaryColorTexture",this.bs),this.be.Gt("u_secondaryColorTexture",this.ws),this.be.Gt("u_transformTexture",this.$s),this.be.Gt("u_rotationTexture",this.Cs),this.be.Gt("u_captureTexture",r),this.be.Gt("u_backgroundMode",!1),this.be.Gt("u_captureDimensions",[r.width,r.height]),this.be.Gt("u_gridCellDimensions",[this._s.cols,this._s.rows]),this.be.Gt("u_gridPixelDimensions",[this._s.width,this._s.height]),this.be.Ut(0,0,this.Os.width,this.Os.height),this.Os.end()}add(r){if(!_.m(r==="brightness"||r==="custom",'Converter type must be either "brightness" or "custom".',{method:"add",providedValue:r}))return;let s;return s=r==="brightness"?new H(this.be,this.Se,this._s):new P(this.be,this.Se,this._s),this.Us.push(s),s}remove(r){if(!_.m(r instanceof P,"Parameter must be a TextmodeConverter instance.",{method:"remove",providedValue:r}))return;const s=this.Us.indexOf(r);_.m(s!==-1,"Converter instance not found in pipeline.",{method:"remove",providedValue:r,convertersCount:this.Us.length})&&this.Us.splice(s,1)}swap(r,s){const i=(h,u)=>{if(typeof h=="number")return _.m(Number.isInteger(h)&&h>=0&&h<this.Us.length,u+" index must be a valid integer within the converter array bounds.",{method:"swap",providedValue:h,convertersCount:this.Us.length})?h:null;if(h instanceof P){const d=this.Us.indexOf(h);return _.m(d!==-1,u+" converter instance not found in pipeline.",{method:"swap",providedValue:h,convertersCount:this.Us.length})?d:null}return _.m(!1,u+" parameter must be either an integer index or a TextmodeConverter instance.",{method:"swap",providedValue:h}),null},o=i(r,"First"),n=i(s,"Second");if(o===null||n===null||!_.m(o!==n,"Cannot swap a converter with itself.",{method:"swap",firstIndex:o,secondIndex:n}))return;const a=this.Us[o];this.Us[o]=this.Us[n],this.Us[n]=a}ns(){this.Os.resize(this._s.width,this._s.height);const r=this._s.cols,s=this._s.rows;this.vs.resize(r,s),this.bs.resize(r,s),this.ws.resize(r,s),this.Cs.resize(r,s),this.$s.resize(r,s);for(const i of this.Us)i.ns()}hasEnabledConverters(){return this.Us.some(r=>r.options.enabled)}disable(){for(const r of this.Us)r.disable()}enable(){for(const r of this.Us)r.enable()}A(){for(const r of this.Us)r.A();this.vs.A(),this.bs.A(),this.ws.A(),this.Cs.A(),this.$s.A(),this.Os.A(),this.Hs.A()}get texture(){return this.Os}get characterFramebuffer(){return this.vs}get primaryColorFramebuffer(){return this.bs}get secondaryColorFramebuffer(){return this.ws}get rotationFramebuffer(){return this.Cs}get transformFramebuffer(){return this.$s}get brightness(){return this.Ls}get custom(){return this.js}}const yt=l=>class extends l{fill(r,s,i,o){this.be.Tt(r,s,i,o)}stroke(r,s,i,o){this.be.Mt(r,s,i,o)}strokeWeight(r){this.be.St(r)}noStroke(){this.be.Dt()}noFill(){this.be.Rt()}rotate(r){this.be.Vt(r)}push(){this.be.It()}pop(){this.be.kt()}rect(r,s,i=1,o=1){this.be.Ut(r,s,i,o)}line(r,s,i,o){this.be.jt(r,s,i,o)}background(r,s=r,i=r,o=255){this.be.Ht(r,s,i,o)}createShader(r,s){return this.be.At(r,s)}createFilterShader(r){return this.be.zt(r)}shader(r){this.be.Ft(r)}setUniform(r,s){this.be.Gt(r,s)}image(r,s,i,o,n){this.be.Nt(r,s,i,o,n)}clear(){this.be.Bt()}createFramebuffer(r,s,i={}){return this.be.Ot(r,s,i)}};class W{Ws(r){const s=r.characterFramebuffer,i=r.primaryColorFramebuffer,o=r.secondaryColorFramebuffer,n=r.transformFramebuffer,a=r.rotationFramebuffer;return s==null||s.loadPixels(),i==null||i.loadPixels(),o==null||o.loadPixels(),n==null||n.loadPixels(),a==null||a.loadPixels(),{characterPixels:(s==null?void 0:s.pixels)||new Uint8Array(0),primaryColorPixels:(i==null?void 0:i.pixels)||new Uint8Array(0),secondaryColorPixels:(o==null?void 0:o.pixels)||new Uint8Array(0),transformPixels:(n==null?void 0:n.pixels)||new Uint8Array(0),rotationPixels:(a==null?void 0:a.pixels)||new Uint8Array(0)}}Ns(r,s){return r[s]+(r[s+1]<<8)}Xs(r,s){return{r:r[s],g:r[s+1],b:r[s+2],a:r[s+3]}}}class X{qs(r,s){return new Blob([r],{type:s})}Ys(r,s,i){try{const o=this.qs(r,i),n=URL.createObjectURL(o),a=document.createElement("a");a.href=n,a.download=s,a.style.display="none",a.rel="noopener",document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(n)}catch(o){throw console.error("Failed to download file:",o),Error("File download failed: "+(o instanceof Error?o.message:"Unknown error"))}}Qs(){return new Date().toISOString().slice(0,19).replace(/:/g,"-")}Zs(){const r=new Date;return{date:r.toISOString().split("T")[0],time:r.toTimeString().split(" ")[0].replace(/:/g,"-")}}Js(r){return r.replace(/[<>:"/\\|?*]/g,"_").replace(/\s+/g,"_").replace(/_{2,}/g,"_").replace(/^_+|_+$/g,"").substring(0,255)}Ks(){return"'textmode-export'-"+this.Qs()}}class Tt extends W{tr(r,s,i){const o=r[i]===255,n=r[i+1]===255,a=r[i+2]===255,h=s[i],u=s[i+1];return{isInverted:o,flipHorizontal:n,flipVertical:a,rotation:Math.round(360*(h+u/255)/255*100)/100}}er(r,s,i){return{x:r,y:s,cellX:r*i.cellWidth,cellY:s*i.cellHeight}}sr(r,s){const i=[];let o=0;for(let n=0;n<s.rows;n++)for(let a=0;a<s.cols;a++){const h=4*o,u=this.Ns(r.characterPixels,h);let d=this.Xs(r.primaryColorPixels,h),f=this.Xs(r.secondaryColorPixels,h);const p=this.tr(r.transformPixels,r.rotationPixels,h);if(p.isInverted){const x=d;d=f,f=x}const g=this.er(a,n,s);i.push({charIndex:u,primaryColor:d,secondaryColor:f,transform:p,position:g}),o++}return i}}class Et{rr(r,s){const i=r.cmap;for(const o of i.tables)if(o.format===4){const n=o;for(let a=0;a<n.startCount.length;a++)if(s>=n.startCount[a]&&s<=n.endCount[a]){if(n.idRangeOffset[a]===0)return s+n.idDelta[a]&65535;{const h=n.idRangeOffset[a]/2+(s-n.startCount[a])-(n.startCount.length-a);if(h>=0&&h<n.glyphIdArray.length){const u=n.glyphIdArray[h];if(u!==0)return u+n.idDelta[a]&65535}}}}else if(o.format===12){const n=o;for(let a=0;a<n.groups.length;a+=3){const h=n.groups[a],u=n.groups[a+1],d=n.groups[a+2];if(s>=h&&s<=u)return d+(s-h)}}return 0}ir(r,s,i,o,n){const a=n/r.head.unitsPerEm;return{getBoundingBox:()=>({x1:i+s.xMin*a,y1:o+-s.yMax*a,x2:i+s.xMax*a,y2:o+-s.yMin*a}),toSVG:()=>this.nr(s,i,o,a)}}nr(r,s,i,o){if(!r||!r.xs)return"";const{xs:n,ys:a,endPts:h,flags:u}=r;if(!(n&&a&&h&&u))return"";let d="",f=0;for(let p=0;p<h.length;p++){const g=h[p];if(!(g<f)){if(g>=f){const x=s+n[f]*o,b=i-a[f]*o;d+=`M${x.toFixed(2)},${b.toFixed(2)}`;let m=f+1;for(;m<=g;)if(1&u[m]){const y=s+n[m]*o,C=i-a[m]*o;d+=`L${y.toFixed(2)},${C.toFixed(2)}`,m++}else{const y=s+n[m]*o,C=i-a[m]*o;let F=m+1>g?f:m+1;if(1&u[F]){const E=s+n[F]*o,S=i-a[F]*o;d+=`Q${y.toFixed(2)},${C.toFixed(2)} ${E.toFixed(2)},${S.toFixed(2)}`,m=F+1}else{const E=(y+(s+n[F]*o))/2,S=(C+(i-a[F]*o))/2;d+=`Q${y.toFixed(2)},${C.toFixed(2)} ${E.toFixed(2)},${S.toFixed(2)}`,m=F}}d+="Z"}f=g+1}}return d}ar(r,s,i,o,n){const a=r.codePointAt(0)||0,h=this.rr(s,a);let u=null;return s.glyf&&s.glyf[h]!==null?u=s.glyf[h]:(u=A.T.glyf.Xt(s,h),s.glyf[h]=u),this.ir(s,u,i,o,n)}hr(r,s,i,o,n,a,h,u){const d=i+(n-u*(h/s.head.unitsPerEm))/2,f=o+(a+.7*h)/2;return this.ar(r,s,d,f,h).toSVG()||null}}class Rt{constructor(){c(this,"lr");this.lr=new Et}cr(r){return`<?xml version="1.0" encoding="UTF-8" standalone="no"?>
47
47
  <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
48
48
  <svg width="${r.width}" height="${r.height}" viewBox="0 0 ${r.width} ${r.height}"
49
49
  xmlns="http://www.w3.org/2000/svg" version="1.1">
50
50
  <title>textmode art generated via textmode.js</title>
51
- <desc>textmode art visualization generated by textmode.js library</desc>`}lr(){return`
51
+ <desc>textmode art visualization generated by textmode.js library</desc>`}ur(){return`
52
52
  </g>
53
- </svg>`}cr(r,s){if(!s.includeBackgroundRectangles)return"";const i=s.backgroundColor,o=`rgba(${i[0]},${i[1]},${i[2]},${i[3]/255})`;return`
54
- <rect width="${r.width}" height="${r.height}" fill="${o}" />`}ur(r){return`rgba(${r.r},${r.g},${r.b},${r.a/255})`}dr(r,s){const{transform:i,position:o}=r,n=o.cellX+s.cellWidth/2,a=o.cellY+s.cellHeight/2,h=[];if(i.flipHorizontal||i.flipVertical){const u=i.flipHorizontal?-1:1,d=i.flipVertical?-1:1;h.push(`translate(${n} ${a})`),h.push(`scale(${u} ${d})`),h.push(`translate(${-n} ${-a})`)}return i.rotation&&h.push(`rotate(${i.rotation} ${n} ${a})`),h.length?` transform="${h.join(" ")}"`:""}pr(r,s,i){if(!i.includeBackgroundRectangles||r.secondaryColor.a===0)return"";const{position:o}=r,n=this.ur(r.secondaryColor);return i.drawMode==="stroke"?`
53
+ </svg>`}dr(r,s){if(!s.includeBackgroundRectangles)return"";const i=s.backgroundColor,o=`rgba(${i[0]},${i[1]},${i[2]},${i[3]/255})`;return`
54
+ <rect width="${r.width}" height="${r.height}" fill="${o}" />`}pr(r){return`rgba(${r.r},${r.g},${r.b},${r.a/255})`}mr(r,s){const{transform:i,position:o}=r,n=o.cellX+s.cellWidth/2,a=o.cellY+s.cellHeight/2,h=[];if(i.flipHorizontal||i.flipVertical){const u=i.flipHorizontal?-1:1,d=i.flipVertical?-1:1;h.push(`translate(${n} ${a})`),h.push(`scale(${u} ${d})`),h.push(`translate(${-n} ${-a})`)}return i.rotation&&h.push(`rotate(${i.rotation} ${n} ${a})`),h.length?` transform="${h.join(" ")}"`:""}gr(r,s,i){if(!i.includeBackgroundRectangles||r.secondaryColor.a===0)return"";const{position:o}=r,n=this.pr(r.secondaryColor);return i.drawMode==="stroke"?`
55
55
  <rect x="${o.cellX}" y="${o.cellY}" width="${s.cellWidth}" height="${s.cellHeight}" stroke="${n}" fill="none" stroke-width="${i.strokeWidth}" />`:`
56
- <rect x="${o.cellX}" y="${o.cellY}" width="${s.cellWidth}" height="${s.cellHeight}" fill="${n}" />`}ir(r,s,i,o){const n=i.characters[r.charIndex];if(!n)return"";const a=this.ar.nr(n.character,i.font,r.position.cellX,r.position.cellY,s.cellWidth,s.cellHeight,i.fontSize,n.advanceWidth);if(!a)return"";const h=this.ur(r.primaryColor);return o.drawMode==="stroke"?`
56
+ <rect x="${o.cellX}" y="${o.cellY}" width="${s.cellWidth}" height="${s.cellHeight}" fill="${n}" />`}ar(r,s,i,o){const n=i.characters[r.charIndex];if(!n)return"";const a=this.lr.hr(n.character,i.font,r.position.cellX,r.position.cellY,s.cellWidth,s.cellHeight,i.fontSize,n.advanceWidth);if(!a)return"";const h=this.pr(r.primaryColor);return o.drawMode==="stroke"?`
57
57
  <path id="${`path-${r.charIndex}-${r.position.cellX}-${r.position.cellY}`.replace(/\./g,"-")}" d="${a}" stroke="${h}" stroke-width="${o.strokeWidth}" fill="none" />`:`
58
- <path d="${a}" fill="${h}" />`}mr(r,s,i,o){let n="";n+=this.pr(r,s,o);const a=this.dr(r,s),h=this.ir(r,s,i,o);return h&&(a?(n+=`
58
+ <path d="${a}" fill="${h}" />`}_r(r,s,i,o){let n="";n+=this.gr(r,s,o);const a=this.mr(r,s),h=this.ar(r,s,i,o);return h&&(a?(n+=`
59
59
  <g${a}>`,n+=h,n+=`
60
- </g>`):n+=h),n}gr(r,s,i,o){let n=this.hr(s);n+=this.cr(s,o),n+=`
61
- <g id="ascii-cells">`;for(const a of r)n+=this.mr(a,s,i,o);return n+=this.lr(),n}_r(r){return r.replace(/<path[^>]*d=""[^>]*\/>/g,"").replace(/\n\s*\n/g,`
62
- `).replace(/[ \t]+$/gm,"")}}class Rt extends N{vr(r){return this.Ns(r,"image/svg+xml;charset=utf-8")}br(r,s){this.Xs(r,this.Qs(s)+".svg","image/svg+xml;charset=utf-8")}wr(r,s){this.br(r,s||this.Zs())}}class it{constructor(){c(this,"Cr");c(this,"yr");c(this,"$r");this.Cr=new _t,this.yr=new Et,this.$r=new Rt}Fr(r){return{includeBackgroundRectangles:r.includeBackgroundRectangles??!0,drawMode:r.drawMode??"fill",strokeWidth:r.strokeWidth??1,backgroundColor:r.backgroundColor??[0,0,0,0]}}Tr(r,s={}){const i=this.Fr(s),o=this.Cr.Os(r.pipeline),n=this.Cr.tr(o,r.grid),a=this.yr.gr(n,r.grid,r.font,i);return this.yr._r(a)}wr(r,s={}){const i=this.Tr(r,s),o=s.filename||this.$r.Zs();this.$r.wr(i,o)}}class Ft extends j{Mr(r,s,i,o=" "){var h;const n=[];let a=0;for(let u=0;u<s.rows;u++){const d=[];for(let f=0;f<s.cols;f++){const p=4*a,g=this.Bs(r.characterPixels,p),x=((h=i.characters[g])==null?void 0:h.character)||o;d.push(x),a++}n.push(d)}return n}}class Mt{Sr(r,s){const i=[];for(const n of r){let a=n.join("");s.preserveTrailingSpaces||(a=a.replace(/\s+$/,"")),i.push(a)}const o=s.lineEnding==="crlf"?`\r
60
+ </g>`):n+=h),n}vr(r,s,i,o){let n=this.cr(s);n+=this.dr(s,o),n+=`
61
+ <g id="ascii-cells">`;for(const a of r)n+=this._r(a,s,i,o);return n+=this.ur(),n}br(r){return r.replace(/<path[^>]*d=""[^>]*\/>/g,"").replace(/\n\s*\n/g,`
62
+ `).replace(/[ \t]+$/gm,"")}}class At extends X{wr(r){return this.qs(r,"image/svg+xml;charset=utf-8")}Cr(r,s){this.Ys(r,this.Js(s)+".svg","image/svg+xml;charset=utf-8")}yr(r,s){this.Cr(r,s||this.Ks())}}class at{constructor(){c(this,"$r");c(this,"Fr");c(this,"Tr");this.$r=new Tt,this.Fr=new Rt,this.Tr=new At}Mr(r){return{includeBackgroundRectangles:r.includeBackgroundRectangles??!0,drawMode:r.drawMode??"fill",strokeWidth:r.strokeWidth??1,backgroundColor:r.backgroundColor??[0,0,0,0]}}Sr(r,s={}){const i=this.Mr(s),o=this.$r.Ws(r.pipeline),n=this.$r.sr(o,r.grid),a=this.Fr.vr(n,r.grid,r.font,i);return this.Fr.br(a)}yr(r,s={}){const i=this.Sr(r,s),o=s.filename||this.Tr.Ks();this.Tr.yr(i,o)}}class St extends W{Dr(r,s,i,o=" "){var h;const n=[];let a=0;for(let u=0;u<s.rows;u++){const d=[];for(let f=0;f<s.cols;f++){const p=4*a,g=this.Ns(r.characterPixels,p),x=((h=i.characters[g])==null?void 0:h.character)||o;d.push(x),a++}n.push(d)}return n}}class Ut{Rr(r,s){const i=[];for(const n of r){let a=n.join("");s.preserveTrailingSpaces||(a=a.replace(/\s+$/,"")),i.push(a)}const o=s.lineEnding==="crlf"?`\r
63
63
  `:`
64
- `;return i.join(o)}}class At extends N{Dr(r,s){const i=this.Rr(s);this.Xs(r,i,"text/plain;charset=utf-8")}Rr(r){let s=this.Qs(r);return s===".txt"||s.length<=4?this.Zs():s}}class ot{constructor(){c(this,"Cr");c(this,"yr");c(this,"$r");this.Cr=new Ft,this.yr=new Mt,this.$r=new At}Fr(r){return{preserveTrailingSpaces:r.preserveTrailingSpaces??!1,lineEnding:r.lineEnding??"lf",emptyCharacter:r.emptyCharacter??" "}}Vr(r,s={}){const i=this.Fr(s),o=this.Cr.Os(r.pipeline),n=this.Cr.Mr(o,r.grid,r.font,i.emptyCharacter);return this.yr.Sr(n,i)}Dr(r,s={}){const i=this.Vr(r,s),o=s.filename||this.$r.Zs();this.$r.Dr(i,o)}}class Pt extends j{kr(r,s=1,i="transparent"){const o=r.canvas;if(s===1&&i==="transparent")return o;const n=document.createElement("canvas"),a=n.getContext("2d"),h=Math.round(o.width*s),u=Math.round(o.height*s);return n.width=h,n.height=u,i!=="transparent"&&(a.fillStyle=i,a.fillRect(0,0,h,u)),a.imageSmoothingEnabled=!1,a.drawImage(o,0,0,o.width,o.height,0,0,h,u),n}}class Dt{Ir(r,s){const i=this.Pr(s.format);return s.format==="png"?r.toDataURL(i):r.toDataURL(i,s.quality)}async zr(r,s){return new Promise((i,o)=>{const n=this.Pr(s.format),a=h=>{h?i(h):o(Error(`Failed to generate ${s.format.toUpperCase()} blob`))};s.format==="png"?r.toBlob(a,n):r.toBlob(a,n,s.quality)})}Pr(r){switch(r){case"png":return"image/png";case"jpg":return"image/jpeg";case"webp":return"image/webp";default:throw Error("Unsupported image format: "+r)}}}const St={png:"image/png",jpg:"image/jpeg",webp:"image/webp"},nt={png:".png",jpg:".jpg",webp:".webp"};class Ut extends N{Er(r,s,i){this.Gr(r,this.Qs(s)+nt[i])}Gr(r,s){const i=URL.createObjectURL(r);try{const o=document.createElement("a");o.href=i,o.download=s,o.style.display="none",o.rel="noopener",document.body.appendChild(o),o.click(),document.body.removeChild(o)}finally{URL.revokeObjectURL(i)}}Ar(r){return r in St&&r in nt}}class $t{constructor(){c(this,"Cr");c(this,"yr");c(this,"$r");this.Cr=new Pt,this.yr=new Dt,this.$r=new Ut}Fr(r){return{format:r.format??"png",quality:r.quality??1,scale:r.scale??1,backgroundColor:r.backgroundColor??"transparent"}}Ur(r){if(console.log("Validating image export options:",r),!this.$r.Ar(r.format))throw Error(`Saving '${r.format}' files is not supported`);if(r.quality<0||r.quality>1)throw Error("Image quality must be between 0.0 and 1.0");if(r.scale<=0)throw Error("Scale factor must be greater than 0");r.scale>10&&console.warn("Large scale factors may result in very large files and slow performance"),r.format==="jpg"&&r.backgroundColor==="transparent"&&(r.backgroundColor="black")}Lr(r,s={}){const i=this.Fr(s);if(this.Ur(i),i.scale===1&&i.backgroundColor==="transparent")return this.yr.Ir(r.canvas,i);const o=this.Cr.kr(r,i.scale,i.backgroundColor);return this.yr.Ir(o,i)}async zr(r,s={}){const i=this.Fr(s);if(this.Ur(i),i.scale===1&&i.backgroundColor==="transparent")return await this.yr.zr(r.canvas,i);const o=this.Cr.kr(r,i.scale,i.backgroundColor);return await this.yr.zr(o,i)}async Er(r,s={}){const i=await this.zr(r,s),o=s.format??"png",n=s.filename||this.$r.Zs();this.$r.Er(i,n,o)}}const It=l=>class extends l{toString(r={}){return new ot().Vr({pipeline:this.jr,grid:this.ps,font:this.Te},r)}saveStrings(r={}){new ot().Dr({pipeline:this.jr,grid:this.ps,font:this.Te},r)}toSVG(r={}){return new it().Tr(this,r)}saveSVG(r={}){new it().wr(this,r)}async saveCanvas(r,s="png",i={}){await new $t().Er(this.Ye,{...i,filename:r,format:s})}},Lt=l=>class extends l{async loadFont(r){return this.Te.Oe(r).then(()=>{const s=this.Te.maxGlyphDimensions;this.ps.Ke(s.width,s.height),this.jr.ss()})}fontSize(r){if(!C.m(typeof r=="number"&&r>0,"Font size must be a positive number greater than 0.",{method:"fontSize",providedValue:r})||this.Te.fontSize===r)return;this.Te.He(r);const s=this.Te.maxGlyphDimensions;this.ps.Ke(s.width,s.height),this.jr.ss(),this.ve.Ot()}},Gt=l=>class extends l{addConverter(r){return this.jr.add(r)}removeConverter(r){this.jr.remove(r)}};class kt{constructor(){c(this,"ve");c(this,"Te");c(this,"jr");c(this,"Ye");c(this,"ps")}}class H extends function(s,...i){return i.reduce((o,n)=>n(o),s)}(kt,yt,It,Lt,Gt){constructor(s=null,i={}){super();c(this,"ns");c(this,"Hr");c(this,"ls");c(this,"Or");c(this,"Br");c(this,"Wr",null);c(this,"Nr",0);c(this,"Xr");c(this,"qr",!0);c(this,"Yr",0);c(this,"Qr",0);c(this,"Zr",0);c(this,"Jr",[]);c(this,"Kr",10);c(this,"ti",!1);c(this,"ei",!1);c(this,"si",()=>{});c(this,"ri",()=>{});c(this,"ii");this.ns=s,this.ei=s===null,this.Or=i.renderMode??"auto",this.Br=i.frameRate??60,this.Xr=1e3/this.Br}static async create(s=null,i={}){const o=new this(s,i),n=o.ei?i:void 0;let a,h;o.Ye=new et(o.ns,o.ei,n),o.ve=new ct(o.Ye.fs()),o.ei?(a=i.width||800,h=i.height||600):(a=o.Ye.width||800,h=o.Ye.height||600),o.Hr=o.ve.Lt(a,h),o.Te=new K(o.ve,i.fontSize??16),await o.Te.Ue(i.fontSource);const u=o.Te.maxGlyphDimensions;return o.ps=new tt(o.Ye.canvas,u.width,u.height),o.jr=new st(o.ve,o.Te,o.ps),o.oi(),o.ni(),o}oi(){this.ii=()=>{this.ei?this.ri():this.ai()},window.addEventListener("resize",this.ii),window.ResizeObserver&&this.ns&&!this.ei&&(this.ls=new ResizeObserver(()=>{this.ai()}),this.ls.observe(this.ns))}render(){this.hi(),this.Zr++,this.ti?console.warn("Cannot render: Required resources have been disposed"):(this.ei?(this.Hr.begin(),this.si(),this.Hr.end()):this.Hr.update(this.ns),this.jr.hasEnabledConverters()?(this.jr.Hs(this.Hr),this.ve.jt(0),this.ve.Bt(this.jr.texture,this.ps.offsetX,this.ps.offsetY,this.jr.texture.width,this.jr.texture.height)):(this.ve.Ht(),this.ve.Bt(this.Hr,this.ps.offsetX,this.ps.offsetY,this.Hr.width,this.Hr.height)))}ai(){this.Ye.ss(),this.Hr.resize(this.Ye.width,this.Ye.height),this.ps.ss(),this.jr.ss(),this.ve.Ot(),this.Or!=="manual"&&this.render()}ni(){if(this.Or!=="auto"||!this.qr)return;this.Nr=performance.now();const s=i=>{if(!this.qr)return void(this.Wr=null);const o=i-this.Nr;o>=this.Xr&&(this.render(),this.Nr=i-o%this.Xr),this.qr&&(this.Wr=requestAnimationFrame(s))};this.Wr=requestAnimationFrame(s)}hi(){const s=performance.now();if(this.Qr>0){const i=s-this.Qr;this.Jr.push(i),this.Jr.length>this.Kr&&this.Jr.shift();const o=this.Jr.reduce((n,a)=>n+a,0)/this.Jr.length;this.Yr=1e3/o}this.Qr=s}li(){this.Wr&&(cancelAnimationFrame(this.Wr),this.Wr=null)}renderMode(s){this.Or!==s&&(this.li(),this.Or=s,s==="auto"&&this.qr&&this.ni())}frameRate(s){if(s===void 0)return this.Yr;this.Br=s,this.Xr=1e3/s,this.Or==="auto"&&this.qr&&(this.li(),this.ni())}noLoop(){this.qr&&(this.qr=!1,this.Wr&&(cancelAnimationFrame(this.Wr),this.Wr=null))}loop(){this.qr||(this.qr=!0,this.Or==="auto"&&this.ni())}redraw(s=1){if(C.m(typeof s=="number"&&s>0&&Number.isInteger(s),"Redraw count must be a positive integer.",{method:"redraw",providedValue:s}))for(let i=0;i<s;i++)this.render()}isLooping(){return this.Or==="auto"&&this.qr}draw(s){this.si=s}windowResized(s){this.ri=s}resizeCanvas(s,i){this.ei&&(this.Ye.ss(s,i),this.Hr.resize(this.Ye.width,this.Ye.height),this.ps.ss(),this.jr.ss(),this.ve.Ot(),this.Or!=="manual"&&this.render())}destroy(){this.ti||(this.li(),window.removeEventListener("resize",this.ii),this.ls&&this.ls.disconnect(),this.jr.P(),this.Te.P(),this.Hr.P(),this.ve.P(),this.ti=!0)}get grid(){return this.ps}get font(){return this.Te}get mode(){return this.Or}get pipeline(){return this.jr}get frameCount(){return this.Zr}get renderer(){return this.ve}set frameCount(s){this.Zr=s}get width(){return this.Ye.width}get height(){return this.Ye.height}get canvas(){return this.Ye}get isDisposed(){return this.ti}}class G{constructor(){throw new b("Textmode is a static class and cannot be instantiated.")}static async create(r,s={}){if(!(r==null||r instanceof HTMLCanvasElement||r instanceof HTMLVideoElement||typeof r=="object"))throw new b("First parameter must be HTMLCanvasElement, HTMLVideoElement, or options object.");if(typeof s!="object")throw new b("Second parameter must be an options object.");if(r instanceof HTMLCanvasElement||r instanceof HTMLVideoElement)return H.create(r,s);{const i=r||{};return H.create(null,i)}}static setErrorLevel(r){C._(r)}static get version(){return"0.1.9-beta.6"}}const Yt=Object.freeze(Object.defineProperty({__proto__:null},Symbol.toStringTag,{value:"Module"})),Bt=G.create,Vt=G.setErrorLevel,Ot=G.version;w.TextmodeCanvas=et,w.TextmodeColorPalette=rt,w.TextmodeConversionPipeline=st,w.TextmodeErrorLevel=D,w.TextmodeFont=K,w.TextmodeGrid=tt,w.Textmodifier=H,w.converters=Ct,w.create=Bt,w.default=G,w.export=Yt,w.setErrorLevel=Vt,w.textmode=G,w.version=Ot,Object.defineProperties(w,{ci:{value:!0},[Symbol.toStringTag]:{value:"Module"}})},typeof exports=="object"&&typeof module<"u"?e(exports):typeof define=="function"&&define.amd?define(["exports"],e):e((t=typeof globalThis<"u"?globalThis:t||self).textmode={});
64
+ `;return i.join(o)}}class Mt extends X{Vr(r,s){const i=this.Ir(s);this.Ys(r,i,"text/plain;charset=utf-8")}Ir(r){let s=this.Js(r);return s===".txt"||s.length<=4?this.Ks():s}}class ht{constructor(){c(this,"$r");c(this,"Fr");c(this,"Tr");this.$r=new St,this.Fr=new Ut,this.Tr=new Mt}Mr(r){return{preserveTrailingSpaces:r.preserveTrailingSpaces??!1,lineEnding:r.lineEnding??"lf",emptyCharacter:r.emptyCharacter??" "}}kr(r,s={}){const i=this.Mr(s),o=this.$r.Ws(r.pipeline),n=this.$r.Dr(o,r.grid,r.font,i.emptyCharacter);return this.Fr.Rr(n,i)}Vr(r,s={}){const i=this.kr(r,s),o=s.filename||this.Tr.Ks();this.Tr.Vr(i,o)}}class Dt extends W{Er(r,s=1,i="transparent"){const o=r.canvas;if(s===1&&i==="transparent")return o;const n=document.createElement("canvas"),a=n.getContext("2d"),h=Math.round(o.width*s),u=Math.round(o.height*s);return n.width=h,n.height=u,i!=="transparent"&&(a.fillStyle=i,a.fillRect(0,0,h,u)),a.imageSmoothingEnabled=!1,a.drawImage(o,0,0,o.width,o.height,0,0,h,u),n}}class Pt{Pr(r,s){const i=this.Ar(s.format);return s.format==="png"?r.toDataURL(i):r.toDataURL(i,s.quality)}async zr(r,s){return new Promise((i,o)=>{const n=this.Ar(s.format),a=h=>{h?i(h):o(Error(`Failed to generate ${s.format.toUpperCase()} blob`))};s.format==="png"?r.toBlob(a,n):r.toBlob(a,n,s.quality)})}Ar(r){switch(r){case"png":return"image/png";case"jpg":return"image/jpeg";case"webp":return"image/webp";default:throw Error("Unsupported image format: "+r)}}}const $t={png:"image/png",jpg:"image/jpeg",webp:"image/webp"},lt={png:".png",jpg:".jpg",webp:".webp"};class Gt extends X{Gr(r,s,i){this.Ur(r,this.Js(s)+lt[i])}Ur(r,s){const i=URL.createObjectURL(r);try{const o=document.createElement("a");o.href=i,o.download=s,o.style.display="none",o.rel="noopener",document.body.appendChild(o),o.click(),document.body.removeChild(o)}finally{URL.revokeObjectURL(i)}}Lr(r){return r in $t&&r in lt}}class It{constructor(){c(this,"$r");c(this,"Fr");c(this,"Tr");this.$r=new Dt,this.Fr=new Pt,this.Tr=new Gt}Mr(r){return{format:r.format??"png",quality:r.quality??1,scale:r.scale??1,backgroundColor:r.backgroundColor??"transparent"}}jr(r){if(console.log("Validating image export options:",r),!this.Tr.Lr(r.format))throw Error(`Saving '${r.format}' files is not supported`);if(r.quality<0||r.quality>1)throw Error("Image quality must be between 0.0 and 1.0");if(r.scale<=0)throw Error("Scale factor must be greater than 0");r.scale>10&&console.warn("Large scale factors may result in very large files and slow performance"),r.format==="jpg"&&r.backgroundColor==="transparent"&&(r.backgroundColor="black")}Or(r,s={}){const i=this.Mr(s);if(this.jr(i),i.scale===1&&i.backgroundColor==="transparent")return this.Fr.Pr(r.canvas,i);const o=this.$r.Er(r,i.scale,i.backgroundColor);return this.Fr.Pr(o,i)}async zr(r,s={}){const i=this.Mr(s);if(this.jr(i),i.scale===1&&i.backgroundColor==="transparent")return await this.Fr.zr(r.canvas,i);const o=this.$r.Er(r,i.scale,i.backgroundColor);return await this.Fr.zr(o,i)}async Gr(r,s={}){const i=await this.zr(r,s),o=s.format??"png",n=s.filename||this.Tr.Ks();this.Tr.Gr(i,n,o)}}const Bt=l=>class extends l{toString(r={}){return new ht().kr({pipeline:this.Hr,grid:this._s,font:this.Se},r)}saveStrings(r={}){new ht().Vr({pipeline:this.Hr,grid:this._s,font:this.Se},r)}toSVG(r={}){return new at().Sr(this,r)}saveSVG(r={}){new at().yr(this,r)}async saveCanvas(r,s="png",i={}){await new It().Gr(this.Ze,{...i,filename:r,format:s})}},Ot=l=>class extends l{async loadFont(r){return this.Se.We(r).then(()=>{const s=this.Se.maxGlyphDimensions;this._s.es(s.width,s.height),this.Hr.ns()})}fontSize(r){if(!_.m(typeof r=="number"&&r>0,"Font size must be a positive number greater than 0.",{method:"fontSize",providedValue:r})||this.Se.fontSize===r)return;this.Se.Be(r);const s=this.Se.maxGlyphDimensions;this._s.es(s.width,s.height),this.Hr.ns(),this.be.Wt()}},Lt=l=>class extends l{addConverter(r){return this.Hr.add(r)}removeConverter(r){this.Hr.remove(r)}};class kt{constructor(){c(this,"be");c(this,"Se");c(this,"Hr");c(this,"Ze");c(this,"_s")}}class j extends function(s,...i){return i.reduce((o,n)=>n(o),s)}(kt,yt,Bt,Ot,Lt){constructor(s=null,i={}){super();c(this,"ls");c(this,"Br");c(this,"us");c(this,"Wr");c(this,"Nr");c(this,"Xr",null);c(this,"qr",0);c(this,"Yr");c(this,"Qr",!0);c(this,"Zr",0);c(this,"Jr",0);c(this,"Kr",0);c(this,"ti",[]);c(this,"ei",10);c(this,"si",!1);c(this,"ri",!1);c(this,"ii",()=>{});c(this,"oi",()=>{});c(this,"ni");this.ls=s,this.ri=s===null,this.Wr=i.renderMode??"auto",this.Nr=i.frameRate??60,this.Yr=1e3/this.Nr}static async create(s=null,i={}){const o=new this(s,i),n=o.ri?i:void 0;let a,h;o.Ze=new st(o.ls,o.ri,n),o.be=new ft(o.Ze.ps()),o.ri?(a=i.width||800,h=i.height||600):(a=o.Ze.width||800,h=o.Ze.height||600),o.Br=o.be.Ot(a,h),o.Se=new et(o.be,i.fontSize??16),await o.Se.je(i.fontSource);const u=o.Se.maxGlyphDimensions;return o._s=new rt(o.Ze.canvas,u.width,u.height),o.Hr=new nt(o.be,o.Se,o._s),o.ai(),o.hi(),o}ai(){this.ni=()=>{this.ri?this.oi():this.li()},window.addEventListener("resize",this.ni),window.ResizeObserver&&this.ls&&!this.ri&&(this.us=new ResizeObserver(()=>{this.li()}),this.us.observe(this.ls))}render(){this.ci(),this.Kr++,this.si?console.warn("Cannot render: Required resources have been disposed"):(this.ri?(this.Br.begin(),this.ii(),this.Br.end()):this.Br.P(this.ls),this.Hr.hasEnabledConverters()?(this.Hr.Bs(this.Br),this.be.Ht(0),this.be.Nt(this.Hr.texture,this._s.offsetX,this._s.offsetY,this.Hr.texture.width,this.Hr.texture.height)):(this.be.Bt(),this.be.Nt(this.Br,this._s.offsetX,this._s.offsetY,this.Br.width,this.Br.height)))}li(){this.Ze.ns(),this.Br.resize(this.Ze.width,this.Ze.height),this._s.ns(),this.Hr.ns(),this.be.Wt(),this.Wr!=="manual"&&this.render()}hi(){if(this.Wr!=="auto"||!this.Qr)return;this.qr=performance.now();const s=i=>{if(!this.Qr)return void(this.Xr=null);const o=i-this.qr;o>=this.Yr&&(this.render(),this.qr=i-o%this.Yr),this.Qr&&(this.Xr=requestAnimationFrame(s))};this.Xr=requestAnimationFrame(s)}ci(){const s=performance.now();if(this.Jr>0){const i=s-this.Jr;this.ti.push(i),this.ti.length>this.ei&&this.ti.shift();const o=this.ti.reduce((n,a)=>n+a,0)/this.ti.length;this.Zr=1e3/o}this.Jr=s}ui(){this.Xr&&(cancelAnimationFrame(this.Xr),this.Xr=null)}renderMode(s){this.Wr!==s&&(this.ui(),this.Wr=s,s==="auto"&&this.Qr&&this.hi())}frameRate(s){if(s===void 0)return this.Zr;this.Nr=s,this.Yr=1e3/s,this.Wr==="auto"&&this.Qr&&(this.ui(),this.hi())}noLoop(){this.Qr&&(this.Qr=!1,this.Xr&&(cancelAnimationFrame(this.Xr),this.Xr=null))}loop(){this.Qr||(this.Qr=!0,this.Wr==="auto"&&this.hi())}redraw(s=1){if(_.m(typeof s=="number"&&s>0&&Number.isInteger(s),"Redraw count must be a positive integer.",{method:"redraw",providedValue:s}))for(let i=0;i<s;i++)this.render()}isLooping(){return this.Wr==="auto"&&this.Qr}draw(s){this.ii=s}windowResized(s){this.oi=s}resizeCanvas(s,i){this.ri&&(this.Ze.ns(s,i),this.Br.resize(this.Ze.width,this.Ze.height),this._s.ns(),this.Hr.ns(),this.be.Wt(),this.Wr!=="manual"&&this.render())}destroy(){this.si||(this.ui(),window.removeEventListener("resize",this.ni),this.us&&this.us.disconnect(),this.Hr.A(),this.Se.A(),this.Br.A(),this.be.A(),this.si=!0)}get grid(){return this._s}get font(){return this.Se}get mode(){return this.Wr}get pipeline(){return this.Hr}get frameCount(){return this.Kr}get renderer(){return this.be}set frameCount(s){this.Kr=s}get width(){return this.Ze.width}get height(){return this.Ze.height}get canvas(){return this.Ze}get isDisposed(){return this.si}}class V{constructor(){throw new v("Textmode is a static class and cannot be instantiated.")}static async create(r,s={}){if(!(r==null||r instanceof HTMLCanvasElement||r instanceof HTMLVideoElement||typeof r=="object"))throw new v("First parameter must be HTMLCanvasElement, HTMLVideoElement, or options object.");if(typeof s!="object")throw new v("Second parameter must be an options object.");if(r instanceof HTMLCanvasElement||r instanceof HTMLVideoElement)return j.create(r,s);{const i=r||{};return j.create(null,i)}}static setErrorLevel(r){_._(r)}static get version(){return"0.1.9"}}const Vt=Object.freeze(Object.defineProperty({__proto__:null},Symbol.toStringTag,{value:"Module"})),zt=Object.freeze(Object.defineProperty({__proto__:null,DEFAULT_FRAMEBUFFER_OPTIONS:{filter:"nearest",wrap:"clamp",format:"rgba",type:"unsigned_byte"},Framebuffer:q,Shader:Q},Symbol.toStringTag,{value:"Module"})),Nt=V.create,Ht=V.setErrorLevel,Wt=V.version;w.TextmodeCanvas=st,w.TextmodeColorPalette=it,w.TextmodeConversionPipeline=nt,w.TextmodeErrorLevel=M,w.TextmodeFont=et,w.TextmodeGrid=rt,w.Textmodifier=j,w.converters=Ft,w.create=Nt,w.export=Vt,w.rendering=zt,w.setErrorLevel=Ht,w.textmode=V,w.version=Wt,Object.defineProperty(w,Symbol.toStringTag,{value:"Module"})},typeof exports=="object"&&typeof module<"u"?e(exports):typeof define=="function"&&define.amd?define(["exports"],e):e((t=typeof globalThis<"u"?globalThis:t||self).textmode={});
@@ -1,7 +1,8 @@
1
- import { Framebuffer } from './rendering/webgl/Framebuffer';
1
+ import { Framebuffer } from './rendering/core/Framebuffer';
2
2
  import type { GLRenderer } from './rendering/webgl/Renderer';
3
3
  /**
4
4
  * A 1D color palette stored in a framebuffer that is used to pass colors to shaders.
5
+ * @ignore
5
6
  */
6
7
  export declare class TextmodeColorPalette {
7
8
  /** The framebuffer used to store the color palette. */
@@ -31,8 +32,4 @@ export declare class TextmodeColorPalette {
31
32
  * Get the framebuffer containing the colors of the palette.
32
33
  */
33
34
  get framebuffer(): Framebuffer;
34
- /**
35
- * Get the texture from the framebuffer for use in shaders.
36
- */
37
- get texture(): WebGLTexture;
38
35
  }
@@ -1,5 +1,7 @@
1
1
  import type { FramebufferData } from './types';
2
2
  import { DataExtractor } from '../base';
3
+ import type { TextmodeGrid } from '../../textmode/Grid';
4
+ import type { TextmodeFont } from '../../textmode/font';
3
5
  /**
4
6
  * Extracts and processes data from framebuffers for TXT generation.
5
7
  * This class handles the conversion of raw pixel data into character arrays.
@@ -13,7 +15,5 @@ export declare class TXTDataExtractor extends DataExtractor {
13
15
  * @param emptyCharacter Character to use for empty cells
14
16
  * @returns 2D array of characters (rows x columns)
15
17
  */
16
- $extractCharacterGrid(framebufferData: FramebufferData, grid: any, // TextmodeGrid type - avoiding import to prevent circular dependency
17
- font: any, // TextmodeFont type - avoiding import to prevent circular dependency
18
- emptyCharacter?: string): string[][];
18
+ $extractCharacterGrid(framebufferData: FramebufferData, grid: TextmodeGrid, font: TextmodeFont, emptyCharacter?: string): string[][];
19
19
  }
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * TXT-specific type definitions for the textmode.js library.
3
3
  */
4
+ import type { TextmodeFont, TextmodeGrid } from '../..';
5
+ import type { TextmodeConversionPipeline } from '../../textmode/ConversionPipeline';
4
6
  /**
5
7
  * Options for exporting the textmode content to TXT format.
6
8
  */
@@ -43,9 +45,9 @@ export interface TXTGenerationOptions {
43
45
  * Data required for textmode rendering export
44
46
  */
45
47
  export interface TextmodeRenderingData {
46
- pipeline: any;
47
- grid: any;
48
- font: any;
48
+ pipeline: TextmodeConversionPipeline;
49
+ grid: TextmodeGrid;
50
+ font: TextmodeFont;
49
51
  }
50
52
  /**
51
53
  * Re-export shared types from SVG module that are also used by TXT exporter
@@ -13,7 +13,8 @@ export { TextmodeErrorLevel } from './errors/ErrorHandler';
13
13
  /** Contains all converters that can be added to a rendering pipeline to shape the textmode output. */
14
14
  export * as converters from './textmode/converters';
15
15
  export { Textmode as textmode } from './Textmode';
16
- export default Textmode;
16
+ /** Contains all rendering-related utilities and components. */
17
+ export * as rendering from './rendering/core';
17
18
  /**
18
19
  * Exports the create, setErrorLevel, and version functions from the Textmode class for UMD compatibility,
19
20
  * so calls like `textmode.create()` can be used.
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Common framebuffer configuration options
3
+ */
4
+ export type FramebufferOptions = {
5
+ /** Texture filtering mode */
6
+ filter?: 'nearest' | 'linear';
7
+ /** Texture wrapping mode */
8
+ wrap?: 'clamp' | 'repeat';
9
+ /** Texture format */
10
+ format?: 'rgba' | 'rgb';
11
+ /** Data type for texture data */
12
+ type?: 'unsigned_byte' | 'float';
13
+ };
14
+ /**
15
+ * Core interface that all framebuffer implementations must satisfy.
16
+ * Defines the contract for render targets across different graphics APIs.
17
+ * @ignore
18
+ */
19
+ export interface IFramebuffer {
20
+ /** Width of the framebuffer in pixels */
21
+ readonly width: number;
22
+ /** Height of the framebuffer in pixels */
23
+ readonly height: number;
24
+ /** Current pixel data *(if loaded)* */
25
+ readonly pixels: Uint8Array | null;
26
+ /**
27
+ * Begin rendering to this framebuffer.
28
+ * Saves current render state and sets this framebuffer as the active render target.
29
+ */
30
+ begin(): void;
31
+ /**
32
+ * End rendering to this framebuffer and restore previous render state.
33
+ */
34
+ end(): void;
35
+ /**
36
+ * Resize the framebuffer to new dimensions.
37
+ * @param width New width in pixels
38
+ * @param height New height in pixels
39
+ */
40
+ resize(width: number, height: number): void;
41
+ /**
42
+ * Update the framebuffer texture with media source content.
43
+ * @param source Canvas or video element to copy from
44
+ * @ignore
45
+ */
46
+ $update(source: HTMLCanvasElement | HTMLVideoElement): void;
47
+ /**
48
+ * Update the framebuffer texture with raw pixel data.
49
+ * @param pixelData RGBA pixel data
50
+ * @param width Width of the pixel data
51
+ * @param height Height of the pixel data
52
+ */
53
+ updatePixels(pixelData: Uint8Array, width: number, height: number): void;
54
+ /**
55
+ * Load pixel data from the framebuffer into the pixels property.
56
+ * This operation may be expensive and should be used sparingly.
57
+ */
58
+ loadPixels(): void;
59
+ /**
60
+ * Get pixel data from the framebuffer.
61
+ * Overloaded to support different access patterns:
62
+ * - No parameters: returns entire framebuffer as `Uint8Array`
63
+ * - Two parameters `(x, y)`: returns single pixel as `RGBA` array
64
+ * - Four parameters `(x, y, w, h)`: returns region as `Uint8Array`
65
+ */
66
+ get(): Uint8Array;
67
+ get(x: number, y: number): [number, number, number, number];
68
+ get(x: number, y: number, w: number, h: number): Uint8Array;
69
+ /**
70
+ * Dispose of resources used by this framebuffer.
71
+ * After calling this method, the framebuffer should not be used.
72
+ * @ignore
73
+ */
74
+ $dispose(): void;
75
+ }
76
+ /**
77
+ * Abstract base class for framebuffer implementations.
78
+ */
79
+ export declare abstract class Framebuffer implements IFramebuffer {
80
+ protected _width: number;
81
+ protected _height: number;
82
+ protected _options: FramebufferOptions;
83
+ protected _pixels: Uint8Array | null;
84
+ /**
85
+ * Creates an instance of the Framebuffer class.
86
+ * @param width - The width of the framebuffer.
87
+ * @param height - The height of the framebuffer.
88
+ * @param options - Optional configuration options for the framebuffer.
89
+ * @ignore
90
+ */
91
+ constructor(width: number, height?: number, options?: FramebufferOptions);
92
+ get width(): number;
93
+ get height(): number;
94
+ get pixels(): Uint8Array | null;
95
+ get options(): FramebufferOptions;
96
+ /**
97
+ * Validate and clamp coordinates to framebuffer bounds.
98
+ * @param x X coordinate
99
+ * @param y Y coordinate
100
+ * @param showWarning Whether to show warning for out-of-bounds coordinates
101
+ * @returns Clamped coordinates
102
+ */
103
+ protected validateCoordinates(x: number, y: number, showWarning?: boolean): [number, number];
104
+ /**
105
+ * Validate and clamp region bounds to framebuffer dimensions.
106
+ * @param x X coordinate
107
+ * @param y Y coordinate
108
+ * @param w Width
109
+ * @param h Height
110
+ * @returns Clamped region bounds
111
+ */
112
+ protected validateRegion(x: number, y: number, w: number, h: number): [number, number, number, number];
113
+ /**
114
+ * Update internal dimensions and clear pixel cache.
115
+ * Should be called by subclasses when resizing.
116
+ * @param width New width
117
+ * @param height New height
118
+ */
119
+ protected updateDimensions(width: number, height: number): void;
120
+ abstract begin(): void;
121
+ abstract end(): void;
122
+ abstract resize(width: number, height: number): void;
123
+ abstract $update(source: HTMLCanvasElement | HTMLVideoElement): void;
124
+ abstract updatePixels(pixelData: Uint8Array, width: number, height: number): void;
125
+ abstract loadPixels(): void;
126
+ abstract get(): Uint8Array;
127
+ abstract get(x: number, y: number): [number, number, number, number];
128
+ abstract get(x: number, y: number, w: number, h: number): Uint8Array;
129
+ abstract $dispose(): void;
130
+ }
131
+ /**
132
+ * Default framebuffer options used when no options are specified.
133
+ *
134
+ * **Default values:**
135
+ * - `filter`: `'nearest'` - Use nearest neighbor filtering for sharp pixels
136
+ * - `wrap`: `'clamp'` - Clamp texture coordinates to edges
137
+ * - `format`: `'rgba'` - Use RGBA color format with alpha channel
138
+ * - `type`: `'unsigned_byte'` - Store color components as 8-bit unsigned integers *(0-255)*
139
+ */
140
+ export declare const DEFAULT_FRAMEBUFFER_OPTIONS: FramebufferOptions;