@utsp/render 0.14.0 → 0.14.1
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/2d/index.cjs +3 -0
- package/dist/2d/index.mjs +3 -0
- package/dist/gl/index.cjs +3 -0
- package/dist/gl/index.mjs +3 -0
- package/dist/index.cjs +6 -0
- package/dist/index.mjs +6 -0
- package/package.json +2 -2
package/dist/2d/index.cjs
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
justify-content: center !important;
|
|
20
20
|
align-items: center !important;
|
|
21
21
|
isolation: isolate !important;
|
|
22
|
+
pointer-events: none !important;
|
|
22
23
|
`,this.canvas=document.createElement("canvas"),this.canvas.className="terminal2d-canvas",e.className&&(this.canvas.className+=" "+e.className),e.style&&Object.assign(this.canvas.style,e.style),this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges",this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv);let 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.ctx.imageSmoothingEnabled=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid(),this.showDebugGrid&&(this.gridOverlay=new x(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;if(!this.customCellSize){let o,c;if(this.fontType==="image"&&this.imageAtlas){let d=this.imageAtlas.getCellDimensions();o=d.width,c=d.height}else this.fontType==="bitmap"?(o=this.bitmapCharWidth,c=this.bitmapCharHeight):(o=Math.round(this.cellWidth)||10,c=Math.round(this.cellHeight)||14);this.cellWidth=Math.round(o),this.cellHeight=Math.round(c)}this.scalingMode===C.ScalingMode.Responsive?(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1):this.fixedGridMode&&this.fixedCols&&this.fixedRows?(this.cols=this.fixedCols,this.rows=this.fixedRows):(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1);let s=this.cols*this.cellWidth,i=this.rows*this.cellHeight,a=t/s,n=e/i,r=Math.min(a,n),l;switch(this.scalingMode){case C.ScalingMode.Integer:l=Math.max(1,Math.floor(r));break;case C.ScalingMode.Half:l=Math.max(.5,Math.floor(r*2)/2);break;case C.ScalingMode.Quarter:l=Math.max(.25,Math.floor(r*4)/4);break;case C.ScalingMode.Eighth:l=Math.max(.125,Math.floor(r*8)/8);break;case C.ScalingMode.Responsive:l=1;break;case C.ScalingMode.None:default:l=Math.max(.1,r);break}this.currentScale=l,this.canvas.width=s,this.canvas.height=i,this.ctx.imageSmoothingEnabled=!1,this.canvas.style.cssText=`
|
|
23
24
|
flex-shrink: 0 !important;
|
|
24
25
|
flex-grow: 0 !important;
|
|
@@ -31,4 +32,6 @@
|
|
|
31
32
|
transform: scale(${l}) !important;
|
|
32
33
|
will-change: transform !important;
|
|
33
34
|
backface-visibility: hidden !important;
|
|
35
|
+
pointer-events: auto !important;
|
|
36
|
+
touch-action: none !important;
|
|
34
37
|
`,this.fontType==="web"&&(this.fontSize=Math.round(this.cellHeight/14*12)),this.offsetX=0,this.offsetY=0}createEmptyGrid(){let t=[];for(let e=0;e<this.rows;e++){let 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),a=Math.min(e,this.rows);for(let n=0;n<a;n++)for(let r=0;r<i;r++)this.cells[n][r]=s[n][r]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(t,e,s,i,a){if(e<0||e>=this.rows||t<0||t>=this.cols)return;let n=s&&typeof s=="string"?s.charAt(0):" ";this.cells[e][t]={char:n,fgColor:i??this.defaultFgColor,bgColor:a??this.defaultBgColor}}getCell(t,e){return e<0||e>=this.rows||t<0||t>=this.cols?null:this.cells[e][t]}write(t,e,s,i,a){for(let n=0;n<s.length;n++)this.setCell(t+n,e,s[n],i,a)}fillRect(t,e,s,i,a=" ",n,r){for(let l=e;l<e+i;l++)for(let o=t;o<t+s;o++)this.setCell(o,l,a,n,r)}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 a=0;a<t.width;a++){let n=t.cells[s];i<this.rows&&a<this.cols&&this.setCell(a,i,n.char,n.fgColor,n.bgColor),s++}}render(){if(this.fontType==="bitmap"&&this.bitmapFont&&this.useImageDataRendering){this.renderWithImageData();return}this.renderClassic()}renderWithImageData(){if(!this.bitmapFont)return;let 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 l=0;l<this.rows;l++)for(let o=0;o<this.cols;o++){let c=this.cells[l][o],d=this.parseColorToRGB(c.bgColor),g=this.parseColorToRGB(c.fgColor),u=c.char.charCodeAt(0),v=this.bitmapFont.get(u);for(let b=0;b<this.bitmapCharHeight;b++)for(let p=0;p<this.bitmapCharWidth;p++){let w=o*this.bitmapCharWidth+p,y=((l*this.bitmapCharHeight+b)*t+w)*4,F=!1;if(v&&b<v.length){let $=v[b],U=1<<7-p;F=($&U)!==0}F?(s[y]=g.r,s[y+1]=g.g,s[y+2]=g.b,s[y+3]=g.a):(s[y]=d.r,s[y+1]=d.g,s[y+2]=d.b,s[y+3]=d.a)}}this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges";let i=document.createElement("canvas");i.width=t,i.height=e,i.getContext("2d").putImageData(this.imageDataBuffer,0,0);let n=this.cols*this.cellWidth,r=this.rows*this.cellHeight;this.ctx.drawImage(i,0,0,t,e,this.offsetX,this.offsetY,n,r),this.showDebugGrid&&this.drawDebugGrid()}parseColorToRGB(t){let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10),a:e[4]?Math.round(parseFloat(e[4])*255):255};if(t.startsWith("#")){let a=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(a,(r,l,o,c)=>l+l+o+o+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.fontType==="image"?(this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges"):(this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.canvas.style.imageRendering="auto",this.ctx.font=`${this.fontSize}px ${this.fontFamily}`,this.ctx.textBaseline="top",this.ctx.textRendering="optimizeLegibility");for(let t=0;t<this.rows;t++)for(let e=0;e<this.cols;e++){let s=this.cells[t][e],i=Math.floor(this.offsetX+e*this.cellWidth),a=Math.floor(this.offsetY+t*this.cellHeight),n=Math.floor(this.offsetX+(e+1)*this.cellWidth),r=Math.floor(this.offsetY+(t+1)*this.cellHeight),l=n-i,o=r-a;if((this.canvasBgColor!==null||s.bgColor!==this.defaultBgColor)&&(this.ctx.fillStyle=s.bgColor,this.ctx.fillRect(i,a,l,o)),s.char!==" ")if(this.fontType==="image"&&this.imageAtlas){let d=s.char.charCodeAt(0);this.imageAtlas.drawChar(this.ctx,d,i,a,l,o,s.fgColor)}else if(this.fontType==="bitmap"&&this.bitmapFont)this.drawBitmapChar(s.char,i,a,l,o,s.fgColor);else{this.ctx.fillStyle=s.fgColor;let d=i+(l-this.ctx.measureText(s.char).width)/2,g=a+(o-this.fontSize)/2;this.ctx.fillText(s.char,d,g)}}this.showDebugGrid&&this.drawDebugGrid()}drawBitmapChar(t,e,s,i,a,n){let r=t.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,r,e,s,i,a,n);return}if(!this.bitmapFont)return;let l=this.bitmapFont.get(r);if(!l)return;let o=i/this.bitmapCharWidth,c=a/this.bitmapCharHeight;this.ctx.fillStyle=n;for(let d=0;d<Math.min(l.length,this.bitmapCharHeight);d++){let g=l[d],u=s+d*c,v=s+(d+1)*c;for(let b=0;b<this.bitmapCharWidth;b++){let p=1<<7-b;if(g&p){let w=e+b*o,k=e+(b+1)*o;this.ctx.fillRect(w,u,k-w,v-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}getCurrentScale(){return this.currentScale}getScalingMode(){return this.scalingMode}getOffsets(){return{offsetX:this.offsetX,offsetY:this.offsetY}}setDebugGrid(t){this.showDebugGrid=t,t&&!this.gridOverlay?(this.gridOverlay=new x(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,a=this.rows,n=this.cells;if(this.calculateGridSize(),this.cols!==i||this.rows!==a){this.cells=this.createEmptyGrid();let r=Math.min(i,this.cols),l=Math.min(a,this.rows);for(let o=0;o<l;o++)for(let c=0;c<r;c++)this.cells[o][c]=n[o][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,a=this.cells;if(this.calculateGridSize(),this.cols!==s||this.rows!==i){this.cells=this.createEmptyGrid();let n=Math.min(s,this.cols),r=Math.min(i,this.rows);for(let l=0;l<r;l++)for(let o=0;o<n;o++)this.cells[l][o]=a[l][o]}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,a){this.fontType="bitmap",this.bitmapFont=t,this.bitmapCharWidth=e,this.bitmapCharHeight=s,this.bitmapAtlas=new M(t,e,s,i,a),this.cellWidth=i,this.cellHeight=a,this.calculateGridSize(),this.cells=this.createEmptyGrid()}async setImageFont(t,e,s,i,a,n){this.fontType="image",this.imageAtlas=new H({glyphWidth:e,glyphHeight:s,cellWidth:i,cellHeight:a,atlasBlocks:n}),await this.imageAtlas.loadFromPNG(t),this.cellWidth=i,this.cellHeight=a,this.bitmapCharWidth=e,this.bitmapCharHeight=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 s=f(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 a=e[i];return!a||typeof a.r!="number"?(console.warn(`[Terminal2D] Corrupted palette entry at index ${i}:`,a),this.defaultFgColor):`rgba(${a.r}, ${a.g}, ${a.b}, ${a.a/255})`},"convertColor");for(let i=0;i<t.height&&i<this.rows;i++)for(let a=0;a<t.width&&a<this.cols;a++){let n=i*t.width+a;if(n>=t.cells.length)break;let r=t.cells[n];if(!r)continue;let l=s(r.fgColorIndex),o=s(r.bgColorIndex);this.setCell(a,i,r.char??" ",l,o)}this.render()}isReady(){return!0}getCols(){return this.cols}getRows(){return this.rows}resize(t,e){this.setFixedGrid(t,e)}setScalingMode(t){if(this.scalingMode===t)return;let e=this.cols,s=this.rows;if(this.scalingMode=t,this.calculateGridSize(),this.cols!==e||this.rows!==s){let i=this.cells;if(this.cells=this.createEmptyGrid(),i&&i.length>0){let a=Math.min(e,this.cols),n=Math.min(s,this.rows);for(let r=0;r<n;r++)for(let l=0;l<a;l++)i[r]&&i[r][l]&&(this.cells[r][l]=i[r][l])}}this.render()}setCellSize(t,e){let s=Math.max(1,Math.min(255,Math.round(t))),i=Math.max(1,Math.min(255,Math.round(e)));if(this.cellWidth===s&&this.cellHeight===i)return;let a=this.cols,n=this.rows;if(this.cellWidth=s,this.cellHeight=i,this.customCellSize=!0,this.calculateGridSize(),this.cols!==a||this.rows!==n){let r=this.cells;if(this.cells=this.createEmptyGrid(),r&&r.length>0){let l=Math.min(a,this.cols),o=Math.min(n,this.rows);for(let c=0;c<o;c++)for(let d=0;d<l;d++)r[c]&&r[c][d]&&(this.cells[c][d]=r[c][d])}}this.render()}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}getMaxCells(){return 65536}destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=void 0),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}};f(G,"Terminal2D");var A=G;var S=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff","#080808","#121212","#1c1c1c","#262626","#303030","#3a3a3a","#444444","#4e4e4e","#585858","#626262","#6c6c6c","#767676","#808080","#8a8a8a","#949494","#9e9e9e","#a80000","#00a800","#a8a800","#0000a8","#a800a8","#00a8a8","#a8a8a8","#545454","#fc5454","#54fc54","#fcfc54","#5454fc","#fc54fc","#54fcfc","#fcfcfc","#000000",...Array(192).fill("#808080")];function z(m,t=S){return m<0||m>=t.length?"#ff00ff":t[m]}f(z,"paletteIndexToColor");function L(m,t=S){let e=t.indexOf(m.toLowerCase());return e>=0?e:0}f(L,"colorToPaletteIndex");var O=require("@utsp/types");
|
package/dist/2d/index.mjs
CHANGED
|
@@ -19,6 +19,7 @@ var F=Object.defineProperty;var O=(g,t,e)=>t in g?F(g,t,{enumerable:!0,configura
|
|
|
19
19
|
justify-content: center !important;
|
|
20
20
|
align-items: center !important;
|
|
21
21
|
isolation: isolate !important;
|
|
22
|
+
pointer-events: none !important;
|
|
22
23
|
`,this.canvas=document.createElement("canvas"),this.canvas.className="terminal2d-canvas",e.className&&(this.canvas.className+=" "+e.className),e.style&&Object.assign(this.canvas.style,e.style),this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges",this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv);let s=this.canvas.getContext("2d",{alpha:!0,desynchronized:!1});if(!s)throw new Error("UTSPRender: Impossible d'obtenir le contexte 2D du canvas");this.ctx=s,this.ctx.imageSmoothingEnabled=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid(),this.showDebugGrid&&(this.gridOverlay=new x(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;if(!this.customCellSize){let o,c;if(this.fontType==="image"&&this.imageAtlas){let d=this.imageAtlas.getCellDimensions();o=d.width,c=d.height}else this.fontType==="bitmap"?(o=this.bitmapCharWidth,c=this.bitmapCharHeight):(o=Math.round(this.cellWidth)||10,c=Math.round(this.cellHeight)||14);this.cellWidth=Math.round(o),this.cellHeight=Math.round(c)}this.scalingMode===w.Responsive?(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1):this.fixedGridMode&&this.fixedCols&&this.fixedRows?(this.cols=this.fixedCols,this.rows=this.fixedRows):(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1);let i=this.cols*this.cellWidth,s=this.rows*this.cellHeight,a=t/i,n=e/s,r=Math.min(a,n),l;switch(this.scalingMode){case w.Integer:l=Math.max(1,Math.floor(r));break;case w.Half:l=Math.max(.5,Math.floor(r*2)/2);break;case w.Quarter:l=Math.max(.25,Math.floor(r*4)/4);break;case w.Eighth:l=Math.max(.125,Math.floor(r*8)/8);break;case w.Responsive:l=1;break;case w.None:default:l=Math.max(.1,r);break}this.currentScale=l,this.canvas.width=i,this.canvas.height=s,this.ctx.imageSmoothingEnabled=!1,this.canvas.style.cssText=`
|
|
23
24
|
flex-shrink: 0 !important;
|
|
24
25
|
flex-grow: 0 !important;
|
|
@@ -31,4 +32,6 @@ var F=Object.defineProperty;var O=(g,t,e)=>t in g?F(g,t,{enumerable:!0,configura
|
|
|
31
32
|
transform: scale(${l}) !important;
|
|
32
33
|
will-change: transform !important;
|
|
33
34
|
backface-visibility: hidden !important;
|
|
35
|
+
pointer-events: auto !important;
|
|
36
|
+
touch-action: none !important;
|
|
34
37
|
`,this.fontType==="web"&&(this.fontSize=Math.round(this.cellHeight/14*12)),this.offsetX=0,this.offsetY=0}createEmptyGrid(){let t=[];for(let e=0;e<this.rows;e++){let i=[];for(let s=0;s<this.cols;s++)i.push({char:" ",fgColor:this.defaultFgColor,bgColor:this.defaultBgColor});t.push(i)}return t}enableAutoResize(){this.resizeObserver=new ResizeObserver(()=>{let t=this.cols,e=this.rows;if(this.calculateGridSize(),this.cols!==t||this.rows!==e){let i=this.cells;this.cells=this.createEmptyGrid();let s=Math.min(t,this.cols),a=Math.min(e,this.rows);for(let n=0;n<a;n++)for(let r=0;r<s;r++)this.cells[n][r]=i[n][r]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(t,e,i,s,a){if(e<0||e>=this.rows||t<0||t>=this.cols)return;let n=i&&typeof i=="string"?i.charAt(0):" ";this.cells[e][t]={char:n,fgColor:s??this.defaultFgColor,bgColor:a??this.defaultBgColor}}getCell(t,e){return e<0||e>=this.rows||t<0||t>=this.cols?null:this.cells[e][t]}write(t,e,i,s,a){for(let n=0;n<i.length;n++)this.setCell(t+n,e,i[n],s,a)}fillRect(t,e,i,s,a=" ",n,r){for(let l=e;l<e+s;l++)for(let o=t;o<t+i;o++)this.setCell(o,l,a,n,r)}clear(){this.cells=this.createEmptyGrid()}setFromArray(t){let e=t.width*t.height;if(t.cells.length!==e)throw new Error(`Invalid array length: expected ${e} (${t.width}\xD7${t.height}), got ${t.cells.length}`);let i=0;for(let s=0;s<t.height;s++)for(let a=0;a<t.width;a++){let n=t.cells[i];s<this.rows&&a<this.cols&&this.setCell(a,s,n.char,n.fgColor,n.bgColor),i++}}render(){if(this.fontType==="bitmap"&&this.bitmapFont&&this.useImageDataRendering){this.renderWithImageData();return}this.renderClassic()}renderWithImageData(){if(!this.bitmapFont)return;let 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 l=0;l<this.rows;l++)for(let o=0;o<this.cols;o++){let c=this.cells[l][o],d=this.parseColorToRGB(c.bgColor),m=this.parseColorToRGB(c.fgColor),u=c.char.charCodeAt(0),C=this.bitmapFont.get(u);for(let b=0;b<this.bitmapCharHeight;b++)for(let p=0;p<this.bitmapCharWidth;p++){let v=o*this.bitmapCharWidth+p,y=((l*this.bitmapCharHeight+b)*t+v)*4,k=!1;if(C&&b<C.length){let z=C[b],L=1<<7-p;k=(z&L)!==0}k?(i[y]=m.r,i[y+1]=m.g,i[y+2]=m.b,i[y+3]=m.a):(i[y]=d.r,i[y+1]=d.g,i[y+2]=d.b,i[y+3]=d.a)}}this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges";let s=document.createElement("canvas");s.width=t,s.height=e,s.getContext("2d").putImageData(this.imageDataBuffer,0,0);let n=this.cols*this.cellWidth,r=this.rows*this.cellHeight;this.ctx.drawImage(s,0,0,t,e,this.offsetX,this.offsetY,n,r),this.showDebugGrid&&this.drawDebugGrid()}parseColorToRGB(t){let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10),a:e[4]?Math.round(parseFloat(e[4])*255):255};if(t.startsWith("#")){let a=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(a,(r,l,o,c)=>l+l+o+o+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 s={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255],transparent:[0,0,0]}[t.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2],a:t==="transparent"?0:255}:{r:255,g:255,b:255,a:255}}renderClassic(){this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.fontType==="bitmap"||this.fontType==="image"?(this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges"):(this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.canvas.style.imageRendering="auto",this.ctx.font=`${this.fontSize}px ${this.fontFamily}`,this.ctx.textBaseline="top",this.ctx.textRendering="optimizeLegibility");for(let t=0;t<this.rows;t++)for(let e=0;e<this.cols;e++){let i=this.cells[t][e],s=Math.floor(this.offsetX+e*this.cellWidth),a=Math.floor(this.offsetY+t*this.cellHeight),n=Math.floor(this.offsetX+(e+1)*this.cellWidth),r=Math.floor(this.offsetY+(t+1)*this.cellHeight),l=n-s,o=r-a;if((this.canvasBgColor!==null||i.bgColor!==this.defaultBgColor)&&(this.ctx.fillStyle=i.bgColor,this.ctx.fillRect(s,a,l,o)),i.char!==" ")if(this.fontType==="image"&&this.imageAtlas){let d=i.char.charCodeAt(0);this.imageAtlas.drawChar(this.ctx,d,s,a,l,o,i.fgColor)}else if(this.fontType==="bitmap"&&this.bitmapFont)this.drawBitmapChar(i.char,s,a,l,o,i.fgColor);else{this.ctx.fillStyle=i.fgColor;let d=s+(l-this.ctx.measureText(i.char).width)/2,m=a+(o-this.fontSize)/2;this.ctx.fillText(i.char,d,m)}}this.showDebugGrid&&this.drawDebugGrid()}drawBitmapChar(t,e,i,s,a,n){let r=t.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,r,e,i,s,a,n);return}if(!this.bitmapFont)return;let l=this.bitmapFont.get(r);if(!l)return;let o=s/this.bitmapCharWidth,c=a/this.bitmapCharHeight;this.ctx.fillStyle=n;for(let d=0;d<Math.min(l.length,this.bitmapCharHeight);d++){let m=l[d],u=i+d*c,C=i+(d+1)*c;for(let b=0;b<this.bitmapCharWidth;b++){let p=1<<7-b;if(m&p){let v=e+b*o,G=e+(b+1)*o;this.ctx.fillRect(v,u,G-v,C-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}getCurrentScale(){return this.currentScale}getScalingMode(){return this.scalingMode}getOffsets(){return{offsetX:this.offsetX,offsetY:this.offsetY}}setDebugGrid(t){this.showDebugGrid=t,t&&!this.gridOverlay?(this.gridOverlay=new x(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10}),this.drawDebugGrid()):!t&&this.gridOverlay?(this.gridOverlay.destroy(),this.gridOverlay=void 0):t&&this.gridOverlay&&this.gridOverlay.setVisible(!0)}setCanvasBackgroundColor(t){this.canvasBgColor=t}getCanvasBackgroundColor(){return this.canvasBgColor}setFixedGrid(t,e,i){this.fixedGridMode=!0,this.fixedCols=t,this.fixedRows=e,i!==void 0&&(this.cellAspectRatio=i);let s=this.cols,a=this.rows,n=this.cells;if(this.calculateGridSize(),this.cols!==s||this.rows!==a){this.cells=this.createEmptyGrid();let r=Math.min(s,this.cols),l=Math.min(a,this.rows);for(let o=0;o<l;o++)for(let c=0;c<r;c++)this.cells[o][c]=n[o][c]}this.render()}setAdaptiveGrid(t,e){this.fixedGridMode=!1,this.fixedCols=void 0,this.fixedRows=void 0,t!==void 0&&(this.cellWidth=t),e!==void 0&&(this.cellHeight=e);let i=this.cols,s=this.rows,a=this.cells;if(this.calculateGridSize(),this.cols!==i||this.rows!==s){this.cells=this.createEmptyGrid();let n=Math.min(i,this.cols),r=Math.min(s,this.rows);for(let l=0;l<r;l++)for(let o=0;o<n;o++)this.cells[l][o]=a[l][o]}this.render()}isFixedGridMode(){return this.fixedGridMode}setDebugGridColor(t){this.debugGridColor=t}isDebugGridEnabled(){return this.showDebugGrid}setImageDataRendering(t){this.useImageDataRendering=t,t&&this.fontType==="bitmap"?console.warn("[Render] ImageData rendering enabled (optimized for benchmarks)"):t&&(console.warn("[Render] ImageData rendering requires bitmap font, keeping classic mode"),this.useImageDataRendering=!1)}isImageDataRenderingEnabled(){return this.useImageDataRendering}setWebFont(t,e){this.fontType="web",this.fontFamily=t,e!==void 0&&(this.fontSize=e),this.bitmapFont=void 0,this.bitmapAtlas=void 0,this.useImageDataRendering=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid()}setBitmapFont(t,e,i,s,a){this.fontType="bitmap",this.bitmapFont=t,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.bitmapAtlas=new M(t,e,i,s,a),this.cellWidth=s,this.cellHeight=a,this.calculateGridSize(),this.cells=this.createEmptyGrid()}async setImageFont(t,e,i,s,a,n){this.fontType="image",this.imageAtlas=new H({glyphWidth:e,glyphHeight:i,cellWidth:s,cellHeight:a,atlasBlocks:n}),await this.imageAtlas.loadFromPNG(t),this.cellWidth=s,this.cellHeight=a,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.calculateGridSize(),this.cells=this.createEmptyGrid()}getFontType(){return this.fontType}getBitmapFont(){return this.bitmapFont}getBitmapCharDimensions(){return this.fontType!=="bitmap"?null:{width:this.bitmapCharWidth,height:this.bitmapCharHeight}}setPalette(t){this.paletteCache=t}renderDisplayData(t){if(!t||!t.cells||t.cells.length===0){console.warn("[Terminal2D] Empty display data");return}if(t.width===0||t.height===0){console.warn("[Terminal2D] Invalid display dimensions:",t.width,t.height);return}(t.width!==this.cols||t.height!==this.rows)&&this.setFixedGrid(t.width,t.height,this.cellAspectRatio);let e=this.paletteCache??t.palette;if(!e||e.length===0){console.error("[Terminal2D] No palette available (neither cached nor in display)");return}let i=f(s=>{if(s==null||isNaN(s))return console.warn("[Terminal2D] Invalid palette index (undefined/null/NaN):",s),this.defaultFgColor;if(s===255)return"rgba(0, 0, 0, 0)";if(s<0||s>=e.length)return console.warn(`[Terminal2D] Invalid palette index: ${s}`),this.defaultFgColor;let a=e[s];return!a||typeof a.r!="number"?(console.warn(`[Terminal2D] Corrupted palette entry at index ${s}:`,a),this.defaultFgColor):`rgba(${a.r}, ${a.g}, ${a.b}, ${a.a/255})`},"convertColor");for(let s=0;s<t.height&&s<this.rows;s++)for(let a=0;a<t.width&&a<this.cols;a++){let n=s*t.width+a;if(n>=t.cells.length)break;let r=t.cells[n];if(!r)continue;let l=i(r.fgColorIndex),o=i(r.bgColorIndex);this.setCell(a,s,r.char??" ",l,o)}this.render()}isReady(){return!0}getCols(){return this.cols}getRows(){return this.rows}resize(t,e){this.setFixedGrid(t,e)}setScalingMode(t){if(this.scalingMode===t)return;let e=this.cols,i=this.rows;if(this.scalingMode=t,this.calculateGridSize(),this.cols!==e||this.rows!==i){let s=this.cells;if(this.cells=this.createEmptyGrid(),s&&s.length>0){let a=Math.min(e,this.cols),n=Math.min(i,this.rows);for(let r=0;r<n;r++)for(let l=0;l<a;l++)s[r]&&s[r][l]&&(this.cells[r][l]=s[r][l])}}this.render()}setCellSize(t,e){let i=Math.max(1,Math.min(255,Math.round(t))),s=Math.max(1,Math.min(255,Math.round(e)));if(this.cellWidth===i&&this.cellHeight===s)return;let a=this.cols,n=this.rows;if(this.cellWidth=i,this.cellHeight=s,this.customCellSize=!0,this.calculateGridSize(),this.cols!==a||this.rows!==n){let r=this.cells;if(this.cells=this.createEmptyGrid(),r&&r.length>0){let l=Math.min(a,this.cols),o=Math.min(n,this.rows);for(let c=0;c<o;c++)for(let d=0;d<l;d++)r[c]&&r[c][d]&&(this.cells[c][d]=r[c][d])}}this.render()}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}getMaxCells(){return 65536}destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=void 0),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}};f(T,"Terminal2D");var I=T;var B=["#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 $(g,t=B){return g<0||g>=t.length?"#ff00ff":t[g]}f($,"paletteIndexToColor");function U(g,t=B){let e=t.indexOf(g.toLowerCase());return e>=0?e:0}f(U,"colorToPaletteIndex");import{ScalingMode as ft}from"@utsp/types";export{M as BitmapFontAtlas,B as DEFAULT_PALETTE,x as GridOverlay,H as ImageFontAtlas,ft as ScalingMode,I as Terminal2D,U as colorToPaletteIndex,E as getAtlasColumns,W as getCharGridPosition,D as getMaxCharCode,$ as paletteIndexToColor};
|
package/dist/gl/index.cjs
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
justify-content: center !important;
|
|
20
20
|
align-items: center !important;
|
|
21
21
|
isolation: isolate !important;
|
|
22
|
+
pointer-events: none !important;
|
|
22
23
|
`,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
24
|
flex-shrink: 0 !important;
|
|
24
25
|
width: ${this.canvas.width}px !important;
|
|
@@ -32,6 +33,8 @@
|
|
|
32
33
|
backface-visibility: hidden !important;
|
|
33
34
|
position: relative !important;
|
|
34
35
|
z-index: 1 !important;
|
|
36
|
+
pointer-events: auto !important;
|
|
37
|
+
touch-action: none !important;
|
|
35
38
|
`;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=n||!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"),s=t.getContext("webgl")||t.getContext("experimental-webgl");if(!s||!(s instanceof WebGLRenderingContext))return e.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),e;let i=s;e.webgl1=!0;try{e.maxTextureSize=i.getParameter(i.MAX_TEXTURE_SIZE);let o=i.getParameter(i.MAX_VIEWPORT_DIMS);e.maxViewportDims=[o[0],o[1]]}catch(o){return e.errors.push(`\u274C Failed to query WebGL parameters: ${o}`),e}let n=i.getExtension("OES_element_index_uint");e.uint32Indices=!!n;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),this.instanceData=new Float32Array(this.maxCells*8),console.warn(`[TerminalGL] \u{1F680} initInstancedBuffers: maxCells=${this.maxCells}, instanceData.length=${this.instanceData.length}`),e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer),e.bufferData(e.ARRAY_BUFFER,this.instanceData.byteLength,e.DYNAMIC_DRAW)}initRenderBuffers(){let e=this.cols*this.rows*2;this.maxCells=Math.ceil(e*2),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.staticPositionsInitialized=!1}precomputeStaticPositions(){let e=this.cellWidth,t=this.cellHeight,s=this.glyphOffsetX,i=this.glyphOffsetY,n=this.charWidth,a=this.charHeight,l=0,o=0,c=0;for(let h=0;h<this.rows;h++){let m=Math.round(h*t),b=Math.round(m+t);for(let v=0;v<this.cols;v++){let u=Math.round(v*e),g=Math.round(u+e);this.renderPositions[l++]=u,this.renderPositions[l++]=m,this.renderPositions[l++]=g,this.renderPositions[l++]=m,this.renderPositions[l++]=u,this.renderPositions[l++]=b,this.renderPositions[l++]=g,this.renderPositions[l++]=b,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 E=Math.round(u+s),p=Math.round(m+i),w=Math.round(E+n),A=Math.round(p+a);this.renderPositions[l++]=E,this.renderPositions[l++]=p,this.renderPositions[l++]=w,this.renderPositions[l++]=p,this.renderPositions[l++]=E,this.renderPositions[l++]=A,this.renderPositions[l++]=w,this.renderPositions[l++]=A,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
39
|
// Per-vertex attributes (template quad)
|
|
37
40
|
attribute vec2 aPosition; // Local quad position (0,0 to cellW,cellH)
|
package/dist/gl/index.mjs
CHANGED
|
@@ -19,6 +19,7 @@ var $=Object.defineProperty;var V=(v,e,t)=>e in v?$(v,e,{enumerable:!0,configura
|
|
|
19
19
|
justify-content: center !important;
|
|
20
20
|
align-items: center !important;
|
|
21
21
|
isolation: isolate !important;
|
|
22
|
+
pointer-events: none !important;
|
|
22
23
|
`,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
24
|
flex-shrink: 0 !important;
|
|
24
25
|
width: ${this.canvas.width}px !important;
|
|
@@ -32,6 +33,8 @@ var $=Object.defineProperty;var V=(v,e,t)=>e in v?$(v,e,{enumerable:!0,configura
|
|
|
32
33
|
backface-visibility: hidden !important;
|
|
33
34
|
position: relative !important;
|
|
34
35
|
z-index: 1 !important;
|
|
36
|
+
pointer-events: auto !important;
|
|
37
|
+
touch-action: none !important;
|
|
35
38
|
`;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=n||!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"),s=t.getContext("webgl")||t.getContext("experimental-webgl");if(!s||!(s instanceof WebGLRenderingContext))return e.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),e;let i=s;e.webgl1=!0;try{e.maxTextureSize=i.getParameter(i.MAX_TEXTURE_SIZE);let o=i.getParameter(i.MAX_VIEWPORT_DIMS);e.maxViewportDims=[o[0],o[1]]}catch(o){return e.errors.push(`\u274C Failed to query WebGL parameters: ${o}`),e}let n=i.getExtension("OES_element_index_uint");e.uint32Indices=!!n;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),this.instanceData=new Float32Array(this.maxCells*8),console.warn(`[TerminalGL] \u{1F680} initInstancedBuffers: maxCells=${this.maxCells}, instanceData.length=${this.instanceData.length}`),e.bindBuffer(e.ARRAY_BUFFER,this.instanceDataBuffer),e.bufferData(e.ARRAY_BUFFER,this.instanceData.byteLength,e.DYNAMIC_DRAW)}initRenderBuffers(){let e=this.cols*this.rows*2;this.maxCells=Math.ceil(e*2),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.staticPositionsInitialized=!1}precomputeStaticPositions(){let e=this.cellWidth,t=this.cellHeight,s=this.glyphOffsetX,i=this.glyphOffsetY,n=this.charWidth,a=this.charHeight,l=0,o=0,c=0;for(let h=0;h<this.rows;h++){let u=Math.round(h*t),m=Math.round(u+t);for(let b=0;b<this.cols;b++){let f=Math.round(b*e),p=Math.round(f+e);this.renderPositions[l++]=f,this.renderPositions[l++]=u,this.renderPositions[l++]=p,this.renderPositions[l++]=u,this.renderPositions[l++]=f,this.renderPositions[l++]=m,this.renderPositions[l++]=p,this.renderPositions[l++]=m,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 g=Math.round(f+s),x=Math.round(u+i),w=Math.round(g+n),A=Math.round(x+a);this.renderPositions[l++]=g,this.renderPositions[l++]=x,this.renderPositions[l++]=w,this.renderPositions[l++]=x,this.renderPositions[l++]=g,this.renderPositions[l++]=A,this.renderPositions[l++]=w,this.renderPositions[l++]=A,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
39
|
// Per-vertex attributes (template quad)
|
|
37
40
|
attribute vec2 aPosition; // Local quad position (0,0 to cellW,cellH)
|
package/dist/index.cjs
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
justify-content: center !important;
|
|
20
20
|
align-items: center !important;
|
|
21
21
|
isolation: isolate !important;
|
|
22
|
+
pointer-events: none !important;
|
|
22
23
|
`,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
24
|
flex-shrink: 0 !important;
|
|
24
25
|
width: ${this.canvas.width}px !important;
|
|
@@ -32,6 +33,8 @@
|
|
|
32
33
|
backface-visibility: hidden !important;
|
|
33
34
|
position: relative !important;
|
|
34
35
|
z-index: 1 !important;
|
|
36
|
+
pointer-events: auto !important;
|
|
37
|
+
touch-action: none !important;
|
|
35
38
|
`;let h=this.canvas.getContext("webgl",{alpha:this.canvasBgColor===null,premultipliedAlpha:!1});if(!h)throw new Error("TerminalGL: WebGL not supported");this.gl=h,this.supportsUint32Indices=!!h.getExtension("OES_element_index_uint"),this.useUint16Indices=a||!this.supportsUint32Indices,this.useUint16Indices?console.warn(`[TerminalGL] \u{1F4CA} Using Uint16 indices (max ${s.maxCellsUint16} cells)`):console.warn(`[TerminalGL] \u{1F4CA} Using Uint32 indices (max ${s.maxCellsUint32} cells)`),this.vaoExtension=h.getExtension("OES_vertex_array_object"),this.vaoExtension&&console.warn("[TerminalGL] \u2705 VAO extension enabled (faster attribute binding)"),this.instancedExtension=h.getExtension("ANGLE_instanced_arrays"),this.instancedExtension?(this.useInstancing=!0,console.warn("[TerminalGL] \u{1F680} Instanced rendering enabled (massive draw call reduction)")):console.warn("[TerminalGL] \u26A0\uFE0F Instanced rendering not available (fallback to standard rendering)"),this.containerDiv.appendChild(this.canvas),this.ambientEffectEnabled&&(this.createAmbientEffectCanvas(),console.warn("[TerminalGL] \u{1F308} Ambient effect enabled at startup")),this.parentElement.appendChild(this.containerDiv),this.initRenderBuffers();try{this.initWebGL()}catch(c){throw console.error("[TerminalGL] \u274C Failed to initialize WebGL:",c),c}this.showGrid&&this.initGridOverlay(),this.setupResizeObserver()}static checkCompatibility(){let t={webgl1:!1,uint32Indices:!1,maxTextureSize:0,maxViewportDims:[0,0],maxCellsUint16:0,maxCellsUint32:0,recommendedMaxCells:0,warnings:[],errors:[]},e=document.createElement("canvas"),i=e.getContext("webgl")||e.getContext("experimental-webgl");if(!i||!(i instanceof WebGLRenderingContext))return t.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),t;let s=i;t.webgl1=!0;try{t.maxTextureSize=s.getParameter(s.MAX_TEXTURE_SIZE);let n=s.getParameter(s.MAX_VIEWPORT_DIMS);t.maxViewportDims=[n[0],n[1]]}catch(n){return t.errors.push(`\u274C Failed to query WebGL parameters: ${n}`),t}let a=s.getExtension("OES_element_index_uint");t.uint32Indices=!!a;let r=8;if(t.maxCellsUint16=Math.floor(65535/r),t.uint32Indices){let n=Math.floor(t.maxTextureSize*t.maxTextureSize/64);t.maxCellsUint32=Math.min(n,262144)}else t.maxCellsUint32=t.maxCellsUint16,t.warnings.push(`\u26A0\uFE0F OES_element_index_uint not supported - limited to ${t.maxCellsUint16} cells (e.g., 90\xD790 or 127\xD764)`);return t.recommendedMaxCells=Math.floor((t.uint32Indices?t.maxCellsUint32:t.maxCellsUint16)*.8),t.maxTextureSize<256?t.errors.push(`\u274C MAX_TEXTURE_SIZE too small: ${t.maxTextureSize} (minimum 256 required for font atlas)`):t.maxTextureSize<2048&&t.warnings.push(`\u26A0\uFE0F Small MAX_TEXTURE_SIZE: ${t.maxTextureSize} (may limit font atlas)`),(t.maxViewportDims[0]<1024||t.maxViewportDims[1]<768)&&t.warnings.push(`\u26A0\uFE0F Small MAX_VIEWPORT_DIMS: ${t.maxViewportDims[0]}\xD7${t.maxViewportDims[1]}`),s.getExtension("WEBGL_lose_context")||t.warnings.push("\u26A0\uFE0F WEBGL_lose_context not supported - may cause memory leaks"),t}initInstancedBuffers(){let t=this.gl;this.templateQuadPositions=new Float32Array([0,0,this.cellWidth,0,0,this.cellHeight,this.cellWidth,this.cellHeight]),this.templateQuadIndices=new Uint16Array([0,1,2,2,1,3]),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.templateQuadPositions,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,this.templateQuadIndices,t.STATIC_DRAW),this.instanceData=new Float32Array(this.maxCells*8),console.warn(`[TerminalGL] \u{1F680} initInstancedBuffers: maxCells=${this.maxCells}, instanceData.length=${this.instanceData.length}`),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer),t.bufferData(t.ARRAY_BUFFER,this.instanceData.byteLength,t.DYNAMIC_DRAW)}initRenderBuffers(){let t=this.cols*this.rows*2;this.maxCells=Math.ceil(t*2),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.staticPositionsInitialized=!1}precomputeStaticPositions(){let t=this.cellWidth,e=this.cellHeight,i=this.glyphOffsetX,s=this.glyphOffsetY,a=this.charWidth,r=this.charHeight,o=0,n=0,h=0;for(let d=0;d<this.rows;d++){let f=Math.round(d*e),m=Math.round(f+e);for(let g=0;g<this.cols;g++){let u=Math.round(g*t),p=Math.round(u+t);this.renderPositions[o++]=u,this.renderPositions[o++]=f,this.renderPositions[o++]=p,this.renderPositions[o++]=f,this.renderPositions[o++]=u,this.renderPositions[o++]=m,this.renderPositions[o++]=p,this.renderPositions[o++]=m,this.renderIndices[n++]=h,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+3,h+=4;let C=Math.round(u+i),x=Math.round(f+s),E=Math.round(C+a),w=Math.round(x+r);this.renderPositions[o++]=C,this.renderPositions[o++]=x,this.renderPositions[o++]=E,this.renderPositions[o++]=x,this.renderPositions[o++]=C,this.renderPositions[o++]=w,this.renderPositions[o++]=E,this.renderPositions[o++]=w,this.renderIndices[n++]=h,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+3,h+=4}}let c=this.gl;c.bindBuffer(c.ARRAY_BUFFER,this.positionBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,this.renderPositions),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,this.indexBuffer),c.bufferSubData(c.ELEMENT_ARRAY_BUFFER,0,this.renderIndices),this.staticPositionsInitialized=!0}initWebGL(){let t=this.gl,e;this.useInstancing?e=`
|
|
36
39
|
// Per-vertex attributes (template quad)
|
|
37
40
|
attribute vec2 aPosition; // Local quad position (0,0 to cellW,cellH)
|
|
@@ -138,6 +141,7 @@
|
|
|
138
141
|
justify-content: center !important;
|
|
139
142
|
align-items: center !important;
|
|
140
143
|
isolation: isolate !important;
|
|
144
|
+
pointer-events: none !important;
|
|
141
145
|
`,this.canvas=document.createElement("canvas"),this.canvas.className="terminal2d-canvas",e.className&&(this.canvas.className+=" "+e.className),e.style&&Object.assign(this.canvas.style,e.style),this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges",this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv);let s=this.canvas.getContext("2d",{alpha:!0,desynchronized:!1});if(!s)throw new Error("UTSPRender: Impossible d'obtenir le contexte 2D du canvas");this.ctx=s,this.ctx.imageSmoothingEnabled=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid(),this.showDebugGrid&&(this.gridOverlay=new A(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;if(!this.customCellSize){let h,c;if(this.fontType==="image"&&this.imageAtlas){let d=this.imageAtlas.getCellDimensions();h=d.width,c=d.height}else this.fontType==="bitmap"?(h=this.bitmapCharWidth,c=this.bitmapCharHeight):(h=Math.round(this.cellWidth)||10,c=Math.round(this.cellHeight)||14);this.cellWidth=Math.round(h),this.cellHeight=Math.round(c)}this.scalingMode===R.ScalingMode.Responsive?(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1):this.fixedGridMode&&this.fixedCols&&this.fixedRows?(this.cols=this.fixedCols,this.rows=this.fixedRows):(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1);let i=this.cols*this.cellWidth,s=this.rows*this.cellHeight,a=t/i,r=e/s,o=Math.min(a,r),n;switch(this.scalingMode){case R.ScalingMode.Integer:n=Math.max(1,Math.floor(o));break;case R.ScalingMode.Half:n=Math.max(.5,Math.floor(o*2)/2);break;case R.ScalingMode.Quarter:n=Math.max(.25,Math.floor(o*4)/4);break;case R.ScalingMode.Eighth:n=Math.max(.125,Math.floor(o*8)/8);break;case R.ScalingMode.Responsive:n=1;break;case R.ScalingMode.None:default:n=Math.max(.1,o);break}this.currentScale=n,this.canvas.width=i,this.canvas.height=s,this.ctx.imageSmoothingEnabled=!1,this.canvas.style.cssText=`
|
|
142
146
|
flex-shrink: 0 !important;
|
|
143
147
|
flex-grow: 0 !important;
|
|
@@ -150,6 +154,8 @@
|
|
|
150
154
|
transform: scale(${n}) !important;
|
|
151
155
|
will-change: transform !important;
|
|
152
156
|
backface-visibility: hidden !important;
|
|
157
|
+
pointer-events: auto !important;
|
|
158
|
+
touch-action: none !important;
|
|
153
159
|
`,this.fontType==="web"&&(this.fontSize=Math.round(this.cellHeight/14*12)),this.offsetX=0,this.offsetY=0}createEmptyGrid(){let t=[];for(let e=0;e<this.rows;e++){let i=[];for(let s=0;s<this.cols;s++)i.push({char:" ",fgColor:this.defaultFgColor,bgColor:this.defaultBgColor});t.push(i)}return t}enableAutoResize(){this.resizeObserver=new ResizeObserver(()=>{let t=this.cols,e=this.rows;if(this.calculateGridSize(),this.cols!==t||this.rows!==e){let i=this.cells;this.cells=this.createEmptyGrid();let s=Math.min(t,this.cols),a=Math.min(e,this.rows);for(let r=0;r<a;r++)for(let o=0;o<s;o++)this.cells[r][o]=i[r][o]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(t,e,i,s,a){if(e<0||e>=this.rows||t<0||t>=this.cols)return;let r=i&&typeof i=="string"?i.charAt(0):" ";this.cells[e][t]={char:r,fgColor:s??this.defaultFgColor,bgColor:a??this.defaultBgColor}}getCell(t,e){return e<0||e>=this.rows||t<0||t>=this.cols?null:this.cells[e][t]}write(t,e,i,s,a){for(let r=0;r<i.length;r++)this.setCell(t+r,e,i[r],s,a)}fillRect(t,e,i,s,a=" ",r,o){for(let n=e;n<e+s;n++)for(let h=t;h<t+i;h++)this.setCell(h,n,a,r,o)}clear(){this.cells=this.createEmptyGrid()}setFromArray(t){let e=t.width*t.height;if(t.cells.length!==e)throw new Error(`Invalid array length: expected ${e} (${t.width}\xD7${t.height}), got ${t.cells.length}`);let i=0;for(let s=0;s<t.height;s++)for(let a=0;a<t.width;a++){let r=t.cells[i];s<this.rows&&a<this.cols&&this.setCell(a,s,r.char,r.fgColor,r.bgColor),i++}}render(){if(this.fontType==="bitmap"&&this.bitmapFont&&this.useImageDataRendering){this.renderWithImageData();return}this.renderClassic()}renderWithImageData(){if(!this.bitmapFont)return;let t=this.cols*this.bitmapCharWidth,e=this.rows*this.bitmapCharHeight;(!this.imageDataBuffer||this.imageDataBuffer.width!==t||this.imageDataBuffer.height!==e)&&(this.imageDataBuffer=this.ctx.createImageData(t,e));let i=this.imageDataBuffer.data;for(let n=0;n<this.rows;n++)for(let h=0;h<this.cols;h++){let c=this.cells[n][h],d=this.parseColorToRGB(c.bgColor),f=this.parseColorToRGB(c.fgColor),m=c.char.charCodeAt(0),g=this.bitmapFont.get(m);for(let u=0;u<this.bitmapCharHeight;u++)for(let p=0;p<this.bitmapCharWidth;p++){let C=h*this.bitmapCharWidth+p,E=((n*this.bitmapCharHeight+u)*t+C)*4,w=!1;if(g&&u<g.length){let H=g[u],T=1<<7-p;w=(H&T)!==0}w?(i[E]=f.r,i[E+1]=f.g,i[E+2]=f.b,i[E+3]=f.a):(i[E]=d.r,i[E+1]=d.g,i[E+2]=d.b,i[E+3]=d.a)}}this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges";let s=document.createElement("canvas");s.width=t,s.height=e,s.getContext("2d").putImageData(this.imageDataBuffer,0,0);let r=this.cols*this.cellWidth,o=this.rows*this.cellHeight;this.ctx.drawImage(s,0,0,t,e,this.offsetX,this.offsetY,r,o),this.showDebugGrid&&this.drawDebugGrid()}parseColorToRGB(t){let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10),a:e[4]?Math.round(parseFloat(e[4])*255):255};if(t.startsWith("#")){let a=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(a,(o,n,h,c)=>n+n+h+h+c+c);let r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);if(r)return{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16),a:255}}let s={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255],transparent:[0,0,0]}[t.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2],a:t==="transparent"?0:255}:{r:255,g:255,b:255,a:255}}renderClassic(){this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.fontType==="bitmap"||this.fontType==="image"?(this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges"):(this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.canvas.style.imageRendering="auto",this.ctx.font=`${this.fontSize}px ${this.fontFamily}`,this.ctx.textBaseline="top",this.ctx.textRendering="optimizeLegibility");for(let t=0;t<this.rows;t++)for(let e=0;e<this.cols;e++){let i=this.cells[t][e],s=Math.floor(this.offsetX+e*this.cellWidth),a=Math.floor(this.offsetY+t*this.cellHeight),r=Math.floor(this.offsetX+(e+1)*this.cellWidth),o=Math.floor(this.offsetY+(t+1)*this.cellHeight),n=r-s,h=o-a;if((this.canvasBgColor!==null||i.bgColor!==this.defaultBgColor)&&(this.ctx.fillStyle=i.bgColor,this.ctx.fillRect(s,a,n,h)),i.char!==" ")if(this.fontType==="image"&&this.imageAtlas){let d=i.char.charCodeAt(0);this.imageAtlas.drawChar(this.ctx,d,s,a,n,h,i.fgColor)}else if(this.fontType==="bitmap"&&this.bitmapFont)this.drawBitmapChar(i.char,s,a,n,h,i.fgColor);else{this.ctx.fillStyle=i.fgColor;let d=s+(n-this.ctx.measureText(i.char).width)/2,f=a+(h-this.fontSize)/2;this.ctx.fillText(i.char,d,f)}}this.showDebugGrid&&this.drawDebugGrid()}drawBitmapChar(t,e,i,s,a,r){let o=t.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,o,e,i,s,a,r);return}if(!this.bitmapFont)return;let n=this.bitmapFont.get(o);if(!n)return;let h=s/this.bitmapCharWidth,c=a/this.bitmapCharHeight;this.ctx.fillStyle=r;for(let d=0;d<Math.min(n.length,this.bitmapCharHeight);d++){let f=n[d],m=i+d*c,g=i+(d+1)*c;for(let u=0;u<this.bitmapCharWidth;u++){let p=1<<7-u;if(f&p){let C=e+u*h,x=e+(u+1)*h;this.ctx.fillRect(C,m,x-C,g-m)}}}}drawDebugGrid(){if(!this.gridOverlay)return;let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;this.gridOverlay.update(this.cols,this.rows,this.cellWidth,this.cellHeight,t,e,this.offsetX,this.offsetY)}getCanvas(){return this.canvas}getContext(){return this.ctx}getDimensions(){return{cols:this.cols,rows:this.rows}}getCellDimensions(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getScalingMode(){return this.scalingMode}getOffsets(){return{offsetX:this.offsetX,offsetY:this.offsetY}}setDebugGrid(t){this.showDebugGrid=t,t&&!this.gridOverlay?(this.gridOverlay=new A(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10}),this.drawDebugGrid()):!t&&this.gridOverlay?(this.gridOverlay.destroy(),this.gridOverlay=void 0):t&&this.gridOverlay&&this.gridOverlay.setVisible(!0)}setCanvasBackgroundColor(t){this.canvasBgColor=t}getCanvasBackgroundColor(){return this.canvasBgColor}setFixedGrid(t,e,i){this.fixedGridMode=!0,this.fixedCols=t,this.fixedRows=e,i!==void 0&&(this.cellAspectRatio=i);let s=this.cols,a=this.rows,r=this.cells;if(this.calculateGridSize(),this.cols!==s||this.rows!==a){this.cells=this.createEmptyGrid();let o=Math.min(s,this.cols),n=Math.min(a,this.rows);for(let h=0;h<n;h++)for(let c=0;c<o;c++)this.cells[h][c]=r[h][c]}this.render()}setAdaptiveGrid(t,e){this.fixedGridMode=!1,this.fixedCols=void 0,this.fixedRows=void 0,t!==void 0&&(this.cellWidth=t),e!==void 0&&(this.cellHeight=e);let i=this.cols,s=this.rows,a=this.cells;if(this.calculateGridSize(),this.cols!==i||this.rows!==s){this.cells=this.createEmptyGrid();let r=Math.min(i,this.cols),o=Math.min(s,this.rows);for(let n=0;n<o;n++)for(let h=0;h<r;h++)this.cells[n][h]=a[n][h]}this.render()}isFixedGridMode(){return this.fixedGridMode}setDebugGridColor(t){this.debugGridColor=t}isDebugGridEnabled(){return this.showDebugGrid}setImageDataRendering(t){this.useImageDataRendering=t,t&&this.fontType==="bitmap"?console.warn("[Render] ImageData rendering enabled (optimized for benchmarks)"):t&&(console.warn("[Render] ImageData rendering requires bitmap font, keeping classic mode"),this.useImageDataRendering=!1)}isImageDataRenderingEnabled(){return this.useImageDataRendering}setWebFont(t,e){this.fontType="web",this.fontFamily=t,e!==void 0&&(this.fontSize=e),this.bitmapFont=void 0,this.bitmapAtlas=void 0,this.useImageDataRendering=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid()}setBitmapFont(t,e,i,s,a){this.fontType="bitmap",this.bitmapFont=t,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.bitmapAtlas=new D(t,e,i,s,a),this.cellWidth=s,this.cellHeight=a,this.calculateGridSize(),this.cells=this.createEmptyGrid()}async setImageFont(t,e,i,s,a,r){this.fontType="image",this.imageAtlas=new F({glyphWidth:e,glyphHeight:i,cellWidth:s,cellHeight:a,atlasBlocks:r}),await this.imageAtlas.loadFromPNG(t),this.cellWidth=s,this.cellHeight=a,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.calculateGridSize(),this.cells=this.createEmptyGrid()}getFontType(){return this.fontType}getBitmapFont(){return this.bitmapFont}getBitmapCharDimensions(){return this.fontType!=="bitmap"?null:{width:this.bitmapCharWidth,height:this.bitmapCharHeight}}setPalette(t){this.paletteCache=t}renderDisplayData(t){if(!t||!t.cells||t.cells.length===0){console.warn("[Terminal2D] Empty display data");return}if(t.width===0||t.height===0){console.warn("[Terminal2D] Invalid display dimensions:",t.width,t.height);return}(t.width!==this.cols||t.height!==this.rows)&&this.setFixedGrid(t.width,t.height,this.cellAspectRatio);let e=this.paletteCache??t.palette;if(!e||e.length===0){console.error("[Terminal2D] No palette available (neither cached nor in display)");return}let i=v(s=>{if(s==null||isNaN(s))return console.warn("[Terminal2D] Invalid palette index (undefined/null/NaN):",s),this.defaultFgColor;if(s===255)return"rgba(0, 0, 0, 0)";if(s<0||s>=e.length)return console.warn(`[Terminal2D] Invalid palette index: ${s}`),this.defaultFgColor;let a=e[s];return!a||typeof a.r!="number"?(console.warn(`[Terminal2D] Corrupted palette entry at index ${s}:`,a),this.defaultFgColor):`rgba(${a.r}, ${a.g}, ${a.b}, ${a.a/255})`},"convertColor");for(let s=0;s<t.height&&s<this.rows;s++)for(let a=0;a<t.width&&a<this.cols;a++){let r=s*t.width+a;if(r>=t.cells.length)break;let o=t.cells[r];if(!o)continue;let n=i(o.fgColorIndex),h=i(o.bgColorIndex);this.setCell(a,s,o.char??" ",n,h)}this.render()}isReady(){return!0}getCols(){return this.cols}getRows(){return this.rows}resize(t,e){this.setFixedGrid(t,e)}setScalingMode(t){if(this.scalingMode===t)return;let e=this.cols,i=this.rows;if(this.scalingMode=t,this.calculateGridSize(),this.cols!==e||this.rows!==i){let s=this.cells;if(this.cells=this.createEmptyGrid(),s&&s.length>0){let a=Math.min(e,this.cols),r=Math.min(i,this.rows);for(let o=0;o<r;o++)for(let n=0;n<a;n++)s[o]&&s[o][n]&&(this.cells[o][n]=s[o][n])}}this.render()}setCellSize(t,e){let i=Math.max(1,Math.min(255,Math.round(t))),s=Math.max(1,Math.min(255,Math.round(e)));if(this.cellWidth===i&&this.cellHeight===s)return;let a=this.cols,r=this.rows;if(this.cellWidth=i,this.cellHeight=s,this.customCellSize=!0,this.calculateGridSize(),this.cols!==a||this.rows!==r){let o=this.cells;if(this.cells=this.createEmptyGrid(),o&&o.length>0){let n=Math.min(a,this.cols),h=Math.min(r,this.rows);for(let c=0;c<h;c++)for(let d=0;d<n;d++)o[c]&&o[c][d]&&(this.cells[c][d]=o[c][d])}}this.render()}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}getMaxCells(){return 65536}destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=void 0),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}};v(V,"Terminal2D");var P=V;var X=class X{constructor(t,e={}){l(this,"container");l(this,"overlayDiv",null);l(this,"button",null);l(this,"options");l(this,"started",!1);l(this,"onStartCallback");this.container=t,this.options={buttonText:e.buttonText??"Click to Start",onStart:e.onStart??(()=>{}),backgroundColor:e.backgroundColor??"rgba(0, 0, 0, 0.8)",buttonColor:e.buttonColor??"#4a90d9",buttonHoverColor:e.buttonHoverColor??"#357abd",buttonTextColor:e.buttonTextColor??"#ffffff",zIndex:e.zIndex??1e3},this.onStartCallback=e.onStart,this.createOverlay()}createOverlay(){let t=window.getComputedStyle(this.container).position;t!=="relative"&&t!=="absolute"&&t!=="fixed"&&(this.container.style.position="relative"),this.overlayDiv=document.createElement("div"),this.overlayDiv.className="utsp-autoplay-overlay",this.overlayDiv.style.cssText=`
|
|
154
160
|
position: absolute !important;
|
|
155
161
|
top: 0 !important;
|
package/dist/index.mjs
CHANGED
|
@@ -19,6 +19,7 @@ var it=Object.defineProperty;var at=(b,t,e)=>t in b?it(b,t,{enumerable:!0,config
|
|
|
19
19
|
justify-content: center !important;
|
|
20
20
|
align-items: center !important;
|
|
21
21
|
isolation: isolate !important;
|
|
22
|
+
pointer-events: none !important;
|
|
22
23
|
`,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
24
|
flex-shrink: 0 !important;
|
|
24
25
|
width: ${this.canvas.width}px !important;
|
|
@@ -32,6 +33,8 @@ var it=Object.defineProperty;var at=(b,t,e)=>t in b?it(b,t,{enumerable:!0,config
|
|
|
32
33
|
backface-visibility: hidden !important;
|
|
33
34
|
position: relative !important;
|
|
34
35
|
z-index: 1 !important;
|
|
36
|
+
pointer-events: auto !important;
|
|
37
|
+
touch-action: none !important;
|
|
35
38
|
`;let h=this.canvas.getContext("webgl",{alpha:this.canvasBgColor===null,premultipliedAlpha:!1});if(!h)throw new Error("TerminalGL: WebGL not supported");this.gl=h,this.supportsUint32Indices=!!h.getExtension("OES_element_index_uint"),this.useUint16Indices=a||!this.supportsUint32Indices,this.useUint16Indices?console.warn(`[TerminalGL] \u{1F4CA} Using Uint16 indices (max ${s.maxCellsUint16} cells)`):console.warn(`[TerminalGL] \u{1F4CA} Using Uint32 indices (max ${s.maxCellsUint32} cells)`),this.vaoExtension=h.getExtension("OES_vertex_array_object"),this.vaoExtension&&console.warn("[TerminalGL] \u2705 VAO extension enabled (faster attribute binding)"),this.instancedExtension=h.getExtension("ANGLE_instanced_arrays"),this.instancedExtension?(this.useInstancing=!0,console.warn("[TerminalGL] \u{1F680} Instanced rendering enabled (massive draw call reduction)")):console.warn("[TerminalGL] \u26A0\uFE0F Instanced rendering not available (fallback to standard rendering)"),this.containerDiv.appendChild(this.canvas),this.ambientEffectEnabled&&(this.createAmbientEffectCanvas(),console.warn("[TerminalGL] \u{1F308} Ambient effect enabled at startup")),this.parentElement.appendChild(this.containerDiv),this.initRenderBuffers();try{this.initWebGL()}catch(c){throw console.error("[TerminalGL] \u274C Failed to initialize WebGL:",c),c}this.showGrid&&this.initGridOverlay(),this.setupResizeObserver()}static checkCompatibility(){let t={webgl1:!1,uint32Indices:!1,maxTextureSize:0,maxViewportDims:[0,0],maxCellsUint16:0,maxCellsUint32:0,recommendedMaxCells:0,warnings:[],errors:[]},e=document.createElement("canvas"),i=e.getContext("webgl")||e.getContext("experimental-webgl");if(!i||!(i instanceof WebGLRenderingContext))return t.errors.push("\u274C WebGL 1.0 not supported by this browser/device"),t;let s=i;t.webgl1=!0;try{t.maxTextureSize=s.getParameter(s.MAX_TEXTURE_SIZE);let n=s.getParameter(s.MAX_VIEWPORT_DIMS);t.maxViewportDims=[n[0],n[1]]}catch(n){return t.errors.push(`\u274C Failed to query WebGL parameters: ${n}`),t}let a=s.getExtension("OES_element_index_uint");t.uint32Indices=!!a;let r=8;if(t.maxCellsUint16=Math.floor(65535/r),t.uint32Indices){let n=Math.floor(t.maxTextureSize*t.maxTextureSize/64);t.maxCellsUint32=Math.min(n,262144)}else t.maxCellsUint32=t.maxCellsUint16,t.warnings.push(`\u26A0\uFE0F OES_element_index_uint not supported - limited to ${t.maxCellsUint16} cells (e.g., 90\xD790 or 127\xD764)`);return t.recommendedMaxCells=Math.floor((t.uint32Indices?t.maxCellsUint32:t.maxCellsUint16)*.8),t.maxTextureSize<256?t.errors.push(`\u274C MAX_TEXTURE_SIZE too small: ${t.maxTextureSize} (minimum 256 required for font atlas)`):t.maxTextureSize<2048&&t.warnings.push(`\u26A0\uFE0F Small MAX_TEXTURE_SIZE: ${t.maxTextureSize} (may limit font atlas)`),(t.maxViewportDims[0]<1024||t.maxViewportDims[1]<768)&&t.warnings.push(`\u26A0\uFE0F Small MAX_VIEWPORT_DIMS: ${t.maxViewportDims[0]}\xD7${t.maxViewportDims[1]}`),s.getExtension("WEBGL_lose_context")||t.warnings.push("\u26A0\uFE0F WEBGL_lose_context not supported - may cause memory leaks"),t}initInstancedBuffers(){let t=this.gl;this.templateQuadPositions=new Float32Array([0,0,this.cellWidth,0,0,this.cellHeight,this.cellWidth,this.cellHeight]),this.templateQuadIndices=new Uint16Array([0,1,2,2,1,3]),t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferData(t.ARRAY_BUFFER,this.templateQuadPositions,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer),t.bufferData(t.ELEMENT_ARRAY_BUFFER,this.templateQuadIndices,t.STATIC_DRAW),this.instanceData=new Float32Array(this.maxCells*8),console.warn(`[TerminalGL] \u{1F680} initInstancedBuffers: maxCells=${this.maxCells}, instanceData.length=${this.instanceData.length}`),t.bindBuffer(t.ARRAY_BUFFER,this.instanceDataBuffer),t.bufferData(t.ARRAY_BUFFER,this.instanceData.byteLength,t.DYNAMIC_DRAW)}initRenderBuffers(){let t=this.cols*this.rows*2;this.maxCells=Math.ceil(t*2),this.renderPositions=new Float32Array(this.maxCells*4*2),this.renderTexCoords=new Float32Array(this.maxCells*4*2),this.renderColorIndices=new Float32Array(this.maxCells*4),this.useUint16Indices?this.renderIndices=new Uint16Array(this.maxCells*6):this.renderIndices=new Uint32Array(this.maxCells*6),this.staticPositionsInitialized=!1}precomputeStaticPositions(){let t=this.cellWidth,e=this.cellHeight,i=this.glyphOffsetX,s=this.glyphOffsetY,a=this.charWidth,r=this.charHeight,o=0,n=0,h=0;for(let d=0;d<this.rows;d++){let f=Math.round(d*e),m=Math.round(f+e);for(let g=0;g<this.cols;g++){let u=Math.round(g*t),p=Math.round(u+t);this.renderPositions[o++]=u,this.renderPositions[o++]=f,this.renderPositions[o++]=p,this.renderPositions[o++]=f,this.renderPositions[o++]=u,this.renderPositions[o++]=m,this.renderPositions[o++]=p,this.renderPositions[o++]=m,this.renderIndices[n++]=h,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+3,h+=4;let C=Math.round(u+i),x=Math.round(f+s),y=Math.round(C+a),E=Math.round(x+r);this.renderPositions[o++]=C,this.renderPositions[o++]=x,this.renderPositions[o++]=y,this.renderPositions[o++]=x,this.renderPositions[o++]=C,this.renderPositions[o++]=E,this.renderPositions[o++]=y,this.renderPositions[o++]=E,this.renderIndices[n++]=h,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+2,this.renderIndices[n++]=h+1,this.renderIndices[n++]=h+3,h+=4}}let c=this.gl;c.bindBuffer(c.ARRAY_BUFFER,this.positionBuffer),c.bufferSubData(c.ARRAY_BUFFER,0,this.renderPositions),c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,this.indexBuffer),c.bufferSubData(c.ELEMENT_ARRAY_BUFFER,0,this.renderIndices),this.staticPositionsInitialized=!0}initWebGL(){let t=this.gl,e;this.useInstancing?e=`
|
|
36
39
|
// Per-vertex attributes (template quad)
|
|
37
40
|
attribute vec2 aPosition; // Local quad position (0,0 to cellW,cellH)
|
|
@@ -138,6 +141,7 @@ var it=Object.defineProperty;var at=(b,t,e)=>t in b?it(b,t,{enumerable:!0,config
|
|
|
138
141
|
justify-content: center !important;
|
|
139
142
|
align-items: center !important;
|
|
140
143
|
isolation: isolate !important;
|
|
144
|
+
pointer-events: none !important;
|
|
141
145
|
`,this.canvas=document.createElement("canvas"),this.canvas.className="terminal2d-canvas",e.className&&(this.canvas.className+=" "+e.className),e.style&&Object.assign(this.canvas.style,e.style),this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges",this.containerDiv.appendChild(this.canvas),this.parentElement.appendChild(this.containerDiv);let s=this.canvas.getContext("2d",{alpha:!0,desynchronized:!1});if(!s)throw new Error("UTSPRender: Impossible d'obtenir le contexte 2D du canvas");this.ctx=s,this.ctx.imageSmoothingEnabled=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid(),this.showDebugGrid&&(this.gridOverlay=new A(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10})),this.enableAutoResize(),this.render()}calculateGridSize(){let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;if(!this.customCellSize){let h,c;if(this.fontType==="image"&&this.imageAtlas){let d=this.imageAtlas.getCellDimensions();h=d.width,c=d.height}else this.fontType==="bitmap"?(h=this.bitmapCharWidth,c=this.bitmapCharHeight):(h=Math.round(this.cellWidth)||10,c=Math.round(this.cellHeight)||14);this.cellWidth=Math.round(h),this.cellHeight=Math.round(c)}this.scalingMode===T.Responsive?(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1):this.fixedGridMode&&this.fixedCols&&this.fixedRows?(this.cols=this.fixedCols,this.rows=this.fixedRows):(this.cols=Math.floor(t/this.cellWidth)||1,this.rows=Math.floor(e/this.cellHeight)||1);let i=this.cols*this.cellWidth,s=this.rows*this.cellHeight,a=t/i,r=e/s,o=Math.min(a,r),n;switch(this.scalingMode){case T.Integer:n=Math.max(1,Math.floor(o));break;case T.Half:n=Math.max(.5,Math.floor(o*2)/2);break;case T.Quarter:n=Math.max(.25,Math.floor(o*4)/4);break;case T.Eighth:n=Math.max(.125,Math.floor(o*8)/8);break;case T.Responsive:n=1;break;case T.None:default:n=Math.max(.1,o);break}this.currentScale=n,this.canvas.width=i,this.canvas.height=s,this.ctx.imageSmoothingEnabled=!1,this.canvas.style.cssText=`
|
|
142
146
|
flex-shrink: 0 !important;
|
|
143
147
|
flex-grow: 0 !important;
|
|
@@ -150,6 +154,8 @@ var it=Object.defineProperty;var at=(b,t,e)=>t in b?it(b,t,{enumerable:!0,config
|
|
|
150
154
|
transform: scale(${n}) !important;
|
|
151
155
|
will-change: transform !important;
|
|
152
156
|
backface-visibility: hidden !important;
|
|
157
|
+
pointer-events: auto !important;
|
|
158
|
+
touch-action: none !important;
|
|
153
159
|
`,this.fontType==="web"&&(this.fontSize=Math.round(this.cellHeight/14*12)),this.offsetX=0,this.offsetY=0}createEmptyGrid(){let t=[];for(let e=0;e<this.rows;e++){let i=[];for(let s=0;s<this.cols;s++)i.push({char:" ",fgColor:this.defaultFgColor,bgColor:this.defaultBgColor});t.push(i)}return t}enableAutoResize(){this.resizeObserver=new ResizeObserver(()=>{let t=this.cols,e=this.rows;if(this.calculateGridSize(),this.cols!==t||this.rows!==e){let i=this.cells;this.cells=this.createEmptyGrid();let s=Math.min(t,this.cols),a=Math.min(e,this.rows);for(let r=0;r<a;r++)for(let o=0;o<s;o++)this.cells[r][o]=i[r][o]}this.render()}),this.resizeObserver.observe(this.parentElement)}setCell(t,e,i,s,a){if(e<0||e>=this.rows||t<0||t>=this.cols)return;let r=i&&typeof i=="string"?i.charAt(0):" ";this.cells[e][t]={char:r,fgColor:s??this.defaultFgColor,bgColor:a??this.defaultBgColor}}getCell(t,e){return e<0||e>=this.rows||t<0||t>=this.cols?null:this.cells[e][t]}write(t,e,i,s,a){for(let r=0;r<i.length;r++)this.setCell(t+r,e,i[r],s,a)}fillRect(t,e,i,s,a=" ",r,o){for(let n=e;n<e+s;n++)for(let h=t;h<t+i;h++)this.setCell(h,n,a,r,o)}clear(){this.cells=this.createEmptyGrid()}setFromArray(t){let e=t.width*t.height;if(t.cells.length!==e)throw new Error(`Invalid array length: expected ${e} (${t.width}\xD7${t.height}), got ${t.cells.length}`);let i=0;for(let s=0;s<t.height;s++)for(let a=0;a<t.width;a++){let r=t.cells[i];s<this.rows&&a<this.cols&&this.setCell(a,s,r.char,r.fgColor,r.bgColor),i++}}render(){if(this.fontType==="bitmap"&&this.bitmapFont&&this.useImageDataRendering){this.renderWithImageData();return}this.renderClassic()}renderWithImageData(){if(!this.bitmapFont)return;let t=this.cols*this.bitmapCharWidth,e=this.rows*this.bitmapCharHeight;(!this.imageDataBuffer||this.imageDataBuffer.width!==t||this.imageDataBuffer.height!==e)&&(this.imageDataBuffer=this.ctx.createImageData(t,e));let i=this.imageDataBuffer.data;for(let n=0;n<this.rows;n++)for(let h=0;h<this.cols;h++){let c=this.cells[n][h],d=this.parseColorToRGB(c.bgColor),f=this.parseColorToRGB(c.fgColor),m=c.char.charCodeAt(0),g=this.bitmapFont.get(m);for(let u=0;u<this.bitmapCharHeight;u++)for(let p=0;p<this.bitmapCharWidth;p++){let C=h*this.bitmapCharWidth+p,y=((n*this.bitmapCharHeight+u)*t+C)*4,E=!1;if(g&&u<g.length){let L=g[u],w=1<<7-p;E=(L&w)!==0}E?(i[y]=f.r,i[y+1]=f.g,i[y+2]=f.b,i[y+3]=f.a):(i[y]=d.r,i[y+1]=d.g,i[y+2]=d.b,i[y+3]=d.a)}}this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges";let s=document.createElement("canvas");s.width=t,s.height=e,s.getContext("2d").putImageData(this.imageDataBuffer,0,0);let r=this.cols*this.cellWidth,o=this.rows*this.cellHeight;this.ctx.drawImage(s,0,0,t,e,this.offsetX,this.offsetY,r,o),this.showDebugGrid&&this.drawDebugGrid()}parseColorToRGB(t){let e=/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/.exec(t);if(e)return{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10),a:e[4]?Math.round(parseFloat(e[4])*255):255};if(t.startsWith("#")){let a=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;t=t.replace(a,(o,n,h,c)=>n+n+h+h+c+c);let r=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);if(r)return{r:parseInt(r[1],16),g:parseInt(r[2],16),b:parseInt(r[3],16),a:255}}let s={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],yellow:[255,255,0],cyan:[0,255,255],magenta:[255,0,255],transparent:[0,0,0]}[t.toLowerCase()];return s?{r:s[0],g:s[1],b:s[2],a:t==="transparent"?0:255}:{r:255,g:255,b:255,a:255}}renderClassic(){this.canvasBgColor!==null?(this.ctx.fillStyle=this.canvasBgColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.fontType==="bitmap"||this.fontType==="image"?(this.ctx.imageSmoothingEnabled=!1,this.canvas.style.imageRendering="pixelated",this.canvas.style.imageRendering="crisp-edges"):(this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality="high",this.canvas.style.imageRendering="auto",this.ctx.font=`${this.fontSize}px ${this.fontFamily}`,this.ctx.textBaseline="top",this.ctx.textRendering="optimizeLegibility");for(let t=0;t<this.rows;t++)for(let e=0;e<this.cols;e++){let i=this.cells[t][e],s=Math.floor(this.offsetX+e*this.cellWidth),a=Math.floor(this.offsetY+t*this.cellHeight),r=Math.floor(this.offsetX+(e+1)*this.cellWidth),o=Math.floor(this.offsetY+(t+1)*this.cellHeight),n=r-s,h=o-a;if((this.canvasBgColor!==null||i.bgColor!==this.defaultBgColor)&&(this.ctx.fillStyle=i.bgColor,this.ctx.fillRect(s,a,n,h)),i.char!==" ")if(this.fontType==="image"&&this.imageAtlas){let d=i.char.charCodeAt(0);this.imageAtlas.drawChar(this.ctx,d,s,a,n,h,i.fgColor)}else if(this.fontType==="bitmap"&&this.bitmapFont)this.drawBitmapChar(i.char,s,a,n,h,i.fgColor);else{this.ctx.fillStyle=i.fgColor;let d=s+(n-this.ctx.measureText(i.char).width)/2,f=a+(h-this.fontSize)/2;this.ctx.fillText(i.char,d,f)}}this.showDebugGrid&&this.drawDebugGrid()}drawBitmapChar(t,e,i,s,a,r){let o=t.charCodeAt(0);if(this.bitmapAtlas){this.bitmapAtlas.drawChar(this.ctx,o,e,i,s,a,r);return}if(!this.bitmapFont)return;let n=this.bitmapFont.get(o);if(!n)return;let h=s/this.bitmapCharWidth,c=a/this.bitmapCharHeight;this.ctx.fillStyle=r;for(let d=0;d<Math.min(n.length,this.bitmapCharHeight);d++){let f=n[d],m=i+d*c,g=i+(d+1)*c;for(let u=0;u<this.bitmapCharWidth;u++){let p=1<<7-u;if(f&p){let C=e+u*h,x=e+(u+1)*h;this.ctx.fillRect(C,m,x-C,g-m)}}}}drawDebugGrid(){if(!this.gridOverlay)return;let t=this.parentElement.clientWidth||800,e=this.parentElement.clientHeight||600;this.gridOverlay.update(this.cols,this.rows,this.cellWidth,this.cellHeight,t,e,this.offsetX,this.offsetY)}getCanvas(){return this.canvas}getContext(){return this.ctx}getDimensions(){return{cols:this.cols,rows:this.rows}}getCellDimensions(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getCellWidth(){return this.cellWidth}getCellHeight(){return this.cellHeight}getCurrentScale(){return this.currentScale}getScalingMode(){return this.scalingMode}getOffsets(){return{offsetX:this.offsetX,offsetY:this.offsetY}}setDebugGrid(t){this.showDebugGrid=t,t&&!this.gridOverlay?(this.gridOverlay=new A(this.parentElement,{strokeColor:this.debugGridColor,lineWidth:1,zIndex:10}),this.drawDebugGrid()):!t&&this.gridOverlay?(this.gridOverlay.destroy(),this.gridOverlay=void 0):t&&this.gridOverlay&&this.gridOverlay.setVisible(!0)}setCanvasBackgroundColor(t){this.canvasBgColor=t}getCanvasBackgroundColor(){return this.canvasBgColor}setFixedGrid(t,e,i){this.fixedGridMode=!0,this.fixedCols=t,this.fixedRows=e,i!==void 0&&(this.cellAspectRatio=i);let s=this.cols,a=this.rows,r=this.cells;if(this.calculateGridSize(),this.cols!==s||this.rows!==a){this.cells=this.createEmptyGrid();let o=Math.min(s,this.cols),n=Math.min(a,this.rows);for(let h=0;h<n;h++)for(let c=0;c<o;c++)this.cells[h][c]=r[h][c]}this.render()}setAdaptiveGrid(t,e){this.fixedGridMode=!1,this.fixedCols=void 0,this.fixedRows=void 0,t!==void 0&&(this.cellWidth=t),e!==void 0&&(this.cellHeight=e);let i=this.cols,s=this.rows,a=this.cells;if(this.calculateGridSize(),this.cols!==i||this.rows!==s){this.cells=this.createEmptyGrid();let r=Math.min(i,this.cols),o=Math.min(s,this.rows);for(let n=0;n<o;n++)for(let h=0;h<r;h++)this.cells[n][h]=a[n][h]}this.render()}isFixedGridMode(){return this.fixedGridMode}setDebugGridColor(t){this.debugGridColor=t}isDebugGridEnabled(){return this.showDebugGrid}setImageDataRendering(t){this.useImageDataRendering=t,t&&this.fontType==="bitmap"?console.warn("[Render] ImageData rendering enabled (optimized for benchmarks)"):t&&(console.warn("[Render] ImageData rendering requires bitmap font, keeping classic mode"),this.useImageDataRendering=!1)}isImageDataRenderingEnabled(){return this.useImageDataRendering}setWebFont(t,e){this.fontType="web",this.fontFamily=t,e!==void 0&&(this.fontSize=e),this.bitmapFont=void 0,this.bitmapAtlas=void 0,this.useImageDataRendering=!1,this.calculateGridSize(),this.cells=this.createEmptyGrid()}setBitmapFont(t,e,i,s,a){this.fontType="bitmap",this.bitmapFont=t,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.bitmapAtlas=new F(t,e,i,s,a),this.cellWidth=s,this.cellHeight=a,this.calculateGridSize(),this.cells=this.createEmptyGrid()}async setImageFont(t,e,i,s,a,r){this.fontType="image",this.imageAtlas=new U({glyphWidth:e,glyphHeight:i,cellWidth:s,cellHeight:a,atlasBlocks:r}),await this.imageAtlas.loadFromPNG(t),this.cellWidth=s,this.cellHeight=a,this.bitmapCharWidth=e,this.bitmapCharHeight=i,this.calculateGridSize(),this.cells=this.createEmptyGrid()}getFontType(){return this.fontType}getBitmapFont(){return this.bitmapFont}getBitmapCharDimensions(){return this.fontType!=="bitmap"?null:{width:this.bitmapCharWidth,height:this.bitmapCharHeight}}setPalette(t){this.paletteCache=t}renderDisplayData(t){if(!t||!t.cells||t.cells.length===0){console.warn("[Terminal2D] Empty display data");return}if(t.width===0||t.height===0){console.warn("[Terminal2D] Invalid display dimensions:",t.width,t.height);return}(t.width!==this.cols||t.height!==this.rows)&&this.setFixedGrid(t.width,t.height,this.cellAspectRatio);let e=this.paletteCache??t.palette;if(!e||e.length===0){console.error("[Terminal2D] No palette available (neither cached nor in display)");return}let i=v(s=>{if(s==null||isNaN(s))return console.warn("[Terminal2D] Invalid palette index (undefined/null/NaN):",s),this.defaultFgColor;if(s===255)return"rgba(0, 0, 0, 0)";if(s<0||s>=e.length)return console.warn(`[Terminal2D] Invalid palette index: ${s}`),this.defaultFgColor;let a=e[s];return!a||typeof a.r!="number"?(console.warn(`[Terminal2D] Corrupted palette entry at index ${s}:`,a),this.defaultFgColor):`rgba(${a.r}, ${a.g}, ${a.b}, ${a.a/255})`},"convertColor");for(let s=0;s<t.height&&s<this.rows;s++)for(let a=0;a<t.width&&a<this.cols;a++){let r=s*t.width+a;if(r>=t.cells.length)break;let o=t.cells[r];if(!o)continue;let n=i(o.fgColorIndex),h=i(o.bgColorIndex);this.setCell(a,s,o.char??" ",n,h)}this.render()}isReady(){return!0}getCols(){return this.cols}getRows(){return this.rows}resize(t,e){this.setFixedGrid(t,e)}setScalingMode(t){if(this.scalingMode===t)return;let e=this.cols,i=this.rows;if(this.scalingMode=t,this.calculateGridSize(),this.cols!==e||this.rows!==i){let s=this.cells;if(this.cells=this.createEmptyGrid(),s&&s.length>0){let a=Math.min(e,this.cols),r=Math.min(i,this.rows);for(let o=0;o<r;o++)for(let n=0;n<a;n++)s[o]&&s[o][n]&&(this.cells[o][n]=s[o][n])}}this.render()}setCellSize(t,e){let i=Math.max(1,Math.min(255,Math.round(t))),s=Math.max(1,Math.min(255,Math.round(e)));if(this.cellWidth===i&&this.cellHeight===s)return;let a=this.cols,r=this.rows;if(this.cellWidth=i,this.cellHeight=s,this.customCellSize=!0,this.calculateGridSize(),this.cols!==a||this.rows!==r){let o=this.cells;if(this.cells=this.createEmptyGrid(),o&&o.length>0){let n=Math.min(a,this.cols),h=Math.min(r,this.rows);for(let c=0;c<h;c++)for(let d=0;d<n;d++)o[c]&&o[c][d]&&(this.cells[c][d]=o[c][d])}}this.render()}getCellSize(){return{cellWidth:this.cellWidth,cellHeight:this.cellHeight}}getAvailableSize(){return{width:this.parentElement.clientWidth,height:this.parentElement.clientHeight}}getMaxCells(){return 65536}destroy(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=void 0),this.gridOverlay&&(this.gridOverlay.destroy(),this.gridOverlay=void 0),this.containerDiv.parentElement&&this.containerDiv.parentElement.removeChild(this.containerDiv)}};v($,"Terminal2D");var k=$;var Y=class Y{constructor(t,e={}){l(this,"container");l(this,"overlayDiv",null);l(this,"button",null);l(this,"options");l(this,"started",!1);l(this,"onStartCallback");this.container=t,this.options={buttonText:e.buttonText??"Click to Start",onStart:e.onStart??(()=>{}),backgroundColor:e.backgroundColor??"rgba(0, 0, 0, 0.8)",buttonColor:e.buttonColor??"#4a90d9",buttonHoverColor:e.buttonHoverColor??"#357abd",buttonTextColor:e.buttonTextColor??"#ffffff",zIndex:e.zIndex??1e3},this.onStartCallback=e.onStart,this.createOverlay()}createOverlay(){let t=window.getComputedStyle(this.container).position;t!=="relative"&&t!=="absolute"&&t!=="fixed"&&(this.container.style.position="relative"),this.overlayDiv=document.createElement("div"),this.overlayDiv.className="utsp-autoplay-overlay",this.overlayDiv.style.cssText=`
|
|
154
160
|
position: absolute !important;
|
|
155
161
|
top: 0 !important;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@utsp/render",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "UTSP Render - Rendering engine for terminal graphics with WebGL, Canvas 2D, and ANSI terminal support",
|
|
5
5
|
"author": "THP Software",
|
|
6
6
|
"license": "MIT",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"access": "public"
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"@utsp/types": "0.14.
|
|
89
|
+
"@utsp/types": "0.14.1"
|
|
90
90
|
},
|
|
91
91
|
"devDependencies": {
|
|
92
92
|
"typescript": "^5.6.3"
|