@utsp/render
Version:
UTSP Render - Browser-based rendering engine for terminal graphics
1,142 lines (1,132 loc) • 37.3 kB
TypeScript
import { IRenderer, RGBColor, RenderState } from '@utsp/types';
export { IColorPalette, IRenderer, RenderState } from '@utsp/types';
/**
* Default color palette (VGA colors + extended)
* Maps palette index to CSS color string
*/
declare const DEFAULT_PALETTE: readonly string[];
/**
* Convert a color palette index to CSS color string
*/
declare function paletteIndexToColor(index: number, palette?: readonly string[]): string;
/**
* Convert CSS color string to palette index (finds closest match)
*/
declare function colorToPaletteIndex(color: string, palette?: readonly string[]): number;
/**
* Représente une cellule du terminal
*/
interface TerminalCell {
/** Le caractère à afficher */
char: string;
/** Couleur du caractère (format CSS) */
fgColor: string;
/** Couleur de fond de la cellule (format CSS) */
bgColor: string;
}
/**
* Données brutes pour définir le terminal en une fois
*/
interface TerminalData {
/** Largeur en cellules */
width: number;
/** Hauteur en cellules */
height: number;
/** Tableau de cellules (longueur = width * height) */
cells: Array<{
/** Code du caractère ou le caractère lui-même */
char: string;
/** Couleur du texte (format CSS) */
fgColor: string;
/** Couleur de fond (format CSS) */
bgColor: string;
}>;
}
/**
* Police bitmap matricielle
* Map qui associe un code de caractère (charCode) à une représentation bitmap 8x8
* Chaque Uint8Array contient 8 octets, un par ligne de pixels
*/
type BitmapFont$1 = Map<number, Uint8Array>;
/**
* Type de police à utiliser
*/
type FontType = {
type: 'web';
fontFamily: string;
fontSize: number;
} | {
type: 'bitmap';
font: BitmapFont$1;
charWidth: number;
charHeight: number;
};
/**
* Options pour la configuration du terminal
*/
interface RenderOptions {
/** Largeur d'une cellule en pixels (défaut: 10) - ignoré en mode fixedGrid */
cellWidth?: number;
/** Hauteur d'une cellule en pixels (défaut: 14) - ignoré en mode fixedGrid */
cellHeight?: number;
/** Taille de la police en pixels (défaut: 12) */
fontSize?: number;
/** Famille de police (défaut: "monospace") */
fontFamily?: string;
/** Couleur de texte par défaut (défaut: "#ffffff") */
defaultFgColor?: string;
/** Couleur de fond par défaut (défaut: "#000000") */
defaultBgColor?: string;
/** Couleur de fond du canvas lui-même (défaut: transparent). Si null ou undefined, le canvas sera transparent */
canvasBgColor?: string | null;
/** Afficher une grille de débogage (défaut: false) */
showDebugGrid?: boolean;
/** Couleur de la grille de débogage (défaut: "rgba(255, 0, 0, 0.3)") */
debugGridColor?: string;
/** Classes CSS additionnelles pour le canvas */
className?: string;
/** Style inline pour le canvas */
style?: Partial<CSSStyleDeclaration>;
/** Nombre de colonnes fixe (active le mode fixedGrid) */
fixedCols?: number;
/** Nombre de lignes fixe (active le mode fixedGrid) */
fixedRows?: number;
/** Ratio largeur/hauteur de cellule pour mode fixedGrid (défaut: 10/14 ≈ 0.714) */
cellAspectRatio?: number;
}
/**
* UTSP Render - Gère une grille de caractères avec couleurs
* Similaire à un terminal mais avec contrôle total de chaque cellule
*
* Implements IRenderer interface for compatibility with TerminalGL and dependency injection.
*/
declare class Terminal2D implements IRenderer {
private canvas;
private ctx;
private parentElement;
private cells;
private cols;
private rows;
private fontSize;
private fontFamily;
private defaultFgColor;
private defaultBgColor;
private canvasBgColor;
private cellWidth;
private cellHeight;
private offsetX;
private offsetY;
private fontType;
private bitmapFont?;
private bitmapAtlas?;
private bitmapCharWidth;
private bitmapCharHeight;
private showDebugGrid;
private debugGridColor;
private gridOverlay?;
private fixedGridMode;
private fixedCols?;
private fixedRows?;
private cellAspectRatio;
private resizeObserver?;
private imageDataBuffer?;
private useImageDataRendering;
private paletteCache?;
/**
* Crée une instance de UTSPRender
* @param parentDiv - L'élément HTML parent dans lequel créer le canvas
* @param options - Options de configuration du terminal
*/
constructor(parentDiv: HTMLElement, options?: RenderOptions);
/**
* Calcule le nombre de colonnes et de lignes en fonction de la taille du parent
* et centre le terminal dans le canvas
*/
private calculateGridSize;
/**
* Crée une grille vide avec les valeurs par défaut
*/
private createEmptyGrid;
/**
* Active le redimensionnement automatique
* Recalcule le nombre de colonnes/lignes quand le parent change de taille
*/
private enableAutoResize;
/**
* Définit le contenu d'une cellule
* @param col - Colonne (0-indexed)
* @param row - Ligne (0-indexed)
* @param char - Caractère à afficher
* @param fgColor - Couleur du texte (optionnel, utilise la valeur par défaut si non fourni)
* @param bgColor - Couleur de fond (optionnel, utilise la valeur par défaut si non fourni)
*/
setCell(col: number, row: number, char: string, fgColor?: string, bgColor?: string): void;
/**
* Récupère le contenu d'une cellule
* @param col - Colonne (0-indexed)
* @param row - Ligne (0-indexed)
*/
getCell(col: number, row: number): TerminalCell | null;
/**
* Écrit une chaîne de caractères à partir d'une position
* @param col - Colonne de départ
* @param row - Ligne
* @param text - Texte à écrire
* @param fgColor - Couleur du texte (optionnel)
* @param bgColor - Couleur de fond (optionnel)
*/
write(col: number, row: number, text: string, fgColor?: string, bgColor?: string): void;
/**
* Remplit une zone rectangulaire
* @param startCol - Colonne de départ
* @param startRow - Ligne de départ
* @param width - Largeur en cellules
* @param height - Hauteur en cellules
* @param char - Caractère de remplissage
* @param fgColor - Couleur du texte (optionnel)
* @param bgColor - Couleur de fond (optionnel)
*/
fillRect(startCol: number, startRow: number, width: number, height: number, char?: string, fgColor?: string, bgColor?: string): void;
/**
* Efface tout le terminal (remplit avec des espaces)
*/
clear(): void;
/**
* Définit tout le contenu du terminal à partir d'un tableau de données
* Le tableau doit contenir width * height éléments
* Les cellules sont lues ligne par ligne (row-major order)
*
* @param data - Données du terminal avec dimensions et cellules
* @throws Error si le tableau n'a pas la bonne taille
*
* @example
* terminal.setFromArray({
* width: 3,
* height: 2,
* cells: [
* { char: 'A', fgColor: '#ff0000', bgColor: '#000000' }, // (0,0)
* { char: 'B', fgColor: '#00ff00', bgColor: '#000000' }, // (1,0)
* { char: 'C', fgColor: '#0000ff', bgColor: '#000000' }, // (2,0)
* { char: 'D', fgColor: '#ffff00', bgColor: '#000000' }, // (0,1)
* { char: 'E', fgColor: '#ff00ff', bgColor: '#000000' }, // (1,1)
* { char: 'F', fgColor: '#00ffff', bgColor: '#000000' }, // (2,1)
* ]
* });
*/
setFromArray(data: TerminalData): void;
/**
* Rend la grille sur le canvas
*/
render(): void;
/**
* Rendu ultra-rapide avec ImageData (bitmap)
* ~10-20× plus rapide que fillRect en boucle
* Fonctionne avec scaling : buffer natif 8×8 puis drawImage() pour upscale
*/
private renderWithImageData;
/**
* Parse une couleur CSS en composantes RGBA
*/
private parseColorToRGB;
/**
* Rendu classique avec fillRect/fillText (compatible scaling, web fonts, etc.)
*/
private renderClassic;
/**
* Dessine un caractère en utilisant une police bitmap
*/
private drawBitmapChar;
/**
* Dessine une grille de débogage pour visualiser les cellules
*/
private drawDebugGrid;
/**
* Obtient le canvas HTML
*/
getCanvas(): HTMLCanvasElement;
/**
* Obtient le contexte 2D
*/
getContext(): CanvasRenderingContext2D;
/**
* Obtient les dimensions de la grille
*/
getDimensions(): {
cols: number;
rows: number;
};
/**
* Obtient les dimensions des cellules
*/
getCellDimensions(): {
cellWidth: number;
cellHeight: number;
};
/**
* Obtient la largeur d'une cellule
*/
getCellWidth(): number;
/**
* Obtient la hauteur d'une cellule
*/
getCellHeight(): number;
/**
* Obtient les décalages de centrage du terminal
*/
getOffsets(): {
offsetX: number;
offsetY: number;
};
/**
* Active ou désactive la grille de débogage
* @param show - true pour afficher la grille, false pour la masquer
*/
setDebugGrid(show: boolean): void;
/**
* Change la couleur de fond du canvas
* @param color - Couleur CSS (ex: "#000000", "rgba(0,0,0,0.5)") ou null pour transparent
*/
setCanvasBackgroundColor(color: string | null): void;
/**
* Obtient la couleur de fond actuelle du canvas
* @returns La couleur de fond ou null si transparent
*/
getCanvasBackgroundColor(): string | null;
/**
* Active le mode grille fixe avec le nombre de colonnes/lignes spécifié
* Les cellules s'adapteront en taille pour maintenir les dimensions demandées
* @param cols - Nombre de colonnes fixe
* @param rows - Nombre de lignes fixe
* @param aspectRatio - Ratio largeur/hauteur de cellule (optionnel, défaut: 10/14)
*/
setFixedGrid(cols: number, rows: number, aspectRatio?: number): void;
/**
* Désactive le mode grille fixe et revient au mode adaptatif
* @param cellWidth - Largeur de cellule en pixels (optionnel)
* @param cellHeight - Hauteur de cellule en pixels (optionnel)
*/
setAdaptiveGrid(cellWidth?: number, cellHeight?: number): void;
/**
* Vérifie si le terminal est en mode grille fixe
*/
isFixedGridMode(): boolean;
/**
* Définit la couleur de la grille de débogage
* @param color - Couleur CSS (ex: "rgba(255, 0, 0, 0.3)" ou "#ff0000")
*/
setDebugGridColor(color: string): void;
/**
* Vérifie si la grille de débogage est activée
*/
isDebugGridEnabled(): boolean;
/**
* Active ou désactive le rendu optimisé avec ImageData
* Uniquement disponible pour les polices bitmap à taille native (pas de scaling)
* Environ 10-20× plus rapide que le rendu classique, idéal pour les benchmarks
*
* @param enable - true pour activer, false pour désactiver
*/
setImageDataRendering(enable: boolean): void;
/**
* Vérifie si le rendu ImageData est activé
*/
isImageDataRenderingEnabled(): boolean;
/**
* Configure une police web (CSS)
* @param fontFamily - Nom de la police CSS (ex: "Courier New", "monospace")
* @param fontSize - Taille de la police en pixels (optionnel, garde la taille actuelle si non spécifié)
*/
setWebFont(fontFamily: string, fontSize?: number): void;
/**
* Configure une police bitmap matricielle
* @param font - Map contenant les définitions bitmap des caractères (charCode -> Uint8Array)
* @param charWidth - Largeur du glyphe en pixels (bitmap source)
* @param charHeight - Hauteur du glyphe en pixels (bitmap source)
* @param cellWidth - Largeur de la cellule de rendu en pixels
* @param cellHeight - Hauteur de la cellule de rendu en pixels
*/
setBitmapFont(font: BitmapFont$1, charWidth: number, charHeight: number, cellWidth: number, cellHeight: number): void;
/**
* Retourne le type de police actuellement utilisé
*/
getFontType(): 'web' | 'bitmap';
/**
* Retourne la police bitmap actuelle (si applicable)
*/
getBitmapFont(): BitmapFont$1 | undefined;
/**
* Retourne les dimensions de caractère bitmap (si applicable)
*/
getBitmapCharDimensions(): {
width: number;
height: number;
} | null;
/**
* Set color palette (IRenderer contract).
* Called by ClientRuntime when Core palette changes.
*
* @param palette - Array of 256 RGBA colors
*/
setPalette(palette: RGBColor[]): void;
/**
* Render display data (IRenderer contract).
* Converts RenderState from Core to cell-based rendering.
*
* @param display - Display data with palette indices
*/
renderDisplayData(display: RenderState): void;
/**
* Check if renderer is ready to render (IRenderer contract).
* Canvas 2D is always ready immediately (no async initialization).
*
* @returns Always true for Canvas 2D
*/
isReady(): boolean;
/**
* Get width in columns (IRenderer contract).
*/
getCols(): number;
/**
* Get height in rows (IRenderer contract).
*/
getRows(): number;
/**
* Resize renderer dimensions (IRenderer contract).
*
* @param cols - New width in columns
* @param rows - New height in rows
*/
resize(cols: number, rows: number): void;
/**
* Détruit le terminal et nettoie les ressources
*/
destroy(): void;
}
/**
* WebGL compatibility report
*/
interface WebGLCompatibilityReport {
/** WebGL 1.0 support */
webgl1: boolean;
/** OES_element_index_uint extension (Uint32 indices) */
uint32Indices: boolean;
/** Maximum texture size */
maxTextureSize: number;
/** Maximum viewport dimensions */
maxViewportDims: [number, number];
/** Maximum terminal size with Uint16 indices (cols × rows) */
maxCellsUint16: number;
/** Maximum terminal size with Uint32 indices (cols × rows) */
maxCellsUint32: number;
/** Recommended maximum terminal size for this device */
recommendedMaxCells: number;
/** Warnings (empty if fully compatible) */
warnings: string[];
/** Errors (empty if compatible) */
errors: string[];
}
/**
* Options for WebGL terminal configuration
*/
interface TerminalGLOptions {
/** Number of columns (required) */
cols: number;
/** Number of rows (required) */
rows: number;
/** Character width in pixels */
charWidth?: number;
/** Character height in pixels */
charHeight?: number;
/** Canvas background color (CSS format, for gl.clearColor) */
canvasBgColor?: string | null;
/** Show cell delimitation grid (debug) */
showGrid?: boolean;
/** Force Uint16 indices (for compatibility testing, auto-detected by default) */
forceUint16?: boolean;
}
/**
* Simplified terminal using WebGL for basic rendering
* Only supports bitmap fonts with atlas
* Implements IRenderer interface for dependency injection with core
*
* ✨ SIMPLIFIED VERSION: Only backgrounds + colored characters
*/
declare class TerminalGL implements IRenderer {
/**
* Check WebGL 1.0 compatibility and device capabilities
*
* Tests all required WebGL features and returns a detailed compatibility report.
* Use this before creating a TerminalGL instance to ensure device support.
*
* @returns Detailed compatibility report with warnings and errors
*
* @example
* ```typescript
* const report = TerminalGL.checkCompatibility();
* if (report.errors.length > 0) {
* console.error('WebGL not supported:', report.errors);
* // Fallback to Canvas 2D renderer
* } else if (report.warnings.length > 0) {
* console.warn('WebGL limitations:', report.warnings);
* }
* console.log(`Max terminal size: ${report.recommendedMaxCells} cells`);
* ```
*/
static checkCompatibility(): WebGLCompatibilityReport;
private canvas;
private gl;
private parentElement;
private containerDiv;
private cols;
private rows;
private charWidth;
private charHeight;
private cellWidth;
private cellHeight;
private glyphOffsetX;
private glyphOffsetY;
private canvasBgColor;
private showGrid;
private supportsUint32Indices;
private useUint16Indices;
private gridOverlay?;
private bitmapFont?;
private atlasTexture;
private atlasCanvas?;
private atlasColumns;
private paletteTexture;
private program;
private positionBuffer;
private texCoordBuffer;
private colorIndexBuffer;
private indexBuffer;
private aPosition?;
private aTexCoord?;
private aColorIndex?;
private uResolution;
private uTexture;
private uPalette;
private resizeObserver?;
private charCodeToAtlasIndex;
private atlasUVs;
private cachedAtlasWidth;
private cachedAtlasHeight;
private paletteFloat;
private maxCells;
private renderPositions;
private renderTexCoords;
private renderColorIndices;
private renderIndices;
private cachedResolution;
private cachedTextureUnit;
private cachedPaletteUnit;
private cachedTextureUniform;
private cachedPaletteUniform;
private paletteHash;
private staticPositionsInitialized;
private vaoExtension;
private vao;
private instancedExtension;
private useInstancing;
private instanceDataBuffer;
private instanceData;
private templateQuadPositions;
private templateQuadIndices;
constructor(parentDiv: HTMLDivElement, options: TerminalGLOptions);
/**
* 🚀 INSTANCING: Initialize template quad and instance buffers
* Called once at init if instancing is supported
*/
private initInstancedBuffers;
/**
* 🚀 OPTIMIZATION: Initialize pre-allocated buffers for rendering
* Avoids allocations each frame
* Uses Uint16 or Uint32 indices based on device support
*/
private initRenderBuffers;
/**
* 🚀 MEGA OPTIMIZATION: Pre-compute static positions for ALL possible quads
* Called only once after font load, or after resize
* Positions never change during rendering - only colors and UVs change!
*/
private precomputeStaticPositions;
/**
* Initialize WebGL (shaders, buffers, etc.)
*/
private initWebGL;
/**
* Compile a shader
*/
private compileShader;
/**
* 🔲 Initialize 2D canvas overlay for debug grid
* Performance: 2D canvas drawn only once, 0ms per frame
*/
private initGridOverlay;
/**
* 🔲 Draw grid lines on 2D canvas overlay
* Called only once at init and resize
*/
private updateGridOverlay;
/**
* Configure bitmap font and generate atlas
*
* ⚠️ **INTERNAL USE ONLY** - This method is called automatically by ClientRuntime's
* event system when Core.loadBitmapFontById() is called. Do NOT call this directly
* unless you're implementing a custom runtime.
*
* Event flow: Core.loadBitmapFontById() → Core.onBitmapFontChangedCallback
* → ClientRuntime.onCoreBitmapFontChanged() → RendererManager.setBitmapFont()
*
* @param font - Bitmap font mapping (charCode → byte array)
* @param charWidth - Width of each character in pixels
* @param charHeight - Height of each character in pixels
* @param cellWidth - Width of each cell in pixels
* @param cellHeight - Height of each cell in pixels
* @throws {Error} If atlas generation fails
*
* @example
* ```typescript
* // ❌ DON'T: Call setBitmapFont directly
* renderer.setBitmapFont(font, 8, 16, 8, 16);
*
* // ✅ DO: Use Core's loadBitmapFontById (triggers event automatically)
* core.loadBitmapFontById(1, {
* charWidth: 8, charHeight: 16,
* cellWidth: 8, cellHeight: 16,
* glyphs: new Map([[65, new Uint8Array([...])]])
* });
* ```
*/
setBitmapFont(font: BitmapFont$1, charWidth: number, charHeight: number, cellWidth: number, cellHeight: number): void;
/**
* Generate texture atlas from bitmap font
*/
private generateAtlas;
/**
* 🚀 OPTIMIZED: Build charCode → atlas index using direct array lookup
*/
private buildCharCodeMap;
/**
* 🚀 MEGA OPTIMIZATION: Pre-compute ALL atlas UVs
* Called once after atlas generation - UVs never change!
* Eliminates per-frame division and modulo operations
*/
private precomputeAtlasUVs;
/**
* Create WebGL texture from atlas
*/
private createAtlasTexture;
/**
* Clear entire terminal
*
* Clears the WebGL canvas. Note: Actual terminal content clearing is handled
* by Core's RenderState, not by this renderer.
*
* @example
* ```typescript
* renderer.clear();
* ```
*/
clear(): void;
/**
* Parse CSS color to normalized RGBA (0-1)
*/
private parseColor;
/**
* Configure ResizeObserver to adapt canvas
*/
private setupResizeObserver;
/**
* Update canvas display size
*
* 🎯 PIXEL PERFECT: Forces display dimensions to be exact multiples of cell size
* to avoid sub-pixel rendering artifacts (like Terminal2D does).
*
* Strategy: Keep canvas internal resolution fixed at base size (cols × cellWidth),
* and use CSS scaling with image-rendering: pixelated for integer upscaling.
*/
private updateCanvasSize;
/**
* Set color palette and upload to GPU
*
* ⚠️ IMPORTANT: This is the ONLY way to update the palette.
* Typically called automatically by ClientRuntime via Core.onPaletteChanged() event.
* Do NOT call this directly unless you know what you're doing.
*
* @param palette - Array of 256 RGB colors
*
* @example
* ```typescript
* // ✅ Normal usage: Core handles this automatically
* core.loadPalette([...]);
* // → Core emits event
* // → ClientRuntime receives event
* // → renderer.setPalette() called automatically
*
* // ⚠️ Manual usage (advanced):
* const myPalette: RGBColor[] = [
* { r: 0, g: 0, b: 0, a: 255 }, // Color 0: Black
* { r: 255, g: 0, b: 0, a: 255 }, // Color 1: Red
* // ... 254 more colors
* ];
* renderer.setPalette(myPalette);
* ```
*/
setPalette(palette: RGBColor[]): void;
/**
* 🚀 GPU OPTIMIZATION: Upload palette to GPU texture (256×1 RGBA)
*/
private updatePaletteTexture;
/**
* Render display data from core engine (ULTRA-OPTIMIZED)
*
* Bypasses internal cells and renders directly from RenderState for maximum performance.
* Uses GPU palette texture lookup to minimize CPU→GPU bandwidth (4× reduction).
*
* @param data - Render state containing cells, dimensions, and palette
*
* @example
* ```typescript
* const renderState: RenderState = {
* cells: [...],
* width: 80,
* height: 25,
* palette: [...]
* };
* renderer.renderDisplayData(renderState);
* ```
*/
renderDisplayData(data: RenderState): void;
/**
* 🚀 NEW METHOD: Render directly from RenderState
* Bypass this.cells for maximum performance
*/
private renderDirect;
/**
* 🚀 INSTANCED RENDERING: 1 draw call for entire terminal
* MASSIVE performance boost - reduces draw calls from cols×rows×2 to just 1!
*/
private renderInstanced;
/**
* 🚀 ULTRA-OPTIMIZED: Update ONLY dynamic data (colors + UVs)
* Positions are static and pre-computed - only updated on resize!
* This is a MASSIVE performance win - positions never change during normal rendering
*/
private renderDirectBuffers;
/**
* Resize the terminal dimensions
*
* Changes the number of columns and rows. Preserves existing cell content
* where possible. Reallocates render buffers if needed.
*
* @param cols - New number of columns (must be positive integer)
* @param rows - New number of rows (must be positive integer)
*
* @example
* ```typescript
* renderer.resize(120, 40); // Resize to 120×40
* ```
*/
resize(cols: number, rows: number): void;
/**
* Get canvas element
*/
getCanvas(): HTMLCanvasElement;
/**
* Get grid dimensions
*/
getGridSize(): {
cols: number;
rows: number;
};
/**
* Get cell width
*/
getCellWidth(): number;
/**
* Get cell height
*/
getCellHeight(): number;
/**
* Get number of columns (IRenderer interface)
*
* @returns Current number of columns
*
* @example
* ```typescript
* const cols = renderer.getCols(); // 80
* ```
*/
getCols(): number;
/**
* Get number of rows (IRenderer interface)
*
* @returns Current number of rows
*
* @example
* ```typescript
* const rows = renderer.getRows(); // 25
* ```
*/
getRows(): number;
/**
* Check if renderer is ready (IRenderer interface)
*
* Returns true when bitmap font, atlas texture, and shader program are initialized.
*
* @returns true if ready to render, false otherwise
*
* @example
* ```typescript
* if (renderer.isReady()) {
* renderer.renderDisplayData(data);
* }
* ```
*/
isReady(): boolean;
/**
* Destroy/cleanup resources (IRenderer interface)
*
* Destroys WebGL resources (textures, buffers), disconnects ResizeObserver,
* and removes canvases from DOM. Call this before removing the renderer.
*
* @example
* ```typescript
* renderer.destroy();
* renderer = null;
* ```
*/
destroy(): void;
/**
* Cleanup resources
*/
dispose(): void;
}
/**
* Police bitmap matricielle
* Map qui associe un code de caractère (charCode) à une représentation bitmap
*/
type BitmapFont = Map<number, Uint8Array>;
/**
* Atlas à une résolution spécifique
*/
interface AtlasResolution {
canvas: HTMLCanvasElement;
ctx: CanvasRenderingContext2D;
scale: number;
charWidth: number;
charHeight: number;
}
/**
* Classe pour générer et gérer un atlas de police bitmap multi-résolution
* Convertit une police matricielle (bits) en plusieurs textures canvas à différentes échelles
* pour un rendu ultra-rapide avec qualité optimale quelque soit le zoom
*
* Utilise un cache LRU de glyphes colorés pour éviter la re-colorisation
*/
declare class BitmapFontAtlas {
private atlases;
private charMap;
private baseCharWidth;
private baseCharHeight;
private baseCellWidth;
private baseCellHeight;
private atlasColumns;
private font;
private readonly SCALES;
private colorCache;
private readonly MAX_CACHE_SIZE;
/**
* Construit un atlas de police bitmap multi-résolution
* @param font La police bitmap source
* @param charWidth Largeur de base d'un caractère en pixels (taille du glyphe dans l'atlas)
* @param charHeight Hauteur de base d'un caractère en pixels (taille du glyphe dans l'atlas)
* @param cellWidth Largeur de base d'une cellule en pixels (peut être > charWidth pour l'espacement)
* @param cellHeight Hauteur de base d'une cellule en pixels (peut être > charHeight pour l'espacement)
*/
constructor(font: BitmapFont, charWidth: number, charHeight: number, cellWidth?: number, cellHeight?: number); /**
* Génère les 4 atlas à différentes résolutions (1x, 2x, 4x, 8x)
* Très rapide: ~4-8ms pour 256 caractères × 4 résolutions
*/
private generateAtlases;
/**
* Récupère ou crée un atlas pour une échelle donnée
*/
private getOrCreateAtlas;
/**
* Rend un caractère bitmap dans un atlas à une résolution donnée
* Utilise fillRect pour un rendu ultra-rapide
*/
private renderBitmapToAtlas;
/**
* Dessine un caractère en utilisant le cache de glyphes colorés
* Ultra-rapide: 1 seul drawImage() par caractère
* Utilise ImageData pour coloriser + Canvas cache pour éviter la re-colorisation
*
* @param ctx - Contexte de destination
* @param charCode - Code du caractère à dessiner
* @param x - Position X de destination (coin de la cellule)
* @param y - Position Y de destination (coin de la cellule)
* @param width - Largeur de la cellule de destination
* @param height - Hauteur de la cellule de destination
* @param color - Couleur du caractère (format CSS)
*/
drawChar(ctx: CanvasRenderingContext2D, charCode: number, x: number, y: number, width: number, height: number, color: string): void;
/**
* Crée un glyphe colorisé à partir de l'atlas blanc
* Utilise ImageData pour une colorisation ultra-rapide
*/
private createColoredGlyph;
/**
* Convertit une couleur hex en RGB
*/
private hexToRgb;
/**
* Élimine les entrées les moins récemment utilisées du cache (LRU)
*/
private evictLRU;
/**
* Retourne le canvas d'atlas pour une résolution donnée (pour débogage/visualisation)
* Par défaut retourne l'atlas 1x
*/
getAtlasCanvas(scale?: number): HTMLCanvasElement | undefined;
/**
* Retourne tous les atlas disponibles
*/
getAllAtlases(): Map<number, AtlasResolution>;
/**
* Retourne les dimensions de base d'un caractère
*/
getCharDimensions(): {
width: number;
height: number;
};
/**
* Retourne le nombre de caractères dans l'atlas
*/
getCharCount(): number;
/**
* Vérifie si un caractère existe dans l'atlas
*/
hasChar(charCode: number): boolean;
/**
* Retourne les dimensions d'un atlas à une résolution donnée
*/
getAtlasDimensions(scale?: number): {
width: number;
height: number;
} | undefined;
/**
* Exporte un atlas en Data URL (pour débogage)
* Permet de visualiser l'atlas ou de le sauvegarder
*/
toDataURL(scale?: number, type?: string): string | undefined;
/**
* Retourne les statistiques du cache de glyphes colorés
*/
getCacheStats(): {
size: number;
maxSize: number;
hitRate?: number;
};
/**
* Vide le cache de glyphes colorés
*/
clearCache(): void;
/**
* Libère les ressources
*/
destroy(): void;
}
/**
* 🔲 GridOverlay - Classe réutilisable pour gérer le canvas de grille de débogage
*
* Gère un canvas 2D superposé qui affiche une grille de cellules.
* Au lieu de simples lignes, dessine un cadre fin à l'intérieur de chaque cellule
* pour une meilleure visualisation.
*
* @example
* ```typescript
* const grid = new GridOverlay(containerElement);
* grid.setDimensions(80, 24, 10, 16);
* grid.render();
* ```
*/
declare class GridOverlay {
private canvas;
private ctx;
private container;
private cols;
private rows;
private cellWidth;
private cellHeight;
private offsetX;
private offsetY;
private strokeColor;
private lineWidth;
private innerPadding;
/**
* Crée une nouvelle overlay de grille
* @param container - Élément parent qui contiendra le canvas
* @param options - Options de configuration
*/
constructor(container: HTMLElement, options?: {
strokeColor?: string;
lineWidth?: number;
innerPadding?: number;
zIndex?: number;
});
/**
* Configure les dimensions de la grille
* @param cols - Nombre de colonnes
* @param rows - Nombre de lignes
* @param cellWidth - Largeur d'une cellule en pixels
* @param cellHeight - Hauteur d'une cellule en pixels
* @param offsetX - Décalage horizontal (optionnel)
* @param offsetY - Décalage vertical (optionnel)
*/
setDimensions(cols: number, rows: number, cellWidth: number, cellHeight: number, offsetX?: number, offsetY?: number): void;
/**
* Configure la taille physique du canvas
* Doit correspondre à la taille d'affichage du canvas principal
* @param displayWidth - Largeur d'affichage en pixels
* @param displayHeight - Hauteur d'affichage en pixels
*/
setCanvasSize(displayWidth: number, displayHeight: number): void;
/**
* Configure les options visuelles
* @param options - Options de rendu
*/
setStyle(options: {
strokeColor?: string;
lineWidth?: number;
innerPadding?: number;
}): void;
/**
* Dessine la grille avec des lignes fines continues
*
* Dessine une grille continue sans écarts entre les cellules.
* Les lignes sont décalées vers l'intérieur de la cellule (innerPadding)
* pour créer un effet visuel élégant tout en gardant la grille continue.
*/
render(): void;
/**
* Met à jour et redessine la grille avec de nouvelles dimensions
* Méthode pratique qui combine setDimensions, setCanvasSize et render
*
* @param cols - Nombre de colonnes
* @param rows - Nombre de lignes
* @param cellWidth - Largeur d'une cellule
* @param cellHeight - Hauteur d'une cellule
* @param displayWidth - Largeur d'affichage du canvas
* @param displayHeight - Hauteur d'affichage du canvas
* @param offsetX - Décalage horizontal (optionnel)
* @param offsetY - Décalage vertical (optionnel)
*/
update(cols: number, rows: number, cellWidth: number, cellHeight: number, displayWidth: number, displayHeight: number, offsetX?: number, offsetY?: number): void;
/**
* Affiche ou cache la grille
* @param visible - true pour afficher, false pour cacher
*/
setVisible(visible: boolean): void;
/**
* Supprime le canvas de grille du DOM
*/
destroy(): void;
/**
* Retourne le canvas HTML
*/
getCanvas(): HTMLCanvasElement;
}
/**
* AutoplayOverlay - Displays a play button overlay that must be clicked to start the application
*
* This is useful for:
* - Audio APIs that require user interaction before playing
* - Preventing automatic resource consumption
* - Better UX on mobile where autoplay may not be desired
*
* @example
* ```typescript
* const overlay = new AutoplayOverlay(container, {
* buttonText: 'Click to Start',
* onStart: () => {
* // Application starts here
* }
* });
*
* // To programmatically start (e.g., if autoplay is enabled):
* overlay.start();
*
* // Cleanup:
* overlay.destroy();
* ```
*/
interface AutoplayOverlayOptions {
/** Text to display on the button (default: 'Click to Start') */
buttonText?: string;
/** Callback when user clicks the button */
onStart?: () => void;
/** Background color of the overlay (default: 'rgba(0, 0, 0, 0.8)') */
backgroundColor?: string;
/** Button background color (default: '#4a90d9') */
buttonColor?: string;
/** Button hover color (default: '#357abd') */
buttonHoverColor?: string;
/** Button text color (default: '#ffffff') */
buttonTextColor?: string;
/** Z-index of the overlay (default: 1000) */
zIndex?: number;
}
declare class AutoplayOverlay {
private container;
private overlayDiv;
private button;
private options;
private started;
private onStartCallback?;
constructor(container: HTMLElement, options?: AutoplayOverlayOptions);
/**
* Create the overlay DOM elements
*/
private createOverlay;
/**
* Start the application (hide overlay and call onStart callback)
* Can be called programmatically if autoplay is enabled
*/
start(): void;
/**
* Check if the overlay has been started
*/
isStarted(): boolean;
/**
* Check if the overlay is currently visible
*/
isVisible(): boolean;
/**
* Remove the overlay from DOM
*/
private removeOverlay;
/**
* Set the button text
*/
setButtonText(text: string): void;
/**
* Update the onStart callback
*/
setOnStart(callback: () => void): void;
/**
* Destroy the overlay and cleanup
*/
destroy(): void;
}
/**
* UTSP Render - Main entry point
*
* Terminal de caractères avec rendu WebGL optimisé
* TerminalGL est le renderer principal - WebGL 1.0 avec palette GPU
*/
declare const version = "0.1.0";
export { AutoplayOverlay, BitmapFontAtlas, DEFAULT_PALETTE, GridOverlay, Terminal2D, TerminalGL, colorToPaletteIndex, paletteIndexToColor, version };
export type { AutoplayOverlayOptions, BitmapFont$1 as BitmapFont, FontType, RenderOptions, TerminalCell, TerminalData, TerminalGLOptions, WebGLCompatibilityReport };