canvas-ultrafast 1.0.2 → 1.0.3
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/README.md
CHANGED
|
@@ -99,12 +99,28 @@ api.fillText('hello', 20, 80);
|
|
|
99
99
|
| `getCanvasAPI()` | Return the `CanvasAPI` instance |
|
|
100
100
|
| `submitBatch(commands)` | Execute commands into the write FBO, swap write ↔ ready |
|
|
101
101
|
| `startDisplay()` / `stopDisplay()` | Control the RAF display loop |
|
|
102
|
+
| `setBackgroundColor(r, g, b)` | Set the opaque clear color (values in [0, 1]) |
|
|
102
103
|
| `getReadyTexture()` | Return the ready FBO's texture for external rendering |
|
|
103
104
|
| `getGL()` | Access the underlying `WebGL2RenderingContext` |
|
|
104
105
|
| `getCanvas()` / `getCanvasSize()` | Canvas element and dimensions |
|
|
105
106
|
| `screenshot()` | Capture the current display frame as `ImageBitmap` |
|
|
106
107
|
| `destroy()` | Release all WebGL resources |
|
|
107
108
|
|
|
109
|
+
## Opaque canvas
|
|
110
|
+
|
|
111
|
+
The WebGL context is created with `alpha: false` and `desynchronized: true`. This means the canvas is always opaque — there is no alpha channel, and the browser compositor is bypassed entirely.
|
|
112
|
+
|
|
113
|
+
**Why:** `alpha: false` tells the GPU to skip per-pixel alpha blending in the compositor, saving significant bandwidth on mobile GPUs (2-4ms/frame on Adreno 3xx/4xx, Mali-T6xx at 1080p). `desynchronized: true` enables direct-to-display rendering, eliminating an additional frame of latency and reducing CPU overhead from compositor wake-ups. Together, these can be the difference between hitting 60fps and dropping frames on low-end hardware.
|
|
114
|
+
|
|
115
|
+
**Tradeoff:** `clearRect()` produces the configured background color (default: black) rather than transparency. Use `setBackgroundColor(r, g, b)` to control the clear color:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const renderer = new UltrafastRenderer(canvas);
|
|
119
|
+
renderer.setBackgroundColor(0.16, 0.22, 0.35); // dark blue, values in [0, 1]
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
[maalata](https://github.com/emansom/maalata) auto-detects the background color from the canvas element's DOM ancestors, so no manual configuration is needed in most cases.
|
|
123
|
+
|
|
108
124
|
## Extension points
|
|
109
125
|
|
|
110
126
|
canvas-ultrafast is designed to be taken over by a downstream consumer. The pattern:
|
|
@@ -520,6 +520,8 @@ class Canvas2DShim {
|
|
|
520
520
|
// Text rendering surface
|
|
521
521
|
_textCanvas;
|
|
522
522
|
_textCtx;
|
|
523
|
+
// Background color for opaque canvas clear
|
|
524
|
+
_bgColor = new Float32Array([0, 0, 0]);
|
|
523
525
|
// Temp arrays to avoid allocation in hot path
|
|
524
526
|
_tmpColor = new Float32Array(4);
|
|
525
527
|
constructor(gl, width, height) {
|
|
@@ -579,6 +581,15 @@ class Canvas2DShim {
|
|
|
579
581
|
}
|
|
580
582
|
}
|
|
581
583
|
}
|
|
584
|
+
/**
|
|
585
|
+
* Set the opaque clear color for clearRect.
|
|
586
|
+
* No _ prefix: called cross-file from renderer.
|
|
587
|
+
*/
|
|
588
|
+
setBackgroundColor(r, g, b) {
|
|
589
|
+
this._bgColor[0] = r;
|
|
590
|
+
this._bgColor[1] = g;
|
|
591
|
+
this._bgColor[2] = b;
|
|
592
|
+
}
|
|
582
593
|
/**
|
|
583
594
|
* Update canvas dimensions on resize.
|
|
584
595
|
* No _ prefix: called cross-file.
|
|
@@ -779,9 +790,10 @@ class Canvas2DShim {
|
|
|
779
790
|
// -------------------------------------------------------------------------
|
|
780
791
|
_clearRect(x, y, w, h) {
|
|
781
792
|
const gl = this._gl;
|
|
793
|
+
const bg = this._bgColor;
|
|
782
794
|
gl.enable(gl.SCISSOR_TEST);
|
|
783
795
|
gl.scissor(x, this._height - y - h, w, h);
|
|
784
|
-
gl.clearColor(0,
|
|
796
|
+
gl.clearColor(bg[0], bg[1], bg[2], 1);
|
|
785
797
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
786
798
|
gl.disable(gl.SCISSOR_TEST);
|
|
787
799
|
}
|
|
@@ -1233,6 +1245,8 @@ class UltrafastRenderer {
|
|
|
1233
1245
|
_readyIdx = 1;
|
|
1234
1246
|
_displayIdx = 2;
|
|
1235
1247
|
_hasContent = false;
|
|
1248
|
+
// Background color for opaque canvas clear (default: black, backwards compatible)
|
|
1249
|
+
_bgColor = new Float32Array([0, 0, 0]);
|
|
1236
1250
|
// Display program
|
|
1237
1251
|
_passthroughProgram;
|
|
1238
1252
|
// Fullscreen quad VBO
|
|
@@ -1311,6 +1325,17 @@ class UltrafastRenderer {
|
|
|
1311
1325
|
this._renderDisplay();
|
|
1312
1326
|
return createImageBitmap(this._canvas);
|
|
1313
1327
|
}
|
|
1328
|
+
/**
|
|
1329
|
+
* Set the opaque clear color used by clearRect and FBO initialization.
|
|
1330
|
+
* With alpha: false, cleared areas are opaque — this controls what color
|
|
1331
|
+
* they appear as instead of black. Values are in [0, 1] range.
|
|
1332
|
+
*/
|
|
1333
|
+
setBackgroundColor(r, g, b) {
|
|
1334
|
+
this._bgColor[0] = r;
|
|
1335
|
+
this._bgColor[1] = g;
|
|
1336
|
+
this._bgColor[2] = b;
|
|
1337
|
+
this._shim.setBackgroundColor(r, g, b);
|
|
1338
|
+
}
|
|
1314
1339
|
/** Clean up all WebGL resources. */
|
|
1315
1340
|
destroy() {
|
|
1316
1341
|
this.stopDisplay();
|
|
@@ -1397,13 +1422,14 @@ class UltrafastRenderer {
|
|
|
1397
1422
|
}
|
|
1398
1423
|
_clearAllFBOs() {
|
|
1399
1424
|
const gl = this._gl;
|
|
1425
|
+
const bg = this._bgColor;
|
|
1400
1426
|
for (const fbo of this._fbos) {
|
|
1401
1427
|
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo._fbo);
|
|
1402
|
-
gl.clearColor(0,
|
|
1428
|
+
gl.clearColor(bg[0], bg[1], bg[2], 1);
|
|
1403
1429
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
1404
1430
|
}
|
|
1405
1431
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
1406
|
-
gl.clearColor(0,
|
|
1432
|
+
gl.clearColor(bg[0], bg[1], bg[2], 1);
|
|
1407
1433
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
1408
1434
|
}
|
|
1409
1435
|
_initQuadVBO() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canvas-ultrafast.es.js","sources":["../src/canvas-api.ts","../src/matrix-stack.ts","../src/color-parser.ts","../src/shaders.ts","../src/canvas2d-shim.ts","../src/renderer.ts"],"sourcesContent":["/**\n * Canvas API Wrapper\n *\n * Provides a Canvas 2D API that records commands locally without await.\n * Commands are batched and sent to the worker for execution.\n */\n\ntype CanvasPropertyMap = {\n fillStyle: string | CanvasGradient | CanvasPattern;\n strokeStyle: string | CanvasGradient | CanvasPattern;\n lineWidth: number;\n lineCap: CanvasLineCap;\n lineJoin: CanvasLineJoin;\n miterLimit: number;\n lineDashOffset: number;\n font: string;\n textAlign: CanvasTextAlign;\n textBaseline: CanvasTextBaseline;\n globalAlpha: number;\n globalCompositeOperation: GlobalCompositeOperation;\n shadowBlur: number;\n shadowColor: string;\n shadowOffsetX: number;\n shadowOffsetY: number;\n imageSmoothingEnabled: boolean;\n letterSpacing: string;\n};\n\nexport type CanvasCommand =\n | { type: 'property'; name: string; value: unknown }\n | { type: 'method'; name: string; args: unknown[] };\n\nexport class CanvasAPI {\n private _c: CanvasCommand[] = [];\n private _cp: Partial<CanvasPropertyMap> = {};\n\n private _m(n: string, ...a: unknown[]): void {\n this._c.push({ type: 'method', name: n, args: a });\n }\n\n private _p<K extends keyof CanvasPropertyMap>(n: K, v: CanvasPropertyMap[K]): void {\n this._cp[n] = v;\n this._c.push({ type: 'property', name: n, value: v });\n }\n\n /**\n * Drain and return all buffered commands.\n * No _ prefix: called cross-file from pipeline, must survive mangleProps.\n */\n takeCommands(): CanvasCommand[] {\n if (this._c.length === 0) return [];\n const cmds = this._c;\n this._c = [];\n return cmds;\n }\n\n // Canvas 2D API methods\n\n // State\n save(): void { this._m('save'); }\n restore(): void { this._m('restore'); }\n\n // Transform\n scale(x: number, y: number): void { this._m('scale', x, y); }\n rotate(angle: number): void { this._m('rotate', angle); }\n translate(x: number, y: number): void { this._m('translate', x, y); }\n transform(a: number, b: number, c: number, d: number, e: number, f: number): void { this._m('transform', a, b, c, d, e, f); }\n setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void { this._m('setTransform', a, b, c, d, e, f); }\n resetTransform(): void { this._m('resetTransform'); }\n\n // Rectangles\n clearRect(x: number, y: number, width: number, height: number): void { this._m('clearRect', x, y, width, height); }\n fillRect(x: number, y: number, width: number, height: number): void { this._m('fillRect', x, y, width, height); }\n strokeRect(x: number, y: number, width: number, height: number): void { this._m('strokeRect', x, y, width, height); }\n\n // Text\n fillText(text: string, x: number, y: number, maxWidth?: number): void {\n this._m('fillText', ...(maxWidth !== undefined ? [text, x, y, maxWidth] : [text, x, y]));\n }\n\n strokeText(text: string, x: number, y: number, maxWidth?: number): void {\n this._m('strokeText', ...(maxWidth !== undefined ? [text, x, y, maxWidth] : [text, x, y]));\n }\n\n /** Synchronous text measurement — cannot go through the async command pipeline. */\n private _measureCtx: OffscreenCanvasRenderingContext2D | null = null;\n\n measureText(text: string): TextMetrics {\n if (!this._measureCtx) {\n this._measureCtx = new OffscreenCanvas(1, 1).getContext('2d')!;\n }\n this._measureCtx.font = this.font;\n return this._measureCtx.measureText(text);\n }\n\n // Line drawing\n beginPath(): void { this._m('beginPath'); }\n closePath(): void { this._m('closePath'); }\n moveTo(x: number, y: number): void { this._m('moveTo', x, y); }\n lineTo(x: number, y: number): void { this._m('lineTo', x, y); }\n\n bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void {\n this._m('bezierCurveTo', cp1x, cp1y, cp2x, cp2y, x, y);\n }\n\n quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void { this._m('quadraticCurveTo', cpx, cpy, x, y); }\n\n arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void {\n this._m('arc', ...(counterclockwise !== undefined ? [x, y, radius, startAngle, endAngle, counterclockwise] : [x, y, radius, startAngle, endAngle]));\n }\n\n arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void { this._m('arcTo', x1, y1, x2, y2, radius); }\n\n ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void {\n this._m('ellipse', ...(counterclockwise !== undefined ? [x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise] : [x, y, radiusX, radiusY, rotation, startAngle, endAngle]));\n }\n\n rect(x: number, y: number, width: number, height: number): void { this._m('rect', x, y, width, height); }\n\n // Images\n drawImage(image: CanvasImageSource, dx: number, dy: number): void;\n drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;\n drawImage(image: CanvasImageSource, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void;\n drawImage(...args: [CanvasImageSource, ...number[]]): void {\n this._m('drawImage', ...args);\n }\n\n // Fill and stroke\n fill(): void { this._m('fill'); }\n stroke(): void { this._m('stroke'); }\n clip(): void { this._m('clip'); }\n\n // Properties (setters)\n set fillStyle(value: string | CanvasGradient | CanvasPattern) { this._p('fillStyle', value); }\n set strokeStyle(value: string | CanvasGradient | CanvasPattern) { this._p('strokeStyle', value); }\n set lineWidth(value: number) { this._p('lineWidth', value); }\n set lineCap(value: CanvasLineCap) { this._p('lineCap', value); }\n set lineJoin(value: CanvasLineJoin) { this._p('lineJoin', value); }\n set miterLimit(value: number) { this._p('miterLimit', value); }\n set lineDashOffset(value: number) { this._p('lineDashOffset', value); }\n set font(value: string) { this._p('font', value); }\n set textAlign(value: CanvasTextAlign) { this._p('textAlign', value); }\n set textBaseline(value: CanvasTextBaseline) { this._p('textBaseline', value); }\n set globalAlpha(value: number) { this._p('globalAlpha', value); }\n set globalCompositeOperation(value: GlobalCompositeOperation) { this._p('globalCompositeOperation', value); }\n set shadowBlur(value: number) { this._p('shadowBlur', value); }\n set shadowColor(value: string) { this._p('shadowColor', value); }\n set shadowOffsetX(value: number) { this._p('shadowOffsetX', value); }\n set shadowOffsetY(value: number) { this._p('shadowOffsetY', value); }\n set imageSmoothingEnabled(value: boolean) { this._p('imageSmoothingEnabled', value); }\n set letterSpacing(value: string) { this._p('letterSpacing', value); }\n\n // Property getters (return local cached values)\n get fillStyle() { return this._cp['fillStyle'] ?? '#000'; }\n get strokeStyle() { return this._cp['strokeStyle'] ?? '#000'; }\n get lineWidth() { return this._cp['lineWidth'] ?? 1; }\n get lineCap() { return this._cp['lineCap'] ?? 'butt'; }\n get lineJoin() { return this._cp['lineJoin'] ?? 'miter'; }\n get miterLimit() { return this._cp['miterLimit'] ?? 10; }\n get lineDashOffset() { return this._cp['lineDashOffset'] ?? 0; }\n get font() { return this._cp['font'] ?? '10px sans-serif'; }\n get textAlign() { return this._cp['textAlign'] ?? 'start'; }\n get textBaseline() { return this._cp['textBaseline'] ?? 'alphabetic'; }\n get globalAlpha() { return this._cp['globalAlpha'] ?? 1; }\n get globalCompositeOperation() { return this._cp['globalCompositeOperation'] ?? 'source-over'; }\n get shadowBlur() { return this._cp['shadowBlur'] ?? 0; }\n get shadowColor() { return this._cp['shadowColor'] ?? 'rgba(0, 0, 0, 0)'; }\n get shadowOffsetX() { return this._cp['shadowOffsetX'] ?? 0; }\n get shadowOffsetY() { return this._cp['shadowOffsetY'] ?? 0; }\n get imageSmoothingEnabled() { return this._cp['imageSmoothingEnabled'] ?? true; }\n get letterSpacing() { return this._cp['letterSpacing'] ?? ''; }\n}","/**\n * 3×3 Affine Transform Matrix Stack\n *\n * Replicates Canvas 2D's save()/restore()/translate()/rotate()/scale()\n * as a matrix stack for WebGL uniform upload.\n *\n * Matrices are 3×3 column-major (for gl.uniformMatrix3fv), representing\n * 2D affine transforms. The base matrix includes an orthographic projection\n * that maps canvas pixel coordinates (top-left origin, Y-down) to WebGL\n * clip space ([-1,1], Y-up).\n *\n * Column-major layout of a 3×3 affine matrix:\n * [0] [3] [6] a c tx\n * [1] [4] [7] = b d ty\n * [2] [5] [8] 0 0 1\n */\n\nexport class MatrixStack {\n private _stack: Float32Array[] = [];\n private _current: Float32Array;\n private _projection: Float32Array;\n\n /**\n * @param width Canvas width in pixels\n * @param height Canvas height in pixels\n */\n constructor(width: number, height: number) {\n this._projection = _ortho(width, height);\n this._current = new Float32Array(this._projection);\n }\n\n /** Push current matrix onto the stack. No _ prefix: cross-file. */\n save(): void {\n this._stack.push(new Float32Array(this._current));\n }\n\n /** Pop and restore the top matrix. No _ prefix: cross-file. */\n restore(): void {\n if (this._stack.length > 0) {\n this._current = this._stack.pop()!;\n }\n }\n\n /** Translate the current matrix. No _ prefix: cross-file. */\n translate(x: number, y: number): void {\n // Multiply current matrix by translation:\n // 1 0 tx\n // 0 1 ty\n // 0 0 1\n // In column-major: m[6] += m[0]*tx + m[3]*ty\n // m[7] += m[1]*tx + m[4]*ty\n const m = this._current;\n m[6] += m[0] * x + m[3] * y;\n m[7] += m[1] * x + m[4] * y;\n }\n\n /** Rotate the current matrix by angle (radians). No _ prefix: cross-file. */\n rotate(angle: number): void {\n const c = Math.cos(angle);\n const s = Math.sin(angle);\n const m = this._current;\n const m0 = m[0], m1 = m[1], m3 = m[3], m4 = m[4];\n m[0] = m0 * c + m3 * s;\n m[1] = m1 * c + m4 * s;\n m[3] = m0 * -s + m3 * c;\n m[4] = m1 * -s + m4 * c;\n }\n\n /** Scale the current matrix. No _ prefix: cross-file. */\n scale(x: number, y: number): void {\n const m = this._current;\n m[0] *= x; m[1] *= x;\n m[3] *= y; m[4] *= y;\n }\n\n /**\n * Multiply current matrix by an arbitrary 2D affine transform.\n * Canvas 2D transform(a, b, c, d, e, f) matrix:\n * a c e\n * b d f\n * 0 0 1\n * No _ prefix: cross-file.\n */\n transform(a: number, b: number, c: number, d: number, e: number, f: number): void {\n const m = this._current;\n const m0 = m[0], m1 = m[1], m3 = m[3], m4 = m[4], m6 = m[6], m7 = m[7];\n m[0] = m0 * a + m3 * b;\n m[1] = m1 * a + m4 * b;\n m[3] = m0 * c + m3 * d;\n m[4] = m1 * c + m4 * d;\n m[6] = m0 * e + m3 * f + m6;\n m[7] = m1 * e + m4 * f + m7;\n }\n\n /**\n * Reset to projection then apply the given affine transform.\n * Canvas 2D setTransform(a, b, c, d, e, f).\n * No _ prefix: cross-file.\n */\n setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void {\n this._current.set(this._projection);\n this.transform(a, b, c, d, e, f);\n }\n\n /** Reset to the base orthographic projection. No _ prefix: cross-file. */\n resetTransform(): void {\n this._current.set(this._projection);\n }\n\n /**\n * Update canvas dimensions (e.g., on resize).\n * Recomputes the projection and resets the current matrix.\n * No _ prefix: cross-file.\n */\n resize(width: number, height: number): void {\n this._projection = _ortho(width, height);\n this._current = new Float32Array(this._projection);\n this._stack = [];\n }\n\n /**\n * Returns the current 3×3 matrix for gl.uniformMatrix3fv.\n * No _ prefix: cross-file.\n */\n getMatrix(): Float32Array {\n return this._current;\n }\n}\n\n/**\n * Create an orthographic projection matrix that maps:\n * Canvas coords (0,0)=top-left, (w,h)=bottom-right, Y-down\n * → Clip space (-1,-1)=bottom-left, (1,1)=top-right, Y-up\n *\n * The transform is:\n * x_clip = x * 2/w - 1\n * y_clip = -(y * 2/h - 1) = 1 - y * 2/h\n *\n * Column-major 3×3:\n * 2/w 0 -1\n * 0 -2/h 1\n * 0 0 1\n */\nfunction _ortho(w: number, h: number): Float32Array {\n return new Float32Array([\n 2 / w, 0, 0, // column 0\n 0, -2 / h, 0, // column 1\n -1, 1, 1, // column 2\n ]);\n}\n","/**\n * CSS Color Parser\n *\n * Converts CSS color strings to Float32Array [r, g, b, a] in [0, 1] range\n * for use as WebGL uniform values.\n *\n * Supported formats:\n * - Hex: #rgb, #rrggbb, #rrggbbaa\n * - Functional: rgb(r, g, b), rgba(r, g, b, a)\n * - Named: basic CSS color keywords\n *\n * Includes a cache for repeated lookups (the demo reuses ~10 colors).\n */\n\nconst _NAMED_COLORS: Record<string, number> = {\n black: 0x000000ff,\n white: 0xffffffff,\n red: 0xff0000ff,\n green: 0x008000ff,\n blue: 0x0000ffff,\n yellow: 0xffff00ff,\n cyan: 0x00ffffff,\n magenta: 0xff00ffff,\n orange: 0xffa500ff,\n transparent: 0x00000000,\n};\n\nconst _cache = new Map<string, Float32Array>();\n\n/**\n * Parse a CSS color string into [r, g, b, a] floats in [0, 1].\n * Returns a cached Float32Array — do NOT mutate the result.\n *\n * No _ prefix: called cross-file from canvas2d-shim.\n */\nexport function parseColor(css: string): Float32Array {\n const cached = _cache.get(css);\n if (cached) return cached;\n\n const result = _parse(css);\n _cache.set(css, result);\n return result;\n}\n\nfunction _parse(css: string): Float32Array {\n const s = css.trim();\n\n // #hex\n if (s.charCodeAt(0) === 0x23) { // '#'\n return _parseHex(s);\n }\n\n // rgb() / rgba()\n if (s.charCodeAt(0) === 0x72) { // 'r'\n return _parseRgb(s);\n }\n\n // Named color\n const named = _NAMED_COLORS[s.toLowerCase()];\n if (named !== undefined) {\n return new Float32Array([\n ((named >>> 24) & 0xff) / 255,\n ((named >>> 16) & 0xff) / 255,\n ((named >>> 8) & 0xff) / 255,\n (named & 0xff) / 255,\n ]);\n }\n\n // Fallback: opaque black\n return new Float32Array([0, 0, 0, 1]);\n}\n\nfunction _parseHex(s: string): Float32Array {\n const len = s.length;\n\n if (len === 4) {\n // #rgb → expand to #rrggbb\n const r = parseInt(s[1], 16);\n const g = parseInt(s[2], 16);\n const b = parseInt(s[3], 16);\n return new Float32Array([\n (r * 17) / 255,\n (g * 17) / 255,\n (b * 17) / 255,\n 1,\n ]);\n }\n\n if (len === 7) {\n // #rrggbb\n const r = parseInt(s.slice(1, 3), 16);\n const g = parseInt(s.slice(3, 5), 16);\n const b = parseInt(s.slice(5, 7), 16);\n return new Float32Array([r / 255, g / 255, b / 255, 1]);\n }\n\n if (len === 9) {\n // #rrggbbaa\n const r = parseInt(s.slice(1, 3), 16);\n const g = parseInt(s.slice(3, 5), 16);\n const b = parseInt(s.slice(5, 7), 16);\n const a = parseInt(s.slice(7, 9), 16);\n return new Float32Array([r / 255, g / 255, b / 255, a / 255]);\n }\n\n // #rgba (4-digit with alpha)\n if (len === 5) {\n const r = parseInt(s[1], 16);\n const g = parseInt(s[2], 16);\n const b = parseInt(s[3], 16);\n const a = parseInt(s[4], 16);\n return new Float32Array([\n (r * 17) / 255,\n (g * 17) / 255,\n (b * 17) / 255,\n (a * 17) / 255,\n ]);\n }\n\n return new Float32Array([0, 0, 0, 1]);\n}\n\nfunction _parseRgb(s: string): Float32Array {\n // Match both rgb(...) and rgba(...)\n // Extract the numeric values between parentheses\n const start = s.indexOf('(');\n const end = s.lastIndexOf(')');\n if (start === -1 || end === -1) return new Float32Array([0, 0, 0, 1]);\n\n const parts = s.slice(start + 1, end).split(',');\n const r = parseFloat(parts[0]) / 255;\n const g = parseFloat(parts[1]) / 255;\n const b = parseFloat(parts[2]) / 255;\n const a = parts.length >= 4 ? parseFloat(parts[3]) : 1;\n\n return new Float32Array([r, g, b, a]);\n}\n","/**\n * GLSL Shader Sources for canvas-ultrafast\n *\n * Content shaders (flat-color, textured) plus a passthrough display shader.\n * CRT post-processing shaders live in the maalata package.\n *\n * Coordinate convention:\n * - Content shaders use a 3x3 affine matrix (u_matrix) that maps\n * canvas pixel coordinates (top-left origin, Y-down) to clip space.\n * - Passthrough shader uses a fullscreen quad in [0,1] mapped to [-1,1] clip space.\n */\n\n// ---------------------------------------------------------------------------\n// Flat-color shader: rectangles, line quads, clear regions\n// ---------------------------------------------------------------------------\n\nexport const FLAT_VERTEX_SRC = `\n attribute vec2 a_position;\n uniform mat3 u_matrix;\n void main() {\n vec3 pos = u_matrix * vec3(a_position, 1.0);\n gl_Position = vec4(pos.xy, 0.0, 1.0);\n }\n`;\n\nexport const FLAT_FRAGMENT_SRC = `\n precision mediump float;\n uniform vec4 u_color;\n void main() {\n gl_FragColor = u_color;\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Textured quad shader: text rendering via OffscreenCanvas glyph upload\n// ---------------------------------------------------------------------------\n\nexport const TEXTURED_VERTEX_SRC = `\n attribute vec2 a_position;\n attribute vec2 a_texCoord;\n uniform mat3 u_matrix;\n varying vec2 v_texCoord;\n void main() {\n vec3 pos = u_matrix * vec3(a_position, 1.0);\n gl_Position = vec4(pos.xy, 0.0, 1.0);\n v_texCoord = a_texCoord;\n }\n`;\n\nexport const TEXTURED_FRAGMENT_SRC = `\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_texture;\n uniform vec4 u_color;\n void main() {\n vec4 texel = texture2D(u_texture, v_texCoord);\n gl_FragColor = texel * u_color;\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Passthrough display shader: fullscreen quad, reads FBO texture\n// ---------------------------------------------------------------------------\n\n/**\n * Vertex shader: fullscreen quad [0,1] → clip space [-1,1].\n * FBO textures are already in GL-native bottom-left origin (the orthographic\n * projection in matrix-stack.ts handles the canvas Y-down → GL Y-up flip),\n * so tex coords pass through without Y-flip.\n */\nexport const PASSTHROUGH_VERTEX_SRC = `\n attribute vec2 a_position;\n varying vec2 v_texCoord;\n void main() {\n v_texCoord = a_position;\n gl_Position = vec4(a_position * 2.0 - 1.0, 0, 1);\n }\n`;\n\n/**\n * Passthrough fragment shader: blit FBO texture to screen without effects.\n */\nexport const PASSTHROUGH_FRAGMENT_SRC = `\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_texture;\n void main() {\n gl_FragColor = texture2D(u_texture, v_texCoord);\n }\n`;\n","/**\n * Canvas 2D → WebGL Command Shim\n *\n * Translates CanvasCommand[] (recorded by CanvasAPI) into WebGL draw calls.\n * Handles the subset of Canvas 2D API used by the demo, plus reasonable\n * extensions. Operations not yet implemented log a warning and no-op.\n *\n * Rendering approach per command type:\n * - clearRect: gl.scissor + gl.clear\n * - fillRect: unit quad VBO + flat shader + transform uniform\n * - strokeRect: four thin quads (one per edge)\n * - fillText: render to OffscreenCanvas 2D → texImage2D → textured quad\n * - stroke(): expand line segments to quads on CPU, flat shader\n * - save/restore: matrix + state stack\n *\n * Text rendering uses an OffscreenCanvas with a 2D context as a glyph\n * rendering surface. At 8 FPS with ~5 text draws per frame, per-string\n * rendering (not glyph caching) is appropriate — texImage2D(OffscreenCanvas)\n * is a fast GPU upload path.\n */\n\nimport { CanvasCommand } from './canvas-api';\nimport { MatrixStack } from './matrix-stack';\nimport { parseColor } from './color-parser';\nimport {\n FLAT_VERTEX_SRC, FLAT_FRAGMENT_SRC,\n TEXTURED_VERTEX_SRC, TEXTURED_FRAGMENT_SRC,\n} from './shaders';\n\ninterface _DrawState {\n _fillColor: Float32Array;\n _strokeColor: Float32Array;\n _lineWidth: number;\n _globalAlpha: number;\n _font: string;\n _textAlign: CanvasTextAlign;\n _textBaseline: CanvasTextBaseline;\n _lineCap: CanvasLineCap;\n _lineJoin: CanvasLineJoin;\n _imageSmoothingEnabled: boolean;\n _letterSpacing: string;\n _clipActive: boolean;\n _clipRect: [number, number, number, number] | null;\n}\n\ninterface _ProgramInfo {\n _program: WebGLProgram;\n _matrixLoc: WebGLUniformLocation | null;\n _colorLoc: WebGLUniformLocation | null;\n _textureLoc: WebGLUniformLocation | null;\n _positionLoc: number;\n _texCoordLoc: number;\n}\n\nexport class Canvas2DShim {\n private _gl: WebGLRenderingContext;\n private _width: number;\n private _height: number;\n\n // Transform\n private _matrix: MatrixStack;\n\n // State\n private _fillColor: Float32Array = new Float32Array([0, 0, 0, 1]);\n private _strokeColor: Float32Array = new Float32Array([0, 0, 0, 1]);\n private _lineWidth = 1;\n private _globalAlpha = 1;\n private _font = '10px sans-serif';\n private _textAlign: CanvasTextAlign = 'start';\n private _textBaseline: CanvasTextBaseline = 'alphabetic';\n private _lineCap: CanvasLineCap = 'butt';\n private _lineJoin: CanvasLineJoin = 'miter';\n private _imageSmoothingEnabled = true;\n private _letterSpacing = '';\n private _clipActive = false;\n private _clipRect: [number, number, number, number] | null = null;\n private _pendingClipRect: [number, number, number, number] | null = null;\n private _imageTexCache = new WeakMap<object, { _tex: WebGLTexture; _isImage: boolean }>();\n private _stateStack: _DrawState[] = [];\n\n // Path state\n private _pathSegments: number[] = []; // flat: x0,y0,x1,y1,...\n private _currentX = 0;\n private _currentY = 0;\n private _subpathStartX = 0;\n private _subpathStartY = 0;\n\n // WebGL resources\n private _flat: _ProgramInfo;\n private _textured: _ProgramInfo;\n private _unitQuadVBO: WebGLBuffer;\n private _dynamicVBO: WebGLBuffer;\n private _texturedVBO: WebGLBuffer;\n private _textTexture: WebGLTexture;\n\n // Text rendering surface\n private _textCanvas: OffscreenCanvas;\n private _textCtx: OffscreenCanvasRenderingContext2D;\n\n // Temp arrays to avoid allocation in hot path\n private _tmpColor = new Float32Array(4);\n\n constructor(gl: WebGLRenderingContext, width: number, height: number) {\n this._gl = gl;\n this._width = width;\n this._height = height;\n this._matrix = new MatrixStack(width, height);\n\n // Compile shader programs\n this._flat = this._createProgram(\n FLAT_VERTEX_SRC, FLAT_FRAGMENT_SRC, false\n );\n this._textured = this._createProgram(\n TEXTURED_VERTEX_SRC, TEXTURED_FRAGMENT_SRC, true\n );\n\n // Unit quad VBO: two triangles covering [0,0]-[1,1]\n // Used for fillRect (scaled via matrix) and fullscreen blits\n this._unitQuadVBO = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, this._unitQuadVBO);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([\n 0, 0, 1, 0, 0, 1,\n 0, 1, 1, 0, 1, 1,\n ]), gl.STATIC_DRAW);\n\n // Dynamic VBO for line quads — uses orphaning for double-buffer\n this._dynamicVBO = gl.createBuffer()!;\n\n // Textured quad VBO: position + texcoord interleaved\n this._texturedVBO = gl.createBuffer()!;\n\n // Text rendering texture\n this._textTexture = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, this._textTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n // OffscreenCanvas for text glyph rendering\n this._textCanvas = new OffscreenCanvas(512, 128);\n this._textCtx = this._textCanvas.getContext('2d')!;\n\n // Enable blending for standard source-over compositing\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n }\n\n /**\n * Execute a batch of Canvas 2D commands as WebGL draw calls.\n * No _ prefix: called cross-file from webgl-renderer.\n */\n executeBatch(commands: CanvasCommand[]): void {\n for (const cmd of commands) {\n if (cmd.type === 'property') {\n this._setProperty(cmd.name, cmd.value);\n } else {\n this._callMethod(cmd.name, cmd.args);\n }\n }\n }\n\n /**\n * Update canvas dimensions on resize.\n * No _ prefix: called cross-file.\n */\n resize(width: number, height: number): void {\n this._width = width;\n this._height = height;\n this._matrix.resize(width, height);\n }\n\n /**\n * Clean up WebGL resources.\n * No _ prefix: called cross-file.\n */\n destroy(): void {\n const gl = this._gl;\n gl.deleteBuffer(this._unitQuadVBO);\n gl.deleteBuffer(this._dynamicVBO);\n gl.deleteBuffer(this._texturedVBO);\n gl.deleteTexture(this._textTexture);\n gl.deleteProgram(this._flat._program);\n gl.deleteProgram(this._textured._program);\n }\n\n // -------------------------------------------------------------------------\n // Private: property handling\n // -------------------------------------------------------------------------\n\n private _setProperty(name: string, value: unknown): void {\n switch (name) {\n case 'fillStyle':\n this._fillColor = parseColor(value as string);\n break;\n case 'strokeStyle':\n this._strokeColor = parseColor(value as string);\n break;\n case 'lineWidth':\n this._lineWidth = value as number;\n break;\n case 'globalAlpha':\n this._globalAlpha = value as number;\n break;\n case 'font':\n this._font = value as string;\n break;\n case 'textAlign':\n this._textAlign = value as CanvasTextAlign;\n break;\n case 'textBaseline':\n this._textBaseline = value as CanvasTextBaseline;\n break;\n case 'lineCap':\n this._lineCap = value as CanvasLineCap;\n break;\n case 'lineJoin':\n this._lineJoin = value as CanvasLineJoin;\n break;\n case 'imageSmoothingEnabled':\n this._imageSmoothingEnabled = value as boolean;\n break;\n case 'letterSpacing':\n this._letterSpacing = value as string;\n break;\n default:\n // Unsupported properties: silently ignore\n break;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: method dispatch\n // -------------------------------------------------------------------------\n\n private _callMethod(name: string, args: unknown[]): void {\n switch (name) {\n // Rectangles\n case 'clearRect':\n this._clearRect(args[0] as number, args[1] as number, args[2] as number, args[3] as number);\n break;\n case 'fillRect':\n this._fillRect(args[0] as number, args[1] as number, args[2] as number, args[3] as number);\n break;\n case 'strokeRect':\n this._strokeRect(args[0] as number, args[1] as number, args[2] as number, args[3] as number);\n break;\n\n // Text\n case 'fillText':\n this._fillText(args[0] as string, args[1] as number, args[2] as number);\n break;\n case 'strokeText':\n this._strokeText(args[0] as string, args[1] as number, args[2] as number);\n break;\n\n // Images\n case 'drawImage':\n this._drawImage(args);\n break;\n\n // Path\n case 'beginPath':\n this._pathSegments = [];\n this._pendingClipRect = null;\n break;\n case 'closePath':\n if (this._currentX !== this._subpathStartX || this._currentY !== this._subpathStartY) {\n this._pathSegments.push(\n this._currentX, this._currentY,\n this._subpathStartX, this._subpathStartY\n );\n this._currentX = this._subpathStartX;\n this._currentY = this._subpathStartY;\n }\n break;\n case 'moveTo':\n this._currentX = this._subpathStartX = args[0] as number;\n this._currentY = this._subpathStartY = args[1] as number;\n break;\n case 'lineTo': {\n const x = args[0] as number;\n const y = args[1] as number;\n this._pathSegments.push(this._currentX, this._currentY, x, y);\n this._currentX = x;\n this._currentY = y;\n break;\n }\n case 'rect': {\n const rx = args[0] as number, ry = args[1] as number;\n const rw = args[2] as number, rh = args[3] as number;\n // Store as pending clip rect (used if clip() follows)\n this._pendingClipRect = [rx, ry, rw, rh];\n // Also add 4 line segments to path for potential stroke()\n this._pathSegments.push(\n rx, ry, rx + rw, ry, // top\n rx + rw, ry, rx + rw, ry + rh, // right\n rx + rw, ry + rh, rx, ry + rh, // bottom\n rx, ry + rh, rx, ry, // left\n );\n break;\n }\n case 'clip':\n this._applyClip();\n break;\n case 'stroke':\n this._strokePath();\n break;\n case 'fill':\n // Convex fill only — not heavily used in demo beyond fillRect\n break;\n\n // State\n case 'save':\n this._save();\n break;\n case 'restore':\n this._restore();\n break;\n\n // Transforms\n case 'translate':\n this._matrix.translate(args[0] as number, args[1] as number);\n break;\n case 'rotate':\n this._matrix.rotate(args[0] as number);\n break;\n case 'scale':\n this._matrix.scale(args[0] as number, args[1] as number);\n break;\n case 'transform':\n this._matrix.transform(\n args[0] as number, args[1] as number, args[2] as number,\n args[3] as number, args[4] as number, args[5] as number\n );\n break;\n case 'setTransform':\n this._matrix.setTransform(\n args[0] as number, args[1] as number, args[2] as number,\n args[3] as number, args[4] as number, args[5] as number\n );\n break;\n case 'resetTransform':\n this._matrix.resetTransform();\n break;\n\n default:\n // Unsupported methods: silently ignore (arc, bezierCurveTo, etc.)\n break;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: drawing operations\n // -------------------------------------------------------------------------\n\n private _clearRect(x: number, y: number, w: number, h: number): void {\n const gl = this._gl;\n // WebGL scissor uses bottom-left origin, canvas uses top-left\n gl.enable(gl.SCISSOR_TEST);\n gl.scissor(x, this._height - y - h, w, h);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.disable(gl.SCISSOR_TEST);\n }\n\n private _fillRect(x: number, y: number, w: number, h: number): void {\n const gl = this._gl;\n const prog = this._flat;\n\n gl.useProgram(prog._program);\n\n // Build transform: current matrix × translate(x,y) × scale(w,h)\n // Applied to unit quad [0,1]×[0,1] → fills [x,y,x+w,y+h]\n this._matrix.save();\n this._matrix.translate(x, y);\n this._matrix.scale(w, h);\n\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, this._fillColor, this._globalAlpha);\n\n this._matrix.restore();\n\n // Draw unit quad\n gl.bindBuffer(gl.ARRAY_BUFFER, this._unitQuadVBO);\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, 0, 0);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n }\n\n private _strokeRect(x: number, y: number, w: number, h: number): void {\n // Draw four edges as thin quads\n const lw = this._lineWidth;\n const hlw = lw / 2;\n\n // Top edge\n this._fillRectWithColor(x - hlw, y - hlw, w + lw, lw, this._strokeColor);\n // Bottom edge\n this._fillRectWithColor(x - hlw, y + h - hlw, w + lw, lw, this._strokeColor);\n // Left edge\n this._fillRectWithColor(x - hlw, y + hlw, lw, h - lw, this._strokeColor);\n // Right edge\n this._fillRectWithColor(x + w - hlw, y + hlw, lw, h - lw, this._strokeColor);\n }\n\n /** Internal: draw a filled rect with a specific color (used by strokeRect). */\n private _fillRectWithColor(x: number, y: number, w: number, h: number, color: Float32Array): void {\n const gl = this._gl;\n const prog = this._flat;\n\n gl.useProgram(prog._program);\n\n this._matrix.save();\n this._matrix.translate(x, y);\n this._matrix.scale(w, h);\n\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, color, this._globalAlpha);\n\n this._matrix.restore();\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this._unitQuadVBO);\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, 0, 0);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n }\n\n private _strokePath(): void {\n const segs = this._pathSegments;\n if (segs.length === 0) return;\n\n const gl = this._gl;\n const prog = this._flat;\n const halfW = Math.max(this._lineWidth / 2, 0.5);\n\n // Expand line segments to quads on CPU\n // Each segment (x0,y0,x1,y1) → 6 vertices (2 triangles)\n const segCount = segs.length / 4;\n const vertices = new Float32Array(segCount * 12); // 6 vertices × 2 coords\n\n for (let i = 0, vi = 0; i < segs.length; i += 4) {\n const x0 = segs[i], y0 = segs[i + 1], x1 = segs[i + 2], y1 = segs[i + 3];\n const dx = x1 - x0;\n const dy = y1 - y0;\n const len = Math.sqrt(dx * dx + dy * dy);\n\n if (len < 0.001) continue; // Skip degenerate segments\n\n // Normal perpendicular to line direction\n const nx = (-dy / len) * halfW;\n const ny = (dx / len) * halfW;\n\n // Four corners of the quad\n const ax = x0 + nx, ay = y0 + ny; // top-left\n const bx = x0 - nx, by = y0 - ny; // bottom-left\n const cx = x1 + nx, cy = y1 + ny; // top-right\n const dx2 = x1 - nx, dy2 = y1 - ny; // bottom-right\n\n // Triangle 1: A, B, C\n vertices[vi++] = ax; vertices[vi++] = ay;\n vertices[vi++] = bx; vertices[vi++] = by;\n vertices[vi++] = cx; vertices[vi++] = cy;\n // Triangle 2: B, D, C\n vertices[vi++] = bx; vertices[vi++] = by;\n vertices[vi++] = dx2; vertices[vi++] = dy2;\n vertices[vi++] = cx; vertices[vi++] = cy;\n }\n\n // Upload to dynamic VBO using orphaning (bufferData null pattern)\n gl.bindBuffer(gl.ARRAY_BUFFER, this._dynamicVBO);\n gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW);\n\n gl.useProgram(prog._program);\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, this._strokeColor, this._globalAlpha);\n\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, 0, 0);\n gl.drawArrays(gl.TRIANGLES, 0, segCount * 6);\n }\n\n private _drawImage(args: unknown[]): void {\n const gl = this._gl;\n const image = args[0] as CanvasImageSource;\n\n let sx: number, sy: number, sw: number, sh: number;\n let dx: number, dy: number, dw: number, dh: number;\n\n // Get image dimensions\n const imgW = _getImageWidth(image);\n const imgH = _getImageHeight(image);\n\n if (args.length === 3) {\n // drawImage(image, dx, dy)\n sx = 0; sy = 0; sw = imgW; sh = imgH;\n dx = args[1] as number; dy = args[2] as number;\n dw = imgW; dh = imgH;\n } else if (args.length === 5) {\n // drawImage(image, dx, dy, dw, dh)\n sx = 0; sy = 0; sw = imgW; sh = imgH;\n dx = args[1] as number; dy = args[2] as number;\n dw = args[3] as number; dh = args[4] as number;\n } else {\n // drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)\n sx = args[1] as number; sy = args[2] as number;\n sw = args[3] as number; sh = args[4] as number;\n dx = args[5] as number; dy = args[6] as number;\n dw = args[7] as number; dh = args[8] as number;\n }\n\n // Get or create texture for this image source\n const tex = this._getOrUploadTexture(image, imgW, imgH);\n\n // Set filtering based on imageSmoothingEnabled\n const filter = this._imageSmoothingEnabled ? gl.LINEAR : gl.NEAREST;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);\n\n // Compute UV coordinates for source sub-rect\n const uMin = sx / imgW;\n const vMin = sy / imgH;\n const uMax = (sx + sw) / imgW;\n const vMax = (sy + sh) / imgH;\n\n // Draw textured quad with interleaved position + texcoord\n const prog = this._textured;\n const verts = new Float32Array([\n dx, dy, uMin, vMin,\n dx + dw, dy, uMax, vMin,\n dx, dy + dh, uMin, vMax,\n dx, dy + dh, uMin, vMax,\n dx + dw, dy, uMax, vMin,\n dx + dw, dy + dh, uMax, vMax,\n ]);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this._texturedVBO);\n gl.bufferData(gl.ARRAY_BUFFER, verts, gl.DYNAMIC_DRAW);\n\n gl.useProgram(prog._program);\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n // White color tint with globalAlpha — no color modification, just alpha\n gl.uniform4f(prog._colorLoc!, 1, 1, 1, this._globalAlpha);\n\n // Standard alpha blending (not premultiplied for image textures)\n const stride = 16; // 4 floats × 4 bytes\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, stride, 0);\n gl.enableVertexAttribArray(prog._texCoordLoc);\n gl.vertexAttribPointer(prog._texCoordLoc, 2, gl.FLOAT, false, stride, 8);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.uniform1i(prog._textureLoc, 0);\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Disable texcoord attrib to avoid interfering with flat shader\n gl.disableVertexAttribArray(prog._texCoordLoc);\n }\n\n private _getOrUploadTexture(image: CanvasImageSource, imgW: number, imgH: number): WebGLTexture {\n const gl = this._gl;\n const key = image as unknown as object;\n const cached = this._imageTexCache.get(key);\n\n // HTMLImageElement/SVGImageElement: upload once, cache permanently\n // HTMLCanvasElement/OffscreenCanvas: always re-upload (content may change)\n const isImage = (image instanceof HTMLImageElement) || (image instanceof SVGImageElement);\n\n if (cached) {\n if (cached._isImage) {\n // Static image — reuse cached texture\n return cached._tex;\n }\n // Canvas source — re-upload to existing texture\n gl.bindTexture(gl.TEXTURE_2D, cached._tex);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image as TexImageSource);\n return cached._tex;\n }\n\n // Create new texture\n const tex = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\n // Detect if we need to handle alpha properly\n // For canvas sources, use standard upload; for images, avoid premultiply\n if (imgW > 0 && imgH > 0) {\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image as TexImageSource);\n }\n\n this._imageTexCache.set(key, { _tex: tex, _isImage: isImage });\n return tex;\n }\n\n private _applyClip(): void {\n const gl = this._gl;\n if (this._pendingClipRect) {\n const [x, y, w, h] = this._pendingClipRect;\n gl.enable(gl.SCISSOR_TEST);\n // Convert canvas coords (top-left origin) to GL coords (bottom-left origin)\n gl.scissor(x, this._height - y - h, w, h);\n this._clipActive = true;\n this._clipRect = [x, y, w, h];\n }\n }\n\n private _fillText(text: string, x: number, y: number): void {\n this._renderText(text, x, y, 'fill');\n }\n\n private _strokeText(text: string, x: number, y: number): void {\n this._renderText(text, x, y, 'stroke');\n }\n\n private _renderText(text: string, x: number, y: number, mode: 'fill' | 'stroke'): void {\n const gl = this._gl;\n const tCtx = this._textCtx;\n\n // Configure text rendering context\n tCtx.font = this._font;\n tCtx.textAlign = 'left'; // Always render left-aligned, position via WebGL\n tCtx.textBaseline = 'top'; // Always render from top, adjust Y via offset\n if (this._letterSpacing) {\n tCtx.letterSpacing = this._letterSpacing;\n }\n\n // Measure text\n const metrics = tCtx.measureText(text);\n const textWidth = Math.ceil(metrics.width) + 4; // +4 for antialiasing padding\n const fontSize = _parseFontSize(this._font);\n const textHeight = Math.ceil(fontSize * 1.5) + 4; // approximate height with descenders\n\n if (textWidth <= 0 || textHeight <= 0) return;\n\n // Resize text canvas if needed\n if (this._textCanvas.width < textWidth || this._textCanvas.height < textHeight) {\n this._textCanvas.width = Math.max(this._textCanvas.width, textWidth);\n this._textCanvas.height = Math.max(this._textCanvas.height, textHeight);\n // Re-set font after resize (context is reset)\n tCtx.font = this._font;\n tCtx.textAlign = 'left';\n tCtx.textBaseline = 'top';\n }\n\n // Clear and render text\n tCtx.clearRect(0, 0, this._textCanvas.width, this._textCanvas.height);\n\n if (mode === 'fill') {\n tCtx.fillStyle = 'white'; // White text, tinted by WebGL uniform\n tCtx.fillText(text, 2, 2); // +2 padding offset\n } else {\n tCtx.strokeStyle = 'white';\n tCtx.lineWidth = this._lineWidth;\n tCtx.strokeText(text, 2, 2);\n }\n\n // Upload text canvas to texture\n gl.bindTexture(gl.TEXTURE_2D, this._textTexture);\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);\n gl.texImage2D(\n gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,\n this._textCanvas\n );\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0);\n\n // Compute text position adjustments\n const color = mode === 'fill' ? this._fillColor : this._strokeColor;\n let drawX = x - 2; // compensate for padding\n let drawY = y - 2;\n\n // Adjust for textAlign\n switch (this._textAlign) {\n case 'center': drawX -= textWidth / 2; break;\n case 'right':\n case 'end': drawX -= textWidth; break;\n }\n\n // Adjust for textBaseline\n switch (this._textBaseline) {\n case 'top': /* drawY stays */ break;\n case 'middle': drawY -= textHeight / 2; break;\n case 'alphabetic':\n case 'ideographic': drawY -= fontSize; break;\n case 'bottom':\n case 'hanging': drawY -= textHeight; break;\n }\n\n // Draw textured quad\n this._drawTexturedQuad(\n drawX, drawY, textWidth, textHeight,\n textWidth / this._textCanvas.width,\n textHeight / this._textCanvas.height,\n color\n );\n }\n\n private _drawTexturedQuad(\n x: number, y: number, w: number, h: number,\n uMax: number, vMax: number,\n color: Float32Array\n ): void {\n const gl = this._gl;\n const prog = this._textured;\n\n // Interleaved position + texcoord (x, y, u, v)\n const verts = new Float32Array([\n x, y, 0, 0,\n x + w, y, uMax, 0,\n x, y + h, 0, vMax,\n x, y + h, 0, vMax,\n x + w, y, uMax, 0,\n x + w, y + h, uMax, vMax,\n ]);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this._texturedVBO);\n gl.bufferData(gl.ARRAY_BUFFER, verts, gl.DYNAMIC_DRAW);\n\n gl.useProgram(prog._program);\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, color, this._globalAlpha);\n\n // Use premultiplied alpha blending for text\n gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n\n const stride = 16; // 4 floats × 4 bytes\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, stride, 0);\n gl.enableVertexAttribArray(prog._texCoordLoc);\n gl.vertexAttribPointer(prog._texCoordLoc, 2, gl.FLOAT, false, stride, 8);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this._textTexture);\n gl.uniform1i(prog._textureLoc, 0);\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Restore standard blending\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n\n // Disable texcoord attrib to avoid interfering with flat shader\n gl.disableVertexAttribArray(prog._texCoordLoc);\n }\n\n // -------------------------------------------------------------------------\n // Private: state management\n // -------------------------------------------------------------------------\n\n private _save(): void {\n this._matrix.save();\n this._stateStack.push({\n _fillColor: new Float32Array(this._fillColor),\n _strokeColor: new Float32Array(this._strokeColor),\n _lineWidth: this._lineWidth,\n _globalAlpha: this._globalAlpha,\n _font: this._font,\n _textAlign: this._textAlign,\n _textBaseline: this._textBaseline,\n _lineCap: this._lineCap,\n _lineJoin: this._lineJoin,\n _imageSmoothingEnabled: this._imageSmoothingEnabled,\n _letterSpacing: this._letterSpacing,\n _clipActive: this._clipActive,\n _clipRect: this._clipRect ? [...this._clipRect] as [number, number, number, number] : null,\n });\n }\n\n private _restore(): void {\n this._matrix.restore();\n const gl = this._gl;\n const state = this._stateStack.pop();\n if (state) {\n this._fillColor = state._fillColor;\n this._strokeColor = state._strokeColor;\n this._lineWidth = state._lineWidth;\n this._globalAlpha = state._globalAlpha;\n this._font = state._font;\n this._textAlign = state._textAlign;\n this._textBaseline = state._textBaseline;\n this._lineCap = state._lineCap;\n this._lineJoin = state._lineJoin;\n this._imageSmoothingEnabled = state._imageSmoothingEnabled;\n this._letterSpacing = state._letterSpacing;\n this._clipActive = state._clipActive;\n this._clipRect = state._clipRect;\n\n // Restore scissor state\n if (this._clipActive && this._clipRect) {\n const [x, y, w, h] = this._clipRect;\n gl.enable(gl.SCISSOR_TEST);\n gl.scissor(x, this._height - y - h, w, h);\n } else {\n gl.disable(gl.SCISSOR_TEST);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: WebGL helpers\n // -------------------------------------------------------------------------\n\n private _setColorUniform(loc: WebGLUniformLocation, color: Float32Array, alpha: number): void {\n // Premultiply globalAlpha into the color's alpha channel\n const a = color[3] * alpha;\n this._gl.uniform4f(loc, color[0], color[1], color[2], a);\n }\n\n private _createProgram(vSrc: string, fSrc: string, hasTexCoord: boolean): _ProgramInfo {\n const gl = this._gl;\n const vs = this._compileShader(gl.VERTEX_SHADER, vSrc);\n const fs = this._compileShader(gl.FRAGMENT_SHADER, fSrc);\n\n const program = gl.createProgram()!;\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n throw new Error('Shader link failed: ' + gl.getProgramInfoLog(program));\n }\n\n // Delete shaders after linking (they're embedded in the program now)\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n return {\n _program: program,\n _matrixLoc: gl.getUniformLocation(program, 'u_matrix'),\n _colorLoc: gl.getUniformLocation(program, 'u_color'),\n _textureLoc: hasTexCoord ? gl.getUniformLocation(program, 'u_texture') : null,\n _positionLoc: gl.getAttribLocation(program, 'a_position'),\n _texCoordLoc: hasTexCoord ? gl.getAttribLocation(program, 'a_texCoord') : -1,\n };\n }\n\n private _compileShader(type: number, source: string): WebGLShader {\n const gl = this._gl;\n const shader = gl.createShader(type)!;\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader);\n gl.deleteShader(shader);\n throw new Error('Shader compile failed: ' + info);\n }\n return shader;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Utility\n// ---------------------------------------------------------------------------\n\n/** Extract numeric font size from a CSS font string like \"bold 20px monospace\". */\nfunction _parseFontSize(font: string): number {\n const match = font.match(/(\\d+(?:\\.\\d+)?)\\s*px/);\n return match ? parseFloat(match[1]) : 10;\n}\n\n/** Get width of a CanvasImageSource (handles HTMLImageElement, HTMLCanvasElement, OffscreenCanvas, etc.) */\nfunction _getImageWidth(img: CanvasImageSource): number {\n if ('naturalWidth' in img) return (img as HTMLImageElement).naturalWidth;\n return (img as HTMLCanvasElement | OffscreenCanvas).width;\n}\n\n/** Get height of a CanvasImageSource. */\nfunction _getImageHeight(img: CanvasImageSource): number {\n if ('naturalHeight' in img) return (img as HTMLImageElement).naturalHeight;\n return (img as HTMLCanvasElement | OffscreenCanvas).height;\n}\n","/**\n * UltrafastRenderer — WebGL2 Triple-Buffered Canvas 2D Renderer\n *\n * A standalone WebGL-accelerated Canvas 2D rendering engine. Provides a\n * CanvasAPI for recording draw commands and a triple-buffered FBO pipeline\n * that displays them via a passthrough shader at vsync rate.\n *\n * Triple buffer scheme (all on main thread, lock-free via JS single-threading):\n *\n * Content submission:\n * submitBatch(commands)\n * → bind writeFBO\n * → Canvas2DShim executes commands as WebGL draw calls\n * → swap: writeFBO ↔ readyFBO\n *\n * Display loop (vsync rate via RAF):\n * RAF callback\n * → auto-flush: drain CanvasAPI commands → submitBatch\n * → bind default framebuffer (display canvas)\n * → read readyFBO texture → passthrough blit → screen\n *\n * Extension points for downstream consumers (e.g. maalata CRT display):\n * - getGL(): access the WebGL2 context\n * - getReadyTexture(): read the latest rendered frame as a texture\n * - stopDisplay() / startDisplay(): take over the display loop\n */\n\nimport { CanvasAPI, type CanvasCommand } from './canvas-api';\nimport { Canvas2DShim } from './canvas2d-shim';\nimport {\n PASSTHROUGH_VERTEX_SRC,\n PASSTHROUGH_FRAGMENT_SRC,\n} from './shaders';\n\ninterface _FBO {\n _fbo: WebGLFramebuffer;\n _texture: WebGLTexture;\n}\n\nexport class UltrafastRenderer {\n private _gl: WebGL2RenderingContext;\n private _canvas: HTMLCanvasElement;\n private _shim: Canvas2DShim;\n private _api: CanvasAPI;\n private _rafId: number | null = null;\n\n // Triple buffer: three FBOs with color texture attachments\n private _fbos!: [_FBO, _FBO, _FBO];\n private _writeIdx = 0;\n private _readyIdx = 1;\n private _displayIdx = 2;\n private _hasContent = false;\n\n // Display program\n private _passthroughProgram: WebGLProgram;\n\n // Fullscreen quad VBO\n private _quadVBO!: WebGLBuffer;\n private _quadPositionLoc = -1;\n\n constructor(canvas: HTMLCanvasElement) {\n this._canvas = canvas;\n this._api = new CanvasAPI();\n\n // Create WebGL2 context with optimizations\n const gl = canvas.getContext('webgl2', {\n alpha: false,\n antialias: false,\n desynchronized: true,\n preserveDrawingBuffer: true,\n powerPreference: 'high-performance',\n });\n\n if (!gl) {\n throw new Error('WebGL2 not supported');\n }\n this._gl = gl;\n\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\n\n // Initialize triple buffer FBOs\n this._initFBOs();\n\n // Initialize Canvas 2D shim (uses same GL context)\n this._shim = new Canvas2DShim(gl, canvas.width, canvas.height);\n\n // Initialize passthrough display program\n this._passthroughProgram = this._createShaderProgram(\n PASSTHROUGH_VERTEX_SRC, PASSTHROUGH_FRAGMENT_SRC\n );\n\n // Initialize fullscreen quad VBO for display pass\n this._initQuadVBO();\n\n // Clear all FBOs to black initially\n this._clearAllFBOs();\n\n // Auto-start display loop\n this.startDisplay();\n }\n\n // -------------------------------------------------------------------------\n // Public API (no _ prefix: cross-file access safe from mangleProps)\n // -------------------------------------------------------------------------\n\n /** Get the CanvasAPI for recording draw commands. */\n getCanvasAPI(): CanvasAPI {\n return this._api;\n }\n\n /**\n * Submit a batch of Canvas 2D commands to be rendered into the write FBO.\n * After rendering, the write and ready FBOs are swapped so the display\n * loop picks up the latest frame.\n */\n submitBatch(commands: CanvasCommand[]): void {\n if (commands.length === 0) return;\n const gl = this._gl;\n\n // Bind write FBO as render target\n gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbos[this._writeIdx]._fbo);\n gl.viewport(0, 0, this._canvas.width, this._canvas.height);\n\n // Execute Canvas 2D commands as WebGL draw calls\n this._shim.executeBatch(commands);\n\n // Swap write ↔ ready (new frame becomes available for display)\n const tmp = this._writeIdx;\n this._writeIdx = this._readyIdx;\n this._readyIdx = tmp;\n this._hasContent = true;\n }\n\n /** Start the passthrough RAF display loop with auto-flush. */\n startDisplay(): void {\n if (this._rafId !== null) return;\n this._displayLoop();\n }\n\n /** Stop the passthrough RAF display loop. Last frame persists (preserveDrawingBuffer). */\n stopDisplay(): void {\n if (this._rafId !== null) {\n cancelAnimationFrame(this._rafId);\n this._rafId = null;\n }\n }\n\n /** Returns the display canvas element. */\n getCanvas(): HTMLCanvasElement {\n return this._canvas;\n }\n\n /** Get canvas dimensions. */\n getCanvasSize(): { width: number; height: number } {\n return { width: this._canvas.width, height: this._canvas.height };\n }\n\n /** Capture the current displayed frame as an ImageBitmap. */\n screenshot(): Promise<ImageBitmap> {\n this._renderDisplay();\n return createImageBitmap(this._canvas);\n }\n\n /** Clean up all WebGL resources. */\n destroy(): void {\n this.stopDisplay();\n const gl = this._gl;\n\n this._shim.destroy();\n\n for (const fbo of this._fbos) {\n gl.deleteFramebuffer(fbo._fbo);\n gl.deleteTexture(fbo._texture);\n }\n\n gl.deleteProgram(this._passthroughProgram);\n gl.deleteBuffer(this._quadVBO);\n\n const ext = gl.getExtension('WEBGL_lose_context');\n if (ext) ext.loseContext();\n }\n\n // -------------------------------------------------------------------------\n // Extension points (used by maalata CRT display)\n // -------------------------------------------------------------------------\n\n /** Returns the WebGL2 context for external rendering (e.g. CRT shader). */\n getGL(): WebGL2RenderingContext {\n return this._gl;\n }\n\n /** Returns the ready FBO's texture — the latest fully rendered frame. */\n getReadyTexture(): WebGLTexture {\n return this._fbos[this._readyIdx]._texture;\n }\n\n // -------------------------------------------------------------------------\n // Private: display loop\n // -------------------------------------------------------------------------\n\n private _displayLoop(): void {\n this._rafId = requestAnimationFrame(() => this._displayLoop());\n\n // Auto-flush: drain any pending CanvasAPI commands into the pipeline\n const cmds = this._api.takeCommands();\n if (cmds.length) this.submitBatch(cmds);\n\n this._renderDisplay();\n }\n\n /**\n * Render the ready FBO to the display canvas via passthrough shader.\n * Called at vsync rate by RAF, or once synchronously for screenshots.\n */\n private _renderDisplay(): void {\n if (!this._hasContent) return;\n\n const gl = this._gl;\n\n // Bind default framebuffer (display canvas backbuffer)\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, this._canvas.width, this._canvas.height);\n\n // Bind the ready FBO's texture as input\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this._fbos[this._readyIdx]._texture);\n\n gl.useProgram(this._passthroughProgram);\n\n // Draw fullscreen quad\n gl.bindBuffer(gl.ARRAY_BUFFER, this._quadVBO);\n gl.enableVertexAttribArray(this._quadPositionLoc);\n gl.vertexAttribPointer(this._quadPositionLoc, 2, gl.FLOAT, false, 0, 0);\n\n gl.disable(gl.BLEND);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n gl.enable(gl.BLEND);\n }\n\n // -------------------------------------------------------------------------\n // Private: initialization\n // -------------------------------------------------------------------------\n\n private _initFBOs(): void {\n this._fbos = [\n this._createFBO(),\n this._createFBO(),\n this._createFBO(),\n ];\n }\n\n private _createFBO(): _FBO {\n const gl = this._gl;\n const w = this._canvas.width;\n const h = this._canvas.height;\n\n const fbo = gl.createFramebuffer()!;\n gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);\n\n const texture = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, w, h);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);\n\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error('Framebuffer incomplete: 0x' + status.toString(16));\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n return { _fbo: fbo, _texture: texture };\n }\n\n private _clearAllFBOs(): void {\n const gl = this._gl;\n for (const fbo of this._fbos) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, fbo._fbo);\n gl.clearColor(0, 0, 0, 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.clearColor(0, 0, 0, 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n\n private _initQuadVBO(): void {\n const gl = this._gl;\n\n this._quadVBO = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, this._quadVBO);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([\n 0, 0, 1, 0, 0, 1,\n 0, 1, 1, 0, 1, 1,\n ]), gl.STATIC_DRAW);\n\n this._quadPositionLoc = gl.getAttribLocation(this._passthroughProgram, 'a_position');\n }\n\n // -------------------------------------------------------------------------\n // Private: shader helpers\n // -------------------------------------------------------------------------\n\n private _createShaderProgram(vSrc: string, fSrc: string): WebGLProgram {\n const gl = this._gl;\n const vs = this._compileShader(gl.VERTEX_SHADER, vSrc);\n const fs = this._compileShader(gl.FRAGMENT_SHADER, fSrc);\n\n const program = gl.createProgram()!;\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n throw new Error('Shader link failed: ' + gl.getProgramInfoLog(program));\n }\n\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n return program;\n }\n\n private _compileShader(type: number, source: string): WebGLShader {\n const gl = this._gl;\n const shader = gl.createShader(type)!;\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader);\n gl.deleteShader(shader);\n throw new Error('Shader compile failed: ' + info);\n }\n return shader;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"canvas-ultrafast.es.js","sources":["../src/canvas-api.ts","../src/matrix-stack.ts","../src/color-parser.ts","../src/shaders.ts","../src/canvas2d-shim.ts","../src/renderer.ts"],"sourcesContent":["/**\n * Canvas API Wrapper\n *\n * Provides a Canvas 2D API that records commands locally without await.\n * Commands are batched and sent to the worker for execution.\n */\n\ntype CanvasPropertyMap = {\n fillStyle: string | CanvasGradient | CanvasPattern;\n strokeStyle: string | CanvasGradient | CanvasPattern;\n lineWidth: number;\n lineCap: CanvasLineCap;\n lineJoin: CanvasLineJoin;\n miterLimit: number;\n lineDashOffset: number;\n font: string;\n textAlign: CanvasTextAlign;\n textBaseline: CanvasTextBaseline;\n globalAlpha: number;\n globalCompositeOperation: GlobalCompositeOperation;\n shadowBlur: number;\n shadowColor: string;\n shadowOffsetX: number;\n shadowOffsetY: number;\n imageSmoothingEnabled: boolean;\n letterSpacing: string;\n};\n\nexport type CanvasCommand =\n | { type: 'property'; name: string; value: unknown }\n | { type: 'method'; name: string; args: unknown[] };\n\nexport class CanvasAPI {\n private _c: CanvasCommand[] = [];\n private _cp: Partial<CanvasPropertyMap> = {};\n\n private _m(n: string, ...a: unknown[]): void {\n this._c.push({ type: 'method', name: n, args: a });\n }\n\n private _p<K extends keyof CanvasPropertyMap>(n: K, v: CanvasPropertyMap[K]): void {\n this._cp[n] = v;\n this._c.push({ type: 'property', name: n, value: v });\n }\n\n /**\n * Drain and return all buffered commands.\n * No _ prefix: called cross-file from pipeline, must survive mangleProps.\n */\n takeCommands(): CanvasCommand[] {\n if (this._c.length === 0) return [];\n const cmds = this._c;\n this._c = [];\n return cmds;\n }\n\n // Canvas 2D API methods\n\n // State\n save(): void { this._m('save'); }\n restore(): void { this._m('restore'); }\n\n // Transform\n scale(x: number, y: number): void { this._m('scale', x, y); }\n rotate(angle: number): void { this._m('rotate', angle); }\n translate(x: number, y: number): void { this._m('translate', x, y); }\n transform(a: number, b: number, c: number, d: number, e: number, f: number): void { this._m('transform', a, b, c, d, e, f); }\n setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void { this._m('setTransform', a, b, c, d, e, f); }\n resetTransform(): void { this._m('resetTransform'); }\n\n // Rectangles\n clearRect(x: number, y: number, width: number, height: number): void { this._m('clearRect', x, y, width, height); }\n fillRect(x: number, y: number, width: number, height: number): void { this._m('fillRect', x, y, width, height); }\n strokeRect(x: number, y: number, width: number, height: number): void { this._m('strokeRect', x, y, width, height); }\n\n // Text\n fillText(text: string, x: number, y: number, maxWidth?: number): void {\n this._m('fillText', ...(maxWidth !== undefined ? [text, x, y, maxWidth] : [text, x, y]));\n }\n\n strokeText(text: string, x: number, y: number, maxWidth?: number): void {\n this._m('strokeText', ...(maxWidth !== undefined ? [text, x, y, maxWidth] : [text, x, y]));\n }\n\n /** Synchronous text measurement — cannot go through the async command pipeline. */\n private _measureCtx: OffscreenCanvasRenderingContext2D | null = null;\n\n measureText(text: string): TextMetrics {\n if (!this._measureCtx) {\n this._measureCtx = new OffscreenCanvas(1, 1).getContext('2d')!;\n }\n this._measureCtx.font = this.font;\n return this._measureCtx.measureText(text);\n }\n\n // Line drawing\n beginPath(): void { this._m('beginPath'); }\n closePath(): void { this._m('closePath'); }\n moveTo(x: number, y: number): void { this._m('moveTo', x, y); }\n lineTo(x: number, y: number): void { this._m('lineTo', x, y); }\n\n bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void {\n this._m('bezierCurveTo', cp1x, cp1y, cp2x, cp2y, x, y);\n }\n\n quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void { this._m('quadraticCurveTo', cpx, cpy, x, y); }\n\n arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void {\n this._m('arc', ...(counterclockwise !== undefined ? [x, y, radius, startAngle, endAngle, counterclockwise] : [x, y, radius, startAngle, endAngle]));\n }\n\n arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void { this._m('arcTo', x1, y1, x2, y2, radius); }\n\n ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void {\n this._m('ellipse', ...(counterclockwise !== undefined ? [x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise] : [x, y, radiusX, radiusY, rotation, startAngle, endAngle]));\n }\n\n rect(x: number, y: number, width: number, height: number): void { this._m('rect', x, y, width, height); }\n\n // Images\n drawImage(image: CanvasImageSource, dx: number, dy: number): void;\n drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;\n drawImage(image: CanvasImageSource, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void;\n drawImage(...args: [CanvasImageSource, ...number[]]): void {\n this._m('drawImage', ...args);\n }\n\n // Fill and stroke\n fill(): void { this._m('fill'); }\n stroke(): void { this._m('stroke'); }\n clip(): void { this._m('clip'); }\n\n // Properties (setters)\n set fillStyle(value: string | CanvasGradient | CanvasPattern) { this._p('fillStyle', value); }\n set strokeStyle(value: string | CanvasGradient | CanvasPattern) { this._p('strokeStyle', value); }\n set lineWidth(value: number) { this._p('lineWidth', value); }\n set lineCap(value: CanvasLineCap) { this._p('lineCap', value); }\n set lineJoin(value: CanvasLineJoin) { this._p('lineJoin', value); }\n set miterLimit(value: number) { this._p('miterLimit', value); }\n set lineDashOffset(value: number) { this._p('lineDashOffset', value); }\n set font(value: string) { this._p('font', value); }\n set textAlign(value: CanvasTextAlign) { this._p('textAlign', value); }\n set textBaseline(value: CanvasTextBaseline) { this._p('textBaseline', value); }\n set globalAlpha(value: number) { this._p('globalAlpha', value); }\n set globalCompositeOperation(value: GlobalCompositeOperation) { this._p('globalCompositeOperation', value); }\n set shadowBlur(value: number) { this._p('shadowBlur', value); }\n set shadowColor(value: string) { this._p('shadowColor', value); }\n set shadowOffsetX(value: number) { this._p('shadowOffsetX', value); }\n set shadowOffsetY(value: number) { this._p('shadowOffsetY', value); }\n set imageSmoothingEnabled(value: boolean) { this._p('imageSmoothingEnabled', value); }\n set letterSpacing(value: string) { this._p('letterSpacing', value); }\n\n // Property getters (return local cached values)\n get fillStyle() { return this._cp['fillStyle'] ?? '#000'; }\n get strokeStyle() { return this._cp['strokeStyle'] ?? '#000'; }\n get lineWidth() { return this._cp['lineWidth'] ?? 1; }\n get lineCap() { return this._cp['lineCap'] ?? 'butt'; }\n get lineJoin() { return this._cp['lineJoin'] ?? 'miter'; }\n get miterLimit() { return this._cp['miterLimit'] ?? 10; }\n get lineDashOffset() { return this._cp['lineDashOffset'] ?? 0; }\n get font() { return this._cp['font'] ?? '10px sans-serif'; }\n get textAlign() { return this._cp['textAlign'] ?? 'start'; }\n get textBaseline() { return this._cp['textBaseline'] ?? 'alphabetic'; }\n get globalAlpha() { return this._cp['globalAlpha'] ?? 1; }\n get globalCompositeOperation() { return this._cp['globalCompositeOperation'] ?? 'source-over'; }\n get shadowBlur() { return this._cp['shadowBlur'] ?? 0; }\n get shadowColor() { return this._cp['shadowColor'] ?? 'rgba(0, 0, 0, 0)'; }\n get shadowOffsetX() { return this._cp['shadowOffsetX'] ?? 0; }\n get shadowOffsetY() { return this._cp['shadowOffsetY'] ?? 0; }\n get imageSmoothingEnabled() { return this._cp['imageSmoothingEnabled'] ?? true; }\n get letterSpacing() { return this._cp['letterSpacing'] ?? ''; }\n}","/**\n * 3×3 Affine Transform Matrix Stack\n *\n * Replicates Canvas 2D's save()/restore()/translate()/rotate()/scale()\n * as a matrix stack for WebGL uniform upload.\n *\n * Matrices are 3×3 column-major (for gl.uniformMatrix3fv), representing\n * 2D affine transforms. The base matrix includes an orthographic projection\n * that maps canvas pixel coordinates (top-left origin, Y-down) to WebGL\n * clip space ([-1,1], Y-up).\n *\n * Column-major layout of a 3×3 affine matrix:\n * [0] [3] [6] a c tx\n * [1] [4] [7] = b d ty\n * [2] [5] [8] 0 0 1\n */\n\nexport class MatrixStack {\n private _stack: Float32Array[] = [];\n private _current: Float32Array;\n private _projection: Float32Array;\n\n /**\n * @param width Canvas width in pixels\n * @param height Canvas height in pixels\n */\n constructor(width: number, height: number) {\n this._projection = _ortho(width, height);\n this._current = new Float32Array(this._projection);\n }\n\n /** Push current matrix onto the stack. No _ prefix: cross-file. */\n save(): void {\n this._stack.push(new Float32Array(this._current));\n }\n\n /** Pop and restore the top matrix. No _ prefix: cross-file. */\n restore(): void {\n if (this._stack.length > 0) {\n this._current = this._stack.pop()!;\n }\n }\n\n /** Translate the current matrix. No _ prefix: cross-file. */\n translate(x: number, y: number): void {\n // Multiply current matrix by translation:\n // 1 0 tx\n // 0 1 ty\n // 0 0 1\n // In column-major: m[6] += m[0]*tx + m[3]*ty\n // m[7] += m[1]*tx + m[4]*ty\n const m = this._current;\n m[6] += m[0] * x + m[3] * y;\n m[7] += m[1] * x + m[4] * y;\n }\n\n /** Rotate the current matrix by angle (radians). No _ prefix: cross-file. */\n rotate(angle: number): void {\n const c = Math.cos(angle);\n const s = Math.sin(angle);\n const m = this._current;\n const m0 = m[0], m1 = m[1], m3 = m[3], m4 = m[4];\n m[0] = m0 * c + m3 * s;\n m[1] = m1 * c + m4 * s;\n m[3] = m0 * -s + m3 * c;\n m[4] = m1 * -s + m4 * c;\n }\n\n /** Scale the current matrix. No _ prefix: cross-file. */\n scale(x: number, y: number): void {\n const m = this._current;\n m[0] *= x; m[1] *= x;\n m[3] *= y; m[4] *= y;\n }\n\n /**\n * Multiply current matrix by an arbitrary 2D affine transform.\n * Canvas 2D transform(a, b, c, d, e, f) matrix:\n * a c e\n * b d f\n * 0 0 1\n * No _ prefix: cross-file.\n */\n transform(a: number, b: number, c: number, d: number, e: number, f: number): void {\n const m = this._current;\n const m0 = m[0], m1 = m[1], m3 = m[3], m4 = m[4], m6 = m[6], m7 = m[7];\n m[0] = m0 * a + m3 * b;\n m[1] = m1 * a + m4 * b;\n m[3] = m0 * c + m3 * d;\n m[4] = m1 * c + m4 * d;\n m[6] = m0 * e + m3 * f + m6;\n m[7] = m1 * e + m4 * f + m7;\n }\n\n /**\n * Reset to projection then apply the given affine transform.\n * Canvas 2D setTransform(a, b, c, d, e, f).\n * No _ prefix: cross-file.\n */\n setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void {\n this._current.set(this._projection);\n this.transform(a, b, c, d, e, f);\n }\n\n /** Reset to the base orthographic projection. No _ prefix: cross-file. */\n resetTransform(): void {\n this._current.set(this._projection);\n }\n\n /**\n * Update canvas dimensions (e.g., on resize).\n * Recomputes the projection and resets the current matrix.\n * No _ prefix: cross-file.\n */\n resize(width: number, height: number): void {\n this._projection = _ortho(width, height);\n this._current = new Float32Array(this._projection);\n this._stack = [];\n }\n\n /**\n * Returns the current 3×3 matrix for gl.uniformMatrix3fv.\n * No _ prefix: cross-file.\n */\n getMatrix(): Float32Array {\n return this._current;\n }\n}\n\n/**\n * Create an orthographic projection matrix that maps:\n * Canvas coords (0,0)=top-left, (w,h)=bottom-right, Y-down\n * → Clip space (-1,-1)=bottom-left, (1,1)=top-right, Y-up\n *\n * The transform is:\n * x_clip = x * 2/w - 1\n * y_clip = -(y * 2/h - 1) = 1 - y * 2/h\n *\n * Column-major 3×3:\n * 2/w 0 -1\n * 0 -2/h 1\n * 0 0 1\n */\nfunction _ortho(w: number, h: number): Float32Array {\n return new Float32Array([\n 2 / w, 0, 0, // column 0\n 0, -2 / h, 0, // column 1\n -1, 1, 1, // column 2\n ]);\n}\n","/**\n * CSS Color Parser\n *\n * Converts CSS color strings to Float32Array [r, g, b, a] in [0, 1] range\n * for use as WebGL uniform values.\n *\n * Supported formats:\n * - Hex: #rgb, #rrggbb, #rrggbbaa\n * - Functional: rgb(r, g, b), rgba(r, g, b, a)\n * - Named: basic CSS color keywords\n *\n * Includes a cache for repeated lookups (the demo reuses ~10 colors).\n */\n\nconst _NAMED_COLORS: Record<string, number> = {\n black: 0x000000ff,\n white: 0xffffffff,\n red: 0xff0000ff,\n green: 0x008000ff,\n blue: 0x0000ffff,\n yellow: 0xffff00ff,\n cyan: 0x00ffffff,\n magenta: 0xff00ffff,\n orange: 0xffa500ff,\n transparent: 0x00000000,\n};\n\nconst _cache = new Map<string, Float32Array>();\n\n/**\n * Parse a CSS color string into [r, g, b, a] floats in [0, 1].\n * Returns a cached Float32Array — do NOT mutate the result.\n *\n * No _ prefix: called cross-file from canvas2d-shim.\n */\nexport function parseColor(css: string): Float32Array {\n const cached = _cache.get(css);\n if (cached) return cached;\n\n const result = _parse(css);\n _cache.set(css, result);\n return result;\n}\n\nfunction _parse(css: string): Float32Array {\n const s = css.trim();\n\n // #hex\n if (s.charCodeAt(0) === 0x23) { // '#'\n return _parseHex(s);\n }\n\n // rgb() / rgba()\n if (s.charCodeAt(0) === 0x72) { // 'r'\n return _parseRgb(s);\n }\n\n // Named color\n const named = _NAMED_COLORS[s.toLowerCase()];\n if (named !== undefined) {\n return new Float32Array([\n ((named >>> 24) & 0xff) / 255,\n ((named >>> 16) & 0xff) / 255,\n ((named >>> 8) & 0xff) / 255,\n (named & 0xff) / 255,\n ]);\n }\n\n // Fallback: opaque black\n return new Float32Array([0, 0, 0, 1]);\n}\n\nfunction _parseHex(s: string): Float32Array {\n const len = s.length;\n\n if (len === 4) {\n // #rgb → expand to #rrggbb\n const r = parseInt(s[1], 16);\n const g = parseInt(s[2], 16);\n const b = parseInt(s[3], 16);\n return new Float32Array([\n (r * 17) / 255,\n (g * 17) / 255,\n (b * 17) / 255,\n 1,\n ]);\n }\n\n if (len === 7) {\n // #rrggbb\n const r = parseInt(s.slice(1, 3), 16);\n const g = parseInt(s.slice(3, 5), 16);\n const b = parseInt(s.slice(5, 7), 16);\n return new Float32Array([r / 255, g / 255, b / 255, 1]);\n }\n\n if (len === 9) {\n // #rrggbbaa\n const r = parseInt(s.slice(1, 3), 16);\n const g = parseInt(s.slice(3, 5), 16);\n const b = parseInt(s.slice(5, 7), 16);\n const a = parseInt(s.slice(7, 9), 16);\n return new Float32Array([r / 255, g / 255, b / 255, a / 255]);\n }\n\n // #rgba (4-digit with alpha)\n if (len === 5) {\n const r = parseInt(s[1], 16);\n const g = parseInt(s[2], 16);\n const b = parseInt(s[3], 16);\n const a = parseInt(s[4], 16);\n return new Float32Array([\n (r * 17) / 255,\n (g * 17) / 255,\n (b * 17) / 255,\n (a * 17) / 255,\n ]);\n }\n\n return new Float32Array([0, 0, 0, 1]);\n}\n\nfunction _parseRgb(s: string): Float32Array {\n // Match both rgb(...) and rgba(...)\n // Extract the numeric values between parentheses\n const start = s.indexOf('(');\n const end = s.lastIndexOf(')');\n if (start === -1 || end === -1) return new Float32Array([0, 0, 0, 1]);\n\n const parts = s.slice(start + 1, end).split(',');\n const r = parseFloat(parts[0]) / 255;\n const g = parseFloat(parts[1]) / 255;\n const b = parseFloat(parts[2]) / 255;\n const a = parts.length >= 4 ? parseFloat(parts[3]) : 1;\n\n return new Float32Array([r, g, b, a]);\n}\n","/**\n * GLSL Shader Sources for canvas-ultrafast\n *\n * Content shaders (flat-color, textured) plus a passthrough display shader.\n * CRT post-processing shaders live in the maalata package.\n *\n * Coordinate convention:\n * - Content shaders use a 3x3 affine matrix (u_matrix) that maps\n * canvas pixel coordinates (top-left origin, Y-down) to clip space.\n * - Passthrough shader uses a fullscreen quad in [0,1] mapped to [-1,1] clip space.\n */\n\n// ---------------------------------------------------------------------------\n// Flat-color shader: rectangles, line quads, clear regions\n// ---------------------------------------------------------------------------\n\nexport const FLAT_VERTEX_SRC = `\n attribute vec2 a_position;\n uniform mat3 u_matrix;\n void main() {\n vec3 pos = u_matrix * vec3(a_position, 1.0);\n gl_Position = vec4(pos.xy, 0.0, 1.0);\n }\n`;\n\nexport const FLAT_FRAGMENT_SRC = `\n precision mediump float;\n uniform vec4 u_color;\n void main() {\n gl_FragColor = u_color;\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Textured quad shader: text rendering via OffscreenCanvas glyph upload\n// ---------------------------------------------------------------------------\n\nexport const TEXTURED_VERTEX_SRC = `\n attribute vec2 a_position;\n attribute vec2 a_texCoord;\n uniform mat3 u_matrix;\n varying vec2 v_texCoord;\n void main() {\n vec3 pos = u_matrix * vec3(a_position, 1.0);\n gl_Position = vec4(pos.xy, 0.0, 1.0);\n v_texCoord = a_texCoord;\n }\n`;\n\nexport const TEXTURED_FRAGMENT_SRC = `\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_texture;\n uniform vec4 u_color;\n void main() {\n vec4 texel = texture2D(u_texture, v_texCoord);\n gl_FragColor = texel * u_color;\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Passthrough display shader: fullscreen quad, reads FBO texture\n// ---------------------------------------------------------------------------\n\n/**\n * Vertex shader: fullscreen quad [0,1] → clip space [-1,1].\n * FBO textures are already in GL-native bottom-left origin (the orthographic\n * projection in matrix-stack.ts handles the canvas Y-down → GL Y-up flip),\n * so tex coords pass through without Y-flip.\n */\nexport const PASSTHROUGH_VERTEX_SRC = `\n attribute vec2 a_position;\n varying vec2 v_texCoord;\n void main() {\n v_texCoord = a_position;\n gl_Position = vec4(a_position * 2.0 - 1.0, 0, 1);\n }\n`;\n\n/**\n * Passthrough fragment shader: blit FBO texture to screen without effects.\n */\nexport const PASSTHROUGH_FRAGMENT_SRC = `\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_texture;\n void main() {\n gl_FragColor = texture2D(u_texture, v_texCoord);\n }\n`;\n","/**\n * Canvas 2D → WebGL Command Shim\n *\n * Translates CanvasCommand[] (recorded by CanvasAPI) into WebGL draw calls.\n * Handles the subset of Canvas 2D API used by the demo, plus reasonable\n * extensions. Operations not yet implemented log a warning and no-op.\n *\n * Rendering approach per command type:\n * - clearRect: gl.scissor + gl.clear\n * - fillRect: unit quad VBO + flat shader + transform uniform\n * - strokeRect: four thin quads (one per edge)\n * - fillText: render to OffscreenCanvas 2D → texImage2D → textured quad\n * - stroke(): expand line segments to quads on CPU, flat shader\n * - save/restore: matrix + state stack\n *\n * Text rendering uses an OffscreenCanvas with a 2D context as a glyph\n * rendering surface. At 8 FPS with ~5 text draws per frame, per-string\n * rendering (not glyph caching) is appropriate — texImage2D(OffscreenCanvas)\n * is a fast GPU upload path.\n */\n\nimport { CanvasCommand } from './canvas-api';\nimport { MatrixStack } from './matrix-stack';\nimport { parseColor } from './color-parser';\nimport {\n FLAT_VERTEX_SRC, FLAT_FRAGMENT_SRC,\n TEXTURED_VERTEX_SRC, TEXTURED_FRAGMENT_SRC,\n} from './shaders';\n\ninterface _DrawState {\n _fillColor: Float32Array;\n _strokeColor: Float32Array;\n _lineWidth: number;\n _globalAlpha: number;\n _font: string;\n _textAlign: CanvasTextAlign;\n _textBaseline: CanvasTextBaseline;\n _lineCap: CanvasLineCap;\n _lineJoin: CanvasLineJoin;\n _imageSmoothingEnabled: boolean;\n _letterSpacing: string;\n _clipActive: boolean;\n _clipRect: [number, number, number, number] | null;\n}\n\ninterface _ProgramInfo {\n _program: WebGLProgram;\n _matrixLoc: WebGLUniformLocation | null;\n _colorLoc: WebGLUniformLocation | null;\n _textureLoc: WebGLUniformLocation | null;\n _positionLoc: number;\n _texCoordLoc: number;\n}\n\nexport class Canvas2DShim {\n private _gl: WebGLRenderingContext;\n private _width: number;\n private _height: number;\n\n // Transform\n private _matrix: MatrixStack;\n\n // State\n private _fillColor: Float32Array = new Float32Array([0, 0, 0, 1]);\n private _strokeColor: Float32Array = new Float32Array([0, 0, 0, 1]);\n private _lineWidth = 1;\n private _globalAlpha = 1;\n private _font = '10px sans-serif';\n private _textAlign: CanvasTextAlign = 'start';\n private _textBaseline: CanvasTextBaseline = 'alphabetic';\n private _lineCap: CanvasLineCap = 'butt';\n private _lineJoin: CanvasLineJoin = 'miter';\n private _imageSmoothingEnabled = true;\n private _letterSpacing = '';\n private _clipActive = false;\n private _clipRect: [number, number, number, number] | null = null;\n private _pendingClipRect: [number, number, number, number] | null = null;\n private _imageTexCache = new WeakMap<object, { _tex: WebGLTexture; _isImage: boolean }>();\n private _stateStack: _DrawState[] = [];\n\n // Path state\n private _pathSegments: number[] = []; // flat: x0,y0,x1,y1,...\n private _currentX = 0;\n private _currentY = 0;\n private _subpathStartX = 0;\n private _subpathStartY = 0;\n\n // WebGL resources\n private _flat: _ProgramInfo;\n private _textured: _ProgramInfo;\n private _unitQuadVBO: WebGLBuffer;\n private _dynamicVBO: WebGLBuffer;\n private _texturedVBO: WebGLBuffer;\n private _textTexture: WebGLTexture;\n\n // Text rendering surface\n private _textCanvas: OffscreenCanvas;\n private _textCtx: OffscreenCanvasRenderingContext2D;\n\n // Background color for opaque canvas clear\n private _bgColor = new Float32Array([0, 0, 0]);\n\n // Temp arrays to avoid allocation in hot path\n private _tmpColor = new Float32Array(4);\n\n constructor(gl: WebGLRenderingContext, width: number, height: number) {\n this._gl = gl;\n this._width = width;\n this._height = height;\n this._matrix = new MatrixStack(width, height);\n\n // Compile shader programs\n this._flat = this._createProgram(\n FLAT_VERTEX_SRC, FLAT_FRAGMENT_SRC, false\n );\n this._textured = this._createProgram(\n TEXTURED_VERTEX_SRC, TEXTURED_FRAGMENT_SRC, true\n );\n\n // Unit quad VBO: two triangles covering [0,0]-[1,1]\n // Used for fillRect (scaled via matrix) and fullscreen blits\n this._unitQuadVBO = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, this._unitQuadVBO);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([\n 0, 0, 1, 0, 0, 1,\n 0, 1, 1, 0, 1, 1,\n ]), gl.STATIC_DRAW);\n\n // Dynamic VBO for line quads — uses orphaning for double-buffer\n this._dynamicVBO = gl.createBuffer()!;\n\n // Textured quad VBO: position + texcoord interleaved\n this._texturedVBO = gl.createBuffer()!;\n\n // Text rendering texture\n this._textTexture = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, this._textTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n // OffscreenCanvas for text glyph rendering\n this._textCanvas = new OffscreenCanvas(512, 128);\n this._textCtx = this._textCanvas.getContext('2d')!;\n\n // Enable blending for standard source-over compositing\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n }\n\n /**\n * Execute a batch of Canvas 2D commands as WebGL draw calls.\n * No _ prefix: called cross-file from webgl-renderer.\n */\n executeBatch(commands: CanvasCommand[]): void {\n for (const cmd of commands) {\n if (cmd.type === 'property') {\n this._setProperty(cmd.name, cmd.value);\n } else {\n this._callMethod(cmd.name, cmd.args);\n }\n }\n }\n\n /**\n * Set the opaque clear color for clearRect.\n * No _ prefix: called cross-file from renderer.\n */\n setBackgroundColor(r: number, g: number, b: number): void {\n this._bgColor[0] = r;\n this._bgColor[1] = g;\n this._bgColor[2] = b;\n }\n\n /**\n * Update canvas dimensions on resize.\n * No _ prefix: called cross-file.\n */\n resize(width: number, height: number): void {\n this._width = width;\n this._height = height;\n this._matrix.resize(width, height);\n }\n\n /**\n * Clean up WebGL resources.\n * No _ prefix: called cross-file.\n */\n destroy(): void {\n const gl = this._gl;\n gl.deleteBuffer(this._unitQuadVBO);\n gl.deleteBuffer(this._dynamicVBO);\n gl.deleteBuffer(this._texturedVBO);\n gl.deleteTexture(this._textTexture);\n gl.deleteProgram(this._flat._program);\n gl.deleteProgram(this._textured._program);\n }\n\n // -------------------------------------------------------------------------\n // Private: property handling\n // -------------------------------------------------------------------------\n\n private _setProperty(name: string, value: unknown): void {\n switch (name) {\n case 'fillStyle':\n this._fillColor = parseColor(value as string);\n break;\n case 'strokeStyle':\n this._strokeColor = parseColor(value as string);\n break;\n case 'lineWidth':\n this._lineWidth = value as number;\n break;\n case 'globalAlpha':\n this._globalAlpha = value as number;\n break;\n case 'font':\n this._font = value as string;\n break;\n case 'textAlign':\n this._textAlign = value as CanvasTextAlign;\n break;\n case 'textBaseline':\n this._textBaseline = value as CanvasTextBaseline;\n break;\n case 'lineCap':\n this._lineCap = value as CanvasLineCap;\n break;\n case 'lineJoin':\n this._lineJoin = value as CanvasLineJoin;\n break;\n case 'imageSmoothingEnabled':\n this._imageSmoothingEnabled = value as boolean;\n break;\n case 'letterSpacing':\n this._letterSpacing = value as string;\n break;\n default:\n // Unsupported properties: silently ignore\n break;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: method dispatch\n // -------------------------------------------------------------------------\n\n private _callMethod(name: string, args: unknown[]): void {\n switch (name) {\n // Rectangles\n case 'clearRect':\n this._clearRect(args[0] as number, args[1] as number, args[2] as number, args[3] as number);\n break;\n case 'fillRect':\n this._fillRect(args[0] as number, args[1] as number, args[2] as number, args[3] as number);\n break;\n case 'strokeRect':\n this._strokeRect(args[0] as number, args[1] as number, args[2] as number, args[3] as number);\n break;\n\n // Text\n case 'fillText':\n this._fillText(args[0] as string, args[1] as number, args[2] as number);\n break;\n case 'strokeText':\n this._strokeText(args[0] as string, args[1] as number, args[2] as number);\n break;\n\n // Images\n case 'drawImage':\n this._drawImage(args);\n break;\n\n // Path\n case 'beginPath':\n this._pathSegments = [];\n this._pendingClipRect = null;\n break;\n case 'closePath':\n if (this._currentX !== this._subpathStartX || this._currentY !== this._subpathStartY) {\n this._pathSegments.push(\n this._currentX, this._currentY,\n this._subpathStartX, this._subpathStartY\n );\n this._currentX = this._subpathStartX;\n this._currentY = this._subpathStartY;\n }\n break;\n case 'moveTo':\n this._currentX = this._subpathStartX = args[0] as number;\n this._currentY = this._subpathStartY = args[1] as number;\n break;\n case 'lineTo': {\n const x = args[0] as number;\n const y = args[1] as number;\n this._pathSegments.push(this._currentX, this._currentY, x, y);\n this._currentX = x;\n this._currentY = y;\n break;\n }\n case 'rect': {\n const rx = args[0] as number, ry = args[1] as number;\n const rw = args[2] as number, rh = args[3] as number;\n // Store as pending clip rect (used if clip() follows)\n this._pendingClipRect = [rx, ry, rw, rh];\n // Also add 4 line segments to path for potential stroke()\n this._pathSegments.push(\n rx, ry, rx + rw, ry, // top\n rx + rw, ry, rx + rw, ry + rh, // right\n rx + rw, ry + rh, rx, ry + rh, // bottom\n rx, ry + rh, rx, ry, // left\n );\n break;\n }\n case 'clip':\n this._applyClip();\n break;\n case 'stroke':\n this._strokePath();\n break;\n case 'fill':\n // Convex fill only — not heavily used in demo beyond fillRect\n break;\n\n // State\n case 'save':\n this._save();\n break;\n case 'restore':\n this._restore();\n break;\n\n // Transforms\n case 'translate':\n this._matrix.translate(args[0] as number, args[1] as number);\n break;\n case 'rotate':\n this._matrix.rotate(args[0] as number);\n break;\n case 'scale':\n this._matrix.scale(args[0] as number, args[1] as number);\n break;\n case 'transform':\n this._matrix.transform(\n args[0] as number, args[1] as number, args[2] as number,\n args[3] as number, args[4] as number, args[5] as number\n );\n break;\n case 'setTransform':\n this._matrix.setTransform(\n args[0] as number, args[1] as number, args[2] as number,\n args[3] as number, args[4] as number, args[5] as number\n );\n break;\n case 'resetTransform':\n this._matrix.resetTransform();\n break;\n\n default:\n // Unsupported methods: silently ignore (arc, bezierCurveTo, etc.)\n break;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: drawing operations\n // -------------------------------------------------------------------------\n\n private _clearRect(x: number, y: number, w: number, h: number): void {\n const gl = this._gl;\n const bg = this._bgColor;\n // WebGL scissor uses bottom-left origin, canvas uses top-left\n gl.enable(gl.SCISSOR_TEST);\n gl.scissor(x, this._height - y - h, w, h);\n gl.clearColor(bg[0], bg[1], bg[2], 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.disable(gl.SCISSOR_TEST);\n }\n\n private _fillRect(x: number, y: number, w: number, h: number): void {\n const gl = this._gl;\n const prog = this._flat;\n\n gl.useProgram(prog._program);\n\n // Build transform: current matrix × translate(x,y) × scale(w,h)\n // Applied to unit quad [0,1]×[0,1] → fills [x,y,x+w,y+h]\n this._matrix.save();\n this._matrix.translate(x, y);\n this._matrix.scale(w, h);\n\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, this._fillColor, this._globalAlpha);\n\n this._matrix.restore();\n\n // Draw unit quad\n gl.bindBuffer(gl.ARRAY_BUFFER, this._unitQuadVBO);\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, 0, 0);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n }\n\n private _strokeRect(x: number, y: number, w: number, h: number): void {\n // Draw four edges as thin quads\n const lw = this._lineWidth;\n const hlw = lw / 2;\n\n // Top edge\n this._fillRectWithColor(x - hlw, y - hlw, w + lw, lw, this._strokeColor);\n // Bottom edge\n this._fillRectWithColor(x - hlw, y + h - hlw, w + lw, lw, this._strokeColor);\n // Left edge\n this._fillRectWithColor(x - hlw, y + hlw, lw, h - lw, this._strokeColor);\n // Right edge\n this._fillRectWithColor(x + w - hlw, y + hlw, lw, h - lw, this._strokeColor);\n }\n\n /** Internal: draw a filled rect with a specific color (used by strokeRect). */\n private _fillRectWithColor(x: number, y: number, w: number, h: number, color: Float32Array): void {\n const gl = this._gl;\n const prog = this._flat;\n\n gl.useProgram(prog._program);\n\n this._matrix.save();\n this._matrix.translate(x, y);\n this._matrix.scale(w, h);\n\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, color, this._globalAlpha);\n\n this._matrix.restore();\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this._unitQuadVBO);\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, 0, 0);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n }\n\n private _strokePath(): void {\n const segs = this._pathSegments;\n if (segs.length === 0) return;\n\n const gl = this._gl;\n const prog = this._flat;\n const halfW = Math.max(this._lineWidth / 2, 0.5);\n\n // Expand line segments to quads on CPU\n // Each segment (x0,y0,x1,y1) → 6 vertices (2 triangles)\n const segCount = segs.length / 4;\n const vertices = new Float32Array(segCount * 12); // 6 vertices × 2 coords\n\n for (let i = 0, vi = 0; i < segs.length; i += 4) {\n const x0 = segs[i], y0 = segs[i + 1], x1 = segs[i + 2], y1 = segs[i + 3];\n const dx = x1 - x0;\n const dy = y1 - y0;\n const len = Math.sqrt(dx * dx + dy * dy);\n\n if (len < 0.001) continue; // Skip degenerate segments\n\n // Normal perpendicular to line direction\n const nx = (-dy / len) * halfW;\n const ny = (dx / len) * halfW;\n\n // Four corners of the quad\n const ax = x0 + nx, ay = y0 + ny; // top-left\n const bx = x0 - nx, by = y0 - ny; // bottom-left\n const cx = x1 + nx, cy = y1 + ny; // top-right\n const dx2 = x1 - nx, dy2 = y1 - ny; // bottom-right\n\n // Triangle 1: A, B, C\n vertices[vi++] = ax; vertices[vi++] = ay;\n vertices[vi++] = bx; vertices[vi++] = by;\n vertices[vi++] = cx; vertices[vi++] = cy;\n // Triangle 2: B, D, C\n vertices[vi++] = bx; vertices[vi++] = by;\n vertices[vi++] = dx2; vertices[vi++] = dy2;\n vertices[vi++] = cx; vertices[vi++] = cy;\n }\n\n // Upload to dynamic VBO using orphaning (bufferData null pattern)\n gl.bindBuffer(gl.ARRAY_BUFFER, this._dynamicVBO);\n gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW);\n\n gl.useProgram(prog._program);\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, this._strokeColor, this._globalAlpha);\n\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, 0, 0);\n gl.drawArrays(gl.TRIANGLES, 0, segCount * 6);\n }\n\n private _drawImage(args: unknown[]): void {\n const gl = this._gl;\n const image = args[0] as CanvasImageSource;\n\n let sx: number, sy: number, sw: number, sh: number;\n let dx: number, dy: number, dw: number, dh: number;\n\n // Get image dimensions\n const imgW = _getImageWidth(image);\n const imgH = _getImageHeight(image);\n\n if (args.length === 3) {\n // drawImage(image, dx, dy)\n sx = 0; sy = 0; sw = imgW; sh = imgH;\n dx = args[1] as number; dy = args[2] as number;\n dw = imgW; dh = imgH;\n } else if (args.length === 5) {\n // drawImage(image, dx, dy, dw, dh)\n sx = 0; sy = 0; sw = imgW; sh = imgH;\n dx = args[1] as number; dy = args[2] as number;\n dw = args[3] as number; dh = args[4] as number;\n } else {\n // drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)\n sx = args[1] as number; sy = args[2] as number;\n sw = args[3] as number; sh = args[4] as number;\n dx = args[5] as number; dy = args[6] as number;\n dw = args[7] as number; dh = args[8] as number;\n }\n\n // Get or create texture for this image source\n const tex = this._getOrUploadTexture(image, imgW, imgH);\n\n // Set filtering based on imageSmoothingEnabled\n const filter = this._imageSmoothingEnabled ? gl.LINEAR : gl.NEAREST;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);\n\n // Compute UV coordinates for source sub-rect\n const uMin = sx / imgW;\n const vMin = sy / imgH;\n const uMax = (sx + sw) / imgW;\n const vMax = (sy + sh) / imgH;\n\n // Draw textured quad with interleaved position + texcoord\n const prog = this._textured;\n const verts = new Float32Array([\n dx, dy, uMin, vMin,\n dx + dw, dy, uMax, vMin,\n dx, dy + dh, uMin, vMax,\n dx, dy + dh, uMin, vMax,\n dx + dw, dy, uMax, vMin,\n dx + dw, dy + dh, uMax, vMax,\n ]);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this._texturedVBO);\n gl.bufferData(gl.ARRAY_BUFFER, verts, gl.DYNAMIC_DRAW);\n\n gl.useProgram(prog._program);\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n // White color tint with globalAlpha — no color modification, just alpha\n gl.uniform4f(prog._colorLoc!, 1, 1, 1, this._globalAlpha);\n\n // Standard alpha blending (not premultiplied for image textures)\n const stride = 16; // 4 floats × 4 bytes\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, stride, 0);\n gl.enableVertexAttribArray(prog._texCoordLoc);\n gl.vertexAttribPointer(prog._texCoordLoc, 2, gl.FLOAT, false, stride, 8);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.uniform1i(prog._textureLoc, 0);\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Disable texcoord attrib to avoid interfering with flat shader\n gl.disableVertexAttribArray(prog._texCoordLoc);\n }\n\n private _getOrUploadTexture(image: CanvasImageSource, imgW: number, imgH: number): WebGLTexture {\n const gl = this._gl;\n const key = image as unknown as object;\n const cached = this._imageTexCache.get(key);\n\n // HTMLImageElement/SVGImageElement: upload once, cache permanently\n // HTMLCanvasElement/OffscreenCanvas: always re-upload (content may change)\n const isImage = (image instanceof HTMLImageElement) || (image instanceof SVGImageElement);\n\n if (cached) {\n if (cached._isImage) {\n // Static image — reuse cached texture\n return cached._tex;\n }\n // Canvas source — re-upload to existing texture\n gl.bindTexture(gl.TEXTURE_2D, cached._tex);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image as TexImageSource);\n return cached._tex;\n }\n\n // Create new texture\n const tex = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\n // Detect if we need to handle alpha properly\n // For canvas sources, use standard upload; for images, avoid premultiply\n if (imgW > 0 && imgH > 0) {\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image as TexImageSource);\n }\n\n this._imageTexCache.set(key, { _tex: tex, _isImage: isImage });\n return tex;\n }\n\n private _applyClip(): void {\n const gl = this._gl;\n if (this._pendingClipRect) {\n const [x, y, w, h] = this._pendingClipRect;\n gl.enable(gl.SCISSOR_TEST);\n // Convert canvas coords (top-left origin) to GL coords (bottom-left origin)\n gl.scissor(x, this._height - y - h, w, h);\n this._clipActive = true;\n this._clipRect = [x, y, w, h];\n }\n }\n\n private _fillText(text: string, x: number, y: number): void {\n this._renderText(text, x, y, 'fill');\n }\n\n private _strokeText(text: string, x: number, y: number): void {\n this._renderText(text, x, y, 'stroke');\n }\n\n private _renderText(text: string, x: number, y: number, mode: 'fill' | 'stroke'): void {\n const gl = this._gl;\n const tCtx = this._textCtx;\n\n // Configure text rendering context\n tCtx.font = this._font;\n tCtx.textAlign = 'left'; // Always render left-aligned, position via WebGL\n tCtx.textBaseline = 'top'; // Always render from top, adjust Y via offset\n if (this._letterSpacing) {\n tCtx.letterSpacing = this._letterSpacing;\n }\n\n // Measure text\n const metrics = tCtx.measureText(text);\n const textWidth = Math.ceil(metrics.width) + 4; // +4 for antialiasing padding\n const fontSize = _parseFontSize(this._font);\n const textHeight = Math.ceil(fontSize * 1.5) + 4; // approximate height with descenders\n\n if (textWidth <= 0 || textHeight <= 0) return;\n\n // Resize text canvas if needed\n if (this._textCanvas.width < textWidth || this._textCanvas.height < textHeight) {\n this._textCanvas.width = Math.max(this._textCanvas.width, textWidth);\n this._textCanvas.height = Math.max(this._textCanvas.height, textHeight);\n // Re-set font after resize (context is reset)\n tCtx.font = this._font;\n tCtx.textAlign = 'left';\n tCtx.textBaseline = 'top';\n }\n\n // Clear and render text\n tCtx.clearRect(0, 0, this._textCanvas.width, this._textCanvas.height);\n\n if (mode === 'fill') {\n tCtx.fillStyle = 'white'; // White text, tinted by WebGL uniform\n tCtx.fillText(text, 2, 2); // +2 padding offset\n } else {\n tCtx.strokeStyle = 'white';\n tCtx.lineWidth = this._lineWidth;\n tCtx.strokeText(text, 2, 2);\n }\n\n // Upload text canvas to texture\n gl.bindTexture(gl.TEXTURE_2D, this._textTexture);\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);\n gl.texImage2D(\n gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,\n this._textCanvas\n );\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0);\n\n // Compute text position adjustments\n const color = mode === 'fill' ? this._fillColor : this._strokeColor;\n let drawX = x - 2; // compensate for padding\n let drawY = y - 2;\n\n // Adjust for textAlign\n switch (this._textAlign) {\n case 'center': drawX -= textWidth / 2; break;\n case 'right':\n case 'end': drawX -= textWidth; break;\n }\n\n // Adjust for textBaseline\n switch (this._textBaseline) {\n case 'top': /* drawY stays */ break;\n case 'middle': drawY -= textHeight / 2; break;\n case 'alphabetic':\n case 'ideographic': drawY -= fontSize; break;\n case 'bottom':\n case 'hanging': drawY -= textHeight; break;\n }\n\n // Draw textured quad\n this._drawTexturedQuad(\n drawX, drawY, textWidth, textHeight,\n textWidth / this._textCanvas.width,\n textHeight / this._textCanvas.height,\n color\n );\n }\n\n private _drawTexturedQuad(\n x: number, y: number, w: number, h: number,\n uMax: number, vMax: number,\n color: Float32Array\n ): void {\n const gl = this._gl;\n const prog = this._textured;\n\n // Interleaved position + texcoord (x, y, u, v)\n const verts = new Float32Array([\n x, y, 0, 0,\n x + w, y, uMax, 0,\n x, y + h, 0, vMax,\n x, y + h, 0, vMax,\n x + w, y, uMax, 0,\n x + w, y + h, uMax, vMax,\n ]);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this._texturedVBO);\n gl.bufferData(gl.ARRAY_BUFFER, verts, gl.DYNAMIC_DRAW);\n\n gl.useProgram(prog._program);\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, color, this._globalAlpha);\n\n // Use premultiplied alpha blending for text\n gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n\n const stride = 16; // 4 floats × 4 bytes\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, stride, 0);\n gl.enableVertexAttribArray(prog._texCoordLoc);\n gl.vertexAttribPointer(prog._texCoordLoc, 2, gl.FLOAT, false, stride, 8);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this._textTexture);\n gl.uniform1i(prog._textureLoc, 0);\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Restore standard blending\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n\n // Disable texcoord attrib to avoid interfering with flat shader\n gl.disableVertexAttribArray(prog._texCoordLoc);\n }\n\n // -------------------------------------------------------------------------\n // Private: state management\n // -------------------------------------------------------------------------\n\n private _save(): void {\n this._matrix.save();\n this._stateStack.push({\n _fillColor: new Float32Array(this._fillColor),\n _strokeColor: new Float32Array(this._strokeColor),\n _lineWidth: this._lineWidth,\n _globalAlpha: this._globalAlpha,\n _font: this._font,\n _textAlign: this._textAlign,\n _textBaseline: this._textBaseline,\n _lineCap: this._lineCap,\n _lineJoin: this._lineJoin,\n _imageSmoothingEnabled: this._imageSmoothingEnabled,\n _letterSpacing: this._letterSpacing,\n _clipActive: this._clipActive,\n _clipRect: this._clipRect ? [...this._clipRect] as [number, number, number, number] : null,\n });\n }\n\n private _restore(): void {\n this._matrix.restore();\n const gl = this._gl;\n const state = this._stateStack.pop();\n if (state) {\n this._fillColor = state._fillColor;\n this._strokeColor = state._strokeColor;\n this._lineWidth = state._lineWidth;\n this._globalAlpha = state._globalAlpha;\n this._font = state._font;\n this._textAlign = state._textAlign;\n this._textBaseline = state._textBaseline;\n this._lineCap = state._lineCap;\n this._lineJoin = state._lineJoin;\n this._imageSmoothingEnabled = state._imageSmoothingEnabled;\n this._letterSpacing = state._letterSpacing;\n this._clipActive = state._clipActive;\n this._clipRect = state._clipRect;\n\n // Restore scissor state\n if (this._clipActive && this._clipRect) {\n const [x, y, w, h] = this._clipRect;\n gl.enable(gl.SCISSOR_TEST);\n gl.scissor(x, this._height - y - h, w, h);\n } else {\n gl.disable(gl.SCISSOR_TEST);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: WebGL helpers\n // -------------------------------------------------------------------------\n\n private _setColorUniform(loc: WebGLUniformLocation, color: Float32Array, alpha: number): void {\n // Premultiply globalAlpha into the color's alpha channel\n const a = color[3] * alpha;\n this._gl.uniform4f(loc, color[0], color[1], color[2], a);\n }\n\n private _createProgram(vSrc: string, fSrc: string, hasTexCoord: boolean): _ProgramInfo {\n const gl = this._gl;\n const vs = this._compileShader(gl.VERTEX_SHADER, vSrc);\n const fs = this._compileShader(gl.FRAGMENT_SHADER, fSrc);\n\n const program = gl.createProgram()!;\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n throw new Error('Shader link failed: ' + gl.getProgramInfoLog(program));\n }\n\n // Delete shaders after linking (they're embedded in the program now)\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n return {\n _program: program,\n _matrixLoc: gl.getUniformLocation(program, 'u_matrix'),\n _colorLoc: gl.getUniformLocation(program, 'u_color'),\n _textureLoc: hasTexCoord ? gl.getUniformLocation(program, 'u_texture') : null,\n _positionLoc: gl.getAttribLocation(program, 'a_position'),\n _texCoordLoc: hasTexCoord ? gl.getAttribLocation(program, 'a_texCoord') : -1,\n };\n }\n\n private _compileShader(type: number, source: string): WebGLShader {\n const gl = this._gl;\n const shader = gl.createShader(type)!;\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader);\n gl.deleteShader(shader);\n throw new Error('Shader compile failed: ' + info);\n }\n return shader;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Utility\n// ---------------------------------------------------------------------------\n\n/** Extract numeric font size from a CSS font string like \"bold 20px monospace\". */\nfunction _parseFontSize(font: string): number {\n const match = font.match(/(\\d+(?:\\.\\d+)?)\\s*px/);\n return match ? parseFloat(match[1]) : 10;\n}\n\n/** Get width of a CanvasImageSource (handles HTMLImageElement, HTMLCanvasElement, OffscreenCanvas, etc.) */\nfunction _getImageWidth(img: CanvasImageSource): number {\n if ('naturalWidth' in img) return (img as HTMLImageElement).naturalWidth;\n return (img as HTMLCanvasElement | OffscreenCanvas).width;\n}\n\n/** Get height of a CanvasImageSource. */\nfunction _getImageHeight(img: CanvasImageSource): number {\n if ('naturalHeight' in img) return (img as HTMLImageElement).naturalHeight;\n return (img as HTMLCanvasElement | OffscreenCanvas).height;\n}\n","/**\n * UltrafastRenderer — WebGL2 Triple-Buffered Canvas 2D Renderer\n *\n * A standalone WebGL-accelerated Canvas 2D rendering engine. Provides a\n * CanvasAPI for recording draw commands and a triple-buffered FBO pipeline\n * that displays them via a passthrough shader at vsync rate.\n *\n * Triple buffer scheme (all on main thread, lock-free via JS single-threading):\n *\n * Content submission:\n * submitBatch(commands)\n * → bind writeFBO\n * → Canvas2DShim executes commands as WebGL draw calls\n * → swap: writeFBO ↔ readyFBO\n *\n * Display loop (vsync rate via RAF):\n * RAF callback\n * → auto-flush: drain CanvasAPI commands → submitBatch\n * → bind default framebuffer (display canvas)\n * → read readyFBO texture → passthrough blit → screen\n *\n * Extension points for downstream consumers (e.g. maalata CRT display):\n * - getGL(): access the WebGL2 context\n * - getReadyTexture(): read the latest rendered frame as a texture\n * - stopDisplay() / startDisplay(): take over the display loop\n */\n\nimport { CanvasAPI, type CanvasCommand } from './canvas-api';\nimport { Canvas2DShim } from './canvas2d-shim';\nimport {\n PASSTHROUGH_VERTEX_SRC,\n PASSTHROUGH_FRAGMENT_SRC,\n} from './shaders';\n\ninterface _FBO {\n _fbo: WebGLFramebuffer;\n _texture: WebGLTexture;\n}\n\nexport class UltrafastRenderer {\n private _gl: WebGL2RenderingContext;\n private _canvas: HTMLCanvasElement;\n private _shim: Canvas2DShim;\n private _api: CanvasAPI;\n private _rafId: number | null = null;\n\n // Triple buffer: three FBOs with color texture attachments\n private _fbos!: [_FBO, _FBO, _FBO];\n private _writeIdx = 0;\n private _readyIdx = 1;\n private _displayIdx = 2;\n private _hasContent = false;\n\n // Background color for opaque canvas clear (default: black, backwards compatible)\n private _bgColor = new Float32Array([0, 0, 0]);\n\n // Display program\n private _passthroughProgram: WebGLProgram;\n\n // Fullscreen quad VBO\n private _quadVBO!: WebGLBuffer;\n private _quadPositionLoc = -1;\n\n constructor(canvas: HTMLCanvasElement) {\n this._canvas = canvas;\n this._api = new CanvasAPI();\n\n // Create WebGL2 context with optimizations\n const gl = canvas.getContext('webgl2', {\n alpha: false,\n antialias: false,\n desynchronized: true,\n preserveDrawingBuffer: true,\n powerPreference: 'high-performance',\n });\n\n if (!gl) {\n throw new Error('WebGL2 not supported');\n }\n this._gl = gl;\n\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\n\n // Initialize triple buffer FBOs\n this._initFBOs();\n\n // Initialize Canvas 2D shim (uses same GL context)\n this._shim = new Canvas2DShim(gl, canvas.width, canvas.height);\n\n // Initialize passthrough display program\n this._passthroughProgram = this._createShaderProgram(\n PASSTHROUGH_VERTEX_SRC, PASSTHROUGH_FRAGMENT_SRC\n );\n\n // Initialize fullscreen quad VBO for display pass\n this._initQuadVBO();\n\n // Clear all FBOs to black initially\n this._clearAllFBOs();\n\n // Auto-start display loop\n this.startDisplay();\n }\n\n // -------------------------------------------------------------------------\n // Public API (no _ prefix: cross-file access safe from mangleProps)\n // -------------------------------------------------------------------------\n\n /** Get the CanvasAPI for recording draw commands. */\n getCanvasAPI(): CanvasAPI {\n return this._api;\n }\n\n /**\n * Submit a batch of Canvas 2D commands to be rendered into the write FBO.\n * After rendering, the write and ready FBOs are swapped so the display\n * loop picks up the latest frame.\n */\n submitBatch(commands: CanvasCommand[]): void {\n if (commands.length === 0) return;\n const gl = this._gl;\n\n // Bind write FBO as render target\n gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbos[this._writeIdx]._fbo);\n gl.viewport(0, 0, this._canvas.width, this._canvas.height);\n\n // Execute Canvas 2D commands as WebGL draw calls\n this._shim.executeBatch(commands);\n\n // Swap write ↔ ready (new frame becomes available for display)\n const tmp = this._writeIdx;\n this._writeIdx = this._readyIdx;\n this._readyIdx = tmp;\n this._hasContent = true;\n }\n\n /** Start the passthrough RAF display loop with auto-flush. */\n startDisplay(): void {\n if (this._rafId !== null) return;\n this._displayLoop();\n }\n\n /** Stop the passthrough RAF display loop. Last frame persists (preserveDrawingBuffer). */\n stopDisplay(): void {\n if (this._rafId !== null) {\n cancelAnimationFrame(this._rafId);\n this._rafId = null;\n }\n }\n\n /** Returns the display canvas element. */\n getCanvas(): HTMLCanvasElement {\n return this._canvas;\n }\n\n /** Get canvas dimensions. */\n getCanvasSize(): { width: number; height: number } {\n return { width: this._canvas.width, height: this._canvas.height };\n }\n\n /** Capture the current displayed frame as an ImageBitmap. */\n screenshot(): Promise<ImageBitmap> {\n this._renderDisplay();\n return createImageBitmap(this._canvas);\n }\n\n /**\n * Set the opaque clear color used by clearRect and FBO initialization.\n * With alpha: false, cleared areas are opaque — this controls what color\n * they appear as instead of black. Values are in [0, 1] range.\n */\n setBackgroundColor(r: number, g: number, b: number): void {\n this._bgColor[0] = r;\n this._bgColor[1] = g;\n this._bgColor[2] = b;\n this._shim.setBackgroundColor(r, g, b);\n }\n\n /** Clean up all WebGL resources. */\n destroy(): void {\n this.stopDisplay();\n const gl = this._gl;\n\n this._shim.destroy();\n\n for (const fbo of this._fbos) {\n gl.deleteFramebuffer(fbo._fbo);\n gl.deleteTexture(fbo._texture);\n }\n\n gl.deleteProgram(this._passthroughProgram);\n gl.deleteBuffer(this._quadVBO);\n\n const ext = gl.getExtension('WEBGL_lose_context');\n if (ext) ext.loseContext();\n }\n\n // -------------------------------------------------------------------------\n // Extension points (used by maalata CRT display)\n // -------------------------------------------------------------------------\n\n /** Returns the WebGL2 context for external rendering (e.g. CRT shader). */\n getGL(): WebGL2RenderingContext {\n return this._gl;\n }\n\n /** Returns the ready FBO's texture — the latest fully rendered frame. */\n getReadyTexture(): WebGLTexture {\n return this._fbos[this._readyIdx]._texture;\n }\n\n // -------------------------------------------------------------------------\n // Private: display loop\n // -------------------------------------------------------------------------\n\n private _displayLoop(): void {\n this._rafId = requestAnimationFrame(() => this._displayLoop());\n\n // Auto-flush: drain any pending CanvasAPI commands into the pipeline\n const cmds = this._api.takeCommands();\n if (cmds.length) this.submitBatch(cmds);\n\n this._renderDisplay();\n }\n\n /**\n * Render the ready FBO to the display canvas via passthrough shader.\n * Called at vsync rate by RAF, or once synchronously for screenshots.\n */\n private _renderDisplay(): void {\n if (!this._hasContent) return;\n\n const gl = this._gl;\n\n // Bind default framebuffer (display canvas backbuffer)\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, this._canvas.width, this._canvas.height);\n\n // Bind the ready FBO's texture as input\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this._fbos[this._readyIdx]._texture);\n\n gl.useProgram(this._passthroughProgram);\n\n // Draw fullscreen quad\n gl.bindBuffer(gl.ARRAY_BUFFER, this._quadVBO);\n gl.enableVertexAttribArray(this._quadPositionLoc);\n gl.vertexAttribPointer(this._quadPositionLoc, 2, gl.FLOAT, false, 0, 0);\n\n gl.disable(gl.BLEND);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n gl.enable(gl.BLEND);\n }\n\n // -------------------------------------------------------------------------\n // Private: initialization\n // -------------------------------------------------------------------------\n\n private _initFBOs(): void {\n this._fbos = [\n this._createFBO(),\n this._createFBO(),\n this._createFBO(),\n ];\n }\n\n private _createFBO(): _FBO {\n const gl = this._gl;\n const w = this._canvas.width;\n const h = this._canvas.height;\n\n const fbo = gl.createFramebuffer()!;\n gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);\n\n const texture = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, w, h);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);\n\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error('Framebuffer incomplete: 0x' + status.toString(16));\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n return { _fbo: fbo, _texture: texture };\n }\n\n private _clearAllFBOs(): void {\n const gl = this._gl;\n const bg = this._bgColor;\n for (const fbo of this._fbos) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, fbo._fbo);\n gl.clearColor(bg[0], bg[1], bg[2], 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.clearColor(bg[0], bg[1], bg[2], 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n\n private _initQuadVBO(): void {\n const gl = this._gl;\n\n this._quadVBO = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, this._quadVBO);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([\n 0, 0, 1, 0, 0, 1,\n 0, 1, 1, 0, 1, 1,\n ]), gl.STATIC_DRAW);\n\n this._quadPositionLoc = gl.getAttribLocation(this._passthroughProgram, 'a_position');\n }\n\n // -------------------------------------------------------------------------\n // Private: shader helpers\n // -------------------------------------------------------------------------\n\n private _createShaderProgram(vSrc: string, fSrc: string): WebGLProgram {\n const gl = this._gl;\n const vs = this._compileShader(gl.VERTEX_SHADER, vSrc);\n const fs = this._compileShader(gl.FRAGMENT_SHADER, fSrc);\n\n const program = gl.createProgram()!;\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n throw new Error('Shader link failed: ' + gl.getProgramInfoLog(program));\n }\n\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n return program;\n }\n\n private _compileShader(type: number, source: string): WebGLShader {\n const gl = this._gl;\n const shader = gl.createShader(type)!;\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader);\n gl.deleteShader(shader);\n throw new Error('Shader compile failed: ' + info);\n }\n return shader;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -524,6 +524,8 @@
|
|
|
524
524
|
// Text rendering surface
|
|
525
525
|
_textCanvas;
|
|
526
526
|
_textCtx;
|
|
527
|
+
// Background color for opaque canvas clear
|
|
528
|
+
_bgColor = new Float32Array([0, 0, 0]);
|
|
527
529
|
// Temp arrays to avoid allocation in hot path
|
|
528
530
|
_tmpColor = new Float32Array(4);
|
|
529
531
|
constructor(gl, width, height) {
|
|
@@ -583,6 +585,15 @@
|
|
|
583
585
|
}
|
|
584
586
|
}
|
|
585
587
|
}
|
|
588
|
+
/**
|
|
589
|
+
* Set the opaque clear color for clearRect.
|
|
590
|
+
* No _ prefix: called cross-file from renderer.
|
|
591
|
+
*/
|
|
592
|
+
setBackgroundColor(r, g, b) {
|
|
593
|
+
this._bgColor[0] = r;
|
|
594
|
+
this._bgColor[1] = g;
|
|
595
|
+
this._bgColor[2] = b;
|
|
596
|
+
}
|
|
586
597
|
/**
|
|
587
598
|
* Update canvas dimensions on resize.
|
|
588
599
|
* No _ prefix: called cross-file.
|
|
@@ -783,9 +794,10 @@
|
|
|
783
794
|
// -------------------------------------------------------------------------
|
|
784
795
|
_clearRect(x, y, w, h) {
|
|
785
796
|
const gl = this._gl;
|
|
797
|
+
const bg = this._bgColor;
|
|
786
798
|
gl.enable(gl.SCISSOR_TEST);
|
|
787
799
|
gl.scissor(x, this._height - y - h, w, h);
|
|
788
|
-
gl.clearColor(0,
|
|
800
|
+
gl.clearColor(bg[0], bg[1], bg[2], 1);
|
|
789
801
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
790
802
|
gl.disable(gl.SCISSOR_TEST);
|
|
791
803
|
}
|
|
@@ -1237,6 +1249,8 @@
|
|
|
1237
1249
|
_readyIdx = 1;
|
|
1238
1250
|
_displayIdx = 2;
|
|
1239
1251
|
_hasContent = false;
|
|
1252
|
+
// Background color for opaque canvas clear (default: black, backwards compatible)
|
|
1253
|
+
_bgColor = new Float32Array([0, 0, 0]);
|
|
1240
1254
|
// Display program
|
|
1241
1255
|
_passthroughProgram;
|
|
1242
1256
|
// Fullscreen quad VBO
|
|
@@ -1315,6 +1329,17 @@
|
|
|
1315
1329
|
this._renderDisplay();
|
|
1316
1330
|
return createImageBitmap(this._canvas);
|
|
1317
1331
|
}
|
|
1332
|
+
/**
|
|
1333
|
+
* Set the opaque clear color used by clearRect and FBO initialization.
|
|
1334
|
+
* With alpha: false, cleared areas are opaque — this controls what color
|
|
1335
|
+
* they appear as instead of black. Values are in [0, 1] range.
|
|
1336
|
+
*/
|
|
1337
|
+
setBackgroundColor(r, g, b) {
|
|
1338
|
+
this._bgColor[0] = r;
|
|
1339
|
+
this._bgColor[1] = g;
|
|
1340
|
+
this._bgColor[2] = b;
|
|
1341
|
+
this._shim.setBackgroundColor(r, g, b);
|
|
1342
|
+
}
|
|
1318
1343
|
/** Clean up all WebGL resources. */
|
|
1319
1344
|
destroy() {
|
|
1320
1345
|
this.stopDisplay();
|
|
@@ -1401,13 +1426,14 @@
|
|
|
1401
1426
|
}
|
|
1402
1427
|
_clearAllFBOs() {
|
|
1403
1428
|
const gl = this._gl;
|
|
1429
|
+
const bg = this._bgColor;
|
|
1404
1430
|
for (const fbo of this._fbos) {
|
|
1405
1431
|
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo._fbo);
|
|
1406
|
-
gl.clearColor(0,
|
|
1432
|
+
gl.clearColor(bg[0], bg[1], bg[2], 1);
|
|
1407
1433
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
1408
1434
|
}
|
|
1409
1435
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
1410
|
-
gl.clearColor(0,
|
|
1436
|
+
gl.clearColor(bg[0], bg[1], bg[2], 1);
|
|
1411
1437
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
1412
1438
|
}
|
|
1413
1439
|
_initQuadVBO() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canvas-ultrafast.umd.js","sources":["../src/canvas-api.ts","../src/matrix-stack.ts","../src/color-parser.ts","../src/shaders.ts","../src/canvas2d-shim.ts","../src/renderer.ts"],"sourcesContent":["/**\n * Canvas API Wrapper\n *\n * Provides a Canvas 2D API that records commands locally without await.\n * Commands are batched and sent to the worker for execution.\n */\n\ntype CanvasPropertyMap = {\n fillStyle: string | CanvasGradient | CanvasPattern;\n strokeStyle: string | CanvasGradient | CanvasPattern;\n lineWidth: number;\n lineCap: CanvasLineCap;\n lineJoin: CanvasLineJoin;\n miterLimit: number;\n lineDashOffset: number;\n font: string;\n textAlign: CanvasTextAlign;\n textBaseline: CanvasTextBaseline;\n globalAlpha: number;\n globalCompositeOperation: GlobalCompositeOperation;\n shadowBlur: number;\n shadowColor: string;\n shadowOffsetX: number;\n shadowOffsetY: number;\n imageSmoothingEnabled: boolean;\n letterSpacing: string;\n};\n\nexport type CanvasCommand =\n | { type: 'property'; name: string; value: unknown }\n | { type: 'method'; name: string; args: unknown[] };\n\nexport class CanvasAPI {\n private _c: CanvasCommand[] = [];\n private _cp: Partial<CanvasPropertyMap> = {};\n\n private _m(n: string, ...a: unknown[]): void {\n this._c.push({ type: 'method', name: n, args: a });\n }\n\n private _p<K extends keyof CanvasPropertyMap>(n: K, v: CanvasPropertyMap[K]): void {\n this._cp[n] = v;\n this._c.push({ type: 'property', name: n, value: v });\n }\n\n /**\n * Drain and return all buffered commands.\n * No _ prefix: called cross-file from pipeline, must survive mangleProps.\n */\n takeCommands(): CanvasCommand[] {\n if (this._c.length === 0) return [];\n const cmds = this._c;\n this._c = [];\n return cmds;\n }\n\n // Canvas 2D API methods\n\n // State\n save(): void { this._m('save'); }\n restore(): void { this._m('restore'); }\n\n // Transform\n scale(x: number, y: number): void { this._m('scale', x, y); }\n rotate(angle: number): void { this._m('rotate', angle); }\n translate(x: number, y: number): void { this._m('translate', x, y); }\n transform(a: number, b: number, c: number, d: number, e: number, f: number): void { this._m('transform', a, b, c, d, e, f); }\n setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void { this._m('setTransform', a, b, c, d, e, f); }\n resetTransform(): void { this._m('resetTransform'); }\n\n // Rectangles\n clearRect(x: number, y: number, width: number, height: number): void { this._m('clearRect', x, y, width, height); }\n fillRect(x: number, y: number, width: number, height: number): void { this._m('fillRect', x, y, width, height); }\n strokeRect(x: number, y: number, width: number, height: number): void { this._m('strokeRect', x, y, width, height); }\n\n // Text\n fillText(text: string, x: number, y: number, maxWidth?: number): void {\n this._m('fillText', ...(maxWidth !== undefined ? [text, x, y, maxWidth] : [text, x, y]));\n }\n\n strokeText(text: string, x: number, y: number, maxWidth?: number): void {\n this._m('strokeText', ...(maxWidth !== undefined ? [text, x, y, maxWidth] : [text, x, y]));\n }\n\n /** Synchronous text measurement — cannot go through the async command pipeline. */\n private _measureCtx: OffscreenCanvasRenderingContext2D | null = null;\n\n measureText(text: string): TextMetrics {\n if (!this._measureCtx) {\n this._measureCtx = new OffscreenCanvas(1, 1).getContext('2d')!;\n }\n this._measureCtx.font = this.font;\n return this._measureCtx.measureText(text);\n }\n\n // Line drawing\n beginPath(): void { this._m('beginPath'); }\n closePath(): void { this._m('closePath'); }\n moveTo(x: number, y: number): void { this._m('moveTo', x, y); }\n lineTo(x: number, y: number): void { this._m('lineTo', x, y); }\n\n bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void {\n this._m('bezierCurveTo', cp1x, cp1y, cp2x, cp2y, x, y);\n }\n\n quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void { this._m('quadraticCurveTo', cpx, cpy, x, y); }\n\n arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void {\n this._m('arc', ...(counterclockwise !== undefined ? [x, y, radius, startAngle, endAngle, counterclockwise] : [x, y, radius, startAngle, endAngle]));\n }\n\n arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void { this._m('arcTo', x1, y1, x2, y2, radius); }\n\n ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void {\n this._m('ellipse', ...(counterclockwise !== undefined ? [x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise] : [x, y, radiusX, radiusY, rotation, startAngle, endAngle]));\n }\n\n rect(x: number, y: number, width: number, height: number): void { this._m('rect', x, y, width, height); }\n\n // Images\n drawImage(image: CanvasImageSource, dx: number, dy: number): void;\n drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;\n drawImage(image: CanvasImageSource, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void;\n drawImage(...args: [CanvasImageSource, ...number[]]): void {\n this._m('drawImage', ...args);\n }\n\n // Fill and stroke\n fill(): void { this._m('fill'); }\n stroke(): void { this._m('stroke'); }\n clip(): void { this._m('clip'); }\n\n // Properties (setters)\n set fillStyle(value: string | CanvasGradient | CanvasPattern) { this._p('fillStyle', value); }\n set strokeStyle(value: string | CanvasGradient | CanvasPattern) { this._p('strokeStyle', value); }\n set lineWidth(value: number) { this._p('lineWidth', value); }\n set lineCap(value: CanvasLineCap) { this._p('lineCap', value); }\n set lineJoin(value: CanvasLineJoin) { this._p('lineJoin', value); }\n set miterLimit(value: number) { this._p('miterLimit', value); }\n set lineDashOffset(value: number) { this._p('lineDashOffset', value); }\n set font(value: string) { this._p('font', value); }\n set textAlign(value: CanvasTextAlign) { this._p('textAlign', value); }\n set textBaseline(value: CanvasTextBaseline) { this._p('textBaseline', value); }\n set globalAlpha(value: number) { this._p('globalAlpha', value); }\n set globalCompositeOperation(value: GlobalCompositeOperation) { this._p('globalCompositeOperation', value); }\n set shadowBlur(value: number) { this._p('shadowBlur', value); }\n set shadowColor(value: string) { this._p('shadowColor', value); }\n set shadowOffsetX(value: number) { this._p('shadowOffsetX', value); }\n set shadowOffsetY(value: number) { this._p('shadowOffsetY', value); }\n set imageSmoothingEnabled(value: boolean) { this._p('imageSmoothingEnabled', value); }\n set letterSpacing(value: string) { this._p('letterSpacing', value); }\n\n // Property getters (return local cached values)\n get fillStyle() { return this._cp['fillStyle'] ?? '#000'; }\n get strokeStyle() { return this._cp['strokeStyle'] ?? '#000'; }\n get lineWidth() { return this._cp['lineWidth'] ?? 1; }\n get lineCap() { return this._cp['lineCap'] ?? 'butt'; }\n get lineJoin() { return this._cp['lineJoin'] ?? 'miter'; }\n get miterLimit() { return this._cp['miterLimit'] ?? 10; }\n get lineDashOffset() { return this._cp['lineDashOffset'] ?? 0; }\n get font() { return this._cp['font'] ?? '10px sans-serif'; }\n get textAlign() { return this._cp['textAlign'] ?? 'start'; }\n get textBaseline() { return this._cp['textBaseline'] ?? 'alphabetic'; }\n get globalAlpha() { return this._cp['globalAlpha'] ?? 1; }\n get globalCompositeOperation() { return this._cp['globalCompositeOperation'] ?? 'source-over'; }\n get shadowBlur() { return this._cp['shadowBlur'] ?? 0; }\n get shadowColor() { return this._cp['shadowColor'] ?? 'rgba(0, 0, 0, 0)'; }\n get shadowOffsetX() { return this._cp['shadowOffsetX'] ?? 0; }\n get shadowOffsetY() { return this._cp['shadowOffsetY'] ?? 0; }\n get imageSmoothingEnabled() { return this._cp['imageSmoothingEnabled'] ?? true; }\n get letterSpacing() { return this._cp['letterSpacing'] ?? ''; }\n}","/**\n * 3×3 Affine Transform Matrix Stack\n *\n * Replicates Canvas 2D's save()/restore()/translate()/rotate()/scale()\n * as a matrix stack for WebGL uniform upload.\n *\n * Matrices are 3×3 column-major (for gl.uniformMatrix3fv), representing\n * 2D affine transforms. The base matrix includes an orthographic projection\n * that maps canvas pixel coordinates (top-left origin, Y-down) to WebGL\n * clip space ([-1,1], Y-up).\n *\n * Column-major layout of a 3×3 affine matrix:\n * [0] [3] [6] a c tx\n * [1] [4] [7] = b d ty\n * [2] [5] [8] 0 0 1\n */\n\nexport class MatrixStack {\n private _stack: Float32Array[] = [];\n private _current: Float32Array;\n private _projection: Float32Array;\n\n /**\n * @param width Canvas width in pixels\n * @param height Canvas height in pixels\n */\n constructor(width: number, height: number) {\n this._projection = _ortho(width, height);\n this._current = new Float32Array(this._projection);\n }\n\n /** Push current matrix onto the stack. No _ prefix: cross-file. */\n save(): void {\n this._stack.push(new Float32Array(this._current));\n }\n\n /** Pop and restore the top matrix. No _ prefix: cross-file. */\n restore(): void {\n if (this._stack.length > 0) {\n this._current = this._stack.pop()!;\n }\n }\n\n /** Translate the current matrix. No _ prefix: cross-file. */\n translate(x: number, y: number): void {\n // Multiply current matrix by translation:\n // 1 0 tx\n // 0 1 ty\n // 0 0 1\n // In column-major: m[6] += m[0]*tx + m[3]*ty\n // m[7] += m[1]*tx + m[4]*ty\n const m = this._current;\n m[6] += m[0] * x + m[3] * y;\n m[7] += m[1] * x + m[4] * y;\n }\n\n /** Rotate the current matrix by angle (radians). No _ prefix: cross-file. */\n rotate(angle: number): void {\n const c = Math.cos(angle);\n const s = Math.sin(angle);\n const m = this._current;\n const m0 = m[0], m1 = m[1], m3 = m[3], m4 = m[4];\n m[0] = m0 * c + m3 * s;\n m[1] = m1 * c + m4 * s;\n m[3] = m0 * -s + m3 * c;\n m[4] = m1 * -s + m4 * c;\n }\n\n /** Scale the current matrix. No _ prefix: cross-file. */\n scale(x: number, y: number): void {\n const m = this._current;\n m[0] *= x; m[1] *= x;\n m[3] *= y; m[4] *= y;\n }\n\n /**\n * Multiply current matrix by an arbitrary 2D affine transform.\n * Canvas 2D transform(a, b, c, d, e, f) matrix:\n * a c e\n * b d f\n * 0 0 1\n * No _ prefix: cross-file.\n */\n transform(a: number, b: number, c: number, d: number, e: number, f: number): void {\n const m = this._current;\n const m0 = m[0], m1 = m[1], m3 = m[3], m4 = m[4], m6 = m[6], m7 = m[7];\n m[0] = m0 * a + m3 * b;\n m[1] = m1 * a + m4 * b;\n m[3] = m0 * c + m3 * d;\n m[4] = m1 * c + m4 * d;\n m[6] = m0 * e + m3 * f + m6;\n m[7] = m1 * e + m4 * f + m7;\n }\n\n /**\n * Reset to projection then apply the given affine transform.\n * Canvas 2D setTransform(a, b, c, d, e, f).\n * No _ prefix: cross-file.\n */\n setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void {\n this._current.set(this._projection);\n this.transform(a, b, c, d, e, f);\n }\n\n /** Reset to the base orthographic projection. No _ prefix: cross-file. */\n resetTransform(): void {\n this._current.set(this._projection);\n }\n\n /**\n * Update canvas dimensions (e.g., on resize).\n * Recomputes the projection and resets the current matrix.\n * No _ prefix: cross-file.\n */\n resize(width: number, height: number): void {\n this._projection = _ortho(width, height);\n this._current = new Float32Array(this._projection);\n this._stack = [];\n }\n\n /**\n * Returns the current 3×3 matrix for gl.uniformMatrix3fv.\n * No _ prefix: cross-file.\n */\n getMatrix(): Float32Array {\n return this._current;\n }\n}\n\n/**\n * Create an orthographic projection matrix that maps:\n * Canvas coords (0,0)=top-left, (w,h)=bottom-right, Y-down\n * → Clip space (-1,-1)=bottom-left, (1,1)=top-right, Y-up\n *\n * The transform is:\n * x_clip = x * 2/w - 1\n * y_clip = -(y * 2/h - 1) = 1 - y * 2/h\n *\n * Column-major 3×3:\n * 2/w 0 -1\n * 0 -2/h 1\n * 0 0 1\n */\nfunction _ortho(w: number, h: number): Float32Array {\n return new Float32Array([\n 2 / w, 0, 0, // column 0\n 0, -2 / h, 0, // column 1\n -1, 1, 1, // column 2\n ]);\n}\n","/**\n * CSS Color Parser\n *\n * Converts CSS color strings to Float32Array [r, g, b, a] in [0, 1] range\n * for use as WebGL uniform values.\n *\n * Supported formats:\n * - Hex: #rgb, #rrggbb, #rrggbbaa\n * - Functional: rgb(r, g, b), rgba(r, g, b, a)\n * - Named: basic CSS color keywords\n *\n * Includes a cache for repeated lookups (the demo reuses ~10 colors).\n */\n\nconst _NAMED_COLORS: Record<string, number> = {\n black: 0x000000ff,\n white: 0xffffffff,\n red: 0xff0000ff,\n green: 0x008000ff,\n blue: 0x0000ffff,\n yellow: 0xffff00ff,\n cyan: 0x00ffffff,\n magenta: 0xff00ffff,\n orange: 0xffa500ff,\n transparent: 0x00000000,\n};\n\nconst _cache = new Map<string, Float32Array>();\n\n/**\n * Parse a CSS color string into [r, g, b, a] floats in [0, 1].\n * Returns a cached Float32Array — do NOT mutate the result.\n *\n * No _ prefix: called cross-file from canvas2d-shim.\n */\nexport function parseColor(css: string): Float32Array {\n const cached = _cache.get(css);\n if (cached) return cached;\n\n const result = _parse(css);\n _cache.set(css, result);\n return result;\n}\n\nfunction _parse(css: string): Float32Array {\n const s = css.trim();\n\n // #hex\n if (s.charCodeAt(0) === 0x23) { // '#'\n return _parseHex(s);\n }\n\n // rgb() / rgba()\n if (s.charCodeAt(0) === 0x72) { // 'r'\n return _parseRgb(s);\n }\n\n // Named color\n const named = _NAMED_COLORS[s.toLowerCase()];\n if (named !== undefined) {\n return new Float32Array([\n ((named >>> 24) & 0xff) / 255,\n ((named >>> 16) & 0xff) / 255,\n ((named >>> 8) & 0xff) / 255,\n (named & 0xff) / 255,\n ]);\n }\n\n // Fallback: opaque black\n return new Float32Array([0, 0, 0, 1]);\n}\n\nfunction _parseHex(s: string): Float32Array {\n const len = s.length;\n\n if (len === 4) {\n // #rgb → expand to #rrggbb\n const r = parseInt(s[1], 16);\n const g = parseInt(s[2], 16);\n const b = parseInt(s[3], 16);\n return new Float32Array([\n (r * 17) / 255,\n (g * 17) / 255,\n (b * 17) / 255,\n 1,\n ]);\n }\n\n if (len === 7) {\n // #rrggbb\n const r = parseInt(s.slice(1, 3), 16);\n const g = parseInt(s.slice(3, 5), 16);\n const b = parseInt(s.slice(5, 7), 16);\n return new Float32Array([r / 255, g / 255, b / 255, 1]);\n }\n\n if (len === 9) {\n // #rrggbbaa\n const r = parseInt(s.slice(1, 3), 16);\n const g = parseInt(s.slice(3, 5), 16);\n const b = parseInt(s.slice(5, 7), 16);\n const a = parseInt(s.slice(7, 9), 16);\n return new Float32Array([r / 255, g / 255, b / 255, a / 255]);\n }\n\n // #rgba (4-digit with alpha)\n if (len === 5) {\n const r = parseInt(s[1], 16);\n const g = parseInt(s[2], 16);\n const b = parseInt(s[3], 16);\n const a = parseInt(s[4], 16);\n return new Float32Array([\n (r * 17) / 255,\n (g * 17) / 255,\n (b * 17) / 255,\n (a * 17) / 255,\n ]);\n }\n\n return new Float32Array([0, 0, 0, 1]);\n}\n\nfunction _parseRgb(s: string): Float32Array {\n // Match both rgb(...) and rgba(...)\n // Extract the numeric values between parentheses\n const start = s.indexOf('(');\n const end = s.lastIndexOf(')');\n if (start === -1 || end === -1) return new Float32Array([0, 0, 0, 1]);\n\n const parts = s.slice(start + 1, end).split(',');\n const r = parseFloat(parts[0]) / 255;\n const g = parseFloat(parts[1]) / 255;\n const b = parseFloat(parts[2]) / 255;\n const a = parts.length >= 4 ? parseFloat(parts[3]) : 1;\n\n return new Float32Array([r, g, b, a]);\n}\n","/**\n * GLSL Shader Sources for canvas-ultrafast\n *\n * Content shaders (flat-color, textured) plus a passthrough display shader.\n * CRT post-processing shaders live in the maalata package.\n *\n * Coordinate convention:\n * - Content shaders use a 3x3 affine matrix (u_matrix) that maps\n * canvas pixel coordinates (top-left origin, Y-down) to clip space.\n * - Passthrough shader uses a fullscreen quad in [0,1] mapped to [-1,1] clip space.\n */\n\n// ---------------------------------------------------------------------------\n// Flat-color shader: rectangles, line quads, clear regions\n// ---------------------------------------------------------------------------\n\nexport const FLAT_VERTEX_SRC = `\n attribute vec2 a_position;\n uniform mat3 u_matrix;\n void main() {\n vec3 pos = u_matrix * vec3(a_position, 1.0);\n gl_Position = vec4(pos.xy, 0.0, 1.0);\n }\n`;\n\nexport const FLAT_FRAGMENT_SRC = `\n precision mediump float;\n uniform vec4 u_color;\n void main() {\n gl_FragColor = u_color;\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Textured quad shader: text rendering via OffscreenCanvas glyph upload\n// ---------------------------------------------------------------------------\n\nexport const TEXTURED_VERTEX_SRC = `\n attribute vec2 a_position;\n attribute vec2 a_texCoord;\n uniform mat3 u_matrix;\n varying vec2 v_texCoord;\n void main() {\n vec3 pos = u_matrix * vec3(a_position, 1.0);\n gl_Position = vec4(pos.xy, 0.0, 1.0);\n v_texCoord = a_texCoord;\n }\n`;\n\nexport const TEXTURED_FRAGMENT_SRC = `\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_texture;\n uniform vec4 u_color;\n void main() {\n vec4 texel = texture2D(u_texture, v_texCoord);\n gl_FragColor = texel * u_color;\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Passthrough display shader: fullscreen quad, reads FBO texture\n// ---------------------------------------------------------------------------\n\n/**\n * Vertex shader: fullscreen quad [0,1] → clip space [-1,1].\n * FBO textures are already in GL-native bottom-left origin (the orthographic\n * projection in matrix-stack.ts handles the canvas Y-down → GL Y-up flip),\n * so tex coords pass through without Y-flip.\n */\nexport const PASSTHROUGH_VERTEX_SRC = `\n attribute vec2 a_position;\n varying vec2 v_texCoord;\n void main() {\n v_texCoord = a_position;\n gl_Position = vec4(a_position * 2.0 - 1.0, 0, 1);\n }\n`;\n\n/**\n * Passthrough fragment shader: blit FBO texture to screen without effects.\n */\nexport const PASSTHROUGH_FRAGMENT_SRC = `\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_texture;\n void main() {\n gl_FragColor = texture2D(u_texture, v_texCoord);\n }\n`;\n","/**\n * Canvas 2D → WebGL Command Shim\n *\n * Translates CanvasCommand[] (recorded by CanvasAPI) into WebGL draw calls.\n * Handles the subset of Canvas 2D API used by the demo, plus reasonable\n * extensions. Operations not yet implemented log a warning and no-op.\n *\n * Rendering approach per command type:\n * - clearRect: gl.scissor + gl.clear\n * - fillRect: unit quad VBO + flat shader + transform uniform\n * - strokeRect: four thin quads (one per edge)\n * - fillText: render to OffscreenCanvas 2D → texImage2D → textured quad\n * - stroke(): expand line segments to quads on CPU, flat shader\n * - save/restore: matrix + state stack\n *\n * Text rendering uses an OffscreenCanvas with a 2D context as a glyph\n * rendering surface. At 8 FPS with ~5 text draws per frame, per-string\n * rendering (not glyph caching) is appropriate — texImage2D(OffscreenCanvas)\n * is a fast GPU upload path.\n */\n\nimport { CanvasCommand } from './canvas-api';\nimport { MatrixStack } from './matrix-stack';\nimport { parseColor } from './color-parser';\nimport {\n FLAT_VERTEX_SRC, FLAT_FRAGMENT_SRC,\n TEXTURED_VERTEX_SRC, TEXTURED_FRAGMENT_SRC,\n} from './shaders';\n\ninterface _DrawState {\n _fillColor: Float32Array;\n _strokeColor: Float32Array;\n _lineWidth: number;\n _globalAlpha: number;\n _font: string;\n _textAlign: CanvasTextAlign;\n _textBaseline: CanvasTextBaseline;\n _lineCap: CanvasLineCap;\n _lineJoin: CanvasLineJoin;\n _imageSmoothingEnabled: boolean;\n _letterSpacing: string;\n _clipActive: boolean;\n _clipRect: [number, number, number, number] | null;\n}\n\ninterface _ProgramInfo {\n _program: WebGLProgram;\n _matrixLoc: WebGLUniformLocation | null;\n _colorLoc: WebGLUniformLocation | null;\n _textureLoc: WebGLUniformLocation | null;\n _positionLoc: number;\n _texCoordLoc: number;\n}\n\nexport class Canvas2DShim {\n private _gl: WebGLRenderingContext;\n private _width: number;\n private _height: number;\n\n // Transform\n private _matrix: MatrixStack;\n\n // State\n private _fillColor: Float32Array = new Float32Array([0, 0, 0, 1]);\n private _strokeColor: Float32Array = new Float32Array([0, 0, 0, 1]);\n private _lineWidth = 1;\n private _globalAlpha = 1;\n private _font = '10px sans-serif';\n private _textAlign: CanvasTextAlign = 'start';\n private _textBaseline: CanvasTextBaseline = 'alphabetic';\n private _lineCap: CanvasLineCap = 'butt';\n private _lineJoin: CanvasLineJoin = 'miter';\n private _imageSmoothingEnabled = true;\n private _letterSpacing = '';\n private _clipActive = false;\n private _clipRect: [number, number, number, number] | null = null;\n private _pendingClipRect: [number, number, number, number] | null = null;\n private _imageTexCache = new WeakMap<object, { _tex: WebGLTexture; _isImage: boolean }>();\n private _stateStack: _DrawState[] = [];\n\n // Path state\n private _pathSegments: number[] = []; // flat: x0,y0,x1,y1,...\n private _currentX = 0;\n private _currentY = 0;\n private _subpathStartX = 0;\n private _subpathStartY = 0;\n\n // WebGL resources\n private _flat: _ProgramInfo;\n private _textured: _ProgramInfo;\n private _unitQuadVBO: WebGLBuffer;\n private _dynamicVBO: WebGLBuffer;\n private _texturedVBO: WebGLBuffer;\n private _textTexture: WebGLTexture;\n\n // Text rendering surface\n private _textCanvas: OffscreenCanvas;\n private _textCtx: OffscreenCanvasRenderingContext2D;\n\n // Temp arrays to avoid allocation in hot path\n private _tmpColor = new Float32Array(4);\n\n constructor(gl: WebGLRenderingContext, width: number, height: number) {\n this._gl = gl;\n this._width = width;\n this._height = height;\n this._matrix = new MatrixStack(width, height);\n\n // Compile shader programs\n this._flat = this._createProgram(\n FLAT_VERTEX_SRC, FLAT_FRAGMENT_SRC, false\n );\n this._textured = this._createProgram(\n TEXTURED_VERTEX_SRC, TEXTURED_FRAGMENT_SRC, true\n );\n\n // Unit quad VBO: two triangles covering [0,0]-[1,1]\n // Used for fillRect (scaled via matrix) and fullscreen blits\n this._unitQuadVBO = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, this._unitQuadVBO);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([\n 0, 0, 1, 0, 0, 1,\n 0, 1, 1, 0, 1, 1,\n ]), gl.STATIC_DRAW);\n\n // Dynamic VBO for line quads — uses orphaning for double-buffer\n this._dynamicVBO = gl.createBuffer()!;\n\n // Textured quad VBO: position + texcoord interleaved\n this._texturedVBO = gl.createBuffer()!;\n\n // Text rendering texture\n this._textTexture = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, this._textTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n // OffscreenCanvas for text glyph rendering\n this._textCanvas = new OffscreenCanvas(512, 128);\n this._textCtx = this._textCanvas.getContext('2d')!;\n\n // Enable blending for standard source-over compositing\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n }\n\n /**\n * Execute a batch of Canvas 2D commands as WebGL draw calls.\n * No _ prefix: called cross-file from webgl-renderer.\n */\n executeBatch(commands: CanvasCommand[]): void {\n for (const cmd of commands) {\n if (cmd.type === 'property') {\n this._setProperty(cmd.name, cmd.value);\n } else {\n this._callMethod(cmd.name, cmd.args);\n }\n }\n }\n\n /**\n * Update canvas dimensions on resize.\n * No _ prefix: called cross-file.\n */\n resize(width: number, height: number): void {\n this._width = width;\n this._height = height;\n this._matrix.resize(width, height);\n }\n\n /**\n * Clean up WebGL resources.\n * No _ prefix: called cross-file.\n */\n destroy(): void {\n const gl = this._gl;\n gl.deleteBuffer(this._unitQuadVBO);\n gl.deleteBuffer(this._dynamicVBO);\n gl.deleteBuffer(this._texturedVBO);\n gl.deleteTexture(this._textTexture);\n gl.deleteProgram(this._flat._program);\n gl.deleteProgram(this._textured._program);\n }\n\n // -------------------------------------------------------------------------\n // Private: property handling\n // -------------------------------------------------------------------------\n\n private _setProperty(name: string, value: unknown): void {\n switch (name) {\n case 'fillStyle':\n this._fillColor = parseColor(value as string);\n break;\n case 'strokeStyle':\n this._strokeColor = parseColor(value as string);\n break;\n case 'lineWidth':\n this._lineWidth = value as number;\n break;\n case 'globalAlpha':\n this._globalAlpha = value as number;\n break;\n case 'font':\n this._font = value as string;\n break;\n case 'textAlign':\n this._textAlign = value as CanvasTextAlign;\n break;\n case 'textBaseline':\n this._textBaseline = value as CanvasTextBaseline;\n break;\n case 'lineCap':\n this._lineCap = value as CanvasLineCap;\n break;\n case 'lineJoin':\n this._lineJoin = value as CanvasLineJoin;\n break;\n case 'imageSmoothingEnabled':\n this._imageSmoothingEnabled = value as boolean;\n break;\n case 'letterSpacing':\n this._letterSpacing = value as string;\n break;\n default:\n // Unsupported properties: silently ignore\n break;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: method dispatch\n // -------------------------------------------------------------------------\n\n private _callMethod(name: string, args: unknown[]): void {\n switch (name) {\n // Rectangles\n case 'clearRect':\n this._clearRect(args[0] as number, args[1] as number, args[2] as number, args[3] as number);\n break;\n case 'fillRect':\n this._fillRect(args[0] as number, args[1] as number, args[2] as number, args[3] as number);\n break;\n case 'strokeRect':\n this._strokeRect(args[0] as number, args[1] as number, args[2] as number, args[3] as number);\n break;\n\n // Text\n case 'fillText':\n this._fillText(args[0] as string, args[1] as number, args[2] as number);\n break;\n case 'strokeText':\n this._strokeText(args[0] as string, args[1] as number, args[2] as number);\n break;\n\n // Images\n case 'drawImage':\n this._drawImage(args);\n break;\n\n // Path\n case 'beginPath':\n this._pathSegments = [];\n this._pendingClipRect = null;\n break;\n case 'closePath':\n if (this._currentX !== this._subpathStartX || this._currentY !== this._subpathStartY) {\n this._pathSegments.push(\n this._currentX, this._currentY,\n this._subpathStartX, this._subpathStartY\n );\n this._currentX = this._subpathStartX;\n this._currentY = this._subpathStartY;\n }\n break;\n case 'moveTo':\n this._currentX = this._subpathStartX = args[0] as number;\n this._currentY = this._subpathStartY = args[1] as number;\n break;\n case 'lineTo': {\n const x = args[0] as number;\n const y = args[1] as number;\n this._pathSegments.push(this._currentX, this._currentY, x, y);\n this._currentX = x;\n this._currentY = y;\n break;\n }\n case 'rect': {\n const rx = args[0] as number, ry = args[1] as number;\n const rw = args[2] as number, rh = args[3] as number;\n // Store as pending clip rect (used if clip() follows)\n this._pendingClipRect = [rx, ry, rw, rh];\n // Also add 4 line segments to path for potential stroke()\n this._pathSegments.push(\n rx, ry, rx + rw, ry, // top\n rx + rw, ry, rx + rw, ry + rh, // right\n rx + rw, ry + rh, rx, ry + rh, // bottom\n rx, ry + rh, rx, ry, // left\n );\n break;\n }\n case 'clip':\n this._applyClip();\n break;\n case 'stroke':\n this._strokePath();\n break;\n case 'fill':\n // Convex fill only — not heavily used in demo beyond fillRect\n break;\n\n // State\n case 'save':\n this._save();\n break;\n case 'restore':\n this._restore();\n break;\n\n // Transforms\n case 'translate':\n this._matrix.translate(args[0] as number, args[1] as number);\n break;\n case 'rotate':\n this._matrix.rotate(args[0] as number);\n break;\n case 'scale':\n this._matrix.scale(args[0] as number, args[1] as number);\n break;\n case 'transform':\n this._matrix.transform(\n args[0] as number, args[1] as number, args[2] as number,\n args[3] as number, args[4] as number, args[5] as number\n );\n break;\n case 'setTransform':\n this._matrix.setTransform(\n args[0] as number, args[1] as number, args[2] as number,\n args[3] as number, args[4] as number, args[5] as number\n );\n break;\n case 'resetTransform':\n this._matrix.resetTransform();\n break;\n\n default:\n // Unsupported methods: silently ignore (arc, bezierCurveTo, etc.)\n break;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: drawing operations\n // -------------------------------------------------------------------------\n\n private _clearRect(x: number, y: number, w: number, h: number): void {\n const gl = this._gl;\n // WebGL scissor uses bottom-left origin, canvas uses top-left\n gl.enable(gl.SCISSOR_TEST);\n gl.scissor(x, this._height - y - h, w, h);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.disable(gl.SCISSOR_TEST);\n }\n\n private _fillRect(x: number, y: number, w: number, h: number): void {\n const gl = this._gl;\n const prog = this._flat;\n\n gl.useProgram(prog._program);\n\n // Build transform: current matrix × translate(x,y) × scale(w,h)\n // Applied to unit quad [0,1]×[0,1] → fills [x,y,x+w,y+h]\n this._matrix.save();\n this._matrix.translate(x, y);\n this._matrix.scale(w, h);\n\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, this._fillColor, this._globalAlpha);\n\n this._matrix.restore();\n\n // Draw unit quad\n gl.bindBuffer(gl.ARRAY_BUFFER, this._unitQuadVBO);\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, 0, 0);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n }\n\n private _strokeRect(x: number, y: number, w: number, h: number): void {\n // Draw four edges as thin quads\n const lw = this._lineWidth;\n const hlw = lw / 2;\n\n // Top edge\n this._fillRectWithColor(x - hlw, y - hlw, w + lw, lw, this._strokeColor);\n // Bottom edge\n this._fillRectWithColor(x - hlw, y + h - hlw, w + lw, lw, this._strokeColor);\n // Left edge\n this._fillRectWithColor(x - hlw, y + hlw, lw, h - lw, this._strokeColor);\n // Right edge\n this._fillRectWithColor(x + w - hlw, y + hlw, lw, h - lw, this._strokeColor);\n }\n\n /** Internal: draw a filled rect with a specific color (used by strokeRect). */\n private _fillRectWithColor(x: number, y: number, w: number, h: number, color: Float32Array): void {\n const gl = this._gl;\n const prog = this._flat;\n\n gl.useProgram(prog._program);\n\n this._matrix.save();\n this._matrix.translate(x, y);\n this._matrix.scale(w, h);\n\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, color, this._globalAlpha);\n\n this._matrix.restore();\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this._unitQuadVBO);\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, 0, 0);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n }\n\n private _strokePath(): void {\n const segs = this._pathSegments;\n if (segs.length === 0) return;\n\n const gl = this._gl;\n const prog = this._flat;\n const halfW = Math.max(this._lineWidth / 2, 0.5);\n\n // Expand line segments to quads on CPU\n // Each segment (x0,y0,x1,y1) → 6 vertices (2 triangles)\n const segCount = segs.length / 4;\n const vertices = new Float32Array(segCount * 12); // 6 vertices × 2 coords\n\n for (let i = 0, vi = 0; i < segs.length; i += 4) {\n const x0 = segs[i], y0 = segs[i + 1], x1 = segs[i + 2], y1 = segs[i + 3];\n const dx = x1 - x0;\n const dy = y1 - y0;\n const len = Math.sqrt(dx * dx + dy * dy);\n\n if (len < 0.001) continue; // Skip degenerate segments\n\n // Normal perpendicular to line direction\n const nx = (-dy / len) * halfW;\n const ny = (dx / len) * halfW;\n\n // Four corners of the quad\n const ax = x0 + nx, ay = y0 + ny; // top-left\n const bx = x0 - nx, by = y0 - ny; // bottom-left\n const cx = x1 + nx, cy = y1 + ny; // top-right\n const dx2 = x1 - nx, dy2 = y1 - ny; // bottom-right\n\n // Triangle 1: A, B, C\n vertices[vi++] = ax; vertices[vi++] = ay;\n vertices[vi++] = bx; vertices[vi++] = by;\n vertices[vi++] = cx; vertices[vi++] = cy;\n // Triangle 2: B, D, C\n vertices[vi++] = bx; vertices[vi++] = by;\n vertices[vi++] = dx2; vertices[vi++] = dy2;\n vertices[vi++] = cx; vertices[vi++] = cy;\n }\n\n // Upload to dynamic VBO using orphaning (bufferData null pattern)\n gl.bindBuffer(gl.ARRAY_BUFFER, this._dynamicVBO);\n gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW);\n\n gl.useProgram(prog._program);\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, this._strokeColor, this._globalAlpha);\n\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, 0, 0);\n gl.drawArrays(gl.TRIANGLES, 0, segCount * 6);\n }\n\n private _drawImage(args: unknown[]): void {\n const gl = this._gl;\n const image = args[0] as CanvasImageSource;\n\n let sx: number, sy: number, sw: number, sh: number;\n let dx: number, dy: number, dw: number, dh: number;\n\n // Get image dimensions\n const imgW = _getImageWidth(image);\n const imgH = _getImageHeight(image);\n\n if (args.length === 3) {\n // drawImage(image, dx, dy)\n sx = 0; sy = 0; sw = imgW; sh = imgH;\n dx = args[1] as number; dy = args[2] as number;\n dw = imgW; dh = imgH;\n } else if (args.length === 5) {\n // drawImage(image, dx, dy, dw, dh)\n sx = 0; sy = 0; sw = imgW; sh = imgH;\n dx = args[1] as number; dy = args[2] as number;\n dw = args[3] as number; dh = args[4] as number;\n } else {\n // drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)\n sx = args[1] as number; sy = args[2] as number;\n sw = args[3] as number; sh = args[4] as number;\n dx = args[5] as number; dy = args[6] as number;\n dw = args[7] as number; dh = args[8] as number;\n }\n\n // Get or create texture for this image source\n const tex = this._getOrUploadTexture(image, imgW, imgH);\n\n // Set filtering based on imageSmoothingEnabled\n const filter = this._imageSmoothingEnabled ? gl.LINEAR : gl.NEAREST;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);\n\n // Compute UV coordinates for source sub-rect\n const uMin = sx / imgW;\n const vMin = sy / imgH;\n const uMax = (sx + sw) / imgW;\n const vMax = (sy + sh) / imgH;\n\n // Draw textured quad with interleaved position + texcoord\n const prog = this._textured;\n const verts = new Float32Array([\n dx, dy, uMin, vMin,\n dx + dw, dy, uMax, vMin,\n dx, dy + dh, uMin, vMax,\n dx, dy + dh, uMin, vMax,\n dx + dw, dy, uMax, vMin,\n dx + dw, dy + dh, uMax, vMax,\n ]);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this._texturedVBO);\n gl.bufferData(gl.ARRAY_BUFFER, verts, gl.DYNAMIC_DRAW);\n\n gl.useProgram(prog._program);\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n // White color tint with globalAlpha — no color modification, just alpha\n gl.uniform4f(prog._colorLoc!, 1, 1, 1, this._globalAlpha);\n\n // Standard alpha blending (not premultiplied for image textures)\n const stride = 16; // 4 floats × 4 bytes\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, stride, 0);\n gl.enableVertexAttribArray(prog._texCoordLoc);\n gl.vertexAttribPointer(prog._texCoordLoc, 2, gl.FLOAT, false, stride, 8);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.uniform1i(prog._textureLoc, 0);\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Disable texcoord attrib to avoid interfering with flat shader\n gl.disableVertexAttribArray(prog._texCoordLoc);\n }\n\n private _getOrUploadTexture(image: CanvasImageSource, imgW: number, imgH: number): WebGLTexture {\n const gl = this._gl;\n const key = image as unknown as object;\n const cached = this._imageTexCache.get(key);\n\n // HTMLImageElement/SVGImageElement: upload once, cache permanently\n // HTMLCanvasElement/OffscreenCanvas: always re-upload (content may change)\n const isImage = (image instanceof HTMLImageElement) || (image instanceof SVGImageElement);\n\n if (cached) {\n if (cached._isImage) {\n // Static image — reuse cached texture\n return cached._tex;\n }\n // Canvas source — re-upload to existing texture\n gl.bindTexture(gl.TEXTURE_2D, cached._tex);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image as TexImageSource);\n return cached._tex;\n }\n\n // Create new texture\n const tex = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\n // Detect if we need to handle alpha properly\n // For canvas sources, use standard upload; for images, avoid premultiply\n if (imgW > 0 && imgH > 0) {\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image as TexImageSource);\n }\n\n this._imageTexCache.set(key, { _tex: tex, _isImage: isImage });\n return tex;\n }\n\n private _applyClip(): void {\n const gl = this._gl;\n if (this._pendingClipRect) {\n const [x, y, w, h] = this._pendingClipRect;\n gl.enable(gl.SCISSOR_TEST);\n // Convert canvas coords (top-left origin) to GL coords (bottom-left origin)\n gl.scissor(x, this._height - y - h, w, h);\n this._clipActive = true;\n this._clipRect = [x, y, w, h];\n }\n }\n\n private _fillText(text: string, x: number, y: number): void {\n this._renderText(text, x, y, 'fill');\n }\n\n private _strokeText(text: string, x: number, y: number): void {\n this._renderText(text, x, y, 'stroke');\n }\n\n private _renderText(text: string, x: number, y: number, mode: 'fill' | 'stroke'): void {\n const gl = this._gl;\n const tCtx = this._textCtx;\n\n // Configure text rendering context\n tCtx.font = this._font;\n tCtx.textAlign = 'left'; // Always render left-aligned, position via WebGL\n tCtx.textBaseline = 'top'; // Always render from top, adjust Y via offset\n if (this._letterSpacing) {\n tCtx.letterSpacing = this._letterSpacing;\n }\n\n // Measure text\n const metrics = tCtx.measureText(text);\n const textWidth = Math.ceil(metrics.width) + 4; // +4 for antialiasing padding\n const fontSize = _parseFontSize(this._font);\n const textHeight = Math.ceil(fontSize * 1.5) + 4; // approximate height with descenders\n\n if (textWidth <= 0 || textHeight <= 0) return;\n\n // Resize text canvas if needed\n if (this._textCanvas.width < textWidth || this._textCanvas.height < textHeight) {\n this._textCanvas.width = Math.max(this._textCanvas.width, textWidth);\n this._textCanvas.height = Math.max(this._textCanvas.height, textHeight);\n // Re-set font after resize (context is reset)\n tCtx.font = this._font;\n tCtx.textAlign = 'left';\n tCtx.textBaseline = 'top';\n }\n\n // Clear and render text\n tCtx.clearRect(0, 0, this._textCanvas.width, this._textCanvas.height);\n\n if (mode === 'fill') {\n tCtx.fillStyle = 'white'; // White text, tinted by WebGL uniform\n tCtx.fillText(text, 2, 2); // +2 padding offset\n } else {\n tCtx.strokeStyle = 'white';\n tCtx.lineWidth = this._lineWidth;\n tCtx.strokeText(text, 2, 2);\n }\n\n // Upload text canvas to texture\n gl.bindTexture(gl.TEXTURE_2D, this._textTexture);\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);\n gl.texImage2D(\n gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,\n this._textCanvas\n );\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0);\n\n // Compute text position adjustments\n const color = mode === 'fill' ? this._fillColor : this._strokeColor;\n let drawX = x - 2; // compensate for padding\n let drawY = y - 2;\n\n // Adjust for textAlign\n switch (this._textAlign) {\n case 'center': drawX -= textWidth / 2; break;\n case 'right':\n case 'end': drawX -= textWidth; break;\n }\n\n // Adjust for textBaseline\n switch (this._textBaseline) {\n case 'top': /* drawY stays */ break;\n case 'middle': drawY -= textHeight / 2; break;\n case 'alphabetic':\n case 'ideographic': drawY -= fontSize; break;\n case 'bottom':\n case 'hanging': drawY -= textHeight; break;\n }\n\n // Draw textured quad\n this._drawTexturedQuad(\n drawX, drawY, textWidth, textHeight,\n textWidth / this._textCanvas.width,\n textHeight / this._textCanvas.height,\n color\n );\n }\n\n private _drawTexturedQuad(\n x: number, y: number, w: number, h: number,\n uMax: number, vMax: number,\n color: Float32Array\n ): void {\n const gl = this._gl;\n const prog = this._textured;\n\n // Interleaved position + texcoord (x, y, u, v)\n const verts = new Float32Array([\n x, y, 0, 0,\n x + w, y, uMax, 0,\n x, y + h, 0, vMax,\n x, y + h, 0, vMax,\n x + w, y, uMax, 0,\n x + w, y + h, uMax, vMax,\n ]);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this._texturedVBO);\n gl.bufferData(gl.ARRAY_BUFFER, verts, gl.DYNAMIC_DRAW);\n\n gl.useProgram(prog._program);\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, color, this._globalAlpha);\n\n // Use premultiplied alpha blending for text\n gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n\n const stride = 16; // 4 floats × 4 bytes\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, stride, 0);\n gl.enableVertexAttribArray(prog._texCoordLoc);\n gl.vertexAttribPointer(prog._texCoordLoc, 2, gl.FLOAT, false, stride, 8);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this._textTexture);\n gl.uniform1i(prog._textureLoc, 0);\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Restore standard blending\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n\n // Disable texcoord attrib to avoid interfering with flat shader\n gl.disableVertexAttribArray(prog._texCoordLoc);\n }\n\n // -------------------------------------------------------------------------\n // Private: state management\n // -------------------------------------------------------------------------\n\n private _save(): void {\n this._matrix.save();\n this._stateStack.push({\n _fillColor: new Float32Array(this._fillColor),\n _strokeColor: new Float32Array(this._strokeColor),\n _lineWidth: this._lineWidth,\n _globalAlpha: this._globalAlpha,\n _font: this._font,\n _textAlign: this._textAlign,\n _textBaseline: this._textBaseline,\n _lineCap: this._lineCap,\n _lineJoin: this._lineJoin,\n _imageSmoothingEnabled: this._imageSmoothingEnabled,\n _letterSpacing: this._letterSpacing,\n _clipActive: this._clipActive,\n _clipRect: this._clipRect ? [...this._clipRect] as [number, number, number, number] : null,\n });\n }\n\n private _restore(): void {\n this._matrix.restore();\n const gl = this._gl;\n const state = this._stateStack.pop();\n if (state) {\n this._fillColor = state._fillColor;\n this._strokeColor = state._strokeColor;\n this._lineWidth = state._lineWidth;\n this._globalAlpha = state._globalAlpha;\n this._font = state._font;\n this._textAlign = state._textAlign;\n this._textBaseline = state._textBaseline;\n this._lineCap = state._lineCap;\n this._lineJoin = state._lineJoin;\n this._imageSmoothingEnabled = state._imageSmoothingEnabled;\n this._letterSpacing = state._letterSpacing;\n this._clipActive = state._clipActive;\n this._clipRect = state._clipRect;\n\n // Restore scissor state\n if (this._clipActive && this._clipRect) {\n const [x, y, w, h] = this._clipRect;\n gl.enable(gl.SCISSOR_TEST);\n gl.scissor(x, this._height - y - h, w, h);\n } else {\n gl.disable(gl.SCISSOR_TEST);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: WebGL helpers\n // -------------------------------------------------------------------------\n\n private _setColorUniform(loc: WebGLUniformLocation, color: Float32Array, alpha: number): void {\n // Premultiply globalAlpha into the color's alpha channel\n const a = color[3] * alpha;\n this._gl.uniform4f(loc, color[0], color[1], color[2], a);\n }\n\n private _createProgram(vSrc: string, fSrc: string, hasTexCoord: boolean): _ProgramInfo {\n const gl = this._gl;\n const vs = this._compileShader(gl.VERTEX_SHADER, vSrc);\n const fs = this._compileShader(gl.FRAGMENT_SHADER, fSrc);\n\n const program = gl.createProgram()!;\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n throw new Error('Shader link failed: ' + gl.getProgramInfoLog(program));\n }\n\n // Delete shaders after linking (they're embedded in the program now)\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n return {\n _program: program,\n _matrixLoc: gl.getUniformLocation(program, 'u_matrix'),\n _colorLoc: gl.getUniformLocation(program, 'u_color'),\n _textureLoc: hasTexCoord ? gl.getUniformLocation(program, 'u_texture') : null,\n _positionLoc: gl.getAttribLocation(program, 'a_position'),\n _texCoordLoc: hasTexCoord ? gl.getAttribLocation(program, 'a_texCoord') : -1,\n };\n }\n\n private _compileShader(type: number, source: string): WebGLShader {\n const gl = this._gl;\n const shader = gl.createShader(type)!;\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader);\n gl.deleteShader(shader);\n throw new Error('Shader compile failed: ' + info);\n }\n return shader;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Utility\n// ---------------------------------------------------------------------------\n\n/** Extract numeric font size from a CSS font string like \"bold 20px monospace\". */\nfunction _parseFontSize(font: string): number {\n const match = font.match(/(\\d+(?:\\.\\d+)?)\\s*px/);\n return match ? parseFloat(match[1]) : 10;\n}\n\n/** Get width of a CanvasImageSource (handles HTMLImageElement, HTMLCanvasElement, OffscreenCanvas, etc.) */\nfunction _getImageWidth(img: CanvasImageSource): number {\n if ('naturalWidth' in img) return (img as HTMLImageElement).naturalWidth;\n return (img as HTMLCanvasElement | OffscreenCanvas).width;\n}\n\n/** Get height of a CanvasImageSource. */\nfunction _getImageHeight(img: CanvasImageSource): number {\n if ('naturalHeight' in img) return (img as HTMLImageElement).naturalHeight;\n return (img as HTMLCanvasElement | OffscreenCanvas).height;\n}\n","/**\n * UltrafastRenderer — WebGL2 Triple-Buffered Canvas 2D Renderer\n *\n * A standalone WebGL-accelerated Canvas 2D rendering engine. Provides a\n * CanvasAPI for recording draw commands and a triple-buffered FBO pipeline\n * that displays them via a passthrough shader at vsync rate.\n *\n * Triple buffer scheme (all on main thread, lock-free via JS single-threading):\n *\n * Content submission:\n * submitBatch(commands)\n * → bind writeFBO\n * → Canvas2DShim executes commands as WebGL draw calls\n * → swap: writeFBO ↔ readyFBO\n *\n * Display loop (vsync rate via RAF):\n * RAF callback\n * → auto-flush: drain CanvasAPI commands → submitBatch\n * → bind default framebuffer (display canvas)\n * → read readyFBO texture → passthrough blit → screen\n *\n * Extension points for downstream consumers (e.g. maalata CRT display):\n * - getGL(): access the WebGL2 context\n * - getReadyTexture(): read the latest rendered frame as a texture\n * - stopDisplay() / startDisplay(): take over the display loop\n */\n\nimport { CanvasAPI, type CanvasCommand } from './canvas-api';\nimport { Canvas2DShim } from './canvas2d-shim';\nimport {\n PASSTHROUGH_VERTEX_SRC,\n PASSTHROUGH_FRAGMENT_SRC,\n} from './shaders';\n\ninterface _FBO {\n _fbo: WebGLFramebuffer;\n _texture: WebGLTexture;\n}\n\nexport class UltrafastRenderer {\n private _gl: WebGL2RenderingContext;\n private _canvas: HTMLCanvasElement;\n private _shim: Canvas2DShim;\n private _api: CanvasAPI;\n private _rafId: number | null = null;\n\n // Triple buffer: three FBOs with color texture attachments\n private _fbos!: [_FBO, _FBO, _FBO];\n private _writeIdx = 0;\n private _readyIdx = 1;\n private _displayIdx = 2;\n private _hasContent = false;\n\n // Display program\n private _passthroughProgram: WebGLProgram;\n\n // Fullscreen quad VBO\n private _quadVBO!: WebGLBuffer;\n private _quadPositionLoc = -1;\n\n constructor(canvas: HTMLCanvasElement) {\n this._canvas = canvas;\n this._api = new CanvasAPI();\n\n // Create WebGL2 context with optimizations\n const gl = canvas.getContext('webgl2', {\n alpha: false,\n antialias: false,\n desynchronized: true,\n preserveDrawingBuffer: true,\n powerPreference: 'high-performance',\n });\n\n if (!gl) {\n throw new Error('WebGL2 not supported');\n }\n this._gl = gl;\n\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\n\n // Initialize triple buffer FBOs\n this._initFBOs();\n\n // Initialize Canvas 2D shim (uses same GL context)\n this._shim = new Canvas2DShim(gl, canvas.width, canvas.height);\n\n // Initialize passthrough display program\n this._passthroughProgram = this._createShaderProgram(\n PASSTHROUGH_VERTEX_SRC, PASSTHROUGH_FRAGMENT_SRC\n );\n\n // Initialize fullscreen quad VBO for display pass\n this._initQuadVBO();\n\n // Clear all FBOs to black initially\n this._clearAllFBOs();\n\n // Auto-start display loop\n this.startDisplay();\n }\n\n // -------------------------------------------------------------------------\n // Public API (no _ prefix: cross-file access safe from mangleProps)\n // -------------------------------------------------------------------------\n\n /** Get the CanvasAPI for recording draw commands. */\n getCanvasAPI(): CanvasAPI {\n return this._api;\n }\n\n /**\n * Submit a batch of Canvas 2D commands to be rendered into the write FBO.\n * After rendering, the write and ready FBOs are swapped so the display\n * loop picks up the latest frame.\n */\n submitBatch(commands: CanvasCommand[]): void {\n if (commands.length === 0) return;\n const gl = this._gl;\n\n // Bind write FBO as render target\n gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbos[this._writeIdx]._fbo);\n gl.viewport(0, 0, this._canvas.width, this._canvas.height);\n\n // Execute Canvas 2D commands as WebGL draw calls\n this._shim.executeBatch(commands);\n\n // Swap write ↔ ready (new frame becomes available for display)\n const tmp = this._writeIdx;\n this._writeIdx = this._readyIdx;\n this._readyIdx = tmp;\n this._hasContent = true;\n }\n\n /** Start the passthrough RAF display loop with auto-flush. */\n startDisplay(): void {\n if (this._rafId !== null) return;\n this._displayLoop();\n }\n\n /** Stop the passthrough RAF display loop. Last frame persists (preserveDrawingBuffer). */\n stopDisplay(): void {\n if (this._rafId !== null) {\n cancelAnimationFrame(this._rafId);\n this._rafId = null;\n }\n }\n\n /** Returns the display canvas element. */\n getCanvas(): HTMLCanvasElement {\n return this._canvas;\n }\n\n /** Get canvas dimensions. */\n getCanvasSize(): { width: number; height: number } {\n return { width: this._canvas.width, height: this._canvas.height };\n }\n\n /** Capture the current displayed frame as an ImageBitmap. */\n screenshot(): Promise<ImageBitmap> {\n this._renderDisplay();\n return createImageBitmap(this._canvas);\n }\n\n /** Clean up all WebGL resources. */\n destroy(): void {\n this.stopDisplay();\n const gl = this._gl;\n\n this._shim.destroy();\n\n for (const fbo of this._fbos) {\n gl.deleteFramebuffer(fbo._fbo);\n gl.deleteTexture(fbo._texture);\n }\n\n gl.deleteProgram(this._passthroughProgram);\n gl.deleteBuffer(this._quadVBO);\n\n const ext = gl.getExtension('WEBGL_lose_context');\n if (ext) ext.loseContext();\n }\n\n // -------------------------------------------------------------------------\n // Extension points (used by maalata CRT display)\n // -------------------------------------------------------------------------\n\n /** Returns the WebGL2 context for external rendering (e.g. CRT shader). */\n getGL(): WebGL2RenderingContext {\n return this._gl;\n }\n\n /** Returns the ready FBO's texture — the latest fully rendered frame. */\n getReadyTexture(): WebGLTexture {\n return this._fbos[this._readyIdx]._texture;\n }\n\n // -------------------------------------------------------------------------\n // Private: display loop\n // -------------------------------------------------------------------------\n\n private _displayLoop(): void {\n this._rafId = requestAnimationFrame(() => this._displayLoop());\n\n // Auto-flush: drain any pending CanvasAPI commands into the pipeline\n const cmds = this._api.takeCommands();\n if (cmds.length) this.submitBatch(cmds);\n\n this._renderDisplay();\n }\n\n /**\n * Render the ready FBO to the display canvas via passthrough shader.\n * Called at vsync rate by RAF, or once synchronously for screenshots.\n */\n private _renderDisplay(): void {\n if (!this._hasContent) return;\n\n const gl = this._gl;\n\n // Bind default framebuffer (display canvas backbuffer)\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, this._canvas.width, this._canvas.height);\n\n // Bind the ready FBO's texture as input\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this._fbos[this._readyIdx]._texture);\n\n gl.useProgram(this._passthroughProgram);\n\n // Draw fullscreen quad\n gl.bindBuffer(gl.ARRAY_BUFFER, this._quadVBO);\n gl.enableVertexAttribArray(this._quadPositionLoc);\n gl.vertexAttribPointer(this._quadPositionLoc, 2, gl.FLOAT, false, 0, 0);\n\n gl.disable(gl.BLEND);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n gl.enable(gl.BLEND);\n }\n\n // -------------------------------------------------------------------------\n // Private: initialization\n // -------------------------------------------------------------------------\n\n private _initFBOs(): void {\n this._fbos = [\n this._createFBO(),\n this._createFBO(),\n this._createFBO(),\n ];\n }\n\n private _createFBO(): _FBO {\n const gl = this._gl;\n const w = this._canvas.width;\n const h = this._canvas.height;\n\n const fbo = gl.createFramebuffer()!;\n gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);\n\n const texture = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, w, h);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);\n\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error('Framebuffer incomplete: 0x' + status.toString(16));\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n return { _fbo: fbo, _texture: texture };\n }\n\n private _clearAllFBOs(): void {\n const gl = this._gl;\n for (const fbo of this._fbos) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, fbo._fbo);\n gl.clearColor(0, 0, 0, 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.clearColor(0, 0, 0, 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n\n private _initQuadVBO(): void {\n const gl = this._gl;\n\n this._quadVBO = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, this._quadVBO);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([\n 0, 0, 1, 0, 0, 1,\n 0, 1, 1, 0, 1, 1,\n ]), gl.STATIC_DRAW);\n\n this._quadPositionLoc = gl.getAttribLocation(this._passthroughProgram, 'a_position');\n }\n\n // -------------------------------------------------------------------------\n // Private: shader helpers\n // -------------------------------------------------------------------------\n\n private _createShaderProgram(vSrc: string, fSrc: string): WebGLProgram {\n const gl = this._gl;\n const vs = this._compileShader(gl.VERTEX_SHADER, vSrc);\n const fs = this._compileShader(gl.FRAGMENT_SHADER, fSrc);\n\n const program = gl.createProgram()!;\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n throw new Error('Shader link failed: ' + gl.getProgramInfoLog(program));\n }\n\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n return program;\n }\n\n private _compileShader(type: number, source: string): WebGLShader {\n const gl = this._gl;\n const shader = gl.createShader(type)!;\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader);\n gl.deleteShader(shader);\n throw new Error('Shader compile failed: ' + info);\n }\n return shader;\n }\n}\n"],"names":["exports"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"canvas-ultrafast.umd.js","sources":["../src/canvas-api.ts","../src/matrix-stack.ts","../src/color-parser.ts","../src/shaders.ts","../src/canvas2d-shim.ts","../src/renderer.ts"],"sourcesContent":["/**\n * Canvas API Wrapper\n *\n * Provides a Canvas 2D API that records commands locally without await.\n * Commands are batched and sent to the worker for execution.\n */\n\ntype CanvasPropertyMap = {\n fillStyle: string | CanvasGradient | CanvasPattern;\n strokeStyle: string | CanvasGradient | CanvasPattern;\n lineWidth: number;\n lineCap: CanvasLineCap;\n lineJoin: CanvasLineJoin;\n miterLimit: number;\n lineDashOffset: number;\n font: string;\n textAlign: CanvasTextAlign;\n textBaseline: CanvasTextBaseline;\n globalAlpha: number;\n globalCompositeOperation: GlobalCompositeOperation;\n shadowBlur: number;\n shadowColor: string;\n shadowOffsetX: number;\n shadowOffsetY: number;\n imageSmoothingEnabled: boolean;\n letterSpacing: string;\n};\n\nexport type CanvasCommand =\n | { type: 'property'; name: string; value: unknown }\n | { type: 'method'; name: string; args: unknown[] };\n\nexport class CanvasAPI {\n private _c: CanvasCommand[] = [];\n private _cp: Partial<CanvasPropertyMap> = {};\n\n private _m(n: string, ...a: unknown[]): void {\n this._c.push({ type: 'method', name: n, args: a });\n }\n\n private _p<K extends keyof CanvasPropertyMap>(n: K, v: CanvasPropertyMap[K]): void {\n this._cp[n] = v;\n this._c.push({ type: 'property', name: n, value: v });\n }\n\n /**\n * Drain and return all buffered commands.\n * No _ prefix: called cross-file from pipeline, must survive mangleProps.\n */\n takeCommands(): CanvasCommand[] {\n if (this._c.length === 0) return [];\n const cmds = this._c;\n this._c = [];\n return cmds;\n }\n\n // Canvas 2D API methods\n\n // State\n save(): void { this._m('save'); }\n restore(): void { this._m('restore'); }\n\n // Transform\n scale(x: number, y: number): void { this._m('scale', x, y); }\n rotate(angle: number): void { this._m('rotate', angle); }\n translate(x: number, y: number): void { this._m('translate', x, y); }\n transform(a: number, b: number, c: number, d: number, e: number, f: number): void { this._m('transform', a, b, c, d, e, f); }\n setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void { this._m('setTransform', a, b, c, d, e, f); }\n resetTransform(): void { this._m('resetTransform'); }\n\n // Rectangles\n clearRect(x: number, y: number, width: number, height: number): void { this._m('clearRect', x, y, width, height); }\n fillRect(x: number, y: number, width: number, height: number): void { this._m('fillRect', x, y, width, height); }\n strokeRect(x: number, y: number, width: number, height: number): void { this._m('strokeRect', x, y, width, height); }\n\n // Text\n fillText(text: string, x: number, y: number, maxWidth?: number): void {\n this._m('fillText', ...(maxWidth !== undefined ? [text, x, y, maxWidth] : [text, x, y]));\n }\n\n strokeText(text: string, x: number, y: number, maxWidth?: number): void {\n this._m('strokeText', ...(maxWidth !== undefined ? [text, x, y, maxWidth] : [text, x, y]));\n }\n\n /** Synchronous text measurement — cannot go through the async command pipeline. */\n private _measureCtx: OffscreenCanvasRenderingContext2D | null = null;\n\n measureText(text: string): TextMetrics {\n if (!this._measureCtx) {\n this._measureCtx = new OffscreenCanvas(1, 1).getContext('2d')!;\n }\n this._measureCtx.font = this.font;\n return this._measureCtx.measureText(text);\n }\n\n // Line drawing\n beginPath(): void { this._m('beginPath'); }\n closePath(): void { this._m('closePath'); }\n moveTo(x: number, y: number): void { this._m('moveTo', x, y); }\n lineTo(x: number, y: number): void { this._m('lineTo', x, y); }\n\n bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void {\n this._m('bezierCurveTo', cp1x, cp1y, cp2x, cp2y, x, y);\n }\n\n quadraticCurveTo(cpx: number, cpy: number, x: number, y: number): void { this._m('quadraticCurveTo', cpx, cpy, x, y); }\n\n arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void {\n this._m('arc', ...(counterclockwise !== undefined ? [x, y, radius, startAngle, endAngle, counterclockwise] : [x, y, radius, startAngle, endAngle]));\n }\n\n arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void { this._m('arcTo', x1, y1, x2, y2, radius); }\n\n ellipse(x: number, y: number, radiusX: number, radiusY: number, rotation: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void {\n this._m('ellipse', ...(counterclockwise !== undefined ? [x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise] : [x, y, radiusX, radiusY, rotation, startAngle, endAngle]));\n }\n\n rect(x: number, y: number, width: number, height: number): void { this._m('rect', x, y, width, height); }\n\n // Images\n drawImage(image: CanvasImageSource, dx: number, dy: number): void;\n drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;\n drawImage(image: CanvasImageSource, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void;\n drawImage(...args: [CanvasImageSource, ...number[]]): void {\n this._m('drawImage', ...args);\n }\n\n // Fill and stroke\n fill(): void { this._m('fill'); }\n stroke(): void { this._m('stroke'); }\n clip(): void { this._m('clip'); }\n\n // Properties (setters)\n set fillStyle(value: string | CanvasGradient | CanvasPattern) { this._p('fillStyle', value); }\n set strokeStyle(value: string | CanvasGradient | CanvasPattern) { this._p('strokeStyle', value); }\n set lineWidth(value: number) { this._p('lineWidth', value); }\n set lineCap(value: CanvasLineCap) { this._p('lineCap', value); }\n set lineJoin(value: CanvasLineJoin) { this._p('lineJoin', value); }\n set miterLimit(value: number) { this._p('miterLimit', value); }\n set lineDashOffset(value: number) { this._p('lineDashOffset', value); }\n set font(value: string) { this._p('font', value); }\n set textAlign(value: CanvasTextAlign) { this._p('textAlign', value); }\n set textBaseline(value: CanvasTextBaseline) { this._p('textBaseline', value); }\n set globalAlpha(value: number) { this._p('globalAlpha', value); }\n set globalCompositeOperation(value: GlobalCompositeOperation) { this._p('globalCompositeOperation', value); }\n set shadowBlur(value: number) { this._p('shadowBlur', value); }\n set shadowColor(value: string) { this._p('shadowColor', value); }\n set shadowOffsetX(value: number) { this._p('shadowOffsetX', value); }\n set shadowOffsetY(value: number) { this._p('shadowOffsetY', value); }\n set imageSmoothingEnabled(value: boolean) { this._p('imageSmoothingEnabled', value); }\n set letterSpacing(value: string) { this._p('letterSpacing', value); }\n\n // Property getters (return local cached values)\n get fillStyle() { return this._cp['fillStyle'] ?? '#000'; }\n get strokeStyle() { return this._cp['strokeStyle'] ?? '#000'; }\n get lineWidth() { return this._cp['lineWidth'] ?? 1; }\n get lineCap() { return this._cp['lineCap'] ?? 'butt'; }\n get lineJoin() { return this._cp['lineJoin'] ?? 'miter'; }\n get miterLimit() { return this._cp['miterLimit'] ?? 10; }\n get lineDashOffset() { return this._cp['lineDashOffset'] ?? 0; }\n get font() { return this._cp['font'] ?? '10px sans-serif'; }\n get textAlign() { return this._cp['textAlign'] ?? 'start'; }\n get textBaseline() { return this._cp['textBaseline'] ?? 'alphabetic'; }\n get globalAlpha() { return this._cp['globalAlpha'] ?? 1; }\n get globalCompositeOperation() { return this._cp['globalCompositeOperation'] ?? 'source-over'; }\n get shadowBlur() { return this._cp['shadowBlur'] ?? 0; }\n get shadowColor() { return this._cp['shadowColor'] ?? 'rgba(0, 0, 0, 0)'; }\n get shadowOffsetX() { return this._cp['shadowOffsetX'] ?? 0; }\n get shadowOffsetY() { return this._cp['shadowOffsetY'] ?? 0; }\n get imageSmoothingEnabled() { return this._cp['imageSmoothingEnabled'] ?? true; }\n get letterSpacing() { return this._cp['letterSpacing'] ?? ''; }\n}","/**\n * 3×3 Affine Transform Matrix Stack\n *\n * Replicates Canvas 2D's save()/restore()/translate()/rotate()/scale()\n * as a matrix stack for WebGL uniform upload.\n *\n * Matrices are 3×3 column-major (for gl.uniformMatrix3fv), representing\n * 2D affine transforms. The base matrix includes an orthographic projection\n * that maps canvas pixel coordinates (top-left origin, Y-down) to WebGL\n * clip space ([-1,1], Y-up).\n *\n * Column-major layout of a 3×3 affine matrix:\n * [0] [3] [6] a c tx\n * [1] [4] [7] = b d ty\n * [2] [5] [8] 0 0 1\n */\n\nexport class MatrixStack {\n private _stack: Float32Array[] = [];\n private _current: Float32Array;\n private _projection: Float32Array;\n\n /**\n * @param width Canvas width in pixels\n * @param height Canvas height in pixels\n */\n constructor(width: number, height: number) {\n this._projection = _ortho(width, height);\n this._current = new Float32Array(this._projection);\n }\n\n /** Push current matrix onto the stack. No _ prefix: cross-file. */\n save(): void {\n this._stack.push(new Float32Array(this._current));\n }\n\n /** Pop and restore the top matrix. No _ prefix: cross-file. */\n restore(): void {\n if (this._stack.length > 0) {\n this._current = this._stack.pop()!;\n }\n }\n\n /** Translate the current matrix. No _ prefix: cross-file. */\n translate(x: number, y: number): void {\n // Multiply current matrix by translation:\n // 1 0 tx\n // 0 1 ty\n // 0 0 1\n // In column-major: m[6] += m[0]*tx + m[3]*ty\n // m[7] += m[1]*tx + m[4]*ty\n const m = this._current;\n m[6] += m[0] * x + m[3] * y;\n m[7] += m[1] * x + m[4] * y;\n }\n\n /** Rotate the current matrix by angle (radians). No _ prefix: cross-file. */\n rotate(angle: number): void {\n const c = Math.cos(angle);\n const s = Math.sin(angle);\n const m = this._current;\n const m0 = m[0], m1 = m[1], m3 = m[3], m4 = m[4];\n m[0] = m0 * c + m3 * s;\n m[1] = m1 * c + m4 * s;\n m[3] = m0 * -s + m3 * c;\n m[4] = m1 * -s + m4 * c;\n }\n\n /** Scale the current matrix. No _ prefix: cross-file. */\n scale(x: number, y: number): void {\n const m = this._current;\n m[0] *= x; m[1] *= x;\n m[3] *= y; m[4] *= y;\n }\n\n /**\n * Multiply current matrix by an arbitrary 2D affine transform.\n * Canvas 2D transform(a, b, c, d, e, f) matrix:\n * a c e\n * b d f\n * 0 0 1\n * No _ prefix: cross-file.\n */\n transform(a: number, b: number, c: number, d: number, e: number, f: number): void {\n const m = this._current;\n const m0 = m[0], m1 = m[1], m3 = m[3], m4 = m[4], m6 = m[6], m7 = m[7];\n m[0] = m0 * a + m3 * b;\n m[1] = m1 * a + m4 * b;\n m[3] = m0 * c + m3 * d;\n m[4] = m1 * c + m4 * d;\n m[6] = m0 * e + m3 * f + m6;\n m[7] = m1 * e + m4 * f + m7;\n }\n\n /**\n * Reset to projection then apply the given affine transform.\n * Canvas 2D setTransform(a, b, c, d, e, f).\n * No _ prefix: cross-file.\n */\n setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void {\n this._current.set(this._projection);\n this.transform(a, b, c, d, e, f);\n }\n\n /** Reset to the base orthographic projection. No _ prefix: cross-file. */\n resetTransform(): void {\n this._current.set(this._projection);\n }\n\n /**\n * Update canvas dimensions (e.g., on resize).\n * Recomputes the projection and resets the current matrix.\n * No _ prefix: cross-file.\n */\n resize(width: number, height: number): void {\n this._projection = _ortho(width, height);\n this._current = new Float32Array(this._projection);\n this._stack = [];\n }\n\n /**\n * Returns the current 3×3 matrix for gl.uniformMatrix3fv.\n * No _ prefix: cross-file.\n */\n getMatrix(): Float32Array {\n return this._current;\n }\n}\n\n/**\n * Create an orthographic projection matrix that maps:\n * Canvas coords (0,0)=top-left, (w,h)=bottom-right, Y-down\n * → Clip space (-1,-1)=bottom-left, (1,1)=top-right, Y-up\n *\n * The transform is:\n * x_clip = x * 2/w - 1\n * y_clip = -(y * 2/h - 1) = 1 - y * 2/h\n *\n * Column-major 3×3:\n * 2/w 0 -1\n * 0 -2/h 1\n * 0 0 1\n */\nfunction _ortho(w: number, h: number): Float32Array {\n return new Float32Array([\n 2 / w, 0, 0, // column 0\n 0, -2 / h, 0, // column 1\n -1, 1, 1, // column 2\n ]);\n}\n","/**\n * CSS Color Parser\n *\n * Converts CSS color strings to Float32Array [r, g, b, a] in [0, 1] range\n * for use as WebGL uniform values.\n *\n * Supported formats:\n * - Hex: #rgb, #rrggbb, #rrggbbaa\n * - Functional: rgb(r, g, b), rgba(r, g, b, a)\n * - Named: basic CSS color keywords\n *\n * Includes a cache for repeated lookups (the demo reuses ~10 colors).\n */\n\nconst _NAMED_COLORS: Record<string, number> = {\n black: 0x000000ff,\n white: 0xffffffff,\n red: 0xff0000ff,\n green: 0x008000ff,\n blue: 0x0000ffff,\n yellow: 0xffff00ff,\n cyan: 0x00ffffff,\n magenta: 0xff00ffff,\n orange: 0xffa500ff,\n transparent: 0x00000000,\n};\n\nconst _cache = new Map<string, Float32Array>();\n\n/**\n * Parse a CSS color string into [r, g, b, a] floats in [0, 1].\n * Returns a cached Float32Array — do NOT mutate the result.\n *\n * No _ prefix: called cross-file from canvas2d-shim.\n */\nexport function parseColor(css: string): Float32Array {\n const cached = _cache.get(css);\n if (cached) return cached;\n\n const result = _parse(css);\n _cache.set(css, result);\n return result;\n}\n\nfunction _parse(css: string): Float32Array {\n const s = css.trim();\n\n // #hex\n if (s.charCodeAt(0) === 0x23) { // '#'\n return _parseHex(s);\n }\n\n // rgb() / rgba()\n if (s.charCodeAt(0) === 0x72) { // 'r'\n return _parseRgb(s);\n }\n\n // Named color\n const named = _NAMED_COLORS[s.toLowerCase()];\n if (named !== undefined) {\n return new Float32Array([\n ((named >>> 24) & 0xff) / 255,\n ((named >>> 16) & 0xff) / 255,\n ((named >>> 8) & 0xff) / 255,\n (named & 0xff) / 255,\n ]);\n }\n\n // Fallback: opaque black\n return new Float32Array([0, 0, 0, 1]);\n}\n\nfunction _parseHex(s: string): Float32Array {\n const len = s.length;\n\n if (len === 4) {\n // #rgb → expand to #rrggbb\n const r = parseInt(s[1], 16);\n const g = parseInt(s[2], 16);\n const b = parseInt(s[3], 16);\n return new Float32Array([\n (r * 17) / 255,\n (g * 17) / 255,\n (b * 17) / 255,\n 1,\n ]);\n }\n\n if (len === 7) {\n // #rrggbb\n const r = parseInt(s.slice(1, 3), 16);\n const g = parseInt(s.slice(3, 5), 16);\n const b = parseInt(s.slice(5, 7), 16);\n return new Float32Array([r / 255, g / 255, b / 255, 1]);\n }\n\n if (len === 9) {\n // #rrggbbaa\n const r = parseInt(s.slice(1, 3), 16);\n const g = parseInt(s.slice(3, 5), 16);\n const b = parseInt(s.slice(5, 7), 16);\n const a = parseInt(s.slice(7, 9), 16);\n return new Float32Array([r / 255, g / 255, b / 255, a / 255]);\n }\n\n // #rgba (4-digit with alpha)\n if (len === 5) {\n const r = parseInt(s[1], 16);\n const g = parseInt(s[2], 16);\n const b = parseInt(s[3], 16);\n const a = parseInt(s[4], 16);\n return new Float32Array([\n (r * 17) / 255,\n (g * 17) / 255,\n (b * 17) / 255,\n (a * 17) / 255,\n ]);\n }\n\n return new Float32Array([0, 0, 0, 1]);\n}\n\nfunction _parseRgb(s: string): Float32Array {\n // Match both rgb(...) and rgba(...)\n // Extract the numeric values between parentheses\n const start = s.indexOf('(');\n const end = s.lastIndexOf(')');\n if (start === -1 || end === -1) return new Float32Array([0, 0, 0, 1]);\n\n const parts = s.slice(start + 1, end).split(',');\n const r = parseFloat(parts[0]) / 255;\n const g = parseFloat(parts[1]) / 255;\n const b = parseFloat(parts[2]) / 255;\n const a = parts.length >= 4 ? parseFloat(parts[3]) : 1;\n\n return new Float32Array([r, g, b, a]);\n}\n","/**\n * GLSL Shader Sources for canvas-ultrafast\n *\n * Content shaders (flat-color, textured) plus a passthrough display shader.\n * CRT post-processing shaders live in the maalata package.\n *\n * Coordinate convention:\n * - Content shaders use a 3x3 affine matrix (u_matrix) that maps\n * canvas pixel coordinates (top-left origin, Y-down) to clip space.\n * - Passthrough shader uses a fullscreen quad in [0,1] mapped to [-1,1] clip space.\n */\n\n// ---------------------------------------------------------------------------\n// Flat-color shader: rectangles, line quads, clear regions\n// ---------------------------------------------------------------------------\n\nexport const FLAT_VERTEX_SRC = `\n attribute vec2 a_position;\n uniform mat3 u_matrix;\n void main() {\n vec3 pos = u_matrix * vec3(a_position, 1.0);\n gl_Position = vec4(pos.xy, 0.0, 1.0);\n }\n`;\n\nexport const FLAT_FRAGMENT_SRC = `\n precision mediump float;\n uniform vec4 u_color;\n void main() {\n gl_FragColor = u_color;\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Textured quad shader: text rendering via OffscreenCanvas glyph upload\n// ---------------------------------------------------------------------------\n\nexport const TEXTURED_VERTEX_SRC = `\n attribute vec2 a_position;\n attribute vec2 a_texCoord;\n uniform mat3 u_matrix;\n varying vec2 v_texCoord;\n void main() {\n vec3 pos = u_matrix * vec3(a_position, 1.0);\n gl_Position = vec4(pos.xy, 0.0, 1.0);\n v_texCoord = a_texCoord;\n }\n`;\n\nexport const TEXTURED_FRAGMENT_SRC = `\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_texture;\n uniform vec4 u_color;\n void main() {\n vec4 texel = texture2D(u_texture, v_texCoord);\n gl_FragColor = texel * u_color;\n }\n`;\n\n// ---------------------------------------------------------------------------\n// Passthrough display shader: fullscreen quad, reads FBO texture\n// ---------------------------------------------------------------------------\n\n/**\n * Vertex shader: fullscreen quad [0,1] → clip space [-1,1].\n * FBO textures are already in GL-native bottom-left origin (the orthographic\n * projection in matrix-stack.ts handles the canvas Y-down → GL Y-up flip),\n * so tex coords pass through without Y-flip.\n */\nexport const PASSTHROUGH_VERTEX_SRC = `\n attribute vec2 a_position;\n varying vec2 v_texCoord;\n void main() {\n v_texCoord = a_position;\n gl_Position = vec4(a_position * 2.0 - 1.0, 0, 1);\n }\n`;\n\n/**\n * Passthrough fragment shader: blit FBO texture to screen without effects.\n */\nexport const PASSTHROUGH_FRAGMENT_SRC = `\n precision mediump float;\n varying vec2 v_texCoord;\n uniform sampler2D u_texture;\n void main() {\n gl_FragColor = texture2D(u_texture, v_texCoord);\n }\n`;\n","/**\n * Canvas 2D → WebGL Command Shim\n *\n * Translates CanvasCommand[] (recorded by CanvasAPI) into WebGL draw calls.\n * Handles the subset of Canvas 2D API used by the demo, plus reasonable\n * extensions. Operations not yet implemented log a warning and no-op.\n *\n * Rendering approach per command type:\n * - clearRect: gl.scissor + gl.clear\n * - fillRect: unit quad VBO + flat shader + transform uniform\n * - strokeRect: four thin quads (one per edge)\n * - fillText: render to OffscreenCanvas 2D → texImage2D → textured quad\n * - stroke(): expand line segments to quads on CPU, flat shader\n * - save/restore: matrix + state stack\n *\n * Text rendering uses an OffscreenCanvas with a 2D context as a glyph\n * rendering surface. At 8 FPS with ~5 text draws per frame, per-string\n * rendering (not glyph caching) is appropriate — texImage2D(OffscreenCanvas)\n * is a fast GPU upload path.\n */\n\nimport { CanvasCommand } from './canvas-api';\nimport { MatrixStack } from './matrix-stack';\nimport { parseColor } from './color-parser';\nimport {\n FLAT_VERTEX_SRC, FLAT_FRAGMENT_SRC,\n TEXTURED_VERTEX_SRC, TEXTURED_FRAGMENT_SRC,\n} from './shaders';\n\ninterface _DrawState {\n _fillColor: Float32Array;\n _strokeColor: Float32Array;\n _lineWidth: number;\n _globalAlpha: number;\n _font: string;\n _textAlign: CanvasTextAlign;\n _textBaseline: CanvasTextBaseline;\n _lineCap: CanvasLineCap;\n _lineJoin: CanvasLineJoin;\n _imageSmoothingEnabled: boolean;\n _letterSpacing: string;\n _clipActive: boolean;\n _clipRect: [number, number, number, number] | null;\n}\n\ninterface _ProgramInfo {\n _program: WebGLProgram;\n _matrixLoc: WebGLUniformLocation | null;\n _colorLoc: WebGLUniformLocation | null;\n _textureLoc: WebGLUniformLocation | null;\n _positionLoc: number;\n _texCoordLoc: number;\n}\n\nexport class Canvas2DShim {\n private _gl: WebGLRenderingContext;\n private _width: number;\n private _height: number;\n\n // Transform\n private _matrix: MatrixStack;\n\n // State\n private _fillColor: Float32Array = new Float32Array([0, 0, 0, 1]);\n private _strokeColor: Float32Array = new Float32Array([0, 0, 0, 1]);\n private _lineWidth = 1;\n private _globalAlpha = 1;\n private _font = '10px sans-serif';\n private _textAlign: CanvasTextAlign = 'start';\n private _textBaseline: CanvasTextBaseline = 'alphabetic';\n private _lineCap: CanvasLineCap = 'butt';\n private _lineJoin: CanvasLineJoin = 'miter';\n private _imageSmoothingEnabled = true;\n private _letterSpacing = '';\n private _clipActive = false;\n private _clipRect: [number, number, number, number] | null = null;\n private _pendingClipRect: [number, number, number, number] | null = null;\n private _imageTexCache = new WeakMap<object, { _tex: WebGLTexture; _isImage: boolean }>();\n private _stateStack: _DrawState[] = [];\n\n // Path state\n private _pathSegments: number[] = []; // flat: x0,y0,x1,y1,...\n private _currentX = 0;\n private _currentY = 0;\n private _subpathStartX = 0;\n private _subpathStartY = 0;\n\n // WebGL resources\n private _flat: _ProgramInfo;\n private _textured: _ProgramInfo;\n private _unitQuadVBO: WebGLBuffer;\n private _dynamicVBO: WebGLBuffer;\n private _texturedVBO: WebGLBuffer;\n private _textTexture: WebGLTexture;\n\n // Text rendering surface\n private _textCanvas: OffscreenCanvas;\n private _textCtx: OffscreenCanvasRenderingContext2D;\n\n // Background color for opaque canvas clear\n private _bgColor = new Float32Array([0, 0, 0]);\n\n // Temp arrays to avoid allocation in hot path\n private _tmpColor = new Float32Array(4);\n\n constructor(gl: WebGLRenderingContext, width: number, height: number) {\n this._gl = gl;\n this._width = width;\n this._height = height;\n this._matrix = new MatrixStack(width, height);\n\n // Compile shader programs\n this._flat = this._createProgram(\n FLAT_VERTEX_SRC, FLAT_FRAGMENT_SRC, false\n );\n this._textured = this._createProgram(\n TEXTURED_VERTEX_SRC, TEXTURED_FRAGMENT_SRC, true\n );\n\n // Unit quad VBO: two triangles covering [0,0]-[1,1]\n // Used for fillRect (scaled via matrix) and fullscreen blits\n this._unitQuadVBO = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, this._unitQuadVBO);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([\n 0, 0, 1, 0, 0, 1,\n 0, 1, 1, 0, 1, 1,\n ]), gl.STATIC_DRAW);\n\n // Dynamic VBO for line quads — uses orphaning for double-buffer\n this._dynamicVBO = gl.createBuffer()!;\n\n // Textured quad VBO: position + texcoord interleaved\n this._texturedVBO = gl.createBuffer()!;\n\n // Text rendering texture\n this._textTexture = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, this._textTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n // OffscreenCanvas for text glyph rendering\n this._textCanvas = new OffscreenCanvas(512, 128);\n this._textCtx = this._textCanvas.getContext('2d')!;\n\n // Enable blending for standard source-over compositing\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n }\n\n /**\n * Execute a batch of Canvas 2D commands as WebGL draw calls.\n * No _ prefix: called cross-file from webgl-renderer.\n */\n executeBatch(commands: CanvasCommand[]): void {\n for (const cmd of commands) {\n if (cmd.type === 'property') {\n this._setProperty(cmd.name, cmd.value);\n } else {\n this._callMethod(cmd.name, cmd.args);\n }\n }\n }\n\n /**\n * Set the opaque clear color for clearRect.\n * No _ prefix: called cross-file from renderer.\n */\n setBackgroundColor(r: number, g: number, b: number): void {\n this._bgColor[0] = r;\n this._bgColor[1] = g;\n this._bgColor[2] = b;\n }\n\n /**\n * Update canvas dimensions on resize.\n * No _ prefix: called cross-file.\n */\n resize(width: number, height: number): void {\n this._width = width;\n this._height = height;\n this._matrix.resize(width, height);\n }\n\n /**\n * Clean up WebGL resources.\n * No _ prefix: called cross-file.\n */\n destroy(): void {\n const gl = this._gl;\n gl.deleteBuffer(this._unitQuadVBO);\n gl.deleteBuffer(this._dynamicVBO);\n gl.deleteBuffer(this._texturedVBO);\n gl.deleteTexture(this._textTexture);\n gl.deleteProgram(this._flat._program);\n gl.deleteProgram(this._textured._program);\n }\n\n // -------------------------------------------------------------------------\n // Private: property handling\n // -------------------------------------------------------------------------\n\n private _setProperty(name: string, value: unknown): void {\n switch (name) {\n case 'fillStyle':\n this._fillColor = parseColor(value as string);\n break;\n case 'strokeStyle':\n this._strokeColor = parseColor(value as string);\n break;\n case 'lineWidth':\n this._lineWidth = value as number;\n break;\n case 'globalAlpha':\n this._globalAlpha = value as number;\n break;\n case 'font':\n this._font = value as string;\n break;\n case 'textAlign':\n this._textAlign = value as CanvasTextAlign;\n break;\n case 'textBaseline':\n this._textBaseline = value as CanvasTextBaseline;\n break;\n case 'lineCap':\n this._lineCap = value as CanvasLineCap;\n break;\n case 'lineJoin':\n this._lineJoin = value as CanvasLineJoin;\n break;\n case 'imageSmoothingEnabled':\n this._imageSmoothingEnabled = value as boolean;\n break;\n case 'letterSpacing':\n this._letterSpacing = value as string;\n break;\n default:\n // Unsupported properties: silently ignore\n break;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: method dispatch\n // -------------------------------------------------------------------------\n\n private _callMethod(name: string, args: unknown[]): void {\n switch (name) {\n // Rectangles\n case 'clearRect':\n this._clearRect(args[0] as number, args[1] as number, args[2] as number, args[3] as number);\n break;\n case 'fillRect':\n this._fillRect(args[0] as number, args[1] as number, args[2] as number, args[3] as number);\n break;\n case 'strokeRect':\n this._strokeRect(args[0] as number, args[1] as number, args[2] as number, args[3] as number);\n break;\n\n // Text\n case 'fillText':\n this._fillText(args[0] as string, args[1] as number, args[2] as number);\n break;\n case 'strokeText':\n this._strokeText(args[0] as string, args[1] as number, args[2] as number);\n break;\n\n // Images\n case 'drawImage':\n this._drawImage(args);\n break;\n\n // Path\n case 'beginPath':\n this._pathSegments = [];\n this._pendingClipRect = null;\n break;\n case 'closePath':\n if (this._currentX !== this._subpathStartX || this._currentY !== this._subpathStartY) {\n this._pathSegments.push(\n this._currentX, this._currentY,\n this._subpathStartX, this._subpathStartY\n );\n this._currentX = this._subpathStartX;\n this._currentY = this._subpathStartY;\n }\n break;\n case 'moveTo':\n this._currentX = this._subpathStartX = args[0] as number;\n this._currentY = this._subpathStartY = args[1] as number;\n break;\n case 'lineTo': {\n const x = args[0] as number;\n const y = args[1] as number;\n this._pathSegments.push(this._currentX, this._currentY, x, y);\n this._currentX = x;\n this._currentY = y;\n break;\n }\n case 'rect': {\n const rx = args[0] as number, ry = args[1] as number;\n const rw = args[2] as number, rh = args[3] as number;\n // Store as pending clip rect (used if clip() follows)\n this._pendingClipRect = [rx, ry, rw, rh];\n // Also add 4 line segments to path for potential stroke()\n this._pathSegments.push(\n rx, ry, rx + rw, ry, // top\n rx + rw, ry, rx + rw, ry + rh, // right\n rx + rw, ry + rh, rx, ry + rh, // bottom\n rx, ry + rh, rx, ry, // left\n );\n break;\n }\n case 'clip':\n this._applyClip();\n break;\n case 'stroke':\n this._strokePath();\n break;\n case 'fill':\n // Convex fill only — not heavily used in demo beyond fillRect\n break;\n\n // State\n case 'save':\n this._save();\n break;\n case 'restore':\n this._restore();\n break;\n\n // Transforms\n case 'translate':\n this._matrix.translate(args[0] as number, args[1] as number);\n break;\n case 'rotate':\n this._matrix.rotate(args[0] as number);\n break;\n case 'scale':\n this._matrix.scale(args[0] as number, args[1] as number);\n break;\n case 'transform':\n this._matrix.transform(\n args[0] as number, args[1] as number, args[2] as number,\n args[3] as number, args[4] as number, args[5] as number\n );\n break;\n case 'setTransform':\n this._matrix.setTransform(\n args[0] as number, args[1] as number, args[2] as number,\n args[3] as number, args[4] as number, args[5] as number\n );\n break;\n case 'resetTransform':\n this._matrix.resetTransform();\n break;\n\n default:\n // Unsupported methods: silently ignore (arc, bezierCurveTo, etc.)\n break;\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: drawing operations\n // -------------------------------------------------------------------------\n\n private _clearRect(x: number, y: number, w: number, h: number): void {\n const gl = this._gl;\n const bg = this._bgColor;\n // WebGL scissor uses bottom-left origin, canvas uses top-left\n gl.enable(gl.SCISSOR_TEST);\n gl.scissor(x, this._height - y - h, w, h);\n gl.clearColor(bg[0], bg[1], bg[2], 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.disable(gl.SCISSOR_TEST);\n }\n\n private _fillRect(x: number, y: number, w: number, h: number): void {\n const gl = this._gl;\n const prog = this._flat;\n\n gl.useProgram(prog._program);\n\n // Build transform: current matrix × translate(x,y) × scale(w,h)\n // Applied to unit quad [0,1]×[0,1] → fills [x,y,x+w,y+h]\n this._matrix.save();\n this._matrix.translate(x, y);\n this._matrix.scale(w, h);\n\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, this._fillColor, this._globalAlpha);\n\n this._matrix.restore();\n\n // Draw unit quad\n gl.bindBuffer(gl.ARRAY_BUFFER, this._unitQuadVBO);\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, 0, 0);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n }\n\n private _strokeRect(x: number, y: number, w: number, h: number): void {\n // Draw four edges as thin quads\n const lw = this._lineWidth;\n const hlw = lw / 2;\n\n // Top edge\n this._fillRectWithColor(x - hlw, y - hlw, w + lw, lw, this._strokeColor);\n // Bottom edge\n this._fillRectWithColor(x - hlw, y + h - hlw, w + lw, lw, this._strokeColor);\n // Left edge\n this._fillRectWithColor(x - hlw, y + hlw, lw, h - lw, this._strokeColor);\n // Right edge\n this._fillRectWithColor(x + w - hlw, y + hlw, lw, h - lw, this._strokeColor);\n }\n\n /** Internal: draw a filled rect with a specific color (used by strokeRect). */\n private _fillRectWithColor(x: number, y: number, w: number, h: number, color: Float32Array): void {\n const gl = this._gl;\n const prog = this._flat;\n\n gl.useProgram(prog._program);\n\n this._matrix.save();\n this._matrix.translate(x, y);\n this._matrix.scale(w, h);\n\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, color, this._globalAlpha);\n\n this._matrix.restore();\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this._unitQuadVBO);\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, 0, 0);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n }\n\n private _strokePath(): void {\n const segs = this._pathSegments;\n if (segs.length === 0) return;\n\n const gl = this._gl;\n const prog = this._flat;\n const halfW = Math.max(this._lineWidth / 2, 0.5);\n\n // Expand line segments to quads on CPU\n // Each segment (x0,y0,x1,y1) → 6 vertices (2 triangles)\n const segCount = segs.length / 4;\n const vertices = new Float32Array(segCount * 12); // 6 vertices × 2 coords\n\n for (let i = 0, vi = 0; i < segs.length; i += 4) {\n const x0 = segs[i], y0 = segs[i + 1], x1 = segs[i + 2], y1 = segs[i + 3];\n const dx = x1 - x0;\n const dy = y1 - y0;\n const len = Math.sqrt(dx * dx + dy * dy);\n\n if (len < 0.001) continue; // Skip degenerate segments\n\n // Normal perpendicular to line direction\n const nx = (-dy / len) * halfW;\n const ny = (dx / len) * halfW;\n\n // Four corners of the quad\n const ax = x0 + nx, ay = y0 + ny; // top-left\n const bx = x0 - nx, by = y0 - ny; // bottom-left\n const cx = x1 + nx, cy = y1 + ny; // top-right\n const dx2 = x1 - nx, dy2 = y1 - ny; // bottom-right\n\n // Triangle 1: A, B, C\n vertices[vi++] = ax; vertices[vi++] = ay;\n vertices[vi++] = bx; vertices[vi++] = by;\n vertices[vi++] = cx; vertices[vi++] = cy;\n // Triangle 2: B, D, C\n vertices[vi++] = bx; vertices[vi++] = by;\n vertices[vi++] = dx2; vertices[vi++] = dy2;\n vertices[vi++] = cx; vertices[vi++] = cy;\n }\n\n // Upload to dynamic VBO using orphaning (bufferData null pattern)\n gl.bindBuffer(gl.ARRAY_BUFFER, this._dynamicVBO);\n gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW);\n\n gl.useProgram(prog._program);\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, this._strokeColor, this._globalAlpha);\n\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, 0, 0);\n gl.drawArrays(gl.TRIANGLES, 0, segCount * 6);\n }\n\n private _drawImage(args: unknown[]): void {\n const gl = this._gl;\n const image = args[0] as CanvasImageSource;\n\n let sx: number, sy: number, sw: number, sh: number;\n let dx: number, dy: number, dw: number, dh: number;\n\n // Get image dimensions\n const imgW = _getImageWidth(image);\n const imgH = _getImageHeight(image);\n\n if (args.length === 3) {\n // drawImage(image, dx, dy)\n sx = 0; sy = 0; sw = imgW; sh = imgH;\n dx = args[1] as number; dy = args[2] as number;\n dw = imgW; dh = imgH;\n } else if (args.length === 5) {\n // drawImage(image, dx, dy, dw, dh)\n sx = 0; sy = 0; sw = imgW; sh = imgH;\n dx = args[1] as number; dy = args[2] as number;\n dw = args[3] as number; dh = args[4] as number;\n } else {\n // drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)\n sx = args[1] as number; sy = args[2] as number;\n sw = args[3] as number; sh = args[4] as number;\n dx = args[5] as number; dy = args[6] as number;\n dw = args[7] as number; dh = args[8] as number;\n }\n\n // Get or create texture for this image source\n const tex = this._getOrUploadTexture(image, imgW, imgH);\n\n // Set filtering based on imageSmoothingEnabled\n const filter = this._imageSmoothingEnabled ? gl.LINEAR : gl.NEAREST;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);\n\n // Compute UV coordinates for source sub-rect\n const uMin = sx / imgW;\n const vMin = sy / imgH;\n const uMax = (sx + sw) / imgW;\n const vMax = (sy + sh) / imgH;\n\n // Draw textured quad with interleaved position + texcoord\n const prog = this._textured;\n const verts = new Float32Array([\n dx, dy, uMin, vMin,\n dx + dw, dy, uMax, vMin,\n dx, dy + dh, uMin, vMax,\n dx, dy + dh, uMin, vMax,\n dx + dw, dy, uMax, vMin,\n dx + dw, dy + dh, uMax, vMax,\n ]);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this._texturedVBO);\n gl.bufferData(gl.ARRAY_BUFFER, verts, gl.DYNAMIC_DRAW);\n\n gl.useProgram(prog._program);\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n // White color tint with globalAlpha — no color modification, just alpha\n gl.uniform4f(prog._colorLoc!, 1, 1, 1, this._globalAlpha);\n\n // Standard alpha blending (not premultiplied for image textures)\n const stride = 16; // 4 floats × 4 bytes\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, stride, 0);\n gl.enableVertexAttribArray(prog._texCoordLoc);\n gl.vertexAttribPointer(prog._texCoordLoc, 2, gl.FLOAT, false, stride, 8);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.uniform1i(prog._textureLoc, 0);\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Disable texcoord attrib to avoid interfering with flat shader\n gl.disableVertexAttribArray(prog._texCoordLoc);\n }\n\n private _getOrUploadTexture(image: CanvasImageSource, imgW: number, imgH: number): WebGLTexture {\n const gl = this._gl;\n const key = image as unknown as object;\n const cached = this._imageTexCache.get(key);\n\n // HTMLImageElement/SVGImageElement: upload once, cache permanently\n // HTMLCanvasElement/OffscreenCanvas: always re-upload (content may change)\n const isImage = (image instanceof HTMLImageElement) || (image instanceof SVGImageElement);\n\n if (cached) {\n if (cached._isImage) {\n // Static image — reuse cached texture\n return cached._tex;\n }\n // Canvas source — re-upload to existing texture\n gl.bindTexture(gl.TEXTURE_2D, cached._tex);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image as TexImageSource);\n return cached._tex;\n }\n\n // Create new texture\n const tex = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\n // Detect if we need to handle alpha properly\n // For canvas sources, use standard upload; for images, avoid premultiply\n if (imgW > 0 && imgH > 0) {\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image as TexImageSource);\n }\n\n this._imageTexCache.set(key, { _tex: tex, _isImage: isImage });\n return tex;\n }\n\n private _applyClip(): void {\n const gl = this._gl;\n if (this._pendingClipRect) {\n const [x, y, w, h] = this._pendingClipRect;\n gl.enable(gl.SCISSOR_TEST);\n // Convert canvas coords (top-left origin) to GL coords (bottom-left origin)\n gl.scissor(x, this._height - y - h, w, h);\n this._clipActive = true;\n this._clipRect = [x, y, w, h];\n }\n }\n\n private _fillText(text: string, x: number, y: number): void {\n this._renderText(text, x, y, 'fill');\n }\n\n private _strokeText(text: string, x: number, y: number): void {\n this._renderText(text, x, y, 'stroke');\n }\n\n private _renderText(text: string, x: number, y: number, mode: 'fill' | 'stroke'): void {\n const gl = this._gl;\n const tCtx = this._textCtx;\n\n // Configure text rendering context\n tCtx.font = this._font;\n tCtx.textAlign = 'left'; // Always render left-aligned, position via WebGL\n tCtx.textBaseline = 'top'; // Always render from top, adjust Y via offset\n if (this._letterSpacing) {\n tCtx.letterSpacing = this._letterSpacing;\n }\n\n // Measure text\n const metrics = tCtx.measureText(text);\n const textWidth = Math.ceil(metrics.width) + 4; // +4 for antialiasing padding\n const fontSize = _parseFontSize(this._font);\n const textHeight = Math.ceil(fontSize * 1.5) + 4; // approximate height with descenders\n\n if (textWidth <= 0 || textHeight <= 0) return;\n\n // Resize text canvas if needed\n if (this._textCanvas.width < textWidth || this._textCanvas.height < textHeight) {\n this._textCanvas.width = Math.max(this._textCanvas.width, textWidth);\n this._textCanvas.height = Math.max(this._textCanvas.height, textHeight);\n // Re-set font after resize (context is reset)\n tCtx.font = this._font;\n tCtx.textAlign = 'left';\n tCtx.textBaseline = 'top';\n }\n\n // Clear and render text\n tCtx.clearRect(0, 0, this._textCanvas.width, this._textCanvas.height);\n\n if (mode === 'fill') {\n tCtx.fillStyle = 'white'; // White text, tinted by WebGL uniform\n tCtx.fillText(text, 2, 2); // +2 padding offset\n } else {\n tCtx.strokeStyle = 'white';\n tCtx.lineWidth = this._lineWidth;\n tCtx.strokeText(text, 2, 2);\n }\n\n // Upload text canvas to texture\n gl.bindTexture(gl.TEXTURE_2D, this._textTexture);\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);\n gl.texImage2D(\n gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,\n this._textCanvas\n );\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0);\n\n // Compute text position adjustments\n const color = mode === 'fill' ? this._fillColor : this._strokeColor;\n let drawX = x - 2; // compensate for padding\n let drawY = y - 2;\n\n // Adjust for textAlign\n switch (this._textAlign) {\n case 'center': drawX -= textWidth / 2; break;\n case 'right':\n case 'end': drawX -= textWidth; break;\n }\n\n // Adjust for textBaseline\n switch (this._textBaseline) {\n case 'top': /* drawY stays */ break;\n case 'middle': drawY -= textHeight / 2; break;\n case 'alphabetic':\n case 'ideographic': drawY -= fontSize; break;\n case 'bottom':\n case 'hanging': drawY -= textHeight; break;\n }\n\n // Draw textured quad\n this._drawTexturedQuad(\n drawX, drawY, textWidth, textHeight,\n textWidth / this._textCanvas.width,\n textHeight / this._textCanvas.height,\n color\n );\n }\n\n private _drawTexturedQuad(\n x: number, y: number, w: number, h: number,\n uMax: number, vMax: number,\n color: Float32Array\n ): void {\n const gl = this._gl;\n const prog = this._textured;\n\n // Interleaved position + texcoord (x, y, u, v)\n const verts = new Float32Array([\n x, y, 0, 0,\n x + w, y, uMax, 0,\n x, y + h, 0, vMax,\n x, y + h, 0, vMax,\n x + w, y, uMax, 0,\n x + w, y + h, uMax, vMax,\n ]);\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this._texturedVBO);\n gl.bufferData(gl.ARRAY_BUFFER, verts, gl.DYNAMIC_DRAW);\n\n gl.useProgram(prog._program);\n gl.uniformMatrix3fv(prog._matrixLoc, false, this._matrix.getMatrix());\n this._setColorUniform(prog._colorLoc!, color, this._globalAlpha);\n\n // Use premultiplied alpha blending for text\n gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n\n const stride = 16; // 4 floats × 4 bytes\n gl.enableVertexAttribArray(prog._positionLoc);\n gl.vertexAttribPointer(prog._positionLoc, 2, gl.FLOAT, false, stride, 0);\n gl.enableVertexAttribArray(prog._texCoordLoc);\n gl.vertexAttribPointer(prog._texCoordLoc, 2, gl.FLOAT, false, stride, 8);\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this._textTexture);\n gl.uniform1i(prog._textureLoc, 0);\n\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n\n // Restore standard blending\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);\n\n // Disable texcoord attrib to avoid interfering with flat shader\n gl.disableVertexAttribArray(prog._texCoordLoc);\n }\n\n // -------------------------------------------------------------------------\n // Private: state management\n // -------------------------------------------------------------------------\n\n private _save(): void {\n this._matrix.save();\n this._stateStack.push({\n _fillColor: new Float32Array(this._fillColor),\n _strokeColor: new Float32Array(this._strokeColor),\n _lineWidth: this._lineWidth,\n _globalAlpha: this._globalAlpha,\n _font: this._font,\n _textAlign: this._textAlign,\n _textBaseline: this._textBaseline,\n _lineCap: this._lineCap,\n _lineJoin: this._lineJoin,\n _imageSmoothingEnabled: this._imageSmoothingEnabled,\n _letterSpacing: this._letterSpacing,\n _clipActive: this._clipActive,\n _clipRect: this._clipRect ? [...this._clipRect] as [number, number, number, number] : null,\n });\n }\n\n private _restore(): void {\n this._matrix.restore();\n const gl = this._gl;\n const state = this._stateStack.pop();\n if (state) {\n this._fillColor = state._fillColor;\n this._strokeColor = state._strokeColor;\n this._lineWidth = state._lineWidth;\n this._globalAlpha = state._globalAlpha;\n this._font = state._font;\n this._textAlign = state._textAlign;\n this._textBaseline = state._textBaseline;\n this._lineCap = state._lineCap;\n this._lineJoin = state._lineJoin;\n this._imageSmoothingEnabled = state._imageSmoothingEnabled;\n this._letterSpacing = state._letterSpacing;\n this._clipActive = state._clipActive;\n this._clipRect = state._clipRect;\n\n // Restore scissor state\n if (this._clipActive && this._clipRect) {\n const [x, y, w, h] = this._clipRect;\n gl.enable(gl.SCISSOR_TEST);\n gl.scissor(x, this._height - y - h, w, h);\n } else {\n gl.disable(gl.SCISSOR_TEST);\n }\n }\n }\n\n // -------------------------------------------------------------------------\n // Private: WebGL helpers\n // -------------------------------------------------------------------------\n\n private _setColorUniform(loc: WebGLUniformLocation, color: Float32Array, alpha: number): void {\n // Premultiply globalAlpha into the color's alpha channel\n const a = color[3] * alpha;\n this._gl.uniform4f(loc, color[0], color[1], color[2], a);\n }\n\n private _createProgram(vSrc: string, fSrc: string, hasTexCoord: boolean): _ProgramInfo {\n const gl = this._gl;\n const vs = this._compileShader(gl.VERTEX_SHADER, vSrc);\n const fs = this._compileShader(gl.FRAGMENT_SHADER, fSrc);\n\n const program = gl.createProgram()!;\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n throw new Error('Shader link failed: ' + gl.getProgramInfoLog(program));\n }\n\n // Delete shaders after linking (they're embedded in the program now)\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n return {\n _program: program,\n _matrixLoc: gl.getUniformLocation(program, 'u_matrix'),\n _colorLoc: gl.getUniformLocation(program, 'u_color'),\n _textureLoc: hasTexCoord ? gl.getUniformLocation(program, 'u_texture') : null,\n _positionLoc: gl.getAttribLocation(program, 'a_position'),\n _texCoordLoc: hasTexCoord ? gl.getAttribLocation(program, 'a_texCoord') : -1,\n };\n }\n\n private _compileShader(type: number, source: string): WebGLShader {\n const gl = this._gl;\n const shader = gl.createShader(type)!;\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader);\n gl.deleteShader(shader);\n throw new Error('Shader compile failed: ' + info);\n }\n return shader;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Utility\n// ---------------------------------------------------------------------------\n\n/** Extract numeric font size from a CSS font string like \"bold 20px monospace\". */\nfunction _parseFontSize(font: string): number {\n const match = font.match(/(\\d+(?:\\.\\d+)?)\\s*px/);\n return match ? parseFloat(match[1]) : 10;\n}\n\n/** Get width of a CanvasImageSource (handles HTMLImageElement, HTMLCanvasElement, OffscreenCanvas, etc.) */\nfunction _getImageWidth(img: CanvasImageSource): number {\n if ('naturalWidth' in img) return (img as HTMLImageElement).naturalWidth;\n return (img as HTMLCanvasElement | OffscreenCanvas).width;\n}\n\n/** Get height of a CanvasImageSource. */\nfunction _getImageHeight(img: CanvasImageSource): number {\n if ('naturalHeight' in img) return (img as HTMLImageElement).naturalHeight;\n return (img as HTMLCanvasElement | OffscreenCanvas).height;\n}\n","/**\n * UltrafastRenderer — WebGL2 Triple-Buffered Canvas 2D Renderer\n *\n * A standalone WebGL-accelerated Canvas 2D rendering engine. Provides a\n * CanvasAPI for recording draw commands and a triple-buffered FBO pipeline\n * that displays them via a passthrough shader at vsync rate.\n *\n * Triple buffer scheme (all on main thread, lock-free via JS single-threading):\n *\n * Content submission:\n * submitBatch(commands)\n * → bind writeFBO\n * → Canvas2DShim executes commands as WebGL draw calls\n * → swap: writeFBO ↔ readyFBO\n *\n * Display loop (vsync rate via RAF):\n * RAF callback\n * → auto-flush: drain CanvasAPI commands → submitBatch\n * → bind default framebuffer (display canvas)\n * → read readyFBO texture → passthrough blit → screen\n *\n * Extension points for downstream consumers (e.g. maalata CRT display):\n * - getGL(): access the WebGL2 context\n * - getReadyTexture(): read the latest rendered frame as a texture\n * - stopDisplay() / startDisplay(): take over the display loop\n */\n\nimport { CanvasAPI, type CanvasCommand } from './canvas-api';\nimport { Canvas2DShim } from './canvas2d-shim';\nimport {\n PASSTHROUGH_VERTEX_SRC,\n PASSTHROUGH_FRAGMENT_SRC,\n} from './shaders';\n\ninterface _FBO {\n _fbo: WebGLFramebuffer;\n _texture: WebGLTexture;\n}\n\nexport class UltrafastRenderer {\n private _gl: WebGL2RenderingContext;\n private _canvas: HTMLCanvasElement;\n private _shim: Canvas2DShim;\n private _api: CanvasAPI;\n private _rafId: number | null = null;\n\n // Triple buffer: three FBOs with color texture attachments\n private _fbos!: [_FBO, _FBO, _FBO];\n private _writeIdx = 0;\n private _readyIdx = 1;\n private _displayIdx = 2;\n private _hasContent = false;\n\n // Background color for opaque canvas clear (default: black, backwards compatible)\n private _bgColor = new Float32Array([0, 0, 0]);\n\n // Display program\n private _passthroughProgram: WebGLProgram;\n\n // Fullscreen quad VBO\n private _quadVBO!: WebGLBuffer;\n private _quadPositionLoc = -1;\n\n constructor(canvas: HTMLCanvasElement) {\n this._canvas = canvas;\n this._api = new CanvasAPI();\n\n // Create WebGL2 context with optimizations\n const gl = canvas.getContext('webgl2', {\n alpha: false,\n antialias: false,\n desynchronized: true,\n preserveDrawingBuffer: true,\n powerPreference: 'high-performance',\n });\n\n if (!gl) {\n throw new Error('WebGL2 not supported');\n }\n this._gl = gl;\n\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\n\n // Initialize triple buffer FBOs\n this._initFBOs();\n\n // Initialize Canvas 2D shim (uses same GL context)\n this._shim = new Canvas2DShim(gl, canvas.width, canvas.height);\n\n // Initialize passthrough display program\n this._passthroughProgram = this._createShaderProgram(\n PASSTHROUGH_VERTEX_SRC, PASSTHROUGH_FRAGMENT_SRC\n );\n\n // Initialize fullscreen quad VBO for display pass\n this._initQuadVBO();\n\n // Clear all FBOs to black initially\n this._clearAllFBOs();\n\n // Auto-start display loop\n this.startDisplay();\n }\n\n // -------------------------------------------------------------------------\n // Public API (no _ prefix: cross-file access safe from mangleProps)\n // -------------------------------------------------------------------------\n\n /** Get the CanvasAPI for recording draw commands. */\n getCanvasAPI(): CanvasAPI {\n return this._api;\n }\n\n /**\n * Submit a batch of Canvas 2D commands to be rendered into the write FBO.\n * After rendering, the write and ready FBOs are swapped so the display\n * loop picks up the latest frame.\n */\n submitBatch(commands: CanvasCommand[]): void {\n if (commands.length === 0) return;\n const gl = this._gl;\n\n // Bind write FBO as render target\n gl.bindFramebuffer(gl.FRAMEBUFFER, this._fbos[this._writeIdx]._fbo);\n gl.viewport(0, 0, this._canvas.width, this._canvas.height);\n\n // Execute Canvas 2D commands as WebGL draw calls\n this._shim.executeBatch(commands);\n\n // Swap write ↔ ready (new frame becomes available for display)\n const tmp = this._writeIdx;\n this._writeIdx = this._readyIdx;\n this._readyIdx = tmp;\n this._hasContent = true;\n }\n\n /** Start the passthrough RAF display loop with auto-flush. */\n startDisplay(): void {\n if (this._rafId !== null) return;\n this._displayLoop();\n }\n\n /** Stop the passthrough RAF display loop. Last frame persists (preserveDrawingBuffer). */\n stopDisplay(): void {\n if (this._rafId !== null) {\n cancelAnimationFrame(this._rafId);\n this._rafId = null;\n }\n }\n\n /** Returns the display canvas element. */\n getCanvas(): HTMLCanvasElement {\n return this._canvas;\n }\n\n /** Get canvas dimensions. */\n getCanvasSize(): { width: number; height: number } {\n return { width: this._canvas.width, height: this._canvas.height };\n }\n\n /** Capture the current displayed frame as an ImageBitmap. */\n screenshot(): Promise<ImageBitmap> {\n this._renderDisplay();\n return createImageBitmap(this._canvas);\n }\n\n /**\n * Set the opaque clear color used by clearRect and FBO initialization.\n * With alpha: false, cleared areas are opaque — this controls what color\n * they appear as instead of black. Values are in [0, 1] range.\n */\n setBackgroundColor(r: number, g: number, b: number): void {\n this._bgColor[0] = r;\n this._bgColor[1] = g;\n this._bgColor[2] = b;\n this._shim.setBackgroundColor(r, g, b);\n }\n\n /** Clean up all WebGL resources. */\n destroy(): void {\n this.stopDisplay();\n const gl = this._gl;\n\n this._shim.destroy();\n\n for (const fbo of this._fbos) {\n gl.deleteFramebuffer(fbo._fbo);\n gl.deleteTexture(fbo._texture);\n }\n\n gl.deleteProgram(this._passthroughProgram);\n gl.deleteBuffer(this._quadVBO);\n\n const ext = gl.getExtension('WEBGL_lose_context');\n if (ext) ext.loseContext();\n }\n\n // -------------------------------------------------------------------------\n // Extension points (used by maalata CRT display)\n // -------------------------------------------------------------------------\n\n /** Returns the WebGL2 context for external rendering (e.g. CRT shader). */\n getGL(): WebGL2RenderingContext {\n return this._gl;\n }\n\n /** Returns the ready FBO's texture — the latest fully rendered frame. */\n getReadyTexture(): WebGLTexture {\n return this._fbos[this._readyIdx]._texture;\n }\n\n // -------------------------------------------------------------------------\n // Private: display loop\n // -------------------------------------------------------------------------\n\n private _displayLoop(): void {\n this._rafId = requestAnimationFrame(() => this._displayLoop());\n\n // Auto-flush: drain any pending CanvasAPI commands into the pipeline\n const cmds = this._api.takeCommands();\n if (cmds.length) this.submitBatch(cmds);\n\n this._renderDisplay();\n }\n\n /**\n * Render the ready FBO to the display canvas via passthrough shader.\n * Called at vsync rate by RAF, or once synchronously for screenshots.\n */\n private _renderDisplay(): void {\n if (!this._hasContent) return;\n\n const gl = this._gl;\n\n // Bind default framebuffer (display canvas backbuffer)\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, this._canvas.width, this._canvas.height);\n\n // Bind the ready FBO's texture as input\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this._fbos[this._readyIdx]._texture);\n\n gl.useProgram(this._passthroughProgram);\n\n // Draw fullscreen quad\n gl.bindBuffer(gl.ARRAY_BUFFER, this._quadVBO);\n gl.enableVertexAttribArray(this._quadPositionLoc);\n gl.vertexAttribPointer(this._quadPositionLoc, 2, gl.FLOAT, false, 0, 0);\n\n gl.disable(gl.BLEND);\n gl.drawArrays(gl.TRIANGLES, 0, 6);\n gl.enable(gl.BLEND);\n }\n\n // -------------------------------------------------------------------------\n // Private: initialization\n // -------------------------------------------------------------------------\n\n private _initFBOs(): void {\n this._fbos = [\n this._createFBO(),\n this._createFBO(),\n this._createFBO(),\n ];\n }\n\n private _createFBO(): _FBO {\n const gl = this._gl;\n const w = this._canvas.width;\n const h = this._canvas.height;\n\n const fbo = gl.createFramebuffer()!;\n gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);\n\n const texture = gl.createTexture()!;\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, w, h);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);\n\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error('Framebuffer incomplete: 0x' + status.toString(16));\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n return { _fbo: fbo, _texture: texture };\n }\n\n private _clearAllFBOs(): void {\n const gl = this._gl;\n const bg = this._bgColor;\n for (const fbo of this._fbos) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, fbo._fbo);\n gl.clearColor(bg[0], bg[1], bg[2], 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.clearColor(bg[0], bg[1], bg[2], 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n\n private _initQuadVBO(): void {\n const gl = this._gl;\n\n this._quadVBO = gl.createBuffer()!;\n gl.bindBuffer(gl.ARRAY_BUFFER, this._quadVBO);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([\n 0, 0, 1, 0, 0, 1,\n 0, 1, 1, 0, 1, 1,\n ]), gl.STATIC_DRAW);\n\n this._quadPositionLoc = gl.getAttribLocation(this._passthroughProgram, 'a_position');\n }\n\n // -------------------------------------------------------------------------\n // Private: shader helpers\n // -------------------------------------------------------------------------\n\n private _createShaderProgram(vSrc: string, fSrc: string): WebGLProgram {\n const gl = this._gl;\n const vs = this._compileShader(gl.VERTEX_SHADER, vSrc);\n const fs = this._compileShader(gl.FRAGMENT_SHADER, fSrc);\n\n const program = gl.createProgram()!;\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n throw new Error('Shader link failed: ' + gl.getProgramInfoLog(program));\n }\n\n gl.deleteShader(vs);\n gl.deleteShader(fs);\n\n return program;\n }\n\n private _compileShader(type: number, source: string): WebGLShader {\n const gl = this._gl;\n const shader = gl.createShader(type)!;\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const info = gl.getShaderInfoLog(shader);\n gl.deleteShader(shader);\n throw new Error('Shader compile failed: ' + info);\n }\n return shader;\n }\n}\n"],"names":["exports"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -191,6 +191,7 @@ export declare class UltrafastRenderer {
|
|
|
191
191
|
private _readyIdx;
|
|
192
192
|
private _displayIdx;
|
|
193
193
|
private _hasContent;
|
|
194
|
+
private _bgColor;
|
|
194
195
|
private _passthroughProgram;
|
|
195
196
|
private _quadVBO;
|
|
196
197
|
private _quadPositionLoc;
|
|
@@ -216,6 +217,12 @@ export declare class UltrafastRenderer {
|
|
|
216
217
|
};
|
|
217
218
|
/** Capture the current displayed frame as an ImageBitmap. */
|
|
218
219
|
screenshot(): Promise<ImageBitmap>;
|
|
220
|
+
/**
|
|
221
|
+
* Set the opaque clear color used by clearRect and FBO initialization.
|
|
222
|
+
* With alpha: false, cleared areas are opaque — this controls what color
|
|
223
|
+
* they appear as instead of black. Values are in [0, 1] range.
|
|
224
|
+
*/
|
|
225
|
+
setBackgroundColor(r: number, g: number, b: number): void;
|
|
219
226
|
/** Clean up all WebGL resources. */
|
|
220
227
|
destroy(): void;
|
|
221
228
|
/** Returns the WebGL2 context for external rendering (e.g. CRT shader). */
|