@weasel-js/renderer 0.0.0-stage → 1.9.4
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/LICENSE +21 -0
- package/README.md +61 -2
- package/dist/chunk-2VOBNWBN.js +11 -0
- package/dist/chunk-2VOBNWBN.js.map +1 -0
- package/dist/chunk-ORBXHIRB.js +178 -0
- package/dist/chunk-ORBXHIRB.js.map +1 -0
- package/dist/chunk-VHQJ56XQ.js +1437 -0
- package/dist/chunk-VHQJ56XQ.js.map +1 -0
- package/dist/imageCache-oJVgxhkr.d.ts +372 -0
- package/dist/index.d.ts +1070 -0
- package/dist/index.js +4086 -0
- package/dist/index.js.map +1 -0
- package/dist/mesh.d.ts +274 -0
- package/dist/mesh.js +603 -0
- package/dist/mesh.js.map +1 -0
- package/dist/paintKinds-B2vEy9A4.d.ts +330 -0
- package/dist/patterns-builtin.d.ts +118 -0
- package/dist/patterns-builtin.js +28 -0
- package/dist/patterns-builtin.js.map +1 -0
- package/dist/test-seams.d.ts +120 -0
- package/dist/test-seams.js +4 -0
- package/dist/test-seams.js.map +1 -0
- package/dist/testing/glRecorder.d.ts +36 -0
- package/dist/testing/glRecorder.js +155 -0
- package/dist/testing/glRecorder.js.map +1 -0
- package/dist/testing/vertexUploads.d.ts +30 -0
- package/dist/testing/vertexUploads.js +48 -0
- package/dist/testing/vertexUploads.js.map +1 -0
- package/package.json +71 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cache/GLImageCache.ts","../src/cache/cache.ts","../src/shaders/registerProgram.ts","../src/paintKinds.ts","../src/cache/strokeMeshCache.ts","../src/fillInPoseFrame.ts","../src/patterns/resolveSpec.ts","../src/patterns/commandPaint.ts","../src/markerCommands.ts","../src/cache/markerCommandCache.ts","../src/cache/outlineMeshCache.ts","../src/cache/outlineStrokeMeshCache.ts","../src/shaders/batchFill.ts","../src/batchClip.ts","../src/drawBatch.ts","../src/images/imageCache.ts"],"names":["cache","createReflectable","map","markerHeads","tessellate","metricKey","tessellateStroke","pathFromD","startLoad"],"mappings":"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","file":"chunk-VHQJ56XQ.js","sourcesContent":["/**\n * GL texture upload cache for ImageBitmap objects.\n *\n * Key: ImageBitmap (or pattern source object) identity (WeakMap) — lets GC\n * reclaim unreferenced bitmaps. A collected source's texture is queued and\n * deleted at the renderer's next frame, the way `GLMeshCache` frees a mesh's\n * buffers; GC timing is not prompt, so a source's owner that knows it will\n * never be drawn again frees it at once with {@link releaseImageSource}, and\n * `dispose` frees them all.\n *\n * Wrapping is set once at upload time per the `repetition` parameter:\n * - undefined / 'no-repeat' → CLAMP_TO_EDGE\n * - 'repeat' → REPEAT (both axes)\n * - 'repeat-x' → REPEAT on S, CLAMP on T\n * - 'repeat-y' → CLAMP on S, REPEAT on T\n *\n * Convention §2: texels stored straight; shader premultiplies.\n */\n\nexport type PatternRepetition = 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat';\n\n/** MIN_FILTER strategy for uploaded textures. */\nexport type ImageMinification = 'linear' | 'mipmap';\n\ntype TexSource = ImageBitmap | ImageData | HTMLCanvasElement | HTMLImageElement;\n\n/** Assumed when no live context has reported its `MAX_TEXTURE_SIZE`. Above\n * WebGL2's guaranteed 2048, and at or below what every current GPU reports. */\nconst DEFAULT_MAX_TEXTURE_SIDE = 4096;\n\nconst live = new Set<GLImageCache>();\n\n/** Free `key`'s texture in every live renderer. For an owner that has replaced\n * a source and will never draw the old one again — a later draw of it simply\n * re-uploads. */\nexport function releaseImageSource(key: object): void {\n for (const cache of live) cache.release(key);\n}\n\n/** The largest texture side every live renderer can hold: the smallest\n * `MAX_TEXTURE_SIZE` among them, or a conservative default when none is live. */\nexport function maxImageTextureSide(): number {\n let side = Infinity;\n for (const cache of live) side = Math.min(side, cache.maxTextureSide);\n return Number.isFinite(side) ? side : DEFAULT_MAX_TEXTURE_SIDE;\n}\n\nexport class GLImageCache {\n /** This context's `MAX_TEXTURE_SIZE`. */\n readonly maxTextureSide: number;\n\n private readonly map = new WeakMap<object, WebGLTexture>();\n /** Every texture `map` holds, so `dispose` can reach them — a WeakMap\n * cannot be enumerated. */\n private readonly textures = new Set<WebGLTexture>();\n /**\n * MAG_FILTER each texture currently carries, so a redundant write can be\n * skipped.\n *\n * The batch sets this per flush — the same bitmap can be drawn at both\n * filters in one frame, and the value has to be right at the draw rather than\n * at upload. Filtering is state on the *texture object*, though, not on the\n * unit, so re-asserting a value it already has is a write to a live texture\n * for no reason. On a large sheet that is not free: a consumer's wall samples\n * a 5652px-square atlas, 122MB resident, and measured `sampling: 'nearest'`\n * costing up to 8x `'linear'` there — where the linear pass re-asserts the\n * upload default and the nearest pass changes state on every draw.\n *\n * Whether that is the cause is unproven (see `docs/TODO.md`), but the write\n * was redundant either way.\n */\n private readonly magFilters = new WeakMap<object, number>();\n private readonly finalizer: FinalizationRegistry<WebGLTexture>;\n private readonly pendingDeletes: WebGLTexture[] = [];\n\n /** `minification` selects the MIN_FILTER strategy for uploaded textures.\n * `'linear'` (default) is the screen path's existing behavior. `'mipmap'`\n * generates mipmaps and filters LINEAR_MIPMAP_LINEAR — required for\n * quality minification when a large source bitmap is drawn small (the\n * headless print/export path); bilinear-only minification undersamples\n * and produces moiré. */\n constructor(\n private readonly gl: WebGL2RenderingContext,\n private readonly minification: ImageMinification = 'linear',\n ) {\n const reported: unknown = gl.getParameter(gl.MAX_TEXTURE_SIZE);\n this.maxTextureSide = typeof reported === 'number' && reported > 0\n ? reported\n : DEFAULT_MAX_TEXTURE_SIDE;\n this.finalizer = new FinalizationRegistry<WebGLTexture>((tex) => {\n if (this.textures.delete(tex)) this.pendingDeletes.push(tex);\n });\n live.add(this);\n }\n\n /** Delete the textures of sources collected since the last call. The\n * renderer calls this at the top of each `render()`. */\n drainPendingDeletes(): void {\n if (this.pendingDeletes.length === 0) return;\n for (const tex of this.pendingDeletes) this.gl.deleteTexture(tex);\n this.pendingDeletes.length = 0;\n }\n\n /** Delete `key`'s texture, if it has one. */\n release(key: object): void {\n const tex = this.map.get(key);\n if (!tex) return;\n this.gl.deleteTexture(tex);\n this.textures.delete(tex);\n this.finalizer.unregister(key);\n this.map.delete(key);\n this.magFilters.delete(key);\n }\n\n /** Delete every texture this cache uploaded and stop answering\n * {@link releaseImageSource} and {@link maxImageTextureSide}. Idempotent. */\n dispose(): void {\n for (const tex of this.textures) this.gl.deleteTexture(tex);\n this.drainPendingDeletes();\n this.abandon();\n }\n\n /** {@link dispose} without the deletes, for a cache whose context was lost:\n * its textures died with it. */\n abandon(): void {\n this.textures.clear();\n this.pendingDeletes.length = 0;\n live.delete(this);\n }\n\n upload(\n key: object,\n source: TexSource,\n repetition?: PatternRepetition,\n ): WebGLTexture {\n const existing = this.map.get(key);\n if (existing) return existing;\n\n const gl = this.gl;\n const tex = gl.createTexture();\n if (!tex) throw new Error('GLImageCache: createTexture failed');\n\n gl.bindTexture(gl.TEXTURE_2D, tex);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source as TexImageSource);\n gl.texParameteri(\n gl.TEXTURE_2D,\n gl.TEXTURE_MIN_FILTER,\n this.minification === 'mipmap' ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR,\n );\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n this.magFilters.set(key, gl.LINEAR);\n\n const [wrapS, wrapT] = wrapModes(gl, repetition);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);\n if (this.minification === 'mipmap') gl.generateMipmap(gl.TEXTURE_2D);\n gl.bindTexture(gl.TEXTURE_2D, null);\n\n this.map.set(key, tex);\n this.textures.add(tex);\n this.finalizer.register(key, tex, key);\n return tex;\n }\n\n bind(key: object, unit: number): void {\n const tex = this.map.get(key);\n if (!tex) throw new Error('GLImageCache: image not uploaded; call upload() first');\n const gl = this.gl;\n gl.activeTexture(gl.TEXTURE0 + unit);\n gl.bindTexture(gl.TEXTURE_2D, tex);\n }\n\n /** Set `key`'s MAG_FILTER, skipping the call when it already holds that\n * value. Its texture must be bound to the active unit — callers pair this\n * with `bind`. */\n setMagFilter(key: object, filter: number): void {\n if (this.magFilters.get(key) === filter) return;\n this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, filter);\n this.magFilters.set(key, filter);\n }\n}\n\nfunction wrapModes(\n gl: WebGL2RenderingContext,\n rep?: PatternRepetition,\n): [number, number] {\n switch (rep) {\n case 'repeat': return [gl.REPEAT, gl.REPEAT];\n case 'repeat-x': return [gl.REPEAT, gl.CLAMP_TO_EDGE];\n case 'repeat-y': return [gl.CLAMP_TO_EDGE, gl.REPEAT];\n default: return [gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE];\n }\n}\n","import type { Path } from '@weasel-js/geom';\nimport { type Mesh, tessellate } from '@weasel-js/geom/tessellate';\n\nlet cache = new WeakMap<Path, Mesh>();\n\n/**\n * Return the tessellated Mesh for `path`, computing and caching on first call.\n * Cached by Path identity (WeakMap) — different Path objects with the same\n * coords are distinct cache entries.\n *\n * A rect path the batch stages as a quad never reaches this cache. One used\n * as a clip, or filled with a pattern or vertex colors, does.\n *\n * Also bypassed whenever `DrawContext.flattenTolerance` is set: `fillMeshHandle`\n * (see `../draw`) routes custom-tolerance fills through a fresh transient\n * tessellation instead of this cache.\n */\nexport function getMesh(path: Path): Mesh {\n const cached = cache.get(path);\n if (cached !== undefined) return cached;\n const mesh = tessellate(path);\n cache.set(path, mesh);\n return mesh;\n}\n\n/** Test helper. Do not call from product code. */\nexport function _resetCacheForTests(): void {\n cache = new WeakMap();\n}\n","/**\n * registerProgram — public API for registering custom shader programs.\n *\n * Stores raw GLSL source strings in a module-level registry. GL compilation\n * happens on each WeaselRenderer via WeaselRenderer.registerProgram(), which\n * calls getProgramSource() and compiles the result. This keeps registerProgram\n * GL-context-agnostic — identical pattern to registerFont storing ImageBitmap.\n *\n * Module-level state = source strings only; compiled GL\n * programs live on each renderer's programRegistry (Map<id, ShaderProgram>).\n *\n * Lifecycle: program sources live for the module lifetime. No unregister in v1.\n */\n\nimport { createReflectable, type Reflection } from '@weasel-js/registry';\nimport { type TextureHandle } from '../textures/registerTexture';\n\nexport type { TextureHandle };\n\n/** Opaque handle to a compiled custom shader program. */\nexport interface ShaderProgramHandle {\n readonly id: string;\n}\n\n/**\n * A value for one uniform in `ShaderDrawCommand.uniforms`.\n *\n * | TS type | GL call |\n * |-------------------------|--------------------------------------|\n * | number | uniform1f |\n * | [n, n] | uniform2fv |\n * | [n, n, n] | uniform3fv |\n * | [n, n, n, n] | uniform4fv |\n * | Float32Array length 9 | uniformMatrix3fv (column-major) |\n * | Float64Array | as the Float32Array of its values |\n * | Float32Array length 16 | uniformMatrix4fv (column-major) |\n * | TextureHandle | bind to next tex unit + uniform1i |\n *\n * **Array uniforms.** Keyed by an array's bare name (`u_ripples` for\n * `uniform vec3 u_ripples[8]`), a flat `number[]`, `Float32Array`,\n * `Int32Array` or `Uint32Array` fills the array from slot 0 in one\n * `uniform*v` call chosen by the declared element type (`vec3` →\n * `uniform3fv`, `ivec2` → `uniform2iv`, `mat4` → `uniformMatrix4fv`, …).\n * Its length must be a whole number of elements and at most the declared\n * size; a shorter value leaves the remaining slots as they were. Per-slot\n * keys (`u_ripples[2]`) keep working and take the table above.\n */\nexport type ShaderUniform =\n | number\n | [number, number]\n | [number, number, number]\n | [number, number, number, number]\n | readonly number[]\n | Float32Array\n | Float64Array\n | Int32Array\n | Uint32Array\n | TextureHandle;\n\n/** A registered program's GLSL source. An empty `vert` means the kit's default vertex shader. */\nexport interface ProgramSource {\n vert: string;\n frag: string;\n}\n\nconst registry = createReflectable<ProgramSource>();\n\n/** Every registered program's GLSL source, keyed by program id. */\nexport const programSourceRegistry: Reflection<ProgramSource> = registry.reflection;\n\n/** @internal Test helper — do not call from product code. */\nexport function _resetProgramRegistryForTests(): void {\n registry.clear();\n}\n\n/** The source registered under `id`, or `null` when nothing is. */\nexport function getProgramSource(id: string): ProgramSource | null {\n return registry.get(id) ?? null;\n}\n\nconst isDev = (): boolean =>\n typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n\n/**\n * Register a custom shader program by id.\n *\n * Pass an empty string for `vert` to use the kit's default vertex shader\n * (recommended). The kit's vertex shader exposes `v_uv`, `v_screen`, and\n * `v_world` varyings plus `u_bounds` and `u_view` uniforms.\n *\n * **IMPORTANT — Premultiplied alpha:**\n * Your fragment shader MUST output premultiplied alpha:\n * `outColor = vec4(rgb * a, a);` ← correct\n * `outColor = vec4(rgb, a);` ← WRONG — over-brightens translucent regions\n *\n * The renderer uses `gl.blendFunc(ONE, ONE_MINUS_SRC_ALPHA)` to match.\n * Opaque fragments (a=1) are unaffected; only fragments with a < 1 differ.\n *\n * **Re-registration behavior:**\n * - Dev mode (`NODE_ENV !== 'production'`): calling with an existing id and new\n * source replaces it (hot reload). Every renderer that compiled the old source\n * recompiles on its next frame and deletes the program it replaces; a\n * `<Canvas shaders>` naming the id repaints to show it. If the new source fails\n * to compile, the renderer logs the error once and keeps drawing the old one.\n * - Prod mode: calling with an existing id throws.\n *\n * Actual GL compilation and `ShaderCompileError` throwing happen in\n * `WeaselRenderer.registerProgram()`, not here.\n *\n * @experimental API may break before v2.\n */\nexport function registerProgram(\n id: string,\n vert: string,\n frag: string,\n): ShaderProgramHandle {\n if (registry.has(id) && !isDev()) {\n throw new Error(`weasel registerProgram: duplicate program id \"${id}\". ` +\n `In production, re-registration is not allowed. Pass a unique id or call in dev mode.`);\n }\n registry.set(id, { vert, frag });\n return { id };\n}\n","/**\n * The renderer's half of a paint kind: what it takes to draw one.\n *\n * Solids, patterns and the three gradients are branches inside the GL\n * renderer and never come through here. A kind beyond those registers its\n * bind slot, its frame conversions and its shaders, and the renderer consults\n * this registry for any kind it does not recognize. What an editor or a\n * serializer needs of a kind is not the renderer's to know; whoever owns\n * those registers it beside this.\n */\n\nimport type { ColorSpace, FillStyle, GradientUnits, GradStop } from '@weasel-js/paint';\nimport { createReflectable, type Reflection } from '@weasel-js/registry';\nimport type { FillPoseBox } from './fillInPoseFrame';\nimport type { GlMat3 } from '@weasel-js/geom';\nimport type { ShaderProgram } from './shaders/ShaderProgram';\nimport { getProgramSource, registerProgram, type ProgramSource } from './shaders/registerProgram';\n\n/** A compiled GL program. A paint kind gets one from\n * {@link PaintBindContext.program} and hands it back from `bind`. */\nexport type PaintProgram = ShaderProgram;\n\n/**\n * The lifetime a paint kind's GPU state belongs to: one renderer on one live\n * context. The object itself is the key — a kind caches textures in a\n * `WeakMap` on it, so two renderers sharing a context never trade them — and\n * `onRelease` is where it frees them.\n */\nexport interface PaintResources {\n /** Run `release` once, when this lifetime ends: the renderer is disposed, or\n * its context was lost and restored. Free every GL object made under it\n * there. */\n onRelease(release: () => void): void;\n}\n\n/**\n * The renderer surface a paint kind binds against, narrowed to what a paint\n * needs. The full `DrawContext` is not consumer surface.\n */\nexport interface PaintBindContext {\n readonly gl: WebGL2RenderingContext;\n /** The group alpha this draw inherits — multiply it into the paint's own. */\n readonly alpha: number;\n /**\n * The compiled program for a `registerProgram` id, compiled against this\n * renderer on first use. `null` when no source is registered under `id` or\n * compilation failed.\n */\n program(id: string): PaintProgram | null;\n /** Send `u_proj` and `u_model`, which every kit vertex shader takes. */\n setProjAndModel(program: PaintProgram): void;\n /**\n * `u_worldInv` for a paint declaring `units` — the inverse of the transform\n * from the paint's space to the frame the geometry arrives in. Paired with\n * the vertex shader's `v_world` varying this is *the* paint-space\n * convention; it is not gradient-specific.\n *\n * `null` when that space has no inverse — a transform or view that flattens\n * an axis. Nothing the paint draws there means anything, so `bind` should\n * return `null` and draw nothing.\n */\n spaceInverse(units: GradientUnits | undefined): GlMat3 | null;\n /**\n * The transform from the space `units` names to device pixels of the target\n * this draw lands in — screen pixels times the pixel ratio on screen, output\n * pixels in a headless render. It is what a paint baking a texture measures\n * its resolution against. `null` where `spaceInverse` is.\n */\n spaceToDevice(units: GradientUnits | undefined): GlMat3 | null;\n /** The largest texture side this context accepts, `MAX_TEXTURE_SIZE`. */\n readonly maxTextureSize: number;\n /** The lifetime GPU state made for this draw belongs to. Stable across the\n * frames of one renderer, so it is the key for a kind's texture cache. */\n readonly resources: PaintResources;\n /**\n * Bake a stop ramp into the frame's ramp atlas, bind that atlas to a texture\n * unit, and return the `v` the ramp's own row sits at — every ramp in a\n * frame shares one texture, so a paint must sample at the returned `v` and\n * not at a constant.\n *\n * `space` is the blend the stops are baked through, defaulting to `'rgb'`.\n * It is part of the atlas key, so the same stops under two spaces take two\n * rows rather than colliding.\n */\n bindRamp(stops: GradStop[], unit: number, space?: ColorSpace): number;\n}\n\n/**\n * What the renderer needs of one paint kind. Every slot is optional, but\n * `inPoseFrame` and `toBoundsFrame` come as a pair or not at all: a kind that\n * converts one direction and not the other paints correctly once and then\n * drifts on the next resize.\n */\nexport interface PaintDrawKind {\n id: string;\n /**\n * Render slot: bind program, uniforms and textures for `fill` and return the\n * bound program; `null` declines the paint.\n *\n * Binding is split from drawing on purpose — a caller owning its own stencil\n * state (an inner/outer-aligned stroke, an even-odd fill) must issue its own\n * draw call, and the kit's draw wrapper would clobber that state. Shader\n * output must be premultiplied: `outColor = vec4(rgb * a, a)`.\n *\n * The geometry is not always the node's own. Text below the outline tier\n * paints by drawing a quad over its glyphs' screen box into an offscreen\n * buffer and masking that with glyph coverage, so a paint must come from\n * `v_world` through `spaceInverse`, not from where `a_position` happens to\n * lie.\n */\n bind?(ctx: PaintBindContext, fill: FillStyle): PaintProgram | null;\n /** Bounds frame → the frame the node is painted in. */\n inPoseFrame?(fill: FillStyle, box: FillPoseBox): FillStyle;\n /** The inverse. Required whenever `inPoseFrame` is supplied. */\n toBoundsFrame?(fill: FillStyle, box: FillPoseBox): FillStyle;\n /**\n * Shader programs `bind` looks up through `ctx.program`, keyed by program\n * id; registering the kind registers them. Declaring them here rather than\n * calling `registerProgram` at import keeps a kind loaded by\n * {@link registerPaintDrawKindLoader} free of the shader registry.\n */\n programs?: Readonly<Record<string, ProgramSource>>;\n}\n\nconst KINDS = createReflectable<PaintDrawKind>();\n\n/** Every registered draw kind, with the overrides each displaced. */\nexport const paintDrawKindRegistry: Reflection<PaintDrawKind> = KINDS.reflection;\n\n/** Register a kind's draw half. Returns a disposer that removes it.\n * Re-registering an existing id is an override; disposing it uncovers\n * whatever it displaced. */\nexport function registerPaintDrawKind(entry: PaintDrawKind): () => void {\n if ((entry.inPoseFrame === undefined) !== (entry.toBoundsFrame === undefined)) {\n const missing = entry.inPoseFrame === undefined ? 'inPoseFrame' : 'toBoundsFrame';\n throw new Error(\n `weasel registerPaintKind: kind \"${entry.id}\" is missing ${missing}. A kind ` +\n 'that converts one frame direction and not the other drifts on the next ' +\n 'resize; supply both or neither.',\n );\n }\n for (const [id, src] of Object.entries(entry.programs ?? {})) {\n const have = getProgramSource(id);\n if (!have || have.vert !== src.vert || have.frag !== src.frag) registerProgram(id, src.vert, src.frag);\n }\n return KINDS.push(entry.id, entry);\n}\n\n/** The draw half for `kind`, or `undefined`. A lookup that misses on a kind\n * with a loader starts that load; see {@link registerPaintDrawKindLoader}. */\nexport function getPaintDrawKind(kind: string | undefined): PaintDrawKind | undefined {\n const id = kind ?? 'solid';\n const entry = KINDS.get(id);\n if (!entry && LOADERS.has(id)) void startLoad(id).catch(() => {});\n return entry;\n}\n\n/** Resolves with the draw half of a kind that is loaded on first use. */\nexport type PaintDrawKindLoader = () => Promise<PaintDrawKind>;\n\nconst LOADERS = new Map<string, PaintDrawKindLoader>();\n\n/** One load per kind, kept after it settles: a failed load is not retried on\n * every frame that meets the kind. */\nconst LOADS = new Map<string, Promise<void>>();\n\n/**\n * Declare a paint kind that is loaded the first time something looks it up,\n * so its code stays out of the bundle until a paint of it appears — typically\n * `() => import('./myKind').then((m) => m.myKindEntry)`.\n *\n * Until it lands the kind is unregistered and the renderer draws nothing for\n * its paints. Call {@link warmPaintKinds} to load ahead of the first frame\n * instead.\n *\n * A kind that is already registered never calls its loader. Returns a\n * disposer that removes the loader.\n */\nexport function registerPaintDrawKindLoader(id: string, load: PaintDrawKindLoader): () => void {\n LOADERS.set(id, load);\n return () => {\n if (LOADERS.get(id) === load) LOADERS.delete(id);\n };\n}\n\nfunction startLoad(id: string): Promise<void> {\n const running = LOADS.get(id);\n if (running) return running;\n const load = LOADERS.get(id)!;\n const done = load().then(\n (entry) => {\n if (entry.id !== id) {\n throw new Error(`weasel: the loader for paint kind \"${id}\" resolved to \"${entry.id}\".`);\n }\n if (!KINDS.has(id)) registerPaintDrawKind(entry);\n },\n ).catch((err: unknown) => {\n console.error(`weasel: paint kind \"${id}\" failed to load:`, err);\n throw err;\n });\n LOADS.set(id, done);\n return done;\n}\n\n/** Is `id` registered, or declared with a loader? */\nexport function isPaintKindKnown(id: string): boolean {\n return KINDS.has(id) || LOADERS.has(id);\n}\n\n/**\n * Load paint kinds ahead of their first use, so the first frame that meets\n * one draws it rather than a blank. With no list, loads every kind that has a\n * loader.\n *\n * Resolves once every kind is registered; a kind already registered counts\n * as loaded. Rejects when a load fails, or for a kind that is neither\n * registered nor loadable.\n */\nexport function warmPaintKinds(kinds?: readonly string[]): Promise<void> {\n const ids = kinds ?? [...LOADERS.keys()];\n const loads: Promise<void>[] = [];\n for (const id of ids) {\n if (KINDS.has(id)) continue;\n if (!LOADERS.has(id)) {\n return Promise.reject(new Error(\n `weasel warmPaintKinds: \"${id}\" is neither registered nor loadable.`,\n ));\n }\n loads.push(startLoad(id));\n }\n return Promise.all(loads).then(() => undefined);\n}\n\n/** @internal Test helper — do not call from product code. */\nexport function _resetPaintDrawKindsForTests(): void {\n KINDS.clear();\n LOADERS.clear();\n LOADS.clear();\n}\n","/**\n * Tessellated stroke ribbons for scene paths, keyed on `Path` identity.\n *\n * The sibling of `cache.ts` (fills) and `outlineStrokeMeshCache.ts` (glyph\n * ribbons in em space), and it inherits their contract: identity, not content.\n * A `Path` rebuilt with equal coords is a distinct entry.\n *\n * Design: `docs/superpowers/specs/2026-08-15-stroke-ribbon-cache-design.md`.\n */\n\nimport type { Path } from '@weasel-js/geom';\nimport type { Stroke } from '@weasel-js/paint';\nimport { tessellateStroke, resolveStrokeWidth } from '@weasel-js/stroke';\nimport { strokeInsets } from '@weasel-js/stroke';\nimport { metricKey, type ScreenSpace, type StrokeSpaces } from '@weasel-js/stroke';\nimport type { InsetLength } from '@weasel-js/stroke';\nimport type { Mesh } from '@weasel-js/geom/tessellate';\n\n/**\n * Distinct stroke configurations kept per path before that path's map is\n * dropped wholesale. A document uses a handful; a width slider passes this on\n * its first drag and then degrades to tessellating every frame, which is what\n * it did before this cache existed.\n */\nexport const STROKE_CONFIGS_PER_PATH = 8;\n\n/** Screen-pixel bound on how far a quantized `{ px }` ribbon's width may\n * drift from the width asked for: each edge moves at most half of it. */\nconst PX_WIDTH_TOLERANCE = 1 / 8;\n\n/**\n * `scale` snapped to a log-spaced grid, for resolving a `{ px }` width against.\n * Resolving against the raw scale gives a continuous zoom a new cache key every\n * frame. The grid is fine enough that the resolved ribbon stays within\n * `PX_WIDTH_TOLERANCE` screen pixels of `px`, so it is coarser for thin\n * strokes, and powers of two land on it exactly.\n */\nexport function quantizeStrokeScale(px: number, scale: number): number {\n if (!(px > 0) || !(scale > 0) || !Number.isFinite(scale)) return scale;\n const stepsPerOctave = Math.ceil(Math.LN2 / (2 * Math.log1p(PX_WIDTH_TOLERANCE / px)));\n return 2 ** (Math.round(Math.log2(scale) * stepsPerOctave) / stepsPerOctave);\n}\n\ninterface StrokeEntry {\n readonly mesh: Mesh;\n /** Compared by reference — long enough that stringifying it per frame would\n * cost what the cache saves. */\n readonly vertexWidths: number[] | undefined;\n}\n\nlet cache = new WeakMap<Path, Map<string, StrokeEntry>>();\n\n/** The stroke parameters that change the ribbon's geometry. `paint` and\n * `vertexColors` are absent on purpose: both are applied over the same\n * triangles at draw time. Marker *identity* is absent too — only the\n * resolved trim distance affects these triangles, so two heads with the\n * same inset share one entry. */\nfunction configKey(stroke: Stroke, flattenTolerance: number | undefined, spaces: StrokeSpaces): string {\n const width = resolveStrokeWidth(stroke.width ?? 1, 1);\n const insets = strokeInsets(stroke, width);\n const ribbon = spaces.ribbon?.metric;\n return [\n width,\n stroke.cap ?? 'butt',\n stroke.join ?? 'miter',\n stroke.miterLimit ?? '',\n stroke.align ?? 'center',\n (stroke.dash ?? []).join(','),\n stroke.varyingWidthJoinThreshold ?? '',\n flattenTolerance ?? '',\n insets.start,\n insets.end,\n metricKey(ribbon),\n metricKey(spaces.start?.metric),\n metricKey(spaces.end?.metric),\n ].join('|');\n}\n\n/** The tessellated ribbon for `path` under `stroke`, built in the space\n * `spaces` names for it, and stopped short of each head in that head's own.\n * The same `Mesh` object comes back for as long as the entry lives. */\nexport function strokeMesh(\n path: Path,\n stroke: Stroke,\n flattenTolerance: number | undefined,\n spaces: StrokeSpaces = {},\n): Mesh {\n let byConfig = cache.get(path);\n if (byConfig === undefined) {\n byConfig = new Map<string, StrokeEntry>();\n cache.set(path, byConfig);\n }\n\n const key = configKey(stroke, flattenTolerance, spaces);\n const entry = byConfig.get(key);\n if (entry !== undefined && entry.vertexWidths === stroke.vertexWidths) {\n return entry.mesh;\n }\n\n const width = resolveStrokeWidth(stroke.width ?? 1, 1);\n const insets = strokeInsets(stroke, width);\n const mesh = tessellateStroke(path, stroke, {\n flattenTolerance,\n startInset: insetIn(insets.start, spaces.start, spaces.ribbon),\n endInset: insetIn(insets.end, spaces.end, spaces.ribbon),\n metric: spaces.ribbon?.metric,\n });\n // Only a new key grows the map; replacing one under a churning\n // `vertexWidths` must not evict the other configurations alongside it.\n if (entry === undefined && byConfig.size >= STROKE_CONFIGS_PER_PATH) byConfig.clear();\n byConfig.set(key, { mesh, vertexWidths: stroke.vertexWidths });\n return mesh;\n}\n\n/** `length`, measured in `head`'s space, as the tessellator reads it. */\nfunction insetIn(length: number, head: ScreenSpace | undefined, ribbon: ScreenSpace | undefined): InsetLength {\n return head?.metric === ribbon?.metric ? length : { length, metric: head?.metric ?? null };\n}\n\n/** Test helper. Do not call from product code. */\nexport function _resetStrokeMeshCacheForTests(): void {\n cache = new WeakMap();\n}\n","/**\n * Resolve a `units: 'bounds'` gradient into the frame its node is painted in.\n *\n * Node painters bake the pose into their geometry (`pathInPoseFrame`) rather\n * than emitting a per-node transform, so by the time the renderer sees a\n * scene node there is no node-local space left for a gradient to refer to.\n * This is the paint-side counterpart: it maps box-relative gradient geometry\n * onto the same box the path was just projected into, so the two arrive in\n * the renderer in one frame.\n */\n\nimport type { FillStyle, GradientFill, PosedFill } from '@weasel-js/paint';\nimport { getPaintDrawKind } from './paintKinds';\n\n/** The box a `'bounds'` gradient's normalized geometry is mapped onto —\n * usually a node's bounds. */\nexport interface FillPoseBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * Map a `'bounds'` gradient's `0..1` geometry onto `box`, returning it in the\n * box's own frame (`units: 'local'`). Any other fill — solid, pattern, or a\n * gradient in another space — is returned untouched.\n *\n * Radii scale by the box's normalized diagonal, SVG's rule for a percentage\n * radius against `objectBoundingBox`: `sqrt(w² + h²) / sqrt(2)`, which is\n * exactly `w` for a square box. The renderer's radial gradient is circular,\n * so a non-square box cannot make it the ellipse SVG would — this keeps the\n * radius proportionate instead.\n */\nexport function fillInPoseFrame(fill: FillStyle, box: FillPoseBox): PosedFill {\n if (!isBuiltinKind(fill)) {\n return (getPaintDrawKind(fill.fill)?.inPoseFrame?.(fill, box) ?? fill) as PosedFill;\n }\n if (isBoundsPattern(fill)) {\n const o = fill.origin ?? { x: 0, y: 0 };\n return { ...fill, origin: { x: box.x + o.x, y: box.y + o.y }, units: 'local' as const };\n }\n if (!isBoundsGradient(fill)) return fill as PosedFill;\n\n const toBox = (p: { x: number; y: number }): { x: number; y: number } => ({\n x: box.x + p.x * box.width,\n y: box.y + p.y * box.height,\n });\n\n if (fill.fill === 'linear-gradient') {\n return { ...fill, from: toBox(fill.from), to: toBox(fill.to), units: 'local' as const };\n }\n if (fill.fill === 'radial-gradient') {\n const scale = Math.hypot(box.width, box.height) / Math.SQRT2;\n return { ...fill, center: toBox(fill.center), radius: fill.radius * scale, units: 'local' as const };\n }\n return { ...fill, center: toBox(fill.center), units: 'local' as const };\n}\n\n/**\n * Inverse of {@link fillInPoseFrame}: express a gradient already positioned\n * in `box`'s frame as `0..1` fractions of that box (`units: 'bounds'`), so\n * it follows the node when moved or resized.\n *\n * The importer's counterpart — SVG `userSpaceOnUse` coordinates arrive in\n * page space, and normalizing them here makes an imported gradient behave\n * exactly like one drawn in the app.\n *\n * A zero-width or zero-height box has no frame to normalize against; the\n * fill is returned untouched rather than divided by zero.\n */\nexport function fillToBoundsFrame(fill: FillStyle, box: FillPoseBox): FillStyle {\n if (!isBuiltinKind(fill)) {\n return getPaintDrawKind(fill.fill)?.toBoundsFrame?.(fill, box) ?? fill;\n }\n if (fill.fill === 'pattern') {\n const o = fill.origin ?? { x: 0, y: 0 };\n return { ...fill, origin: { x: o.x - box.x, y: o.y - box.y }, units: 'bounds' as const };\n }\n const isGradient = fill.fill === 'linear-gradient'\n || fill.fill === 'radial-gradient'\n || fill.fill === 'conic-gradient';\n if (!isGradient) return fill;\n if (box.width === 0 || box.height === 0) return fill;\n\n const fromBox = (p: { x: number; y: number }): { x: number; y: number } => ({\n x: (p.x - box.x) / box.width,\n y: (p.y - box.y) / box.height,\n });\n\n if (fill.fill === 'linear-gradient') {\n return { ...fill, from: fromBox(fill.from), to: fromBox(fill.to), units: 'bounds' as const };\n }\n if (fill.fill === 'radial-gradient') {\n const scale = Math.hypot(box.width, box.height) / Math.SQRT2;\n return { ...fill, center: fromBox(fill.center), radius: fill.radius / scale, units: 'bounds' as const };\n }\n return { ...fill, center: fromBox(fill.center), units: 'bounds' as const };\n}\n\n/** True when this fill is a pattern anchored to the painted node's box.\n * Rebasing it is a translation only — a resize must reveal more tiles, not\n * stretch them, which is the whole reason patterns get their own branch. */\nfunction isBoundsPattern(\n fill: FillStyle,\n): fill is Extract<FillStyle, { fill: 'pattern' }> {\n return fill.fill === 'pattern' && fill.units === 'bounds';\n}\n\n/** True when this fill is a gradient declaring box-relative geometry. */\nfunction isBoundsGradient(fill: FillStyle | undefined): fill is GradientFill {\n if (fill === undefined) return false;\n const kind = fill.fill;\n if (kind !== 'linear-gradient' && kind !== 'radial-gradient' && kind !== 'conic-gradient') {\n return false;\n }\n return fill.units === 'bounds';\n}\n\n/** The five kinds whose frame conversion is written above. Anything else is a\n * registered kind and converts through its own entry. */\nfunction isBuiltinKind(fill: FillStyle): boolean {\n const kind = fill.fill ?? 'solid';\n return kind === 'solid' || kind === 'pattern'\n || kind === 'linear-gradient' || kind === 'radial-gradient' || kind === 'conic-gradient';\n}\n","/**\n * `TilePatternSpec` → `TextureHandle`. The bridge between the serializable\n * half of a pattern paint and the GL texture that paints it.\n *\n * Memoized on the spec's field values, so identical specs across nodes share\n * one texture and a re-render never re-rasterizes. The memo keeps the\n * `PATTERN_TILE_CACHE_LIMIT` tiles most recently resolved or drawn and\n * unregisters the rest. A handle outliving its tile still draws: its id is\n * the spec, and the texture registry asks this module to rebuild it.\n */\n\nimport type { CommandFill, FillStyle, PosedFill, TilePatternSpec } from '@weasel-js/paint';\nimport {\n ownTextureIds, registerTextureAs, textureRegistry, unregisterTexture,\n type TextureHandle,\n} from '../textures/registerTexture';\nimport { rasterizeTile } from './rasterizeTile';\nimport { drawTileShapes, tileGeometry, tileSize } from './tileGeometry';\n\n/** How many built-in tiles stay rasterized at once. A scene drawing more\n * distinct specs than this in one frame rebuilds the overflow every frame. */\nexport const PATTERN_TILE_CACHE_LIMIT = 256;\n\nconst ID_PREFIX = 'pattern:';\n\n/** Texture id → handle, least recently used first. */\nconst cache = new Map<string, TextureHandle | null>();\n\n/** Stable across key order — specs arriving from JSON have no guaranteed\n * field order, and two orderings must not rasterize two tiles. */\nfunction specId(spec: TilePatternSpec): string {\n const bag = spec as unknown as Record<string, unknown>;\n const sorted: Record<string, unknown> = {};\n for (const k of Object.keys(bag).sort()) sorted[k] = bag[k];\n return ID_PREFIX + JSON.stringify(sorted);\n}\n\n/** @internal Test helper — do not call from product code. */\nexport function _resetPatternSpecCacheForTests(): void {\n cache.clear();\n}\n\n/**\n * Build (or fetch) the texture for a spec. Returns `null` when the tile\n * can't be rasterized — no `OffscreenCanvas`, same as `createTilePattern`.\n */\nexport function resolvePatternSpec(spec: TilePatternSpec): TextureHandle | null {\n const id = specId(spec);\n const hit = cache.get(id);\n if (hit !== undefined) {\n markUsed(id);\n return hit;\n }\n return build(id, spec);\n}\n\nfunction markUsed(id: string): void {\n const hit = cache.get(id);\n if (hit === undefined) return;\n cache.delete(id);\n cache.set(id, hit);\n}\n\nfunction build(id: string, spec: TilePatternSpec): TextureHandle | null {\n const bitmap = TILES.has(spec.tile)\n ? rasterizeTile({\n size: tileSize(spec),\n draw: (oc) => drawTileShapes(oc, tileGeometry(spec)),\n })\n : null;\n const handle = bitmap ? registerTextureAs(id, bitmap) : null;\n cache.delete(id);\n cache.set(id, handle);\n while (cache.size > PATTERN_TILE_CACHE_LIMIT) evict(cache.keys().next().value!);\n return handle;\n}\n\nconst TILES: ReadonlySet<string> = new Set<TilePatternSpec['tile']>([\n 'hatch', 'crosshatch', 'dots', 'chunks',\n]);\n\nfunction evict(id: string): void {\n cache.delete(id);\n const source = textureRegistry.get(id)?.source;\n unregisterTexture({ id });\n if (source && 'close' in source) source.close();\n}\n\nfunction revive(id: string): void {\n let spec: unknown;\n try {\n spec = JSON.parse(id.slice(ID_PREFIX.length));\n } catch {\n return;\n }\n if (typeof spec !== 'object' || spec === null || !('tile' in spec)) return;\n build(id, spec as TilePatternSpec);\n}\n\nownTextureIds(ID_PREFIX, { revive, touched: markUsed });\n\n/** Whether a pattern payload is a spec rather than an already-built handle. */\nexport function isPatternSpec(\n payload: TextureHandle | TilePatternSpec,\n): payload is TilePatternSpec {\n return 'tile' in payload;\n}\n\n/**\n * Swap a pattern paint's spec payload for the texture that paints it,\n * leaving every other fill untouched. The built-in painters run this\n * alongside `fillInPoseFrame`; a consumer emitting its own draw commands\n * runs it at the same place it runs that one.\n *\n * A spec that can't rasterize drops the fill rather than painting garbage.\n */\nexport function resolveFillPattern(fill: PosedFill): CommandFill | null;\nexport function resolveFillPattern(fill: FillStyle): FillStyle | null;\nexport function resolveFillPattern(fill: FillStyle): FillStyle | null {\n if (fill.fill !== 'pattern') return fill;\n if (!isPatternSpec(fill.pattern)) return fill;\n const handle = resolvePatternSpec(fill.pattern);\n return handle ? { ...fill, pattern: handle } : null;\n}\n","/**\n * A node's paint, resolved into what a draw command takes. One place composes\n * the two resolutions so every painter and layer applies both.\n */\n\nimport type { CommandFill, CommandStroke, FillStyle, Stroke } from '@weasel-js/paint';\nimport { fillInPoseFrame, type FillPoseBox } from '../fillInPoseFrame';\nimport { resolveFillPattern } from './resolveSpec';\n\n/**\n * `fill` as a draw command's fill: `'bounds'` units mapped onto `box`, and a\n * tile spec swapped for its texture. `null` when a spec cannot rasterize.\n */\nexport function commandFill(fill: FillStyle, box: FillPoseBox): CommandFill | null {\n return resolveFillPattern(fillInPoseFrame(fill, box));\n}\n\n/**\n * `stroke` as a draw command's stroke, its paint resolved as\n * {@link commandFill} resolves a fill. `null` when the stroke carries no\n * paint, or its paint cannot be resolved.\n */\nexport function commandStroke(stroke: Stroke, box: FillPoseBox): CommandStroke | null {\n if (stroke.paint == null) return null;\n const paint = commandFill(stroke.paint, box);\n if (paint === null) return null;\n // Same object when nothing changed: the renderer's stroke caches key on it.\n return paint === stroke.paint ? (stroke as CommandStroke) : { ...stroke, paint };\n}\n","/**\n * Turning a stroke's markers into draw commands.\n *\n * Separate `PathDrawCommand`s rather than triangles appended to the stroke\n * ribbon: an entry may carry a fill and an outline at once, or a paint that\n * differs from the line's, neither of which one mesh can express — and folding\n * them in would drag the whole marker vocabulary into the ribbon cache key.\n */\n\nimport type { CommandFill, CommandStroke } from '@weasel-js/paint';\nimport { type Path, type PolygonPath, boundsOfPath } from '@weasel-js/geom';\nimport { markerHeads, type MarkerHead, type MarkerPaint } from '@weasel-js/stroke';\nimport type { PathDrawCommand } from './DrawCommand';\nimport { commandFill } from './patterns/commandPaint';\n\n/** A marker's own paint is resolved against its head's box, as a node's is\n * against the node's. */\nfunction resolvePaint(\n p: MarkerPaint | undefined, stroke: CommandStroke, fallback: MarkerPaint, head: PolygonPath,\n): CommandFill | undefined {\n const v = p ?? fallback;\n if (v === 'none') return undefined;\n if (v === 'line') return stroke.paint;\n return commandFill(v, boundsOfPath(head)) ?? undefined;\n}\n\n/** `heads` as draw commands in `stroke`'s paint. A head whose fill and outline\n * both resolve to no paint is dropped. */\nexport function headCommands(heads: readonly MarkerHead[], stroke: CommandStroke): PathDrawCommand[] {\n const out: PathDrawCommand[] = [];\n for (const { entry, path, size, space } of heads) {\n const fill = resolvePaint(entry.fill, stroke, 'line', path);\n // A head built in a screen space is in world once placed, but its outline\n // width is still in that space's units — so it goes out as the screen\n // width it stands for, and is stroked as exactly as the line.\n const width = entry.outline ? entry.outline.width * size : 0;\n const outline = entry.outline\n ? { paint: resolvePaint(entry.outline.paint, stroke, 'line', path), width: space ? { px: width * space.pxPerUnit } : width }\n : null;\n if (fill === undefined && (outline === null || outline.paint === undefined)) continue;\n out.push({\n kind: 'path',\n path,\n ...(fill ? { fill } : {}),\n ...(outline && outline.paint\n ? { stroke: { paint: outline.paint, width: outline.width, cap: 'round', join: 'round' } }\n : {}),\n });\n }\n return out;\n}\n\n/** Every marker command for `path` under `stroke`; see `markerHeads`. */\nexport function markerDrawCommands(\n path: Path,\n stroke: CommandStroke,\n strokeWidth: number,\n flattenTolerance: number | undefined,\n): PathDrawCommand[] {\n return headCommands(markerHeads(path, stroke, strokeWidth, flattenTolerance), stroke);\n}\n","/**\n * A stroke's marker commands, cached per path. The placed head is a fresh\n * `Path`, and the fill cache keys on path identity — so rebuilding it every\n * frame would re-tessellate and re-upload every head every frame.\n *\n * Keyed on value, so a painter that builds a new stroke object every frame\n * still hits: the resolved lengths, the flatten tolerance, the registry's\n * generation, the marker refs and whatever fields each head declares it reads.\n * A head that does not declare them may read any field, so for it the stroke\n * as the command carried it — before any `{ px }` length was resolved — joins\n * the key by identity. Paint is applied over the cached geometry, so a new\n * paint reuses the heads.\n */\n\nimport type { Path } from '@weasel-js/geom';\nimport type { CommandFill, MarkerRef, CommandStroke } from '@weasel-js/paint';\nimport type { PathDrawCommand } from '../DrawCommand';\nimport { headCommands } from '../markerCommands';\nimport { markerHeads, markerReadsKey, type MarkerHead } from '@weasel-js/stroke';\nimport { getMarker, markerGeneration } from '@weasel-js/stroke';\nimport { markerKeyOf } from '@weasel-js/stroke';\nimport { STROKE_CONFIGS_PER_PATH } from './strokeMeshCache';\nimport { screenSpaceKey, type StrokeSpaces } from '@weasel-js/stroke';\n\ninterface Entry {\n readonly heads: MarkerHead[];\n paint: CommandFill | undefined;\n cmds: PathDrawCommand[];\n}\n\nlet byValue = new WeakMap<Path, Map<string, Entry>>();\nlet byStroke = new WeakMap<Path, WeakMap<CommandStroke, Map<string, Entry>>>();\n\nconst refKey = (ref: MarkerRef | undefined): string =>\n ref === undefined ? '' : typeof ref === 'string' ? ref : `${ref.key}@${String(ref.size ?? '')}`;\n\n/** What every head of `stroke` reads, or `null` if any head does not say. */\nfunction readsKey(stroke: CommandStroke): string | null {\n let key = '';\n for (const ref of [stroke.markerStart, stroke.markerMid, stroke.markerEnd]) {\n const entry = ref === undefined ? undefined : getMarker(markerKeyOf(ref));\n if (entry === undefined) {\n key += '/';\n continue;\n }\n const reads = markerReadsKey(entry, stroke);\n if (reads === null) return null;\n key += `${reads}/`;\n }\n return key;\n}\n\nfunction mapFor(path: Path, source: CommandStroke, reads: string | null): Map<string, Entry> {\n if (reads !== null) {\n let map = byValue.get(path);\n if (map === undefined) byValue.set(path, (map = new Map()));\n return map;\n }\n let strokes = byStroke.get(path);\n if (strokes === undefined) byStroke.set(path, (strokes = new WeakMap()));\n let map = strokes.get(source);\n if (map === undefined) strokes.set(source, (map = new Map()));\n return map;\n}\n\n/**\n * The marker commands for `path` under `stroke`, whose lengths are already\n * resolved. `source` is the stroke before that resolution. A head's lengths are\n * in the space `spaces` builds it in.\n */\nexport function cachedMarkerCommands(\n path: Path,\n source: CommandStroke,\n stroke: CommandStroke,\n strokeWidth: number,\n flattenTolerance: number | undefined,\n spaces: StrokeSpaces = {},\n): PathDrawCommand[] {\n if (stroke.markerStart === undefined && stroke.markerMid === undefined && stroke.markerEnd === undefined) {\n return [];\n }\n const reads = readsKey(stroke);\n const map = mapFor(path, source, reads);\n const key = [\n strokeWidth,\n flattenTolerance ?? '',\n markerGeneration(),\n refKey(stroke.markerStart),\n refKey(stroke.markerMid),\n refKey(stroke.markerEnd),\n reads ?? '',\n screenSpaceKey(spaces.start),\n screenSpaceKey(spaces.mid),\n screenSpaceKey(spaces.end),\n ].join('|');\n let entry = map.get(key);\n if (entry === undefined) {\n const heads = markerHeads(path, stroke, strokeWidth, flattenTolerance, spaces);\n entry = { heads, paint: stroke.paint, cmds: headCommands(heads, stroke) };\n if (map.size >= STROKE_CONFIGS_PER_PATH) map.clear();\n map.set(key, entry);\n } else if (entry.paint !== stroke.paint) {\n entry.paint = stroke.paint;\n entry.cmds = headCommands(entry.heads, stroke);\n }\n return entry.cmds;\n}\n\n/** Test helper. Do not call from product code. */\nexport function _resetMarkerCommandCacheForTests(): void {\n byValue = new WeakMap();\n byStroke = new WeakMap();\n}\n","/**\n * Tessellated glyph outlines, in em space.\n *\n * This is the half of the outline text tier that is expensive: parsing `d`\n * into a path and running earcut over it costs far more than the per-instance\n * transform that follows. It is also the half that does not vary — em space\n * is unit-scale and baseline-relative, so the same glyph of the same face is\n * the same triangles at every size, position and zoom. Tessellate once, keep\n * it, and pay only a scale-and-translate per occurrence.\n *\n * That is why the renderer transforms cached vertices on the CPU and appends\n * them into one shared buffer rather than giving each glyph its own model\n * matrix: a per-glyph matrix would mean a draw call per glyph, throwing away\n * the batching the atlas tier already has, in exchange for saving an\n * arithmetic pass over a few hundred vertices.\n *\n * ### Flatten tolerance\n *\n * Tessellating once means committing to a curve tolerance once, and em space\n * makes that a clean tradeoff rather than a guess: an error of `T` em shows\n * up as `T × fontSize × viewScale` screen pixels. At 1/4096 em, a glyph would\n * have to reach ~4000 screen pixels tall before the flattening error covered\n * a single pixel — well past any size a document is read at, and far enough\n * past the tier's own threshold that the two never interact.\n *\n * ### Bound\n *\n * A plain `Map` with a cap and wholesale eviction. Glyph tessellations are\n * small (a few hundred vertices) and the working set is a charset, not a\n * document — the cap exists so a page that cycles through many faces cannot\n * grow without limit, not because pressure is expected. Wholesale rather than\n * LRU because the refill cost is bounded by what is actually on screen, and\n * an LRU's bookkeeping would cost more than the misses it avoids.\n */\n\nimport { pathFromD } from '@weasel-js/geom';\nimport { tessellate, type Mesh } from '@weasel-js/geom/tessellate';\n\n/** Curve flattening tolerance for glyph outlines, in em. See the header. */\nexport const OUTLINE_FLATTEN_TOLERANCE = 1 / 4096;\n\n/** Cached glyph tessellations before the cache is dropped wholesale. */\nexport const OUTLINE_MESH_CACHE_LIMIT = 2048;\n\nlet cache = new Map<string, Mesh>();\n\n/**\n * The em-space tessellation of one glyph.\n *\n * `key` identifies the glyph — face identity plus codepoint, assembled by\n * `layoutRuns`. `d` is only read on a miss, so passing the path data on every\n * call costs nothing; it is already in hand from the same source.\n */\nexport function outlineMesh(key: string, d: string): Mesh {\n const cached = cache.get(key);\n if (cached !== undefined) return cached;\n if (cache.size >= OUTLINE_MESH_CACHE_LIMIT) cache = new Map();\n const mesh = tessellate(pathFromD(d), { flattenTolerance: OUTLINE_FLATTEN_TOLERANCE });\n cache.set(key, mesh);\n return mesh;\n}\n\n/** Test helper. Do not call from product code. */\nexport function _resetOutlineMeshCacheForTests(): void {\n cache = new Map();\n}\n","/**\n * Tessellated glyph *outlines' strokes*, in em space.\n *\n * The sibling of `outlineMeshCache`, and cached for the same reason: parsing\n * `d` and tessellating a ribbon costs far more than the per-instance\n * transform that follows, and em space is size- and position-independent, so\n * one tessellation serves every occurrence of that glyph.\n *\n * ### Why the width is in the key\n *\n * A fill mesh is the same triangles at every size. A stroke's is not — the\n * ribbon's width relative to the glyph decides the geometry, so the em-space\n * mesh depends on `strokeWidth / fontSize`. That ratio is a property of the\n * run's style, not of the frame, so it is stable across frames and makes a\n * perfectly good cache key; what it is *not* is free, so a document that\n * animates stroke width or font size will miss every frame. That is the same\n * bargain `tessellate` makes everywhere else, and it is the reason the width\n * is quantized before it reaches the key: neighbouring sub-quantum widths\n * would otherwise each get their own entry and evict each other.\n *\n * Joins, caps, miter limit, alignment and dash all change the ribbon too, so\n * they are in the key as well — assembled by the caller, which already has\n * the `Stroke` in hand.\n */\n\nimport { pathFromD } from '@weasel-js/geom';\nimport { tessellateStroke } from '@weasel-js/stroke';\nimport { metricKey, type StrokeMetric } from '@weasel-js/stroke';\nimport type { Stroke } from '@weasel-js/paint';\nimport type { Mesh } from '@weasel-js/geom/tessellate';\nimport { OUTLINE_FLATTEN_TOLERANCE } from './outlineMeshCache';\n\n/** Cached ribbons before the cache is dropped wholesale. Matches the fill\n * cache's cap: the working set is a charset times the handful of stroke\n * widths a document actually uses. */\nexport const OUTLINE_STROKE_MESH_CACHE_LIMIT = 2048;\n\n/**\n * Em-width quantum. 1/1024 em is finer than any width a reader can\n * distinguish at the sizes this tier serves — a 0.001 em difference is a\n * fifth of a screen pixel on 200px text — and coarse enough that a slider\n * dragged across a range lands on a bounded set of keys.\n */\nconst WIDTH_QUANTUM = 1 / 1024;\n\nlet cache = new Map<string, Mesh>();\n\n/** Quantized em width, exported so the key builder and the tessellator agree\n * on the number rather than each rounding for themselves. */\nexport function quantizeEmWidth(emWidth: number): number {\n return Math.round(emWidth / WIDTH_QUANTUM) * WIDTH_QUANTUM;\n}\n\n/**\n * The em-space stroke tessellation of one glyph.\n *\n * `glyphKey` identifies the glyph (face identity plus codepoint, assembled by\n * `layoutRuns`); `emWidth` is the stroke width in em, already quantized, and\n * `stroke`'s dashes are in em too. Given a `metric`, the ribbon is built in its\n * space and both are lengths there. `d` is only read on a miss.\n *\n * Returns `null` when the ribbon has no area — a zero or negative width, or a\n * glyph whose path is empty (a space).\n */\nexport function outlineStrokeMesh(\n glyphKey: string,\n d: string,\n emWidth: number,\n stroke: Stroke,\n metric?: StrokeMetric,\n): Mesh | null {\n if (!(emWidth > 0)) return null;\n const key = [\n glyphKey, emWidth, stroke.join ?? 'miter', stroke.cap ?? 'butt',\n stroke.miterLimit ?? '', stroke.align ?? 'center', (stroke.dash ?? []).join(','),\n metricKey(metric),\n ].join('|');\n\n const cached = cache.get(key);\n if (cached !== undefined) return cached.indices.length === 0 ? null : cached;\n if (cache.size >= OUTLINE_STROKE_MESH_CACHE_LIMIT) cache = new Map();\n\n const mesh = tessellateStroke(\n pathFromD(d),\n { ...stroke, width: emWidth },\n { flattenTolerance: OUTLINE_FLATTEN_TOLERANCE, metric },\n );\n cache.set(key, mesh);\n return mesh.indices.length === 0 ? null : mesh;\n}\n\n/** Test helper. Do not call from product code. */\nexport function _resetOutlineStrokeMeshCacheForTests(): void {\n cache = new Map();\n}\n","/**\n * GLSL ES 3.0 source for the batch program — the one shader a run of solid\n * geometry, image quads and glyphs shares.\n *\n * **Every vertex names the texture it samples.** `a_texSlot` is an index into\n * `u_samplers`, and slot 0 is always the 1x1 white texel, so a solid's\n * `texture() * a_vertexColor` is the vertex color exactly. The multiply is\n * exact: an 8-bit white texel samples to 1.0, and 1.0 * x is x.\n *\n * The slot is per vertex rather than per flush because the run holds several\n * textures at once. Reserving slot 0 for white is what makes a solid's promise\n * true no matter what else joins its run: before this, a solid carried the\n * white texel's UV but the flush bound the run's *image*, so every ground rect\n * beside an atlas quad came out multiplied by whatever texel sat at the middle\n * of that atlas. A wall of white grounds drew olive.\n *\n * **The chain is unrolled because GLSL ES 3.0 will not index a sampler array\n * with a variable** — the index must be a constant expression, so `if (i == 0)\n * … if (i == 1) …` over constants is the only legal form. `v_texSlot` is\n * constant across a primitive, so the branch is uniform within any one\n * triangle; the coordinate it samples is a varying computed before the branch,\n * which is what keeps the implicit derivatives well defined.\n *\n * **The paint mode rides in `a_texSlot`, and the glyph math runs either way.**\n * A glyph vertex names a font atlas whose texel is a distance field rather than\n * a color, so its coverage comes from `glyphCoverage` and its color comes from\n * the vertex alone. That coverage is computed on every fragment, glyph or not,\n * because a derivative in non-uniform control flow is undefined and it\n * has to be taken before anything selects on the mode — see\n * `GLYPH_COVERAGE_GLSL`. Priced head to head at 432M fragments a frame\n * (`tests/perf/fill-rate.spec.ts`, teitou, 2026-10-05), that adds a quarter to\n * a half to a fragment that is not a glyph — 27–48% over four sittings. The\n * figure recorded when text landed was 1.4%, and it was wrong: the control\n * gated its glyph math on a factor the compiler folds to zero, so it timed a\n * shader with that math deleted. Fill is not what a wall is bound by, which is\n * why the conclusion stands even though the number did not.\n *\n * **A gradient is a textured quad off the ramp atlas.** A linear one needs no\n * mode: its ramp position is affine in position, so `a_uv` is (ramp position,\n * atlas row) and the plain path samples it. A radial or conic one carries the\n * gradient-space coordinate instead — affine even where the ramp position is\n * not — with the row in `a_post`, and the fragment takes a `length` or an\n * `atan` of it behind a branch on the flat mode. That branch carries the sample\n * itself, not just the coordinate: a fetch from a varying is one the hardware\n * schedules ahead, and one from a computed coordinate is not: on teitou the\n * computed-coordinate form costs 29–54% of a fragment, and the split one\n * −5–11%, which is the spread of the measurement itself\n * (`tests/perf/fill-rate.spec.ts`, 2026-10-05).\n *\n * **Mode and slot share one attribute because the vertex is the thing that\n * costs.** Both are small enumerations, so `slot + 8 * mode` packs them with\n * room to spare. Carrying the mode as a float of its own instead measured\n * slower at the densest rung of `tests/perf/atlas-wall.spec.ts`, timed then in\n * blocks of frames, a method since retired (`tests/perf/README.md`, \"Timing a\n * frame\"), so the size of it is unknown. The reason holds without the number: the\n * whole batch exists to make one buffer write a frame cheap, and every extra\n * float widens that write for every rect and quad in the run, not just for the\n * glyphs that read it.\n *\n * `a_post` is the alpha factor applied *after* the color matrix. An image quad\n * puts its opacity there, where `u_opacity` used to be — the fold is exact for\n * the same reason the old image shader's was, the matrix cannot see it. Solid\n * geometry and glyphs leave it at 1 and fold their own alpha into\n * `a_vertexColor`, which is only sound under an identity matrix; `draw.ts` owns\n * that condition.\n *\n * Inputs:\n * a_position vec2 screen-space x,y of the corner\n * a_vertexColor vec4 straight-alpha color; (1,1,1,1) on an image vertex\n * a_uv vec2 texture coordinate 0..1; the white texel for solids\n * a_post float alpha factor applied after the color matrix\n * a_texSlot float slot + 8 * paint mode; slot 0 is the white texel\n *\n * Output: PREMULTIPLIED alpha. Blend: `gl.blendFunc(ONE, ONE_MINUS_SRC_ALPHA)`.\n */\n\nimport { GLYPH_COVERAGE_GLSL } from '@weasel-js/font';\n\n/**\n * Texture units the batch program samples, slot 0 being the white texel.\n *\n * Fixed rather than queried: WebGL2 guarantees at least 16 fragment texture\n * units, so 8 is available everywhere without asking, and asking would mean a\n * `getParameter` the GL recorder answers with a recording function rather than\n * a number. Seven textures in one run is what \"a document with a handful of\n * distinct images, and a font or two\" needs; past that the run breaks as it\n * always did, and every extra slot is another compare in the fragment chain.\n */\nexport const BATCH_TEXTURE_SLOTS = 8;\n\n/** Slot every solid vertex carries — the white texel, bound by `flushBatch`. */\nexport const WHITE_SLOT = 0;\n\n/** Paint mode for everything whose texel is a color rather than a field. */\nexport const PAINT_MODE_PLAIN = 0;\n\n/**\n * Paint modes for the two gradients whose ramp position is not affine in\n * position — the ones a vertex cannot simply carry.\n *\n * They sit above the glyph modes (1 and 2), so `isGlyph` is a range rather than\n * a threshold. What a vertex carries in these modes is the *gradient-space\n * coordinate* in `a_uv` and its atlas row in `a_post`: that coordinate is\n * affine even where the ramp position is not, so the CPU folds it to two affine\n * rows and the shader takes a `length` or an `atan` of the result.\n *\n * A linear gradient has neither mode: its ramp position is affine outright, so\n * it is a textured quad off the atlas at `PAINT_MODE_PLAIN` and pays nothing\n * here.\n */\nexport const PAINT_MODE_RADIAL = 3;\nexport const PAINT_MODE_CONIC = 4;\n\n/** 1 / 2π, which turns a conic gradient's angle into a ramp position. */\nconst INV_TAU = (1 / (2 * Math.PI)).toFixed(10);\n\n/** Pack a texture slot and a paint mode into the one `a_texSlot` float. */\nexport function packSlot(slot: number, mode: number): number {\n return slot + BATCH_TEXTURE_SLOTS * mode;\n}\n\n/** The paint mode packed into an `a_texSlot` value — for the tests, which read\n * a vertex back out of the buffer it was staged into. */\nexport function paintModeOf(packed: number): number {\n return Math.floor((packed + 0.5) / BATCH_TEXTURE_SLOTS);\n}\n\n/**\n * Where each batch attribute lives, pinned rather than left to the linker so\n * `glyphPaint`'s program can draw from the same VAO.\n */\nexport const BATCH_ATTRIBUTE_LOCATIONS = {\n a_position: 0, a_vertexColor: 1, a_uv: 2, a_post: 3, a_texSlot: 4,\n} as const;\n\nconst L = BATCH_ATTRIBUTE_LOCATIONS;\n\nfunction sampleChain(slots: number): string {\n const arms: string[] = [];\n for (let i = 1; i < slots; i++) {\n arms.push(` if (slot == ${i}) return texture(u_samplers[${i}], uv);`);\n }\n return arms.join('\\n');\n}\n\nexport const BATCH_VERT_SRC = /* glsl */ `#version 300 es\nlayout(location = ${L.a_position}) in vec2 a_position;\nlayout(location = ${L.a_vertexColor}) in vec4 a_vertexColor;\nlayout(location = ${L.a_uv}) in vec2 a_uv;\nlayout(location = ${L.a_post}) in float a_post;\nlayout(location = ${L.a_texSlot}) in float a_texSlot;\nuniform mat3 u_proj;\nuniform mat3 u_model;\nout vec4 v_vertexColor;\nout vec2 v_uv;\nout float v_post;\nflat out int v_texSlot;\nflat out float v_paintMode;\nvoid main() {\n vec3 screen = u_model * vec3(a_position, 1.0);\n vec3 clip = u_proj * vec3(screen.xy, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n v_vertexColor = a_vertexColor;\n v_uv = a_uv;\n v_post = a_post;\n // slot + 8 * mode, unpacked — see the file header for why they share a float.\n int packed = int(a_texSlot + 0.5);\n v_texSlot = packed % ${BATCH_TEXTURE_SLOTS};\n v_paintMode = float(packed / ${BATCH_TEXTURE_SLOTS});\n}\n`;\n\nexport const BATCH_FRAG_SRC = /* glsl */ `#version 300 es\nprecision highp float;\nin vec4 v_vertexColor;\nin vec2 v_uv;\nin float v_post;\nflat in int v_texSlot;\nflat in float v_paintMode;\nuniform sampler2D u_samplers[${BATCH_TEXTURE_SLOTS}];\nuniform vec4 u_color;\nuniform float u_alpha;\nuniform float u_synthBold;\nuniform vec2 u_fieldScale[${BATCH_TEXTURE_SLOTS}];\nuniform mat4 u_colorMatrix;\nuniform vec4 u_colorBias;\nout vec4 outColor;\n\nvec4 sampleSlot(int slot, vec2 uv) {\n${sampleChain(BATCH_TEXTURE_SLOTS)}\n return texture(u_samplers[0], uv);\n}\n${GLYPH_COVERAGE_GLSL}\nvoid main() {\n float isGrad = step(2.5, v_paintMode);\n // A radial or conic vertex carries a gradient-space coordinate rather than a\n // texture coordinate, and its atlas row rather than an alpha. The sample is\n // split across the branch rather than the coordinate selected before it: an\n // arm that reads v_uv straight is a fetch the hardware can schedule against a\n // varying, and one reading a coordinate the shader computed is not. Selecting\n // the coordinate first and sampling once costs 29-54% of a fragment that is\n // not a gradient; splitting it is within the measurement's own spread of free\n // (tests/perf/fill-rate.spec.ts, teitou, 2026-10-05).\n //\n // Branching at all is safe here where it would not be around the glyph math:\n // v_paintMode is flat, so every fragment of a quad takes the same arm, and\n // nothing in either arm is a derivative.\n vec4 texel;\n if (isGrad > 0.5) {\n float t = v_paintMode > ${PAINT_MODE_CONIC - 0.5}\n ? fract(atan(v_uv.y, v_uv.x) * ${INV_TAU})\n : length(v_uv);\n texel = sampleSlot(v_texSlot, vec2(t, v_post));\n } else {\n texel = sampleSlot(v_texSlot, v_uv);\n }\n float isGlyph = step(0.5, v_paintMode) * step(v_paintMode, 2.5);\n // Unconditional, and multiplied out afterwards rather than branched around:\n // see the file header.\n float coverage = glyphCoverage(texel, v_paintMode, u_synthBold, v_uv, u_fieldScale[v_texSlot]);\n // A glyph's texel is a distance field, so it takes no part in the color; a\n // plain vertex multiplies its texel in as it always did.\n vec4 src = mix(texel, vec4(1.0), isGlyph) * u_color * v_vertexColor;\n vec4 mapped = clamp(u_colorMatrix * src + u_colorBias, 0.0, 1.0);\n float a = mapped.a * u_alpha * mix(v_post, 1.0, isGrad) * mix(1.0, coverage, isGlyph);\n outColor = vec4(mapped.rgb * a, a);\n}\n`;\n\nexport const BATCH_FILL_UNIFORMS = [\n 'u_proj', 'u_model', 'u_samplers', 'u_color', 'u_alpha', 'u_synthBold', 'u_fieldScale',\n 'u_colorMatrix', 'u_colorBias',\n] as const;\n\nexport const BATCH_FILL_ATTRIBUTES = [\n 'a_position', 'a_vertexColor', 'a_uv', 'a_post', 'a_texSlot',\n] as const;\n","/**\n * Clipping staged geometry to an axis-aligned rect on the CPU, so a rect clip\n * needs no stencil and does not break the run.\n *\n * A stencil clip is GL state, so content inside one cannot share a draw with\n * content outside it, and every clipped group paid a flush on the way in and\n * another on the way out. A rect under a transform that keeps it axis-aligned\n * is the common clip, and for that one the clip can ride the geometry instead:\n * cut each staged polygon to the rect before it joins the run.\n *\n * Exact, not approximate: every attribute a batch vertex carries is affine\n * across the polygon it belongs to, so interpolating along a cut edge gives\n * the value the rasterizer would have produced there, and the cut polygon\n * covers the same pixel centers the stencil would have passed.\n */\n\nimport type { Path, GlMat3 } from '@weasel-js/geom';\n\n/** In the space batch vertices are staged in: after the model transform,\n * before the projection. */\nexport interface ClipRect {\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n}\n\n/**\n * `path` under `m` as a `ClipRect`, or `null` when it is not one: not a rect\n * path, or a transform that rotates or skews it off the axes.\n */\nexport function axisAlignedClipRect(path: Path, m: GlMat3): ClipRect | null {\n if (path.kind !== 'rect') return null;\n const keepsAxes = (m[1] === 0 && m[3] === 0) || (m[0] === 0 && m[4] === 0);\n if (!keepsAxes) return null;\n const ax = m[0] * path.x + m[3] * path.y + m[6];\n const ay = m[1] * path.x + m[4] * path.y + m[7];\n const x1 = path.x + path.width;\n const y1 = path.y + path.height;\n const bx = m[0] * x1 + m[3] * y1 + m[6];\n const by = m[1] * x1 + m[4] * y1 + m[7];\n return {\n x0: Math.min(ax, bx), y0: Math.min(ay, by),\n x1: Math.max(ax, bx), y1: Math.max(ay, by),\n };\n}\n\nexport function intersectClipRects(a: ClipRect, b: ClipRect): ClipRect {\n return {\n x0: Math.max(a.x0, b.x0), y0: Math.max(a.y0, b.y0),\n x1: Math.min(a.x1, b.x1), y1: Math.min(a.y1, b.y1),\n };\n}\n\n/**\n * Cut the convex polygon of `n` vertices in `src` (each `stride` floats, x and\n * y first) to `rect`, writing the result to `dst`. Returns the vertex count,\n * which is below 3 when nothing is left. `tmp` must hold as many floats as\n * `dst`; both need room for `n + 4` vertices.\n */\nexport function clipConvexPolygon(\n src: Float32Array, n: number, stride: number, rect: ClipRect,\n dst: Float32Array, tmp: Float32Array,\n): number {\n // Four passes, ping-ponging so the last one lands in `dst`.\n let count = clipEdge(src, n, stride, 0, rect.x0, 1, tmp);\n count = clipEdge(tmp, count, stride, 0, rect.x1, -1, dst);\n count = clipEdge(dst, count, stride, 1, rect.y0, 1, tmp);\n return clipEdge(tmp, count, stride, 1, rect.y1, -1, dst);\n}\n\n/** One Sutherland–Hodgman pass: keep the side of `axis = at` where\n * `sign * (v - at) >= 0`. */\nfunction clipEdge(\n src: Float32Array, n: number, stride: number,\n axis: 0 | 1, at: number, sign: 1 | -1, out: Float32Array,\n): number {\n if (n === 0) return 0;\n let m = 0;\n let prev = n - 1;\n let prevIn = sign * (src[prev * stride + axis] - at) >= 0;\n for (let cur = 0; cur < n; cur++) {\n const curIn = sign * (src[cur * stride + axis] - at) >= 0;\n if (curIn !== prevIn) {\n const a = prev * stride;\n const b = cur * stride;\n const t = (at - src[a + axis]) / (src[b + axis] - src[a + axis]);\n const o = m * stride;\n for (let k = 0; k < stride; k++) out[o + k] = src[a + k] + t * (src[b + k] - src[a + k]);\n // On the line exactly, whatever the interpolation rounded to.\n out[o + axis] = at;\n m++;\n }\n if (curIn) {\n const o = m * stride;\n const c = cur * stride;\n for (let k = 0; k < stride; k++) out[o + k] = src[c + k];\n m++;\n }\n prev = cur;\n prevIn = curIn;\n }\n return m;\n}\n","/**\n * Growable vertex staging for a run of solid-fill geometry, image quads and\n * glyphs.\n *\n * Geometry only: `draw.ts` owns when a run starts, what breaks it, and the\n * uniforms the flush draws under.\n *\n * **One batch for all three, because a page interleaves them.** A grid of\n * thumbnails is a ground rect under an atlas quad under a caption, per cell,\n * and while each kind staged separately every one had to drain the others\n * before it could stage — so a shape that batches perfectly in any one half\n * alone paid a flush per command. Everything a vertex needs to say which it is\n * fits in the same vertex: solids carry the UV of a 1x1 white texel and are\n * their own color, quads carry their atlas UV and a white color, glyphs carry\n * a font atlas UV, their text color, and a paint mode saying the texel is a\n * distance field rather than a color. Gradients join as a fourth off the ramp\n * atlas — a linear one without a mode of its own, since (ramp position, row) is\n * what the plain mode already samples, and a radial or conic one with a mode\n * that says its UV is a gradient-space coordinate to take a `length` or an\n * `atan` of. See `shaders/batchFill.ts`.\n *\n * Colors ride the vertices because shapes in a run differ in color and a merged\n * draw has one set of uniforms — and so does the model transform, applied here\n * rather than uploaded, so shapes under different transforms still share a\n * draw. The texture rides them too, as a slot index into the units the flush\n * binds: slot 0 is the white texel every solid samples, and `draw.ts` hands out\n * the rest per bitmap. A run holds as many bitmaps as there are slots, so an\n * atlas is what makes a wall of one sheet coalesce and a handful of loose\n * bitmaps no longer breaks a run per command.\n */\n\nimport type { Mesh } from '@weasel-js/geom/tessellate';\nimport type { GlMat3 } from '@weasel-js/geom';\nimport type { ShaderProgram } from './shaders/ShaderProgram';\nimport { PAINT_MODE_PLAIN, WHITE_SLOT, packSlot } from './shaders/batchFill';\nimport { clipConvexPolygon, type ClipRect } from './batchClip';\n\n/** Vertices per flush. Caps staging memory; a longer run flushes in chunks,\n * which stays correct because painter's order survives a flush. */\nexport const MAX_VERTICES_PER_BATCH = 32768;\n\n/** vec2 a_position + vec4 a_vertexColor + vec2 a_uv + float a_post + float\n * a_texSlot. Exported so the buffer-replay tests read fields by name rather\n * than by a stride they repeat — a hard-coded one silently reads a different\n * field when the vertex grows, instead of failing. */\nexport const FLOATS_PER_VERTEX = 10;\n\n/** Float offset of `a_texSlot` within a vertex, which carries the paint mode\n * packed alongside the slot — `paintModeOf` unpacks it. */\nexport const TEX_SLOT_OFFSET = 9;\nconst INITIAL_VERTICES = 256;\nconst INITIAL_INDICES = 384;\n\n/** UV of the white texel bound at slot 0. Its texture is 1x1, so any\n * coordinate lands on it; the center is the one that stays on it under either\n * filter. */\nexport const WHITE_U = 0.5;\nexport const WHITE_V = 0.5;\n\n/**\n * A gradient vertex's `a_uv`, each channel affine in the coordinates the\n * geometry arrives in: `u = ux*x + uy*y + u0`, and the same for `v`.\n *\n * One shape for all three gradients. A linear one's `v` row is the constant\n * atlas row and its `u` row is the ramp position; a radial or conic one's two\n * rows are the gradient-space coordinate, and the row rides `a_post` instead.\n */\nexport interface GradientUV {\n ux: number; uy: number; u0: number;\n vx: number; vy: number; v0: number;\n}\n\n/** What `a_texSlot` carries on a vertex that is its own color: the white texel\n * at the plain paint mode. */\nconst PLAIN_WHITE = packSlot(WHITE_SLOT, PAINT_MODE_PLAIN);\n\n/**\n * Flushes between one ring slot's write and its next.\n *\n * Sized for a driver that tracks a write hazard per buffer object, where\n * rewriting one buffer before every flush makes each write wait on the draw\n * still reading it. That was measured on an M2 Max by timing blocks of frames,\n * a method since retired (`tests/perf/README.md`, \"Timing a frame\"), and on\n * teitou (M5 Max, ANGLE Metal, 2026-10-05) one frame a task does not show it:\n * `tests/perf/image-quad.spec.ts` puts a quad through a ring of 64 at 3.3–5.2 us\n * over two sittings, through one buffer rewritten each time at 2.5–3.0, and\n * through a buffer nothing writes at 0.16–0.22.\n */\nexport const SOLID_RING_SIZE = 64;\n\n/**\n * Slot sizes, smallest first. A flush takes the first it fits in.\n *\n * **Tiered because a write into a big slot costs more than the same write into\n * a small one.** On teitou (M5 Max, ANGLE Metal, 2026-10-05), a frame of 20,000\n * quads each drawn alone (`tests/perf/image-quad.spec.ts`, `renderer/unmerged`)\n * costs 19.2–19.9 us a quad with these tiers against 21.0 with 1,024 vertices\n * as the smallest slot, and a merged run is unmoved either way. The 92 ms\n * against 53 recorded before came from timing blocks of frames, a method since\n * retired. The run that most wants a small buffer — one command, because the\n * next broke it — is exactly the run a batch is otherwise pure overhead for.\n */\nexport const BATCH_TIERS: readonly { vertices: number; indices: number }[] = [\n { vertices: 16, indices: 24 },\n { vertices: 1024, indices: 3072 },\n];\n\n/** What a standard slot holds, named for the tests and the flush-cost specs. */\nexport const SOLID_RING_SLOT_VERTICES = BATCH_TIERS[BATCH_TIERS.length - 1].vertices;\n\n/** Slots for flushes past the largest tier. These grow to fit, so they are few:\n * a run that big is a run few things broke, and there are not many of them in\n * a frame to cycle between. */\nexport const SOLID_LARGE_RING_SIZE = 4;\n\n/** One VAO and the two buffers its attribute and element bindings name. */\ninterface BufferSet {\n vao: WebGLVertexArrayObject;\n vbo: WebGLBuffer;\n ibo: WebGLBuffer;\n /** What the GPU buffers are currently sized for. */\n vertexCapacity: number;\n indexCapacity: number;\n /**\n * Quads for which this slot's element buffer holds the canonical pattern,\n * or 0 for contents that cannot be named that way (a mesh's rebased indices,\n * or a buffer just respecified).\n *\n * The pattern for N quads is a prefix of the pattern for any larger N, so a\n * slot written to its capacity serves every quad flush it ever takes and the\n * upload happens once per slot rather than once per flush. Rects and image\n * quads share it: both wind 0-1-2 / 0-2-3.\n */\n canonicalQuads: number;\n}\n\nfunction doubledTo(from: number, need: number): number {\n let capacity = from;\n while (capacity < need) capacity *= 2;\n return capacity;\n}\n\n/** The canonical quad index pattern for `quads` quads, as the push helpers\n * wind them: two triangles over corners 0-1-2 and 0-2-3. */\nfunction quadIndices(quads: number): Uint32Array {\n const out = new Uint32Array(quads * 6);\n for (let q = 0; q < quads; q++) {\n const b = q * 4;\n const j = q * 6;\n out[j] = b; out[j + 1] = b + 1; out[j + 2] = b + 2;\n out[j + 3] = b; out[j + 4] = b + 2; out[j + 5] = b + 3;\n }\n return out;\n}\n\nexport class DrawBatch {\n private readonly gl: WebGL2RenderingContext;\n private readonly aPos: number;\n private readonly aColor: number;\n private readonly aUv: number;\n private readonly aPost: number;\n private readonly aSlot: number;\n\n /** One ring per tier, cycled per flush. Slots are created on first use, so a\n * renderer that flushes rarely allocates as few as it flushes. */\n private readonly rings: (BufferSet | undefined)[][] =\n BATCH_TIERS.map(() => new Array(SOLID_RING_SIZE).fill(undefined));\n private readonly nextInRing: number[] = BATCH_TIERS.map(() => 0);\n /** The same, for flushes past the largest tier; these sets grow to fit. */\n private readonly largeRing: (BufferSet | undefined)[] =\n new Array(SOLID_LARGE_RING_SIZE).fill(undefined);\n private nextLarge = 0;\n\n private verts = new Float32Array(INITIAL_VERTICES * FLOATS_PER_VERTEX);\n private idx = new Uint32Array(INITIAL_INDICES);\n private nVerts = 0;\n private nIdx = 0;\n /** Whether the staged run is quads alone, so its indices are the canonical\n * pattern and a slot already holding that pattern needs no upload. */\n private pureRects = true;\n\n /** The rect every push is cut to, or `null`. `draw.ts` sets it as rect\n * clips enter and leave — see `batchClip.ts`. A push returns `false`, having\n * staged nothing, for geometry it cannot cut exactly; see `clipQuad`. */\n clip: ClipRect | null = null;\n /** Polygon scratch for `clip`: a quad cut by four edges has at most eight\n * corners. */\n private readonly polyIn = new Float32Array(8 * FLOATS_PER_VERTEX);\n private readonly polyOut = new Float32Array(8 * FLOATS_PER_VERTEX);\n private readonly polyTmp = new Float32Array(8 * FLOATS_PER_VERTEX);\n\n constructor(gl: WebGL2RenderingContext, prog: ShaderProgram) {\n const aPos = prog.attribute('a_position');\n const aColor = prog.attribute('a_vertexColor');\n const aUv = prog.attribute('a_uv');\n const aPost = prog.attribute('a_post');\n const aSlot = prog.attribute('a_texSlot');\n if (aPos === undefined || aColor === undefined || aUv === undefined\n || aPost === undefined || aSlot === undefined) {\n throw new Error(\n 'DrawBatch: batch program is missing a_position / a_vertexColor / a_uv / '\n + 'a_post / a_texSlot',\n );\n }\n this.gl = gl;\n this.aPos = aPos;\n this.aColor = aColor;\n this.aUv = aUv;\n this.aPost = aPost;\n this.aSlot = aSlot;\n }\n\n get length(): number {\n return this.nIdx;\n }\n\n /** Whether staging `vertices` more would put the run past the per-flush cap. */\n wouldOverflow(vertices: number): boolean {\n return this.nVerts + vertices > MAX_VERTICES_PER_BATCH;\n }\n\n /**\n * Append one rect's four corners through `m`, all carrying `rgba` (straight\n * alpha). An affine maps a rect to a parallelogram, so two triangles still\n * cover it and the batch draws at `u_model` identity.\n */\n pushRect(\n x: number, y: number, w: number, h: number, m: GlMat3,\n r: number, g: number, b: number, a: number,\n ): boolean {\n this.reserve(4, 6);\n let i = this.nVerts * FLOATS_PER_VERTEX;\n const ma = m[0], mb = m[1], mc = m[3], md = m[4], mtx = m[6], mty = m[7];\n const x1 = x + w;\n const y1 = y + h;\n const ax = ma * x + mc * y + mtx, ay = mb * x + md * y + mty;\n const bx = ma * x1 + mc * y + mtx, by = mb * x1 + md * y + mty;\n const cx = ma * x1 + mc * y1 + mtx, cy = mb * x1 + md * y1 + mty;\n const dx = ma * x + mc * y1 + mtx, dy = mb * x + md * y1 + mty;\n const P = PLAIN_WHITE;\n i = this.writeVertex(i, ax, ay, r, g, b, a, WHITE_U, WHITE_V, 1, P);\n i = this.writeVertex(i, bx, by, r, g, b, a, WHITE_U, WHITE_V, 1, P);\n i = this.writeVertex(i, cx, cy, r, g, b, a, WHITE_U, WHITE_V, 1, P);\n this.writeVertex(i, dx, dy, r, g, b, a, WHITE_U, WHITE_V, 1, P);\n this.pushQuadIndices();\n return this.clip === null || this.clipQuad(this.nVerts - 4, this.nIdx - 6, this.clip);\n }\n\n /**\n * Append one image quad: the destination rect `(x, y, w, h)` mapped through\n * `m`, sampling `(u0, v0)`-`(u1, v1)`, every corner carrying `post` as the\n * after-the-color-matrix alpha factor.\n *\n * Corners wind top-left, top-right, bottom-right, bottom-left with UVs\n * following — the same winding `pushRect` uses, which is what lets a run of\n * mixed rects and quads keep the canonical index pattern. The flips a command\n * asks for are already in the `u` / `v` the caller passes.\n *\n * `slot` is the texture unit the corners sample, which `draw.ts` assigns per\n * bitmap within the run.\n */\n pushQuad(\n x: number, y: number, w: number, h: number, m: GlMat3,\n u0: number, v0: number, u1: number, v1: number,\n post: number, slot: number,\n ): boolean {\n this.reserve(4, 6);\n let i = this.nVerts * FLOATS_PER_VERTEX;\n const ma = m[0], mb = m[1], mc = m[3], md = m[4], mtx = m[6], mty = m[7];\n const x1 = x + w;\n const y1 = y + h;\n const ax = ma * x + mc * y + mtx, ay = mb * x + md * y + mty;\n const bx = ma * x1 + mc * y + mtx, by = mb * x1 + md * y + mty;\n const cx = ma * x1 + mc * y1 + mtx, cy = mb * x1 + md * y1 + mty;\n const dx = ma * x + mc * y1 + mtx, dy = mb * x + md * y1 + mty;\n const P = packSlot(slot, PAINT_MODE_PLAIN);\n i = this.writeVertex(i, ax, ay, 1, 1, 1, 1, u0, v0, post, P);\n i = this.writeVertex(i, bx, by, 1, 1, 1, 1, u1, v0, post, P);\n i = this.writeVertex(i, cx, cy, 1, 1, 1, 1, u1, v1, post, P);\n this.writeVertex(i, dx, dy, 1, 1, 1, 1, u0, v1, post, P);\n this.pushQuadIndices();\n return this.clip === null || this.clipQuad(this.nVerts - 4, this.nIdx - 6, this.clip);\n }\n\n /**\n * Append one glyph quad: the box `(x0, y0)`-`(x1, y1)` mapped through `m`,\n * sampling `(u0, v0)`-`(u1, v1)` of the font atlas at `slot`, painted in\n * `rgba`.\n *\n * `mode` says which channels of that atlas carry the distance field, and\n * rides the vertices packed into the slot — so a run off a baked MSDF atlas\n * and one off the runtime canvas bake still share a draw. The synthetic-bold\n * threshold does not: it is `u_synthBold`, and `draw.ts` breaks the run when\n * it changes.\n *\n * **A synthetic oblique is sheared here rather than in the shader.** The old\n * text program carried the baseline per vertex and skewed against\n * `u_synthItalic`; the batch places its own corners, so the shear is one\n * multiply while they are being placed, and `tanItalic` is 0 for an upright\n * face. It has to happen before `m`, which is where the shader had it too.\n *\n * Corners wind top-left, top-right, bottom-right, bottom-left — `pushQuad`'s\n * winding, which is what lets a run of mixed rects, image quads and glyphs\n * keep the canonical index pattern.\n */\n pushGlyph(\n x0: number, y0: number, x1: number, y1: number,\n baselineY: number, tanItalic: number, m: GlMat3,\n u0: number, v0: number, u1: number, v1: number,\n r: number, g: number, b: number, a: number,\n slot: number, mode: number,\n ): boolean {\n this.reserve(4, 6);\n let i = this.nVerts * FLOATS_PER_VERTEX;\n const ma = m[0], mb = m[1], mc = m[3], md = m[4], mtx = m[6], mty = m[7];\n // Above-baseline corners (lower y in screen coords) lean further right.\n const topShift = (baselineY - y0) * tanItalic;\n const botShift = (baselineY - y1) * tanItalic;\n const tx0 = x0 + topShift, tx1 = x1 + topShift;\n const bx0 = x0 + botShift, bx1 = x1 + botShift;\n const ax = ma * tx0 + mc * y0 + mtx, ay = mb * tx0 + md * y0 + mty;\n const bx = ma * tx1 + mc * y0 + mtx, by = mb * tx1 + md * y0 + mty;\n const cx = ma * bx1 + mc * y1 + mtx, cy = mb * bx1 + md * y1 + mty;\n const dx = ma * bx0 + mc * y1 + mtx, dy = mb * bx0 + md * y1 + mty;\n const P = packSlot(slot, mode);\n i = this.writeVertex(i, ax, ay, r, g, b, a, u0, v0, 1, P);\n i = this.writeVertex(i, bx, by, r, g, b, a, u1, v0, 1, P);\n i = this.writeVertex(i, cx, cy, r, g, b, a, u1, v1, 1, P);\n this.writeVertex(i, dx, dy, r, g, b, a, u0, v1, 1, P);\n this.pushQuadIndices();\n return this.clip === null || this.clipQuad(this.nVerts - 4, this.nIdx - 6, this.clip);\n }\n\n /**\n * Append one rect filled by a gradient: the corners of `(x, y, w, h)` mapped\n * through `m`, sampling the ramp atlas at `slot`.\n *\n * `uv` gives each channel of `a_uv` as an affine function of the coordinates\n * the corners arrive in, which is what lets a gradient ride the vertices at\n * all: a linear one's ramp position is affine in position outright, and a\n * radial or conic one's gradient-space *coordinate* is, even though the ramp\n * position it yields is not. Either way the rasterizer's interpolation across\n * a triangle is exact. `mode` says which of the two the fragment shader is\n * looking at, and `post` carries the atlas row for the modes that read it —\n * see `shaders/batchFill.ts`.\n *\n * Values outside 0..1 are the sampler's business; the atlas clamps to the\n * edge texel, which is what the gradient shader's own `clamp` did.\n */\n pushGradientRect(\n x: number, y: number, w: number, h: number, m: GlMat3,\n uv: GradientUV, post: number, slot: number, mode: number,\n r: number, g: number, b: number, a: number,\n ): boolean {\n this.reserve(4, 6);\n let i = this.nVerts * FLOATS_PER_VERTEX;\n const ma = m[0], mb = m[1], mc = m[3], md = m[4], mtx = m[6], mty = m[7];\n const x1 = x + w;\n const y1 = y + h;\n const P = packSlot(slot, mode);\n const corner = (cx: number, cy: number): number => {\n const at = i;\n i = this.writeVertex(\n at, ma * cx + mc * cy + mtx, mb * cx + md * cy + mty,\n r, g, b, a,\n uv.ux * cx + uv.uy * cy + uv.u0,\n uv.vx * cx + uv.vy * cy + uv.v0,\n post, P,\n );\n return i;\n };\n corner(x, y);\n corner(x1, y);\n corner(x1, y1);\n corner(x, y1);\n this.pushQuadIndices();\n return this.clip === null || this.clipQuad(this.nVerts - 4, this.nIdx - 6, this.clip);\n }\n\n /** `pushMesh` for a mesh filled by a gradient — see `pushGradientRect` for\n * what `uv`, `post` and `mode` carry. */\n pushGradientMesh(\n mesh: Mesh, m: GlMat3,\n uv: GradientUV, post: number, slot: number, mode: number,\n r: number, g: number, b: number, a: number,\n ): boolean {\n const src = mesh.vertices;\n const srcIdx = mesh.indices;\n const n = src.length >> 1;\n this.reserve(n, srcIdx.length);\n this.pureRects = false;\n const v = this.verts;\n let i = this.nVerts * FLOATS_PER_VERTEX;\n const ma = m[0], mb = m[1], mc = m[3], md = m[4], mtx = m[6], mty = m[7];\n const P = packSlot(slot, mode);\n for (let k = 0; k < n; k++) {\n const x = src[k * 2];\n const y = src[k * 2 + 1];\n v[i++] = ma * x + mc * y + mtx;\n v[i++] = mb * x + md * y + mty;\n v[i++] = r; v[i++] = g; v[i++] = b; v[i++] = a;\n v[i++] = uv.ux * x + uv.uy * y + uv.u0;\n v[i++] = uv.vx * x + uv.vy * y + uv.v0;\n v[i++] = post; v[i++] = P;\n }\n const base = this.nVerts;\n const out = this.idx;\n let j = this.nIdx;\n for (let k = 0; k < srcIdx.length; k++) out[j++] = base + srcIdx[k];\n this.nVerts += n;\n this.nIdx += srcIdx.length;\n return this.clip === null || this.clipMesh(base, this.nIdx - srcIdx.length, this.clip);\n }\n\n /**\n * Append a tessellated mesh through `m`, all vertices carrying `rgba`. The\n * mesh's own indices are rebased onto the staged vertices, which is why the\n * index buffer is uploaded per flush rather than written once.\n */\n pushMesh(\n mesh: Mesh, m: GlMat3,\n r: number, g: number, b: number, a: number,\n ): boolean {\n const src = mesh.vertices;\n const srcIdx = mesh.indices;\n const n = src.length >> 1;\n this.reserve(n, srcIdx.length);\n this.pureRects = false;\n const v = this.verts;\n let i = this.nVerts * FLOATS_PER_VERTEX;\n const ma = m[0], mb = m[1], mc = m[3], md = m[4], mtx = m[6], mty = m[7];\n for (let k = 0; k < n; k++) {\n const x = src[k * 2];\n const y = src[k * 2 + 1];\n v[i++] = ma * x + mc * y + mtx;\n v[i++] = mb * x + md * y + mty;\n v[i++] = r; v[i++] = g; v[i++] = b; v[i++] = a;\n v[i++] = WHITE_U; v[i++] = WHITE_V; v[i++] = 1; v[i++] = PLAIN_WHITE;\n }\n const base = this.nVerts;\n const out = this.idx;\n let j = this.nIdx;\n for (let k = 0; k < srcIdx.length; k++) out[j++] = base + srcIdx[k];\n this.nVerts += n;\n this.nIdx += srcIdx.length;\n return this.clip === null || this.clipMesh(base, this.nIdx - srcIdx.length, this.clip);\n }\n\n /** Upload the staged geometry into the next set of buffers and bind its VAO.\n * Returns the index count for the caller's `drawElements`. */\n uploadAndBind(): number {\n const gl = this.gl;\n const tier = BATCH_TIERS.findIndex(\n (t) => this.nVerts <= t.vertices && this.nIdx <= t.indices,\n );\n const set = tier < 0 ? this.nextLargeSlot() : this.nextRingSlot(tier);\n gl.bindVertexArray(set.vao);\n gl.bindBuffer(gl.ARRAY_BUFFER, set.vbo);\n gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.verts, 0, this.nVerts * FLOATS_PER_VERTEX);\n if (!this.pureRects) {\n gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, this.idx, 0, this.nIdx);\n set.canonicalQuads = 0;\n } else if (set.canonicalQuads < this.nVerts >> 2) {\n // Written to the slot's capacity, not this flush's length: the extra\n // costs one upload the slot never repeats.\n const quads = Math.min(set.vertexCapacity >> 2, Math.floor(set.indexCapacity / 6));\n gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, 0, quadIndices(quads));\n set.canonicalQuads = quads;\n }\n return this.nIdx;\n }\n\n reset(): void {\n this.nVerts = 0;\n this.nIdx = 0;\n this.pureRects = true;\n }\n\n dispose(): void {\n for (const set of [...this.rings.flat(), ...this.largeRing]) {\n if (set) this.deleteSet(set);\n }\n for (const ring of this.rings) ring.fill(undefined);\n this.largeRing.fill(undefined);\n }\n\n private writeVertex(\n i: number,\n x: number, y: number,\n r: number, g: number, b: number, a: number,\n u: number, v: number, post: number, packed: number,\n ): number {\n const out = this.verts;\n out[i] = x; out[i + 1] = y;\n out[i + 2] = r; out[i + 3] = g; out[i + 4] = b; out[i + 5] = a;\n out[i + 6] = u; out[i + 7] = v; out[i + 8] = post; out[i + 9] = packed;\n return i + FLOATS_PER_VERTEX;\n }\n\n /**\n * Fit the quad just written at `v0` to `rect`: keep it if it lies inside,\n * drop it if it misses, and cut it if it crosses — but only if its edges\n * run along the axes. Cutting a slanted edge moves its endpoint off the\n * subpixel grid the rasterizer snaps to, and the shortened edge then covers\n * different samples than the whole one did; along an axis the cut edge is\n * the same line exactly. So a slanted quad that crosses is rolled back and\n * refused, for `draw.ts` to clip through the stencil instead.\n *\n * A cut axis-aligned quad is still four corners, so the run stays pure.\n */\n private clipQuad(v0: number, i0: number, rect: ClipRect): boolean {\n const v = this.verts;\n const at = v0 * FLOATS_PER_VERTEX;\n const F = FLOATS_PER_VERTEX;\n const ax = v[at], ay = v[at + 1], bx = v[at + F], by = v[at + F + 1];\n const cx = v[at + 2 * F], cy = v[at + 2 * F + 1], dx = v[at + 3 * F], dy = v[at + 3 * F + 1];\n const minX = Math.min(ax, bx, cx, dx), maxX = Math.max(ax, bx, cx, dx);\n const minY = Math.min(ay, by, cy, dy), maxY = Math.max(ay, by, cy, dy);\n if (minX >= rect.x0 && maxX <= rect.x1 && minY >= rect.y0 && maxY <= rect.y1) return true;\n this.nVerts = v0;\n this.nIdx = i0;\n if (maxX <= rect.x0 || minX >= rect.x1 || maxY <= rect.y0 || minY >= rect.y1) return true;\n const alongAxes = (ay === by && bx === cx && cy === dy && dx === ax)\n || (ax === bx && by === cy && cx === dx && dy === ay);\n if (!alongAxes) return false;\n this.polyIn.set(v.subarray(at, at + 4 * F));\n const n = clipConvexPolygon(this.polyIn, 4, F, rect, this.polyOut, this.polyTmp);\n this.appendFan(this.polyOut, n);\n return true;\n }\n\n /** `clipQuad` for a mesh staged from `v0`. A mesh's edges are slanted in\n * general, so one that crosses is refused rather than cut. */\n private clipMesh(v0: number, i0: number, rect: ClipRect): boolean {\n const v = this.verts;\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (let i = v0 * FLOATS_PER_VERTEX; i < this.nVerts * FLOATS_PER_VERTEX; i += FLOATS_PER_VERTEX) {\n const x = v[i];\n const y = v[i + 1];\n if (x < minX) minX = x; if (x > maxX) maxX = x;\n if (y < minY) minY = y; if (y > maxY) maxY = y;\n }\n if (minX >= rect.x0 && maxX <= rect.x1 && minY >= rect.y0 && maxY <= rect.y1) return true;\n this.nVerts = v0;\n this.nIdx = i0;\n return maxX <= rect.x0 || minX >= rect.x1 || maxY <= rect.y0 || minY >= rect.y1;\n }\n\n /** Append the `n`-corner convex polygon in `poly` as a triangle fan. */\n private appendFan(poly: Float32Array, n: number): void {\n if (n < 3) return;\n this.reserve(n, (n - 2) * 3);\n if (n !== 4) this.pureRects = false;\n const base = this.nVerts;\n this.verts.set(poly.subarray(0, n * FLOATS_PER_VERTEX), base * FLOATS_PER_VERTEX);\n let j = this.nIdx;\n for (let k = 1; k < n - 1; k++) {\n this.idx[j++] = base; this.idx[j++] = base + k; this.idx[j++] = base + k + 1;\n }\n this.nVerts += n;\n this.nIdx = j;\n }\n\n /** Two triangles over the four corners just written. */\n private pushQuadIndices(): void {\n const base = this.nVerts;\n let j = this.nIdx;\n this.idx[j++] = base; this.idx[j++] = base + 1; this.idx[j++] = base + 2;\n this.idx[j++] = base; this.idx[j++] = base + 2; this.idx[j++] = base + 3;\n this.nVerts += 4;\n this.nIdx += 6;\n }\n\n /** Grow the CPU arrays so `vertices` / `indices` more fit. */\n private reserve(vertices: number, indices: number): void {\n const needVerts = (this.nVerts + vertices) * FLOATS_PER_VERTEX;\n if (needVerts > this.verts.length) {\n const grown = new Float32Array(doubledTo(this.verts.length, needVerts));\n grown.set(this.verts);\n this.verts = grown;\n }\n const needIdx = this.nIdx + indices;\n if (needIdx > this.idx.length) {\n const grown = new Uint32Array(doubledTo(this.idx.length, needIdx));\n grown.set(this.idx);\n this.idx = grown;\n }\n }\n\n private nextRingSlot(tier: number): BufferSet {\n const ring = this.rings[tier];\n const slot = this.nextInRing[tier];\n this.nextInRing[tier] = (slot + 1) % ring.length;\n const existing = ring[slot];\n if (existing) return existing;\n const set = this.createSet(BATCH_TIERS[tier].vertices, BATCH_TIERS[tier].indices);\n ring[slot] = set;\n return set;\n }\n\n private nextLargeSlot(): BufferSet {\n const gl = this.gl;\n const slot = this.nextLarge;\n this.nextLarge = (slot + 1) % SOLID_LARGE_RING_SIZE;\n let set = this.largeRing[slot];\n if (!set) {\n set = this.createSet(\n doubledTo(SOLID_RING_SLOT_VERTICES, this.nVerts),\n doubledTo(BATCH_TIERS[BATCH_TIERS.length - 1].indices, this.nIdx),\n );\n this.largeRing[slot] = set;\n return set;\n }\n if (this.nVerts > set.vertexCapacity) {\n set.vertexCapacity = doubledTo(set.vertexCapacity, this.nVerts);\n gl.bindBuffer(gl.ARRAY_BUFFER, set.vbo);\n gl.bufferData(gl.ARRAY_BUFFER, set.vertexCapacity * FLOATS_PER_VERTEX * 4, gl.DYNAMIC_DRAW);\n }\n if (this.nIdx > set.indexCapacity) {\n set.indexCapacity = doubledTo(set.indexCapacity, this.nIdx);\n gl.bindVertexArray(set.vao);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, set.ibo);\n gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, set.indexCapacity * 4, gl.DYNAMIC_DRAW);\n gl.bindVertexArray(null);\n // Respecified, so whatever pattern it held is gone.\n set.canonicalQuads = 0;\n }\n return set;\n }\n\n private createSet(vertices: number, indices: number): BufferSet {\n const gl = this.gl;\n const vao = gl.createVertexArray();\n const vbo = gl.createBuffer();\n const ibo = gl.createBuffer();\n if (!vao || !vbo || !ibo) throw new Error('DrawBatch: failed to create GL objects');\n const stride = FLOATS_PER_VERTEX * 4;\n gl.bindVertexArray(vao);\n gl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n gl.bufferData(gl.ARRAY_BUFFER, vertices * stride, gl.DYNAMIC_DRAW);\n gl.enableVertexAttribArray(this.aPos);\n gl.vertexAttribPointer(this.aPos, 2, gl.FLOAT, false, stride, 0);\n gl.enableVertexAttribArray(this.aColor);\n gl.vertexAttribPointer(this.aColor, 4, gl.FLOAT, false, stride, 8);\n gl.enableVertexAttribArray(this.aUv);\n gl.vertexAttribPointer(this.aUv, 2, gl.FLOAT, false, stride, 24);\n gl.enableVertexAttribArray(this.aPost);\n gl.vertexAttribPointer(this.aPost, 1, gl.FLOAT, false, stride, 32);\n gl.enableVertexAttribArray(this.aSlot);\n gl.vertexAttribPointer(this.aSlot, 1, gl.FLOAT, false, stride, 36);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);\n gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices * 4, gl.DYNAMIC_DRAW);\n gl.bindVertexArray(null);\n return { vao, vbo, ibo, vertexCapacity: vertices, indexCapacity: indices, canonicalQuads: 0 };\n }\n\n private deleteSet(set: BufferSet): void {\n const gl = this.gl;\n gl.deleteBuffer(set.vbo);\n gl.deleteBuffer(set.ibo);\n gl.deleteVertexArray(set.vao);\n }\n}\n","/**\n * imageCache — the kit's per-`src` image loader + cache.\n *\n * The shape-painter chain (`kit:image` in `NodeShape.ts`) is synchronous, but\n * decoding an image is async. This module bridges the two: `getImageBitmap` is\n * a synchronous read that returns the decoded `ImageBitmap` when ready, and\n * otherwise returns `undefined` and lazily kicks off a de-duped async load.\n * When a load resolves (or errors), every `subscribeImageReady` listener fires\n * — `<SceneCanvas>` subscribes and calls `requestRedraw()`, so the painter\n * re-runs and emits the now-ready bitmap.\n *\n * `src` is any browser-loadable image string: a remote URL, a `blob:` URL, or\n * a `data:image/…;base64,…` URI (the embedded-bytes path). The decoded bitmap\n * lives only here, keyed by `src` — never in node `data` — so `scene.toJSON()`\n * round-trips the (serializable) `src` string untouched.\n */\n\nimport { maxImageTextureSide, releaseImageSource } from '../cache/GLImageCache';\n\n/** Public shape of an image node's `data`. `src` round-trips through\n * serialization; the decoded bitmap is held in this cache, not on the node. */\nexport interface ImageNodeData {\n image: {\n src: string;\n opacity?: number;\n /** The part of the bitmap drawn into the pose rect, as fractions of the\n * bitmap's width and height from its top-left. Omitted draws the whole\n * bitmap. Fractions, so the data means the same thing before the bitmap\n * has decoded and after `src` is swapped for another resolution. */\n source?: { x: number; y: number; width: number; height: number };\n /** Mirror the drawn region within the pose rect. The rect does not move. */\n flipX?: boolean;\n flipY?: boolean;\n };\n}\n\n/** Where an image is in its load: never requested, in flight, decoded, or\n * failed. Renderers paint a placeholder for anything but `'ready'`. */\nexport type ImageStatus = 'idle' | 'loading' | 'ready' | 'error';\n\n/** A size in device pixels. */\nexport interface ImageRasterSize {\n width: number;\n height: number;\n}\n\n/** A vector source's raster bookkeeping. `scale` is the current raster's size\n * over the natural one, always a power of two unless a cap cut it short. */\ninterface VectorRaster {\n natural: ImageRasterSize;\n scale: number;\n pending?: number;\n failed: Set<number>;\n /** The scale the last shrink left, until something asks for more. */\n shrunkTo?: number;\n /** The largest scale a shrunk raster was asked to grow back to. One raster\n * serves every size a source is drawn at, so that request may be a second\n * consumer the shrink starved; shrinking below it again would loop. */\n floor: number;\n}\n\ninterface Entry {\n status: ImageStatus;\n bitmap?: ImageBitmap;\n vector?: VectorRaster;\n}\n\n/** `size` is absent for the first load, which decodes at natural size. */\ntype Loader = (src: string, size?: ImageRasterSize) => Promise<ImageBitmap>;\n\n/** One vector raster may hold at most 64MB of RGBA. */\nconst MAX_VECTOR_RASTER_PIXELS = 4096 * 4096;\n/** A raster is only shrunk once it is this many times larger than needed, so\n * zooming back and forth across a bucket edge does not re-raster each way. */\nconst SHRINK_SLACK = 4;\n// CSS default object size, as `kit:svg` measures a viewBox-only SVG.\nconst FALLBACK_WIDTH = 300;\nconst FALLBACK_HEIGHT = 150;\n\nconst cache = new Map<string, Entry>();\nconst subscribers = new Set<() => void>();\nconst decodedVectors = new Map<string, Promise<HTMLImageElement>>();\n\n/** True when `src` names SVG — a `data:image/svg+xml` URI, or a URL whose path\n * ends in `.svg`/`.svgz`. Such sources re-rasterize at the size they are drawn\n * at; everything else decodes once. A `blob:` URL carries no type and counts\n * as raster. */\nexport function isVectorImageSrc(src: string): boolean {\n if (/^data:image\\/svg\\+xml[;,]/i.test(src)) return true;\n if (/^(data|blob):/i.test(src)) return false;\n return /\\.svgz?$/i.test(src.replace(/[?#].*$/, ''));\n}\n\nfunction requireDom(): void {\n if (typeof Image === 'undefined' || typeof createImageBitmap === 'undefined') {\n throw new Error('weasel imageCache: no DOM image loader in this environment');\n }\n}\n\nasync function decodeImage(src: string): Promise<HTMLImageElement> {\n const img = new Image();\n img.crossOrigin = 'anonymous';\n img.src = src;\n await img.decode();\n return img;\n}\n\nfunction decodeVector(src: string): Promise<HTMLImageElement> {\n let decoded = decodedVectors.get(src);\n if (!decoded) {\n decoded = decodeImage(src);\n decodedVectors.set(src, decoded);\n decoded.catch(() => decodedVectors.delete(src));\n }\n return decoded;\n}\n\n// `createImageBitmap` rejects SVG blobs and resamples an SVG `<img>` rather\n// than re-drawing it, so vectors go through a canvas `drawImage` at full size.\nasync function rasterizeVector(src: string, size?: ImageRasterSize): Promise<ImageBitmap> {\n const img = await decodeVector(src);\n const width = size?.width ?? (img.naturalWidth || FALLBACK_WIDTH);\n const height = size?.height ?? (img.naturalHeight || FALLBACK_HEIGHT);\n const canvas: OffscreenCanvas | HTMLCanvasElement = typeof OffscreenCanvas !== 'undefined'\n ? new OffscreenCanvas(width, height)\n : Object.assign(document.createElement('canvas'), { width, height });\n const c2d = canvas.getContext('2d') as CanvasDrawImage | null;\n if (!c2d) throw new Error('weasel imageCache: no 2D context to rasterize an SVG');\n c2d.drawImage(img, 0, 0, width, height);\n return createImageBitmap(canvas);\n}\n\nconst defaultLoader: Loader = async (src, size) => {\n requireDom();\n if (isVectorImageSrc(src)) return rasterizeVector(src, size);\n return createImageBitmap(await decodeImage(src));\n};\n\nlet loader: Loader = defaultLoader;\n\nfunction notify(): void {\n for (const cb of subscribers) cb();\n}\n\nfunction startLoad(src: string): void {\n const entry: Entry = { status: 'loading' };\n cache.set(src, entry);\n loader(src).then(\n (bitmap) => {\n // The entry may have been replaced/cleared mid-flight (reset, etc.);\n // only commit if this src is still the one we started loading.\n if (cache.get(src) !== entry) return;\n cache.set(src, {\n status: 'ready',\n bitmap,\n ...(isVectorImageSrc(src)\n ? { vector: { natural: { width: bitmap.width, height: bitmap.height }, scale: 1, failed: new Set<number>(), floor: 0 } }\n : {}),\n });\n notify();\n },\n () => {\n // Cache the error so a broken `src` doesn't reload-storm.\n if (cache.get(src) !== entry) return;\n cache.set(src, { status: 'error' });\n notify();\n },\n );\n}\n\n/** The raster scale `drawnAt` calls for: the next power of two at or above the\n * natural-to-drawn ratio, capped by texture size and the pixel ceiling. */\nfunction rasterScaleFor(natural: ImageRasterSize, drawnAt: ImageRasterSize): number | undefined {\n const need = Math.max(drawnAt.width / natural.width, drawnAt.height / natural.height);\n if (!(need > 0) || !Number.isFinite(need)) return undefined;\n const side = maxImageTextureSide();\n const cap = Math.min(\n side / natural.width,\n side / natural.height,\n Math.sqrt(MAX_VECTOR_RASTER_PIXELS / (natural.width * natural.height)),\n );\n return Math.min(2 ** Math.ceil(Math.log2(need)), cap);\n}\n\nfunction maybeReraster(src: string, entry: Entry, v: VectorRaster, drawnAt: ImageRasterSize): void {\n if (v.pending !== undefined) return;\n const wanted = rasterScaleFor(v.natural, drawnAt);\n if (wanted === undefined) return;\n const grow = wanted > v.scale;\n if (grow && v.shrunkTo === v.scale) v.floor = Math.max(v.floor, wanted);\n const target = grow ? wanted : Math.max(wanted, v.floor);\n if (!grow && target * SHRINK_SLACK > v.scale) return;\n for (const f of v.failed) if (target === f || (grow && f > v.scale && target >= f)) return;\n\n v.pending = target;\n const size = {\n width: Math.max(1, Math.round(v.natural.width * target)),\n height: Math.max(1, Math.round(v.natural.height * target)),\n };\n loader(src, size).then(\n (bitmap) => {\n if (cache.get(src) !== entry) return;\n v.pending = undefined;\n const old = entry.bitmap;\n entry.bitmap = bitmap;\n v.shrunkTo = grow ? undefined : target;\n v.scale = target;\n if (old && old !== bitmap) releaseImageSource(old);\n notify();\n },\n () => {\n // The previous raster keeps painting; only this scale is given up on.\n if (cache.get(src) !== entry) return;\n v.pending = undefined;\n v.failed.add(target);\n },\n );\n}\n\n/** Synchronous read. Returns the decoded bitmap when ready; otherwise returns\n * `undefined` and lazily starts a de-duped async load for `src`.\n *\n * `drawnAt` is the size in device pixels the image is about to cover. A\n * vector source ({@link isVectorImageSrc}) uses it to re-rasterize in\n * power-of-two steps — the current raster is returned until the sharper one\n * is ready. Raster sources ignore it. */\nexport function getImageBitmap(src: string, drawnAt?: ImageRasterSize): ImageBitmap | undefined {\n const entry = cache.get(src);\n if (!entry) {\n startLoad(src);\n return undefined;\n }\n if (drawnAt && entry.vector) maybeReraster(src, entry, entry.vector, drawnAt);\n return entry.bitmap;\n}\n\n/** Current load status for `src` (`'idle'` if never requested). */\nexport function imageStatus(src: string): ImageStatus {\n return cache.get(src)?.status ?? 'idle';\n}\n\n/**\n * Forget `src`: drop its decoded bitmap, its decoded SVG, and the texture every\n * live renderer holds for it, and abandon a load in flight. The cache is keyed\n * by `src` across every scene on the page, so it cannot know when the last use\n * is gone; whoever does know calls this. A later {@link getImageBitmap} for the\n * same `src` loads it again.\n */\nexport function releaseImage(src: string): void {\n const entry = cache.get(src);\n cache.delete(src);\n decodedVectors.delete(src);\n if (entry?.bitmap) releaseImageSource(entry.bitmap);\n}\n\n/** Load a `src` whose last load failed again. Does nothing for a `src` in any\n * other state; one that failed otherwise stays `'error'` for the page's life. */\nexport function retryImage(src: string): void {\n if (cache.get(src)?.status !== 'error') return;\n startLoad(src);\n notify();\n}\n\n/** Subscribe to load-resolution events (fires after any `src` resolves or\n * errors). Returns an unsubscribe. */\nexport function subscribeImageReady(cb: () => void): () => void {\n subscribers.add(cb);\n return () => {\n subscribers.delete(cb);\n };\n}\n\n/** @internal test seam — override the async loader so unit tests don't need\n * a real DOM image. Not part of the public barrel. */\nexport function __setImageLoaderForTests(fn: Loader): void {\n loader = fn;\n}\n\n/** @internal test seam — clear cache + subscribers and restore the default\n * loader. Not part of the public barrel. */\nexport function _resetImageCacheForTests(): void {\n cache.clear();\n subscribers.clear();\n decodedVectors.clear();\n loader = defaultLoader;\n}\n"]}
|