@utsp/render 0.10.0 → 0.11.0-nightly.20251213232121.8b318c1

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.
@@ -0,0 +1,127 @@
1
+ var k=Object.defineProperty;var V=(b,e,t)=>e in b?k(b,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):b[e]=t;var C=(b,e)=>k(b,"name",{value:e,configurable:!0});var n=(b,e,t)=>(V(b,typeof e!="symbol"?e+"":e,t),t);var F=class F{constructor(e,t){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=e,this.canvas=document.createElement("canvas"),this.canvas.className="grid-overlay-canvas";let r=t?.zIndex??10;this.canvas.style.cssText=`
2
+ display: block !important;
3
+ position: absolute !important;
4
+ pointer-events: none !important;
5
+ image-rendering: pixelated !important;
6
+ image-rendering: crisp-edges !important;
7
+ z-index: ${r} !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,t&&(t.strokeColor&&(this.strokeColor=t.strokeColor),t.lineWidth!==void 0&&(this.lineWidth=t.lineWidth))}setDimensions(e,t,r,i,s=0,a=0){this.cols=e,this.rows=t,this.cellWidth=r,this.cellHeight=i,this.offsetX=s,this.offsetY=a}setCanvasSize(e,t){this.canvas.width=e,this.canvas.height=t,this.ctx.setTransform(1,0,0,1,0,0)}setStyle(e){e.strokeColor&&(this.strokeColor=e.strokeColor),e.lineWidth!==void 0&&(this.lineWidth=e.lineWidth)}setTransform(e,t,r,i,s){let a=i.left-s.left,l=i.top-s.top,o=i.width,c=i.height;(this.canvas.width!==o||this.canvas.height!==c)&&(this.canvas.width=o,this.canvas.height=c);let d=this.canvas.style;d.width=`${o}px`,d.height=`${c}px`,d.left=`${a}px`,d.top=`${l}px`}render(){if(!this.ctx)return;let e=this.cols*this.cellWidth,t=this.rows*this.cellHeight,r=e>0?this.canvas.width/e:1,i=t>0?this.canvas.height/t:1,s=Math.min(r,i),a=this.cellWidth*s,l=this.cellHeight*s,o=this.cols*a,c=this.rows*l,d=this.offsetX*s,h=this.offsetY*s;if(!(o===0||c===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*s),this.ctx.beginPath();for(let f=0;f<=this.cols;f++){let u=d+f*a+.5;this.ctx.moveTo(u,h),this.ctx.lineTo(u,h+c)}for(let f=0;f<=this.rows;f++){let u=h+f*l+.5;this.ctx.moveTo(d,u),this.ctx.lineTo(d+o,u)}this.ctx.stroke()}}update(e,t,r,i,s,a,l=0,o=0){this.setDimensions(e,t,r,i,l,o),this.setCanvasSize(s,a),this.render()}setVisible(e){this.canvas.style.display=e?"block":"none"}destroy(){this.canvas.parentElement&&this.canvas.parentElement.removeChild(this.canvas)}getCanvas(){return this.canvas}};C(F,"GridOverlay");var I=F;function L(b){return Math.sqrt(b)*16}C(L,"getAtlasColumns");function _(b){return b*256-1}C(_,"getMaxCharCode");function D(b,e){let t=Math.floor(b/256),r=b%256,i=Math.sqrt(e),s=t%i,a=Math.floor(t/i),l=r%16,o=Math.floor(r/16);return{col:s*16+l,row:a*16+o}}C(D,"getCharGridPosition");import{POST_PROCESS_DEFAULTS as B,ScalingMode as T}from"@utsp/types";var U=class U{constructor(e,t){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,"fontLoaded",!1);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",T.None);n(this,"ambientEffectEnabled",!1);n(this,"ambientEffectCanvas",null);n(this,"ambientEffectCtx",null);n(this,"ambientEffectBlur",B.ambientEffect.blur);n(this,"ambientEffectScale",B.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(!e)throw new Error("TerminalGL: Parent element is required");if(!Number.isInteger(t.cols)||t.cols<=0)throw new Error(`TerminalGL: Invalid cols: ${t.cols}. Must be a positive integer.`);if(!Number.isInteger(t.rows)||t.rows<=0)throw new Error(`TerminalGL: Invalid rows: ${t.rows}. Must be a positive integer.`);let r=t.cols*t.rows,i=U.checkCompatibility();if(i.errors.length>0)throw new Error(`TerminalGL: WebGL incompatible - ${i.errors.join(", ")}`);let s=t.forceUint16??!1;if(s&&r>i.maxCellsUint16)throw new Error(`TerminalGL: Terminal size ${t.cols}\xD7${t.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 ${t.cols}\xD7${t.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 ${t.cols}\xD7${t.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 a=t.charWidth??8,l=t.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=e,this.cols=t.cols,this.rows=t.rows,this.charWidth=a,this.charHeight=l,this.canvasBgColor=t.canvasBgColor!==void 0?t.canvasBgColor:null,this.showGrid=t.showGrid??!1,this.scalingMode=t.scalingMode??T.None,t.ambientEffect&&(this.ambientEffectEnabled=!0,typeof t.ambientEffect=="object"&&(this.ambientEffectBlur=t.ambientEffect.blur??B.ambientEffect.blur,this.ambientEffectScale=t.ambientEffect.scale??B.ambientEffect.scale,this.ambientEffectOpacity=t.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=`
9
+ position: absolute !important;
10
+ top: 0 !important;
11
+ left: 0 !important;
12
+ right: 0 !important;
13
+ bottom: 0 !important;
14
+ width: 100% !important;
15
+ height: 100% !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;
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=`
23
+ flex-shrink: 0 !important;
24
+ width: ${this.canvas.width}px !important;
25
+ height: ${this.canvas.height}px !important;
26
+ image-rendering: pixelated !important;
27
+ image-rendering: crisp-edges !important;
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 c=this.canvas.getContext("webgl",{alpha:this.canvasBgColor===null,premultipliedAlpha:!1});if(!c)throw new Error("TerminalGL: WebGL not supported");this.gl=c,this.supportsUint32Indices=!!c.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=c.getExtension("OES_vertex_array_object"),this.vaoExtension&&console.warn("[TerminalGL] \u2705 VAO extension enabled (faster attribute binding)"),this.instancedExtension=c.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(d){throw console.error("[TerminalGL] \u274C Failed to initialize WebGL:",d),d}this.showGrid&&this.initGridOverlay(),this.setupResizeObserver()}static checkCompatibility(){let e={webgl1:!1,uint32Indices:!1,maxTextureSize:0,maxViewportDims:[0,0],maxCellsUint16:0,maxCellsUint32:0,recommendedMaxCells:0,warnings:[],errors:[]},t=document.createElement("canvas"),r=t.getContext("webgl")||t.getContext("experimental-webgl");if(!r||!(r instanceof WebGLRenderingContext))return e.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),e;let i=r;e.webgl1=!0;try{e.maxTextureSize=i.getParameter(i.MAX_TEXTURE_SIZE);let o=i.getParameter(i.MAX_VIEWPORT_DIMS);e.maxViewportDims=[o[0],o[1]]}catch(o){return e.errors.push(`\u274C Failed to query WebGL parameters: ${o}`),e}let s=i.getExtension("OES_element_index_uint");e.uint32Indices=!!s;let a=8;if(e.maxCellsUint16=Math.floor(65535/a),e.uint32Indices){let o=Math.floor(e.maxTextureSize*e.maxTextureSize/64);e.maxCellsUint32=Math.min(o,262144)}else e.maxCellsUint32=e.maxCellsUint16,e.warnings.push(`\u26A0\uFE0F OES_element_index_uint not supported - limited to ${e.maxCellsUint16} cells (e.g., 90\xD790 or 127\xD764)`);return e.recommendedMaxCells=Math.floor((e.uint32Indices?e.maxCellsUint32:e.maxCellsUint16)*.8),e.maxTextureSize<256?e.errors.push(`\u274C MAX_TEXTURE_SIZE too small: ${e.maxTextureSize} (minimum 256 required for font atlas)`):e.maxTextureSize<2048&&e.warnings.push(`\u26A0\uFE0F Small MAX_TEXTURE_SIZE: ${e.maxTextureSize} (may limit font atlas)`),(e.maxViewportDims[0]<1024||e.maxViewportDims[1]<768)&&e.warnings.push(`\u26A0\uFE0F Small MAX_VIEWPORT_DIMS: ${e.maxViewportDims[0]}\xD7${e.maxViewportDims[1]}`),i.getExtension("WEBGL_lose_context")||e.warnings.push("\u26A0\uFE0F WEBGL_lose_context not supported - may cause memory leaks"),e}initInstancedBuffers(){let e=this.gl;this.templateQuadPositions=new Float32Array([0,0,this.cellWidth,0,0,this.cellHeight,this.cellWidth,this.cellHeight]),this.templateQuadIndices=new Uint16Array([0,1,2,2,1,3]),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.bufferData(e.ARRAY_BUFFER,this.templateQuadPositions,e.STATIC_DRAW),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),e.bufferData(e.ELEMENT_ARRAY_BUFFER,this.templateQuadIndices,e.STATIC_DRAW);let t=this.cols*this.rows*2;this.instanceData=new Float32Array(t*8),e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer),e.bufferData(e.ARRAY_BUFFER,this.instanceData.byteLength,e.DYNAMIC_DRAW)}initRenderBuffers(){this.maxCells=this.cols*this.rows*2,this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.staticPositionsInitialized=!1}precomputeStaticPositions(){let e=this.cellWidth,t=this.cellHeight,r=this.glyphOffsetX,i=this.glyphOffsetY,s=this.charWidth,a=this.charHeight,l=0,o=0,c=0;for(let h=0;h<this.rows;h++){let f=Math.round(h*t),u=Math.round(f+t);for(let m=0;m<this.cols;m++){let p=Math.round(m*e),g=Math.round(p+e);this.renderPositions[l++]=p,this.renderPositions[l++]=f,this.renderPositions[l++]=g,this.renderPositions[l++]=f,this.renderPositions[l++]=p,this.renderPositions[l++]=u,this.renderPositions[l++]=g,this.renderPositions[l++]=u,this.renderIndices[o++]=c,this.renderIndices[o++]=c+1,this.renderIndices[o++]=c+2,this.renderIndices[o++]=c+2,this.renderIndices[o++]=c+1,this.renderIndices[o++]=c+3,c+=4;let A=Math.round(p+r),R=Math.round(f+i),v=Math.round(A+s),E=Math.round(R+a);this.renderPositions[l++]=A,this.renderPositions[l++]=R,this.renderPositions[l++]=v,this.renderPositions[l++]=R,this.renderPositions[l++]=A,this.renderPositions[l++]=E,this.renderPositions[l++]=v,this.renderPositions[l++]=E,this.renderIndices[o++]=c,this.renderIndices[o++]=c+1,this.renderIndices[o++]=c+2,this.renderIndices[o++]=c+2,this.renderIndices[o++]=c+1,this.renderIndices[o++]=c+3,c+=4}}let d=this.gl;d.bindBuffer(d.ARRAY_BUFFER,this.positionBuffer),d.bufferSubData(d.ARRAY_BUFFER,0,this.renderPositions),d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,this.indexBuffer),d.bufferSubData(d.ELEMENT_ARRAY_BUFFER,0,this.renderIndices),this.staticPositionsInitialized=!0}initWebGL(){let e=this.gl,t;this.useInstancing?t=`
36
+ // Per-vertex attributes (template quad)
37
+ attribute vec2 aPosition; // Local quad position (0,0 to cellW,cellH)
38
+
39
+ // Per-instance attributes (different for each cell)
40
+ attribute vec2 aInstanceOffset; // Cell grid position (col, row)
41
+ attribute vec4 aInstanceUVs; // Atlas UVs (u1, v1, u2, v2)
42
+ attribute vec2 aInstanceColors; // (bgColorIdx, fgColorIdx)
43
+
44
+ uniform vec2 uResolution;
45
+ uniform vec2 uCellSize; // (cellWidth, cellHeight)
46
+ uniform sampler2D uPalette;
47
+
48
+ varying vec2 vTexCoord;
49
+ varying vec4 vColor;
50
+
51
+ void main() {
52
+ // Compute world position: instance offset + local quad position
53
+ vec2 worldPos = aInstanceOffset * uCellSize + aPosition;
54
+ vec2 clipSpace = (worldPos / uResolution) * 2.0 - 1.0;
55
+ gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
56
+
57
+ // Interpolate UVs based on local position
58
+ vec2 localUV = aPosition / uCellSize; // (0,0) to (1,1)
59
+ vTexCoord = mix(
60
+ aInstanceUVs.xy, // top-left (u1, v1)
61
+ aInstanceUVs.zw, // bottom-right (u2, v2)
62
+ localUV
63
+ );
64
+
65
+ // Choose background or foreground color based on instance UVs
66
+ // If instance UVs are all (0,0), it's a background quad
67
+ float isBg = step(length(aInstanceUVs), 0.001);
68
+ float colorIndex = mix(aInstanceColors.y, aInstanceColors.x, isBg);
69
+
70
+ // Lookup color in palette
71
+ float paletteU = (colorIndex + 0.5) / 256.0;
72
+ vColor = texture2D(uPalette, vec2(paletteU, 0.5));
73
+ }
74
+ `:t=`
75
+ attribute vec2 aPosition;
76
+ attribute vec2 aTexCoord;
77
+ attribute float aColorIndex; // \u{1F680} Index dans palette (0-255)
78
+
79
+ uniform vec2 uResolution;
80
+ uniform sampler2D uPalette; // \u{1F680} Texture palette 256\xD71 RGBA
81
+
82
+ varying vec2 vTexCoord;
83
+ varying vec4 vColor;
84
+
85
+ void main() {
86
+ // Convert from pixels to clip space (-1 to 1)
87
+ vec2 clipSpace = (aPosition / uResolution) * 2.0 - 1.0;
88
+ gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
89
+
90
+ vTexCoord = aTexCoord;
91
+
92
+ // \u{1F680} Lookup couleur dans la palette texture (GPU-side)
93
+ float paletteU = (aColorIndex + 0.5) / 256.0;
94
+ vColor = texture2D(uPalette, vec2(paletteU, 0.5));
95
+ }
96
+ `;let r=`
97
+ precision mediump float;
98
+
99
+ uniform sampler2D uTexture;
100
+
101
+ varying vec2 vTexCoord;
102
+ varying vec4 vColor;
103
+
104
+ void main() {
105
+ // If texCoord is (0, 0), it's a background without texture
106
+ if (vTexCoord.x == 0.0 && vTexCoord.y == 0.0) {
107
+ gl_FragColor = vColor;
108
+ } else {
109
+ // Textured character: multiply atlas color by uniform color
110
+ // - White glyph (1,1,1) \u2192 uniform color applied normally
111
+ // - Colored glyph \u2192 atlas color \xD7 uniform color (multiply blend)
112
+ vec4 texColor = texture2D(uTexture, vTexCoord);
113
+ gl_FragColor = vec4(texColor.rgb * vColor.rgb, texColor.a);
114
+ }
115
+ }
116
+ `,i=this.compileShader(e.VERTEX_SHADER,t),s=this.compileShader(e.FRAGMENT_SHADER,r);if(!i||!s)throw new Error("Shader compilation error");let a=e.createProgram();if(!a)throw new Error("Unable to create WebGL program");if(e.attachShader(a,i),e.attachShader(a,s),e.linkProgram(a),!e.getProgramParameter(a,e.LINK_STATUS)){let l=e.getProgramInfoLog(a);throw new Error("Program linking error: "+l)}this.program=a,this.cachedTextureUniform=!1,this.cachedPaletteUniform=!1,this.aPosition=e.getAttribLocation(a,"aPosition"),this.useInstancing?(this.aTexCoord=e.getAttribLocation(a,"aInstanceOffset"),this.aColorIndex=e.getAttribLocation(a,"aInstanceUVs"),this.instanceDataBuffer=e.createBuffer()):(this.aTexCoord=e.getAttribLocation(a,"aTexCoord"),this.aColorIndex=e.getAttribLocation(a,"aColorIndex")),this.uResolution=e.getUniformLocation(a,"uResolution"),this.uTexture=e.getUniformLocation(a,"uTexture"),this.uPalette=e.getUniformLocation(a,"uPalette"),this.positionBuffer=e.createBuffer(),this.texCoordBuffer=e.createBuffer(),this.colorIndexBuffer=e.createBuffer(),this.indexBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderPositions.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderTexCoords.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.bufferData(e.ARRAY_BUFFER,this.renderColorIndices.byteLength,e.DYNAMIC_DRAW),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),e.bufferData(e.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,e.DYNAMIC_DRAW),this.vaoExtension&&(this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(this.aPosition),e.vertexAttribPointer(this.aPosition,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.texCoordBuffer),e.enableVertexAttribArray(this.aTexCoord),e.vertexAttribPointer(this.aTexCoord,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.colorIndexBuffer),e.enableVertexAttribArray(this.aColorIndex),e.vertexAttribPointer(this.aColorIndex,1,e.FLOAT,!1,0,0),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null))),e.enable(e.BLEND),e.blendFunc(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA),e.viewport(0,0,this.canvas.width,this.canvas.height)}compileShader(e,t){let r=this.gl,i=r.createShader(e);return i?(r.shaderSource(i,t),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 I(this.containerDiv,{strokeColor:"rgba(144, 24, 24, 1)",lineWidth:1,zIndex:10}),this.updateGridOverlay()}updateGridOverlay(){if(!this.gridOverlay)return;let e=this.cols*this.cellWidth,t=this.rows*this.cellHeight,r=this.canvas.getBoundingClientRect(),i=this.containerDiv.getBoundingClientRect();this.gridOverlay.setDimensions(this.cols,this.rows,this.cellWidth,this.cellHeight,0,0),this.gridOverlay.setTransform(this.currentScale,e,t,r,i),this.gridOverlay.render()}setBitmapFont(e,t,r,i,s){this.bitmapFont=e,this.fontLoaded=!0,this.charWidth=Math.round(t),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(a){throw console.error("[TerminalGL] \u274C Failed to generate atlas:",a),a}this.buildCharCodeMap(),this.precomputeAtlasUVs(),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async setImageFont(e,t,r,i,s,a){this.fontLoaded=!0,this.charWidth=Math.round(t),this.charHeight=Math.round(r),this.cellWidth=Math.round(i),this.cellHeight=Math.round(s),this.atlasColumns=L(a);let l=_(a);this.glyphOffsetX=Math.round((this.cellWidth-this.charWidth)/2),this.glyphOffsetY=Math.round((this.cellHeight-this.charHeight)/2),this.useInstancing&&(console.warn("[TerminalGL] \u{1F680} Initializing instanced buffers for ImageFont..."),this.initInstancedBuffers()),await this.loadImageFontAtlas(e),this.charCodeToAtlasIndex.fill(65535);for(let o=0;o<=l;o++)this.charCodeToAtlasIndex[o]=o;this.precomputeImageFontUVs(a),this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.useInstancing||this.precomputeStaticPositions(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}async loadImageFontAtlas(e){return new Promise((t,r)=>{let i=new Uint8Array(e),s=new Blob([i],{type:"image/png"}),a=URL.createObjectURL(s),l=new Image;l.onload=()=>{URL.revokeObjectURL(a),this.atlasCanvas=document.createElement("canvas"),this.atlasCanvas.width=l.width,this.atlasCanvas.height=l.height;let o=this.atlasCanvas.getContext("2d");if(!o){r(new Error("Failed to create 2D context for atlas"));return}o.drawImage(l,0,0),this.cachedAtlasWidth=l.width,this.cachedAtlasHeight=l.height,this.createAtlasTexture(),t()},l.onerror=()=>{URL.revokeObjectURL(a),r(new Error("Failed to load PNG image for ImageFont atlas"))},l.src=a})}precomputeImageFontUVs(e){let t=e*256;this.atlasUVs=new Float32Array(t*4);let r=this.cachedAtlasWidth,i=this.cachedAtlasHeight,s=.5/r,a=.5/i;for(let l=0;l<t;l++){let{col:o,row:c}=D(l,e),d=(o*this.charWidth+s)/r,h=(c*this.charHeight+a)/i,f=((o+1)*this.charWidth-s)/r,u=((c+1)*this.charHeight-a)/i,m=l*4;this.atlasUVs[m]=d,this.atlasUVs[m+1]=h,this.atlasUVs[m+2]=f,this.atlasUVs[m+3]=u}}generateAtlas(){if(!this.bitmapFont)return;let e=Array.from(this.bitmapFont.keys()).sort((o,c)=>o-c),t=e.length;this.atlasColumns=Math.ceil(Math.sqrt(t));let r=Math.ceil(t/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 a=this.atlasCanvas.getContext("2d");if(!a)throw new Error("Unable to create 2D context for atlas");a.clearRect(0,0,i,s),a.fillStyle="#ffffff";let l=0;for(let o of e){let c=this.bitmapFont.get(o);if(!c)continue;let d=l%this.atlasColumns,h=Math.floor(l/this.atlasColumns),f=d*this.charWidth,u=h*this.charHeight;for(let m=0;m<Math.min(c.length,this.charHeight);m++){let p=c[m];for(let g=0;g<this.charWidth;g++){let A=1<<7-g;p&A&&a.fillRect(f+g,u+m,1,1)}}l++}this.createAtlasTexture()}buildCharCodeMap(){if(!this.bitmapFont)return;this.charCodeToAtlasIndex.fill(65535);let e=Array.from(this.bitmapFont.keys()).sort((t,r)=>t-r);for(let t=0;t<e.length;t++)this.charCodeToAtlasIndex[e[t]]=t}precomputeAtlasUVs(){if(!this.bitmapFont)return;let e=this.bitmapFont.size;this.atlasUVs=new Float32Array(e*4),this.cachedAtlasWidth=this.atlasColumns*this.charWidth,this.cachedAtlasHeight=Math.ceil(e/this.atlasColumns)*this.charHeight;let t=this.cachedAtlasWidth,r=this.cachedAtlasHeight,i=.5/t,s=.5/r;for(let a=0;a<e;a++){let l=a%this.atlasColumns,o=Math.floor(a/this.atlasColumns),c=(l*this.charWidth+i)/t,d=(o*this.charHeight+s)/r,h=((l+1)*this.charWidth-i)/t,f=((o+1)*this.charHeight-s)/r,u=a*4;this.atlasUVs[u]=c,this.atlasUVs[u+1]=d,this.atlasUVs[u+2]=h,this.atlasUVs[u+3]=f}}createAtlasTexture(){if(this.atlasCanvas)try{let e=this.gl,t=e.createTexture();if(!t)throw new Error("Unable to create texture");e.bindTexture(e.TEXTURE_2D,t),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,this.atlasCanvas),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),this.atlasTexture=t}catch(e){throw console.error("[TerminalGL] \u274C Failed to create atlas texture:",e),e}}clear(){let e=this.gl;e&&e.clear(e.COLOR_BUFFER_BIT)}parseColor(e){if(e.startsWith("#")){let t=e.slice(1),r=0,i=0,s=0;return t.length===3?(r=parseInt(t[0]+t[0],16),i=parseInt(t[1]+t[1],16),s=parseInt(t[2]+t[2],16)):t.length===6&&(r=parseInt(t.slice(0,2),16),i=parseInt(t.slice(2,4),16),s=parseInt(t.slice(4,6),16)),[r/255,i/255,s/255,1]}if(e.startsWith("rgb")){let t=e.match(/rgba?\(([^)]+)\)/);if(t){let r=t[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(e){console.error("[TerminalGL] \u274C Error in resize callback:",e)}}),this.resizeObserver.observe(this.parentElement),this.updateCanvasSize()}catch(e){console.error("[TerminalGL] \u274C Failed to setup ResizeObserver:",e)}}updateCanvasSize(){let e=this.parentElement.clientWidth,t=this.parentElement.clientHeight;if(e===0||t===0)return;let r=this.cols*this.cellWidth,i=this.rows*this.cellHeight;if(r===0||i===0)return;let s=e/r,a=t/i,l=Math.min(s,a),o;switch(this.scalingMode){case T.Integer:o=Math.max(1,Math.floor(l));break;case T.Half:o=Math.max(1,Math.floor(l*2)/2);break;case T.Quarter:o=Math.max(1,Math.floor(l*4)/4);break;case T.Eighth:o=Math.max(1,Math.floor(l*8)/8);break;case T.None:default:o=Math.max(.1,l);break}if(this.canvas.style.transform=`scale(${o})`,this.ambientEffectEnabled&&this.ambientEffectCanvas){let c=o*this.ambientEffectScale;this.ambientEffectCanvas.style.transform=`scale(${c})`}this.currentScale=o,this.onResizeCallback&&this.onResizeCallback(),this.showGrid&&this.gridOverlay&&this.updateGridOverlay()}updateAmbientEffect(){!this.ambientEffectCanvas||!this.ambientEffectCtx||this.ambientEffectCtx.drawImage(this.canvas,0,0)}setPalette(e){let t=0;for(let r=0;r<Math.min(e.length,256);r++){let i=e[r];t=(t<<5)-t+i.r,t=(t<<5)-t+i.g,t=(t<<5)-t+i.b,t=(t<<5)-t+i.a,t=t|0}if(t!==this.paletteHash){this.paletteHash=t;for(let r=0;r<e.length&&r<256;r++){let i=e[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 e=this.gl;this.paletteTexture||(this.paletteTexture=e.createTexture()),e.bindTexture(e.TEXTURE_2D,this.paletteTexture);let t=new Uint8Array(256*4);for(let r=0;r<256;r++){let i=r*4;t[i]=this.paletteFloat[i]*255,t[i+1]=this.paletteFloat[i+1]*255,t[i+2]=this.paletteFloat[i+2]*255,t[i+3]=this.paletteFloat[i+3]*255}e.texImage2D(e.TEXTURE_2D,0,e.RGBA,256,1,0,e.RGBA,e.UNSIGNED_BYTE,t),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.bindTexture(e.TEXTURE_2D,null)}catch(e){throw console.error("[TerminalGL] \u274C Failed to update palette texture:",e),e}}renderDisplayData(e){try{if(!this.isReady()){console.warn("[TerminalGL] \u26A0\uFE0F Not ready: font not loaded yet");return}(e.width!==this.cols||e.height!==this.rows)&&this.resize(e.width,e.height),this.renderDirect(e),this.ambientEffectEnabled&&this.ambientEffectCanvas&&this.ambientEffectCtx&&this.updateAmbientEffect()}catch(t){console.error("[TerminalGL] \u274C Error rendering display data:",t)}}renderDirect(e){let t=this.gl;if(!this.staticPositionsInitialized&&!this.useInstancing&&this.precomputeStaticPositions(),this.canvasBgColor!==null){let r=this.parseColor(this.canvasBgColor);t.clearColor(r[0],r[1],r[2],r[3])}else t.clearColor(0,0,0,0);t.clear(t.COLOR_BUFFER_BIT),this.useInstancing?this.renderInstanced(e):this.renderDirectBuffers(e)}renderInstanced(e){let t=this.gl,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(e);return}let i=e.width*e.height;if(this.useUint16Indices&&i>8191){console.warn(`[TerminalGL] \u26A0\uFE0F Terminal too large for instanced rendering with Uint16 (${i} cells > 8191). Falling back to standard rendering.`),this.useInstancing=!1,this.renderDirectBuffers(e);return}let s=0,a=this.instanceData.length/8;for(let f=0;f<e.height;f++)for(let u=0;u<e.width;u++){let m=e.cells[f*e.width+u],p=m.bgColorIndex,g=m.fgColorIndex,A=this.canvasBgColor!==null&&p===255,R=m.char===" "||g===255;if(!A){if(s>=a){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${a}`);break}let v=s*8;this.instanceData[v]=u,this.instanceData[v+1]=f,this.instanceData[v+2]=0,this.instanceData[v+3]=0,this.instanceData[v+4]=0,this.instanceData[v+5]=0,this.instanceData[v+6]=p,this.instanceData[v+7]=0,s++}if(!R){let v=m.char.charCodeAt(0),E=this.charCodeToAtlasIndex[v];if(E!==65535){if(s>=a){console.error(`[TerminalGL] \u274C Instance buffer overflow! instanceIdx=${s}, max=${a}`);break}let w=E*4,x=s*8;this.instanceData[x]=u,this.instanceData[x+1]=f,this.instanceData[x+2]=this.atlasUVs[w],this.instanceData[x+3]=this.atlasUVs[w+1],this.instanceData[x+4]=this.atlasUVs[w+2],this.instanceData[x+5]=this.atlasUVs[w+3],this.instanceData[x+6]=0,this.instanceData[x+7]=g,s++}}}if(s===0){console.warn("[TerminalGL] \u26A0\uFE0F No instances to draw (all cells skipped)");return}t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.instanceData.subarray(0,s*8)),t.useProgram(this.program),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),r.vertexAttribDivisorANGLE(this.aPosition,0),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer);let l=8*Float32Array.BYTES_PER_ELEMENT,o=t.getAttribLocation(this.program,"aInstanceOffset");t.enableVertexAttribArray(o),t.vertexAttribPointer(o,2,t.FLOAT,!1,l,0),r.vertexAttribDivisorANGLE(o,1);let c=t.getAttribLocation(this.program,"aInstanceUVs");t.enableVertexAttribArray(c),t.vertexAttribPointer(c,4,t.FLOAT,!1,l,2*Float32Array.BYTES_PER_ELEMENT),r.vertexAttribDivisorANGLE(c,1);let d=t.getAttribLocation(this.program,"aInstanceColors");t.enableVertexAttribArray(d),t.vertexAttribPointer(d,2,t.FLOAT,!1,l,6*Float32Array.BYTES_PER_ELEMENT),r.vertexAttribDivisorANGLE(d,1),t.uniform2f(this.uResolution,this.canvas.width,this.canvas.height);let h=t.getUniformLocation(this.program,"uCellSize");t.uniform2f(h,this.cellWidth,this.cellHeight),t.activeTexture(t.TEXTURE0),t.bindTexture(t.TEXTURE_2D,this.atlasTexture),t.uniform1i(this.uTexture,0),t.activeTexture(t.TEXTURE1),t.bindTexture(t.TEXTURE_2D,this.paletteTexture),t.uniform1i(this.uPalette,1),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),r.drawElementsInstancedANGLE(t.TRIANGLES,6,t.UNSIGNED_SHORT,0,s),r.vertexAttribDivisorANGLE(this.aPosition,0),r.vertexAttribDivisorANGLE(o,0),r.vertexAttribDivisorANGLE(c,0),r.vertexAttribDivisorANGLE(d,0)}renderDirectBuffers(e){let t=this.gl,r=e.width*e.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,a=0,l=e.cells,o=r;for(let m=0;m<o;m++){let p=l[m],g=p.bgColorIndex,R=this.canvasBgColor!==null&&g===255?255:g,v=0;for(let x=0;x<4;x++)this.renderTexCoords[s++]=v,this.renderTexCoords[s++]=v,this.renderColorIndices[a++]=R;let E=p.fgColorIndex,w=p.char;if(w===" "||E===255)for(let x=0;x<4;x++)this.renderTexCoords[s++]=0,this.renderTexCoords[s++]=0,this.renderColorIndices[a++]=255;else{let x=w.charCodeAt(0),S=this.charCodeToAtlasIndex[x];if(S!==65535){let y=S*4,G=this.atlasUVs[y],W=this.atlasUVs[y+1],O=this.atlasUVs[y+2],H=this.atlasUVs[y+3];this.renderTexCoords[s++]=G,this.renderTexCoords[s++]=W,this.renderColorIndices[a++]=E,this.renderTexCoords[s++]=O,this.renderTexCoords[s++]=W,this.renderColorIndices[a++]=E,this.renderTexCoords[s++]=G,this.renderTexCoords[s++]=H,this.renderColorIndices[a++]=E,this.renderTexCoords[s++]=O,this.renderTexCoords[s++]=H,this.renderColorIndices[a++]=E}else for(let y=0;y<4;y++)this.renderTexCoords[s++]=0,this.renderTexCoords[s++]=0,this.renderColorIndices[a++]=255}}(s!==o*2*4*2||a!==o*2*4)&&console.error("[TerminalGL] \u274C Buffer index mismatch!",{texIdx:s,colorIdx:a,expected:o*2*4}),t.useProgram(this.program),this.vao&&this.vaoExtension?(this.vaoExtension.bindVertexArrayOES(this.vao),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,s)),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,a))):(t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.enableVertexAttribArray(this.aPosition),t.vertexAttribPointer(this.aPosition,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.texCoordBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderTexCoords.subarray(0,s)),t.enableVertexAttribArray(this.aTexCoord),t.vertexAttribPointer(this.aTexCoord,2,t.FLOAT,!1,0,0),t.bindBuffer(t.ARRAY_BUFFER,this.colorIndexBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,this.renderColorIndices.subarray(0,a)),t.enableVertexAttribArray(this.aColorIndex),t.vertexAttribPointer(this.aColorIndex,1,t.FLOAT,!1,0,0));let c=this.canvas.width,d=this.canvas.height;(this.cachedResolution[0]!==c||this.cachedResolution[1]!==d)&&(t.uniform2f(this.uResolution,c,d),this.cachedResolution[0]=c,this.cachedResolution[1]=d),this.cachedTextureUnit!==0&&(t.activeTexture(t.TEXTURE0),this.cachedTextureUnit=0),t.bindTexture(t.TEXTURE_2D,this.atlasTexture),this.cachedTextureUniform||(t.uniform1i(this.uTexture,0),this.cachedTextureUniform=!0),this.cachedPaletteUnit!==1&&(t.activeTexture(t.TEXTURE1),this.cachedPaletteUnit=1),t.bindTexture(t.TEXTURE_2D,this.paletteTexture),this.cachedPaletteUniform||(t.uniform1i(this.uPalette,1),this.cachedPaletteUniform=!0),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer);let f=e.width*e.height*2*6,u=this.useUint16Indices?t.UNSIGNED_SHORT:t.UNSIGNED_INT;t.drawElements(t.TRIANGLES,f,u,0)}resize(e,t){if(!Number.isInteger(e)||e<=0){console.error(`[TerminalGL] \u274C Invalid cols: ${e}. Must be positive integer.`);return}if(!Number.isInteger(t)||t<=0){console.error(`[TerminalGL] \u274C Invalid rows: ${t}. Must be positive integer.`);return}if(e===this.cols&&t===this.rows)return;let r=e*t,i=this.useUint16Indices?8191:262144;if(r>i){let d=Math.floor(Math.sqrt(i));console.error(`[TerminalGL] \u274C Cannot resize to ${e}\xD7${t} (${r} cells). Device limit: ${i} cells (max ~${d}\xD7${d}). ${this.useUint16Indices?"Device lacks OES_element_index_uint extension.":""}`);return}let s=U.checkCompatibility();r>s.recommendedMaxCells&&console.warn(`[TerminalGL] \u26A0\uFE0F Resizing to ${e}\xD7${t} (${r} cells) exceeds recommended limit (${s.recommendedMaxCells} cells). Performance may degrade.`),this.cols=e,this.rows=t,this.staticPositionsInitialized=!1;let a=this.cols*this.rows*2,l=Math.ceil(a*1.5),o=a>this.maxCells,c=this.maxCells>l*4;if(o||c){let d=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 h=this.gl;this.useInstancing||(h.bindBuffer(h.ARRAY_BUFFER,this.positionBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderPositions.byteLength,h.DYNAMIC_DRAW)),h.bindBuffer(h.ARRAY_BUFFER,this.texCoordBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderTexCoords.byteLength,h.DYNAMIC_DRAW),h.bindBuffer(h.ARRAY_BUFFER,this.colorIndexBuffer),h.bufferData(h.ARRAY_BUFFER,this.renderColorIndices.byteLength,h.DYNAMIC_DRAW),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.indexBuffer),h.bufferData(h.ELEMENT_ARRAY_BUFFER,this.renderIndices.byteLength,h.DYNAMIC_DRAW),this.vaoExtension&&this.vao&&(this.vaoExtension.deleteVertexArrayOES(this.vao),this.vao=this.vaoExtension.createVertexArrayOES(),this.vao&&(this.vaoExtension.bindVertexArrayOES(this.vao),h.bindBuffer(h.ARRAY_BUFFER,this.positionBuffer),h.enableVertexAttribArray(this.aPosition),h.vertexAttribPointer(this.aPosition,2,h.FLOAT,!1,0,0),h.bindBuffer(h.ARRAY_BUFFER,this.texCoordBuffer),h.enableVertexAttribArray(this.aTexCoord),h.vertexAttribPointer(this.aTexCoord,2,h.FLOAT,!1,0,0),h.bindBuffer(h.ARRAY_BUFFER,this.colorIndexBuffer),h.enableVertexAttribArray(this.aColorIndex),h.vertexAttribPointer(this.aColorIndex,1,h.FLOAT,!1,0,0),h.bindBuffer(h.ELEMENT_ARRAY_BUFFER,this.indexBuffer),this.vaoExtension.bindVertexArrayOES(null)));let f=o?"\u{1F4C8} Growing":"\u{1F4C9} Shrinking",u=d*160/1048576,m=this.maxCells*160/1048576;console.warn(`[TerminalGL] ${f} buffers: ${u.toFixed(2)}MB \u2192 ${m.toFixed(2)}MB (${d} \u2192 ${this.maxCells} quads)`)}this.canvas.width=this.cols*this.cellWidth,this.canvas.height=this.rows*this.cellHeight,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.ambientEffectEnabled&&this.ambientEffectCanvas&&(this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.width=`${this.canvas.width}px`,this.ambientEffectCanvas.style.height=`${this.canvas.height}px`),this.showGrid&&this.gridOverlay&&this.updateGridOverlay(),this.updateCanvasSize()}getCanvas(){return this.canvas}getGridSize(){return{cols:this.cols,rows:this.rows}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getBaseDimensions(){return{width:this.cols*this.cellWidth,height:this.rows*this.cellHeight}}setOnResizeCallback(e){this.onResizeCallback=e}clearOnResizeCallback(){this.onResizeCallback=void 0}setScalingMode(e){this.scalingMode!==e&&(this.scalingMode=e,this.updateCanvasSize())}getScalingMode(){return this.scalingMode}setGrid(e){e.enabled?(this.gridOverlay?this.gridOverlay.setStyle({strokeColor:e.color,lineWidth:e.lineWidth}):this.gridOverlay=new I(this.containerDiv,{strokeColor:e.color??"rgba(144, 24, 24, 1)",lineWidth:e.lineWidth??1,zIndex:10}),this.showGrid=!0,this.gridOverlay.setVisible(!0),this.updateGridOverlay()):(this.showGrid=!1,this.gridOverlay&&this.gridOverlay.setVisible(!1))}isGridEnabled(){return this.showGrid}setAmbientEffect(e){typeof e=="boolean"?this.ambientEffectEnabled=e:(this.ambientEffectEnabled=!0,e.blur!==void 0&&(this.ambientEffectBlur=e.blur),e.scale!==void 0&&(this.ambientEffectScale=e.scale)),this.ambientEffectEnabled&&!this.ambientEffectCanvas&&this.createAmbientEffectCanvas(),this.ambientEffectCanvas&&(this.ambientEffectEnabled?(this.ambientEffectCanvas.style.display="block",this.ambientEffectCanvas.style.filter=`blur(${this.ambientEffectBlur}px)`,this.ambientEffectCanvas.style.transform=`scale(${this.ambientEffectScale})`,this.updateAmbientEffect()):this.ambientEffectCanvas.style.display="none")}createAmbientEffectCanvas(){this.ambientEffectCanvas||(this.ambientEffectCanvas=document.createElement("canvas"),this.ambientEffectCanvas.className="terminalgl-ambient-effect-canvas",this.ambientEffectCanvas.width=this.canvas.width,this.ambientEffectCanvas.height=this.canvas.height,this.ambientEffectCanvas.style.cssText=`
117
+ display: block !important;
118
+ position: absolute !important;
119
+ width: ${this.canvas.width}px !important;
120
+ height: ${this.canvas.height}px !important;
121
+ filter: blur(${this.ambientEffectBlur}px) !important;
122
+ opacity: ${this.ambientEffectOpacity} !important;
123
+ transform-origin: center center !important;
124
+ transform: scale(${this.ambientEffectScale}) !important;
125
+ pointer-events: none !important;
126
+ z-index: 0 !important;
127
+ `,this.ambientEffectCtx=this.ambientEffectCanvas.getContext("2d",{alpha:!0}),this.containerDiv.insertBefore(this.ambientEffectCanvas,this.canvas),console.warn("[TerminalGL] \u{1F308} ambient effect canvas created dynamically"))}isAmbientEffectEnabled(){return this.ambientEffectEnabled}getAmbientEffectConfig(){return{enabled:this.ambientEffectEnabled,blur:this.ambientEffectBlur,scale:this.ambientEffectScale}}getCols(){return this.cols}getRows(){return this.rows}isReady(){return!!(this.fontLoaded&&this.atlasTexture&&this.program)}destroy(){this.dispose()}dispose(){this.resizeObserver&&this.resizeObserver.disconnect();let e=this.gl;this.program&&e.deleteProgram(this.program),this.positionBuffer&&e.deleteBuffer(this.positionBuffer),this.texCoordBuffer&&e.deleteBuffer(this.texCoordBuffer),this.colorIndexBuffer&&e.deleteBuffer(this.colorIndexBuffer),this.indexBuffer&&e.deleteBuffer(this.indexBuffer),this.instanceDataBuffer&&e.deleteBuffer(this.instanceDataBuffer),this.atlasTexture&&e.deleteTexture(this.atlasTexture),this.paletteTexture&&e.deleteTexture(this.paletteTexture),this.vao&&this.vaoExtension&&this.vaoExtension.deleteVertexArrayOES(this.vao);let t=e.getExtension("WEBGL_lose_context");t&&t.loseContext(),this.atlasCanvas&&(this.atlasCanvas.width=0,this.atlasCanvas.height=0,this.atlasCanvas=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv),this.canvas.width=0,this.canvas.height=0,this.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)}};C(U,"TerminalGL");var M=U;var P=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff","#080808","#121212","#1c1c1c","#262626","#303030","#3a3a3a","#444444","#4e4e4e","#585858","#626262","#6c6c6c","#767676","#808080","#8a8a8a","#949494","#9e9e9e","#a80000","#00a800","#a8a800","#0000a8","#a800a8","#00a8a8","#a8a8a8","#545454","#fc5454","#54fc54","#fcfc54","#5454fc","#fc54fc","#54fcfc","#fcfcfc","#000000",...Array(192).fill("#808080")];function Y(b,e=P){return b<0||b>=e.length?"#ff00ff":e[b]}C(Y,"paletteIndexToColor");function N(b,e=P){let t=e.indexOf(b.toLowerCase());return t>=0?t:0}C(N,"colorToPaletteIndex");export{P as DEFAULT_PALETTE,I as GridOverlay,T as ScalingMode,M as TerminalGL,N as colorToPaletteIndex,L as getAtlasColumns,D as getCharGridPosition,_ as getMaxCharCode,Y as paletteIndexToColor};