textmode.js
Version:
Apply real-time ASCII conversion to any HTML canvas.
7 lines (5 loc) • 75 kB
JavaScript
(function(v,_){typeof exports=="object"&&typeof module<"u"?_(exports):typeof define=="function"&&define.amd?define(["exports"],_):(v=typeof globalThis<"u"?globalThis:v||self,_(v.textmode={}))})(this,function(v){"use strict";var Oe=Object.defineProperty;var We=(v,_,E)=>_ in v?Oe(v,_,{enumerable:!0,configurable:!0,writable:!0,value:E}):v[_]=E;var o=(v,_,E)=>We(v,typeof _!="symbol"?_+"":_,E);class _ extends Error{constructor(t,r,i={}){const s=_.createFormattedMessage(t,i);super(s);o(this,"originalError");o(this,"context");this.name="TextmodeError",this.originalError=r,this.context=i}static createFormattedMessage(t,r){let i=t;if(r&&Object.keys(r).length>0){i+=`
📋 Context:`;for(const[s,a]of Object.entries(r)){const n=_.formatValue(a);i+=`
- ${s}: ${n}`}}return i+=`
`,i+="↓".repeat(24)+`
`,i}static formatValue(t){if(t===null)return"null";if(t===void 0)return"undefined";if(typeof t=="string")return`"${t}"`;if(typeof t=="number"||typeof t=="boolean")return String(t);if(Array.isArray(t))return t.length===0?"[]":t.length<=5?`[${t.map(r=>_.formatValue(r)).join(", ")}]`:`[${t.slice(0,3).map(r=>_.formatValue(r)).join(", ")}, ... +${t.length-3} more]`;if(typeof t=="object"){const r=Object.keys(t);return r.length===0?"{}":r.length<=3?`{ ${r.map(a=>`${a}: ${_.formatValue(t[a])}`).join(", ")} }`:`{ ${r.slice(0,2).map(s=>`${s}: ${_.formatValue(t[s])}`).join(", ")}, ... +${r.length-2} more }`}return String(t)}}var E=(l=>(l[l.SILENT=0]="SILENT",l[l.WARNING=1]="WARNING",l[l.ERROR=2]="ERROR",l[l.THROW=3]="THROW",l))(E||{});const U=class U{constructor(){o(this,"_options",{globalLevel:3})}static getInstance(){return U._instance||(U._instance=new U),U._instance}_handle(e,t,r){const i="[textmode.js]";switch(this._options.globalLevel){case 0:return!1;case 1:return console.group(`%c${i} Oops! (╯°□°)╯︵ Something went wrong in your code.`,"color: #f44336; font-weight: bold; background: #ffebee; padding: 2px 6px; border-radius: 3px;"),console.warn(_.createFormattedMessage(e,t)),console.groupEnd(),!1;case 2:return console.group(`%c${i} Oops! (╯°□°)╯︵ Something went wrong in your code.`,"color: #f44336; font-weight: bold; background: #ffebee; padding: 2px 6px; border-radius: 3px;"),console.error(_.createFormattedMessage(e,t)),console.groupEnd(),!1;case 3:default:const s=new _(e,r,t);throw console.group(`%c${i} Oops! (╯°□°)╯︵ Something went wrong in your code.`,"color: #d32f2f; font-weight: bold; background: #ffcdd2; padding: 2px 6px; border-radius: 3px;"),s}}validate(e,t,r){return e?!0:(this._handle(t,r),!1)}setGlobalLevel(e){this._options.globalLevel=e}};o(U,"_instance",null);let V=U;const C=V.getInstance();class ie{constructor(e,t,r=t,i={}){o(this,"gl");o(this,"_framebuffer");o(this,"_texture");o(this,"_width");o(this,"_height");o(this,"options");o(this,"previousState",null);o(this,"_pixels",null);this.gl=e,this._width=t,this._height=r,this.options={filter:"nearest",wrap:"clamp",format:"rgba",type:"unsigned_byte",...i},this._texture=this.createTexture(),this._framebuffer=e.createFramebuffer(),this.attachTexture()}createTexture(){const{gl:e}=this,t=e.createTexture();e.bindTexture(e.TEXTURE_2D,t);const r=this.options.filter==="linear"?e.LINEAR:e.NEAREST,i=this.options.wrap==="repeat"?e.REPEAT:e.CLAMP_TO_EDGE;return e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,r),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,r),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,i),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,i),this.updateTextureSize(),t}updateTextureSize(){const{gl:e}=this,t=e.RGBA,r=e.RGBA,i=this.options.type==="float"?e.FLOAT:e.UNSIGNED_BYTE;e.texImage2D(e.TEXTURE_2D,0,t,this._width,this._height,0,r,i,null)}attachTexture(){const{gl:e}=this;e.bindFramebuffer(e.FRAMEBUFFER,this._framebuffer),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this._texture,0),e.bindFramebuffer(e.FRAMEBUFFER,null)}update(e){const{gl:t}=this;e instanceof HTMLVideoElement&&e.readyState<2||(t.bindTexture(t.TEXTURE_2D,this._texture),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,e),t.bindTexture(t.TEXTURE_2D,null))}updatePixels(e,t,r){const{gl:i}=this;i.bindTexture(i.TEXTURE_2D,this._texture),i.texImage2D(i.TEXTURE_2D,0,i.RGBA,t,r,0,i.RGBA,i.UNSIGNED_BYTE,e),i.bindTexture(i.TEXTURE_2D,null)}resize(e,t){const{gl:r}=this;this._width=e,this._height=t,r.bindTexture(r.TEXTURE_2D,this._texture),this.updateTextureSize(),r.bindTexture(r.TEXTURE_2D,null)}begin(){const{gl:e}=this;this.previousState={framebuffer:e.getParameter(e.FRAMEBUFFER_BINDING),viewport:e.getParameter(e.VIEWPORT)},e.bindFramebuffer(e.FRAMEBUFFER,this._framebuffer),e.viewport(0,0,this._width,this._height)}end(){if(!this.previousState)return;const{gl:e}=this;e.bindFramebuffer(e.FRAMEBUFFER,this.previousState.framebuffer),e.viewport(...this.previousState.viewport),this.previousState=null}loadPixels(){const{gl:e}=this;this._pixels||(this._pixels=new Uint8Array(this._width*this._height*4));const t=e.getParameter(e.FRAMEBUFFER_BINDING);e.bindFramebuffer(e.FRAMEBUFFER,this._framebuffer),e.readPixels(0,0,this._width,this._height,e.RGBA,e.UNSIGNED_BYTE,this._pixels),e.bindFramebuffer(e.FRAMEBUFFER,t)}get(e,t,r,i){const{gl:s}=this;if(e===void 0&&t===void 0){const a=new Uint8Array(this._width*this._height*4),n=s.getParameter(s.FRAMEBUFFER_BINDING);return s.bindFramebuffer(s.FRAMEBUFFER,this._framebuffer),s.readPixels(0,0,this._width,this._height,s.RGBA,s.UNSIGNED_BYTE,a),s.bindFramebuffer(s.FRAMEBUFFER,n),a}else if(r===void 0&&i===void 0){(e<0||t<0||e>=this._width||t>=this._height)&&(console.warn("The x and y values passed to Framebuffer.get are outside of its range and will be clamped."),e=Math.max(0,Math.min(e,this._width-1)),t=Math.max(0,Math.min(t,this._height-1)));const a=new Uint8Array(4),n=s.getParameter(s.FRAMEBUFFER_BINDING);return s.bindFramebuffer(s.FRAMEBUFFER,this._framebuffer),s.readPixels(e,t,1,1,s.RGBA,s.UNSIGNED_BYTE,a),s.bindFramebuffer(s.FRAMEBUFFER,n),[a[0],a[1],a[2],a[3]]}else{e=Math.max(0,Math.min(e,this._width-1)),t=Math.max(0,Math.min(t,this._height-1)),r=Math.max(1,Math.min(r,this._width-e)),i=Math.max(1,Math.min(i,this._height-t));const a=new Uint8Array(r*i*4),n=s.getParameter(s.FRAMEBUFFER_BINDING);return s.bindFramebuffer(s.FRAMEBUFFER,this._framebuffer),s.readPixels(e,t,r,i,s.RGBA,s.UNSIGNED_BYTE,a),s.bindFramebuffer(s.FRAMEBUFFER,n),a}}get framebuffer(){return this._framebuffer}get texture(){return this._texture}get width(){return this._width}get height(){return this._height}get pixels(){return this._pixels}}class j{constructor(e,t,r){o(this,"gl");o(this,"x");o(this,"y");this.gl=e,this.x=t,this.y=r}}class D{constructor(e,t,r,i,s){o(this,"gl");o(this,"vertexBuffer");o(this,"vertexCount",6);o(this,"bytesPerVertex");this.gl=e,this.bytesPerVertex=16;const a=e.getParameter(e.VIEWPORT),n=a[2],h=a[3],c=e.getParameter(e.FRAMEBUFFER_BINDING)!==null,u=t/n*2-1,d=(t+i)/n*2-1;let f,g;c?(f=r/h*2-1,g=(r+s)/h*2-1):(f=1-r/h*2,g=1-(r+s)/h*2);let x,p,F,w;x=u,F=d,p=f,w=g;const b=this.generateVertices(x,p,F,w);this.vertexBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.vertexBuffer),e.bufferData(e.ARRAY_BUFFER,b,e.STATIC_DRAW)}generateVertices(e,t,r,i){return new Float32Array([e,i,0,1,r,i,1,1,e,t,0,0,e,t,0,0,r,i,1,1,r,t,1,0])}render(){this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer);const e=this.gl.getParameter(this.gl.CURRENT_PROGRAM);let t=this.gl.getAttribLocation(e,"a_position"),r=this.gl.getAttribLocation(e,"a_texCoord");this.gl.enableVertexAttribArray(t),this.gl.vertexAttribPointer(t,2,this.gl.FLOAT,!1,this.bytesPerVertex,0),this.gl.enableVertexAttribArray(r),this.gl.vertexAttribPointer(r,2,this.gl.FLOAT,!1,this.bytesPerVertex,8),this.gl.drawArrays(this.gl.TRIANGLES,0,this.vertexCount),this.gl.disableVertexAttribArray(t),this.gl.disableVertexAttribArray(r)}}class se extends j{constructor(t,r,i,s,a){super(t,r,i);o(this,"width");o(this,"height");this.width=s,this.height=a}renderFill(){new D(this.gl,this.x,this.y,this.width,this.height).render()}renderStroke(t){if(t<=0)return;const r=new D(this.gl,this.x,this.y,this.width,t),i=new D(this.gl,this.x+this.width-t,this.y,t,this.height),s=new D(this.gl,this.x,this.y+this.height-t,this.width,t),a=new D(this.gl,this.x,this.y,t,this.height);r.render(),i.render(),s.render(),a.render()}}class ae{constructor(e,t,r,i,s,a){o(this,"gl");o(this,"vertexBuffer");o(this,"vertexCount",6);o(this,"bytesPerVertex");this.gl=e,this.bytesPerVertex=16;const n=e.getParameter(e.VIEWPORT),h=n[2],c=n[3],u=e.getParameter(e.FRAMEBUFFER_BINDING)!==null,d=i-t,f=s-r,g=Math.sqrt(d*d+f*f);if(g===0){const Ne=this.generateVertices(0,0,0,0);this.vertexBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.vertexBuffer),e.bufferData(e.ARRAY_BUFFER,Ne,e.STATIC_DRAW);return}const x=d/g,F=-(f/g),w=x,b=a/2,y=t+F*b,B=r+w*b,A=t-F*b,R=r-w*b,H=i+F*b,G=s+w*b,ke=i-F*b,re=s-w*b,$e=y/h*2-1,ze=A/h*2-1,Le=H/h*2-1,Xe=ke/h*2-1;let N,O,W,Y;u?(N=B/c*2-1,O=R/c*2-1,W=G/c*2-1,Y=re/c*2-1):(N=1-B/c*2,O=1-R/c*2,W=1-G/c*2,Y=1-re/c*2);const He=this.generateLineVertices($e,N,ze,O,Le,W,Xe,Y);this.vertexBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.vertexBuffer),e.bufferData(e.ARRAY_BUFFER,He,e.STATIC_DRAW)}generateVertices(e,t,r,i){return new Float32Array([e,i,0,1,r,i,1,1,e,t,0,0,e,t,0,0,r,i,1,1,r,t,1,0])}generateLineVertices(e,t,r,i,s,a,n,h){return new Float32Array([e,t,0,0,r,i,0,1,s,a,1,0,r,i,0,1,n,h,1,1,s,a,1,0])}render(){this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer);const e=this.gl.getParameter(this.gl.CURRENT_PROGRAM);let t=this.gl.getAttribLocation(e,"a_position"),r=this.gl.getAttribLocation(e,"a_texCoord");this.gl.enableVertexAttribArray(t),this.gl.vertexAttribPointer(t,2,this.gl.FLOAT,!1,this.bytesPerVertex,0),this.gl.enableVertexAttribArray(r),this.gl.vertexAttribPointer(r,2,this.gl.FLOAT,!1,this.bytesPerVertex,8),this.gl.drawArrays(this.gl.TRIANGLES,0,this.vertexCount),this.gl.disableVertexAttribArray(t),this.gl.disableVertexAttribArray(r)}}class ne extends j{constructor(t,r,i,s,a){super(t,r,i);o(this,"x2");o(this,"y2");this.x2=s,this.y2=a}renderFill(){}renderStroke(t){if(t<=0)return;new ae(this.gl,this.x,this.y,this.x2,this.y2,t).render()}}class T{constructor(e,t,r){o(this,"gl");o(this,"program");o(this,"uniformLocations",new Map);o(this,"attributeLocations",new Map);o(this,"textureUnitCounter",0);this.gl=e,this.program=this.createProgram(t,r),this.cacheLocations()}createProgram(e,t){const r=this.createShader(this.gl.VERTEX_SHADER,e),i=this.createShader(this.gl.FRAGMENT_SHADER,t),s=this.gl.createProgram();if(this.gl.attachShader(s,r),this.gl.attachShader(s,i),this.gl.linkProgram(s),!this.gl.getProgramParameter(s,this.gl.LINK_STATUS)){const a=this.gl.getProgramInfoLog(s);throw new Error(`Shader program link error: ${a}`)}return this.gl.deleteShader(r),this.gl.deleteShader(i),s}createShader(e,t){const r=this.gl.createShader(e);if(this.gl.shaderSource(r,t),this.gl.compileShader(r),!this.gl.getShaderParameter(r,this.gl.COMPILE_STATUS)){const i=this.gl.getShaderInfoLog(r);throw this.gl.deleteShader(r),new Error(`Shader compilation error: ${i}`)}return r}cacheLocations(){const e=this.gl.getProgramParameter(this.program,this.gl.ACTIVE_UNIFORMS);for(let r=0;r<e;r++){const i=this.gl.getActiveUniform(this.program,r);if(i){const s=this.gl.getUniformLocation(this.program,i.name);s&&this.uniformLocations.set(i.name,s)}}const t=this.gl.getProgramParameter(this.program,this.gl.ACTIVE_ATTRIBUTES);for(let r=0;r<t;r++){const i=this.gl.getActiveAttrib(this.program,r);if(i){const s=this.gl.getAttribLocation(this.program,i.name);this.attributeLocations.set(i.name,s)}}}use(){this.gl.useProgram(this.program),this.resetTextureUnits()}setUniform(e,t){const r=this.uniformLocations.get(e);if(!r)return;const i=this.getUniformInfo(e);if(typeof t=="number")i&&i.type===this.gl.INT?this.gl.uniform1i(r,Math.floor(t)):this.gl.uniform1f(r,t);else if(typeof t=="boolean")this.gl.uniform1i(r,t?1:0);else if(Array.isArray(t))if(i&&(i.type===this.gl.INT_VEC2||i.type===this.gl.INT_VEC3||i.type===this.gl.INT_VEC4)){const s=t.map(a=>Math.floor(a));switch(s.length){case 2:this.gl.uniform2iv(r,s);break;case 3:this.gl.uniform3iv(r,s);break;case 4:this.gl.uniform4iv(r,s);break;default:console.warn(`Unsupported array length ${s.length} for uniform '${e}'`)}}else switch(t.length){case 2:this.gl.uniform2f(r,t[0],t[1]);break;case 3:this.gl.uniform3f(r,t[0],t[1],t[2]);break;case 4:this.gl.uniform4f(r,t[0],t[1],t[2],t[3]);break;default:console.warn(`Unsupported array length ${t.length} for uniform '${e}'`)}else if(t instanceof WebGLTexture){const s=this.getNextTextureUnit();this.gl.uniform1i(r,s),this.gl.activeTexture(this.gl.TEXTURE0+s),this.gl.bindTexture(this.gl.TEXTURE_2D,t)}else if(t&&typeof t=="object"&&"texture"in t){const s=this.getNextTextureUnit();this.gl.uniform1i(r,s),this.gl.activeTexture(this.gl.TEXTURE0+s),this.gl.bindTexture(this.gl.TEXTURE_2D,t.texture)}else console.warn(`Unsupported uniform type for '${e}':`,typeof t)}getUniformInfo(e){const t=this.gl.getProgramParameter(this.program,this.gl.ACTIVE_UNIFORMS);for(let r=0;r<t;r++){const i=this.gl.getActiveUniform(this.program,r);if(i&&i.name===e)return i}return null}getNextTextureUnit(){return this.textureUnitCounter++}hasUniform(e){return this.uniformLocations.has(e)}hasAttribute(e){return this.attributeLocations.has(e)}get glProgram(){return this.program}resetTextureUnits(){this.textureUnitCounter=0}}var S="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);}",oe="precision lowp float;uniform sampler2D u_texture;varying vec2 v_uv;void main(){gl_FragColor=texture2D(u_texture,v_uv);}",le="precision lowp float;uniform vec4 u_color;void main(){gl_FragColor=u_color;}";class he{constructor(e){o(this,"gl");o(this,"imageShader");o(this,"solidColorShader");o(this,"currentShader",null);o(this,"currentFillColor",[1,1,1,1]);o(this,"fillMode",!0);o(this,"currentStrokeColor",[0,0,0,1]);o(this,"currentStrokeWeight",1);o(this,"strokeMode",!0);o(this,"currentRotation",0);o(this,"stateStack",[]);this.gl=e,this.imageShader=new T(this.gl,S,oe),this.solidColorShader=new T(this.gl,S,le),this.gl.enable(this.gl.BLEND),this.gl.blendEquation(this.gl.FUNC_ADD),this.gl.blendFunc(this.gl.ONE,this.gl.ONE_MINUS_SRC_ALPHA)}shader(e){this.currentShader=e,e.use()}fill(e,t,r,i){if(this.fillMode=!0,t===void 0&&r===void 0&&i===void 0){const s=e/255;this.currentFillColor=[s,s,s,1]}else if(r!==void 0&&i===void 0)this.currentFillColor=[e/255,t/255,r/255,1];else if(r!==void 0&&i!==void 0)this.currentFillColor=[e/255,t/255,r/255,i/255];else throw new Error("Invalid fill parameters. Use fill(gray), fill(r,g,b), or fill(r,g,b,a)")}stroke(e,t,r,i){if(this.strokeMode=!0,t===void 0&&r===void 0&&i===void 0){const s=e/255;this.currentStrokeColor=[s,s,s,1]}else if(r!==void 0&&i===void 0)this.currentStrokeColor=[e/255,t/255,r/255,1];else if(r!==void 0&&i!==void 0)this.currentStrokeColor=[e/255,t/255,r/255,i/255];else throw new Error("Invalid stroke parameters. Use stroke(gray), stroke(r,g,b), or stroke(r,g,b,a)")}strokeWeight(e){if(e<0)throw new Error("Stroke weight must be non-negative");this.currentStrokeWeight=e}noStroke(){this.strokeMode=!1}noFill(){this.fillMode=!1}rotate(e){this.currentRotation=e}push(){this.stateStack.push({fillColor:[...this.currentFillColor],fillMode:this.fillMode,strokeColor:[...this.currentStrokeColor],strokeWeight:this.currentStrokeWeight,strokeMode:this.strokeMode,rotation:this.currentRotation})}pop(){const e=this.stateStack.pop();e?(this.currentFillColor=e.fillColor,this.fillMode=e.fillMode,this.currentStrokeColor=e.strokeColor,this.currentStrokeWeight=e.strokeWeight,this.strokeMode=e.strokeMode,this.currentRotation=e.rotation):console.warn("pop() called without matching push()")}reset(){this.currentShader=null,this.stateStack=[],this.currentRotation=0,this.fillMode=!0,this.strokeMode=!0,this.currentFillColor=[1,1,1,1],this.currentStrokeColor=[0,0,0,1],this.currentStrokeWeight=1}createShader(e,t){return new T(this.gl,e,t)}setUniform(e,t){this.currentShader.setUniform(e,t)}rect(e,t,r,i){const s=new se(this.gl,e,t,r,i);if(this.currentShader!==null){if(this.currentRotation!==0){const{centerX:d,centerY:f,radians:g,aspectRatio:x}=this.calculateRotationParams(e,t,r,i);this.setUniform("u_rotation",g),this.setUniform("u_center",[d,f]),this.setUniform("u_aspectRatio",x)}else this.setUniform("u_rotation",0),this.setUniform("u_center",[0,0]),this.setUniform("u_aspectRatio",1);s.renderFill(),this.currentShader=null;return}const a=this.solidColorShader,{centerX:n,centerY:h,radians:c,aspectRatio:u}=this.calculateRotationParams(e,t,r,i);this.fillMode&&(this.shader(a),this.setUniform("u_color",this.currentFillColor),this.setUniform("u_rotation",c),this.setUniform("u_center",[n,h]),this.setUniform("u_aspectRatio",u),s.renderFill()),this.strokeMode&&(this.shader(a),this.setUniform("u_color",this.currentStrokeColor),this.setUniform("u_rotation",c),this.setUniform("u_center",[n,h]),this.setUniform("u_aspectRatio",u),s.renderStroke(this.currentStrokeWeight)),this.currentShader=null}line(e,t,r,i){if(!this.strokeMode)return;const s=new ne(this.gl,e,t,r,i);if(this.currentShader!==null){if(this.currentRotation!==0){const p=(e+r)/2,F=(t+i)/2,w=Math.abs(r-e),b=Math.abs(i-t),{centerX:y,centerY:B,radians:A,aspectRatio:R}=this.calculateRotationParams(p-w/2,F-b/2,w,b);this.setUniform("u_rotation",A),this.setUniform("u_center",[y,B]),this.setUniform("u_aspectRatio",R)}else this.setUniform("u_rotation",0),this.setUniform("u_center",[0,0]),this.setUniform("u_aspectRatio",1);s.renderStroke(this.currentStrokeWeight),this.currentShader=null;return}const a=this.solidColorShader,n=(e+r)/2,h=(t+i)/2,c=Math.abs(r-e),u=Math.abs(i-t),{centerX:d,centerY:f,radians:g,aspectRatio:x}=this.calculateRotationParams(n-c/2,h-u/2,c,u);this.shader(a),this.setUniform("u_color",this.currentStrokeColor),this.setUniform("u_rotation",g),this.setUniform("u_center",[d,f]),this.setUniform("u_aspectRatio",x),s.renderStroke(this.currentStrokeWeight),this.currentShader=null}calculateRotationParams(e,t,r,i){const s=this.gl.getParameter(this.gl.VIEWPORT),a=s[2],n=s[3],h=a/n,c=this.gl.getParameter(this.gl.FRAMEBUFFER_BINDING)!==null,u=e+r/2,d=t+i/2,f=u/a*2-1;let g;c?g=d/n*2-1:g=1-d/n*2;const x=this.currentRotation*Math.PI/180;return{centerX:f,centerY:g,radians:x,aspectRatio:h}}createFramebuffer(e,t,r={}){return new ie(this.gl,e,t,r)}background(e,t=e,r=e,i=255){this.clear(e/255,t/255,r/255,i/255)}clear(e=0,t=0,r=0,i=0){this.gl.clearColor(e,t,r,i),this.gl.clear(this.gl.COLOR_BUFFER_BIT)}resetViewport(){this.gl.viewport(0,0,this.gl.canvas.width,this.gl.canvas.height)}get context(){return this.gl}image(e,t,r,i,s){this.shader(this.imageShader),this.setUniform("u_texture",e.texture);const{centerX:a,centerY:n,radians:h,aspectRatio:c}=this.calculateRotationParams(t,r,i??e.width,s??e.height);this.setUniform("u_rotation",h),this.setUniform("u_center",[a,n]),this.setUniform("u_aspectRatio",c),this.rect(t,r,i??e.width,s??e.height)}}var m={};m.parse=function(l){var e=function(s,a,n,h){var c=m.T,u={cmap:c.cmap,head:c.head,hhea:c.hhea,maxp:c.maxp,hmtx:c.hmtx,loca:c.loca,glyf:c.glyf},d={_data:s,_index:a,_offset:n};for(var f in u){var g=m.findTable(s,f,n);if(g){var x=g[0],p=h[x];p==null&&(p=u[f].parseTab(s,x,g[1],d)),d[f]=h[x]=p}}return d},t=new Uint8Array(l),r={},i=e(t,0,0,r);return[i]},m.findTable=function(l,e,t){for(var r=m.B,i=r.readUshort(l,t+4),s=t+12,a=0;a<i;a++){var n=r.readASCII(l,s,4);r.readUint(l,s+4);var h=r.readUint(l,s+8),c=r.readUint(l,s+12);if(n==e)return[h,c];s+=16}return null},m.T={},m.B={readShort:function(l,e){var t=m.B.t.uint16;return t[0]=l[e]<<8|l[e+1],m.B.t.int16[0]},readUshort:function(l,e){return l[e]<<8|l[e+1]},readUshorts:function(l,e,t){for(var r=[],i=0;i<t;i++)r.push(m.B.readUshort(l,e+i*2));return r},readUint:function(l,e){var t=m.B.t.uint8;return t[3]=l[e],t[2]=l[e+1],t[1]=l[e+2],t[0]=l[e+3],m.B.t.uint32[0]},readASCII:function(l,e,t){for(var r="",i=0;i<t;i++)r+=String.fromCharCode(l[e+i]);return r},t:function(){var l=new ArrayBuffer(8);return{uint8:new Uint8Array(l),int16:new Int16Array(l),uint16:new Uint16Array(l),uint32:new Uint32Array(l)}}()},m.T.cmap={parseTab:function(l,e,t){var r={tables:[],ids:{},off:e};l=new Uint8Array(l.buffer,e,t),e=0;var i=m.B,s=i.readUshort,a=m.T.cmap;s(l,e),e+=2;var n=s(l,e);e+=2;for(var h=[],c=0;c<n;c++){var u=s(l,e);e+=2;var d=s(l,e);e+=2;var f=i.readUint(l,e);e+=4;var g="p"+u+"e"+d,x=h.indexOf(f);if(x==-1){x=r.tables.length;var p={};h.push(f);var F=p.format=s(l,f);F==4?p=a.parse4(l,f,p):F==12&&(p=a.parse12(l,f,p)),r.tables.push(p)}r.ids[g]!=null&&console.log("multiple tables for one platform+encoding: "+g),r.ids[g]=x}return r},parse4:function(l,e,t){var r=m.B,i=r.readUshort,s=r.readUshorts,a=e;e+=2;var n=i(l,e);e+=2,i(l,e),e+=2;var h=i(l,e);e+=2;var c=h>>>1;t.searchRange=i(l,e),e+=2,t.entrySelector=i(l,e),e+=2,t.rangeShift=i(l,e),e+=2,t.endCount=s(l,e,c),e+=c*2,e+=2,t.startCount=s(l,e,c),e+=c*2,t.idDelta=[];for(var u=0;u<c;u++)t.idDelta.push(r.readShort(l,e)),e+=2;return t.idRangeOffset=s(l,e,c),e+=c*2,t.glyphIdArray=s(l,e,a+n-e>>1),t},parse12:function(l,e,t){var r=m.B,i=r.readUint;e+=4,i(l,e),e+=4,i(l,e),e+=4;var s=i(l,e)*3;e+=4;for(var a=t.groups=new Uint32Array(s),n=0;n<s;n+=3)a[n]=i(l,e+(n<<2)),a[n+1]=i(l,e+(n<<2)+4),a[n+2]=i(l,e+(n<<2)+8);return t}},m.T.head={parseTab:function(l,e,t){var r=m.B,i={};return e+=18,i.unitsPerEm=r.readUshort(l,e),e+=2,e+=16,i.xMin=r.readShort(l,e),e+=2,i.yMin=r.readShort(l,e),e+=2,i.xMax=r.readShort(l,e),e+=2,i.yMax=r.readShort(l,e),e+=2,e+=6,i.indexToLocFormat=r.readShort(l,e),i}},m.T.hhea={parseTab:function(l,e,t){var r=m.B,i={};e+=4;for(var s=["ascender","descender","lineGap","advanceWidthMax","minLeftSideBearing","minRightSideBearing","xMaxExtent","caretSlopeRise","caretSlopeRun","caretOffset","res0","res1","res2","res3","metricDataFormat","numberOfHMetrics"],a=0;a<s.length;a++){var n=s[a],h=n=="advanceWidthMax"||n=="numberOfHMetrics"?r.readUshort:r.readShort;i[n]=h(l,e+a*2)}return i}},m.T.hmtx={parseTab:function(l,e,t,r){for(var i=m.B,s=[],a=[],n=r.maxp.numGlyphs,h=r.hhea.numberOfHMetrics,c=0,u=0,d=0;d<h;)c=i.readUshort(l,e+(d<<2)),u=i.readShort(l,e+(d<<2)+2),s.push(c),a.push(u),d++;for(;d<n;)s.push(c),a.push(u),d++;return{aWidth:s,lsBearing:a}}},m.T.maxp={parseTab:function(l,e,t){var r=m.B,i=r.readUshort,s={};return r.readUint(l,e),e+=4,s.numGlyphs=i(l,e),e+=2,s}},m.T.loca={parseTab:function(l,e,t,r){var i=m.B,s=[],a=r.head.indexToLocFormat,n=r.maxp.numGlyphs+1;if(a==0)for(var h=0;h<n;h++)s.push(i.readUshort(l,e+(h<<1))<<1);if(a==1)for(var h=0;h<n;h++)s.push(i.readUint(l,e+(h<<2)));return s}},m.T.glyf={parseTab:function(l,e,t,r){for(var i=[],s=r.maxp.numGlyphs,a=0;a<s;a++)i.push(null);return i},_parseGlyf:function(l,e){var t=m.B,r=l._data,i=l.loca;if(i[e]==i[e+1])return null;var s=m.findTable(r,"glyf",l._offset)[0]+i[e],a={};if(a.noc=t.readShort(r,s),s+=2,a.xMin=t.readShort(r,s),s+=2,a.yMin=t.readShort(r,s),s+=2,a.xMax=t.readShort(r,s),s+=2,a.yMax=t.readShort(r,s),s+=2,a.xMin>=a.xMax||a.yMin>=a.yMax)return null;if(a.noc>0){a.endPts=[];for(var n=0;n<a.noc;n++)a.endPts.push(t.readUshort(r,s)),s+=2;var h=t.readUshort(r,s);if(s+=2,r.length-s<h)return null;s+=h;var c=a.endPts[a.noc-1]+1;a.flags=[];for(var n=0;n<c;n++){var u=r[s];if(s++,a.flags.push(u),u&8){var d=r[s];s++;for(var f=0;f<d;f++)a.flags.push(u),n++}}a.xs=[];for(var n=0;n<c;n++){var g=(a.flags[n]&2)!=0,x=(a.flags[n]&16)!=0;g?(a.xs.push(x?r[s]:-r[s]),s++):x?a.xs.push(0):(a.xs.push(t.readShort(r,s)),s+=2)}a.ys=[];for(var n=0;n<c;n++){var g=(a.flags[n]&4)!=0,x=(a.flags[n]&32)!=0;g?(a.ys.push(x?r[s]:-r[s]),s++):x?a.ys.push(0):(a.ys.push(t.readShort(r,s)),s+=2)}for(var p=0,F=0,n=0;n<c;n++)p+=a.xs[n],F+=a.ys[n],a.xs[n]=p,a.ys[n]=F}else a.parts=[];return a}},typeof module<"u"&&module.exports?module.exports=m:typeof window<"u"&&(window.Typr=m);class ce{extractCharacters(e){var r;const t=[];return(r=e==null?void 0:e.cmap)!=null&&r.tables?(e.cmap.tables.forEach(i=>{if(i.format===4){const s=this._extractCharactersFromFormat4Table(i);t.push(...s)}else if(i.format===12){const s=this._extractCharactersFromFormat12Table(i);t.push(...s)}}),[...new Set(t)]):[]}_extractCharactersFromFormat4Table(e){const t=[];if(!e.startCount||!e.endCount||!e.idRangeOffset||!e.idDelta)return t;for(let r=0;r<e.startCount.length;r++){const i=e.startCount[r],s=e.endCount[r];if(!(i===65535&&s===65535)){for(let a=i;a<=s;a++)if(this._calculateGlyphIndexFormat4(e,a,r)>0){const h=String.fromCodePoint(a);t.push(h)}}}return t}_extractCharactersFromFormat12Table(e){const t=[];if(!e.groups)return t;for(let r=0;r<e.groups.length;r+=3){const i=e.groups[r],s=e.groups[r+1],a=e.groups[r+2];for(let n=i;n<=s;n++)if(a+(n-i)>0){const c=String.fromCodePoint(n);t.push(c)}}return t}_calculateGlyphIndexFormat4(e,t,r){if(e.idRangeOffset[r]===0)return t+e.idDelta[r]&65535;{const i=e.idRangeOffset[r]/2+(t-e.startCount[r])-(e.startCount.length-r);if(i>=0&&e.glyphIdArray&&i<e.glyphIdArray.length){const s=e.glyphIdArray[i];if(s!==0)return s+e.idDelta[r]&65535}}return 0}filterProblematicCharacters(e){return e.filter(t=>this._isValidCharacter(t))}_isValidCharacter(e){const t=e.codePointAt(0)||0;return!(t>=0&&t<=31&&t!==9&&t!==10&&t!==13||t>=127&&t<=159)}}class ue{constructor(e){o(this,"_textureCanvas");o(this,"_textureContext");o(this,"_renderer");this._renderer=e,this._textureCanvas=document.createElement("canvas"),this._textureContext=this._textureCanvas.getContext("2d",{willReadFrequently:!0,alpha:!1})}createTextureAtlas(e,t,r,i){const s=e.length,a=Math.ceil(Math.sqrt(s)),n=Math.ceil(s/a),h=t.width*a,c=t.height*n;this._setupCanvas(h,c,r,i),this._renderCharactersToCanvas(e,t,a,r),this._applyBlackWhiteThreshold();const u=this._renderer.createFramebuffer(h,c,{filter:"nearest"});return u.update(this._textureCanvas),{framebuffer:u,columns:a,rows:n}}_setupCanvas(e,t,r,i){this._textureCanvas.width=e,this._textureCanvas.height=t,this._textureCanvas.style.width=e+"px",this._textureCanvas.style.height=e+"px",this._textureContext.imageSmoothingEnabled=!1,this._textureCanvas.style.imageRendering="pixelated",this._textureContext.fillStyle="black",this._textureContext.fillRect(0,0,e,t),this._textureContext.font=`${r}px ${i}`,this._textureContext.textBaseline="top",this._textureContext.textAlign="left",this._textureContext.fillStyle="white"}_renderCharactersToCanvas(e,t,r,i){for(let s=0;s<e.length;s++){const a=s%r,n=Math.floor(s/r),h=a*t.width+t.width*.5,c=n*t.height+t.height*.5,u=Math.round(h-t.width*.5),d=Math.round(c-i*.5);this._textureContext.fillText(e[s].character,u,d)}}_applyBlackWhiteThreshold(e=128){const t=this._textureContext.getImageData(0,0,this._textureCanvas.width,this._textureCanvas.height),r=t.data;for(let i=0;i<r.length;i+=4){const s=.299*r[i]+.587*r[i+1]+.114*r[i+2],a=e+32,n=s>a?255:0;r[i]=n,r[i+1]=n,r[i+2]=n}this._textureContext.putImageData(t,0,0)}}class de{constructor(){o(this,"_tempCanvas");o(this,"_tempContext");this._tempCanvas=document.createElement("canvas"),this._tempContext=this._tempCanvas.getContext("2d")}calculateMaxGlyphDimensions(e,t,r){this._tempContext.font=`${t}px ${r}`;let i=0,s=0;for(const a of e){const n=this._tempContext.measureText(a),h=n.width,c=n.actualBoundingBoxAscent+n.actualBoundingBoxDescent;h>0&&(i=Math.max(i,h),s=Math.max(s,c))}return{width:Math.ceil(i),height:Math.ceil(s)}}}class fe{createCharacterObjects(e,t){return e.map((r,i)=>{const s=r.codePointAt(0)||0,a=this._generateCharacterColor(i);let n=0;if(t.hmtx&&t.hmtx.aWidth){const h=this._getGlyphIndex(t,s);h>0&&t.hmtx.aWidth[h]!==void 0&&(n=t.hmtx.aWidth[h])}return{character:r,unicode:s,color:a,advanceWidth:n}})}_getGlyphIndex(e,t){const r=e.cmap;if(!r||!r.tables)return 0;for(const i of r.tables)if(i.format===4){for(let s=0;s<i.startCount.length;s++)if(t>=i.startCount[s]&&t<=i.endCount[s]){if(i.idRangeOffset[s]===0)return t+i.idDelta[s]&65535;{const a=i.idRangeOffset[s]/2+(t-i.startCount[s])-(i.startCount.length-s);if(a>=0&&a<i.glyphIdArray.length){const n=i.glyphIdArray[a];if(n!==0)return n+i.idDelta[s]&65535}}}}return 0}_generateCharacterColor(e){const t=e%256,r=Math.floor(e/256)%256,i=Math.floor(e/65536)%256;return[t,r,i]}getCharacterColor(e,t){if(!C.validate(typeof e=="string"&&e.length===1,"Character must be a single character string.",{method:"getCharacterColor",providedValue:e}))return[0,0,0];const r=t.find(i=>i.character===e);return r?r.color:[0,0,0]}getCharacterColors(e,t){return C.validate(typeof e=="string"&&e.length>0,"Characters must be a string with at least one character.",{method:"getCharacterColors",providedValue:e})?e.split("").map(r=>this.getCharacterColor(r,t)||[0,0,0]):[[0,0,0]]}}class q{constructor(e,t=16){o(this,"_font");o(this,"_characters",[]);o(this,"_fontFramebuffer");o(this,"_fontSize",16);o(this,"_textureColumns",0);o(this,"_textureRows",0);o(this,"_maxGlyphDimensions",{width:0,height:0});o(this,"_fontFace");o(this,"_fontFamilyName","UrsaFont");o(this,"_characterExtractor");o(this,"_textureAtlas");o(this,"_metricsCalculator");o(this,"_characterColorMapper");this._fontSize=t,this._characterExtractor=new ce,this._textureAtlas=new ue(e),this._metricsCalculator=new de,this._characterColorMapper=new fe}async initialize(e){let t;if(e){const r=await fetch(e);if(!r.ok)throw new _(`Failed to load font file: ${r.status} ${r.statusText}`);t=await r.arrayBuffer()}else throw new _("Embedded font not available. This appears to be a minified build - please provide `fontSource`.");await this._loadFontFace(t),this._font=m.parse(t)[0],await this._initializeFont()}setFontSize(e){if(e===void 0)return this._fontSize;this._fontSize=e,this._maxGlyphDimensions=this._metricsCalculator.calculateMaxGlyphDimensions(this._characters.map(r=>r.character),this._fontSize,this._fontFamilyName);const t=this._textureAtlas.createTextureAtlas(this._characters,this._maxGlyphDimensions,this._fontSize,this._fontFamilyName);this._fontFramebuffer=t.framebuffer,this._textureColumns=t.columns,this._textureRows=t.rows}async loadFont(e){try{const t=await fetch(e);if(!t.ok)throw new _(`Failed to load font file: ${t.status} ${t.statusText}`);const r=await t.arrayBuffer();await this._loadFontFace(r);const i=m.parse(r);if(!i||i.length===0)throw new Error("Failed to parse font file");this._font=i[0],await this._initializeFont()}catch(t){throw new _(`Failed to load font: ${t instanceof Error?t.message:"Unknown error"}`,t)}}async _loadFontFace(e){const t=Date.now();this._fontFamilyName=this._fontFamilyName==="UrsaFont"?"UrsaFont":`CustomFont_${t}`,this._fontFace=new FontFace(this._fontFamilyName,e),await this._fontFace.load(),document.fonts.add(this._fontFace)}async _initializeFont(){const e=this._characterExtractor.extractCharacters(this._font),t=this._characterExtractor.filterProblematicCharacters(e);this._characters=this._characterColorMapper.createCharacterObjects(t,this._font),this._maxGlyphDimensions=this._metricsCalculator.calculateMaxGlyphDimensions(t,this._fontSize,this._fontFamilyName);const r=this._textureAtlas.createTextureAtlas(this._characters,this._maxGlyphDimensions,this._fontSize,this._fontFamilyName);this._fontFramebuffer=r.framebuffer,this._textureColumns=r.columns,this._textureRows=r.rows}getCharacterColor(e){return this._characterColorMapper.getCharacterColor(e,this._characters)}getCharacterColors(e){return this._characterColorMapper.getCharacterColors(e,this._characters)}hasAllCharacters(e){if(typeof e!="string"||e.length===0)return!1;const t=new Set(this._characters.map(r=>r.character));for(const r of e)if(!t.has(r))return!1;return!0}get fontFramebuffer(){return this._fontFramebuffer}get characters(){return this._characters}get textureColumns(){return this._textureColumns}get textureRows(){return this._textureRows}get maxGlyphDimensions(){return this._maxGlyphDimensions}get fontSize(){return this._fontSize}get font(){return this._font}}class Q{constructor(e,t,r){o(this,"_cols");o(this,"_rows");o(this,"_width");o(this,"_height");o(this,"_offsetX");o(this,"_offsetY");o(this,"_fixedDimensions",!1);o(this,"_canvas");o(this,"_cellWidth");o(this,"_cellHeight");this._canvas=e,this._cellWidth=t,this._cellHeight=r,this.reset()}reset(){if(!this._fixedDimensions){const e=this._canvas.getBoundingClientRect();let t=Math.round(e.width),r=Math.round(e.height);[this._cols,this._rows]=[Math.floor(t/this._cellWidth),Math.floor(r/this._cellHeight)]}this._resizeGrid()}_resizeGrid(){const e=this._canvas.getBoundingClientRect();let t=Math.round(e.width),r=Math.round(e.height);this._width=this._cols*this._cellWidth,this._height=this._rows*this._cellHeight,this._offsetX=Math.floor((t-this._width)/2),this._offsetY=Math.floor((r-this._height)/2)}resizeCellPixelDimensions(e,t){[this._cellWidth,this._cellHeight]=[e,t],this.reset()}resizeGridDimensions(e,t){this._fixedDimensions=!0,[this._cols,this._rows]=[e,t],this._resizeGrid()}resetGridDimensions(){this._fixedDimensions=!1,this.reset()}resize(){this._fixedDimensions?this._resizeGrid():this.reset()}fixedDimensions(e){if(e===void 0)return this._fixedDimensions;this._fixedDimensions=e}get cellWidth(){return this._cellWidth}get cellHeight(){return this._cellHeight}get cols(){return this._cols}get rows(){return this._rows}get width(){return this._width}get height(){return this._height}get offsetX(){return this._offsetX}get offsetY(){return this._offsetY}}class Z{constructor(e,t=!1,r={}){o(this,"_canvas");o(this,"captureSource");o(this,"_isStandalone");this.captureSource=e,this._isStandalone=t,this._canvas=this.createCanvas(r.width,r.height)}createCanvas(e,t){var i;const r=document.createElement("canvas");if(r.className="textmodeCanvas",this._isStandalone)r.width=e||800,r.height=t||600,r.style.width=e+"px",r.style.height=t+"px",document.body.appendChild(r);else{const s=this.captureSource.getBoundingClientRect();let a=Math.round(s.width),n=Math.round(s.height);if(this.captureSource instanceof HTMLVideoElement){const u=this.captureSource;(a===0||n===0)&&u.videoWidth>0&&u.videoHeight>0&&(a=u.videoWidth,n=u.videoHeight)}r.width=a,r.height=n,r.style.width=a+"px",r.style.height=n+"px",r.style.position="absolute",r.style.pointerEvents="none";const h=window.getComputedStyle(this.captureSource);let c=parseInt(h.zIndex||"0",10);isNaN(c)&&(c=0),r.style.zIndex=(c+1).toString(),this.positionOverlayCanvas(r),(i=this.captureSource.parentNode)==null||i.insertBefore(r,this.captureSource.nextSibling)}return r}positionOverlayCanvas(e){const t=this.captureSource.getBoundingClientRect();let r=this.captureSource.offsetParent;if(r&&r!==document.body){const i=r.getBoundingClientRect();e.style.top=t.top-i.top+"px",e.style.left=t.left-i.left+"px"}else e.style.top=t.top+window.scrollY+"px",e.style.left=t.left+window.scrollX+"px"}resize(e,t){if(this._isStandalone)this._canvas.width=e??this._canvas.width,this._canvas.height=t??this._canvas.height,this._canvas.style.width=(e??this._canvas.width)+"px",this._canvas.style.height=(t??this._canvas.height)+"px";else{const r=this.captureSource.getBoundingClientRect();let i=Math.round(r.width),s=Math.round(r.height);if(this.captureSource instanceof HTMLVideoElement){const a=this.captureSource;(i===0||s===0)&&a.videoWidth>0&&a.videoHeight>0&&(i=a.videoWidth,s=a.videoHeight)}this._canvas.width=i,this._canvas.height=s,this._canvas.style.width=i+"px",this._canvas.style.height=s+"px",this.positionOverlayCanvas(this._canvas)}}getWebGLContext(){const e={alpha:!1,premultipliedAlpha:!1,preserveDrawingBuffer:!0,antialias:!1,depth:!1,stencil:!1,powerPreference:"high-performance"},t=this._canvas.getContext("webgl2",e)||this._canvas.getContext("webgl",e);if(!t)throw new _("WebGL context could not be created. Ensure your browser supports WebGL.");return t}get canvas(){return this._canvas}get width(){return this._canvas.width}get height(){return this._canvas.height}}class M{constructor(e,t,r,i={}){o(this,"renderer");o(this,"fontManager");o(this,"grid");o(this,"_characterFramebuffer");o(this,"_primaryColorFramebuffer");o(this,"_secondaryColorFramebuffer");o(this,"_rotationFramebuffer");o(this,"_transformFramebuffer");o(this,"_options");this.renderer=e,this.fontManager=t,this.grid=r,this._options=i,this._characterFramebuffer=this.renderer.createFramebuffer(this.grid.cols,this.grid.rows),this._primaryColorFramebuffer=this.renderer.createFramebuffer(this.grid.cols,this.grid.rows),this._secondaryColorFramebuffer=this.renderer.createFramebuffer(this.grid.cols,this.grid.rows),this._rotationFramebuffer=this.renderer.createFramebuffer(this.grid.cols,this.grid.rows),this._transformFramebuffer=this.renderer.createFramebuffer(this.grid.cols,this.grid.rows)}resize(){this._characterFramebuffer.resize(this.grid.cols,this.grid.rows),this._primaryColorFramebuffer.resize(this.grid.cols,this.grid.rows),this._secondaryColorFramebuffer.resize(this.grid.cols,this.grid.rows),this._rotationFramebuffer.resize(this.grid.cols,this.grid.rows),this._transformFramebuffer.resize(this.grid.cols,this.grid.rows)}enabled(e){this._options.enabled=e}enable(){this.enabled(!0)}disable(){this.enabled(!1)}get characterFramebuffer(){return this._characterFramebuffer}get primaryColorFramebuffer(){return this._primaryColorFramebuffer}get secondaryColorFramebuffer(){return this._secondaryColorFramebuffer}get rotationFramebuffer(){return this._rotationFramebuffer}get transformFramebuffer(){return this._transformFramebuffer}get options(){return this._options}}class me{constructor(e,t){o(this,"_framebuffer");o(this,"_renderer");o(this,"_colors");this._renderer=e,this._colors=t;const r=Math.max(this._colors.length,1);this._framebuffer=this._renderer.createFramebuffer(r,1),this._updateFramebuffer()}_updateFramebuffer(){if(!this._framebuffer)return;const e=Math.max(this._colors.length,1),t=1;this._framebuffer.width!==e&&this._framebuffer.resize(e,t);const r=new Uint8Array(e*t*4);for(let i=0;i<e;i++){const s=i<this._colors.length?this._colors[i]:[0,0,0],a=i*4;r[a]=s[0],r[a+1]=s[1],r[a+2]=s[2],r[a+3]=255}this._framebuffer.updatePixels(r,e,t)}setColors(e){this._colors=e,this._updateFramebuffer()}get colors(){return this._colors}get framebuffer(){return this._framebuffer}get texture(){return this._framebuffer.texture}}class k extends M{constructor(t,r,i,s={}){super(t,r,i,s);o(this,"palette");this.palette=new me(this.renderer,this.fontManager.getCharacterColors(" .:-=+*%@#"))}characters(t){C.validate(this.fontManager.hasAllCharacters(t),"One or more characters do not exist in the current font.",{method:"characters",providedValue:t})&&(this._options.characters=t,this.palette.setColors(this.fontManager.getCharacterColors(t)))}characterColor(t,r=t,i=t,s=255){C.validate([t,r,i,s].every(a=>a>=0&&a<=255),"Character color values must be between 0 and 255",{method:"characterColor",providedValues:{r:t,g:r,b:i,a:s}})&&(this._options.characterColor=[t,r,i,s])}characterColorMode(t){C.validate(["sampled","fixed"].includes(t),"Invalid character color mode. Must be 'sampled' or 'fixed'.",{method:"characterColorMode",providedValue:t})&&(this._options.characterColorMode=t)}cellColor(t,r=t,i=t,s=255){C.validate([t,r,i,s].every(a=>a>=0&&a<=255),"Cell color values must be between 0 and 255",{method:"cellColor",providedValues:{r:t,g:r,b:i,a:s}})&&(this._options.cellColor=[t,r,i,s])}cellColorMode(t){C.validate(["sampled","fixed"].includes(t),"Invalid cell color mode. Must be 'sampled' or 'fixed'.",{method:"cellColorMode",providedValue:t})&&(this._options.cellColorMode=t)}invert(t){C.validate(typeof t=="boolean"||typeof t=="number"&&Number.isInteger(t),"Invert must be a boolean value or an integer (0 for false, any other number for true).",{method:"invert",providedValue:t})&&(this._options.invert=!!t)}rotation(t){if(!C.validate(typeof t=="number","Rotation angle must be a number.",{method:"rotation",providedValue:t}))return;t=t%360,t<0&&(t+=360);const r=t*255/360,i=Math.floor(r)/255,s=Math.round(r-i);this._options.rotation=[i,s,0,1]}flipHorizontally(t){C.validate(typeof t=="boolean"||typeof t=="number"&&Number.isInteger(t),"Flip horizontally must be a boolean value or an integer (0 for false, any other number for true).",{method:"flipHorizontally",providedValue:t})&&(this._options.flipHorizontally=!!t)}flipVertically(t){C.validate(typeof t=="boolean"||typeof t=="number"&&Number.isInteger(t),"Flip vertically must be a boolean value or an integer (0 for false, any other number for true).",{method:"flipVertically",providedValue:t})&&(this._options.flipVertically=!!t)}}var ge="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);}}",pe="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);}}",_e="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);}}",xe="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);}}",ve="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);}";const Ce={enabled:!0,characters:" .:-=+*%@#",characterColor:[255,255,255,255],characterColorMode:"sampled",cellColor:[0,0,0,255],cellColorMode:"fixed",invert:!1,rotation:[0,0,0,255],flipHorizontally:!1,flipVertically:!1,brightnessRange:[0,255]};class $ extends k{constructor(t,r,i){super(t,r,i,{...Ce});o(this,"sampleShader");o(this,"colorFillShader");o(this,"charMappingShader");o(this,"transformFillShader");o(this,"rotationFillShader");o(this,"sampleFramebuffer");this.sampleShader=new T(t.context,S,ge),this.colorFillShader=new T(t.context,S,pe),this.transformFillShader=new T(t.context,S,_e),this.rotationFillShader=new T(t.context,S,xe),this.charMappingShader=new T(t.context,S,ve),this.sampleFramebuffer=this.renderer.createFramebuffer(this.grid.cols,this.grid.rows)}convert(t){this.sampleFramebuffer.begin(),this.renderer.clear(),this.renderer.shader(this.sampleShader),this.renderer.setUniform("u_sketchTexture",t),this.renderer.setUniform("u_gridCellDimensions",[this.grid.cols,this.grid.rows]),this.renderer.setUniform("u_brightnessRange",this._options.brightnessRange),this.renderer.rect(0,0,this.grid.cols,this.grid.rows),this.sampleFramebuffer.end(),this._primaryColorFramebuffer.begin(),this.renderer.clear(),this.renderer.shader(this.colorFillShader),this.renderer.setUniform("u_sampleTexture",this.sampleFramebuffer.texture),this.renderer.setUniform("u_fillColor",this._options.characterColor),this.renderer.setUniform("u_useFixedColor",this._options.characterColorMode==="fixed"),this.renderer.rect(0,0,this.grid.cols,this.grid.rows),this._primaryColorFramebuffer.end(),this._secondaryColorFramebuffer.begin(),this.renderer.clear(),this.renderer.shader(this.colorFillShader),this.renderer.setUniform("u_sampleTexture",this.sampleFramebuffer.texture),this.renderer.setUniform("u_fillColor",this._options.cellColor),this.renderer.setUniform("u_useFixedColor",this._options.cellColorMode==="fixed"),this.renderer.rect(0,0,this.grid.cols,this.grid.rows),this._secondaryColorFramebuffer.end(),this._transformFramebuffer.begin(),this.renderer.clear(),this.renderer.shader(this.transformFillShader),this.renderer.setUniform("u_sampleTexture",this.sampleFramebuffer.texture),this.renderer.setUniform("u_invert",this._options.invert),this.renderer.setUniform("u_flipHorizontally",this._options.flipHorizontally),this.renderer.setUniform("u_flipVertically",this._options.flipVertically),this.renderer.rect(0,0,this.grid.cols,this.grid.rows),this._transformFramebuffer.end(),this._rotationFramebuffer.begin(),this.renderer.clear(),this.renderer.shader(this.rotationFillShader),this.renderer.setUniform("u_sampleTexture",this.sampleFramebuffer.texture),this.renderer.setUniform("u_rotationColor",this._options.rotation),this.renderer.rect(0,0,this.grid.cols,this.grid.rows),this._rotationFramebuffer.end(),this._characterFramebuffer.begin(),this.renderer.clear(0,0,0,0),this.renderer.shader(this.charMappingShader),this.renderer.setUniform("u_colorSampleFramebuffer",this.sampleFramebuffer.texture),this.renderer.setUniform("u_charPaletteTexture",this.palette.texture),this.renderer.setUniform("u_charPaletteSize",[this.palette.colors.length,1]),this.renderer.setUniform("u_brightnessRange",this._options.brightnessRange),this.renderer.rect(0,0,this.grid.cols,this.grid.rows),this._characterFramebuffer.end()}resize(){super.resize(),this.sampleFramebuffer.resize(this.grid.cols,this.grid.rows)}brightnessRange(t){C.validate(Array.isArray(t)&&t.length===2&&t.every(r=>typeof r=="number"&&r>=0&&r<=255),"Brightness range must be an array of two numbers between 0 and 255.",{method:"brightnessRange",providedValue:t})&&(this._options.brightnessRange=t)}}const be=Object.freeze(Object.defineProperty({__proto__:null,TextmodeBrightnessConverter:$,TextmodeConverter:M,TextmodeFeatureConverter:k},Symbol.toStringTag,{value:"Module"}));var Fe="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);vec2 charCoord=vec2(charCol,charRow)/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);}";class J{constructor(e,t,r){o(this,"renderer");o(this,"font");o(this,"grid");o(this,"converters");o(this,"_resultFramebuffer");o(this,"_asciiShader");o(this,"_characterFramebuffer");o(this,"_primaryColorFramebuffer");o(this,"_secondaryColorFramebuffer");o(this,"_rotationFramebuffer");o(this,"_transformFramebuffer");this.renderer=e,this.font=t,this.grid=r,this._asciiShader=this.renderer.createShader(S,Fe),this.converters=[{name:"brightness",converter:new $(e,t,r)},{name:"custom",converter:new M(e,t,r)}],this._characterFramebuffer=this.renderer.createFramebuffer(r.cols,r.rows),this._primaryColorFramebuffer=this.renderer.createFramebuffer(r.cols,r.rows),this._secondaryColorFramebuffer=this.renderer.createFramebuffer(r.cols,r.rows),this._rotationFramebuffer=this.renderer.createFramebuffer(r.cols,r.rows),this._transformFramebuffer=this.renderer.createFramebuffer(r.cols,r.rows),this._resultFramebuffer=this.re