@utsp/render 0.15.0 → 0.16.0-nightly.20260101200530.42ed56f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/gl/index.cjs CHANGED
@@ -116,7 +116,7 @@
116
116
  gl_FragColor = vec4(texColor.rgb * vColor.rgb, texColor.a);
117
117
  }
118
118
  }
119
- `,i=this.compileShader(e.VERTEX_SHADER,t),n=this.compileShader(e.FRAGMENT_SHADER,s);if(!i||!n)throw new Error("Shader compilation error");let a=e.createProgram();if(!a)throw new Error("Unable to create WebGL program");if(e.attachShader(a,i),e.attachShader(a,n),e.linkProgram(a),!e.getProgramParameter(a,e.LINK_STATUS)){let l=e.getProgramInfoLog(a);throw new Error("Program linking error: "+l)}this.program=a,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=e.getAttribLocation(a,"aPosition"),this.useInstancing?(this.aInstanceOffset=e.getAttribLocation(a,"aInstanceOffset"),this.aInstanceUVs=e.getAttribLocation(a,"aInstanceUVs"),this.aInstanceColors=e.getAttribLocation(a,"aInstanceColors"),this.uCellSize=e.getUniformLocation(a,"uCellSize"),this.instanceDataBuffer=e.createBuffer(),this.aTexCoord=this.aInstanceOffset,this.aColorIndex=this.aInstanceUVs):(this.aTexCoord=e.getAttribLocation(a,"aTexCoord"),this.aColorIndex=e.getAttribLocation(a,"aColorIndex")),this.uResolution=e.getUniformLocation(a,"uResolution"),this.uTexture=e.getUniformLocation(a,"uTexture"),this.uPalette=e.getUniformLocation(a,"uPalette"),this.positionBuffer=e.createBuffer(),this.texCoordBuffer=e.createBuffer(),this.colorIndexBuffer=e.createBuffer(),this.indexBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderPositions.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderTexCoords.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderColorIndices.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),e.bufferData(e.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,e.DYNAMIC_DRAW),this.vaoExtension&&(this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.enableVertexAttribArray(this.aTexCoord),e.vertexAttribPointer(this.aTexCoord,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.enableVertexAttribArray(this.aColorIndex),e.vertexAttribPointer(this.aColorIndex,1,e.FLOAT,!1,0,0),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null))),e.enable(e.BLEND),e.blendFunc(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA),e.viewport(0,0,this.canvas.width,this.canvas.height)}compileShader(e,t){let s=this.gl,i=s.createShader(e);return i?(s.shaderSource(i,t),s.compileShader(i),s.getShaderParameter(i,s.COMPILE_STATUS)?i:(console.error("Shader compilation error:",s.getShaderInfoLog(i)),s.deleteShader(i),null)):null}initGridOverlay(){this.gridOverlay=new I(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let e=this.cols*this.cellWidth,t=this.rows*this.cellHeight,s=this.canvas.getBoundingClientRect(),i=this.containerDiv.getBoundingClientRect();this.gridOverlay.setDimensions(this.cols,this.rows,this.cellWidth,this.cellHeight,0,0),this.gridOverlay.setTransform(this.currentScale,e,t,s,i),this.gridOverlay.render()}setBitmapFont(e,t,s,i,n){this.bitmapFont=e,this.fontLoaded=!0,this.charWidth=Math.round(t),this.charHeight=Math.round(s),this.cellWidth=Math.round(i),this.cellHeight=Math.round(n),this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers..."),this.initInstancedBuffers());try{this.generateAtlas()}catch(a){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",a),a}this.buildCharCodeMap(),this.precomputeAtlasUVs(),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async setImageFont(e,t,s,i,n,a){this.fontLoaded=!0,this.charWidth=Math.round(t),this.charHeight=Math.round(s),this.cellWidth=Math.round(i),this.cellHeight=Math.round(n),this.atlasColumns=B(a);let l=F(a);this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers for ImageFont..."),this.initInstancedBuffers()),await this.loadImageFontAtlas(e),this.charCodeToAtlasIndex.fill(65535);for(let o=0;o<=l;o++)this.charCodeToAtlasIndex[o]=o;this.precomputeImageFontUVs(a),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async loadImageFontAtlas(e){return new Promise((t,s)=>{let i=new Uint8Array(e),n=new Blob([i],{type:"image/png"}),a=URL.createObjectURL(n),l=new Image;l.onload=()=>{URL.revokeObjectURL(a),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=l.width,this.atlasCanvas.height=l.height;let o=this.atlasCanvas.getContext("2d");if(!o){s(new Error("Failed to create 2D context for atlas"));return}o.drawImage(l,0,0),this.cachedAtlasWidth=l.width,this.cachedAtlasHeight=l.height,this.createAtlasTexture(),t()},l.onerror=()=>{URL.revokeObjectURL(a),s(new Error("Failed to load PNG image for ImageFont atlas"))},l.src=a})}precomputeImageFontUVs(e){let t=e*256;this.atlasUVs=new Float32Array(t*4);let s=this.cachedAtlasWidth,i=this.cachedAtlasHeight,n=.5/s,a=.5/i;for(let l=0;l<t;l++){let{col:o,row:c}=L(l,e),d=(o*this.charWidth+n)/s,h=(c*this.charHeight+a)/i,m=((o+1)*this.charWidth-n)/s,b=((c+1)*this.charHeight-a)/i,v=l*4;this.atlasUVs[v]=d,this.atlasUVs[v+1]=h,this.atlasUVs[v+2]=m,this.atlasUVs[v+3]=b}}generateAtlas(){if(!this.bitmapFont)return;let e=Array.from(this.bitmapFont.keys()).sort((o,c)=>o-c),t=e.length;this.atlasColumns=Math.ceil(Math.sqrt(t));let s=Math.ceil(t/this.atlasColumns),i=this.atlasColumns*this.charWidth,n=s*this.charHeight;this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=i,this.atlasCanvas.height=n;let a=this.atlasCanvas.getContext("2d");if(!a)throw new Error("Unable to create 2D context for atlas");a.clearRect(0,0,i,n),a.fillStyle="#ffffff";let l=0;for(let o of e){let c=this.bitmapFont.get(o);if(!c)continue;let d=l%this.atlasColumns,h=Math.floor(l/this.atlasColumns),m=d*this.charWidth,b=h*this.charHeight;for(let v=0;v<Math.min(c.length,this.charHeight);v++){let u=c[v];for(let g=0;g<this.charWidth;g++){let E=1<<7-g;u&E&&a.fillRect(m+g,b+v,1,1)}}l++}this.createAtlasTexture()}buildCharCodeMap(){if(!this.bitmapFont)return;this.charCodeToAtlasIndex.fill(65535);let e=Array.from(this.bitmapFont.keys()).sort((t,s)=>t-s);for(let t=0;t<e.length;t++)this.charCodeToAtlasIndex[e[t]]=t}precomputeAtlasUVs(){if(!this.bitmapFont)return;let e=this.bitmapFont.size;this.atlasUVs=new Float32Array(e*4),this.cachedAtlasWidth=this.atlasColumns*this.charWidth,this.cachedAtlasHeight=Math.ceil(e/this.atlasColumns)*this.charHeight;let t=this.cachedAtlasWidth,s=this.cachedAtlasHeight,i=.5/t,n=.5/s;for(let a=0;a<e;a++){let l=a%this.atlasColumns,o=Math.floor(a/this.atlasColumns),c=(l*this.charWidth+i)/t,d=(o*this.charHeight+n)/s,h=((l+1)*this.charWidth-i)/t,m=((o+1)*this.charHeight-n)/s,b=a*4;this.atlasUVs[b]=c,this.atlasUVs[b+1]=d,this.atlasUVs[b+2]=h,this.atlasUVs[b+3]=m}}createAtlasTexture(){if(this.atlasCanvas)try{let e=this.gl,t=e.createTexture();if(!t)throw new Error("Unable to create texture");e.bindTexture(e.TEXTURE_2D,t),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,this.atlasCanvas),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),this.atlasTexture=t}catch(e){throw console.error("[TerminalGL] \u274C Failed to create atlas texture:",e),e}}clear(){let e=this.gl;e&&e.clear(e.COLOR_BUFFER_BIT)}parseColor(e){if(e.startsWith("#")){let t=e.slice(1),s=0,i=0,n=0;return t.length===3?(s=parseInt(t[0]+t[0],16),i=parseInt(t[1]+t[1],16),n=parseInt(t[2]+t[2],16)):t.length===6&&(s=parseInt(t.slice(0,2),16),i=parseInt(t.slice(2,4),16),n=parseInt(t.slice(4,6),16)),[s/255,i/255,n/255,1]}if(e.startsWith("rgb")){let t=e.match(/rgba?\(([^)]+)\)/);if(t){let s=t[1].split(",").map(i=>parseFloat(i.trim()));return[s[0]/255,s[1]/255,s[2]/255,s[3]!==void 0?s[3]:1]}}return[1,1,1,1]}setupResizeObserver(){if(!(typeof ResizeObserver>"u"))try{this.resizeObserver=new ResizeObserver(()=>{try{this.updateCanvasSize()}catch(e){console.error("[TerminalGL] \u274C Error in resize callback:",e)}}),this.resizeObserver.observe(this.parentElement),this.updateCanvasSize()}catch(e){console.error("[TerminalGL] \u274C Failed to setup ResizeObserver:",e)}}updateCanvasSize(){let e=this.parentElement.clientWidth,t=this.parentElement.clientHeight;if(e===0||t===0)return;let s=this.cols*this.cellWidth,i=this.rows*this.cellHeight;if(s===0||i===0)return;let n=e/s,a=t/i,l=Math.min(n,a),o;switch(this.scalingMode){case x.ScalingMode.Integer:o=Math.max(1,Math.floor(l));break;case x.ScalingMode.Half:o=Math.max(1,Math.floor(l*2)/2);break;case x.ScalingMode.Quarter:o=Math.max(1,Math.floor(l*4)/4);break;case x.ScalingMode.Eighth:o=Math.max(1,Math.floor(l*8)/8);break;case x.ScalingMode.Responsive:o=1;break;case x.ScalingMode.None:default:o=Math.max(.1,l);break}if(this.canvas.style.transform=`scale(${o})`,this.ambientEffectEnabled&&this.ambientEffectCanvas){let c=o*this.ambientEffectScale;this.ambientEffectCanvas.style.transform=`scale(${c})`}this.currentScale=o,this.onResizeCallback&&this.onResizeCallback(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}updateAmbientEffect(){!this.ambientEffectCanvas||!this.ambientEffectCtx||this.ambientEffectCtx.drawImage(this.canvas,0,0)}setPalette(e){let t=0;for(let s=0;s<Math.min(e.length,256);s++){let i=e[s];t=(t<<5)-t+i.r,t=(t<<5)-t+i.g,t=(t<<5)-t+i.b,t=(t<<5)-t+i.a,t=t|0}if(t!==this.paletteHash){this.paletteHash=t;for(let s=0;s<e.length&&s<256;s++){let i=e[s],n=s*4;this.paletteFloat[n]=i.r/255,this.paletteFloat[n+1]=i.g/255,this.paletteFloat[n+2]=i.b/255,this.paletteFloat[n+3]=i.a/255}this.updatePaletteTexture()}}updatePaletteTexture(){try{let e=this.gl;this.paletteTexture||(this.paletteTexture=e.createTexture()),e.bindTexture(e.TEXTURE_2D,this.paletteTexture);let t=new Uint8Array(256*4);for(let s=0;s<256;s++){let i=s*4;t[i]=this.paletteFloat[i]*255,t[i+1]=this.paletteFloat[i+1]*255,t[i+2]=this.paletteFloat[i+2]*255,t[i+3]=this.paletteFloat[i+3]*255}e.texImage2D(e.TEXTURE_2D,0,e.RGBA,256,1,0,e.RGBA,e.UNSIGNED_BYTE,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.bindTexture(e.TEXTURE_2D,null)}catch(e){throw console.error("[TerminalGL] \u274C Failed to update palette texture:",e),e}}renderDisplayData(e){try{if(!this.isReady()){console.warn("[TerminalGL] \u26A0\uFE0F Not ready: font not loaded yet");return}(e.width!==this.cols||e.height!==this.rows)&&this.resize(e.width,e.height),this.renderDirect(e),this.ambientEffectEnabled&&this.ambientEffectCanvas&&this.ambientEffectCtx&&this.updateAmbientEffect()}catch(t){console.error("[TerminalGL] \u274C Error rendering display data:",t)}}renderDirect(e){let t=this.gl;if(!this.staticPositionsInitialized&&!this.useInstancing&&this.precomputeStaticPositions(),this.canvasBgColor!==null){let s=this.parseColor(this.canvasBgColor);t.clearColor(s[0],s[1],s[2],s[3])}else t.clearColor(0,0,0,0);t.clear(t.COLOR_BUFFER_BIT),this.useInstancing?this.renderInstanced(e):this.renderDirectBuffers(e)}renderInstanced(e){let t=this.gl,s=this.instancedExtension;if(!this.instanceData||this.instanceData.length===0){console.warn("[TerminalGL] \u26A0\uFE0F Instance data not initialized, falling back to standard rendering"),this.renderDirectBuffers(e);return}let i=0,n=this.instanceData.length/8,a=e.width*e.height*2;if(a>n){console.error(`[TerminalGL] \u274C Instance buffer too small! Need ${a}, have ${n}. Display size: ${e.width}\xD7${e.height}, buffer was sized for smaller terminal.`),this.renderDirectBuffers(e);return}for(let o=0;o<e.height;o++)for(let c=0;c<e.width;c++){let d=e.cells[o*e.width+c],h=d.bgColorIndex,m=d.fgColorIndex,b=this.canvasBgColor!==null&&h===255,v=d.char===" "||m===255;if(!b){if(i>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${i}, max=${n}`);break}let u=i*8;this.instanceData[u]=c,this.instanceData[u+1]=o,this.instanceData[u+2]=0,this.instanceData[u+3]=0,this.instanceData[u+4]=0,this.instanceData[u+5]=0,this.instanceData[u+6]=h,this.instanceData[u+7]=0,i++}if(!v){let u=d.char.charCodeAt(0),g=this.charCodeToAtlasIndex[u];if(g!==65535){if(i>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${i}, max=${n}`);break}let E=g*4,p=i*8;this.instanceData[p]=c,this.instanceData[p+1]=o,this.instanceData[p+2]=this.atlasUVs[E],this.instanceData[p+3]=this.atlasUVs[E+1],this.instanceData[p+4]=this.atlasUVs[E+2],this.instanceData[p+5]=this.atlasUVs[E+3],this.instanceData[p+6]=0,this.instanceData[p+7]=m,i++}}}if(i===0){console.warn("[TerminalGL] \u26A0\uFE0F No instances to draw (all cells skipped)");return}t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.instanceData.subarray(0,i*8)),t.useProgram(this.program),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),s.vertexAttribDivisorANGLE(this.aPosition,0),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer);let l=8*Float32Array.BYTES_PER_ELEMENT;t.enableVertexAttribArray(this.aInstanceOffset),t.vertexAttribPointer(this.aInstanceOffset,2,t.FLOAT,!1,l,0),s.vertexAttribDivisorANGLE(this.aInstanceOffset,1),t.enableVertexAttribArray(this.aInstanceUVs),t.vertexAttribPointer(this.aInstanceUVs,4,t.FLOAT,!1,l,2*Float32Array.BYTES_PER_ELEMENT),s.vertexAttribDivisorANGLE(this.aInstanceUVs,1),t.enableVertexAttribArray(this.aInstanceColors),t.vertexAttribPointer(this.aInstanceColors,2,t.FLOAT,!1,l,6*Float32Array.BYTES_PER_ELEMENT),s.vertexAttribDivisorANGLE(this.aInstanceColors,1),t.uniform2f(this.uResolution,this.canvas.width,this.canvas.height),t.uniform2f(this.uCellSize,this.cellWidth,this.cellHeight),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.atlasTexture),t.uniform1i(this.uTexture,0),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.paletteTexture),t.uniform1i(this.uPalette,1),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),s.drawElementsInstancedANGLE(t.TRIANGLES,6,t.UNSIGNED_SHORT,0,i),s.vertexAttribDivisorANGLE(this.aPosition,0),s.vertexAttribDivisorANGLE(this.aInstanceOffset,0),s.vertexAttribDivisorANGLE(this.aInstanceUVs,0),s.vertexAttribDivisorANGLE(this.aInstanceColors,0)}renderDirectBuffers(e){let t=this.gl,s=e.width*e.height,i=s*2;if(i>this.maxCells){console.error(`[TerminalGL] \u274C Buffer overflow detected! Trying to render ${i} quads but buffer capacity is ${this.maxCells}. This should not happen - resize() should have reallocated.`);return}let n=0,a=0,l=e.cells,o=s;for(let v=0;v<o;v++){let u=l[v],g=u.bgColorIndex,p=this.canvasBgColor!==null&&g===255?255:g,w=0;for(let T=0;T<4;T++)this.renderTexCoords[n++]=w,this.renderTexCoords[n++]=w,this.renderColorIndices[a++]=p;let A=u.fgColorIndex,S=u.char;if(S===" "||A===255)for(let T=0;T<4;T++)this.renderTexCoords[n++]=0,this.renderTexCoords[n++]=0,this.renderColorIndices[a++]=255;else{let T=S.charCodeAt(0),P=this.charCodeToAtlasIndex[T];if(P!==65535){let R=P*4,G=this.atlasUVs[R],W=this.atlasUVs[R+1],O=this.atlasUVs[R+2],H=this.atlasUVs[R+3];this.renderTexCoords[n++]=G,this.renderTexCoords[n++]=W,this.renderColorIndices[a++]=A,this.renderTexCoords[n++]=O,this.renderTexCoords[n++]=W,this.renderColorIndices[a++]=A,this.renderTexCoords[n++]=G,this.renderTexCoords[n++]=H,this.renderColorIndices[a++]=A,this.renderTexCoords[n++]=O,this.renderTexCoords[n++]=H,this.renderColorIndices[a++]=A}else for(let R=0;R<4;R++)this.renderTexCoords[n++]=0,this.renderTexCoords[n++]=0,this.renderColorIndices[a++]=255}}(n!==o*2*4*2||a!==o*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:n,colorIdx:a,expected:o*2*4}),t.useProgram(this.program),this.vao&&this.vaoExtension?(this.vaoExtension.bindVertexArrayOES(this.vao),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,n)),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,a))):(t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,n)),t.enableVertexAttribArray(this.aTexCoord),t.vertexAttribPointer(this.aTexCoord,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,a)),t.enableVertexAttribArray(this.aColorIndex),t.vertexAttribPointer(this.aColorIndex,1,t.FLOAT,!1,0,0));let c=this.canvas.width,d=this.canvas.height;(this.cachedResolution[0]!==c||this.cachedResolution[1]!==d)&&(t.uniform2f(this.uResolution,c,d),this.cachedResolution[0]=c,this.cachedResolution[1]=d),this.cachedTextureUnit!==0&&(t.activeTexture(t.TEXTURE0),this.cachedTextureUnit=0),t.bindTexture(t.TEXTURE_2D,this.atlasTexture),this.cachedTextureUniform||(t.uniform1i(this.uTexture,0),this.cachedTextureUniform=!0),this.cachedPaletteUnit!==1&&(t.activeTexture(t.TEXTURE1),this.cachedPaletteUnit=1),t.bindTexture(t.TEXTURE_2D,this.paletteTexture),this.cachedPaletteUniform||(t.uniform1i(this.uPalette,1),this.cachedPaletteUniform=!0),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer);let m=e.width*e.height*2*6,b=this.useUint16Indices?t.UNSIGNED_SHORT:t.UNSIGNED_INT;t.drawElements(t.TRIANGLES,m,b,0)}resize(e,t){if(!Number.isInteger(e)||e<=0){console.error(`[TerminalGL] \u274C Invalid cols: ${e}. Must be positive integer.`);return}if(!Number.isInteger(t)||t<=0){console.error(`[TerminalGL] \u274C Invalid rows: ${t}. Must be positive integer.`);return}if(e===this.cols&&t===this.rows)return;let s=e*t,i=this.useInstancing?262144:this.useUint16Indices?8191:262144;if(s>i){let d=Math.floor(Math.sqrt(i));console.error(`[TerminalGL] \u274C Cannot resize to ${e}\xD7${t} (${s} cells). Device limit: ${i} cells (max ~${d}\xD7${d}). ${!this.useInstancing&&this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let n=U.checkCompatibility();s>n.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${e}\xD7${t} (${s} cells) exceeds recommended limit (${n.recommendedMaxCells} cells). Performance may degrade.`),this.cols=e,this.rows=t,this.staticPositionsInitialized=!1;let a=this.cols*this.rows*2,l=Math.ceil(a*1.5),o=a>this.maxCells,c=this.maxCells>l*4;if(console.warn(`[TerminalGL] \u{1F4D0} resize check: cols=${e}, rows=${t}, newMaxCells=${a}, this.maxCells=${this.maxCells}, needGrow=${o}, needShrink=${c}`),o||c){let d=this.maxCells;if(this.maxCells=l,console.warn(`[TerminalGL] \u{1F4D0} resize realloc: ${d} \u2192 ${this.maxCells} (needGrow=${o}, needShrink=${c})`),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.useInstancing&&this.instanceDataBuffer){this.instanceData=new Float32Array(this.maxCells*8);let u=this.gl;u.bindBuffer(u.ARRAY_BUFFER,this.instanceDataBuffer),u.bufferData(u.ARRAY_BUFFER,this.instanceData.byteLength,u.DYNAMIC_DRAW)}let h=this.gl;this.useInstancing||(h.bindBuffer(h.ARRAY_BUFFER,this.positionBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderPositions.byteLength,h.DYNAMIC_DRAW)),h.bindBuffer(h.ARRAY_BUFFER,this.texCoordBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderTexCoords.byteLength,h.DYNAMIC_DRAW),h.bindBuffer(h.ARRAY_BUFFER,this.colorIndexBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderColorIndices.byteLength,h.DYNAMIC_DRAW),this.useInstancing||(h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.indexBuffer),h.bufferData(h.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,h.DYNAMIC_DRAW)),this.vaoExtension&&this.vao&&(this.vaoExtension.deleteVertexArrayOES(this.vao),this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),h.bindBuffer(h.ARRAY_BUFFER,this.positionBuffer),h.enableVertexAttribArray(this.aPosition),h.vertexAttribPointer(this.aPosition,2,h.FLOAT,!1,0,0),h.bindBuffer(h.ARRAY_BUFFER,this.texCoordBuffer),h.enableVertexAttribArray(this.aTexCoord),h.vertexAttribPointer(this.aTexCoord,2,h.FLOAT,!1,0,0),h.bindBuffer(h.ARRAY_BUFFER,this.colorIndexBuffer),h.enableVertexAttribArray(this.aColorIndex),h.vertexAttribPointer(this.aColorIndex,1,h.FLOAT,!1,0,0),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null)));let m=o?"\u{1F4C8} Growing":"\u{1F4C9} Shrinking",b=d*160/1048576,v=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${m} buffers: ${b.toFixed(2)}MB \u2192 ${v.toFixed(2)}MB (${d} \u2192 ${this.maxCells} quads)`)}this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.canvas.style.width=`${this.canvas.width}px`,this.canvas.style.height=`${this.canvas.height}px`,this.ambientEffectEnabled&&this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.width=`${this.canvas.width}px`,this.ambientEffectCanvas.style.height=`${this.canvas.height}px`),this.showGrid&&this.gridOverlay&&this.updateGridOverlay(),this.updateCanvasSize()}getCanvas(){return this.canvas}getGridSize(){return{cols:this.cols,rows:this.rows}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getBaseDimensions(){return{width:this.cols*this.cellWidth,height:this.rows*this.cellHeight}}setOnResizeCallback(e){this.onResizeCallback=e}clearOnResizeCallback(){this.onResizeCallback=void 0}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}setScalingMode(e){this.scalingMode!==e&&(this.scalingMode=e,this.updateCanvasSize())}getScalingMode(){return this.scalingMode}setCellSize(e,t){let s=Math.max(1,Math.min(255,Math.round(e))),i=Math.max(1,Math.min(255,Math.round(t)));this.cellWidth===s&&this.cellHeight===i||(this.cellWidth=s,this.cellHeight=i,this.charWidth=s,this.charHeight=i,this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.fontLoaded&&this.generateAtlas(),this.useInstancing&&this.initInstancedBuffers(),this.updateCanvasSize())}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getMaxCells(){return this.useInstancing?262144:this.useUint16Indices?8191:262144}setGrid(e){e.enabled?(this.gridOverlay?this.gridOverlay.setStyle({strokeColor:e.color,lineWidth:e.lineWidth}):this.gridOverlay=new I(this.containerDiv,{strokeColor:e.color??"rgba(144, 24, 24, 1)",lineWidth:e.lineWidth??1,zIndex:10}),this.showGrid=!0,this.gridOverlay.setVisible(!0),this.updateGridOverlay()):(this.showGrid=!1,this.gridOverlay&&this.gridOverlay.setVisible(!1))}isGridEnabled(){return this.showGrid}setAmbientEffect(e){typeof e=="boolean"?this.ambientEffectEnabled=e:(this.ambientEffectEnabled=!0,e.blur!==void 0&&(this.ambientEffectBlur=e.blur),e.scale!==void 0&&(this.ambientEffectScale=e.scale)),this.ambientEffectEnabled&&!this.ambientEffectCanvas&&this.createAmbientEffectCanvas(),this.ambientEffectCanvas&&(this.ambientEffectEnabled?(this.ambientEffectCanvas.style.display="block",this.ambientEffectCanvas.style.filter=`blur(${this.ambientEffectBlur}px)`,this.ambientEffectCanvas.style.transform=`scale(${this.ambientEffectScale})`,this.updateAmbientEffect()):this.ambientEffectCanvas.style.display="none")}createAmbientEffectCanvas(){this.ambientEffectCanvas||(this.ambientEffectCanvas=document.createElement("canvas"),this.ambientEffectCanvas.className="terminalgl-ambient-effect-canvas",this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.cssText=`
119
+ `,i=this.compileShader(e.VERTEX_SHADER,t),n=this.compileShader(e.FRAGMENT_SHADER,s);if(!i||!n)throw new Error("Shader compilation error");let a=e.createProgram();if(!a)throw new Error("Unable to create WebGL program");if(e.attachShader(a,i),e.attachShader(a,n),e.linkProgram(a),!e.getProgramParameter(a,e.LINK_STATUS)){let l=e.getProgramInfoLog(a);throw new Error("Program linking error: "+l)}this.program=a,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=e.getAttribLocation(a,"aPosition"),this.useInstancing?(this.aInstanceOffset=e.getAttribLocation(a,"aInstanceOffset"),this.aInstanceUVs=e.getAttribLocation(a,"aInstanceUVs"),this.aInstanceColors=e.getAttribLocation(a,"aInstanceColors"),this.uCellSize=e.getUniformLocation(a,"uCellSize"),this.instanceDataBuffer=e.createBuffer(),this.aTexCoord=this.aInstanceOffset,this.aColorIndex=this.aInstanceUVs):(this.aTexCoord=e.getAttribLocation(a,"aTexCoord"),this.aColorIndex=e.getAttribLocation(a,"aColorIndex")),this.uResolution=e.getUniformLocation(a,"uResolution"),this.uTexture=e.getUniformLocation(a,"uTexture"),this.uPalette=e.getUniformLocation(a,"uPalette"),this.positionBuffer=e.createBuffer(),this.texCoordBuffer=e.createBuffer(),this.colorIndexBuffer=e.createBuffer(),this.indexBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderPositions.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderTexCoords.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderColorIndices.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),e.bufferData(e.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,e.DYNAMIC_DRAW),this.vaoExtension&&(this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.enableVertexAttribArray(this.aTexCoord),e.vertexAttribPointer(this.aTexCoord,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.enableVertexAttribArray(this.aColorIndex),e.vertexAttribPointer(this.aColorIndex,1,e.FLOAT,!1,0,0),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null))),e.enable(e.BLEND),e.blendFunc(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA),e.viewport(0,0,this.canvas.width,this.canvas.height)}compileShader(e,t){let s=this.gl,i=s.createShader(e);return i?(s.shaderSource(i,t),s.compileShader(i),s.getShaderParameter(i,s.COMPILE_STATUS)?i:(console.error("Shader compilation error:",s.getShaderInfoLog(i)),s.deleteShader(i),null)):null}initGridOverlay(){this.gridOverlay=new I(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let e=this.cols*this.cellWidth,t=this.rows*this.cellHeight,s=this.canvas.getBoundingClientRect(),i=this.containerDiv.getBoundingClientRect();this.gridOverlay.setDimensions(this.cols,this.rows,this.cellWidth,this.cellHeight,0,0),this.gridOverlay.setTransform(this.currentScale,e,t,s,i),this.gridOverlay.render()}setBitmapFont(e,t,s,i,n){this.bitmapFont=e,this.fontLoaded=!0,this.charWidth=Math.round(t),this.charHeight=Math.round(s),this.cellWidth=Math.round(i),this.cellHeight=Math.round(n),this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers..."),this.initInstancedBuffers());try{this.generateAtlas()}catch(a){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",a),a}this.buildCharCodeMap(),this.precomputeAtlasUVs(),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async setImageFont(e,t,s,i,n,a){this.fontLoaded=!0,this.charWidth=Math.round(t),this.charHeight=Math.round(s),this.cellWidth=Math.round(i),this.cellHeight=Math.round(n),this.atlasColumns=B(a);let l=F(a);this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers for ImageFont..."),this.initInstancedBuffers()),await this.loadImageFontAtlas(e),this.charCodeToAtlasIndex.fill(65535);for(let o=0;o<=l;o++)this.charCodeToAtlasIndex[o]=o;this.precomputeImageFontUVs(a),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async loadImageFontAtlas(e){return new Promise((t,s)=>{let i=new Uint8Array(e),n=new Blob([i],{type:"image/png"}),a=URL.createObjectURL(n),l=new Image;l.onload=()=>{URL.revokeObjectURL(a),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=l.width,this.atlasCanvas.height=l.height;let o=this.atlasCanvas.getContext("2d");if(!o){s(new Error("Failed to create 2D context for atlas"));return}o.drawImage(l,0,0),this.cachedAtlasWidth=l.width,this.cachedAtlasHeight=l.height,this.createAtlasTexture(),t()},l.onerror=()=>{URL.revokeObjectURL(a),s(new Error("Failed to load PNG image for ImageFont atlas"))},l.src=a})}precomputeImageFontUVs(e){let t=e*256;this.atlasUVs=new Float32Array(t*4);let s=this.cachedAtlasWidth,i=this.cachedAtlasHeight,n=.5/s,a=.5/i;for(let l=0;l<t;l++){let{col:o,row:c}=L(l,e),d=(o*this.charWidth+n)/s,h=(c*this.charHeight+a)/i,m=((o+1)*this.charWidth-n)/s,b=((c+1)*this.charHeight-a)/i,v=l*4;this.atlasUVs[v]=d,this.atlasUVs[v+1]=h,this.atlasUVs[v+2]=m,this.atlasUVs[v+3]=b}}generateAtlas(){if(!this.bitmapFont)return;let e=Array.from(this.bitmapFont.keys()).sort((o,c)=>o-c),t=e.length;this.atlasColumns=Math.ceil(Math.sqrt(t));let s=Math.ceil(t/this.atlasColumns),i=this.atlasColumns*this.charWidth,n=s*this.charHeight;this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=i,this.atlasCanvas.height=n;let a=this.atlasCanvas.getContext("2d");if(!a)throw new Error("Unable to create 2D context for atlas");a.clearRect(0,0,i,n),a.fillStyle="#ffffff";let l=0;for(let o of e){let c=this.bitmapFont.get(o);if(!c)continue;let d=l%this.atlasColumns,h=Math.floor(l/this.atlasColumns),m=d*this.charWidth,b=h*this.charHeight;for(let v=0;v<Math.min(c.length,this.charHeight);v++){let u=c[v];for(let g=0;g<this.charWidth;g++){let E=1<<7-g;u&E&&a.fillRect(m+g,b+v,1,1)}}l++}this.createAtlasTexture()}buildCharCodeMap(){if(!this.bitmapFont)return;this.charCodeToAtlasIndex.fill(65535);let e=Array.from(this.bitmapFont.keys()).sort((t,s)=>t-s);for(let t=0;t<e.length;t++)this.charCodeToAtlasIndex[e[t]]=t}precomputeAtlasUVs(){if(!this.bitmapFont)return;let e=this.bitmapFont.size;this.atlasUVs=new Float32Array(e*4),this.cachedAtlasWidth=this.atlasColumns*this.charWidth,this.cachedAtlasHeight=Math.ceil(e/this.atlasColumns)*this.charHeight;let t=this.cachedAtlasWidth,s=this.cachedAtlasHeight,i=.5/t,n=.5/s;for(let a=0;a<e;a++){let l=a%this.atlasColumns,o=Math.floor(a/this.atlasColumns),c=(l*this.charWidth+i)/t,d=(o*this.charHeight+n)/s,h=((l+1)*this.charWidth-i)/t,m=((o+1)*this.charHeight-n)/s,b=a*4;this.atlasUVs[b]=c,this.atlasUVs[b+1]=d,this.atlasUVs[b+2]=h,this.atlasUVs[b+3]=m}}createAtlasTexture(){if(this.atlasCanvas)try{let e=this.gl,t=e.createTexture();if(!t)throw new Error("Unable to create texture");e.bindTexture(e.TEXTURE_2D,t),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,this.atlasCanvas),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),this.atlasTexture=t}catch(e){throw console.error("[TerminalGL] \u274C Failed to create atlas texture:",e),e}}clear(){let e=this.gl;e&&e.clear(e.COLOR_BUFFER_BIT)}parseColor(e){if(e.startsWith("#")){let t=e.slice(1),s=0,i=0,n=0;return t.length===3?(s=parseInt(t[0]+t[0],16),i=parseInt(t[1]+t[1],16),n=parseInt(t[2]+t[2],16)):t.length===6&&(s=parseInt(t.slice(0,2),16),i=parseInt(t.slice(2,4),16),n=parseInt(t.slice(4,6),16)),[s/255,i/255,n/255,1]}if(e.startsWith("rgb")){let t=e.match(/rgba?\(([^)]+)\)/);if(t){let s=t[1].split(",").map(i=>parseFloat(i.trim()));return[s[0]/255,s[1]/255,s[2]/255,s[3]!==void 0?s[3]:1]}}return[1,1,1,1]}setupResizeObserver(){if(!(typeof ResizeObserver>"u"))try{this.resizeObserver=new ResizeObserver(()=>{try{this.updateCanvasSize()}catch(e){console.error("[TerminalGL] \u274C Error in resize callback:",e)}}),this.resizeObserver.observe(this.parentElement),this.updateCanvasSize()}catch(e){console.error("[TerminalGL] \u274C Failed to setup ResizeObserver:",e)}}updateCanvasSize(){let e=this.parentElement.clientWidth,t=this.parentElement.clientHeight;if(e===0||t===0)return;let s=this.cols*this.cellWidth,i=this.rows*this.cellHeight;if(s===0||i===0)return;let n=e/s,a=t/i,l=Math.min(n,a),o;switch(this.scalingMode){case x.ScalingMode.Integer:o=Math.max(1,Math.floor(l));break;case x.ScalingMode.Half:o=Math.max(1,Math.floor(l*2)/2);break;case x.ScalingMode.Quarter:o=Math.max(1,Math.floor(l*4)/4);break;case x.ScalingMode.Eighth:o=Math.max(1,Math.floor(l*8)/8);break;case x.ScalingMode.Responsive:o=1;break;case x.ScalingMode.None:default:o=Math.max(.1,l);break}if(this.canvas.style.transform=`scale(${o})`,this.ambientEffectEnabled&&this.ambientEffectCanvas){let c=o*this.ambientEffectScale;this.ambientEffectCanvas.style.transform=`scale(${c})`}this.currentScale=o,this.onResizeCallback&&this.onResizeCallback(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}updateAmbientEffect(){!this.ambientEffectCanvas||!this.ambientEffectCtx||this.ambientEffectCtx.drawImage(this.canvas,0,0)}setPalette(e){let t=0;for(let s=0;s<Math.min(e.length,256);s++){let i=e[s];t=(t<<5)-t+i.r,t=(t<<5)-t+i.g,t=(t<<5)-t+i.b,t=(t<<5)-t+i.a,t=t|0}if(t!==this.paletteHash){this.paletteHash=t;for(let s=0;s<e.length&&s<256;s++){let i=e[s],n=s*4;this.paletteFloat[n]=i.r/255,this.paletteFloat[n+1]=i.g/255,this.paletteFloat[n+2]=i.b/255,this.paletteFloat[n+3]=i.a/255}this.updatePaletteTexture()}}updatePaletteTexture(){try{let e=this.gl;this.paletteTexture||(this.paletteTexture=e.createTexture()),e.bindTexture(e.TEXTURE_2D,this.paletteTexture);let t=new Uint8Array(256*4);for(let s=0;s<256;s++){let i=s*4;t[i]=this.paletteFloat[i]*255,t[i+1]=this.paletteFloat[i+1]*255,t[i+2]=this.paletteFloat[i+2]*255,t[i+3]=this.paletteFloat[i+3]*255}e.texImage2D(e.TEXTURE_2D,0,e.RGBA,256,1,0,e.RGBA,e.UNSIGNED_BYTE,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.bindTexture(e.TEXTURE_2D,null)}catch(e){throw console.error("[TerminalGL] \u274C Failed to update palette texture:",e),e}}renderDisplayData(e){try{if(!this.isReady()){console.warn("[TerminalGL] \u26A0\uFE0F Not ready: font not loaded yet");return}(e.width!==this.cols||e.height!==this.rows)&&this.resize(e.width,e.height),e.passes&&e.passes.length>0?this.renderMultiPass(e,e.passes):this.renderDirect(e),this.ambientEffectEnabled&&this.ambientEffectCanvas&&this.ambientEffectCtx&&this.updateAmbientEffect()}catch(t){console.error("[TerminalGL] \u274C Error rendering display data:",t)}}renderMultiPass(e,t){for(let s=0;s<t.length;s++){let i=t[s],n={id:e.id,width:e.width,height:e.height,palette:e.palette,cells:i.cells};this.renderDirect(n,s===0)}}renderDirect(e,t=!0){let s=this.gl;if(!this.staticPositionsInitialized&&!this.useInstancing&&this.precomputeStaticPositions(),t){if(this.canvasBgColor!==null){let i=this.parseColor(this.canvasBgColor);s.clearColor(i[0],i[1],i[2],i[3])}else s.clearColor(0,0,0,0);s.clear(s.COLOR_BUFFER_BIT)}this.useInstancing?this.renderInstanced(e):this.renderDirectBuffers(e)}renderInstanced(e){let t=this.gl,s=this.instancedExtension;if(!this.instanceData||this.instanceData.length===0){console.warn("[TerminalGL] \u26A0\uFE0F Instance data not initialized, falling back to standard rendering"),this.renderDirectBuffers(e);return}let i=0,n=this.instanceData.length/8,a=e.width*e.height*2;if(a>n){console.error(`[TerminalGL] \u274C Instance buffer too small! Need ${a}, have ${n}. Display size: ${e.width}\xD7${e.height}, buffer was sized for smaller terminal.`),this.renderDirectBuffers(e);return}for(let o=0;o<e.height;o++)for(let c=0;c<e.width;c++){let d=e.cells[o*e.width+c],h=d.bgColorIndex,m=d.fgColorIndex,b=this.canvasBgColor!==null&&h===255,v=d.char===" "||m===255;if(!b){if(i>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${i}, max=${n}`);break}let u=i*8;this.instanceData[u]=c,this.instanceData[u+1]=o,this.instanceData[u+2]=0,this.instanceData[u+3]=0,this.instanceData[u+4]=0,this.instanceData[u+5]=0,this.instanceData[u+6]=h,this.instanceData[u+7]=0,i++}if(!v){let u=d.char.charCodeAt(0),g=this.charCodeToAtlasIndex[u];if(g!==65535){if(i>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${i}, max=${n}`);break}let E=g*4,p=i*8;this.instanceData[p]=c,this.instanceData[p+1]=o,this.instanceData[p+2]=this.atlasUVs[E],this.instanceData[p+3]=this.atlasUVs[E+1],this.instanceData[p+4]=this.atlasUVs[E+2],this.instanceData[p+5]=this.atlasUVs[E+3],this.instanceData[p+6]=0,this.instanceData[p+7]=m,i++}}}if(i===0){console.warn("[TerminalGL] \u26A0\uFE0F No instances to draw (all cells skipped)");return}t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.instanceData.subarray(0,i*8)),t.useProgram(this.program),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),s.vertexAttribDivisorANGLE(this.aPosition,0),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer);let l=8*Float32Array.BYTES_PER_ELEMENT;t.enableVertexAttribArray(this.aInstanceOffset),t.vertexAttribPointer(this.aInstanceOffset,2,t.FLOAT,!1,l,0),s.vertexAttribDivisorANGLE(this.aInstanceOffset,1),t.enableVertexAttribArray(this.aInstanceUVs),t.vertexAttribPointer(this.aInstanceUVs,4,t.FLOAT,!1,l,2*Float32Array.BYTES_PER_ELEMENT),s.vertexAttribDivisorANGLE(this.aInstanceUVs,1),t.enableVertexAttribArray(this.aInstanceColors),t.vertexAttribPointer(this.aInstanceColors,2,t.FLOAT,!1,l,6*Float32Array.BYTES_PER_ELEMENT),s.vertexAttribDivisorANGLE(this.aInstanceColors,1),t.uniform2f(this.uResolution,this.canvas.width,this.canvas.height),t.uniform2f(this.uCellSize,this.cellWidth,this.cellHeight),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.atlasTexture),t.uniform1i(this.uTexture,0),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.paletteTexture),t.uniform1i(this.uPalette,1),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),s.drawElementsInstancedANGLE(t.TRIANGLES,6,t.UNSIGNED_SHORT,0,i),s.vertexAttribDivisorANGLE(this.aPosition,0),s.vertexAttribDivisorANGLE(this.aInstanceOffset,0),s.vertexAttribDivisorANGLE(this.aInstanceUVs,0),s.vertexAttribDivisorANGLE(this.aInstanceColors,0)}renderDirectBuffers(e){let t=this.gl,s=e.width*e.height,i=s*2;if(i>this.maxCells){console.error(`[TerminalGL] \u274C Buffer overflow detected! Trying to render ${i} quads but buffer capacity is ${this.maxCells}. This should not happen - resize() should have reallocated.`);return}let n=0,a=0,l=e.cells,o=s;for(let v=0;v<o;v++){let u=l[v],g=u.bgColorIndex,p=this.canvasBgColor!==null&&g===255?255:g,w=0;for(let T=0;T<4;T++)this.renderTexCoords[n++]=w,this.renderTexCoords[n++]=w,this.renderColorIndices[a++]=p;let A=u.fgColorIndex,S=u.char;if(S===" "||A===255)for(let T=0;T<4;T++)this.renderTexCoords[n++]=0,this.renderTexCoords[n++]=0,this.renderColorIndices[a++]=255;else{let T=S.charCodeAt(0),P=this.charCodeToAtlasIndex[T];if(P!==65535){let R=P*4,G=this.atlasUVs[R],W=this.atlasUVs[R+1],O=this.atlasUVs[R+2],H=this.atlasUVs[R+3];this.renderTexCoords[n++]=G,this.renderTexCoords[n++]=W,this.renderColorIndices[a++]=A,this.renderTexCoords[n++]=O,this.renderTexCoords[n++]=W,this.renderColorIndices[a++]=A,this.renderTexCoords[n++]=G,this.renderTexCoords[n++]=H,this.renderColorIndices[a++]=A,this.renderTexCoords[n++]=O,this.renderTexCoords[n++]=H,this.renderColorIndices[a++]=A}else for(let R=0;R<4;R++)this.renderTexCoords[n++]=0,this.renderTexCoords[n++]=0,this.renderColorIndices[a++]=255}}(n!==o*2*4*2||a!==o*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:n,colorIdx:a,expected:o*2*4}),t.useProgram(this.program),this.vao&&this.vaoExtension?(this.vaoExtension.bindVertexArrayOES(this.vao),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,n)),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,a))):(t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,n)),t.enableVertexAttribArray(this.aTexCoord),t.vertexAttribPointer(this.aTexCoord,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,a)),t.enableVertexAttribArray(this.aColorIndex),t.vertexAttribPointer(this.aColorIndex,1,t.FLOAT,!1,0,0));let c=this.canvas.width,d=this.canvas.height;(this.cachedResolution[0]!==c||this.cachedResolution[1]!==d)&&(t.uniform2f(this.uResolution,c,d),this.cachedResolution[0]=c,this.cachedResolution[1]=d),this.cachedTextureUnit!==0&&(t.activeTexture(t.TEXTURE0),this.cachedTextureUnit=0),t.bindTexture(t.TEXTURE_2D,this.atlasTexture),this.cachedTextureUniform||(t.uniform1i(this.uTexture,0),this.cachedTextureUniform=!0),this.cachedPaletteUnit!==1&&(t.activeTexture(t.TEXTURE1),this.cachedPaletteUnit=1),t.bindTexture(t.TEXTURE_2D,this.paletteTexture),this.cachedPaletteUniform||(t.uniform1i(this.uPalette,1),this.cachedPaletteUniform=!0),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer);let m=e.width*e.height*2*6,b=this.useUint16Indices?t.UNSIGNED_SHORT:t.UNSIGNED_INT;t.drawElements(t.TRIANGLES,m,b,0)}resize(e,t){if(!Number.isInteger(e)||e<=0){console.error(`[TerminalGL] \u274C Invalid cols: ${e}. Must be positive integer.`);return}if(!Number.isInteger(t)||t<=0){console.error(`[TerminalGL] \u274C Invalid rows: ${t}. Must be positive integer.`);return}if(e===this.cols&&t===this.rows)return;let s=e*t,i=this.useInstancing?262144:this.useUint16Indices?8191:262144;if(s>i){let d=Math.floor(Math.sqrt(i));console.error(`[TerminalGL] \u274C Cannot resize to ${e}\xD7${t} (${s} cells). Device limit: ${i} cells (max ~${d}\xD7${d}). ${!this.useInstancing&&this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let n=U.checkCompatibility();s>n.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${e}\xD7${t} (${s} cells) exceeds recommended limit (${n.recommendedMaxCells} cells). Performance may degrade.`),this.cols=e,this.rows=t,this.staticPositionsInitialized=!1;let a=this.cols*this.rows*2,l=Math.ceil(a*1.5),o=a>this.maxCells,c=this.maxCells>l*4;if(console.warn(`[TerminalGL] \u{1F4D0} resize check: cols=${e}, rows=${t}, newMaxCells=${a}, this.maxCells=${this.maxCells}, needGrow=${o}, needShrink=${c}`),o||c){let d=this.maxCells;if(this.maxCells=l,console.warn(`[TerminalGL] \u{1F4D0} resize realloc: ${d} \u2192 ${this.maxCells} (needGrow=${o}, needShrink=${c})`),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.useInstancing&&this.instanceDataBuffer){this.instanceData=new Float32Array(this.maxCells*8);let u=this.gl;u.bindBuffer(u.ARRAY_BUFFER,this.instanceDataBuffer),u.bufferData(u.ARRAY_BUFFER,this.instanceData.byteLength,u.DYNAMIC_DRAW)}let h=this.gl;this.useInstancing||(h.bindBuffer(h.ARRAY_BUFFER,this.positionBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderPositions.byteLength,h.DYNAMIC_DRAW)),h.bindBuffer(h.ARRAY_BUFFER,this.texCoordBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderTexCoords.byteLength,h.DYNAMIC_DRAW),h.bindBuffer(h.ARRAY_BUFFER,this.colorIndexBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderColorIndices.byteLength,h.DYNAMIC_DRAW),this.useInstancing||(h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.indexBuffer),h.bufferData(h.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,h.DYNAMIC_DRAW)),this.vaoExtension&&this.vao&&(this.vaoExtension.deleteVertexArrayOES(this.vao),this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),h.bindBuffer(h.ARRAY_BUFFER,this.positionBuffer),h.enableVertexAttribArray(this.aPosition),h.vertexAttribPointer(this.aPosition,2,h.FLOAT,!1,0,0),h.bindBuffer(h.ARRAY_BUFFER,this.texCoordBuffer),h.enableVertexAttribArray(this.aTexCoord),h.vertexAttribPointer(this.aTexCoord,2,h.FLOAT,!1,0,0),h.bindBuffer(h.ARRAY_BUFFER,this.colorIndexBuffer),h.enableVertexAttribArray(this.aColorIndex),h.vertexAttribPointer(this.aColorIndex,1,h.FLOAT,!1,0,0),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null)));let m=o?"\u{1F4C8} Growing":"\u{1F4C9} Shrinking",b=d*160/1048576,v=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${m} buffers: ${b.toFixed(2)}MB \u2192 ${v.toFixed(2)}MB (${d} \u2192 ${this.maxCells} quads)`)}this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.canvas.style.width=`${this.canvas.width}px`,this.canvas.style.height=`${this.canvas.height}px`,this.ambientEffectEnabled&&this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.width=`${this.canvas.width}px`,this.ambientEffectCanvas.style.height=`${this.canvas.height}px`),this.showGrid&&this.gridOverlay&&this.updateGridOverlay(),this.updateCanvasSize()}getCanvas(){return this.canvas}getGridSize(){return{cols:this.cols,rows:this.rows}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getBaseDimensions(){return{width:this.cols*this.cellWidth,height:this.rows*this.cellHeight}}setOnResizeCallback(e){this.onResizeCallback=e}clearOnResizeCallback(){this.onResizeCallback=void 0}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}setScalingMode(e){this.scalingMode!==e&&(this.scalingMode=e,this.updateCanvasSize())}getScalingMode(){return this.scalingMode}setCellSize(e,t){let s=Math.max(1,Math.min(255,Math.round(e))),i=Math.max(1,Math.min(255,Math.round(t)));this.cellWidth===s&&this.cellHeight===i||(this.cellWidth=s,this.cellHeight=i,this.charWidth=s,this.charHeight=i,this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.fontLoaded&&this.generateAtlas(),this.useInstancing&&this.initInstancedBuffers(),this.updateCanvasSize())}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getMaxCells(){return this.useInstancing?262144:this.useUint16Indices?8191:262144}setGrid(e){e.enabled?(this.gridOverlay?this.gridOverlay.setStyle({strokeColor:e.color,lineWidth:e.lineWidth}):this.gridOverlay=new I(this.containerDiv,{strokeColor:e.color??"rgba(144, 24, 24, 1)",lineWidth:e.lineWidth??1,zIndex:10}),this.showGrid=!0,this.gridOverlay.setVisible(!0),this.updateGridOverlay()):(this.showGrid=!1,this.gridOverlay&&this.gridOverlay.setVisible(!1))}isGridEnabled(){return this.showGrid}setAmbientEffect(e){typeof e=="boolean"?this.ambientEffectEnabled=e:(this.ambientEffectEnabled=!0,e.blur!==void 0&&(this.ambientEffectBlur=e.blur),e.scale!==void 0&&(this.ambientEffectScale=e.scale)),this.ambientEffectEnabled&&!this.ambientEffectCanvas&&this.createAmbientEffectCanvas(),this.ambientEffectCanvas&&(this.ambientEffectEnabled?(this.ambientEffectCanvas.style.display="block",this.ambientEffectCanvas.style.filter=`blur(${this.ambientEffectBlur}px)`,this.ambientEffectCanvas.style.transform=`scale(${this.ambientEffectScale})`,this.updateAmbientEffect()):this.ambientEffectCanvas.style.display="none")}createAmbientEffectCanvas(){this.ambientEffectCanvas||(this.ambientEffectCanvas=document.createElement("canvas"),this.ambientEffectCanvas.className="terminalgl-ambient-effect-canvas",this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.cssText=`
120
120
  display: block !important;
121
121
  position: absolute !important;
122
122
  width: ${this.canvas.width}px !important;
@@ -456,6 +456,10 @@ declare class TerminalGL implements IRenderer {
456
456
  * ```
457
457
  */
458
458
  renderDisplayData(data: RenderState): void;
459
+ /**
460
+ * Render multiple passes in order, clearing once then layering.
461
+ */
462
+ private renderMultiPass;
459
463
  /**
460
464
  * 🚀 NEW METHOD: Render directly from RenderState
461
465
  * Bypass this.cells for maximum performance
package/dist/gl/index.mjs CHANGED
@@ -116,7 +116,7 @@ var $=Object.defineProperty;var V=(v,e,t)=>e in v?$(v,e,{enumerable:!0,configura
116
116
  gl_FragColor = vec4(texColor.rgb * vColor.rgb, texColor.a);
117
117
  }
118
118
  }
119
- `,i=this.compileShader(e.VERTEX_SHADER,t),n=this.compileShader(e.FRAGMENT_SHADER,s);if(!i||!n)throw new Error("Shader compilation error");let a=e.createProgram();if(!a)throw new Error("Unable to create WebGL program");if(e.attachShader(a,i),e.attachShader(a,n),e.linkProgram(a),!e.getProgramParameter(a,e.LINK_STATUS)){let l=e.getProgramInfoLog(a);throw new Error("Program linking error: "+l)}this.program=a,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=e.getAttribLocation(a,"aPosition"),this.useInstancing?(this.aInstanceOffset=e.getAttribLocation(a,"aInstanceOffset"),this.aInstanceUVs=e.getAttribLocation(a,"aInstanceUVs"),this.aInstanceColors=e.getAttribLocation(a,"aInstanceColors"),this.uCellSize=e.getUniformLocation(a,"uCellSize"),this.instanceDataBuffer=e.createBuffer(),this.aTexCoord=this.aInstanceOffset,this.aColorIndex=this.aInstanceUVs):(this.aTexCoord=e.getAttribLocation(a,"aTexCoord"),this.aColorIndex=e.getAttribLocation(a,"aColorIndex")),this.uResolution=e.getUniformLocation(a,"uResolution"),this.uTexture=e.getUniformLocation(a,"uTexture"),this.uPalette=e.getUniformLocation(a,"uPalette"),this.positionBuffer=e.createBuffer(),this.texCoordBuffer=e.createBuffer(),this.colorIndexBuffer=e.createBuffer(),this.indexBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderPositions.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderTexCoords.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderColorIndices.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),e.bufferData(e.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,e.DYNAMIC_DRAW),this.vaoExtension&&(this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.enableVertexAttribArray(this.aTexCoord),e.vertexAttribPointer(this.aTexCoord,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.enableVertexAttribArray(this.aColorIndex),e.vertexAttribPointer(this.aColorIndex,1,e.FLOAT,!1,0,0),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null))),e.enable(e.BLEND),e.blendFunc(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA),e.viewport(0,0,this.canvas.width,this.canvas.height)}compileShader(e,t){let s=this.gl,i=s.createShader(e);return i?(s.shaderSource(i,t),s.compileShader(i),s.getShaderParameter(i,s.COMPILE_STATUS)?i:(console.error("Shader compilation error:",s.getShaderInfoLog(i)),s.deleteShader(i),null)):null}initGridOverlay(){this.gridOverlay=new I(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let e=this.cols*this.cellWidth,t=this.rows*this.cellHeight,s=this.canvas.getBoundingClientRect(),i=this.containerDiv.getBoundingClientRect();this.gridOverlay.setDimensions(this.cols,this.rows,this.cellWidth,this.cellHeight,0,0),this.gridOverlay.setTransform(this.currentScale,e,t,s,i),this.gridOverlay.render()}setBitmapFont(e,t,s,i,n){this.bitmapFont=e,this.fontLoaded=!0,this.charWidth=Math.round(t),this.charHeight=Math.round(s),this.cellWidth=Math.round(i),this.cellHeight=Math.round(n),this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers..."),this.initInstancedBuffers());try{this.generateAtlas()}catch(a){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",a),a}this.buildCharCodeMap(),this.precomputeAtlasUVs(),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async setImageFont(e,t,s,i,n,a){this.fontLoaded=!0,this.charWidth=Math.round(t),this.charHeight=Math.round(s),this.cellWidth=Math.round(i),this.cellHeight=Math.round(n),this.atlasColumns=F(a);let l=L(a);this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers for ImageFont..."),this.initInstancedBuffers()),await this.loadImageFontAtlas(e),this.charCodeToAtlasIndex.fill(65535);for(let o=0;o<=l;o++)this.charCodeToAtlasIndex[o]=o;this.precomputeImageFontUVs(a),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async loadImageFontAtlas(e){return new Promise((t,s)=>{let i=new Uint8Array(e),n=new Blob([i],{type:"image/png"}),a=URL.createObjectURL(n),l=new Image;l.onload=()=>{URL.revokeObjectURL(a),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=l.width,this.atlasCanvas.height=l.height;let o=this.atlasCanvas.getContext("2d");if(!o){s(new Error("Failed to create 2D context for atlas"));return}o.drawImage(l,0,0),this.cachedAtlasWidth=l.width,this.cachedAtlasHeight=l.height,this.createAtlasTexture(),t()},l.onerror=()=>{URL.revokeObjectURL(a),s(new Error("Failed to load PNG image for ImageFont atlas"))},l.src=a})}precomputeImageFontUVs(e){let t=e*256;this.atlasUVs=new Float32Array(t*4);let s=this.cachedAtlasWidth,i=this.cachedAtlasHeight,n=.5/s,a=.5/i;for(let l=0;l<t;l++){let{col:o,row:c}=_(l,e),d=(o*this.charWidth+n)/s,h=(c*this.charHeight+a)/i,u=((o+1)*this.charWidth-n)/s,m=((c+1)*this.charHeight-a)/i,b=l*4;this.atlasUVs[b]=d,this.atlasUVs[b+1]=h,this.atlasUVs[b+2]=u,this.atlasUVs[b+3]=m}}generateAtlas(){if(!this.bitmapFont)return;let e=Array.from(this.bitmapFont.keys()).sort((o,c)=>o-c),t=e.length;this.atlasColumns=Math.ceil(Math.sqrt(t));let s=Math.ceil(t/this.atlasColumns),i=this.atlasColumns*this.charWidth,n=s*this.charHeight;this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=i,this.atlasCanvas.height=n;let a=this.atlasCanvas.getContext("2d");if(!a)throw new Error("Unable to create 2D context for atlas");a.clearRect(0,0,i,n),a.fillStyle="#ffffff";let l=0;for(let o of e){let c=this.bitmapFont.get(o);if(!c)continue;let d=l%this.atlasColumns,h=Math.floor(l/this.atlasColumns),u=d*this.charWidth,m=h*this.charHeight;for(let b=0;b<Math.min(c.length,this.charHeight);b++){let f=c[b];for(let p=0;p<this.charWidth;p++){let g=1<<7-p;f&g&&a.fillRect(u+p,m+b,1,1)}}l++}this.createAtlasTexture()}buildCharCodeMap(){if(!this.bitmapFont)return;this.charCodeToAtlasIndex.fill(65535);let e=Array.from(this.bitmapFont.keys()).sort((t,s)=>t-s);for(let t=0;t<e.length;t++)this.charCodeToAtlasIndex[e[t]]=t}precomputeAtlasUVs(){if(!this.bitmapFont)return;let e=this.bitmapFont.size;this.atlasUVs=new Float32Array(e*4),this.cachedAtlasWidth=this.atlasColumns*this.charWidth,this.cachedAtlasHeight=Math.ceil(e/this.atlasColumns)*this.charHeight;let t=this.cachedAtlasWidth,s=this.cachedAtlasHeight,i=.5/t,n=.5/s;for(let a=0;a<e;a++){let l=a%this.atlasColumns,o=Math.floor(a/this.atlasColumns),c=(l*this.charWidth+i)/t,d=(o*this.charHeight+n)/s,h=((l+1)*this.charWidth-i)/t,u=((o+1)*this.charHeight-n)/s,m=a*4;this.atlasUVs[m]=c,this.atlasUVs[m+1]=d,this.atlasUVs[m+2]=h,this.atlasUVs[m+3]=u}}createAtlasTexture(){if(this.atlasCanvas)try{let e=this.gl,t=e.createTexture();if(!t)throw new Error("Unable to create texture");e.bindTexture(e.TEXTURE_2D,t),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,this.atlasCanvas),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),this.atlasTexture=t}catch(e){throw console.error("[TerminalGL] \u274C Failed to create atlas texture:",e),e}}clear(){let e=this.gl;e&&e.clear(e.COLOR_BUFFER_BIT)}parseColor(e){if(e.startsWith("#")){let t=e.slice(1),s=0,i=0,n=0;return t.length===3?(s=parseInt(t[0]+t[0],16),i=parseInt(t[1]+t[1],16),n=parseInt(t[2]+t[2],16)):t.length===6&&(s=parseInt(t.slice(0,2),16),i=parseInt(t.slice(2,4),16),n=parseInt(t.slice(4,6),16)),[s/255,i/255,n/255,1]}if(e.startsWith("rgb")){let t=e.match(/rgba?\(([^)]+)\)/);if(t){let s=t[1].split(",").map(i=>parseFloat(i.trim()));return[s[0]/255,s[1]/255,s[2]/255,s[3]!==void 0?s[3]:1]}}return[1,1,1,1]}setupResizeObserver(){if(!(typeof ResizeObserver>"u"))try{this.resizeObserver=new ResizeObserver(()=>{try{this.updateCanvasSize()}catch(e){console.error("[TerminalGL] \u274C Error in resize callback:",e)}}),this.resizeObserver.observe(this.parentElement),this.updateCanvasSize()}catch(e){console.error("[TerminalGL] \u274C Failed to setup ResizeObserver:",e)}}updateCanvasSize(){let e=this.parentElement.clientWidth,t=this.parentElement.clientHeight;if(e===0||t===0)return;let s=this.cols*this.cellWidth,i=this.rows*this.cellHeight;if(s===0||i===0)return;let n=e/s,a=t/i,l=Math.min(n,a),o;switch(this.scalingMode){case C.Integer:o=Math.max(1,Math.floor(l));break;case C.Half:o=Math.max(1,Math.floor(l*2)/2);break;case C.Quarter:o=Math.max(1,Math.floor(l*4)/4);break;case C.Eighth:o=Math.max(1,Math.floor(l*8)/8);break;case C.Responsive:o=1;break;case C.None:default:o=Math.max(.1,l);break}if(this.canvas.style.transform=`scale(${o})`,this.ambientEffectEnabled&&this.ambientEffectCanvas){let c=o*this.ambientEffectScale;this.ambientEffectCanvas.style.transform=`scale(${c})`}this.currentScale=o,this.onResizeCallback&&this.onResizeCallback(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}updateAmbientEffect(){!this.ambientEffectCanvas||!this.ambientEffectCtx||this.ambientEffectCtx.drawImage(this.canvas,0,0)}setPalette(e){let t=0;for(let s=0;s<Math.min(e.length,256);s++){let i=e[s];t=(t<<5)-t+i.r,t=(t<<5)-t+i.g,t=(t<<5)-t+i.b,t=(t<<5)-t+i.a,t=t|0}if(t!==this.paletteHash){this.paletteHash=t;for(let s=0;s<e.length&&s<256;s++){let i=e[s],n=s*4;this.paletteFloat[n]=i.r/255,this.paletteFloat[n+1]=i.g/255,this.paletteFloat[n+2]=i.b/255,this.paletteFloat[n+3]=i.a/255}this.updatePaletteTexture()}}updatePaletteTexture(){try{let e=this.gl;this.paletteTexture||(this.paletteTexture=e.createTexture()),e.bindTexture(e.TEXTURE_2D,this.paletteTexture);let t=new Uint8Array(256*4);for(let s=0;s<256;s++){let i=s*4;t[i]=this.paletteFloat[i]*255,t[i+1]=this.paletteFloat[i+1]*255,t[i+2]=this.paletteFloat[i+2]*255,t[i+3]=this.paletteFloat[i+3]*255}e.texImage2D(e.TEXTURE_2D,0,e.RGBA,256,1,0,e.RGBA,e.UNSIGNED_BYTE,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.bindTexture(e.TEXTURE_2D,null)}catch(e){throw console.error("[TerminalGL] \u274C Failed to update palette texture:",e),e}}renderDisplayData(e){try{if(!this.isReady()){console.warn("[TerminalGL] \u26A0\uFE0F Not ready: font not loaded yet");return}(e.width!==this.cols||e.height!==this.rows)&&this.resize(e.width,e.height),this.renderDirect(e),this.ambientEffectEnabled&&this.ambientEffectCanvas&&this.ambientEffectCtx&&this.updateAmbientEffect()}catch(t){console.error("[TerminalGL] \u274C Error rendering display data:",t)}}renderDirect(e){let t=this.gl;if(!this.staticPositionsInitialized&&!this.useInstancing&&this.precomputeStaticPositions(),this.canvasBgColor!==null){let s=this.parseColor(this.canvasBgColor);t.clearColor(s[0],s[1],s[2],s[3])}else t.clearColor(0,0,0,0);t.clear(t.COLOR_BUFFER_BIT),this.useInstancing?this.renderInstanced(e):this.renderDirectBuffers(e)}renderInstanced(e){let t=this.gl,s=this.instancedExtension;if(!this.instanceData||this.instanceData.length===0){console.warn("[TerminalGL] \u26A0\uFE0F Instance data not initialized, falling back to standard rendering"),this.renderDirectBuffers(e);return}let i=0,n=this.instanceData.length/8,a=e.width*e.height*2;if(a>n){console.error(`[TerminalGL] \u274C Instance buffer too small! Need ${a}, have ${n}. Display size: ${e.width}\xD7${e.height}, buffer was sized for smaller terminal.`),this.renderDirectBuffers(e);return}for(let o=0;o<e.height;o++)for(let c=0;c<e.width;c++){let d=e.cells[o*e.width+c],h=d.bgColorIndex,u=d.fgColorIndex,m=this.canvasBgColor!==null&&h===255,b=d.char===" "||u===255;if(!m){if(i>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${i}, max=${n}`);break}let f=i*8;this.instanceData[f]=c,this.instanceData[f+1]=o,this.instanceData[f+2]=0,this.instanceData[f+3]=0,this.instanceData[f+4]=0,this.instanceData[f+5]=0,this.instanceData[f+6]=h,this.instanceData[f+7]=0,i++}if(!b){let f=d.char.charCodeAt(0),p=this.charCodeToAtlasIndex[f];if(p!==65535){if(i>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${i}, max=${n}`);break}let g=p*4,x=i*8;this.instanceData[x]=c,this.instanceData[x+1]=o,this.instanceData[x+2]=this.atlasUVs[g],this.instanceData[x+3]=this.atlasUVs[g+1],this.instanceData[x+4]=this.atlasUVs[g+2],this.instanceData[x+5]=this.atlasUVs[g+3],this.instanceData[x+6]=0,this.instanceData[x+7]=u,i++}}}if(i===0){console.warn("[TerminalGL] \u26A0\uFE0F No instances to draw (all cells skipped)");return}t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.instanceData.subarray(0,i*8)),t.useProgram(this.program),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),s.vertexAttribDivisorANGLE(this.aPosition,0),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer);let l=8*Float32Array.BYTES_PER_ELEMENT;t.enableVertexAttribArray(this.aInstanceOffset),t.vertexAttribPointer(this.aInstanceOffset,2,t.FLOAT,!1,l,0),s.vertexAttribDivisorANGLE(this.aInstanceOffset,1),t.enableVertexAttribArray(this.aInstanceUVs),t.vertexAttribPointer(this.aInstanceUVs,4,t.FLOAT,!1,l,2*Float32Array.BYTES_PER_ELEMENT),s.vertexAttribDivisorANGLE(this.aInstanceUVs,1),t.enableVertexAttribArray(this.aInstanceColors),t.vertexAttribPointer(this.aInstanceColors,2,t.FLOAT,!1,l,6*Float32Array.BYTES_PER_ELEMENT),s.vertexAttribDivisorANGLE(this.aInstanceColors,1),t.uniform2f(this.uResolution,this.canvas.width,this.canvas.height),t.uniform2f(this.uCellSize,this.cellWidth,this.cellHeight),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.atlasTexture),t.uniform1i(this.uTexture,0),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.paletteTexture),t.uniform1i(this.uPalette,1),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),s.drawElementsInstancedANGLE(t.TRIANGLES,6,t.UNSIGNED_SHORT,0,i),s.vertexAttribDivisorANGLE(this.aPosition,0),s.vertexAttribDivisorANGLE(this.aInstanceOffset,0),s.vertexAttribDivisorANGLE(this.aInstanceUVs,0),s.vertexAttribDivisorANGLE(this.aInstanceColors,0)}renderDirectBuffers(e){let t=this.gl,s=e.width*e.height,i=s*2;if(i>this.maxCells){console.error(`[TerminalGL] \u274C Buffer overflow detected! Trying to render ${i} quads but buffer capacity is ${this.maxCells}. This should not happen - resize() should have reallocated.`);return}let n=0,a=0,l=e.cells,o=s;for(let b=0;b<o;b++){let f=l[b],p=f.bgColorIndex,x=this.canvasBgColor!==null&&p===255?255:p,w=0;for(let T=0;T<4;T++)this.renderTexCoords[n++]=w,this.renderTexCoords[n++]=w,this.renderColorIndices[a++]=x;let A=f.fgColorIndex,S=f.char;if(S===" "||A===255)for(let T=0;T<4;T++)this.renderTexCoords[n++]=0,this.renderTexCoords[n++]=0,this.renderColorIndices[a++]=255;else{let T=S.charCodeAt(0),P=this.charCodeToAtlasIndex[T];if(P!==65535){let R=P*4,G=this.atlasUVs[R],W=this.atlasUVs[R+1],O=this.atlasUVs[R+2],H=this.atlasUVs[R+3];this.renderTexCoords[n++]=G,this.renderTexCoords[n++]=W,this.renderColorIndices[a++]=A,this.renderTexCoords[n++]=O,this.renderTexCoords[n++]=W,this.renderColorIndices[a++]=A,this.renderTexCoords[n++]=G,this.renderTexCoords[n++]=H,this.renderColorIndices[a++]=A,this.renderTexCoords[n++]=O,this.renderTexCoords[n++]=H,this.renderColorIndices[a++]=A}else for(let R=0;R<4;R++)this.renderTexCoords[n++]=0,this.renderTexCoords[n++]=0,this.renderColorIndices[a++]=255}}(n!==o*2*4*2||a!==o*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:n,colorIdx:a,expected:o*2*4}),t.useProgram(this.program),this.vao&&this.vaoExtension?(this.vaoExtension.bindVertexArrayOES(this.vao),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,n)),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,a))):(t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,n)),t.enableVertexAttribArray(this.aTexCoord),t.vertexAttribPointer(this.aTexCoord,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,a)),t.enableVertexAttribArray(this.aColorIndex),t.vertexAttribPointer(this.aColorIndex,1,t.FLOAT,!1,0,0));let c=this.canvas.width,d=this.canvas.height;(this.cachedResolution[0]!==c||this.cachedResolution[1]!==d)&&(t.uniform2f(this.uResolution,c,d),this.cachedResolution[0]=c,this.cachedResolution[1]=d),this.cachedTextureUnit!==0&&(t.activeTexture(t.TEXTURE0),this.cachedTextureUnit=0),t.bindTexture(t.TEXTURE_2D,this.atlasTexture),this.cachedTextureUniform||(t.uniform1i(this.uTexture,0),this.cachedTextureUniform=!0),this.cachedPaletteUnit!==1&&(t.activeTexture(t.TEXTURE1),this.cachedPaletteUnit=1),t.bindTexture(t.TEXTURE_2D,this.paletteTexture),this.cachedPaletteUniform||(t.uniform1i(this.uPalette,1),this.cachedPaletteUniform=!0),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer);let u=e.width*e.height*2*6,m=this.useUint16Indices?t.UNSIGNED_SHORT:t.UNSIGNED_INT;t.drawElements(t.TRIANGLES,u,m,0)}resize(e,t){if(!Number.isInteger(e)||e<=0){console.error(`[TerminalGL] \u274C Invalid cols: ${e}. Must be positive integer.`);return}if(!Number.isInteger(t)||t<=0){console.error(`[TerminalGL] \u274C Invalid rows: ${t}. Must be positive integer.`);return}if(e===this.cols&&t===this.rows)return;let s=e*t,i=this.useInstancing?262144:this.useUint16Indices?8191:262144;if(s>i){let d=Math.floor(Math.sqrt(i));console.error(`[TerminalGL] \u274C Cannot resize to ${e}\xD7${t} (${s} cells). Device limit: ${i} cells (max ~${d}\xD7${d}). ${!this.useInstancing&&this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let n=y.checkCompatibility();s>n.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${e}\xD7${t} (${s} cells) exceeds recommended limit (${n.recommendedMaxCells} cells). Performance may degrade.`),this.cols=e,this.rows=t,this.staticPositionsInitialized=!1;let a=this.cols*this.rows*2,l=Math.ceil(a*1.5),o=a>this.maxCells,c=this.maxCells>l*4;if(console.warn(`[TerminalGL] \u{1F4D0} resize check: cols=${e}, rows=${t}, newMaxCells=${a}, this.maxCells=${this.maxCells}, needGrow=${o}, needShrink=${c}`),o||c){let d=this.maxCells;if(this.maxCells=l,console.warn(`[TerminalGL] \u{1F4D0} resize realloc: ${d} \u2192 ${this.maxCells} (needGrow=${o}, needShrink=${c})`),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.useInstancing&&this.instanceDataBuffer){this.instanceData=new Float32Array(this.maxCells*8);let f=this.gl;f.bindBuffer(f.ARRAY_BUFFER,this.instanceDataBuffer),f.bufferData(f.ARRAY_BUFFER,this.instanceData.byteLength,f.DYNAMIC_DRAW)}let h=this.gl;this.useInstancing||(h.bindBuffer(h.ARRAY_BUFFER,this.positionBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderPositions.byteLength,h.DYNAMIC_DRAW)),h.bindBuffer(h.ARRAY_BUFFER,this.texCoordBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderTexCoords.byteLength,h.DYNAMIC_DRAW),h.bindBuffer(h.ARRAY_BUFFER,this.colorIndexBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderColorIndices.byteLength,h.DYNAMIC_DRAW),this.useInstancing||(h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.indexBuffer),h.bufferData(h.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,h.DYNAMIC_DRAW)),this.vaoExtension&&this.vao&&(this.vaoExtension.deleteVertexArrayOES(this.vao),this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),h.bindBuffer(h.ARRAY_BUFFER,this.positionBuffer),h.enableVertexAttribArray(this.aPosition),h.vertexAttribPointer(this.aPosition,2,h.FLOAT,!1,0,0),h.bindBuffer(h.ARRAY_BUFFER,this.texCoordBuffer),h.enableVertexAttribArray(this.aTexCoord),h.vertexAttribPointer(this.aTexCoord,2,h.FLOAT,!1,0,0),h.bindBuffer(h.ARRAY_BUFFER,this.colorIndexBuffer),h.enableVertexAttribArray(this.aColorIndex),h.vertexAttribPointer(this.aColorIndex,1,h.FLOAT,!1,0,0),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null)));let u=o?"\u{1F4C8} Growing":"\u{1F4C9} Shrinking",m=d*160/1048576,b=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${u} buffers: ${m.toFixed(2)}MB \u2192 ${b.toFixed(2)}MB (${d} \u2192 ${this.maxCells} quads)`)}this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.canvas.style.width=`${this.canvas.width}px`,this.canvas.style.height=`${this.canvas.height}px`,this.ambientEffectEnabled&&this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.width=`${this.canvas.width}px`,this.ambientEffectCanvas.style.height=`${this.canvas.height}px`),this.showGrid&&this.gridOverlay&&this.updateGridOverlay(),this.updateCanvasSize()}getCanvas(){return this.canvas}getGridSize(){return{cols:this.cols,rows:this.rows}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getBaseDimensions(){return{width:this.cols*this.cellWidth,height:this.rows*this.cellHeight}}setOnResizeCallback(e){this.onResizeCallback=e}clearOnResizeCallback(){this.onResizeCallback=void 0}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}setScalingMode(e){this.scalingMode!==e&&(this.scalingMode=e,this.updateCanvasSize())}getScalingMode(){return this.scalingMode}setCellSize(e,t){let s=Math.max(1,Math.min(255,Math.round(e))),i=Math.max(1,Math.min(255,Math.round(t)));this.cellWidth===s&&this.cellHeight===i||(this.cellWidth=s,this.cellHeight=i,this.charWidth=s,this.charHeight=i,this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.fontLoaded&&this.generateAtlas(),this.useInstancing&&this.initInstancedBuffers(),this.updateCanvasSize())}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getMaxCells(){return this.useInstancing?262144:this.useUint16Indices?8191:262144}setGrid(e){e.enabled?(this.gridOverlay?this.gridOverlay.setStyle({strokeColor:e.color,lineWidth:e.lineWidth}):this.gridOverlay=new I(this.containerDiv,{strokeColor:e.color??"rgba(144, 24, 24, 1)",lineWidth:e.lineWidth??1,zIndex:10}),this.showGrid=!0,this.gridOverlay.setVisible(!0),this.updateGridOverlay()):(this.showGrid=!1,this.gridOverlay&&this.gridOverlay.setVisible(!1))}isGridEnabled(){return this.showGrid}setAmbientEffect(e){typeof e=="boolean"?this.ambientEffectEnabled=e:(this.ambientEffectEnabled=!0,e.blur!==void 0&&(this.ambientEffectBlur=e.blur),e.scale!==void 0&&(this.ambientEffectScale=e.scale)),this.ambientEffectEnabled&&!this.ambientEffectCanvas&&this.createAmbientEffectCanvas(),this.ambientEffectCanvas&&(this.ambientEffectEnabled?(this.ambientEffectCanvas.style.display="block",this.ambientEffectCanvas.style.filter=`blur(${this.ambientEffectBlur}px)`,this.ambientEffectCanvas.style.transform=`scale(${this.ambientEffectScale})`,this.updateAmbientEffect()):this.ambientEffectCanvas.style.display="none")}createAmbientEffectCanvas(){this.ambientEffectCanvas||(this.ambientEffectCanvas=document.createElement("canvas"),this.ambientEffectCanvas.className="terminalgl-ambient-effect-canvas",this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.cssText=`
119
+ `,i=this.compileShader(e.VERTEX_SHADER,t),n=this.compileShader(e.FRAGMENT_SHADER,s);if(!i||!n)throw new Error("Shader compilation error");let a=e.createProgram();if(!a)throw new Error("Unable to create WebGL program");if(e.attachShader(a,i),e.attachShader(a,n),e.linkProgram(a),!e.getProgramParameter(a,e.LINK_STATUS)){let l=e.getProgramInfoLog(a);throw new Error("Program linking error: "+l)}this.program=a,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=e.getAttribLocation(a,"aPosition"),this.useInstancing?(this.aInstanceOffset=e.getAttribLocation(a,"aInstanceOffset"),this.aInstanceUVs=e.getAttribLocation(a,"aInstanceUVs"),this.aInstanceColors=e.getAttribLocation(a,"aInstanceColors"),this.uCellSize=e.getUniformLocation(a,"uCellSize"),this.instanceDataBuffer=e.createBuffer(),this.aTexCoord=this.aInstanceOffset,this.aColorIndex=this.aInstanceUVs):(this.aTexCoord=e.getAttribLocation(a,"aTexCoord"),this.aColorIndex=e.getAttribLocation(a,"aColorIndex")),this.uResolution=e.getUniformLocation(a,"uResolution"),this.uTexture=e.getUniformLocation(a,"uTexture"),this.uPalette=e.getUniformLocation(a,"uPalette"),this.positionBuffer=e.createBuffer(),this.texCoordBuffer=e.createBuffer(),this.colorIndexBuffer=e.createBuffer(),this.indexBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderPositions.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderTexCoords.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderColorIndices.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),e.bufferData(e.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,e.DYNAMIC_DRAW),this.vaoExtension&&(this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.enableVertexAttribArray(this.aTexCoord),e.vertexAttribPointer(this.aTexCoord,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.enableVertexAttribArray(this.aColorIndex),e.vertexAttribPointer(this.aColorIndex,1,e.FLOAT,!1,0,0),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null))),e.enable(e.BLEND),e.blendFunc(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA),e.viewport(0,0,this.canvas.width,this.canvas.height)}compileShader(e,t){let s=this.gl,i=s.createShader(e);return i?(s.shaderSource(i,t),s.compileShader(i),s.getShaderParameter(i,s.COMPILE_STATUS)?i:(console.error("Shader compilation error:",s.getShaderInfoLog(i)),s.deleteShader(i),null)):null}initGridOverlay(){this.gridOverlay=new I(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let e=this.cols*this.cellWidth,t=this.rows*this.cellHeight,s=this.canvas.getBoundingClientRect(),i=this.containerDiv.getBoundingClientRect();this.gridOverlay.setDimensions(this.cols,this.rows,this.cellWidth,this.cellHeight,0,0),this.gridOverlay.setTransform(this.currentScale,e,t,s,i),this.gridOverlay.render()}setBitmapFont(e,t,s,i,n){this.bitmapFont=e,this.fontLoaded=!0,this.charWidth=Math.round(t),this.charHeight=Math.round(s),this.cellWidth=Math.round(i),this.cellHeight=Math.round(n),this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers..."),this.initInstancedBuffers());try{this.generateAtlas()}catch(a){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",a),a}this.buildCharCodeMap(),this.precomputeAtlasUVs(),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async setImageFont(e,t,s,i,n,a){this.fontLoaded=!0,this.charWidth=Math.round(t),this.charHeight=Math.round(s),this.cellWidth=Math.round(i),this.cellHeight=Math.round(n),this.atlasColumns=F(a);let l=L(a);this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers for ImageFont..."),this.initInstancedBuffers()),await this.loadImageFontAtlas(e),this.charCodeToAtlasIndex.fill(65535);for(let o=0;o<=l;o++)this.charCodeToAtlasIndex[o]=o;this.precomputeImageFontUVs(a),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async loadImageFontAtlas(e){return new Promise((t,s)=>{let i=new Uint8Array(e),n=new Blob([i],{type:"image/png"}),a=URL.createObjectURL(n),l=new Image;l.onload=()=>{URL.revokeObjectURL(a),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=l.width,this.atlasCanvas.height=l.height;let o=this.atlasCanvas.getContext("2d");if(!o){s(new Error("Failed to create 2D context for atlas"));return}o.drawImage(l,0,0),this.cachedAtlasWidth=l.width,this.cachedAtlasHeight=l.height,this.createAtlasTexture(),t()},l.onerror=()=>{URL.revokeObjectURL(a),s(new Error("Failed to load PNG image for ImageFont atlas"))},l.src=a})}precomputeImageFontUVs(e){let t=e*256;this.atlasUVs=new Float32Array(t*4);let s=this.cachedAtlasWidth,i=this.cachedAtlasHeight,n=.5/s,a=.5/i;for(let l=0;l<t;l++){let{col:o,row:c}=_(l,e),d=(o*this.charWidth+n)/s,h=(c*this.charHeight+a)/i,u=((o+1)*this.charWidth-n)/s,m=((c+1)*this.charHeight-a)/i,b=l*4;this.atlasUVs[b]=d,this.atlasUVs[b+1]=h,this.atlasUVs[b+2]=u,this.atlasUVs[b+3]=m}}generateAtlas(){if(!this.bitmapFont)return;let e=Array.from(this.bitmapFont.keys()).sort((o,c)=>o-c),t=e.length;this.atlasColumns=Math.ceil(Math.sqrt(t));let s=Math.ceil(t/this.atlasColumns),i=this.atlasColumns*this.charWidth,n=s*this.charHeight;this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=i,this.atlasCanvas.height=n;let a=this.atlasCanvas.getContext("2d");if(!a)throw new Error("Unable to create 2D context for atlas");a.clearRect(0,0,i,n),a.fillStyle="#ffffff";let l=0;for(let o of e){let c=this.bitmapFont.get(o);if(!c)continue;let d=l%this.atlasColumns,h=Math.floor(l/this.atlasColumns),u=d*this.charWidth,m=h*this.charHeight;for(let b=0;b<Math.min(c.length,this.charHeight);b++){let f=c[b];for(let p=0;p<this.charWidth;p++){let g=1<<7-p;f&g&&a.fillRect(u+p,m+b,1,1)}}l++}this.createAtlasTexture()}buildCharCodeMap(){if(!this.bitmapFont)return;this.charCodeToAtlasIndex.fill(65535);let e=Array.from(this.bitmapFont.keys()).sort((t,s)=>t-s);for(let t=0;t<e.length;t++)this.charCodeToAtlasIndex[e[t]]=t}precomputeAtlasUVs(){if(!this.bitmapFont)return;let e=this.bitmapFont.size;this.atlasUVs=new Float32Array(e*4),this.cachedAtlasWidth=this.atlasColumns*this.charWidth,this.cachedAtlasHeight=Math.ceil(e/this.atlasColumns)*this.charHeight;let t=this.cachedAtlasWidth,s=this.cachedAtlasHeight,i=.5/t,n=.5/s;for(let a=0;a<e;a++){let l=a%this.atlasColumns,o=Math.floor(a/this.atlasColumns),c=(l*this.charWidth+i)/t,d=(o*this.charHeight+n)/s,h=((l+1)*this.charWidth-i)/t,u=((o+1)*this.charHeight-n)/s,m=a*4;this.atlasUVs[m]=c,this.atlasUVs[m+1]=d,this.atlasUVs[m+2]=h,this.atlasUVs[m+3]=u}}createAtlasTexture(){if(this.atlasCanvas)try{let e=this.gl,t=e.createTexture();if(!t)throw new Error("Unable to create texture");e.bindTexture(e.TEXTURE_2D,t),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,this.atlasCanvas),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),this.atlasTexture=t}catch(e){throw console.error("[TerminalGL] \u274C Failed to create atlas texture:",e),e}}clear(){let e=this.gl;e&&e.clear(e.COLOR_BUFFER_BIT)}parseColor(e){if(e.startsWith("#")){let t=e.slice(1),s=0,i=0,n=0;return t.length===3?(s=parseInt(t[0]+t[0],16),i=parseInt(t[1]+t[1],16),n=parseInt(t[2]+t[2],16)):t.length===6&&(s=parseInt(t.slice(0,2),16),i=parseInt(t.slice(2,4),16),n=parseInt(t.slice(4,6),16)),[s/255,i/255,n/255,1]}if(e.startsWith("rgb")){let t=e.match(/rgba?\(([^)]+)\)/);if(t){let s=t[1].split(",").map(i=>parseFloat(i.trim()));return[s[0]/255,s[1]/255,s[2]/255,s[3]!==void 0?s[3]:1]}}return[1,1,1,1]}setupResizeObserver(){if(!(typeof ResizeObserver>"u"))try{this.resizeObserver=new ResizeObserver(()=>{try{this.updateCanvasSize()}catch(e){console.error("[TerminalGL] \u274C Error in resize callback:",e)}}),this.resizeObserver.observe(this.parentElement),this.updateCanvasSize()}catch(e){console.error("[TerminalGL] \u274C Failed to setup ResizeObserver:",e)}}updateCanvasSize(){let e=this.parentElement.clientWidth,t=this.parentElement.clientHeight;if(e===0||t===0)return;let s=this.cols*this.cellWidth,i=this.rows*this.cellHeight;if(s===0||i===0)return;let n=e/s,a=t/i,l=Math.min(n,a),o;switch(this.scalingMode){case C.Integer:o=Math.max(1,Math.floor(l));break;case C.Half:o=Math.max(1,Math.floor(l*2)/2);break;case C.Quarter:o=Math.max(1,Math.floor(l*4)/4);break;case C.Eighth:o=Math.max(1,Math.floor(l*8)/8);break;case C.Responsive:o=1;break;case C.None:default:o=Math.max(.1,l);break}if(this.canvas.style.transform=`scale(${o})`,this.ambientEffectEnabled&&this.ambientEffectCanvas){let c=o*this.ambientEffectScale;this.ambientEffectCanvas.style.transform=`scale(${c})`}this.currentScale=o,this.onResizeCallback&&this.onResizeCallback(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}updateAmbientEffect(){!this.ambientEffectCanvas||!this.ambientEffectCtx||this.ambientEffectCtx.drawImage(this.canvas,0,0)}setPalette(e){let t=0;for(let s=0;s<Math.min(e.length,256);s++){let i=e[s];t=(t<<5)-t+i.r,t=(t<<5)-t+i.g,t=(t<<5)-t+i.b,t=(t<<5)-t+i.a,t=t|0}if(t!==this.paletteHash){this.paletteHash=t;for(let s=0;s<e.length&&s<256;s++){let i=e[s],n=s*4;this.paletteFloat[n]=i.r/255,this.paletteFloat[n+1]=i.g/255,this.paletteFloat[n+2]=i.b/255,this.paletteFloat[n+3]=i.a/255}this.updatePaletteTexture()}}updatePaletteTexture(){try{let e=this.gl;this.paletteTexture||(this.paletteTexture=e.createTexture()),e.bindTexture(e.TEXTURE_2D,this.paletteTexture);let t=new Uint8Array(256*4);for(let s=0;s<256;s++){let i=s*4;t[i]=this.paletteFloat[i]*255,t[i+1]=this.paletteFloat[i+1]*255,t[i+2]=this.paletteFloat[i+2]*255,t[i+3]=this.paletteFloat[i+3]*255}e.texImage2D(e.TEXTURE_2D,0,e.RGBA,256,1,0,e.RGBA,e.UNSIGNED_BYTE,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.bindTexture(e.TEXTURE_2D,null)}catch(e){throw console.error("[TerminalGL] \u274C Failed to update palette texture:",e),e}}renderDisplayData(e){try{if(!this.isReady()){console.warn("[TerminalGL] \u26A0\uFE0F Not ready: font not loaded yet");return}(e.width!==this.cols||e.height!==this.rows)&&this.resize(e.width,e.height),e.passes&&e.passes.length>0?this.renderMultiPass(e,e.passes):this.renderDirect(e),this.ambientEffectEnabled&&this.ambientEffectCanvas&&this.ambientEffectCtx&&this.updateAmbientEffect()}catch(t){console.error("[TerminalGL] \u274C Error rendering display data:",t)}}renderMultiPass(e,t){for(let s=0;s<t.length;s++){let i=t[s],n={id:e.id,width:e.width,height:e.height,palette:e.palette,cells:i.cells};this.renderDirect(n,s===0)}}renderDirect(e,t=!0){let s=this.gl;if(!this.staticPositionsInitialized&&!this.useInstancing&&this.precomputeStaticPositions(),t){if(this.canvasBgColor!==null){let i=this.parseColor(this.canvasBgColor);s.clearColor(i[0],i[1],i[2],i[3])}else s.clearColor(0,0,0,0);s.clear(s.COLOR_BUFFER_BIT)}this.useInstancing?this.renderInstanced(e):this.renderDirectBuffers(e)}renderInstanced(e){let t=this.gl,s=this.instancedExtension;if(!this.instanceData||this.instanceData.length===0){console.warn("[TerminalGL] \u26A0\uFE0F Instance data not initialized, falling back to standard rendering"),this.renderDirectBuffers(e);return}let i=0,n=this.instanceData.length/8,a=e.width*e.height*2;if(a>n){console.error(`[TerminalGL] \u274C Instance buffer too small! Need ${a}, have ${n}. Display size: ${e.width}\xD7${e.height}, buffer was sized for smaller terminal.`),this.renderDirectBuffers(e);return}for(let o=0;o<e.height;o++)for(let c=0;c<e.width;c++){let d=e.cells[o*e.width+c],h=d.bgColorIndex,u=d.fgColorIndex,m=this.canvasBgColor!==null&&h===255,b=d.char===" "||u===255;if(!m){if(i>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${i}, max=${n}`);break}let f=i*8;this.instanceData[f]=c,this.instanceData[f+1]=o,this.instanceData[f+2]=0,this.instanceData[f+3]=0,this.instanceData[f+4]=0,this.instanceData[f+5]=0,this.instanceData[f+6]=h,this.instanceData[f+7]=0,i++}if(!b){let f=d.char.charCodeAt(0),p=this.charCodeToAtlasIndex[f];if(p!==65535){if(i>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${i}, max=${n}`);break}let g=p*4,x=i*8;this.instanceData[x]=c,this.instanceData[x+1]=o,this.instanceData[x+2]=this.atlasUVs[g],this.instanceData[x+3]=this.atlasUVs[g+1],this.instanceData[x+4]=this.atlasUVs[g+2],this.instanceData[x+5]=this.atlasUVs[g+3],this.instanceData[x+6]=0,this.instanceData[x+7]=u,i++}}}if(i===0){console.warn("[TerminalGL] \u26A0\uFE0F No instances to draw (all cells skipped)");return}t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.instanceData.subarray(0,i*8)),t.useProgram(this.program),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),s.vertexAttribDivisorANGLE(this.aPosition,0),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer);let l=8*Float32Array.BYTES_PER_ELEMENT;t.enableVertexAttribArray(this.aInstanceOffset),t.vertexAttribPointer(this.aInstanceOffset,2,t.FLOAT,!1,l,0),s.vertexAttribDivisorANGLE(this.aInstanceOffset,1),t.enableVertexAttribArray(this.aInstanceUVs),t.vertexAttribPointer(this.aInstanceUVs,4,t.FLOAT,!1,l,2*Float32Array.BYTES_PER_ELEMENT),s.vertexAttribDivisorANGLE(this.aInstanceUVs,1),t.enableVertexAttribArray(this.aInstanceColors),t.vertexAttribPointer(this.aInstanceColors,2,t.FLOAT,!1,l,6*Float32Array.BYTES_PER_ELEMENT),s.vertexAttribDivisorANGLE(this.aInstanceColors,1),t.uniform2f(this.uResolution,this.canvas.width,this.canvas.height),t.uniform2f(this.uCellSize,this.cellWidth,this.cellHeight),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.atlasTexture),t.uniform1i(this.uTexture,0),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.paletteTexture),t.uniform1i(this.uPalette,1),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),s.drawElementsInstancedANGLE(t.TRIANGLES,6,t.UNSIGNED_SHORT,0,i),s.vertexAttribDivisorANGLE(this.aPosition,0),s.vertexAttribDivisorANGLE(this.aInstanceOffset,0),s.vertexAttribDivisorANGLE(this.aInstanceUVs,0),s.vertexAttribDivisorANGLE(this.aInstanceColors,0)}renderDirectBuffers(e){let t=this.gl,s=e.width*e.height,i=s*2;if(i>this.maxCells){console.error(`[TerminalGL] \u274C Buffer overflow detected! Trying to render ${i} quads but buffer capacity is ${this.maxCells}. This should not happen - resize() should have reallocated.`);return}let n=0,a=0,l=e.cells,o=s;for(let b=0;b<o;b++){let f=l[b],p=f.bgColorIndex,x=this.canvasBgColor!==null&&p===255?255:p,w=0;for(let T=0;T<4;T++)this.renderTexCoords[n++]=w,this.renderTexCoords[n++]=w,this.renderColorIndices[a++]=x;let A=f.fgColorIndex,S=f.char;if(S===" "||A===255)for(let T=0;T<4;T++)this.renderTexCoords[n++]=0,this.renderTexCoords[n++]=0,this.renderColorIndices[a++]=255;else{let T=S.charCodeAt(0),P=this.charCodeToAtlasIndex[T];if(P!==65535){let R=P*4,G=this.atlasUVs[R],W=this.atlasUVs[R+1],O=this.atlasUVs[R+2],H=this.atlasUVs[R+3];this.renderTexCoords[n++]=G,this.renderTexCoords[n++]=W,this.renderColorIndices[a++]=A,this.renderTexCoords[n++]=O,this.renderTexCoords[n++]=W,this.renderColorIndices[a++]=A,this.renderTexCoords[n++]=G,this.renderTexCoords[n++]=H,this.renderColorIndices[a++]=A,this.renderTexCoords[n++]=O,this.renderTexCoords[n++]=H,this.renderColorIndices[a++]=A}else for(let R=0;R<4;R++)this.renderTexCoords[n++]=0,this.renderTexCoords[n++]=0,this.renderColorIndices[a++]=255}}(n!==o*2*4*2||a!==o*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:n,colorIdx:a,expected:o*2*4}),t.useProgram(this.program),this.vao&&this.vaoExtension?(this.vaoExtension.bindVertexArrayOES(this.vao),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,n)),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,a))):(t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,n)),t.enableVertexAttribArray(this.aTexCoord),t.vertexAttribPointer(this.aTexCoord,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,a)),t.enableVertexAttribArray(this.aColorIndex),t.vertexAttribPointer(this.aColorIndex,1,t.FLOAT,!1,0,0));let c=this.canvas.width,d=this.canvas.height;(this.cachedResolution[0]!==c||this.cachedResolution[1]!==d)&&(t.uniform2f(this.uResolution,c,d),this.cachedResolution[0]=c,this.cachedResolution[1]=d),this.cachedTextureUnit!==0&&(t.activeTexture(t.TEXTURE0),this.cachedTextureUnit=0),t.bindTexture(t.TEXTURE_2D,this.atlasTexture),this.cachedTextureUniform||(t.uniform1i(this.uTexture,0),this.cachedTextureUniform=!0),this.cachedPaletteUnit!==1&&(t.activeTexture(t.TEXTURE1),this.cachedPaletteUnit=1),t.bindTexture(t.TEXTURE_2D,this.paletteTexture),this.cachedPaletteUniform||(t.uniform1i(this.uPalette,1),this.cachedPaletteUniform=!0),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer);let u=e.width*e.height*2*6,m=this.useUint16Indices?t.UNSIGNED_SHORT:t.UNSIGNED_INT;t.drawElements(t.TRIANGLES,u,m,0)}resize(e,t){if(!Number.isInteger(e)||e<=0){console.error(`[TerminalGL] \u274C Invalid cols: ${e}. Must be positive integer.`);return}if(!Number.isInteger(t)||t<=0){console.error(`[TerminalGL] \u274C Invalid rows: ${t}. Must be positive integer.`);return}if(e===this.cols&&t===this.rows)return;let s=e*t,i=this.useInstancing?262144:this.useUint16Indices?8191:262144;if(s>i){let d=Math.floor(Math.sqrt(i));console.error(`[TerminalGL] \u274C Cannot resize to ${e}\xD7${t} (${s} cells). Device limit: ${i} cells (max ~${d}\xD7${d}). ${!this.useInstancing&&this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let n=y.checkCompatibility();s>n.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${e}\xD7${t} (${s} cells) exceeds recommended limit (${n.recommendedMaxCells} cells). Performance may degrade.`),this.cols=e,this.rows=t,this.staticPositionsInitialized=!1;let a=this.cols*this.rows*2,l=Math.ceil(a*1.5),o=a>this.maxCells,c=this.maxCells>l*4;if(console.warn(`[TerminalGL] \u{1F4D0} resize check: cols=${e}, rows=${t}, newMaxCells=${a}, this.maxCells=${this.maxCells}, needGrow=${o}, needShrink=${c}`),o||c){let d=this.maxCells;if(this.maxCells=l,console.warn(`[TerminalGL] \u{1F4D0} resize realloc: ${d} \u2192 ${this.maxCells} (needGrow=${o}, needShrink=${c})`),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.useInstancing&&this.instanceDataBuffer){this.instanceData=new Float32Array(this.maxCells*8);let f=this.gl;f.bindBuffer(f.ARRAY_BUFFER,this.instanceDataBuffer),f.bufferData(f.ARRAY_BUFFER,this.instanceData.byteLength,f.DYNAMIC_DRAW)}let h=this.gl;this.useInstancing||(h.bindBuffer(h.ARRAY_BUFFER,this.positionBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderPositions.byteLength,h.DYNAMIC_DRAW)),h.bindBuffer(h.ARRAY_BUFFER,this.texCoordBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderTexCoords.byteLength,h.DYNAMIC_DRAW),h.bindBuffer(h.ARRAY_BUFFER,this.colorIndexBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderColorIndices.byteLength,h.DYNAMIC_DRAW),this.useInstancing||(h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.indexBuffer),h.bufferData(h.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,h.DYNAMIC_DRAW)),this.vaoExtension&&this.vao&&(this.vaoExtension.deleteVertexArrayOES(this.vao),this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),h.bindBuffer(h.ARRAY_BUFFER,this.positionBuffer),h.enableVertexAttribArray(this.aPosition),h.vertexAttribPointer(this.aPosition,2,h.FLOAT,!1,0,0),h.bindBuffer(h.ARRAY_BUFFER,this.texCoordBuffer),h.enableVertexAttribArray(this.aTexCoord),h.vertexAttribPointer(this.aTexCoord,2,h.FLOAT,!1,0,0),h.bindBuffer(h.ARRAY_BUFFER,this.colorIndexBuffer),h.enableVertexAttribArray(this.aColorIndex),h.vertexAttribPointer(this.aColorIndex,1,h.FLOAT,!1,0,0),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null)));let u=o?"\u{1F4C8} Growing":"\u{1F4C9} Shrinking",m=d*160/1048576,b=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${u} buffers: ${m.toFixed(2)}MB \u2192 ${b.toFixed(2)}MB (${d} \u2192 ${this.maxCells} quads)`)}this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.canvas.style.width=`${this.canvas.width}px`,this.canvas.style.height=`${this.canvas.height}px`,this.ambientEffectEnabled&&this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.width=`${this.canvas.width}px`,this.ambientEffectCanvas.style.height=`${this.canvas.height}px`),this.showGrid&&this.gridOverlay&&this.updateGridOverlay(),this.updateCanvasSize()}getCanvas(){return this.canvas}getGridSize(){return{cols:this.cols,rows:this.rows}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getBaseDimensions(){return{width:this.cols*this.cellWidth,height:this.rows*this.cellHeight}}setOnResizeCallback(e){this.onResizeCallback=e}clearOnResizeCallback(){this.onResizeCallback=void 0}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}setScalingMode(e){this.scalingMode!==e&&(this.scalingMode=e,this.updateCanvasSize())}getScalingMode(){return this.scalingMode}setCellSize(e,t){let s=Math.max(1,Math.min(255,Math.round(e))),i=Math.max(1,Math.min(255,Math.round(t)));this.cellWidth===s&&this.cellHeight===i||(this.cellWidth=s,this.cellHeight=i,this.charWidth=s,this.charHeight=i,this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.fontLoaded&&this.generateAtlas(),this.useInstancing&&this.initInstancedBuffers(),this.updateCanvasSize())}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getMaxCells(){return this.useInstancing?262144:this.useUint16Indices?8191:262144}setGrid(e){e.enabled?(this.gridOverlay?this.gridOverlay.setStyle({strokeColor:e.color,lineWidth:e.lineWidth}):this.gridOverlay=new I(this.containerDiv,{strokeColor:e.color??"rgba(144, 24, 24, 1)",lineWidth:e.lineWidth??1,zIndex:10}),this.showGrid=!0,this.gridOverlay.setVisible(!0),this.updateGridOverlay()):(this.showGrid=!1,this.gridOverlay&&this.gridOverlay.setVisible(!1))}isGridEnabled(){return this.showGrid}setAmbientEffect(e){typeof e=="boolean"?this.ambientEffectEnabled=e:(this.ambientEffectEnabled=!0,e.blur!==void 0&&(this.ambientEffectBlur=e.blur),e.scale!==void 0&&(this.ambientEffectScale=e.scale)),this.ambientEffectEnabled&&!this.ambientEffectCanvas&&this.createAmbientEffectCanvas(),this.ambientEffectCanvas&&(this.ambientEffectEnabled?(this.ambientEffectCanvas.style.display="block",this.ambientEffectCanvas.style.filter=`blur(${this.ambientEffectBlur}px)`,this.ambientEffectCanvas.style.transform=`scale(${this.ambientEffectScale})`,this.updateAmbientEffect()):this.ambientEffectCanvas.style.display="none")}createAmbientEffectCanvas(){this.ambientEffectCanvas||(this.ambientEffectCanvas=document.createElement("canvas"),this.ambientEffectCanvas.className="terminalgl-ambient-effect-canvas",this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.cssText=`
120
120
  display: block !important;
121
121
  position: absolute !important;
122
122
  width: ${this.canvas.width}px !important;
package/dist/index.cjs CHANGED
@@ -1,11 +1,11 @@
1
- "use strict";var U=Object.defineProperty;var ht=Object.getOwnPropertyDescriptor;var ct=Object.getOwnPropertyNames;var dt=Object.prototype.hasOwnProperty;var ft=(b,t,e)=>t in b?U(b,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):b[t]=e;var v=(b,t)=>U(b,"name",{value:t,configurable:!0});var ut=(b,t)=>{for(var e in t)U(b,e,{get:t[e],enumerable:!0})},mt=(b,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of ct(t))!dt.call(b,s)&&s!==e&&U(b,s,{get:()=>t[s],enumerable:!(i=ht(t,s))||i.enumerable});return b};var gt=b=>mt(U({},"__esModule",{value:!0}),b);var l=(b,t,e)=>(ft(b,typeof t!="symbol"?t+"":t,e),e);var xt={};ut(xt,{AutoplayOverlay:()=>O,BitmapFontAtlas:()=>D,DEFAULT_PALETTE:()=>G,GridOverlay:()=>A,ImageFontAtlas:()=>F,PostProcessOverlay:()=>z,ScalingMode:()=>y.ScalingMode,Terminal2D:()=>P,TerminalANSI:()=>k,TerminalGL:()=>_,colorToPaletteIndex:()=>st,createTestRenderState:()=>lt,getAtlasColumns:()=>M,getCharGridPosition:()=>B,getMaxCharCode:()=>S,hexToRGB:()=>nt,paletteIndexToColor:()=>it,rgbToHex:()=>ot,version:()=>Ct});module.exports=gt(xt);var G=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff","#080808","#121212","#1c1c1c","#262626","#303030","#3a3a3a","#444444","#4e4e4e","#585858","#626262","#6c6c6c","#767676","#808080","#8a8a8a","#949494","#9e9e9e","#a80000","#00a800","#a8a800","#0000a8","#a800a8","#00a8a8","#a8a8a8","#545454","#fc5454","#54fc54","#fcfc54","#5454fc","#fc54fc","#54fcfc","#fcfcfc","#000000",...Array(192).fill("#808080")];function it(b,t=G){return b<0||b>=t.length?"#ff00ff":t[b]}v(it,"paletteIndexToColor");function st(b,t=G){let e=t.indexOf(b.toLowerCase());return e>=0?e:0}v(st,"colorToPaletteIndex");var $=class ${constructor(t,e){l(this,"canvas");l(this,"ctx");l(this,"container");l(this,"cols",0);l(this,"rows",0);l(this,"cellWidth",0);l(this,"cellHeight",0);l(this,"offsetX",0);l(this,"offsetY",0);l(this,"strokeColor","rgba(80, 80, 80, 0.4)");l(this,"lineWidth",1);this.container=t,this.canvas=document.createElement("canvas"),this.canvas.className="grid-overlay-canvas";let i=e?.zIndex??10;this.canvas.style.cssText=`
1
+ "use strict";var U=Object.defineProperty;var ht=Object.getOwnPropertyDescriptor;var ct=Object.getOwnPropertyNames;var dt=Object.prototype.hasOwnProperty;var ft=(b,t,e)=>t in b?U(b,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):b[t]=e;var v=(b,t)=>U(b,"name",{value:t,configurable:!0});var ut=(b,t)=>{for(var e in t)U(b,e,{get:t[e],enumerable:!0})},mt=(b,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of ct(t))!dt.call(b,s)&&s!==e&&U(b,s,{get:()=>t[s],enumerable:!(i=ht(t,s))||i.enumerable});return b};var gt=b=>mt(U({},"__esModule",{value:!0}),b);var l=(b,t,e)=>(ft(b,typeof t!="symbol"?t+"":t,e),e);var xt={};ut(xt,{AutoplayOverlay:()=>O,BitmapFontAtlas:()=>D,DEFAULT_PALETTE:()=>G,GridOverlay:()=>A,ImageFontAtlas:()=>F,PostProcessOverlay:()=>z,ScalingMode:()=>y.ScalingMode,Terminal2D:()=>_,TerminalANSI:()=>k,TerminalGL:()=>P,colorToPaletteIndex:()=>st,createTestRenderState:()=>lt,getAtlasColumns:()=>M,getCharGridPosition:()=>B,getMaxCharCode:()=>S,hexToRGB:()=>at,paletteIndexToColor:()=>it,rgbToHex:()=>ot,version:()=>Ct});module.exports=gt(xt);var G=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff","#080808","#121212","#1c1c1c","#262626","#303030","#3a3a3a","#444444","#4e4e4e","#585858","#626262","#6c6c6c","#767676","#808080","#8a8a8a","#949494","#9e9e9e","#a80000","#00a800","#a8a800","#0000a8","#a800a8","#00a8a8","#a8a8a8","#545454","#fc5454","#54fc54","#fcfc54","#5454fc","#fc54fc","#54fcfc","#fcfcfc","#000000",...Array(192).fill("#808080")];function it(b,t=G){return b<0||b>=t.length?"#ff00ff":t[b]}v(it,"paletteIndexToColor");function st(b,t=G){let e=t.indexOf(b.toLowerCase());return e>=0?e:0}v(st,"colorToPaletteIndex");var $=class ${constructor(t,e){l(this,"canvas");l(this,"ctx");l(this,"container");l(this,"cols",0);l(this,"rows",0);l(this,"cellWidth",0);l(this,"cellHeight",0);l(this,"offsetX",0);l(this,"offsetY",0);l(this,"strokeColor","rgba(80, 80, 80, 0.4)");l(this,"lineWidth",1);this.container=t,this.canvas=document.createElement("canvas"),this.canvas.className="grid-overlay-canvas";let i=e?.zIndex??10;this.canvas.style.cssText=`
2
2
  display: block !important;
3
3
  position: absolute !important;
4
4
  pointer-events: none !important;
5
5
  image-rendering: pixelated !important;
6
6
  image-rendering: crisp-edges !important;
7
7
  z-index: ${i} !important;
8
- `,this.container.appendChild(this.canvas);let s=this.canvas.getContext("2d");if(!s)throw new Error("[GridOverlay] Impossible de cr\xE9er le contexte 2D");this.ctx=s,e&&(e.strokeColor&&(this.strokeColor=e.strokeColor),e.lineWidth!==void 0&&(this.lineWidth=e.lineWidth))}setDimensions(t,e,i,s,a=0,r=0){this.cols=t,this.rows=e,this.cellWidth=i,this.cellHeight=s,this.offsetX=a,this.offsetY=r}setCanvasSize(t,e){this.canvas.width=t,this.canvas.height=e,this.ctx.setTransform(1,0,0,1,0,0)}setStyle(t){t.strokeColor&&(this.strokeColor=t.strokeColor),t.lineWidth!==void 0&&(this.lineWidth=t.lineWidth)}setTransform(t,e,i,s,a){let r=s.left-a.left,o=s.top-a.top,n=s.width,h=s.height;(this.canvas.width!==n||this.canvas.height!==h)&&(this.canvas.width=n,this.canvas.height=h);let c=this.canvas.style;c.width=`${n}px`,c.height=`${h}px`,c.left=`${r}px`,c.top=`${o}px`}render(){if(!this.ctx)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,i=t>0?this.canvas.width/t:1,s=e>0?this.canvas.height/e:1,a=Math.min(i,s),r=this.cellWidth*a,o=this.cellHeight*a,n=this.cols*r,h=this.rows*o,c=this.offsetX*a,d=this.offsetY*a;if(!(n===0||h===0)){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.strokeStyle=this.strokeColor,this.ctx.lineWidth=Math.max(1,this.lineWidth*a),this.ctx.beginPath();for(let f=0;f<=this.cols;f++){let m=c+f*r+.5;this.ctx.moveTo(m,d),this.ctx.lineTo(m,d+h)}for(let f=0;f<=this.rows;f++){let m=d+f*o+.5;this.ctx.moveTo(c,m),this.ctx.lineTo(c+n,m)}this.ctx.stroke()}}update(t,e,i,s,a,r,o=0,n=0){this.setDimensions(t,e,i,s,o,n),this.setCanvasSize(a,r),this.render()}setVisible(t){this.canvas.style.display=t?"block":"none"}destroy(){this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}getCanvas(){return this.canvas}};v($,"GridOverlay");var A=$;function M(b){return Math.sqrt(b)*16}v(M,"getAtlasColumns");function S(b){return b*256-1}v(S,"getMaxCharCode");function B(b,t){let e=Math.floor(b/256),i=b%256,s=Math.sqrt(t),a=e%s,r=Math.floor(e/s),o=i%16,n=Math.floor(i/16);return{col:a*16+o,row:r*16+n}}v(B,"getCharGridPosition");var y=require("@utsp/types");var L=class L{constructor(t,e){l(this,"canvas");l(this,"gl");l(this,"parentElement");l(this,"containerDiv");l(this,"cols");l(this,"rows");l(this,"charWidth");l(this,"charHeight");l(this,"cellWidth",8);l(this,"cellHeight",8);l(this,"glyphOffsetX",0);l(this,"glyphOffsetY",0);l(this,"canvasBgColor");l(this,"showGrid");l(this,"supportsUint32Indices",!1);l(this,"useUint16Indices",!1);l(this,"gridOverlay");l(this,"bitmapFont");l(this,"atlasTexture",null);l(this,"atlasCanvas");l(this,"atlasColumns",0);l(this,"fontLoaded",!1);l(this,"paletteTexture",null);l(this,"program",null);l(this,"positionBuffer",null);l(this,"texCoordBuffer",null);l(this,"colorIndexBuffer",null);l(this,"indexBuffer",null);l(this,"aPosition");l(this,"aTexCoord");l(this,"aColorIndex");l(this,"uResolution",null);l(this,"uTexture",null);l(this,"uPalette",null);l(this,"resizeObserver");l(this,"charCodeToAtlasIndex",new Uint16Array(65536).fill(65535));l(this,"atlasUVs",new Float32Array(0));l(this,"cachedAtlasWidth",0);l(this,"cachedAtlasHeight",0);l(this,"paletteFloat",new Float32Array(256*4));l(this,"maxCells",0);l(this,"renderPositions",new Float32Array(0));l(this,"renderTexCoords",new Float32Array(0));l(this,"renderColorIndices",new Float32Array(0));l(this,"renderIndices",new Uint32Array(0));l(this,"cachedResolution",[0,0]);l(this,"cachedTextureUnit",-1);l(this,"cachedPaletteUnit",-1);l(this,"cachedTextureUniform",!1);l(this,"cachedPaletteUniform",!1);l(this,"paletteHash",0);l(this,"currentScale",1);l(this,"scalingMode",y.ScalingMode.None);l(this,"ambientEffectEnabled",!1);l(this,"ambientEffectCanvas",null);l(this,"ambientEffectCtx",null);l(this,"ambientEffectBlur",y.POST_PROCESS_DEFAULTS.ambientEffect.blur);l(this,"ambientEffectScale",y.POST_PROCESS_DEFAULTS.ambientEffect.scale);l(this,"ambientEffectOpacity",.7);l(this,"onResizeCallback");l(this,"staticPositionsInitialized",!1);l(this,"vaoExtension",null);l(this,"vao",null);l(this,"instancedExtension",null);l(this,"useInstancing",!1);l(this,"instanceDataBuffer",null);l(this,"instanceData",new Float32Array(0));l(this,"templateQuadPositions",new Float32Array(0));l(this,"templateQuadIndices",new Uint16Array(0));l(this,"aInstanceOffset",-1);l(this,"aInstanceUVs",-1);l(this,"aInstanceColors",-1);l(this,"uCellSize",null);if(!t)throw new Error("TerminalGL: Parent element is required");if(!Number.isInteger(e.cols)||e.cols<=0)throw new Error(`TerminalGL: Invalid cols: ${e.cols}. Must be a positive integer.`);if(!Number.isInteger(e.rows)||e.rows<=0)throw new Error(`TerminalGL: Invalid rows: ${e.rows}. Must be a positive integer.`);let i=e.cols*e.rows,s=L.checkCompatibility();if(s.errors.length>0)throw new Error(`TerminalGL: WebGL incompatible - ${s.errors.join(", ")}`);let a=e.forceUint16??!1;if(a&&i>s.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds Uint16 limit of ${s.maxCellsUint16} cells. Maximum size with Uint16: ${Math.floor(Math.sqrt(s.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(s.maxCellsUint16))} (or smaller rectangles like 127\xD764)`);if(!s.uint32Indices&&i>s.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds device limit of ${s.maxCellsUint16} cells (OES_element_index_uint not supported). Maximum size: ${Math.floor(Math.sqrt(s.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(s.maxCellsUint16))}`);i>s.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Large terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds recommended limit of ${s.recommendedMaxCells} cells. Performance may be impacted.`),s.warnings.length>0&&console.warn("[TerminalGL] WebGL Compatibility Warnings:",s.warnings);let r=e.charWidth??8,o=e.charHeight??8;if(!Number.isFinite(r)||r<=0)throw new Error(`TerminalGL: Invalid charWidth: ${r}. Must be a positive number.`);if(!Number.isFinite(o)||o<=0)throw new Error(`TerminalGL: Invalid charHeight: ${o}. Must be a positive number.`);for(this.parentElement=t,this.cols=e.cols,this.rows=e.rows,this.charWidth=r,this.charHeight=o,this.canvasBgColor=e.canvasBgColor!==void 0?e.canvasBgColor:null,this.showGrid=e.showGrid??!1,this.scalingMode=e.scalingMode??y.ScalingMode.None,e.ambientEffect&&(this.ambientEffectEnabled=!0,typeof e.ambientEffect=="object"&&(this.ambientEffectBlur=e.ambientEffect.blur??y.POST_PROCESS_DEFAULTS.ambientEffect.blur,this.ambientEffectScale=e.ambientEffect.scale??y.POST_PROCESS_DEFAULTS.ambientEffect.scale,this.ambientEffectOpacity=e.ambientEffect.opacity??.7));this.parentElement.firstChild;)this.parentElement.removeChild(this.parentElement.firstChild);let n=window.getComputedStyle(this.parentElement).position;n!=="relative"&&n!=="absolute"&&n!=="fixed"&&(this.parentElement.style.position="relative"),this.containerDiv=document.createElement("div"),this.containerDiv.className="terminalgl-container",this.containerDiv.style.cssText=`
8
+ `,this.container.appendChild(this.canvas);let s=this.canvas.getContext("2d");if(!s)throw new Error("[GridOverlay] Impossible de cr\xE9er le contexte 2D");this.ctx=s,e&&(e.strokeColor&&(this.strokeColor=e.strokeColor),e.lineWidth!==void 0&&(this.lineWidth=e.lineWidth))}setDimensions(t,e,i,s,n=0,r=0){this.cols=t,this.rows=e,this.cellWidth=i,this.cellHeight=s,this.offsetX=n,this.offsetY=r}setCanvasSize(t,e){this.canvas.width=t,this.canvas.height=e,this.ctx.setTransform(1,0,0,1,0,0)}setStyle(t){t.strokeColor&&(this.strokeColor=t.strokeColor),t.lineWidth!==void 0&&(this.lineWidth=t.lineWidth)}setTransform(t,e,i,s,n){let r=s.left-n.left,o=s.top-n.top,a=s.width,h=s.height;(this.canvas.width!==a||this.canvas.height!==h)&&(this.canvas.width=a,this.canvas.height=h);let c=this.canvas.style;c.width=`${a}px`,c.height=`${h}px`,c.left=`${r}px`,c.top=`${o}px`}render(){if(!this.ctx)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,i=t>0?this.canvas.width/t:1,s=e>0?this.canvas.height/e:1,n=Math.min(i,s),r=this.cellWidth*n,o=this.cellHeight*n,a=this.cols*r,h=this.rows*o,c=this.offsetX*n,d=this.offsetY*n;if(!(a===0||h===0)){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.strokeStyle=this.strokeColor,this.ctx.lineWidth=Math.max(1,this.lineWidth*n),this.ctx.beginPath();for(let f=0;f<=this.cols;f++){let m=c+f*r+.5;this.ctx.moveTo(m,d),this.ctx.lineTo(m,d+h)}for(let f=0;f<=this.rows;f++){let m=d+f*o+.5;this.ctx.moveTo(c,m),this.ctx.lineTo(c+a,m)}this.ctx.stroke()}}update(t,e,i,s,n,r,o=0,a=0){this.setDimensions(t,e,i,s,o,a),this.setCanvasSize(n,r),this.render()}setVisible(t){this.canvas.style.display=t?"block":"none"}destroy(){this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}getCanvas(){return this.canvas}};v($,"GridOverlay");var A=$;function M(b){return Math.sqrt(b)*16}v(M,"getAtlasColumns");function S(b){return b*256-1}v(S,"getMaxCharCode");function B(b,t){let e=Math.floor(b/256),i=b%256,s=Math.sqrt(t),n=e%s,r=Math.floor(e/s),o=i%16,a=Math.floor(i/16);return{col:n*16+o,row:r*16+a}}v(B,"getCharGridPosition");var y=require("@utsp/types");var L=class L{constructor(t,e){l(this,"canvas");l(this,"gl");l(this,"parentElement");l(this,"containerDiv");l(this,"cols");l(this,"rows");l(this,"charWidth");l(this,"charHeight");l(this,"cellWidth",8);l(this,"cellHeight",8);l(this,"glyphOffsetX",0);l(this,"glyphOffsetY",0);l(this,"canvasBgColor");l(this,"showGrid");l(this,"supportsUint32Indices",!1);l(this,"useUint16Indices",!1);l(this,"gridOverlay");l(this,"bitmapFont");l(this,"atlasTexture",null);l(this,"atlasCanvas");l(this,"atlasColumns",0);l(this,"fontLoaded",!1);l(this,"paletteTexture",null);l(this,"program",null);l(this,"positionBuffer",null);l(this,"texCoordBuffer",null);l(this,"colorIndexBuffer",null);l(this,"indexBuffer",null);l(this,"aPosition");l(this,"aTexCoord");l(this,"aColorIndex");l(this,"uResolution",null);l(this,"uTexture",null);l(this,"uPalette",null);l(this,"resizeObserver");l(this,"charCodeToAtlasIndex",new Uint16Array(65536).fill(65535));l(this,"atlasUVs",new Float32Array(0));l(this,"cachedAtlasWidth",0);l(this,"cachedAtlasHeight",0);l(this,"paletteFloat",new Float32Array(256*4));l(this,"maxCells",0);l(this,"renderPositions",new Float32Array(0));l(this,"renderTexCoords",new Float32Array(0));l(this,"renderColorIndices",new Float32Array(0));l(this,"renderIndices",new Uint32Array(0));l(this,"cachedResolution",[0,0]);l(this,"cachedTextureUnit",-1);l(this,"cachedPaletteUnit",-1);l(this,"cachedTextureUniform",!1);l(this,"cachedPaletteUniform",!1);l(this,"paletteHash",0);l(this,"currentScale",1);l(this,"scalingMode",y.ScalingMode.None);l(this,"ambientEffectEnabled",!1);l(this,"ambientEffectCanvas",null);l(this,"ambientEffectCtx",null);l(this,"ambientEffectBlur",y.POST_PROCESS_DEFAULTS.ambientEffect.blur);l(this,"ambientEffectScale",y.POST_PROCESS_DEFAULTS.ambientEffect.scale);l(this,"ambientEffectOpacity",.7);l(this,"onResizeCallback");l(this,"staticPositionsInitialized",!1);l(this,"vaoExtension",null);l(this,"vao",null);l(this,"instancedExtension",null);l(this,"useInstancing",!1);l(this,"instanceDataBuffer",null);l(this,"instanceData",new Float32Array(0));l(this,"templateQuadPositions",new Float32Array(0));l(this,"templateQuadIndices",new Uint16Array(0));l(this,"aInstanceOffset",-1);l(this,"aInstanceUVs",-1);l(this,"aInstanceColors",-1);l(this,"uCellSize",null);if(!t)throw new Error("TerminalGL: Parent element is required");if(!Number.isInteger(e.cols)||e.cols<=0)throw new Error(`TerminalGL: Invalid cols: ${e.cols}. Must be a positive integer.`);if(!Number.isInteger(e.rows)||e.rows<=0)throw new Error(`TerminalGL: Invalid rows: ${e.rows}. Must be a positive integer.`);let i=e.cols*e.rows,s=L.checkCompatibility();if(s.errors.length>0)throw new Error(`TerminalGL: WebGL incompatible - ${s.errors.join(", ")}`);let n=e.forceUint16??!1;if(n&&i>s.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds Uint16 limit of ${s.maxCellsUint16} cells. Maximum size with Uint16: ${Math.floor(Math.sqrt(s.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(s.maxCellsUint16))} (or smaller rectangles like 127\xD764)`);if(!s.uint32Indices&&i>s.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds device limit of ${s.maxCellsUint16} cells (OES_element_index_uint not supported). Maximum size: ${Math.floor(Math.sqrt(s.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(s.maxCellsUint16))}`);i>s.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Large terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds recommended limit of ${s.recommendedMaxCells} cells. Performance may be impacted.`),s.warnings.length>0&&console.warn("[TerminalGL] WebGL Compatibility Warnings:",s.warnings);let r=e.charWidth??8,o=e.charHeight??8;if(!Number.isFinite(r)||r<=0)throw new Error(`TerminalGL: Invalid charWidth: ${r}. Must be a positive number.`);if(!Number.isFinite(o)||o<=0)throw new Error(`TerminalGL: Invalid charHeight: ${o}. Must be a positive number.`);for(this.parentElement=t,this.cols=e.cols,this.rows=e.rows,this.charWidth=r,this.charHeight=o,this.canvasBgColor=e.canvasBgColor!==void 0?e.canvasBgColor:null,this.showGrid=e.showGrid??!1,this.scalingMode=e.scalingMode??y.ScalingMode.None,e.ambientEffect&&(this.ambientEffectEnabled=!0,typeof e.ambientEffect=="object"&&(this.ambientEffectBlur=e.ambientEffect.blur??y.POST_PROCESS_DEFAULTS.ambientEffect.blur,this.ambientEffectScale=e.ambientEffect.scale??y.POST_PROCESS_DEFAULTS.ambientEffect.scale,this.ambientEffectOpacity=e.ambientEffect.opacity??.7));this.parentElement.firstChild;)this.parentElement.removeChild(this.parentElement.firstChild);let a=window.getComputedStyle(this.parentElement).position;a!=="relative"&&a!=="absolute"&&a!=="fixed"&&(this.parentElement.style.position="relative"),this.containerDiv=document.createElement("div"),this.containerDiv.className="terminalgl-container",this.containerDiv.style.cssText=`
9
9
  position: absolute !important;
10
10
  top: 0 !important;
11
11
  left: 0 !important;
@@ -35,7 +35,7 @@
35
35
  z-index: 1 !important;
36
36
  pointer-events: auto !important;
37
37
  touch-action: none !important;
38
- `;let h=this.canvas.getContext("webgl",{alpha:this.canvasBgColor===null,premultipliedAlpha:!1});if(!h)throw new Error("TerminalGL: WebGL not supported");this.gl=h,this.supportsUint32Indices=!!h.getExtension("OES_element_index_uint"),this.useUint16Indices=a||!this.supportsUint32Indices,this.useUint16Indices?console.warn(`[TerminalGL] \u{1F4CA} Using Uint16 indices (max ${s.maxCellsUint16} cells)`):console.warn(`[TerminalGL] \u{1F4CA} Using Uint32 indices (max ${s.maxCellsUint32} cells)`),this.vaoExtension=h.getExtension("OES_vertex_array_object"),this.vaoExtension&&console.warn("[TerminalGL] \u2705 VAO extension enabled (faster attribute binding)"),this.instancedExtension=h.getExtension("ANGLE_instanced_arrays"),this.instancedExtension?(this.useInstancing=!0,console.warn("[TerminalGL] \u{1F680} Instanced rendering enabled (massive draw call reduction)")):console.warn("[TerminalGL] \u26A0\uFE0F Instanced rendering not available (fallback to standard rendering)"),this.containerDiv.appendChild(this.canvas),this.ambientEffectEnabled&&(this.createAmbientEffectCanvas(),console.warn("[TerminalGL] \u{1F308} Ambient effect enabled at startup")),this.parentElement.appendChild(this.containerDiv),this.initRenderBuffers();try{this.initWebGL()}catch(c){throw console.error("[TerminalGL] \u274C Failed to initialize WebGL:",c),c}this.showGrid&&this.initGridOverlay(),this.setupResizeObserver()}static checkCompatibility(){let t={webgl1:!1,uint32Indices:!1,maxTextureSize:0,maxViewportDims:[0,0],maxCellsUint16:0,maxCellsUint32:0,recommendedMaxCells:0,warnings:[],errors:[]},e=document.createElement("canvas"),i=e.getContext("webgl")||e.getContext("experimental-webgl");if(!i||!(i instanceof WebGLRenderingContext))return t.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),t;let s=i;t.webgl1=!0;try{t.maxTextureSize=s.getParameter(s.MAX_TEXTURE_SIZE);let n=s.getParameter(s.MAX_VIEWPORT_DIMS);t.maxViewportDims=[n[0],n[1]]}catch(n){return t.errors.push(`\u274C Failed to query WebGL parameters: ${n}`),t}let a=s.getExtension("OES_element_index_uint");t.uint32Indices=!!a;let r=8;if(t.maxCellsUint16=Math.floor(65535/r),t.uint32Indices){let n=Math.floor(t.maxTextureSize*t.maxTextureSize/64);t.maxCellsUint32=Math.min(n,262144)}else t.maxCellsUint32=t.maxCellsUint16,t.warnings.push(`\u26A0\uFE0F OES_element_index_uint not supported - limited to ${t.maxCellsUint16} cells (e.g., 90\xD790 or 127\xD764)`);return t.recommendedMaxCells=Math.floor((t.uint32Indices?t.maxCellsUint32:t.maxCellsUint16)*.8),t.maxTextureSize<256?t.errors.push(`\u274C MAX_TEXTURE_SIZE too small: ${t.maxTextureSize} (minimum 256 required for font atlas)`):t.maxTextureSize<2048&&t.warnings.push(`\u26A0\uFE0F Small MAX_TEXTURE_SIZE: ${t.maxTextureSize} (may limit font atlas)`),(t.maxViewportDims[0]<1024||t.maxViewportDims[1]<768)&&t.warnings.push(`\u26A0\uFE0F Small MAX_VIEWPORT_DIMS: ${t.maxViewportDims[0]}\xD7${t.maxViewportDims[1]}`),s.getExtension("WEBGL_lose_context")||t.warnings.push("\u26A0\uFE0F WEBGL_lose_context not supported - may cause memory leaks"),t}initInstancedBuffers(){let t=this.gl;this.templateQuadPositions=new Float32Array([0,0,this.cellWidth,0,0,this.cellHeight,this.cellWidth,this.cellHeight]),this.templateQuadIndices=new Uint16Array([0,1,2,2,1,3]),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.templateQuadPositions,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,this.templateQuadIndices,t.STATIC_DRAW),this.instanceData=new Float32Array(this.maxCells*8),console.warn(`[TerminalGL] \u{1F680} initInstancedBuffers: maxCells=${this.maxCells}, instanceData.length=${this.instanceData.length}`),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer),t.bufferData(t.ARRAY_BUFFER,this.instanceData.byteLength,t.DYNAMIC_DRAW)}initRenderBuffers(){let t=this.cols*this.rows*2;this.maxCells=Math.ceil(t*2),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.staticPositionsInitialized=!1}precomputeStaticPositions(){let t=this.cellWidth,e=this.cellHeight,i=this.glyphOffsetX,s=this.glyphOffsetY,a=this.charWidth,r=this.charHeight,o=0,n=0,h=0;for(let d=0;d<this.rows;d++){let f=Math.round(d*e),m=Math.round(f+e);for(let g=0;g<this.cols;g++){let u=Math.round(g*t),p=Math.round(u+t);this.renderPositions[o++]=u,this.renderPositions[o++]=f,this.renderPositions[o++]=p,this.renderPositions[o++]=f,this.renderPositions[o++]=u,this.renderPositions[o++]=m,this.renderPositions[o++]=p,this.renderPositions[o++]=m,this.renderIndices[n++]=h,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+3,h+=4;let C=Math.round(u+i),x=Math.round(f+s),E=Math.round(C+a),w=Math.round(x+r);this.renderPositions[o++]=C,this.renderPositions[o++]=x,this.renderPositions[o++]=E,this.renderPositions[o++]=x,this.renderPositions[o++]=C,this.renderPositions[o++]=w,this.renderPositions[o++]=E,this.renderPositions[o++]=w,this.renderIndices[n++]=h,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+3,h+=4}}let c=this.gl;c.bindBuffer(c.ARRAY_BUFFER,this.positionBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,this.renderPositions),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,this.indexBuffer),c.bufferSubData(c.ELEMENT_ARRAY_BUFFER,0,this.renderIndices),this.staticPositionsInitialized=!0}initWebGL(){let t=this.gl,e;this.useInstancing?e=`
38
+ `;let h=this.canvas.getContext("webgl",{alpha:this.canvasBgColor===null,premultipliedAlpha:!1});if(!h)throw new Error("TerminalGL: WebGL not supported");this.gl=h,this.supportsUint32Indices=!!h.getExtension("OES_element_index_uint"),this.useUint16Indices=n||!this.supportsUint32Indices,this.useUint16Indices?console.warn(`[TerminalGL] \u{1F4CA} Using Uint16 indices (max ${s.maxCellsUint16} cells)`):console.warn(`[TerminalGL] \u{1F4CA} Using Uint32 indices (max ${s.maxCellsUint32} cells)`),this.vaoExtension=h.getExtension("OES_vertex_array_object"),this.vaoExtension&&console.warn("[TerminalGL] \u2705 VAO extension enabled (faster attribute binding)"),this.instancedExtension=h.getExtension("ANGLE_instanced_arrays"),this.instancedExtension?(this.useInstancing=!0,console.warn("[TerminalGL] \u{1F680} Instanced rendering enabled (massive draw call reduction)")):console.warn("[TerminalGL] \u26A0\uFE0F Instanced rendering not available (fallback to standard rendering)"),this.containerDiv.appendChild(this.canvas),this.ambientEffectEnabled&&(this.createAmbientEffectCanvas(),console.warn("[TerminalGL] \u{1F308} Ambient effect enabled at startup")),this.parentElement.appendChild(this.containerDiv),this.initRenderBuffers();try{this.initWebGL()}catch(c){throw console.error("[TerminalGL] \u274C Failed to initialize WebGL:",c),c}this.showGrid&&this.initGridOverlay(),this.setupResizeObserver()}static checkCompatibility(){let t={webgl1:!1,uint32Indices:!1,maxTextureSize:0,maxViewportDims:[0,0],maxCellsUint16:0,maxCellsUint32:0,recommendedMaxCells:0,warnings:[],errors:[]},e=document.createElement("canvas"),i=e.getContext("webgl")||e.getContext("experimental-webgl");if(!i||!(i instanceof WebGLRenderingContext))return t.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),t;let s=i;t.webgl1=!0;try{t.maxTextureSize=s.getParameter(s.MAX_TEXTURE_SIZE);let a=s.getParameter(s.MAX_VIEWPORT_DIMS);t.maxViewportDims=[a[0],a[1]]}catch(a){return t.errors.push(`\u274C Failed to query WebGL parameters: ${a}`),t}let n=s.getExtension("OES_element_index_uint");t.uint32Indices=!!n;let r=8;if(t.maxCellsUint16=Math.floor(65535/r),t.uint32Indices){let a=Math.floor(t.maxTextureSize*t.maxTextureSize/64);t.maxCellsUint32=Math.min(a,262144)}else t.maxCellsUint32=t.maxCellsUint16,t.warnings.push(`\u26A0\uFE0F OES_element_index_uint not supported - limited to ${t.maxCellsUint16} cells (e.g., 90\xD790 or 127\xD764)`);return t.recommendedMaxCells=Math.floor((t.uint32Indices?t.maxCellsUint32:t.maxCellsUint16)*.8),t.maxTextureSize<256?t.errors.push(`\u274C MAX_TEXTURE_SIZE too small: ${t.maxTextureSize} (minimum 256 required for font atlas)`):t.maxTextureSize<2048&&t.warnings.push(`\u26A0\uFE0F Small MAX_TEXTURE_SIZE: ${t.maxTextureSize} (may limit font atlas)`),(t.maxViewportDims[0]<1024||t.maxViewportDims[1]<768)&&t.warnings.push(`\u26A0\uFE0F Small MAX_VIEWPORT_DIMS: ${t.maxViewportDims[0]}\xD7${t.maxViewportDims[1]}`),s.getExtension("WEBGL_lose_context")||t.warnings.push("\u26A0\uFE0F WEBGL_lose_context not supported - may cause memory leaks"),t}initInstancedBuffers(){let t=this.gl;this.templateQuadPositions=new Float32Array([0,0,this.cellWidth,0,0,this.cellHeight,this.cellWidth,this.cellHeight]),this.templateQuadIndices=new Uint16Array([0,1,2,2,1,3]),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.templateQuadPositions,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,this.templateQuadIndices,t.STATIC_DRAW),this.instanceData=new Float32Array(this.maxCells*8),console.warn(`[TerminalGL] \u{1F680} initInstancedBuffers: maxCells=${this.maxCells}, instanceData.length=${this.instanceData.length}`),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer),t.bufferData(t.ARRAY_BUFFER,this.instanceData.byteLength,t.DYNAMIC_DRAW)}initRenderBuffers(){let t=this.cols*this.rows*2;this.maxCells=Math.ceil(t*2),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.staticPositionsInitialized=!1}precomputeStaticPositions(){let t=this.cellWidth,e=this.cellHeight,i=this.glyphOffsetX,s=this.glyphOffsetY,n=this.charWidth,r=this.charHeight,o=0,a=0,h=0;for(let d=0;d<this.rows;d++){let f=Math.round(d*e),m=Math.round(f+e);for(let g=0;g<this.cols;g++){let u=Math.round(g*t),p=Math.round(u+t);this.renderPositions[o++]=u,this.renderPositions[o++]=f,this.renderPositions[o++]=p,this.renderPositions[o++]=f,this.renderPositions[o++]=u,this.renderPositions[o++]=m,this.renderPositions[o++]=p,this.renderPositions[o++]=m,this.renderIndices[a++]=h,this.renderIndices[a++]=h+1,this.renderIndices[a++]=h+2,this.renderIndices[a++]=h+2,this.renderIndices[a++]=h+1,this.renderIndices[a++]=h+3,h+=4;let C=Math.round(u+i),x=Math.round(f+s),E=Math.round(C+n),w=Math.round(x+r);this.renderPositions[o++]=C,this.renderPositions[o++]=x,this.renderPositions[o++]=E,this.renderPositions[o++]=x,this.renderPositions[o++]=C,this.renderPositions[o++]=w,this.renderPositions[o++]=E,this.renderPositions[o++]=w,this.renderIndices[a++]=h,this.renderIndices[a++]=h+1,this.renderIndices[a++]=h+2,this.renderIndices[a++]=h+2,this.renderIndices[a++]=h+1,this.renderIndices[a++]=h+3,h+=4}}let c=this.gl;c.bindBuffer(c.ARRAY_BUFFER,this.positionBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,this.renderPositions),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,this.indexBuffer),c.bufferSubData(c.ELEMENT_ARRAY_BUFFER,0,this.renderIndices),this.staticPositionsInitialized=!0}initWebGL(){let t=this.gl,e;this.useInstancing?e=`
39
39
  // Per-vertex attributes (template quad)
40
40
  attribute vec2 aPosition; // Local quad position (0,0 to cellW,cellH)
41
41
 
@@ -116,7 +116,7 @@
116
116
  gl_FragColor = vec4(texColor.rgb * vColor.rgb, texColor.a);
117
117
  }
118
118
  }
119
- `,s=this.compileShader(t.VERTEX_SHADER,e),a=this.compileShader(t.FRAGMENT_SHADER,i);if(!s||!a)throw new Error("Shader compilation error");let r=t.createProgram();if(!r)throw new Error("Unable to create WebGL program");if(t.attachShader(r,s),t.attachShader(r,a),t.linkProgram(r),!t.getProgramParameter(r,t.LINK_STATUS)){let o=t.getProgramInfoLog(r);throw new Error("Program linking error: "+o)}this.program=r,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=t.getAttribLocation(r,"aPosition"),this.useInstancing?(this.aInstanceOffset=t.getAttribLocation(r,"aInstanceOffset"),this.aInstanceUVs=t.getAttribLocation(r,"aInstanceUVs"),this.aInstanceColors=t.getAttribLocation(r,"aInstanceColors"),this.uCellSize=t.getUniformLocation(r,"uCellSize"),this.instanceDataBuffer=t.createBuffer(),this.aTexCoord=this.aInstanceOffset,this.aColorIndex=this.aInstanceUVs):(this.aTexCoord=t.getAttribLocation(r,"aTexCoord"),this.aColorIndex=t.getAttribLocation(r,"aColorIndex")),this.uResolution=t.getUniformLocation(r,"uResolution"),this.uTexture=t.getUniformLocation(r,"uTexture"),this.uPalette=t.getUniformLocation(r,"uPalette"),this.positionBuffer=t.createBuffer(),this.texCoordBuffer=t.createBuffer(),this.colorIndexBuffer=t.createBuffer(),this.indexBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.renderPositions.byteLength,t.DYNAMIC_DRAW),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferData(t.ARRAY_BUFFER,this.renderTexCoords.byteLength,t.DYNAMIC_DRAW),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferData(t.ARRAY_BUFFER,this.renderColorIndices.byteLength,t.DYNAMIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,t.DYNAMIC_DRAW),this.vaoExtension&&(this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.enableVertexAttribArray(this.aTexCoord),t.vertexAttribPointer(this.aTexCoord,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.enableVertexAttribArray(this.aColorIndex),t.vertexAttribPointer(this.aColorIndex,1,t.FLOAT,!1,0,0),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null))),t.enable(t.BLEND),t.blendFunc(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA),t.viewport(0,0,this.canvas.width,this.canvas.height)}compileShader(t,e){let i=this.gl,s=i.createShader(t);return s?(i.shaderSource(s,e),i.compileShader(s),i.getShaderParameter(s,i.COMPILE_STATUS)?s:(console.error("Shader compilation error:",i.getShaderInfoLog(s)),i.deleteShader(s),null)):null}initGridOverlay(){this.gridOverlay=new A(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,i=this.canvas.getBoundingClientRect(),s=this.containerDiv.getBoundingClientRect();this.gridOverlay.setDimensions(this.cols,this.rows,this.cellWidth,this.cellHeight,0,0),this.gridOverlay.setTransform(this.currentScale,t,e,i,s),this.gridOverlay.render()}setBitmapFont(t,e,i,s,a){this.bitmapFont=t,this.fontLoaded=!0,this.charWidth=Math.round(e),this.charHeight=Math.round(i),this.cellWidth=Math.round(s),this.cellHeight=Math.round(a),this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers..."),this.initInstancedBuffers());try{this.generateAtlas()}catch(r){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",r),r}this.buildCharCodeMap(),this.precomputeAtlasUVs(),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async setImageFont(t,e,i,s,a,r){this.fontLoaded=!0,this.charWidth=Math.round(e),this.charHeight=Math.round(i),this.cellWidth=Math.round(s),this.cellHeight=Math.round(a),this.atlasColumns=M(r);let o=S(r);this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers for ImageFont..."),this.initInstancedBuffers()),await this.loadImageFontAtlas(t),this.charCodeToAtlasIndex.fill(65535);for(let n=0;n<=o;n++)this.charCodeToAtlasIndex[n]=n;this.precomputeImageFontUVs(r),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async loadImageFontAtlas(t){return new Promise((e,i)=>{let s=new Uint8Array(t),a=new Blob([s],{type:"image/png"}),r=URL.createObjectURL(a),o=new Image;o.onload=()=>{URL.revokeObjectURL(r),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=o.width,this.atlasCanvas.height=o.height;let n=this.atlasCanvas.getContext("2d");if(!n){i(new Error("Failed to create 2D context for atlas"));return}n.drawImage(o,0,0),this.cachedAtlasWidth=o.width,this.cachedAtlasHeight=o.height,this.createAtlasTexture(),e()},o.onerror=()=>{URL.revokeObjectURL(r),i(new Error("Failed to load PNG image for ImageFont atlas"))},o.src=r})}precomputeImageFontUVs(t){let e=t*256;this.atlasUVs=new Float32Array(e*4);let i=this.cachedAtlasWidth,s=this.cachedAtlasHeight,a=.5/i,r=.5/s;for(let o=0;o<e;o++){let{col:n,row:h}=B(o,t),c=(n*this.charWidth+a)/i,d=(h*this.charHeight+r)/s,f=((n+1)*this.charWidth-a)/i,m=((h+1)*this.charHeight-r)/s,g=o*4;this.atlasUVs[g]=c,this.atlasUVs[g+1]=d,this.atlasUVs[g+2]=f,this.atlasUVs[g+3]=m}}generateAtlas(){if(!this.bitmapFont)return;let t=Array.from(this.bitmapFont.keys()).sort((n,h)=>n-h),e=t.length;this.atlasColumns=Math.ceil(Math.sqrt(e));let i=Math.ceil(e/this.atlasColumns),s=this.atlasColumns*this.charWidth,a=i*this.charHeight;this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=s,this.atlasCanvas.height=a;let r=this.atlasCanvas.getContext("2d");if(!r)throw new Error("Unable to create 2D context for atlas");r.clearRect(0,0,s,a),r.fillStyle="#ffffff";let o=0;for(let n of t){let h=this.bitmapFont.get(n);if(!h)continue;let c=o%this.atlasColumns,d=Math.floor(o/this.atlasColumns),f=c*this.charWidth,m=d*this.charHeight;for(let g=0;g<Math.min(h.length,this.charHeight);g++){let u=h[g];for(let p=0;p<this.charWidth;p++){let C=1<<7-p;u&C&&r.fillRect(f+p,m+g,1,1)}}o++}this.createAtlasTexture()}buildCharCodeMap(){if(!this.bitmapFont)return;this.charCodeToAtlasIndex.fill(65535);let t=Array.from(this.bitmapFont.keys()).sort((e,i)=>e-i);for(let e=0;e<t.length;e++)this.charCodeToAtlasIndex[t[e]]=e}precomputeAtlasUVs(){if(!this.bitmapFont)return;let t=this.bitmapFont.size;this.atlasUVs=new Float32Array(t*4),this.cachedAtlasWidth=this.atlasColumns*this.charWidth,this.cachedAtlasHeight=Math.ceil(t/this.atlasColumns)*this.charHeight;let e=this.cachedAtlasWidth,i=this.cachedAtlasHeight,s=.5/e,a=.5/i;for(let r=0;r<t;r++){let o=r%this.atlasColumns,n=Math.floor(r/this.atlasColumns),h=(o*this.charWidth+s)/e,c=(n*this.charHeight+a)/i,d=((o+1)*this.charWidth-s)/e,f=((n+1)*this.charHeight-a)/i,m=r*4;this.atlasUVs[m]=h,this.atlasUVs[m+1]=c,this.atlasUVs[m+2]=d,this.atlasUVs[m+3]=f}}createAtlasTexture(){if(this.atlasCanvas)try{let t=this.gl,e=t.createTexture();if(!e)throw new Error("Unable to create texture");t.bindTexture(t.TEXTURE_2D,e),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,this.atlasCanvas),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),this.atlasTexture=e}catch(t){throw console.error("[TerminalGL] \u274C Failed to create atlas texture:",t),t}}clear(){let t=this.gl;t&&t.clear(t.COLOR_BUFFER_BIT)}parseColor(t){if(t.startsWith("#")){let e=t.slice(1),i=0,s=0,a=0;return e.length===3?(i=parseInt(e[0]+e[0],16),s=parseInt(e[1]+e[1],16),a=parseInt(e[2]+e[2],16)):e.length===6&&(i=parseInt(e.slice(0,2),16),s=parseInt(e.slice(2,4),16),a=parseInt(e.slice(4,6),16)),[i/255,s/255,a/255,1]}if(t.startsWith("rgb")){let e=t.match(/rgba?\(([^)]+)\)/);if(e){let i=e[1].split(",").map(s=>parseFloat(s.trim()));return[i[0]/255,i[1]/255,i[2]/255,i[3]!==void 0?i[3]:1]}}return[1,1,1,1]}setupResizeObserver(){if(!(typeof ResizeObserver>"u"))try{this.resizeObserver=new ResizeObserver(()=>{try{this.updateCanvasSize()}catch(t){console.error("[TerminalGL] \u274C Error in resize callback:",t)}}),this.resizeObserver.observe(this.parentElement),this.updateCanvasSize()}catch(t){console.error("[TerminalGL] \u274C Failed to setup ResizeObserver:",t)}}updateCanvasSize(){let t=this.parentElement.clientWidth,e=this.parentElement.clientHeight;if(t===0||e===0)return;let i=this.cols*this.cellWidth,s=this.rows*this.cellHeight;if(i===0||s===0)return;let a=t/i,r=e/s,o=Math.min(a,r),n;switch(this.scalingMode){case y.ScalingMode.Integer:n=Math.max(1,Math.floor(o));break;case y.ScalingMode.Half:n=Math.max(1,Math.floor(o*2)/2);break;case y.ScalingMode.Quarter:n=Math.max(1,Math.floor(o*4)/4);break;case y.ScalingMode.Eighth:n=Math.max(1,Math.floor(o*8)/8);break;case y.ScalingMode.Responsive:n=1;break;case y.ScalingMode.None:default:n=Math.max(.1,o);break}if(this.canvas.style.transform=`scale(${n})`,this.ambientEffectEnabled&&this.ambientEffectCanvas){let h=n*this.ambientEffectScale;this.ambientEffectCanvas.style.transform=`scale(${h})`}this.currentScale=n,this.onResizeCallback&&this.onResizeCallback(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}updateAmbientEffect(){!this.ambientEffectCanvas||!this.ambientEffectCtx||this.ambientEffectCtx.drawImage(this.canvas,0,0)}setPalette(t){let e=0;for(let i=0;i<Math.min(t.length,256);i++){let s=t[i];e=(e<<5)-e+s.r,e=(e<<5)-e+s.g,e=(e<<5)-e+s.b,e=(e<<5)-e+s.a,e=e|0}if(e!==this.paletteHash){this.paletteHash=e;for(let i=0;i<t.length&&i<256;i++){let s=t[i],a=i*4;this.paletteFloat[a]=s.r/255,this.paletteFloat[a+1]=s.g/255,this.paletteFloat[a+2]=s.b/255,this.paletteFloat[a+3]=s.a/255}this.updatePaletteTexture()}}updatePaletteTexture(){try{let t=this.gl;this.paletteTexture||(this.paletteTexture=t.createTexture()),t.bindTexture(t.TEXTURE_2D,this.paletteTexture);let e=new Uint8Array(256*4);for(let i=0;i<256;i++){let s=i*4;e[s]=this.paletteFloat[s]*255,e[s+1]=this.paletteFloat[s+1]*255,e[s+2]=this.paletteFloat[s+2]*255,e[s+3]=this.paletteFloat[s+3]*255}t.texImage2D(t.TEXTURE_2D,0,t.RGBA,256,1,0,t.RGBA,t.UNSIGNED_BYTE,e),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.bindTexture(t.TEXTURE_2D,null)}catch(t){throw console.error("[TerminalGL] \u274C Failed to update palette texture:",t),t}}renderDisplayData(t){try{if(!this.isReady()){console.warn("[TerminalGL] \u26A0\uFE0F Not ready: font not loaded yet");return}(t.width!==this.cols||t.height!==this.rows)&&this.resize(t.width,t.height),this.renderDirect(t),this.ambientEffectEnabled&&this.ambientEffectCanvas&&this.ambientEffectCtx&&this.updateAmbientEffect()}catch(e){console.error("[TerminalGL] \u274C Error rendering display data:",e)}}renderDirect(t){let e=this.gl;if(!this.staticPositionsInitialized&&!this.useInstancing&&this.precomputeStaticPositions(),this.canvasBgColor!==null){let i=this.parseColor(this.canvasBgColor);e.clearColor(i[0],i[1],i[2],i[3])}else e.clearColor(0,0,0,0);e.clear(e.COLOR_BUFFER_BIT),this.useInstancing?this.renderInstanced(t):this.renderDirectBuffers(t)}renderInstanced(t){let e=this.gl,i=this.instancedExtension;if(!this.instanceData||this.instanceData.length===0){console.warn("[TerminalGL] \u26A0\uFE0F Instance data not initialized, falling back to standard rendering"),this.renderDirectBuffers(t);return}let s=0,a=this.instanceData.length/8,r=t.width*t.height*2;if(r>a){console.error(`[TerminalGL] \u274C Instance buffer too small! Need ${r}, have ${a}. Display size: ${t.width}\xD7${t.height}, buffer was sized for smaller terminal.`),this.renderDirectBuffers(t);return}for(let n=0;n<t.height;n++)for(let h=0;h<t.width;h++){let c=t.cells[n*t.width+h],d=c.bgColorIndex,f=c.fgColorIndex,m=this.canvasBgColor!==null&&d===255,g=c.char===" "||f===255;if(!m){if(s>=a){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${a}`);break}let u=s*8;this.instanceData[u]=h,this.instanceData[u+1]=n,this.instanceData[u+2]=0,this.instanceData[u+3]=0,this.instanceData[u+4]=0,this.instanceData[u+5]=0,this.instanceData[u+6]=d,this.instanceData[u+7]=0,s++}if(!g){let u=c.char.charCodeAt(0),p=this.charCodeToAtlasIndex[u];if(p!==65535){if(s>=a){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${a}`);break}let C=p*4,x=s*8;this.instanceData[x]=h,this.instanceData[x+1]=n,this.instanceData[x+2]=this.atlasUVs[C],this.instanceData[x+3]=this.atlasUVs[C+1],this.instanceData[x+4]=this.atlasUVs[C+2],this.instanceData[x+5]=this.atlasUVs[C+3],this.instanceData[x+6]=0,this.instanceData[x+7]=f,s++}}}if(s===0){console.warn("[TerminalGL] \u26A0\uFE0F No instances to draw (all cells skipped)");return}e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.instanceData.subarray(0,s*8)),e.useProgram(this.program),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),i.vertexAttribDivisorANGLE(this.aPosition,0),e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer);let o=8*Float32Array.BYTES_PER_ELEMENT;e.enableVertexAttribArray(this.aInstanceOffset),e.vertexAttribPointer(this.aInstanceOffset,2,e.FLOAT,!1,o,0),i.vertexAttribDivisorANGLE(this.aInstanceOffset,1),e.enableVertexAttribArray(this.aInstanceUVs),e.vertexAttribPointer(this.aInstanceUVs,4,e.FLOAT,!1,o,2*Float32Array.BYTES_PER_ELEMENT),i.vertexAttribDivisorANGLE(this.aInstanceUVs,1),e.enableVertexAttribArray(this.aInstanceColors),e.vertexAttribPointer(this.aInstanceColors,2,e.FLOAT,!1,o,6*Float32Array.BYTES_PER_ELEMENT),i.vertexAttribDivisorANGLE(this.aInstanceColors,1),e.uniform2f(this.uResolution,this.canvas.width,this.canvas.height),e.uniform2f(this.uCellSize,this.cellWidth,this.cellHeight),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,this.atlasTexture),e.uniform1i(this.uTexture,0),e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,this.paletteTexture),e.uniform1i(this.uPalette,1),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),i.drawElementsInstancedANGLE(e.TRIANGLES,6,e.UNSIGNED_SHORT,0,s),i.vertexAttribDivisorANGLE(this.aPosition,0),i.vertexAttribDivisorANGLE(this.aInstanceOffset,0),i.vertexAttribDivisorANGLE(this.aInstanceUVs,0),i.vertexAttribDivisorANGLE(this.aInstanceColors,0)}renderDirectBuffers(t){let e=this.gl,i=t.width*t.height,s=i*2;if(s>this.maxCells){console.error(`[TerminalGL] \u274C Buffer overflow detected! Trying to render ${s} quads but buffer capacity is ${this.maxCells}. This should not happen - resize() should have reallocated.`);return}let a=0,r=0,o=t.cells,n=i;for(let g=0;g<n;g++){let u=o[g],p=u.bgColorIndex,x=this.canvasBgColor!==null&&p===255?255:p,E=0;for(let T=0;T<4;T++)this.renderTexCoords[a++]=E,this.renderTexCoords[a++]=E,this.renderColorIndices[r++]=x;let w=u.fgColorIndex,H=u.char;if(H===" "||w===255)for(let T=0;T<4;T++)this.renderTexCoords[a++]=0,this.renderTexCoords[a++]=0,this.renderColorIndices[r++]=255;else{let T=H.charCodeAt(0),Z=this.charCodeToAtlasIndex[T];if(Z!==65535){let I=Z*4,K=this.atlasUVs[I],J=this.atlasUVs[I+1],tt=this.atlasUVs[I+2],et=this.atlasUVs[I+3];this.renderTexCoords[a++]=K,this.renderTexCoords[a++]=J,this.renderColorIndices[r++]=w,this.renderTexCoords[a++]=tt,this.renderTexCoords[a++]=J,this.renderColorIndices[r++]=w,this.renderTexCoords[a++]=K,this.renderTexCoords[a++]=et,this.renderColorIndices[r++]=w,this.renderTexCoords[a++]=tt,this.renderTexCoords[a++]=et,this.renderColorIndices[r++]=w}else for(let I=0;I<4;I++)this.renderTexCoords[a++]=0,this.renderTexCoords[a++]=0,this.renderColorIndices[r++]=255}}(a!==n*2*4*2||r!==n*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:a,colorIdx:r,expected:n*2*4}),e.useProgram(this.program),this.vao&&this.vaoExtension?(this.vaoExtension.bindVertexArrayOES(this.vao),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,a)),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,r))):(e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,a)),e.enableVertexAttribArray(this.aTexCoord),e.vertexAttribPointer(this.aTexCoord,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,r)),e.enableVertexAttribArray(this.aColorIndex),e.vertexAttribPointer(this.aColorIndex,1,e.FLOAT,!1,0,0));let h=this.canvas.width,c=this.canvas.height;(this.cachedResolution[0]!==h||this.cachedResolution[1]!==c)&&(e.uniform2f(this.uResolution,h,c),this.cachedResolution[0]=h,this.cachedResolution[1]=c),this.cachedTextureUnit!==0&&(e.activeTexture(e.TEXTURE0),this.cachedTextureUnit=0),e.bindTexture(e.TEXTURE_2D,this.atlasTexture),this.cachedTextureUniform||(e.uniform1i(this.uTexture,0),this.cachedTextureUniform=!0),this.cachedPaletteUnit!==1&&(e.activeTexture(e.TEXTURE1),this.cachedPaletteUnit=1),e.bindTexture(e.TEXTURE_2D,this.paletteTexture),this.cachedPaletteUniform||(e.uniform1i(this.uPalette,1),this.cachedPaletteUniform=!0),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer);let f=t.width*t.height*2*6,m=this.useUint16Indices?e.UNSIGNED_SHORT:e.UNSIGNED_INT;e.drawElements(e.TRIANGLES,f,m,0)}resize(t,e){if(!Number.isInteger(t)||t<=0){console.error(`[TerminalGL] \u274C Invalid cols: ${t}. Must be positive integer.`);return}if(!Number.isInteger(e)||e<=0){console.error(`[TerminalGL] \u274C Invalid rows: ${e}. Must be positive integer.`);return}if(t===this.cols&&e===this.rows)return;let i=t*e,s=this.useInstancing?262144:this.useUint16Indices?8191:262144;if(i>s){let c=Math.floor(Math.sqrt(s));console.error(`[TerminalGL] \u274C Cannot resize to ${t}\xD7${e} (${i} cells). Device limit: ${s} cells (max ~${c}\xD7${c}). ${!this.useInstancing&&this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let a=L.checkCompatibility();i>a.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${t}\xD7${e} (${i} cells) exceeds recommended limit (${a.recommendedMaxCells} cells). Performance may degrade.`),this.cols=t,this.rows=e,this.staticPositionsInitialized=!1;let r=this.cols*this.rows*2,o=Math.ceil(r*1.5),n=r>this.maxCells,h=this.maxCells>o*4;if(console.warn(`[TerminalGL] \u{1F4D0} resize check: cols=${t}, rows=${e}, newMaxCells=${r}, this.maxCells=${this.maxCells}, needGrow=${n}, needShrink=${h}`),n||h){let c=this.maxCells;if(this.maxCells=o,console.warn(`[TerminalGL] \u{1F4D0} resize realloc: ${c} \u2192 ${this.maxCells} (needGrow=${n}, needShrink=${h})`),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.useInstancing&&this.instanceDataBuffer){this.instanceData=new Float32Array(this.maxCells*8);let u=this.gl;u.bindBuffer(u.ARRAY_BUFFER,this.instanceDataBuffer),u.bufferData(u.ARRAY_BUFFER,this.instanceData.byteLength,u.DYNAMIC_DRAW)}let d=this.gl;this.useInstancing||(d.bindBuffer(d.ARRAY_BUFFER,this.positionBuffer),d.bufferData(d.ARRAY_BUFFER,this.renderPositions.byteLength,d.DYNAMIC_DRAW)),d.bindBuffer(d.ARRAY_BUFFER,this.texCoordBuffer),d.bufferData(d.ARRAY_BUFFER,this.renderTexCoords.byteLength,d.DYNAMIC_DRAW),d.bindBuffer(d.ARRAY_BUFFER,this.colorIndexBuffer),d.bufferData(d.ARRAY_BUFFER,this.renderColorIndices.byteLength,d.DYNAMIC_DRAW),this.useInstancing||(d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,this.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,d.DYNAMIC_DRAW)),this.vaoExtension&&this.vao&&(this.vaoExtension.deleteVertexArrayOES(this.vao),this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),d.bindBuffer(d.ARRAY_BUFFER,this.positionBuffer),d.enableVertexAttribArray(this.aPosition),d.vertexAttribPointer(this.aPosition,2,d.FLOAT,!1,0,0),d.bindBuffer(d.ARRAY_BUFFER,this.texCoordBuffer),d.enableVertexAttribArray(this.aTexCoord),d.vertexAttribPointer(this.aTexCoord,2,d.FLOAT,!1,0,0),d.bindBuffer(d.ARRAY_BUFFER,this.colorIndexBuffer),d.enableVertexAttribArray(this.aColorIndex),d.vertexAttribPointer(this.aColorIndex,1,d.FLOAT,!1,0,0),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null)));let f=n?"\u{1F4C8} Growing":"\u{1F4C9} Shrinking",m=c*160/1048576,g=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${f} buffers: ${m.toFixed(2)}MB \u2192 ${g.toFixed(2)}MB (${c} \u2192 ${this.maxCells} quads)`)}this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.canvas.style.width=`${this.canvas.width}px`,this.canvas.style.height=`${this.canvas.height}px`,this.ambientEffectEnabled&&this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.width=`${this.canvas.width}px`,this.ambientEffectCanvas.style.height=`${this.canvas.height}px`),this.showGrid&&this.gridOverlay&&this.updateGridOverlay(),this.updateCanvasSize()}getCanvas(){return this.canvas}getGridSize(){return{cols:this.cols,rows:this.rows}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getBaseDimensions(){return{width:this.cols*this.cellWidth,height:this.rows*this.cellHeight}}setOnResizeCallback(t){this.onResizeCallback=t}clearOnResizeCallback(){this.onResizeCallback=void 0}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}setScalingMode(t){this.scalingMode!==t&&(this.scalingMode=t,this.updateCanvasSize())}getScalingMode(){return this.scalingMode}setCellSize(t,e){let i=Math.max(1,Math.min(255,Math.round(t))),s=Math.max(1,Math.min(255,Math.round(e)));this.cellWidth===i&&this.cellHeight===s||(this.cellWidth=i,this.cellHeight=s,this.charWidth=i,this.charHeight=s,this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.fontLoaded&&this.generateAtlas(),this.useInstancing&&this.initInstancedBuffers(),this.updateCanvasSize())}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getMaxCells(){return this.useInstancing?262144:this.useUint16Indices?8191:262144}setGrid(t){t.enabled?(this.gridOverlay?this.gridOverlay.setStyle({strokeColor:t.color,lineWidth:t.lineWidth}):this.gridOverlay=new A(this.containerDiv,{strokeColor:t.color??"rgba(144, 24, 24, 1)",lineWidth:t.lineWidth??1,zIndex:10}),this.showGrid=!0,this.gridOverlay.setVisible(!0),this.updateGridOverlay()):(this.showGrid=!1,this.gridOverlay&&this.gridOverlay.setVisible(!1))}isGridEnabled(){return this.showGrid}setAmbientEffect(t){typeof t=="boolean"?this.ambientEffectEnabled=t:(this.ambientEffectEnabled=!0,t.blur!==void 0&&(this.ambientEffectBlur=t.blur),t.scale!==void 0&&(this.ambientEffectScale=t.scale)),this.ambientEffectEnabled&&!this.ambientEffectCanvas&&this.createAmbientEffectCanvas(),this.ambientEffectCanvas&&(this.ambientEffectEnabled?(this.ambientEffectCanvas.style.display="block",this.ambientEffectCanvas.style.filter=`blur(${this.ambientEffectBlur}px)`,this.ambientEffectCanvas.style.transform=`scale(${this.ambientEffectScale})`,this.updateAmbientEffect()):this.ambientEffectCanvas.style.display="none")}createAmbientEffectCanvas(){this.ambientEffectCanvas||(this.ambientEffectCanvas=document.createElement("canvas"),this.ambientEffectCanvas.className="terminalgl-ambient-effect-canvas",this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.cssText=`
119
+ `,s=this.compileShader(t.VERTEX_SHADER,e),n=this.compileShader(t.FRAGMENT_SHADER,i);if(!s||!n)throw new Error("Shader compilation error");let r=t.createProgram();if(!r)throw new Error("Unable to create WebGL program");if(t.attachShader(r,s),t.attachShader(r,n),t.linkProgram(r),!t.getProgramParameter(r,t.LINK_STATUS)){let o=t.getProgramInfoLog(r);throw new Error("Program linking error: "+o)}this.program=r,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=t.getAttribLocation(r,"aPosition"),this.useInstancing?(this.aInstanceOffset=t.getAttribLocation(r,"aInstanceOffset"),this.aInstanceUVs=t.getAttribLocation(r,"aInstanceUVs"),this.aInstanceColors=t.getAttribLocation(r,"aInstanceColors"),this.uCellSize=t.getUniformLocation(r,"uCellSize"),this.instanceDataBuffer=t.createBuffer(),this.aTexCoord=this.aInstanceOffset,this.aColorIndex=this.aInstanceUVs):(this.aTexCoord=t.getAttribLocation(r,"aTexCoord"),this.aColorIndex=t.getAttribLocation(r,"aColorIndex")),this.uResolution=t.getUniformLocation(r,"uResolution"),this.uTexture=t.getUniformLocation(r,"uTexture"),this.uPalette=t.getUniformLocation(r,"uPalette"),this.positionBuffer=t.createBuffer(),this.texCoordBuffer=t.createBuffer(),this.colorIndexBuffer=t.createBuffer(),this.indexBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.renderPositions.byteLength,t.DYNAMIC_DRAW),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferData(t.ARRAY_BUFFER,this.renderTexCoords.byteLength,t.DYNAMIC_DRAW),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferData(t.ARRAY_BUFFER,this.renderColorIndices.byteLength,t.DYNAMIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,t.DYNAMIC_DRAW),this.vaoExtension&&(this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.enableVertexAttribArray(this.aTexCoord),t.vertexAttribPointer(this.aTexCoord,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.enableVertexAttribArray(this.aColorIndex),t.vertexAttribPointer(this.aColorIndex,1,t.FLOAT,!1,0,0),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null))),t.enable(t.BLEND),t.blendFunc(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA),t.viewport(0,0,this.canvas.width,this.canvas.height)}compileShader(t,e){let i=this.gl,s=i.createShader(t);return s?(i.shaderSource(s,e),i.compileShader(s),i.getShaderParameter(s,i.COMPILE_STATUS)?s:(console.error("Shader compilation error:",i.getShaderInfoLog(s)),i.deleteShader(s),null)):null}initGridOverlay(){this.gridOverlay=new A(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,i=this.canvas.getBoundingClientRect(),s=this.containerDiv.getBoundingClientRect();this.gridOverlay.setDimensions(this.cols,this.rows,this.cellWidth,this.cellHeight,0,0),this.gridOverlay.setTransform(this.currentScale,t,e,i,s),this.gridOverlay.render()}setBitmapFont(t,e,i,s,n){this.bitmapFont=t,this.fontLoaded=!0,this.charWidth=Math.round(e),this.charHeight=Math.round(i),this.cellWidth=Math.round(s),this.cellHeight=Math.round(n),this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers..."),this.initInstancedBuffers());try{this.generateAtlas()}catch(r){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",r),r}this.buildCharCodeMap(),this.precomputeAtlasUVs(),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async setImageFont(t,e,i,s,n,r){this.fontLoaded=!0,this.charWidth=Math.round(e),this.charHeight=Math.round(i),this.cellWidth=Math.round(s),this.cellHeight=Math.round(n),this.atlasColumns=M(r);let o=S(r);this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers for ImageFont..."),this.initInstancedBuffers()),await this.loadImageFontAtlas(t),this.charCodeToAtlasIndex.fill(65535);for(let a=0;a<=o;a++)this.charCodeToAtlasIndex[a]=a;this.precomputeImageFontUVs(r),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async loadImageFontAtlas(t){return new Promise((e,i)=>{let s=new Uint8Array(t),n=new Blob([s],{type:"image/png"}),r=URL.createObjectURL(n),o=new Image;o.onload=()=>{URL.revokeObjectURL(r),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=o.width,this.atlasCanvas.height=o.height;let a=this.atlasCanvas.getContext("2d");if(!a){i(new Error("Failed to create 2D context for atlas"));return}a.drawImage(o,0,0),this.cachedAtlasWidth=o.width,this.cachedAtlasHeight=o.height,this.createAtlasTexture(),e()},o.onerror=()=>{URL.revokeObjectURL(r),i(new Error("Failed to load PNG image for ImageFont atlas"))},o.src=r})}precomputeImageFontUVs(t){let e=t*256;this.atlasUVs=new Float32Array(e*4);let i=this.cachedAtlasWidth,s=this.cachedAtlasHeight,n=.5/i,r=.5/s;for(let o=0;o<e;o++){let{col:a,row:h}=B(o,t),c=(a*this.charWidth+n)/i,d=(h*this.charHeight+r)/s,f=((a+1)*this.charWidth-n)/i,m=((h+1)*this.charHeight-r)/s,g=o*4;this.atlasUVs[g]=c,this.atlasUVs[g+1]=d,this.atlasUVs[g+2]=f,this.atlasUVs[g+3]=m}}generateAtlas(){if(!this.bitmapFont)return;let t=Array.from(this.bitmapFont.keys()).sort((a,h)=>a-h),e=t.length;this.atlasColumns=Math.ceil(Math.sqrt(e));let i=Math.ceil(e/this.atlasColumns),s=this.atlasColumns*this.charWidth,n=i*this.charHeight;this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=s,this.atlasCanvas.height=n;let r=this.atlasCanvas.getContext("2d");if(!r)throw new Error("Unable to create 2D context for atlas");r.clearRect(0,0,s,n),r.fillStyle="#ffffff";let o=0;for(let a of t){let h=this.bitmapFont.get(a);if(!h)continue;let c=o%this.atlasColumns,d=Math.floor(o/this.atlasColumns),f=c*this.charWidth,m=d*this.charHeight;for(let g=0;g<Math.min(h.length,this.charHeight);g++){let u=h[g];for(let p=0;p<this.charWidth;p++){let C=1<<7-p;u&C&&r.fillRect(f+p,m+g,1,1)}}o++}this.createAtlasTexture()}buildCharCodeMap(){if(!this.bitmapFont)return;this.charCodeToAtlasIndex.fill(65535);let t=Array.from(this.bitmapFont.keys()).sort((e,i)=>e-i);for(let e=0;e<t.length;e++)this.charCodeToAtlasIndex[t[e]]=e}precomputeAtlasUVs(){if(!this.bitmapFont)return;let t=this.bitmapFont.size;this.atlasUVs=new Float32Array(t*4),this.cachedAtlasWidth=this.atlasColumns*this.charWidth,this.cachedAtlasHeight=Math.ceil(t/this.atlasColumns)*this.charHeight;let e=this.cachedAtlasWidth,i=this.cachedAtlasHeight,s=.5/e,n=.5/i;for(let r=0;r<t;r++){let o=r%this.atlasColumns,a=Math.floor(r/this.atlasColumns),h=(o*this.charWidth+s)/e,c=(a*this.charHeight+n)/i,d=((o+1)*this.charWidth-s)/e,f=((a+1)*this.charHeight-n)/i,m=r*4;this.atlasUVs[m]=h,this.atlasUVs[m+1]=c,this.atlasUVs[m+2]=d,this.atlasUVs[m+3]=f}}createAtlasTexture(){if(this.atlasCanvas)try{let t=this.gl,e=t.createTexture();if(!e)throw new Error("Unable to create texture");t.bindTexture(t.TEXTURE_2D,e),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,this.atlasCanvas),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),this.atlasTexture=e}catch(t){throw console.error("[TerminalGL] \u274C Failed to create atlas texture:",t),t}}clear(){let t=this.gl;t&&t.clear(t.COLOR_BUFFER_BIT)}parseColor(t){if(t.startsWith("#")){let e=t.slice(1),i=0,s=0,n=0;return e.length===3?(i=parseInt(e[0]+e[0],16),s=parseInt(e[1]+e[1],16),n=parseInt(e[2]+e[2],16)):e.length===6&&(i=parseInt(e.slice(0,2),16),s=parseInt(e.slice(2,4),16),n=parseInt(e.slice(4,6),16)),[i/255,s/255,n/255,1]}if(t.startsWith("rgb")){let e=t.match(/rgba?\(([^)]+)\)/);if(e){let i=e[1].split(",").map(s=>parseFloat(s.trim()));return[i[0]/255,i[1]/255,i[2]/255,i[3]!==void 0?i[3]:1]}}return[1,1,1,1]}setupResizeObserver(){if(!(typeof ResizeObserver>"u"))try{this.resizeObserver=new ResizeObserver(()=>{try{this.updateCanvasSize()}catch(t){console.error("[TerminalGL] \u274C Error in resize callback:",t)}}),this.resizeObserver.observe(this.parentElement),this.updateCanvasSize()}catch(t){console.error("[TerminalGL] \u274C Failed to setup ResizeObserver:",t)}}updateCanvasSize(){let t=this.parentElement.clientWidth,e=this.parentElement.clientHeight;if(t===0||e===0)return;let i=this.cols*this.cellWidth,s=this.rows*this.cellHeight;if(i===0||s===0)return;let n=t/i,r=e/s,o=Math.min(n,r),a;switch(this.scalingMode){case y.ScalingMode.Integer:a=Math.max(1,Math.floor(o));break;case y.ScalingMode.Half:a=Math.max(1,Math.floor(o*2)/2);break;case y.ScalingMode.Quarter:a=Math.max(1,Math.floor(o*4)/4);break;case y.ScalingMode.Eighth:a=Math.max(1,Math.floor(o*8)/8);break;case y.ScalingMode.Responsive:a=1;break;case y.ScalingMode.None:default:a=Math.max(.1,o);break}if(this.canvas.style.transform=`scale(${a})`,this.ambientEffectEnabled&&this.ambientEffectCanvas){let h=a*this.ambientEffectScale;this.ambientEffectCanvas.style.transform=`scale(${h})`}this.currentScale=a,this.onResizeCallback&&this.onResizeCallback(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}updateAmbientEffect(){!this.ambientEffectCanvas||!this.ambientEffectCtx||this.ambientEffectCtx.drawImage(this.canvas,0,0)}setPalette(t){let e=0;for(let i=0;i<Math.min(t.length,256);i++){let s=t[i];e=(e<<5)-e+s.r,e=(e<<5)-e+s.g,e=(e<<5)-e+s.b,e=(e<<5)-e+s.a,e=e|0}if(e!==this.paletteHash){this.paletteHash=e;for(let i=0;i<t.length&&i<256;i++){let s=t[i],n=i*4;this.paletteFloat[n]=s.r/255,this.paletteFloat[n+1]=s.g/255,this.paletteFloat[n+2]=s.b/255,this.paletteFloat[n+3]=s.a/255}this.updatePaletteTexture()}}updatePaletteTexture(){try{let t=this.gl;this.paletteTexture||(this.paletteTexture=t.createTexture()),t.bindTexture(t.TEXTURE_2D,this.paletteTexture);let e=new Uint8Array(256*4);for(let i=0;i<256;i++){let s=i*4;e[s]=this.paletteFloat[s]*255,e[s+1]=this.paletteFloat[s+1]*255,e[s+2]=this.paletteFloat[s+2]*255,e[s+3]=this.paletteFloat[s+3]*255}t.texImage2D(t.TEXTURE_2D,0,t.RGBA,256,1,0,t.RGBA,t.UNSIGNED_BYTE,e),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.bindTexture(t.TEXTURE_2D,null)}catch(t){throw console.error("[TerminalGL] \u274C Failed to update palette texture:",t),t}}renderDisplayData(t){try{if(!this.isReady()){console.warn("[TerminalGL] \u26A0\uFE0F Not ready: font not loaded yet");return}(t.width!==this.cols||t.height!==this.rows)&&this.resize(t.width,t.height),t.passes&&t.passes.length>0?this.renderMultiPass(t,t.passes):this.renderDirect(t),this.ambientEffectEnabled&&this.ambientEffectCanvas&&this.ambientEffectCtx&&this.updateAmbientEffect()}catch(e){console.error("[TerminalGL] \u274C Error rendering display data:",e)}}renderMultiPass(t,e){for(let i=0;i<e.length;i++){let s=e[i],n={id:t.id,width:t.width,height:t.height,palette:t.palette,cells:s.cells};this.renderDirect(n,i===0)}}renderDirect(t,e=!0){let i=this.gl;if(!this.staticPositionsInitialized&&!this.useInstancing&&this.precomputeStaticPositions(),e){if(this.canvasBgColor!==null){let s=this.parseColor(this.canvasBgColor);i.clearColor(s[0],s[1],s[2],s[3])}else i.clearColor(0,0,0,0);i.clear(i.COLOR_BUFFER_BIT)}this.useInstancing?this.renderInstanced(t):this.renderDirectBuffers(t)}renderInstanced(t){let e=this.gl,i=this.instancedExtension;if(!this.instanceData||this.instanceData.length===0){console.warn("[TerminalGL] \u26A0\uFE0F Instance data not initialized, falling back to standard rendering"),this.renderDirectBuffers(t);return}let s=0,n=this.instanceData.length/8,r=t.width*t.height*2;if(r>n){console.error(`[TerminalGL] \u274C Instance buffer too small! Need ${r}, have ${n}. Display size: ${t.width}\xD7${t.height}, buffer was sized for smaller terminal.`),this.renderDirectBuffers(t);return}for(let a=0;a<t.height;a++)for(let h=0;h<t.width;h++){let c=t.cells[a*t.width+h],d=c.bgColorIndex,f=c.fgColorIndex,m=this.canvasBgColor!==null&&d===255,g=c.char===" "||f===255;if(!m){if(s>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${n}`);break}let u=s*8;this.instanceData[u]=h,this.instanceData[u+1]=a,this.instanceData[u+2]=0,this.instanceData[u+3]=0,this.instanceData[u+4]=0,this.instanceData[u+5]=0,this.instanceData[u+6]=d,this.instanceData[u+7]=0,s++}if(!g){let u=c.char.charCodeAt(0),p=this.charCodeToAtlasIndex[u];if(p!==65535){if(s>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${n}`);break}let C=p*4,x=s*8;this.instanceData[x]=h,this.instanceData[x+1]=a,this.instanceData[x+2]=this.atlasUVs[C],this.instanceData[x+3]=this.atlasUVs[C+1],this.instanceData[x+4]=this.atlasUVs[C+2],this.instanceData[x+5]=this.atlasUVs[C+3],this.instanceData[x+6]=0,this.instanceData[x+7]=f,s++}}}if(s===0){console.warn("[TerminalGL] \u26A0\uFE0F No instances to draw (all cells skipped)");return}e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.instanceData.subarray(0,s*8)),e.useProgram(this.program),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),i.vertexAttribDivisorANGLE(this.aPosition,0),e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer);let o=8*Float32Array.BYTES_PER_ELEMENT;e.enableVertexAttribArray(this.aInstanceOffset),e.vertexAttribPointer(this.aInstanceOffset,2,e.FLOAT,!1,o,0),i.vertexAttribDivisorANGLE(this.aInstanceOffset,1),e.enableVertexAttribArray(this.aInstanceUVs),e.vertexAttribPointer(this.aInstanceUVs,4,e.FLOAT,!1,o,2*Float32Array.BYTES_PER_ELEMENT),i.vertexAttribDivisorANGLE(this.aInstanceUVs,1),e.enableVertexAttribArray(this.aInstanceColors),e.vertexAttribPointer(this.aInstanceColors,2,e.FLOAT,!1,o,6*Float32Array.BYTES_PER_ELEMENT),i.vertexAttribDivisorANGLE(this.aInstanceColors,1),e.uniform2f(this.uResolution,this.canvas.width,this.canvas.height),e.uniform2f(this.uCellSize,this.cellWidth,this.cellHeight),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,this.atlasTexture),e.uniform1i(this.uTexture,0),e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,this.paletteTexture),e.uniform1i(this.uPalette,1),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),i.drawElementsInstancedANGLE(e.TRIANGLES,6,e.UNSIGNED_SHORT,0,s),i.vertexAttribDivisorANGLE(this.aPosition,0),i.vertexAttribDivisorANGLE(this.aInstanceOffset,0),i.vertexAttribDivisorANGLE(this.aInstanceUVs,0),i.vertexAttribDivisorANGLE(this.aInstanceColors,0)}renderDirectBuffers(t){let e=this.gl,i=t.width*t.height,s=i*2;if(s>this.maxCells){console.error(`[TerminalGL] \u274C Buffer overflow detected! Trying to render ${s} quads but buffer capacity is ${this.maxCells}. This should not happen - resize() should have reallocated.`);return}let n=0,r=0,o=t.cells,a=i;for(let g=0;g<a;g++){let u=o[g],p=u.bgColorIndex,x=this.canvasBgColor!==null&&p===255?255:p,E=0;for(let T=0;T<4;T++)this.renderTexCoords[n++]=E,this.renderTexCoords[n++]=E,this.renderColorIndices[r++]=x;let w=u.fgColorIndex,H=u.char;if(H===" "||w===255)for(let T=0;T<4;T++)this.renderTexCoords[n++]=0,this.renderTexCoords[n++]=0,this.renderColorIndices[r++]=255;else{let T=H.charCodeAt(0),Z=this.charCodeToAtlasIndex[T];if(Z!==65535){let I=Z*4,K=this.atlasUVs[I],J=this.atlasUVs[I+1],tt=this.atlasUVs[I+2],et=this.atlasUVs[I+3];this.renderTexCoords[n++]=K,this.renderTexCoords[n++]=J,this.renderColorIndices[r++]=w,this.renderTexCoords[n++]=tt,this.renderTexCoords[n++]=J,this.renderColorIndices[r++]=w,this.renderTexCoords[n++]=K,this.renderTexCoords[n++]=et,this.renderColorIndices[r++]=w,this.renderTexCoords[n++]=tt,this.renderTexCoords[n++]=et,this.renderColorIndices[r++]=w}else for(let I=0;I<4;I++)this.renderTexCoords[n++]=0,this.renderTexCoords[n++]=0,this.renderColorIndices[r++]=255}}(n!==a*2*4*2||r!==a*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:n,colorIdx:r,expected:a*2*4}),e.useProgram(this.program),this.vao&&this.vaoExtension?(this.vaoExtension.bindVertexArrayOES(this.vao),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,n)),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,r))):(e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,n)),e.enableVertexAttribArray(this.aTexCoord),e.vertexAttribPointer(this.aTexCoord,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,r)),e.enableVertexAttribArray(this.aColorIndex),e.vertexAttribPointer(this.aColorIndex,1,e.FLOAT,!1,0,0));let h=this.canvas.width,c=this.canvas.height;(this.cachedResolution[0]!==h||this.cachedResolution[1]!==c)&&(e.uniform2f(this.uResolution,h,c),this.cachedResolution[0]=h,this.cachedResolution[1]=c),this.cachedTextureUnit!==0&&(e.activeTexture(e.TEXTURE0),this.cachedTextureUnit=0),e.bindTexture(e.TEXTURE_2D,this.atlasTexture),this.cachedTextureUniform||(e.uniform1i(this.uTexture,0),this.cachedTextureUniform=!0),this.cachedPaletteUnit!==1&&(e.activeTexture(e.TEXTURE1),this.cachedPaletteUnit=1),e.bindTexture(e.TEXTURE_2D,this.paletteTexture),this.cachedPaletteUniform||(e.uniform1i(this.uPalette,1),this.cachedPaletteUniform=!0),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer);let f=t.width*t.height*2*6,m=this.useUint16Indices?e.UNSIGNED_SHORT:e.UNSIGNED_INT;e.drawElements(e.TRIANGLES,f,m,0)}resize(t,e){if(!Number.isInteger(t)||t<=0){console.error(`[TerminalGL] \u274C Invalid cols: ${t}. Must be positive integer.`);return}if(!Number.isInteger(e)||e<=0){console.error(`[TerminalGL] \u274C Invalid rows: ${e}. Must be positive integer.`);return}if(t===this.cols&&e===this.rows)return;let i=t*e,s=this.useInstancing?262144:this.useUint16Indices?8191:262144;if(i>s){let c=Math.floor(Math.sqrt(s));console.error(`[TerminalGL] \u274C Cannot resize to ${t}\xD7${e} (${i} cells). Device limit: ${s} cells (max ~${c}\xD7${c}). ${!this.useInstancing&&this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let n=L.checkCompatibility();i>n.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${t}\xD7${e} (${i} cells) exceeds recommended limit (${n.recommendedMaxCells} cells). Performance may degrade.`),this.cols=t,this.rows=e,this.staticPositionsInitialized=!1;let r=this.cols*this.rows*2,o=Math.ceil(r*1.5),a=r>this.maxCells,h=this.maxCells>o*4;if(console.warn(`[TerminalGL] \u{1F4D0} resize check: cols=${t}, rows=${e}, newMaxCells=${r}, this.maxCells=${this.maxCells}, needGrow=${a}, needShrink=${h}`),a||h){let c=this.maxCells;if(this.maxCells=o,console.warn(`[TerminalGL] \u{1F4D0} resize realloc: ${c} \u2192 ${this.maxCells} (needGrow=${a}, needShrink=${h})`),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.useInstancing&&this.instanceDataBuffer){this.instanceData=new Float32Array(this.maxCells*8);let u=this.gl;u.bindBuffer(u.ARRAY_BUFFER,this.instanceDataBuffer),u.bufferData(u.ARRAY_BUFFER,this.instanceData.byteLength,u.DYNAMIC_DRAW)}let d=this.gl;this.useInstancing||(d.bindBuffer(d.ARRAY_BUFFER,this.positionBuffer),d.bufferData(d.ARRAY_BUFFER,this.renderPositions.byteLength,d.DYNAMIC_DRAW)),d.bindBuffer(d.ARRAY_BUFFER,this.texCoordBuffer),d.bufferData(d.ARRAY_BUFFER,this.renderTexCoords.byteLength,d.DYNAMIC_DRAW),d.bindBuffer(d.ARRAY_BUFFER,this.colorIndexBuffer),d.bufferData(d.ARRAY_BUFFER,this.renderColorIndices.byteLength,d.DYNAMIC_DRAW),this.useInstancing||(d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,this.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,d.DYNAMIC_DRAW)),this.vaoExtension&&this.vao&&(this.vaoExtension.deleteVertexArrayOES(this.vao),this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),d.bindBuffer(d.ARRAY_BUFFER,this.positionBuffer),d.enableVertexAttribArray(this.aPosition),d.vertexAttribPointer(this.aPosition,2,d.FLOAT,!1,0,0),d.bindBuffer(d.ARRAY_BUFFER,this.texCoordBuffer),d.enableVertexAttribArray(this.aTexCoord),d.vertexAttribPointer(this.aTexCoord,2,d.FLOAT,!1,0,0),d.bindBuffer(d.ARRAY_BUFFER,this.colorIndexBuffer),d.enableVertexAttribArray(this.aColorIndex),d.vertexAttribPointer(this.aColorIndex,1,d.FLOAT,!1,0,0),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null)));let f=a?"\u{1F4C8} Growing":"\u{1F4C9} Shrinking",m=c*160/1048576,g=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${f} buffers: ${m.toFixed(2)}MB \u2192 ${g.toFixed(2)}MB (${c} \u2192 ${this.maxCells} quads)`)}this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.canvas.style.width=`${this.canvas.width}px`,this.canvas.style.height=`${this.canvas.height}px`,this.ambientEffectEnabled&&this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.width=`${this.canvas.width}px`,this.ambientEffectCanvas.style.height=`${this.canvas.height}px`),this.showGrid&&this.gridOverlay&&this.updateGridOverlay(),this.updateCanvasSize()}getCanvas(){return this.canvas}getGridSize(){return{cols:this.cols,rows:this.rows}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getBaseDimensions(){return{width:this.cols*this.cellWidth,height:this.rows*this.cellHeight}}setOnResizeCallback(t){this.onResizeCallback=t}clearOnResizeCallback(){this.onResizeCallback=void 0}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}setScalingMode(t){this.scalingMode!==t&&(this.scalingMode=t,this.updateCanvasSize())}getScalingMode(){return this.scalingMode}setCellSize(t,e){let i=Math.max(1,Math.min(255,Math.round(t))),s=Math.max(1,Math.min(255,Math.round(e)));this.cellWidth===i&&this.cellHeight===s||(this.cellWidth=i,this.cellHeight=s,this.charWidth=i,this.charHeight=s,this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.fontLoaded&&this.generateAtlas(),this.useInstancing&&this.initInstancedBuffers(),this.updateCanvasSize())}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getMaxCells(){return this.useInstancing?262144:this.useUint16Indices?8191:262144}setGrid(t){t.enabled?(this.gridOverlay?this.gridOverlay.setStyle({strokeColor:t.color,lineWidth:t.lineWidth}):this.gridOverlay=new A(this.containerDiv,{strokeColor:t.color??"rgba(144, 24, 24, 1)",lineWidth:t.lineWidth??1,zIndex:10}),this.showGrid=!0,this.gridOverlay.setVisible(!0),this.updateGridOverlay()):(this.showGrid=!1,this.gridOverlay&&this.gridOverlay.setVisible(!1))}isGridEnabled(){return this.showGrid}setAmbientEffect(t){typeof t=="boolean"?this.ambientEffectEnabled=t:(this.ambientEffectEnabled=!0,t.blur!==void 0&&(this.ambientEffectBlur=t.blur),t.scale!==void 0&&(this.ambientEffectScale=t.scale)),this.ambientEffectEnabled&&!this.ambientEffectCanvas&&this.createAmbientEffectCanvas(),this.ambientEffectCanvas&&(this.ambientEffectEnabled?(this.ambientEffectCanvas.style.display="block",this.ambientEffectCanvas.style.filter=`blur(${this.ambientEffectBlur}px)`,this.ambientEffectCanvas.style.transform=`scale(${this.ambientEffectScale})`,this.updateAmbientEffect()):this.ambientEffectCanvas.style.display="none")}createAmbientEffectCanvas(){this.ambientEffectCanvas||(this.ambientEffectCanvas=document.createElement("canvas"),this.ambientEffectCanvas.className="terminalgl-ambient-effect-canvas",this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.cssText=`
120
120
  display: block !important;
121
121
  position: absolute !important;
122
122
  width: ${this.canvas.width}px !important;
@@ -127,7 +127,7 @@
127
127
  transform: scale(${this.ambientEffectScale}) !important;
128
128
  pointer-events: none !important;
129
129
  z-index: 0 !important;
130
- `,this.ambientEffectCtx=this.ambientEffectCanvas.getContext("2d",{alpha:!0}),this.containerDiv.insertBefore(this.ambientEffectCanvas,this.canvas),console.warn("[TerminalGL] \u{1F308} ambient effect canvas created dynamically"))}isAmbientEffectEnabled(){return this.ambientEffectEnabled}getAmbientEffectConfig(){return{enabled:this.ambientEffectEnabled,blur:this.ambientEffectBlur,scale:this.ambientEffectScale}}getCols(){return this.cols}getRows(){return this.rows}isReady(){return!!(this.fontLoaded&&this.atlasTexture&&this.program)}destroy(){this.dispose()}dispose(){this.resizeObserver&&this.resizeObserver.disconnect();let t=this.gl;this.program&&t.deleteProgram(this.program),this.positionBuffer&&t.deleteBuffer(this.positionBuffer),this.texCoordBuffer&&t.deleteBuffer(this.texCoordBuffer),this.colorIndexBuffer&&t.deleteBuffer(this.colorIndexBuffer),this.indexBuffer&&t.deleteBuffer(this.indexBuffer),this.instanceDataBuffer&&t.deleteBuffer(this.instanceDataBuffer),this.atlasTexture&&t.deleteTexture(this.atlasTexture),this.paletteTexture&&t.deleteTexture(this.paletteTexture),this.vao&&this.vaoExtension&&this.vaoExtension.deleteVertexArrayOES(this.vao);let e=t.getExtension("WEBGL_lose_context");e&&e.loseContext(),this.atlasCanvas&&(this.atlasCanvas.width=0,this.atlasCanvas.height=0,this.atlasCanvas=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv),this.canvas.width=0,this.canvas.height=0,this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=0,this.ambientEffectCanvas.height=0,this.ambientEffectCanvas=null),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.renderPositions=new Float32Array(0),this.renderTexCoords=new Float32Array(0),this.renderColorIndices=new Float32Array(0),this.renderIndices=new Uint32Array(0),this.paletteFloat=new Float32Array(0),this.atlasUVs=new Float32Array(0),this.instanceData=new Float32Array(0),this.templateQuadPositions=new Float32Array(0),this.templateQuadIndices=new Uint16Array(0)}};v(L,"TerminalGL");var _=L;var N=class N{constructor(t,e,i,s,a){l(this,"atlases");l(this,"charMap");l(this,"baseCharWidth");l(this,"baseCharHeight");l(this,"baseCellWidth");l(this,"baseCellHeight");l(this,"atlasColumns",16);l(this,"font");l(this,"SCALES",[1,2,4,8]);l(this,"colorCache",new Map);l(this,"MAX_CACHE_SIZE",512);this.font=t,this.baseCharWidth=e,this.baseCharHeight=i,this.baseCellWidth=s??e,this.baseCellHeight=a??i,this.charMap=new Map,this.atlases=new Map,this.generateAtlases()}generateAtlases(){this.atlasColumns=16;let t=0;for(let[e,i]of this.font){let s=t%this.atlasColumns,a=Math.floor(t/this.atlasColumns);this.charMap.set(e,{x:s*this.baseCharWidth,y:a*this.baseCharHeight});for(let r of this.SCALES){let o=this.getOrCreateAtlas(r),n=s*o.charWidth,h=a*o.charHeight;this.renderBitmapToAtlas(o,i,n,h)}t++}}getOrCreateAtlas(t){let e=this.atlases.get(t);if(!e){let i=this.baseCharWidth*t,s=this.baseCharHeight*t,r=Math.ceil(256/this.atlasColumns),o=document.createElement("canvas");o.width=this.atlasColumns*i,o.height=r*s;let n=o.getContext("2d",{alpha:!0,willReadFrequently:!1});if(!n)throw new Error(`Impossible de cr\xE9er le contexte 2D pour l'atlas ${t}x`);n.imageSmoothingEnabled=!1,e={canvas:o,ctx:n,scale:t,charWidth:i,charHeight:s},this.atlases.set(t,e)}return e}renderBitmapToAtlas(t,e,i,s){let a=t.scale,r=t.ctx;r.fillStyle="#ffffff";for(let o=0;o<Math.min(e.length,this.baseCharHeight);o++){let n=e[o];for(let h=0;h<this.baseCharWidth;h++){let c=1<<7-h;n&c&&r.fillRect(i+h*a,s+o*a,a,a)}}}drawChar(t,e,i,s,a,r,o){let n=this.charMap.get(e);if(!n)return;let h=`${e}:${o}`,c=this.colorCache.get(h);if(c)c.lastUsed=performance.now();else{let C=this.createColoredGlyph(e,o,n);if(!C)return;c={canvas:C,lastUsed:performance.now()},this.colorCache.set(h,c),this.colorCache.size>this.MAX_CACHE_SIZE&&this.evictLRU()}let d=a/this.baseCellWidth,f=r/this.baseCellHeight,m=(this.baseCellWidth-this.baseCharWidth)/2*d,g=(this.baseCellHeight-this.baseCharHeight)/2*f,u=this.baseCharWidth*d,p=this.baseCharHeight*f;t.drawImage(c.canvas,i+m,s+g,u,p)}createColoredGlyph(t,e,i){let s=this.atlases.get(1);if(!s)return null;let a=s.ctx.getImageData(i.x,i.y,this.baseCharWidth,this.baseCharHeight),r=a.data,o=this.hexToRgb(e);for(let c=0;c<r.length;c+=4)r[c+3]>0&&(r[c]=o.r,r[c+1]=o.g,r[c+2]=o.b);let n=document.createElement("canvas");n.width=this.baseCharWidth,n.height=this.baseCharHeight;let h=n.getContext("2d",{alpha:!0});return h?(h.imageSmoothingEnabled=!1,h.putImageData(a,0,0),n):null}hexToRgb(t){if(t.startsWith("#")){let a=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(a,(o,n,h,c)=>n+n+h+h+c+c);let r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return r?{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16)}:{r:255,g:255,b:255}}let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10)};let s={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255]}[t.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2]}:{r:255,g:255,b:255}}evictLRU(){let t=null,e=1/0;for(let[i,s]of this.colorCache)s.lastUsed<e&&(e=s.lastUsed,t=i);if(t){let i=this.colorCache.get(t);i&&(i.canvas.width=0,i.canvas.height=0),this.colorCache.delete(t)}}getAtlasCanvas(t=1){return this.atlases.get(t)?.canvas}getAllAtlases(){return this.atlases}getCharDimensions(){return{width:this.baseCharWidth,height:this.baseCharHeight}}getCharCount(){return this.charMap.size}hasChar(t){return this.charMap.has(t)}getAtlasDimensions(t=1){let e=this.atlases.get(t);if(e)return{width:e.canvas.width,height:e.canvas.height}}toDataURL(t=1,e="image/png"){return this.atlases.get(t)?.canvas.toDataURL(e)}getCacheStats(){return{size:this.colorCache.size,maxSize:this.MAX_CACHE_SIZE}}clearCache(){for(let t of this.colorCache.values())t.canvas.width=0,t.canvas.height=0;this.colorCache.clear()}destroy(){this.charMap.clear();for(let t of this.atlases.values())t.canvas.width=0,t.canvas.height=0;this.atlases.clear(),this.clearCache()}};v(N,"BitmapFontAtlas");var D=N;var Y=class Y{constructor(t){l(this,"atlasCanvas",null);l(this,"atlasCtx",null);l(this,"atlasImage",null);l(this,"glyphWidth");l(this,"glyphHeight");l(this,"cellWidth");l(this,"cellHeight");l(this,"atlasBlocks");l(this,"atlasColumns");l(this,"maxCharCode");l(this,"isLoaded",!1);l(this,"colorCache",new Map);l(this,"MAX_CACHE_SIZE",1024);this.glyphWidth=t.glyphWidth,this.glyphHeight=t.glyphHeight,this.cellWidth=t.cellWidth??t.glyphWidth,this.cellHeight=t.cellHeight??t.glyphHeight,this.atlasBlocks=t.atlasBlocks,this.atlasColumns=M(t.atlasBlocks),this.maxCharCode=S(t.atlasBlocks)}async loadFromPNG(t){return new Promise((e,i)=>{let s=new Uint8Array(t),a=new Blob([s],{type:"image/png"}),r=URL.createObjectURL(a),o=new Image;o.onload=()=>{URL.revokeObjectURL(r);let n=this.atlasColumns*this.glyphWidth,h=this.atlasColumns*this.glyphHeight;if((o.width!==n||o.height!==h)&&console.warn(`ImageFontAtlas: Image size ${o.width}\xD7${o.height} doesn't match expected ${n}\xD7${h} for ${this.atlasBlocks} block(s) with ${this.glyphWidth}\xD7${this.glyphHeight} glyphs`),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=o.width,this.atlasCanvas.height=o.height,this.atlasCtx=this.atlasCanvas.getContext("2d",{alpha:!0,willReadFrequently:!0}),!this.atlasCtx){i(new Error("Failed to create 2D context for atlas"));return}this.atlasCtx.imageSmoothingEnabled=!1,this.atlasCtx.drawImage(o,0,0),this.atlasImage=o,this.isLoaded=!0,e()},o.onerror=()=>{URL.revokeObjectURL(r),i(new Error("Failed to load PNG image for atlas"))},o.src=r})}isReady(){return this.isLoaded}getGlyphPosition(t){if(t<0||t>this.maxCharCode)return null;let{col:e,row:i}=B(t,this.atlasBlocks);return{x:e*this.glyphWidth,y:i*this.glyphHeight}}getCharUV(t){if(t<0||t>this.maxCharCode)return null;let{col:e,row:i}=B(t,this.atlasBlocks),s=e/this.atlasColumns,a=i/this.atlasColumns,r=(e+1)/this.atlasColumns,o=(i+1)/this.atlasColumns;return{u1:s,v1:a,u2:r,v2:o}}drawChar(t,e,i,s,a,r,o){if(!this.isLoaded||!this.atlasCanvas)return;let n=this.getGlyphPosition(e);if(!n)return;let h=`${e}:${o}`,c=this.colorCache.get(h);if(c)c.lastUsed=performance.now();else{let f=this.createColoredGlyph(e,o,n);if(!f)return;c={canvas:f,lastUsed:performance.now()},this.colorCache.set(h,c),this.colorCache.size>this.MAX_CACHE_SIZE&&this.evictLRU()}if(t.imageSmoothingEnabled=!1,a===this.cellWidth&&r===this.cellHeight){let f=Math.floor((this.cellWidth-this.glyphWidth)/2),m=Math.floor((this.cellHeight-this.glyphHeight)/2);t.drawImage(c.canvas,Math.floor(i)+f,Math.floor(s)+m)}else{let f=a/this.cellWidth,m=r/this.cellHeight,g=Math.floor((this.cellWidth-this.glyphWidth)/2*f),u=Math.floor((this.cellHeight-this.glyphHeight)/2*m),p=Math.ceil(this.glyphWidth*f),C=Math.ceil(this.glyphHeight*m);t.drawImage(c.canvas,Math.floor(i)+g,Math.floor(s)+u,p,C)}}createColoredGlyph(t,e,i){if(!this.atlasCtx)return null;let s=this.atlasCtx.getImageData(i.x,i.y,this.glyphWidth,this.glyphHeight),a=s.data,r=this.parseColor(e);for(let h=0;h<a.length;h+=4)a[h+3]>0&&(a[h]=r.r,a[h+1]=r.g,a[h+2]=r.b);let o=document.createElement("canvas");o.width=this.glyphWidth,o.height=this.glyphHeight;let n=o.getContext("2d",{alpha:!0});return n?(n.putImageData(s,0,0),o):null}parseColor(t){if(t.startsWith("#")){let i=t.slice(1);return i.length===3&&(i=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]),{r:parseInt(i.slice(0,2),16),g:parseInt(i.slice(2,4),16),b:parseInt(i.slice(4,6),16)}}let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(t);return e?{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10)}:{r:255,g:255,b:255}}evictLRU(){let t=null,e=1/0;for(let[i,s]of this.colorCache)s.lastUsed<e&&(e=s.lastUsed,t=i);if(t){let i=this.colorCache.get(t);i&&(i.canvas.width=0,i.canvas.height=0),this.colorCache.delete(t)}}getAtlasCanvas(){return this.atlasCanvas}getAtlasImage(){return this.atlasImage}getConfig(){return{glyphWidth:this.glyphWidth,glyphHeight:this.glyphHeight,cellWidth:this.cellWidth,cellHeight:this.cellHeight,atlasBlocks:this.atlasBlocks}}getGlyphDimensions(){return{width:this.glyphWidth,height:this.glyphHeight}}getCellDimensions(){return{width:this.cellWidth,height:this.cellHeight}}getAtlasDimensions(){return{width:this.atlasColumns*this.glyphWidth,height:this.atlasColumns*this.glyphHeight}}getAtlasColumns(){return this.atlasColumns}getMaxCharCode(){return this.maxCharCode}isValidCharCode(t){return t>=0&&t<=this.maxCharCode}clearCache(){for(let t of this.colorCache.values())t.canvas.width=0,t.canvas.height=0;this.colorCache.clear()}getCacheStats(){return{size:this.colorCache.size,maxSize:this.MAX_CACHE_SIZE}}destroy(){this.clearCache(),this.atlasCanvas&&(this.atlasCanvas.width=0,this.atlasCanvas.height=0,this.atlasCanvas=null),this.atlasCtx=null,this.atlasImage=null,this.isLoaded=!1}};v(Y,"ImageFontAtlas");var F=Y;var R=require("@utsp/types");var V=class V{constructor(t,e={}){l(this,"containerDiv");l(this,"canvas");l(this,"ctx");l(this,"parentElement");l(this,"cells");l(this,"cols",0);l(this,"rows",0);l(this,"fontSize");l(this,"fontFamily");l(this,"defaultFgColor");l(this,"defaultBgColor");l(this,"canvasBgColor");l(this,"cellWidth");l(this,"cellHeight");l(this,"offsetX",0);l(this,"offsetY",0);l(this,"fontType","web");l(this,"bitmapFont");l(this,"bitmapAtlas");l(this,"imageAtlas");l(this,"bitmapCharWidth",8);l(this,"bitmapCharHeight",8);l(this,"showDebugGrid");l(this,"debugGridColor");l(this,"gridOverlay");l(this,"fixedGridMode");l(this,"fixedCols");l(this,"fixedRows");l(this,"cellAspectRatio");l(this,"resizeObserver");l(this,"imageDataBuffer");l(this,"useImageDataRendering",!1);l(this,"paletteCache");l(this,"scalingMode",R.ScalingMode.None);l(this,"currentScale",1);l(this,"customCellSize",!1);if(!t)throw new Error("Render: L'\xE9l\xE9ment parent est requis");this.parentElement=t,this.fixedGridMode=!!(e.fixedCols&&e.fixedRows),this.fixedCols=e.fixedCols,this.fixedRows=e.fixedRows,this.cellAspectRatio=e.cellAspectRatio??1,this.cellWidth=e.cellWidth??8,this.cellHeight=e.cellHeight??8,this.fontSize=e.fontSize??12,this.fontFamily=e.fontFamily??"monospace",this.defaultFgColor=e.defaultFgColor??"#ffffff",this.defaultBgColor=e.defaultBgColor??"#000000",this.canvasBgColor=e.canvasBgColor!==void 0?e.canvasBgColor:null,this.showDebugGrid=e.showDebugGrid??!1,this.debugGridColor=e.debugGridColor??"rgba(144, 24, 24, 1)",this.scalingMode=e.scalingMode??R.ScalingMode.None,window.getComputedStyle(this.parentElement).position==="static"&&(this.parentElement.style.position="relative"),this.containerDiv=document.createElement("div"),this.containerDiv.className="terminal2d-container",this.containerDiv.style.cssText=`
130
+ `,this.ambientEffectCtx=this.ambientEffectCanvas.getContext("2d",{alpha:!0}),this.containerDiv.insertBefore(this.ambientEffectCanvas,this.canvas),console.warn("[TerminalGL] \u{1F308} ambient effect canvas created dynamically"))}isAmbientEffectEnabled(){return this.ambientEffectEnabled}getAmbientEffectConfig(){return{enabled:this.ambientEffectEnabled,blur:this.ambientEffectBlur,scale:this.ambientEffectScale}}getCols(){return this.cols}getRows(){return this.rows}isReady(){return!!(this.fontLoaded&&this.atlasTexture&&this.program)}destroy(){this.dispose()}dispose(){this.resizeObserver&&this.resizeObserver.disconnect();let t=this.gl;this.program&&t.deleteProgram(this.program),this.positionBuffer&&t.deleteBuffer(this.positionBuffer),this.texCoordBuffer&&t.deleteBuffer(this.texCoordBuffer),this.colorIndexBuffer&&t.deleteBuffer(this.colorIndexBuffer),this.indexBuffer&&t.deleteBuffer(this.indexBuffer),this.instanceDataBuffer&&t.deleteBuffer(this.instanceDataBuffer),this.atlasTexture&&t.deleteTexture(this.atlasTexture),this.paletteTexture&&t.deleteTexture(this.paletteTexture),this.vao&&this.vaoExtension&&this.vaoExtension.deleteVertexArrayOES(this.vao);let e=t.getExtension("WEBGL_lose_context");e&&e.loseContext(),this.atlasCanvas&&(this.atlasCanvas.width=0,this.atlasCanvas.height=0,this.atlasCanvas=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv),this.canvas.width=0,this.canvas.height=0,this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=0,this.ambientEffectCanvas.height=0,this.ambientEffectCanvas=null),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.renderPositions=new Float32Array(0),this.renderTexCoords=new Float32Array(0),this.renderColorIndices=new Float32Array(0),this.renderIndices=new Uint32Array(0),this.paletteFloat=new Float32Array(0),this.atlasUVs=new Float32Array(0),this.instanceData=new Float32Array(0),this.templateQuadPositions=new Float32Array(0),this.templateQuadIndices=new Uint16Array(0)}};v(L,"TerminalGL");var P=L;var N=class N{constructor(t,e,i,s,n){l(this,"atlases");l(this,"charMap");l(this,"baseCharWidth");l(this,"baseCharHeight");l(this,"baseCellWidth");l(this,"baseCellHeight");l(this,"atlasColumns",16);l(this,"font");l(this,"SCALES",[1,2,4,8]);l(this,"colorCache",new Map);l(this,"MAX_CACHE_SIZE",512);this.font=t,this.baseCharWidth=e,this.baseCharHeight=i,this.baseCellWidth=s??e,this.baseCellHeight=n??i,this.charMap=new Map,this.atlases=new Map,this.generateAtlases()}generateAtlases(){this.atlasColumns=16;let t=0;for(let[e,i]of this.font){let s=t%this.atlasColumns,n=Math.floor(t/this.atlasColumns);this.charMap.set(e,{x:s*this.baseCharWidth,y:n*this.baseCharHeight});for(let r of this.SCALES){let o=this.getOrCreateAtlas(r),a=s*o.charWidth,h=n*o.charHeight;this.renderBitmapToAtlas(o,i,a,h)}t++}}getOrCreateAtlas(t){let e=this.atlases.get(t);if(!e){let i=this.baseCharWidth*t,s=this.baseCharHeight*t,r=Math.ceil(256/this.atlasColumns),o=document.createElement("canvas");o.width=this.atlasColumns*i,o.height=r*s;let a=o.getContext("2d",{alpha:!0,willReadFrequently:!1});if(!a)throw new Error(`Impossible de cr\xE9er le contexte 2D pour l'atlas ${t}x`);a.imageSmoothingEnabled=!1,e={canvas:o,ctx:a,scale:t,charWidth:i,charHeight:s},this.atlases.set(t,e)}return e}renderBitmapToAtlas(t,e,i,s){let n=t.scale,r=t.ctx;r.fillStyle="#ffffff";for(let o=0;o<Math.min(e.length,this.baseCharHeight);o++){let a=e[o];for(let h=0;h<this.baseCharWidth;h++){let c=1<<7-h;a&c&&r.fillRect(i+h*n,s+o*n,n,n)}}}drawChar(t,e,i,s,n,r,o){let a=this.charMap.get(e);if(!a)return;let h=`${e}:${o}`,c=this.colorCache.get(h);if(c)c.lastUsed=performance.now();else{let C=this.createColoredGlyph(e,o,a);if(!C)return;c={canvas:C,lastUsed:performance.now()},this.colorCache.set(h,c),this.colorCache.size>this.MAX_CACHE_SIZE&&this.evictLRU()}let d=n/this.baseCellWidth,f=r/this.baseCellHeight,m=(this.baseCellWidth-this.baseCharWidth)/2*d,g=(this.baseCellHeight-this.baseCharHeight)/2*f,u=this.baseCharWidth*d,p=this.baseCharHeight*f;t.drawImage(c.canvas,i+m,s+g,u,p)}createColoredGlyph(t,e,i){let s=this.atlases.get(1);if(!s)return null;let n=s.ctx.getImageData(i.x,i.y,this.baseCharWidth,this.baseCharHeight),r=n.data,o=this.hexToRgb(e);for(let c=0;c<r.length;c+=4)r[c+3]>0&&(r[c]=o.r,r[c+1]=o.g,r[c+2]=o.b);let a=document.createElement("canvas");a.width=this.baseCharWidth,a.height=this.baseCharHeight;let h=a.getContext("2d",{alpha:!0});return h?(h.imageSmoothingEnabled=!1,h.putImageData(n,0,0),a):null}hexToRgb(t){if(t.startsWith("#")){let n=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(n,(o,a,h,c)=>a+a+h+h+c+c);let r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return r?{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16)}:{r:255,g:255,b:255}}let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10)};let s={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255]}[t.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2]}:{r:255,g:255,b:255}}evictLRU(){let t=null,e=1/0;for(let[i,s]of this.colorCache)s.lastUsed<e&&(e=s.lastUsed,t=i);if(t){let i=this.colorCache.get(t);i&&(i.canvas.width=0,i.canvas.height=0),this.colorCache.delete(t)}}getAtlasCanvas(t=1){return this.atlases.get(t)?.canvas}getAllAtlases(){return this.atlases}getCharDimensions(){return{width:this.baseCharWidth,height:this.baseCharHeight}}getCharCount(){return this.charMap.size}hasChar(t){return this.charMap.has(t)}getAtlasDimensions(t=1){let e=this.atlases.get(t);if(e)return{width:e.canvas.width,height:e.canvas.height}}toDataURL(t=1,e="image/png"){return this.atlases.get(t)?.canvas.toDataURL(e)}getCacheStats(){return{size:this.colorCache.size,maxSize:this.MAX_CACHE_SIZE}}clearCache(){for(let t of this.colorCache.values())t.canvas.width=0,t.canvas.height=0;this.colorCache.clear()}destroy(){this.charMap.clear();for(let t of this.atlases.values())t.canvas.width=0,t.canvas.height=0;this.atlases.clear(),this.clearCache()}};v(N,"BitmapFontAtlas");var D=N;var Y=class Y{constructor(t){l(this,"atlasCanvas",null);l(this,"atlasCtx",null);l(this,"atlasImage",null);l(this,"glyphWidth");l(this,"glyphHeight");l(this,"cellWidth");l(this,"cellHeight");l(this,"atlasBlocks");l(this,"atlasColumns");l(this,"maxCharCode");l(this,"isLoaded",!1);l(this,"colorCache",new Map);l(this,"MAX_CACHE_SIZE",1024);this.glyphWidth=t.glyphWidth,this.glyphHeight=t.glyphHeight,this.cellWidth=t.cellWidth??t.glyphWidth,this.cellHeight=t.cellHeight??t.glyphHeight,this.atlasBlocks=t.atlasBlocks,this.atlasColumns=M(t.atlasBlocks),this.maxCharCode=S(t.atlasBlocks)}async loadFromPNG(t){return new Promise((e,i)=>{let s=new Uint8Array(t),n=new Blob([s],{type:"image/png"}),r=URL.createObjectURL(n),o=new Image;o.onload=()=>{URL.revokeObjectURL(r);let a=this.atlasColumns*this.glyphWidth,h=this.atlasColumns*this.glyphHeight;if((o.width!==a||o.height!==h)&&console.warn(`ImageFontAtlas: Image size ${o.width}\xD7${o.height} doesn't match expected ${a}\xD7${h} for ${this.atlasBlocks} block(s) with ${this.glyphWidth}\xD7${this.glyphHeight} glyphs`),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=o.width,this.atlasCanvas.height=o.height,this.atlasCtx=this.atlasCanvas.getContext("2d",{alpha:!0,willReadFrequently:!0}),!this.atlasCtx){i(new Error("Failed to create 2D context for atlas"));return}this.atlasCtx.imageSmoothingEnabled=!1,this.atlasCtx.drawImage(o,0,0),this.atlasImage=o,this.isLoaded=!0,e()},o.onerror=()=>{URL.revokeObjectURL(r),i(new Error("Failed to load PNG image for atlas"))},o.src=r})}isReady(){return this.isLoaded}getGlyphPosition(t){if(t<0||t>this.maxCharCode)return null;let{col:e,row:i}=B(t,this.atlasBlocks);return{x:e*this.glyphWidth,y:i*this.glyphHeight}}getCharUV(t){if(t<0||t>this.maxCharCode)return null;let{col:e,row:i}=B(t,this.atlasBlocks),s=e/this.atlasColumns,n=i/this.atlasColumns,r=(e+1)/this.atlasColumns,o=(i+1)/this.atlasColumns;return{u1:s,v1:n,u2:r,v2:o}}drawChar(t,e,i,s,n,r,o){if(!this.isLoaded||!this.atlasCanvas)return;let a=this.getGlyphPosition(e);if(!a)return;let h=`${e}:${o}`,c=this.colorCache.get(h);if(c)c.lastUsed=performance.now();else{let f=this.createColoredGlyph(e,o,a);if(!f)return;c={canvas:f,lastUsed:performance.now()},this.colorCache.set(h,c),this.colorCache.size>this.MAX_CACHE_SIZE&&this.evictLRU()}if(t.imageSmoothingEnabled=!1,n===this.cellWidth&&r===this.cellHeight){let f=Math.floor((this.cellWidth-this.glyphWidth)/2),m=Math.floor((this.cellHeight-this.glyphHeight)/2);t.drawImage(c.canvas,Math.floor(i)+f,Math.floor(s)+m)}else{let f=n/this.cellWidth,m=r/this.cellHeight,g=Math.floor((this.cellWidth-this.glyphWidth)/2*f),u=Math.floor((this.cellHeight-this.glyphHeight)/2*m),p=Math.ceil(this.glyphWidth*f),C=Math.ceil(this.glyphHeight*m);t.drawImage(c.canvas,Math.floor(i)+g,Math.floor(s)+u,p,C)}}createColoredGlyph(t,e,i){if(!this.atlasCtx)return null;let s=this.atlasCtx.getImageData(i.x,i.y,this.glyphWidth,this.glyphHeight),n=s.data,r=this.parseColor(e);for(let h=0;h<n.length;h+=4)n[h+3]>0&&(n[h]=r.r,n[h+1]=r.g,n[h+2]=r.b);let o=document.createElement("canvas");o.width=this.glyphWidth,o.height=this.glyphHeight;let a=o.getContext("2d",{alpha:!0});return a?(a.putImageData(s,0,0),o):null}parseColor(t){if(t.startsWith("#")){let i=t.slice(1);return i.length===3&&(i=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]),{r:parseInt(i.slice(0,2),16),g:parseInt(i.slice(2,4),16),b:parseInt(i.slice(4,6),16)}}let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(t);return e?{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10)}:{r:255,g:255,b:255}}evictLRU(){let t=null,e=1/0;for(let[i,s]of this.colorCache)s.lastUsed<e&&(e=s.lastUsed,t=i);if(t){let i=this.colorCache.get(t);i&&(i.canvas.width=0,i.canvas.height=0),this.colorCache.delete(t)}}getAtlasCanvas(){return this.atlasCanvas}getAtlasImage(){return this.atlasImage}getConfig(){return{glyphWidth:this.glyphWidth,glyphHeight:this.glyphHeight,cellWidth:this.cellWidth,cellHeight:this.cellHeight,atlasBlocks:this.atlasBlocks}}getGlyphDimensions(){return{width:this.glyphWidth,height:this.glyphHeight}}getCellDimensions(){return{width:this.cellWidth,height:this.cellHeight}}getAtlasDimensions(){return{width:this.atlasColumns*this.glyphWidth,height:this.atlasColumns*this.glyphHeight}}getAtlasColumns(){return this.atlasColumns}getMaxCharCode(){return this.maxCharCode}isValidCharCode(t){return t>=0&&t<=this.maxCharCode}clearCache(){for(let t of this.colorCache.values())t.canvas.width=0,t.canvas.height=0;this.colorCache.clear()}getCacheStats(){return{size:this.colorCache.size,maxSize:this.MAX_CACHE_SIZE}}destroy(){this.clearCache(),this.atlasCanvas&&(this.atlasCanvas.width=0,this.atlasCanvas.height=0,this.atlasCanvas=null),this.atlasCtx=null,this.atlasImage=null,this.isLoaded=!1}};v(Y,"ImageFontAtlas");var F=Y;var R=require("@utsp/types");var V=class V{constructor(t,e={}){l(this,"containerDiv");l(this,"canvas");l(this,"ctx");l(this,"parentElement");l(this,"cells");l(this,"cols",0);l(this,"rows",0);l(this,"fontSize");l(this,"fontFamily");l(this,"defaultFgColor");l(this,"defaultBgColor");l(this,"canvasBgColor");l(this,"cellWidth");l(this,"cellHeight");l(this,"offsetX",0);l(this,"offsetY",0);l(this,"fontType","web");l(this,"bitmapFont");l(this,"bitmapAtlas");l(this,"imageAtlas");l(this,"bitmapCharWidth",8);l(this,"bitmapCharHeight",8);l(this,"showDebugGrid");l(this,"debugGridColor");l(this,"gridOverlay");l(this,"fixedGridMode");l(this,"fixedCols");l(this,"fixedRows");l(this,"cellAspectRatio");l(this,"resizeObserver");l(this,"imageDataBuffer");l(this,"useImageDataRendering",!1);l(this,"paletteCache");l(this,"scalingMode",R.ScalingMode.None);l(this,"currentScale",1);l(this,"customCellSize",!1);if(!t)throw new Error("Render: L'\xE9l\xE9ment parent est requis");this.parentElement=t,this.fixedGridMode=!!(e.fixedCols&&e.fixedRows),this.fixedCols=e.fixedCols,this.fixedRows=e.fixedRows,this.cellAspectRatio=e.cellAspectRatio??1,this.cellWidth=e.cellWidth??8,this.cellHeight=e.cellHeight??8,this.fontSize=e.fontSize??12,this.fontFamily=e.fontFamily??"monospace",this.defaultFgColor=e.defaultFgColor??"#ffffff",this.defaultBgColor=e.defaultBgColor??"#000000",this.canvasBgColor=e.canvasBgColor!==void 0?e.canvasBgColor:null,this.showDebugGrid=e.showDebugGrid??!1,this.debugGridColor=e.debugGridColor??"rgba(144, 24, 24, 1)",this.scalingMode=e.scalingMode??R.ScalingMode.None,window.getComputedStyle(this.parentElement).position==="static"&&(this.parentElement.style.position="relative"),this.containerDiv=document.createElement("div"),this.containerDiv.className="terminal2d-container",this.containerDiv.style.cssText=`
131
131
  position: absolute !important;
132
132
  top: 0 !important;
133
133
  left: 0 !important;
@@ -142,7 +142,7 @@
142
142
  align-items: center !important;
143
143
  isolation: isolate !important;
144
144
  pointer-events: none !important;
145
- `,this.canvas=document.createElement("canvas"),this.canvas.className="terminal2d-canvas",e.className&&(this.canvas.className+=" "+e.className),e.style&&Object.assign(this.canvas.style,e.style),this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges",this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv);let s=this.canvas.getContext("2d",{alpha:!0,desynchronized:!1});if(!s)throw new Error("UTSPRender: Impossible d'obtenir le contexte 2D du canvas");this.ctx=s,this.ctx.imageSmoothingEnabled=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid(),this.showDebugGrid&&(this.gridOverlay=new A(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;if(!this.customCellSize){let h,c;if(this.fontType==="image"&&this.imageAtlas){let d=this.imageAtlas.getCellDimensions();h=d.width,c=d.height}else this.fontType==="bitmap"?(h=this.bitmapCharWidth,c=this.bitmapCharHeight):(h=Math.round(this.cellWidth)||10,c=Math.round(this.cellHeight)||14);this.cellWidth=Math.round(h),this.cellHeight=Math.round(c)}this.scalingMode===R.ScalingMode.Responsive?(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1):this.fixedGridMode&&this.fixedCols&&this.fixedRows?(this.cols=this.fixedCols,this.rows=this.fixedRows):(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1);let i=this.cols*this.cellWidth,s=this.rows*this.cellHeight,a=t/i,r=e/s,o=Math.min(a,r),n;switch(this.scalingMode){case R.ScalingMode.Integer:n=Math.max(1,Math.floor(o));break;case R.ScalingMode.Half:n=Math.max(.5,Math.floor(o*2)/2);break;case R.ScalingMode.Quarter:n=Math.max(.25,Math.floor(o*4)/4);break;case R.ScalingMode.Eighth:n=Math.max(.125,Math.floor(o*8)/8);break;case R.ScalingMode.Responsive:n=1;break;case R.ScalingMode.None:default:n=Math.max(.1,o);break}this.currentScale=n,this.canvas.width=i,this.canvas.height=s,this.ctx.imageSmoothingEnabled=!1,this.canvas.style.cssText=`
145
+ `,this.canvas=document.createElement("canvas"),this.canvas.className="terminal2d-canvas",e.className&&(this.canvas.className+=" "+e.className),e.style&&Object.assign(this.canvas.style,e.style),this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges",this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv);let s=this.canvas.getContext("2d",{alpha:!0,desynchronized:!1});if(!s)throw new Error("UTSPRender: Impossible d'obtenir le contexte 2D du canvas");this.ctx=s,this.ctx.imageSmoothingEnabled=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid(),this.showDebugGrid&&(this.gridOverlay=new A(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;if(!this.customCellSize){let h,c;if(this.fontType==="image"&&this.imageAtlas){let d=this.imageAtlas.getCellDimensions();h=d.width,c=d.height}else this.fontType==="bitmap"?(h=this.bitmapCharWidth,c=this.bitmapCharHeight):(h=Math.round(this.cellWidth)||10,c=Math.round(this.cellHeight)||14);this.cellWidth=Math.round(h),this.cellHeight=Math.round(c)}this.scalingMode===R.ScalingMode.Responsive?(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1):this.fixedGridMode&&this.fixedCols&&this.fixedRows?(this.cols=this.fixedCols,this.rows=this.fixedRows):(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1);let i=this.cols*this.cellWidth,s=this.rows*this.cellHeight,n=t/i,r=e/s,o=Math.min(n,r),a;switch(this.scalingMode){case R.ScalingMode.Integer:a=Math.max(1,Math.floor(o));break;case R.ScalingMode.Half:a=Math.max(.5,Math.floor(o*2)/2);break;case R.ScalingMode.Quarter:a=Math.max(.25,Math.floor(o*4)/4);break;case R.ScalingMode.Eighth:a=Math.max(.125,Math.floor(o*8)/8);break;case R.ScalingMode.Responsive:a=1;break;case R.ScalingMode.None:default:a=Math.max(.1,o);break}this.currentScale=a,this.canvas.width=i,this.canvas.height=s,this.ctx.imageSmoothingEnabled=!1,this.canvas.style.cssText=`
146
146
  flex-shrink: 0 !important;
147
147
  flex-grow: 0 !important;
148
148
  width: ${i}px !important;
@@ -151,12 +151,12 @@
151
151
  image-rendering: crisp-edges !important;
152
152
  -ms-interpolation-mode: nearest-neighbor !important;
153
153
  transform-origin: center center !important;
154
- transform: scale(${n}) !important;
154
+ transform: scale(${a}) !important;
155
155
  will-change: transform !important;
156
156
  backface-visibility: hidden !important;
157
157
  pointer-events: auto !important;
158
158
  touch-action: none !important;
159
- `,this.fontType==="web"&&(this.fontSize=Math.round(this.cellHeight/14*12)),this.offsetX=0,this.offsetY=0}createEmptyGrid(){let t=[];for(let e=0;e<this.rows;e++){let i=[];for(let s=0;s<this.cols;s++)i.push({char:" ",fgColor:this.defaultFgColor,bgColor:this.defaultBgColor});t.push(i)}return t}enableAutoResize(){this.resizeObserver=new ResizeObserver(()=>{let t=this.cols,e=this.rows;if(this.calculateGridSize(),this.cols!==t||this.rows!==e){let i=this.cells;this.cells=this.createEmptyGrid();let s=Math.min(t,this.cols),a=Math.min(e,this.rows);for(let r=0;r<a;r++)for(let o=0;o<s;o++)this.cells[r][o]=i[r][o]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(t,e,i,s,a){if(e<0||e>=this.rows||t<0||t>=this.cols)return;let r=i&&typeof i=="string"?i.charAt(0):" ";this.cells[e][t]={char:r,fgColor:s??this.defaultFgColor,bgColor:a??this.defaultBgColor}}getCell(t,e){return e<0||e>=this.rows||t<0||t>=this.cols?null:this.cells[e][t]}write(t,e,i,s,a){for(let r=0;r<i.length;r++)this.setCell(t+r,e,i[r],s,a)}fillRect(t,e,i,s,a=" ",r,o){for(let n=e;n<e+s;n++)for(let h=t;h<t+i;h++)this.setCell(h,n,a,r,o)}clear(){this.cells=this.createEmptyGrid()}setFromArray(t){let e=t.width*t.height;if(t.cells.length!==e)throw new Error(`Invalid array length: expected ${e} (${t.width}\xD7${t.height}), got ${t.cells.length}`);let i=0;for(let s=0;s<t.height;s++)for(let a=0;a<t.width;a++){let r=t.cells[i];s<this.rows&&a<this.cols&&this.setCell(a,s,r.char,r.fgColor,r.bgColor),i++}}render(){if(this.fontType==="bitmap"&&this.bitmapFont&&this.useImageDataRendering){this.renderWithImageData();return}this.renderClassic()}renderWithImageData(){if(!this.bitmapFont)return;let t=this.cols*this.bitmapCharWidth,e=this.rows*this.bitmapCharHeight;(!this.imageDataBuffer||this.imageDataBuffer.width!==t||this.imageDataBuffer.height!==e)&&(this.imageDataBuffer=this.ctx.createImageData(t,e));let i=this.imageDataBuffer.data;for(let n=0;n<this.rows;n++)for(let h=0;h<this.cols;h++){let c=this.cells[n][h],d=this.parseColorToRGB(c.bgColor),f=this.parseColorToRGB(c.fgColor),m=c.char.charCodeAt(0),g=this.bitmapFont.get(m);for(let u=0;u<this.bitmapCharHeight;u++)for(let p=0;p<this.bitmapCharWidth;p++){let C=h*this.bitmapCharWidth+p,E=((n*this.bitmapCharHeight+u)*t+C)*4,w=!1;if(g&&u<g.length){let H=g[u],T=1<<7-p;w=(H&T)!==0}w?(i[E]=f.r,i[E+1]=f.g,i[E+2]=f.b,i[E+3]=f.a):(i[E]=d.r,i[E+1]=d.g,i[E+2]=d.b,i[E+3]=d.a)}}this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges";let s=document.createElement("canvas");s.width=t,s.height=e,s.getContext("2d").putImageData(this.imageDataBuffer,0,0);let r=this.cols*this.cellWidth,o=this.rows*this.cellHeight;this.ctx.drawImage(s,0,0,t,e,this.offsetX,this.offsetY,r,o),this.showDebugGrid&&this.drawDebugGrid()}parseColorToRGB(t){let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10),a:e[4]?Math.round(parseFloat(e[4])*255):255};if(t.startsWith("#")){let a=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(a,(o,n,h,c)=>n+n+h+h+c+c);let r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);if(r)return{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16),a:255}}let s={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255],transparent:[0,0,0]}[t.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2],a:t==="transparent"?0:255}:{r:255,g:255,b:255,a:255}}renderClassic(){this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.fontType==="bitmap"||this.fontType==="image"?(this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges"):(this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.canvas.style.imageRendering="auto",this.ctx.font=`${this.fontSize}px ${this.fontFamily}`,this.ctx.textBaseline="top",this.ctx.textRendering="optimizeLegibility");for(let t=0;t<this.rows;t++)for(let e=0;e<this.cols;e++){let i=this.cells[t][e],s=Math.floor(this.offsetX+e*this.cellWidth),a=Math.floor(this.offsetY+t*this.cellHeight),r=Math.floor(this.offsetX+(e+1)*this.cellWidth),o=Math.floor(this.offsetY+(t+1)*this.cellHeight),n=r-s,h=o-a;if((this.canvasBgColor!==null||i.bgColor!==this.defaultBgColor)&&(this.ctx.fillStyle=i.bgColor,this.ctx.fillRect(s,a,n,h)),i.char!==" ")if(this.fontType==="image"&&this.imageAtlas){let d=i.char.charCodeAt(0);this.imageAtlas.drawChar(this.ctx,d,s,a,n,h,i.fgColor)}else if(this.fontType==="bitmap"&&this.bitmapFont)this.drawBitmapChar(i.char,s,a,n,h,i.fgColor);else{this.ctx.fillStyle=i.fgColor;let d=s+(n-this.ctx.measureText(i.char).width)/2,f=a+(h-this.fontSize)/2;this.ctx.fillText(i.char,d,f)}}this.showDebugGrid&&this.drawDebugGrid()}drawBitmapChar(t,e,i,s,a,r){let o=t.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,o,e,i,s,a,r);return}if(!this.bitmapFont)return;let n=this.bitmapFont.get(o);if(!n)return;let h=s/this.bitmapCharWidth,c=a/this.bitmapCharHeight;this.ctx.fillStyle=r;for(let d=0;d<Math.min(n.length,this.bitmapCharHeight);d++){let f=n[d],m=i+d*c,g=i+(d+1)*c;for(let u=0;u<this.bitmapCharWidth;u++){let p=1<<7-u;if(f&p){let C=e+u*h,x=e+(u+1)*h;this.ctx.fillRect(C,m,x-C,g-m)}}}}drawDebugGrid(){if(!this.gridOverlay)return;let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;this.gridOverlay.update(this.cols,this.rows,this.cellWidth,this.cellHeight,t,e,this.offsetX,this.offsetY)}getCanvas(){return this.canvas}getContext(){return this.ctx}getDimensions(){return{cols:this.cols,rows:this.rows}}getCellDimensions(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getScalingMode(){return this.scalingMode}getOffsets(){return{offsetX:this.offsetX,offsetY:this.offsetY}}setDebugGrid(t){this.showDebugGrid=t,t&&!this.gridOverlay?(this.gridOverlay=new A(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10}),this.drawDebugGrid()):!t&&this.gridOverlay?(this.gridOverlay.destroy(),this.gridOverlay=void 0):t&&this.gridOverlay&&this.gridOverlay.setVisible(!0)}setCanvasBackgroundColor(t){this.canvasBgColor=t}getCanvasBackgroundColor(){return this.canvasBgColor}setFixedGrid(t,e,i){this.fixedGridMode=!0,this.fixedCols=t,this.fixedRows=e,i!==void 0&&(this.cellAspectRatio=i);let s=this.cols,a=this.rows,r=this.cells;if(this.calculateGridSize(),this.cols!==s||this.rows!==a){this.cells=this.createEmptyGrid();let o=Math.min(s,this.cols),n=Math.min(a,this.rows);for(let h=0;h<n;h++)for(let c=0;c<o;c++)this.cells[h][c]=r[h][c]}this.render()}setAdaptiveGrid(t,e){this.fixedGridMode=!1,this.fixedCols=void 0,this.fixedRows=void 0,t!==void 0&&(this.cellWidth=t),e!==void 0&&(this.cellHeight=e);let i=this.cols,s=this.rows,a=this.cells;if(this.calculateGridSize(),this.cols!==i||this.rows!==s){this.cells=this.createEmptyGrid();let r=Math.min(i,this.cols),o=Math.min(s,this.rows);for(let n=0;n<o;n++)for(let h=0;h<r;h++)this.cells[n][h]=a[n][h]}this.render()}isFixedGridMode(){return this.fixedGridMode}setDebugGridColor(t){this.debugGridColor=t}isDebugGridEnabled(){return this.showDebugGrid}setImageDataRendering(t){this.useImageDataRendering=t,t&&this.fontType==="bitmap"?console.warn("[Render] ImageData rendering enabled (optimized for benchmarks)"):t&&(console.warn("[Render] ImageData rendering requires bitmap font, keeping classic mode"),this.useImageDataRendering=!1)}isImageDataRenderingEnabled(){return this.useImageDataRendering}setWebFont(t,e){this.fontType="web",this.fontFamily=t,e!==void 0&&(this.fontSize=e),this.bitmapFont=void 0,this.bitmapAtlas=void 0,this.useImageDataRendering=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid()}setBitmapFont(t,e,i,s,a){this.fontType="bitmap",this.bitmapFont=t,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.bitmapAtlas=new D(t,e,i,s,a),this.cellWidth=s,this.cellHeight=a,this.calculateGridSize(),this.cells=this.createEmptyGrid()}async setImageFont(t,e,i,s,a,r){this.fontType="image",this.imageAtlas=new F({glyphWidth:e,glyphHeight:i,cellWidth:s,cellHeight:a,atlasBlocks:r}),await this.imageAtlas.loadFromPNG(t),this.cellWidth=s,this.cellHeight=a,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.calculateGridSize(),this.cells=this.createEmptyGrid()}getFontType(){return this.fontType}getBitmapFont(){return this.bitmapFont}getBitmapCharDimensions(){return this.fontType!=="bitmap"?null:{width:this.bitmapCharWidth,height:this.bitmapCharHeight}}setPalette(t){this.paletteCache=t}renderDisplayData(t){if(!t||!t.cells||t.cells.length===0){console.warn("[Terminal2D] Empty display data");return}if(t.width===0||t.height===0){console.warn("[Terminal2D] Invalid display dimensions:",t.width,t.height);return}(t.width!==this.cols||t.height!==this.rows)&&this.setFixedGrid(t.width,t.height,this.cellAspectRatio);let e=this.paletteCache??t.palette;if(!e||e.length===0){console.error("[Terminal2D] No palette available (neither cached nor in display)");return}let i=v(s=>{if(s==null||isNaN(s))return console.warn("[Terminal2D] Invalid palette index (undefined/null/NaN):",s),this.defaultFgColor;if(s===255)return"rgba(0, 0, 0, 0)";if(s<0||s>=e.length)return console.warn(`[Terminal2D] Invalid palette index: ${s}`),this.defaultFgColor;let a=e[s];return!a||typeof a.r!="number"?(console.warn(`[Terminal2D] Corrupted palette entry at index ${s}:`,a),this.defaultFgColor):`rgba(${a.r}, ${a.g}, ${a.b}, ${a.a/255})`},"convertColor");for(let s=0;s<t.height&&s<this.rows;s++)for(let a=0;a<t.width&&a<this.cols;a++){let r=s*t.width+a;if(r>=t.cells.length)break;let o=t.cells[r];if(!o)continue;let n=i(o.fgColorIndex),h=i(o.bgColorIndex);this.setCell(a,s,o.char??" ",n,h)}this.render()}isReady(){return!0}getCols(){return this.cols}getRows(){return this.rows}resize(t,e){this.setFixedGrid(t,e)}setScalingMode(t){if(this.scalingMode===t)return;let e=this.cols,i=this.rows;if(this.scalingMode=t,this.calculateGridSize(),this.cols!==e||this.rows!==i){let s=this.cells;if(this.cells=this.createEmptyGrid(),s&&s.length>0){let a=Math.min(e,this.cols),r=Math.min(i,this.rows);for(let o=0;o<r;o++)for(let n=0;n<a;n++)s[o]&&s[o][n]&&(this.cells[o][n]=s[o][n])}}this.render()}setCellSize(t,e){let i=Math.max(1,Math.min(255,Math.round(t))),s=Math.max(1,Math.min(255,Math.round(e)));if(this.cellWidth===i&&this.cellHeight===s)return;let a=this.cols,r=this.rows;if(this.cellWidth=i,this.cellHeight=s,this.customCellSize=!0,this.calculateGridSize(),this.cols!==a||this.rows!==r){let o=this.cells;if(this.cells=this.createEmptyGrid(),o&&o.length>0){let n=Math.min(a,this.cols),h=Math.min(r,this.rows);for(let c=0;c<h;c++)for(let d=0;d<n;d++)o[c]&&o[c][d]&&(this.cells[c][d]=o[c][d])}}this.render()}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}getMaxCells(){return 65536}destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=void 0),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}};v(V,"Terminal2D");var P=V;var X=class X{constructor(t,e={}){l(this,"container");l(this,"overlayDiv",null);l(this,"button",null);l(this,"options");l(this,"started",!1);l(this,"onStartCallback");this.container=t,this.options={buttonText:e.buttonText??"Click to Start",onStart:e.onStart??(()=>{}),backgroundColor:e.backgroundColor??"rgba(0, 0, 0, 0.8)",buttonColor:e.buttonColor??"#4a90d9",buttonHoverColor:e.buttonHoverColor??"#357abd",buttonTextColor:e.buttonTextColor??"#ffffff",zIndex:e.zIndex??1e3},this.onStartCallback=e.onStart,this.createOverlay()}createOverlay(){let t=window.getComputedStyle(this.container).position;t!=="relative"&&t!=="absolute"&&t!=="fixed"&&(this.container.style.position="relative"),this.overlayDiv=document.createElement("div"),this.overlayDiv.className="utsp-autoplay-overlay",this.overlayDiv.style.cssText=`
159
+ `,this.fontType==="web"&&(this.fontSize=Math.round(this.cellHeight/14*12)),this.offsetX=0,this.offsetY=0}createEmptyGrid(){let t=[];for(let e=0;e<this.rows;e++){let i=[];for(let s=0;s<this.cols;s++)i.push({char:" ",fgColor:this.defaultFgColor,bgColor:this.defaultBgColor});t.push(i)}return t}enableAutoResize(){this.resizeObserver=new ResizeObserver(()=>{let t=this.cols,e=this.rows;if(this.calculateGridSize(),this.cols!==t||this.rows!==e){let i=this.cells;this.cells=this.createEmptyGrid();let s=Math.min(t,this.cols),n=Math.min(e,this.rows);for(let r=0;r<n;r++)for(let o=0;o<s;o++)this.cells[r][o]=i[r][o]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(t,e,i,s,n){if(e<0||e>=this.rows||t<0||t>=this.cols)return;let r=i&&typeof i=="string"?i.charAt(0):" ";this.cells[e][t]={char:r,fgColor:s??this.defaultFgColor,bgColor:n??this.defaultBgColor}}getCell(t,e){return e<0||e>=this.rows||t<0||t>=this.cols?null:this.cells[e][t]}write(t,e,i,s,n){for(let r=0;r<i.length;r++)this.setCell(t+r,e,i[r],s,n)}fillRect(t,e,i,s,n=" ",r,o){for(let a=e;a<e+s;a++)for(let h=t;h<t+i;h++)this.setCell(h,a,n,r,o)}clear(){this.cells=this.createEmptyGrid()}setFromArray(t){let e=t.width*t.height;if(t.cells.length!==e)throw new Error(`Invalid array length: expected ${e} (${t.width}\xD7${t.height}), got ${t.cells.length}`);let i=0;for(let s=0;s<t.height;s++)for(let n=0;n<t.width;n++){let r=t.cells[i];s<this.rows&&n<this.cols&&this.setCell(n,s,r.char,r.fgColor,r.bgColor),i++}}render(){if(this.fontType==="bitmap"&&this.bitmapFont&&this.useImageDataRendering){this.renderWithImageData();return}this.renderClassic()}renderWithImageData(){if(!this.bitmapFont)return;let t=this.cols*this.bitmapCharWidth,e=this.rows*this.bitmapCharHeight;(!this.imageDataBuffer||this.imageDataBuffer.width!==t||this.imageDataBuffer.height!==e)&&(this.imageDataBuffer=this.ctx.createImageData(t,e));let i=this.imageDataBuffer.data;for(let a=0;a<this.rows;a++)for(let h=0;h<this.cols;h++){let c=this.cells[a][h],d=this.parseColorToRGB(c.bgColor),f=this.parseColorToRGB(c.fgColor),m=c.char.charCodeAt(0),g=this.bitmapFont.get(m);for(let u=0;u<this.bitmapCharHeight;u++)for(let p=0;p<this.bitmapCharWidth;p++){let C=h*this.bitmapCharWidth+p,E=((a*this.bitmapCharHeight+u)*t+C)*4,w=!1;if(g&&u<g.length){let H=g[u],T=1<<7-p;w=(H&T)!==0}w?(i[E]=f.r,i[E+1]=f.g,i[E+2]=f.b,i[E+3]=f.a):(i[E]=d.r,i[E+1]=d.g,i[E+2]=d.b,i[E+3]=d.a)}}this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges";let s=document.createElement("canvas");s.width=t,s.height=e,s.getContext("2d").putImageData(this.imageDataBuffer,0,0);let r=this.cols*this.cellWidth,o=this.rows*this.cellHeight;this.ctx.drawImage(s,0,0,t,e,this.offsetX,this.offsetY,r,o),this.showDebugGrid&&this.drawDebugGrid()}parseColorToRGB(t){let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10),a:e[4]?Math.round(parseFloat(e[4])*255):255};if(t.startsWith("#")){let n=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(n,(o,a,h,c)=>a+a+h+h+c+c);let r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);if(r)return{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16),a:255}}let s={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255],transparent:[0,0,0]}[t.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2],a:t==="transparent"?0:255}:{r:255,g:255,b:255,a:255}}renderClassic(){this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.fontType==="bitmap"||this.fontType==="image"?(this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges"):(this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.canvas.style.imageRendering="auto",this.ctx.font=`${this.fontSize}px ${this.fontFamily}`,this.ctx.textBaseline="top",this.ctx.textRendering="optimizeLegibility");for(let t=0;t<this.rows;t++)for(let e=0;e<this.cols;e++){let i=this.cells[t][e],s=Math.floor(this.offsetX+e*this.cellWidth),n=Math.floor(this.offsetY+t*this.cellHeight),r=Math.floor(this.offsetX+(e+1)*this.cellWidth),o=Math.floor(this.offsetY+(t+1)*this.cellHeight),a=r-s,h=o-n;if((this.canvasBgColor!==null||i.bgColor!==this.defaultBgColor)&&(this.ctx.fillStyle=i.bgColor,this.ctx.fillRect(s,n,a,h)),i.char!==" ")if(this.fontType==="image"&&this.imageAtlas){let d=i.char.charCodeAt(0);this.imageAtlas.drawChar(this.ctx,d,s,n,a,h,i.fgColor)}else if(this.fontType==="bitmap"&&this.bitmapFont)this.drawBitmapChar(i.char,s,n,a,h,i.fgColor);else{this.ctx.fillStyle=i.fgColor;let d=s+(a-this.ctx.measureText(i.char).width)/2,f=n+(h-this.fontSize)/2;this.ctx.fillText(i.char,d,f)}}this.showDebugGrid&&this.drawDebugGrid()}drawBitmapChar(t,e,i,s,n,r){let o=t.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,o,e,i,s,n,r);return}if(!this.bitmapFont)return;let a=this.bitmapFont.get(o);if(!a)return;let h=s/this.bitmapCharWidth,c=n/this.bitmapCharHeight;this.ctx.fillStyle=r;for(let d=0;d<Math.min(a.length,this.bitmapCharHeight);d++){let f=a[d],m=i+d*c,g=i+(d+1)*c;for(let u=0;u<this.bitmapCharWidth;u++){let p=1<<7-u;if(f&p){let C=e+u*h,x=e+(u+1)*h;this.ctx.fillRect(C,m,x-C,g-m)}}}}drawDebugGrid(){if(!this.gridOverlay)return;let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;this.gridOverlay.update(this.cols,this.rows,this.cellWidth,this.cellHeight,t,e,this.offsetX,this.offsetY)}getCanvas(){return this.canvas}getContext(){return this.ctx}getDimensions(){return{cols:this.cols,rows:this.rows}}getCellDimensions(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getScalingMode(){return this.scalingMode}getOffsets(){return{offsetX:this.offsetX,offsetY:this.offsetY}}setDebugGrid(t){this.showDebugGrid=t,t&&!this.gridOverlay?(this.gridOverlay=new A(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10}),this.drawDebugGrid()):!t&&this.gridOverlay?(this.gridOverlay.destroy(),this.gridOverlay=void 0):t&&this.gridOverlay&&this.gridOverlay.setVisible(!0)}setCanvasBackgroundColor(t){this.canvasBgColor=t}getCanvasBackgroundColor(){return this.canvasBgColor}setFixedGrid(t,e,i){this.fixedGridMode=!0,this.fixedCols=t,this.fixedRows=e,i!==void 0&&(this.cellAspectRatio=i);let s=this.cols,n=this.rows,r=this.cells;if(this.calculateGridSize(),this.cols!==s||this.rows!==n){this.cells=this.createEmptyGrid();let o=Math.min(s,this.cols),a=Math.min(n,this.rows);for(let h=0;h<a;h++)for(let c=0;c<o;c++)this.cells[h][c]=r[h][c]}this.render()}setAdaptiveGrid(t,e){this.fixedGridMode=!1,this.fixedCols=void 0,this.fixedRows=void 0,t!==void 0&&(this.cellWidth=t),e!==void 0&&(this.cellHeight=e);let i=this.cols,s=this.rows,n=this.cells;if(this.calculateGridSize(),this.cols!==i||this.rows!==s){this.cells=this.createEmptyGrid();let r=Math.min(i,this.cols),o=Math.min(s,this.rows);for(let a=0;a<o;a++)for(let h=0;h<r;h++)this.cells[a][h]=n[a][h]}this.render()}isFixedGridMode(){return this.fixedGridMode}setDebugGridColor(t){this.debugGridColor=t}isDebugGridEnabled(){return this.showDebugGrid}setImageDataRendering(t){this.useImageDataRendering=t,t&&this.fontType==="bitmap"?console.warn("[Render] ImageData rendering enabled (optimized for benchmarks)"):t&&(console.warn("[Render] ImageData rendering requires bitmap font, keeping classic mode"),this.useImageDataRendering=!1)}isImageDataRenderingEnabled(){return this.useImageDataRendering}setWebFont(t,e){this.fontType="web",this.fontFamily=t,e!==void 0&&(this.fontSize=e),this.bitmapFont=void 0,this.bitmapAtlas=void 0,this.useImageDataRendering=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid()}setBitmapFont(t,e,i,s,n){this.fontType="bitmap",this.bitmapFont=t,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.bitmapAtlas=new D(t,e,i,s,n),this.cellWidth=s,this.cellHeight=n,this.calculateGridSize(),this.cells=this.createEmptyGrid()}async setImageFont(t,e,i,s,n,r){this.fontType="image",this.imageAtlas=new F({glyphWidth:e,glyphHeight:i,cellWidth:s,cellHeight:n,atlasBlocks:r}),await this.imageAtlas.loadFromPNG(t),this.cellWidth=s,this.cellHeight=n,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.calculateGridSize(),this.cells=this.createEmptyGrid()}getFontType(){return this.fontType}getBitmapFont(){return this.bitmapFont}getBitmapCharDimensions(){return this.fontType!=="bitmap"?null:{width:this.bitmapCharWidth,height:this.bitmapCharHeight}}setPalette(t){this.paletteCache=t}renderDisplayData(t){if(!t||!t.cells||t.cells.length===0){console.warn("[Terminal2D] Empty display data");return}if(t.width===0||t.height===0){console.warn("[Terminal2D] Invalid display dimensions:",t.width,t.height);return}(t.width!==this.cols||t.height!==this.rows)&&this.setFixedGrid(t.width,t.height,this.cellAspectRatio);let e=this.paletteCache??t.palette;if(!e||e.length===0){console.error("[Terminal2D] No palette available (neither cached nor in display)");return}let i=v(s=>{if(s==null||isNaN(s))return console.warn("[Terminal2D] Invalid palette index (undefined/null/NaN):",s),this.defaultFgColor;if(s===255)return"rgba(0, 0, 0, 0)";if(s<0||s>=e.length)return console.warn(`[Terminal2D] Invalid palette index: ${s}`),this.defaultFgColor;let n=e[s];return!n||typeof n.r!="number"?(console.warn(`[Terminal2D] Corrupted palette entry at index ${s}:`,n),this.defaultFgColor):`rgba(${n.r}, ${n.g}, ${n.b}, ${n.a/255})`},"convertColor");for(let s=0;s<t.height&&s<this.rows;s++)for(let n=0;n<t.width&&n<this.cols;n++){let r=s*t.width+n;if(r>=t.cells.length)break;let o=t.cells[r];if(!o)continue;let a=i(o.fgColorIndex),h=i(o.bgColorIndex);this.setCell(n,s,o.char??" ",a,h)}this.render()}isReady(){return!0}getCols(){return this.cols}getRows(){return this.rows}resize(t,e){this.setFixedGrid(t,e)}setScalingMode(t){if(this.scalingMode===t)return;let e=this.cols,i=this.rows;if(this.scalingMode=t,this.calculateGridSize(),this.cols!==e||this.rows!==i){let s=this.cells;if(this.cells=this.createEmptyGrid(),s&&s.length>0){let n=Math.min(e,this.cols),r=Math.min(i,this.rows);for(let o=0;o<r;o++)for(let a=0;a<n;a++)s[o]&&s[o][a]&&(this.cells[o][a]=s[o][a])}}this.render()}setCellSize(t,e){let i=Math.max(1,Math.min(255,Math.round(t))),s=Math.max(1,Math.min(255,Math.round(e)));if(this.cellWidth===i&&this.cellHeight===s)return;let n=this.cols,r=this.rows;if(this.cellWidth=i,this.cellHeight=s,this.customCellSize=!0,this.calculateGridSize(),this.cols!==n||this.rows!==r){let o=this.cells;if(this.cells=this.createEmptyGrid(),o&&o.length>0){let a=Math.min(n,this.cols),h=Math.min(r,this.rows);for(let c=0;c<h;c++)for(let d=0;d<a;d++)o[c]&&o[c][d]&&(this.cells[c][d]=o[c][d])}}this.render()}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}getMaxCells(){return 65536}destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=void 0),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}};v(V,"Terminal2D");var _=V;var X=class X{constructor(t,e={}){l(this,"container");l(this,"overlayDiv",null);l(this,"button",null);l(this,"options");l(this,"started",!1);l(this,"onStartCallback");this.container=t,this.options={buttonText:e.buttonText??"Click to Start",onStart:e.onStart??(()=>{}),backgroundColor:e.backgroundColor??"rgba(0, 0, 0, 0.8)",buttonColor:e.buttonColor??"#4a90d9",buttonHoverColor:e.buttonHoverColor??"#357abd",buttonTextColor:e.buttonTextColor??"#ffffff",zIndex:e.zIndex??1e3},this.onStartCallback=e.onStart,this.createOverlay()}createOverlay(){let t=window.getComputedStyle(this.container).position;t!=="relative"&&t!=="absolute"&&t!=="fixed"&&(this.container.style.position="relative"),this.overlayDiv=document.createElement("div"),this.overlayDiv.className="utsp-autoplay-overlay",this.overlayDiv.style.cssText=`
160
160
  position: absolute !important;
161
161
  top: 0 !important;
162
162
  left: 0 !important;
@@ -198,5 +198,5 @@
198
198
  width: 100% !important;
199
199
  height: 100% !important;
200
200
  pointer-events: none !important;
201
- `;let i=this.canvas.getContext("2d",{alpha:!0});if(!i)throw new Error("PostProcessOverlay: Failed to get 2D context");this.ctx=i,this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv),this.resizeObserver=new ResizeObserver(a=>{for(let r of a){let{width:o,height:n}=r.contentRect;o>0&&n>0&&this.handleResize(Math.floor(o),Math.floor(n))}}),this.resizeObserver.observe(this.parentElement);let s=this.parentElement.getBoundingClientRect();s.width>0&&s.height>0&&this.handleResize(Math.floor(s.width),Math.floor(s.height)),this.hide()}handleResize(t,e){this.width===t&&this.height===e||(this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.currentConfig&&this.isActive()&&this.render())}setConfig(t){let e=this.hashConfig(t);if(e!==this.configHash){if(this.currentConfig=t,this.configHash=e,!t||!this.isActiveConfig(t)){this.clear(),this.hide();return}this.show(),this.render()}}setScanlines(t){t===null?this.setConfig({scanlines:{enabled:!1}}):this.setConfig({scanlines:t})}setScanlinesEnabled(t){if(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:!0,opacity:e?.opacity??W.POST_PROCESS_DEFAULTS.scanlines.opacity,pattern:e?.pattern??"horizontal",spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}else this.setScanlines({enabled:!1})}setScanlinesOpacity(t){let e=Math.max(0,Math.min(1,t)),i=this.currentConfig?.scanlines;this.setScanlines({enabled:i?.enabled??!0,opacity:e,pattern:i?.pattern??"horizontal",spacing:i?.spacing??2,thickness:i?.thickness??1,color:i?.color??{r:0,g:0,b:0}})}setScanlinesPattern(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:e?.enabled??!0,opacity:e?.opacity??W.POST_PROCESS_DEFAULTS.scanlines.opacity,pattern:t,spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}setScanlinesSpacing(t){let e=Math.max(2,Math.round(t)),i=this.currentConfig?.scanlines;this.setScanlines({enabled:i?.enabled??!0,opacity:i?.opacity??W.POST_PROCESS_DEFAULTS.scanlines.opacity,pattern:i?.pattern??"horizontal",spacing:e,thickness:i?.thickness??1,color:i?.color??{r:0,g:0,b:0}})}getConfig(){return this.currentConfig}isActive(){return this.isActiveConfig(this.currentConfig)}destroy(){this.resizeObserver.disconnect(),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}syncWithRenderer(t){}resize(t,e){}setCellDimensions(t,e){}show(){this.containerDiv.style.display="block"}hide(){this.containerDiv.style.display="none"}clear(){this.ctx.clearRect(0,0,this.width,this.height)}isActiveConfig(t){return t?.scanlines?.enabled??!1}render(){this.clear(),this.currentConfig?.scanlines?.enabled&&this.renderScanlines(this.currentConfig.scanlines)}renderScanlines(t){let e=t.opacity??W.POST_PROCESS_DEFAULTS.scanlines.opacity,i=t.pattern??"horizontal",s=t.spacing??2,a=t.thickness??1,r=t.color??{r:0,g:0,b:0},o=this.ctx;switch(o.fillStyle=`rgba(${r.r}, ${r.g}, ${r.b}, ${e})`,i){case"horizontal":for(let n=s-1;n<this.height;n+=s)o.fillRect(0,n,this.width,a);break;case"vertical":for(let n=s-1;n<this.width;n+=s)o.fillRect(n,0,a,this.height);break;case"grid":for(let n=s-1;n<this.height;n+=s)o.fillRect(0,n,this.width,a);for(let n=s-1;n<this.width;n+=s)o.fillRect(n,0,a,this.height);break}}hashConfig(t){return t?JSON.stringify(t):"null"}};v(q,"PostProcessOverlay");var z=q;var j="\x1B[0m",rt="\x1B[H",bt="\x1B[2J",at="\x1B[?25l",pt="\x1B[?25h",vt=`
202
- `,Q=class Q{constructor(t={}){l(this,"options");l(this,"fgCache",[]);l(this,"bgCache",[]);l(this,"lastPalette",null);this.options={optimizeColors:t.optimizeColors??!0,includeHome:t.includeHome??!0,hideCursor:t.hideCursor??!0,includeNewlines:t.includeNewlines??!0,includeReset:t.includeReset??!0}}buildColorCache(t){if(this.lastPalette!==t){this.fgCache=new Array(t.length),this.bgCache=new Array(t.length);for(let e=0;e<t.length;e++){let i=t[e];this.fgCache[e]=`\x1B[38;2;${i.r};${i.g};${i.b}m`,this.bgCache[e]=`\x1B[48;2;${i.r};${i.g};${i.b}m`}this.lastPalette=t}}render(t){let{width:e,height:i,cells:s,palette:a}=t;this.buildColorCache(a);let r="";this.options.hideCursor&&(r+=at),this.options.includeHome&&(r+=rt);let o=-1,n=-1,h=this.options.optimizeColors,c=this.options.includeNewlines;for(let d=0;d<i;d++){let f=d*e;for(let m=0;m<e;m++){let g=s[f+m],u=g.fgColorIndex,p=g.bgColorIndex;h?(p!==n&&(r+=this.bgCache[p],n=p),u!==o&&(r+=this.fgCache[u],o=u)):(r+=this.bgCache[p],r+=this.fgCache[u]),r+=g.char||" "}c&&d<i-1&&(r+=vt)}return this.options.includeReset&&(r+=j),r}renderRow(t,e){let{width:i,cells:s,palette:a}=t;this.buildColorCache(a);let r=`\x1B[${e+1};1H`,o=-1,n=-1,h=this.options.optimizeColors,c=e*i;for(let d=0;d<i;d++){let f=s[c+d],m=f.fgColorIndex,g=f.bgColorIndex;h?(g!==n&&(r+=this.bgCache[g],n=g),m!==o&&(r+=this.fgCache[m],o=m)):(r+=this.bgCache[g],r+=this.fgCache[m]),r+=f.char||" "}return this.options.includeReset&&(r+=j),r}clear(){return bt+rt}showCursor(){return pt}hideCursor(){return at}reset(){return j}moveTo(t,e){return`\x1B[${t+1};${e+1}H`}};v(Q,"TerminalANSI");var k=Q;function nt(b){let t=b.startsWith("#")?b.slice(1):b,e=t.length===3?t[0]+t[0]+t[1]+t[1]+t[2]+t[2]:t,i=parseInt(e,16);return{r:i>>16&255,g:i>>8&255,b:i&255,a:255}}v(nt,"hexToRGB");function ot(b){let t=b.r.toString(16).padStart(2,"0"),e=b.g.toString(16).padStart(2,"0"),i=b.b.toString(16).padStart(2,"0");return`#${t}${e}${i}`}v(ot,"rgbToHex");function lt(b,t){let e=[{r:0,g:0,b:0,a:255},{r:128,g:0,b:0,a:255},{r:0,g:128,b:0,a:255},{r:128,g:128,b:0,a:255},{r:0,g:0,b:128,a:255},{r:128,g:0,b:128,a:255},{r:0,g:128,b:128,a:255},{r:192,g:192,b:192,a:255},{r:128,g:128,b:128,a:255},{r:255,g:0,b:0,a:255},{r:0,g:255,b:0,a:255},{r:255,g:255,b:0,a:255},{r:0,g:0,b:255,a:255},{r:255,g:0,b:255,a:255},{r:0,g:255,b:255,a:255},{r:255,g:255,b:255,a:255}];for(;e.length<256;)e.push({r:128,g:128,b:128,a:255});let i=[];for(let s=0;s<t;s++)for(let a=0;a<b;a++)i.push({char:String.fromCharCode(65+(a+s)%26),fgColorIndex:15,bgColorIndex:(a+s)%16,fgEmission:0,bgEmission:0});return{id:0,width:b,height:t,cells:i,palette:e}}v(lt,"createTestRenderState");var Ct="0.1.0";
201
+ `;let i=this.canvas.getContext("2d",{alpha:!0});if(!i)throw new Error("PostProcessOverlay: Failed to get 2D context");this.ctx=i,this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv),this.resizeObserver=new ResizeObserver(n=>{for(let r of n){let{width:o,height:a}=r.contentRect;o>0&&a>0&&this.handleResize(Math.floor(o),Math.floor(a))}}),this.resizeObserver.observe(this.parentElement);let s=this.parentElement.getBoundingClientRect();s.width>0&&s.height>0&&this.handleResize(Math.floor(s.width),Math.floor(s.height)),this.hide()}handleResize(t,e){this.width===t&&this.height===e||(this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.currentConfig&&this.isActive()&&this.render())}setConfig(t){let e=this.hashConfig(t);if(e!==this.configHash){if(this.currentConfig=t,this.configHash=e,!t||!this.isActiveConfig(t)){this.clear(),this.hide();return}this.show(),this.render()}}setScanlines(t){t===null?this.setConfig({scanlines:{enabled:!1}}):this.setConfig({scanlines:t})}setScanlinesEnabled(t){if(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:!0,opacity:e?.opacity??W.POST_PROCESS_DEFAULTS.scanlines.opacity,pattern:e?.pattern??"horizontal",spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}else this.setScanlines({enabled:!1})}setScanlinesOpacity(t){let e=Math.max(0,Math.min(1,t)),i=this.currentConfig?.scanlines;this.setScanlines({enabled:i?.enabled??!0,opacity:e,pattern:i?.pattern??"horizontal",spacing:i?.spacing??2,thickness:i?.thickness??1,color:i?.color??{r:0,g:0,b:0}})}setScanlinesPattern(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:e?.enabled??!0,opacity:e?.opacity??W.POST_PROCESS_DEFAULTS.scanlines.opacity,pattern:t,spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}setScanlinesSpacing(t){let e=Math.max(2,Math.round(t)),i=this.currentConfig?.scanlines;this.setScanlines({enabled:i?.enabled??!0,opacity:i?.opacity??W.POST_PROCESS_DEFAULTS.scanlines.opacity,pattern:i?.pattern??"horizontal",spacing:e,thickness:i?.thickness??1,color:i?.color??{r:0,g:0,b:0}})}getConfig(){return this.currentConfig}isActive(){return this.isActiveConfig(this.currentConfig)}destroy(){this.resizeObserver.disconnect(),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}syncWithRenderer(t){}resize(t,e){}setCellDimensions(t,e){}show(){this.containerDiv.style.display="block"}hide(){this.containerDiv.style.display="none"}clear(){this.ctx.clearRect(0,0,this.width,this.height)}isActiveConfig(t){return t?.scanlines?.enabled??!1}render(){this.clear(),this.currentConfig?.scanlines?.enabled&&this.renderScanlines(this.currentConfig.scanlines)}renderScanlines(t){let e=t.opacity??W.POST_PROCESS_DEFAULTS.scanlines.opacity,i=t.pattern??"horizontal",s=t.spacing??2,n=t.thickness??1,r=t.color??{r:0,g:0,b:0},o=this.ctx;switch(o.fillStyle=`rgba(${r.r}, ${r.g}, ${r.b}, ${e})`,i){case"horizontal":for(let a=s-1;a<this.height;a+=s)o.fillRect(0,a,this.width,n);break;case"vertical":for(let a=s-1;a<this.width;a+=s)o.fillRect(a,0,n,this.height);break;case"grid":for(let a=s-1;a<this.height;a+=s)o.fillRect(0,a,this.width,n);for(let a=s-1;a<this.width;a+=s)o.fillRect(a,0,n,this.height);break}}hashConfig(t){return t?JSON.stringify(t):"null"}};v(q,"PostProcessOverlay");var z=q;var j="\x1B[0m",rt="\x1B[H",bt="\x1B[2J",nt="\x1B[?25l",pt="\x1B[?25h",vt=`
202
+ `,Q=class Q{constructor(t={}){l(this,"options");l(this,"fgCache",[]);l(this,"bgCache",[]);l(this,"lastPalette",null);this.options={optimizeColors:t.optimizeColors??!0,includeHome:t.includeHome??!0,hideCursor:t.hideCursor??!0,includeNewlines:t.includeNewlines??!0,includeReset:t.includeReset??!0}}buildColorCache(t){if(this.lastPalette!==t){this.fgCache=new Array(t.length),this.bgCache=new Array(t.length);for(let e=0;e<t.length;e++){let i=t[e];this.fgCache[e]=`\x1B[38;2;${i.r};${i.g};${i.b}m`,this.bgCache[e]=`\x1B[48;2;${i.r};${i.g};${i.b}m`}this.lastPalette=t}}render(t){let{width:e,height:i,cells:s,palette:n}=t;this.buildColorCache(n);let r="";this.options.hideCursor&&(r+=nt),this.options.includeHome&&(r+=rt);let o=-1,a=-1,h=this.options.optimizeColors,c=this.options.includeNewlines;for(let d=0;d<i;d++){let f=d*e;for(let m=0;m<e;m++){let g=s[f+m],u=g.fgColorIndex,p=g.bgColorIndex;h?(p!==a&&(r+=this.bgCache[p],a=p),u!==o&&(r+=this.fgCache[u],o=u)):(r+=this.bgCache[p],r+=this.fgCache[u]),r+=g.char||" "}c&&d<i-1&&(r+=vt)}return this.options.includeReset&&(r+=j),r}renderRow(t,e){let{width:i,cells:s,palette:n}=t;this.buildColorCache(n);let r=`\x1B[${e+1};1H`,o=-1,a=-1,h=this.options.optimizeColors,c=e*i;for(let d=0;d<i;d++){let f=s[c+d],m=f.fgColorIndex,g=f.bgColorIndex;h?(g!==a&&(r+=this.bgCache[g],a=g),m!==o&&(r+=this.fgCache[m],o=m)):(r+=this.bgCache[g],r+=this.fgCache[m]),r+=f.char||" "}return this.options.includeReset&&(r+=j),r}clear(){return bt+rt}showCursor(){return pt}hideCursor(){return nt}reset(){return j}moveTo(t,e){return`\x1B[${t+1};${e+1}H`}};v(Q,"TerminalANSI");var k=Q;function at(b){let t=b.startsWith("#")?b.slice(1):b,e=t.length===3?t[0]+t[0]+t[1]+t[1]+t[2]+t[2]:t,i=parseInt(e,16);return{r:i>>16&255,g:i>>8&255,b:i&255,a:255}}v(at,"hexToRGB");function ot(b){let t=b.r.toString(16).padStart(2,"0"),e=b.g.toString(16).padStart(2,"0"),i=b.b.toString(16).padStart(2,"0");return`#${t}${e}${i}`}v(ot,"rgbToHex");function lt(b,t){let e=[{r:0,g:0,b:0,a:255},{r:128,g:0,b:0,a:255},{r:0,g:128,b:0,a:255},{r:128,g:128,b:0,a:255},{r:0,g:0,b:128,a:255},{r:128,g:0,b:128,a:255},{r:0,g:128,b:128,a:255},{r:192,g:192,b:192,a:255},{r:128,g:128,b:128,a:255},{r:255,g:0,b:0,a:255},{r:0,g:255,b:0,a:255},{r:255,g:255,b:0,a:255},{r:0,g:0,b:255,a:255},{r:255,g:0,b:255,a:255},{r:0,g:255,b:255,a:255},{r:255,g:255,b:255,a:255}];for(;e.length<256;)e.push({r:128,g:128,b:128,a:255});let i=[];for(let s=0;s<t;s++)for(let n=0;n<b;n++)i.push({char:String.fromCharCode(65+(n+s)%26),fgColorIndex:15,bgColorIndex:(n+s)%16,fgEmission:0,bgEmission:0});return{id:0,width:b,height:t,cells:i,palette:e}}v(lt,"createTestRenderState");var Ct="0.1.0";
package/dist/index.d.ts CHANGED
@@ -945,6 +945,10 @@ declare class TerminalGL implements IRenderer {
945
945
  * ```
946
946
  */
947
947
  renderDisplayData(data: RenderState): void;
948
+ /**
949
+ * Render multiple passes in order, clearing once then layering.
950
+ */
951
+ private renderMultiPass;
948
952
  /**
949
953
  * 🚀 NEW METHOD: Render directly from RenderState
950
954
  * Bypass this.cells for maximum performance
package/dist/index.mjs CHANGED
@@ -1,11 +1,11 @@
1
- var it=Object.defineProperty;var at=(b,t,e)=>t in b?it(b,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):b[t]=e;var v=(b,t)=>it(b,"name",{value:t,configurable:!0});var l=(b,t,e)=>(at(b,typeof t!="symbol"?t+"":t,e),e);var G=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff","#080808","#121212","#1c1c1c","#262626","#303030","#3a3a3a","#444444","#4e4e4e","#585858","#626262","#6c6c6c","#767676","#808080","#8a8a8a","#949494","#9e9e9e","#a80000","#00a800","#a8a800","#0000a8","#a800a8","#00a8a8","#a8a8a8","#545454","#fc5454","#54fc54","#fcfc54","#5454fc","#fc54fc","#54fcfc","#fcfcfc","#000000",...Array(192).fill("#808080")];function nt(b,t=G){return b<0||b>=t.length?"#ff00ff":t[b]}v(nt,"paletteIndexToColor");function ot(b,t=G){let e=t.indexOf(b.toLowerCase());return e>=0?e:0}v(ot,"colorToPaletteIndex");var _=class _{constructor(t,e){l(this,"canvas");l(this,"ctx");l(this,"container");l(this,"cols",0);l(this,"rows",0);l(this,"cellWidth",0);l(this,"cellHeight",0);l(this,"offsetX",0);l(this,"offsetY",0);l(this,"strokeColor","rgba(80, 80, 80, 0.4)");l(this,"lineWidth",1);this.container=t,this.canvas=document.createElement("canvas"),this.canvas.className="grid-overlay-canvas";let i=e?.zIndex??10;this.canvas.style.cssText=`
1
+ var it=Object.defineProperty;var nt=(b,t,e)=>t in b?it(b,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):b[t]=e;var v=(b,t)=>it(b,"name",{value:t,configurable:!0});var l=(b,t,e)=>(nt(b,typeof t!="symbol"?t+"":t,e),e);var G=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff","#080808","#121212","#1c1c1c","#262626","#303030","#3a3a3a","#444444","#4e4e4e","#585858","#626262","#6c6c6c","#767676","#808080","#8a8a8a","#949494","#9e9e9e","#a80000","#00a800","#a8a800","#0000a8","#a800a8","#00a8a8","#a8a8a8","#545454","#fc5454","#54fc54","#fcfc54","#5454fc","#fc54fc","#54fcfc","#fcfcfc","#000000",...Array(192).fill("#808080")];function at(b,t=G){return b<0||b>=t.length?"#ff00ff":t[b]}v(at,"paletteIndexToColor");function ot(b,t=G){let e=t.indexOf(b.toLowerCase());return e>=0?e:0}v(ot,"colorToPaletteIndex");var P=class P{constructor(t,e){l(this,"canvas");l(this,"ctx");l(this,"container");l(this,"cols",0);l(this,"rows",0);l(this,"cellWidth",0);l(this,"cellHeight",0);l(this,"offsetX",0);l(this,"offsetY",0);l(this,"strokeColor","rgba(80, 80, 80, 0.4)");l(this,"lineWidth",1);this.container=t,this.canvas=document.createElement("canvas"),this.canvas.className="grid-overlay-canvas";let i=e?.zIndex??10;this.canvas.style.cssText=`
2
2
  display: block !important;
3
3
  position: absolute !important;
4
4
  pointer-events: none !important;
5
5
  image-rendering: pixelated !important;
6
6
  image-rendering: crisp-edges !important;
7
7
  z-index: ${i} !important;
8
- `,this.container.appendChild(this.canvas);let s=this.canvas.getContext("2d");if(!s)throw new Error("[GridOverlay] Impossible de cr\xE9er le contexte 2D");this.ctx=s,e&&(e.strokeColor&&(this.strokeColor=e.strokeColor),e.lineWidth!==void 0&&(this.lineWidth=e.lineWidth))}setDimensions(t,e,i,s,a=0,r=0){this.cols=t,this.rows=e,this.cellWidth=i,this.cellHeight=s,this.offsetX=a,this.offsetY=r}setCanvasSize(t,e){this.canvas.width=t,this.canvas.height=e,this.ctx.setTransform(1,0,0,1,0,0)}setStyle(t){t.strokeColor&&(this.strokeColor=t.strokeColor),t.lineWidth!==void 0&&(this.lineWidth=t.lineWidth)}setTransform(t,e,i,s,a){let r=s.left-a.left,o=s.top-a.top,n=s.width,h=s.height;(this.canvas.width!==n||this.canvas.height!==h)&&(this.canvas.width=n,this.canvas.height=h);let c=this.canvas.style;c.width=`${n}px`,c.height=`${h}px`,c.left=`${r}px`,c.top=`${o}px`}render(){if(!this.ctx)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,i=t>0?this.canvas.width/t:1,s=e>0?this.canvas.height/e:1,a=Math.min(i,s),r=this.cellWidth*a,o=this.cellHeight*a,n=this.cols*r,h=this.rows*o,c=this.offsetX*a,d=this.offsetY*a;if(!(n===0||h===0)){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.strokeStyle=this.strokeColor,this.ctx.lineWidth=Math.max(1,this.lineWidth*a),this.ctx.beginPath();for(let f=0;f<=this.cols;f++){let m=c+f*r+.5;this.ctx.moveTo(m,d),this.ctx.lineTo(m,d+h)}for(let f=0;f<=this.rows;f++){let m=d+f*o+.5;this.ctx.moveTo(c,m),this.ctx.lineTo(c+n,m)}this.ctx.stroke()}}update(t,e,i,s,a,r,o=0,n=0){this.setDimensions(t,e,i,s,o,n),this.setCanvasSize(a,r),this.render()}setVisible(t){this.canvas.style.display=t?"block":"none"}destroy(){this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}getCanvas(){return this.canvas}};v(_,"GridOverlay");var A=_;function M(b){return Math.sqrt(b)*16}v(M,"getAtlasColumns");function S(b){return b*256-1}v(S,"getMaxCharCode");function B(b,t){let e=Math.floor(b/256),i=b%256,s=Math.sqrt(t),a=e%s,r=Math.floor(e/s),o=i%16,n=Math.floor(i/16);return{col:a*16+o,row:r*16+n}}v(B,"getCharGridPosition");import{POST_PROCESS_DEFAULTS as W,ScalingMode as R}from"@utsp/types";var D=class D{constructor(t,e){l(this,"canvas");l(this,"gl");l(this,"parentElement");l(this,"containerDiv");l(this,"cols");l(this,"rows");l(this,"charWidth");l(this,"charHeight");l(this,"cellWidth",8);l(this,"cellHeight",8);l(this,"glyphOffsetX",0);l(this,"glyphOffsetY",0);l(this,"canvasBgColor");l(this,"showGrid");l(this,"supportsUint32Indices",!1);l(this,"useUint16Indices",!1);l(this,"gridOverlay");l(this,"bitmapFont");l(this,"atlasTexture",null);l(this,"atlasCanvas");l(this,"atlasColumns",0);l(this,"fontLoaded",!1);l(this,"paletteTexture",null);l(this,"program",null);l(this,"positionBuffer",null);l(this,"texCoordBuffer",null);l(this,"colorIndexBuffer",null);l(this,"indexBuffer",null);l(this,"aPosition");l(this,"aTexCoord");l(this,"aColorIndex");l(this,"uResolution",null);l(this,"uTexture",null);l(this,"uPalette",null);l(this,"resizeObserver");l(this,"charCodeToAtlasIndex",new Uint16Array(65536).fill(65535));l(this,"atlasUVs",new Float32Array(0));l(this,"cachedAtlasWidth",0);l(this,"cachedAtlasHeight",0);l(this,"paletteFloat",new Float32Array(256*4));l(this,"maxCells",0);l(this,"renderPositions",new Float32Array(0));l(this,"renderTexCoords",new Float32Array(0));l(this,"renderColorIndices",new Float32Array(0));l(this,"renderIndices",new Uint32Array(0));l(this,"cachedResolution",[0,0]);l(this,"cachedTextureUnit",-1);l(this,"cachedPaletteUnit",-1);l(this,"cachedTextureUniform",!1);l(this,"cachedPaletteUniform",!1);l(this,"paletteHash",0);l(this,"currentScale",1);l(this,"scalingMode",R.None);l(this,"ambientEffectEnabled",!1);l(this,"ambientEffectCanvas",null);l(this,"ambientEffectCtx",null);l(this,"ambientEffectBlur",W.ambientEffect.blur);l(this,"ambientEffectScale",W.ambientEffect.scale);l(this,"ambientEffectOpacity",.7);l(this,"onResizeCallback");l(this,"staticPositionsInitialized",!1);l(this,"vaoExtension",null);l(this,"vao",null);l(this,"instancedExtension",null);l(this,"useInstancing",!1);l(this,"instanceDataBuffer",null);l(this,"instanceData",new Float32Array(0));l(this,"templateQuadPositions",new Float32Array(0));l(this,"templateQuadIndices",new Uint16Array(0));l(this,"aInstanceOffset",-1);l(this,"aInstanceUVs",-1);l(this,"aInstanceColors",-1);l(this,"uCellSize",null);if(!t)throw new Error("TerminalGL: Parent element is required");if(!Number.isInteger(e.cols)||e.cols<=0)throw new Error(`TerminalGL: Invalid cols: ${e.cols}. Must be a positive integer.`);if(!Number.isInteger(e.rows)||e.rows<=0)throw new Error(`TerminalGL: Invalid rows: ${e.rows}. Must be a positive integer.`);let i=e.cols*e.rows,s=D.checkCompatibility();if(s.errors.length>0)throw new Error(`TerminalGL: WebGL incompatible - ${s.errors.join(", ")}`);let a=e.forceUint16??!1;if(a&&i>s.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds Uint16 limit of ${s.maxCellsUint16} cells. Maximum size with Uint16: ${Math.floor(Math.sqrt(s.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(s.maxCellsUint16))} (or smaller rectangles like 127\xD764)`);if(!s.uint32Indices&&i>s.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds device limit of ${s.maxCellsUint16} cells (OES_element_index_uint not supported). Maximum size: ${Math.floor(Math.sqrt(s.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(s.maxCellsUint16))}`);i>s.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Large terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds recommended limit of ${s.recommendedMaxCells} cells. Performance may be impacted.`),s.warnings.length>0&&console.warn("[TerminalGL] WebGL Compatibility Warnings:",s.warnings);let r=e.charWidth??8,o=e.charHeight??8;if(!Number.isFinite(r)||r<=0)throw new Error(`TerminalGL: Invalid charWidth: ${r}. Must be a positive number.`);if(!Number.isFinite(o)||o<=0)throw new Error(`TerminalGL: Invalid charHeight: ${o}. Must be a positive number.`);for(this.parentElement=t,this.cols=e.cols,this.rows=e.rows,this.charWidth=r,this.charHeight=o,this.canvasBgColor=e.canvasBgColor!==void 0?e.canvasBgColor:null,this.showGrid=e.showGrid??!1,this.scalingMode=e.scalingMode??R.None,e.ambientEffect&&(this.ambientEffectEnabled=!0,typeof e.ambientEffect=="object"&&(this.ambientEffectBlur=e.ambientEffect.blur??W.ambientEffect.blur,this.ambientEffectScale=e.ambientEffect.scale??W.ambientEffect.scale,this.ambientEffectOpacity=e.ambientEffect.opacity??.7));this.parentElement.firstChild;)this.parentElement.removeChild(this.parentElement.firstChild);let n=window.getComputedStyle(this.parentElement).position;n!=="relative"&&n!=="absolute"&&n!=="fixed"&&(this.parentElement.style.position="relative"),this.containerDiv=document.createElement("div"),this.containerDiv.className="terminalgl-container",this.containerDiv.style.cssText=`
8
+ `,this.container.appendChild(this.canvas);let s=this.canvas.getContext("2d");if(!s)throw new Error("[GridOverlay] Impossible de cr\xE9er le contexte 2D");this.ctx=s,e&&(e.strokeColor&&(this.strokeColor=e.strokeColor),e.lineWidth!==void 0&&(this.lineWidth=e.lineWidth))}setDimensions(t,e,i,s,n=0,r=0){this.cols=t,this.rows=e,this.cellWidth=i,this.cellHeight=s,this.offsetX=n,this.offsetY=r}setCanvasSize(t,e){this.canvas.width=t,this.canvas.height=e,this.ctx.setTransform(1,0,0,1,0,0)}setStyle(t){t.strokeColor&&(this.strokeColor=t.strokeColor),t.lineWidth!==void 0&&(this.lineWidth=t.lineWidth)}setTransform(t,e,i,s,n){let r=s.left-n.left,o=s.top-n.top,a=s.width,h=s.height;(this.canvas.width!==a||this.canvas.height!==h)&&(this.canvas.width=a,this.canvas.height=h);let c=this.canvas.style;c.width=`${a}px`,c.height=`${h}px`,c.left=`${r}px`,c.top=`${o}px`}render(){if(!this.ctx)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,i=t>0?this.canvas.width/t:1,s=e>0?this.canvas.height/e:1,n=Math.min(i,s),r=this.cellWidth*n,o=this.cellHeight*n,a=this.cols*r,h=this.rows*o,c=this.offsetX*n,d=this.offsetY*n;if(!(a===0||h===0)){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.strokeStyle=this.strokeColor,this.ctx.lineWidth=Math.max(1,this.lineWidth*n),this.ctx.beginPath();for(let f=0;f<=this.cols;f++){let m=c+f*r+.5;this.ctx.moveTo(m,d),this.ctx.lineTo(m,d+h)}for(let f=0;f<=this.rows;f++){let m=d+f*o+.5;this.ctx.moveTo(c,m),this.ctx.lineTo(c+a,m)}this.ctx.stroke()}}update(t,e,i,s,n,r,o=0,a=0){this.setDimensions(t,e,i,s,o,a),this.setCanvasSize(n,r),this.render()}setVisible(t){this.canvas.style.display=t?"block":"none"}destroy(){this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}getCanvas(){return this.canvas}};v(P,"GridOverlay");var A=P;function M(b){return Math.sqrt(b)*16}v(M,"getAtlasColumns");function S(b){return b*256-1}v(S,"getMaxCharCode");function B(b,t){let e=Math.floor(b/256),i=b%256,s=Math.sqrt(t),n=e%s,r=Math.floor(e/s),o=i%16,a=Math.floor(i/16);return{col:n*16+o,row:r*16+a}}v(B,"getCharGridPosition");import{POST_PROCESS_DEFAULTS as W,ScalingMode as R}from"@utsp/types";var D=class D{constructor(t,e){l(this,"canvas");l(this,"gl");l(this,"parentElement");l(this,"containerDiv");l(this,"cols");l(this,"rows");l(this,"charWidth");l(this,"charHeight");l(this,"cellWidth",8);l(this,"cellHeight",8);l(this,"glyphOffsetX",0);l(this,"glyphOffsetY",0);l(this,"canvasBgColor");l(this,"showGrid");l(this,"supportsUint32Indices",!1);l(this,"useUint16Indices",!1);l(this,"gridOverlay");l(this,"bitmapFont");l(this,"atlasTexture",null);l(this,"atlasCanvas");l(this,"atlasColumns",0);l(this,"fontLoaded",!1);l(this,"paletteTexture",null);l(this,"program",null);l(this,"positionBuffer",null);l(this,"texCoordBuffer",null);l(this,"colorIndexBuffer",null);l(this,"indexBuffer",null);l(this,"aPosition");l(this,"aTexCoord");l(this,"aColorIndex");l(this,"uResolution",null);l(this,"uTexture",null);l(this,"uPalette",null);l(this,"resizeObserver");l(this,"charCodeToAtlasIndex",new Uint16Array(65536).fill(65535));l(this,"atlasUVs",new Float32Array(0));l(this,"cachedAtlasWidth",0);l(this,"cachedAtlasHeight",0);l(this,"paletteFloat",new Float32Array(256*4));l(this,"maxCells",0);l(this,"renderPositions",new Float32Array(0));l(this,"renderTexCoords",new Float32Array(0));l(this,"renderColorIndices",new Float32Array(0));l(this,"renderIndices",new Uint32Array(0));l(this,"cachedResolution",[0,0]);l(this,"cachedTextureUnit",-1);l(this,"cachedPaletteUnit",-1);l(this,"cachedTextureUniform",!1);l(this,"cachedPaletteUniform",!1);l(this,"paletteHash",0);l(this,"currentScale",1);l(this,"scalingMode",R.None);l(this,"ambientEffectEnabled",!1);l(this,"ambientEffectCanvas",null);l(this,"ambientEffectCtx",null);l(this,"ambientEffectBlur",W.ambientEffect.blur);l(this,"ambientEffectScale",W.ambientEffect.scale);l(this,"ambientEffectOpacity",.7);l(this,"onResizeCallback");l(this,"staticPositionsInitialized",!1);l(this,"vaoExtension",null);l(this,"vao",null);l(this,"instancedExtension",null);l(this,"useInstancing",!1);l(this,"instanceDataBuffer",null);l(this,"instanceData",new Float32Array(0));l(this,"templateQuadPositions",new Float32Array(0));l(this,"templateQuadIndices",new Uint16Array(0));l(this,"aInstanceOffset",-1);l(this,"aInstanceUVs",-1);l(this,"aInstanceColors",-1);l(this,"uCellSize",null);if(!t)throw new Error("TerminalGL: Parent element is required");if(!Number.isInteger(e.cols)||e.cols<=0)throw new Error(`TerminalGL: Invalid cols: ${e.cols}. Must be a positive integer.`);if(!Number.isInteger(e.rows)||e.rows<=0)throw new Error(`TerminalGL: Invalid rows: ${e.rows}. Must be a positive integer.`);let i=e.cols*e.rows,s=D.checkCompatibility();if(s.errors.length>0)throw new Error(`TerminalGL: WebGL incompatible - ${s.errors.join(", ")}`);let n=e.forceUint16??!1;if(n&&i>s.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds Uint16 limit of ${s.maxCellsUint16} cells. Maximum size with Uint16: ${Math.floor(Math.sqrt(s.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(s.maxCellsUint16))} (or smaller rectangles like 127\xD764)`);if(!s.uint32Indices&&i>s.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds device limit of ${s.maxCellsUint16} cells (OES_element_index_uint not supported). Maximum size: ${Math.floor(Math.sqrt(s.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(s.maxCellsUint16))}`);i>s.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Large terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds recommended limit of ${s.recommendedMaxCells} cells. Performance may be impacted.`),s.warnings.length>0&&console.warn("[TerminalGL] WebGL Compatibility Warnings:",s.warnings);let r=e.charWidth??8,o=e.charHeight??8;if(!Number.isFinite(r)||r<=0)throw new Error(`TerminalGL: Invalid charWidth: ${r}. Must be a positive number.`);if(!Number.isFinite(o)||o<=0)throw new Error(`TerminalGL: Invalid charHeight: ${o}. Must be a positive number.`);for(this.parentElement=t,this.cols=e.cols,this.rows=e.rows,this.charWidth=r,this.charHeight=o,this.canvasBgColor=e.canvasBgColor!==void 0?e.canvasBgColor:null,this.showGrid=e.showGrid??!1,this.scalingMode=e.scalingMode??R.None,e.ambientEffect&&(this.ambientEffectEnabled=!0,typeof e.ambientEffect=="object"&&(this.ambientEffectBlur=e.ambientEffect.blur??W.ambientEffect.blur,this.ambientEffectScale=e.ambientEffect.scale??W.ambientEffect.scale,this.ambientEffectOpacity=e.ambientEffect.opacity??.7));this.parentElement.firstChild;)this.parentElement.removeChild(this.parentElement.firstChild);let a=window.getComputedStyle(this.parentElement).position;a!=="relative"&&a!=="absolute"&&a!=="fixed"&&(this.parentElement.style.position="relative"),this.containerDiv=document.createElement("div"),this.containerDiv.className="terminalgl-container",this.containerDiv.style.cssText=`
9
9
  position: absolute !important;
10
10
  top: 0 !important;
11
11
  left: 0 !important;
@@ -35,7 +35,7 @@ var it=Object.defineProperty;var at=(b,t,e)=>t in b?it(b,t,{enumerable:!0,config
35
35
  z-index: 1 !important;
36
36
  pointer-events: auto !important;
37
37
  touch-action: none !important;
38
- `;let h=this.canvas.getContext("webgl",{alpha:this.canvasBgColor===null,premultipliedAlpha:!1});if(!h)throw new Error("TerminalGL: WebGL not supported");this.gl=h,this.supportsUint32Indices=!!h.getExtension("OES_element_index_uint"),this.useUint16Indices=a||!this.supportsUint32Indices,this.useUint16Indices?console.warn(`[TerminalGL] \u{1F4CA} Using Uint16 indices (max ${s.maxCellsUint16} cells)`):console.warn(`[TerminalGL] \u{1F4CA} Using Uint32 indices (max ${s.maxCellsUint32} cells)`),this.vaoExtension=h.getExtension("OES_vertex_array_object"),this.vaoExtension&&console.warn("[TerminalGL] \u2705 VAO extension enabled (faster attribute binding)"),this.instancedExtension=h.getExtension("ANGLE_instanced_arrays"),this.instancedExtension?(this.useInstancing=!0,console.warn("[TerminalGL] \u{1F680} Instanced rendering enabled (massive draw call reduction)")):console.warn("[TerminalGL] \u26A0\uFE0F Instanced rendering not available (fallback to standard rendering)"),this.containerDiv.appendChild(this.canvas),this.ambientEffectEnabled&&(this.createAmbientEffectCanvas(),console.warn("[TerminalGL] \u{1F308} Ambient effect enabled at startup")),this.parentElement.appendChild(this.containerDiv),this.initRenderBuffers();try{this.initWebGL()}catch(c){throw console.error("[TerminalGL] \u274C Failed to initialize WebGL:",c),c}this.showGrid&&this.initGridOverlay(),this.setupResizeObserver()}static checkCompatibility(){let t={webgl1:!1,uint32Indices:!1,maxTextureSize:0,maxViewportDims:[0,0],maxCellsUint16:0,maxCellsUint32:0,recommendedMaxCells:0,warnings:[],errors:[]},e=document.createElement("canvas"),i=e.getContext("webgl")||e.getContext("experimental-webgl");if(!i||!(i instanceof WebGLRenderingContext))return t.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),t;let s=i;t.webgl1=!0;try{t.maxTextureSize=s.getParameter(s.MAX_TEXTURE_SIZE);let n=s.getParameter(s.MAX_VIEWPORT_DIMS);t.maxViewportDims=[n[0],n[1]]}catch(n){return t.errors.push(`\u274C Failed to query WebGL parameters: ${n}`),t}let a=s.getExtension("OES_element_index_uint");t.uint32Indices=!!a;let r=8;if(t.maxCellsUint16=Math.floor(65535/r),t.uint32Indices){let n=Math.floor(t.maxTextureSize*t.maxTextureSize/64);t.maxCellsUint32=Math.min(n,262144)}else t.maxCellsUint32=t.maxCellsUint16,t.warnings.push(`\u26A0\uFE0F OES_element_index_uint not supported - limited to ${t.maxCellsUint16} cells (e.g., 90\xD790 or 127\xD764)`);return t.recommendedMaxCells=Math.floor((t.uint32Indices?t.maxCellsUint32:t.maxCellsUint16)*.8),t.maxTextureSize<256?t.errors.push(`\u274C MAX_TEXTURE_SIZE too small: ${t.maxTextureSize} (minimum 256 required for font atlas)`):t.maxTextureSize<2048&&t.warnings.push(`\u26A0\uFE0F Small MAX_TEXTURE_SIZE: ${t.maxTextureSize} (may limit font atlas)`),(t.maxViewportDims[0]<1024||t.maxViewportDims[1]<768)&&t.warnings.push(`\u26A0\uFE0F Small MAX_VIEWPORT_DIMS: ${t.maxViewportDims[0]}\xD7${t.maxViewportDims[1]}`),s.getExtension("WEBGL_lose_context")||t.warnings.push("\u26A0\uFE0F WEBGL_lose_context not supported - may cause memory leaks"),t}initInstancedBuffers(){let t=this.gl;this.templateQuadPositions=new Float32Array([0,0,this.cellWidth,0,0,this.cellHeight,this.cellWidth,this.cellHeight]),this.templateQuadIndices=new Uint16Array([0,1,2,2,1,3]),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.templateQuadPositions,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,this.templateQuadIndices,t.STATIC_DRAW),this.instanceData=new Float32Array(this.maxCells*8),console.warn(`[TerminalGL] \u{1F680} initInstancedBuffers: maxCells=${this.maxCells}, instanceData.length=${this.instanceData.length}`),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer),t.bufferData(t.ARRAY_BUFFER,this.instanceData.byteLength,t.DYNAMIC_DRAW)}initRenderBuffers(){let t=this.cols*this.rows*2;this.maxCells=Math.ceil(t*2),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.staticPositionsInitialized=!1}precomputeStaticPositions(){let t=this.cellWidth,e=this.cellHeight,i=this.glyphOffsetX,s=this.glyphOffsetY,a=this.charWidth,r=this.charHeight,o=0,n=0,h=0;for(let d=0;d<this.rows;d++){let f=Math.round(d*e),m=Math.round(f+e);for(let g=0;g<this.cols;g++){let u=Math.round(g*t),p=Math.round(u+t);this.renderPositions[o++]=u,this.renderPositions[o++]=f,this.renderPositions[o++]=p,this.renderPositions[o++]=f,this.renderPositions[o++]=u,this.renderPositions[o++]=m,this.renderPositions[o++]=p,this.renderPositions[o++]=m,this.renderIndices[n++]=h,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+3,h+=4;let C=Math.round(u+i),x=Math.round(f+s),y=Math.round(C+a),E=Math.round(x+r);this.renderPositions[o++]=C,this.renderPositions[o++]=x,this.renderPositions[o++]=y,this.renderPositions[o++]=x,this.renderPositions[o++]=C,this.renderPositions[o++]=E,this.renderPositions[o++]=y,this.renderPositions[o++]=E,this.renderIndices[n++]=h,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+3,h+=4}}let c=this.gl;c.bindBuffer(c.ARRAY_BUFFER,this.positionBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,this.renderPositions),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,this.indexBuffer),c.bufferSubData(c.ELEMENT_ARRAY_BUFFER,0,this.renderIndices),this.staticPositionsInitialized=!0}initWebGL(){let t=this.gl,e;this.useInstancing?e=`
38
+ `;let h=this.canvas.getContext("webgl",{alpha:this.canvasBgColor===null,premultipliedAlpha:!1});if(!h)throw new Error("TerminalGL: WebGL not supported");this.gl=h,this.supportsUint32Indices=!!h.getExtension("OES_element_index_uint"),this.useUint16Indices=n||!this.supportsUint32Indices,this.useUint16Indices?console.warn(`[TerminalGL] \u{1F4CA} Using Uint16 indices (max ${s.maxCellsUint16} cells)`):console.warn(`[TerminalGL] \u{1F4CA} Using Uint32 indices (max ${s.maxCellsUint32} cells)`),this.vaoExtension=h.getExtension("OES_vertex_array_object"),this.vaoExtension&&console.warn("[TerminalGL] \u2705 VAO extension enabled (faster attribute binding)"),this.instancedExtension=h.getExtension("ANGLE_instanced_arrays"),this.instancedExtension?(this.useInstancing=!0,console.warn("[TerminalGL] \u{1F680} Instanced rendering enabled (massive draw call reduction)")):console.warn("[TerminalGL] \u26A0\uFE0F Instanced rendering not available (fallback to standard rendering)"),this.containerDiv.appendChild(this.canvas),this.ambientEffectEnabled&&(this.createAmbientEffectCanvas(),console.warn("[TerminalGL] \u{1F308} Ambient effect enabled at startup")),this.parentElement.appendChild(this.containerDiv),this.initRenderBuffers();try{this.initWebGL()}catch(c){throw console.error("[TerminalGL] \u274C Failed to initialize WebGL:",c),c}this.showGrid&&this.initGridOverlay(),this.setupResizeObserver()}static checkCompatibility(){let t={webgl1:!1,uint32Indices:!1,maxTextureSize:0,maxViewportDims:[0,0],maxCellsUint16:0,maxCellsUint32:0,recommendedMaxCells:0,warnings:[],errors:[]},e=document.createElement("canvas"),i=e.getContext("webgl")||e.getContext("experimental-webgl");if(!i||!(i instanceof WebGLRenderingContext))return t.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),t;let s=i;t.webgl1=!0;try{t.maxTextureSize=s.getParameter(s.MAX_TEXTURE_SIZE);let a=s.getParameter(s.MAX_VIEWPORT_DIMS);t.maxViewportDims=[a[0],a[1]]}catch(a){return t.errors.push(`\u274C Failed to query WebGL parameters: ${a}`),t}let n=s.getExtension("OES_element_index_uint");t.uint32Indices=!!n;let r=8;if(t.maxCellsUint16=Math.floor(65535/r),t.uint32Indices){let a=Math.floor(t.maxTextureSize*t.maxTextureSize/64);t.maxCellsUint32=Math.min(a,262144)}else t.maxCellsUint32=t.maxCellsUint16,t.warnings.push(`\u26A0\uFE0F OES_element_index_uint not supported - limited to ${t.maxCellsUint16} cells (e.g., 90\xD790 or 127\xD764)`);return t.recommendedMaxCells=Math.floor((t.uint32Indices?t.maxCellsUint32:t.maxCellsUint16)*.8),t.maxTextureSize<256?t.errors.push(`\u274C MAX_TEXTURE_SIZE too small: ${t.maxTextureSize} (minimum 256 required for font atlas)`):t.maxTextureSize<2048&&t.warnings.push(`\u26A0\uFE0F Small MAX_TEXTURE_SIZE: ${t.maxTextureSize} (may limit font atlas)`),(t.maxViewportDims[0]<1024||t.maxViewportDims[1]<768)&&t.warnings.push(`\u26A0\uFE0F Small MAX_VIEWPORT_DIMS: ${t.maxViewportDims[0]}\xD7${t.maxViewportDims[1]}`),s.getExtension("WEBGL_lose_context")||t.warnings.push("\u26A0\uFE0F WEBGL_lose_context not supported - may cause memory leaks"),t}initInstancedBuffers(){let t=this.gl;this.templateQuadPositions=new Float32Array([0,0,this.cellWidth,0,0,this.cellHeight,this.cellWidth,this.cellHeight]),this.templateQuadIndices=new Uint16Array([0,1,2,2,1,3]),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.templateQuadPositions,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,this.templateQuadIndices,t.STATIC_DRAW),this.instanceData=new Float32Array(this.maxCells*8),console.warn(`[TerminalGL] \u{1F680} initInstancedBuffers: maxCells=${this.maxCells}, instanceData.length=${this.instanceData.length}`),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer),t.bufferData(t.ARRAY_BUFFER,this.instanceData.byteLength,t.DYNAMIC_DRAW)}initRenderBuffers(){let t=this.cols*this.rows*2;this.maxCells=Math.ceil(t*2),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.staticPositionsInitialized=!1}precomputeStaticPositions(){let t=this.cellWidth,e=this.cellHeight,i=this.glyphOffsetX,s=this.glyphOffsetY,n=this.charWidth,r=this.charHeight,o=0,a=0,h=0;for(let d=0;d<this.rows;d++){let f=Math.round(d*e),m=Math.round(f+e);for(let g=0;g<this.cols;g++){let u=Math.round(g*t),p=Math.round(u+t);this.renderPositions[o++]=u,this.renderPositions[o++]=f,this.renderPositions[o++]=p,this.renderPositions[o++]=f,this.renderPositions[o++]=u,this.renderPositions[o++]=m,this.renderPositions[o++]=p,this.renderPositions[o++]=m,this.renderIndices[a++]=h,this.renderIndices[a++]=h+1,this.renderIndices[a++]=h+2,this.renderIndices[a++]=h+2,this.renderIndices[a++]=h+1,this.renderIndices[a++]=h+3,h+=4;let C=Math.round(u+i),x=Math.round(f+s),y=Math.round(C+n),E=Math.round(x+r);this.renderPositions[o++]=C,this.renderPositions[o++]=x,this.renderPositions[o++]=y,this.renderPositions[o++]=x,this.renderPositions[o++]=C,this.renderPositions[o++]=E,this.renderPositions[o++]=y,this.renderPositions[o++]=E,this.renderIndices[a++]=h,this.renderIndices[a++]=h+1,this.renderIndices[a++]=h+2,this.renderIndices[a++]=h+2,this.renderIndices[a++]=h+1,this.renderIndices[a++]=h+3,h+=4}}let c=this.gl;c.bindBuffer(c.ARRAY_BUFFER,this.positionBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,this.renderPositions),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,this.indexBuffer),c.bufferSubData(c.ELEMENT_ARRAY_BUFFER,0,this.renderIndices),this.staticPositionsInitialized=!0}initWebGL(){let t=this.gl,e;this.useInstancing?e=`
39
39
  // Per-vertex attributes (template quad)
40
40
  attribute vec2 aPosition; // Local quad position (0,0 to cellW,cellH)
41
41
 
@@ -116,7 +116,7 @@ var it=Object.defineProperty;var at=(b,t,e)=>t in b?it(b,t,{enumerable:!0,config
116
116
  gl_FragColor = vec4(texColor.rgb * vColor.rgb, texColor.a);
117
117
  }
118
118
  }
119
- `,s=this.compileShader(t.VERTEX_SHADER,e),a=this.compileShader(t.FRAGMENT_SHADER,i);if(!s||!a)throw new Error("Shader compilation error");let r=t.createProgram();if(!r)throw new Error("Unable to create WebGL program");if(t.attachShader(r,s),t.attachShader(r,a),t.linkProgram(r),!t.getProgramParameter(r,t.LINK_STATUS)){let o=t.getProgramInfoLog(r);throw new Error("Program linking error: "+o)}this.program=r,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=t.getAttribLocation(r,"aPosition"),this.useInstancing?(this.aInstanceOffset=t.getAttribLocation(r,"aInstanceOffset"),this.aInstanceUVs=t.getAttribLocation(r,"aInstanceUVs"),this.aInstanceColors=t.getAttribLocation(r,"aInstanceColors"),this.uCellSize=t.getUniformLocation(r,"uCellSize"),this.instanceDataBuffer=t.createBuffer(),this.aTexCoord=this.aInstanceOffset,this.aColorIndex=this.aInstanceUVs):(this.aTexCoord=t.getAttribLocation(r,"aTexCoord"),this.aColorIndex=t.getAttribLocation(r,"aColorIndex")),this.uResolution=t.getUniformLocation(r,"uResolution"),this.uTexture=t.getUniformLocation(r,"uTexture"),this.uPalette=t.getUniformLocation(r,"uPalette"),this.positionBuffer=t.createBuffer(),this.texCoordBuffer=t.createBuffer(),this.colorIndexBuffer=t.createBuffer(),this.indexBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.renderPositions.byteLength,t.DYNAMIC_DRAW),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferData(t.ARRAY_BUFFER,this.renderTexCoords.byteLength,t.DYNAMIC_DRAW),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferData(t.ARRAY_BUFFER,this.renderColorIndices.byteLength,t.DYNAMIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,t.DYNAMIC_DRAW),this.vaoExtension&&(this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.enableVertexAttribArray(this.aTexCoord),t.vertexAttribPointer(this.aTexCoord,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.enableVertexAttribArray(this.aColorIndex),t.vertexAttribPointer(this.aColorIndex,1,t.FLOAT,!1,0,0),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null))),t.enable(t.BLEND),t.blendFunc(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA),t.viewport(0,0,this.canvas.width,this.canvas.height)}compileShader(t,e){let i=this.gl,s=i.createShader(t);return s?(i.shaderSource(s,e),i.compileShader(s),i.getShaderParameter(s,i.COMPILE_STATUS)?s:(console.error("Shader compilation error:",i.getShaderInfoLog(s)),i.deleteShader(s),null)):null}initGridOverlay(){this.gridOverlay=new A(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,i=this.canvas.getBoundingClientRect(),s=this.containerDiv.getBoundingClientRect();this.gridOverlay.setDimensions(this.cols,this.rows,this.cellWidth,this.cellHeight,0,0),this.gridOverlay.setTransform(this.currentScale,t,e,i,s),this.gridOverlay.render()}setBitmapFont(t,e,i,s,a){this.bitmapFont=t,this.fontLoaded=!0,this.charWidth=Math.round(e),this.charHeight=Math.round(i),this.cellWidth=Math.round(s),this.cellHeight=Math.round(a),this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers..."),this.initInstancedBuffers());try{this.generateAtlas()}catch(r){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",r),r}this.buildCharCodeMap(),this.precomputeAtlasUVs(),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async setImageFont(t,e,i,s,a,r){this.fontLoaded=!0,this.charWidth=Math.round(e),this.charHeight=Math.round(i),this.cellWidth=Math.round(s),this.cellHeight=Math.round(a),this.atlasColumns=M(r);let o=S(r);this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers for ImageFont..."),this.initInstancedBuffers()),await this.loadImageFontAtlas(t),this.charCodeToAtlasIndex.fill(65535);for(let n=0;n<=o;n++)this.charCodeToAtlasIndex[n]=n;this.precomputeImageFontUVs(r),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async loadImageFontAtlas(t){return new Promise((e,i)=>{let s=new Uint8Array(t),a=new Blob([s],{type:"image/png"}),r=URL.createObjectURL(a),o=new Image;o.onload=()=>{URL.revokeObjectURL(r),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=o.width,this.atlasCanvas.height=o.height;let n=this.atlasCanvas.getContext("2d");if(!n){i(new Error("Failed to create 2D context for atlas"));return}n.drawImage(o,0,0),this.cachedAtlasWidth=o.width,this.cachedAtlasHeight=o.height,this.createAtlasTexture(),e()},o.onerror=()=>{URL.revokeObjectURL(r),i(new Error("Failed to load PNG image for ImageFont atlas"))},o.src=r})}precomputeImageFontUVs(t){let e=t*256;this.atlasUVs=new Float32Array(e*4);let i=this.cachedAtlasWidth,s=this.cachedAtlasHeight,a=.5/i,r=.5/s;for(let o=0;o<e;o++){let{col:n,row:h}=B(o,t),c=(n*this.charWidth+a)/i,d=(h*this.charHeight+r)/s,f=((n+1)*this.charWidth-a)/i,m=((h+1)*this.charHeight-r)/s,g=o*4;this.atlasUVs[g]=c,this.atlasUVs[g+1]=d,this.atlasUVs[g+2]=f,this.atlasUVs[g+3]=m}}generateAtlas(){if(!this.bitmapFont)return;let t=Array.from(this.bitmapFont.keys()).sort((n,h)=>n-h),e=t.length;this.atlasColumns=Math.ceil(Math.sqrt(e));let i=Math.ceil(e/this.atlasColumns),s=this.atlasColumns*this.charWidth,a=i*this.charHeight;this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=s,this.atlasCanvas.height=a;let r=this.atlasCanvas.getContext("2d");if(!r)throw new Error("Unable to create 2D context for atlas");r.clearRect(0,0,s,a),r.fillStyle="#ffffff";let o=0;for(let n of t){let h=this.bitmapFont.get(n);if(!h)continue;let c=o%this.atlasColumns,d=Math.floor(o/this.atlasColumns),f=c*this.charWidth,m=d*this.charHeight;for(let g=0;g<Math.min(h.length,this.charHeight);g++){let u=h[g];for(let p=0;p<this.charWidth;p++){let C=1<<7-p;u&C&&r.fillRect(f+p,m+g,1,1)}}o++}this.createAtlasTexture()}buildCharCodeMap(){if(!this.bitmapFont)return;this.charCodeToAtlasIndex.fill(65535);let t=Array.from(this.bitmapFont.keys()).sort((e,i)=>e-i);for(let e=0;e<t.length;e++)this.charCodeToAtlasIndex[t[e]]=e}precomputeAtlasUVs(){if(!this.bitmapFont)return;let t=this.bitmapFont.size;this.atlasUVs=new Float32Array(t*4),this.cachedAtlasWidth=this.atlasColumns*this.charWidth,this.cachedAtlasHeight=Math.ceil(t/this.atlasColumns)*this.charHeight;let e=this.cachedAtlasWidth,i=this.cachedAtlasHeight,s=.5/e,a=.5/i;for(let r=0;r<t;r++){let o=r%this.atlasColumns,n=Math.floor(r/this.atlasColumns),h=(o*this.charWidth+s)/e,c=(n*this.charHeight+a)/i,d=((o+1)*this.charWidth-s)/e,f=((n+1)*this.charHeight-a)/i,m=r*4;this.atlasUVs[m]=h,this.atlasUVs[m+1]=c,this.atlasUVs[m+2]=d,this.atlasUVs[m+3]=f}}createAtlasTexture(){if(this.atlasCanvas)try{let t=this.gl,e=t.createTexture();if(!e)throw new Error("Unable to create texture");t.bindTexture(t.TEXTURE_2D,e),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,this.atlasCanvas),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),this.atlasTexture=e}catch(t){throw console.error("[TerminalGL] \u274C Failed to create atlas texture:",t),t}}clear(){let t=this.gl;t&&t.clear(t.COLOR_BUFFER_BIT)}parseColor(t){if(t.startsWith("#")){let e=t.slice(1),i=0,s=0,a=0;return e.length===3?(i=parseInt(e[0]+e[0],16),s=parseInt(e[1]+e[1],16),a=parseInt(e[2]+e[2],16)):e.length===6&&(i=parseInt(e.slice(0,2),16),s=parseInt(e.slice(2,4),16),a=parseInt(e.slice(4,6),16)),[i/255,s/255,a/255,1]}if(t.startsWith("rgb")){let e=t.match(/rgba?\(([^)]+)\)/);if(e){let i=e[1].split(",").map(s=>parseFloat(s.trim()));return[i[0]/255,i[1]/255,i[2]/255,i[3]!==void 0?i[3]:1]}}return[1,1,1,1]}setupResizeObserver(){if(!(typeof ResizeObserver>"u"))try{this.resizeObserver=new ResizeObserver(()=>{try{this.updateCanvasSize()}catch(t){console.error("[TerminalGL] \u274C Error in resize callback:",t)}}),this.resizeObserver.observe(this.parentElement),this.updateCanvasSize()}catch(t){console.error("[TerminalGL] \u274C Failed to setup ResizeObserver:",t)}}updateCanvasSize(){let t=this.parentElement.clientWidth,e=this.parentElement.clientHeight;if(t===0||e===0)return;let i=this.cols*this.cellWidth,s=this.rows*this.cellHeight;if(i===0||s===0)return;let a=t/i,r=e/s,o=Math.min(a,r),n;switch(this.scalingMode){case R.Integer:n=Math.max(1,Math.floor(o));break;case R.Half:n=Math.max(1,Math.floor(o*2)/2);break;case R.Quarter:n=Math.max(1,Math.floor(o*4)/4);break;case R.Eighth:n=Math.max(1,Math.floor(o*8)/8);break;case R.Responsive:n=1;break;case R.None:default:n=Math.max(.1,o);break}if(this.canvas.style.transform=`scale(${n})`,this.ambientEffectEnabled&&this.ambientEffectCanvas){let h=n*this.ambientEffectScale;this.ambientEffectCanvas.style.transform=`scale(${h})`}this.currentScale=n,this.onResizeCallback&&this.onResizeCallback(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}updateAmbientEffect(){!this.ambientEffectCanvas||!this.ambientEffectCtx||this.ambientEffectCtx.drawImage(this.canvas,0,0)}setPalette(t){let e=0;for(let i=0;i<Math.min(t.length,256);i++){let s=t[i];e=(e<<5)-e+s.r,e=(e<<5)-e+s.g,e=(e<<5)-e+s.b,e=(e<<5)-e+s.a,e=e|0}if(e!==this.paletteHash){this.paletteHash=e;for(let i=0;i<t.length&&i<256;i++){let s=t[i],a=i*4;this.paletteFloat[a]=s.r/255,this.paletteFloat[a+1]=s.g/255,this.paletteFloat[a+2]=s.b/255,this.paletteFloat[a+3]=s.a/255}this.updatePaletteTexture()}}updatePaletteTexture(){try{let t=this.gl;this.paletteTexture||(this.paletteTexture=t.createTexture()),t.bindTexture(t.TEXTURE_2D,this.paletteTexture);let e=new Uint8Array(256*4);for(let i=0;i<256;i++){let s=i*4;e[s]=this.paletteFloat[s]*255,e[s+1]=this.paletteFloat[s+1]*255,e[s+2]=this.paletteFloat[s+2]*255,e[s+3]=this.paletteFloat[s+3]*255}t.texImage2D(t.TEXTURE_2D,0,t.RGBA,256,1,0,t.RGBA,t.UNSIGNED_BYTE,e),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.bindTexture(t.TEXTURE_2D,null)}catch(t){throw console.error("[TerminalGL] \u274C Failed to update palette texture:",t),t}}renderDisplayData(t){try{if(!this.isReady()){console.warn("[TerminalGL] \u26A0\uFE0F Not ready: font not loaded yet");return}(t.width!==this.cols||t.height!==this.rows)&&this.resize(t.width,t.height),this.renderDirect(t),this.ambientEffectEnabled&&this.ambientEffectCanvas&&this.ambientEffectCtx&&this.updateAmbientEffect()}catch(e){console.error("[TerminalGL] \u274C Error rendering display data:",e)}}renderDirect(t){let e=this.gl;if(!this.staticPositionsInitialized&&!this.useInstancing&&this.precomputeStaticPositions(),this.canvasBgColor!==null){let i=this.parseColor(this.canvasBgColor);e.clearColor(i[0],i[1],i[2],i[3])}else e.clearColor(0,0,0,0);e.clear(e.COLOR_BUFFER_BIT),this.useInstancing?this.renderInstanced(t):this.renderDirectBuffers(t)}renderInstanced(t){let e=this.gl,i=this.instancedExtension;if(!this.instanceData||this.instanceData.length===0){console.warn("[TerminalGL] \u26A0\uFE0F Instance data not initialized, falling back to standard rendering"),this.renderDirectBuffers(t);return}let s=0,a=this.instanceData.length/8,r=t.width*t.height*2;if(r>a){console.error(`[TerminalGL] \u274C Instance buffer too small! Need ${r}, have ${a}. Display size: ${t.width}\xD7${t.height}, buffer was sized for smaller terminal.`),this.renderDirectBuffers(t);return}for(let n=0;n<t.height;n++)for(let h=0;h<t.width;h++){let c=t.cells[n*t.width+h],d=c.bgColorIndex,f=c.fgColorIndex,m=this.canvasBgColor!==null&&d===255,g=c.char===" "||f===255;if(!m){if(s>=a){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${a}`);break}let u=s*8;this.instanceData[u]=h,this.instanceData[u+1]=n,this.instanceData[u+2]=0,this.instanceData[u+3]=0,this.instanceData[u+4]=0,this.instanceData[u+5]=0,this.instanceData[u+6]=d,this.instanceData[u+7]=0,s++}if(!g){let u=c.char.charCodeAt(0),p=this.charCodeToAtlasIndex[u];if(p!==65535){if(s>=a){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${a}`);break}let C=p*4,x=s*8;this.instanceData[x]=h,this.instanceData[x+1]=n,this.instanceData[x+2]=this.atlasUVs[C],this.instanceData[x+3]=this.atlasUVs[C+1],this.instanceData[x+4]=this.atlasUVs[C+2],this.instanceData[x+5]=this.atlasUVs[C+3],this.instanceData[x+6]=0,this.instanceData[x+7]=f,s++}}}if(s===0){console.warn("[TerminalGL] \u26A0\uFE0F No instances to draw (all cells skipped)");return}e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.instanceData.subarray(0,s*8)),e.useProgram(this.program),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),i.vertexAttribDivisorANGLE(this.aPosition,0),e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer);let o=8*Float32Array.BYTES_PER_ELEMENT;e.enableVertexAttribArray(this.aInstanceOffset),e.vertexAttribPointer(this.aInstanceOffset,2,e.FLOAT,!1,o,0),i.vertexAttribDivisorANGLE(this.aInstanceOffset,1),e.enableVertexAttribArray(this.aInstanceUVs),e.vertexAttribPointer(this.aInstanceUVs,4,e.FLOAT,!1,o,2*Float32Array.BYTES_PER_ELEMENT),i.vertexAttribDivisorANGLE(this.aInstanceUVs,1),e.enableVertexAttribArray(this.aInstanceColors),e.vertexAttribPointer(this.aInstanceColors,2,e.FLOAT,!1,o,6*Float32Array.BYTES_PER_ELEMENT),i.vertexAttribDivisorANGLE(this.aInstanceColors,1),e.uniform2f(this.uResolution,this.canvas.width,this.canvas.height),e.uniform2f(this.uCellSize,this.cellWidth,this.cellHeight),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,this.atlasTexture),e.uniform1i(this.uTexture,0),e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,this.paletteTexture),e.uniform1i(this.uPalette,1),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),i.drawElementsInstancedANGLE(e.TRIANGLES,6,e.UNSIGNED_SHORT,0,s),i.vertexAttribDivisorANGLE(this.aPosition,0),i.vertexAttribDivisorANGLE(this.aInstanceOffset,0),i.vertexAttribDivisorANGLE(this.aInstanceUVs,0),i.vertexAttribDivisorANGLE(this.aInstanceColors,0)}renderDirectBuffers(t){let e=this.gl,i=t.width*t.height,s=i*2;if(s>this.maxCells){console.error(`[TerminalGL] \u274C Buffer overflow detected! Trying to render ${s} quads but buffer capacity is ${this.maxCells}. This should not happen - resize() should have reallocated.`);return}let a=0,r=0,o=t.cells,n=i;for(let g=0;g<n;g++){let u=o[g],p=u.bgColorIndex,x=this.canvasBgColor!==null&&p===255?255:p,y=0;for(let w=0;w<4;w++)this.renderTexCoords[a++]=y,this.renderTexCoords[a++]=y,this.renderColorIndices[r++]=x;let E=u.fgColorIndex,L=u.char;if(L===" "||E===255)for(let w=0;w<4;w++)this.renderTexCoords[a++]=0,this.renderTexCoords[a++]=0,this.renderColorIndices[r++]=255;else{let w=L.charCodeAt(0),Z=this.charCodeToAtlasIndex[w];if(Z!==65535){let I=Z*4,K=this.atlasUVs[I],J=this.atlasUVs[I+1],tt=this.atlasUVs[I+2],et=this.atlasUVs[I+3];this.renderTexCoords[a++]=K,this.renderTexCoords[a++]=J,this.renderColorIndices[r++]=E,this.renderTexCoords[a++]=tt,this.renderTexCoords[a++]=J,this.renderColorIndices[r++]=E,this.renderTexCoords[a++]=K,this.renderTexCoords[a++]=et,this.renderColorIndices[r++]=E,this.renderTexCoords[a++]=tt,this.renderTexCoords[a++]=et,this.renderColorIndices[r++]=E}else for(let I=0;I<4;I++)this.renderTexCoords[a++]=0,this.renderTexCoords[a++]=0,this.renderColorIndices[r++]=255}}(a!==n*2*4*2||r!==n*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:a,colorIdx:r,expected:n*2*4}),e.useProgram(this.program),this.vao&&this.vaoExtension?(this.vaoExtension.bindVertexArrayOES(this.vao),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,a)),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,r))):(e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,a)),e.enableVertexAttribArray(this.aTexCoord),e.vertexAttribPointer(this.aTexCoord,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,r)),e.enableVertexAttribArray(this.aColorIndex),e.vertexAttribPointer(this.aColorIndex,1,e.FLOAT,!1,0,0));let h=this.canvas.width,c=this.canvas.height;(this.cachedResolution[0]!==h||this.cachedResolution[1]!==c)&&(e.uniform2f(this.uResolution,h,c),this.cachedResolution[0]=h,this.cachedResolution[1]=c),this.cachedTextureUnit!==0&&(e.activeTexture(e.TEXTURE0),this.cachedTextureUnit=0),e.bindTexture(e.TEXTURE_2D,this.atlasTexture),this.cachedTextureUniform||(e.uniform1i(this.uTexture,0),this.cachedTextureUniform=!0),this.cachedPaletteUnit!==1&&(e.activeTexture(e.TEXTURE1),this.cachedPaletteUnit=1),e.bindTexture(e.TEXTURE_2D,this.paletteTexture),this.cachedPaletteUniform||(e.uniform1i(this.uPalette,1),this.cachedPaletteUniform=!0),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer);let f=t.width*t.height*2*6,m=this.useUint16Indices?e.UNSIGNED_SHORT:e.UNSIGNED_INT;e.drawElements(e.TRIANGLES,f,m,0)}resize(t,e){if(!Number.isInteger(t)||t<=0){console.error(`[TerminalGL] \u274C Invalid cols: ${t}. Must be positive integer.`);return}if(!Number.isInteger(e)||e<=0){console.error(`[TerminalGL] \u274C Invalid rows: ${e}. Must be positive integer.`);return}if(t===this.cols&&e===this.rows)return;let i=t*e,s=this.useInstancing?262144:this.useUint16Indices?8191:262144;if(i>s){let c=Math.floor(Math.sqrt(s));console.error(`[TerminalGL] \u274C Cannot resize to ${t}\xD7${e} (${i} cells). Device limit: ${s} cells (max ~${c}\xD7${c}). ${!this.useInstancing&&this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let a=D.checkCompatibility();i>a.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${t}\xD7${e} (${i} cells) exceeds recommended limit (${a.recommendedMaxCells} cells). Performance may degrade.`),this.cols=t,this.rows=e,this.staticPositionsInitialized=!1;let r=this.cols*this.rows*2,o=Math.ceil(r*1.5),n=r>this.maxCells,h=this.maxCells>o*4;if(console.warn(`[TerminalGL] \u{1F4D0} resize check: cols=${t}, rows=${e}, newMaxCells=${r}, this.maxCells=${this.maxCells}, needGrow=${n}, needShrink=${h}`),n||h){let c=this.maxCells;if(this.maxCells=o,console.warn(`[TerminalGL] \u{1F4D0} resize realloc: ${c} \u2192 ${this.maxCells} (needGrow=${n}, needShrink=${h})`),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.useInstancing&&this.instanceDataBuffer){this.instanceData=new Float32Array(this.maxCells*8);let u=this.gl;u.bindBuffer(u.ARRAY_BUFFER,this.instanceDataBuffer),u.bufferData(u.ARRAY_BUFFER,this.instanceData.byteLength,u.DYNAMIC_DRAW)}let d=this.gl;this.useInstancing||(d.bindBuffer(d.ARRAY_BUFFER,this.positionBuffer),d.bufferData(d.ARRAY_BUFFER,this.renderPositions.byteLength,d.DYNAMIC_DRAW)),d.bindBuffer(d.ARRAY_BUFFER,this.texCoordBuffer),d.bufferData(d.ARRAY_BUFFER,this.renderTexCoords.byteLength,d.DYNAMIC_DRAW),d.bindBuffer(d.ARRAY_BUFFER,this.colorIndexBuffer),d.bufferData(d.ARRAY_BUFFER,this.renderColorIndices.byteLength,d.DYNAMIC_DRAW),this.useInstancing||(d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,this.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,d.DYNAMIC_DRAW)),this.vaoExtension&&this.vao&&(this.vaoExtension.deleteVertexArrayOES(this.vao),this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),d.bindBuffer(d.ARRAY_BUFFER,this.positionBuffer),d.enableVertexAttribArray(this.aPosition),d.vertexAttribPointer(this.aPosition,2,d.FLOAT,!1,0,0),d.bindBuffer(d.ARRAY_BUFFER,this.texCoordBuffer),d.enableVertexAttribArray(this.aTexCoord),d.vertexAttribPointer(this.aTexCoord,2,d.FLOAT,!1,0,0),d.bindBuffer(d.ARRAY_BUFFER,this.colorIndexBuffer),d.enableVertexAttribArray(this.aColorIndex),d.vertexAttribPointer(this.aColorIndex,1,d.FLOAT,!1,0,0),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null)));let f=n?"\u{1F4C8} Growing":"\u{1F4C9} Shrinking",m=c*160/1048576,g=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${f} buffers: ${m.toFixed(2)}MB \u2192 ${g.toFixed(2)}MB (${c} \u2192 ${this.maxCells} quads)`)}this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.canvas.style.width=`${this.canvas.width}px`,this.canvas.style.height=`${this.canvas.height}px`,this.ambientEffectEnabled&&this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.width=`${this.canvas.width}px`,this.ambientEffectCanvas.style.height=`${this.canvas.height}px`),this.showGrid&&this.gridOverlay&&this.updateGridOverlay(),this.updateCanvasSize()}getCanvas(){return this.canvas}getGridSize(){return{cols:this.cols,rows:this.rows}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getBaseDimensions(){return{width:this.cols*this.cellWidth,height:this.rows*this.cellHeight}}setOnResizeCallback(t){this.onResizeCallback=t}clearOnResizeCallback(){this.onResizeCallback=void 0}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}setScalingMode(t){this.scalingMode!==t&&(this.scalingMode=t,this.updateCanvasSize())}getScalingMode(){return this.scalingMode}setCellSize(t,e){let i=Math.max(1,Math.min(255,Math.round(t))),s=Math.max(1,Math.min(255,Math.round(e)));this.cellWidth===i&&this.cellHeight===s||(this.cellWidth=i,this.cellHeight=s,this.charWidth=i,this.charHeight=s,this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.fontLoaded&&this.generateAtlas(),this.useInstancing&&this.initInstancedBuffers(),this.updateCanvasSize())}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getMaxCells(){return this.useInstancing?262144:this.useUint16Indices?8191:262144}setGrid(t){t.enabled?(this.gridOverlay?this.gridOverlay.setStyle({strokeColor:t.color,lineWidth:t.lineWidth}):this.gridOverlay=new A(this.containerDiv,{strokeColor:t.color??"rgba(144, 24, 24, 1)",lineWidth:t.lineWidth??1,zIndex:10}),this.showGrid=!0,this.gridOverlay.setVisible(!0),this.updateGridOverlay()):(this.showGrid=!1,this.gridOverlay&&this.gridOverlay.setVisible(!1))}isGridEnabled(){return this.showGrid}setAmbientEffect(t){typeof t=="boolean"?this.ambientEffectEnabled=t:(this.ambientEffectEnabled=!0,t.blur!==void 0&&(this.ambientEffectBlur=t.blur),t.scale!==void 0&&(this.ambientEffectScale=t.scale)),this.ambientEffectEnabled&&!this.ambientEffectCanvas&&this.createAmbientEffectCanvas(),this.ambientEffectCanvas&&(this.ambientEffectEnabled?(this.ambientEffectCanvas.style.display="block",this.ambientEffectCanvas.style.filter=`blur(${this.ambientEffectBlur}px)`,this.ambientEffectCanvas.style.transform=`scale(${this.ambientEffectScale})`,this.updateAmbientEffect()):this.ambientEffectCanvas.style.display="none")}createAmbientEffectCanvas(){this.ambientEffectCanvas||(this.ambientEffectCanvas=document.createElement("canvas"),this.ambientEffectCanvas.className="terminalgl-ambient-effect-canvas",this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.cssText=`
119
+ `,s=this.compileShader(t.VERTEX_SHADER,e),n=this.compileShader(t.FRAGMENT_SHADER,i);if(!s||!n)throw new Error("Shader compilation error");let r=t.createProgram();if(!r)throw new Error("Unable to create WebGL program");if(t.attachShader(r,s),t.attachShader(r,n),t.linkProgram(r),!t.getProgramParameter(r,t.LINK_STATUS)){let o=t.getProgramInfoLog(r);throw new Error("Program linking error: "+o)}this.program=r,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=t.getAttribLocation(r,"aPosition"),this.useInstancing?(this.aInstanceOffset=t.getAttribLocation(r,"aInstanceOffset"),this.aInstanceUVs=t.getAttribLocation(r,"aInstanceUVs"),this.aInstanceColors=t.getAttribLocation(r,"aInstanceColors"),this.uCellSize=t.getUniformLocation(r,"uCellSize"),this.instanceDataBuffer=t.createBuffer(),this.aTexCoord=this.aInstanceOffset,this.aColorIndex=this.aInstanceUVs):(this.aTexCoord=t.getAttribLocation(r,"aTexCoord"),this.aColorIndex=t.getAttribLocation(r,"aColorIndex")),this.uResolution=t.getUniformLocation(r,"uResolution"),this.uTexture=t.getUniformLocation(r,"uTexture"),this.uPalette=t.getUniformLocation(r,"uPalette"),this.positionBuffer=t.createBuffer(),this.texCoordBuffer=t.createBuffer(),this.colorIndexBuffer=t.createBuffer(),this.indexBuffer=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.renderPositions.byteLength,t.DYNAMIC_DRAW),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferData(t.ARRAY_BUFFER,this.renderTexCoords.byteLength,t.DYNAMIC_DRAW),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferData(t.ARRAY_BUFFER,this.renderColorIndices.byteLength,t.DYNAMIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,t.DYNAMIC_DRAW),this.vaoExtension&&(this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.enableVertexAttribArray(this.aTexCoord),t.vertexAttribPointer(this.aTexCoord,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.enableVertexAttribArray(this.aColorIndex),t.vertexAttribPointer(this.aColorIndex,1,t.FLOAT,!1,0,0),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null))),t.enable(t.BLEND),t.blendFunc(t.SRC_ALPHA,t.ONE_MINUS_SRC_ALPHA),t.viewport(0,0,this.canvas.width,this.canvas.height)}compileShader(t,e){let i=this.gl,s=i.createShader(t);return s?(i.shaderSource(s,e),i.compileShader(s),i.getShaderParameter(s,i.COMPILE_STATUS)?s:(console.error("Shader compilation error:",i.getShaderInfoLog(s)),i.deleteShader(s),null)):null}initGridOverlay(){this.gridOverlay=new A(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,i=this.canvas.getBoundingClientRect(),s=this.containerDiv.getBoundingClientRect();this.gridOverlay.setDimensions(this.cols,this.rows,this.cellWidth,this.cellHeight,0,0),this.gridOverlay.setTransform(this.currentScale,t,e,i,s),this.gridOverlay.render()}setBitmapFont(t,e,i,s,n){this.bitmapFont=t,this.fontLoaded=!0,this.charWidth=Math.round(e),this.charHeight=Math.round(i),this.cellWidth=Math.round(s),this.cellHeight=Math.round(n),this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers..."),this.initInstancedBuffers());try{this.generateAtlas()}catch(r){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",r),r}this.buildCharCodeMap(),this.precomputeAtlasUVs(),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async setImageFont(t,e,i,s,n,r){this.fontLoaded=!0,this.charWidth=Math.round(e),this.charHeight=Math.round(i),this.cellWidth=Math.round(s),this.cellHeight=Math.round(n),this.atlasColumns=M(r);let o=S(r);this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers for ImageFont..."),this.initInstancedBuffers()),await this.loadImageFontAtlas(t),this.charCodeToAtlasIndex.fill(65535);for(let a=0;a<=o;a++)this.charCodeToAtlasIndex[a]=a;this.precomputeImageFontUVs(r),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async loadImageFontAtlas(t){return new Promise((e,i)=>{let s=new Uint8Array(t),n=new Blob([s],{type:"image/png"}),r=URL.createObjectURL(n),o=new Image;o.onload=()=>{URL.revokeObjectURL(r),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=o.width,this.atlasCanvas.height=o.height;let a=this.atlasCanvas.getContext("2d");if(!a){i(new Error("Failed to create 2D context for atlas"));return}a.drawImage(o,0,0),this.cachedAtlasWidth=o.width,this.cachedAtlasHeight=o.height,this.createAtlasTexture(),e()},o.onerror=()=>{URL.revokeObjectURL(r),i(new Error("Failed to load PNG image for ImageFont atlas"))},o.src=r})}precomputeImageFontUVs(t){let e=t*256;this.atlasUVs=new Float32Array(e*4);let i=this.cachedAtlasWidth,s=this.cachedAtlasHeight,n=.5/i,r=.5/s;for(let o=0;o<e;o++){let{col:a,row:h}=B(o,t),c=(a*this.charWidth+n)/i,d=(h*this.charHeight+r)/s,f=((a+1)*this.charWidth-n)/i,m=((h+1)*this.charHeight-r)/s,g=o*4;this.atlasUVs[g]=c,this.atlasUVs[g+1]=d,this.atlasUVs[g+2]=f,this.atlasUVs[g+3]=m}}generateAtlas(){if(!this.bitmapFont)return;let t=Array.from(this.bitmapFont.keys()).sort((a,h)=>a-h),e=t.length;this.atlasColumns=Math.ceil(Math.sqrt(e));let i=Math.ceil(e/this.atlasColumns),s=this.atlasColumns*this.charWidth,n=i*this.charHeight;this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=s,this.atlasCanvas.height=n;let r=this.atlasCanvas.getContext("2d");if(!r)throw new Error("Unable to create 2D context for atlas");r.clearRect(0,0,s,n),r.fillStyle="#ffffff";let o=0;for(let a of t){let h=this.bitmapFont.get(a);if(!h)continue;let c=o%this.atlasColumns,d=Math.floor(o/this.atlasColumns),f=c*this.charWidth,m=d*this.charHeight;for(let g=0;g<Math.min(h.length,this.charHeight);g++){let u=h[g];for(let p=0;p<this.charWidth;p++){let C=1<<7-p;u&C&&r.fillRect(f+p,m+g,1,1)}}o++}this.createAtlasTexture()}buildCharCodeMap(){if(!this.bitmapFont)return;this.charCodeToAtlasIndex.fill(65535);let t=Array.from(this.bitmapFont.keys()).sort((e,i)=>e-i);for(let e=0;e<t.length;e++)this.charCodeToAtlasIndex[t[e]]=e}precomputeAtlasUVs(){if(!this.bitmapFont)return;let t=this.bitmapFont.size;this.atlasUVs=new Float32Array(t*4),this.cachedAtlasWidth=this.atlasColumns*this.charWidth,this.cachedAtlasHeight=Math.ceil(t/this.atlasColumns)*this.charHeight;let e=this.cachedAtlasWidth,i=this.cachedAtlasHeight,s=.5/e,n=.5/i;for(let r=0;r<t;r++){let o=r%this.atlasColumns,a=Math.floor(r/this.atlasColumns),h=(o*this.charWidth+s)/e,c=(a*this.charHeight+n)/i,d=((o+1)*this.charWidth-s)/e,f=((a+1)*this.charHeight-n)/i,m=r*4;this.atlasUVs[m]=h,this.atlasUVs[m+1]=c,this.atlasUVs[m+2]=d,this.atlasUVs[m+3]=f}}createAtlasTexture(){if(this.atlasCanvas)try{let t=this.gl,e=t.createTexture();if(!e)throw new Error("Unable to create texture");t.bindTexture(t.TEXTURE_2D,e),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,this.atlasCanvas),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),this.atlasTexture=e}catch(t){throw console.error("[TerminalGL] \u274C Failed to create atlas texture:",t),t}}clear(){let t=this.gl;t&&t.clear(t.COLOR_BUFFER_BIT)}parseColor(t){if(t.startsWith("#")){let e=t.slice(1),i=0,s=0,n=0;return e.length===3?(i=parseInt(e[0]+e[0],16),s=parseInt(e[1]+e[1],16),n=parseInt(e[2]+e[2],16)):e.length===6&&(i=parseInt(e.slice(0,2),16),s=parseInt(e.slice(2,4),16),n=parseInt(e.slice(4,6),16)),[i/255,s/255,n/255,1]}if(t.startsWith("rgb")){let e=t.match(/rgba?\(([^)]+)\)/);if(e){let i=e[1].split(",").map(s=>parseFloat(s.trim()));return[i[0]/255,i[1]/255,i[2]/255,i[3]!==void 0?i[3]:1]}}return[1,1,1,1]}setupResizeObserver(){if(!(typeof ResizeObserver>"u"))try{this.resizeObserver=new ResizeObserver(()=>{try{this.updateCanvasSize()}catch(t){console.error("[TerminalGL] \u274C Error in resize callback:",t)}}),this.resizeObserver.observe(this.parentElement),this.updateCanvasSize()}catch(t){console.error("[TerminalGL] \u274C Failed to setup ResizeObserver:",t)}}updateCanvasSize(){let t=this.parentElement.clientWidth,e=this.parentElement.clientHeight;if(t===0||e===0)return;let i=this.cols*this.cellWidth,s=this.rows*this.cellHeight;if(i===0||s===0)return;let n=t/i,r=e/s,o=Math.min(n,r),a;switch(this.scalingMode){case R.Integer:a=Math.max(1,Math.floor(o));break;case R.Half:a=Math.max(1,Math.floor(o*2)/2);break;case R.Quarter:a=Math.max(1,Math.floor(o*4)/4);break;case R.Eighth:a=Math.max(1,Math.floor(o*8)/8);break;case R.Responsive:a=1;break;case R.None:default:a=Math.max(.1,o);break}if(this.canvas.style.transform=`scale(${a})`,this.ambientEffectEnabled&&this.ambientEffectCanvas){let h=a*this.ambientEffectScale;this.ambientEffectCanvas.style.transform=`scale(${h})`}this.currentScale=a,this.onResizeCallback&&this.onResizeCallback(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}updateAmbientEffect(){!this.ambientEffectCanvas||!this.ambientEffectCtx||this.ambientEffectCtx.drawImage(this.canvas,0,0)}setPalette(t){let e=0;for(let i=0;i<Math.min(t.length,256);i++){let s=t[i];e=(e<<5)-e+s.r,e=(e<<5)-e+s.g,e=(e<<5)-e+s.b,e=(e<<5)-e+s.a,e=e|0}if(e!==this.paletteHash){this.paletteHash=e;for(let i=0;i<t.length&&i<256;i++){let s=t[i],n=i*4;this.paletteFloat[n]=s.r/255,this.paletteFloat[n+1]=s.g/255,this.paletteFloat[n+2]=s.b/255,this.paletteFloat[n+3]=s.a/255}this.updatePaletteTexture()}}updatePaletteTexture(){try{let t=this.gl;this.paletteTexture||(this.paletteTexture=t.createTexture()),t.bindTexture(t.TEXTURE_2D,this.paletteTexture);let e=new Uint8Array(256*4);for(let i=0;i<256;i++){let s=i*4;e[s]=this.paletteFloat[s]*255,e[s+1]=this.paletteFloat[s+1]*255,e[s+2]=this.paletteFloat[s+2]*255,e[s+3]=this.paletteFloat[s+3]*255}t.texImage2D(t.TEXTURE_2D,0,t.RGBA,256,1,0,t.RGBA,t.UNSIGNED_BYTE,e),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.bindTexture(t.TEXTURE_2D,null)}catch(t){throw console.error("[TerminalGL] \u274C Failed to update palette texture:",t),t}}renderDisplayData(t){try{if(!this.isReady()){console.warn("[TerminalGL] \u26A0\uFE0F Not ready: font not loaded yet");return}(t.width!==this.cols||t.height!==this.rows)&&this.resize(t.width,t.height),t.passes&&t.passes.length>0?this.renderMultiPass(t,t.passes):this.renderDirect(t),this.ambientEffectEnabled&&this.ambientEffectCanvas&&this.ambientEffectCtx&&this.updateAmbientEffect()}catch(e){console.error("[TerminalGL] \u274C Error rendering display data:",e)}}renderMultiPass(t,e){for(let i=0;i<e.length;i++){let s=e[i],n={id:t.id,width:t.width,height:t.height,palette:t.palette,cells:s.cells};this.renderDirect(n,i===0)}}renderDirect(t,e=!0){let i=this.gl;if(!this.staticPositionsInitialized&&!this.useInstancing&&this.precomputeStaticPositions(),e){if(this.canvasBgColor!==null){let s=this.parseColor(this.canvasBgColor);i.clearColor(s[0],s[1],s[2],s[3])}else i.clearColor(0,0,0,0);i.clear(i.COLOR_BUFFER_BIT)}this.useInstancing?this.renderInstanced(t):this.renderDirectBuffers(t)}renderInstanced(t){let e=this.gl,i=this.instancedExtension;if(!this.instanceData||this.instanceData.length===0){console.warn("[TerminalGL] \u26A0\uFE0F Instance data not initialized, falling back to standard rendering"),this.renderDirectBuffers(t);return}let s=0,n=this.instanceData.length/8,r=t.width*t.height*2;if(r>n){console.error(`[TerminalGL] \u274C Instance buffer too small! Need ${r}, have ${n}. Display size: ${t.width}\xD7${t.height}, buffer was sized for smaller terminal.`),this.renderDirectBuffers(t);return}for(let a=0;a<t.height;a++)for(let h=0;h<t.width;h++){let c=t.cells[a*t.width+h],d=c.bgColorIndex,f=c.fgColorIndex,m=this.canvasBgColor!==null&&d===255,g=c.char===" "||f===255;if(!m){if(s>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${n}`);break}let u=s*8;this.instanceData[u]=h,this.instanceData[u+1]=a,this.instanceData[u+2]=0,this.instanceData[u+3]=0,this.instanceData[u+4]=0,this.instanceData[u+5]=0,this.instanceData[u+6]=d,this.instanceData[u+7]=0,s++}if(!g){let u=c.char.charCodeAt(0),p=this.charCodeToAtlasIndex[u];if(p!==65535){if(s>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${n}`);break}let C=p*4,x=s*8;this.instanceData[x]=h,this.instanceData[x+1]=a,this.instanceData[x+2]=this.atlasUVs[C],this.instanceData[x+3]=this.atlasUVs[C+1],this.instanceData[x+4]=this.atlasUVs[C+2],this.instanceData[x+5]=this.atlasUVs[C+3],this.instanceData[x+6]=0,this.instanceData[x+7]=f,s++}}}if(s===0){console.warn("[TerminalGL] \u26A0\uFE0F No instances to draw (all cells skipped)");return}e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.instanceData.subarray(0,s*8)),e.useProgram(this.program),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),i.vertexAttribDivisorANGLE(this.aPosition,0),e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer);let o=8*Float32Array.BYTES_PER_ELEMENT;e.enableVertexAttribArray(this.aInstanceOffset),e.vertexAttribPointer(this.aInstanceOffset,2,e.FLOAT,!1,o,0),i.vertexAttribDivisorANGLE(this.aInstanceOffset,1),e.enableVertexAttribArray(this.aInstanceUVs),e.vertexAttribPointer(this.aInstanceUVs,4,e.FLOAT,!1,o,2*Float32Array.BYTES_PER_ELEMENT),i.vertexAttribDivisorANGLE(this.aInstanceUVs,1),e.enableVertexAttribArray(this.aInstanceColors),e.vertexAttribPointer(this.aInstanceColors,2,e.FLOAT,!1,o,6*Float32Array.BYTES_PER_ELEMENT),i.vertexAttribDivisorANGLE(this.aInstanceColors,1),e.uniform2f(this.uResolution,this.canvas.width,this.canvas.height),e.uniform2f(this.uCellSize,this.cellWidth,this.cellHeight),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,this.atlasTexture),e.uniform1i(this.uTexture,0),e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,this.paletteTexture),e.uniform1i(this.uPalette,1),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),i.drawElementsInstancedANGLE(e.TRIANGLES,6,e.UNSIGNED_SHORT,0,s),i.vertexAttribDivisorANGLE(this.aPosition,0),i.vertexAttribDivisorANGLE(this.aInstanceOffset,0),i.vertexAttribDivisorANGLE(this.aInstanceUVs,0),i.vertexAttribDivisorANGLE(this.aInstanceColors,0)}renderDirectBuffers(t){let e=this.gl,i=t.width*t.height,s=i*2;if(s>this.maxCells){console.error(`[TerminalGL] \u274C Buffer overflow detected! Trying to render ${s} quads but buffer capacity is ${this.maxCells}. This should not happen - resize() should have reallocated.`);return}let n=0,r=0,o=t.cells,a=i;for(let g=0;g<a;g++){let u=o[g],p=u.bgColorIndex,x=this.canvasBgColor!==null&&p===255?255:p,y=0;for(let w=0;w<4;w++)this.renderTexCoords[n++]=y,this.renderTexCoords[n++]=y,this.renderColorIndices[r++]=x;let E=u.fgColorIndex,L=u.char;if(L===" "||E===255)for(let w=0;w<4;w++)this.renderTexCoords[n++]=0,this.renderTexCoords[n++]=0,this.renderColorIndices[r++]=255;else{let w=L.charCodeAt(0),Z=this.charCodeToAtlasIndex[w];if(Z!==65535){let I=Z*4,K=this.atlasUVs[I],J=this.atlasUVs[I+1],tt=this.atlasUVs[I+2],et=this.atlasUVs[I+3];this.renderTexCoords[n++]=K,this.renderTexCoords[n++]=J,this.renderColorIndices[r++]=E,this.renderTexCoords[n++]=tt,this.renderTexCoords[n++]=J,this.renderColorIndices[r++]=E,this.renderTexCoords[n++]=K,this.renderTexCoords[n++]=et,this.renderColorIndices[r++]=E,this.renderTexCoords[n++]=tt,this.renderTexCoords[n++]=et,this.renderColorIndices[r++]=E}else for(let I=0;I<4;I++)this.renderTexCoords[n++]=0,this.renderTexCoords[n++]=0,this.renderColorIndices[r++]=255}}(n!==a*2*4*2||r!==a*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:n,colorIdx:r,expected:a*2*4}),e.useProgram(this.program),this.vao&&this.vaoExtension?(this.vaoExtension.bindVertexArrayOES(this.vao),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,n)),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,r))):(e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,n)),e.enableVertexAttribArray(this.aTexCoord),e.vertexAttribPointer(this.aTexCoord,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,r)),e.enableVertexAttribArray(this.aColorIndex),e.vertexAttribPointer(this.aColorIndex,1,e.FLOAT,!1,0,0));let h=this.canvas.width,c=this.canvas.height;(this.cachedResolution[0]!==h||this.cachedResolution[1]!==c)&&(e.uniform2f(this.uResolution,h,c),this.cachedResolution[0]=h,this.cachedResolution[1]=c),this.cachedTextureUnit!==0&&(e.activeTexture(e.TEXTURE0),this.cachedTextureUnit=0),e.bindTexture(e.TEXTURE_2D,this.atlasTexture),this.cachedTextureUniform||(e.uniform1i(this.uTexture,0),this.cachedTextureUniform=!0),this.cachedPaletteUnit!==1&&(e.activeTexture(e.TEXTURE1),this.cachedPaletteUnit=1),e.bindTexture(e.TEXTURE_2D,this.paletteTexture),this.cachedPaletteUniform||(e.uniform1i(this.uPalette,1),this.cachedPaletteUniform=!0),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer);let f=t.width*t.height*2*6,m=this.useUint16Indices?e.UNSIGNED_SHORT:e.UNSIGNED_INT;e.drawElements(e.TRIANGLES,f,m,0)}resize(t,e){if(!Number.isInteger(t)||t<=0){console.error(`[TerminalGL] \u274C Invalid cols: ${t}. Must be positive integer.`);return}if(!Number.isInteger(e)||e<=0){console.error(`[TerminalGL] \u274C Invalid rows: ${e}. Must be positive integer.`);return}if(t===this.cols&&e===this.rows)return;let i=t*e,s=this.useInstancing?262144:this.useUint16Indices?8191:262144;if(i>s){let c=Math.floor(Math.sqrt(s));console.error(`[TerminalGL] \u274C Cannot resize to ${t}\xD7${e} (${i} cells). Device limit: ${s} cells (max ~${c}\xD7${c}). ${!this.useInstancing&&this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let n=D.checkCompatibility();i>n.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${t}\xD7${e} (${i} cells) exceeds recommended limit (${n.recommendedMaxCells} cells). Performance may degrade.`),this.cols=t,this.rows=e,this.staticPositionsInitialized=!1;let r=this.cols*this.rows*2,o=Math.ceil(r*1.5),a=r>this.maxCells,h=this.maxCells>o*4;if(console.warn(`[TerminalGL] \u{1F4D0} resize check: cols=${t}, rows=${e}, newMaxCells=${r}, this.maxCells=${this.maxCells}, needGrow=${a}, needShrink=${h}`),a||h){let c=this.maxCells;if(this.maxCells=o,console.warn(`[TerminalGL] \u{1F4D0} resize realloc: ${c} \u2192 ${this.maxCells} (needGrow=${a}, needShrink=${h})`),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.useInstancing&&this.instanceDataBuffer){this.instanceData=new Float32Array(this.maxCells*8);let u=this.gl;u.bindBuffer(u.ARRAY_BUFFER,this.instanceDataBuffer),u.bufferData(u.ARRAY_BUFFER,this.instanceData.byteLength,u.DYNAMIC_DRAW)}let d=this.gl;this.useInstancing||(d.bindBuffer(d.ARRAY_BUFFER,this.positionBuffer),d.bufferData(d.ARRAY_BUFFER,this.renderPositions.byteLength,d.DYNAMIC_DRAW)),d.bindBuffer(d.ARRAY_BUFFER,this.texCoordBuffer),d.bufferData(d.ARRAY_BUFFER,this.renderTexCoords.byteLength,d.DYNAMIC_DRAW),d.bindBuffer(d.ARRAY_BUFFER,this.colorIndexBuffer),d.bufferData(d.ARRAY_BUFFER,this.renderColorIndices.byteLength,d.DYNAMIC_DRAW),this.useInstancing||(d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,this.indexBuffer),d.bufferData(d.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,d.DYNAMIC_DRAW)),this.vaoExtension&&this.vao&&(this.vaoExtension.deleteVertexArrayOES(this.vao),this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),d.bindBuffer(d.ARRAY_BUFFER,this.positionBuffer),d.enableVertexAttribArray(this.aPosition),d.vertexAttribPointer(this.aPosition,2,d.FLOAT,!1,0,0),d.bindBuffer(d.ARRAY_BUFFER,this.texCoordBuffer),d.enableVertexAttribArray(this.aTexCoord),d.vertexAttribPointer(this.aTexCoord,2,d.FLOAT,!1,0,0),d.bindBuffer(d.ARRAY_BUFFER,this.colorIndexBuffer),d.enableVertexAttribArray(this.aColorIndex),d.vertexAttribPointer(this.aColorIndex,1,d.FLOAT,!1,0,0),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null)));let f=a?"\u{1F4C8} Growing":"\u{1F4C9} Shrinking",m=c*160/1048576,g=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${f} buffers: ${m.toFixed(2)}MB \u2192 ${g.toFixed(2)}MB (${c} \u2192 ${this.maxCells} quads)`)}this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.canvas.style.width=`${this.canvas.width}px`,this.canvas.style.height=`${this.canvas.height}px`,this.ambientEffectEnabled&&this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.width=`${this.canvas.width}px`,this.ambientEffectCanvas.style.height=`${this.canvas.height}px`),this.showGrid&&this.gridOverlay&&this.updateGridOverlay(),this.updateCanvasSize()}getCanvas(){return this.canvas}getGridSize(){return{cols:this.cols,rows:this.rows}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getBaseDimensions(){return{width:this.cols*this.cellWidth,height:this.rows*this.cellHeight}}setOnResizeCallback(t){this.onResizeCallback=t}clearOnResizeCallback(){this.onResizeCallback=void 0}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}setScalingMode(t){this.scalingMode!==t&&(this.scalingMode=t,this.updateCanvasSize())}getScalingMode(){return this.scalingMode}setCellSize(t,e){let i=Math.max(1,Math.min(255,Math.round(t))),s=Math.max(1,Math.min(255,Math.round(e)));this.cellWidth===i&&this.cellHeight===s||(this.cellWidth=i,this.cellHeight=s,this.charWidth=i,this.charHeight=s,this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.fontLoaded&&this.generateAtlas(),this.useInstancing&&this.initInstancedBuffers(),this.updateCanvasSize())}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getMaxCells(){return this.useInstancing?262144:this.useUint16Indices?8191:262144}setGrid(t){t.enabled?(this.gridOverlay?this.gridOverlay.setStyle({strokeColor:t.color,lineWidth:t.lineWidth}):this.gridOverlay=new A(this.containerDiv,{strokeColor:t.color??"rgba(144, 24, 24, 1)",lineWidth:t.lineWidth??1,zIndex:10}),this.showGrid=!0,this.gridOverlay.setVisible(!0),this.updateGridOverlay()):(this.showGrid=!1,this.gridOverlay&&this.gridOverlay.setVisible(!1))}isGridEnabled(){return this.showGrid}setAmbientEffect(t){typeof t=="boolean"?this.ambientEffectEnabled=t:(this.ambientEffectEnabled=!0,t.blur!==void 0&&(this.ambientEffectBlur=t.blur),t.scale!==void 0&&(this.ambientEffectScale=t.scale)),this.ambientEffectEnabled&&!this.ambientEffectCanvas&&this.createAmbientEffectCanvas(),this.ambientEffectCanvas&&(this.ambientEffectEnabled?(this.ambientEffectCanvas.style.display="block",this.ambientEffectCanvas.style.filter=`blur(${this.ambientEffectBlur}px)`,this.ambientEffectCanvas.style.transform=`scale(${this.ambientEffectScale})`,this.updateAmbientEffect()):this.ambientEffectCanvas.style.display="none")}createAmbientEffectCanvas(){this.ambientEffectCanvas||(this.ambientEffectCanvas=document.createElement("canvas"),this.ambientEffectCanvas.className="terminalgl-ambient-effect-canvas",this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.cssText=`
120
120
  display: block !important;
121
121
  position: absolute !important;
122
122
  width: ${this.canvas.width}px !important;
@@ -127,7 +127,7 @@ var it=Object.defineProperty;var at=(b,t,e)=>t in b?it(b,t,{enumerable:!0,config
127
127
  transform: scale(${this.ambientEffectScale}) !important;
128
128
  pointer-events: none !important;
129
129
  z-index: 0 !important;
130
- `,this.ambientEffectCtx=this.ambientEffectCanvas.getContext("2d",{alpha:!0}),this.containerDiv.insertBefore(this.ambientEffectCanvas,this.canvas),console.warn("[TerminalGL] \u{1F308} ambient effect canvas created dynamically"))}isAmbientEffectEnabled(){return this.ambientEffectEnabled}getAmbientEffectConfig(){return{enabled:this.ambientEffectEnabled,blur:this.ambientEffectBlur,scale:this.ambientEffectScale}}getCols(){return this.cols}getRows(){return this.rows}isReady(){return!!(this.fontLoaded&&this.atlasTexture&&this.program)}destroy(){this.dispose()}dispose(){this.resizeObserver&&this.resizeObserver.disconnect();let t=this.gl;this.program&&t.deleteProgram(this.program),this.positionBuffer&&t.deleteBuffer(this.positionBuffer),this.texCoordBuffer&&t.deleteBuffer(this.texCoordBuffer),this.colorIndexBuffer&&t.deleteBuffer(this.colorIndexBuffer),this.indexBuffer&&t.deleteBuffer(this.indexBuffer),this.instanceDataBuffer&&t.deleteBuffer(this.instanceDataBuffer),this.atlasTexture&&t.deleteTexture(this.atlasTexture),this.paletteTexture&&t.deleteTexture(this.paletteTexture),this.vao&&this.vaoExtension&&this.vaoExtension.deleteVertexArrayOES(this.vao);let e=t.getExtension("WEBGL_lose_context");e&&e.loseContext(),this.atlasCanvas&&(this.atlasCanvas.width=0,this.atlasCanvas.height=0,this.atlasCanvas=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv),this.canvas.width=0,this.canvas.height=0,this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=0,this.ambientEffectCanvas.height=0,this.ambientEffectCanvas=null),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.renderPositions=new Float32Array(0),this.renderTexCoords=new Float32Array(0),this.renderColorIndices=new Float32Array(0),this.renderIndices=new Uint32Array(0),this.paletteFloat=new Float32Array(0),this.atlasUVs=new Float32Array(0),this.instanceData=new Float32Array(0),this.templateQuadPositions=new Float32Array(0),this.templateQuadIndices=new Uint16Array(0)}};v(D,"TerminalGL");var P=D;var O=class O{constructor(t,e,i,s,a){l(this,"atlases");l(this,"charMap");l(this,"baseCharWidth");l(this,"baseCharHeight");l(this,"baseCellWidth");l(this,"baseCellHeight");l(this,"atlasColumns",16);l(this,"font");l(this,"SCALES",[1,2,4,8]);l(this,"colorCache",new Map);l(this,"MAX_CACHE_SIZE",512);this.font=t,this.baseCharWidth=e,this.baseCharHeight=i,this.baseCellWidth=s??e,this.baseCellHeight=a??i,this.charMap=new Map,this.atlases=new Map,this.generateAtlases()}generateAtlases(){this.atlasColumns=16;let t=0;for(let[e,i]of this.font){let s=t%this.atlasColumns,a=Math.floor(t/this.atlasColumns);this.charMap.set(e,{x:s*this.baseCharWidth,y:a*this.baseCharHeight});for(let r of this.SCALES){let o=this.getOrCreateAtlas(r),n=s*o.charWidth,h=a*o.charHeight;this.renderBitmapToAtlas(o,i,n,h)}t++}}getOrCreateAtlas(t){let e=this.atlases.get(t);if(!e){let i=this.baseCharWidth*t,s=this.baseCharHeight*t,r=Math.ceil(256/this.atlasColumns),o=document.createElement("canvas");o.width=this.atlasColumns*i,o.height=r*s;let n=o.getContext("2d",{alpha:!0,willReadFrequently:!1});if(!n)throw new Error(`Impossible de cr\xE9er le contexte 2D pour l'atlas ${t}x`);n.imageSmoothingEnabled=!1,e={canvas:o,ctx:n,scale:t,charWidth:i,charHeight:s},this.atlases.set(t,e)}return e}renderBitmapToAtlas(t,e,i,s){let a=t.scale,r=t.ctx;r.fillStyle="#ffffff";for(let o=0;o<Math.min(e.length,this.baseCharHeight);o++){let n=e[o];for(let h=0;h<this.baseCharWidth;h++){let c=1<<7-h;n&c&&r.fillRect(i+h*a,s+o*a,a,a)}}}drawChar(t,e,i,s,a,r,o){let n=this.charMap.get(e);if(!n)return;let h=`${e}:${o}`,c=this.colorCache.get(h);if(c)c.lastUsed=performance.now();else{let C=this.createColoredGlyph(e,o,n);if(!C)return;c={canvas:C,lastUsed:performance.now()},this.colorCache.set(h,c),this.colorCache.size>this.MAX_CACHE_SIZE&&this.evictLRU()}let d=a/this.baseCellWidth,f=r/this.baseCellHeight,m=(this.baseCellWidth-this.baseCharWidth)/2*d,g=(this.baseCellHeight-this.baseCharHeight)/2*f,u=this.baseCharWidth*d,p=this.baseCharHeight*f;t.drawImage(c.canvas,i+m,s+g,u,p)}createColoredGlyph(t,e,i){let s=this.atlases.get(1);if(!s)return null;let a=s.ctx.getImageData(i.x,i.y,this.baseCharWidth,this.baseCharHeight),r=a.data,o=this.hexToRgb(e);for(let c=0;c<r.length;c+=4)r[c+3]>0&&(r[c]=o.r,r[c+1]=o.g,r[c+2]=o.b);let n=document.createElement("canvas");n.width=this.baseCharWidth,n.height=this.baseCharHeight;let h=n.getContext("2d",{alpha:!0});return h?(h.imageSmoothingEnabled=!1,h.putImageData(a,0,0),n):null}hexToRgb(t){if(t.startsWith("#")){let a=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(a,(o,n,h,c)=>n+n+h+h+c+c);let r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return r?{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16)}:{r:255,g:255,b:255}}let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10)};let s={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255]}[t.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2]}:{r:255,g:255,b:255}}evictLRU(){let t=null,e=1/0;for(let[i,s]of this.colorCache)s.lastUsed<e&&(e=s.lastUsed,t=i);if(t){let i=this.colorCache.get(t);i&&(i.canvas.width=0,i.canvas.height=0),this.colorCache.delete(t)}}getAtlasCanvas(t=1){return this.atlases.get(t)?.canvas}getAllAtlases(){return this.atlases}getCharDimensions(){return{width:this.baseCharWidth,height:this.baseCharHeight}}getCharCount(){return this.charMap.size}hasChar(t){return this.charMap.has(t)}getAtlasDimensions(t=1){let e=this.atlases.get(t);if(e)return{width:e.canvas.width,height:e.canvas.height}}toDataURL(t=1,e="image/png"){return this.atlases.get(t)?.canvas.toDataURL(e)}getCacheStats(){return{size:this.colorCache.size,maxSize:this.MAX_CACHE_SIZE}}clearCache(){for(let t of this.colorCache.values())t.canvas.width=0,t.canvas.height=0;this.colorCache.clear()}destroy(){this.charMap.clear();for(let t of this.atlases.values())t.canvas.width=0,t.canvas.height=0;this.atlases.clear(),this.clearCache()}};v(O,"BitmapFontAtlas");var F=O;var z=class z{constructor(t){l(this,"atlasCanvas",null);l(this,"atlasCtx",null);l(this,"atlasImage",null);l(this,"glyphWidth");l(this,"glyphHeight");l(this,"cellWidth");l(this,"cellHeight");l(this,"atlasBlocks");l(this,"atlasColumns");l(this,"maxCharCode");l(this,"isLoaded",!1);l(this,"colorCache",new Map);l(this,"MAX_CACHE_SIZE",1024);this.glyphWidth=t.glyphWidth,this.glyphHeight=t.glyphHeight,this.cellWidth=t.cellWidth??t.glyphWidth,this.cellHeight=t.cellHeight??t.glyphHeight,this.atlasBlocks=t.atlasBlocks,this.atlasColumns=M(t.atlasBlocks),this.maxCharCode=S(t.atlasBlocks)}async loadFromPNG(t){return new Promise((e,i)=>{let s=new Uint8Array(t),a=new Blob([s],{type:"image/png"}),r=URL.createObjectURL(a),o=new Image;o.onload=()=>{URL.revokeObjectURL(r);let n=this.atlasColumns*this.glyphWidth,h=this.atlasColumns*this.glyphHeight;if((o.width!==n||o.height!==h)&&console.warn(`ImageFontAtlas: Image size ${o.width}\xD7${o.height} doesn't match expected ${n}\xD7${h} for ${this.atlasBlocks} block(s) with ${this.glyphWidth}\xD7${this.glyphHeight} glyphs`),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=o.width,this.atlasCanvas.height=o.height,this.atlasCtx=this.atlasCanvas.getContext("2d",{alpha:!0,willReadFrequently:!0}),!this.atlasCtx){i(new Error("Failed to create 2D context for atlas"));return}this.atlasCtx.imageSmoothingEnabled=!1,this.atlasCtx.drawImage(o,0,0),this.atlasImage=o,this.isLoaded=!0,e()},o.onerror=()=>{URL.revokeObjectURL(r),i(new Error("Failed to load PNG image for atlas"))},o.src=r})}isReady(){return this.isLoaded}getGlyphPosition(t){if(t<0||t>this.maxCharCode)return null;let{col:e,row:i}=B(t,this.atlasBlocks);return{x:e*this.glyphWidth,y:i*this.glyphHeight}}getCharUV(t){if(t<0||t>this.maxCharCode)return null;let{col:e,row:i}=B(t,this.atlasBlocks),s=e/this.atlasColumns,a=i/this.atlasColumns,r=(e+1)/this.atlasColumns,o=(i+1)/this.atlasColumns;return{u1:s,v1:a,u2:r,v2:o}}drawChar(t,e,i,s,a,r,o){if(!this.isLoaded||!this.atlasCanvas)return;let n=this.getGlyphPosition(e);if(!n)return;let h=`${e}:${o}`,c=this.colorCache.get(h);if(c)c.lastUsed=performance.now();else{let f=this.createColoredGlyph(e,o,n);if(!f)return;c={canvas:f,lastUsed:performance.now()},this.colorCache.set(h,c),this.colorCache.size>this.MAX_CACHE_SIZE&&this.evictLRU()}if(t.imageSmoothingEnabled=!1,a===this.cellWidth&&r===this.cellHeight){let f=Math.floor((this.cellWidth-this.glyphWidth)/2),m=Math.floor((this.cellHeight-this.glyphHeight)/2);t.drawImage(c.canvas,Math.floor(i)+f,Math.floor(s)+m)}else{let f=a/this.cellWidth,m=r/this.cellHeight,g=Math.floor((this.cellWidth-this.glyphWidth)/2*f),u=Math.floor((this.cellHeight-this.glyphHeight)/2*m),p=Math.ceil(this.glyphWidth*f),C=Math.ceil(this.glyphHeight*m);t.drawImage(c.canvas,Math.floor(i)+g,Math.floor(s)+u,p,C)}}createColoredGlyph(t,e,i){if(!this.atlasCtx)return null;let s=this.atlasCtx.getImageData(i.x,i.y,this.glyphWidth,this.glyphHeight),a=s.data,r=this.parseColor(e);for(let h=0;h<a.length;h+=4)a[h+3]>0&&(a[h]=r.r,a[h+1]=r.g,a[h+2]=r.b);let o=document.createElement("canvas");o.width=this.glyphWidth,o.height=this.glyphHeight;let n=o.getContext("2d",{alpha:!0});return n?(n.putImageData(s,0,0),o):null}parseColor(t){if(t.startsWith("#")){let i=t.slice(1);return i.length===3&&(i=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]),{r:parseInt(i.slice(0,2),16),g:parseInt(i.slice(2,4),16),b:parseInt(i.slice(4,6),16)}}let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(t);return e?{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10)}:{r:255,g:255,b:255}}evictLRU(){let t=null,e=1/0;for(let[i,s]of this.colorCache)s.lastUsed<e&&(e=s.lastUsed,t=i);if(t){let i=this.colorCache.get(t);i&&(i.canvas.width=0,i.canvas.height=0),this.colorCache.delete(t)}}getAtlasCanvas(){return this.atlasCanvas}getAtlasImage(){return this.atlasImage}getConfig(){return{glyphWidth:this.glyphWidth,glyphHeight:this.glyphHeight,cellWidth:this.cellWidth,cellHeight:this.cellHeight,atlasBlocks:this.atlasBlocks}}getGlyphDimensions(){return{width:this.glyphWidth,height:this.glyphHeight}}getCellDimensions(){return{width:this.cellWidth,height:this.cellHeight}}getAtlasDimensions(){return{width:this.atlasColumns*this.glyphWidth,height:this.atlasColumns*this.glyphHeight}}getAtlasColumns(){return this.atlasColumns}getMaxCharCode(){return this.maxCharCode}isValidCharCode(t){return t>=0&&t<=this.maxCharCode}clearCache(){for(let t of this.colorCache.values())t.canvas.width=0,t.canvas.height=0;this.colorCache.clear()}getCacheStats(){return{size:this.colorCache.size,maxSize:this.MAX_CACHE_SIZE}}destroy(){this.clearCache(),this.atlasCanvas&&(this.atlasCanvas.width=0,this.atlasCanvas.height=0,this.atlasCanvas=null),this.atlasCtx=null,this.atlasImage=null,this.isLoaded=!1}};v(z,"ImageFontAtlas");var U=z;import{ScalingMode as T}from"@utsp/types";var $=class ${constructor(t,e={}){l(this,"containerDiv");l(this,"canvas");l(this,"ctx");l(this,"parentElement");l(this,"cells");l(this,"cols",0);l(this,"rows",0);l(this,"fontSize");l(this,"fontFamily");l(this,"defaultFgColor");l(this,"defaultBgColor");l(this,"canvasBgColor");l(this,"cellWidth");l(this,"cellHeight");l(this,"offsetX",0);l(this,"offsetY",0);l(this,"fontType","web");l(this,"bitmapFont");l(this,"bitmapAtlas");l(this,"imageAtlas");l(this,"bitmapCharWidth",8);l(this,"bitmapCharHeight",8);l(this,"showDebugGrid");l(this,"debugGridColor");l(this,"gridOverlay");l(this,"fixedGridMode");l(this,"fixedCols");l(this,"fixedRows");l(this,"cellAspectRatio");l(this,"resizeObserver");l(this,"imageDataBuffer");l(this,"useImageDataRendering",!1);l(this,"paletteCache");l(this,"scalingMode",T.None);l(this,"currentScale",1);l(this,"customCellSize",!1);if(!t)throw new Error("Render: L'\xE9l\xE9ment parent est requis");this.parentElement=t,this.fixedGridMode=!!(e.fixedCols&&e.fixedRows),this.fixedCols=e.fixedCols,this.fixedRows=e.fixedRows,this.cellAspectRatio=e.cellAspectRatio??1,this.cellWidth=e.cellWidth??8,this.cellHeight=e.cellHeight??8,this.fontSize=e.fontSize??12,this.fontFamily=e.fontFamily??"monospace",this.defaultFgColor=e.defaultFgColor??"#ffffff",this.defaultBgColor=e.defaultBgColor??"#000000",this.canvasBgColor=e.canvasBgColor!==void 0?e.canvasBgColor:null,this.showDebugGrid=e.showDebugGrid??!1,this.debugGridColor=e.debugGridColor??"rgba(144, 24, 24, 1)",this.scalingMode=e.scalingMode??T.None,window.getComputedStyle(this.parentElement).position==="static"&&(this.parentElement.style.position="relative"),this.containerDiv=document.createElement("div"),this.containerDiv.className="terminal2d-container",this.containerDiv.style.cssText=`
130
+ `,this.ambientEffectCtx=this.ambientEffectCanvas.getContext("2d",{alpha:!0}),this.containerDiv.insertBefore(this.ambientEffectCanvas,this.canvas),console.warn("[TerminalGL] \u{1F308} ambient effect canvas created dynamically"))}isAmbientEffectEnabled(){return this.ambientEffectEnabled}getAmbientEffectConfig(){return{enabled:this.ambientEffectEnabled,blur:this.ambientEffectBlur,scale:this.ambientEffectScale}}getCols(){return this.cols}getRows(){return this.rows}isReady(){return!!(this.fontLoaded&&this.atlasTexture&&this.program)}destroy(){this.dispose()}dispose(){this.resizeObserver&&this.resizeObserver.disconnect();let t=this.gl;this.program&&t.deleteProgram(this.program),this.positionBuffer&&t.deleteBuffer(this.positionBuffer),this.texCoordBuffer&&t.deleteBuffer(this.texCoordBuffer),this.colorIndexBuffer&&t.deleteBuffer(this.colorIndexBuffer),this.indexBuffer&&t.deleteBuffer(this.indexBuffer),this.instanceDataBuffer&&t.deleteBuffer(this.instanceDataBuffer),this.atlasTexture&&t.deleteTexture(this.atlasTexture),this.paletteTexture&&t.deleteTexture(this.paletteTexture),this.vao&&this.vaoExtension&&this.vaoExtension.deleteVertexArrayOES(this.vao);let e=t.getExtension("WEBGL_lose_context");e&&e.loseContext(),this.atlasCanvas&&(this.atlasCanvas.width=0,this.atlasCanvas.height=0,this.atlasCanvas=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv),this.canvas.width=0,this.canvas.height=0,this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=0,this.ambientEffectCanvas.height=0,this.ambientEffectCanvas=null),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.renderPositions=new Float32Array(0),this.renderTexCoords=new Float32Array(0),this.renderColorIndices=new Float32Array(0),this.renderIndices=new Uint32Array(0),this.paletteFloat=new Float32Array(0),this.atlasUVs=new Float32Array(0),this.instanceData=new Float32Array(0),this.templateQuadPositions=new Float32Array(0),this.templateQuadIndices=new Uint16Array(0)}};v(D,"TerminalGL");var _=D;var O=class O{constructor(t,e,i,s,n){l(this,"atlases");l(this,"charMap");l(this,"baseCharWidth");l(this,"baseCharHeight");l(this,"baseCellWidth");l(this,"baseCellHeight");l(this,"atlasColumns",16);l(this,"font");l(this,"SCALES",[1,2,4,8]);l(this,"colorCache",new Map);l(this,"MAX_CACHE_SIZE",512);this.font=t,this.baseCharWidth=e,this.baseCharHeight=i,this.baseCellWidth=s??e,this.baseCellHeight=n??i,this.charMap=new Map,this.atlases=new Map,this.generateAtlases()}generateAtlases(){this.atlasColumns=16;let t=0;for(let[e,i]of this.font){let s=t%this.atlasColumns,n=Math.floor(t/this.atlasColumns);this.charMap.set(e,{x:s*this.baseCharWidth,y:n*this.baseCharHeight});for(let r of this.SCALES){let o=this.getOrCreateAtlas(r),a=s*o.charWidth,h=n*o.charHeight;this.renderBitmapToAtlas(o,i,a,h)}t++}}getOrCreateAtlas(t){let e=this.atlases.get(t);if(!e){let i=this.baseCharWidth*t,s=this.baseCharHeight*t,r=Math.ceil(256/this.atlasColumns),o=document.createElement("canvas");o.width=this.atlasColumns*i,o.height=r*s;let a=o.getContext("2d",{alpha:!0,willReadFrequently:!1});if(!a)throw new Error(`Impossible de cr\xE9er le contexte 2D pour l'atlas ${t}x`);a.imageSmoothingEnabled=!1,e={canvas:o,ctx:a,scale:t,charWidth:i,charHeight:s},this.atlases.set(t,e)}return e}renderBitmapToAtlas(t,e,i,s){let n=t.scale,r=t.ctx;r.fillStyle="#ffffff";for(let o=0;o<Math.min(e.length,this.baseCharHeight);o++){let a=e[o];for(let h=0;h<this.baseCharWidth;h++){let c=1<<7-h;a&c&&r.fillRect(i+h*n,s+o*n,n,n)}}}drawChar(t,e,i,s,n,r,o){let a=this.charMap.get(e);if(!a)return;let h=`${e}:${o}`,c=this.colorCache.get(h);if(c)c.lastUsed=performance.now();else{let C=this.createColoredGlyph(e,o,a);if(!C)return;c={canvas:C,lastUsed:performance.now()},this.colorCache.set(h,c),this.colorCache.size>this.MAX_CACHE_SIZE&&this.evictLRU()}let d=n/this.baseCellWidth,f=r/this.baseCellHeight,m=(this.baseCellWidth-this.baseCharWidth)/2*d,g=(this.baseCellHeight-this.baseCharHeight)/2*f,u=this.baseCharWidth*d,p=this.baseCharHeight*f;t.drawImage(c.canvas,i+m,s+g,u,p)}createColoredGlyph(t,e,i){let s=this.atlases.get(1);if(!s)return null;let n=s.ctx.getImageData(i.x,i.y,this.baseCharWidth,this.baseCharHeight),r=n.data,o=this.hexToRgb(e);for(let c=0;c<r.length;c+=4)r[c+3]>0&&(r[c]=o.r,r[c+1]=o.g,r[c+2]=o.b);let a=document.createElement("canvas");a.width=this.baseCharWidth,a.height=this.baseCharHeight;let h=a.getContext("2d",{alpha:!0});return h?(h.imageSmoothingEnabled=!1,h.putImageData(n,0,0),a):null}hexToRgb(t){if(t.startsWith("#")){let n=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(n,(o,a,h,c)=>a+a+h+h+c+c);let r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return r?{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16)}:{r:255,g:255,b:255}}let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10)};let s={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255]}[t.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2]}:{r:255,g:255,b:255}}evictLRU(){let t=null,e=1/0;for(let[i,s]of this.colorCache)s.lastUsed<e&&(e=s.lastUsed,t=i);if(t){let i=this.colorCache.get(t);i&&(i.canvas.width=0,i.canvas.height=0),this.colorCache.delete(t)}}getAtlasCanvas(t=1){return this.atlases.get(t)?.canvas}getAllAtlases(){return this.atlases}getCharDimensions(){return{width:this.baseCharWidth,height:this.baseCharHeight}}getCharCount(){return this.charMap.size}hasChar(t){return this.charMap.has(t)}getAtlasDimensions(t=1){let e=this.atlases.get(t);if(e)return{width:e.canvas.width,height:e.canvas.height}}toDataURL(t=1,e="image/png"){return this.atlases.get(t)?.canvas.toDataURL(e)}getCacheStats(){return{size:this.colorCache.size,maxSize:this.MAX_CACHE_SIZE}}clearCache(){for(let t of this.colorCache.values())t.canvas.width=0,t.canvas.height=0;this.colorCache.clear()}destroy(){this.charMap.clear();for(let t of this.atlases.values())t.canvas.width=0,t.canvas.height=0;this.atlases.clear(),this.clearCache()}};v(O,"BitmapFontAtlas");var F=O;var z=class z{constructor(t){l(this,"atlasCanvas",null);l(this,"atlasCtx",null);l(this,"atlasImage",null);l(this,"glyphWidth");l(this,"glyphHeight");l(this,"cellWidth");l(this,"cellHeight");l(this,"atlasBlocks");l(this,"atlasColumns");l(this,"maxCharCode");l(this,"isLoaded",!1);l(this,"colorCache",new Map);l(this,"MAX_CACHE_SIZE",1024);this.glyphWidth=t.glyphWidth,this.glyphHeight=t.glyphHeight,this.cellWidth=t.cellWidth??t.glyphWidth,this.cellHeight=t.cellHeight??t.glyphHeight,this.atlasBlocks=t.atlasBlocks,this.atlasColumns=M(t.atlasBlocks),this.maxCharCode=S(t.atlasBlocks)}async loadFromPNG(t){return new Promise((e,i)=>{let s=new Uint8Array(t),n=new Blob([s],{type:"image/png"}),r=URL.createObjectURL(n),o=new Image;o.onload=()=>{URL.revokeObjectURL(r);let a=this.atlasColumns*this.glyphWidth,h=this.atlasColumns*this.glyphHeight;if((o.width!==a||o.height!==h)&&console.warn(`ImageFontAtlas: Image size ${o.width}\xD7${o.height} doesn't match expected ${a}\xD7${h} for ${this.atlasBlocks} block(s) with ${this.glyphWidth}\xD7${this.glyphHeight} glyphs`),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=o.width,this.atlasCanvas.height=o.height,this.atlasCtx=this.atlasCanvas.getContext("2d",{alpha:!0,willReadFrequently:!0}),!this.atlasCtx){i(new Error("Failed to create 2D context for atlas"));return}this.atlasCtx.imageSmoothingEnabled=!1,this.atlasCtx.drawImage(o,0,0),this.atlasImage=o,this.isLoaded=!0,e()},o.onerror=()=>{URL.revokeObjectURL(r),i(new Error("Failed to load PNG image for atlas"))},o.src=r})}isReady(){return this.isLoaded}getGlyphPosition(t){if(t<0||t>this.maxCharCode)return null;let{col:e,row:i}=B(t,this.atlasBlocks);return{x:e*this.glyphWidth,y:i*this.glyphHeight}}getCharUV(t){if(t<0||t>this.maxCharCode)return null;let{col:e,row:i}=B(t,this.atlasBlocks),s=e/this.atlasColumns,n=i/this.atlasColumns,r=(e+1)/this.atlasColumns,o=(i+1)/this.atlasColumns;return{u1:s,v1:n,u2:r,v2:o}}drawChar(t,e,i,s,n,r,o){if(!this.isLoaded||!this.atlasCanvas)return;let a=this.getGlyphPosition(e);if(!a)return;let h=`${e}:${o}`,c=this.colorCache.get(h);if(c)c.lastUsed=performance.now();else{let f=this.createColoredGlyph(e,o,a);if(!f)return;c={canvas:f,lastUsed:performance.now()},this.colorCache.set(h,c),this.colorCache.size>this.MAX_CACHE_SIZE&&this.evictLRU()}if(t.imageSmoothingEnabled=!1,n===this.cellWidth&&r===this.cellHeight){let f=Math.floor((this.cellWidth-this.glyphWidth)/2),m=Math.floor((this.cellHeight-this.glyphHeight)/2);t.drawImage(c.canvas,Math.floor(i)+f,Math.floor(s)+m)}else{let f=n/this.cellWidth,m=r/this.cellHeight,g=Math.floor((this.cellWidth-this.glyphWidth)/2*f),u=Math.floor((this.cellHeight-this.glyphHeight)/2*m),p=Math.ceil(this.glyphWidth*f),C=Math.ceil(this.glyphHeight*m);t.drawImage(c.canvas,Math.floor(i)+g,Math.floor(s)+u,p,C)}}createColoredGlyph(t,e,i){if(!this.atlasCtx)return null;let s=this.atlasCtx.getImageData(i.x,i.y,this.glyphWidth,this.glyphHeight),n=s.data,r=this.parseColor(e);for(let h=0;h<n.length;h+=4)n[h+3]>0&&(n[h]=r.r,n[h+1]=r.g,n[h+2]=r.b);let o=document.createElement("canvas");o.width=this.glyphWidth,o.height=this.glyphHeight;let a=o.getContext("2d",{alpha:!0});return a?(a.putImageData(s,0,0),o):null}parseColor(t){if(t.startsWith("#")){let i=t.slice(1);return i.length===3&&(i=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]),{r:parseInt(i.slice(0,2),16),g:parseInt(i.slice(2,4),16),b:parseInt(i.slice(4,6),16)}}let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(t);return e?{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10)}:{r:255,g:255,b:255}}evictLRU(){let t=null,e=1/0;for(let[i,s]of this.colorCache)s.lastUsed<e&&(e=s.lastUsed,t=i);if(t){let i=this.colorCache.get(t);i&&(i.canvas.width=0,i.canvas.height=0),this.colorCache.delete(t)}}getAtlasCanvas(){return this.atlasCanvas}getAtlasImage(){return this.atlasImage}getConfig(){return{glyphWidth:this.glyphWidth,glyphHeight:this.glyphHeight,cellWidth:this.cellWidth,cellHeight:this.cellHeight,atlasBlocks:this.atlasBlocks}}getGlyphDimensions(){return{width:this.glyphWidth,height:this.glyphHeight}}getCellDimensions(){return{width:this.cellWidth,height:this.cellHeight}}getAtlasDimensions(){return{width:this.atlasColumns*this.glyphWidth,height:this.atlasColumns*this.glyphHeight}}getAtlasColumns(){return this.atlasColumns}getMaxCharCode(){return this.maxCharCode}isValidCharCode(t){return t>=0&&t<=this.maxCharCode}clearCache(){for(let t of this.colorCache.values())t.canvas.width=0,t.canvas.height=0;this.colorCache.clear()}getCacheStats(){return{size:this.colorCache.size,maxSize:this.MAX_CACHE_SIZE}}destroy(){this.clearCache(),this.atlasCanvas&&(this.atlasCanvas.width=0,this.atlasCanvas.height=0,this.atlasCanvas=null),this.atlasCtx=null,this.atlasImage=null,this.isLoaded=!1}};v(z,"ImageFontAtlas");var U=z;import{ScalingMode as T}from"@utsp/types";var $=class ${constructor(t,e={}){l(this,"containerDiv");l(this,"canvas");l(this,"ctx");l(this,"parentElement");l(this,"cells");l(this,"cols",0);l(this,"rows",0);l(this,"fontSize");l(this,"fontFamily");l(this,"defaultFgColor");l(this,"defaultBgColor");l(this,"canvasBgColor");l(this,"cellWidth");l(this,"cellHeight");l(this,"offsetX",0);l(this,"offsetY",0);l(this,"fontType","web");l(this,"bitmapFont");l(this,"bitmapAtlas");l(this,"imageAtlas");l(this,"bitmapCharWidth",8);l(this,"bitmapCharHeight",8);l(this,"showDebugGrid");l(this,"debugGridColor");l(this,"gridOverlay");l(this,"fixedGridMode");l(this,"fixedCols");l(this,"fixedRows");l(this,"cellAspectRatio");l(this,"resizeObserver");l(this,"imageDataBuffer");l(this,"useImageDataRendering",!1);l(this,"paletteCache");l(this,"scalingMode",T.None);l(this,"currentScale",1);l(this,"customCellSize",!1);if(!t)throw new Error("Render: L'\xE9l\xE9ment parent est requis");this.parentElement=t,this.fixedGridMode=!!(e.fixedCols&&e.fixedRows),this.fixedCols=e.fixedCols,this.fixedRows=e.fixedRows,this.cellAspectRatio=e.cellAspectRatio??1,this.cellWidth=e.cellWidth??8,this.cellHeight=e.cellHeight??8,this.fontSize=e.fontSize??12,this.fontFamily=e.fontFamily??"monospace",this.defaultFgColor=e.defaultFgColor??"#ffffff",this.defaultBgColor=e.defaultBgColor??"#000000",this.canvasBgColor=e.canvasBgColor!==void 0?e.canvasBgColor:null,this.showDebugGrid=e.showDebugGrid??!1,this.debugGridColor=e.debugGridColor??"rgba(144, 24, 24, 1)",this.scalingMode=e.scalingMode??T.None,window.getComputedStyle(this.parentElement).position==="static"&&(this.parentElement.style.position="relative"),this.containerDiv=document.createElement("div"),this.containerDiv.className="terminal2d-container",this.containerDiv.style.cssText=`
131
131
  position: absolute !important;
132
132
  top: 0 !important;
133
133
  left: 0 !important;
@@ -142,7 +142,7 @@ var it=Object.defineProperty;var at=(b,t,e)=>t in b?it(b,t,{enumerable:!0,config
142
142
  align-items: center !important;
143
143
  isolation: isolate !important;
144
144
  pointer-events: none !important;
145
- `,this.canvas=document.createElement("canvas"),this.canvas.className="terminal2d-canvas",e.className&&(this.canvas.className+=" "+e.className),e.style&&Object.assign(this.canvas.style,e.style),this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges",this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv);let s=this.canvas.getContext("2d",{alpha:!0,desynchronized:!1});if(!s)throw new Error("UTSPRender: Impossible d'obtenir le contexte 2D du canvas");this.ctx=s,this.ctx.imageSmoothingEnabled=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid(),this.showDebugGrid&&(this.gridOverlay=new A(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;if(!this.customCellSize){let h,c;if(this.fontType==="image"&&this.imageAtlas){let d=this.imageAtlas.getCellDimensions();h=d.width,c=d.height}else this.fontType==="bitmap"?(h=this.bitmapCharWidth,c=this.bitmapCharHeight):(h=Math.round(this.cellWidth)||10,c=Math.round(this.cellHeight)||14);this.cellWidth=Math.round(h),this.cellHeight=Math.round(c)}this.scalingMode===T.Responsive?(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1):this.fixedGridMode&&this.fixedCols&&this.fixedRows?(this.cols=this.fixedCols,this.rows=this.fixedRows):(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1);let i=this.cols*this.cellWidth,s=this.rows*this.cellHeight,a=t/i,r=e/s,o=Math.min(a,r),n;switch(this.scalingMode){case T.Integer:n=Math.max(1,Math.floor(o));break;case T.Half:n=Math.max(.5,Math.floor(o*2)/2);break;case T.Quarter:n=Math.max(.25,Math.floor(o*4)/4);break;case T.Eighth:n=Math.max(.125,Math.floor(o*8)/8);break;case T.Responsive:n=1;break;case T.None:default:n=Math.max(.1,o);break}this.currentScale=n,this.canvas.width=i,this.canvas.height=s,this.ctx.imageSmoothingEnabled=!1,this.canvas.style.cssText=`
145
+ `,this.canvas=document.createElement("canvas"),this.canvas.className="terminal2d-canvas",e.className&&(this.canvas.className+=" "+e.className),e.style&&Object.assign(this.canvas.style,e.style),this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges",this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv);let s=this.canvas.getContext("2d",{alpha:!0,desynchronized:!1});if(!s)throw new Error("UTSPRender: Impossible d'obtenir le contexte 2D du canvas");this.ctx=s,this.ctx.imageSmoothingEnabled=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid(),this.showDebugGrid&&(this.gridOverlay=new A(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;if(!this.customCellSize){let h,c;if(this.fontType==="image"&&this.imageAtlas){let d=this.imageAtlas.getCellDimensions();h=d.width,c=d.height}else this.fontType==="bitmap"?(h=this.bitmapCharWidth,c=this.bitmapCharHeight):(h=Math.round(this.cellWidth)||10,c=Math.round(this.cellHeight)||14);this.cellWidth=Math.round(h),this.cellHeight=Math.round(c)}this.scalingMode===T.Responsive?(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1):this.fixedGridMode&&this.fixedCols&&this.fixedRows?(this.cols=this.fixedCols,this.rows=this.fixedRows):(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1);let i=this.cols*this.cellWidth,s=this.rows*this.cellHeight,n=t/i,r=e/s,o=Math.min(n,r),a;switch(this.scalingMode){case T.Integer:a=Math.max(1,Math.floor(o));break;case T.Half:a=Math.max(.5,Math.floor(o*2)/2);break;case T.Quarter:a=Math.max(.25,Math.floor(o*4)/4);break;case T.Eighth:a=Math.max(.125,Math.floor(o*8)/8);break;case T.Responsive:a=1;break;case T.None:default:a=Math.max(.1,o);break}this.currentScale=a,this.canvas.width=i,this.canvas.height=s,this.ctx.imageSmoothingEnabled=!1,this.canvas.style.cssText=`
146
146
  flex-shrink: 0 !important;
147
147
  flex-grow: 0 !important;
148
148
  width: ${i}px !important;
@@ -151,12 +151,12 @@ var it=Object.defineProperty;var at=(b,t,e)=>t in b?it(b,t,{enumerable:!0,config
151
151
  image-rendering: crisp-edges !important;
152
152
  -ms-interpolation-mode: nearest-neighbor !important;
153
153
  transform-origin: center center !important;
154
- transform: scale(${n}) !important;
154
+ transform: scale(${a}) !important;
155
155
  will-change: transform !important;
156
156
  backface-visibility: hidden !important;
157
157
  pointer-events: auto !important;
158
158
  touch-action: none !important;
159
- `,this.fontType==="web"&&(this.fontSize=Math.round(this.cellHeight/14*12)),this.offsetX=0,this.offsetY=0}createEmptyGrid(){let t=[];for(let e=0;e<this.rows;e++){let i=[];for(let s=0;s<this.cols;s++)i.push({char:" ",fgColor:this.defaultFgColor,bgColor:this.defaultBgColor});t.push(i)}return t}enableAutoResize(){this.resizeObserver=new ResizeObserver(()=>{let t=this.cols,e=this.rows;if(this.calculateGridSize(),this.cols!==t||this.rows!==e){let i=this.cells;this.cells=this.createEmptyGrid();let s=Math.min(t,this.cols),a=Math.min(e,this.rows);for(let r=0;r<a;r++)for(let o=0;o<s;o++)this.cells[r][o]=i[r][o]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(t,e,i,s,a){if(e<0||e>=this.rows||t<0||t>=this.cols)return;let r=i&&typeof i=="string"?i.charAt(0):" ";this.cells[e][t]={char:r,fgColor:s??this.defaultFgColor,bgColor:a??this.defaultBgColor}}getCell(t,e){return e<0||e>=this.rows||t<0||t>=this.cols?null:this.cells[e][t]}write(t,e,i,s,a){for(let r=0;r<i.length;r++)this.setCell(t+r,e,i[r],s,a)}fillRect(t,e,i,s,a=" ",r,o){for(let n=e;n<e+s;n++)for(let h=t;h<t+i;h++)this.setCell(h,n,a,r,o)}clear(){this.cells=this.createEmptyGrid()}setFromArray(t){let e=t.width*t.height;if(t.cells.length!==e)throw new Error(`Invalid array length: expected ${e} (${t.width}\xD7${t.height}), got ${t.cells.length}`);let i=0;for(let s=0;s<t.height;s++)for(let a=0;a<t.width;a++){let r=t.cells[i];s<this.rows&&a<this.cols&&this.setCell(a,s,r.char,r.fgColor,r.bgColor),i++}}render(){if(this.fontType==="bitmap"&&this.bitmapFont&&this.useImageDataRendering){this.renderWithImageData();return}this.renderClassic()}renderWithImageData(){if(!this.bitmapFont)return;let t=this.cols*this.bitmapCharWidth,e=this.rows*this.bitmapCharHeight;(!this.imageDataBuffer||this.imageDataBuffer.width!==t||this.imageDataBuffer.height!==e)&&(this.imageDataBuffer=this.ctx.createImageData(t,e));let i=this.imageDataBuffer.data;for(let n=0;n<this.rows;n++)for(let h=0;h<this.cols;h++){let c=this.cells[n][h],d=this.parseColorToRGB(c.bgColor),f=this.parseColorToRGB(c.fgColor),m=c.char.charCodeAt(0),g=this.bitmapFont.get(m);for(let u=0;u<this.bitmapCharHeight;u++)for(let p=0;p<this.bitmapCharWidth;p++){let C=h*this.bitmapCharWidth+p,y=((n*this.bitmapCharHeight+u)*t+C)*4,E=!1;if(g&&u<g.length){let L=g[u],w=1<<7-p;E=(L&w)!==0}E?(i[y]=f.r,i[y+1]=f.g,i[y+2]=f.b,i[y+3]=f.a):(i[y]=d.r,i[y+1]=d.g,i[y+2]=d.b,i[y+3]=d.a)}}this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges";let s=document.createElement("canvas");s.width=t,s.height=e,s.getContext("2d").putImageData(this.imageDataBuffer,0,0);let r=this.cols*this.cellWidth,o=this.rows*this.cellHeight;this.ctx.drawImage(s,0,0,t,e,this.offsetX,this.offsetY,r,o),this.showDebugGrid&&this.drawDebugGrid()}parseColorToRGB(t){let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10),a:e[4]?Math.round(parseFloat(e[4])*255):255};if(t.startsWith("#")){let a=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(a,(o,n,h,c)=>n+n+h+h+c+c);let r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);if(r)return{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16),a:255}}let s={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255],transparent:[0,0,0]}[t.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2],a:t==="transparent"?0:255}:{r:255,g:255,b:255,a:255}}renderClassic(){this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.fontType==="bitmap"||this.fontType==="image"?(this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges"):(this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.canvas.style.imageRendering="auto",this.ctx.font=`${this.fontSize}px ${this.fontFamily}`,this.ctx.textBaseline="top",this.ctx.textRendering="optimizeLegibility");for(let t=0;t<this.rows;t++)for(let e=0;e<this.cols;e++){let i=this.cells[t][e],s=Math.floor(this.offsetX+e*this.cellWidth),a=Math.floor(this.offsetY+t*this.cellHeight),r=Math.floor(this.offsetX+(e+1)*this.cellWidth),o=Math.floor(this.offsetY+(t+1)*this.cellHeight),n=r-s,h=o-a;if((this.canvasBgColor!==null||i.bgColor!==this.defaultBgColor)&&(this.ctx.fillStyle=i.bgColor,this.ctx.fillRect(s,a,n,h)),i.char!==" ")if(this.fontType==="image"&&this.imageAtlas){let d=i.char.charCodeAt(0);this.imageAtlas.drawChar(this.ctx,d,s,a,n,h,i.fgColor)}else if(this.fontType==="bitmap"&&this.bitmapFont)this.drawBitmapChar(i.char,s,a,n,h,i.fgColor);else{this.ctx.fillStyle=i.fgColor;let d=s+(n-this.ctx.measureText(i.char).width)/2,f=a+(h-this.fontSize)/2;this.ctx.fillText(i.char,d,f)}}this.showDebugGrid&&this.drawDebugGrid()}drawBitmapChar(t,e,i,s,a,r){let o=t.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,o,e,i,s,a,r);return}if(!this.bitmapFont)return;let n=this.bitmapFont.get(o);if(!n)return;let h=s/this.bitmapCharWidth,c=a/this.bitmapCharHeight;this.ctx.fillStyle=r;for(let d=0;d<Math.min(n.length,this.bitmapCharHeight);d++){let f=n[d],m=i+d*c,g=i+(d+1)*c;for(let u=0;u<this.bitmapCharWidth;u++){let p=1<<7-u;if(f&p){let C=e+u*h,x=e+(u+1)*h;this.ctx.fillRect(C,m,x-C,g-m)}}}}drawDebugGrid(){if(!this.gridOverlay)return;let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;this.gridOverlay.update(this.cols,this.rows,this.cellWidth,this.cellHeight,t,e,this.offsetX,this.offsetY)}getCanvas(){return this.canvas}getContext(){return this.ctx}getDimensions(){return{cols:this.cols,rows:this.rows}}getCellDimensions(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getScalingMode(){return this.scalingMode}getOffsets(){return{offsetX:this.offsetX,offsetY:this.offsetY}}setDebugGrid(t){this.showDebugGrid=t,t&&!this.gridOverlay?(this.gridOverlay=new A(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10}),this.drawDebugGrid()):!t&&this.gridOverlay?(this.gridOverlay.destroy(),this.gridOverlay=void 0):t&&this.gridOverlay&&this.gridOverlay.setVisible(!0)}setCanvasBackgroundColor(t){this.canvasBgColor=t}getCanvasBackgroundColor(){return this.canvasBgColor}setFixedGrid(t,e,i){this.fixedGridMode=!0,this.fixedCols=t,this.fixedRows=e,i!==void 0&&(this.cellAspectRatio=i);let s=this.cols,a=this.rows,r=this.cells;if(this.calculateGridSize(),this.cols!==s||this.rows!==a){this.cells=this.createEmptyGrid();let o=Math.min(s,this.cols),n=Math.min(a,this.rows);for(let h=0;h<n;h++)for(let c=0;c<o;c++)this.cells[h][c]=r[h][c]}this.render()}setAdaptiveGrid(t,e){this.fixedGridMode=!1,this.fixedCols=void 0,this.fixedRows=void 0,t!==void 0&&(this.cellWidth=t),e!==void 0&&(this.cellHeight=e);let i=this.cols,s=this.rows,a=this.cells;if(this.calculateGridSize(),this.cols!==i||this.rows!==s){this.cells=this.createEmptyGrid();let r=Math.min(i,this.cols),o=Math.min(s,this.rows);for(let n=0;n<o;n++)for(let h=0;h<r;h++)this.cells[n][h]=a[n][h]}this.render()}isFixedGridMode(){return this.fixedGridMode}setDebugGridColor(t){this.debugGridColor=t}isDebugGridEnabled(){return this.showDebugGrid}setImageDataRendering(t){this.useImageDataRendering=t,t&&this.fontType==="bitmap"?console.warn("[Render] ImageData rendering enabled (optimized for benchmarks)"):t&&(console.warn("[Render] ImageData rendering requires bitmap font, keeping classic mode"),this.useImageDataRendering=!1)}isImageDataRenderingEnabled(){return this.useImageDataRendering}setWebFont(t,e){this.fontType="web",this.fontFamily=t,e!==void 0&&(this.fontSize=e),this.bitmapFont=void 0,this.bitmapAtlas=void 0,this.useImageDataRendering=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid()}setBitmapFont(t,e,i,s,a){this.fontType="bitmap",this.bitmapFont=t,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.bitmapAtlas=new F(t,e,i,s,a),this.cellWidth=s,this.cellHeight=a,this.calculateGridSize(),this.cells=this.createEmptyGrid()}async setImageFont(t,e,i,s,a,r){this.fontType="image",this.imageAtlas=new U({glyphWidth:e,glyphHeight:i,cellWidth:s,cellHeight:a,atlasBlocks:r}),await this.imageAtlas.loadFromPNG(t),this.cellWidth=s,this.cellHeight=a,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.calculateGridSize(),this.cells=this.createEmptyGrid()}getFontType(){return this.fontType}getBitmapFont(){return this.bitmapFont}getBitmapCharDimensions(){return this.fontType!=="bitmap"?null:{width:this.bitmapCharWidth,height:this.bitmapCharHeight}}setPalette(t){this.paletteCache=t}renderDisplayData(t){if(!t||!t.cells||t.cells.length===0){console.warn("[Terminal2D] Empty display data");return}if(t.width===0||t.height===0){console.warn("[Terminal2D] Invalid display dimensions:",t.width,t.height);return}(t.width!==this.cols||t.height!==this.rows)&&this.setFixedGrid(t.width,t.height,this.cellAspectRatio);let e=this.paletteCache??t.palette;if(!e||e.length===0){console.error("[Terminal2D] No palette available (neither cached nor in display)");return}let i=v(s=>{if(s==null||isNaN(s))return console.warn("[Terminal2D] Invalid palette index (undefined/null/NaN):",s),this.defaultFgColor;if(s===255)return"rgba(0, 0, 0, 0)";if(s<0||s>=e.length)return console.warn(`[Terminal2D] Invalid palette index: ${s}`),this.defaultFgColor;let a=e[s];return!a||typeof a.r!="number"?(console.warn(`[Terminal2D] Corrupted palette entry at index ${s}:`,a),this.defaultFgColor):`rgba(${a.r}, ${a.g}, ${a.b}, ${a.a/255})`},"convertColor");for(let s=0;s<t.height&&s<this.rows;s++)for(let a=0;a<t.width&&a<this.cols;a++){let r=s*t.width+a;if(r>=t.cells.length)break;let o=t.cells[r];if(!o)continue;let n=i(o.fgColorIndex),h=i(o.bgColorIndex);this.setCell(a,s,o.char??" ",n,h)}this.render()}isReady(){return!0}getCols(){return this.cols}getRows(){return this.rows}resize(t,e){this.setFixedGrid(t,e)}setScalingMode(t){if(this.scalingMode===t)return;let e=this.cols,i=this.rows;if(this.scalingMode=t,this.calculateGridSize(),this.cols!==e||this.rows!==i){let s=this.cells;if(this.cells=this.createEmptyGrid(),s&&s.length>0){let a=Math.min(e,this.cols),r=Math.min(i,this.rows);for(let o=0;o<r;o++)for(let n=0;n<a;n++)s[o]&&s[o][n]&&(this.cells[o][n]=s[o][n])}}this.render()}setCellSize(t,e){let i=Math.max(1,Math.min(255,Math.round(t))),s=Math.max(1,Math.min(255,Math.round(e)));if(this.cellWidth===i&&this.cellHeight===s)return;let a=this.cols,r=this.rows;if(this.cellWidth=i,this.cellHeight=s,this.customCellSize=!0,this.calculateGridSize(),this.cols!==a||this.rows!==r){let o=this.cells;if(this.cells=this.createEmptyGrid(),o&&o.length>0){let n=Math.min(a,this.cols),h=Math.min(r,this.rows);for(let c=0;c<h;c++)for(let d=0;d<n;d++)o[c]&&o[c][d]&&(this.cells[c][d]=o[c][d])}}this.render()}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}getMaxCells(){return 65536}destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=void 0),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}};v($,"Terminal2D");var k=$;var Y=class Y{constructor(t,e={}){l(this,"container");l(this,"overlayDiv",null);l(this,"button",null);l(this,"options");l(this,"started",!1);l(this,"onStartCallback");this.container=t,this.options={buttonText:e.buttonText??"Click to Start",onStart:e.onStart??(()=>{}),backgroundColor:e.backgroundColor??"rgba(0, 0, 0, 0.8)",buttonColor:e.buttonColor??"#4a90d9",buttonHoverColor:e.buttonHoverColor??"#357abd",buttonTextColor:e.buttonTextColor??"#ffffff",zIndex:e.zIndex??1e3},this.onStartCallback=e.onStart,this.createOverlay()}createOverlay(){let t=window.getComputedStyle(this.container).position;t!=="relative"&&t!=="absolute"&&t!=="fixed"&&(this.container.style.position="relative"),this.overlayDiv=document.createElement("div"),this.overlayDiv.className="utsp-autoplay-overlay",this.overlayDiv.style.cssText=`
159
+ `,this.fontType==="web"&&(this.fontSize=Math.round(this.cellHeight/14*12)),this.offsetX=0,this.offsetY=0}createEmptyGrid(){let t=[];for(let e=0;e<this.rows;e++){let i=[];for(let s=0;s<this.cols;s++)i.push({char:" ",fgColor:this.defaultFgColor,bgColor:this.defaultBgColor});t.push(i)}return t}enableAutoResize(){this.resizeObserver=new ResizeObserver(()=>{let t=this.cols,e=this.rows;if(this.calculateGridSize(),this.cols!==t||this.rows!==e){let i=this.cells;this.cells=this.createEmptyGrid();let s=Math.min(t,this.cols),n=Math.min(e,this.rows);for(let r=0;r<n;r++)for(let o=0;o<s;o++)this.cells[r][o]=i[r][o]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(t,e,i,s,n){if(e<0||e>=this.rows||t<0||t>=this.cols)return;let r=i&&typeof i=="string"?i.charAt(0):" ";this.cells[e][t]={char:r,fgColor:s??this.defaultFgColor,bgColor:n??this.defaultBgColor}}getCell(t,e){return e<0||e>=this.rows||t<0||t>=this.cols?null:this.cells[e][t]}write(t,e,i,s,n){for(let r=0;r<i.length;r++)this.setCell(t+r,e,i[r],s,n)}fillRect(t,e,i,s,n=" ",r,o){for(let a=e;a<e+s;a++)for(let h=t;h<t+i;h++)this.setCell(h,a,n,r,o)}clear(){this.cells=this.createEmptyGrid()}setFromArray(t){let e=t.width*t.height;if(t.cells.length!==e)throw new Error(`Invalid array length: expected ${e} (${t.width}\xD7${t.height}), got ${t.cells.length}`);let i=0;for(let s=0;s<t.height;s++)for(let n=0;n<t.width;n++){let r=t.cells[i];s<this.rows&&n<this.cols&&this.setCell(n,s,r.char,r.fgColor,r.bgColor),i++}}render(){if(this.fontType==="bitmap"&&this.bitmapFont&&this.useImageDataRendering){this.renderWithImageData();return}this.renderClassic()}renderWithImageData(){if(!this.bitmapFont)return;let t=this.cols*this.bitmapCharWidth,e=this.rows*this.bitmapCharHeight;(!this.imageDataBuffer||this.imageDataBuffer.width!==t||this.imageDataBuffer.height!==e)&&(this.imageDataBuffer=this.ctx.createImageData(t,e));let i=this.imageDataBuffer.data;for(let a=0;a<this.rows;a++)for(let h=0;h<this.cols;h++){let c=this.cells[a][h],d=this.parseColorToRGB(c.bgColor),f=this.parseColorToRGB(c.fgColor),m=c.char.charCodeAt(0),g=this.bitmapFont.get(m);for(let u=0;u<this.bitmapCharHeight;u++)for(let p=0;p<this.bitmapCharWidth;p++){let C=h*this.bitmapCharWidth+p,y=((a*this.bitmapCharHeight+u)*t+C)*4,E=!1;if(g&&u<g.length){let L=g[u],w=1<<7-p;E=(L&w)!==0}E?(i[y]=f.r,i[y+1]=f.g,i[y+2]=f.b,i[y+3]=f.a):(i[y]=d.r,i[y+1]=d.g,i[y+2]=d.b,i[y+3]=d.a)}}this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges";let s=document.createElement("canvas");s.width=t,s.height=e,s.getContext("2d").putImageData(this.imageDataBuffer,0,0);let r=this.cols*this.cellWidth,o=this.rows*this.cellHeight;this.ctx.drawImage(s,0,0,t,e,this.offsetX,this.offsetY,r,o),this.showDebugGrid&&this.drawDebugGrid()}parseColorToRGB(t){let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10),a:e[4]?Math.round(parseFloat(e[4])*255):255};if(t.startsWith("#")){let n=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(n,(o,a,h,c)=>a+a+h+h+c+c);let r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);if(r)return{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16),a:255}}let s={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255],transparent:[0,0,0]}[t.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2],a:t==="transparent"?0:255}:{r:255,g:255,b:255,a:255}}renderClassic(){this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.fontType==="bitmap"||this.fontType==="image"?(this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges"):(this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.canvas.style.imageRendering="auto",this.ctx.font=`${this.fontSize}px ${this.fontFamily}`,this.ctx.textBaseline="top",this.ctx.textRendering="optimizeLegibility");for(let t=0;t<this.rows;t++)for(let e=0;e<this.cols;e++){let i=this.cells[t][e],s=Math.floor(this.offsetX+e*this.cellWidth),n=Math.floor(this.offsetY+t*this.cellHeight),r=Math.floor(this.offsetX+(e+1)*this.cellWidth),o=Math.floor(this.offsetY+(t+1)*this.cellHeight),a=r-s,h=o-n;if((this.canvasBgColor!==null||i.bgColor!==this.defaultBgColor)&&(this.ctx.fillStyle=i.bgColor,this.ctx.fillRect(s,n,a,h)),i.char!==" ")if(this.fontType==="image"&&this.imageAtlas){let d=i.char.charCodeAt(0);this.imageAtlas.drawChar(this.ctx,d,s,n,a,h,i.fgColor)}else if(this.fontType==="bitmap"&&this.bitmapFont)this.drawBitmapChar(i.char,s,n,a,h,i.fgColor);else{this.ctx.fillStyle=i.fgColor;let d=s+(a-this.ctx.measureText(i.char).width)/2,f=n+(h-this.fontSize)/2;this.ctx.fillText(i.char,d,f)}}this.showDebugGrid&&this.drawDebugGrid()}drawBitmapChar(t,e,i,s,n,r){let o=t.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,o,e,i,s,n,r);return}if(!this.bitmapFont)return;let a=this.bitmapFont.get(o);if(!a)return;let h=s/this.bitmapCharWidth,c=n/this.bitmapCharHeight;this.ctx.fillStyle=r;for(let d=0;d<Math.min(a.length,this.bitmapCharHeight);d++){let f=a[d],m=i+d*c,g=i+(d+1)*c;for(let u=0;u<this.bitmapCharWidth;u++){let p=1<<7-u;if(f&p){let C=e+u*h,x=e+(u+1)*h;this.ctx.fillRect(C,m,x-C,g-m)}}}}drawDebugGrid(){if(!this.gridOverlay)return;let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;this.gridOverlay.update(this.cols,this.rows,this.cellWidth,this.cellHeight,t,e,this.offsetX,this.offsetY)}getCanvas(){return this.canvas}getContext(){return this.ctx}getDimensions(){return{cols:this.cols,rows:this.rows}}getCellDimensions(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getScalingMode(){return this.scalingMode}getOffsets(){return{offsetX:this.offsetX,offsetY:this.offsetY}}setDebugGrid(t){this.showDebugGrid=t,t&&!this.gridOverlay?(this.gridOverlay=new A(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10}),this.drawDebugGrid()):!t&&this.gridOverlay?(this.gridOverlay.destroy(),this.gridOverlay=void 0):t&&this.gridOverlay&&this.gridOverlay.setVisible(!0)}setCanvasBackgroundColor(t){this.canvasBgColor=t}getCanvasBackgroundColor(){return this.canvasBgColor}setFixedGrid(t,e,i){this.fixedGridMode=!0,this.fixedCols=t,this.fixedRows=e,i!==void 0&&(this.cellAspectRatio=i);let s=this.cols,n=this.rows,r=this.cells;if(this.calculateGridSize(),this.cols!==s||this.rows!==n){this.cells=this.createEmptyGrid();let o=Math.min(s,this.cols),a=Math.min(n,this.rows);for(let h=0;h<a;h++)for(let c=0;c<o;c++)this.cells[h][c]=r[h][c]}this.render()}setAdaptiveGrid(t,e){this.fixedGridMode=!1,this.fixedCols=void 0,this.fixedRows=void 0,t!==void 0&&(this.cellWidth=t),e!==void 0&&(this.cellHeight=e);let i=this.cols,s=this.rows,n=this.cells;if(this.calculateGridSize(),this.cols!==i||this.rows!==s){this.cells=this.createEmptyGrid();let r=Math.min(i,this.cols),o=Math.min(s,this.rows);for(let a=0;a<o;a++)for(let h=0;h<r;h++)this.cells[a][h]=n[a][h]}this.render()}isFixedGridMode(){return this.fixedGridMode}setDebugGridColor(t){this.debugGridColor=t}isDebugGridEnabled(){return this.showDebugGrid}setImageDataRendering(t){this.useImageDataRendering=t,t&&this.fontType==="bitmap"?console.warn("[Render] ImageData rendering enabled (optimized for benchmarks)"):t&&(console.warn("[Render] ImageData rendering requires bitmap font, keeping classic mode"),this.useImageDataRendering=!1)}isImageDataRenderingEnabled(){return this.useImageDataRendering}setWebFont(t,e){this.fontType="web",this.fontFamily=t,e!==void 0&&(this.fontSize=e),this.bitmapFont=void 0,this.bitmapAtlas=void 0,this.useImageDataRendering=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid()}setBitmapFont(t,e,i,s,n){this.fontType="bitmap",this.bitmapFont=t,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.bitmapAtlas=new F(t,e,i,s,n),this.cellWidth=s,this.cellHeight=n,this.calculateGridSize(),this.cells=this.createEmptyGrid()}async setImageFont(t,e,i,s,n,r){this.fontType="image",this.imageAtlas=new U({glyphWidth:e,glyphHeight:i,cellWidth:s,cellHeight:n,atlasBlocks:r}),await this.imageAtlas.loadFromPNG(t),this.cellWidth=s,this.cellHeight=n,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.calculateGridSize(),this.cells=this.createEmptyGrid()}getFontType(){return this.fontType}getBitmapFont(){return this.bitmapFont}getBitmapCharDimensions(){return this.fontType!=="bitmap"?null:{width:this.bitmapCharWidth,height:this.bitmapCharHeight}}setPalette(t){this.paletteCache=t}renderDisplayData(t){if(!t||!t.cells||t.cells.length===0){console.warn("[Terminal2D] Empty display data");return}if(t.width===0||t.height===0){console.warn("[Terminal2D] Invalid display dimensions:",t.width,t.height);return}(t.width!==this.cols||t.height!==this.rows)&&this.setFixedGrid(t.width,t.height,this.cellAspectRatio);let e=this.paletteCache??t.palette;if(!e||e.length===0){console.error("[Terminal2D] No palette available (neither cached nor in display)");return}let i=v(s=>{if(s==null||isNaN(s))return console.warn("[Terminal2D] Invalid palette index (undefined/null/NaN):",s),this.defaultFgColor;if(s===255)return"rgba(0, 0, 0, 0)";if(s<0||s>=e.length)return console.warn(`[Terminal2D] Invalid palette index: ${s}`),this.defaultFgColor;let n=e[s];return!n||typeof n.r!="number"?(console.warn(`[Terminal2D] Corrupted palette entry at index ${s}:`,n),this.defaultFgColor):`rgba(${n.r}, ${n.g}, ${n.b}, ${n.a/255})`},"convertColor");for(let s=0;s<t.height&&s<this.rows;s++)for(let n=0;n<t.width&&n<this.cols;n++){let r=s*t.width+n;if(r>=t.cells.length)break;let o=t.cells[r];if(!o)continue;let a=i(o.fgColorIndex),h=i(o.bgColorIndex);this.setCell(n,s,o.char??" ",a,h)}this.render()}isReady(){return!0}getCols(){return this.cols}getRows(){return this.rows}resize(t,e){this.setFixedGrid(t,e)}setScalingMode(t){if(this.scalingMode===t)return;let e=this.cols,i=this.rows;if(this.scalingMode=t,this.calculateGridSize(),this.cols!==e||this.rows!==i){let s=this.cells;if(this.cells=this.createEmptyGrid(),s&&s.length>0){let n=Math.min(e,this.cols),r=Math.min(i,this.rows);for(let o=0;o<r;o++)for(let a=0;a<n;a++)s[o]&&s[o][a]&&(this.cells[o][a]=s[o][a])}}this.render()}setCellSize(t,e){let i=Math.max(1,Math.min(255,Math.round(t))),s=Math.max(1,Math.min(255,Math.round(e)));if(this.cellWidth===i&&this.cellHeight===s)return;let n=this.cols,r=this.rows;if(this.cellWidth=i,this.cellHeight=s,this.customCellSize=!0,this.calculateGridSize(),this.cols!==n||this.rows!==r){let o=this.cells;if(this.cells=this.createEmptyGrid(),o&&o.length>0){let a=Math.min(n,this.cols),h=Math.min(r,this.rows);for(let c=0;c<h;c++)for(let d=0;d<a;d++)o[c]&&o[c][d]&&(this.cells[c][d]=o[c][d])}}this.render()}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}getMaxCells(){return 65536}destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=void 0),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}};v($,"Terminal2D");var k=$;var Y=class Y{constructor(t,e={}){l(this,"container");l(this,"overlayDiv",null);l(this,"button",null);l(this,"options");l(this,"started",!1);l(this,"onStartCallback");this.container=t,this.options={buttonText:e.buttonText??"Click to Start",onStart:e.onStart??(()=>{}),backgroundColor:e.backgroundColor??"rgba(0, 0, 0, 0.8)",buttonColor:e.buttonColor??"#4a90d9",buttonHoverColor:e.buttonHoverColor??"#357abd",buttonTextColor:e.buttonTextColor??"#ffffff",zIndex:e.zIndex??1e3},this.onStartCallback=e.onStart,this.createOverlay()}createOverlay(){let t=window.getComputedStyle(this.container).position;t!=="relative"&&t!=="absolute"&&t!=="fixed"&&(this.container.style.position="relative"),this.overlayDiv=document.createElement("div"),this.overlayDiv.className="utsp-autoplay-overlay",this.overlayDiv.style.cssText=`
160
160
  position: absolute !important;
161
161
  top: 0 !important;
162
162
  left: 0 !important;
@@ -198,5 +198,5 @@ var it=Object.defineProperty;var at=(b,t,e)=>t in b?it(b,t,{enumerable:!0,config
198
198
  width: 100% !important;
199
199
  height: 100% !important;
200
200
  pointer-events: none !important;
201
- `;let i=this.canvas.getContext("2d",{alpha:!0});if(!i)throw new Error("PostProcessOverlay: Failed to get 2D context");this.ctx=i,this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv),this.resizeObserver=new ResizeObserver(a=>{for(let r of a){let{width:o,height:n}=r.contentRect;o>0&&n>0&&this.handleResize(Math.floor(o),Math.floor(n))}}),this.resizeObserver.observe(this.parentElement);let s=this.parentElement.getBoundingClientRect();s.width>0&&s.height>0&&this.handleResize(Math.floor(s.width),Math.floor(s.height)),this.hide()}handleResize(t,e){this.width===t&&this.height===e||(this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.currentConfig&&this.isActive()&&this.render())}setConfig(t){let e=this.hashConfig(t);if(e!==this.configHash){if(this.currentConfig=t,this.configHash=e,!t||!this.isActiveConfig(t)){this.clear(),this.hide();return}this.show(),this.render()}}setScanlines(t){t===null?this.setConfig({scanlines:{enabled:!1}}):this.setConfig({scanlines:t})}setScanlinesEnabled(t){if(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:!0,opacity:e?.opacity??H.scanlines.opacity,pattern:e?.pattern??"horizontal",spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}else this.setScanlines({enabled:!1})}setScanlinesOpacity(t){let e=Math.max(0,Math.min(1,t)),i=this.currentConfig?.scanlines;this.setScanlines({enabled:i?.enabled??!0,opacity:e,pattern:i?.pattern??"horizontal",spacing:i?.spacing??2,thickness:i?.thickness??1,color:i?.color??{r:0,g:0,b:0}})}setScanlinesPattern(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:e?.enabled??!0,opacity:e?.opacity??H.scanlines.opacity,pattern:t,spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}setScanlinesSpacing(t){let e=Math.max(2,Math.round(t)),i=this.currentConfig?.scanlines;this.setScanlines({enabled:i?.enabled??!0,opacity:i?.opacity??H.scanlines.opacity,pattern:i?.pattern??"horizontal",spacing:e,thickness:i?.thickness??1,color:i?.color??{r:0,g:0,b:0}})}getConfig(){return this.currentConfig}isActive(){return this.isActiveConfig(this.currentConfig)}destroy(){this.resizeObserver.disconnect(),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}syncWithRenderer(t){}resize(t,e){}setCellDimensions(t,e){}show(){this.containerDiv.style.display="block"}hide(){this.containerDiv.style.display="none"}clear(){this.ctx.clearRect(0,0,this.width,this.height)}isActiveConfig(t){return t?.scanlines?.enabled??!1}render(){this.clear(),this.currentConfig?.scanlines?.enabled&&this.renderScanlines(this.currentConfig.scanlines)}renderScanlines(t){let e=t.opacity??H.scanlines.opacity,i=t.pattern??"horizontal",s=t.spacing??2,a=t.thickness??1,r=t.color??{r:0,g:0,b:0},o=this.ctx;switch(o.fillStyle=`rgba(${r.r}, ${r.g}, ${r.b}, ${e})`,i){case"horizontal":for(let n=s-1;n<this.height;n+=s)o.fillRect(0,n,this.width,a);break;case"vertical":for(let n=s-1;n<this.width;n+=s)o.fillRect(n,0,a,this.height);break;case"grid":for(let n=s-1;n<this.height;n+=s)o.fillRect(0,n,this.width,a);for(let n=s-1;n<this.width;n+=s)o.fillRect(n,0,a,this.height);break}}hashConfig(t){return t?JSON.stringify(t):"null"}};v(X,"PostProcessOverlay");var V=X;var q="\x1B[0m",st="\x1B[H",lt="\x1B[2J",rt="\x1B[?25l",ht="\x1B[?25h",ct=`
202
- `,Q=class Q{constructor(t={}){l(this,"options");l(this,"fgCache",[]);l(this,"bgCache",[]);l(this,"lastPalette",null);this.options={optimizeColors:t.optimizeColors??!0,includeHome:t.includeHome??!0,hideCursor:t.hideCursor??!0,includeNewlines:t.includeNewlines??!0,includeReset:t.includeReset??!0}}buildColorCache(t){if(this.lastPalette!==t){this.fgCache=new Array(t.length),this.bgCache=new Array(t.length);for(let e=0;e<t.length;e++){let i=t[e];this.fgCache[e]=`\x1B[38;2;${i.r};${i.g};${i.b}m`,this.bgCache[e]=`\x1B[48;2;${i.r};${i.g};${i.b}m`}this.lastPalette=t}}render(t){let{width:e,height:i,cells:s,palette:a}=t;this.buildColorCache(a);let r="";this.options.hideCursor&&(r+=rt),this.options.includeHome&&(r+=st);let o=-1,n=-1,h=this.options.optimizeColors,c=this.options.includeNewlines;for(let d=0;d<i;d++){let f=d*e;for(let m=0;m<e;m++){let g=s[f+m],u=g.fgColorIndex,p=g.bgColorIndex;h?(p!==n&&(r+=this.bgCache[p],n=p),u!==o&&(r+=this.fgCache[u],o=u)):(r+=this.bgCache[p],r+=this.fgCache[u]),r+=g.char||" "}c&&d<i-1&&(r+=ct)}return this.options.includeReset&&(r+=q),r}renderRow(t,e){let{width:i,cells:s,palette:a}=t;this.buildColorCache(a);let r=`\x1B[${e+1};1H`,o=-1,n=-1,h=this.options.optimizeColors,c=e*i;for(let d=0;d<i;d++){let f=s[c+d],m=f.fgColorIndex,g=f.bgColorIndex;h?(g!==n&&(r+=this.bgCache[g],n=g),m!==o&&(r+=this.fgCache[m],o=m)):(r+=this.bgCache[g],r+=this.fgCache[m]),r+=f.char||" "}return this.options.includeReset&&(r+=q),r}clear(){return lt+st}showCursor(){return ht}hideCursor(){return rt}reset(){return q}moveTo(t,e){return`\x1B[${t+1};${e+1}H`}};v(Q,"TerminalANSI");var j=Q;function dt(b){let t=b.startsWith("#")?b.slice(1):b,e=t.length===3?t[0]+t[0]+t[1]+t[1]+t[2]+t[2]:t,i=parseInt(e,16);return{r:i>>16&255,g:i>>8&255,b:i&255,a:255}}v(dt,"hexToRGB");function ft(b){let t=b.r.toString(16).padStart(2,"0"),e=b.g.toString(16).padStart(2,"0"),i=b.b.toString(16).padStart(2,"0");return`#${t}${e}${i}`}v(ft,"rgbToHex");function ut(b,t){let e=[{r:0,g:0,b:0,a:255},{r:128,g:0,b:0,a:255},{r:0,g:128,b:0,a:255},{r:128,g:128,b:0,a:255},{r:0,g:0,b:128,a:255},{r:128,g:0,b:128,a:255},{r:0,g:128,b:128,a:255},{r:192,g:192,b:192,a:255},{r:128,g:128,b:128,a:255},{r:255,g:0,b:0,a:255},{r:0,g:255,b:0,a:255},{r:255,g:255,b:0,a:255},{r:0,g:0,b:255,a:255},{r:255,g:0,b:255,a:255},{r:0,g:255,b:255,a:255},{r:255,g:255,b:255,a:255}];for(;e.length<256;)e.push({r:128,g:128,b:128,a:255});let i=[];for(let s=0;s<t;s++)for(let a=0;a<b;a++)i.push({char:String.fromCharCode(65+(a+s)%26),fgColorIndex:15,bgColorIndex:(a+s)%16,fgEmission:0,bgEmission:0});return{id:0,width:b,height:t,cells:i,palette:e}}v(ut,"createTestRenderState");var Yt="0.1.0";export{N as AutoplayOverlay,F as BitmapFontAtlas,G as DEFAULT_PALETTE,A as GridOverlay,U as ImageFontAtlas,V as PostProcessOverlay,R as ScalingMode,k as Terminal2D,j as TerminalANSI,P as TerminalGL,ot as colorToPaletteIndex,ut as createTestRenderState,M as getAtlasColumns,B as getCharGridPosition,S as getMaxCharCode,dt as hexToRGB,nt as paletteIndexToColor,ft as rgbToHex,Yt as version};
201
+ `;let i=this.canvas.getContext("2d",{alpha:!0});if(!i)throw new Error("PostProcessOverlay: Failed to get 2D context");this.ctx=i,this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv),this.resizeObserver=new ResizeObserver(n=>{for(let r of n){let{width:o,height:a}=r.contentRect;o>0&&a>0&&this.handleResize(Math.floor(o),Math.floor(a))}}),this.resizeObserver.observe(this.parentElement);let s=this.parentElement.getBoundingClientRect();s.width>0&&s.height>0&&this.handleResize(Math.floor(s.width),Math.floor(s.height)),this.hide()}handleResize(t,e){this.width===t&&this.height===e||(this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.currentConfig&&this.isActive()&&this.render())}setConfig(t){let e=this.hashConfig(t);if(e!==this.configHash){if(this.currentConfig=t,this.configHash=e,!t||!this.isActiveConfig(t)){this.clear(),this.hide();return}this.show(),this.render()}}setScanlines(t){t===null?this.setConfig({scanlines:{enabled:!1}}):this.setConfig({scanlines:t})}setScanlinesEnabled(t){if(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:!0,opacity:e?.opacity??H.scanlines.opacity,pattern:e?.pattern??"horizontal",spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}else this.setScanlines({enabled:!1})}setScanlinesOpacity(t){let e=Math.max(0,Math.min(1,t)),i=this.currentConfig?.scanlines;this.setScanlines({enabled:i?.enabled??!0,opacity:e,pattern:i?.pattern??"horizontal",spacing:i?.spacing??2,thickness:i?.thickness??1,color:i?.color??{r:0,g:0,b:0}})}setScanlinesPattern(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:e?.enabled??!0,opacity:e?.opacity??H.scanlines.opacity,pattern:t,spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}setScanlinesSpacing(t){let e=Math.max(2,Math.round(t)),i=this.currentConfig?.scanlines;this.setScanlines({enabled:i?.enabled??!0,opacity:i?.opacity??H.scanlines.opacity,pattern:i?.pattern??"horizontal",spacing:e,thickness:i?.thickness??1,color:i?.color??{r:0,g:0,b:0}})}getConfig(){return this.currentConfig}isActive(){return this.isActiveConfig(this.currentConfig)}destroy(){this.resizeObserver.disconnect(),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}syncWithRenderer(t){}resize(t,e){}setCellDimensions(t,e){}show(){this.containerDiv.style.display="block"}hide(){this.containerDiv.style.display="none"}clear(){this.ctx.clearRect(0,0,this.width,this.height)}isActiveConfig(t){return t?.scanlines?.enabled??!1}render(){this.clear(),this.currentConfig?.scanlines?.enabled&&this.renderScanlines(this.currentConfig.scanlines)}renderScanlines(t){let e=t.opacity??H.scanlines.opacity,i=t.pattern??"horizontal",s=t.spacing??2,n=t.thickness??1,r=t.color??{r:0,g:0,b:0},o=this.ctx;switch(o.fillStyle=`rgba(${r.r}, ${r.g}, ${r.b}, ${e})`,i){case"horizontal":for(let a=s-1;a<this.height;a+=s)o.fillRect(0,a,this.width,n);break;case"vertical":for(let a=s-1;a<this.width;a+=s)o.fillRect(a,0,n,this.height);break;case"grid":for(let a=s-1;a<this.height;a+=s)o.fillRect(0,a,this.width,n);for(let a=s-1;a<this.width;a+=s)o.fillRect(a,0,n,this.height);break}}hashConfig(t){return t?JSON.stringify(t):"null"}};v(X,"PostProcessOverlay");var V=X;var q="\x1B[0m",st="\x1B[H",lt="\x1B[2J",rt="\x1B[?25l",ht="\x1B[?25h",ct=`
202
+ `,Q=class Q{constructor(t={}){l(this,"options");l(this,"fgCache",[]);l(this,"bgCache",[]);l(this,"lastPalette",null);this.options={optimizeColors:t.optimizeColors??!0,includeHome:t.includeHome??!0,hideCursor:t.hideCursor??!0,includeNewlines:t.includeNewlines??!0,includeReset:t.includeReset??!0}}buildColorCache(t){if(this.lastPalette!==t){this.fgCache=new Array(t.length),this.bgCache=new Array(t.length);for(let e=0;e<t.length;e++){let i=t[e];this.fgCache[e]=`\x1B[38;2;${i.r};${i.g};${i.b}m`,this.bgCache[e]=`\x1B[48;2;${i.r};${i.g};${i.b}m`}this.lastPalette=t}}render(t){let{width:e,height:i,cells:s,palette:n}=t;this.buildColorCache(n);let r="";this.options.hideCursor&&(r+=rt),this.options.includeHome&&(r+=st);let o=-1,a=-1,h=this.options.optimizeColors,c=this.options.includeNewlines;for(let d=0;d<i;d++){let f=d*e;for(let m=0;m<e;m++){let g=s[f+m],u=g.fgColorIndex,p=g.bgColorIndex;h?(p!==a&&(r+=this.bgCache[p],a=p),u!==o&&(r+=this.fgCache[u],o=u)):(r+=this.bgCache[p],r+=this.fgCache[u]),r+=g.char||" "}c&&d<i-1&&(r+=ct)}return this.options.includeReset&&(r+=q),r}renderRow(t,e){let{width:i,cells:s,palette:n}=t;this.buildColorCache(n);let r=`\x1B[${e+1};1H`,o=-1,a=-1,h=this.options.optimizeColors,c=e*i;for(let d=0;d<i;d++){let f=s[c+d],m=f.fgColorIndex,g=f.bgColorIndex;h?(g!==a&&(r+=this.bgCache[g],a=g),m!==o&&(r+=this.fgCache[m],o=m)):(r+=this.bgCache[g],r+=this.fgCache[m]),r+=f.char||" "}return this.options.includeReset&&(r+=q),r}clear(){return lt+st}showCursor(){return ht}hideCursor(){return rt}reset(){return q}moveTo(t,e){return`\x1B[${t+1};${e+1}H`}};v(Q,"TerminalANSI");var j=Q;function dt(b){let t=b.startsWith("#")?b.slice(1):b,e=t.length===3?t[0]+t[0]+t[1]+t[1]+t[2]+t[2]:t,i=parseInt(e,16);return{r:i>>16&255,g:i>>8&255,b:i&255,a:255}}v(dt,"hexToRGB");function ft(b){let t=b.r.toString(16).padStart(2,"0"),e=b.g.toString(16).padStart(2,"0"),i=b.b.toString(16).padStart(2,"0");return`#${t}${e}${i}`}v(ft,"rgbToHex");function ut(b,t){let e=[{r:0,g:0,b:0,a:255},{r:128,g:0,b:0,a:255},{r:0,g:128,b:0,a:255},{r:128,g:128,b:0,a:255},{r:0,g:0,b:128,a:255},{r:128,g:0,b:128,a:255},{r:0,g:128,b:128,a:255},{r:192,g:192,b:192,a:255},{r:128,g:128,b:128,a:255},{r:255,g:0,b:0,a:255},{r:0,g:255,b:0,a:255},{r:255,g:255,b:0,a:255},{r:0,g:0,b:255,a:255},{r:255,g:0,b:255,a:255},{r:0,g:255,b:255,a:255},{r:255,g:255,b:255,a:255}];for(;e.length<256;)e.push({r:128,g:128,b:128,a:255});let i=[];for(let s=0;s<t;s++)for(let n=0;n<b;n++)i.push({char:String.fromCharCode(65+(n+s)%26),fgColorIndex:15,bgColorIndex:(n+s)%16,fgEmission:0,bgEmission:0});return{id:0,width:b,height:t,cells:i,palette:e}}v(ut,"createTestRenderState");var Yt="0.1.0";export{N as AutoplayOverlay,F as BitmapFontAtlas,G as DEFAULT_PALETTE,A as GridOverlay,U as ImageFontAtlas,V as PostProcessOverlay,R as ScalingMode,k as Terminal2D,j as TerminalANSI,_ as TerminalGL,ot as colorToPaletteIndex,ut as createTestRenderState,M as getAtlasColumns,B as getCharGridPosition,S as getMaxCharCode,dt as hexToRGB,at as paletteIndexToColor,ft as rgbToHex,Yt as version};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utsp/render",
3
- "version": "0.15.0",
3
+ "version": "0.16.0-nightly.20260101200530.42ed56f",
4
4
  "description": "UTSP Render - Rendering engine for terminal graphics with WebGL, Canvas 2D, and ANSI terminal support",
5
5
  "author": "THP Software",
6
6
  "license": "MIT",
@@ -86,7 +86,7 @@
86
86
  "access": "public"
87
87
  },
88
88
  "dependencies": {
89
- "@utsp/types": "0.15.0"
89
+ "@utsp/types": "0.16.0-nightly.20260101200530.42ed56f"
90
90
  },
91
91
  "devDependencies": {
92
92
  "typescript": "^5.6.3"