@utsp/render 0.7.0-nightly.20251207021518.b0c5521 → 0.7.0

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,29 +1,38 @@
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=`
1
+ "use strict";var D=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var Z=Object.prototype.hasOwnProperty;var K=(v,t,e)=>t in v?D(v,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):v[t]=e;var E=(v,t)=>D(v,"name",{value:t,configurable:!0});var J=(v,t)=>{for(var e in t)D(v,e,{get:t[e],enumerable:!0})},tt=(v,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Q(t))!Z.call(v,i)&&i!==e&&D(v,i,{get:()=>t[i],enumerable:!(s=j(t,i))||s.enumerable});return v};var et=v=>tt(D({},"__esModule",{value:!0}),v);var n=(v,t,e)=>(K(v,typeof t!="symbol"?t+"":t,e),e);var st={};J(st,{AutoplayOverlay:()=>_,BitmapFontAtlas:()=>B,DEFAULT_PALETTE:()=>U,GridOverlay:()=>T,PostProcessOverlay:()=>G,ScalingMode:()=>y.ScalingMode,Terminal2D:()=>L,TerminalGL:()=>M,colorToPaletteIndex:()=>q,paletteIndexToColor:()=>X,version:()=>it});module.exports=et(st);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 X(v,t=U){return v<0||v>=t.length?"#ff00ff":t[v]}E(X,"paletteIndexToColor");function q(v,t=U){let e=t.indexOf(v.toLowerCase());return e>=0?e:0}E(q,"colorToPaletteIndex");var W=class W{constructor(t,e){n(this,"canvas");n(this,"ctx");n(this,"container");n(this,"cols",0);n(this,"rows",0);n(this,"cellWidth",0);n(this,"cellHeight",0);n(this,"offsetX",0);n(this,"offsetY",0);n(this,"strokeColor","rgba(80, 80, 80, 0.4)");n(this,"lineWidth",1);this.container=t,this.canvas=document.createElement("canvas"),this.canvas.className="grid-overlay-canvas";let s=e?.zIndex??10;this.canvas.style.cssText=`
2
+ display: block !important;
2
3
  position: absolute !important;
3
- top: 0 !important;
4
- left: 0 !important;
5
- width: 100% !important;
6
- height: 100% !important;
7
- object-fit: contain !important;
8
- z-index: ${r} !important;
9
4
  pointer-events: none !important;
10
5
  image-rendering: pixelated !important;
11
6
  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,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=`
7
+ z-index: ${s} !important;
8
+ `,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))}setDimensions(t,e,s,i,r=0,a=0){this.cols=t,this.rows=e,this.cellWidth=s,this.cellHeight=i,this.offsetX=r,this.offsetY=a}setCanvasSize(t,e){this.canvas.width=t,this.canvas.height=e,this.ctx.setTransform(1,0,0,1,0,0)}setStyle(t){t.strokeColor&&(this.strokeColor=t.strokeColor),t.lineWidth!==void 0&&(this.lineWidth=t.lineWidth)}setTransform(t,e,s,i,r){let a=i.left-r.left,l=i.top-r.top,o=i.width,h=i.height;(this.canvas.width!==o||this.canvas.height!==h)&&(this.canvas.width=o,this.canvas.height=h);let c=this.canvas.style;c.width=`${o}px`,c.height=`${h}px`,c.left=`${a}px`,c.top=`${l}px`}render(){if(!this.ctx)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,s=t>0?this.canvas.width/t:1,i=e>0?this.canvas.height/e:1,r=Math.min(s,i),a=this.cellWidth*r,l=this.cellHeight*r,o=this.cols*a,h=this.rows*l,c=this.offsetX*r,d=this.offsetY*r;if(!(o===0||h===0)){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.strokeStyle=this.strokeColor,this.ctx.lineWidth=Math.max(1,this.lineWidth*r),this.ctx.beginPath();for(let f=0;f<=this.cols;f++){let u=c+f*a+.5;this.ctx.moveTo(u,d),this.ctx.lineTo(u,d+h)}for(let f=0;f<=this.rows;f++){let u=d+f*l+.5;this.ctx.moveTo(c,u),this.ctx.lineTo(c+o,u)}this.ctx.stroke()}}update(t,e,s,i,r,a,l=0,o=0){this.setDimensions(t,e,s,i,l,o),this.setCanvasSize(r,a),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(W,"GridOverlay");var T=W;var y=require("@utsp/types");var F=class F{constructor(t,e){n(this,"canvas");n(this,"gl");n(this,"parentElement");n(this,"containerDiv");n(this,"cols");n(this,"rows");n(this,"charWidth");n(this,"charHeight");n(this,"cellWidth",8);n(this,"cellHeight",8);n(this,"glyphOffsetX",0);n(this,"glyphOffsetY",0);n(this,"canvasBgColor");n(this,"showGrid");n(this,"supportsUint32Indices",!1);n(this,"useUint16Indices",!1);n(this,"gridOverlay");n(this,"bitmapFont");n(this,"atlasTexture",null);n(this,"atlasCanvas");n(this,"atlasColumns",0);n(this,"paletteTexture",null);n(this,"program",null);n(this,"positionBuffer",null);n(this,"texCoordBuffer",null);n(this,"colorIndexBuffer",null);n(this,"indexBuffer",null);n(this,"aPosition");n(this,"aTexCoord");n(this,"aColorIndex");n(this,"uResolution",null);n(this,"uTexture",null);n(this,"uPalette",null);n(this,"resizeObserver");n(this,"charCodeToAtlasIndex",new Uint16Array(65536).fill(65535));n(this,"atlasUVs",new Float32Array(0));n(this,"cachedAtlasWidth",0);n(this,"cachedAtlasHeight",0);n(this,"paletteFloat",new Float32Array(256*4));n(this,"maxCells",0);n(this,"renderPositions",new Float32Array(0));n(this,"renderTexCoords",new Float32Array(0));n(this,"renderColorIndices",new Float32Array(0));n(this,"renderIndices",new Uint32Array(0));n(this,"cachedResolution",[0,0]);n(this,"cachedTextureUnit",-1);n(this,"cachedPaletteUnit",-1);n(this,"cachedTextureUniform",!1);n(this,"cachedPaletteUniform",!1);n(this,"paletteHash",0);n(this,"currentScale",1);n(this,"scalingMode",y.ScalingMode.None);n(this,"ambientEffectEnabled",!1);n(this,"ambientEffectCanvas",null);n(this,"ambientEffectCtx",null);n(this,"ambientEffectBlur",y.POST_PROCESS_DEFAULTS.ambientEffect.blur);n(this,"ambientEffectScale",y.POST_PROCESS_DEFAULTS.ambientEffect.scale);n(this,"ambientEffectOpacity",.7);n(this,"onResizeCallback");n(this,"staticPositionsInitialized",!1);n(this,"vaoExtension",null);n(this,"vao",null);n(this,"instancedExtension",null);n(this,"useInstancing",!1);n(this,"instanceDataBuffer",null);n(this,"instanceData",new Float32Array(0));n(this,"templateQuadPositions",new Float32Array(0));n(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 s=e.cols*e.rows,i=F.checkCompatibility();if(i.errors.length>0)throw new Error(`TerminalGL: WebGL incompatible - ${i.errors.join(", ")}`);let r=e.forceUint16??!1;if(r&&s>i.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.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 ${e.cols}\xD7${e.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 ${e.cols}\xD7${e.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 a=e.charWidth??8,l=e.charHeight??8;if(!Number.isFinite(a)||a<=0)throw new Error(`TerminalGL: Invalid charWidth: ${a}. 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=a,this.charHeight=l,this.canvasBgColor=e.canvasBgColor!==void 0?e.canvasBgColor:null,this.showGrid=e.showGrid??!1,this.scalingMode=e.scalingMode??y.ScalingMode.None,e.ambientEffect&&(this.ambientEffectEnabled=!0,typeof e.ambientEffect=="object"&&(this.ambientEffectBlur=e.ambientEffect.blur??y.POST_PROCESS_DEFAULTS.ambientEffect.blur,this.ambientEffectScale=e.ambientEffect.scale??y.POST_PROCESS_DEFAULTS.ambientEffect.scale,this.ambientEffectOpacity=e.ambientEffect.opacity??.7));this.parentElement.firstChild;)this.parentElement.removeChild(this.parentElement.firstChild);let 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
9
  position: absolute !important;
14
10
  top: 0 !important;
15
11
  left: 0 !important;
12
+ right: 0 !important;
13
+ bottom: 0 !important;
16
14
  width: 100% !important;
17
15
  height: 100% !important;
18
- overflow: hidden !important;
16
+ overflow: visible !important;
17
+ contain: layout style !important;
18
+ display: flex !important;
19
+ justify-content: center !important;
20
+ align-items: center !important;
21
+ isolation: isolate !important;
19
22
  `,this.canvas=document.createElement("canvas"),this.canvas.className="terminalgl-webgl-canvas",this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.canvas.style.cssText=`
20
- position: absolute !important;
21
- top: 0 !important;
22
- left: 0 !important;
23
+ flex-shrink: 0 !important;
24
+ width: ${this.canvas.width}px !important;
25
+ height: ${this.canvas.height}px !important;
23
26
  image-rendering: pixelated !important;
24
27
  image-rendering: crisp-edges !important;
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=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=`
28
+ -ms-interpolation-mode: nearest-neighbor !important;
29
+ transform-origin: center center !important;
30
+ transform: scale(1) !important;
31
+ will-change: transform !important;
32
+ backface-visibility: hidden !important;
33
+ position: relative !important;
34
+ z-index: 1 !important;
35
+ `;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.ambientEffectEnabled&&(this.createAmbientEffectCanvas(),console.warn("[TerminalGL] \u{1F308} Ambient effect enabled at startup")),this.parentElement.appendChild(this.containerDiv),this.initRenderBuffers();try{this.initWebGL()}catch(c){throw console.error("[TerminalGL] \u274C Failed to initialize WebGL:",c),c}this.showGrid&&this.initGridOverlay(),this.setupResizeObserver()}static checkCompatibility(){let t={webgl1:!1,uint32Indices:!1,maxTextureSize:0,maxViewportDims:[0,0],maxCellsUint16:0,maxCellsUint32:0,recommendedMaxCells:0,warnings:[],errors:[]},e=document.createElement("canvas"),s=e.getContext("webgl")||e.getContext("experimental-webgl");if(!s||!(s instanceof WebGLRenderingContext))return t.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),t;let i=s;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 r=i.getExtension("OES_element_index_uint");t.uint32Indices=!!r;let a=8;if(t.maxCellsUint16=Math.floor(65535/a),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,s=this.glyphOffsetX,i=this.glyphOffsetY,r=this.charWidth,a=this.charHeight,l=0,o=0,h=0;for(let d=0;d<this.rows;d++){let f=Math.round(d*e),u=Math.round(f+e);for(let m=0;m<this.cols;m++){let b=Math.round(m*t),g=Math.round(b+t);this.renderPositions[l++]=b,this.renderPositions[l++]=f,this.renderPositions[l++]=g,this.renderPositions[l++]=f,this.renderPositions[l++]=b,this.renderPositions[l++]=u,this.renderPositions[l++]=g,this.renderPositions[l++]=u,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(b+s),R=Math.round(f+i),p=Math.round(x+r),w=Math.round(R+a);this.renderPositions[l++]=x,this.renderPositions[l++]=R,this.renderPositions[l++]=p,this.renderPositions[l++]=R,this.renderPositions[l++]=x,this.renderPositions[l++]=w,this.renderPositions[l++]=p,this.renderPositions[l++]=w,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
36
  // Per-vertex attributes (template quad)
28
37
  attribute vec2 aPosition; // Local quad position (0,0 to cellW,cellH)
29
38
 
@@ -84,7 +93,7 @@
84
93
  float paletteU = (aColorIndex + 0.5) / 256.0;
85
94
  vColor = texture2D(uPalette, vec2(paletteU, 0.5));
86
95
  }
87
- `;let r=`
96
+ `;let s=`
88
97
  precision mediump float;
89
98
 
90
99
  uniform sampler2D uTexture;
@@ -102,7 +111,18 @@
102
111
  gl_FragColor = vec4(vColor.rgb * texColor.a, texColor.a);
103
112
  }
104
113
  }
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=`
114
+ `,i=this.compileShader(t.VERTEX_SHADER,e),r=this.compileShader(t.FRAGMENT_SHADER,s);if(!i||!r)throw new Error("Shader compilation error");let a=t.createProgram();if(!a)throw new Error("Unable to create WebGL program");if(t.attachShader(a,i),t.attachShader(a,r),t.linkProgram(a),!t.getProgramParameter(a,t.LINK_STATUS)){let l=t.getProgramInfoLog(a);throw new Error("Program linking error: "+l)}this.program=a,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=t.getAttribLocation(a,"aPosition"),this.useInstancing?(this.aTexCoord=t.getAttribLocation(a,"aInstanceOffset"),this.aColorIndex=t.getAttribLocation(a,"aInstanceUVs"),this.instanceDataBuffer=t.createBuffer()):(this.aTexCoord=t.getAttribLocation(a,"aTexCoord"),this.aColorIndex=t.getAttribLocation(a,"aColorIndex")),this.uResolution=t.getUniformLocation(a,"uResolution"),this.uTexture=t.getUniformLocation(a,"uTexture"),this.uPalette=t.getUniformLocation(a,"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 s=this.gl,i=s.createShader(t);return i?(s.shaderSource(i,e),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 T(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,s=this.canvas.getBoundingClientRect(),i=this.containerDiv.getBoundingClientRect();this.gridOverlay.setDimensions(this.cols,this.rows,this.cellWidth,this.cellHeight,0,0),this.gridOverlay.setTransform(this.currentScale,t,e,s,i),this.gridOverlay.render()}setBitmapFont(t,e,s,i,r){this.bitmapFont=t,this.charWidth=Math.round(e),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(a){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",a),a}this.buildCharCodeMap(),this.precomputeAtlasUVs(),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}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 s=Math.ceil(e/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 a=this.atlasCanvas.getContext("2d");if(!a)throw new Error("Unable to create 2D context for atlas");a.clearRect(0,0,i,r),a.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,u=d*this.charHeight;for(let m=0;m<Math.min(h.length,this.charHeight);m++){let b=h[m];for(let g=0;g<this.charWidth;g++){let x=1<<7-g;b&x&&a.fillRect(f+g,u+m,1,1)}}l++}this.createAtlasTexture()}buildCharCodeMap(){if(!this.bitmapFont)return;this.charCodeToAtlasIndex.fill(65535);let t=Array.from(this.bitmapFont.keys()).sort((e,s)=>e-s);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,s=this.cachedAtlasHeight,i=.5/e,r=.5/s;for(let a=0;a<t;a++){let l=a%this.atlasColumns,o=Math.floor(a/this.atlasColumns),h=(l*this.charWidth+i)/e,c=(o*this.charHeight+r)/s,d=((l+1)*this.charWidth-i)/e,f=((o+1)*this.charHeight-r)/s,u=a*4;this.atlasUVs[u]=h,this.atlasUVs[u+1]=c,this.atlasUVs[u+2]=d,this.atlasUVs[u+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),s=0,i=0,r=0;return e.length===3?(s=parseInt(e[0]+e[0],16),i=parseInt(e[1]+e[1],16),r=parseInt(e[2]+e[2],16)):e.length===6&&(s=parseInt(e.slice(0,2),16),i=parseInt(e.slice(2,4),16),r=parseInt(e.slice(4,6),16)),[s/255,i/255,r/255,1]}if(t.startsWith("rgb")){let e=t.match(/rgba?\(([^)]+)\)/);if(e){let s=e[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(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 s=this.cols*this.cellWidth,i=this.rows*this.cellHeight;if(s===0||i===0)return;let r=t/s,a=e/i,l=Math.min(r,a),o;switch(this.scalingMode){case y.ScalingMode.Integer:o=Math.max(1,Math.floor(l));break;case y.ScalingMode.Half:o=Math.max(1,Math.floor(l*2)/2);break;case y.ScalingMode.Quarter:o=Math.max(1,Math.floor(l*4)/4);break;case y.ScalingMode.Eighth:o=Math.max(1,Math.floor(l*8)/8);break;case y.ScalingMode.None:default:o=Math.max(.1,l);break}if(this.canvas.style.transform=`scale(${o})`,this.ambientEffectEnabled&&this.ambientEffectCanvas){let h=o*this.ambientEffectScale;this.ambientEffectCanvas.style.transform=`scale(${h})`}this.currentScale=o,this.onResizeCallback&&this.onResizeCallback(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}updateAmbientEffect(){!this.ambientEffectCanvas||!this.ambientEffectCtx||this.ambientEffectCtx.drawImage(this.canvas,0,0)}setPalette(t){let e=0;for(let s=0;s<Math.min(t.length,256);s++){let i=t[s];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 s=0;s<t.length&&s<256;s++){let i=t[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 t=this.gl;this.paletteTexture||(this.paletteTexture=t.createTexture()),t.bindTexture(t.TEXTURE_2D,this.paletteTexture);let e=new Uint8Array(256*4);for(let s=0;s<256;s++){let i=s*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),this.ambientEffectEnabled&&this.ambientEffectCanvas&&this.ambientEffectCtx&&this.updateAmbientEffect()}catch(e){console.error("[TerminalGL] \u274C Error rendering display data:",e)}}renderDirect(t){let e=this.gl;if(!this.staticPositionsInitialized&&!this.useInstancing&&this.precomputeStaticPositions(),this.canvasBgColor!==null){let s=this.parseColor(this.canvasBgColor);e.clearColor(s[0],s[1],s[2],s[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,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(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 r=0,a=this.instanceData.length/8;for(let f=0;f<t.height;f++)for(let u=0;u<t.width;u++){let m=t.cells[f*t.width+u],b=m.bgColorIndex,g=m.fgColorIndex,x=this.canvasBgColor!==null&&b===255,R=m.char===" "||g===255;if(!x){if(r>=a){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${r}, max=${a}`);break}let p=r*8;this.instanceData[p]=u,this.instanceData[p+1]=f,this.instanceData[p+2]=0,this.instanceData[p+3]=0,this.instanceData[p+4]=0,this.instanceData[p+5]=0,this.instanceData[p+6]=b,this.instanceData[p+7]=0,r++}if(!R){let p=m.char.charCodeAt(0),w=this.charCodeToAtlasIndex[p];if(w!==65535){if(r>=a){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${r}, max=${a}`);break}let A=w*4,C=r*8;this.instanceData[C]=u,this.instanceData[C+1]=f,this.instanceData[C+2]=this.atlasUVs[A],this.instanceData[C+3]=this.atlasUVs[A+1],this.instanceData[C+4]=this.atlasUVs[A+2],this.instanceData[C+5]=this.atlasUVs[A+3],this.instanceData[C+6]=0,this.instanceData[C+7]=g,r++}}}if(r===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,r*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),s.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),s.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),s.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),s.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),s.drawElementsInstancedANGLE(e.TRIANGLES,6,e.UNSIGNED_SHORT,0,r),s.vertexAttribDivisorANGLE(this.aPosition,0),s.vertexAttribDivisorANGLE(o,0),s.vertexAttribDivisorANGLE(h,0),s.vertexAttribDivisorANGLE(c,0)}renderDirectBuffers(t){let e=this.gl,s=t.width*t.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,a=0,l=t.cells,o=s;for(let m=0;m<o;m++){let b=l[m],g=b.bgColorIndex,R=this.canvasBgColor!==null&&g===255?255:g,p=0;for(let C=0;C<4;C++)this.renderTexCoords[r++]=p,this.renderTexCoords[r++]=p,this.renderColorIndices[a++]=R;let w=b.fgColorIndex,A=b.char;if(A===" "||w===255)for(let C=0;C<4;C++)this.renderTexCoords[r++]=0,this.renderTexCoords[r++]=0,this.renderColorIndices[a++]=255;else{let C=A.charCodeAt(0),k=this.charCodeToAtlasIndex[C];if(k!==65535){let I=k*4,$=this.atlasUVs[I],Y=this.atlasUVs[I+1],N=this.atlasUVs[I+2],V=this.atlasUVs[I+3];this.renderTexCoords[r++]=$,this.renderTexCoords[r++]=Y,this.renderColorIndices[a++]=w,this.renderTexCoords[r++]=N,this.renderTexCoords[r++]=Y,this.renderColorIndices[a++]=w,this.renderTexCoords[r++]=$,this.renderTexCoords[r++]=V,this.renderColorIndices[a++]=w,this.renderTexCoords[r++]=N,this.renderTexCoords[r++]=V,this.renderColorIndices[a++]=w}else for(let I=0;I<4;I++)this.renderTexCoords[r++]=0,this.renderTexCoords[r++]=0,this.renderColorIndices[a++]=255}}(r!==o*2*4*2||a!==o*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:r,colorIdx:a,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,r)),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,a))):(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,r)),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,a)),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,u=this.useUint16Indices?e.UNSIGNED_SHORT:e.UNSIGNED_INT;e.drawElements(e.TRIANGLES,f,u,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 s=t*e,i=this.useUint16Indices?8191:262144;if(s>i){let c=Math.floor(Math.sqrt(i));console.error(`[TerminalGL] \u274C Cannot resize to ${t}\xD7${e} (${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 ${t}\xD7${e} (${s} cells) exceeds recommended limit (${r.recommendedMaxCells} cells). Performance may degrade.`),this.cols=t,this.rows=e,this.staticPositionsInitialized=!1;let a=this.cols*this.rows*2,l=Math.ceil(a*1.5),o=a>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",u=c*160/1048576,m=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${f} buffers: ${u.toFixed(2)}MB \u2192 ${m.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.ambientEffectEnabled&&this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.width=`${this.canvas.width}px`,this.ambientEffectCanvas.style.height=`${this.canvas.height}px`),this.showGrid&&this.gridOverlay&&this.updateGridOverlay(),this.updateCanvasSize()}getCanvas(){return this.canvas}getGridSize(){return{cols:this.cols,rows:this.rows}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getBaseDimensions(){return{width:this.cols*this.cellWidth,height:this.rows*this.cellHeight}}setOnResizeCallback(t){this.onResizeCallback=t}clearOnResizeCallback(){this.onResizeCallback=void 0}setScalingMode(t){this.scalingMode!==t&&(this.scalingMode=t,this.updateCanvasSize())}getScalingMode(){return this.scalingMode}setGrid(t){t.enabled?(this.gridOverlay?this.gridOverlay.setStyle({strokeColor:t.color,lineWidth:t.lineWidth}):this.gridOverlay=new T(this.containerDiv,{strokeColor:t.color??"rgba(144, 24, 24, 1)",lineWidth:t.lineWidth??1,zIndex:10}),this.showGrid=!0,this.gridOverlay.setVisible(!0),this.updateGridOverlay()):(this.showGrid=!1,this.gridOverlay&&this.gridOverlay.setVisible(!1))}isGridEnabled(){return this.showGrid}setAmbientEffect(t){typeof t=="boolean"?this.ambientEffectEnabled=t:(this.ambientEffectEnabled=!0,t.blur!==void 0&&(this.ambientEffectBlur=t.blur),t.scale!==void 0&&(this.ambientEffectScale=t.scale)),this.ambientEffectEnabled&&!this.ambientEffectCanvas&&this.createAmbientEffectCanvas(),this.ambientEffectCanvas&&(this.ambientEffectEnabled?(this.ambientEffectCanvas.style.display="block",this.ambientEffectCanvas.style.filter=`blur(${this.ambientEffectBlur}px)`,this.ambientEffectCanvas.style.transform=`scale(${this.ambientEffectScale})`,this.updateAmbientEffect()):this.ambientEffectCanvas.style.display="none")}createAmbientEffectCanvas(){this.ambientEffectCanvas||(this.ambientEffectCanvas=document.createElement("canvas"),this.ambientEffectCanvas.className="terminalgl-ambient-effect-canvas",this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.cssText=`
115
+ display: block !important;
116
+ position: absolute !important;
117
+ width: ${this.canvas.width}px !important;
118
+ height: ${this.canvas.height}px !important;
119
+ filter: blur(${this.ambientEffectBlur}px) !important;
120
+ opacity: ${this.ambientEffectOpacity} !important;
121
+ transform-origin: center center !important;
122
+ transform: scale(${this.ambientEffectScale}) !important;
123
+ pointer-events: none !important;
124
+ z-index: 0 !important;
125
+ `,this.ambientEffectCtx=this.ambientEffectCanvas.getContext("2d",{alpha:!0}),this.containerDiv.insertBefore(this.ambientEffectCanvas,this.canvas),console.warn("[TerminalGL] \u{1F308} ambient effect canvas created dynamically"))}isAmbientEffectEnabled(){return this.ambientEffectEnabled}getAmbientEffectConfig(){return{enabled:this.ambientEffectEnabled,blur:this.ambientEffectBlur,scale:this.ambientEffectScale}}getCols(){return this.cols}getRows(){return this.rows}isReady(){return!!(this.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.ambientEffectCanvas&&(this.ambientEffectCanvas.width=0,this.ambientEffectCanvas.height=0,this.ambientEffectCanvas=null),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.renderPositions=new Float32Array(0),this.renderTexCoords=new Float32Array(0),this.renderColorIndices=new Float32Array(0),this.renderIndices=new Uint32Array(0),this.paletteFloat=new Float32Array(0),this.atlasUVs=new Float32Array(0),this.instanceData=new Float32Array(0),this.templateQuadPositions=new Float32Array(0),this.templateQuadIndices=new Uint16Array(0)}};E(F,"TerminalGL");var M=F;var P=class P{constructor(t,e,s,i,r){n(this,"atlases");n(this,"charMap");n(this,"baseCharWidth");n(this,"baseCharHeight");n(this,"baseCellWidth");n(this,"baseCellHeight");n(this,"atlasColumns",16);n(this,"font");n(this,"SCALES",[1,2,4,8]);n(this,"colorCache",new Map);n(this,"MAX_CACHE_SIZE",512);this.font=t,this.baseCharWidth=e,this.baseCharHeight=s,this.baseCellWidth=i??e,this.baseCellHeight=r??s,this.charMap=new Map,this.atlases=new Map,this.generateAtlases()}generateAtlases(){this.atlasColumns=16;let t=0;for(let[e,s]of this.font){let i=t%this.atlasColumns,r=Math.floor(t/this.atlasColumns);this.charMap.set(e,{x:i*this.baseCharWidth,y:r*this.baseCharHeight});for(let a of this.SCALES){let l=this.getOrCreateAtlas(a),o=i*l.charWidth,h=r*l.charHeight;this.renderBitmapToAtlas(l,s,o,h)}t++}}getOrCreateAtlas(t){let e=this.atlases.get(t);if(!e){let s=this.baseCharWidth*t,i=this.baseCharHeight*t,a=Math.ceil(256/this.atlasColumns),l=document.createElement("canvas");l.width=this.atlasColumns*s,l.height=a*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:s,charHeight:i},this.atlases.set(t,e)}return e}renderBitmapToAtlas(t,e,s,i){let r=t.scale,a=t.ctx;a.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&&a.fillRect(s+h*r,i+l*r,r,r)}}}drawChar(t,e,s,i,r,a,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=r/this.baseCellWidth,f=a/this.baseCellHeight,u=(this.baseCellWidth-this.baseCharWidth)/2*d,m=(this.baseCellHeight-this.baseCharHeight)/2*f,b=this.baseCharWidth*d,g=this.baseCharHeight*f;t.drawImage(c.canvas,s+u,i+m,b,g)}createColoredGlyph(t,e,s){let i=this.atlases.get(1);if(!i)return null;let r=i.ctx.getImageData(s.x,s.y,this.baseCharWidth,this.baseCharHeight),a=r.data,l=this.hexToRgb(e);for(let c=0;c<a.length;c+=4)a[c+3]>0&&(a[c]=l.r,a[c+1]=l.g,a[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(t){if(t.startsWith("#")){let r=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(r,(l,o,h,c)=>o+o+h+h+c+c);let a=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return a?{r:parseInt(a[1],16),g:parseInt(a[2],16),b:parseInt(a[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[s,i]of this.colorCache)i.lastUsed<e&&(e=i.lastUsed,t=s);if(t){let s=this.colorCache.get(t);s&&(s.canvas.width=0,s.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(P,"BitmapFontAtlas");var B=P;var O=class O{constructor(t,e={}){n(this,"canvas");n(this,"ctx");n(this,"parentElement");n(this,"cells");n(this,"cols",0);n(this,"rows",0);n(this,"fontSize");n(this,"fontFamily");n(this,"defaultFgColor");n(this,"defaultBgColor");n(this,"canvasBgColor");n(this,"cellWidth");n(this,"cellHeight");n(this,"offsetX",0);n(this,"offsetY",0);n(this,"fontType","web");n(this,"bitmapFont");n(this,"bitmapAtlas");n(this,"bitmapCharWidth",8);n(this,"bitmapCharHeight",8);n(this,"showDebugGrid");n(this,"debugGridColor");n(this,"gridOverlay");n(this,"fixedGridMode");n(this,"fixedCols");n(this,"fixedRows");n(this,"cellAspectRatio");n(this,"resizeObserver");n(this,"imageDataBuffer");n(this,"useImageDataRendering",!1);n(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 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 T(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;if(this.fixedGridMode&&this.fixedCols&&this.fixedRows)if(this.cols=this.fixedCols,this.rows=this.fixedRows,this.fontType==="bitmap"){let a=t/this.cols,l=e/this.rows,o=this.bitmapCharWidth/this.bitmapCharHeight;a/l>o?(this.cellHeight=Math.floor(l),this.cellWidth=Math.floor(this.cellHeight*o)):(this.cellWidth=Math.floor(a),this.cellHeight=Math.floor(this.cellWidth/o))}else{let a=t/this.cols,l=e/this.rows;a/l>this.cellAspectRatio?(this.cellHeight=Math.floor(l*100)/100,this.cellWidth=Math.floor(this.cellHeight*this.cellAspectRatio*100)/100):(this.cellWidth=Math.floor(a*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 s=this.cols*this.cellWidth,i=this.rows*this.cellHeight;this.offsetX=Math.floor((t-s)/2),this.offsetY=Math.floor((e-i)/2);let r=window.devicePixelRatio||1;this.canvas.style.width=`${t}px`,this.canvas.style.height=`${e}px`,this.canvas.width=t*r,this.canvas.height=e*r,this.ctx.scale(r,r)}createEmptyGrid(){let t=[];for(let e=0;e<this.rows;e++){let s=[];for(let i=0;i<this.cols;i++)s.push({char:" ",fgColor:this.defaultFgColor,bgColor:this.defaultBgColor});t.push(s)}return t}enableAutoResize(){this.resizeObserver=new ResizeObserver(()=>{let t=this.cols,e=this.rows;if(this.calculateGridSize(),this.cols!==t||this.rows!==e){let s=this.cells;this.cells=this.createEmptyGrid();let i=Math.min(t,this.cols),r=Math.min(e,this.rows);for(let a=0;a<r;a++)for(let l=0;l<i;l++)this.cells[a][l]=s[a][l]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(t,e,s,i,r){if(e<0||e>=this.rows||t<0||t>=this.cols)return;let a=s&&typeof s=="string"?s.charAt(0):" ";this.cells[e][t]={char:a,fgColor:i??this.defaultFgColor,bgColor:r??this.defaultBgColor}}getCell(t,e){return e<0||e>=this.rows||t<0||t>=this.cols?null:this.cells[e][t]}write(t,e,s,i,r){for(let a=0;a<s.length;a++)this.setCell(t+a,e,s[a],i,r)}fillRect(t,e,s,i,r=" ",a,l){for(let o=e;o<e+i;o++)for(let h=t;h<t+s;h++)this.setCell(h,o,r,a,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 s=0;for(let i=0;i<t.height;i++)for(let r=0;r<t.width;r++){let a=t.cells[s];i<this.rows&&r<this.cols&&this.setCell(r,i,a.char,a.fgColor,a.bgColor),s++}}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 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),u=c.char.charCodeAt(0),m=this.bitmapFont.get(u);for(let b=0;b<this.bitmapCharHeight;b++)for(let g=0;g<this.bitmapCharWidth;g++){let x=h*this.bitmapCharWidth+g,p=((o*this.bitmapCharHeight+b)*t+x)*4,w=!1;if(m&&b<m.length){let A=m[b],C=1<<7-g;w=(A&C)!==0}w?(s[p]=f.r,s[p+1]=f.g,s[p+2]=f.b,s[p+3]=f.a):(s[p]=d.r,s[p+1]=d.g,s[p+2]=d.b,s[p+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 a=this.cols*this.cellWidth,l=this.rows*this.cellHeight;this.ctx.drawImage(i,0,0,t,e,this.offsetX,this.offsetY,a,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 r=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(r,(l,o,h,c)=>o+o+h+h+c+c);let a=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);if(a)return{r:parseInt(a[1],16),g:parseInt(a[2],16),b:parseInt(a[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 s=this.cells[t][e],i=Math.floor(this.offsetX+e*this.cellWidth),r=Math.floor(this.offsetY+t*this.cellHeight),a=Math.floor(this.offsetX+(e+1)*this.cellWidth),l=Math.floor(this.offsetY+(t+1)*this.cellHeight),o=a-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(t,e,s,i,r,a){let l=t.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,l,e,s,i,r,a);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=a;for(let d=0;d<Math.min(o.length,this.bitmapCharHeight);d++){let f=o[d],u=s+d*c,m=s+(d+1)*c;for(let b=0;b<this.bitmapCharWidth;b++){let g=1<<7-b;if(f&g){let x=e+b*h,R=e+(b+1)*h;this.ctx.fillRect(x,u,R-x,m-u)}}}}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 T(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10}),this.drawDebugGrid()):!t&&this.gridOverlay?(this.gridOverlay.destroy(),this.gridOverlay=void 0):t&&this.gridOverlay&&this.gridOverlay.setVisible(!0)}setCanvasBackgroundColor(t){this.canvasBgColor=t}getCanvasBackgroundColor(){return this.canvasBgColor}setFixedGrid(t,e,s){this.fixedGridMode=!0,this.fixedCols=t,this.fixedRows=e,s!==void 0&&(this.cellAspectRatio=s);let i=this.cols,r=this.rows,a=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]=a[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 s=this.cols,i=this.rows,r=this.cells;if(this.calculateGridSize(),this.cols!==s||this.rows!==i){this.cells=this.createEmptyGrid();let a=Math.min(s,this.cols),l=Math.min(i,this.rows);for(let o=0;o<l;o++)for(let h=0;h<a;h++)this.cells[o][h]=r[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,s,i,r){this.fontType="bitmap",this.bitmapFont=t,this.bitmapCharWidth=e,this.bitmapCharHeight=s,this.bitmapAtlas=new B(t,e,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(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 s=E(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 r=e[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<t.height&&i<this.rows;i++)for(let r=0;r<t.width&&r<this.cols;r++){let a=i*t.width+r;if(a>=t.cells.length)break;let l=t.cells[a];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(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(O,"Terminal2D");var L=O;var H=class H{constructor(t,e={}){n(this,"container");n(this,"overlayDiv",null);n(this,"button",null);n(this,"options");n(this,"started",!1);n(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
126
  position: absolute !important;
107
127
  top: 0 !important;
108
128
  left: 0 !important;
@@ -126,4 +146,22 @@
126
146
  cursor: pointer !important;
127
147
  transition: background-color 0.2s ease, transform 0.1s ease !important;
128
148
  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";
149
+ `,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(H,"AutoplayOverlay");var _=H;var S=require("@utsp/types");var z=class z{constructor(t,e){n(this,"canvas");n(this,"ctx");n(this,"containerDiv");n(this,"parentElement");n(this,"resizeObserver");n(this,"width",0);n(this,"height",0);n(this,"currentConfig",null);n(this,"configHash","");this.parentElement=t,this.containerDiv=document.createElement("div"),this.containerDiv.className="postprocess-container",this.containerDiv.style.cssText=`
150
+ position: absolute !important;
151
+ top: 0 !important;
152
+ left: 0 !important;
153
+ right: 0 !important;
154
+ bottom: 0 !important;
155
+ width: 100% !important;
156
+ height: 100% !important;
157
+ pointer-events: none !important;
158
+ z-index: 10 !important;
159
+ overflow: hidden !important;
160
+ `,this.canvas=document.createElement("canvas"),this.canvas.className="postprocess-canvas",this.canvas.style.cssText=`
161
+ position: absolute !important;
162
+ top: 0 !important;
163
+ left: 0 !important;
164
+ width: 100% !important;
165
+ height: 100% !important;
166
+ pointer-events: none !important;
167
+ `;let s=this.canvas.getContext("2d",{alpha:!0});if(!s)throw new Error("PostProcessOverlay: Failed to get 2D context");this.ctx=s,this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv),this.resizeObserver=new ResizeObserver(r=>{for(let a of r){let{width:l,height:o}=a.contentRect;l>0&&o>0&&this.handleResize(Math.floor(l),Math.floor(o))}}),this.resizeObserver.observe(this.parentElement);let i=this.parentElement.getBoundingClientRect();i.width>0&&i.height>0&&this.handleResize(Math.floor(i.width),Math.floor(i.height)),this.hide()}handleResize(t,e){this.width===t&&this.height===e||(this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.currentConfig&&this.isActive()&&this.render())}setConfig(t){let e=this.hashConfig(t);if(e!==this.configHash){if(this.currentConfig=t,this.configHash=e,!t||!this.isActiveConfig(t)){this.clear(),this.hide();return}this.show(),this.render()}}setScanlines(t){t===null?this.setConfig({scanlines:{enabled:!1}}):this.setConfig({scanlines:t})}setScanlinesEnabled(t){if(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:!0,opacity:e?.opacity??S.POST_PROCESS_DEFAULTS.scanlines.opacity,pattern:e?.pattern??"horizontal",spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}else this.setScanlines({enabled:!1})}setScanlinesOpacity(t){let e=Math.max(0,Math.min(1,t)),s=this.currentConfig?.scanlines;this.setScanlines({enabled:s?.enabled??!0,opacity:e,pattern:s?.pattern??"horizontal",spacing:s?.spacing??2,thickness:s?.thickness??1,color:s?.color??{r:0,g:0,b:0}})}setScanlinesPattern(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:e?.enabled??!0,opacity:e?.opacity??S.POST_PROCESS_DEFAULTS.scanlines.opacity,pattern:t,spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}setScanlinesSpacing(t){let e=Math.max(2,Math.round(t)),s=this.currentConfig?.scanlines;this.setScanlines({enabled:s?.enabled??!0,opacity:s?.opacity??S.POST_PROCESS_DEFAULTS.scanlines.opacity,pattern:s?.pattern??"horizontal",spacing:e,thickness:s?.thickness??1,color:s?.color??{r:0,g:0,b:0}})}getConfig(){return this.currentConfig}isActive(){return this.isActiveConfig(this.currentConfig)}destroy(){this.resizeObserver.disconnect(),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}syncWithRenderer(t){}resize(t,e){}setCellDimensions(t,e){}show(){this.containerDiv.style.display="block"}hide(){this.containerDiv.style.display="none"}clear(){this.ctx.clearRect(0,0,this.width,this.height)}isActiveConfig(t){return t?.scanlines?.enabled??!1}render(){this.clear(),this.currentConfig?.scanlines?.enabled&&this.renderScanlines(this.currentConfig.scanlines)}renderScanlines(t){let e=t.opacity??S.POST_PROCESS_DEFAULTS.scanlines.opacity,s=t.pattern??"horizontal",i=t.spacing??2,r=t.thickness??1,a=t.color??{r:0,g:0,b:0},l=this.ctx;switch(l.fillStyle=`rgba(${a.r}, ${a.g}, ${a.b}, ${e})`,s){case"horizontal":for(let o=i-1;o<this.height;o+=i)l.fillRect(0,o,this.width,r);break;case"vertical":for(let o=i-1;o<this.width;o+=i)l.fillRect(o,0,r,this.height);break;case"grid":for(let o=i-1;o<this.height;o+=i)l.fillRect(0,o,this.width,r);for(let o=i-1;o<this.width;o+=i)l.fillRect(o,0,r,this.height);break}}hashConfig(t){return t?JSON.stringify(t):"null"}};E(z,"PostProcessOverlay");var G=z;var it="0.1.0";
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { IRenderer, RGBColor, RenderState } from '@utsp/types';
2
- export { IColorPalette, IRenderer, RenderState } from '@utsp/types';
1
+ import { IRenderer, RGBColor, RenderState, ScalingMode, PostProcessConfig, ScanlinesConfig } from '@utsp/types';
2
+ export { IColorPalette, IRenderer, PostProcessConfig, RenderState, ScalingMode, ScanlinesConfig } from '@utsp/types';
3
3
 
4
4
  /**
5
5
  * Default color palette (VGA colors + extended)
@@ -446,6 +446,35 @@ interface TerminalGLOptions {
446
446
  showGrid?: boolean;
447
447
  /** Force Uint16 indices (for compatibility testing, auto-detected by default) */
448
448
  forceUint16?: boolean;
449
+ /**
450
+ * Scaling mode for pixel-perfect rendering (default: ScalingMode.None)
451
+ *
452
+ * Controls how the canvas is scaled to fit the container:
453
+ * - ScalingMode.None: Fills available space, may have sub-pixel artifacts (default)
454
+ * - ScalingMode.Eighth: Snaps to 0.125 increments (1.0, 1.125, 1.25...)
455
+ * - ScalingMode.Quarter: Snaps to 0.25 increments (1.0, 1.25, 1.5...)
456
+ * - ScalingMode.Half: Snaps to 0.5 increments (1.0, 1.5, 2.0...)
457
+ * - ScalingMode.Integer: Integer scaling only (1x, 2x, 3x...), crispest pixels
458
+ */
459
+ scalingMode?: ScalingMode;
460
+ /**
461
+ * Ambient effect configuration
462
+ *
463
+ * Creates a blurred glow effect around the terminal when using pixel-perfect
464
+ * scaling modes that leave empty space around the canvas.
465
+ *
466
+ * - false or undefined: Disabled (default)
467
+ * - true: Enabled with default settings (blur: 30px, scale: 1.15, opacity: 0.7)
468
+ * - object: Custom configuration
469
+ */
470
+ ambientEffect?: boolean | {
471
+ /** Blur radius in pixels (default: 30) */
472
+ blur?: number;
473
+ /** Scale factor for the background canvas (default: 1.15) */
474
+ scale?: number;
475
+ /** Opacity of the ambient effect (0-1, default: 0.7) */
476
+ opacity?: number;
477
+ };
449
478
  }
450
479
  /**
451
480
  * Simplified terminal using WebGL for basic rendering
@@ -526,6 +555,15 @@ declare class TerminalGL implements IRenderer {
526
555
  private cachedTextureUniform;
527
556
  private cachedPaletteUniform;
528
557
  private paletteHash;
558
+ private currentScale;
559
+ private scalingMode;
560
+ private ambientEffectEnabled;
561
+ private ambientEffectCanvas;
562
+ private ambientEffectCtx;
563
+ private ambientEffectBlur;
564
+ private ambientEffectScale;
565
+ private ambientEffectOpacity;
566
+ private onResizeCallback?;
529
567
  private staticPositionsInitialized;
530
568
  private vaoExtension;
531
569
  private vao;
@@ -569,6 +607,11 @@ declare class TerminalGL implements IRenderer {
569
607
  /**
570
608
  * 🔲 Draw grid lines on 2D canvas overlay
571
609
  * Called only once at init and resize
610
+ *
611
+ * The grid must match the terminal's pixel-perfect scaling:
612
+ * - Same base size as the main canvas
613
+ * - Same transform: scale() factor
614
+ * - Centered in the container like the main canvas (via flexbox or calculated position)
572
615
  */
573
616
  private updateGridOverlay;
574
617
  /**
@@ -643,13 +686,34 @@ declare class TerminalGL implements IRenderer {
643
686
  /**
644
687
  * Update canvas display size
645
688
  *
646
- * 🎯 PIXEL PERFECT: Forces display dimensions to be exact multiples of cell size
647
- * to avoid sub-pixel rendering artifacts (like Terminal2D does).
689
+ * Supports multiple scaling modes:
648
690
  *
649
- * Strategy: Keep canvas internal resolution fixed at base size (cols × cellWidth),
650
- * and use CSS scaling with image-rendering: pixelated for integer upscaling.
691
+ * 🎯 INTEGER MODE (ScalingMode.Integer):
692
+ * Uses integer scaling (1x, 2x, 3x...) for crisp pixels without artifacts.
693
+ * The canvas is centered in the container via flexbox.
694
+ * May leave empty space around the canvas.
695
+ *
696
+ * 📐 HALF MODE (ScalingMode.Half):
697
+ * Snaps to half increments (1.0, 1.5, 2.0...).
698
+ * Good balance between space usage and visual quality.
699
+ *
700
+ * 📏 QUARTER MODE (ScalingMode.Quarter):
701
+ * Snaps to quarter increments (1.0, 1.25, 1.5, 1.75, 2.0...).
702
+ * Finer control over scaling with minimal artifacts.
703
+ *
704
+ * 🔲 NONE MODE (ScalingMode.None):
705
+ * Scales to fill as much space as possible while maintaining aspect ratio.
706
+ * May cause some lines to appear thicker due to sub-pixel rendering.
707
+ * Useful when maximizing screen usage is more important than pixel purity.
651
708
  */
652
709
  private updateCanvasSize;
710
+ /**
711
+ * 🌈 AMBIENT EFFECT: Copy main canvas to ambient effect background
712
+ *
713
+ * This creates a glow effect around the terminal by copying the main
714
+ * WebGL canvas to a 2D canvas behind it, which has CSS blur applied.
715
+ */
716
+ private updateAmbientEffect;
653
717
  /**
654
718
  * Set color palette and upload to GPU
655
719
  *
@@ -751,6 +815,116 @@ declare class TerminalGL implements IRenderer {
751
815
  * Get cell height
752
816
  */
753
817
  getCellHeight(): number;
818
+ /**
819
+ * Get current integer scale factor
820
+ * Used by PostProcessOverlay to sync dimensions
821
+ */
822
+ getCurrentScale(): number;
823
+ /**
824
+ * Get base canvas dimensions (before scaling)
825
+ * Used by PostProcessOverlay to sync dimensions
826
+ */
827
+ getBaseDimensions(): {
828
+ width: number;
829
+ height: number;
830
+ };
831
+ /**
832
+ * Set callback to be called after every resize
833
+ * Used by ClientRuntime to sync PostProcessOverlay
834
+ */
835
+ setOnResizeCallback(callback: () => void): void;
836
+ /**
837
+ * Clear the resize callback
838
+ */
839
+ clearOnResizeCallback(): void;
840
+ /**
841
+ * Set scaling mode
842
+ *
843
+ * @param mode - ScalingMode enum value:
844
+ * - ScalingMode.None: Fill space, may have sub-pixel artifacts
845
+ * - ScalingMode.Eighth: Snap to 0.125 increments (1.0, 1.125, 1.25...)
846
+ * - ScalingMode.Quarter: Snap to 0.25 increments (1.0, 1.25, 1.5...)
847
+ * - ScalingMode.Half: Snap to 0.5 increments (1.0, 1.5, 2.0...)
848
+ * - ScalingMode.Integer: Crisp pixels, may waste space (1x, 2x, 3x...)
849
+ */
850
+ setScalingMode(mode: ScalingMode): void;
851
+ /**
852
+ * Get current scaling mode
853
+ */
854
+ getScalingMode(): ScalingMode;
855
+ /**
856
+ * Enable or configure debug grid overlay
857
+ *
858
+ * The grid shows cell boundaries aligned with the terminal grid.
859
+ * Useful for debugging layout and alignment issues.
860
+ *
861
+ * @param config - Configuration options:
862
+ * - enabled: Whether to show the grid
863
+ * - color: CSS color string (e.g., 'rgba(255,0,0,0.5)', '#ff0000')
864
+ * - lineWidth: Line width in pixels (1-10)
865
+ *
866
+ * @example
867
+ * ```typescript
868
+ * // Enable with default red color
869
+ * renderer.setGrid({ enabled: true });
870
+ *
871
+ * // Custom green grid
872
+ * renderer.setGrid({ enabled: true, color: 'rgba(0, 255, 0, 0.5)' });
873
+ *
874
+ * // Disable grid
875
+ * renderer.setGrid({ enabled: false });
876
+ * ```
877
+ */
878
+ setGrid(config: {
879
+ enabled: boolean;
880
+ color?: string;
881
+ lineWidth?: number;
882
+ }): void;
883
+ /**
884
+ * Check if grid is currently enabled
885
+ */
886
+ isGridEnabled(): boolean;
887
+ /**
888
+ * Enable or configure ambient effect
889
+ *
890
+ * Ambient effect creates a blurred glow around the terminal canvas,
891
+ * filling the unused space with colors from the terminal content.
892
+ *
893
+ * @param config - true to enable with defaults, false to disable,
894
+ * or object with blur and scale settings
895
+ *
896
+ * @example
897
+ * ```typescript
898
+ * // Enable with defaults (blur: 30px, scale: 1.3)
899
+ * renderer.setAmbientEffect(true);
900
+ *
901
+ * // Disable
902
+ * renderer.setAmbientEffect(false);
903
+ *
904
+ * // Custom settings
905
+ * renderer.setAmbientEffect({ blur: 50, scale: 1.5 });
906
+ * ```
907
+ */
908
+ setAmbientEffect(config: boolean | {
909
+ blur?: number;
910
+ scale?: number;
911
+ }): void;
912
+ /**
913
+ * Create the ambient effect canvas element (called lazily if needed)
914
+ */
915
+ private createAmbientEffectCanvas;
916
+ /**
917
+ * Check if ambient effect is enabled
918
+ */
919
+ isAmbientEffectEnabled(): boolean;
920
+ /**
921
+ * Get current ambient effect configuration
922
+ */
923
+ getAmbientEffectConfig(): {
924
+ enabled: boolean;
925
+ blur: number;
926
+ scale: number;
927
+ };
754
928
  /**
755
929
  * Get number of columns (IRenderer interface)
756
930
  *
@@ -970,7 +1144,6 @@ declare class GridOverlay {
970
1144
  private offsetY;
971
1145
  private strokeColor;
972
1146
  private lineWidth;
973
- private innerPadding;
974
1147
  /**
975
1148
  * Crée une nouvelle overlay de grille
976
1149
  * @param container - Élément parent qui contiendra le canvas
@@ -979,7 +1152,6 @@ declare class GridOverlay {
979
1152
  constructor(container: HTMLElement, options?: {
980
1153
  strokeColor?: string;
981
1154
  lineWidth?: number;
982
- innerPadding?: number;
983
1155
  zIndex?: number;
984
1156
  });
985
1157
  /**
@@ -994,11 +1166,15 @@ declare class GridOverlay {
994
1166
  setDimensions(cols: number, rows: number, cellWidth: number, cellHeight: number, offsetX?: number, offsetY?: number): void;
995
1167
  /**
996
1168
  * Configure la taille physique du canvas
997
- * Doit correspondre à la taille d'affichage du canvas principal
998
- * @param displayWidth - Largeur d'affichage en pixels
999
- * @param displayHeight - Hauteur d'affichage en pixels
1169
+ * Le canvas doit avoir la MÊME approche que le canvas principal WebGL :
1170
+ * - Résolution physique = dimensions de base (SANS DPR)
1171
+ * - Taille CSS = dimensions de base
1172
+ * - Le scaling visuel est fait via transform: scale()
1173
+ *
1174
+ * @param baseWidth - Largeur de base en pixels
1175
+ * @param baseHeight - Hauteur de base en pixels
1000
1176
  */
1001
- setCanvasSize(displayWidth: number, displayHeight: number): void;
1177
+ setCanvasSize(baseWidth: number, baseHeight: number): void;
1002
1178
  /**
1003
1179
  * Configure les options visuelles
1004
1180
  * @param options - Options de rendu
@@ -1006,14 +1182,27 @@ declare class GridOverlay {
1006
1182
  setStyle(options: {
1007
1183
  strokeColor?: string;
1008
1184
  lineWidth?: number;
1009
- innerPadding?: number;
1010
1185
  }): void;
1011
1186
  /**
1012
- * Dessine la grille avec des lignes fines continues
1187
+ * Configure la transformation et le positionnement du canvas de grille
1188
+ * pour qu'il corresponde exactement au canvas principal (pixel-perfect scaling)
1189
+ *
1190
+ * APPROCHE SIMPLE : On ne fait PAS de transform: scale().
1191
+ * On définit le canvas à la taille finale (scalée) directement,
1192
+ * et on le positionne exactement où est le canvas principal.
1193
+ *
1194
+ * Le dessin de la grille doit alors être fait à l'échelle scalée.
1013
1195
  *
1014
- * Dessine une grille continue sans écarts entre les cellules.
1015
- * Les lignes sont décalées vers l'intérieur de la cellule (innerPadding)
1016
- * pour créer un effet visuel élégant tout en gardant la grille continue.
1196
+ * @param scale - Facteur de scale (même valeur que le canvas principal)
1197
+ * @param baseWidth - Largeur de base du canvas (avant scale)
1198
+ * @param baseHeight - Hauteur de base du canvas (avant scale)
1199
+ * @param mainCanvasRect - Le getBoundingClientRect() du canvas principal
1200
+ * @param containerRect - Le getBoundingClientRect() du container
1201
+ */
1202
+ setTransform(_scale: number, _baseWidth: number, _baseHeight: number, mainCanvasRect: DOMRect, containerRect: DOMRect): void;
1203
+ /**
1204
+ * Dessine la grille avec des lignes fines continues
1205
+ * Les lignes sont dessinées aux bords exacts des cellules.
1017
1206
  */
1018
1207
  render(): void;
1019
1208
  /**
@@ -1128,6 +1317,128 @@ declare class AutoplayOverlay {
1128
1317
  destroy(): void;
1129
1318
  }
1130
1319
 
1320
+ /**
1321
+ * PostProcessOverlay - Static overlay canvas for post-processing effects
1322
+ *
1323
+ * This overlay is completely INDEPENDENT of the terminal renderer.
1324
+ * It covers the entire container and draws effects at native screen resolution.
1325
+ *
1326
+ * 🎯 SIMPLE DESIGN:
1327
+ * - Canvas fills 100% of the parent container
1328
+ * - Effects are drawn at native resolution (no scaling needed)
1329
+ * - ResizeObserver handles container size changes
1330
+ * - No synchronization with TerminalGL required
1331
+ *
1332
+ * 🎨 EFFECTS:
1333
+ * - Scanlines: Horizontal, vertical, or grid patterns
1334
+ * - Lines are drawn at fixed pixel intervals (e.g., every 2 pixels)
1335
+ * - Works regardless of terminal scale or cell size
1336
+ *
1337
+ * 🛡️ ROBUST:
1338
+ * - Uses !important on critical CSS properties
1339
+ * - pointer-events: none to not interfere with input
1340
+ * - Redraws only on config change or container resize
1341
+ */
1342
+
1343
+ /**
1344
+ * Options for PostProcessOverlay constructor
1345
+ */
1346
+ interface PostProcessOverlayOptions {
1347
+ }
1348
+ /**
1349
+ * Static post-processing overlay
1350
+ *
1351
+ * Key design principles:
1352
+ * 1. INDEPENDENT of TerminalGL - no sync required
1353
+ * 2. Fills entire container at native resolution
1354
+ * 3. Rendered ONCE when configured (no per-frame cost)
1355
+ * 4. Own ResizeObserver for container size changes
1356
+ */
1357
+ declare class PostProcessOverlay {
1358
+ private canvas;
1359
+ private ctx;
1360
+ private containerDiv;
1361
+ private parentElement;
1362
+ private resizeObserver;
1363
+ private width;
1364
+ private height;
1365
+ private currentConfig;
1366
+ private configHash;
1367
+ constructor(parentElement: HTMLElement, _options?: PostProcessOverlayOptions);
1368
+ /**
1369
+ * Handle container resize
1370
+ */
1371
+ private handleResize;
1372
+ /**
1373
+ * Set the post-processing configuration
1374
+ * Only re-renders if config actually changed
1375
+ */
1376
+ setConfig(config: PostProcessConfig | null): void;
1377
+ /**
1378
+ * Update scanlines configuration
1379
+ */
1380
+ setScanlines(config: ScanlinesConfig | null): void;
1381
+ /**
1382
+ * Enable/disable scanlines with default settings
1383
+ */
1384
+ setScanlinesEnabled(enabled: boolean): void;
1385
+ /**
1386
+ * Set scanlines opacity (0-1)
1387
+ */
1388
+ setScanlinesOpacity(opacity: number): void;
1389
+ /**
1390
+ * Set scanlines pattern
1391
+ */
1392
+ setScanlinesPattern(pattern: 'horizontal' | 'vertical' | 'grid'): void;
1393
+ /**
1394
+ * Set scanlines spacing (pixels between lines)
1395
+ */
1396
+ setScanlinesSpacing(spacing: number): void;
1397
+ /**
1398
+ * Get current configuration
1399
+ */
1400
+ getConfig(): PostProcessConfig | null;
1401
+ /**
1402
+ * Check if any effect is currently active
1403
+ */
1404
+ isActive(): boolean;
1405
+ /**
1406
+ * Cleanup resources
1407
+ */
1408
+ destroy(): void;
1409
+ /**
1410
+ * @deprecated No longer needed - overlay is independent of renderer
1411
+ */
1412
+ syncWithRenderer(_renderer: unknown): void;
1413
+ /**
1414
+ * @deprecated No longer needed - overlay handles its own resize
1415
+ */
1416
+ resize(_cols: number, _rows: number): void;
1417
+ /**
1418
+ * @deprecated No longer needed - overlay is independent
1419
+ */
1420
+ setCellDimensions(_cellWidth: number, _cellHeight: number): void;
1421
+ private show;
1422
+ private hide;
1423
+ private clear;
1424
+ private isActiveConfig;
1425
+ /**
1426
+ * Render all active effects to the canvas
1427
+ */
1428
+ private render;
1429
+ /**
1430
+ * Render scanlines pattern at native resolution
1431
+ *
1432
+ * Simply draws lines at fixed pixel intervals across the entire canvas.
1433
+ * Completely independent of terminal scaling.
1434
+ */
1435
+ private renderScanlines;
1436
+ /**
1437
+ * Create a hash of the config to detect changes
1438
+ */
1439
+ private hashConfig;
1440
+ }
1441
+
1131
1442
  /**
1132
1443
  * UTSP Render - Main entry point
1133
1444
  *
@@ -1137,5 +1448,5 @@ declare class AutoplayOverlay {
1137
1448
 
1138
1449
  declare const version = "0.1.0";
1139
1450
 
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 };
1451
+ export { AutoplayOverlay, BitmapFontAtlas, DEFAULT_PALETTE, GridOverlay, PostProcessOverlay, Terminal2D, TerminalGL, colorToPaletteIndex, paletteIndexToColor, version };
1452
+ export type { AutoplayOverlayOptions, BitmapFont$1 as BitmapFont, FontType, PostProcessOverlayOptions, RenderOptions, TerminalCell, TerminalData, TerminalGLOptions, WebGLCompatibilityReport };
package/dist/index.mjs CHANGED
@@ -1,29 +1,38 @@
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=`
1
+ var X=Object.defineProperty;var q=(y,t,e)=>t in y?X(y,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):y[t]=e;var x=(y,t)=>X(y,"name",{value:t,configurable:!0});var n=(y,t,e)=>(q(y,typeof t!="symbol"?t+"":t,e),e);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 j(y,t=U){return y<0||y>=t.length?"#ff00ff":t[y]}x(j,"paletteIndexToColor");function Q(y,t=U){let e=t.indexOf(y.toLowerCase());return e>=0?e:0}x(Q,"colorToPaletteIndex");var M=class M{constructor(t,e){n(this,"canvas");n(this,"ctx");n(this,"container");n(this,"cols",0);n(this,"rows",0);n(this,"cellWidth",0);n(this,"cellHeight",0);n(this,"offsetX",0);n(this,"offsetY",0);n(this,"strokeColor","rgba(80, 80, 80, 0.4)");n(this,"lineWidth",1);this.container=t,this.canvas=document.createElement("canvas"),this.canvas.className="grid-overlay-canvas";let s=e?.zIndex??10;this.canvas.style.cssText=`
2
+ display: block !important;
2
3
  position: absolute !important;
3
- top: 0 !important;
4
- left: 0 !important;
5
- width: 100% !important;
6
- height: 100% !important;
7
- object-fit: contain !important;
8
- z-index: ${i} !important;
9
4
  pointer-events: none !important;
10
5
  image-rendering: pixelated !important;
11
6
  image-rendering: crisp-edges !important;
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=`
7
+ z-index: ${s} !important;
8
+ `,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))}setDimensions(t,e,s,i,r=0,a=0){this.cols=t,this.rows=e,this.cellWidth=s,this.cellHeight=i,this.offsetX=r,this.offsetY=a}setCanvasSize(t,e){this.canvas.width=t,this.canvas.height=e,this.ctx.setTransform(1,0,0,1,0,0)}setStyle(t){t.strokeColor&&(this.strokeColor=t.strokeColor),t.lineWidth!==void 0&&(this.lineWidth=t.lineWidth)}setTransform(t,e,s,i,r){let a=i.left-r.left,l=i.top-r.top,o=i.width,h=i.height;(this.canvas.width!==o||this.canvas.height!==h)&&(this.canvas.width=o,this.canvas.height=h);let c=this.canvas.style;c.width=`${o}px`,c.height=`${h}px`,c.left=`${a}px`,c.top=`${l}px`}render(){if(!this.ctx)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,s=t>0?this.canvas.width/t:1,i=e>0?this.canvas.height/e:1,r=Math.min(s,i),a=this.cellWidth*r,l=this.cellHeight*r,o=this.cols*a,h=this.rows*l,c=this.offsetX*r,d=this.offsetY*r;if(!(o===0||h===0)){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.strokeStyle=this.strokeColor,this.ctx.lineWidth=Math.max(1,this.lineWidth*r),this.ctx.beginPath();for(let f=0;f<=this.cols;f++){let u=c+f*a+.5;this.ctx.moveTo(u,d),this.ctx.lineTo(u,d+h)}for(let f=0;f<=this.rows;f++){let u=d+f*l+.5;this.ctx.moveTo(c,u),this.ctx.lineTo(c+o,u)}this.ctx.stroke()}}update(t,e,s,i,r,a,l=0,o=0){this.setDimensions(t,e,s,i,l,o),this.setCanvasSize(r,a),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}};x(M,"GridOverlay");var T=M;import{POST_PROCESS_DEFAULTS as F,ScalingMode as A}from"@utsp/types";var B=class B{constructor(t,e){n(this,"canvas");n(this,"gl");n(this,"parentElement");n(this,"containerDiv");n(this,"cols");n(this,"rows");n(this,"charWidth");n(this,"charHeight");n(this,"cellWidth",8);n(this,"cellHeight",8);n(this,"glyphOffsetX",0);n(this,"glyphOffsetY",0);n(this,"canvasBgColor");n(this,"showGrid");n(this,"supportsUint32Indices",!1);n(this,"useUint16Indices",!1);n(this,"gridOverlay");n(this,"bitmapFont");n(this,"atlasTexture",null);n(this,"atlasCanvas");n(this,"atlasColumns",0);n(this,"paletteTexture",null);n(this,"program",null);n(this,"positionBuffer",null);n(this,"texCoordBuffer",null);n(this,"colorIndexBuffer",null);n(this,"indexBuffer",null);n(this,"aPosition");n(this,"aTexCoord");n(this,"aColorIndex");n(this,"uResolution",null);n(this,"uTexture",null);n(this,"uPalette",null);n(this,"resizeObserver");n(this,"charCodeToAtlasIndex",new Uint16Array(65536).fill(65535));n(this,"atlasUVs",new Float32Array(0));n(this,"cachedAtlasWidth",0);n(this,"cachedAtlasHeight",0);n(this,"paletteFloat",new Float32Array(256*4));n(this,"maxCells",0);n(this,"renderPositions",new Float32Array(0));n(this,"renderTexCoords",new Float32Array(0));n(this,"renderColorIndices",new Float32Array(0));n(this,"renderIndices",new Uint32Array(0));n(this,"cachedResolution",[0,0]);n(this,"cachedTextureUnit",-1);n(this,"cachedPaletteUnit",-1);n(this,"cachedTextureUniform",!1);n(this,"cachedPaletteUniform",!1);n(this,"paletteHash",0);n(this,"currentScale",1);n(this,"scalingMode",A.None);n(this,"ambientEffectEnabled",!1);n(this,"ambientEffectCanvas",null);n(this,"ambientEffectCtx",null);n(this,"ambientEffectBlur",F.ambientEffect.blur);n(this,"ambientEffectScale",F.ambientEffect.scale);n(this,"ambientEffectOpacity",.7);n(this,"onResizeCallback");n(this,"staticPositionsInitialized",!1);n(this,"vaoExtension",null);n(this,"vao",null);n(this,"instancedExtension",null);n(this,"useInstancing",!1);n(this,"instanceDataBuffer",null);n(this,"instanceData",new Float32Array(0));n(this,"templateQuadPositions",new Float32Array(0));n(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 s=e.cols*e.rows,i=B.checkCompatibility();if(i.errors.length>0)throw new Error(`TerminalGL: WebGL incompatible - ${i.errors.join(", ")}`);let r=e.forceUint16??!1;if(r&&s>i.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${e.cols}\xD7${e.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 ${e.cols}\xD7${e.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 ${e.cols}\xD7${e.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 a=e.charWidth??8,l=e.charHeight??8;if(!Number.isFinite(a)||a<=0)throw new Error(`TerminalGL: Invalid charWidth: ${a}. 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=a,this.charHeight=l,this.canvasBgColor=e.canvasBgColor!==void 0?e.canvasBgColor:null,this.showGrid=e.showGrid??!1,this.scalingMode=e.scalingMode??A.None,e.ambientEffect&&(this.ambientEffectEnabled=!0,typeof e.ambientEffect=="object"&&(this.ambientEffectBlur=e.ambientEffect.blur??F.ambientEffect.blur,this.ambientEffectScale=e.ambientEffect.scale??F.ambientEffect.scale,this.ambientEffectOpacity=e.ambientEffect.opacity??.7));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
9
  position: absolute !important;
14
10
  top: 0 !important;
15
11
  left: 0 !important;
12
+ right: 0 !important;
13
+ bottom: 0 !important;
16
14
  width: 100% !important;
17
15
  height: 100% !important;
18
- overflow: hidden !important;
16
+ overflow: visible !important;
17
+ contain: layout style !important;
18
+ display: flex !important;
19
+ justify-content: center !important;
20
+ align-items: center !important;
21
+ isolation: isolate !important;
19
22
  `,this.canvas=document.createElement("canvas"),this.canvas.className="terminalgl-webgl-canvas",this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.canvas.style.cssText=`
20
- position: absolute !important;
21
- top: 0 !important;
22
- left: 0 !important;
23
+ flex-shrink: 0 !important;
24
+ width: ${this.canvas.width}px !important;
25
+ height: ${this.canvas.height}px !important;
23
26
  image-rendering: pixelated !important;
24
27
  image-rendering: crisp-edges !important;
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=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=`
28
+ -ms-interpolation-mode: nearest-neighbor !important;
29
+ transform-origin: center center !important;
30
+ transform: scale(1) !important;
31
+ will-change: transform !important;
32
+ backface-visibility: hidden !important;
33
+ position: relative !important;
34
+ z-index: 1 !important;
35
+ `;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.ambientEffectEnabled&&(this.createAmbientEffectCanvas(),console.warn("[TerminalGL] \u{1F308} Ambient effect enabled at startup")),this.parentElement.appendChild(this.containerDiv),this.initRenderBuffers();try{this.initWebGL()}catch(c){throw console.error("[TerminalGL] \u274C Failed to initialize WebGL:",c),c}this.showGrid&&this.initGridOverlay(),this.setupResizeObserver()}static checkCompatibility(){let t={webgl1:!1,uint32Indices:!1,maxTextureSize:0,maxViewportDims:[0,0],maxCellsUint16:0,maxCellsUint32:0,recommendedMaxCells:0,warnings:[],errors:[]},e=document.createElement("canvas"),s=e.getContext("webgl")||e.getContext("experimental-webgl");if(!s||!(s instanceof WebGLRenderingContext))return t.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),t;let i=s;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 r=i.getExtension("OES_element_index_uint");t.uint32Indices=!!r;let a=8;if(t.maxCellsUint16=Math.floor(65535/a),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,s=this.glyphOffsetX,i=this.glyphOffsetY,r=this.charWidth,a=this.charHeight,l=0,o=0,h=0;for(let d=0;d<this.rows;d++){let f=Math.round(d*e),u=Math.round(f+e);for(let m=0;m<this.cols;m++){let b=Math.round(m*t),g=Math.round(b+t);this.renderPositions[l++]=b,this.renderPositions[l++]=f,this.renderPositions[l++]=g,this.renderPositions[l++]=f,this.renderPositions[l++]=b,this.renderPositions[l++]=u,this.renderPositions[l++]=g,this.renderPositions[l++]=u,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(b+s),w=Math.round(f+i),p=Math.round(C+r),E=Math.round(w+a);this.renderPositions[l++]=C,this.renderPositions[l++]=w,this.renderPositions[l++]=p,this.renderPositions[l++]=w,this.renderPositions[l++]=C,this.renderPositions[l++]=E,this.renderPositions[l++]=p,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
36
  // Per-vertex attributes (template quad)
28
37
  attribute vec2 aPosition; // Local quad position (0,0 to cellW,cellH)
29
38
 
@@ -84,7 +93,7 @@ var Y=Object.defineProperty;var $=(T,t,e)=>t in T?Y(T,t,{enumerable:!0,configura
84
93
  float paletteU = (aColorIndex + 0.5) / 256.0;
85
94
  vColor = texture2D(uPalette, vec2(paletteU, 0.5));
86
95
  }
87
- `;let i=`
96
+ `;let s=`
88
97
  precision mediump float;
89
98
 
90
99
  uniform sampler2D uTexture;
@@ -102,7 +111,18 @@ var Y=Object.defineProperty;var $=(T,t,e)=>t in T?Y(T,t,{enumerable:!0,configura
102
111
  gl_FragColor = vec4(vColor.rgb * texColor.a, texColor.a);
103
112
  }
104
113
  }
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=`
114
+ `,i=this.compileShader(t.VERTEX_SHADER,e),r=this.compileShader(t.FRAGMENT_SHADER,s);if(!i||!r)throw new Error("Shader compilation error");let a=t.createProgram();if(!a)throw new Error("Unable to create WebGL program");if(t.attachShader(a,i),t.attachShader(a,r),t.linkProgram(a),!t.getProgramParameter(a,t.LINK_STATUS)){let l=t.getProgramInfoLog(a);throw new Error("Program linking error: "+l)}this.program=a,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=t.getAttribLocation(a,"aPosition"),this.useInstancing?(this.aTexCoord=t.getAttribLocation(a,"aInstanceOffset"),this.aColorIndex=t.getAttribLocation(a,"aInstanceUVs"),this.instanceDataBuffer=t.createBuffer()):(this.aTexCoord=t.getAttribLocation(a,"aTexCoord"),this.aColorIndex=t.getAttribLocation(a,"aColorIndex")),this.uResolution=t.getUniformLocation(a,"uResolution"),this.uTexture=t.getUniformLocation(a,"uTexture"),this.uPalette=t.getUniformLocation(a,"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 s=this.gl,i=s.createShader(t);return i?(s.shaderSource(i,e),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 T(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let t=this.cols*this.cellWidth,e=this.rows*this.cellHeight,s=this.canvas.getBoundingClientRect(),i=this.containerDiv.getBoundingClientRect();this.gridOverlay.setDimensions(this.cols,this.rows,this.cellWidth,this.cellHeight,0,0),this.gridOverlay.setTransform(this.currentScale,t,e,s,i),this.gridOverlay.render()}setBitmapFont(t,e,s,i,r){this.bitmapFont=t,this.charWidth=Math.round(e),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(a){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",a),a}this.buildCharCodeMap(),this.precomputeAtlasUVs(),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}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 s=Math.ceil(e/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 a=this.atlasCanvas.getContext("2d");if(!a)throw new Error("Unable to create 2D context for atlas");a.clearRect(0,0,i,r),a.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,u=d*this.charHeight;for(let m=0;m<Math.min(h.length,this.charHeight);m++){let b=h[m];for(let g=0;g<this.charWidth;g++){let C=1<<7-g;b&C&&a.fillRect(f+g,u+m,1,1)}}l++}this.createAtlasTexture()}buildCharCodeMap(){if(!this.bitmapFont)return;this.charCodeToAtlasIndex.fill(65535);let t=Array.from(this.bitmapFont.keys()).sort((e,s)=>e-s);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,s=this.cachedAtlasHeight,i=.5/e,r=.5/s;for(let a=0;a<t;a++){let l=a%this.atlasColumns,o=Math.floor(a/this.atlasColumns),h=(l*this.charWidth+i)/e,c=(o*this.charHeight+r)/s,d=((l+1)*this.charWidth-i)/e,f=((o+1)*this.charHeight-r)/s,u=a*4;this.atlasUVs[u]=h,this.atlasUVs[u+1]=c,this.atlasUVs[u+2]=d,this.atlasUVs[u+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),s=0,i=0,r=0;return e.length===3?(s=parseInt(e[0]+e[0],16),i=parseInt(e[1]+e[1],16),r=parseInt(e[2]+e[2],16)):e.length===6&&(s=parseInt(e.slice(0,2),16),i=parseInt(e.slice(2,4),16),r=parseInt(e.slice(4,6),16)),[s/255,i/255,r/255,1]}if(t.startsWith("rgb")){let e=t.match(/rgba?\(([^)]+)\)/);if(e){let s=e[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(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 s=this.cols*this.cellWidth,i=this.rows*this.cellHeight;if(s===0||i===0)return;let r=t/s,a=e/i,l=Math.min(r,a),o;switch(this.scalingMode){case A.Integer:o=Math.max(1,Math.floor(l));break;case A.Half:o=Math.max(1,Math.floor(l*2)/2);break;case A.Quarter:o=Math.max(1,Math.floor(l*4)/4);break;case A.Eighth:o=Math.max(1,Math.floor(l*8)/8);break;case A.None:default:o=Math.max(.1,l);break}if(this.canvas.style.transform=`scale(${o})`,this.ambientEffectEnabled&&this.ambientEffectCanvas){let h=o*this.ambientEffectScale;this.ambientEffectCanvas.style.transform=`scale(${h})`}this.currentScale=o,this.onResizeCallback&&this.onResizeCallback(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}updateAmbientEffect(){!this.ambientEffectCanvas||!this.ambientEffectCtx||this.ambientEffectCtx.drawImage(this.canvas,0,0)}setPalette(t){let e=0;for(let s=0;s<Math.min(t.length,256);s++){let i=t[s];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 s=0;s<t.length&&s<256;s++){let i=t[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 t=this.gl;this.paletteTexture||(this.paletteTexture=t.createTexture()),t.bindTexture(t.TEXTURE_2D,this.paletteTexture);let e=new Uint8Array(256*4);for(let s=0;s<256;s++){let i=s*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),this.ambientEffectEnabled&&this.ambientEffectCanvas&&this.ambientEffectCtx&&this.updateAmbientEffect()}catch(e){console.error("[TerminalGL] \u274C Error rendering display data:",e)}}renderDirect(t){let e=this.gl;if(!this.staticPositionsInitialized&&!this.useInstancing&&this.precomputeStaticPositions(),this.canvasBgColor!==null){let s=this.parseColor(this.canvasBgColor);e.clearColor(s[0],s[1],s[2],s[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,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(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 r=0,a=this.instanceData.length/8;for(let f=0;f<t.height;f++)for(let u=0;u<t.width;u++){let m=t.cells[f*t.width+u],b=m.bgColorIndex,g=m.fgColorIndex,C=this.canvasBgColor!==null&&b===255,w=m.char===" "||g===255;if(!C){if(r>=a){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${r}, max=${a}`);break}let p=r*8;this.instanceData[p]=u,this.instanceData[p+1]=f,this.instanceData[p+2]=0,this.instanceData[p+3]=0,this.instanceData[p+4]=0,this.instanceData[p+5]=0,this.instanceData[p+6]=b,this.instanceData[p+7]=0,r++}if(!w){let p=m.char.charCodeAt(0),E=this.charCodeToAtlasIndex[p];if(E!==65535){if(r>=a){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${r}, max=${a}`);break}let R=E*4,v=r*8;this.instanceData[v]=u,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]=g,r++}}}if(r===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,r*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),s.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),s.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),s.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),s.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),s.drawElementsInstancedANGLE(e.TRIANGLES,6,e.UNSIGNED_SHORT,0,r),s.vertexAttribDivisorANGLE(this.aPosition,0),s.vertexAttribDivisorANGLE(o,0),s.vertexAttribDivisorANGLE(h,0),s.vertexAttribDivisorANGLE(c,0)}renderDirectBuffers(t){let e=this.gl,s=t.width*t.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,a=0,l=t.cells,o=s;for(let m=0;m<o;m++){let b=l[m],g=b.bgColorIndex,w=this.canvasBgColor!==null&&g===255?255:g,p=0;for(let v=0;v<4;v++)this.renderTexCoords[r++]=p,this.renderTexCoords[r++]=p,this.renderColorIndices[a++]=w;let E=b.fgColorIndex,R=b.char;if(R===" "||E===255)for(let v=0;v<4;v++)this.renderTexCoords[r++]=0,this.renderTexCoords[r++]=0,this.renderColorIndices[a++]=255;else{let v=R.charCodeAt(0),k=this.charCodeToAtlasIndex[v];if(k!==65535){let I=k*4,$=this.atlasUVs[I],Y=this.atlasUVs[I+1],N=this.atlasUVs[I+2],V=this.atlasUVs[I+3];this.renderTexCoords[r++]=$,this.renderTexCoords[r++]=Y,this.renderColorIndices[a++]=E,this.renderTexCoords[r++]=N,this.renderTexCoords[r++]=Y,this.renderColorIndices[a++]=E,this.renderTexCoords[r++]=$,this.renderTexCoords[r++]=V,this.renderColorIndices[a++]=E,this.renderTexCoords[r++]=N,this.renderTexCoords[r++]=V,this.renderColorIndices[a++]=E}else for(let I=0;I<4;I++)this.renderTexCoords[r++]=0,this.renderTexCoords[r++]=0,this.renderColorIndices[a++]=255}}(r!==o*2*4*2||a!==o*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:r,colorIdx:a,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,r)),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferSubData(e.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,a))):(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,r)),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,a)),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,u=this.useUint16Indices?e.UNSIGNED_SHORT:e.UNSIGNED_INT;e.drawElements(e.TRIANGLES,f,u,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 s=t*e,i=this.useUint16Indices?8191:262144;if(s>i){let c=Math.floor(Math.sqrt(i));console.error(`[TerminalGL] \u274C Cannot resize to ${t}\xD7${e} (${s} cells). Device limit: ${i} cells (max ~${c}\xD7${c}). ${this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let r=B.checkCompatibility();s>r.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${t}\xD7${e} (${s} cells) exceeds recommended limit (${r.recommendedMaxCells} cells). Performance may degrade.`),this.cols=t,this.rows=e,this.staticPositionsInitialized=!1;let a=this.cols*this.rows*2,l=Math.ceil(a*1.5),o=a>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",u=c*160/1048576,m=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${f} buffers: ${u.toFixed(2)}MB \u2192 ${m.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.ambientEffectEnabled&&this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.width=`${this.canvas.width}px`,this.ambientEffectCanvas.style.height=`${this.canvas.height}px`),this.showGrid&&this.gridOverlay&&this.updateGridOverlay(),this.updateCanvasSize()}getCanvas(){return this.canvas}getGridSize(){return{cols:this.cols,rows:this.rows}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getBaseDimensions(){return{width:this.cols*this.cellWidth,height:this.rows*this.cellHeight}}setOnResizeCallback(t){this.onResizeCallback=t}clearOnResizeCallback(){this.onResizeCallback=void 0}setScalingMode(t){this.scalingMode!==t&&(this.scalingMode=t,this.updateCanvasSize())}getScalingMode(){return this.scalingMode}setGrid(t){t.enabled?(this.gridOverlay?this.gridOverlay.setStyle({strokeColor:t.color,lineWidth:t.lineWidth}):this.gridOverlay=new T(this.containerDiv,{strokeColor:t.color??"rgba(144, 24, 24, 1)",lineWidth:t.lineWidth??1,zIndex:10}),this.showGrid=!0,this.gridOverlay.setVisible(!0),this.updateGridOverlay()):(this.showGrid=!1,this.gridOverlay&&this.gridOverlay.setVisible(!1))}isGridEnabled(){return this.showGrid}setAmbientEffect(t){typeof t=="boolean"?this.ambientEffectEnabled=t:(this.ambientEffectEnabled=!0,t.blur!==void 0&&(this.ambientEffectBlur=t.blur),t.scale!==void 0&&(this.ambientEffectScale=t.scale)),this.ambientEffectEnabled&&!this.ambientEffectCanvas&&this.createAmbientEffectCanvas(),this.ambientEffectCanvas&&(this.ambientEffectEnabled?(this.ambientEffectCanvas.style.display="block",this.ambientEffectCanvas.style.filter=`blur(${this.ambientEffectBlur}px)`,this.ambientEffectCanvas.style.transform=`scale(${this.ambientEffectScale})`,this.updateAmbientEffect()):this.ambientEffectCanvas.style.display="none")}createAmbientEffectCanvas(){this.ambientEffectCanvas||(this.ambientEffectCanvas=document.createElement("canvas"),this.ambientEffectCanvas.className="terminalgl-ambient-effect-canvas",this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.cssText=`
115
+ display: block !important;
116
+ position: absolute !important;
117
+ width: ${this.canvas.width}px !important;
118
+ height: ${this.canvas.height}px !important;
119
+ filter: blur(${this.ambientEffectBlur}px) !important;
120
+ opacity: ${this.ambientEffectOpacity} !important;
121
+ transform-origin: center center !important;
122
+ transform: scale(${this.ambientEffectScale}) !important;
123
+ pointer-events: none !important;
124
+ z-index: 0 !important;
125
+ `,this.ambientEffectCtx=this.ambientEffectCanvas.getContext("2d",{alpha:!0}),this.containerDiv.insertBefore(this.ambientEffectCanvas,this.canvas),console.warn("[TerminalGL] \u{1F308} ambient effect canvas created dynamically"))}isAmbientEffectEnabled(){return this.ambientEffectEnabled}getAmbientEffectConfig(){return{enabled:this.ambientEffectEnabled,blur:this.ambientEffectBlur,scale:this.ambientEffectScale}}getCols(){return this.cols}getRows(){return this.rows}isReady(){return!!(this.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.ambientEffectCanvas&&(this.ambientEffectCanvas.width=0,this.ambientEffectCanvas.height=0,this.ambientEffectCanvas=null),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.renderPositions=new Float32Array(0),this.renderTexCoords=new Float32Array(0),this.renderColorIndices=new Float32Array(0),this.renderIndices=new Uint32Array(0),this.paletteFloat=new Float32Array(0),this.atlasUVs=new Float32Array(0),this.instanceData=new Float32Array(0),this.templateQuadPositions=new Float32Array(0),this.templateQuadIndices=new Uint16Array(0)}};x(B,"TerminalGL");var L=B;var _=class _{constructor(t,e,s,i,r){n(this,"atlases");n(this,"charMap");n(this,"baseCharWidth");n(this,"baseCharHeight");n(this,"baseCellWidth");n(this,"baseCellHeight");n(this,"atlasColumns",16);n(this,"font");n(this,"SCALES",[1,2,4,8]);n(this,"colorCache",new Map);n(this,"MAX_CACHE_SIZE",512);this.font=t,this.baseCharWidth=e,this.baseCharHeight=s,this.baseCellWidth=i??e,this.baseCellHeight=r??s,this.charMap=new Map,this.atlases=new Map,this.generateAtlases()}generateAtlases(){this.atlasColumns=16;let t=0;for(let[e,s]of this.font){let i=t%this.atlasColumns,r=Math.floor(t/this.atlasColumns);this.charMap.set(e,{x:i*this.baseCharWidth,y:r*this.baseCharHeight});for(let a of this.SCALES){let l=this.getOrCreateAtlas(a),o=i*l.charWidth,h=r*l.charHeight;this.renderBitmapToAtlas(l,s,o,h)}t++}}getOrCreateAtlas(t){let e=this.atlases.get(t);if(!e){let s=this.baseCharWidth*t,i=this.baseCharHeight*t,a=Math.ceil(256/this.atlasColumns),l=document.createElement("canvas");l.width=this.atlasColumns*s,l.height=a*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:s,charHeight:i},this.atlases.set(t,e)}return e}renderBitmapToAtlas(t,e,s,i){let r=t.scale,a=t.ctx;a.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&&a.fillRect(s+h*r,i+l*r,r,r)}}}drawChar(t,e,s,i,r,a,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=r/this.baseCellWidth,f=a/this.baseCellHeight,u=(this.baseCellWidth-this.baseCharWidth)/2*d,m=(this.baseCellHeight-this.baseCharHeight)/2*f,b=this.baseCharWidth*d,g=this.baseCharHeight*f;t.drawImage(c.canvas,s+u,i+m,b,g)}createColoredGlyph(t,e,s){let i=this.atlases.get(1);if(!i)return null;let r=i.ctx.getImageData(s.x,s.y,this.baseCharWidth,this.baseCharHeight),a=r.data,l=this.hexToRgb(e);for(let c=0;c<a.length;c+=4)a[c+3]>0&&(a[c]=l.r,a[c+1]=l.g,a[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(t){if(t.startsWith("#")){let r=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(r,(l,o,h,c)=>o+o+h+h+c+c);let a=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return a?{r:parseInt(a[1],16),g:parseInt(a[2],16),b:parseInt(a[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[s,i]of this.colorCache)i.lastUsed<e&&(e=i.lastUsed,t=s);if(t){let s=this.colorCache.get(t);s&&(s.canvas.width=0,s.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()}};x(_,"BitmapFontAtlas");var D=_;var W=class W{constructor(t,e={}){n(this,"canvas");n(this,"ctx");n(this,"parentElement");n(this,"cells");n(this,"cols",0);n(this,"rows",0);n(this,"fontSize");n(this,"fontFamily");n(this,"defaultFgColor");n(this,"defaultBgColor");n(this,"canvasBgColor");n(this,"cellWidth");n(this,"cellHeight");n(this,"offsetX",0);n(this,"offsetY",0);n(this,"fontType","web");n(this,"bitmapFont");n(this,"bitmapAtlas");n(this,"bitmapCharWidth",8);n(this,"bitmapCharHeight",8);n(this,"showDebugGrid");n(this,"debugGridColor");n(this,"gridOverlay");n(this,"fixedGridMode");n(this,"fixedCols");n(this,"fixedRows");n(this,"cellAspectRatio");n(this,"resizeObserver");n(this,"imageDataBuffer");n(this,"useImageDataRendering",!1);n(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 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 T(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;if(this.fixedGridMode&&this.fixedCols&&this.fixedRows)if(this.cols=this.fixedCols,this.rows=this.fixedRows,this.fontType==="bitmap"){let a=t/this.cols,l=e/this.rows,o=this.bitmapCharWidth/this.bitmapCharHeight;a/l>o?(this.cellHeight=Math.floor(l),this.cellWidth=Math.floor(this.cellHeight*o)):(this.cellWidth=Math.floor(a),this.cellHeight=Math.floor(this.cellWidth/o))}else{let a=t/this.cols,l=e/this.rows;a/l>this.cellAspectRatio?(this.cellHeight=Math.floor(l*100)/100,this.cellWidth=Math.floor(this.cellHeight*this.cellAspectRatio*100)/100):(this.cellWidth=Math.floor(a*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 s=this.cols*this.cellWidth,i=this.rows*this.cellHeight;this.offsetX=Math.floor((t-s)/2),this.offsetY=Math.floor((e-i)/2);let r=window.devicePixelRatio||1;this.canvas.style.width=`${t}px`,this.canvas.style.height=`${e}px`,this.canvas.width=t*r,this.canvas.height=e*r,this.ctx.scale(r,r)}createEmptyGrid(){let t=[];for(let e=0;e<this.rows;e++){let s=[];for(let i=0;i<this.cols;i++)s.push({char:" ",fgColor:this.defaultFgColor,bgColor:this.defaultBgColor});t.push(s)}return t}enableAutoResize(){this.resizeObserver=new ResizeObserver(()=>{let t=this.cols,e=this.rows;if(this.calculateGridSize(),this.cols!==t||this.rows!==e){let s=this.cells;this.cells=this.createEmptyGrid();let i=Math.min(t,this.cols),r=Math.min(e,this.rows);for(let a=0;a<r;a++)for(let l=0;l<i;l++)this.cells[a][l]=s[a][l]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(t,e,s,i,r){if(e<0||e>=this.rows||t<0||t>=this.cols)return;let a=s&&typeof s=="string"?s.charAt(0):" ";this.cells[e][t]={char:a,fgColor:i??this.defaultFgColor,bgColor:r??this.defaultBgColor}}getCell(t,e){return e<0||e>=this.rows||t<0||t>=this.cols?null:this.cells[e][t]}write(t,e,s,i,r){for(let a=0;a<s.length;a++)this.setCell(t+a,e,s[a],i,r)}fillRect(t,e,s,i,r=" ",a,l){for(let o=e;o<e+i;o++)for(let h=t;h<t+s;h++)this.setCell(h,o,r,a,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 s=0;for(let i=0;i<t.height;i++)for(let r=0;r<t.width;r++){let a=t.cells[s];i<this.rows&&r<this.cols&&this.setCell(r,i,a.char,a.fgColor,a.bgColor),s++}}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 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),u=c.char.charCodeAt(0),m=this.bitmapFont.get(u);for(let b=0;b<this.bitmapCharHeight;b++)for(let g=0;g<this.bitmapCharWidth;g++){let C=h*this.bitmapCharWidth+g,p=((o*this.bitmapCharHeight+b)*t+C)*4,E=!1;if(m&&b<m.length){let R=m[b],v=1<<7-g;E=(R&v)!==0}E?(s[p]=f.r,s[p+1]=f.g,s[p+2]=f.b,s[p+3]=f.a):(s[p]=d.r,s[p+1]=d.g,s[p+2]=d.b,s[p+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 a=this.cols*this.cellWidth,l=this.rows*this.cellHeight;this.ctx.drawImage(i,0,0,t,e,this.offsetX,this.offsetY,a,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 r=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(r,(l,o,h,c)=>o+o+h+h+c+c);let a=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);if(a)return{r:parseInt(a[1],16),g:parseInt(a[2],16),b:parseInt(a[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 s=this.cells[t][e],i=Math.floor(this.offsetX+e*this.cellWidth),r=Math.floor(this.offsetY+t*this.cellHeight),a=Math.floor(this.offsetX+(e+1)*this.cellWidth),l=Math.floor(this.offsetY+(t+1)*this.cellHeight),o=a-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(t,e,s,i,r,a){let l=t.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,l,e,s,i,r,a);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=a;for(let d=0;d<Math.min(o.length,this.bitmapCharHeight);d++){let f=o[d],u=s+d*c,m=s+(d+1)*c;for(let b=0;b<this.bitmapCharWidth;b++){let g=1<<7-b;if(f&g){let C=e+b*h,w=e+(b+1)*h;this.ctx.fillRect(C,u,w-C,m-u)}}}}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 T(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10}),this.drawDebugGrid()):!t&&this.gridOverlay?(this.gridOverlay.destroy(),this.gridOverlay=void 0):t&&this.gridOverlay&&this.gridOverlay.setVisible(!0)}setCanvasBackgroundColor(t){this.canvasBgColor=t}getCanvasBackgroundColor(){return this.canvasBgColor}setFixedGrid(t,e,s){this.fixedGridMode=!0,this.fixedCols=t,this.fixedRows=e,s!==void 0&&(this.cellAspectRatio=s);let i=this.cols,r=this.rows,a=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]=a[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 s=this.cols,i=this.rows,r=this.cells;if(this.calculateGridSize(),this.cols!==s||this.rows!==i){this.cells=this.createEmptyGrid();let a=Math.min(s,this.cols),l=Math.min(i,this.rows);for(let o=0;o<l;o++)for(let h=0;h<a;h++)this.cells[o][h]=r[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,s,i,r){this.fontType="bitmap",this.bitmapFont=t,this.bitmapCharWidth=e,this.bitmapCharHeight=s,this.bitmapAtlas=new D(t,e,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(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 s=x(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 r=e[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<t.height&&i<this.rows;i++)for(let r=0;r<t.width&&r<this.cols;r++){let a=i*t.width+r;if(a>=t.cells.length)break;let l=t.cells[a];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(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)}};x(W,"Terminal2D");var G=W;var O=class O{constructor(t,e={}){n(this,"container");n(this,"overlayDiv",null);n(this,"button",null);n(this,"options");n(this,"started",!1);n(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
126
  position: absolute !important;
107
127
  top: 0 !important;
108
128
  left: 0 !important;
@@ -126,4 +146,22 @@ var Y=Object.defineProperty;var $=(T,t,e)=>t in T?Y(T,t,{enumerable:!0,configura
126
146
  cursor: pointer !important;
127
147
  transition: background-color 0.2s ease, transform 0.1s ease !important;
128
148
  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};
149
+ `,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}};x(O,"AutoplayOverlay");var P=O;import{POST_PROCESS_DEFAULTS as S}from"@utsp/types";var z=class z{constructor(t,e){n(this,"canvas");n(this,"ctx");n(this,"containerDiv");n(this,"parentElement");n(this,"resizeObserver");n(this,"width",0);n(this,"height",0);n(this,"currentConfig",null);n(this,"configHash","");this.parentElement=t,this.containerDiv=document.createElement("div"),this.containerDiv.className="postprocess-container",this.containerDiv.style.cssText=`
150
+ position: absolute !important;
151
+ top: 0 !important;
152
+ left: 0 !important;
153
+ right: 0 !important;
154
+ bottom: 0 !important;
155
+ width: 100% !important;
156
+ height: 100% !important;
157
+ pointer-events: none !important;
158
+ z-index: 10 !important;
159
+ overflow: hidden !important;
160
+ `,this.canvas=document.createElement("canvas"),this.canvas.className="postprocess-canvas",this.canvas.style.cssText=`
161
+ position: absolute !important;
162
+ top: 0 !important;
163
+ left: 0 !important;
164
+ width: 100% !important;
165
+ height: 100% !important;
166
+ pointer-events: none !important;
167
+ `;let s=this.canvas.getContext("2d",{alpha:!0});if(!s)throw new Error("PostProcessOverlay: Failed to get 2D context");this.ctx=s,this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv),this.resizeObserver=new ResizeObserver(r=>{for(let a of r){let{width:l,height:o}=a.contentRect;l>0&&o>0&&this.handleResize(Math.floor(l),Math.floor(o))}}),this.resizeObserver.observe(this.parentElement);let i=this.parentElement.getBoundingClientRect();i.width>0&&i.height>0&&this.handleResize(Math.floor(i.width),Math.floor(i.height)),this.hide()}handleResize(t,e){this.width===t&&this.height===e||(this.width=t,this.height=e,this.canvas.width=t,this.canvas.height=e,this.currentConfig&&this.isActive()&&this.render())}setConfig(t){let e=this.hashConfig(t);if(e!==this.configHash){if(this.currentConfig=t,this.configHash=e,!t||!this.isActiveConfig(t)){this.clear(),this.hide();return}this.show(),this.render()}}setScanlines(t){t===null?this.setConfig({scanlines:{enabled:!1}}):this.setConfig({scanlines:t})}setScanlinesEnabled(t){if(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:!0,opacity:e?.opacity??S.scanlines.opacity,pattern:e?.pattern??"horizontal",spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}else this.setScanlines({enabled:!1})}setScanlinesOpacity(t){let e=Math.max(0,Math.min(1,t)),s=this.currentConfig?.scanlines;this.setScanlines({enabled:s?.enabled??!0,opacity:e,pattern:s?.pattern??"horizontal",spacing:s?.spacing??2,thickness:s?.thickness??1,color:s?.color??{r:0,g:0,b:0}})}setScanlinesPattern(t){let e=this.currentConfig?.scanlines;this.setScanlines({enabled:e?.enabled??!0,opacity:e?.opacity??S.scanlines.opacity,pattern:t,spacing:e?.spacing??2,thickness:e?.thickness??1,color:e?.color??{r:0,g:0,b:0}})}setScanlinesSpacing(t){let e=Math.max(2,Math.round(t)),s=this.currentConfig?.scanlines;this.setScanlines({enabled:s?.enabled??!0,opacity:s?.opacity??S.scanlines.opacity,pattern:s?.pattern??"horizontal",spacing:e,thickness:s?.thickness??1,color:s?.color??{r:0,g:0,b:0}})}getConfig(){return this.currentConfig}isActive(){return this.isActiveConfig(this.currentConfig)}destroy(){this.resizeObserver.disconnect(),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}syncWithRenderer(t){}resize(t,e){}setCellDimensions(t,e){}show(){this.containerDiv.style.display="block"}hide(){this.containerDiv.style.display="none"}clear(){this.ctx.clearRect(0,0,this.width,this.height)}isActiveConfig(t){return t?.scanlines?.enabled??!1}render(){this.clear(),this.currentConfig?.scanlines?.enabled&&this.renderScanlines(this.currentConfig.scanlines)}renderScanlines(t){let e=t.opacity??S.scanlines.opacity,s=t.pattern??"horizontal",i=t.spacing??2,r=t.thickness??1,a=t.color??{r:0,g:0,b:0},l=this.ctx;switch(l.fillStyle=`rgba(${a.r}, ${a.g}, ${a.b}, ${e})`,s){case"horizontal":for(let o=i-1;o<this.height;o+=i)l.fillRect(0,o,this.width,r);break;case"vertical":for(let o=i-1;o<this.width;o+=i)l.fillRect(o,0,r,this.height);break;case"grid":for(let o=i-1;o<this.height;o+=i)l.fillRect(0,o,this.width,r);for(let o=i-1;o<this.width;o+=i)l.fillRect(o,0,r,this.height);break}}hashConfig(t){return t?JSON.stringify(t):"null"}};x(z,"PostProcessOverlay");var H=z;var gt="0.1.0";export{P as AutoplayOverlay,D as BitmapFontAtlas,U as DEFAULT_PALETTE,T as GridOverlay,H as PostProcessOverlay,A as ScalingMode,G as Terminal2D,L as TerminalGL,Q as colorToPaletteIndex,j as paletteIndexToColor,gt as version};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utsp/render",
3
- "version": "0.7.0-nightly.20251207021518.b0c5521",
3
+ "version": "0.7.0",
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.7.0-nightly.20251207021518.b0c5521"
52
+ "@utsp/types": "0.7.0"
53
53
  },
54
54
  "devDependencies": {
55
55
  "typescript": "^5.6.3"