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, 0, 0, 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, 0, 0, 1);
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, 0, 0, 1);
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, 0, 0, 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, 0, 0, 1);
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, 0, 0, 1);
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). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canvas-ultrafast",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "WebGL-accelerated Canvas 2D rendering engine with triple-buffered FBOs",
5
5
  "type": "module",
6
6
  "main": "dist/canvas-ultrafast.umd.js",