@utsp/render 0.16.1 → 0.17.0-nightly.20260120215017.712755a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -66,473 +66,457 @@ declare function getCharGridPosition(charCode: number, blocks: AtlasBlocks): {
66
66
  };
67
67
 
68
68
  /**
69
- * Représente une cellule du terminal
70
- */
71
- interface TerminalCell {
72
- /** Le caractère à afficher */
73
- char: string;
74
- /** Couleur du caractère (format CSS) */
75
- fgColor: string;
76
- /** Couleur de fond de la cellule (format CSS) */
77
- bgColor: string;
78
- }
79
- /**
80
- * Données brutes pour définir le terminal en une fois
69
+ * WebGL compatibility report
81
70
  */
82
- interface TerminalData {
83
- /** Largeur en cellules */
84
- width: number;
85
- /** Hauteur en cellules */
86
- height: number;
87
- /** Tableau de cellules (longueur = width * height) */
88
- cells: Array<{
89
- /** Code du caractère ou le caractère lui-même */
90
- char: string;
91
- /** Couleur du texte (format CSS) */
92
- fgColor: string;
93
- /** Couleur de fond (format CSS) */
94
- bgColor: string;
95
- }>;
71
+ interface WebGLCompatibilityReport {
72
+ /** WebGL 1.0 support */
73
+ webgl1: boolean;
74
+ /** OES_element_index_uint extension (Uint32 indices) */
75
+ uint32Indices: boolean;
76
+ /** Maximum texture size */
77
+ maxTextureSize: number;
78
+ /** Maximum viewport dimensions */
79
+ maxViewportDims: [number, number];
80
+ /** Maximum terminal size with Uint16 indices (cols × rows) */
81
+ maxCellsUint16: number;
82
+ /** Maximum terminal size with Uint32 indices (cols × rows) */
83
+ maxCellsUint32: number;
84
+ /** Recommended maximum terminal size for this device */
85
+ recommendedMaxCells: number;
86
+ /** Warnings (empty if fully compatible) */
87
+ warnings: string[];
88
+ /** Errors (empty if compatible) */
89
+ errors: string[];
96
90
  }
97
91
  /**
98
- * Police bitmap matricielle
99
- * Map qui associe un code de caractère (charCode) à une représentation bitmap 8x8
100
- * Chaque Uint8Array contient 8 octets, un par ligne de pixels
101
- */
102
- type BitmapFont$1 = Map<number, Uint8Array>;
103
- /**
104
- * Type de police à utiliser
105
- */
106
- type FontType = {
107
- type: 'web';
108
- fontFamily: string;
109
- fontSize: number;
110
- } | {
111
- type: 'bitmap';
112
- font: BitmapFont$1;
113
- charWidth: number;
114
- charHeight: number;
115
- };
116
- /**
117
- * Options pour la configuration du terminal
92
+ * Options for WebGL terminal configuration
118
93
  */
119
- interface RenderOptions {
120
- /** Largeur d'une cellule en pixels (défaut: 8) - ignoré en mode fixedGrid */
121
- cellWidth?: number;
122
- /** Hauteur d'une cellule en pixels (défaut: 8) - ignoré en mode fixedGrid */
123
- cellHeight?: number;
124
- /** Taille de la police en pixels (défaut: 12) */
125
- fontSize?: number;
126
- /** Famille de police (défaut: "monospace") */
127
- fontFamily?: string;
128
- /** Couleur de texte par défaut (défaut: "#ffffff") */
129
- defaultFgColor?: string;
130
- /** Couleur de fond par défaut (défaut: "#000000") */
131
- defaultBgColor?: string;
132
- /** Couleur de fond du canvas lui-même (défaut: transparent). Si null ou undefined, le canvas sera transparent */
94
+ interface TerminalGLOptions {
95
+ /** Number of columns (required) */
96
+ cols: number;
97
+ /** Number of rows (required) */
98
+ rows: number;
99
+ /** Character width in pixels */
100
+ charWidth?: number;
101
+ /** Character height in pixels */
102
+ charHeight?: number;
103
+ /** Canvas background color (CSS format, for gl.clearColor) */
133
104
  canvasBgColor?: string | null;
134
- /** Afficher une grille de débogage (défaut: false) */
135
- showDebugGrid?: boolean;
136
- /** Couleur de la grille de débogage (défaut: "rgba(255, 0, 0, 0.3)") */
137
- debugGridColor?: string;
138
- /** Classes CSS additionnelles pour le canvas */
139
- className?: string;
140
- /** Style inline pour le canvas */
141
- style?: Partial<CSSStyleDeclaration>;
142
- /** Nombre de colonnes fixe (active le mode fixedGrid) */
143
- fixedCols?: number;
144
- /** Nombre de lignes fixe (active le mode fixedGrid) */
145
- fixedRows?: number;
146
- /** Ratio largeur/hauteur de cellule pour mode fixedGrid (défaut: 1 = carré) */
147
- cellAspectRatio?: number;
105
+ /** Show cell delimitation grid (debug) */
106
+ showGrid?: boolean;
107
+ /** Force Uint16 indices (for compatibility testing, auto-detected by default) */
108
+ forceUint16?: boolean;
148
109
  /**
149
110
  * Scaling mode for pixel-perfect rendering (default: ScalingMode.None)
150
111
  *
151
112
  * Controls how the canvas is scaled to fit the container:
152
- * - ScalingMode.None: Scales cells to fill space, may have sub-pixel artifacts
113
+ * - ScalingMode.None: Fills available space, may have sub-pixel artifacts (default)
153
114
  * - ScalingMode.Eighth: Snaps to 0.125 increments (1.0, 1.125, 1.25...)
154
115
  * - ScalingMode.Quarter: Snaps to 0.25 increments (1.0, 1.25, 1.5...)
155
116
  * - ScalingMode.Half: Snaps to 0.5 increments (1.0, 1.5, 2.0...)
156
117
  * - ScalingMode.Integer: Integer scaling only (1x, 2x, 3x...), crispest pixels
157
- *
158
- * Note: For ImageFont mode, this uses native glyph sizes + CSS transform scaling.
159
118
  */
160
119
  scalingMode?: ScalingMode;
120
+ /**
121
+ * Ambient effect configuration
122
+ *
123
+ * Creates a blurred glow effect around the terminal when using pixel-perfect
124
+ * scaling modes that leave empty space around the canvas.
125
+ *
126
+ * - false or undefined: Disabled (default)
127
+ * - true: Enabled with default settings (blur: 30px, scale: 1.15, opacity: 0.7)
128
+ * - object: Custom configuration
129
+ */
130
+ ambientEffect?: boolean | {
131
+ /** Blur radius in pixels (default: 30) */
132
+ blur?: number;
133
+ /** Scale factor for the background canvas (default: 1.15) */
134
+ scale?: number;
135
+ /** Opacity of the ambient effect (0-1, default: 0.7) */
136
+ opacity?: number;
137
+ };
161
138
  }
162
139
  /**
163
- * UTSP Render - Gère une grille de caractères avec couleurs
164
- * Similaire à un terminal mais avec contrôle total de chaque cellule
140
+ * Simplified terminal using WebGL for basic rendering
141
+ * Only supports bitmap fonts with atlas
142
+ * Implements IRenderer interface for dependency injection with core
165
143
  *
166
- * Implements IRenderer interface for compatibility with TerminalGL and dependency injection.
144
+ * SIMPLIFIED VERSION: Only backgrounds + colored characters
167
145
  */
168
- declare class Terminal2D implements IRenderer {
169
- private containerDiv;
146
+ declare class TerminalGL implements IRenderer {
147
+ /**
148
+ * Check WebGL 1.0 compatibility and device capabilities
149
+ *
150
+ * Tests all required WebGL features and returns a detailed compatibility report.
151
+ * Use this before creating a TerminalGL instance to ensure device support.
152
+ *
153
+ * @returns Detailed compatibility report with warnings and errors
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const report = TerminalGL.checkCompatibility();
158
+ * if (report.errors.length > 0) {
159
+ * console.error('WebGL not supported:', report.errors);
160
+ * // Fallback to Canvas 2D renderer
161
+ * } else if (report.warnings.length > 0) {
162
+ * console.warn('WebGL limitations:', report.warnings);
163
+ * }
164
+ * console.log(`Max terminal size: ${report.recommendedMaxCells} cells`);
165
+ * ```
166
+ */
167
+ static checkCompatibility(): WebGLCompatibilityReport;
170
168
  private canvas;
171
- private ctx;
169
+ private gl;
172
170
  private parentElement;
173
- private cells;
171
+ private containerDiv;
174
172
  private cols;
175
173
  private rows;
176
- private fontSize;
177
- private fontFamily;
178
- private defaultFgColor;
179
- private defaultBgColor;
180
- private canvasBgColor;
174
+ private charWidth;
175
+ private charHeight;
181
176
  private cellWidth;
182
177
  private cellHeight;
183
- private offsetX;
184
- private offsetY;
185
- private fontType;
186
- private bitmapFont?;
187
- private bitmapAtlas?;
188
- private imageAtlas?;
189
- private bitmapCharWidth;
190
- private bitmapCharHeight;
191
- private showDebugGrid;
192
- private debugGridColor;
178
+ private glyphOffsetX;
179
+ private glyphOffsetY;
180
+ private canvasBgColor;
181
+ private showGrid;
182
+ private supportsUint32Indices;
183
+ private useUint16Indices;
193
184
  private gridOverlay?;
194
- private fixedGridMode;
195
- private fixedCols?;
196
- private fixedRows?;
197
- private cellAspectRatio;
185
+ private bitmapFont?;
186
+ private atlasTexture;
187
+ private atlasCanvas?;
188
+ private atlasColumns;
189
+ private fontLoaded;
190
+ private paletteTexture;
191
+ private program;
192
+ private positionBuffer;
193
+ private texCoordBuffer;
194
+ private colorIndexBuffer;
195
+ private indexBuffer;
196
+ private aPosition?;
197
+ private aTexCoord?;
198
+ private aColorIndex?;
199
+ private uResolution;
200
+ private uTexture;
201
+ private uPalette;
198
202
  private resizeObserver?;
199
- private imageDataBuffer?;
200
- private useImageDataRendering;
201
- private paletteCache?;
202
- private scalingMode;
203
+ private charCodeToAtlasIndex;
204
+ private atlasUVs;
205
+ private cachedAtlasWidth;
206
+ private cachedAtlasHeight;
207
+ private paletteFloat;
208
+ private maxCells;
209
+ private renderPositions;
210
+ private renderTexCoords;
211
+ private renderColorIndices;
212
+ private renderIndices;
213
+ private cachedResolution;
214
+ private cachedTextureUnit;
215
+ private cachedPaletteUnit;
216
+ private cachedTextureUniform;
217
+ private cachedPaletteUniform;
218
+ private paletteHash;
203
219
  private currentScale;
204
- private customCellSize;
220
+ private scalingMode;
221
+ private ambientEffectEnabled;
222
+ private ambientEffectCanvas;
223
+ private ambientEffectCtx;
224
+ private ambientEffectBlur;
225
+ private ambientEffectScale;
226
+ private ambientEffectOpacity;
227
+ private onResizeCallback?;
228
+ private staticPositionsInitialized;
229
+ private vaoExtension;
230
+ private vao;
231
+ private instancedExtension;
232
+ private useInstancing;
233
+ private instanceDataBuffer;
234
+ private instanceData;
235
+ private templateQuadPositions;
236
+ private templateQuadIndices;
237
+ private aInstanceOffset;
238
+ private aInstanceUVs;
239
+ private aInstanceColors;
240
+ private uCellSize;
241
+ constructor(parentDiv: HTMLDivElement, options: TerminalGLOptions);
205
242
  /**
206
- * Crée une instance de UTSPRender
207
- * @param parentDiv - L'élément HTML parent dans lequel créer le canvas
208
- * @param options - Options de configuration du terminal
243
+ * 🚀 INSTANCING: Initialize template quad and instance buffers
244
+ * Called once at init if instancing is supported
209
245
  */
210
- constructor(parentDiv: HTMLElement, options?: RenderOptions);
246
+ private initInstancedBuffers;
211
247
  /**
212
- * Calcule le nombre de colonnes et de lignes en fonction de la taille du parent
213
- * et centre le terminal dans le canvas
214
- *
215
- * 🎯 PIXEL-PERFECT APPROACH (like TerminalGL):
216
- * 1. Cell dimensions are ALWAYS integers (native font size)
217
- * 2. Canvas renders at native resolution (cols * cellWidth)
218
- * 3. CSS transform: scale() handles visual upscaling
219
- * 4. Flexbox handles centering
248
+ * 🚀 OPTIMIZATION: Initialize pre-allocated buffers for rendering
249
+ * Avoids allocations each frame
250
+ * Uses Uint16 or Uint32 indices based on device support
220
251
  */
221
- private calculateGridSize;
252
+ private initRenderBuffers;
222
253
  /**
223
- * Crée une grille vide avec les valeurs par défaut
254
+ * 🚀 MEGA OPTIMIZATION: Pre-compute static positions for ALL possible quads
255
+ * Called only once after font load, or after resize
256
+ * Positions never change during rendering - only colors and UVs change!
224
257
  */
225
- private createEmptyGrid;
258
+ private precomputeStaticPositions;
226
259
  /**
227
- * Active le redimensionnement automatique
228
- * Recalcule le nombre de colonnes/lignes quand le parent change de taille
260
+ * Initialize WebGL (shaders, buffers, etc.)
229
261
  */
230
- private enableAutoResize;
231
- /**
232
- * Définit le contenu d'une cellule
233
- * @param col - Colonne (0-indexed)
234
- * @param row - Ligne (0-indexed)
235
- * @param char - Caractère à afficher
236
- * @param fgColor - Couleur du texte (optionnel, utilise la valeur par défaut si non fourni)
237
- * @param bgColor - Couleur de fond (optionnel, utilise la valeur par défaut si non fourni)
238
- */
239
- setCell(col: number, row: number, char: string, fgColor?: string, bgColor?: string): void;
240
- /**
241
- * Récupère le contenu d'une cellule
242
- * @param col - Colonne (0-indexed)
243
- * @param row - Ligne (0-indexed)
244
- */
245
- getCell(col: number, row: number): TerminalCell | null;
262
+ private initWebGL;
246
263
  /**
247
- * Écrit une chaîne de caractères à partir d'une position
248
- * @param col - Colonne de départ
249
- * @param row - Ligne
250
- * @param text - Texte à écrire
251
- * @param fgColor - Couleur du texte (optionnel)
252
- * @param bgColor - Couleur de fond (optionnel)
264
+ * Compile a shader
253
265
  */
254
- write(col: number, row: number, text: string, fgColor?: string, bgColor?: string): void;
266
+ private compileShader;
255
267
  /**
256
- * Remplit une zone rectangulaire
257
- * @param startCol - Colonne de départ
258
- * @param startRow - Ligne de départ
259
- * @param width - Largeur en cellules
260
- * @param height - Hauteur en cellules
261
- * @param char - Caractère de remplissage
262
- * @param fgColor - Couleur du texte (optionnel)
263
- * @param bgColor - Couleur de fond (optionnel)
268
+ * 🔲 Initialize 2D canvas overlay for debug grid
269
+ * Performance: 2D canvas drawn only once, 0ms per frame
264
270
  */
265
- fillRect(startCol: number, startRow: number, width: number, height: number, char?: string, fgColor?: string, bgColor?: string): void;
271
+ private initGridOverlay;
266
272
  /**
267
- * Efface tout le terminal (remplit avec des espaces)
273
+ * 🔲 Draw grid lines on 2D canvas overlay
274
+ * Called only once at init and resize
275
+ *
276
+ * The grid must match the terminal's pixel-perfect scaling:
277
+ * - Same base size as the main canvas
278
+ * - Same transform: scale() factor
279
+ * - Centered in the container like the main canvas (via flexbox or calculated position)
268
280
  */
269
- clear(): void;
281
+ private updateGridOverlay;
270
282
  /**
271
- * Définit tout le contenu du terminal à partir d'un tableau de données
272
- * Le tableau doit contenir width * height éléments
273
- * Les cellules sont lues ligne par ligne (row-major order)
283
+ * Configure bitmap font and generate atlas
274
284
  *
275
- * @param data - Données du terminal avec dimensions et cellules
276
- * @throws Error si le tableau n'a pas la bonne taille
285
+ * ⚠️ **INTERNAL USE ONLY** - This method is called automatically by ClientRuntime's
286
+ * event system when Core.loadBitmapFontById() is called. Do NOT call this directly
287
+ * unless you're implementing a custom runtime.
277
288
  *
278
- * @example
279
- * terminal.setFromArray({
280
- * width: 3,
281
- * height: 2,
282
- * cells: [
283
- * { char: 'A', fgColor: '#ff0000', bgColor: '#000000' }, // (0,0)
284
- * { char: 'B', fgColor: '#00ff00', bgColor: '#000000' }, // (1,0)
285
- * { char: 'C', fgColor: '#0000ff', bgColor: '#000000' }, // (2,0)
286
- * { char: 'D', fgColor: '#ffff00', bgColor: '#000000' }, // (0,1)
287
- * { char: 'E', fgColor: '#ff00ff', bgColor: '#000000' }, // (1,1)
288
- * { char: 'F', fgColor: '#00ffff', bgColor: '#000000' }, // (2,1)
289
- * ]
290
- * });
291
- */
292
- setFromArray(data: TerminalData): void;
293
- /**
294
- * Rend la grille sur le canvas
295
- * @param clearCanvas - Whether to clear the canvas before rendering (default: true)
296
- * Set to false for multi-pass rendering (stacking layers)
289
+ * Event flow: Core.loadBitmapFontById() → Core.onBitmapFontChangedCallback
290
+ * → ClientRuntime.onCoreBitmapFontChanged() → RendererManager.setBitmapFont()
291
+ *
292
+ * @param font - Bitmap font mapping (charCode → byte array)
293
+ * @param charWidth - Width of each character in pixels
294
+ * @param charHeight - Height of each character in pixels
297
295
  */
298
- render(clearCanvas?: boolean): void;
296
+ setBitmapFont(font: Map<number, Uint8Array>, charWidth: number, charHeight: number, cellWidth?: number, cellHeight?: number): void;
299
297
  /**
300
- * Rendu ultra-rapide avec ImageData (bitmap)
301
- * ~10-20× plus rapide que fillRect en boucle
302
- * Fonctionne avec scaling : buffer natif 8×8 puis drawImage() pour upscale
303
- * @param clearCanvas - Whether to clear the canvas before rendering
298
+ * Convertit la police Bitmap en texture Atlas
304
299
  */
305
- private renderWithImageData;
300
+ private generateAtlas;
306
301
  /**
307
- * Parse une couleur CSS en composantes RGBA
302
+ * Initialize ImageFont structure (allocate texture)
308
303
  */
309
- private parseColorToRGB;
304
+ setImageFontStructure(glyphWidth: number, glyphHeight: number, cellWidth: number, cellHeight: number, atlasBlocks: AtlasBlocks): Promise<void>;
310
305
  /**
311
- * Rendu classique avec fillRect/fillText (compatible scaling, web fonts, etc.)
312
- * @param clearCanvas - Whether to clear the canvas before rendering
306
+ * Upload an image block to the atlas
313
307
  */
314
- private renderClassic;
308
+ setImageFontBlock(blockIndex: number, data: Uint8Array): Promise<void>;
315
309
  /**
316
- * Dessine un caractère en utilisant une police bitmap
310
+ * Set image font (legacy/full)
317
311
  */
318
- private drawBitmapChar;
312
+ setImageFont(imageData: Uint8Array, glyphWidth: number, glyphHeight: number, cellWidth: number, cellHeight: number, atlasBlocks: AtlasBlocks): Promise<void>;
319
313
  /**
320
- * Dessine une grille de débogage pour visualiser les cellules
314
+ * Load PNG image and create WebGL texture
321
315
  */
322
- private drawDebugGrid;
316
+ private loadImageFontAtlas;
323
317
  /**
324
- * Obtient le canvas HTML
318
+ * Pre-compute UVs for ImageFont (block-based grid layout)
319
+ *
320
+ * Atlas layout for multi-block fonts:
321
+ * - Each block contains 256 chars in a 16×16 grid
322
+ * - Blocks are arranged visually:
323
+ * - 1 block: 1×1 (16×16 chars)
324
+ * - 4 blocks: 2×2 (32×32 chars total)
325
+ * - 16 blocks: 4×4 (64×64 chars total)
326
+ *
327
+ * CharCode mapping:
328
+ * charCode 0-255 → Block 0 (top-left)
329
+ * charCode 256-511 → Block 1 (top-right for 4 blocks)
330
+ * charCode 512-767 → Block 2 (bottom-left for 4 blocks)
331
+ * etc.
325
332
  */
326
- getCanvas(): HTMLCanvasElement;
333
+ private precomputeImageFontUVs;
327
334
  /**
328
- * Obtient le contexte 2D
335
+ * Create WebGL texture from atlas (Empty allocation)
329
336
  */
330
- getContext(): CanvasRenderingContext2D;
337
+ private allocateAtlasTexture;
331
338
  /**
332
- * Obtient les dimensions de la grille
339
+ * Create WebGL texture from atlas (Legacy canvas based)
333
340
  */
334
- getDimensions(): {
335
- cols: number;
336
- rows: number;
337
- };
341
+ private createAtlasTexture;
338
342
  /**
339
- * Obtient les dimensions des cellules
343
+ * Clear entire terminal
344
+ *
345
+ * Clears the WebGL canvas. Note: Actual terminal content clearing is handled
346
+ * by Core's RenderState, not by this renderer.
347
+ *
348
+ * @example
349
+ * ```typescript
350
+ * renderer.clear();
351
+ * ```
340
352
  */
341
- getCellDimensions(): {
342
- cellWidth: number;
343
- cellHeight: number;
344
- };
353
+ clear(): void;
345
354
  /**
346
- * Obtient la largeur d'une cellule
355
+ * Parse CSS color to normalized RGBA (0-1)
347
356
  */
348
- getCellWidth(): number;
357
+ private parseColor;
349
358
  /**
350
- * Obtient la hauteur d'une cellule
359
+ * Configure ResizeObserver to adapt canvas
351
360
  */
352
- getCellHeight(): number;
361
+ private setupResizeObserver;
353
362
  /**
354
- * Get current scaling factor (for pixel-perfect modes)
355
- * Returns 1 if scalingMode is None or not using ImageFont
363
+ * Update canvas display size
364
+ *
365
+ * Supports multiple scaling modes:
366
+ *
367
+ * 🎯 INTEGER MODE (ScalingMode.Integer):
368
+ * Uses integer scaling (1x, 2x, 3x...) for crisp pixels without artifacts.
369
+ * The canvas is centered in the container via flexbox.
370
+ * May leave empty space around the canvas.
371
+ *
372
+ * 📐 HALF MODE (ScalingMode.Half):
373
+ * Snaps to half increments (1.0, 1.5, 2.0...).
374
+ * Good balance between space usage and visual quality.
375
+ *
376
+ * 📏 QUARTER MODE (ScalingMode.Quarter):
377
+ * Snaps to quarter increments (1.0, 1.25, 1.5, 1.75, 2.0...).
378
+ * Finer control over scaling with minimal artifacts.
379
+ *
380
+ * 🔲 NONE MODE (ScalingMode.None):
381
+ * Scales to fill as much space as possible while maintaining aspect ratio.
382
+ * May cause some lines to appear thicker due to sub-pixel rendering.
383
+ * Useful when maximizing screen usage is more important than pixel purity.
356
384
  */
357
- getCurrentScale(): number;
385
+ private updateCanvasSize;
358
386
  /**
359
- * Get scaling mode
387
+ * 🌈 AMBIENT EFFECT: Copy main canvas to ambient effect background
388
+ *
389
+ * This creates a glow effect around the terminal by copying the main
390
+ * WebGL canvas to a 2D canvas behind it, which has CSS blur applied.
360
391
  */
361
- getScalingMode(): ScalingMode;
392
+ private updateAmbientEffect;
362
393
  /**
363
- * Obtient les décalages de centrage du terminal
394
+ * Set color palette and upload to GPU
395
+ *
396
+ * ⚠️ IMPORTANT: This is the ONLY way to update the palette.
397
+ * Typically called automatically by ClientRuntime via Core.onPaletteChanged() event.
398
+ * Do NOT call this directly unless you know what you're doing.
399
+ *
400
+ * @param palette - Array of 256 RGB colors
401
+ *
402
+ * @example
403
+ * ```typescript
404
+ * // ✅ Normal usage: Core handles this automatically
405
+ * core.loadPaletteToSlot(0, [...]);
406
+ * display.switchPalette(0);
407
+ * // → ClientRuntime applies slot palette
408
+ * // → renderer.setPalette() called automatically
409
+ *
410
+ * // ⚠️ Manual usage (advanced):
411
+ * const myPalette: RGBColor[] = [
412
+ * { r: 0, g: 0, b: 0, a: 255 }, // Color 0: Black
413
+ * { r: 255, g: 0, b: 0, a: 255 }, // Color 1: Red
414
+ * // ... 254 more colors
415
+ * ];
416
+ * renderer.setPalette(myPalette);
417
+ * ```
364
418
  */
365
- getOffsets(): {
366
- offsetX: number;
367
- offsetY: number;
368
- };
419
+ setPalette(palette: RGBColor[]): void;
369
420
  /**
370
- * Active ou désactive la grille de débogage
371
- * @param show - true pour afficher la grille, false pour la masquer
421
+ * 🚀 GPU OPTIMIZATION: Upload palette to GPU texture (256×1 RGBA)
372
422
  */
373
- setDebugGrid(show: boolean): void;
423
+ private updatePaletteTexture;
374
424
  /**
375
- * Change la couleur de fond du canvas
376
- * @param color - Couleur CSS (ex: "#000000", "rgba(0,0,0,0.5)") ou null pour transparent
425
+ * Render display data from core engine (ULTRA-OPTIMIZED)
426
+ *
427
+ * Bypasses internal cells and renders directly from RenderState for maximum performance.
428
+ * Uses GPU palette texture lookup to minimize CPU→GPU bandwidth (4× reduction).
429
+ *
430
+ * @param data - Render state containing cells, dimensions, and palette
431
+ *
432
+ * @example
433
+ * ```typescript
434
+ * const renderState: RenderState = {
435
+ * cells: [...],
436
+ * width: 80,
437
+ * height: 25,
438
+ * palette: [...]
439
+ * };
440
+ * renderer.renderDisplayData(renderState);
441
+ * ```
377
442
  */
378
- setCanvasBackgroundColor(color: string | null): void;
443
+ renderDisplayData(data: RenderState): void;
379
444
  /**
380
- * Obtient la couleur de fond actuelle du canvas
381
- * @returns La couleur de fond ou null si transparent
445
+ * Render multiple passes in order, clearing once then layering.
382
446
  */
383
- getCanvasBackgroundColor(): string | null;
447
+ private renderMultiPass;
384
448
  /**
385
- * Active le mode grille fixe avec le nombre de colonnes/lignes spécifié
386
- * Les cellules s'adapteront en taille pour maintenir les dimensions demandées
387
- * @param cols - Nombre de colonnes fixe
388
- * @param rows - Nombre de lignes fixe
389
- * @param aspectRatio - Ratio largeur/hauteur de cellule (optionnel, défaut: 10/14)
449
+ * 🚀 NEW METHOD: Render directly from RenderState
450
+ * Bypass this.cells for maximum performance
390
451
  */
391
- setFixedGrid(cols: number, rows: number, aspectRatio?: number): void;
452
+ private renderDirect;
392
453
  /**
393
- * Désactive le mode grille fixe et revient au mode adaptatif
394
- * @param cellWidth - Largeur de cellule en pixels (optionnel)
395
- * @param cellHeight - Hauteur de cellule en pixels (optionnel)
454
+ * 🚀 INSTANCED RENDERING: 1 draw call for entire terminal
455
+ * MASSIVE performance boost - reduces draw calls from cols×rows×2 to just 1!
396
456
  */
397
- setAdaptiveGrid(cellWidth?: number, cellHeight?: number): void;
457
+ private renderInstanced;
398
458
  /**
399
- * Vérifie si le terminal est en mode grille fixe
459
+ * 🚀 ULTRA-OPTIMIZED: Update ONLY dynamic data (colors + UVs)
460
+ * Positions are static and pre-computed - only updated on resize!
461
+ * This is a MASSIVE performance win - positions never change during normal rendering
400
462
  */
401
- isFixedGridMode(): boolean;
463
+ private renderDirectBuffers;
402
464
  /**
403
- * Définit la couleur de la grille de débogage
404
- * @param color - Couleur CSS (ex: "rgba(255, 0, 0, 0.3)" ou "#ff0000")
405
- */
406
- setDebugGridColor(color: string): void;
407
- /**
408
- * Vérifie si la grille de débogage est activée
409
- */
410
- isDebugGridEnabled(): boolean;
411
- /**
412
- * Active ou désactive le rendu optimisé avec ImageData
413
- * Uniquement disponible pour les polices bitmap à taille native (pas de scaling)
414
- * Environ 10-20× plus rapide que le rendu classique, idéal pour les benchmarks
465
+ * Resize the terminal dimensions
415
466
  *
416
- * @param enable - true pour activer, false pour désactiver
417
- */
418
- setImageDataRendering(enable: boolean): void;
419
- /**
420
- * Vérifie si le rendu ImageData est activé
421
- */
422
- isImageDataRenderingEnabled(): boolean;
423
- /**
424
- * Configure une police web (CSS)
425
- * @param fontFamily - Nom de la police CSS (ex: "Courier New", "monospace")
426
- * @param fontSize - Taille de la police en pixels (optionnel, garde la taille actuelle si non spécifié)
427
- */
428
- setWebFont(fontFamily: string, fontSize?: number): void;
429
- /**
430
- * Configure une police bitmap matricielle
431
- * @param font - Map contenant les définitions bitmap des caractères (charCode -> Uint8Array)
432
- * @param charWidth - Largeur du glyphe en pixels (bitmap source)
433
- * @param charHeight - Hauteur du glyphe en pixels (bitmap source)
434
- * @param cellWidth - Largeur de la cellule de rendu en pixels
435
- * @param cellHeight - Hauteur de la cellule de rendu en pixels
436
- */
437
- setBitmapFont(font: BitmapFont$1, charWidth: number, charHeight: number, cellWidth: number, cellHeight: number): void;
438
- /**
439
- * Configure une police image (atlas PNG)
440
- * @param imageData - Données PNG brutes
441
- * @param glyphWidth - Largeur du glyphe en pixels
442
- * @param glyphHeight - Hauteur du glyphe en pixels
443
- * @param cellWidth - Largeur de la cellule en pixels
444
- * @param cellHeight - Hauteur de la cellule en pixels
445
- * @param atlasBlocks - Nombre de blocs de 256 caractères (1, 4, ou 16)
446
- */
447
- setImageFont(imageData: Uint8Array, glyphWidth: number, glyphHeight: number, cellWidth: number, cellHeight: number, atlasBlocks: AtlasBlocks): Promise<void>;
448
- /**
449
- * Retourne le type de police actuellement utilisé
450
- */
451
- getFontType(): 'web' | 'bitmap' | 'image';
452
- /**
453
- * Retourne la police bitmap actuelle (si applicable)
454
- */
455
- getBitmapFont(): BitmapFont$1 | undefined;
456
- /**
457
- * Retourne les dimensions de caractère bitmap (si applicable)
458
- */
459
- getBitmapCharDimensions(): {
460
- width: number;
461
- height: number;
462
- } | null;
463
- /**
464
- * Set color palette (IRenderer contract).
465
- * Called by ClientRuntime when Core palette changes.
467
+ * Changes the number of columns and rows. Preserves existing cell content
468
+ * where possible. Reallocates render buffers if needed.
466
469
  *
467
- * @param palette - Array of 256 RGBA colors
468
- */
469
- setPalette(palette: RGBColor[]): void;
470
- /**
471
- * Render display data (IRenderer contract).
472
- * Converts RenderState from Core to cell-based rendering.
470
+ * @param cols - New number of columns (must be positive integer)
471
+ * @param rows - New number of rows (must be positive integer)
473
472
  *
474
- * @param display - Display data with palette indices
475
- */
476
- /**
477
- * Helper: Convert palette index to CSS color
473
+ * @example
474
+ * ```typescript
475
+ * renderer.resize(120, 40); // Resize to 120×40
476
+ * ```
478
477
  */
479
- private convertColor;
478
+ resize(cols: number, rows: number): void;
480
479
  /**
481
- * Helper: Render a specific set of cells (one pass or full display)
480
+ * Get canvas element
482
481
  */
483
- private renderDirect;
484
- renderDisplayData(display: RenderState): void;
482
+ getCanvas(): HTMLCanvasElement;
485
483
  /**
486
- * Check if renderer is ready to render (IRenderer contract).
487
- * Canvas 2D is always ready immediately (no async initialization).
488
- *
489
- * @returns Always true for Canvas 2D
484
+ * Get grid dimensions
490
485
  */
491
- isReady(): boolean;
486
+ getGridSize(): {
487
+ cols: number;
488
+ rows: number;
489
+ };
492
490
  /**
493
- * Get width in columns (IRenderer contract).
491
+ * Get cell width
494
492
  */
495
- getCols(): number;
493
+ getCellWidth(): number;
496
494
  /**
497
- * Get height in rows (IRenderer contract).
495
+ * Get cell height
498
496
  */
499
- getRows(): number;
497
+ getCellHeight(): number;
500
498
  /**
501
- * Resize renderer dimensions (IRenderer contract).
502
- *
503
- * @param cols - New width in columns
504
- * @param rows - New height in rows
499
+ * Get current integer scale factor
500
+ * Used by PostProcessOverlay to sync dimensions
505
501
  */
506
- resize(cols: number, rows: number): void;
502
+ getCurrentScale(): number;
507
503
  /**
508
- * Set scaling mode for pixel-perfect rendering
509
- *
510
- * @param mode - ScalingMode enum value:
511
- * - ScalingMode.None: Fill space, may have sub-pixel artifacts
512
- * - ScalingMode.Eighth: Snap to 0.125 increments (1.0, 1.125, 1.25...)
513
- * - ScalingMode.Quarter: Snap to 0.25 increments (1.0, 1.25, 1.5...)
514
- * - ScalingMode.Half: Snap to 0.5 increments (1.0, 1.5, 2.0...)
515
- * - ScalingMode.Integer: Crisp pixels, may waste space (1x, 2x, 3x...)
516
- * - ScalingMode.Responsive: No CSS scaling, cols/rows adapt to space
504
+ * Get base canvas dimensions (before scaling)
505
+ * Used by PostProcessOverlay to sync dimensions
517
506
  */
518
- setScalingMode(mode: ScalingMode): void;
507
+ getBaseDimensions(): {
508
+ width: number;
509
+ height: number;
510
+ };
519
511
  /**
520
- * Set cell dimensions in pixels (for Responsive mode)
521
- *
522
- * Changes the native pixel size of each character cell.
523
- * This will trigger a canvas resize and re-render.
524
- *
525
- * @param cellWidth - Cell width in pixels (1-255)
526
- * @param cellHeight - Cell height in pixels (1-255)
512
+ * Set callback to be called after every resize
513
+ * Used by ClientRuntime to sync PostProcessOverlay
527
514
  */
528
- setCellSize(cellWidth: number, cellHeight: number): void;
515
+ setOnResizeCallback(callback: () => void): void;
529
516
  /**
530
- * Get current cell size
517
+ * Clear the resize callback
531
518
  */
532
- getCellSize(): {
533
- cellWidth: number;
534
- cellHeight: number;
535
- };
519
+ clearOnResizeCallback(): void;
536
520
  /**
537
521
  * Get the available size from the parent container.
538
522
  * This is the actual pixel space available for rendering.
@@ -545,812 +529,588 @@ declare class Terminal2D implements IRenderer {
545
529
  height: number;
546
530
  };
547
531
  /**
548
- * Get the maximum number of cells this renderer can handle
549
- *
550
- * Canvas 2D has very generous limits compared to WebGL.
551
- * The main constraint is memory for the ImageData buffer.
552
- *
553
- * @returns Maximum cells supported (256×256 = 65536 for compatibility)
554
- */
555
- getMaxCells(): number;
556
- /**
557
- * Détruit le terminal et nettoie les ressources
558
- */
559
- destroy(): void;
560
- }
561
-
562
- /**
563
- * WebGL compatibility report
564
- */
565
- interface WebGLCompatibilityReport {
566
- /** WebGL 1.0 support */
567
- webgl1: boolean;
568
- /** OES_element_index_uint extension (Uint32 indices) */
569
- uint32Indices: boolean;
570
- /** Maximum texture size */
571
- maxTextureSize: number;
572
- /** Maximum viewport dimensions */
573
- maxViewportDims: [number, number];
574
- /** Maximum terminal size with Uint16 indices (cols × rows) */
575
- maxCellsUint16: number;
576
- /** Maximum terminal size with Uint32 indices (cols × rows) */
577
- maxCellsUint32: number;
578
- /** Recommended maximum terminal size for this device */
579
- recommendedMaxCells: number;
580
- /** Warnings (empty if fully compatible) */
581
- warnings: string[];
582
- /** Errors (empty if compatible) */
583
- errors: string[];
584
- }
585
- /**
586
- * Options for WebGL terminal configuration
587
- */
588
- interface TerminalGLOptions {
589
- /** Number of columns (required) */
590
- cols: number;
591
- /** Number of rows (required) */
592
- rows: number;
593
- /** Character width in pixels */
594
- charWidth?: number;
595
- /** Character height in pixels */
596
- charHeight?: number;
597
- /** Canvas background color (CSS format, for gl.clearColor) */
598
- canvasBgColor?: string | null;
599
- /** Show cell delimitation grid (debug) */
600
- showGrid?: boolean;
601
- /** Force Uint16 indices (for compatibility testing, auto-detected by default) */
602
- forceUint16?: boolean;
603
- /**
604
- * Scaling mode for pixel-perfect rendering (default: ScalingMode.None)
605
- *
606
- * Controls how the canvas is scaled to fit the container:
607
- * - ScalingMode.None: Fills available space, may have sub-pixel artifacts (default)
608
- * - ScalingMode.Eighth: Snaps to 0.125 increments (1.0, 1.125, 1.25...)
609
- * - ScalingMode.Quarter: Snaps to 0.25 increments (1.0, 1.25, 1.5...)
610
- * - ScalingMode.Half: Snaps to 0.5 increments (1.0, 1.5, 2.0...)
611
- * - ScalingMode.Integer: Integer scaling only (1x, 2x, 3x...), crispest pixels
612
- */
613
- scalingMode?: ScalingMode;
614
- /**
615
- * Ambient effect configuration
616
- *
617
- * Creates a blurred glow effect around the terminal when using pixel-perfect
618
- * scaling modes that leave empty space around the canvas.
619
- *
620
- * - false or undefined: Disabled (default)
621
- * - true: Enabled with default settings (blur: 30px, scale: 1.15, opacity: 0.7)
622
- * - object: Custom configuration
623
- */
624
- ambientEffect?: boolean | {
625
- /** Blur radius in pixels (default: 30) */
626
- blur?: number;
627
- /** Scale factor for the background canvas (default: 1.15) */
628
- scale?: number;
629
- /** Opacity of the ambient effect (0-1, default: 0.7) */
630
- opacity?: number;
631
- };
632
- }
633
- /**
634
- * Simplified terminal using WebGL for basic rendering
635
- * Only supports bitmap fonts with atlas
636
- * Implements IRenderer interface for dependency injection with core
637
- *
638
- * ✨ SIMPLIFIED VERSION: Only backgrounds + colored characters
639
- */
640
- declare class TerminalGL implements IRenderer {
641
- /**
642
- * Check WebGL 1.0 compatibility and device capabilities
643
- *
644
- * Tests all required WebGL features and returns a detailed compatibility report.
645
- * Use this before creating a TerminalGL instance to ensure device support.
646
- *
647
- * @returns Detailed compatibility report with warnings and errors
532
+ * Set scaling mode
648
533
  *
649
- * @example
650
- * ```typescript
651
- * const report = TerminalGL.checkCompatibility();
652
- * if (report.errors.length > 0) {
653
- * console.error('WebGL not supported:', report.errors);
654
- * // Fallback to Canvas 2D renderer
655
- * } else if (report.warnings.length > 0) {
656
- * console.warn('WebGL limitations:', report.warnings);
657
- * }
658
- * console.log(`Max terminal size: ${report.recommendedMaxCells} cells`);
659
- * ```
660
- */
661
- static checkCompatibility(): WebGLCompatibilityReport;
662
- private canvas;
663
- private gl;
664
- private parentElement;
665
- private containerDiv;
666
- private cols;
667
- private rows;
668
- private charWidth;
669
- private charHeight;
670
- private cellWidth;
671
- private cellHeight;
672
- private glyphOffsetX;
673
- private glyphOffsetY;
674
- private canvasBgColor;
675
- private showGrid;
676
- private supportsUint32Indices;
677
- private useUint16Indices;
678
- private gridOverlay?;
679
- private bitmapFont?;
680
- private atlasTexture;
681
- private atlasCanvas?;
682
- private atlasColumns;
683
- private fontLoaded;
684
- private paletteTexture;
685
- private program;
686
- private positionBuffer;
687
- private texCoordBuffer;
688
- private colorIndexBuffer;
689
- private indexBuffer;
690
- private aPosition?;
691
- private aTexCoord?;
692
- private aColorIndex?;
693
- private uResolution;
694
- private uTexture;
695
- private uPalette;
696
- private resizeObserver?;
697
- private charCodeToAtlasIndex;
698
- private atlasUVs;
699
- private cachedAtlasWidth;
700
- private cachedAtlasHeight;
701
- private paletteFloat;
702
- private maxCells;
703
- private renderPositions;
704
- private renderTexCoords;
705
- private renderColorIndices;
706
- private renderIndices;
707
- private cachedResolution;
708
- private cachedTextureUnit;
709
- private cachedPaletteUnit;
710
- private cachedTextureUniform;
711
- private cachedPaletteUniform;
712
- private paletteHash;
713
- private currentScale;
714
- private scalingMode;
715
- private ambientEffectEnabled;
716
- private ambientEffectCanvas;
717
- private ambientEffectCtx;
718
- private ambientEffectBlur;
719
- private ambientEffectScale;
720
- private ambientEffectOpacity;
721
- private onResizeCallback?;
722
- private staticPositionsInitialized;
723
- private vaoExtension;
724
- private vao;
725
- private instancedExtension;
726
- private useInstancing;
727
- private instanceDataBuffer;
728
- private instanceData;
729
- private templateQuadPositions;
730
- private templateQuadIndices;
731
- private aInstanceOffset;
732
- private aInstanceUVs;
733
- private aInstanceColors;
734
- private uCellSize;
735
- constructor(parentDiv: HTMLDivElement, options: TerminalGLOptions);
736
- /**
737
- * 🚀 INSTANCING: Initialize template quad and instance buffers
738
- * Called once at init if instancing is supported
739
- */
740
- private initInstancedBuffers;
741
- /**
742
- * 🚀 OPTIMIZATION: Initialize pre-allocated buffers for rendering
743
- * Avoids allocations each frame
744
- * Uses Uint16 or Uint32 indices based on device support
745
- */
746
- private initRenderBuffers;
747
- /**
748
- * 🚀 MEGA OPTIMIZATION: Pre-compute static positions for ALL possible quads
749
- * Called only once after font load, or after resize
750
- * Positions never change during rendering - only colors and UVs change!
534
+ * @param mode - ScalingMode enum value:
535
+ * - ScalingMode.None: Fill space, may have sub-pixel artifacts
536
+ * - ScalingMode.Eighth: Snap to 0.125 increments (1.0, 1.125, 1.25...)
537
+ * - ScalingMode.Quarter: Snap to 0.25 increments (1.0, 1.25, 1.5...)
538
+ * - ScalingMode.Half: Snap to 0.5 increments (1.0, 1.5, 2.0...)
539
+ * - ScalingMode.Integer: Crisp pixels, may waste space (1x, 2x, 3x...)
751
540
  */
752
- private precomputeStaticPositions;
541
+ setScalingMode(mode: ScalingMode): void;
753
542
  /**
754
- * Initialize WebGL (shaders, buffers, etc.)
543
+ * Get current scaling mode
755
544
  */
756
- private initWebGL;
545
+ getScalingMode(): ScalingMode;
757
546
  /**
758
- * Compile a shader
547
+ * Set cell dimensions in pixels
548
+ *
549
+ * Changes the native pixel size of each character cell.
550
+ * This will trigger a canvas resize and buffer reallocation.
551
+ *
552
+ * @param cellWidth - Cell width in pixels (1-255)
553
+ * @param cellHeight - Cell height in pixels (1-255)
759
554
  */
760
- private compileShader;
555
+ setCellSize(cellWidth: number, cellHeight: number): void;
761
556
  /**
762
- * 🔲 Initialize 2D canvas overlay for debug grid
763
- * Performance: 2D canvas drawn only once, 0ms per frame
557
+ * Get current cell size
764
558
  */
765
- private initGridOverlay;
559
+ getCellSize(): {
560
+ cellWidth: number;
561
+ cellHeight: number;
562
+ };
766
563
  /**
767
- * 🔲 Draw grid lines on 2D canvas overlay
768
- * Called only once at init and resize
564
+ * Get the maximum number of cells this renderer can handle
769
565
  *
770
- * The grid must match the terminal's pixel-perfect scaling:
771
- * - Same base size as the main canvas
772
- * - Same transform: scale() factor
773
- * - Centered in the container like the main canvas (via flexbox or calculated position)
566
+ * This depends on device capabilities:
567
+ * - With instanced rendering: ~262,144 cells (limited by GPU memory)
568
+ * - With Uint32 indices: ~262,144 cells
569
+ * - With Uint16 indices only: ~8,191 cells (~90×90)
570
+ *
571
+ * Use this in responsive mode to clamp calculated cols/rows.
572
+ *
573
+ * @returns Maximum cells supported by this renderer
774
574
  */
775
- private updateGridOverlay;
575
+ getMaxCells(): number;
776
576
  /**
777
- * Configure bitmap font and generate atlas
778
- *
779
- * ⚠️ **INTERNAL USE ONLY** - This method is called automatically by ClientRuntime's
780
- * event system when Core.loadBitmapFontById() is called. Do NOT call this directly
781
- * unless you're implementing a custom runtime.
577
+ * Enable or configure debug grid overlay
782
578
  *
783
- * Event flow: Core.loadBitmapFontById() Core.onBitmapFontChangedCallback
784
- * ClientRuntime.onCoreBitmapFontChanged() RendererManager.setBitmapFont()
579
+ * The grid shows cell boundaries aligned with the terminal grid.
580
+ * Useful for debugging layout and alignment issues.
785
581
  *
786
- * @param font - Bitmap font mapping (charCode → byte array)
787
- * @param charWidth - Width of each character in pixels
788
- * @param charHeight - Height of each character in pixels
789
- * @param cellWidth - Width of each cell in pixels
790
- * @param cellHeight - Height of each cell in pixels
791
- * @throws {Error} If atlas generation fails
582
+ * @param config - Configuration options:
583
+ * - enabled: Whether to show the grid
584
+ * - color: CSS color string (e.g., 'rgba(255,0,0,0.5)', '#ff0000')
585
+ * - lineWidth: Line width in pixels (1-10)
792
586
  *
793
587
  * @example
794
588
  * ```typescript
795
- * // DON'T: Call setBitmapFont directly
796
- * renderer.setBitmapFont(font, 8, 16, 8, 16);
797
- *
798
- * // DO: Use Core's loadBitmapFontById (triggers event automatically)
799
- * core.loadBitmapFontById(1, {
800
- * charWidth: 8, charHeight: 16,
801
- * cellWidth: 8, cellHeight: 16,
802
- * glyphs: new Map([[65, new Uint8Array([...])]])
803
- * });
804
- * ```
805
- */
806
- setBitmapFont(font: BitmapFont$1, charWidth: number, charHeight: number, cellWidth: number, cellHeight: number): void;
807
- /**
808
- * Set image font (PNG atlas) for extended character rendering
809
- * Supports 1, 4, or 16 blocks (256, 1024, or 4096 characters)
589
+ * // Enable with default red color
590
+ * renderer.setGrid({ enabled: true });
591
+ *
592
+ * // Custom green grid
593
+ * renderer.setGrid({ enabled: true, color: 'rgba(0, 255, 0, 0.5)' });
810
594
  *
811
- * @param imageData - PNG image data as Uint8Array
812
- * @param glyphWidth - Glyph width in pixels
813
- * @param glyphHeight - Glyph height in pixels
814
- * @param cellWidth - Cell width in pixels
815
- * @param cellHeight - Cell height in pixels
816
- * @param atlasBlocks - Number of 256-char blocks (1, 4, or 16)
595
+ * // Disable grid
596
+ * renderer.setGrid({ enabled: false });
597
+ * ```
817
598
  */
818
- setImageFont(imageData: Uint8Array, glyphWidth: number, glyphHeight: number, cellWidth: number, cellHeight: number, atlasBlocks: AtlasBlocks): Promise<void>;
599
+ setGrid(config: {
600
+ enabled: boolean;
601
+ color?: string;
602
+ lineWidth?: number;
603
+ }): void;
819
604
  /**
820
- * Load PNG image and create WebGL texture
605
+ * Check if grid is currently enabled
821
606
  */
822
- private loadImageFontAtlas;
607
+ isGridEnabled(): boolean;
823
608
  /**
824
- * Pre-compute UVs for ImageFont (block-based grid layout)
609
+ * Enable or configure ambient effect
825
610
  *
826
- * Atlas layout for multi-block fonts:
827
- * - Each block contains 256 chars in a 16×16 grid
828
- * - Blocks are arranged visually:
829
- * - 1 block: 1×1 (16×16 chars)
830
- * - 4 blocks: 2×2 (32×32 chars total)
831
- * - 16 blocks: 4×4 (64×64 chars total)
611
+ * Ambient effect creates a blurred glow around the terminal canvas,
612
+ * filling the unused space with colors from the terminal content.
832
613
  *
833
- * CharCode mapping:
834
- * charCode 0-255 → Block 0 (top-left)
835
- * charCode 256-511 → Block 1 (top-right for 4 blocks)
836
- * charCode 512-767 → Block 2 (bottom-left for 4 blocks)
837
- * etc.
838
- */
839
- private precomputeImageFontUVs;
840
- /**
841
- * Generate texture atlas from bitmap font
614
+ * @param config - true to enable with defaults, false to disable,
615
+ * or object with blur and scale settings
616
+ *
617
+ * @example
618
+ * ```typescript
619
+ * // Enable with defaults (blur: 30px, scale: 1.3)
620
+ * renderer.setAmbientEffect(true);
621
+ *
622
+ * // Disable
623
+ * renderer.setAmbientEffect(false);
624
+ *
625
+ * // Custom settings
626
+ * renderer.setAmbientEffect({ blur: 50, scale: 1.5 });
627
+ * ```
842
628
  */
843
- private generateAtlas;
629
+ setAmbientEffect(config: boolean | {
630
+ blur?: number;
631
+ scale?: number;
632
+ }): void;
844
633
  /**
845
- * 🚀 OPTIMIZED: Build charCode atlas index using direct array lookup
634
+ * Create the ambient effect canvas element (called lazily if needed)
846
635
  */
847
- private buildCharCodeMap;
636
+ private createAmbientEffectCanvas;
848
637
  /**
849
- * 🚀 MEGA OPTIMIZATION: Pre-compute ALL atlas UVs
850
- * Called once after atlas generation - UVs never change!
851
- * Eliminates per-frame division and modulo operations
638
+ * Check if ambient effect is enabled
852
639
  */
853
- private precomputeAtlasUVs;
640
+ isAmbientEffectEnabled(): boolean;
854
641
  /**
855
- * Create WebGL texture from atlas
642
+ * Get current ambient effect configuration
856
643
  */
857
- private createAtlasTexture;
644
+ getAmbientEffectConfig(): {
645
+ enabled: boolean;
646
+ blur: number;
647
+ scale: number;
648
+ };
858
649
  /**
859
- * Clear entire terminal
650
+ * Get number of columns (IRenderer interface)
860
651
  *
861
- * Clears the WebGL canvas. Note: Actual terminal content clearing is handled
862
- * by Core's RenderState, not by this renderer.
652
+ * @returns Current number of columns
863
653
  *
864
654
  * @example
865
655
  * ```typescript
866
- * renderer.clear();
656
+ * const cols = renderer.getCols(); // 80
867
657
  * ```
868
658
  */
869
- clear(): void;
870
- /**
871
- * Parse CSS color to normalized RGBA (0-1)
872
- */
873
- private parseColor;
659
+ getCols(): number;
874
660
  /**
875
- * Configure ResizeObserver to adapt canvas
661
+ * Get number of rows (IRenderer interface)
662
+ *
663
+ * @returns Current number of rows
664
+ *
665
+ * @example
666
+ * ```typescript
667
+ * const rows = renderer.getRows(); // 25
668
+ * ```
876
669
  */
877
- private setupResizeObserver;
670
+ getRows(): number;
878
671
  /**
879
- * Update canvas display size
672
+ * Check if renderer is ready (IRenderer interface)
880
673
  *
881
- * Supports multiple scaling modes:
674
+ * Returns true when bitmap font, atlas texture, and shader program are initialized.
882
675
  *
883
- * 🎯 INTEGER MODE (ScalingMode.Integer):
884
- * Uses integer scaling (1x, 2x, 3x...) for crisp pixels without artifacts.
885
- * The canvas is centered in the container via flexbox.
886
- * May leave empty space around the canvas.
676
+ * @returns true if ready to render, false otherwise
887
677
  *
888
- * 📐 HALF MODE (ScalingMode.Half):
889
- * Snaps to half increments (1.0, 1.5, 2.0...).
890
- * Good balance between space usage and visual quality.
678
+ * @example
679
+ * ```typescript
680
+ * if (renderer.isReady()) {
681
+ * renderer.renderDisplayData(data);
682
+ * }
683
+ * ```
684
+ */
685
+ isReady(): boolean;
686
+ /**
687
+ * Destroy/cleanup resources (IRenderer interface)
891
688
  *
892
- * 📏 QUARTER MODE (ScalingMode.Quarter):
893
- * Snaps to quarter increments (1.0, 1.25, 1.5, 1.75, 2.0...).
894
- * Finer control over scaling with minimal artifacts.
689
+ * Destroys WebGL resources (textures, buffers), disconnects ResizeObserver,
690
+ * and removes canvases from DOM. Call this before removing the renderer.
895
691
  *
896
- * 🔲 NONE MODE (ScalingMode.None):
897
- * Scales to fill as much space as possible while maintaining aspect ratio.
898
- * May cause some lines to appear thicker due to sub-pixel rendering.
899
- * Useful when maximizing screen usage is more important than pixel purity.
692
+ * @example
693
+ * ```typescript
694
+ * renderer.destroy();
695
+ * renderer = null;
696
+ * ```
900
697
  */
901
- private updateCanvasSize;
698
+ destroy(): void;
902
699
  /**
903
- * 🌈 AMBIENT EFFECT: Copy main canvas to ambient effect background
904
- *
905
- * This creates a glow effect around the terminal by copying the main
906
- * WebGL canvas to a 2D canvas behind it, which has CSS blur applied.
700
+ * Cleanup resources
907
701
  */
908
- private updateAmbientEffect;
702
+ dispose(): void;
703
+ }
704
+
705
+ /**
706
+ * Représente une cellule du terminal
707
+ */
708
+ interface TerminalCell {
709
+ /** Le caractère à afficher */
710
+ char: string;
711
+ /** Couleur du caractère (format CSS) */
712
+ fgColor: string;
713
+ /** Couleur de fond de la cellule (format CSS) */
714
+ bgColor: string;
715
+ }
716
+ /**
717
+ * Données brutes pour définir le terminal en une fois
718
+ */
719
+ interface TerminalData {
720
+ /** Largeur en cellules */
721
+ width: number;
722
+ /** Hauteur en cellules */
723
+ height: number;
724
+ /** Tableau de cellules (longueur = width * height) */
725
+ cells: Array<{
726
+ /** Code du caractère ou le caractère lui-même */
727
+ char: string;
728
+ /** Couleur du texte (format CSS) */
729
+ fgColor: string;
730
+ /** Couleur de fond (format CSS) */
731
+ bgColor: string;
732
+ }>;
733
+ }
734
+ /**
735
+ * Options pour la configuration du terminal
736
+ */
737
+ interface RenderOptions {
738
+ /** Largeur d'une cellule en pixels (défaut: 8) - ignoré en mode fixedGrid */
739
+ cellWidth?: number;
740
+ /** Hauteur d'une cellule en pixels (défaut: 8) - ignoré en mode fixedGrid */
741
+ cellHeight?: number;
742
+ /** Couleur de texte par défaut (défaut: "#ffffff") */
743
+ defaultFgColor?: string;
744
+ /** Couleur de fond par défaut (défaut: "#000000") */
745
+ defaultBgColor?: string;
746
+ /** Couleur de fond du canvas lui-même (défaut: transparent). Si null ou undefined, le canvas sera transparent */
747
+ canvasBgColor?: string | null;
748
+ /** Afficher une grille de débogage (défaut: false) */
749
+ showDebugGrid?: boolean;
750
+ /** Couleur de la grille de débogage (défaut: "rgba(255, 0, 0, 0.3)") */
751
+ debugGridColor?: string;
752
+ /** Classes CSS additionnelles pour le canvas */
753
+ className?: string;
754
+ /** Style inline pour le canvas */
755
+ style?: Partial<CSSStyleDeclaration>;
756
+ /** Nombre de colonnes fixe (active le mode fixedGrid) */
757
+ fixedCols?: number;
758
+ /** Nombre de lignes fixe (active le mode fixedGrid) */
759
+ fixedRows?: number;
760
+ /** Ratio largeur/hauteur de cellule pour mode fixedGrid (défaut: 1 = carré) */
761
+ cellAspectRatio?: number;
909
762
  /**
910
- * Set color palette and upload to GPU
911
- *
912
- * ⚠️ IMPORTANT: This is the ONLY way to update the palette.
913
- * Typically called automatically by ClientRuntime via Core.onPaletteChanged() event.
914
- * Do NOT call this directly unless you know what you're doing.
915
- *
916
- * @param palette - Array of 256 RGB colors
763
+ * Scaling mode for pixel-perfect rendering (default: ScalingMode.None)
917
764
  *
918
- * @example
919
- * ```typescript
920
- * // Normal usage: Core handles this automatically
921
- * core.loadPalette([...]);
922
- * // Core emits event
923
- * // ClientRuntime receives event
924
- * // → renderer.setPalette() called automatically
765
+ * Controls how the canvas is scaled to fit the container:
766
+ * - ScalingMode.None: Scales cells to fill space, may have sub-pixel artifacts
767
+ * - ScalingMode.Eighth: Snaps to 0.125 increments (1.0, 1.125, 1.25...)
768
+ * - ScalingMode.Quarter: Snaps to 0.25 increments (1.0, 1.25, 1.5...)
769
+ * - ScalingMode.Half: Snaps to 0.5 increments (1.0, 1.5, 2.0...)
770
+ * - ScalingMode.Integer: Integer scaling only (1x, 2x, 3x...), crispest pixels
925
771
  *
926
- * // ⚠️ Manual usage (advanced):
927
- * const myPalette: RGBColor[] = [
928
- * { r: 0, g: 0, b: 0, a: 255 }, // Color 0: Black
929
- * { r: 255, g: 0, b: 0, a: 255 }, // Color 1: Red
930
- * // ... 254 more colors
931
- * ];
932
- * renderer.setPalette(myPalette);
933
- * ```
772
+ * Note: For ImageFont mode, this uses native glyph sizes + CSS transform scaling.
934
773
  */
935
- setPalette(palette: RGBColor[]): void;
774
+ scalingMode?: ScalingMode;
775
+ }
776
+ /**
777
+ * UTSP Render - Gère une grille de caractères avec couleurs
778
+ * Similaire à un terminal mais avec contrôle total de chaque cellule
779
+ *
780
+ * Implements IRenderer interface for compatibility with TerminalGL and dependency injection.
781
+ */
782
+ declare class Terminal2D implements IRenderer {
783
+ private containerDiv;
784
+ private canvas;
785
+ private ctx;
786
+ private parentElement;
787
+ private cells;
788
+ private cols;
789
+ private rows;
790
+ private defaultFgColor;
791
+ private defaultBgColor;
792
+ private canvasBgColor;
793
+ private cellWidth;
794
+ private cellHeight;
795
+ private offsetX;
796
+ private offsetY;
797
+ private imageAtlas?;
798
+ private showDebugGrid;
799
+ private debugGridColor;
800
+ private gridOverlay?;
801
+ private fixedGridMode;
802
+ private fixedCols?;
803
+ private fixedRows?;
804
+ private cellAspectRatio;
805
+ private resizeObserver?;
806
+ private paletteCache?;
807
+ private scalingMode;
808
+ private currentScale;
809
+ private customCellSize;
936
810
  /**
937
- * 🚀 GPU OPTIMIZATION: Upload palette to GPU texture (256×1 RGBA)
811
+ * Crée une instance de UTSPRender
812
+ * @param parentDiv - L'élément HTML parent dans lequel créer le canvas
813
+ * @param options - Options de configuration du terminal
938
814
  */
939
- private updatePaletteTexture;
815
+ constructor(parentDiv: HTMLElement, options?: RenderOptions);
940
816
  /**
941
- * Render display data from core engine (ULTRA-OPTIMIZED)
942
- *
943
- * Bypasses internal cells and renders directly from RenderState for maximum performance.
944
- * Uses GPU palette texture lookup to minimize CPU→GPU bandwidth (4× reduction).
945
- *
946
- * @param data - Render state containing cells, dimensions, and palette
817
+ * Calcule le nombre de colonnes et de lignes en fonction de la taille du parent
818
+ * et centre le terminal dans le canvas
947
819
  *
948
- * @example
949
- * ```typescript
950
- * const renderState: RenderState = {
951
- * cells: [...],
952
- * width: 80,
953
- * height: 25,
954
- * palette: [...]
955
- * };
956
- * renderer.renderDisplayData(renderState);
957
- * ```
820
+ * 🎯 PIXEL-PERFECT APPROACH (like TerminalGL):
821
+ * 1. Cell dimensions are ALWAYS integers (native font size)
822
+ * 2. Canvas renders at native resolution (cols * cellWidth)
823
+ * 3. CSS transform: scale() handles visual upscaling
824
+ * 4. Flexbox handles centering
958
825
  */
959
- renderDisplayData(data: RenderState): void;
826
+ private calculateGridSize;
960
827
  /**
961
- * Render multiple passes in order, clearing once then layering.
828
+ * Crée une grille vide avec les valeurs par défaut
962
829
  */
963
- private renderMultiPass;
830
+ private createEmptyGrid;
964
831
  /**
965
- * 🚀 NEW METHOD: Render directly from RenderState
966
- * Bypass this.cells for maximum performance
832
+ * Active le redimensionnement automatique
833
+ * Recalcule le nombre de colonnes/lignes quand le parent change de taille
967
834
  */
968
- private renderDirect;
835
+ private enableAutoResize;
969
836
  /**
970
- * 🚀 INSTANCED RENDERING: 1 draw call for entire terminal
971
- * MASSIVE performance boost - reduces draw calls from cols×rows×2 to just 1!
837
+ * Définit le contenu d'une cellule
838
+ * @param col - Colonne (0-indexed)
839
+ * @param row - Ligne (0-indexed)
840
+ * @param char - Caractère à afficher
841
+ * @param fgColor - Couleur du texte (optionnel, utilise la valeur par défaut si non fourni)
842
+ * @param bgColor - Couleur de fond (optionnel, utilise la valeur par défaut si non fourni)
972
843
  */
973
- private renderInstanced;
844
+ setCell(col: number, row: number, char: string, fgColor?: string, bgColor?: string): void;
974
845
  /**
975
- * 🚀 ULTRA-OPTIMIZED: Update ONLY dynamic data (colors + UVs)
976
- * Positions are static and pre-computed - only updated on resize!
977
- * This is a MASSIVE performance win - positions never change during normal rendering
846
+ * Récupère le contenu d'une cellule
847
+ * @param col - Colonne (0-indexed)
848
+ * @param row - Ligne (0-indexed)
978
849
  */
979
- private renderDirectBuffers;
850
+ getCell(col: number, row: number): TerminalCell | null;
980
851
  /**
981
- * Resize the terminal dimensions
982
- *
983
- * Changes the number of columns and rows. Preserves existing cell content
984
- * where possible. Reallocates render buffers if needed.
985
- *
986
- * @param cols - New number of columns (must be positive integer)
987
- * @param rows - New number of rows (must be positive integer)
988
- *
989
- * @example
990
- * ```typescript
991
- * renderer.resize(120, 40); // Resize to 120×40
992
- * ```
852
+ * Écrit une chaîne de caractères à partir d'une position
853
+ * @param col - Colonne de départ
854
+ * @param row - Ligne
855
+ * @param text - Texte à écrire
856
+ * @param fgColor - Couleur du texte (optionnel)
857
+ * @param bgColor - Couleur de fond (optionnel)
993
858
  */
994
- resize(cols: number, rows: number): void;
859
+ write(col: number, row: number, text: string, fgColor?: string, bgColor?: string): void;
995
860
  /**
996
- * Get canvas element
861
+ * Remplit une zone rectangulaire
862
+ * @param startCol - Colonne de départ
863
+ * @param startRow - Ligne de départ
864
+ * @param width - Largeur en cellules
865
+ * @param height - Hauteur en cellules
866
+ * @param char - Caractère de remplissage
867
+ * @param fgColor - Couleur du texte (optionnel)
868
+ * @param bgColor - Couleur de fond (optionnel)
997
869
  */
998
- getCanvas(): HTMLCanvasElement;
870
+ fillRect(startCol: number, startRow: number, width: number, height: number, char?: string, fgColor?: string, bgColor?: string): void;
999
871
  /**
1000
- * Get grid dimensions
872
+ * Efface tout le terminal (remplit avec des espaces)
1001
873
  */
1002
- getGridSize(): {
1003
- cols: number;
1004
- rows: number;
1005
- };
874
+ clear(): void;
1006
875
  /**
1007
- * Get cell width
876
+ * Définit tout le contenu du terminal à partir d'un tableau de données
877
+ * Le tableau doit contenir width * height éléments
878
+ * Les cellules sont lues ligne par ligne (row-major order)
879
+ *
880
+ * @param data - Données du terminal avec dimensions et cellules
881
+ * @throws Error si le tableau n'a pas la bonne taille
882
+ *
883
+ * @example
884
+ * terminal.setFromArray({
885
+ * width: 3,
886
+ * height: 2,
887
+ * cells: [
888
+ * { char: 'A', fgColor: '#ff0000', bgColor: '#000000' }, // (0,0)
889
+ * { char: 'B', fgColor: '#00ff00', bgColor: '#000000' }, // (1,0)
890
+ * { char: 'C', fgColor: '#0000ff', bgColor: '#000000' }, // (2,0)
891
+ * { char: 'D', fgColor: '#ffff00', bgColor: '#000000' }, // (0,1)
892
+ * { char: 'E', fgColor: '#ff00ff', bgColor: '#000000' }, // (1,1)
893
+ * { char: 'F', fgColor: '#00ffff', bgColor: '#000000' }, // (2,1)
894
+ * ]
895
+ * });
1008
896
  */
1009
- getCellWidth(): number;
897
+ setFromArray(data: TerminalData): void;
1010
898
  /**
1011
- * Get cell height
899
+ * Rend la grille sur le canvas
900
+ * @param clearCanvas - Whether to clear the canvas before rendering (default: true)
901
+ * Set to false for multi-pass rendering (stacking layers)
1012
902
  */
1013
- getCellHeight(): number;
903
+ render(clearCanvas?: boolean): void;
1014
904
  /**
1015
- * Get current integer scale factor
1016
- * Used by PostProcessOverlay to sync dimensions
905
+ * Rendu classique avec fillRect + atlas/bitmap
906
+ * @param clearCanvas - Whether to clear the canvas before rendering
1017
907
  */
1018
- getCurrentScale(): number;
908
+ private renderClassic;
1019
909
  /**
1020
- * Get base canvas dimensions (before scaling)
1021
- * Used by PostProcessOverlay to sync dimensions
910
+ * Dessine une grille de débogage pour visualiser les cellules
1022
911
  */
1023
- getBaseDimensions(): {
1024
- width: number;
1025
- height: number;
1026
- };
912
+ private drawDebugGrid;
1027
913
  /**
1028
- * Set callback to be called after every resize
1029
- * Used by ClientRuntime to sync PostProcessOverlay
914
+ * Obtient le canvas HTML
1030
915
  */
1031
- setOnResizeCallback(callback: () => void): void;
916
+ getCanvas(): HTMLCanvasElement;
1032
917
  /**
1033
- * Clear the resize callback
918
+ * Obtient le contexte 2D
1034
919
  */
1035
- clearOnResizeCallback(): void;
920
+ getContext(): CanvasRenderingContext2D;
1036
921
  /**
1037
- * Get the available size from the parent container.
1038
- * This is the actual pixel space available for rendering.
1039
- * Useful in Responsive mode to calculate how many cells can fit.
1040
- *
1041
- * @returns Object with width and height in pixels
922
+ * Obtient les dimensions de la grille
1042
923
  */
1043
- getAvailableSize(): {
1044
- width: number;
1045
- height: number;
924
+ getDimensions(): {
925
+ cols: number;
926
+ rows: number;
1046
927
  };
1047
928
  /**
1048
- * Set scaling mode
1049
- *
1050
- * @param mode - ScalingMode enum value:
1051
- * - ScalingMode.None: Fill space, may have sub-pixel artifacts
1052
- * - ScalingMode.Eighth: Snap to 0.125 increments (1.0, 1.125, 1.25...)
1053
- * - ScalingMode.Quarter: Snap to 0.25 increments (1.0, 1.25, 1.5...)
1054
- * - ScalingMode.Half: Snap to 0.5 increments (1.0, 1.5, 2.0...)
1055
- * - ScalingMode.Integer: Crisp pixels, may waste space (1x, 2x, 3x...)
1056
- */
1057
- setScalingMode(mode: ScalingMode): void;
1058
- /**
1059
- * Get current scaling mode
1060
- */
1061
- getScalingMode(): ScalingMode;
1062
- /**
1063
- * Set cell dimensions in pixels
1064
- *
1065
- * Changes the native pixel size of each character cell.
1066
- * This will trigger a canvas resize and buffer reallocation.
1067
- *
1068
- * @param cellWidth - Cell width in pixels (1-255)
1069
- * @param cellHeight - Cell height in pixels (1-255)
1070
- */
1071
- setCellSize(cellWidth: number, cellHeight: number): void;
1072
- /**
1073
- * Get current cell size
929
+ * Obtient les dimensions des cellules
1074
930
  */
1075
- getCellSize(): {
931
+ getCellDimensions(): {
1076
932
  cellWidth: number;
1077
933
  cellHeight: number;
1078
934
  };
1079
935
  /**
1080
- * Get the maximum number of cells this renderer can handle
1081
- *
1082
- * This depends on device capabilities:
1083
- * - With instanced rendering: ~262,144 cells (limited by GPU memory)
1084
- * - With Uint32 indices: ~262,144 cells
1085
- * - With Uint16 indices only: ~8,191 cells (~90×90)
1086
- *
1087
- * Use this in responsive mode to clamp calculated cols/rows.
1088
- *
1089
- * @returns Maximum cells supported by this renderer
936
+ * Obtient la largeur d'une cellule
1090
937
  */
1091
- getMaxCells(): number;
938
+ getCellWidth(): number;
1092
939
  /**
1093
- * Enable or configure debug grid overlay
1094
- *
1095
- * The grid shows cell boundaries aligned with the terminal grid.
1096
- * Useful for debugging layout and alignment issues.
1097
- *
1098
- * @param config - Configuration options:
1099
- * - enabled: Whether to show the grid
1100
- * - color: CSS color string (e.g., 'rgba(255,0,0,0.5)', '#ff0000')
1101
- * - lineWidth: Line width in pixels (1-10)
1102
- *
1103
- * @example
1104
- * ```typescript
1105
- * // Enable with default red color
1106
- * renderer.setGrid({ enabled: true });
1107
- *
1108
- * // Custom green grid
1109
- * renderer.setGrid({ enabled: true, color: 'rgba(0, 255, 0, 0.5)' });
1110
- *
1111
- * // Disable grid
1112
- * renderer.setGrid({ enabled: false });
1113
- * ```
940
+ * Obtient la hauteur d'une cellule
1114
941
  */
1115
- setGrid(config: {
1116
- enabled: boolean;
1117
- color?: string;
1118
- lineWidth?: number;
1119
- }): void;
942
+ getCellHeight(): number;
1120
943
  /**
1121
- * Check if grid is currently enabled
944
+ * Get current scaling factor (for pixel-perfect modes)
945
+ * Returns 1 if scalingMode is None or not using ImageFont
1122
946
  */
1123
- isGridEnabled(): boolean;
947
+ getCurrentScale(): number;
1124
948
  /**
1125
- * Enable or configure ambient effect
1126
- *
1127
- * Ambient effect creates a blurred glow around the terminal canvas,
1128
- * filling the unused space with colors from the terminal content.
1129
- *
1130
- * @param config - true to enable with defaults, false to disable,
1131
- * or object with blur and scale settings
1132
- *
1133
- * @example
1134
- * ```typescript
1135
- * // Enable with defaults (blur: 30px, scale: 1.3)
1136
- * renderer.setAmbientEffect(true);
1137
- *
1138
- * // Disable
1139
- * renderer.setAmbientEffect(false);
1140
- *
1141
- * // Custom settings
1142
- * renderer.setAmbientEffect({ blur: 50, scale: 1.5 });
1143
- * ```
949
+ * Get scaling mode
1144
950
  */
1145
- setAmbientEffect(config: boolean | {
1146
- blur?: number;
1147
- scale?: number;
1148
- }): void;
951
+ getScalingMode(): ScalingMode;
1149
952
  /**
1150
- * Create the ambient effect canvas element (called lazily if needed)
953
+ * Obtient les décalages de centrage du terminal
1151
954
  */
1152
- private createAmbientEffectCanvas;
955
+ getOffsets(): {
956
+ offsetX: number;
957
+ offsetY: number;
958
+ };
1153
959
  /**
1154
- * Check if ambient effect is enabled
960
+ * Active ou désactive la grille de débogage
961
+ * @param show - true pour afficher la grille, false pour la masquer
1155
962
  */
1156
- isAmbientEffectEnabled(): boolean;
963
+ setDebugGrid(show: boolean): void;
1157
964
  /**
1158
- * Get current ambient effect configuration
965
+ * Change la couleur de fond du canvas
966
+ * @param color - Couleur CSS (ex: "#000000", "rgba(0,0,0,0.5)") ou null pour transparent
1159
967
  */
1160
- getAmbientEffectConfig(): {
1161
- enabled: boolean;
1162
- blur: number;
1163
- scale: number;
1164
- };
968
+ setCanvasBackgroundColor(color: string | null): void;
1165
969
  /**
1166
- * Get number of columns (IRenderer interface)
1167
- *
1168
- * @returns Current number of columns
1169
- *
1170
- * @example
1171
- * ```typescript
1172
- * const cols = renderer.getCols(); // 80
1173
- * ```
970
+ * Obtient la couleur de fond actuelle du canvas
971
+ * @returns La couleur de fond ou null si transparent
1174
972
  */
1175
- getCols(): number;
973
+ getCanvasBackgroundColor(): string | null;
1176
974
  /**
1177
- * Get number of rows (IRenderer interface)
1178
- *
1179
- * @returns Current number of rows
1180
- *
1181
- * @example
1182
- * ```typescript
1183
- * const rows = renderer.getRows(); // 25
1184
- * ```
975
+ * Active le mode grille fixe avec le nombre de colonnes/lignes spécifié
976
+ * Les cellules s'adapteront en taille pour maintenir les dimensions demandées
977
+ * @param cols - Nombre de colonnes fixe
978
+ * @param rows - Nombre de lignes fixe
979
+ * @param aspectRatio - Ratio largeur/hauteur de cellule (optionnel, défaut: 10/14)
1185
980
  */
1186
- getRows(): number;
981
+ setFixedGrid(cols: number, rows: number, aspectRatio?: number): void;
1187
982
  /**
1188
- * Check if renderer is ready (IRenderer interface)
1189
- *
1190
- * Returns true when bitmap font, atlas texture, and shader program are initialized.
1191
- *
1192
- * @returns true if ready to render, false otherwise
1193
- *
1194
- * @example
1195
- * ```typescript
1196
- * if (renderer.isReady()) {
1197
- * renderer.renderDisplayData(data);
1198
- * }
1199
- * ```
983
+ * Désactive le mode grille fixe et revient au mode adaptatif
984
+ * @param cellWidth - Largeur de cellule en pixels (optionnel)
985
+ * @param cellHeight - Hauteur de cellule en pixels (optionnel)
1200
986
  */
1201
- isReady(): boolean;
987
+ setAdaptiveGrid(cellWidth?: number, cellHeight?: number): void;
1202
988
  /**
1203
- * Destroy/cleanup resources (IRenderer interface)
1204
- *
1205
- * Destroys WebGL resources (textures, buffers), disconnects ResizeObserver,
1206
- * and removes canvases from DOM. Call this before removing the renderer.
1207
- *
1208
- * @example
1209
- * ```typescript
1210
- * renderer.destroy();
1211
- * renderer = null;
1212
- * ```
989
+ * Vérifie si le terminal est en mode grille fixe
1213
990
  */
1214
- destroy(): void;
991
+ isFixedGridMode(): boolean;
1215
992
  /**
1216
- * Cleanup resources
993
+ * Définit la couleur de la grille de débogage
994
+ * @param color - Couleur CSS (ex: "rgba(255, 0, 0, 0.3)" ou "#ff0000")
1217
995
  */
1218
- dispose(): void;
1219
- }
1220
-
1221
- /**
1222
- * Police bitmap matricielle
1223
- * Map qui associe un code de caractère (charCode) à une représentation bitmap
1224
- */
1225
- type BitmapFont = Map<number, Uint8Array>;
1226
- /**
1227
- * Atlas à une résolution spécifique
1228
- */
1229
- interface AtlasResolution {
1230
- canvas: HTMLCanvasElement;
1231
- ctx: CanvasRenderingContext2D;
1232
- scale: number;
1233
- charWidth: number;
1234
- charHeight: number;
1235
- }
1236
- /**
1237
- * Classe pour générer et gérer un atlas de police bitmap multi-résolution
1238
- * Convertit une police matricielle (bits) en plusieurs textures canvas à différentes échelles
1239
- * pour un rendu ultra-rapide avec qualité optimale quelque soit le zoom
1240
- *
1241
- * Utilise un cache LRU de glyphes colorés pour éviter la re-colorisation
1242
- */
1243
- declare class BitmapFontAtlas {
1244
- private atlases;
1245
- private charMap;
1246
- private baseCharWidth;
1247
- private baseCharHeight;
1248
- private baseCellWidth;
1249
- private baseCellHeight;
1250
- private atlasColumns;
1251
- private font;
1252
- private readonly SCALES;
1253
- private colorCache;
1254
- private readonly MAX_CACHE_SIZE;
996
+ setDebugGridColor(color: string): void;
1255
997
  /**
1256
- * Construit un atlas de police bitmap multi-résolution
1257
- * @param font La police bitmap source
1258
- * @param charWidth Largeur de base d'un caractère en pixels (taille du glyphe dans l'atlas)
1259
- * @param charHeight Hauteur de base d'un caractère en pixels (taille du glyphe dans l'atlas)
1260
- * @param cellWidth Largeur de base d'une cellule en pixels (peut être > charWidth pour l'espacement)
1261
- * @param cellHeight Hauteur de base d'une cellule en pixels (peut être > charHeight pour l'espacement)
998
+ * Vérifie si la grille de débogage est activée
1262
999
  */
1263
- constructor(font: BitmapFont, charWidth: number, charHeight: number, cellWidth?: number, cellHeight?: number); /**
1264
- * Génère les 4 atlas à différentes résolutions (1x, 2x, 4x, 8x)
1265
- * Très rapide: ~4-8ms pour 256 caractères × 4 résolutions
1000
+ isDebugGridEnabled(): boolean;
1001
+ /**
1002
+ * Configure une police image (atlas PNG)
1003
+ * @param imageData - Données PNG brutes
1004
+ * @param glyphWidth - Largeur du glyphe en pixels
1005
+ * @param glyphHeight - Hauteur du glyphe en pixels
1006
+ * @param cellWidth - Largeur de la cellule en pixels
1007
+ * @param cellHeight - Hauteur de la cellule en pixels
1008
+ * @param atlasBlocks - Nombre de blocs de 256 caractères (1, 4, ou 16)
1266
1009
  */
1267
- private generateAtlases;
1010
+ setImageFont(imageData: Uint8Array, glyphWidth: number, glyphHeight: number, cellWidth: number, cellHeight: number, atlasBlocks: AtlasBlocks): Promise<void>;
1268
1011
  /**
1269
- * Récupère ou crée un atlas pour une échelle donnée
1012
+ * Initialise la structure pour une police progressive
1270
1013
  */
1271
- private getOrCreateAtlas;
1014
+ setImageFontStructure(glyphWidth: number, glyphHeight: number, cellWidth: number, cellHeight: number, atlasBlocks: AtlasBlocks): Promise<void>;
1272
1015
  /**
1273
- * Rend un caractère bitmap dans un atlas à une résolution donnée
1274
- * Utilise fillRect pour un rendu ultra-rapide
1016
+ * Ajoute un bloc d'image à la police courante
1275
1017
  */
1276
- private renderBitmapToAtlas;
1018
+ setImageFontBlock(blockIndex: number, data: Uint8Array): Promise<void>;
1277
1019
  /**
1278
- * Dessine un caractère en utilisant le cache de glyphes colorés
1279
- * Ultra-rapide: 1 seul drawImage() par caractère
1280
- * Utilise ImageData pour coloriser + Canvas cache pour éviter la re-colorisation
1020
+ * Set color palette (IRenderer contract).
1021
+ * Called by ClientRuntime when Core palette changes.
1281
1022
  *
1282
- * @param ctx - Contexte de destination
1283
- * @param charCode - Code du caractère à dessiner
1284
- * @param x - Position X de destination (coin de la cellule)
1285
- * @param y - Position Y de destination (coin de la cellule)
1286
- * @param width - Largeur de la cellule de destination
1287
- * @param height - Hauteur de la cellule de destination
1288
- * @param color - Couleur du caractère (format CSS)
1023
+ * @param palette - Array of 256 RGBA colors
1289
1024
  */
1290
- drawChar(ctx: CanvasRenderingContext2D, charCode: number, x: number, y: number, width: number, height: number, color: string): void;
1025
+ setPalette(palette: RGBColor[]): void;
1291
1026
  /**
1292
- * Crée un glyphe colorisé à partir de l'atlas blanc
1293
- * Utilise ImageData pour une colorisation ultra-rapide
1027
+ * Render display data (IRenderer contract).
1028
+ * Converts RenderState from Core to cell-based rendering.
1029
+ *
1030
+ * @param display - Display data with palette indices
1294
1031
  */
1295
- private createColoredGlyph;
1296
1032
  /**
1297
- * Convertit une couleur hex en RGB
1033
+ * Helper: Convert palette index to CSS color
1298
1034
  */
1299
- private hexToRgb;
1035
+ private convertColor;
1300
1036
  /**
1301
- * Élimine les entrées les moins récemment utilisées du cache (LRU)
1037
+ * Helper: Render a specific set of cells (one pass or full display)
1302
1038
  */
1303
- private evictLRU;
1039
+ private renderDirect;
1040
+ renderDisplayData(display: RenderState): void;
1304
1041
  /**
1305
- * Retourne le canvas d'atlas pour une résolution donnée (pour débogage/visualisation)
1306
- * Par défaut retourne l'atlas 1x
1042
+ * Check if renderer is ready to render (IRenderer contract).
1043
+ * Canvas 2D is always ready immediately (no async initialization).
1044
+ *
1045
+ * @returns Always true for Canvas 2D
1307
1046
  */
1308
- getAtlasCanvas(scale?: number): HTMLCanvasElement | undefined;
1047
+ isReady(): boolean;
1309
1048
  /**
1310
- * Retourne tous les atlas disponibles
1049
+ * Get width in columns (IRenderer contract).
1311
1050
  */
1312
- getAllAtlases(): Map<number, AtlasResolution>;
1051
+ getCols(): number;
1313
1052
  /**
1314
- * Retourne les dimensions de base d'un caractère
1053
+ * Get height in rows (IRenderer contract).
1315
1054
  */
1316
- getCharDimensions(): {
1317
- width: number;
1318
- height: number;
1319
- };
1055
+ getRows(): number;
1320
1056
  /**
1321
- * Retourne le nombre de caractères dans l'atlas
1057
+ * Resize renderer dimensions (IRenderer contract).
1058
+ *
1059
+ * @param cols - New width in columns
1060
+ * @param rows - New height in rows
1322
1061
  */
1323
- getCharCount(): number;
1062
+ resize(cols: number, rows: number): void;
1324
1063
  /**
1325
- * Vérifie si un caractère existe dans l'atlas
1064
+ * Set scaling mode for pixel-perfect rendering
1065
+ *
1066
+ * @param mode - ScalingMode enum value:
1067
+ * - ScalingMode.None: Fill space, may have sub-pixel artifacts
1068
+ * - ScalingMode.Eighth: Snap to 0.125 increments (1.0, 1.125, 1.25...)
1069
+ * - ScalingMode.Quarter: Snap to 0.25 increments (1.0, 1.25, 1.5...)
1070
+ * - ScalingMode.Half: Snap to 0.5 increments (1.0, 1.5, 2.0...)
1071
+ * - ScalingMode.Integer: Crisp pixels, may waste space (1x, 2x, 3x...)
1072
+ * - ScalingMode.Responsive: No CSS scaling, cols/rows adapt to space
1326
1073
  */
1327
- hasChar(charCode: number): boolean;
1074
+ setScalingMode(mode: ScalingMode): void;
1328
1075
  /**
1329
- * Retourne les dimensions d'un atlas à une résolution donnée
1076
+ * Set cell dimensions in pixels (for Responsive mode)
1077
+ *
1078
+ * Changes the native pixel size of each character cell.
1079
+ * This will trigger a canvas resize and re-render.
1080
+ *
1081
+ * @param cellWidth - Cell width in pixels (1-255)
1082
+ * @param cellHeight - Cell height in pixels (1-255)
1330
1083
  */
1331
- getAtlasDimensions(scale?: number): {
1332
- width: number;
1333
- height: number;
1334
- } | undefined;
1084
+ setCellSize(cellWidth: number, cellHeight: number): void;
1335
1085
  /**
1336
- * Exporte un atlas en Data URL (pour débogage)
1337
- * Permet de visualiser l'atlas ou de le sauvegarder
1086
+ * Get current cell size
1338
1087
  */
1339
- toDataURL(scale?: number, type?: string): string | undefined;
1088
+ getCellSize(): {
1089
+ cellWidth: number;
1090
+ cellHeight: number;
1091
+ };
1340
1092
  /**
1341
- * Retourne les statistiques du cache de glyphes colorés
1093
+ * Get the available size from the parent container.
1094
+ * This is the actual pixel space available for rendering.
1095
+ * Useful in Responsive mode to calculate how many cells can fit.
1096
+ *
1097
+ * @returns Object with width and height in pixels
1342
1098
  */
1343
- getCacheStats(): {
1344
- size: number;
1345
- maxSize: number;
1346
- hitRate?: number;
1099
+ getAvailableSize(): {
1100
+ width: number;
1101
+ height: number;
1347
1102
  };
1348
1103
  /**
1349
- * Vide le cache de glyphes colorés
1104
+ * Get the maximum number of cells this renderer can handle
1105
+ *
1106
+ * Canvas 2D has very generous limits compared to WebGL.
1107
+ * The main constraint is memory for the ImageData buffer.
1108
+ *
1109
+ * @returns Maximum cells supported (256×256 = 65536 for compatibility)
1350
1110
  */
1351
- clearCache(): void;
1111
+ getMaxCells(): number;
1352
1112
  /**
1353
- * Libère les ressources
1113
+ * Détruit le terminal et nettoie les ressources
1354
1114
  */
1355
1115
  destroy(): void;
1356
1116
  }
@@ -1394,7 +1154,29 @@ declare class ImageFontAtlas {
1394
1154
  private readonly MAX_CACHE_SIZE;
1395
1155
  constructor(config: ImageFontAtlasConfig);
1396
1156
  /**
1397
- * Load atlas from PNG binary data
1157
+ * Get the underlying canvas method
1158
+ */
1159
+ getCanvas(): HTMLCanvasElement | null;
1160
+ /**
1161
+ * Get glyph width
1162
+ */
1163
+ getGlyphWidth(): number;
1164
+ /**
1165
+ * Get glyph height
1166
+ */
1167
+ getGlyphHeight(): number;
1168
+ /**
1169
+ * Initialize empty atlas properties
1170
+ */
1171
+ prepare(): void;
1172
+ /**
1173
+ * Load a block into the atlas
1174
+ * @param blockIndex Block index (0-15)
1175
+ * @param pngData PNG data for the block
1176
+ */
1177
+ loadBlock(blockIndex: number, pngData: Uint8Array): Promise<void>;
1178
+ /**
1179
+ * Load atlas from PNG binary data (Legacy Monolithic)
1398
1180
  * @param pngData PNG image as Uint8Array
1399
1181
  * @returns Promise that resolves when atlas is loaded
1400
1182
  */
@@ -1988,5 +1770,5 @@ declare function createTestRenderState(width: number, height: number): RenderSta
1988
1770
 
1989
1771
  declare const version = "0.1.0";
1990
1772
 
1991
- export { AutoplayOverlay, BitmapFontAtlas, DEFAULT_PALETTE, GridOverlay, ImageFontAtlas, PostProcessOverlay, Terminal2D, TerminalANSI, TerminalGL, colorToPaletteIndex, createTestRenderState, getAtlasColumns, getCharGridPosition, getMaxCharCode, hexToRGB, paletteIndexToColor, rgbToHex, version };
1992
- export type { AtlasBlocks, AutoplayOverlayOptions, BitmapFont$1 as BitmapFont, FontType, ImageFontAtlasConfig, PostProcessOverlayOptions, RenderOptions, TerminalANSIOptions, TerminalCell, TerminalData, TerminalGLOptions, WebGLCompatibilityReport };
1773
+ export { AutoplayOverlay, DEFAULT_PALETTE, GridOverlay, ImageFontAtlas, PostProcessOverlay, Terminal2D, TerminalANSI, TerminalGL, colorToPaletteIndex, createTestRenderState, getAtlasColumns, getCharGridPosition, getMaxCharCode, hexToRGB, paletteIndexToColor, rgbToHex, version };
1774
+ export type { AtlasBlocks, AutoplayOverlayOptions, ImageFontAtlasConfig, PostProcessOverlayOptions, RenderOptions, TerminalANSIOptions, TerminalCell, TerminalData, TerminalGLOptions, WebGLCompatibilityReport };