@utsp/render 0.2.0-nightly.20251129171929.16a5bbd → 0.3.0-nightly.20251201155650.4e6ade1

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/index.cjs CHANGED
@@ -1,15 +1,15 @@
1
- "use strict";var B=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var X=Object.prototype.hasOwnProperty;var V=(v,e,t)=>e in v?B(v,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):v[e]=t;var A=(v,e)=>B(v,"name",{value:e,configurable:!0});var k=(v,e)=>{for(var t in e)B(v,t,{get:e[t],enumerable:!0})},q=(v,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of $(e))!X.call(v,i)&&i!==t&&B(v,i,{get:()=>e[i],enumerable:!(s=N(e,i))||s.enumerable});return v};var j=v=>q(B({},"__esModule",{value:!0}),v);var a=(v,e,t)=>(V(v,typeof e!="symbol"?e+"":e,t),t);var Z={};k(Z,{BitmapFontAtlas:()=>I,DEFAULT_PALETTE:()=>U,GridOverlay:()=>w,Terminal2D:()=>L,TerminalGL:()=>D,colorToPaletteIndex:()=>z,paletteIndexToColor:()=>Y,version:()=>Q});module.exports=j(Z);var U=["#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 Y(v,e=U){return v<0||v>=e.length?"#ff00ff":e[v]}A(Y,"paletteIndexToColor");function z(v,e=U){let t=e.indexOf(v.toLowerCase());return t>=0?t:0}A(z,"colorToPaletteIndex");var _=class _{constructor(e,t){a(this,"canvas");a(this,"ctx");a(this,"container");a(this,"cols",0);a(this,"rows",0);a(this,"cellWidth",0);a(this,"cellHeight",0);a(this,"offsetX",0);a(this,"offsetY",0);a(this,"strokeColor","rgba(80, 80, 80, 0.4)");a(this,"lineWidth",1);a(this,"innerPadding",1);this.container=e,this.canvas=document.createElement("canvas"),this.canvas.className="grid-overlay-canvas";let s=t?.zIndex??10;this.canvas.style.cssText=`
1
+ "use strict";var B=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var V=Object.prototype.hasOwnProperty;var q=(v,t,e)=>t in v?B(v,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):v[t]=e;var T=(v,t)=>B(v,"name",{value:t,configurable:!0});var j=(v,t)=>{for(var e in t)B(v,e,{get:t[e],enumerable:!0})},Q=(v,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of X(t))!V.call(v,i)&&i!==e&&B(v,i,{get:()=>t[i],enumerable:!(r=k(t,i))||r.enumerable});return v};var Z=v=>Q(B({},"__esModule",{value:!0}),v);var a=(v,t,e)=>(q(v,typeof t!="symbol"?t+"":t,e),e);var J={};j(J,{AutoplayOverlay:()=>M,BitmapFontAtlas:()=>I,DEFAULT_PALETTE:()=>D,GridOverlay:()=>y,Terminal2D:()=>L,TerminalGL:()=>U,colorToPaletteIndex:()=>N,paletteIndexToColor:()=>$,version:()=>K});module.exports=Z(J);var D=["#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 $(v,t=D){return v<0||v>=t.length?"#ff00ff":t[v]}T($,"paletteIndexToColor");function N(v,t=D){let e=t.indexOf(v.toLowerCase());return e>=0?e:0}T(N,"colorToPaletteIndex");var _=class _{constructor(t,e){a(this,"canvas");a(this,"ctx");a(this,"container");a(this,"cols",0);a(this,"rows",0);a(this,"cellWidth",0);a(this,"cellHeight",0);a(this,"offsetX",0);a(this,"offsetY",0);a(this,"strokeColor","rgba(80, 80, 80, 0.4)");a(this,"lineWidth",1);a(this,"innerPadding",1);this.container=t,this.canvas=document.createElement("canvas"),this.canvas.className="grid-overlay-canvas";let r=e?.zIndex??10;this.canvas.style.cssText=`
2
2
  position: absolute !important;
3
3
  top: 0 !important;
4
4
  left: 0 !important;
5
5
  width: 100% !important;
6
6
  height: 100% !important;
7
7
  object-fit: contain !important;
8
- z-index: ${s} !important;
8
+ z-index: ${r} !important;
9
9
  pointer-events: none !important;
10
10
  image-rendering: pixelated !important;
11
11
  image-rendering: crisp-edges !important;
12
- `,this.container.appendChild(this.canvas);let i=this.canvas.getContext("2d");if(!i)throw new Error("[GridOverlay] Impossible de cr\xE9er le contexte 2D");this.ctx=i,t&&(t.strokeColor&&(this.strokeColor=t.strokeColor),t.lineWidth!==void 0&&(this.lineWidth=t.lineWidth),t.innerPadding!==void 0&&(this.innerPadding=t.innerPadding))}setDimensions(e,t,s,i,r=0,n=0){this.cols=e,this.rows=t,this.cellWidth=s,this.cellHeight=i,this.offsetX=r,this.offsetY=n}setCanvasSize(e,t){let s=window.devicePixelRatio||1;this.canvas.width=e*s,this.canvas.height=t*s,this.ctx.setTransform(1,0,0,1,0,0),this.ctx.scale(s,s)}setStyle(e){e.strokeColor&&(this.strokeColor=e.strokeColor),e.lineWidth!==void 0&&(this.lineWidth=e.lineWidth),e.innerPadding!==void 0&&(this.innerPadding=e.innerPadding)}render(){if(!this.ctx)return;this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.strokeStyle=this.strokeColor,this.ctx.lineWidth=this.lineWidth;let e=this.cols*this.cellWidth,t=this.rows*this.cellHeight;this.ctx.beginPath();for(let s=0;s<=this.cols;s++){let i=this.offsetX+s*this.cellWidth;if(s===0){let r=i+this.innerPadding+.5;this.ctx.moveTo(r,this.offsetY+this.innerPadding),this.ctx.lineTo(r,this.offsetY+t-this.innerPadding)}else if(s===this.cols){let r=i-this.innerPadding+.5;this.ctx.moveTo(r,this.offsetY+this.innerPadding),this.ctx.lineTo(r,this.offsetY+t-this.innerPadding)}else{let r=i+.5;this.ctx.moveTo(r,this.offsetY+this.innerPadding),this.ctx.lineTo(r,this.offsetY+t-this.innerPadding)}}for(let s=0;s<=this.rows;s++){let i=this.offsetY+s*this.cellHeight;if(s===0){let r=i+this.innerPadding+.5;this.ctx.moveTo(this.offsetX+this.innerPadding,r),this.ctx.lineTo(this.offsetX+e-this.innerPadding,r)}else if(s===this.rows){let r=i-this.innerPadding+.5;this.ctx.moveTo(this.offsetX+this.innerPadding,r),this.ctx.lineTo(this.offsetX+e-this.innerPadding,r)}else{let r=i+.5;this.ctx.moveTo(this.offsetX+this.innerPadding,r),this.ctx.lineTo(this.offsetX+e-this.innerPadding,r)}}this.ctx.stroke()}update(e,t,s,i,r,n,l=0,o=0){this.setDimensions(e,t,s,i,l,o),this.setCanvasSize(r,n),this.render()}setVisible(e){this.canvas.style.display=e?"block":"none"}destroy(){this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}getCanvas(){return this.canvas}};A(_,"GridOverlay");var w=_;var F=class F{constructor(e,t){a(this,"canvas");a(this,"gl");a(this,"parentElement");a(this,"containerDiv");a(this,"cols");a(this,"rows");a(this,"charWidth");a(this,"charHeight");a(this,"cellWidth",8);a(this,"cellHeight",8);a(this,"glyphOffsetX",0);a(this,"glyphOffsetY",0);a(this,"canvasBgColor");a(this,"showGrid");a(this,"supportsUint32Indices",!1);a(this,"useUint16Indices",!1);a(this,"gridOverlay");a(this,"bitmapFont");a(this,"atlasTexture",null);a(this,"atlasCanvas");a(this,"atlasColumns",0);a(this,"paletteTexture",null);a(this,"program",null);a(this,"positionBuffer",null);a(this,"texCoordBuffer",null);a(this,"colorIndexBuffer",null);a(this,"indexBuffer",null);a(this,"aPosition");a(this,"aTexCoord");a(this,"aColorIndex");a(this,"uResolution",null);a(this,"uTexture",null);a(this,"uPalette",null);a(this,"resizeObserver");a(this,"charCodeToAtlasIndex",new Uint16Array(65536).fill(65535));a(this,"atlasUVs",new Float32Array(0));a(this,"cachedAtlasWidth",0);a(this,"cachedAtlasHeight",0);a(this,"paletteFloat",new Float32Array(256*4));a(this,"maxCells",0);a(this,"renderPositions",new Float32Array(0));a(this,"renderTexCoords",new Float32Array(0));a(this,"renderColorIndices",new Float32Array(0));a(this,"renderIndices",new Uint32Array(0));a(this,"cachedResolution",[0,0]);a(this,"cachedTextureUnit",-1);a(this,"cachedPaletteUnit",-1);a(this,"cachedTextureUniform",!1);a(this,"cachedPaletteUniform",!1);a(this,"paletteHash",0);a(this,"staticPositionsInitialized",!1);a(this,"vaoExtension",null);a(this,"vao",null);a(this,"instancedExtension",null);a(this,"useInstancing",!1);a(this,"instanceDataBuffer",null);a(this,"instanceData",new Float32Array(0));a(this,"templateQuadPositions",new Float32Array(0));a(this,"templateQuadIndices",new Uint16Array(0));if(!e)throw new Error("TerminalGL: Parent element is required");if(!Number.isInteger(t.cols)||t.cols<=0)throw new Error(`TerminalGL: Invalid cols: ${t.cols}. Must be a positive integer.`);if(!Number.isInteger(t.rows)||t.rows<=0)throw new Error(`TerminalGL: Invalid rows: ${t.rows}. Must be a positive integer.`);let s=t.cols*t.rows,i=F.checkCompatibility();if(i.errors.length>0)throw new Error(`TerminalGL: WebGL incompatible - ${i.errors.join(", ")}`);let r=t.forceUint16??!1;if(r&&s>i.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${t.cols}\xD7${t.rows} (${s} cells) exceeds Uint16 limit of ${i.maxCellsUint16} cells. Maximum size with Uint16: ${Math.floor(Math.sqrt(i.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(i.maxCellsUint16))} (or smaller rectangles like 127\xD764)`);if(!i.uint32Indices&&s>i.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${t.cols}\xD7${t.rows} (${s} cells) exceeds device limit of ${i.maxCellsUint16} cells (OES_element_index_uint not supported). Maximum size: ${Math.floor(Math.sqrt(i.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(i.maxCellsUint16))}`);s>i.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Large terminal size ${t.cols}\xD7${t.rows} (${s} cells) exceeds recommended limit of ${i.recommendedMaxCells} cells. Performance may be impacted.`),i.warnings.length>0&&console.warn("[TerminalGL] WebGL Compatibility Warnings:",i.warnings);let n=t.charWidth??8,l=t.charHeight??8;if(!Number.isFinite(n)||n<=0)throw new Error(`TerminalGL: Invalid charWidth: ${n}. Must be a positive number.`);if(!Number.isFinite(l)||l<=0)throw new Error(`TerminalGL: Invalid charHeight: ${l}. Must be a positive number.`);for(this.parentElement=e,this.cols=t.cols,this.rows=t.rows,this.charWidth=n,this.charHeight=l,this.canvasBgColor=t.canvasBgColor!==void 0?t.canvasBgColor:null,this.showGrid=t.showGrid??!1;this.parentElement.firstChild;)this.parentElement.removeChild(this.parentElement.firstChild);let o=window.getComputedStyle(this.parentElement).position;o!=="relative"&&o!=="absolute"&&o!=="fixed"&&(this.parentElement.style.position="relative"),this.containerDiv=document.createElement("div"),this.containerDiv.className="terminalgl-container",this.containerDiv.style.cssText=`
12
+ `,this.container.appendChild(this.canvas);let i=this.canvas.getContext("2d");if(!i)throw new Error("[GridOverlay] Impossible de cr\xE9er le contexte 2D");this.ctx=i,e&&(e.strokeColor&&(this.strokeColor=e.strokeColor),e.lineWidth!==void 0&&(this.lineWidth=e.lineWidth),e.innerPadding!==void 0&&(this.innerPadding=e.innerPadding))}setDimensions(t,e,r,i,s=0,n=0){this.cols=t,this.rows=e,this.cellWidth=r,this.cellHeight=i,this.offsetX=s,this.offsetY=n}setCanvasSize(t,e){let r=window.devicePixelRatio||1;this.canvas.width=t*r,this.canvas.height=e*r,this.ctx.setTransform(1,0,0,1,0,0),this.ctx.scale(r,r)}setStyle(t){t.strokeColor&&(this.strokeColor=t.strokeColor),t.lineWidth!==void 0&&(this.lineWidth=t.lineWidth),t.innerPadding!==void 0&&(this.innerPadding=t.innerPadding)}render(){if(!this.ctx)return;this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.strokeStyle=this.strokeColor,this.ctx.lineWidth=this.lineWidth;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight;this.ctx.beginPath();for(let r=0;r<=this.cols;r++){let i=this.offsetX+r*this.cellWidth;if(r===0){let s=i+this.innerPadding+.5;this.ctx.moveTo(s,this.offsetY+this.innerPadding),this.ctx.lineTo(s,this.offsetY+e-this.innerPadding)}else if(r===this.cols){let s=i-this.innerPadding+.5;this.ctx.moveTo(s,this.offsetY+this.innerPadding),this.ctx.lineTo(s,this.offsetY+e-this.innerPadding)}else{let s=i+.5;this.ctx.moveTo(s,this.offsetY+this.innerPadding),this.ctx.lineTo(s,this.offsetY+e-this.innerPadding)}}for(let r=0;r<=this.rows;r++){let i=this.offsetY+r*this.cellHeight;if(r===0){let s=i+this.innerPadding+.5;this.ctx.moveTo(this.offsetX+this.innerPadding,s),this.ctx.lineTo(this.offsetX+t-this.innerPadding,s)}else if(r===this.rows){let s=i-this.innerPadding+.5;this.ctx.moveTo(this.offsetX+this.innerPadding,s),this.ctx.lineTo(this.offsetX+t-this.innerPadding,s)}else{let s=i+.5;this.ctx.moveTo(this.offsetX+this.innerPadding,s),this.ctx.lineTo(this.offsetX+t-this.innerPadding,s)}}this.ctx.stroke()}update(t,e,r,i,s,n,l=0,o=0){this.setDimensions(t,e,r,i,l,o),this.setCanvasSize(s,n),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}};T(_,"GridOverlay");var y=_;var F=class F{constructor(t,e){a(this,"canvas");a(this,"gl");a(this,"parentElement");a(this,"containerDiv");a(this,"cols");a(this,"rows");a(this,"charWidth");a(this,"charHeight");a(this,"cellWidth",8);a(this,"cellHeight",8);a(this,"glyphOffsetX",0);a(this,"glyphOffsetY",0);a(this,"canvasBgColor");a(this,"showGrid");a(this,"supportsUint32Indices",!1);a(this,"useUint16Indices",!1);a(this,"gridOverlay");a(this,"bitmapFont");a(this,"atlasTexture",null);a(this,"atlasCanvas");a(this,"atlasColumns",0);a(this,"paletteTexture",null);a(this,"program",null);a(this,"positionBuffer",null);a(this,"texCoordBuffer",null);a(this,"colorIndexBuffer",null);a(this,"indexBuffer",null);a(this,"aPosition");a(this,"aTexCoord");a(this,"aColorIndex");a(this,"uResolution",null);a(this,"uTexture",null);a(this,"uPalette",null);a(this,"resizeObserver");a(this,"charCodeToAtlasIndex",new Uint16Array(65536).fill(65535));a(this,"atlasUVs",new Float32Array(0));a(this,"cachedAtlasWidth",0);a(this,"cachedAtlasHeight",0);a(this,"paletteFloat",new Float32Array(256*4));a(this,"maxCells",0);a(this,"renderPositions",new Float32Array(0));a(this,"renderTexCoords",new Float32Array(0));a(this,"renderColorIndices",new Float32Array(0));a(this,"renderIndices",new Uint32Array(0));a(this,"cachedResolution",[0,0]);a(this,"cachedTextureUnit",-1);a(this,"cachedPaletteUnit",-1);a(this,"cachedTextureUniform",!1);a(this,"cachedPaletteUniform",!1);a(this,"paletteHash",0);a(this,"staticPositionsInitialized",!1);a(this,"vaoExtension",null);a(this,"vao",null);a(this,"instancedExtension",null);a(this,"useInstancing",!1);a(this,"instanceDataBuffer",null);a(this,"instanceData",new Float32Array(0));a(this,"templateQuadPositions",new Float32Array(0));a(this,"templateQuadIndices",new Uint16Array(0));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 r=e.cols*e.rows,i=F.checkCompatibility();if(i.errors.length>0)throw new Error(`TerminalGL: WebGL incompatible - ${i.errors.join(", ")}`);let s=e.forceUint16??!1;if(s&&r>i.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.rows} (${r} cells) exceeds Uint16 limit of ${i.maxCellsUint16} cells. Maximum size with Uint16: ${Math.floor(Math.sqrt(i.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(i.maxCellsUint16))} (or smaller rectangles like 127\xD764)`);if(!i.uint32Indices&&r>i.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.rows} (${r} cells) exceeds device limit of ${i.maxCellsUint16} cells (OES_element_index_uint not supported). Maximum size: ${Math.floor(Math.sqrt(i.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(i.maxCellsUint16))}`);r>i.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Large terminal size ${e.cols}\xD7${e.rows} (${r} cells) exceeds recommended limit of ${i.recommendedMaxCells} cells. Performance may be impacted.`),i.warnings.length>0&&console.warn("[TerminalGL] WebGL Compatibility Warnings:",i.warnings);let n=e.charWidth??8,l=e.charHeight??8;if(!Number.isFinite(n)||n<=0)throw new Error(`TerminalGL: Invalid charWidth: ${n}. Must be a positive number.`);if(!Number.isFinite(l)||l<=0)throw new Error(`TerminalGL: Invalid charHeight: ${l}. Must be a positive number.`);for(this.parentElement=t,this.cols=e.cols,this.rows=e.rows,this.charWidth=n,this.charHeight=l,this.canvasBgColor=e.canvasBgColor!==void 0?e.canvasBgColor:null,this.showGrid=e.showGrid??!1;this.parentElement.firstChild;)this.parentElement.removeChild(this.parentElement.firstChild);let o=window.getComputedStyle(this.parentElement).position;o!=="relative"&&o!=="absolute"&&o!=="fixed"&&(this.parentElement.style.position="relative"),this.containerDiv=document.createElement("div"),this.containerDiv.className="terminalgl-container",this.containerDiv.style.cssText=`
13
13
  position: absolute !important;
14
14
  top: 0 !important;
15
15
  left: 0 !important;
@@ -23,7 +23,7 @@
23
23
  image-rendering: pixelated !important;
24
24
  image-rendering: crisp-edges !important;
25
25
  object-fit: contain !important;
26
- `;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=r||!this.supportsUint32Indices,this.useUint16Indices?console.warn(`[TerminalGL] \u{1F4CA} Using Uint16 indices (max ${i.maxCellsUint16} cells)`):console.warn(`[TerminalGL] \u{1F4CA} Using Uint32 indices (max ${i.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.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 e={webgl1:!1,uint32Indices:!1,maxTextureSize:0,maxViewportDims:[0,0],maxCellsUint16:0,maxCellsUint32:0,recommendedMaxCells:0,warnings:[],errors:[]},t=document.createElement("canvas"),s=t.getContext("webgl")||t.getContext("experimental-webgl");if(!s||!(s instanceof WebGLRenderingContext))return e.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),e;let i=s;e.webgl1=!0;try{e.maxTextureSize=i.getParameter(i.MAX_TEXTURE_SIZE);let o=i.getParameter(i.MAX_VIEWPORT_DIMS);e.maxViewportDims=[o[0],o[1]]}catch(o){return e.errors.push(`\u274C Failed to query WebGL parameters: ${o}`),e}let r=i.getExtension("OES_element_index_uint");e.uint32Indices=!!r;let n=8;if(e.maxCellsUint16=Math.floor(65535/n),e.uint32Indices){let o=Math.floor(e.maxTextureSize*e.maxTextureSize/64);e.maxCellsUint32=Math.min(o,262144)}else e.maxCellsUint32=e.maxCellsUint16,e.warnings.push(`\u26A0\uFE0F OES_element_index_uint not supported - limited to ${e.maxCellsUint16} cells (e.g., 90\xD790 or 127\xD764)`);return e.recommendedMaxCells=Math.floor((e.uint32Indices?e.maxCellsUint32:e.maxCellsUint16)*.8),e.maxTextureSize<256?e.errors.push(`\u274C MAX_TEXTURE_SIZE too small: ${e.maxTextureSize} (minimum 256 required for font atlas)`):e.maxTextureSize<2048&&e.warnings.push(`\u26A0\uFE0F Small MAX_TEXTURE_SIZE: ${e.maxTextureSize} (may limit font atlas)`),(e.maxViewportDims[0]<1024||e.maxViewportDims[1]<768)&&e.warnings.push(`\u26A0\uFE0F Small MAX_VIEWPORT_DIMS: ${e.maxViewportDims[0]}\xD7${e.maxViewportDims[1]}`),i.getExtension("WEBGL_lose_context")||e.warnings.push("\u26A0\uFE0F WEBGL_lose_context not supported - may cause memory leaks"),e}initInstancedBuffers(){let e=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]),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.bufferData(e.ARRAY_BUFFER,this.templateQuadPositions,e.STATIC_DRAW),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),e.bufferData(e.ELEMENT_ARRAY_BUFFER,this.templateQuadIndices,e.STATIC_DRAW);let t=this.cols*this.rows*2;this.instanceData=new Float32Array(t*8),e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer),e.bufferData(e.ARRAY_BUFFER,this.instanceData.byteLength,e.DYNAMIC_DRAW)}initRenderBuffers(){this.maxCells=this.cols*this.rows*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 e=this.cellWidth,t=this.cellHeight,s=this.glyphOffsetX,i=this.glyphOffsetY,r=this.charWidth,n=this.charHeight,l=0,o=0,h=0;for(let d=0;d<this.rows;d++){let f=Math.round(d*t),g=Math.round(f+t);for(let u=0;u<this.cols;u++){let m=Math.round(u*e),p=Math.round(m+e);this.renderPositions[l++]=m,this.renderPositions[l++]=f,this.renderPositions[l++]=p,this.renderPositions[l++]=f,this.renderPositions[l++]=m,this.renderPositions[l++]=g,this.renderPositions[l++]=p,this.renderPositions[l++]=g,this.renderIndices[o++]=h,this.renderIndices[o++]=h+1,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+1,this.renderIndices[o++]=h+3,h+=4;let C=Math.round(m+s),T=Math.round(f+i),b=Math.round(C+r),E=Math.round(T+n);this.renderPositions[l++]=C,this.renderPositions[l++]=T,this.renderPositions[l++]=b,this.renderPositions[l++]=T,this.renderPositions[l++]=C,this.renderPositions[l++]=E,this.renderPositions[l++]=b,this.renderPositions[l++]=E,this.renderIndices[o++]=h,this.renderIndices[o++]=h+1,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+1,this.renderIndices[o++]=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 e=this.gl,t;this.useInstancing?t=`
26
+ `;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=s||!this.supportsUint32Indices,this.useUint16Indices?console.warn(`[TerminalGL] \u{1F4CA} Using Uint16 indices (max ${i.maxCellsUint16} cells)`):console.warn(`[TerminalGL] \u{1F4CA} Using Uint32 indices (max ${i.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.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"),r=e.getContext("webgl")||e.getContext("experimental-webgl");if(!r||!(r instanceof WebGLRenderingContext))return t.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),t;let i=r;t.webgl1=!0;try{t.maxTextureSize=i.getParameter(i.MAX_TEXTURE_SIZE);let o=i.getParameter(i.MAX_VIEWPORT_DIMS);t.maxViewportDims=[o[0],o[1]]}catch(o){return t.errors.push(`\u274C Failed to query WebGL parameters: ${o}`),t}let s=i.getExtension("OES_element_index_uint");t.uint32Indices=!!s;let n=8;if(t.maxCellsUint16=Math.floor(65535/n),t.uint32Indices){let o=Math.floor(t.maxTextureSize*t.maxTextureSize/64);t.maxCellsUint32=Math.min(o,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]}`),i.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);let e=this.cols*this.rows*2;this.instanceData=new Float32Array(e*8),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer),t.bufferData(t.ARRAY_BUFFER,this.instanceData.byteLength,t.DYNAMIC_DRAW)}initRenderBuffers(){this.maxCells=this.cols*this.rows*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,r=this.glyphOffsetX,i=this.glyphOffsetY,s=this.charWidth,n=this.charHeight,l=0,o=0,h=0;for(let d=0;d<this.rows;d++){let f=Math.round(d*e),g=Math.round(f+e);for(let u=0;u<this.cols;u++){let m=Math.round(u*t),p=Math.round(m+t);this.renderPositions[l++]=m,this.renderPositions[l++]=f,this.renderPositions[l++]=p,this.renderPositions[l++]=f,this.renderPositions[l++]=m,this.renderPositions[l++]=g,this.renderPositions[l++]=p,this.renderPositions[l++]=g,this.renderIndices[o++]=h,this.renderIndices[o++]=h+1,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+1,this.renderIndices[o++]=h+3,h+=4;let C=Math.round(m+r),A=Math.round(f+i),b=Math.round(C+s),E=Math.round(A+n);this.renderPositions[l++]=C,this.renderPositions[l++]=A,this.renderPositions[l++]=b,this.renderPositions[l++]=A,this.renderPositions[l++]=C,this.renderPositions[l++]=E,this.renderPositions[l++]=b,this.renderPositions[l++]=E,this.renderIndices[o++]=h,this.renderIndices[o++]=h+1,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+1,this.renderIndices[o++]=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=`
27
27
  // Per-vertex attributes (template quad)
28
28
  attribute vec2 aPosition; // Local quad position (0,0 to cellW,cellH)
29
29
 
@@ -62,7 +62,7 @@
62
62
  float paletteU = (colorIndex + 0.5) / 256.0;
63
63
  vColor = texture2D(uPalette, vec2(paletteU, 0.5));
64
64
  }
65
- `:t=`
65
+ `:e=`
66
66
  attribute vec2 aPosition;
67
67
  attribute vec2 aTexCoord;
68
68
  attribute float aColorIndex; // \u{1F680} Index dans palette (0-255)
@@ -84,7 +84,7 @@
84
84
  float paletteU = (aColorIndex + 0.5) / 256.0;
85
85
  vColor = texture2D(uPalette, vec2(paletteU, 0.5));
86
86
  }
87
- `;let s=`
87
+ `;let r=`
88
88
  precision mediump float;
89
89
 
90
90
  uniform sampler2D uTexture;
@@ -102,4 +102,28 @@
102
102
  gl_FragColor = vec4(vColor.rgb * texColor.a, texColor.a);
103
103
  }
104
104
  }
105
- `,i=this.compileShader(e.VERTEX_SHADER,t),r=this.compileShader(e.FRAGMENT_SHADER,s);if(!i||!r)throw new Error("Shader compilation error");let n=e.createProgram();if(!n)throw new Error("Unable to create WebGL program");if(e.attachShader(n,i),e.attachShader(n,r),e.linkProgram(n),!e.getProgramParameter(n,e.LINK_STATUS)){let l=e.getProgramInfoLog(n);throw new Error("Program linking error: "+l)}this.program=n,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=e.getAttribLocation(n,"aPosition"),this.useInstancing?(this.aTexCoord=e.getAttribLocation(n,"aInstanceOffset"),this.aColorIndex=e.getAttribLocation(n,"aInstanceUVs"),this.instanceDataBuffer=e.createBuffer()):(this.aTexCoord=e.getAttribLocation(n,"aTexCoord"),this.aColorIndex=e.getAttribLocation(n,"aColorIndex")),this.uResolution=e.getUniformLocation(n,"uResolution"),this.uTexture=e.getUniformLocation(n,"uTexture"),this.uPalette=e.getUniformLocation(n,"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 w(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,innerPadding:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let e=parseFloat(this.canvas.style.width)||this.cols*this.charWidth,t=parseFloat(this.canvas.style.height)||this.rows*this.charHeight,s=e/this.cols,i=t/this.rows;this.gridOverlay.update(this.cols,this.rows,s,i,e,t,0,0)}setBitmapFont(e,t,s,i,r){this.bitmapFont=e,this.charWidth=Math.round(t),this.charHeight=Math.round(s),this.cellWidth=Math.round(i),this.cellHeight=Math.round(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..."),this.initInstancedBuffers());try{this.generateAtlas()}catch(n){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",n),n}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()}generateAtlas(){if(!this.bitmapFont)return;let e=Array.from(this.bitmapFont.keys()).sort((o,h)=>o-h),t=e.length;this.atlasColumns=Math.ceil(Math.sqrt(t));let s=Math.ceil(t/this.atlasColumns),i=this.atlasColumns*this.charWidth,r=s*this.charHeight;this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=i,this.atlasCanvas.height=r;let n=this.atlasCanvas.getContext("2d");if(!n)throw new Error("Unable to create 2D context for atlas");n.clearRect(0,0,i,r),n.fillStyle="#ffffff";let l=0;for(let o of e){let h=this.bitmapFont.get(o);if(!h)continue;let c=l%this.atlasColumns,d=Math.floor(l/this.atlasColumns),f=c*this.charWidth,g=d*this.charHeight;for(let u=0;u<Math.min(h.length,this.charHeight);u++){let m=h[u];for(let p=0;p<this.charWidth;p++){let C=1<<7-p;m&C&&n.fillRect(f+p,g+u,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,r=.5/s;for(let n=0;n<e;n++){let l=n%this.atlasColumns,o=Math.floor(n/this.atlasColumns),h=(l*this.charWidth+i)/t,c=(o*this.charHeight+r)/s,d=((l+1)*this.charWidth-i)/t,f=((o+1)*this.charHeight-r)/s,g=n*4;this.atlasUVs[g]=h,this.atlasUVs[g+1]=c,this.atlasUVs[g+2]=d,this.atlasUVs[g+3]=f}}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,r=0;return t.length===3?(s=parseInt(t[0]+t[0],16),i=parseInt(t[1]+t[1],16),r=parseInt(t[2]+t[2],16)):t.length===6&&(s=parseInt(t.slice(0,2),16),i=parseInt(t.slice(2,4),16),r=parseInt(t.slice(4,6),16)),[s/255,i/255,r/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=Math.floor(e/this.cellWidth),i=Math.floor(t/this.cellHeight),r=s/this.cols,n=i/this.rows,l=Math.min(r,n),o=Math.max(1,Math.floor(l)),h=this.cols*this.cellWidth*o,c=this.rows*this.cellHeight*o;this.canvas.style.width=`${h}px`,this.canvas.style.height=`${c}px`,this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}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],r=s*4;this.paletteFloat[r]=i.r/255,this.paletteFloat[r+1]=i.g/255,this.paletteFloat[r+2]=i.b/255,this.paletteFloat[r+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)}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.useInstancing=!1,this.renderDirectBuffers(e);return}let i=e.width*e.height;if(this.useUint16Indices&&i>8191){console.warn(`[TerminalGL] \u26A0\uFE0F Terminal too large for instanced rendering with Uint16 (${i} cells > 8191). Falling back to standard rendering.`),this.useInstancing=!1,this.renderDirectBuffers(e);return}let r=0,n=this.instanceData.length/8;for(let f=0;f<e.height;f++)for(let g=0;g<e.width;g++){let u=e.cells[f*e.width+g],m=u.bgColorIndex,p=u.fgColorIndex,C=this.canvasBgColor!==null&&m===255,T=u.char===" "||p===255;if(!C){if(r>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${r}, max=${n}`);break}let b=r*8;this.instanceData[b]=g,this.instanceData[b+1]=f,this.instanceData[b+2]=0,this.instanceData[b+3]=0,this.instanceData[b+4]=0,this.instanceData[b+5]=0,this.instanceData[b+6]=m,this.instanceData[b+7]=0,r++}if(!T){let b=u.char.charCodeAt(0),E=this.charCodeToAtlasIndex[b];if(E!==65535){if(r>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${r}, max=${n}`);break}let R=E*4,x=r*8;this.instanceData[x]=g,this.instanceData[x+1]=f,this.instanceData[x+2]=this.atlasUVs[R],this.instanceData[x+3]=this.atlasUVs[R+1],this.instanceData[x+4]=this.atlasUVs[R+2],this.instanceData[x+5]=this.atlasUVs[R+3],this.instanceData[x+6]=0,this.instanceData[x+7]=p,r++}}}if(r===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,r*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,o=t.getAttribLocation(this.program,"aInstanceOffset");t.enableVertexAttribArray(o),t.vertexAttribPointer(o,2,t.FLOAT,!1,l,0),s.vertexAttribDivisorANGLE(o,1);let h=t.getAttribLocation(this.program,"aInstanceUVs");t.enableVertexAttribArray(h),t.vertexAttribPointer(h,4,t.FLOAT,!1,l,2*Float32Array.BYTES_PER_ELEMENT),s.vertexAttribDivisorANGLE(h,1);let c=t.getAttribLocation(this.program,"aInstanceColors");t.enableVertexAttribArray(c),t.vertexAttribPointer(c,2,t.FLOAT,!1,l,6*Float32Array.BYTES_PER_ELEMENT),s.vertexAttribDivisorANGLE(c,1),t.uniform2f(this.uResolution,this.canvas.width,this.canvas.height);let d=t.getUniformLocation(this.program,"uCellSize");t.uniform2f(d,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,r),s.vertexAttribDivisorANGLE(this.aPosition,0),s.vertexAttribDivisorANGLE(o,0),s.vertexAttribDivisorANGLE(h,0),s.vertexAttribDivisorANGLE(c,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 r=0,n=0,l=e.cells,o=s;for(let u=0;u<o;u++){let m=l[u],p=m.bgColorIndex,T=this.canvasBgColor!==null&&p===255?255:p,b=0;for(let x=0;x<4;x++)this.renderTexCoords[r++]=b,this.renderTexCoords[r++]=b,this.renderColorIndices[n++]=T;let E=m.fgColorIndex,R=m.char;if(R===" "||E===255)for(let x=0;x<4;x++)this.renderTexCoords[r++]=0,this.renderTexCoords[r++]=0,this.renderColorIndices[n++]=255;else{let x=R.charCodeAt(0),P=this.charCodeToAtlasIndex[x];if(P!==65535){let y=P*4,W=this.atlasUVs[y],S=this.atlasUVs[y+1],H=this.atlasUVs[y+2],O=this.atlasUVs[y+3];this.renderTexCoords[r++]=W,this.renderTexCoords[r++]=S,this.renderColorIndices[n++]=E,this.renderTexCoords[r++]=H,this.renderTexCoords[r++]=S,this.renderColorIndices[n++]=E,this.renderTexCoords[r++]=W,this.renderTexCoords[r++]=O,this.renderColorIndices[n++]=E,this.renderTexCoords[r++]=H,this.renderTexCoords[r++]=O,this.renderColorIndices[n++]=E}else for(let y=0;y<4;y++)this.renderTexCoords[r++]=0,this.renderTexCoords[r++]=0,this.renderColorIndices[n++]=255}}(r!==o*2*4*2||n!==o*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:r,colorIdx:n,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,r)),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,n))):(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,r)),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,n)),t.enableVertexAttribArray(this.aColorIndex),t.vertexAttribPointer(this.aColorIndex,1,t.FLOAT,!1,0,0));let h=this.canvas.width,c=this.canvas.height;(this.cachedResolution[0]!==h||this.cachedResolution[1]!==c)&&(t.uniform2f(this.uResolution,h,c),this.cachedResolution[0]=h,this.cachedResolution[1]=c),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 f=e.width*e.height*2*6,g=this.useUint16Indices?t.UNSIGNED_SHORT:t.UNSIGNED_INT;t.drawElements(t.TRIANGLES,f,g,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.useUint16Indices?8191:262144;if(s>i){let c=Math.floor(Math.sqrt(i));console.error(`[TerminalGL] \u274C Cannot resize to ${e}\xD7${t} (${s} cells). Device limit: ${i} cells (max ~${c}\xD7${c}). ${this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let r=F.checkCompatibility();s>r.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${e}\xD7${t} (${s} cells) exceeds recommended limit (${r.recommendedMaxCells} cells). Performance may degrade.`),this.cols=e,this.rows=t,this.staticPositionsInitialized=!1;let n=this.cols*this.rows*2,l=Math.ceil(n*1.5),o=n>this.maxCells,h=this.maxCells>l*4;if(o||h){let c=this.maxCells;this.maxCells=l,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);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),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=o?"\u{1F4C8} Growing":"\u{1F4C9} Shrinking",g=c*160/1048576,u=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${f} buffers: ${g.toFixed(2)}MB \u2192 ${u.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.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}getCols(){return this.cols}getRows(){return this.rows}isReady(){return!!(this.bitmapFont&&this.atlasTexture&&this.program)}destroy(){this.dispose()}dispose(){this.resizeObserver&&this.resizeObserver.disconnect();let e=this.gl;this.program&&e.deleteProgram(this.program),this.positionBuffer&&e.deleteBuffer(this.positionBuffer),this.texCoordBuffer&&e.deleteBuffer(this.texCoordBuffer),this.colorIndexBuffer&&e.deleteBuffer(this.colorIndexBuffer),this.indexBuffer&&e.deleteBuffer(this.indexBuffer),this.instanceDataBuffer&&e.deleteBuffer(this.instanceDataBuffer),this.atlasTexture&&e.deleteTexture(this.atlasTexture),this.paletteTexture&&e.deleteTexture(this.paletteTexture),this.vao&&this.vaoExtension&&this.vaoExtension.deleteVertexArrayOES(this.vao);let t=e.getExtension("WEBGL_lose_context");t&&t.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.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)}};A(F,"TerminalGL");var D=F;var G=class G{constructor(e,t,s,i,r){a(this,"atlases");a(this,"charMap");a(this,"baseCharWidth");a(this,"baseCharHeight");a(this,"baseCellWidth");a(this,"baseCellHeight");a(this,"atlasColumns",16);a(this,"font");a(this,"SCALES",[1,2,4,8]);a(this,"colorCache",new Map);a(this,"MAX_CACHE_SIZE",512);this.font=e,this.baseCharWidth=t,this.baseCharHeight=s,this.baseCellWidth=i??t,this.baseCellHeight=r??s,this.charMap=new Map,this.atlases=new Map,this.generateAtlases()}generateAtlases(){this.atlasColumns=16;let e=0;for(let[t,s]of this.font){let i=e%this.atlasColumns,r=Math.floor(e/this.atlasColumns);this.charMap.set(t,{x:i*this.baseCharWidth,y:r*this.baseCharHeight});for(let n of this.SCALES){let l=this.getOrCreateAtlas(n),o=i*l.charWidth,h=r*l.charHeight;this.renderBitmapToAtlas(l,s,o,h)}e++}}getOrCreateAtlas(e){let t=this.atlases.get(e);if(!t){let s=this.baseCharWidth*e,i=this.baseCharHeight*e,n=Math.ceil(256/this.atlasColumns),l=document.createElement("canvas");l.width=this.atlasColumns*s,l.height=n*i;let o=l.getContext("2d",{alpha:!0,willReadFrequently:!1});if(!o)throw new Error(`Impossible de cr\xE9er le contexte 2D pour l'atlas ${e}x`);o.imageSmoothingEnabled=!1,t={canvas:l,ctx:o,scale:e,charWidth:s,charHeight:i},this.atlases.set(e,t)}return t}renderBitmapToAtlas(e,t,s,i){let r=e.scale,n=e.ctx;n.fillStyle="#ffffff";for(let l=0;l<Math.min(t.length,this.baseCharHeight);l++){let o=t[l];for(let h=0;h<this.baseCharWidth;h++){let c=1<<7-h;o&c&&n.fillRect(s+h*r,i+l*r,r,r)}}}drawChar(e,t,s,i,r,n,l){let o=this.charMap.get(t);if(!o)return;let h=`${t}:${l}`,c=this.colorCache.get(h);if(c)c.lastUsed=performance.now();else{let C=this.createColoredGlyph(t,l,o);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=r/this.baseCellWidth,f=n/this.baseCellHeight,g=(this.baseCellWidth-this.baseCharWidth)/2*d,u=(this.baseCellHeight-this.baseCharHeight)/2*f,m=this.baseCharWidth*d,p=this.baseCharHeight*f;e.drawImage(c.canvas,s+g,i+u,m,p)}createColoredGlyph(e,t,s){let i=this.atlases.get(1);if(!i)return null;let r=i.ctx.getImageData(s.x,s.y,this.baseCharWidth,this.baseCharHeight),n=r.data,l=this.hexToRgb(t);for(let c=0;c<n.length;c+=4)n[c+3]>0&&(n[c]=l.r,n[c+1]=l.g,n[c+2]=l.b);let o=document.createElement("canvas");o.width=this.baseCharWidth,o.height=this.baseCharHeight;let h=o.getContext("2d",{alpha:!0});return h?(h.imageSmoothingEnabled=!1,h.putImageData(r,0,0),o):null}hexToRgb(e){if(e.startsWith("#")){let r=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;e=e.replace(r,(l,o,h,c)=>o+o+h+h+c+c);let n=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return n?{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[3],16)}:{r:255,g:255,b:255}}let t=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/.exec(e);if(t)return{r:parseInt(t[1],10),g:parseInt(t[2],10),b:parseInt(t[3],10)};let i={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]}[e.toLowerCase()];return i?{r:i[0],g:i[1],b:i[2]}:{r:255,g:255,b:255}}evictLRU(){let e=null,t=1/0;for(let[s,i]of this.colorCache)i.lastUsed<t&&(t=i.lastUsed,e=s);if(e){let s=this.colorCache.get(e);s&&(s.canvas.width=0,s.canvas.height=0),this.colorCache.delete(e)}}getAtlasCanvas(e=1){return this.atlases.get(e)?.canvas}getAllAtlases(){return this.atlases}getCharDimensions(){return{width:this.baseCharWidth,height:this.baseCharHeight}}getCharCount(){return this.charMap.size}hasChar(e){return this.charMap.has(e)}getAtlasDimensions(e=1){let t=this.atlases.get(e);if(t)return{width:t.canvas.width,height:t.canvas.height}}toDataURL(e=1,t="image/png"){return this.atlases.get(e)?.canvas.toDataURL(t)}getCacheStats(){return{size:this.colorCache.size,maxSize:this.MAX_CACHE_SIZE}}clearCache(){for(let e of this.colorCache.values())e.canvas.width=0,e.canvas.height=0;this.colorCache.clear()}destroy(){this.charMap.clear();for(let e of this.atlases.values())e.canvas.width=0,e.canvas.height=0;this.atlases.clear(),this.clearCache()}};A(G,"BitmapFontAtlas");var I=G;var M=class M{constructor(e,t={}){a(this,"canvas");a(this,"ctx");a(this,"parentElement");a(this,"cells");a(this,"cols",0);a(this,"rows",0);a(this,"fontSize");a(this,"fontFamily");a(this,"defaultFgColor");a(this,"defaultBgColor");a(this,"canvasBgColor");a(this,"cellWidth");a(this,"cellHeight");a(this,"offsetX",0);a(this,"offsetY",0);a(this,"fontType","web");a(this,"bitmapFont");a(this,"bitmapAtlas");a(this,"bitmapCharWidth",8);a(this,"bitmapCharHeight",8);a(this,"showDebugGrid");a(this,"debugGridColor");a(this,"gridOverlay");a(this,"fixedGridMode");a(this,"fixedCols");a(this,"fixedRows");a(this,"cellAspectRatio");a(this,"resizeObserver");a(this,"imageDataBuffer");a(this,"useImageDataRendering",!1);a(this,"paletteCache");if(!e)throw new Error("Render: L'\xE9l\xE9ment parent est requis");this.parentElement=e,this.fixedGridMode=!!(t.fixedCols&&t.fixedRows),this.fixedCols=t.fixedCols,this.fixedRows=t.fixedRows,this.cellAspectRatio=t.cellAspectRatio??10/14,this.cellWidth=t.cellWidth??10,this.cellHeight=t.cellHeight??14,this.fontSize=t.fontSize??12,this.fontFamily=t.fontFamily??"monospace",this.defaultFgColor=t.defaultFgColor??"#ffffff",this.defaultBgColor=t.defaultBgColor??"#000000",this.canvasBgColor=t.canvasBgColor!==void 0?t.canvasBgColor:null,this.showDebugGrid=t.showDebugGrid??!1,this.debugGridColor=t.debugGridColor??"rgba(144, 24, 24, 1)",this.canvas=document.createElement("canvas"),t.className&&(this.canvas.className=t.className),t.style&&Object.assign(this.canvas.style,t.style),this.canvas.style.imageRendering="auto",this.parentElement.appendChild(this.canvas);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.calculateGridSize(),this.cells=this.createEmptyGrid(),this.showDebugGrid&&(this.gridOverlay=new w(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,innerPadding:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let e=this.parentElement.clientWidth||800,t=this.parentElement.clientHeight||600;if(this.fixedGridMode&&this.fixedCols&&this.fixedRows)if(this.cols=this.fixedCols,this.rows=this.fixedRows,this.fontType==="bitmap"){let n=e/this.cols,l=t/this.rows,o=this.bitmapCharWidth/this.bitmapCharHeight;n/l>o?(this.cellHeight=Math.floor(l),this.cellWidth=Math.floor(this.cellHeight*o)):(this.cellWidth=Math.floor(n),this.cellHeight=Math.floor(this.cellWidth/o))}else{let n=e/this.cols,l=t/this.rows;n/l>this.cellAspectRatio?(this.cellHeight=Math.floor(l*100)/100,this.cellWidth=Math.floor(this.cellHeight*this.cellAspectRatio*100)/100):(this.cellWidth=Math.floor(n*100)/100,this.cellHeight=Math.floor(this.cellWidth/this.cellAspectRatio*100)/100);let o=14,h=12;this.fontSize=Math.floor(this.cellHeight/o*h*100)/100}else this.cols=Math.floor(e/this.cellWidth),this.rows=Math.floor(t/this.cellHeight);let s=this.cols*this.cellWidth,i=this.rows*this.cellHeight;this.offsetX=Math.floor((e-s)/2),this.offsetY=Math.floor((t-i)/2);let r=window.devicePixelRatio||1;this.canvas.style.width=`${e}px`,this.canvas.style.height=`${t}px`,this.canvas.width=e*r,this.canvas.height=t*r,this.ctx.scale(r,r)}createEmptyGrid(){let e=[];for(let t=0;t<this.rows;t++){let s=[];for(let i=0;i<this.cols;i++)s.push({char:" ",fgColor:this.defaultFgColor,bgColor:this.defaultBgColor});e.push(s)}return e}enableAutoResize(){this.resizeObserver=new ResizeObserver(()=>{let e=this.cols,t=this.rows;if(this.calculateGridSize(),this.cols!==e||this.rows!==t){let s=this.cells;this.cells=this.createEmptyGrid();let i=Math.min(e,this.cols),r=Math.min(t,this.rows);for(let n=0;n<r;n++)for(let l=0;l<i;l++)this.cells[n][l]=s[n][l]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(e,t,s,i,r){if(t<0||t>=this.rows||e<0||e>=this.cols)return;let n=s&&typeof s=="string"?s.charAt(0):" ";this.cells[t][e]={char:n,fgColor:i??this.defaultFgColor,bgColor:r??this.defaultBgColor}}getCell(e,t){return t<0||t>=this.rows||e<0||e>=this.cols?null:this.cells[t][e]}write(e,t,s,i,r){for(let n=0;n<s.length;n++)this.setCell(e+n,t,s[n],i,r)}fillRect(e,t,s,i,r=" ",n,l){for(let o=t;o<t+i;o++)for(let h=e;h<e+s;h++)this.setCell(h,o,r,n,l)}clear(){this.cells=this.createEmptyGrid()}setFromArray(e){let t=e.width*e.height;if(e.cells.length!==t)throw new Error(`Invalid array length: expected ${t} (${e.width}\xD7${e.height}), got ${e.cells.length}`);let s=0;for(let i=0;i<e.height;i++)for(let r=0;r<e.width;r++){let n=e.cells[s];i<this.rows&&r<this.cols&&this.setCell(r,i,n.char,n.fgColor,n.bgColor),s++}}render(){if(this.fontType==="bitmap"&&this.bitmapFont&&this.useImageDataRendering){this.renderWithImageData();return}this.renderClassic()}renderWithImageData(){if(!this.bitmapFont)return;let e=this.cols*this.bitmapCharWidth,t=this.rows*this.bitmapCharHeight;(!this.imageDataBuffer||this.imageDataBuffer.width!==e||this.imageDataBuffer.height!==t)&&(this.imageDataBuffer=this.ctx.createImageData(e,t));let s=this.imageDataBuffer.data;for(let o=0;o<this.rows;o++)for(let h=0;h<this.cols;h++){let c=this.cells[o][h],d=this.parseColorToRGB(c.bgColor),f=this.parseColorToRGB(c.fgColor),g=c.char.charCodeAt(0),u=this.bitmapFont.get(g);for(let m=0;m<this.bitmapCharHeight;m++)for(let p=0;p<this.bitmapCharWidth;p++){let C=h*this.bitmapCharWidth+p,b=((o*this.bitmapCharHeight+m)*e+C)*4,E=!1;if(u&&m<u.length){let R=u[m],x=1<<7-p;E=(R&x)!==0}E?(s[b]=f.r,s[b+1]=f.g,s[b+2]=f.b,s[b+3]=f.a):(s[b]=d.r,s[b+1]=d.g,s[b+2]=d.b,s[b+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 i=document.createElement("canvas");i.width=e,i.height=t,i.getContext("2d").putImageData(this.imageDataBuffer,0,0);let n=this.cols*this.cellWidth,l=this.rows*this.cellHeight;this.ctx.drawImage(i,0,0,e,t,this.offsetX,this.offsetY,n,l),this.showDebugGrid&&this.drawDebugGrid()}parseColorToRGB(e){let t=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/.exec(e);if(t)return{r:parseInt(t[1],10),g:parseInt(t[2],10),b:parseInt(t[3],10),a:t[4]?Math.round(parseFloat(t[4])*255):255};if(e.startsWith("#")){let r=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;e=e.replace(r,(l,o,h,c)=>o+o+h+h+c+c);let n=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);if(n)return{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[3],16),a:255}}let i={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]}[e.toLowerCase()];return i?{r:i[0],g:i[1],b:i[2],a:e==="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.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 e=0;e<this.rows;e++)for(let t=0;t<this.cols;t++){let s=this.cells[e][t],i=Math.floor(this.offsetX+t*this.cellWidth),r=Math.floor(this.offsetY+e*this.cellHeight),n=Math.floor(this.offsetX+(t+1)*this.cellWidth),l=Math.floor(this.offsetY+(e+1)*this.cellHeight),o=n-i,h=l-r;if((this.canvasBgColor!==null||s.bgColor!==this.defaultBgColor)&&(this.ctx.fillStyle=s.bgColor,this.ctx.fillRect(i,r,o,h)),s.char!==" ")if(this.fontType==="bitmap"&&this.bitmapFont)this.drawBitmapChar(s.char,i,r,o,h,s.fgColor);else{this.ctx.fillStyle=s.fgColor;let d=i+(o-this.ctx.measureText(s.char).width)/2,f=r+(h-this.fontSize)/2;this.ctx.fillText(s.char,d,f)}}this.showDebugGrid&&this.drawDebugGrid()}drawBitmapChar(e,t,s,i,r,n){let l=e.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,l,t,s,i,r,n);return}if(!this.bitmapFont)return;let o=this.bitmapFont.get(l);if(!o)return;let h=i/this.bitmapCharWidth,c=r/this.bitmapCharHeight;this.ctx.fillStyle=n;for(let d=0;d<Math.min(o.length,this.bitmapCharHeight);d++){let f=o[d],g=s+d*c,u=s+(d+1)*c;for(let m=0;m<this.bitmapCharWidth;m++){let p=1<<7-m;if(f&p){let C=t+m*h,T=t+(m+1)*h;this.ctx.fillRect(C,g,T-C,u-g)}}}}drawDebugGrid(){if(!this.gridOverlay)return;let e=this.parentElement.clientWidth||800,t=this.parentElement.clientHeight||600;this.gridOverlay.update(this.cols,this.rows,this.cellWidth,this.cellHeight,e,t,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}getOffsets(){return{offsetX:this.offsetX,offsetY:this.offsetY}}setDebugGrid(e){this.showDebugGrid=e,e&&!this.gridOverlay?(this.gridOverlay=new w(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,innerPadding:1,zIndex:10}),this.drawDebugGrid()):!e&&this.gridOverlay?(this.gridOverlay.destroy(),this.gridOverlay=void 0):e&&this.gridOverlay&&this.gridOverlay.setVisible(!0)}setCanvasBackgroundColor(e){this.canvasBgColor=e}getCanvasBackgroundColor(){return this.canvasBgColor}setFixedGrid(e,t,s){this.fixedGridMode=!0,this.fixedCols=e,this.fixedRows=t,s!==void 0&&(this.cellAspectRatio=s);let i=this.cols,r=this.rows,n=this.cells;if(this.calculateGridSize(),this.cols!==i||this.rows!==r){this.cells=this.createEmptyGrid();let l=Math.min(i,this.cols),o=Math.min(r,this.rows);for(let h=0;h<o;h++)for(let c=0;c<l;c++)this.cells[h][c]=n[h][c]}this.render()}setAdaptiveGrid(e,t){this.fixedGridMode=!1,this.fixedCols=void 0,this.fixedRows=void 0,e!==void 0&&(this.cellWidth=e),t!==void 0&&(this.cellHeight=t);let s=this.cols,i=this.rows,r=this.cells;if(this.calculateGridSize(),this.cols!==s||this.rows!==i){this.cells=this.createEmptyGrid();let n=Math.min(s,this.cols),l=Math.min(i,this.rows);for(let o=0;o<l;o++)for(let h=0;h<n;h++)this.cells[o][h]=r[o][h]}this.render()}isFixedGridMode(){return this.fixedGridMode}setDebugGridColor(e){this.debugGridColor=e}isDebugGridEnabled(){return this.showDebugGrid}setImageDataRendering(e){this.useImageDataRendering=e,e&&this.fontType==="bitmap"?console.warn("[Render] ImageData rendering enabled (optimized for benchmarks)"):e&&(console.warn("[Render] ImageData rendering requires bitmap font, keeping classic mode"),this.useImageDataRendering=!1)}isImageDataRenderingEnabled(){return this.useImageDataRendering}setWebFont(e,t){this.fontType="web",this.fontFamily=e,t!==void 0&&(this.fontSize=t),this.bitmapFont=void 0,this.bitmapAtlas=void 0,this.useImageDataRendering=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid()}setBitmapFont(e,t,s,i,r){this.fontType="bitmap",this.bitmapFont=e,this.bitmapCharWidth=t,this.bitmapCharHeight=s,this.bitmapAtlas=new I(e,t,s,i,r),this.cellWidth=i,this.cellHeight=r,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(e){this.paletteCache=e}renderDisplayData(e){if(!e||!e.cells||e.cells.length===0){console.warn("[Terminal2D] Empty display data");return}if(e.width===0||e.height===0){console.warn("[Terminal2D] Invalid display dimensions:",e.width,e.height);return}(e.width!==this.cols||e.height!==this.rows)&&this.setFixedGrid(e.width,e.height,this.cellAspectRatio);let t=this.paletteCache??e.palette;if(!t||t.length===0){console.error("[Terminal2D] No palette available (neither cached nor in display)");return}let s=A(i=>{if(i==null||isNaN(i))return console.warn("[Terminal2D] Invalid palette index (undefined/null/NaN):",i),this.defaultFgColor;if(i===255)return"rgba(0, 0, 0, 0)";if(i<0||i>=t.length)return console.warn(`[Terminal2D] Invalid palette index: ${i}`),this.defaultFgColor;let r=t[i];return!r||typeof r.r!="number"?(console.warn(`[Terminal2D] Corrupted palette entry at index ${i}:`,r),this.defaultFgColor):`rgba(${r.r}, ${r.g}, ${r.b}, ${r.a/255})`},"convertColor");for(let i=0;i<e.height&&i<this.rows;i++)for(let r=0;r<e.width&&r<this.cols;r++){let n=i*e.width+r;if(n>=e.cells.length)break;let l=e.cells[n];if(!l)continue;let o=s(l.fgColorIndex),h=s(l.bgColorIndex);this.setCell(r,i,l.char??" ",o,h)}this.render()}isReady(){return!0}getCols(){return this.cols}getRows(){return this.rows}resize(e,t){this.setFixedGrid(e,t)}destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=void 0),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}};A(M,"Terminal2D");var L=M;var Q="0.1.0";
105
+ `,i=this.compileShader(t.VERTEX_SHADER,e),s=this.compileShader(t.FRAGMENT_SHADER,r);if(!i||!s)throw new Error("Shader compilation error");let n=t.createProgram();if(!n)throw new Error("Unable to create WebGL program");if(t.attachShader(n,i),t.attachShader(n,s),t.linkProgram(n),!t.getProgramParameter(n,t.LINK_STATUS)){let l=t.getProgramInfoLog(n);throw new Error("Program linking error: "+l)}this.program=n,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=t.getAttribLocation(n,"aPosition"),this.useInstancing?(this.aTexCoord=t.getAttribLocation(n,"aInstanceOffset"),this.aColorIndex=t.getAttribLocation(n,"aInstanceUVs"),this.instanceDataBuffer=t.createBuffer()):(this.aTexCoord=t.getAttribLocation(n,"aTexCoord"),this.aColorIndex=t.getAttribLocation(n,"aColorIndex")),this.uResolution=t.getUniformLocation(n,"uResolution"),this.uTexture=t.getUniformLocation(n,"uTexture"),this.uPalette=t.getUniformLocation(n,"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 r=this.gl,i=r.createShader(t);return i?(r.shaderSource(i,e),r.compileShader(i),r.getShaderParameter(i,r.COMPILE_STATUS)?i:(console.error("Shader compilation error:",r.getShaderInfoLog(i)),r.deleteShader(i),null)):null}initGridOverlay(){this.gridOverlay=new y(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,innerPadding:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let t=parseFloat(this.canvas.style.width)||this.cols*this.charWidth,e=parseFloat(this.canvas.style.height)||this.rows*this.charHeight,r=t/this.cols,i=e/this.rows;this.gridOverlay.update(this.cols,this.rows,r,i,t,e,0,0)}setBitmapFont(t,e,r,i,s){this.bitmapFont=t,this.charWidth=Math.round(e),this.charHeight=Math.round(r),this.cellWidth=Math.round(i),this.cellHeight=Math.round(s),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(n){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",n),n}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()}generateAtlas(){if(!this.bitmapFont)return;let t=Array.from(this.bitmapFont.keys()).sort((o,h)=>o-h),e=t.length;this.atlasColumns=Math.ceil(Math.sqrt(e));let r=Math.ceil(e/this.atlasColumns),i=this.atlasColumns*this.charWidth,s=r*this.charHeight;this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=i,this.atlasCanvas.height=s;let n=this.atlasCanvas.getContext("2d");if(!n)throw new Error("Unable to create 2D context for atlas");n.clearRect(0,0,i,s),n.fillStyle="#ffffff";let l=0;for(let o of t){let h=this.bitmapFont.get(o);if(!h)continue;let c=l%this.atlasColumns,d=Math.floor(l/this.atlasColumns),f=c*this.charWidth,g=d*this.charHeight;for(let u=0;u<Math.min(h.length,this.charHeight);u++){let m=h[u];for(let p=0;p<this.charWidth;p++){let C=1<<7-p;m&C&&n.fillRect(f+p,g+u,1,1)}}l++}this.createAtlasTexture()}buildCharCodeMap(){if(!this.bitmapFont)return;this.charCodeToAtlasIndex.fill(65535);let t=Array.from(this.bitmapFont.keys()).sort((e,r)=>e-r);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,r=this.cachedAtlasHeight,i=.5/e,s=.5/r;for(let n=0;n<t;n++){let l=n%this.atlasColumns,o=Math.floor(n/this.atlasColumns),h=(l*this.charWidth+i)/e,c=(o*this.charHeight+s)/r,d=((l+1)*this.charWidth-i)/e,f=((o+1)*this.charHeight-s)/r,g=n*4;this.atlasUVs[g]=h,this.atlasUVs[g+1]=c,this.atlasUVs[g+2]=d,this.atlasUVs[g+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),r=0,i=0,s=0;return e.length===3?(r=parseInt(e[0]+e[0],16),i=parseInt(e[1]+e[1],16),s=parseInt(e[2]+e[2],16)):e.length===6&&(r=parseInt(e.slice(0,2),16),i=parseInt(e.slice(2,4),16),s=parseInt(e.slice(4,6),16)),[r/255,i/255,s/255,1]}if(t.startsWith("rgb")){let e=t.match(/rgba?\(([^)]+)\)/);if(e){let r=e[1].split(",").map(i=>parseFloat(i.trim()));return[r[0]/255,r[1]/255,r[2]/255,r[3]!==void 0?r[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 r=Math.floor(t/this.cellWidth),i=Math.floor(e/this.cellHeight),s=r/this.cols,n=i/this.rows,l=Math.min(s,n),o=Math.max(1,Math.floor(l)),h=this.cols*this.cellWidth*o,c=this.rows*this.cellHeight*o;this.canvas.style.width=`${h}px`,this.canvas.style.height=`${c}px`,this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}setPalette(t){let e=0;for(let r=0;r<Math.min(t.length,256);r++){let i=t[r];e=(e<<5)-e+i.r,e=(e<<5)-e+i.g,e=(e<<5)-e+i.b,e=(e<<5)-e+i.a,e=e|0}if(e!==this.paletteHash){this.paletteHash=e;for(let r=0;r<t.length&&r<256;r++){let i=t[r],s=r*4;this.paletteFloat[s]=i.r/255,this.paletteFloat[s+1]=i.g/255,this.paletteFloat[s+2]=i.b/255,this.paletteFloat[s+3]=i.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 r=0;r<256;r++){let i=r*4;e[i]=this.paletteFloat[i]*255,e[i+1]=this.paletteFloat[i+1]*255,e[i+2]=this.paletteFloat[i+2]*255,e[i+3]=this.paletteFloat[i+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)}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 r=this.parseColor(this.canvasBgColor);e.clearColor(r[0],r[1],r[2],r[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,r=this.instancedExtension;if(!this.instanceData||this.instanceData.length===0){console.warn("[TerminalGL] \u26A0\uFE0F Instance data not initialized, falling back to standard rendering"),this.useInstancing=!1,this.renderDirectBuffers(t);return}let i=t.width*t.height;if(this.useUint16Indices&&i>8191){console.warn(`[TerminalGL] \u26A0\uFE0F Terminal too large for instanced rendering with Uint16 (${i} cells > 8191). Falling back to standard rendering.`),this.useInstancing=!1,this.renderDirectBuffers(t);return}let s=0,n=this.instanceData.length/8;for(let f=0;f<t.height;f++)for(let g=0;g<t.width;g++){let u=t.cells[f*t.width+g],m=u.bgColorIndex,p=u.fgColorIndex,C=this.canvasBgColor!==null&&m===255,A=u.char===" "||p===255;if(!C){if(s>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${n}`);break}let b=s*8;this.instanceData[b]=g,this.instanceData[b+1]=f,this.instanceData[b+2]=0,this.instanceData[b+3]=0,this.instanceData[b+4]=0,this.instanceData[b+5]=0,this.instanceData[b+6]=m,this.instanceData[b+7]=0,s++}if(!A){let b=u.char.charCodeAt(0),E=this.charCodeToAtlasIndex[b];if(E!==65535){if(s>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${n}`);break}let R=E*4,x=s*8;this.instanceData[x]=g,this.instanceData[x+1]=f,this.instanceData[x+2]=this.atlasUVs[R],this.instanceData[x+3]=this.atlasUVs[R+1],this.instanceData[x+4]=this.atlasUVs[R+2],this.instanceData[x+5]=this.atlasUVs[R+3],this.instanceData[x+6]=0,this.instanceData[x+7]=p,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),r.vertexAttribDivisorANGLE(this.aPosition,0),e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer);let l=8*Float32Array.BYTES_PER_ELEMENT,o=e.getAttribLocation(this.program,"aInstanceOffset");e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,l,0),r.vertexAttribDivisorANGLE(o,1);let h=e.getAttribLocation(this.program,"aInstanceUVs");e.enableVertexAttribArray(h),e.vertexAttribPointer(h,4,e.FLOAT,!1,l,2*Float32Array.BYTES_PER_ELEMENT),r.vertexAttribDivisorANGLE(h,1);let c=e.getAttribLocation(this.program,"aInstanceColors");e.enableVertexAttribArray(c),e.vertexAttribPointer(c,2,e.FLOAT,!1,l,6*Float32Array.BYTES_PER_ELEMENT),r.vertexAttribDivisorANGLE(c,1),e.uniform2f(this.uResolution,this.canvas.width,this.canvas.height);let d=e.getUniformLocation(this.program,"uCellSize");e.uniform2f(d,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),r.drawElementsInstancedANGLE(e.TRIANGLES,6,e.UNSIGNED_SHORT,0,s),r.vertexAttribDivisorANGLE(this.aPosition,0),r.vertexAttribDivisorANGLE(o,0),r.vertexAttribDivisorANGLE(h,0),r.vertexAttribDivisorANGLE(c,0)}renderDirectBuffers(t){let e=this.gl,r=t.width*t.height,i=r*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 s=0,n=0,l=t.cells,o=r;for(let u=0;u<o;u++){let m=l[u],p=m.bgColorIndex,A=this.canvasBgColor!==null&&p===255?255:p,b=0;for(let x=0;x<4;x++)this.renderTexCoords[s++]=b,this.renderTexCoords[s++]=b,this.renderColorIndices[n++]=A;let E=m.fgColorIndex,R=m.char;if(R===" "||E===255)for(let x=0;x<4;x++)this.renderTexCoords[s++]=0,this.renderTexCoords[s++]=0,this.renderColorIndices[n++]=255;else{let x=R.charCodeAt(0),W=this.charCodeToAtlasIndex[x];if(W!==65535){let w=W*4,H=this.atlasUVs[w],O=this.atlasUVs[w+1],z=this.atlasUVs[w+2],Y=this.atlasUVs[w+3];this.renderTexCoords[s++]=H,this.renderTexCoords[s++]=O,this.renderColorIndices[n++]=E,this.renderTexCoords[s++]=z,this.renderTexCoords[s++]=O,this.renderColorIndices[n++]=E,this.renderTexCoords[s++]=H,this.renderTexCoords[s++]=Y,this.renderColorIndices[n++]=E,this.renderTexCoords[s++]=z,this.renderTexCoords[s++]=Y,this.renderColorIndices[n++]=E}else for(let w=0;w<4;w++)this.renderTexCoords[s++]=0,this.renderTexCoords[s++]=0,this.renderColorIndices[n++]=255}}(s!==o*2*4*2||n!==o*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:s,colorIdx:n,expected:o*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,s)),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,n))):(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,s)),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,n)),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,g=this.useUint16Indices?e.UNSIGNED_SHORT:e.UNSIGNED_INT;e.drawElements(e.TRIANGLES,f,g,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 r=t*e,i=this.useUint16Indices?8191:262144;if(r>i){let c=Math.floor(Math.sqrt(i));console.error(`[TerminalGL] \u274C Cannot resize to ${t}\xD7${e} (${r} cells). Device limit: ${i} cells (max ~${c}\xD7${c}). ${this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let s=F.checkCompatibility();r>s.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${t}\xD7${e} (${r} cells) exceeds recommended limit (${s.recommendedMaxCells} cells). Performance may degrade.`),this.cols=t,this.rows=e,this.staticPositionsInitialized=!1;let n=this.cols*this.rows*2,l=Math.ceil(n*1.5),o=n>this.maxCells,h=this.maxCells>l*4;if(o||h){let c=this.maxCells;this.maxCells=l,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);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),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=o?"\u{1F4C8} Growing":"\u{1F4C9} Shrinking",g=c*160/1048576,u=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${f} buffers: ${g.toFixed(2)}MB \u2192 ${u.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.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}getCols(){return this.cols}getRows(){return this.rows}isReady(){return!!(this.bitmapFont&&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.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)}};T(F,"TerminalGL");var U=F;var G=class G{constructor(t,e,r,i,s){a(this,"atlases");a(this,"charMap");a(this,"baseCharWidth");a(this,"baseCharHeight");a(this,"baseCellWidth");a(this,"baseCellHeight");a(this,"atlasColumns",16);a(this,"font");a(this,"SCALES",[1,2,4,8]);a(this,"colorCache",new Map);a(this,"MAX_CACHE_SIZE",512);this.font=t,this.baseCharWidth=e,this.baseCharHeight=r,this.baseCellWidth=i??e,this.baseCellHeight=s??r,this.charMap=new Map,this.atlases=new Map,this.generateAtlases()}generateAtlases(){this.atlasColumns=16;let t=0;for(let[e,r]of this.font){let i=t%this.atlasColumns,s=Math.floor(t/this.atlasColumns);this.charMap.set(e,{x:i*this.baseCharWidth,y:s*this.baseCharHeight});for(let n of this.SCALES){let l=this.getOrCreateAtlas(n),o=i*l.charWidth,h=s*l.charHeight;this.renderBitmapToAtlas(l,r,o,h)}t++}}getOrCreateAtlas(t){let e=this.atlases.get(t);if(!e){let r=this.baseCharWidth*t,i=this.baseCharHeight*t,n=Math.ceil(256/this.atlasColumns),l=document.createElement("canvas");l.width=this.atlasColumns*r,l.height=n*i;let o=l.getContext("2d",{alpha:!0,willReadFrequently:!1});if(!o)throw new Error(`Impossible de cr\xE9er le contexte 2D pour l'atlas ${t}x`);o.imageSmoothingEnabled=!1,e={canvas:l,ctx:o,scale:t,charWidth:r,charHeight:i},this.atlases.set(t,e)}return e}renderBitmapToAtlas(t,e,r,i){let s=t.scale,n=t.ctx;n.fillStyle="#ffffff";for(let l=0;l<Math.min(e.length,this.baseCharHeight);l++){let o=e[l];for(let h=0;h<this.baseCharWidth;h++){let c=1<<7-h;o&c&&n.fillRect(r+h*s,i+l*s,s,s)}}}drawChar(t,e,r,i,s,n,l){let o=this.charMap.get(e);if(!o)return;let h=`${e}:${l}`,c=this.colorCache.get(h);if(c)c.lastUsed=performance.now();else{let C=this.createColoredGlyph(e,l,o);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=s/this.baseCellWidth,f=n/this.baseCellHeight,g=(this.baseCellWidth-this.baseCharWidth)/2*d,u=(this.baseCellHeight-this.baseCharHeight)/2*f,m=this.baseCharWidth*d,p=this.baseCharHeight*f;t.drawImage(c.canvas,r+g,i+u,m,p)}createColoredGlyph(t,e,r){let i=this.atlases.get(1);if(!i)return null;let s=i.ctx.getImageData(r.x,r.y,this.baseCharWidth,this.baseCharHeight),n=s.data,l=this.hexToRgb(e);for(let c=0;c<n.length;c+=4)n[c+3]>0&&(n[c]=l.r,n[c+1]=l.g,n[c+2]=l.b);let o=document.createElement("canvas");o.width=this.baseCharWidth,o.height=this.baseCharHeight;let h=o.getContext("2d",{alpha:!0});return h?(h.imageSmoothingEnabled=!1,h.putImageData(s,0,0),o):null}hexToRgb(t){if(t.startsWith("#")){let s=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(s,(l,o,h,c)=>o+o+h+h+c+c);let n=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return n?{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[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 i={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 i?{r:i[0],g:i[1],b:i[2]}:{r:255,g:255,b:255}}evictLRU(){let t=null,e=1/0;for(let[r,i]of this.colorCache)i.lastUsed<e&&(e=i.lastUsed,t=r);if(t){let r=this.colorCache.get(t);r&&(r.canvas.width=0,r.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()}};T(G,"BitmapFontAtlas");var I=G;var P=class P{constructor(t,e={}){a(this,"canvas");a(this,"ctx");a(this,"parentElement");a(this,"cells");a(this,"cols",0);a(this,"rows",0);a(this,"fontSize");a(this,"fontFamily");a(this,"defaultFgColor");a(this,"defaultBgColor");a(this,"canvasBgColor");a(this,"cellWidth");a(this,"cellHeight");a(this,"offsetX",0);a(this,"offsetY",0);a(this,"fontType","web");a(this,"bitmapFont");a(this,"bitmapAtlas");a(this,"bitmapCharWidth",8);a(this,"bitmapCharHeight",8);a(this,"showDebugGrid");a(this,"debugGridColor");a(this,"gridOverlay");a(this,"fixedGridMode");a(this,"fixedCols");a(this,"fixedRows");a(this,"cellAspectRatio");a(this,"resizeObserver");a(this,"imageDataBuffer");a(this,"useImageDataRendering",!1);a(this,"paletteCache");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??10/14,this.cellWidth=e.cellWidth??10,this.cellHeight=e.cellHeight??14,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.canvas=document.createElement("canvas"),e.className&&(this.canvas.className=e.className),e.style&&Object.assign(this.canvas.style,e.style),this.canvas.style.imageRendering="auto",this.parentElement.appendChild(this.canvas);let r=this.canvas.getContext("2d",{alpha:!0,desynchronized:!1});if(!r)throw new Error("UTSPRender: Impossible d'obtenir le contexte 2D du canvas");this.ctx=r,this.calculateGridSize(),this.cells=this.createEmptyGrid(),this.showDebugGrid&&(this.gridOverlay=new y(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,innerPadding:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;if(this.fixedGridMode&&this.fixedCols&&this.fixedRows)if(this.cols=this.fixedCols,this.rows=this.fixedRows,this.fontType==="bitmap"){let n=t/this.cols,l=e/this.rows,o=this.bitmapCharWidth/this.bitmapCharHeight;n/l>o?(this.cellHeight=Math.floor(l),this.cellWidth=Math.floor(this.cellHeight*o)):(this.cellWidth=Math.floor(n),this.cellHeight=Math.floor(this.cellWidth/o))}else{let n=t/this.cols,l=e/this.rows;n/l>this.cellAspectRatio?(this.cellHeight=Math.floor(l*100)/100,this.cellWidth=Math.floor(this.cellHeight*this.cellAspectRatio*100)/100):(this.cellWidth=Math.floor(n*100)/100,this.cellHeight=Math.floor(this.cellWidth/this.cellAspectRatio*100)/100);let o=14,h=12;this.fontSize=Math.floor(this.cellHeight/o*h*100)/100}else this.cols=Math.floor(t/this.cellWidth),this.rows=Math.floor(e/this.cellHeight);let r=this.cols*this.cellWidth,i=this.rows*this.cellHeight;this.offsetX=Math.floor((t-r)/2),this.offsetY=Math.floor((e-i)/2);let s=window.devicePixelRatio||1;this.canvas.style.width=`${t}px`,this.canvas.style.height=`${e}px`,this.canvas.width=t*s,this.canvas.height=e*s,this.ctx.scale(s,s)}createEmptyGrid(){let t=[];for(let e=0;e<this.rows;e++){let r=[];for(let i=0;i<this.cols;i++)r.push({char:" ",fgColor:this.defaultFgColor,bgColor:this.defaultBgColor});t.push(r)}return t}enableAutoResize(){this.resizeObserver=new ResizeObserver(()=>{let t=this.cols,e=this.rows;if(this.calculateGridSize(),this.cols!==t||this.rows!==e){let r=this.cells;this.cells=this.createEmptyGrid();let i=Math.min(t,this.cols),s=Math.min(e,this.rows);for(let n=0;n<s;n++)for(let l=0;l<i;l++)this.cells[n][l]=r[n][l]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(t,e,r,i,s){if(e<0||e>=this.rows||t<0||t>=this.cols)return;let n=r&&typeof r=="string"?r.charAt(0):" ";this.cells[e][t]={char:n,fgColor:i??this.defaultFgColor,bgColor:s??this.defaultBgColor}}getCell(t,e){return e<0||e>=this.rows||t<0||t>=this.cols?null:this.cells[e][t]}write(t,e,r,i,s){for(let n=0;n<r.length;n++)this.setCell(t+n,e,r[n],i,s)}fillRect(t,e,r,i,s=" ",n,l){for(let o=e;o<e+i;o++)for(let h=t;h<t+r;h++)this.setCell(h,o,s,n,l)}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 r=0;for(let i=0;i<t.height;i++)for(let s=0;s<t.width;s++){let n=t.cells[r];i<this.rows&&s<this.cols&&this.setCell(s,i,n.char,n.fgColor,n.bgColor),r++}}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 r=this.imageDataBuffer.data;for(let o=0;o<this.rows;o++)for(let h=0;h<this.cols;h++){let c=this.cells[o][h],d=this.parseColorToRGB(c.bgColor),f=this.parseColorToRGB(c.fgColor),g=c.char.charCodeAt(0),u=this.bitmapFont.get(g);for(let m=0;m<this.bitmapCharHeight;m++)for(let p=0;p<this.bitmapCharWidth;p++){let C=h*this.bitmapCharWidth+p,b=((o*this.bitmapCharHeight+m)*t+C)*4,E=!1;if(u&&m<u.length){let R=u[m],x=1<<7-p;E=(R&x)!==0}E?(r[b]=f.r,r[b+1]=f.g,r[b+2]=f.b,r[b+3]=f.a):(r[b]=d.r,r[b+1]=d.g,r[b+2]=d.b,r[b+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 i=document.createElement("canvas");i.width=t,i.height=e,i.getContext("2d").putImageData(this.imageDataBuffer,0,0);let n=this.cols*this.cellWidth,l=this.rows*this.cellHeight;this.ctx.drawImage(i,0,0,t,e,this.offsetX,this.offsetY,n,l),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 s=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(s,(l,o,h,c)=>o+o+h+h+c+c);let n=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);if(n)return{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[3],16),a:255}}let i={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 i?{r:i[0],g:i[1],b:i[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.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 r=this.cells[t][e],i=Math.floor(this.offsetX+e*this.cellWidth),s=Math.floor(this.offsetY+t*this.cellHeight),n=Math.floor(this.offsetX+(e+1)*this.cellWidth),l=Math.floor(this.offsetY+(t+1)*this.cellHeight),o=n-i,h=l-s;if((this.canvasBgColor!==null||r.bgColor!==this.defaultBgColor)&&(this.ctx.fillStyle=r.bgColor,this.ctx.fillRect(i,s,o,h)),r.char!==" ")if(this.fontType==="bitmap"&&this.bitmapFont)this.drawBitmapChar(r.char,i,s,o,h,r.fgColor);else{this.ctx.fillStyle=r.fgColor;let d=i+(o-this.ctx.measureText(r.char).width)/2,f=s+(h-this.fontSize)/2;this.ctx.fillText(r.char,d,f)}}this.showDebugGrid&&this.drawDebugGrid()}drawBitmapChar(t,e,r,i,s,n){let l=t.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,l,e,r,i,s,n);return}if(!this.bitmapFont)return;let o=this.bitmapFont.get(l);if(!o)return;let h=i/this.bitmapCharWidth,c=s/this.bitmapCharHeight;this.ctx.fillStyle=n;for(let d=0;d<Math.min(o.length,this.bitmapCharHeight);d++){let f=o[d],g=r+d*c,u=r+(d+1)*c;for(let m=0;m<this.bitmapCharWidth;m++){let p=1<<7-m;if(f&p){let C=e+m*h,A=e+(m+1)*h;this.ctx.fillRect(C,g,A-C,u-g)}}}}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}getOffsets(){return{offsetX:this.offsetX,offsetY:this.offsetY}}setDebugGrid(t){this.showDebugGrid=t,t&&!this.gridOverlay?(this.gridOverlay=new y(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,innerPadding: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,r){this.fixedGridMode=!0,this.fixedCols=t,this.fixedRows=e,r!==void 0&&(this.cellAspectRatio=r);let i=this.cols,s=this.rows,n=this.cells;if(this.calculateGridSize(),this.cols!==i||this.rows!==s){this.cells=this.createEmptyGrid();let l=Math.min(i,this.cols),o=Math.min(s,this.rows);for(let h=0;h<o;h++)for(let c=0;c<l;c++)this.cells[h][c]=n[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 r=this.cols,i=this.rows,s=this.cells;if(this.calculateGridSize(),this.cols!==r||this.rows!==i){this.cells=this.createEmptyGrid();let n=Math.min(r,this.cols),l=Math.min(i,this.rows);for(let o=0;o<l;o++)for(let h=0;h<n;h++)this.cells[o][h]=s[o][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,r,i,s){this.fontType="bitmap",this.bitmapFont=t,this.bitmapCharWidth=e,this.bitmapCharHeight=r,this.bitmapAtlas=new I(t,e,r,i,s),this.cellWidth=i,this.cellHeight=s,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 r=T(i=>{if(i==null||isNaN(i))return console.warn("[Terminal2D] Invalid palette index (undefined/null/NaN):",i),this.defaultFgColor;if(i===255)return"rgba(0, 0, 0, 0)";if(i<0||i>=e.length)return console.warn(`[Terminal2D] Invalid palette index: ${i}`),this.defaultFgColor;let s=e[i];return!s||typeof s.r!="number"?(console.warn(`[Terminal2D] Corrupted palette entry at index ${i}:`,s),this.defaultFgColor):`rgba(${s.r}, ${s.g}, ${s.b}, ${s.a/255})`},"convertColor");for(let i=0;i<t.height&&i<this.rows;i++)for(let s=0;s<t.width&&s<this.cols;s++){let n=i*t.width+s;if(n>=t.cells.length)break;let l=t.cells[n];if(!l)continue;let o=r(l.fgColorIndex),h=r(l.bgColorIndex);this.setCell(s,i,l.char??" ",o,h)}this.render()}isReady(){return!0}getCols(){return this.cols}getRows(){return this.rows}resize(t,e){this.setFixedGrid(t,e)}destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=void 0),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}};T(P,"Terminal2D");var L=P;var S=class S{constructor(t,e={}){a(this,"container");a(this,"overlayDiv",null);a(this,"button",null);a(this,"options");a(this,"started",!1);a(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=`
106
+ position: absolute !important;
107
+ top: 0 !important;
108
+ left: 0 !important;
109
+ width: 100% !important;
110
+ height: 100% !important;
111
+ background-color: ${this.options.backgroundColor} !important;
112
+ display: flex !important;
113
+ justify-content: center !important;
114
+ align-items: center !important;
115
+ z-index: ${this.options.zIndex} !important;
116
+ cursor: pointer !important;
117
+ `,this.button=document.createElement("button"),this.button.className="utsp-autoplay-button",this.button.textContent=this.options.buttonText,this.button.style.cssText=`
118
+ padding: 16px 32px !important;
119
+ font-size: 18px !important;
120
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif !important;
121
+ font-weight: 600 !important;
122
+ color: ${this.options.buttonTextColor} !important;
123
+ background-color: ${this.options.buttonColor} !important;
124
+ border: none !important;
125
+ border-radius: 8px !important;
126
+ cursor: pointer !important;
127
+ transition: background-color 0.2s ease, transform 0.1s ease !important;
128
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
129
+ `,this.button.addEventListener("mouseenter",()=>{this.button&&(this.button.style.backgroundColor=`${this.options.buttonHoverColor} !important`,this.button.style.transform="scale(1.05)")}),this.button.addEventListener("mouseleave",()=>{this.button&&(this.button.style.backgroundColor=`${this.options.buttonColor} !important`,this.button.style.transform="scale(1)")}),this.button.addEventListener("click",e=>{e.stopPropagation(),this.start()}),this.overlayDiv.addEventListener("click",()=>{this.start()}),this.overlayDiv.appendChild(this.button),this.container.appendChild(this.overlayDiv)}start(){this.started||(this.started=!0,this.overlayDiv&&(this.overlayDiv.style.transition="opacity 0.3s ease",this.overlayDiv.style.opacity="0",setTimeout(()=>{this.removeOverlay()},300)),this.onStartCallback&&this.onStartCallback())}isStarted(){return this.started}isVisible(){return this.overlayDiv!==null&&!this.started}removeOverlay(){this.overlayDiv&&this.overlayDiv.parentElement&&this.overlayDiv.parentElement.removeChild(this.overlayDiv),this.overlayDiv=null,this.button=null}setButtonText(t){this.options.buttonText=t,this.button&&(this.button.textContent=t)}setOnStart(t){this.onStartCallback=t}destroy(){this.removeOverlay(),this.started=!1}};T(S,"AutoplayOverlay");var M=S;var K="0.1.0";
package/dist/index.d.ts CHANGED
@@ -1045,6 +1045,89 @@ declare class GridOverlay {
1045
1045
  getCanvas(): HTMLCanvasElement;
1046
1046
  }
1047
1047
 
1048
+ /**
1049
+ * AutoplayOverlay - Displays a play button overlay that must be clicked to start the application
1050
+ *
1051
+ * This is useful for:
1052
+ * - Audio APIs that require user interaction before playing
1053
+ * - Preventing automatic resource consumption
1054
+ * - Better UX on mobile where autoplay may not be desired
1055
+ *
1056
+ * @example
1057
+ * ```typescript
1058
+ * const overlay = new AutoplayOverlay(container, {
1059
+ * buttonText: 'Click to Start',
1060
+ * onStart: () => {
1061
+ * // Application starts here
1062
+ * }
1063
+ * });
1064
+ *
1065
+ * // To programmatically start (e.g., if autoplay is enabled):
1066
+ * overlay.start();
1067
+ *
1068
+ * // Cleanup:
1069
+ * overlay.destroy();
1070
+ * ```
1071
+ */
1072
+ interface AutoplayOverlayOptions {
1073
+ /** Text to display on the button (default: 'Click to Start') */
1074
+ buttonText?: string;
1075
+ /** Callback when user clicks the button */
1076
+ onStart?: () => void;
1077
+ /** Background color of the overlay (default: 'rgba(0, 0, 0, 0.8)') */
1078
+ backgroundColor?: string;
1079
+ /** Button background color (default: '#4a90d9') */
1080
+ buttonColor?: string;
1081
+ /** Button hover color (default: '#357abd') */
1082
+ buttonHoverColor?: string;
1083
+ /** Button text color (default: '#ffffff') */
1084
+ buttonTextColor?: string;
1085
+ /** Z-index of the overlay (default: 1000) */
1086
+ zIndex?: number;
1087
+ }
1088
+ declare class AutoplayOverlay {
1089
+ private container;
1090
+ private overlayDiv;
1091
+ private button;
1092
+ private options;
1093
+ private started;
1094
+ private onStartCallback?;
1095
+ constructor(container: HTMLElement, options?: AutoplayOverlayOptions);
1096
+ /**
1097
+ * Create the overlay DOM elements
1098
+ */
1099
+ private createOverlay;
1100
+ /**
1101
+ * Start the application (hide overlay and call onStart callback)
1102
+ * Can be called programmatically if autoplay is enabled
1103
+ */
1104
+ start(): void;
1105
+ /**
1106
+ * Check if the overlay has been started
1107
+ */
1108
+ isStarted(): boolean;
1109
+ /**
1110
+ * Check if the overlay is currently visible
1111
+ */
1112
+ isVisible(): boolean;
1113
+ /**
1114
+ * Remove the overlay from DOM
1115
+ */
1116
+ private removeOverlay;
1117
+ /**
1118
+ * Set the button text
1119
+ */
1120
+ setButtonText(text: string): void;
1121
+ /**
1122
+ * Update the onStart callback
1123
+ */
1124
+ setOnStart(callback: () => void): void;
1125
+ /**
1126
+ * Destroy the overlay and cleanup
1127
+ */
1128
+ destroy(): void;
1129
+ }
1130
+
1048
1131
  /**
1049
1132
  * UTSP Render - Main entry point
1050
1133
  *
@@ -1054,5 +1137,5 @@ declare class GridOverlay {
1054
1137
 
1055
1138
  declare const version = "0.1.0";
1056
1139
 
1057
- export { BitmapFontAtlas, DEFAULT_PALETTE, GridOverlay, Terminal2D, TerminalGL, colorToPaletteIndex, paletteIndexToColor, version };
1058
- export type { BitmapFont$1 as BitmapFont, FontType, RenderOptions, TerminalCell, TerminalData, TerminalGLOptions, WebGLCompatibilityReport };
1140
+ export { AutoplayOverlay, BitmapFontAtlas, DEFAULT_PALETTE, GridOverlay, Terminal2D, TerminalGL, colorToPaletteIndex, paletteIndexToColor, version };
1141
+ export type { AutoplayOverlayOptions, BitmapFont$1 as BitmapFont, FontType, RenderOptions, TerminalCell, TerminalData, TerminalGLOptions, WebGLCompatibilityReport };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- var O=Object.defineProperty;var Y=(E,e,t)=>e in E?O(E,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):E[e]=t;var A=(E,e)=>O(E,"name",{value:e,configurable:!0});var a=(E,e,t)=>(Y(E,typeof e!="symbol"?e+"":e,t),t);var F=["#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 z(E,e=F){return E<0||E>=e.length?"#ff00ff":e[E]}A(z,"paletteIndexToColor");function N(E,e=F){let t=e.indexOf(E.toLowerCase());return t>=0?t:0}A(N,"colorToPaletteIndex");var U=class U{constructor(e,t){a(this,"canvas");a(this,"ctx");a(this,"container");a(this,"cols",0);a(this,"rows",0);a(this,"cellWidth",0);a(this,"cellHeight",0);a(this,"offsetX",0);a(this,"offsetY",0);a(this,"strokeColor","rgba(80, 80, 80, 0.4)");a(this,"lineWidth",1);a(this,"innerPadding",1);this.container=e,this.canvas=document.createElement("canvas"),this.canvas.className="grid-overlay-canvas";let i=t?.zIndex??10;this.canvas.style.cssText=`
1
+ var Y=Object.defineProperty;var $=(T,t,e)=>t in T?Y(T,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):T[t]=e;var E=(T,t)=>Y(T,"name",{value:t,configurable:!0});var a=(T,t,e)=>($(T,typeof t!="symbol"?t+"":t,e),e);var F=["#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 N(T,t=F){return T<0||T>=t.length?"#ff00ff":t[T]}E(N,"paletteIndexToColor");function k(T,t=F){let e=t.indexOf(T.toLowerCase());return e>=0?e:0}E(k,"colorToPaletteIndex");var D=class D{constructor(t,e){a(this,"canvas");a(this,"ctx");a(this,"container");a(this,"cols",0);a(this,"rows",0);a(this,"cellWidth",0);a(this,"cellHeight",0);a(this,"offsetX",0);a(this,"offsetY",0);a(this,"strokeColor","rgba(80, 80, 80, 0.4)");a(this,"lineWidth",1);a(this,"innerPadding",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
  position: absolute !important;
3
3
  top: 0 !important;
4
4
  left: 0 !important;
@@ -9,7 +9,7 @@ var O=Object.defineProperty;var Y=(E,e,t)=>e in E?O(E,e,{enumerable:!0,configura
9
9
  pointer-events: none !important;
10
10
  image-rendering: pixelated !important;
11
11
  image-rendering: crisp-edges !important;
12
- `,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,t&&(t.strokeColor&&(this.strokeColor=t.strokeColor),t.lineWidth!==void 0&&(this.lineWidth=t.lineWidth),t.innerPadding!==void 0&&(this.innerPadding=t.innerPadding))}setDimensions(e,t,i,s,r=0,n=0){this.cols=e,this.rows=t,this.cellWidth=i,this.cellHeight=s,this.offsetX=r,this.offsetY=n}setCanvasSize(e,t){let i=window.devicePixelRatio||1;this.canvas.width=e*i,this.canvas.height=t*i,this.ctx.setTransform(1,0,0,1,0,0),this.ctx.scale(i,i)}setStyle(e){e.strokeColor&&(this.strokeColor=e.strokeColor),e.lineWidth!==void 0&&(this.lineWidth=e.lineWidth),e.innerPadding!==void 0&&(this.innerPadding=e.innerPadding)}render(){if(!this.ctx)return;this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.strokeStyle=this.strokeColor,this.ctx.lineWidth=this.lineWidth;let e=this.cols*this.cellWidth,t=this.rows*this.cellHeight;this.ctx.beginPath();for(let i=0;i<=this.cols;i++){let s=this.offsetX+i*this.cellWidth;if(i===0){let r=s+this.innerPadding+.5;this.ctx.moveTo(r,this.offsetY+this.innerPadding),this.ctx.lineTo(r,this.offsetY+t-this.innerPadding)}else if(i===this.cols){let r=s-this.innerPadding+.5;this.ctx.moveTo(r,this.offsetY+this.innerPadding),this.ctx.lineTo(r,this.offsetY+t-this.innerPadding)}else{let r=s+.5;this.ctx.moveTo(r,this.offsetY+this.innerPadding),this.ctx.lineTo(r,this.offsetY+t-this.innerPadding)}}for(let i=0;i<=this.rows;i++){let s=this.offsetY+i*this.cellHeight;if(i===0){let r=s+this.innerPadding+.5;this.ctx.moveTo(this.offsetX+this.innerPadding,r),this.ctx.lineTo(this.offsetX+e-this.innerPadding,r)}else if(i===this.rows){let r=s-this.innerPadding+.5;this.ctx.moveTo(this.offsetX+this.innerPadding,r),this.ctx.lineTo(this.offsetX+e-this.innerPadding,r)}else{let r=s+.5;this.ctx.moveTo(this.offsetX+this.innerPadding,r),this.ctx.lineTo(this.offsetX+e-this.innerPadding,r)}}this.ctx.stroke()}update(e,t,i,s,r,n,l=0,o=0){this.setDimensions(e,t,i,s,l,o),this.setCanvasSize(r,n),this.render()}setVisible(e){this.canvas.style.display=e?"block":"none"}destroy(){this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}getCanvas(){return this.canvas}};A(U,"GridOverlay");var w=U;var I=class I{constructor(e,t){a(this,"canvas");a(this,"gl");a(this,"parentElement");a(this,"containerDiv");a(this,"cols");a(this,"rows");a(this,"charWidth");a(this,"charHeight");a(this,"cellWidth",8);a(this,"cellHeight",8);a(this,"glyphOffsetX",0);a(this,"glyphOffsetY",0);a(this,"canvasBgColor");a(this,"showGrid");a(this,"supportsUint32Indices",!1);a(this,"useUint16Indices",!1);a(this,"gridOverlay");a(this,"bitmapFont");a(this,"atlasTexture",null);a(this,"atlasCanvas");a(this,"atlasColumns",0);a(this,"paletteTexture",null);a(this,"program",null);a(this,"positionBuffer",null);a(this,"texCoordBuffer",null);a(this,"colorIndexBuffer",null);a(this,"indexBuffer",null);a(this,"aPosition");a(this,"aTexCoord");a(this,"aColorIndex");a(this,"uResolution",null);a(this,"uTexture",null);a(this,"uPalette",null);a(this,"resizeObserver");a(this,"charCodeToAtlasIndex",new Uint16Array(65536).fill(65535));a(this,"atlasUVs",new Float32Array(0));a(this,"cachedAtlasWidth",0);a(this,"cachedAtlasHeight",0);a(this,"paletteFloat",new Float32Array(256*4));a(this,"maxCells",0);a(this,"renderPositions",new Float32Array(0));a(this,"renderTexCoords",new Float32Array(0));a(this,"renderColorIndices",new Float32Array(0));a(this,"renderIndices",new Uint32Array(0));a(this,"cachedResolution",[0,0]);a(this,"cachedTextureUnit",-1);a(this,"cachedPaletteUnit",-1);a(this,"cachedTextureUniform",!1);a(this,"cachedPaletteUniform",!1);a(this,"paletteHash",0);a(this,"staticPositionsInitialized",!1);a(this,"vaoExtension",null);a(this,"vao",null);a(this,"instancedExtension",null);a(this,"useInstancing",!1);a(this,"instanceDataBuffer",null);a(this,"instanceData",new Float32Array(0));a(this,"templateQuadPositions",new Float32Array(0));a(this,"templateQuadIndices",new Uint16Array(0));if(!e)throw new Error("TerminalGL: Parent element is required");if(!Number.isInteger(t.cols)||t.cols<=0)throw new Error(`TerminalGL: Invalid cols: ${t.cols}. Must be a positive integer.`);if(!Number.isInteger(t.rows)||t.rows<=0)throw new Error(`TerminalGL: Invalid rows: ${t.rows}. Must be a positive integer.`);let i=t.cols*t.rows,s=I.checkCompatibility();if(s.errors.length>0)throw new Error(`TerminalGL: WebGL incompatible - ${s.errors.join(", ")}`);let r=t.forceUint16??!1;if(r&&i>s.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${t.cols}\xD7${t.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 ${t.cols}\xD7${t.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 ${t.cols}\xD7${t.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 n=t.charWidth??8,l=t.charHeight??8;if(!Number.isFinite(n)||n<=0)throw new Error(`TerminalGL: Invalid charWidth: ${n}. Must be a positive number.`);if(!Number.isFinite(l)||l<=0)throw new Error(`TerminalGL: Invalid charHeight: ${l}. Must be a positive number.`);for(this.parentElement=e,this.cols=t.cols,this.rows=t.rows,this.charWidth=n,this.charHeight=l,this.canvasBgColor=t.canvasBgColor!==void 0?t.canvasBgColor:null,this.showGrid=t.showGrid??!1;this.parentElement.firstChild;)this.parentElement.removeChild(this.parentElement.firstChild);let o=window.getComputedStyle(this.parentElement).position;o!=="relative"&&o!=="absolute"&&o!=="fixed"&&(this.parentElement.style.position="relative"),this.containerDiv=document.createElement("div"),this.containerDiv.className="terminalgl-container",this.containerDiv.style.cssText=`
12
+ `,this.container.appendChild(this.canvas);let r=this.canvas.getContext("2d");if(!r)throw new Error("[GridOverlay] Impossible de cr\xE9er le contexte 2D");this.ctx=r,e&&(e.strokeColor&&(this.strokeColor=e.strokeColor),e.lineWidth!==void 0&&(this.lineWidth=e.lineWidth),e.innerPadding!==void 0&&(this.innerPadding=e.innerPadding))}setDimensions(t,e,i,r,s=0,n=0){this.cols=t,this.rows=e,this.cellWidth=i,this.cellHeight=r,this.offsetX=s,this.offsetY=n}setCanvasSize(t,e){let i=window.devicePixelRatio||1;this.canvas.width=t*i,this.canvas.height=e*i,this.ctx.setTransform(1,0,0,1,0,0),this.ctx.scale(i,i)}setStyle(t){t.strokeColor&&(this.strokeColor=t.strokeColor),t.lineWidth!==void 0&&(this.lineWidth=t.lineWidth),t.innerPadding!==void 0&&(this.innerPadding=t.innerPadding)}render(){if(!this.ctx)return;this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.strokeStyle=this.strokeColor,this.ctx.lineWidth=this.lineWidth;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight;this.ctx.beginPath();for(let i=0;i<=this.cols;i++){let r=this.offsetX+i*this.cellWidth;if(i===0){let s=r+this.innerPadding+.5;this.ctx.moveTo(s,this.offsetY+this.innerPadding),this.ctx.lineTo(s,this.offsetY+e-this.innerPadding)}else if(i===this.cols){let s=r-this.innerPadding+.5;this.ctx.moveTo(s,this.offsetY+this.innerPadding),this.ctx.lineTo(s,this.offsetY+e-this.innerPadding)}else{let s=r+.5;this.ctx.moveTo(s,this.offsetY+this.innerPadding),this.ctx.lineTo(s,this.offsetY+e-this.innerPadding)}}for(let i=0;i<=this.rows;i++){let r=this.offsetY+i*this.cellHeight;if(i===0){let s=r+this.innerPadding+.5;this.ctx.moveTo(this.offsetX+this.innerPadding,s),this.ctx.lineTo(this.offsetX+t-this.innerPadding,s)}else if(i===this.rows){let s=r-this.innerPadding+.5;this.ctx.moveTo(this.offsetX+this.innerPadding,s),this.ctx.lineTo(this.offsetX+t-this.innerPadding,s)}else{let s=r+.5;this.ctx.moveTo(this.offsetX+this.innerPadding,s),this.ctx.lineTo(this.offsetX+t-this.innerPadding,s)}}this.ctx.stroke()}update(t,e,i,r,s,n,l=0,o=0){this.setDimensions(t,e,i,r,l,o),this.setCanvasSize(s,n),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}};E(D,"GridOverlay");var y=D;var I=class I{constructor(t,e){a(this,"canvas");a(this,"gl");a(this,"parentElement");a(this,"containerDiv");a(this,"cols");a(this,"rows");a(this,"charWidth");a(this,"charHeight");a(this,"cellWidth",8);a(this,"cellHeight",8);a(this,"glyphOffsetX",0);a(this,"glyphOffsetY",0);a(this,"canvasBgColor");a(this,"showGrid");a(this,"supportsUint32Indices",!1);a(this,"useUint16Indices",!1);a(this,"gridOverlay");a(this,"bitmapFont");a(this,"atlasTexture",null);a(this,"atlasCanvas");a(this,"atlasColumns",0);a(this,"paletteTexture",null);a(this,"program",null);a(this,"positionBuffer",null);a(this,"texCoordBuffer",null);a(this,"colorIndexBuffer",null);a(this,"indexBuffer",null);a(this,"aPosition");a(this,"aTexCoord");a(this,"aColorIndex");a(this,"uResolution",null);a(this,"uTexture",null);a(this,"uPalette",null);a(this,"resizeObserver");a(this,"charCodeToAtlasIndex",new Uint16Array(65536).fill(65535));a(this,"atlasUVs",new Float32Array(0));a(this,"cachedAtlasWidth",0);a(this,"cachedAtlasHeight",0);a(this,"paletteFloat",new Float32Array(256*4));a(this,"maxCells",0);a(this,"renderPositions",new Float32Array(0));a(this,"renderTexCoords",new Float32Array(0));a(this,"renderColorIndices",new Float32Array(0));a(this,"renderIndices",new Uint32Array(0));a(this,"cachedResolution",[0,0]);a(this,"cachedTextureUnit",-1);a(this,"cachedPaletteUnit",-1);a(this,"cachedTextureUniform",!1);a(this,"cachedPaletteUniform",!1);a(this,"paletteHash",0);a(this,"staticPositionsInitialized",!1);a(this,"vaoExtension",null);a(this,"vao",null);a(this,"instancedExtension",null);a(this,"useInstancing",!1);a(this,"instanceDataBuffer",null);a(this,"instanceData",new Float32Array(0));a(this,"templateQuadPositions",new Float32Array(0));a(this,"templateQuadIndices",new Uint16Array(0));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,r=I.checkCompatibility();if(r.errors.length>0)throw new Error(`TerminalGL: WebGL incompatible - ${r.errors.join(", ")}`);let s=e.forceUint16??!1;if(s&&i>r.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds Uint16 limit of ${r.maxCellsUint16} cells. Maximum size with Uint16: ${Math.floor(Math.sqrt(r.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(r.maxCellsUint16))} (or smaller rectangles like 127\xD764)`);if(!r.uint32Indices&&i>r.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds device limit of ${r.maxCellsUint16} cells (OES_element_index_uint not supported). Maximum size: ${Math.floor(Math.sqrt(r.maxCellsUint16))}\xD7${Math.floor(Math.sqrt(r.maxCellsUint16))}`);i>r.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Large terminal size ${e.cols}\xD7${e.rows} (${i} cells) exceeds recommended limit of ${r.recommendedMaxCells} cells. Performance may be impacted.`),r.warnings.length>0&&console.warn("[TerminalGL] WebGL Compatibility Warnings:",r.warnings);let n=e.charWidth??8,l=e.charHeight??8;if(!Number.isFinite(n)||n<=0)throw new Error(`TerminalGL: Invalid charWidth: ${n}. Must be a positive number.`);if(!Number.isFinite(l)||l<=0)throw new Error(`TerminalGL: Invalid charHeight: ${l}. Must be a positive number.`);for(this.parentElement=t,this.cols=e.cols,this.rows=e.rows,this.charWidth=n,this.charHeight=l,this.canvasBgColor=e.canvasBgColor!==void 0?e.canvasBgColor:null,this.showGrid=e.showGrid??!1;this.parentElement.firstChild;)this.parentElement.removeChild(this.parentElement.firstChild);let o=window.getComputedStyle(this.parentElement).position;o!=="relative"&&o!=="absolute"&&o!=="fixed"&&(this.parentElement.style.position="relative"),this.containerDiv=document.createElement("div"),this.containerDiv.className="terminalgl-container",this.containerDiv.style.cssText=`
13
13
  position: absolute !important;
14
14
  top: 0 !important;
15
15
  left: 0 !important;
@@ -23,7 +23,7 @@ var O=Object.defineProperty;var Y=(E,e,t)=>e in E?O(E,e,{enumerable:!0,configura
23
23
  image-rendering: pixelated !important;
24
24
  image-rendering: crisp-edges !important;
25
25
  object-fit: contain !important;
26
- `;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=r||!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.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 e={webgl1:!1,uint32Indices:!1,maxTextureSize:0,maxViewportDims:[0,0],maxCellsUint16:0,maxCellsUint32:0,recommendedMaxCells:0,warnings:[],errors:[]},t=document.createElement("canvas"),i=t.getContext("webgl")||t.getContext("experimental-webgl");if(!i||!(i instanceof WebGLRenderingContext))return e.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),e;let s=i;e.webgl1=!0;try{e.maxTextureSize=s.getParameter(s.MAX_TEXTURE_SIZE);let o=s.getParameter(s.MAX_VIEWPORT_DIMS);e.maxViewportDims=[o[0],o[1]]}catch(o){return e.errors.push(`\u274C Failed to query WebGL parameters: ${o}`),e}let r=s.getExtension("OES_element_index_uint");e.uint32Indices=!!r;let n=8;if(e.maxCellsUint16=Math.floor(65535/n),e.uint32Indices){let o=Math.floor(e.maxTextureSize*e.maxTextureSize/64);e.maxCellsUint32=Math.min(o,262144)}else e.maxCellsUint32=e.maxCellsUint16,e.warnings.push(`\u26A0\uFE0F OES_element_index_uint not supported - limited to ${e.maxCellsUint16} cells (e.g., 90\xD790 or 127\xD764)`);return e.recommendedMaxCells=Math.floor((e.uint32Indices?e.maxCellsUint32:e.maxCellsUint16)*.8),e.maxTextureSize<256?e.errors.push(`\u274C MAX_TEXTURE_SIZE too small: ${e.maxTextureSize} (minimum 256 required for font atlas)`):e.maxTextureSize<2048&&e.warnings.push(`\u26A0\uFE0F Small MAX_TEXTURE_SIZE: ${e.maxTextureSize} (may limit font atlas)`),(e.maxViewportDims[0]<1024||e.maxViewportDims[1]<768)&&e.warnings.push(`\u26A0\uFE0F Small MAX_VIEWPORT_DIMS: ${e.maxViewportDims[0]}\xD7${e.maxViewportDims[1]}`),s.getExtension("WEBGL_lose_context")||e.warnings.push("\u26A0\uFE0F WEBGL_lose_context not supported - may cause memory leaks"),e}initInstancedBuffers(){let e=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]),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.bufferData(e.ARRAY_BUFFER,this.templateQuadPositions,e.STATIC_DRAW),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),e.bufferData(e.ELEMENT_ARRAY_BUFFER,this.templateQuadIndices,e.STATIC_DRAW);let t=this.cols*this.rows*2;this.instanceData=new Float32Array(t*8),e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer),e.bufferData(e.ARRAY_BUFFER,this.instanceData.byteLength,e.DYNAMIC_DRAW)}initRenderBuffers(){this.maxCells=this.cols*this.rows*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 e=this.cellWidth,t=this.cellHeight,i=this.glyphOffsetX,s=this.glyphOffsetY,r=this.charWidth,n=this.charHeight,l=0,o=0,h=0;for(let d=0;d<this.rows;d++){let f=Math.round(d*t),g=Math.round(f+t);for(let u=0;u<this.cols;u++){let m=Math.round(u*e),p=Math.round(m+e);this.renderPositions[l++]=m,this.renderPositions[l++]=f,this.renderPositions[l++]=p,this.renderPositions[l++]=f,this.renderPositions[l++]=m,this.renderPositions[l++]=g,this.renderPositions[l++]=p,this.renderPositions[l++]=g,this.renderIndices[o++]=h,this.renderIndices[o++]=h+1,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+1,this.renderIndices[o++]=h+3,h+=4;let x=Math.round(m+i),T=Math.round(f+s),b=Math.round(x+r),C=Math.round(T+n);this.renderPositions[l++]=x,this.renderPositions[l++]=T,this.renderPositions[l++]=b,this.renderPositions[l++]=T,this.renderPositions[l++]=x,this.renderPositions[l++]=C,this.renderPositions[l++]=b,this.renderPositions[l++]=C,this.renderIndices[o++]=h,this.renderIndices[o++]=h+1,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+1,this.renderIndices[o++]=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 e=this.gl,t;this.useInstancing?t=`
26
+ `;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=s||!this.supportsUint32Indices,this.useUint16Indices?console.warn(`[TerminalGL] \u{1F4CA} Using Uint16 indices (max ${r.maxCellsUint16} cells)`):console.warn(`[TerminalGL] \u{1F4CA} Using Uint32 indices (max ${r.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.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 r=i;t.webgl1=!0;try{t.maxTextureSize=r.getParameter(r.MAX_TEXTURE_SIZE);let o=r.getParameter(r.MAX_VIEWPORT_DIMS);t.maxViewportDims=[o[0],o[1]]}catch(o){return t.errors.push(`\u274C Failed to query WebGL parameters: ${o}`),t}let s=r.getExtension("OES_element_index_uint");t.uint32Indices=!!s;let n=8;if(t.maxCellsUint16=Math.floor(65535/n),t.uint32Indices){let o=Math.floor(t.maxTextureSize*t.maxTextureSize/64);t.maxCellsUint32=Math.min(o,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]}`),r.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);let e=this.cols*this.rows*2;this.instanceData=new Float32Array(e*8),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer),t.bufferData(t.ARRAY_BUFFER,this.instanceData.byteLength,t.DYNAMIC_DRAW)}initRenderBuffers(){this.maxCells=this.cols*this.rows*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,r=this.glyphOffsetY,s=this.charWidth,n=this.charHeight,l=0,o=0,h=0;for(let d=0;d<this.rows;d++){let f=Math.round(d*e),g=Math.round(f+e);for(let u=0;u<this.cols;u++){let m=Math.round(u*t),p=Math.round(m+t);this.renderPositions[l++]=m,this.renderPositions[l++]=f,this.renderPositions[l++]=p,this.renderPositions[l++]=f,this.renderPositions[l++]=m,this.renderPositions[l++]=g,this.renderPositions[l++]=p,this.renderPositions[l++]=g,this.renderIndices[o++]=h,this.renderIndices[o++]=h+1,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+1,this.renderIndices[o++]=h+3,h+=4;let x=Math.round(m+i),A=Math.round(f+r),b=Math.round(x+s),C=Math.round(A+n);this.renderPositions[l++]=x,this.renderPositions[l++]=A,this.renderPositions[l++]=b,this.renderPositions[l++]=A,this.renderPositions[l++]=x,this.renderPositions[l++]=C,this.renderPositions[l++]=b,this.renderPositions[l++]=C,this.renderIndices[o++]=h,this.renderIndices[o++]=h+1,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+2,this.renderIndices[o++]=h+1,this.renderIndices[o++]=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=`
27
27
  // Per-vertex attributes (template quad)
28
28
  attribute vec2 aPosition; // Local quad position (0,0 to cellW,cellH)
29
29
 
@@ -62,7 +62,7 @@ var O=Object.defineProperty;var Y=(E,e,t)=>e in E?O(E,e,{enumerable:!0,configura
62
62
  float paletteU = (colorIndex + 0.5) / 256.0;
63
63
  vColor = texture2D(uPalette, vec2(paletteU, 0.5));
64
64
  }
65
- `:t=`
65
+ `:e=`
66
66
  attribute vec2 aPosition;
67
67
  attribute vec2 aTexCoord;
68
68
  attribute float aColorIndex; // \u{1F680} Index dans palette (0-255)
@@ -102,4 +102,28 @@ var O=Object.defineProperty;var Y=(E,e,t)=>e in E?O(E,e,{enumerable:!0,configura
102
102
  gl_FragColor = vec4(vColor.rgb * texColor.a, texColor.a);
103
103
  }
104
104
  }
105
- `,s=this.compileShader(e.VERTEX_SHADER,t),r=this.compileShader(e.FRAGMENT_SHADER,i);if(!s||!r)throw new Error("Shader compilation error");let n=e.createProgram();if(!n)throw new Error("Unable to create WebGL program");if(e.attachShader(n,s),e.attachShader(n,r),e.linkProgram(n),!e.getProgramParameter(n,e.LINK_STATUS)){let l=e.getProgramInfoLog(n);throw new Error("Program linking error: "+l)}this.program=n,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=e.getAttribLocation(n,"aPosition"),this.useInstancing?(this.aTexCoord=e.getAttribLocation(n,"aInstanceOffset"),this.aColorIndex=e.getAttribLocation(n,"aInstanceUVs"),this.instanceDataBuffer=e.createBuffer()):(this.aTexCoord=e.getAttribLocation(n,"aTexCoord"),this.aColorIndex=e.getAttribLocation(n,"aColorIndex")),this.uResolution=e.getUniformLocation(n,"uResolution"),this.uTexture=e.getUniformLocation(n,"uTexture"),this.uPalette=e.getUniformLocation(n,"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 i=this.gl,s=i.createShader(e);return s?(i.shaderSource(s,t),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 w(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,innerPadding:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let e=parseFloat(this.canvas.style.width)||this.cols*this.charWidth,t=parseFloat(this.canvas.style.height)||this.rows*this.charHeight,i=e/this.cols,s=t/this.rows;this.gridOverlay.update(this.cols,this.rows,i,s,e,t,0,0)}setBitmapFont(e,t,i,s,r){this.bitmapFont=e,this.charWidth=Math.round(t),this.charHeight=Math.round(i),this.cellWidth=Math.round(s),this.cellHeight=Math.round(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..."),this.initInstancedBuffers());try{this.generateAtlas()}catch(n){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",n),n}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()}generateAtlas(){if(!this.bitmapFont)return;let e=Array.from(this.bitmapFont.keys()).sort((o,h)=>o-h),t=e.length;this.atlasColumns=Math.ceil(Math.sqrt(t));let i=Math.ceil(t/this.atlasColumns),s=this.atlasColumns*this.charWidth,r=i*this.charHeight;this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=s,this.atlasCanvas.height=r;let n=this.atlasCanvas.getContext("2d");if(!n)throw new Error("Unable to create 2D context for atlas");n.clearRect(0,0,s,r),n.fillStyle="#ffffff";let l=0;for(let o of e){let h=this.bitmapFont.get(o);if(!h)continue;let c=l%this.atlasColumns,d=Math.floor(l/this.atlasColumns),f=c*this.charWidth,g=d*this.charHeight;for(let u=0;u<Math.min(h.length,this.charHeight);u++){let m=h[u];for(let p=0;p<this.charWidth;p++){let x=1<<7-p;m&x&&n.fillRect(f+p,g+u,1,1)}}l++}this.createAtlasTexture()}buildCharCodeMap(){if(!this.bitmapFont)return;this.charCodeToAtlasIndex.fill(65535);let e=Array.from(this.bitmapFont.keys()).sort((t,i)=>t-i);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,i=this.cachedAtlasHeight,s=.5/t,r=.5/i;for(let n=0;n<e;n++){let l=n%this.atlasColumns,o=Math.floor(n/this.atlasColumns),h=(l*this.charWidth+s)/t,c=(o*this.charHeight+r)/i,d=((l+1)*this.charWidth-s)/t,f=((o+1)*this.charHeight-r)/i,g=n*4;this.atlasUVs[g]=h,this.atlasUVs[g+1]=c,this.atlasUVs[g+2]=d,this.atlasUVs[g+3]=f}}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),i=0,s=0,r=0;return t.length===3?(i=parseInt(t[0]+t[0],16),s=parseInt(t[1]+t[1],16),r=parseInt(t[2]+t[2],16)):t.length===6&&(i=parseInt(t.slice(0,2),16),s=parseInt(t.slice(2,4),16),r=parseInt(t.slice(4,6),16)),[i/255,s/255,r/255,1]}if(e.startsWith("rgb")){let t=e.match(/rgba?\(([^)]+)\)/);if(t){let i=t[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(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 i=Math.floor(e/this.cellWidth),s=Math.floor(t/this.cellHeight),r=i/this.cols,n=s/this.rows,l=Math.min(r,n),o=Math.max(1,Math.floor(l)),h=this.cols*this.cellWidth*o,c=this.rows*this.cellHeight*o;this.canvas.style.width=`${h}px`,this.canvas.style.height=`${c}px`,this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}setPalette(e){let t=0;for(let i=0;i<Math.min(e.length,256);i++){let s=e[i];t=(t<<5)-t+s.r,t=(t<<5)-t+s.g,t=(t<<5)-t+s.b,t=(t<<5)-t+s.a,t=t|0}if(t!==this.paletteHash){this.paletteHash=t;for(let i=0;i<e.length&&i<256;i++){let s=e[i],r=i*4;this.paletteFloat[r]=s.r/255,this.paletteFloat[r+1]=s.g/255,this.paletteFloat[r+2]=s.b/255,this.paletteFloat[r+3]=s.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 i=0;i<256;i++){let s=i*4;t[s]=this.paletteFloat[s]*255,t[s+1]=this.paletteFloat[s+1]*255,t[s+2]=this.paletteFloat[s+2]*255,t[s+3]=this.paletteFloat[s+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)}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 i=this.parseColor(this.canvasBgColor);t.clearColor(i[0],i[1],i[2],i[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,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.useInstancing=!1,this.renderDirectBuffers(e);return}let s=e.width*e.height;if(this.useUint16Indices&&s>8191){console.warn(`[TerminalGL] \u26A0\uFE0F Terminal too large for instanced rendering with Uint16 (${s} cells > 8191). Falling back to standard rendering.`),this.useInstancing=!1,this.renderDirectBuffers(e);return}let r=0,n=this.instanceData.length/8;for(let f=0;f<e.height;f++)for(let g=0;g<e.width;g++){let u=e.cells[f*e.width+g],m=u.bgColorIndex,p=u.fgColorIndex,x=this.canvasBgColor!==null&&m===255,T=u.char===" "||p===255;if(!x){if(r>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${r}, max=${n}`);break}let b=r*8;this.instanceData[b]=g,this.instanceData[b+1]=f,this.instanceData[b+2]=0,this.instanceData[b+3]=0,this.instanceData[b+4]=0,this.instanceData[b+5]=0,this.instanceData[b+6]=m,this.instanceData[b+7]=0,r++}if(!T){let b=u.char.charCodeAt(0),C=this.charCodeToAtlasIndex[b];if(C!==65535){if(r>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${r}, max=${n}`);break}let R=C*4,v=r*8;this.instanceData[v]=g,this.instanceData[v+1]=f,this.instanceData[v+2]=this.atlasUVs[R],this.instanceData[v+3]=this.atlasUVs[R+1],this.instanceData[v+4]=this.atlasUVs[R+2],this.instanceData[v+5]=this.atlasUVs[R+3],this.instanceData[v+6]=0,this.instanceData[v+7]=p,r++}}}if(r===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,r*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),i.vertexAttribDivisorANGLE(this.aPosition,0),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer);let l=8*Float32Array.BYTES_PER_ELEMENT,o=t.getAttribLocation(this.program,"aInstanceOffset");t.enableVertexAttribArray(o),t.vertexAttribPointer(o,2,t.FLOAT,!1,l,0),i.vertexAttribDivisorANGLE(o,1);let h=t.getAttribLocation(this.program,"aInstanceUVs");t.enableVertexAttribArray(h),t.vertexAttribPointer(h,4,t.FLOAT,!1,l,2*Float32Array.BYTES_PER_ELEMENT),i.vertexAttribDivisorANGLE(h,1);let c=t.getAttribLocation(this.program,"aInstanceColors");t.enableVertexAttribArray(c),t.vertexAttribPointer(c,2,t.FLOAT,!1,l,6*Float32Array.BYTES_PER_ELEMENT),i.vertexAttribDivisorANGLE(c,1),t.uniform2f(this.uResolution,this.canvas.width,this.canvas.height);let d=t.getUniformLocation(this.program,"uCellSize");t.uniform2f(d,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),i.drawElementsInstancedANGLE(t.TRIANGLES,6,t.UNSIGNED_SHORT,0,r),i.vertexAttribDivisorANGLE(this.aPosition,0),i.vertexAttribDivisorANGLE(o,0),i.vertexAttribDivisorANGLE(h,0),i.vertexAttribDivisorANGLE(c,0)}renderDirectBuffers(e){let t=this.gl,i=e.width*e.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 r=0,n=0,l=e.cells,o=i;for(let u=0;u<o;u++){let m=l[u],p=m.bgColorIndex,T=this.canvasBgColor!==null&&p===255?255:p,b=0;for(let v=0;v<4;v++)this.renderTexCoords[r++]=b,this.renderTexCoords[r++]=b,this.renderColorIndices[n++]=T;let C=m.fgColorIndex,R=m.char;if(R===" "||C===255)for(let v=0;v<4;v++)this.renderTexCoords[r++]=0,this.renderTexCoords[r++]=0,this.renderColorIndices[n++]=255;else{let v=R.charCodeAt(0),M=this.charCodeToAtlasIndex[v];if(M!==65535){let y=M*4,P=this.atlasUVs[y],W=this.atlasUVs[y+1],S=this.atlasUVs[y+2],H=this.atlasUVs[y+3];this.renderTexCoords[r++]=P,this.renderTexCoords[r++]=W,this.renderColorIndices[n++]=C,this.renderTexCoords[r++]=S,this.renderTexCoords[r++]=W,this.renderColorIndices[n++]=C,this.renderTexCoords[r++]=P,this.renderTexCoords[r++]=H,this.renderColorIndices[n++]=C,this.renderTexCoords[r++]=S,this.renderTexCoords[r++]=H,this.renderColorIndices[n++]=C}else for(let y=0;y<4;y++)this.renderTexCoords[r++]=0,this.renderTexCoords[r++]=0,this.renderColorIndices[n++]=255}}(r!==o*2*4*2||n!==o*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:r,colorIdx:n,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,r)),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,n))):(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,r)),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,n)),t.enableVertexAttribArray(this.aColorIndex),t.vertexAttribPointer(this.aColorIndex,1,t.FLOAT,!1,0,0));let h=this.canvas.width,c=this.canvas.height;(this.cachedResolution[0]!==h||this.cachedResolution[1]!==c)&&(t.uniform2f(this.uResolution,h,c),this.cachedResolution[0]=h,this.cachedResolution[1]=c),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 f=e.width*e.height*2*6,g=this.useUint16Indices?t.UNSIGNED_SHORT:t.UNSIGNED_INT;t.drawElements(t.TRIANGLES,f,g,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 i=e*t,s=this.useUint16Indices?8191:262144;if(i>s){let c=Math.floor(Math.sqrt(s));console.error(`[TerminalGL] \u274C Cannot resize to ${e}\xD7${t} (${i} cells). Device limit: ${s} cells (max ~${c}\xD7${c}). ${this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let r=I.checkCompatibility();i>r.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${e}\xD7${t} (${i} cells) exceeds recommended limit (${r.recommendedMaxCells} cells). Performance may degrade.`),this.cols=e,this.rows=t,this.staticPositionsInitialized=!1;let n=this.cols*this.rows*2,l=Math.ceil(n*1.5),o=n>this.maxCells,h=this.maxCells>l*4;if(o||h){let c=this.maxCells;this.maxCells=l,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);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),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=o?"\u{1F4C8} Growing":"\u{1F4C9} Shrinking",g=c*160/1048576,u=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${f} buffers: ${g.toFixed(2)}MB \u2192 ${u.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.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}getCols(){return this.cols}getRows(){return this.rows}isReady(){return!!(this.bitmapFont&&this.atlasTexture&&this.program)}destroy(){this.dispose()}dispose(){this.resizeObserver&&this.resizeObserver.disconnect();let e=this.gl;this.program&&e.deleteProgram(this.program),this.positionBuffer&&e.deleteBuffer(this.positionBuffer),this.texCoordBuffer&&e.deleteBuffer(this.texCoordBuffer),this.colorIndexBuffer&&e.deleteBuffer(this.colorIndexBuffer),this.indexBuffer&&e.deleteBuffer(this.indexBuffer),this.instanceDataBuffer&&e.deleteBuffer(this.instanceDataBuffer),this.atlasTexture&&e.deleteTexture(this.atlasTexture),this.paletteTexture&&e.deleteTexture(this.paletteTexture),this.vao&&this.vaoExtension&&this.vaoExtension.deleteVertexArrayOES(this.vao);let t=e.getExtension("WEBGL_lose_context");t&&t.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.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)}};A(I,"TerminalGL");var D=I;var L=class L{constructor(e,t,i,s,r){a(this,"atlases");a(this,"charMap");a(this,"baseCharWidth");a(this,"baseCharHeight");a(this,"baseCellWidth");a(this,"baseCellHeight");a(this,"atlasColumns",16);a(this,"font");a(this,"SCALES",[1,2,4,8]);a(this,"colorCache",new Map);a(this,"MAX_CACHE_SIZE",512);this.font=e,this.baseCharWidth=t,this.baseCharHeight=i,this.baseCellWidth=s??t,this.baseCellHeight=r??i,this.charMap=new Map,this.atlases=new Map,this.generateAtlases()}generateAtlases(){this.atlasColumns=16;let e=0;for(let[t,i]of this.font){let s=e%this.atlasColumns,r=Math.floor(e/this.atlasColumns);this.charMap.set(t,{x:s*this.baseCharWidth,y:r*this.baseCharHeight});for(let n of this.SCALES){let l=this.getOrCreateAtlas(n),o=s*l.charWidth,h=r*l.charHeight;this.renderBitmapToAtlas(l,i,o,h)}e++}}getOrCreateAtlas(e){let t=this.atlases.get(e);if(!t){let i=this.baseCharWidth*e,s=this.baseCharHeight*e,n=Math.ceil(256/this.atlasColumns),l=document.createElement("canvas");l.width=this.atlasColumns*i,l.height=n*s;let o=l.getContext("2d",{alpha:!0,willReadFrequently:!1});if(!o)throw new Error(`Impossible de cr\xE9er le contexte 2D pour l'atlas ${e}x`);o.imageSmoothingEnabled=!1,t={canvas:l,ctx:o,scale:e,charWidth:i,charHeight:s},this.atlases.set(e,t)}return t}renderBitmapToAtlas(e,t,i,s){let r=e.scale,n=e.ctx;n.fillStyle="#ffffff";for(let l=0;l<Math.min(t.length,this.baseCharHeight);l++){let o=t[l];for(let h=0;h<this.baseCharWidth;h++){let c=1<<7-h;o&c&&n.fillRect(i+h*r,s+l*r,r,r)}}}drawChar(e,t,i,s,r,n,l){let o=this.charMap.get(t);if(!o)return;let h=`${t}:${l}`,c=this.colorCache.get(h);if(c)c.lastUsed=performance.now();else{let x=this.createColoredGlyph(t,l,o);if(!x)return;c={canvas:x,lastUsed:performance.now()},this.colorCache.set(h,c),this.colorCache.size>this.MAX_CACHE_SIZE&&this.evictLRU()}let d=r/this.baseCellWidth,f=n/this.baseCellHeight,g=(this.baseCellWidth-this.baseCharWidth)/2*d,u=(this.baseCellHeight-this.baseCharHeight)/2*f,m=this.baseCharWidth*d,p=this.baseCharHeight*f;e.drawImage(c.canvas,i+g,s+u,m,p)}createColoredGlyph(e,t,i){let s=this.atlases.get(1);if(!s)return null;let r=s.ctx.getImageData(i.x,i.y,this.baseCharWidth,this.baseCharHeight),n=r.data,l=this.hexToRgb(t);for(let c=0;c<n.length;c+=4)n[c+3]>0&&(n[c]=l.r,n[c+1]=l.g,n[c+2]=l.b);let o=document.createElement("canvas");o.width=this.baseCharWidth,o.height=this.baseCharHeight;let h=o.getContext("2d",{alpha:!0});return h?(h.imageSmoothingEnabled=!1,h.putImageData(r,0,0),o):null}hexToRgb(e){if(e.startsWith("#")){let r=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;e=e.replace(r,(l,o,h,c)=>o+o+h+h+c+c);let n=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return n?{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[3],16)}:{r:255,g:255,b:255}}let t=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)/.exec(e);if(t)return{r:parseInt(t[1],10),g:parseInt(t[2],10),b:parseInt(t[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]}[e.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2]}:{r:255,g:255,b:255}}evictLRU(){let e=null,t=1/0;for(let[i,s]of this.colorCache)s.lastUsed<t&&(t=s.lastUsed,e=i);if(e){let i=this.colorCache.get(e);i&&(i.canvas.width=0,i.canvas.height=0),this.colorCache.delete(e)}}getAtlasCanvas(e=1){return this.atlases.get(e)?.canvas}getAllAtlases(){return this.atlases}getCharDimensions(){return{width:this.baseCharWidth,height:this.baseCharHeight}}getCharCount(){return this.charMap.size}hasChar(e){return this.charMap.has(e)}getAtlasDimensions(e=1){let t=this.atlases.get(e);if(t)return{width:t.canvas.width,height:t.canvas.height}}toDataURL(e=1,t="image/png"){return this.atlases.get(e)?.canvas.toDataURL(t)}getCacheStats(){return{size:this.colorCache.size,maxSize:this.MAX_CACHE_SIZE}}clearCache(){for(let e of this.colorCache.values())e.canvas.width=0,e.canvas.height=0;this.colorCache.clear()}destroy(){this.charMap.clear();for(let e of this.atlases.values())e.canvas.width=0,e.canvas.height=0;this.atlases.clear(),this.clearCache()}};A(L,"BitmapFontAtlas");var B=L;var G=class G{constructor(e,t={}){a(this,"canvas");a(this,"ctx");a(this,"parentElement");a(this,"cells");a(this,"cols",0);a(this,"rows",0);a(this,"fontSize");a(this,"fontFamily");a(this,"defaultFgColor");a(this,"defaultBgColor");a(this,"canvasBgColor");a(this,"cellWidth");a(this,"cellHeight");a(this,"offsetX",0);a(this,"offsetY",0);a(this,"fontType","web");a(this,"bitmapFont");a(this,"bitmapAtlas");a(this,"bitmapCharWidth",8);a(this,"bitmapCharHeight",8);a(this,"showDebugGrid");a(this,"debugGridColor");a(this,"gridOverlay");a(this,"fixedGridMode");a(this,"fixedCols");a(this,"fixedRows");a(this,"cellAspectRatio");a(this,"resizeObserver");a(this,"imageDataBuffer");a(this,"useImageDataRendering",!1);a(this,"paletteCache");if(!e)throw new Error("Render: L'\xE9l\xE9ment parent est requis");this.parentElement=e,this.fixedGridMode=!!(t.fixedCols&&t.fixedRows),this.fixedCols=t.fixedCols,this.fixedRows=t.fixedRows,this.cellAspectRatio=t.cellAspectRatio??10/14,this.cellWidth=t.cellWidth??10,this.cellHeight=t.cellHeight??14,this.fontSize=t.fontSize??12,this.fontFamily=t.fontFamily??"monospace",this.defaultFgColor=t.defaultFgColor??"#ffffff",this.defaultBgColor=t.defaultBgColor??"#000000",this.canvasBgColor=t.canvasBgColor!==void 0?t.canvasBgColor:null,this.showDebugGrid=t.showDebugGrid??!1,this.debugGridColor=t.debugGridColor??"rgba(144, 24, 24, 1)",this.canvas=document.createElement("canvas"),t.className&&(this.canvas.className=t.className),t.style&&Object.assign(this.canvas.style,t.style),this.canvas.style.imageRendering="auto",this.parentElement.appendChild(this.canvas);let i=this.canvas.getContext("2d",{alpha:!0,desynchronized:!1});if(!i)throw new Error("UTSPRender: Impossible d'obtenir le contexte 2D du canvas");this.ctx=i,this.calculateGridSize(),this.cells=this.createEmptyGrid(),this.showDebugGrid&&(this.gridOverlay=new w(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,innerPadding:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let e=this.parentElement.clientWidth||800,t=this.parentElement.clientHeight||600;if(this.fixedGridMode&&this.fixedCols&&this.fixedRows)if(this.cols=this.fixedCols,this.rows=this.fixedRows,this.fontType==="bitmap"){let n=e/this.cols,l=t/this.rows,o=this.bitmapCharWidth/this.bitmapCharHeight;n/l>o?(this.cellHeight=Math.floor(l),this.cellWidth=Math.floor(this.cellHeight*o)):(this.cellWidth=Math.floor(n),this.cellHeight=Math.floor(this.cellWidth/o))}else{let n=e/this.cols,l=t/this.rows;n/l>this.cellAspectRatio?(this.cellHeight=Math.floor(l*100)/100,this.cellWidth=Math.floor(this.cellHeight*this.cellAspectRatio*100)/100):(this.cellWidth=Math.floor(n*100)/100,this.cellHeight=Math.floor(this.cellWidth/this.cellAspectRatio*100)/100);let o=14,h=12;this.fontSize=Math.floor(this.cellHeight/o*h*100)/100}else this.cols=Math.floor(e/this.cellWidth),this.rows=Math.floor(t/this.cellHeight);let i=this.cols*this.cellWidth,s=this.rows*this.cellHeight;this.offsetX=Math.floor((e-i)/2),this.offsetY=Math.floor((t-s)/2);let r=window.devicePixelRatio||1;this.canvas.style.width=`${e}px`,this.canvas.style.height=`${t}px`,this.canvas.width=e*r,this.canvas.height=t*r,this.ctx.scale(r,r)}createEmptyGrid(){let e=[];for(let t=0;t<this.rows;t++){let i=[];for(let s=0;s<this.cols;s++)i.push({char:" ",fgColor:this.defaultFgColor,bgColor:this.defaultBgColor});e.push(i)}return e}enableAutoResize(){this.resizeObserver=new ResizeObserver(()=>{let e=this.cols,t=this.rows;if(this.calculateGridSize(),this.cols!==e||this.rows!==t){let i=this.cells;this.cells=this.createEmptyGrid();let s=Math.min(e,this.cols),r=Math.min(t,this.rows);for(let n=0;n<r;n++)for(let l=0;l<s;l++)this.cells[n][l]=i[n][l]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(e,t,i,s,r){if(t<0||t>=this.rows||e<0||e>=this.cols)return;let n=i&&typeof i=="string"?i.charAt(0):" ";this.cells[t][e]={char:n,fgColor:s??this.defaultFgColor,bgColor:r??this.defaultBgColor}}getCell(e,t){return t<0||t>=this.rows||e<0||e>=this.cols?null:this.cells[t][e]}write(e,t,i,s,r){for(let n=0;n<i.length;n++)this.setCell(e+n,t,i[n],s,r)}fillRect(e,t,i,s,r=" ",n,l){for(let o=t;o<t+s;o++)for(let h=e;h<e+i;h++)this.setCell(h,o,r,n,l)}clear(){this.cells=this.createEmptyGrid()}setFromArray(e){let t=e.width*e.height;if(e.cells.length!==t)throw new Error(`Invalid array length: expected ${t} (${e.width}\xD7${e.height}), got ${e.cells.length}`);let i=0;for(let s=0;s<e.height;s++)for(let r=0;r<e.width;r++){let n=e.cells[i];s<this.rows&&r<this.cols&&this.setCell(r,s,n.char,n.fgColor,n.bgColor),i++}}render(){if(this.fontType==="bitmap"&&this.bitmapFont&&this.useImageDataRendering){this.renderWithImageData();return}this.renderClassic()}renderWithImageData(){if(!this.bitmapFont)return;let e=this.cols*this.bitmapCharWidth,t=this.rows*this.bitmapCharHeight;(!this.imageDataBuffer||this.imageDataBuffer.width!==e||this.imageDataBuffer.height!==t)&&(this.imageDataBuffer=this.ctx.createImageData(e,t));let i=this.imageDataBuffer.data;for(let o=0;o<this.rows;o++)for(let h=0;h<this.cols;h++){let c=this.cells[o][h],d=this.parseColorToRGB(c.bgColor),f=this.parseColorToRGB(c.fgColor),g=c.char.charCodeAt(0),u=this.bitmapFont.get(g);for(let m=0;m<this.bitmapCharHeight;m++)for(let p=0;p<this.bitmapCharWidth;p++){let x=h*this.bitmapCharWidth+p,b=((o*this.bitmapCharHeight+m)*e+x)*4,C=!1;if(u&&m<u.length){let R=u[m],v=1<<7-p;C=(R&v)!==0}C?(i[b]=f.r,i[b+1]=f.g,i[b+2]=f.b,i[b+3]=f.a):(i[b]=d.r,i[b+1]=d.g,i[b+2]=d.b,i[b+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=e,s.height=t,s.getContext("2d").putImageData(this.imageDataBuffer,0,0);let n=this.cols*this.cellWidth,l=this.rows*this.cellHeight;this.ctx.drawImage(s,0,0,e,t,this.offsetX,this.offsetY,n,l),this.showDebugGrid&&this.drawDebugGrid()}parseColorToRGB(e){let t=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/.exec(e);if(t)return{r:parseInt(t[1],10),g:parseInt(t[2],10),b:parseInt(t[3],10),a:t[4]?Math.round(parseFloat(t[4])*255):255};if(e.startsWith("#")){let r=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;e=e.replace(r,(l,o,h,c)=>o+o+h+h+c+c);let n=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);if(n)return{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[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]}[e.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2],a:e==="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.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 e=0;e<this.rows;e++)for(let t=0;t<this.cols;t++){let i=this.cells[e][t],s=Math.floor(this.offsetX+t*this.cellWidth),r=Math.floor(this.offsetY+e*this.cellHeight),n=Math.floor(this.offsetX+(t+1)*this.cellWidth),l=Math.floor(this.offsetY+(e+1)*this.cellHeight),o=n-s,h=l-r;if((this.canvasBgColor!==null||i.bgColor!==this.defaultBgColor)&&(this.ctx.fillStyle=i.bgColor,this.ctx.fillRect(s,r,o,h)),i.char!==" ")if(this.fontType==="bitmap"&&this.bitmapFont)this.drawBitmapChar(i.char,s,r,o,h,i.fgColor);else{this.ctx.fillStyle=i.fgColor;let d=s+(o-this.ctx.measureText(i.char).width)/2,f=r+(h-this.fontSize)/2;this.ctx.fillText(i.char,d,f)}}this.showDebugGrid&&this.drawDebugGrid()}drawBitmapChar(e,t,i,s,r,n){let l=e.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,l,t,i,s,r,n);return}if(!this.bitmapFont)return;let o=this.bitmapFont.get(l);if(!o)return;let h=s/this.bitmapCharWidth,c=r/this.bitmapCharHeight;this.ctx.fillStyle=n;for(let d=0;d<Math.min(o.length,this.bitmapCharHeight);d++){let f=o[d],g=i+d*c,u=i+(d+1)*c;for(let m=0;m<this.bitmapCharWidth;m++){let p=1<<7-m;if(f&p){let x=t+m*h,T=t+(m+1)*h;this.ctx.fillRect(x,g,T-x,u-g)}}}}drawDebugGrid(){if(!this.gridOverlay)return;let e=this.parentElement.clientWidth||800,t=this.parentElement.clientHeight||600;this.gridOverlay.update(this.cols,this.rows,this.cellWidth,this.cellHeight,e,t,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}getOffsets(){return{offsetX:this.offsetX,offsetY:this.offsetY}}setDebugGrid(e){this.showDebugGrid=e,e&&!this.gridOverlay?(this.gridOverlay=new w(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,innerPadding:1,zIndex:10}),this.drawDebugGrid()):!e&&this.gridOverlay?(this.gridOverlay.destroy(),this.gridOverlay=void 0):e&&this.gridOverlay&&this.gridOverlay.setVisible(!0)}setCanvasBackgroundColor(e){this.canvasBgColor=e}getCanvasBackgroundColor(){return this.canvasBgColor}setFixedGrid(e,t,i){this.fixedGridMode=!0,this.fixedCols=e,this.fixedRows=t,i!==void 0&&(this.cellAspectRatio=i);let s=this.cols,r=this.rows,n=this.cells;if(this.calculateGridSize(),this.cols!==s||this.rows!==r){this.cells=this.createEmptyGrid();let l=Math.min(s,this.cols),o=Math.min(r,this.rows);for(let h=0;h<o;h++)for(let c=0;c<l;c++)this.cells[h][c]=n[h][c]}this.render()}setAdaptiveGrid(e,t){this.fixedGridMode=!1,this.fixedCols=void 0,this.fixedRows=void 0,e!==void 0&&(this.cellWidth=e),t!==void 0&&(this.cellHeight=t);let i=this.cols,s=this.rows,r=this.cells;if(this.calculateGridSize(),this.cols!==i||this.rows!==s){this.cells=this.createEmptyGrid();let n=Math.min(i,this.cols),l=Math.min(s,this.rows);for(let o=0;o<l;o++)for(let h=0;h<n;h++)this.cells[o][h]=r[o][h]}this.render()}isFixedGridMode(){return this.fixedGridMode}setDebugGridColor(e){this.debugGridColor=e}isDebugGridEnabled(){return this.showDebugGrid}setImageDataRendering(e){this.useImageDataRendering=e,e&&this.fontType==="bitmap"?console.warn("[Render] ImageData rendering enabled (optimized for benchmarks)"):e&&(console.warn("[Render] ImageData rendering requires bitmap font, keeping classic mode"),this.useImageDataRendering=!1)}isImageDataRenderingEnabled(){return this.useImageDataRendering}setWebFont(e,t){this.fontType="web",this.fontFamily=e,t!==void 0&&(this.fontSize=t),this.bitmapFont=void 0,this.bitmapAtlas=void 0,this.useImageDataRendering=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid()}setBitmapFont(e,t,i,s,r){this.fontType="bitmap",this.bitmapFont=e,this.bitmapCharWidth=t,this.bitmapCharHeight=i,this.bitmapAtlas=new B(e,t,i,s,r),this.cellWidth=s,this.cellHeight=r,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(e){this.paletteCache=e}renderDisplayData(e){if(!e||!e.cells||e.cells.length===0){console.warn("[Terminal2D] Empty display data");return}if(e.width===0||e.height===0){console.warn("[Terminal2D] Invalid display dimensions:",e.width,e.height);return}(e.width!==this.cols||e.height!==this.rows)&&this.setFixedGrid(e.width,e.height,this.cellAspectRatio);let t=this.paletteCache??e.palette;if(!t||t.length===0){console.error("[Terminal2D] No palette available (neither cached nor in display)");return}let i=A(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>=t.length)return console.warn(`[Terminal2D] Invalid palette index: ${s}`),this.defaultFgColor;let r=t[s];return!r||typeof r.r!="number"?(console.warn(`[Terminal2D] Corrupted palette entry at index ${s}:`,r),this.defaultFgColor):`rgba(${r.r}, ${r.g}, ${r.b}, ${r.a/255})`},"convertColor");for(let s=0;s<e.height&&s<this.rows;s++)for(let r=0;r<e.width&&r<this.cols;r++){let n=s*e.width+r;if(n>=e.cells.length)break;let l=e.cells[n];if(!l)continue;let o=i(l.fgColorIndex),h=i(l.bgColorIndex);this.setCell(r,s,l.char??" ",o,h)}this.render()}isReady(){return!0}getCols(){return this.cols}getRows(){return this.rows}resize(e,t){this.setFixedGrid(e,t)}destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=void 0),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}};A(G,"Terminal2D");var _=G;var re="0.1.0";export{B as BitmapFontAtlas,F as DEFAULT_PALETTE,w as GridOverlay,_ as Terminal2D,D as TerminalGL,N as colorToPaletteIndex,z as paletteIndexToColor,re as version};
105
+ `,r=this.compileShader(t.VERTEX_SHADER,e),s=this.compileShader(t.FRAGMENT_SHADER,i);if(!r||!s)throw new Error("Shader compilation error");let n=t.createProgram();if(!n)throw new Error("Unable to create WebGL program");if(t.attachShader(n,r),t.attachShader(n,s),t.linkProgram(n),!t.getProgramParameter(n,t.LINK_STATUS)){let l=t.getProgramInfoLog(n);throw new Error("Program linking error: "+l)}this.program=n,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=t.getAttribLocation(n,"aPosition"),this.useInstancing?(this.aTexCoord=t.getAttribLocation(n,"aInstanceOffset"),this.aColorIndex=t.getAttribLocation(n,"aInstanceUVs"),this.instanceDataBuffer=t.createBuffer()):(this.aTexCoord=t.getAttribLocation(n,"aTexCoord"),this.aColorIndex=t.getAttribLocation(n,"aColorIndex")),this.uResolution=t.getUniformLocation(n,"uResolution"),this.uTexture=t.getUniformLocation(n,"uTexture"),this.uPalette=t.getUniformLocation(n,"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,r=i.createShader(t);return r?(i.shaderSource(r,e),i.compileShader(r),i.getShaderParameter(r,i.COMPILE_STATUS)?r:(console.error("Shader compilation error:",i.getShaderInfoLog(r)),i.deleteShader(r),null)):null}initGridOverlay(){this.gridOverlay=new y(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,innerPadding:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let t=parseFloat(this.canvas.style.width)||this.cols*this.charWidth,e=parseFloat(this.canvas.style.height)||this.rows*this.charHeight,i=t/this.cols,r=e/this.rows;this.gridOverlay.update(this.cols,this.rows,i,r,t,e,0,0)}setBitmapFont(t,e,i,r,s){this.bitmapFont=t,this.charWidth=Math.round(e),this.charHeight=Math.round(i),this.cellWidth=Math.round(r),this.cellHeight=Math.round(s),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(n){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",n),n}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()}generateAtlas(){if(!this.bitmapFont)return;let t=Array.from(this.bitmapFont.keys()).sort((o,h)=>o-h),e=t.length;this.atlasColumns=Math.ceil(Math.sqrt(e));let i=Math.ceil(e/this.atlasColumns),r=this.atlasColumns*this.charWidth,s=i*this.charHeight;this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=r,this.atlasCanvas.height=s;let n=this.atlasCanvas.getContext("2d");if(!n)throw new Error("Unable to create 2D context for atlas");n.clearRect(0,0,r,s),n.fillStyle="#ffffff";let l=0;for(let o of t){let h=this.bitmapFont.get(o);if(!h)continue;let c=l%this.atlasColumns,d=Math.floor(l/this.atlasColumns),f=c*this.charWidth,g=d*this.charHeight;for(let u=0;u<Math.min(h.length,this.charHeight);u++){let m=h[u];for(let p=0;p<this.charWidth;p++){let x=1<<7-p;m&x&&n.fillRect(f+p,g+u,1,1)}}l++}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,r=.5/e,s=.5/i;for(let n=0;n<t;n++){let l=n%this.atlasColumns,o=Math.floor(n/this.atlasColumns),h=(l*this.charWidth+r)/e,c=(o*this.charHeight+s)/i,d=((l+1)*this.charWidth-r)/e,f=((o+1)*this.charHeight-s)/i,g=n*4;this.atlasUVs[g]=h,this.atlasUVs[g+1]=c,this.atlasUVs[g+2]=d,this.atlasUVs[g+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,r=0,s=0;return e.length===3?(i=parseInt(e[0]+e[0],16),r=parseInt(e[1]+e[1],16),s=parseInt(e[2]+e[2],16)):e.length===6&&(i=parseInt(e.slice(0,2),16),r=parseInt(e.slice(2,4),16),s=parseInt(e.slice(4,6),16)),[i/255,r/255,s/255,1]}if(t.startsWith("rgb")){let e=t.match(/rgba?\(([^)]+)\)/);if(e){let i=e[1].split(",").map(r=>parseFloat(r.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=Math.floor(t/this.cellWidth),r=Math.floor(e/this.cellHeight),s=i/this.cols,n=r/this.rows,l=Math.min(s,n),o=Math.max(1,Math.floor(l)),h=this.cols*this.cellWidth*o,c=this.rows*this.cellHeight*o;this.canvas.style.width=`${h}px`,this.canvas.style.height=`${c}px`,this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}setPalette(t){let e=0;for(let i=0;i<Math.min(t.length,256);i++){let r=t[i];e=(e<<5)-e+r.r,e=(e<<5)-e+r.g,e=(e<<5)-e+r.b,e=(e<<5)-e+r.a,e=e|0}if(e!==this.paletteHash){this.paletteHash=e;for(let i=0;i<t.length&&i<256;i++){let r=t[i],s=i*4;this.paletteFloat[s]=r.r/255,this.paletteFloat[s+1]=r.g/255,this.paletteFloat[s+2]=r.b/255,this.paletteFloat[s+3]=r.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 r=i*4;e[r]=this.paletteFloat[r]*255,e[r+1]=this.paletteFloat[r+1]*255,e[r+2]=this.paletteFloat[r+2]*255,e[r+3]=this.paletteFloat[r+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)}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.useInstancing=!1,this.renderDirectBuffers(t);return}let r=t.width*t.height;if(this.useUint16Indices&&r>8191){console.warn(`[TerminalGL] \u26A0\uFE0F Terminal too large for instanced rendering with Uint16 (${r} cells > 8191). Falling back to standard rendering.`),this.useInstancing=!1,this.renderDirectBuffers(t);return}let s=0,n=this.instanceData.length/8;for(let f=0;f<t.height;f++)for(let g=0;g<t.width;g++){let u=t.cells[f*t.width+g],m=u.bgColorIndex,p=u.fgColorIndex,x=this.canvasBgColor!==null&&m===255,A=u.char===" "||p===255;if(!x){if(s>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${n}`);break}let b=s*8;this.instanceData[b]=g,this.instanceData[b+1]=f,this.instanceData[b+2]=0,this.instanceData[b+3]=0,this.instanceData[b+4]=0,this.instanceData[b+5]=0,this.instanceData[b+6]=m,this.instanceData[b+7]=0,s++}if(!A){let b=u.char.charCodeAt(0),C=this.charCodeToAtlasIndex[b];if(C!==65535){if(s>=n){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${n}`);break}let R=C*4,v=s*8;this.instanceData[v]=g,this.instanceData[v+1]=f,this.instanceData[v+2]=this.atlasUVs[R],this.instanceData[v+3]=this.atlasUVs[R+1],this.instanceData[v+4]=this.atlasUVs[R+2],this.instanceData[v+5]=this.atlasUVs[R+3],this.instanceData[v+6]=0,this.instanceData[v+7]=p,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 l=8*Float32Array.BYTES_PER_ELEMENT,o=e.getAttribLocation(this.program,"aInstanceOffset");e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,l,0),i.vertexAttribDivisorANGLE(o,1);let h=e.getAttribLocation(this.program,"aInstanceUVs");e.enableVertexAttribArray(h),e.vertexAttribPointer(h,4,e.FLOAT,!1,l,2*Float32Array.BYTES_PER_ELEMENT),i.vertexAttribDivisorANGLE(h,1);let c=e.getAttribLocation(this.program,"aInstanceColors");e.enableVertexAttribArray(c),e.vertexAttribPointer(c,2,e.FLOAT,!1,l,6*Float32Array.BYTES_PER_ELEMENT),i.vertexAttribDivisorANGLE(c,1),e.uniform2f(this.uResolution,this.canvas.width,this.canvas.height);let d=e.getUniformLocation(this.program,"uCellSize");e.uniform2f(d,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(o,0),i.vertexAttribDivisorANGLE(h,0),i.vertexAttribDivisorANGLE(c,0)}renderDirectBuffers(t){let e=this.gl,i=t.width*t.height,r=i*2;if(r>this.maxCells){console.error(`[TerminalGL] \u274C Buffer overflow detected! Trying to render ${r} quads but buffer capacity is ${this.maxCells}. This should not happen - resize() should have reallocated.`);return}let s=0,n=0,l=t.cells,o=i;for(let u=0;u<o;u++){let m=l[u],p=m.bgColorIndex,A=this.canvasBgColor!==null&&p===255?255:p,b=0;for(let v=0;v<4;v++)this.renderTexCoords[s++]=b,this.renderTexCoords[s++]=b,this.renderColorIndices[n++]=A;let C=m.fgColorIndex,R=m.char;if(R===" "||C===255)for(let v=0;v<4;v++)this.renderTexCoords[s++]=0,this.renderTexCoords[s++]=0,this.renderColorIndices[n++]=255;else{let v=R.charCodeAt(0),S=this.charCodeToAtlasIndex[v];if(S!==65535){let w=S*4,W=this.atlasUVs[w],H=this.atlasUVs[w+1],O=this.atlasUVs[w+2],z=this.atlasUVs[w+3];this.renderTexCoords[s++]=W,this.renderTexCoords[s++]=H,this.renderColorIndices[n++]=C,this.renderTexCoords[s++]=O,this.renderTexCoords[s++]=H,this.renderColorIndices[n++]=C,this.renderTexCoords[s++]=W,this.renderTexCoords[s++]=z,this.renderColorIndices[n++]=C,this.renderTexCoords[s++]=O,this.renderTexCoords[s++]=z,this.renderColorIndices[n++]=C}else for(let w=0;w<4;w++)this.renderTexCoords[s++]=0,this.renderTexCoords[s++]=0,this.renderColorIndices[n++]=255}}(s!==o*2*4*2||n!==o*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:s,colorIdx:n,expected:o*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,s)),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,n))):(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,s)),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,n)),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,g=this.useUint16Indices?e.UNSIGNED_SHORT:e.UNSIGNED_INT;e.drawElements(e.TRIANGLES,f,g,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,r=this.useUint16Indices?8191:262144;if(i>r){let c=Math.floor(Math.sqrt(r));console.error(`[TerminalGL] \u274C Cannot resize to ${t}\xD7${e} (${i} cells). Device limit: ${r} cells (max ~${c}\xD7${c}). ${this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let s=I.checkCompatibility();i>s.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${t}\xD7${e} (${i} cells) exceeds recommended limit (${s.recommendedMaxCells} cells). Performance may degrade.`),this.cols=t,this.rows=e,this.staticPositionsInitialized=!1;let n=this.cols*this.rows*2,l=Math.ceil(n*1.5),o=n>this.maxCells,h=this.maxCells>l*4;if(o||h){let c=this.maxCells;this.maxCells=l,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);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),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=o?"\u{1F4C8} Growing":"\u{1F4C9} Shrinking",g=c*160/1048576,u=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${f} buffers: ${g.toFixed(2)}MB \u2192 ${u.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.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}getCols(){return this.cols}getRows(){return this.rows}isReady(){return!!(this.bitmapFont&&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.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)}};E(I,"TerminalGL");var U=I;var L=class L{constructor(t,e,i,r,s){a(this,"atlases");a(this,"charMap");a(this,"baseCharWidth");a(this,"baseCharHeight");a(this,"baseCellWidth");a(this,"baseCellHeight");a(this,"atlasColumns",16);a(this,"font");a(this,"SCALES",[1,2,4,8]);a(this,"colorCache",new Map);a(this,"MAX_CACHE_SIZE",512);this.font=t,this.baseCharWidth=e,this.baseCharHeight=i,this.baseCellWidth=r??e,this.baseCellHeight=s??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 r=t%this.atlasColumns,s=Math.floor(t/this.atlasColumns);this.charMap.set(e,{x:r*this.baseCharWidth,y:s*this.baseCharHeight});for(let n of this.SCALES){let l=this.getOrCreateAtlas(n),o=r*l.charWidth,h=s*l.charHeight;this.renderBitmapToAtlas(l,i,o,h)}t++}}getOrCreateAtlas(t){let e=this.atlases.get(t);if(!e){let i=this.baseCharWidth*t,r=this.baseCharHeight*t,n=Math.ceil(256/this.atlasColumns),l=document.createElement("canvas");l.width=this.atlasColumns*i,l.height=n*r;let o=l.getContext("2d",{alpha:!0,willReadFrequently:!1});if(!o)throw new Error(`Impossible de cr\xE9er le contexte 2D pour l'atlas ${t}x`);o.imageSmoothingEnabled=!1,e={canvas:l,ctx:o,scale:t,charWidth:i,charHeight:r},this.atlases.set(t,e)}return e}renderBitmapToAtlas(t,e,i,r){let s=t.scale,n=t.ctx;n.fillStyle="#ffffff";for(let l=0;l<Math.min(e.length,this.baseCharHeight);l++){let o=e[l];for(let h=0;h<this.baseCharWidth;h++){let c=1<<7-h;o&c&&n.fillRect(i+h*s,r+l*s,s,s)}}}drawChar(t,e,i,r,s,n,l){let o=this.charMap.get(e);if(!o)return;let h=`${e}:${l}`,c=this.colorCache.get(h);if(c)c.lastUsed=performance.now();else{let x=this.createColoredGlyph(e,l,o);if(!x)return;c={canvas:x,lastUsed:performance.now()},this.colorCache.set(h,c),this.colorCache.size>this.MAX_CACHE_SIZE&&this.evictLRU()}let d=s/this.baseCellWidth,f=n/this.baseCellHeight,g=(this.baseCellWidth-this.baseCharWidth)/2*d,u=(this.baseCellHeight-this.baseCharHeight)/2*f,m=this.baseCharWidth*d,p=this.baseCharHeight*f;t.drawImage(c.canvas,i+g,r+u,m,p)}createColoredGlyph(t,e,i){let r=this.atlases.get(1);if(!r)return null;let s=r.ctx.getImageData(i.x,i.y,this.baseCharWidth,this.baseCharHeight),n=s.data,l=this.hexToRgb(e);for(let c=0;c<n.length;c+=4)n[c+3]>0&&(n[c]=l.r,n[c+1]=l.g,n[c+2]=l.b);let o=document.createElement("canvas");o.width=this.baseCharWidth,o.height=this.baseCharHeight;let h=o.getContext("2d",{alpha:!0});return h?(h.imageSmoothingEnabled=!1,h.putImageData(s,0,0),o):null}hexToRgb(t){if(t.startsWith("#")){let s=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(s,(l,o,h,c)=>o+o+h+h+c+c);let n=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return n?{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[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 r={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 r?{r:r[0],g:r[1],b:r[2]}:{r:255,g:255,b:255}}evictLRU(){let t=null,e=1/0;for(let[i,r]of this.colorCache)r.lastUsed<e&&(e=r.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()}};E(L,"BitmapFontAtlas");var B=L;var _=class _{constructor(t,e={}){a(this,"canvas");a(this,"ctx");a(this,"parentElement");a(this,"cells");a(this,"cols",0);a(this,"rows",0);a(this,"fontSize");a(this,"fontFamily");a(this,"defaultFgColor");a(this,"defaultBgColor");a(this,"canvasBgColor");a(this,"cellWidth");a(this,"cellHeight");a(this,"offsetX",0);a(this,"offsetY",0);a(this,"fontType","web");a(this,"bitmapFont");a(this,"bitmapAtlas");a(this,"bitmapCharWidth",8);a(this,"bitmapCharHeight",8);a(this,"showDebugGrid");a(this,"debugGridColor");a(this,"gridOverlay");a(this,"fixedGridMode");a(this,"fixedCols");a(this,"fixedRows");a(this,"cellAspectRatio");a(this,"resizeObserver");a(this,"imageDataBuffer");a(this,"useImageDataRendering",!1);a(this,"paletteCache");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??10/14,this.cellWidth=e.cellWidth??10,this.cellHeight=e.cellHeight??14,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.canvas=document.createElement("canvas"),e.className&&(this.canvas.className=e.className),e.style&&Object.assign(this.canvas.style,e.style),this.canvas.style.imageRendering="auto",this.parentElement.appendChild(this.canvas);let i=this.canvas.getContext("2d",{alpha:!0,desynchronized:!1});if(!i)throw new Error("UTSPRender: Impossible d'obtenir le contexte 2D du canvas");this.ctx=i,this.calculateGridSize(),this.cells=this.createEmptyGrid(),this.showDebugGrid&&(this.gridOverlay=new y(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,innerPadding:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;if(this.fixedGridMode&&this.fixedCols&&this.fixedRows)if(this.cols=this.fixedCols,this.rows=this.fixedRows,this.fontType==="bitmap"){let n=t/this.cols,l=e/this.rows,o=this.bitmapCharWidth/this.bitmapCharHeight;n/l>o?(this.cellHeight=Math.floor(l),this.cellWidth=Math.floor(this.cellHeight*o)):(this.cellWidth=Math.floor(n),this.cellHeight=Math.floor(this.cellWidth/o))}else{let n=t/this.cols,l=e/this.rows;n/l>this.cellAspectRatio?(this.cellHeight=Math.floor(l*100)/100,this.cellWidth=Math.floor(this.cellHeight*this.cellAspectRatio*100)/100):(this.cellWidth=Math.floor(n*100)/100,this.cellHeight=Math.floor(this.cellWidth/this.cellAspectRatio*100)/100);let o=14,h=12;this.fontSize=Math.floor(this.cellHeight/o*h*100)/100}else this.cols=Math.floor(t/this.cellWidth),this.rows=Math.floor(e/this.cellHeight);let i=this.cols*this.cellWidth,r=this.rows*this.cellHeight;this.offsetX=Math.floor((t-i)/2),this.offsetY=Math.floor((e-r)/2);let s=window.devicePixelRatio||1;this.canvas.style.width=`${t}px`,this.canvas.style.height=`${e}px`,this.canvas.width=t*s,this.canvas.height=e*s,this.ctx.scale(s,s)}createEmptyGrid(){let t=[];for(let e=0;e<this.rows;e++){let i=[];for(let r=0;r<this.cols;r++)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 r=Math.min(t,this.cols),s=Math.min(e,this.rows);for(let n=0;n<s;n++)for(let l=0;l<r;l++)this.cells[n][l]=i[n][l]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(t,e,i,r,s){if(e<0||e>=this.rows||t<0||t>=this.cols)return;let n=i&&typeof i=="string"?i.charAt(0):" ";this.cells[e][t]={char:n,fgColor:r??this.defaultFgColor,bgColor:s??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,r,s){for(let n=0;n<i.length;n++)this.setCell(t+n,e,i[n],r,s)}fillRect(t,e,i,r,s=" ",n,l){for(let o=e;o<e+r;o++)for(let h=t;h<t+i;h++)this.setCell(h,o,s,n,l)}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 r=0;r<t.height;r++)for(let s=0;s<t.width;s++){let n=t.cells[i];r<this.rows&&s<this.cols&&this.setCell(s,r,n.char,n.fgColor,n.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 o=0;o<this.rows;o++)for(let h=0;h<this.cols;h++){let c=this.cells[o][h],d=this.parseColorToRGB(c.bgColor),f=this.parseColorToRGB(c.fgColor),g=c.char.charCodeAt(0),u=this.bitmapFont.get(g);for(let m=0;m<this.bitmapCharHeight;m++)for(let p=0;p<this.bitmapCharWidth;p++){let x=h*this.bitmapCharWidth+p,b=((o*this.bitmapCharHeight+m)*t+x)*4,C=!1;if(u&&m<u.length){let R=u[m],v=1<<7-p;C=(R&v)!==0}C?(i[b]=f.r,i[b+1]=f.g,i[b+2]=f.b,i[b+3]=f.a):(i[b]=d.r,i[b+1]=d.g,i[b+2]=d.b,i[b+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 r=document.createElement("canvas");r.width=t,r.height=e,r.getContext("2d").putImageData(this.imageDataBuffer,0,0);let n=this.cols*this.cellWidth,l=this.rows*this.cellHeight;this.ctx.drawImage(r,0,0,t,e,this.offsetX,this.offsetY,n,l),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 s=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(s,(l,o,h,c)=>o+o+h+h+c+c);let n=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);if(n)return{r:parseInt(n[1],16),g:parseInt(n[2],16),b:parseInt(n[3],16),a:255}}let r={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 r?{r:r[0],g:r[1],b:r[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.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],r=Math.floor(this.offsetX+e*this.cellWidth),s=Math.floor(this.offsetY+t*this.cellHeight),n=Math.floor(this.offsetX+(e+1)*this.cellWidth),l=Math.floor(this.offsetY+(t+1)*this.cellHeight),o=n-r,h=l-s;if((this.canvasBgColor!==null||i.bgColor!==this.defaultBgColor)&&(this.ctx.fillStyle=i.bgColor,this.ctx.fillRect(r,s,o,h)),i.char!==" ")if(this.fontType==="bitmap"&&this.bitmapFont)this.drawBitmapChar(i.char,r,s,o,h,i.fgColor);else{this.ctx.fillStyle=i.fgColor;let d=r+(o-this.ctx.measureText(i.char).width)/2,f=s+(h-this.fontSize)/2;this.ctx.fillText(i.char,d,f)}}this.showDebugGrid&&this.drawDebugGrid()}drawBitmapChar(t,e,i,r,s,n){let l=t.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,l,e,i,r,s,n);return}if(!this.bitmapFont)return;let o=this.bitmapFont.get(l);if(!o)return;let h=r/this.bitmapCharWidth,c=s/this.bitmapCharHeight;this.ctx.fillStyle=n;for(let d=0;d<Math.min(o.length,this.bitmapCharHeight);d++){let f=o[d],g=i+d*c,u=i+(d+1)*c;for(let m=0;m<this.bitmapCharWidth;m++){let p=1<<7-m;if(f&p){let x=e+m*h,A=e+(m+1)*h;this.ctx.fillRect(x,g,A-x,u-g)}}}}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}getOffsets(){return{offsetX:this.offsetX,offsetY:this.offsetY}}setDebugGrid(t){this.showDebugGrid=t,t&&!this.gridOverlay?(this.gridOverlay=new y(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,innerPadding: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 r=this.cols,s=this.rows,n=this.cells;if(this.calculateGridSize(),this.cols!==r||this.rows!==s){this.cells=this.createEmptyGrid();let l=Math.min(r,this.cols),o=Math.min(s,this.rows);for(let h=0;h<o;h++)for(let c=0;c<l;c++)this.cells[h][c]=n[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,r=this.rows,s=this.cells;if(this.calculateGridSize(),this.cols!==i||this.rows!==r){this.cells=this.createEmptyGrid();let n=Math.min(i,this.cols),l=Math.min(r,this.rows);for(let o=0;o<l;o++)for(let h=0;h<n;h++)this.cells[o][h]=s[o][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,r,s){this.fontType="bitmap",this.bitmapFont=t,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.bitmapAtlas=new B(t,e,i,r,s),this.cellWidth=r,this.cellHeight=s,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=E(r=>{if(r==null||isNaN(r))return console.warn("[Terminal2D] Invalid palette index (undefined/null/NaN):",r),this.defaultFgColor;if(r===255)return"rgba(0, 0, 0, 0)";if(r<0||r>=e.length)return console.warn(`[Terminal2D] Invalid palette index: ${r}`),this.defaultFgColor;let s=e[r];return!s||typeof s.r!="number"?(console.warn(`[Terminal2D] Corrupted palette entry at index ${r}:`,s),this.defaultFgColor):`rgba(${s.r}, ${s.g}, ${s.b}, ${s.a/255})`},"convertColor");for(let r=0;r<t.height&&r<this.rows;r++)for(let s=0;s<t.width&&s<this.cols;s++){let n=r*t.width+s;if(n>=t.cells.length)break;let l=t.cells[n];if(!l)continue;let o=i(l.fgColorIndex),h=i(l.bgColorIndex);this.setCell(s,r,l.char??" ",o,h)}this.render()}isReady(){return!0}getCols(){return this.cols}getRows(){return this.rows}resize(t,e){this.setFixedGrid(t,e)}destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=void 0),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}};E(_,"Terminal2D");var M=_;var P=class P{constructor(t,e={}){a(this,"container");a(this,"overlayDiv",null);a(this,"button",null);a(this,"options");a(this,"started",!1);a(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=`
106
+ position: absolute !important;
107
+ top: 0 !important;
108
+ left: 0 !important;
109
+ width: 100% !important;
110
+ height: 100% !important;
111
+ background-color: ${this.options.backgroundColor} !important;
112
+ display: flex !important;
113
+ justify-content: center !important;
114
+ align-items: center !important;
115
+ z-index: ${this.options.zIndex} !important;
116
+ cursor: pointer !important;
117
+ `,this.button=document.createElement("button"),this.button.className="utsp-autoplay-button",this.button.textContent=this.options.buttonText,this.button.style.cssText=`
118
+ padding: 16px 32px !important;
119
+ font-size: 18px !important;
120
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif !important;
121
+ font-weight: 600 !important;
122
+ color: ${this.options.buttonTextColor} !important;
123
+ background-color: ${this.options.buttonColor} !important;
124
+ border: none !important;
125
+ border-radius: 8px !important;
126
+ cursor: pointer !important;
127
+ transition: background-color 0.2s ease, transform 0.1s ease !important;
128
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
129
+ `,this.button.addEventListener("mouseenter",()=>{this.button&&(this.button.style.backgroundColor=`${this.options.buttonHoverColor} !important`,this.button.style.transform="scale(1.05)")}),this.button.addEventListener("mouseleave",()=>{this.button&&(this.button.style.backgroundColor=`${this.options.buttonColor} !important`,this.button.style.transform="scale(1)")}),this.button.addEventListener("click",e=>{e.stopPropagation(),this.start()}),this.overlayDiv.addEventListener("click",()=>{this.start()}),this.overlayDiv.appendChild(this.button),this.container.appendChild(this.overlayDiv)}start(){this.started||(this.started=!0,this.overlayDiv&&(this.overlayDiv.style.transition="opacity 0.3s ease",this.overlayDiv.style.opacity="0",setTimeout(()=>{this.removeOverlay()},300)),this.onStartCallback&&this.onStartCallback())}isStarted(){return this.started}isVisible(){return this.overlayDiv!==null&&!this.started}removeOverlay(){this.overlayDiv&&this.overlayDiv.parentElement&&this.overlayDiv.parentElement.removeChild(this.overlayDiv),this.overlayDiv=null,this.button=null}setButtonText(t){this.options.buttonText=t,this.button&&(this.button.textContent=t)}setOnStart(t){this.onStartCallback=t}destroy(){this.removeOverlay(),this.started=!1}};E(P,"AutoplayOverlay");var G=P;var lt="0.1.0";export{G as AutoplayOverlay,B as BitmapFontAtlas,F as DEFAULT_PALETTE,y as GridOverlay,M as Terminal2D,U as TerminalGL,k as colorToPaletteIndex,N as paletteIndexToColor,lt as version};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utsp/render",
3
- "version": "0.2.0-nightly.20251129171929.16a5bbd",
3
+ "version": "0.3.0-nightly.20251201155650.4e6ade1",
4
4
  "description": "UTSP Render - Browser-based rendering engine for terminal graphics",
5
5
  "author": "THP Software",
6
6
  "license": "MIT",
@@ -49,7 +49,7 @@
49
49
  "access": "public"
50
50
  },
51
51
  "dependencies": {
52
- "@utsp/types": "0.2.0-nightly.20251129171929.16a5bbd"
52
+ "@utsp/types": "0.3.0-nightly.20251201155650.4e6ade1"
53
53
  },
54
54
  "devDependencies": {
55
55
  "typescript": "^5.6.3"