@weasel-js/core 1.7.3 → 1.8.1

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/dist/animation/colorHelpers.js +58 -58
  3. package/dist/animation/colorHelpers.js.map +1 -1
  4. package/dist/animation/engine/axes.js +36 -0
  5. package/dist/animation/engine/axes.js.map +1 -0
  6. package/dist/animation/engine/codec.js +170 -0
  7. package/dist/animation/engine/codec.js.map +1 -0
  8. package/dist/animation/engine/integrator.js +12 -0
  9. package/dist/animation/engine/integrator.js.map +1 -0
  10. package/dist/animation/useAnimator.js +209 -160
  11. package/dist/animation/useAnimator.js.map +1 -1
  12. package/dist/{builtins-C-gRyVRx.d.ts → builtins-CMEh6-Oc.d.ts} +81 -8
  13. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +12 -12
  14. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  15. package/dist/canvas/pickWalk.js +2 -2
  16. package/dist/canvas/pickWalk.js.map +1 -1
  17. package/dist/canvas/sceneSlotWiring.js +1 -1
  18. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  19. package/dist/canvas/sceneViewRender.js +1 -1
  20. package/dist/canvas/sceneViewRender.js.map +1 -1
  21. package/dist/core/scene/effectivePose.js +1 -1
  22. package/dist/core/scene/effectivePose.js.map +1 -1
  23. package/dist/core/scene/poseOverrides.js +42 -22
  24. package/dist/core/scene/poseOverrides.js.map +1 -1
  25. package/dist/core/scene/scene.js +9 -0
  26. package/dist/core/scene/scene.js.map +1 -1
  27. package/dist/core/scene/types.js.map +1 -1
  28. package/dist/core/selection/useSelection.js +27 -33
  29. package/dist/core/selection/useSelection.js.map +1 -1
  30. package/dist/core/stableStringify.js +8 -0
  31. package/dist/core/stableStringify.js.map +1 -0
  32. package/dist/index.d.ts +35 -25
  33. package/dist/index.js +269 -268
  34. package/dist/renderer/WeaselRenderer.js +4 -1
  35. package/dist/renderer/WeaselRenderer.js.map +1 -1
  36. package/dist/renderer/batchClip.js +46 -0
  37. package/dist/renderer/batchClip.js.map +1 -0
  38. package/dist/renderer/draw.js +367 -294
  39. package/dist/renderer/draw.js.map +1 -1
  40. package/dist/renderer/drawBatch.js +75 -45
  41. package/dist/renderer/drawBatch.js.map +1 -1
  42. package/dist/renderer/shaders/batchFill.js +3 -2
  43. package/dist/renderer/shaders/batchFill.js.map +1 -1
  44. package/dist/renderer.d.ts +1 -1
  45. package/dist/tools/builtin/text/useTextTool.js +8 -8
  46. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  47. package/dist/tools/prefs.js.map +1 -1
  48. package/dist/version.js +1 -1
  49. package/package.json +17 -15
@@ -1 +1 @@
1
- {"version":3,"file":"draw.js","names":["drawTriangles","ctx","count","type","FRAME_UPLOADS","FRAME_PROJ","uploadedFor","byProgram","uploaded","prog","sameValues","prev","next","i","setColorUniform","loc","r","g","b","setAlphaUniform","alpha","BATCH_MODEL","mat3","projFor","proj","COLOR_MATRIX_SCRATCH","setColorMatrixUniforms","gl","mLoc","row","col","cm","bLoc","bias","fillMesh","getMesh","path","tessellate","meshHandle","mesh","fillMeshHandle","dispatch","cmd","drawGroup","drawPath","drawText","drawImage","drawSprites","flushBatch","drawShader","warnedUniforms","warnOnceUniform","key","programId","name","setUniform","value","handle","entry","getTexture","unit","textureCache","arr","ARRAY_UPLOADS","isArrayValue","setUniformArray","isDev","upload","fn","setUniforms","uniforms","program","nextTexUnit","programRegistry","quadVbo","quadIbo","aPosLoc","aUvLoc","uProj","uBounds","uView","applyClipTest","drawGroupWithEffects","parentTarget","parentClipDepth","scissorWasOn","front","targets","width","height","composited","child","effect","back","drawFullscreenQuad","returnToRenderTarget","composite","COMPOSITE_PROGRAM_ID","target","aPos","aUv","texture","source","resolution","texel","newDepth","pushClip","popClip","drawPathFill","drawPathStroke","fill","isSolid","hasVColors","solid","paint","batchPaint","pushRampRect","pushRect","tryStageFill","drawPathFillVColor","drawPathFillStencil","drawPathFillByKind","SAMPLER_UNITS","BATCH_TEXTURE_SLOTS","FIELD_SCALES","isIdentityColorMatrix","IDENTITY_COLOR_MATRIX","stagedStateIsLive","staged","synthBold","image","slotForBitmap","sampling","colorMatrix","nextFreeSlot","slotForRamps","slotForAtlas","id","MAX_BATCHED_MESH_VERTICES","canBatchMesh","stageSolid","vertices","openRun","foldsAlpha","stageImage","slot","stageGlyphs","atlasId","stageRamps","stops","space","stagedAlpha","opacity","stagedColor","a","resolveColor","rect","pushMesh","kind","grad","gradientMap","ramp","PAINT_MODE_PLAIN","linearRampUV","PAINT_MODE_RADIAL","radialRampUV","PAINT_MODE_CONIC","conicRampUV","inverse","gradientSpaceInverse","units","dx","dy","len","k","cos","sin","dx0","dy0","rampVertices","rowV","uv","post","pushRampMesh","batch","indexCount","setProjAndModel","expandAnchorColors","aA","aB","aT","perAnchor","n","out","a4","b4","t","setSolidPaintUniforms","expanded","colorVbo","aVColorLoc","model","color","bindPathFillByKind","bindPathFillSolid","bindPathFillPattern","bindPathFillGradient","bind","getPaintKind","paintBindContext","cached","BIND_CONTEXTS","made","spaceToDevice","unownedPaintResources","UNOWNED_RESOURCES","createPaintResources","bindPattern","tex","tileSpace","patternTileSpace","tw","th","textureSize","w","h","toScreen","ratio","bindGradient","depth","mask","ancestorMask","rasterizePathToStencil","ancestors","newBit","ref","oldBit","oldDepth","clipMask","withResolvedStrokeLengths","stroke","isPxMarker","markerStart","markerMid","markerEnd","scale","resolved","resolveStrokeWidth","quantizeStrokeScale","resolvedMarker","resolveMarkerSize","rawCmd","align","drawPathStrokeStenciled","drawPathStrokeUnclipped","marker","cachedMarkerCommands","strokeMesh","batched","DOUBLED_VERTEX_WIDTHS","doubledVertexWidths","doubled","widths","widerStroke","useVColor","fillHandle","ribbonMesh","ribbonHandle","ribbonProg","OUTLINE_MIN_SCREEN_PX","modelScale","sx","m","sy","style","resolveTextStyle","lineHeight","maxWidth","minScreen","outlineMinSize","laid","cachedLayoutRuns","verticalAlignOffset","group","drawTextOutlineGroup","drawTextGroup","outlineGroupMesh","drawOutlineMesh","strokePaint","ribbon","outlineGroupStrokeMesh","mergeGlyphMeshes","outlineMesh","glyph","outlineStrokeMesh","quantizeEmWidth","parts","vertexFloats","meshFor","shear","SYNTHETIC_ITALIC_RADIANS","indices","vi","ii","base","ex","ey","x","baselineY","drawTextDecorations","d","decorations","glyphPaintKindOf","ruleMesh","x0","y0","x1","y1","SYNTH_BOLD_AMOUNT","syncDynamicPageTexture","ensureFontTexture","dynamicPageTextureId","textureCacheKey","mode","GLYPH_MODE_R8","GLYPH_MODE_MSDF","fieldScale","glyphFieldScale","bold","tanItalic","paintKind","q","GLYPH_PAINT_ATLAS_UNIT","drawPaintedGlyphs","bound","painted","renderPaintToScratch","glyphScreenBounds","bindScratchPaint","drawStagedGlyphs","add","y","top","bottom","UNIT_QUAD","scratch","deviceW","deviceH","px0","py0","maxSide","pw","ph","bindCtx","src","u0","v0","u1","v1","data","SPRITE_STRIDE","groupAlpha","s","sw","sh"],"sources":["../../src/renderer/draw.ts"],"sourcesContent":["import type { ColorSpace, Stroke, FillStyle, GradientUnits, GradStop, MarkerRef } from '@weasel-js/paint';\nimport type { Path } from '@weasel-js/core';\nimport { getPaintKind } from 'core/paintKinds';\nimport type { PaintBindContext, PaintResources } from 'core/paintKinds';\nimport { createPaintResources } from './paintResources';\nimport { resolveTextStyle } from '@weasel-js/text';\nimport type {\n DrawCommand,\n GroupDrawCommand,\n PathDrawCommand,\n TextDrawCommand,\n ImageDrawCommand,\n SpritesDrawCommand,\n ShaderDrawCommand,\n} from './DrawCommand';\nimport { SPRITE_STRIDE } from './DrawCommand';\nimport { getTexture, type TextureHandle } from './textures/registerTexture';\nimport type { ShaderUniform } from './shaders/registerProgram';\nimport { IDENTITY_COLOR_MATRIX, type GroupState } from './state/GroupState';\nimport type { GLMeshCache, GLMeshHandle } from './cache/GLMeshCache';\nimport type { GLTextureCache } from './cache/GLTextureCache';\nimport type { GLImageCache } from './cache/GLImageCache';\nimport type { GradientRampAtlas } from './cache/GradientRampAtlas';\nimport type { ShaderProgram, UniformArray } from './shaders/ShaderProgram';\nimport { mat3, type GlMat3 } from './math/mat3';\nimport { patternTileSpace } from './math/patternSpace';\nimport { getMesh } from './cache/cache';\nimport { tessellate, type Mesh } from '@weasel-js/geom/tessellate';\nimport { resolveStrokeWidth } from 'features/paths/tessellate/stroke';\nimport { resolveColor } from './math/color';\nimport {\n ensureFontTexture,\n textureCacheKey,\n syncDynamicPageTexture,\n dynamicPageTextureId,\n GLYPH_MODE_MSDF,\n GLYPH_MODE_R8,\n glyphFieldScale,\n} from '@weasel-js/font';\nimport {\n type LaidOutGroup, type LaidOutDecoration, type LaidOutOutlineGlyph,\n} from '@weasel-js/text';\nimport { verticalAlignOffset, cachedLayoutRuns } from '@weasel-js/text';\nimport { outlineMesh } from './cache/outlineMeshCache';\nimport { outlineStrokeMesh, quantizeEmWidth } from './cache/outlineStrokeMeshCache';\nimport { strokeMesh, quantizeStrokeScale } from './cache/strokeMeshCache';\nimport { cachedMarkerCommands } from './cache/markerCommandCache';\nimport { resolveMarkerSize } from '../core/markerInset';\nimport { DrawBatch, type GradientUV } from './drawBatch';\nimport {\n BATCH_TEXTURE_SLOTS, PAINT_MODE_PLAIN, PAINT_MODE_RADIAL, PAINT_MODE_CONIC,\n} from './shaders/batchFill';\nimport type { EffectTarget, EffectTargets } from './effects/EffectTargets';\nimport type { PaintScratch } from './paintScratch';\nimport { COMPOSITE_PROGRAM_ID } from './effects/composite';\nimport { SYNTHETIC_ITALIC_RADIANS } from './syntheticItalic';\n\nexport interface DrawContext {\n gl: WebGL2RenderingContext;\n pathFill: ShaderProgram;\n pathFillVColor: ShaderProgram;\n imageFill: ShaderProgram;\n /** The one program a batch flush draws with — `shaders/batchFill.ts`. */\n batchFill: ShaderProgram;\n gradFill: ShaderProgram;\n patternFill: ShaderProgram;\n meshCache: GLMeshCache;\n textureCache: GLTextureCache;\n imageCache: GLImageCache;\n gradRamps: GradientRampAtlas;\n programRegistry: Map<string, ShaderProgram>;\n /** Compile-on-first-use for a registered paint kind's program. Absent when\n * a caller drives `dispatch` without a renderer behind it. */\n ensureProgram?(id: string): ShaderProgram | null;\n /** The program atlas glyphs under a texture paint draw with, compiled on\n * first use. Absent without a renderer behind the context, and then such\n * glyphs draw nothing. */\n glyphPaintProgram?(kind: GlyphPaintKind): ShaderProgram;\n quadVbo: WebGLBuffer | null;\n quadIbo: WebGLBuffer | null;\n /** Staging for the batch. Draws are deferred into it, so a caller driving\n * `dispatch` itself must `flushBatch` when the stream ends. */\n drawBatch: DrawBatch;\n /** Group state the staged run was built under, and what it samples;\n * `undefined` while nothing is staged. Written only by the push helpers\n * and `flushBatch`. */\n batchState?: StagedBatchState;\n /** 1x1 white texture, bound for a flush that samples no image so a solid\n * vertex's `texture() * color` is its color. */\n whiteTexture: WebGLTexture | null;\n state: GroupState;\n widthCss: number;\n heightCss: number;\n /**\n * Current clip nesting depth. Tracked as a flat scalar on DrawContext (not\n * part of GroupState's per-frame stack) because it must survive pop() during\n * drawGroup teardown — we decrement it manually after popClip. Starts at 0;\n * incremented/decremented symmetrically by drawGroup around cmd.clip pushes.\n */\n clipDepth: number;\n /** Flatness tolerance for curve tessellation, in WORLD units. When set,\n * fill meshes bypass the Path-identity cache (whose key excludes\n * tolerance) and are tessellated fresh per frame via the transient pool.\n * See `WeaselRendererOptions.flattenTolerance`. */\n flattenTolerance?: number;\n /** On-screen glyph size (CSS px) at which text switches to tessellated\n * outlines. See `WeaselRendererOptions.textOutlineMinScreenSize`. */\n textOutlineMinScreenSize?: number;\n /** World→screen transform for the frame, when the caller supplied one.\n * Only `units: 'world'` gradients read it; absent, they fall back to\n * screen space. See `WeaselRenderer.render`. */\n viewMatrix?: GlMat3;\n /** Offscreen buffers for group effects. Absent when a caller drives\n * `dispatch` without a renderer behind it, in which case a group's\n * `effects` are skipped and its children draw straight through — the same\n * answer an unregistered effect program gets, and the one that keeps a\n * frame on screen. */\n effectTargets?: EffectTargets;\n /** Where this renderer is currently drawing. `null` is the default\n * framebuffer. Tracked here rather than read back with `getParameter`\n * because a group's effects nest, and each has to restore its parent's. */\n renderTarget?: EffectTarget | null;\n /** Device-pixel size of the drawing buffer, which is what an offscreen\n * target is sized to. */\n deviceWidth?: number;\n deviceHeight?: number;\n /** Put the viewport and scissor back to the renderer's own rect after a\n * group's effects have borrowed them for a full-buffer pass. The renderer\n * owns that rect — see `WeaselRenderer.applyTarget` — and a second copy of\n * its y-flip here would be a second thing to keep in step. */\n restoreTargetRect?(): void;\n /** Where a registered paint kind renders for atlas glyphs to sample. Absent\n * without a renderer behind the context, and then such glyphs draw\n * nothing. */\n paintScratch?: PaintScratch;\n /** The lifetime a registered paint kind's GPU state belongs to. Absent\n * when a caller drives `dispatch` without a renderer behind it, in which\n * case one per context stands in and is never released. */\n paintResources?: PaintResources;\n /** Per-frame counters the renderer reads back after the stream ends.\n * Absent, nothing is counted. */\n stats?: { drawCalls: number };\n}\n\n/** The paints atlas glyphs draw through a program of their own: `texture` is\n * a registered kind, which renders into `paintScratch` for the glyphs to\n * sample. */\nexport type GlyphPaintKind = 'pattern' | 'gradient' | 'texture';\n\n/** Every GL draw the renderer issues goes through here, so the frame's\n * draw-call count cannot miss one. */\nfunction drawTriangles(ctx: DrawContext, count: number, type: number): void {\n ctx.gl.drawElements(ctx.gl.TRIANGLES, count, type, 0);\n if (ctx.stats) ctx.stats.drawCalls++;\n}\n\n/**\n * Upload the cumulative color matrix from GroupState to a shader's\n * `u_colorMatrix` (mat4) and `u_colorBias` (vec4) uniforms. Splits the 4×5\n * row-major form into a column-major mat4 + vec4 bias. Used by every shader\n * that accepts the group color matrix: pathFill, pathFillVColor, imageFill,\n * batchFill.\n */\n/**\n * Uniform values a program already holds this frame.\n *\n * GL keeps uniform state per program object, so re-sending a value the program\n * already has buys nothing. `u_proj` is constant for the whole frame and\n * `u_colorMatrix` is the identity in every scene that does not use one, yet\n * both were re-sent for every command: at a few thousand commands the two were\n * most of the frame.\n *\n * Keyed on the `DrawContext`, which `WeaselRenderer.render` builds fresh per\n * frame, so the cache cannot outlive a frame and go stale against GL state\n * that changed between them.\n *\n * **Only for uniforms this module is the sole writer of.** `u_color` and\n * `u_alpha` qualify because every write of them goes through `setColorUniform`\n * / `setAlphaUniform` — keep it that way. A `gl.uniform4f(… 'u_color' …)` added\n * anywhere else leaves the cache believing a value the program no longer has,\n * and the wrong color is drawn until something else moves it.\n */\ninterface UploadedUniforms {\n proj?: Float32Array;\n model?: Float32Array;\n colorMatrix?: Float32Array;\n colorBias?: Float32Array;\n /** Held as plain numbers, not a `Float32Array`: the caller's values are\n * doubles, and round-tripping them through float32 would compare unequal\n * every time and never skip an upload. */\n color?: [number, number, number, number];\n alpha?: number;\n}\n\nconst FRAME_UPLOADS = new WeakMap<DrawContext, WeakMap<ShaderProgram, UploadedUniforms>>();\nconst FRAME_PROJ = new WeakMap<DrawContext, GlMat3>();\n\nfunction uploadedFor(ctx: DrawContext, prog: ShaderProgram): UploadedUniforms {\n let byProgram = FRAME_UPLOADS.get(ctx);\n if (!byProgram) {\n byProgram = new WeakMap();\n FRAME_UPLOADS.set(ctx, byProgram);\n }\n let uploaded = byProgram.get(prog);\n if (!uploaded) {\n uploaded = {};\n byProgram.set(prog, uploaded);\n }\n return uploaded;\n}\n\n/** Element-wise, so a caller that mutates a shared array in place is still\n * compared by value. A NaN anywhere compares unequal and re-uploads, which is\n * the safe direction. */\nfunction sameValues(prev: Float32Array | undefined, next: ArrayLike<number>): boolean {\n if (prev === undefined || prev.length !== next.length) return false;\n for (let i = 0; i < prev.length; i++) if (prev[i] !== next[i]) return false;\n return true;\n}\n\n/**\n * `u_color`, skipped when the program already holds it.\n *\n * Every writer of `u_color` goes through here — see `UploadedUniforms`. The\n * solid batch is what makes it worth caching: it holds the uniform at white\n * forever and flushed once per state change, so a mixed document re-sent the\n * same white a few hundred times a frame.\n */\nfunction setColorUniform(\n ctx: DrawContext, prog: ShaderProgram,\n r: number, g: number, b: number, a: number,\n): void {\n const loc = prog.uniform('u_color');\n if (loc === undefined) return;\n const uploaded = uploadedFor(ctx, prog);\n const prev = uploaded.color;\n if (prev !== undefined && prev[0] === r && prev[1] === g && prev[2] === b && prev[3] === a) {\n return;\n }\n ctx.gl.uniform4f(loc, r, g, b, a);\n uploaded.color = [r, g, b, a];\n}\n\n/** `u_alpha`, on the same terms as `setColorUniform`. */\nfunction setAlphaUniform(ctx: DrawContext, prog: ShaderProgram, alpha: number): void {\n const loc = prog.uniform('u_alpha');\n if (loc === undefined) return;\n const uploaded = uploadedFor(ctx, prog);\n if (uploaded.alpha === alpha) return;\n ctx.gl.uniform1f(loc, alpha);\n uploaded.alpha = alpha;\n}\n\n/** The rect batch transforms its own corners, so it draws at model identity. */\nconst BATCH_MODEL = mat3.identity();\n\n/** The screen→clip matrix depends only on the frame's dimensions. */\nfunction projFor(ctx: DrawContext): GlMat3 {\n let proj = FRAME_PROJ.get(ctx);\n if (!proj) {\n proj = mat3.screenToClip(ctx.widthCss, ctx.heightCss);\n FRAME_PROJ.set(ctx, proj);\n }\n return proj;\n}\n\n/** Reused across draws: the transpose below rebuilt this every command. */\nconst COLOR_MATRIX_SCRATCH = new Float32Array(16);\n\nfunction setColorMatrixUniforms(\n ctx: DrawContext, prog: ShaderProgram,\n cm: Float32Array = ctx.state.colorMatrix, // row-major 4×5\n): void {\n const gl = ctx.gl;\n const uploaded = uploadedFor(ctx, prog);\n\n const mLoc = prog.uniform('u_colorMatrix');\n if (mLoc !== undefined) {\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n COLOR_MATRIX_SCRATCH[col * 4 + row] = cm[row * 5 + col];\n }\n }\n if (!sameValues(uploaded.colorMatrix, COLOR_MATRIX_SCRATCH)) {\n gl.uniformMatrix4fv(mLoc, false, COLOR_MATRIX_SCRATCH);\n uploaded.colorMatrix = Float32Array.from(COLOR_MATRIX_SCRATCH);\n }\n }\n\n const bLoc = prog.uniform('u_colorBias');\n if (bLoc !== undefined) {\n const bias = [cm[4], cm[9], cm[14], cm[19]];\n if (!sameValues(uploaded.colorBias, bias)) {\n gl.uniform4f(bLoc, bias[0], bias[1], bias[2], bias[3]);\n uploaded.colorBias = Float32Array.from(bias);\n }\n }\n}\n\n/**\n * Tessellate a fill honoring ctx.flattenTolerance: default route is the\n * persistent Path-identity cache; a custom tolerance tessellates fresh, because\n * the persistent cache's key does not include tolerance.\n */\nfunction fillMesh(ctx: DrawContext, path: Path): Mesh {\n if (ctx.flattenTolerance !== undefined) {\n return tessellate(path, { flattenTolerance: ctx.flattenTolerance });\n }\n return getMesh(path);\n}\n\n/** Upload a mesh for its own draw. A freshly tessellated one rides the\n * transient pool, freed at end of frame. */\nfunction meshHandle(ctx: DrawContext, mesh: Mesh): GLMeshHandle {\n if (ctx.flattenTolerance !== undefined) return ctx.meshCache.uploadTransient(mesh);\n return ctx.meshCache.handleFor(mesh);\n}\n\nfunction fillMeshHandle(ctx: DrawContext, path: Path): GLMeshHandle {\n return meshHandle(ctx, fillMesh(ctx, path));\n}\n\nexport function dispatch(ctx: DrawContext, cmd: DrawCommand): void {\n switch (cmd.kind) {\n case 'group': return drawGroup(ctx, cmd);\n case 'path': return drawPath(ctx, cmd);\n case 'text': return drawText(ctx, cmd);\n case 'image': return drawImage(ctx, cmd);\n case 'sprites': return drawSprites(ctx, cmd);\n case 'shader': flushBatch(ctx); return drawShader(ctx, cmd);\n }\n}\n\nconst warnedUniforms = new Set<string>();\nfunction warnOnceUniform(programId: string, name: string): void {\n const key = `${programId}:${name}`;\n if (warnedUniforms.has(key)) return;\n warnedUniforms.add(key);\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n if (isDev) {\n console.warn(`weasel drawShader: uniform \"${name}\" not found in program \"${programId}\". ` +\n `Check spelling, ensure it's used in the shader (unused uniforms are optimized away by the driver).`);\n }\n}\n\n/**\n * Bind a single ShaderUniform value to a GL uniform location.\n *\n * Type detection order:\n * 1. TextureHandle (object with string `.id`) — bind to next tex unit, set sampler.\n * 2. Float32Array — length 9 → mat3, length 16 → mat4. Other lengths throw in dev.\n * 3. Array — uniform2fv / uniform3fv / uniform4fv based on length.\n * 4. number — uniform1f.\n */\nexport function setUniform(\n gl: WebGL2RenderingContext,\n loc: WebGLUniformLocation,\n value: ShaderUniform,\n textureCache: GLTextureCache,\n nextTexUnit: { value: number },\n): void {\n if (value !== null && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Float32Array)\n && 'id' in value && typeof (value as TextureHandle).id === 'string') {\n const handle = value as TextureHandle;\n const entry = getTexture(handle.id);\n if (!entry) {\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n if (isDev) console.warn(`weasel setUniform: TextureHandle \"${handle.id}\" not registered`);\n return;\n }\n const unit = nextTexUnit.value++;\n textureCache.upload(handle.id, entry.source);\n textureCache.bind(handle.id, unit);\n gl.uniform1i(loc, unit);\n return;\n }\n\n if (value instanceof Float32Array) {\n if (value.length === 9) {\n gl.uniformMatrix3fv(loc, false, value);\n } else if (value.length === 16) {\n gl.uniformMatrix4fv(loc, false, value);\n } else {\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n if (isDev) throw new TypeError(`weasel setUniform: Float32Array must be length 9 (mat3) or 16 (mat4), got ${value.length}`);\n }\n return;\n }\n\n if (Array.isArray(value)) {\n const arr = value as readonly number[];\n switch (arr.length) {\n case 2: gl.uniform2fv(loc, arr as [number, number]); break;\n case 3: gl.uniform3fv(loc, arr as [number, number, number]); break;\n case 4: gl.uniform4fv(loc, arr as [number, number, number, number]); break;\n default: {\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n if (isDev) throw new TypeError(`weasel setUniform: array length ${arr.length} not supported`);\n }\n }\n return;\n }\n\n if (typeof value === 'number') {\n gl.uniform1f(loc, value);\n return;\n }\n}\n\n/** How an array's element type is uploaded: the `uniform*v` call and the\n * number of components per element. */\nconst ARRAY_UPLOADS: Readonly<Record<string, { fn: string; n: number; matrix?: true }>> = {\n float: { fn: 'uniform1fv', n: 1 }, vec2: { fn: 'uniform2fv', n: 2 },\n vec3: { fn: 'uniform3fv', n: 3 }, vec4: { fn: 'uniform4fv', n: 4 },\n int: { fn: 'uniform1iv', n: 1 }, ivec2: { fn: 'uniform2iv', n: 2 },\n ivec3: { fn: 'uniform3iv', n: 3 }, ivec4: { fn: 'uniform4iv', n: 4 },\n bool: { fn: 'uniform1iv', n: 1 }, bvec2: { fn: 'uniform2iv', n: 2 },\n bvec3: { fn: 'uniform3iv', n: 3 }, bvec4: { fn: 'uniform4iv', n: 4 },\n uint: { fn: 'uniform1uiv', n: 1 }, uvec2: { fn: 'uniform2uiv', n: 2 },\n uvec3: { fn: 'uniform3uiv', n: 3 }, uvec4: { fn: 'uniform4uiv', n: 4 },\n mat2: { fn: 'uniformMatrix2fv', n: 4, matrix: true },\n mat3: { fn: 'uniformMatrix3fv', n: 9, matrix: true },\n mat4: { fn: 'uniformMatrix4fv', n: 16, matrix: true },\n mat2x2: { fn: 'uniformMatrix2fv', n: 4, matrix: true },\n mat3x3: { fn: 'uniformMatrix3fv', n: 9, matrix: true },\n mat4x4: { fn: 'uniformMatrix4fv', n: 16, matrix: true },\n mat2x3: { fn: 'uniformMatrix2x3fv', n: 6, matrix: true },\n mat2x4: { fn: 'uniformMatrix2x4fv', n: 8, matrix: true },\n mat3x2: { fn: 'uniformMatrix3x2fv', n: 6, matrix: true },\n mat3x4: { fn: 'uniformMatrix3x4fv', n: 12, matrix: true },\n mat4x2: { fn: 'uniformMatrix4x2fv', n: 8, matrix: true },\n mat4x3: { fn: 'uniformMatrix4x3fv', n: 12, matrix: true },\n};\n\ntype ArrayValue = readonly number[] | Float32Array | Int32Array | Uint32Array;\n\nfunction isArrayValue(value: ShaderUniform): value is ArrayValue {\n return Array.isArray(value) || value instanceof Float32Array\n || value instanceof Int32Array || value instanceof Uint32Array;\n}\n\n/** Fill an array uniform from slot 0 with one call. Throws in dev on a value\n * that is not a whole number of elements or overruns the declaration. */\nfunction setUniformArray(\n gl: WebGL2RenderingContext,\n name: string,\n arr: UniformArray,\n value: ArrayValue,\n): void {\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n const upload = ARRAY_UPLOADS[arr.type];\n if (!upload) {\n if (isDev) console.warn(`weasel setUniform: array uniform \"${name}\" has type ${arr.type}, which cannot be written as a whole`);\n return;\n }\n if (value.length % upload.n !== 0 || value.length > upload.n * arr.size) {\n if (isDev) {\n throw new TypeError(\n `weasel setUniform: \"${name}\" is ${arr.type}[${arr.size}], so its value must hold a multiple of ${upload.n} `\n + `numbers, at most ${upload.n * arr.size}; got ${value.length}`,\n );\n }\n return;\n }\n if (value.length === 0) return;\n const fn = (gl as unknown as Record<string, (...args: unknown[]) => void>)[upload.fn];\n if (upload.matrix) fn.call(gl, arr.location, false, value);\n else fn.call(gl, arr.location, value);\n}\n\n/** Write every entry of a command's `uniforms` map. A key naming an array\n * uniform with an array value fills the array; anything else goes to the\n * location of that exact name. */\nfunction setUniforms(\n gl: WebGL2RenderingContext,\n program: ShaderProgram,\n programId: string,\n uniforms: Record<string, ShaderUniform>,\n textureCache: GLTextureCache,\n nextTexUnit: { value: number },\n): void {\n for (const [name, value] of Object.entries(uniforms)) {\n const arr = program.uniformArray(name);\n if (arr && isArrayValue(value)) {\n setUniformArray(gl, name, arr, value);\n continue;\n }\n const loc = program.uniform(name);\n if (loc === undefined) {\n warnOnceUniform(programId, name);\n continue;\n }\n setUniform(gl, loc, value, textureCache, nextTexUnit);\n }\n}\n\nfunction drawShader(ctx: DrawContext, cmd: ShaderDrawCommand): void {\n const { gl, programRegistry, quadVbo, quadIbo, textureCache } = ctx;\n\n const program = programRegistry.get(cmd.program.id);\n if (!program) {\n console.warn(\n `weasel drawShader: program \"${cmd.program.id}\" not compiled on this renderer. ` +\n `Call renderer.registerProgram(handle) after the module-level registerProgram().`,\n );\n return;\n }\n if (!quadVbo || !quadIbo) {\n console.warn('weasel drawShader: quad geometry not initialized');\n return;\n }\n\n gl.useProgram(program.handle);\n\n const aPosLoc = program.attribute('a_position');\n const aUvLoc = program.attribute('a_uv');\n\n gl.bindBuffer(gl.ARRAY_BUFFER, quadVbo);\n if (aPosLoc !== undefined) {\n gl.enableVertexAttribArray(aPosLoc);\n gl.vertexAttribPointer(aPosLoc, 2, gl.FLOAT, false, 16, 0);\n }\n if (aUvLoc !== undefined) {\n gl.enableVertexAttribArray(aUvLoc);\n gl.vertexAttribPointer(aUvLoc, 2, gl.FLOAT, false, 16, 8);\n }\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, quadIbo);\n\n const proj = mat3.screenToClip(ctx.widthCss, ctx.heightCss);\n const uProj = program.uniform('u_proj');\n if (uProj !== undefined) gl.uniformMatrix3fv(uProj, false, proj);\n\n const uBounds = program.uniform('u_bounds');\n if (uBounds !== undefined) {\n gl.uniform4f(uBounds, cmd.bounds.x, cmd.bounds.y, cmd.bounds.w, cmd.bounds.h);\n }\n\n const uView = program.uniform('u_view');\n if (uView !== undefined) gl.uniformMatrix3fv(uView, false, ctx.state.transform);\n\n setUniforms(gl, program, cmd.program.id, cmd.uniforms, textureCache, { value: 1 });\n\n applyClipTest(ctx);\n drawTriangles(ctx, 6, ctx.gl.UNSIGNED_SHORT);\n\n if (aPosLoc !== undefined) gl.disableVertexAttribArray(aPosLoc);\n if (aUvLoc !== undefined) gl.disableVertexAttribArray(aUvLoc);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n}\n\n/**\n * Draw a group's children into a buffer of their own, run its effects over\n * that buffer, and composite the result back where the group sits.\n *\n * Three things are deliberately not inherited by the offscreen render:\n *\n * - **The clip.** A fresh buffer's stencil is empty, so a child drawn at the\n * enclosing clip depth would test against bits that were never written and\n * paint nothing. The enclosing clip belongs on the composite anyway — it\n * clips the group's result, not the pixels an effect reads — so `clipDepth`\n * restarts at 0 inside, which also hands nested clips a fresh budget.\n * - **Alpha and color**, for the same reason from the other end: fading on\n * the way in would give the effect faded pixels to read, and fade them\n * again on the way out. `pushIsolated` returns what the composite owes.\n * - **The scissor**, which belongs to the renderer's sub-rect within the\n * default framebuffer and means nothing in a buffer sized to the whole\n * drawing buffer.\n */\nfunction drawGroupWithEffects(\n ctx: DrawContext,\n cmd: GroupDrawCommand,\n targets: EffectTargets,\n width: number,\n height: number,\n): void {\n const gl = ctx.gl;\n // Anything staged belongs to the parent's buffer, not this one.\n flushBatch(ctx);\n\n const parentTarget = ctx.renderTarget ?? null;\n const parentClipDepth = ctx.clipDepth;\n const scissorWasOn = gl.isEnabled(gl.SCISSOR_TEST);\n\n let front = targets.acquire(width, height);\n const composited = ctx.state.pushIsolated({ transform: cmd.transform });\n ctx.clipDepth = 0;\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, front.fbo);\n ctx.renderTarget = front;\n gl.viewport(0, 0, width, height);\n gl.disable(gl.SCISSOR_TEST);\n gl.stencilMask(0xFF);\n gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);\n\n for (const child of cmd.children) dispatch(ctx, child);\n flushBatch(ctx);\n\n // Passes replace rather than blend: each writes every texel of its target\n // from the whole of its source.\n gl.disable(gl.BLEND);\n for (const effect of cmd.effects!) {\n const program = ctx.ensureProgram?.(effect.program.id) ?? null;\n if (!program) {\n warnOnceUniform(effect.program.id, '(program)');\n continue;\n }\n const back = targets.acquire(width, height);\n gl.bindFramebuffer(gl.FRAMEBUFFER, back.fbo);\n gl.viewport(0, 0, width, height);\n gl.clear(gl.COLOR_BUFFER_BIT);\n drawFullscreenQuad(ctx, program, front.texture, width, height, effect.uniforms,\n undefined, effect.program.id);\n targets.release(front);\n front = back;\n }\n gl.enable(gl.BLEND);\n\n // Back to the parent's buffer, and back under its rules.\n ctx.state.pop();\n ctx.clipDepth = parentClipDepth;\n ctx.renderTarget = parentTarget;\n returnToRenderTarget(ctx, width, height, scissorWasOn);\n\n const composite = ctx.ensureProgram?.(COMPOSITE_PROGRAM_ID) ?? null;\n if (composite) {\n applyClipTest(ctx);\n drawFullscreenQuad(ctx, composite, front.texture, width, height, undefined, {\n alpha: composited.alpha,\n colorMatrix: composited.colorMatrix,\n });\n }\n targets.release(front);\n}\n\n/** Rebind `ctx.renderTarget` after an offscreen pass: a pooled target takes\n * the whole `width` × `height` buffer, the default framebuffer the renderer's\n * own rect and the scissor it had. */\nfunction returnToRenderTarget(\n ctx: DrawContext, width: number, height: number, scissorWasOn: boolean,\n): void {\n const gl = ctx.gl;\n const target = ctx.renderTarget ?? null;\n gl.bindFramebuffer(gl.FRAMEBUFFER, target ? target.fbo : null);\n if (target) {\n gl.viewport(0, 0, width, height);\n } else {\n ctx.restoreTargetRect?.();\n if (scissorWasOn) gl.enable(gl.SCISSOR_TEST);\n }\n}\n\n/** One pass: the kit quad, `u_source` bound to `texture`, and whatever else\n * the caller supplies. Leaves no attribute arrays or buffers bound. */\nfunction drawFullscreenQuad(\n ctx: DrawContext,\n program: ShaderProgram,\n texture: WebGLTexture,\n width: number,\n height: number,\n uniforms?: Record<string, ShaderUniform>,\n composite?: { alpha: number; colorMatrix: Float32Array },\n programId?: string,\n): void {\n const gl = ctx.gl;\n gl.useProgram(program.handle);\n\n const aPos = program.attribute('a_position');\n const aUv = program.attribute('a_uv');\n gl.bindBuffer(gl.ARRAY_BUFFER, ctx.quadVbo);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ctx.quadIbo);\n if (aPos !== undefined && aPos >= 0) {\n gl.enableVertexAttribArray(aPos);\n gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);\n }\n if (aUv !== undefined && aUv >= 0) {\n gl.enableVertexAttribArray(aUv);\n gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);\n }\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n const source = program.uniform('u_source');\n if (source !== undefined) gl.uniform1i(source, 0);\n const resolution = program.uniform('u_resolution');\n if (resolution !== undefined) gl.uniform2f(resolution, width, height);\n const texel = program.uniform('u_texel');\n if (texel !== undefined) gl.uniform2f(texel, 1 / width, 1 / height);\n\n if (composite) {\n const alpha = program.uniform('u_alpha');\n if (alpha !== undefined) gl.uniform1f(alpha, composite.alpha);\n setColorMatrixUniforms(ctx, program, composite.colorMatrix);\n }\n\n // Unit 0 is `u_source`; a consumer texture starts above it.\n if (uniforms) setUniforms(gl, program, programId ?? 'effect', uniforms, ctx.textureCache, { value: 1 });\n\n drawTriangles(ctx, 6, ctx.gl.UNSIGNED_SHORT);\n\n if (aPos !== undefined && aPos >= 0) gl.disableVertexAttribArray(aPos);\n if (aUv !== undefined && aUv >= 0) gl.disableVertexAttribArray(aUv);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n}\n\nexport function drawGroup(ctx: DrawContext, cmd: GroupDrawCommand): void {\n // A group with effects is a render-target boundary rather than another\n // accumulating frame. Without a renderer's buffer pool behind the context\n // there is nowhere to draw, so the effects are skipped and the children\n // paint straight through — a frame missing its blur, not a frame missing.\n if (cmd.effects && cmd.effects.length > 0 && ctx.effectTargets\n && ctx.deviceWidth && ctx.deviceHeight) {\n drawGroupWithEffects(ctx, cmd, ctx.effectTargets, ctx.deviceWidth, ctx.deviceHeight);\n return;\n }\n ctx.state.push({\n transform: cmd.transform,\n alpha: cmd.alpha,\n colorMatrix: cmd.colorMatrix,\n });\n if (cmd.clip) {\n const newDepth = ctx.clipDepth + 1;\n if (newDepth > 7) {\n ctx.state.pop();\n throw new Error(\n 'weasel: clip nesting depth exceeded (max 7). You can\\'t nest more than 7 levels ' +\n 'of clipped containers in a single draw tree. Flatten the hierarchy or compose ' +\n 'poses outside the scene graph.',\n );\n }\n pushClip(ctx, cmd.clip, newDepth);\n ctx.clipDepth = newDepth;\n }\n for (const child of cmd.children) dispatch(ctx, child);\n if (cmd.clip) {\n popClip(ctx, cmd.clip, ctx.clipDepth - 1);\n ctx.clipDepth -= 1;\n }\n ctx.state.pop();\n}\n\n/** A path command whose stroke actually paints something. */\ntype StrokedPathCommand = PathDrawCommand & { stroke: Stroke & { paint: FillStyle } };\n\nfunction drawPath(ctx: DrawContext, cmd: PathDrawCommand): void {\n if (cmd.fill) drawPathFill(ctx, cmd);\n // A stroke with no `paint` paints nothing, the way a node's `fill: null`\n // does. Commands arriving from a consumer painter or overlay can carry one.\n if (cmd.stroke?.paint) drawPathStroke(ctx, cmd as StrokedPathCommand);\n}\n\nfunction drawPathFill(ctx: DrawContext, cmd: PathDrawCommand): void {\n const fill = cmd.fill!;\n // Batchable: see `batchPaint`. A rect skips tessellation entirely; anything\n // else stages its mesh. Both also keep animated demos that mint a fresh Path\n // every frame from allocating a GL buffer per frame.\n const isSolid = fill.fill === undefined || fill.fill === 'solid';\n const hasVColors = !!(cmd.vertexColors && cmd.vertexColors.length > 0);\n const solid = fill as { color: string; opacity?: number };\n const paint = batchPaint(ctx, fill, hasVColors);\n if (paint === null) return;\n\n if (paint !== undefined && cmd.path.kind === 'rect') {\n if (paint.kind === 'ramp') pushRampRect(ctx, cmd.path, paint);\n else pushRect(ctx, cmd.path, paint);\n return;\n }\n\n const mesh = fillMesh(ctx, cmd.path);\n if (tryStageFill(ctx, mesh, paint)) return;\n\n const handle = meshHandle(ctx, mesh);\n if (isSolid && hasVColors) {\n drawPathFillVColor(ctx, cmd, solid, handle);\n } else if (handle.requiresStencil) {\n drawPathFillStencil(ctx, fill, handle);\n } else {\n drawPathFillByKind(ctx, fill, handle);\n }\n}\n\n/** `u_samplers[i] = i`, uploaded whole per flush. Built once: the mapping from\n * slot to texture unit is the identity and never varies. */\nconst SAMPLER_UNITS = new Int32Array(\n Array.from({ length: BATCH_TEXTURE_SLOTS }, (_, i) => i),\n);\n\n/** `u_fieldScale`, per slot: an atlas slot's `glyphFieldScale`. Slots that are\n * not atlases keep whatever a previous flush wrote, which nothing reads. */\nconst FIELD_SCALES = new Float32Array(2 * BATCH_TEXTURE_SLOTS);\n\n/**\n * The group state a staged run was built under.\n *\n * A run outlives the group it started in, so the state live when the flush\n * happens is not the state the rects belong to — the flush draws with these\n * values instead. Transform is absent because it rides the vertices; `alpha`\n * is 1 whenever it rode them too.\n */\ninterface StagedBatchState {\n alpha: number;\n colorMatrix: Float32Array;\n clipDepth: number;\n /**\n * The SDF threshold shift `u_synthBold` draws this run under.\n *\n * A uniform rather than a vertex attribute, and so a thing that breaks a run.\n * Carrying it per vertex measured 9% slower at the densest rung of\n * `tests/perf/atlas-wall.spec.ts` — the batch's whole point is one cheap\n * buffer write a frame, and a float only glyphs read still widens the write\n * for every rect and quad beside them. What it costs instead is a break\n * wherever faked-bold text meets text that is not, which is a fallback path:\n * a registered bold face never sets this at all.\n */\n synthBold: number;\n /** Whether group alpha folded into the vertex colors. */\n foldsAlpha: boolean;\n /**\n * The textures this run samples, in the order they joined. A quad's vertices\n * carry `index + 1`, because slot 0 is the white texel every solid samples.\n *\n * Two kinds, because two caches own them: an image quad names an\n * `ImageBitmap` that `GLImageCache` keys by identity, a glyph names the\n * string id of a font atlas in `GLTextureCache`. They share the slot list so\n * a caption and the thumbnail above it share a draw.\n *\n * A bitmap's `sampling` is per entry and set per flush rather than at upload:\n * MAG_FILTER is state on the texture object, so the same bitmap drawn at both\n * filters in one frame needs two flushes, not two slots. An atlas carries no\n * sampling because `GLTextureCache` owns its filtering — and must keep\n * owning it: filtering a distance field destroys it, so a font atlas is\n * never mipmapped and never joins a shared image atlas.\n */\n textures: BatchTexture[];\n}\n\n/** One entry in a run's slot list. */\ntype BatchTexture =\n | { kind: 'bitmap'; image: ImageBitmap; sampling: 'linear' | 'nearest' }\n | { kind: 'atlas'; id: string; fieldScale: readonly [number, number] }\n | { kind: 'ramps' };\n\n/** Identity in row-major 4×5 leaves `src` untouched *and* leaves the shader's\n * clamp with nothing to do, which is what makes the alpha fold exact. */\nfunction isIdentityColorMatrix(cm: Float32Array): boolean {\n return cm === IDENTITY_COLOR_MATRIX || sameValues(IDENTITY_COLOR_MATRIX, cm);\n}\n\n/**\n * Whether the live group state would draw the staged run identically.\n *\n * By value, not by reference: a group carrying an identity color matrix still\n * goes through `compose4x5`, which allocates a new array holding equal numbers.\n * Twenty float compares are nothing against the draw call they save.\n */\nfunction stagedStateIsLive(\n ctx: DrawContext, staged: StagedBatchState,\n image?: ImageBitmap, sampling?: 'linear' | 'nearest',\n synthBold = 0,\n): boolean {\n if (staged.clipDepth !== ctx.clipDepth) return false;\n // Solids and image quads ask with 0, which is what a run of them carries, so\n // this only ever breaks between two kinds of glyph.\n if (staged.synthBold !== synthBold) return false;\n if (!staged.foldsAlpha && staged.alpha !== ctx.state.alpha) return false;\n if (image !== undefined && slotForBitmap(staged, image, sampling!) < 0) return false;\n const colorMatrix = ctx.state.colorMatrix;\n return staged.colorMatrix === colorMatrix || sameValues(staged.colorMatrix, colorMatrix);\n}\n\n/**\n * The slot `image` would sample from in this run, or -1 if it cannot join.\n *\n * A bitmap already in the run reuses its slot — but only at the filter it went\n * in under, since MAG_FILTER belongs to the texture object and one draw cannot\n * have it both ways. Otherwise it takes the next free slot, and a run with none\n * left is a run this quad has to break.\n */\nfunction slotForBitmap(\n staged: StagedBatchState, image: ImageBitmap, sampling: 'linear' | 'nearest',\n): number {\n for (let i = 0; i < staged.textures.length; i++) {\n const entry = staged.textures[i];\n if (entry.kind !== 'bitmap' || entry.image !== image) continue;\n return entry.sampling === sampling ? i + 1 : -1;\n }\n return nextFreeSlot(staged);\n}\n\n/** The same for the ramp atlas, of which there is one — so every gradient in a\n * run shares the slot, however many distinct ramps they are. */\nfunction slotForRamps(staged: StagedBatchState): number {\n for (let i = 0; i < staged.textures.length; i++) {\n if (staged.textures[i].kind === 'ramps') return i + 1;\n }\n return nextFreeSlot(staged);\n}\n\n/** The same for a font atlas, which has no filter to disagree about. */\nfunction slotForAtlas(staged: StagedBatchState, id: string): number {\n for (let i = 0; i < staged.textures.length; i++) {\n const entry = staged.textures[i];\n if (entry.kind === 'atlas' && entry.id === id) return i + 1;\n }\n return nextFreeSlot(staged);\n}\n\n/** The slot a texture new to this run would take, or -1 if it is full. */\nfunction nextFreeSlot(staged: StagedBatchState): number {\n return staged.textures.length + 1 < BATCH_TEXTURE_SLOTS ? staged.textures.length + 1 : -1;\n}\n\n/**\n * Vertices above which a mesh keeps its own draw.\n *\n * Batching trades a draw call for copying and re-uploading the mesh every\n * frame, where a mesh already in the persistent cache costs nothing per frame\n * beyond the draw. On an M2 Max via ANGLE (`npm run test:perf`) staged geometry\n * runs ~8.5 ns a vertex and a warm mesh draw ~1.8 us, putting break-even near\n * 200 — and the 1.8 us is an upper bound, measured under heavy overdraw. So\n * this sits about at break-even, where being wrong in either direction is a\n * wash, rather than anywhere a big path pays a per-frame copy for a draw call\n * it barely saves.\n */\nconst MAX_BATCHED_MESH_VERTICES = 256;\n\n/** Whether a mesh can join a run. Stencil fills need their own two-pass dance,\n * and a mesh past the cap is cheaper as its own draw. */\nfunction canBatchMesh(mesh: Mesh): boolean {\n return !mesh.requiresStencil && (mesh.vertices.length >> 1) <= MAX_BATCHED_MESH_VERTICES;\n}\n\n/**\n * Open or continue a run for `vertices` more, flushing first if the run would\n * overflow or if the live group state no longer matches what it was staged\n * under. Returns the staged state, which the caller reads to resolve alpha.\n *\n * Fill opacity folds into the vertex alpha, exactly as `u_color` carried it\n * when each shape was its own draw. Group alpha folds in too, but only under an\n * identity color matrix: the shader is `a = clamp(CM * src + bias).a * u_alpha`,\n * so with a real matrix between them a pre-multiplied vertex alpha is a\n * different number. There it stays a uniform, and a differing alpha breaks the\n * run as before.\n */\nfunction stageSolid(ctx: DrawContext, vertices: number): StagedBatchState {\n if (ctx.batchState !== undefined && !stagedStateIsLive(ctx, ctx.batchState)) flushBatch(ctx);\n if (ctx.drawBatch.wouldOverflow(vertices)) flushBatch(ctx);\n return openRun(ctx);\n}\n\n/** The staged state, opening a run under the live group state if none is. */\nfunction openRun(ctx: DrawContext): StagedBatchState {\n if (ctx.batchState === undefined) {\n const colorMatrix = ctx.state.colorMatrix;\n const foldsAlpha = isIdentityColorMatrix(colorMatrix);\n ctx.batchState = {\n alpha: foldsAlpha ? 1 : ctx.state.alpha,\n colorMatrix,\n clipDepth: ctx.clipDepth,\n synthBold: 0,\n foldsAlpha,\n textures: [],\n };\n }\n return ctx.batchState;\n}\n\n/**\n * Open or continue a run for one more image quad, flushing first if the run\n * would overflow or cannot give this bitmap a slot.\n *\n * A run adopts a bitmap it has not seen rather than breaking, which is what\n * lets a wall's ground rect and its atlas quad share a draw, and what lets a\n * cell's art and its badge share one too. Returns the staged state and the slot\n * the quad's vertices must carry.\n */\nfunction stageImage(\n ctx: DrawContext, image: ImageBitmap, sampling: 'linear' | 'nearest',\n): { staged: StagedBatchState; slot: number } {\n if (ctx.batchState !== undefined\n && !stagedStateIsLive(ctx, ctx.batchState, image, sampling)) {\n flushBatch(ctx);\n }\n if (ctx.drawBatch.wouldOverflow(4)) flushBatch(ctx);\n const staged = openRun(ctx);\n let slot = slotForBitmap(staged, image, sampling);\n if (slot > staged.textures.length) {\n staged.textures.push({ kind: 'bitmap', image, sampling });\n slot = staged.textures.length;\n }\n return { staged, slot };\n}\n\n/**\n * Open or continue a run for a glyph off the font atlas `atlasId`, flushing\n * first if the run would overflow or has no slot left for it.\n *\n * The atlas is the unit of coalescing the way a sprite sheet is: every glyph a\n * face contributes to a frame shares one texture, so a paragraph is one run\n * however many glyphs it is, and a second face costs one more slot rather than\n * a flush per word.\n */\nfunction stageGlyphs(\n ctx: DrawContext, atlasId: string, fieldScale: readonly [number, number], synthBold: number,\n): { staged: StagedBatchState; slot: number } {\n if (ctx.batchState !== undefined\n && (!stagedStateIsLive(ctx, ctx.batchState, undefined, undefined, synthBold)\n || slotForAtlas(ctx.batchState, atlasId) < 0)) {\n flushBatch(ctx);\n }\n if (ctx.drawBatch.wouldOverflow(4)) flushBatch(ctx);\n const staged = openRun(ctx);\n // An empty run adopts the threshold; one that already has vertices agreed to\n // it above, since a mismatch flushed.\n staged.synthBold = synthBold;\n let slot = slotForAtlas(staged, atlasId);\n if (slot > staged.textures.length) {\n staged.textures.push({ kind: 'atlas', id: atlasId, fieldScale });\n slot = staged.textures.length;\n }\n return { staged, slot };\n}\n\n/**\n * Open or continue a run for geometry filled from the ramp atlas, flushing\n * first if the run would overflow, has no slot left, or if baking `stops` would\n * move the rows already staged.\n *\n * **That last one is the trap.** A staged vertex names its ramp by where the\n * row sits, so growing the atlas — which changes every row's `v` — or recycling\n * a row repaints geometry already staged with somebody else's gradient. Both\n * are irreversible once done, so the question is asked before the bake, not\n * after.\n */\nfunction stageRamps(\n ctx: DrawContext, stops: GradStop[], space: ColorSpace, vertices: number,\n): { staged: StagedBatchState; slot: number; rowV: number } {\n if (ctx.gradRamps.wouldReshape(stops, space)) flushBatch(ctx);\n if (ctx.batchState !== undefined\n && (!stagedStateIsLive(ctx, ctx.batchState) || slotForRamps(ctx.batchState) < 0)) {\n flushBatch(ctx);\n }\n if (ctx.drawBatch.wouldOverflow(vertices)) flushBatch(ctx);\n const staged = openRun(ctx);\n let slot = slotForRamps(staged);\n if (slot > staged.textures.length) {\n staged.textures.push({ kind: 'ramps' });\n slot = staged.textures.length;\n }\n return { staged, slot, rowV: ctx.gradRamps.rowV(ctx.gradRamps.upload(stops, space)) };\n}\n\n/** Alpha a batched paint's vertices carry: its own opacity, and the group's\n * under an identity color matrix. */\nfunction stagedAlpha(\n ctx: DrawContext, staged: StagedBatchState, opacity: number | undefined,\n): number {\n return (opacity ?? 1) * (staged.foldsAlpha ? ctx.state.alpha : 1);\n}\n\n/** Straight-alpha rgba for a solid paint under the staged state. */\nfunction stagedColor(\n ctx: DrawContext, staged: StagedBatchState,\n paint: { color: string; opacity?: number },\n): [number, number, number, number] {\n const [r, g, b, a] = resolveColor(paint.color);\n return [r, g, b, a * stagedAlpha(ctx, staged, paint.opacity)];\n}\n\nfunction pushRect(\n ctx: DrawContext,\n rect: { x: number; y: number; width: number; height: number },\n fill: { color: string; opacity?: number },\n): void {\n const staged = stageSolid(ctx, 4);\n const [r, g, b, a] = stagedColor(ctx, staged, fill);\n ctx.drawBatch.pushRect(\n rect.x, rect.y, rect.width, rect.height, ctx.state.transform, r, g, b, a,\n );\n}\n\nfunction pushMesh(\n ctx: DrawContext,\n mesh: Mesh,\n paint: { color: string; opacity?: number },\n): void {\n const staged = stageSolid(ctx, mesh.vertices.length >> 1);\n const [r, g, b, a] = stagedColor(ctx, staged, paint);\n ctx.drawBatch.pushMesh(mesh, ctx.state.transform, r, g, b, a);\n}\n\n/** A paint a run can express, resolved from a `FillStyle` by `batchPaint`. */\ntype BatchPaint =\n | { kind: 'solid'; color: string; opacity?: number }\n | {\n kind: 'ramp'; stops: GradStop[]; space: ColorSpace; opacity?: number;\n /** `PAINT_MODE_PLAIN` for a linear gradient, whose ramp position a vertex\n * carries outright; `PAINT_MODE_RADIAL` / `PAINT_MODE_CONIC` otherwise. */\n mode: number;\n uv: GradientUV;\n };\n\n/**\n * `fill` as something a run can carry, or `undefined` for a paint no run can\n * express — a pattern, a shader, per-vertex colors — and `null` for a gradient\n * whose space has no inverse under this transform, which draws nothing.\n *\n * **All three gradients qualify, and for the same reason,** which is not that\n * their ramp position is affine in position — only a linear gradient's is. It\n * is that the *coordinate* the ramp position is computed from is affine in all\n * three, so a vertex can carry that and the rasterizer's interpolation across a\n * triangle is exact. A linear gradient's coordinate is the ramp position\n * itself, which is why it needs no paint mode; the other two carry a\n * gradient-space point and the shader takes a `length` or an `atan` of it.\n */\nfunction batchPaint(\n ctx: DrawContext, fill: FillStyle, hasVColors: boolean,\n): BatchPaint | undefined | null {\n if (hasVColors) return undefined;\n const kind = fill.fill ?? 'solid';\n if (kind === 'solid') {\n const solid = fill as { color: string; opacity?: number };\n return { kind: 'solid', color: solid.color, opacity: solid.opacity };\n }\n if (kind !== 'linear-gradient' && kind !== 'radial-gradient' && kind !== 'conic-gradient') {\n return undefined;\n }\n const grad = fill as Extract<FillStyle, { fill: 'linear-gradient' | 'radial-gradient' | 'conic-gradient' }>;\n const g = gradientMap(ctx, grad.units);\n if (!g) return null;\n if (grad.fill === 'linear-gradient') return ramp(grad, PAINT_MODE_PLAIN, linearRampUV(g, grad));\n if (grad.fill === 'radial-gradient') return ramp(grad, PAINT_MODE_RADIAL, radialRampUV(g, grad));\n return ramp(grad, PAINT_MODE_CONIC, conicRampUV(g, grad));\n}\n\nfunction ramp(\n fill: { stops: GradStop[]; interpolate?: ColorSpace; opacity?: number },\n mode: number, uv: GradientUV,\n): BatchPaint {\n return {\n kind: 'ramp', stops: fill.stops, space: fill.interpolate ?? 'rgb',\n opacity: fill.opacity, mode, uv,\n };\n}\n\n/**\n * Geometry-space → gradient-space, as the one matrix a vertex is measured\n * through.\n *\n * `gradientSpaceInverse` maps a screen position back into the gradient's space\n * and the batch's vertices arrive before the model transform, so the two\n * compose. This is the composition `gradFill`'s vertex shader does in two\n * steps, and the pair have to agree: a radial gradient goes through that one\n * and a linear one through this.\n */\nfunction gradientMap(ctx: DrawContext, units: GradientUnits | undefined): GlMat3 | null {\n const inverse = gradientSpaceInverse(ctx, units);\n return inverse && mat3.multiply(inverse, ctx.state.transform);\n}\n\n/**\n * The gradient shader's `dot(p - from, dir) / len` folded into `u`, with `v`\n * left for the atlas row `stageRamps` fills in.\n */\nfunction linearRampUV(\n g: GlMat3, fill: Extract<FillStyle, { fill: 'linear-gradient' }>,\n): GradientUV {\n const dx = fill.to.x - fill.from.x;\n const dy = fill.to.y - fill.from.y;\n const len = Math.hypot(dx, dy) || 1;\n // dir is (dx, dy)/len and the divisor is len, so the pair is 1/len².\n const k = 1 / (len * len);\n return {\n ux: (g[0] * dx + g[1] * dy) * k,\n uy: (g[3] * dx + g[4] * dy) * k,\n u0: ((g[6] - fill.from.x) * dx + (g[7] - fill.from.y) * dy) * k,\n vx: 0, vy: 0, v0: 0,\n };\n}\n\n/** The gradient-space point scaled so its distance from the center *is* the\n * ramp position, which is what makes the shader's half a `length`. */\nfunction radialRampUV(\n g: GlMat3, fill: Extract<FillStyle, { fill: 'radial-gradient' }>,\n): GradientUV {\n // The floor is `gradFill`'s own `max(u_gradRadius, 0.0001)`.\n const k = 1 / Math.max(fill.radius, 1e-4);\n return {\n ux: g[0] * k, uy: g[3] * k, u0: (g[6] - fill.center.x) * k,\n vx: g[1] * k, vy: g[4] * k, v0: (g[7] - fill.center.y) * k,\n };\n}\n\n/**\n * The gradient-space point about the center, turned by `-angle` so the shader's\n * half is an `atan` of it and nothing else.\n *\n * `gradFill` subtracts the angle from the arctangent instead. The two agree\n * because rotating a point turns its arctangent by the same amount, and the\n * `fract` that follows takes care of the wrap either way.\n */\nfunction conicRampUV(\n g: GlMat3, fill: Extract<FillStyle, { fill: 'conic-gradient' }>,\n): GradientUV {\n const cos = Math.cos(fill.angle);\n const sin = Math.sin(fill.angle);\n const dx0 = g[6] - fill.center.x;\n const dy0 = g[7] - fill.center.y;\n return {\n ux: cos * g[0] + sin * g[1],\n uy: cos * g[3] + sin * g[4],\n u0: cos * dx0 + sin * dy0,\n vx: cos * g[1] - sin * g[0],\n vy: cos * g[4] - sin * g[3],\n v0: cos * dy0 - sin * dx0,\n };\n}\n\n/**\n * What a gradient's vertices carry once its row is known.\n *\n * A linear gradient's `a_uv` is (ramp position, row) and its `a_post` is the\n * plain 1, because that is what the plain paint mode already samples. A radial\n * or conic one needs both `a_uv` channels for its coordinate, so its row goes\n * in `a_post` — which no gradient uses for alpha, its opacity riding the vertex\n * color instead.\n */\nfunction rampVertices(\n paint: Extract<BatchPaint, { kind: 'ramp' }>, rowV: number,\n): { uv: GradientUV; post: number } {\n return paint.mode === PAINT_MODE_PLAIN\n ? { uv: { ...paint.uv, v0: rowV }, post: 1 }\n : { uv: paint.uv, post: rowV };\n}\n\nfunction pushRampRect(\n ctx: DrawContext,\n rect: { x: number; y: number; width: number; height: number },\n paint: Extract<BatchPaint, { kind: 'ramp' }>,\n): void {\n const { staged, slot, rowV } = stageRamps(ctx, paint.stops, paint.space, 4);\n const { uv, post } = rampVertices(paint, rowV);\n // White vertices, so the ramp texel passes through as its own color and the\n // alpha channel carries what `u_opacity` and `u_alpha` used to.\n ctx.drawBatch.pushGradientRect(\n rect.x, rect.y, rect.width, rect.height, ctx.state.transform,\n uv, post, slot, paint.mode, 1, 1, 1, stagedAlpha(ctx, staged, paint.opacity),\n );\n}\n\nfunction pushRampMesh(\n ctx: DrawContext, mesh: Mesh, paint: Extract<BatchPaint, { kind: 'ramp' }>,\n): void {\n const { staged, slot, rowV } = stageRamps(ctx, paint.stops, paint.space, mesh.vertices.length >> 1);\n const { uv, post } = rampVertices(paint, rowV);\n ctx.drawBatch.pushGradientMesh(\n mesh, ctx.state.transform,\n uv, post, slot, paint.mode, 1, 1, 1, stagedAlpha(ctx, staged, paint.opacity),\n );\n}\n\n/**\n * Stage `mesh` into the run, or drain the run so the caller can draw it itself.\n *\n * `true` means the mesh is in the batch and the caller is done. `false` comes\n * back only *after* a flush, so an emitter cannot earn permission to draw for\n * itself without also draining the batch. `paint` is `undefined` when it is one\n * no run can express — see `batchPaint`.\n */\nexport function tryStageFill(\n ctx: DrawContext,\n mesh: Mesh,\n paint: BatchPaint | undefined,\n): boolean {\n if (paint !== undefined && canBatchMesh(mesh)) {\n if (paint.kind === 'ramp') pushRampMesh(ctx, mesh, paint);\n else pushMesh(ctx, mesh, paint);\n return true;\n }\n flushBatch(ctx);\n return false;\n}\n\n/**\n * Draw the staged run as one `drawElements`, under the state it was staged\n * under. Callers that are about to bind a different program, or paint anything\n * that must land on top of the run, call this first; a group that only changes\n * the color matrix does not, because `pushRect` notices and flushes then, and\n * one that only changes transform or alpha does not break the run at all.\n *\n * Clips are the exception both ways: the stencil is real GL state that the\n * staged values cannot reconstruct, so `pushClip` and `popClip` flush *before*\n * mutating it rather than leaving it to the next push.\n *\n * `u_color` stays white: the vertex-color program multiplies it by the\n * per-vertex color, so white makes the result bit-identical to the flat\n * program's `u_color`-only math. `u_model` stays identity for the same reason —\n * the corners arrive already transformed.\n */\nexport function flushBatch(ctx: DrawContext): void {\n const batch = ctx.drawBatch;\n const staged = ctx.batchState;\n if (batch.length === 0 || staged === undefined) return;\n const gl = ctx.gl;\n const prog = ctx.batchFill;\n gl.useProgram(prog.handle);\n const indexCount = batch.uploadAndBind();\n setProjAndModel(ctx, prog, BATCH_MODEL);\n setColorUniform(ctx, prog, 1, 1, 1, 1);\n setAlphaUniform(ctx, prog, staged.alpha);\n gl.uniform1f(prog.uniform('u_synthBold')!, staged.synthBold);\n setColorMatrixUniforms(ctx, prog, staged.colorMatrix);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, ctx.whiteTexture);\n for (let i = 0; i < staged.textures.length; i++) {\n const entry = staged.textures[i];\n if (entry.kind === 'atlas') {\n ctx.textureCache.bind(entry.id, i + 1);\n FIELD_SCALES[2 * (i + 1)] = entry.fieldScale[0];\n FIELD_SCALES[2 * (i + 1) + 1] = entry.fieldScale[1];\n continue;\n }\n if (entry.kind === 'ramps') {\n ctx.gradRamps.bind(i + 1);\n continue;\n }\n ctx.imageCache.bind(entry.image, i + 1);\n // Per flush, not at upload: the same bitmap can be drawn at both filters in\n // one frame. The cache skips the write when the texture already carries the\n // value, which is most flushes.\n ctx.imageCache.setMagFilter(\n entry.image,\n entry.sampling === 'nearest' ? gl.NEAREST : gl.LINEAR,\n );\n }\n gl.uniform1iv(prog.uniform('u_samplers')!, SAMPLER_UNITS);\n gl.uniform2fv(prog.uniform('u_fieldScale')!, FIELD_SCALES);\n applyClipTest(ctx, staged.clipDepth);\n drawTriangles(ctx, indexCount, ctx.gl.UNSIGNED_INT);\n // Everything else in the renderer binds its texture to unit 0 and some of it\n // does so without an `activeTexture` of its own, so leaving unit 6 selected\n // sends the next such bind to a unit nothing samples.\n gl.activeTexture(gl.TEXTURE0);\n // Not redundant: `drawShader` binds no VAO and points attributes at whatever\n // is current, so a slot left bound here comes back corrupted a ring later.\n gl.bindVertexArray(null);\n batch.reset();\n ctx.batchState = undefined;\n}\n\nfunction expandAnchorColors(perAnchor: number[], handle: GLMeshHandle): Float32Array {\n const aA = handle.anchorA;\n const aB = handle.anchorB;\n const aT = handle.anchorT;\n if (!aA || !aB || !aT) {\n // Legacy fallback: mesh lacks anchor params (e.g. non-path mesh). Treat\n // the caller-provided array as already per-vertex.\n return new Float32Array(perAnchor);\n }\n const n = aA.length;\n const out = new Float32Array(n * 4);\n for (let i = 0; i < n; i++) {\n const a4 = aA[i] * 4;\n const b4 = aB[i] * 4;\n const t = aT[i];\n out[i * 4 + 0] = perAnchor[a4 + 0] + (perAnchor[b4 + 0] - perAnchor[a4 + 0]) * t;\n out[i * 4 + 1] = perAnchor[a4 + 1] + (perAnchor[b4 + 1] - perAnchor[a4 + 1]) * t;\n out[i * 4 + 2] = perAnchor[a4 + 2] + (perAnchor[b4 + 2] - perAnchor[a4 + 2]) * t;\n out[i * 4 + 3] = perAnchor[a4 + 3] + (perAnchor[b4 + 3] - perAnchor[a4 + 3]) * t;\n }\n return out;\n}\n\nfunction drawPathFillVColor(\n ctx: DrawContext,\n cmd: PathDrawCommand,\n fill: { color: string; opacity?: number },\n handle: GLMeshHandle,\n): void {\n const gl = ctx.gl;\n const prog = ctx.pathFillVColor;\n gl.useProgram(prog.handle);\n gl.bindVertexArray(handle.vao);\n setProjAndModel(ctx, prog);\n setSolidPaintUniforms(ctx, prog, fill.color, fill.opacity);\n setColorMatrixUniforms(ctx, prog);\n\n const expanded = expandAnchorColors(cmd.vertexColors!, handle);\n const colorVbo = gl.createBuffer();\n if (!colorVbo) throw new Error('drawPathFillVColor: createBuffer (color VBO) returned null');\n gl.bindBuffer(gl.ARRAY_BUFFER, colorVbo);\n gl.bufferData(gl.ARRAY_BUFFER, expanded, gl.DYNAMIC_DRAW);\n const aVColorLoc = prog.attribute('a_vertexColor');\n if (aVColorLoc !== undefined) {\n gl.enableVertexAttribArray(aVColorLoc);\n gl.vertexAttribPointer(aVColorLoc, 4, gl.FLOAT, false, 0, 0);\n }\n\n applyClipTest(ctx);\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n gl.bindVertexArray(null);\n // The per-vertex color VBO is freshly allocated per draw; free it now\n // (after unbinding the VAO) so we don't leak one buffer per vColor draw.\n gl.deleteBuffer(colorVbo);\n}\n\nfunction setProjAndModel(\n ctx: DrawContext, prog: ShaderProgram,\n model: GlMat3 = ctx.state.transform,\n proj: GlMat3 = projFor(ctx),\n): void {\n const gl = ctx.gl;\n const uploaded = uploadedFor(ctx, prog);\n\n if (!sameValues(uploaded.proj, proj)) {\n gl.uniformMatrix3fv(prog.uniform('u_proj')!, false, proj);\n uploaded.proj = Float32Array.from(proj);\n }\n\n if (!sameValues(uploaded.model, model)) {\n gl.uniformMatrix3fv(prog.uniform('u_model')!, false, model);\n uploaded.model = Float32Array.from(model);\n }\n}\n\nfunction setSolidPaintUniforms(\n ctx: DrawContext, prog: ShaderProgram,\n color: string, opacity: number | undefined,\n): void {\n const [r, g, b, a] = resolveColor(color);\n setColorUniform(ctx, prog, r, g, b, a * (opacity ?? 1));\n setAlphaUniform(ctx, prog, ctx.state.alpha);\n}\n\n/**\n * Bind the program, uniforms and textures for `fill`, and return the program.\n *\n * Split from the draw so a caller owning its own stencil state can paint\n * without `applyClipTest` clobbering it — `drawPathStrokeStenciled` clips a\n * doubled ribbon to one side of the silhouette, and `applyClipTest` at depth 0\n * disables the stencil test outright.\n */\nfunction bindPathFillByKind(ctx: DrawContext, fill: FillStyle): ShaderProgram | null {\n const kind = fill.fill ?? 'solid';\n if (kind === 'solid') return bindPathFillSolid(ctx, fill as { color: string; opacity?: number });\n if (kind === 'pattern') return bindPathFillPattern(ctx, fill as Extract<FillStyle, { fill: 'pattern' }>);\n if (kind === 'linear-gradient' || kind === 'radial-gradient' || kind === 'conic-gradient') {\n return bindPathFillGradient(ctx, fill as Extract<FillStyle, { fill: 'linear-gradient' | 'radial-gradient' | 'conic-gradient' }>);\n }\n const bind = getPaintKind(kind)?.bind;\n return bind ? bind(paintBindContext(ctx), fill) : null;\n}\n\n/** The narrow renderer surface a registered paint kind binds against, built\n * once per frame context. `DrawContext` is not consumer surface. */\nfunction paintBindContext(ctx: DrawContext): PaintBindContext {\n const cached = BIND_CONTEXTS.get(ctx);\n if (cached) return cached;\n const made: PaintBindContext = {\n gl: ctx.gl,\n get alpha() { return ctx.state.alpha; },\n program: (id) => ctx.ensureProgram?.(id) ?? ctx.programRegistry.get(id) ?? null,\n setProjAndModel: (prog) => setProjAndModel(ctx, prog),\n spaceInverse: (units) => gradientSpaceInverse(ctx, units),\n spaceToDevice: (units) => spaceToDevice(ctx, units),\n get maxTextureSize() { return ctx.imageCache.maxTextureSide; },\n resources: ctx.paintResources ?? unownedPaintResources(ctx.gl),\n bindRamp: (stops, unit, space) => {\n const row = ctx.gradRamps.upload(stops, space);\n ctx.gradRamps.bind(unit);\n return ctx.gradRamps.rowV(row);\n },\n };\n BIND_CONTEXTS.set(ctx, made);\n return made;\n}\n\nconst BIND_CONTEXTS = new WeakMap<DrawContext, PaintBindContext>();\n\nconst UNOWNED_RESOURCES = new WeakMap<WebGL2RenderingContext, PaintResources>();\n\nfunction unownedPaintResources(gl: WebGL2RenderingContext): PaintResources {\n let made = UNOWNED_RESOURCES.get(gl);\n if (!made) {\n made = createPaintResources();\n UNOWNED_RESOURCES.set(gl, made);\n }\n return made;\n}\n\nfunction drawPathFillByKind(ctx: DrawContext, fill: FillStyle, handle: GLMeshHandle): void {\n const prog = bindPathFillByKind(ctx, fill);\n if (!prog) return;\n const gl = ctx.gl;\n gl.bindVertexArray(handle.vao);\n applyClipTest(ctx);\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n gl.bindVertexArray(null);\n}\n\nfunction bindPathFillSolid(\n ctx: DrawContext,\n fill: { color: string; opacity?: number },\n): ShaderProgram {\n const prog = ctx.pathFill;\n ctx.gl.useProgram(prog.handle);\n setProjAndModel(ctx, prog);\n setSolidPaintUniforms(ctx, prog, fill.color, fill.opacity);\n setColorMatrixUniforms(ctx, prog);\n return prog;\n}\n\nfunction bindPathFillPattern(\n ctx: DrawContext,\n fill: Extract<FillStyle, { fill: 'pattern' }>,\n): ShaderProgram | null {\n return bindPattern(ctx, ctx.patternFill, fill, ctx.state.transform);\n}\n\n/** Bind `prog` — the path program or the glyph one, which share every paint\n * uniform — to draw `fill` under `model`. */\nfunction bindPattern(\n ctx: DrawContext,\n prog: ShaderProgram,\n fill: Extract<FillStyle, { fill: 'pattern' }>,\n model: GlMat3,\n): ShaderProgram | null {\n const tex = fill.pattern as TextureHandle;\n const entry = getTexture(tex.id);\n if (!entry) {\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n if (isDev) console.warn(`weasel: pattern TextureHandle \"${tex.id}\" not registered`);\n return null;\n }\n const inverse = gradientSpaceInverse(ctx, fill.units);\n if (!inverse) return null;\n const tileSpace = patternTileSpace(inverse, fill.origin ?? { x: 0, y: 0 }, fill.transform);\n if (!tileSpace) return null;\n ctx.textureCache.upload(tex.id, entry.source, 'repeat');\n\n // A path fill mesh carries a_position only, so the tile coordinate is\n // recovered per fragment from the screen position — the same route\n // gradients take through `u_worldInv`, and the reason this can't reuse\n // the image-fill shader, whose a_uv such a mesh leaves unbound.\n const gl = ctx.gl;\n gl.useProgram(prog.handle);\n setProjAndModel(ctx, prog, model);\n setColorMatrixUniforms(ctx, prog);\n gl.uniformMatrix3fv(prog.uniform('u_worldInv')!, false, tileSpace);\n const [tw, th] = textureSize(entry.source);\n gl.uniform2f(prog.uniform('u_tileSize')!, tw, th);\n ctx.textureCache.bind(tex.id, 0);\n gl.uniform1i(prog.uniform('u_sampler')!, 0);\n gl.uniform1f(prog.uniform('u_opacity')!, fill.opacity ?? 1);\n setAlphaUniform(ctx, prog, ctx.state.alpha);\n return prog;\n}\n\n/** Tile extent in paint-space units — one tile spans this many units of\n * whatever space `units` names. */\nfunction textureSize(source: HTMLImageElement | ImageBitmap): [number, number] {\n const w = 'naturalWidth' in source ? source.naturalWidth : source.width;\n const h = 'naturalHeight' in source ? source.naturalHeight : source.height;\n return [w || 1, h || 1];\n}\n\n/**\n * Screen→gradient-space matrix for `u_worldInv`, which the vertex shader\n * applies to each fragment's screen position to recover the coordinates the\n * gradient's geometry is expressed in.\n *\n * `'world'` silently degrades to screen space when no view matrix reached\n * the renderer — `render(commands)` without a view is a supported call, and\n * a missing view is not worth a thrown frame. `null` when the space has no\n * inverse; a paint measured in it draws nothing.\n */\nfunction gradientSpaceInverse(ctx: DrawContext, units: GradientUnits | undefined): GlMat3 | null {\n if (units === 'local') return mat3.invert(ctx.state.transform);\n if (units === 'world' && ctx.viewMatrix) return mat3.invert(ctx.viewMatrix);\n return mat3.identity();\n}\n\n/** The paint space `units` names → device pixels: the forward transform\n * `gradientSpaceInverse` undoes, scaled by the target's pixel ratio. */\nfunction spaceToDevice(ctx: DrawContext, units: GradientUnits | undefined): GlMat3 | null {\n const inverse = gradientSpaceInverse(ctx, units);\n const toScreen = inverse && mat3.invert(inverse);\n if (!toScreen) return null;\n const ratio = ctx.deviceWidth && ctx.widthCss > 0 ? ctx.deviceWidth / ctx.widthCss : 1;\n return mat3.multiply(mat3.scaled(mat3.identity(), ratio, ratio), toScreen);\n}\n\nfunction bindPathFillGradient(\n ctx: DrawContext,\n fill: Extract<FillStyle, { fill: 'linear-gradient' | 'radial-gradient' | 'conic-gradient' }>,\n): ShaderProgram | null {\n return bindGradient(ctx, ctx.gradFill, fill, ctx.state.transform);\n}\n\n/** The gradient counterpart of `bindPattern`. */\nfunction bindGradient(\n ctx: DrawContext,\n prog: ShaderProgram,\n fill: Extract<FillStyle, { fill: 'linear-gradient' | 'radial-gradient' | 'conic-gradient' }>,\n model: GlMat3,\n): ShaderProgram | null {\n const inverse = gradientSpaceInverse(ctx, fill.units);\n if (!inverse) return null;\n const gl = ctx.gl;\n const row = ctx.gradRamps.upload(fill.stops, fill.interpolate ?? 'rgb');\n\n gl.useProgram(prog.handle);\n setProjAndModel(ctx, prog, model);\n\n gl.uniformMatrix3fv(prog.uniform('u_worldInv')!, false, inverse);\n setColorMatrixUniforms(ctx, prog);\n\n ctx.gradRamps.bind(0);\n gl.uniform1i(prog.uniform('u_ramp')!, 0);\n gl.uniform1f(prog.uniform('u_rampV')!, ctx.gradRamps.rowV(row));\n setAlphaUniform(ctx, prog, ctx.state.alpha);\n gl.uniform1f(prog.uniform('u_opacity')!, fill.opacity ?? 1);\n\n if (fill.fill === 'linear-gradient') {\n gl.uniform1i(prog.uniform('u_gradKind')!, 0);\n const dx = fill.to.x - fill.from.x;\n const dy = fill.to.y - fill.from.y;\n const len = Math.hypot(dx, dy) || 1;\n gl.uniform2f(prog.uniform('u_gradP0')!, fill.from.x, fill.from.y);\n gl.uniform2f(prog.uniform('u_gradDir')!, dx / len, dy / len);\n gl.uniform1f(prog.uniform('u_gradLen')!, len);\n gl.uniform1f(prog.uniform('u_gradRadius')!, 0);\n gl.uniform1f(prog.uniform('u_gradAngle')!, 0);\n } else if (fill.fill === 'radial-gradient') {\n gl.uniform1i(prog.uniform('u_gradKind')!, 1);\n gl.uniform2f(prog.uniform('u_gradP0')!, fill.center.x, fill.center.y);\n gl.uniform2f(prog.uniform('u_gradDir')!, 0, 0);\n gl.uniform1f(prog.uniform('u_gradLen')!, 0);\n gl.uniform1f(prog.uniform('u_gradRadius')!, fill.radius);\n gl.uniform1f(prog.uniform('u_gradAngle')!, 0);\n } else {\n // conic\n gl.uniform1i(prog.uniform('u_gradKind')!, 2);\n gl.uniform2f(prog.uniform('u_gradP0')!, fill.center.x, fill.center.y);\n gl.uniform2f(prog.uniform('u_gradDir')!, 0, 0);\n gl.uniform1f(prog.uniform('u_gradLen')!, 0);\n gl.uniform1f(prog.uniform('u_gradRadius')!, 0);\n gl.uniform1f(prog.uniform('u_gradAngle')!, fill.angle);\n }\n\n return prog;\n}\n\n// ─── Per-fragment clip test ───────────────────────────────────────────────────\n\n/**\n * Set the stencil test for the current clip depth. Called by every\n * fragment-producing draw before its drawElements call when clipDepth > 0.\n * At clipDepth = 0, disables STENCIL_TEST (zero-overhead common case).\n *\n * Note: not called by drawPathFillStencil / drawPathStrokeStenciled, which\n * manage their own stencil state (evenodd / inner-outer stencil). Those paths\n * coexist with clip bits because they use bit 0 exclusively while clip levels\n * occupy bits 1-7.\n */\nfunction applyClipTest(ctx: DrawContext, depth: number = ctx.clipDepth): void {\n const gl = ctx.gl;\n if (depth === 0) {\n gl.disable(gl.STENCIL_TEST);\n return;\n }\n const mask = ancestorMask(depth);\n gl.enable(gl.STENCIL_TEST);\n gl.stencilFunc(gl.EQUAL, mask, mask);\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);\n}\n\n// ─── Clip-stencil helpers ────────────────────────────────────────────────────\n\n/**\n * Bit-mask for ancestor clip levels.\n * Returns bits 1..depth (inclusive).\n * depth=0 → 0x00; depth=1 → 0x02; depth=3 → 0x0E.\n */\nfunction ancestorMask(depth: number): number {\n return depth === 0 ? 0 : ((1 << (depth + 1)) - 1) & 0xFE;\n}\n\n/**\n * Rasterize a path into the stencil buffer using the pathFill shader geometry.\n * The caller is responsible for setting stencilFunc / stencilOp / stencilMask\n * and colorMask before calling.\n */\nfunction rasterizePathToStencil(ctx: DrawContext, path: Path): void {\n const gl = ctx.gl;\n const handle = fillMeshHandle(ctx, path);\n gl.useProgram(ctx.pathFill.handle);\n gl.bindVertexArray(handle.vao);\n setProjAndModel(ctx, ctx.pathFill);\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n gl.bindVertexArray(null);\n}\n\n/**\n * Push a clip level. Rasterizes the clip path into the stencil buffer,\n * setting bit `newDepth` where (a) the path's fragment passes AND (b) all\n * ancestor clip bits are already set.\n *\n * Invariant: restores stencilMask(0xFF) on exit so callers (draw functions)\n * can rely on an unnarrowed mask after clip ops complete.\n */\nexport function pushClip(ctx: DrawContext, path: Path, newDepth: number): void {\n // First, not last: a run staged outside the clip would otherwise draw under\n // a mask it never had.\n flushBatch(ctx);\n const gl = ctx.gl;\n const ancestors = ancestorMask(newDepth - 1);\n const newBit = 1 << newDepth;\n const ref = ancestors | newBit;\n\n gl.enable(gl.STENCIL_TEST);\n gl.colorMask(false, false, false, false);\n gl.stencilMask(newBit);\n gl.stencilFunc(gl.EQUAL, ref, ancestors);\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);\n\n rasterizePathToStencil(ctx, path);\n\n gl.colorMask(true, true, true, true);\n // Restore full mask so subsequent draw functions don't inherit a narrowed mask.\n gl.stencilMask(0xFF);\n}\n\n/**\n * Pop a clip level. Rasterizes the same path again, clearing bit\n * `oldDepth + 1` where it was set during the matching push.\n *\n * Must re-enable STENCIL_TEST because child draw functions (drawPathFillStencil,\n * drawPathStrokeStenciled) call gl.disable(STENCIL_TEST) at their end. If\n * one of those was the last child before popClip runs, the test would be off\n * and rasterizePathToStencil would write nothing.\n *\n * Invariant: restores stencilMask(0xFF) on exit so callers are not left with\n * a narrowed mask.\n */\nexport function popClip(ctx: DrawContext, path: Path, oldDepth: number): void {\n // First, not last: past here the mask is gone, and these pixels belonged\n // inside it.\n flushBatch(ctx);\n const gl = ctx.gl;\n // Re-enable stencil: child draw functions (evenodd/stenciled-stroke) disable\n // it at their end; we must set it before writing the clear pass.\n gl.enable(gl.STENCIL_TEST);\n\n const oldBit = 1 << (oldDepth + 1);\n const ref = ancestorMask(oldDepth) | oldBit;\n\n gl.colorMask(false, false, false, false);\n gl.stencilMask(oldBit);\n gl.stencilFunc(gl.EQUAL, ref, ref);\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.ZERO);\n\n rasterizePathToStencil(ctx, path);\n\n gl.colorMask(true, true, true, true);\n // Restore full mask so subsequent draw functions don't inherit a narrowed mask.\n gl.stencilMask(0xFF);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction drawPathFillStencil(ctx: DrawContext, fill: FillStyle, handle: GLMeshHandle): void {\n const gl = ctx.gl;\n gl.useProgram(ctx.pathFill.handle);\n gl.bindVertexArray(handle.vao);\n setProjAndModel(ctx, ctx.pathFill);\n\n gl.enable(gl.STENCIL_TEST);\n gl.colorMask(false, false, false, false);\n gl.stencilMask(0x01);\n gl.stencilFunc(gl.ALWAYS, 0, 0x01);\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.INVERT);\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n\n const clipMask = ancestorMask(ctx.clipDepth);\n gl.colorMask(true, true, true, true);\n gl.stencilFunc(gl.EQUAL, clipMask | 0x01, clipMask | 0x01);\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);\n // The paint binds here, not above: pass 1 runs under a false colorMask, so a\n // uniform missed here renders black while the GL-recorder tests still pass.\n // Not `drawPathFillByKind` — its `applyClipTest` would disable this stencil.\n if (bindPathFillByKind(ctx, fill)) {\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n }\n\n // Narrow to bit 0 first: clear only zeroes bits the mask enables, and\n // pushClip owns bits 1-7.\n gl.stencilMask(0x01);\n gl.clear(gl.STENCIL_BUFFER_BIT);\n gl.disable(gl.STENCIL_TEST);\n gl.bindVertexArray(null);\n}\n\n/** `cmd` with its `{ px }` lengths — the stroke width and any marker size —\n * resolved against the accumulated transform's quantized scale, so everything\n * downstream (the ribbon cache key, the insets, the heads) sees world units. */\nfunction withResolvedStrokeLengths(ctx: DrawContext, cmd: StrokedPathCommand): StrokedPathCommand {\n const stroke = cmd.stroke;\n const { markerStart, markerMid, markerEnd } = stroke;\n if (typeof stroke.width !== 'object' && !isPxMarker(markerStart)\n && !isPxMarker(markerMid) && !isPxMarker(markerEnd)) {\n return cmd;\n }\n const scale = mat3.meanScaleOf(ctx.state.transform);\n const resolved: Stroke & { paint: FillStyle } = { ...stroke };\n if (typeof stroke.width === 'object') {\n resolved.width = resolveStrokeWidth(stroke.width, quantizeStrokeScale(stroke.width.px, scale));\n }\n if (isPxMarker(markerStart)) resolved.markerStart = resolvedMarker(markerStart, scale);\n if (isPxMarker(markerMid)) resolved.markerMid = resolvedMarker(markerMid, scale);\n if (isPxMarker(markerEnd)) resolved.markerEnd = resolvedMarker(markerEnd, scale);\n return { ...cmd, stroke: resolved };\n}\n\ntype PxMarker = Exclude<MarkerRef, string> & { size: { px: number } };\n\nfunction isPxMarker(ref: MarkerRef | undefined): ref is PxMarker {\n return typeof ref === 'object' && typeof ref.size === 'object';\n}\n\nfunction resolvedMarker(ref: PxMarker, scale: number): MarkerRef {\n return { ...ref, size: resolveMarkerSize(ref, 0, quantizeStrokeScale(ref.size.px, scale)) };\n}\n\nfunction drawPathStroke(ctx: DrawContext, rawCmd: StrokedPathCommand): void {\n const cmd = withResolvedStrokeLengths(ctx, rawCmd);\n const stroke = cmd.stroke;\n const align = stroke.align ?? 'center';\n if (cmd.path.kind === 'polygon' && align !== 'center') {\n flushBatch(ctx);\n drawPathStrokeStenciled(ctx, cmd, align);\n } else {\n drawPathStrokeUnclipped(ctx, cmd);\n }\n // After the ribbon, so a head sits on top of the line it caps.\n const width = resolveStrokeWidth(stroke.width ?? 1, 1);\n for (const marker of cachedMarkerCommands(cmd.path, rawCmd.stroke, stroke, width, ctx.flattenTolerance)) {\n drawPath(ctx, marker);\n }\n}\n\nfunction drawPathStrokeUnclipped(ctx: DrawContext, cmd: StrokedPathCommand): void {\n const stroke = cmd.stroke;\n const paint = stroke.paint;\n const isSolid = paint.fill === undefined || paint.fill === 'solid';\n const solid = paint as { color: string; opacity?: number };\n const mesh = strokeMesh(cmd.path, stroke, ctx.flattenTolerance);\n if (mesh.indices.length === 0) return;\n\n // Staged, a ribbon allocates nothing and joins the fill it sits on.\n const hasVColors = !!(stroke.vertexColors && stroke.vertexColors.length > 0);\n const batched = batchPaint(ctx, paint, hasVColors);\n if (batched === null) return;\n if (tryStageFill(ctx, mesh, batched)) return;\n\n // The VAO records the per-draw color attribute, so a vertex-colored draw\n // cannot share a persistent one with a draw that has no vertex colors.\n const handle = hasVColors\n ? ctx.meshCache.uploadTransient(mesh)\n : ctx.meshCache.uploadRecurring(mesh);\n\n if (!isSolid && !hasVColors) {\n drawPathFillByKind(ctx, paint, handle);\n return;\n }\n\n const gl = ctx.gl;\n if (hasVColors) {\n const prog = ctx.pathFillVColor;\n gl.useProgram(prog.handle);\n gl.bindVertexArray(handle.vao);\n setProjAndModel(ctx, prog);\n // Per-vertex colors are the paint here; a non-solid base has no single\n // color to multiply by, so white leaves the vertex colors unmodified.\n setSolidPaintUniforms(ctx, prog, isSolid ? solid.color : '#ffffff', paint.opacity);\n setColorMatrixUniforms(ctx, prog);\n\n const expanded = expandAnchorColors(stroke.vertexColors!, handle);\n const colorVbo = gl.createBuffer();\n if (!colorVbo) throw new Error('drawPathStrokeUnclipped: createBuffer (color VBO) returned null');\n gl.bindBuffer(gl.ARRAY_BUFFER, colorVbo);\n gl.bufferData(gl.ARRAY_BUFFER, expanded, gl.DYNAMIC_DRAW);\n const aVColorLoc = prog.attribute('a_vertexColor');\n if (aVColorLoc !== undefined) {\n gl.enableVertexAttribArray(aVColorLoc);\n gl.vertexAttribPointer(aVColorLoc, 4, gl.FLOAT, false, 0, 0);\n }\n applyClipTest(ctx);\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n gl.bindVertexArray(null);\n // Per-draw color VBO; free after VAO unbind to avoid leak per stroke vColor draw.\n gl.deleteBuffer(colorVbo);\n return;\n }\n\n gl.useProgram(ctx.pathFill.handle);\n gl.bindVertexArray(handle.vao);\n setProjAndModel(ctx, ctx.pathFill);\n setSolidPaintUniforms(ctx, ctx.pathFill, solid.color, solid.opacity);\n setColorMatrixUniforms(ctx, ctx.pathFill);\n applyClipTest(ctx);\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n gl.bindVertexArray(null);\n}\n\n/** The ribbon cache compares `vertexWidths` by reference, so the doubled copy\n * has to be the same array on every frame the source array is. */\nconst DOUBLED_VERTEX_WIDTHS = new WeakMap<number[], number[]>();\n\nfunction doubledVertexWidths(widths: number[]): number[] {\n let doubled = DOUBLED_VERTEX_WIDTHS.get(widths);\n if (doubled === undefined) {\n doubled = widths.map((w) => w * 2);\n DOUBLED_VERTEX_WIDTHS.set(widths, doubled);\n }\n return doubled;\n}\n\nfunction drawPathStrokeStenciled(\n ctx: DrawContext,\n cmd: StrokedPathCommand,\n align: 'inner' | 'outer',\n): void {\n const stroke = cmd.stroke;\n const paint = stroke.paint;\n const isSolid = paint.fill === undefined || paint.fill === 'solid';\n const solid = paint as { color: string; opacity?: number };\n const widerStroke: Stroke = {\n ...stroke,\n width: resolveStrokeWidth(stroke.width ?? 1, 1) * 2,\n ...(stroke.vertexWidths ? { vertexWidths: doubledVertexWidths(stroke.vertexWidths) } : {}),\n align: 'center',\n };\n\n const useVColor = !!(stroke.vertexColors && stroke.vertexColors.length > 0);\n\n const fillHandle = fillMeshHandle(ctx, cmd.path);\n const ribbonMesh = strokeMesh(cmd.path, widerStroke, ctx.flattenTolerance);\n if (ribbonMesh.indices.length === 0) return;\n // The VAO records the per-draw color attribute, so a vertex-colored draw\n // cannot share a persistent one with a draw that has no vertex colors.\n const ribbonHandle = useVColor\n ? ctx.meshCache.uploadTransient(ribbonMesh)\n : ctx.meshCache.uploadRecurring(ribbonMesh);\n\n const gl = ctx.gl;\n const prog = useVColor ? ctx.pathFillVColor : ctx.pathFill;\n gl.useProgram(prog.handle);\n setProjAndModel(ctx, prog);\n\n gl.enable(gl.STENCIL_TEST);\n gl.colorMask(false, false, false, false);\n gl.stencilMask(0x01);\n gl.stencilFunc(gl.ALWAYS, 1, 0x01);\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);\n gl.bindVertexArray(fillHandle.vao);\n drawTriangles(ctx, fillHandle.indexCount, ctx.gl.UNSIGNED_INT);\n\n const clipMask = ancestorMask(ctx.clipDepth);\n gl.colorMask(true, true, true, true);\n if (align === 'inner') {\n gl.stencilFunc(gl.EQUAL, clipMask | 0x01, clipMask | 0x01);\n } else {\n gl.stencilFunc(gl.EQUAL, clipMask, clipMask | 0x01);\n }\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);\n // Bind the paint here rather than through `drawPathFillByKind`: that calls\n // `applyClipTest`, which at clip depth 0 disables the stencil test this\n // function just set up to clip the ribbon to one side.\n let ribbonProg: ShaderProgram | null = prog;\n if (useVColor) {\n // Per-vertex colors are the paint here; a non-solid base has no single\n // color to multiply by, so white leaves the vertex colors unmodified.\n setSolidPaintUniforms(ctx, prog, isSolid ? solid.color : '#ffffff', paint.opacity);\n setColorMatrixUniforms(ctx, prog);\n } else {\n ribbonProg = bindPathFillByKind(ctx, paint);\n }\n if (!ribbonProg) {\n gl.stencilMask(0x01);\n gl.clear(gl.STENCIL_BUFFER_BIT);\n gl.disable(gl.STENCIL_TEST);\n gl.bindVertexArray(null);\n return;\n }\n gl.bindVertexArray(ribbonHandle.vao);\n\n let colorVbo: WebGLBuffer | null = null;\n if (useVColor) {\n const expanded = expandAnchorColors(stroke.vertexColors!, ribbonHandle);\n colorVbo = gl.createBuffer();\n if (!colorVbo) throw new Error('drawPathStrokeStenciled: createBuffer (color VBO) returned null');\n gl.bindBuffer(gl.ARRAY_BUFFER, colorVbo);\n gl.bufferData(gl.ARRAY_BUFFER, expanded, gl.DYNAMIC_DRAW);\n const aVColorLoc = ribbonProg.attribute('a_vertexColor');\n if (aVColorLoc !== undefined) {\n gl.enableVertexAttribArray(aVColorLoc);\n gl.vertexAttribPointer(aVColorLoc, 4, gl.FLOAT, false, 0, 0);\n }\n }\n\n drawTriangles(ctx, ribbonHandle.indexCount, ctx.gl.UNSIGNED_INT);\n\n // Narrow to bit 0 first: clear only zeroes bits the mask enables, and\n // pushClip owns bits 1-7.\n gl.stencilMask(0x01);\n gl.clear(gl.STENCIL_BUFFER_BIT);\n gl.disable(gl.STENCIL_TEST);\n gl.bindVertexArray(null);\n // Delete after the unbind: deleting a bound buffer leaves its attribute\n // enabled and pointing at nothing, recorded in whatever VAO is live.\n if (colorVbo) gl.deleteBuffer(colorVbo);\n}\n\n/**\n * On-screen glyph size (CSS px) at or above which a face with registered\n * outlines is drawn as geometry instead of sampled from a distance field.\n *\n * 48 is the dynamic tier's own `BAKE_SIZE`, which makes it the size at which\n * that tier stops being an interpolation and starts being a magnification:\n * `glyphRasterizer.ts` measures coverage error bottoming out *at* the bake\n * size and rising on both sides, and past a few times it the reconstructed\n * field shows the raster as contour wobble. The same number is a safe\n * crossing for the baked MSDF atlas, which is still crisp here — outlines are\n * exact, so switching early costs nothing but the tessellation, and the\n * hinting the atlas has and outlines don't stopped mattering well below this.\n */\nexport const OUTLINE_MIN_SCREEN_PX = 48;\n\n/**\n * Uniform scale the model matrix applies, as the geometric mean of its two\n * axis lengths. Used to turn a screen-pixel threshold into the world-space\n * size layout compares against.\n *\n * The mean rather than either axis alone so a non-uniform scale answers with\n * something between the two instead of picking a side; anisotropy that\n * extreme is not a case this threshold needs to be exact about, since being\n * one glyph-size late or early only changes which of two correct renderings\n * is used.\n */\nfunction modelScale(m: Float32Array): number {\n const sx = Math.hypot(m[0], m[1]);\n const sy = Math.hypot(m[3], m[4]);\n return Math.sqrt(sx * sy) || 1;\n}\n\nfunction drawText(ctx: DrawContext, cmd: TextDrawCommand): void {\n const style = resolveTextStyle(cmd.style);\n const lineHeight = style.lineHeight;\n const align = cmd.align ?? style.align;\n const maxWidth = cmd.maxWidth ?? Infinity;\n\n // Screen threshold → world threshold. Zooming in lowers the world size that\n // qualifies, which is the whole point: a 12px label at 8× zoom is 96 screen\n // pixels of text and wants outlines exactly as much as a 96px heading does.\n const minScreen = ctx.textOutlineMinScreenSize ?? OUTLINE_MIN_SCREEN_PX;\n const outlineMinSize = Number.isFinite(minScreen)\n ? minScreen / modelScale(ctx.state.transform)\n : undefined;\n\n const laid = cachedLayoutRuns(cmd.runs, {\n maxWidth, alignWidth: cmd.width, lineHeight, align, justify: cmd.justify, outlineMinSize,\n });\n // Decorations are checked too: text whose glyphs are all ink-free — every\n // one still awaiting a dynamic-atlas bake, say — produces no groups at all\n // while still carrying a rule that has to be drawn.\n if (laid.groups.length === 0 && laid.decorations.length === 0) return;\n\n // `laid` is origin-relative, so this is the command's position plus the\n // verticalAlign shift. Applied at upload time, not baked in: the layout is\n // shared and not ours to edit — a cached layout that absorbed either offset\n // would gain another one every frame and slide off the page. Every consumer\n // below adds them while packing vertices, which costs one addition inside\n // loops that are already walking every vertex.\n const dx = cmd.x;\n const dy = cmd.y + verticalAlignOffset(cmd.verticalAlign, cmd.height, laid.bounds.height);\n\n for (const group of laid.groups) {\n if (group.source === 'outline') drawTextOutlineGroup(ctx, group, dx, dy);\n else drawTextGroup(ctx, group, dx, dy);\n }\n\n drawTextDecorations(ctx, laid.decorations, dx, dy);\n}\n\n/**\n * Paint one group of tessellated glyph outlines.\n *\n * The whole group becomes a single mesh: cached em-space triangles are\n * transformed on the CPU into world space and appended to one buffer, so a\n * paragraph set in one face and color is one draw call — the same batching\n * the atlas tier gets from packing glyphs into one texture. The alternative,\n * a model matrix per glyph, would be a draw call per glyph.\n *\n * Going through `drawPathFillByKind` rather than straight to `pathFill` is\n * what makes gradient- and pattern-filled text fall out for free: a glyph\n * here is geometry like any other, and those programs shade in world space,\n * so they need nothing from the text pipeline.\n */\nfunction drawTextOutlineGroup(ctx: DrawContext, group: LaidOutGroup, dx: number, dy: number): void {\n const fill = group.fill;\n if (fill !== null) {\n const mesh = outlineGroupMesh(group, dx, dy);\n if (mesh) drawOutlineMesh(ctx, fill, mesh);\n }\n\n // Stroke after fill — Canvas2D's fillText-then-strokeText convention, and\n // SVG's default paint-order. A second batched draw call over the same\n // group, not a call per glyph.\n const strokePaint = group.stroke?.paint;\n if (!strokePaint) return;\n const ribbon = outlineGroupStrokeMesh(group, dx, dy, mat3.meanScaleOf(ctx.state.transform));\n if (ribbon) drawOutlineMesh(ctx, strokePaint, ribbon);\n}\n\n/**\n * Paint one merged glyph-outline mesh, staging it where it fits.\n *\n * Through `tryStageFill` rather than straight to `drawPathFillByKind`,\n * because a paragraph can mix tiers: a heading drawn as outlines and a caption\n * drawn from the atlas are groups of one command, and the atlas half now\n * stages. An outline that painted itself while glyphs sat staged behind it\n * would come out under them.\n */\nfunction drawOutlineMesh(ctx: DrawContext, fill: FillStyle, mesh: Mesh): void {\n const paint = batchPaint(ctx, fill, false);\n if (paint === null) return;\n if (tryStageFill(ctx, mesh, paint)) return;\n drawPathFillByKind(ctx, fill, ctx.meshCache.uploadTransient(mesh));\n}\n\n/**\n * Merge a group's glyphs into one world-space mesh, or `null` when nothing in\n * it has area.\n *\n * Every glyph mesh here is `'nonzero'` (that is what `pathFromD` produces and\n * what a font outline means), so none of them sets `requiresStencil` and\n * concatenating their triangles is sound — an even-odd mesh would be a naive\n * per-contour fan that only resolves correctly through a stencil pass, and\n * merging one into a batch would fill its counters solid.\n */\nfunction outlineGroupMesh(group: LaidOutGroup, dx: number, dy: number): Mesh | null {\n return mergeGlyphMeshes(group, dx, dy, (glyph) => outlineMesh(glyph.key, glyph.d));\n}\n\n/**\n * The same merge for the group's stroke: one ribbon per glyph, tessellated in\n * em space and batched into one buffer, so a stroked paragraph is one extra\n * draw call rather than one per glyph.\n *\n * The width crosses into em space by dividing by the glyph's `scale`, which\n * is world units per em — so `stroke.width` stays a world-unit measure and\n * does not grow with `fontSize`, matching every other stroke in the kit.\n *\n * A synthetic oblique shears the ribbon along with the glyph. That is a real\n * (small) distortion — a sheared circle is an ellipse, so the outline is\n * marginally thicker across the lean than along it — and it is deliberate:\n * shearing the finished ribbon is what keeps the outline glued to the glyph\n * it outlines, which re-tessellating in sheared space would not.\n */\nfunction outlineGroupStrokeMesh(\n group: LaidOutGroup,\n dx: number,\n dy: number,\n scale: number,\n): Mesh | null {\n const stroke = group.stroke;\n if (!stroke) return null;\n const width = resolveStrokeWidth(stroke.width ?? 1, scale);\n if (!(width > 0)) return null;\n return mergeGlyphMeshes(group, dx, dy, (glyph) =>\n glyph.scale > 0\n ? outlineStrokeMesh(glyph.key, glyph.d, quantizeEmWidth(width / glyph.scale), stroke)\n : null);\n}\n\n/**\n * Transform each glyph's em-space mesh into world space and concatenate.\n * Shared by the fill and stroke paths, which differ only in which mesh they\n * ask for per glyph — the placement math must not fork, or an outline would\n * drift off the glyph it outlines.\n */\nfunction mergeGlyphMeshes(\n group: LaidOutGroup,\n dx: number,\n dy: number,\n meshFor: (glyph: LaidOutOutlineGlyph) => Mesh | null,\n): Mesh | null {\n const parts: { mesh: Mesh; glyph: LaidOutOutlineGlyph }[] = [];\n let vertexFloats = 0;\n let indexCount = 0;\n for (const glyph of group.glyphs) {\n const mesh = meshFor(glyph);\n if (!mesh || mesh.indices.length === 0) continue;\n parts.push({ mesh, glyph });\n vertexFloats += mesh.vertices.length;\n indexCount += mesh.indices.length;\n }\n if (parts.length === 0) return null;\n\n // Matches the SDF vertex shader's skew exactly: x moves by\n // `(baselineY - y) * tan(angle)`, and in em space `baselineY - y` is\n // `-ey * scale`, so above-baseline vertices (negative ey) lean right.\n const shear = group.synthetic.italic ? Math.tan(SYNTHETIC_ITALIC_RADIANS) : 0;\n\n const vertices = new Float32Array(vertexFloats);\n const indices = new Uint32Array(indexCount);\n let vi = 0;\n let ii = 0;\n let base = 0;\n for (const { mesh, glyph } of parts) {\n const { x, baselineY, scale } = glyph;\n for (let k = 0; k < mesh.vertices.length; k += 2) {\n const ex = mesh.vertices[k];\n const ey = mesh.vertices[k + 1];\n vertices[vi++] = x + dx + (ex - ey * shear) * scale;\n vertices[vi++] = baselineY + dy + ey * scale;\n }\n for (let k = 0; k < mesh.indices.length; k++) indices[ii++] = base + mesh.indices[k];\n base += mesh.vertices.length / 2;\n }\n return { vertices, indices };\n}\n\n/**\n * Paint underline / strikethrough rules. These are untextured solid rects, so\n * they cannot ride in a `LaidOutGroup`'s quads — those upload a 5-float\n * stride with atlas UVs into an MSDF program. They go through `pathFill`\n * instead, batched by resolved color so a whole decorated paragraph costs\n * one draw call per distinct rule color.\n *\n * Drawn after the glyphs, so a rule sits on top of glyph ink where they\n * overlap (the CSS spec allows either order).\n */\n/**\n * Stage the rules an underline, strikethrough or overline asks for.\n *\n * Color resolution matches `drawTextGroup` exactly — including its ignoring\n * of `fill.opacity` — so a rule can never disagree with the glyphs it\n * underlines. They stage as ordinary rects, which is what keeps them in the\n * run their glyphs are in. A rule under a texture paint is geometry under it,\n * the way an outline glyph is.\n */\nfunction drawTextDecorations(\n ctx: DrawContext, decorations: readonly LaidOutDecoration[], dx: number, dy: number,\n): void {\n for (const d of decorations) {\n if (glyphPaintKindOf(d.fill) !== null) {\n drawOutlineMesh(ctx, d.fill, ruleMesh(d.x0 + dx, d.y0 + dy, d.x1 + dx, d.y1 + dy));\n continue;\n }\n const [r, g, b, a] = 'color' in d.fill ? resolveColor(d.fill.color) : [0, 0, 0, 1];\n const staged = stageSolid(ctx, 4);\n ctx.drawBatch.pushRect(\n d.x0 + dx, d.y0 + dy, d.x1 - d.x0, d.y1 - d.y0, ctx.state.transform,\n r, g, b, a * (staged.foldsAlpha ? ctx.state.alpha : 1),\n );\n }\n}\n\nfunction ruleMesh(x0: number, y0: number, x1: number, y1: number): Mesh {\n return {\n vertices: new Float32Array([x0, y0, x1, y0, x1, y1, x0, y1]),\n indices: new Uint32Array([0, 1, 2, 0, 2, 3]),\n };\n}\n\n/**\n * Amount `a_synthBold` shifts the SDF threshold by when the resolver fell back\n * from a missing bold variant to the regular atlas. Tuned on Inter: it\n * thickens strokes about a pixel at 16px without breaking glyph topology.\n */\nconst SYNTH_BOLD_AMOUNT = 0.08;\n\n/**\n * Stage one group of atlas glyphs into the batch.\n *\n * Everything that used to be a uniform per group rides the vertices instead —\n * the text color, and the atlas as a slot index packed with the paint mode — so\n * a run off a baked MSDF atlas and one off the runtime canvas bake belong to\n * the same draw, and so does whatever else the page put around them. The\n * synthetic-bold threshold is the exception, and `StagedBatchState.synthBold`\n * says why.\n *\n * The synthetic oblique is the one that changes shape rather than home: the\n * old program skewed in the vertex stage against `u_synthItalic`, and the\n * batch places its own corners, so `pushGlyph` shears them as it places them.\n */\nfunction drawTextGroup(\n ctx: DrawContext, group: LaidOutGroup, dx: number, dy: number,\n): void {\n if (group.source === 'canvas') {\n if (!syncDynamicPageTexture(ctx.textureCache, group.page)) return;\n } else {\n if (!ensureFontTexture(group.family, group.weight, group.style, ctx.textureCache)) return;\n }\n if (group.quads.length === 0) return;\n\n const atlasId = group.source === 'canvas'\n ? dynamicPageTextureId(group.page)\n : textureCacheKey(group.family, group.weight, group.style);\n const mode = group.source === 'canvas' ? GLYPH_MODE_R8 : GLYPH_MODE_MSDF;\n const fieldScale = glyphFieldScale(\n group.source === 'canvas' ? 'canvas' : 'atlas', group.family, group.weight, group.style,\n );\n if (!fieldScale) return;\n const bold = group.synthetic.bold ? SYNTH_BOLD_AMOUNT : 0;\n const tanItalic = group.synthetic.italic ? Math.tan(SYNTHETIC_ITALIC_RADIANS) : 0;\n const paintKind = glyphPaintKindOf(group.fill);\n if (paintKind !== null) {\n drawPaintedGlyphs(ctx, group, dx, dy, paintKind, atlasId, mode, bold, tanItalic, fieldScale);\n return;\n }\n const color = group.fill !== null && 'color' in group.fill\n ? resolveColor(group.fill.color)\n : [0, 0, 0, 1];\n\n const batch = ctx.drawBatch;\n const m = ctx.state.transform;\n let { staged, slot } = stageGlyphs(ctx, atlasId, fieldScale, bold);\n let alpha = color[3] * (staged.foldsAlpha ? ctx.state.alpha : 1);\n\n for (const q of group.quads) {\n if (batch.wouldOverflow(4)) {\n flushBatch(ctx);\n ({ staged, slot } = stageGlyphs(ctx, atlasId, fieldScale, bold));\n alpha = color[3] * (staged.foldsAlpha ? ctx.state.alpha : 1);\n }\n batch.pushGlyph(\n q.x0 + dx, q.y0 + dy, q.x1 + dx, q.y1 + dy, q.baselineY + dy, tanItalic, m,\n q.u0, q.v0, q.u1, q.v1,\n color[0], color[1], color[2], alpha,\n slot, mode,\n );\n }\n}\n\n/** Which glyph-paint program `fill` needs, or `null` for a paint the batch\n * draws as one color. */\nfunction glyphPaintKindOf(fill: FillStyle | null): GlyphPaintKind | null {\n const kind = fill?.fill ?? 'solid';\n if (kind === 'pattern') return 'pattern';\n if (kind === 'linear-gradient' || kind === 'radial-gradient' || kind === 'conic-gradient') {\n return 'gradient';\n }\n return kind === 'solid' ? null : 'texture';\n}\n\n/** The atlas's unit while a glyph-paint run draws; the paint has unit 0. */\nconst GLYPH_PAINT_ATLAS_UNIT = 1;\n\n/**\n * Draw one group of atlas glyphs with a texture paint, its coverage masking\n * the paint — see `shaders/glyphPaint.ts`.\n *\n * Its own draw, as a pattern-filled path is: the glyph vertex has no room for\n * a paint coordinate beside its atlas one, and widening it would cost every\n * vertex in every run. The quads still stage through `DrawBatch`, drained\n * first, and are drawn from it here before anything else can stage behind\n * them, so no run ever holds them and nothing outside this function has to\n * know they exist.\n */\nfunction drawPaintedGlyphs(\n ctx: DrawContext, group: LaidOutGroup, dx: number, dy: number,\n kind: GlyphPaintKind, atlasId: string, mode: number, bold: number, tanItalic: number,\n fieldScale: readonly [number, number],\n): void {\n const prog = ctx.glyphPaintProgram?.(kind);\n if (!prog) return;\n flushBatch(ctx);\n const fill = group.fill!;\n const m = ctx.state.transform;\n let bound: ShaderProgram | null;\n if (kind === 'pattern') {\n bound = bindPattern(ctx, prog, fill as Extract<FillStyle, { fill: 'pattern' }>, BATCH_MODEL);\n } else if (kind === 'gradient') {\n bound = bindGradient(ctx, prog, fill as Extract<FillStyle, { fill: 'linear-gradient' | 'radial-gradient' | 'conic-gradient' }>, BATCH_MODEL);\n } else {\n const painted = renderPaintToScratch(ctx, fill, glyphScreenBounds(group, dx, dy, tanItalic, m));\n bound = painted && bindScratchPaint(ctx, prog, painted);\n }\n if (!bound) return;\n const gl = ctx.gl;\n ctx.textureCache.bind(atlasId, GLYPH_PAINT_ATLAS_UNIT);\n gl.uniform1i(prog.uniform('u_atlas')!, GLYPH_PAINT_ATLAS_UNIT);\n gl.uniform1f(prog.uniform('u_synthBold')!, bold);\n gl.uniform2f(prog.uniform('u_fieldScale')!, fieldScale[0], fieldScale[1]);\n applyClipTest(ctx);\n\n const batch = ctx.drawBatch;\n for (const q of group.quads) {\n if (batch.wouldOverflow(4)) drawStagedGlyphs(ctx);\n batch.pushGlyph(\n q.x0 + dx, q.y0 + dy, q.x1 + dx, q.y1 + dy, q.baselineY + dy, tanItalic, m,\n q.u0, q.v0, q.u1, q.v1,\n 1, 1, 1, 1,\n GLYPH_PAINT_ATLAS_UNIT, mode,\n );\n }\n drawStagedGlyphs(ctx);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindVertexArray(null);\n}\n\nfunction drawStagedGlyphs(ctx: DrawContext): void {\n const batch = ctx.drawBatch;\n if (batch.length === 0) return;\n drawTriangles(ctx, batch.uploadAndBind(), ctx.gl.UNSIGNED_INT);\n batch.reset();\n}\n\ninterface ScreenRect { x0: number; y0: number; x1: number; y1: number }\n\n/** The screen-space box of a group's glyph quads, corner for corner as\n * `DrawBatch.pushGlyph` places them. */\nfunction glyphScreenBounds(\n group: LaidOutGroup, dx: number, dy: number, tanItalic: number, m: GlMat3,\n): ScreenRect {\n const b = { x0: Infinity, y0: Infinity, x1: -Infinity, y1: -Infinity };\n const add = (x: number, y: number) => {\n const sx = m[0] * x + m[3] * y + m[6];\n const sy = m[1] * x + m[4] * y + m[7];\n if (sx < b.x0) b.x0 = sx;\n if (sx > b.x1) b.x1 = sx;\n if (sy < b.y0) b.y0 = sy;\n if (sy > b.y1) b.y1 = sy;\n };\n for (const q of group.quads) {\n const x0 = q.x0 + dx, x1 = q.x1 + dx, y0 = q.y0 + dy, y1 = q.y1 + dy;\n const base = q.baselineY + dy;\n const top = (base - y0) * tanItalic;\n const bottom = (base - y1) * tanItalic;\n add(x0 + top, y0);\n add(x1 + top, y0);\n add(x1 + bottom, y1);\n add(x0 + bottom, y1);\n }\n return b;\n}\n\n/** The unit square, stretched over the region a scratch paint covers. */\nconst UNIT_QUAD: Mesh = {\n vertices: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),\n indices: new Uint32Array([0, 1, 2, 0, 2, 3]),\n};\n\ninterface ScratchPaint {\n texture: WebGLTexture;\n /** Screen position → the texture coordinate the paint landed at there. */\n uvFromScreen: GlMat3;\n}\n\n/**\n * Render a registered kind's paint over `rect` (screen px) into the renderer's\n * scratch buffer, through the kind's own `bind` — so any kind that paints a\n * path paints this, with nothing asked of it beyond what a path asks.\n *\n * The region is snapped out to the device-pixel grid and clamped to the\n * drawing buffer, so each texel is one device pixel of the target and a glyph\n * fragment reads its own. The kind sees the same transform, alpha and paint\n * space it would for a path here; only the projection differs, aimed at the\n * scratch buffer instead of the target. No clip and no scissor apply inside:\n * the glyphs that sample the result are drawn under both.\n *\n * `null` when there is no scratch buffer, the region is empty, or the kind\n * declines the paint — and the glyphs then draw nothing, as the outline tier\n * does for a paint no kind binds.\n */\nfunction renderPaintToScratch(ctx: DrawContext, fill: FillStyle, rect: ScreenRect): ScratchPaint | null {\n const scratch = ctx.paintScratch;\n const bind = getPaintKind(fill.fill)?.bind;\n if (!scratch || !bind) return null;\n const ratio = ctx.deviceWidth && ctx.widthCss > 0 ? ctx.deviceWidth / ctx.widthCss : 1;\n const deviceW = ctx.deviceWidth ?? Math.round(ctx.widthCss);\n const deviceH = ctx.deviceHeight ?? Math.round(ctx.heightCss);\n const px0 = Math.max(0, Math.floor(rect.x0 * ratio));\n const py0 = Math.max(0, Math.floor(rect.y0 * ratio));\n const maxSide = ctx.imageCache.maxTextureSide;\n const pw = Math.min(maxSide, Math.min(deviceW, Math.ceil(rect.x1 * ratio)) - px0);\n const ph = Math.min(maxSide, Math.min(deviceH, Math.ceil(rect.y1 * ratio)) - py0);\n if (!(pw > 0 && ph > 0)) return null;\n\n // The region in screen px, and the two matrices a kind's vertex stage\n // multiplies: the unit quad onto it, and it onto the whole of clip space.\n const x0 = px0 / ratio, y0 = py0 / ratio, w = pw / ratio, h = ph / ratio;\n const model = new Float32Array([w, 0, 0, 0, h, 0, x0, y0, 1]);\n const proj = new Float32Array([2 / w, 0, 0, 0, 2 / h, 0, -1 - (2 * x0) / w, -1 - (2 * y0) / h, 1]);\n const base = paintBindContext(ctx);\n const bindCtx: PaintBindContext = {\n ...base,\n alpha: ctx.state.alpha,\n maxTextureSize: base.maxTextureSize,\n setProjAndModel: (prog) => setProjAndModel(ctx, prog, model, proj),\n };\n\n const gl = ctx.gl;\n const target = scratch.acquire(pw, ph);\n const scissorWasOn = gl.isEnabled(gl.SCISSOR_TEST);\n // The last glyph pass left this texture bound to unit 0; a kind sampling a\n // unit it never binds would read the buffer it is drawing into.\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.bindFramebuffer(gl.FRAMEBUFFER, target.fbo);\n gl.viewport(0, 0, pw, ph);\n gl.disable(gl.SCISSOR_TEST);\n gl.disable(gl.STENCIL_TEST);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.disable(gl.BLEND);\n\n const prog = bind(bindCtx, fill);\n if (prog) {\n gl.bindVertexArray(ctx.meshCache.uploadRecurring(UNIT_QUAD).vao);\n drawTriangles(ctx, UNIT_QUAD.indices.length, gl.UNSIGNED_INT);\n gl.bindVertexArray(null);\n }\n\n gl.enable(gl.BLEND);\n returnToRenderTarget(ctx, deviceW, deviceH, scissorWasOn);\n if (!prog) return null;\n return {\n texture: target.texture,\n uvFromScreen: new Float32Array([\n ratio / target.width, 0, 0,\n 0, ratio / target.height, 0,\n -px0 / target.width, -py0 / target.height, 1,\n ]),\n };\n}\n\n/** Bind the glyph program to sample `painted` as its paint. */\nfunction bindScratchPaint(ctx: DrawContext, prog: ShaderProgram, painted: ScratchPaint): ShaderProgram {\n const gl = ctx.gl;\n gl.useProgram(prog.handle);\n setProjAndModel(ctx, prog, BATCH_MODEL);\n gl.uniformMatrix3fv(prog.uniform('u_worldInv')!, false, painted.uvFromScreen);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, painted.texture);\n gl.uniform1i(prog.uniform('u_sampler')!, 0);\n return prog;\n}\n\n/**\n * Stage one image quad. Nothing reaches the GPU here — `flushBatch` draws the\n * run this joins.\n *\n * The upload has to happen now rather than at flush: a run is keyed on bitmap\n * identity, and `flushBatch` binds a texture it assumes already exists.\n */\nfunction drawImage(ctx: DrawContext, cmd: ImageDrawCommand): void {\n ctx.imageCache.upload(cmd.image, cmd.image);\n const { staged, slot } = stageImage(ctx, cmd.image, cmd.sampling ?? 'linear');\n\n // Sampling window: the whole bitmap unless `source` narrows it, with the\n // flips applied by swapping the ends rather than moving the quad.\n const src = cmd.source;\n let u0 = 0, v0 = 0, u1 = 1, v1 = 1;\n if (src) {\n const tw = cmd.image.width, th = cmd.image.height;\n u0 = src.x / tw; u1 = (src.x + src.w) / tw;\n v0 = src.y / th; v1 = (src.y + src.h) / th;\n }\n if (cmd.flipX) { const t = u0; u0 = u1; u1 = t; }\n if (cmd.flipY) { const t = v0; v0 = v1; v1 = t; }\n\n ctx.drawBatch.pushQuad(\n cmd.x, cmd.y, cmd.w, cmd.h, ctx.state.transform,\n u0, v0, u1, v1,\n // Group alpha rides the vertices only where it rode the solid colors too:\n // with a real color matrix in the run it is `u_alpha`, and folding it here\n // as well would apply it twice.\n (cmd.opacity ?? 1) * (staged.foldsAlpha ? ctx.state.alpha : 1),\n slot,\n );\n}\n\n/**\n * Stage a packed run of sprites. The same staging `drawImage` does, minus a\n * command object per quad — see `SpritesDrawCommand`.\n *\n * The run is opened once and reopened only when the per-flush cap forces a\n * chunk, so the state check that costs a command its own run happens twice in\n * a frame rather than twenty thousand times.\n */\nfunction drawSprites(ctx: DrawContext, cmd: SpritesDrawCommand): void {\n const data = cmd.sprites;\n const count = Math.floor(data.length / SPRITE_STRIDE);\n if (count === 0) return;\n\n ctx.imageCache.upload(cmd.image, cmd.image);\n const sampling = cmd.sampling ?? 'linear';\n let { staged, slot } = stageImage(ctx, cmd.image, sampling);\n\n const batch = ctx.drawBatch;\n const m = ctx.state.transform;\n let groupAlpha = staged.foldsAlpha ? ctx.state.alpha : 1;\n const tw = cmd.image.width;\n const th = cmd.image.height;\n\n for (let s = 0, i = 0; s < count; s++, i += SPRITE_STRIDE) {\n if (batch.wouldOverflow(4)) {\n flushBatch(ctx);\n ({ staged, slot } = stageImage(ctx, cmd.image, sampling));\n groupAlpha = staged.foldsAlpha ? ctx.state.alpha : 1;\n }\n const sx = data[i + 4], sy = data[i + 5], sw = data[i + 6], sh = data[i + 7];\n batch.pushQuad(\n data[i], data[i + 1], data[i + 2], data[i + 3], m,\n sx / tw, sy / th, (sx + sw) / tw, (sy + sh) / th,\n data[i + 8] * groupAlpha, slot,\n );\n }\n}\n\nexport { mat3, getMesh };\n"],"mappings":"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"}
1
+ {"version":3,"file":"draw.js","names":["drawTriangles","ctx","count","type","FRAME_UPLOADS","FRAME_PROJ","uploadedFor","byProgram","uploaded","prog","sameValues","prev","next","i","setColorUniform","loc","r","g","b","setAlphaUniform","alpha","BATCH_MODEL","mat3","projFor","proj","COLOR_MATRIX_SCRATCH","setColorMatrixUniforms","gl","mLoc","row","col","cm","bLoc","bias","fillMesh","getMesh","path","tessellate","meshHandle","mesh","fillMeshHandle","dispatch","cmd","drawGroup","drawPath","drawText","drawImage","drawSprites","flushForOwnDraw","drawShader","warnedUniforms","warnOnceUniform","key","programId","name","setUniform","value","handle","entry","getTexture","unit","textureCache","arr","ARRAY_UPLOADS","isArrayValue","setUniformArray","isDev","upload","fn","setUniforms","uniforms","program","nextTexUnit","programRegistry","quadVbo","quadIbo","aPosLoc","aUvLoc","uProj","uBounds","uView","applyClipTest","drawGroupWithEffects","parentTarget","parentClipDepth","parentClipStack","parentBatchClip","scissorWasOn","front","targets","width","height","composited","child","flushBatch","effect","back","drawFullscreenQuad","returnToRenderTarget","composite","COMPOSITE_PROGRAM_ID","target","aPos","aUv","texture","source","resolution","texel","pending","n","leaveClip","enterClip","transform","rect","axisAlignedClipRect","depth","pushClip","popClip","syncBatchClip","materializeClips","intersectClipRects","runClipDepth","stack","enterUncut","cut","leaveUncut","retryUncut","a","drawPathFill","drawPathStroke","fill","isSolid","hasVColors","solid","paint","batchPaint","pushRampRect","pushRect","tryStageFill","drawPathFillVColor","drawPathFillStencil","drawPathFillByKind","SAMPLER_UNITS","BATCH_TEXTURE_SLOTS","FIELD_SCALES","isIdentityColorMatrix","IDENTITY_COLOR_MATRIX","stagedStateIsLive","staged","synthBold","image","slotForBitmap","sampling","colorMatrix","nextFreeSlot","slotForRamps","slotForAtlas","id","MAX_BATCHED_MESH_VERTICES","canBatchMesh","stageSolid","vertices","openRun","foldsAlpha","stageImage","slot","stageGlyphs","atlasId","stageRamps","stops","space","stagedAlpha","opacity","stagedColor","resolveColor","pushMesh","kind","grad","gradientMap","ramp","PAINT_MODE_PLAIN","linearRampUV","PAINT_MODE_RADIAL","radialRampUV","PAINT_MODE_CONIC","conicRampUV","inverse","gradientSpaceInverse","units","dx","dy","len","k","cos","sin","dx0","dy0","rampVertices","rowV","uv","post","pushRampMesh","batch","indexCount","setProjAndModel","expandAnchorColors","aA","aB","aT","perAnchor","out","a4","b4","t","setSolidPaintUniforms","expanded","colorVbo","aVColorLoc","model","color","bindPathFillByKind","bindPathFillSolid","bindPathFillPattern","bindPathFillGradient","bind","getPaintKind","paintBindContext","cached","BIND_CONTEXTS","made","spaceToDevice","unownedPaintResources","UNOWNED_RESOURCES","createPaintResources","bindPattern","tex","tileSpace","patternTileSpace","tw","th","textureSize","w","h","toScreen","ratio","bindGradient","mask","ancestorMask","rasterizePathToStencil","ancestors","newDepth","newBit","ref","oldDepth","oldBit","clipMask","withResolvedStrokeLengths","stroke","isPxMarker","markerStart","markerMid","markerEnd","scale","resolved","resolveStrokeWidth","quantizeStrokeScale","resolvedMarker","resolveMarkerSize","rawCmd","align","drawPathStrokeStenciled","drawPathStrokeUnclipped","marker","cachedMarkerCommands","strokeMesh","batched","DOUBLED_VERTEX_WIDTHS","doubledVertexWidths","doubled","widths","widerStroke","useVColor","fillHandle","ribbonMesh","ribbonHandle","ribbonProg","OUTLINE_MIN_SCREEN_PX","modelScale","sx","m","sy","style","resolveTextStyle","lineHeight","maxWidth","minScreen","outlineMinSize","laid","cachedLayoutRuns","verticalAlignOffset","group","drawTextOutlineGroup","drawTextGroup","outlineGroupMesh","drawOutlineMesh","strokePaint","ribbon","outlineGroupStrokeMesh","mergeGlyphMeshes","outlineMesh","glyph","outlineStrokeMesh","quantizeEmWidth","parts","vertexFloats","meshFor","shear","SYNTHETIC_ITALIC_RADIANS","indices","vi","ii","base","ex","ey","x","baselineY","drawTextDecorations","d","decorations","glyphPaintKindOf","ruleMesh","x0","y0","x1","y1","SYNTH_BOLD_AMOUNT","syncDynamicPageTexture","ensureFontTexture","dynamicPageTextureId","textureCacheKey","mode","GLYPH_MODE_R8","GLYPH_MODE_MSDF","fieldScale","glyphFieldScale","bold","tanItalic","paintKind","q","GLYPH_PAINT_ATLAS_UNIT","drawPaintedGlyphs","bound","painted","renderPaintToScratch","glyphScreenBounds","bindScratchPaint","drawStagedGlyphs","add","y","top","bottom","UNIT_QUAD","scratch","deviceW","deviceH","px0","py0","maxSide","pw","ph","bindCtx","src","u0","v0","u1","v1","data","SPRITE_STRIDE","groupAlpha","s","sw","sh"],"sources":["../../src/renderer/draw.ts"],"sourcesContent":["import type { ColorSpace, Stroke, FillStyle, GradientUnits, GradStop, MarkerRef } from '@weasel-js/paint';\nimport type { Path } from '@weasel-js/core';\nimport { getPaintKind } from 'core/paintKinds';\nimport type { PaintBindContext, PaintResources } from 'core/paintKinds';\nimport { createPaintResources } from './paintResources';\nimport { resolveTextStyle } from '@weasel-js/text';\nimport type {\n DrawCommand,\n GroupDrawCommand,\n PathDrawCommand,\n TextDrawCommand,\n ImageDrawCommand,\n SpritesDrawCommand,\n ShaderDrawCommand,\n} from './DrawCommand';\nimport { SPRITE_STRIDE } from './DrawCommand';\nimport { getTexture, type TextureHandle } from './textures/registerTexture';\nimport type { ShaderUniform } from './shaders/registerProgram';\nimport { IDENTITY_COLOR_MATRIX, type GroupState } from './state/GroupState';\nimport type { GLMeshCache, GLMeshHandle } from './cache/GLMeshCache';\nimport type { GLTextureCache } from './cache/GLTextureCache';\nimport type { GLImageCache } from './cache/GLImageCache';\nimport type { GradientRampAtlas } from './cache/GradientRampAtlas';\nimport type { ShaderProgram, UniformArray } from './shaders/ShaderProgram';\nimport { mat3, type GlMat3 } from './math/mat3';\nimport { patternTileSpace } from './math/patternSpace';\nimport { getMesh } from './cache/cache';\nimport { tessellate, type Mesh } from '@weasel-js/geom/tessellate';\nimport { resolveStrokeWidth } from 'features/paths/tessellate/stroke';\nimport { resolveColor } from './math/color';\nimport {\n ensureFontTexture,\n textureCacheKey,\n syncDynamicPageTexture,\n dynamicPageTextureId,\n GLYPH_MODE_MSDF,\n GLYPH_MODE_R8,\n glyphFieldScale,\n} from '@weasel-js/font';\nimport {\n type LaidOutGroup, type LaidOutDecoration, type LaidOutOutlineGlyph,\n} from '@weasel-js/text';\nimport { verticalAlignOffset, cachedLayoutRuns } from '@weasel-js/text';\nimport { outlineMesh } from './cache/outlineMeshCache';\nimport { outlineStrokeMesh, quantizeEmWidth } from './cache/outlineStrokeMeshCache';\nimport { strokeMesh, quantizeStrokeScale } from './cache/strokeMeshCache';\nimport { cachedMarkerCommands } from './cache/markerCommandCache';\nimport { resolveMarkerSize } from '../core/markerInset';\nimport { DrawBatch, type GradientUV } from './drawBatch';\nimport { axisAlignedClipRect, intersectClipRects, type ClipRect } from './batchClip';\nimport {\n BATCH_TEXTURE_SLOTS, PAINT_MODE_PLAIN, PAINT_MODE_RADIAL, PAINT_MODE_CONIC,\n} from './shaders/batchFill';\nimport type { EffectTarget, EffectTargets } from './effects/EffectTargets';\nimport type { PaintScratch } from './paintScratch';\nimport { COMPOSITE_PROGRAM_ID } from './effects/composite';\nimport { SYNTHETIC_ITALIC_RADIANS } from './syntheticItalic';\n\nexport interface DrawContext {\n gl: WebGL2RenderingContext;\n pathFill: ShaderProgram;\n pathFillVColor: ShaderProgram;\n imageFill: ShaderProgram;\n /** The one program a batch flush draws with — `shaders/batchFill.ts`. */\n batchFill: ShaderProgram;\n gradFill: ShaderProgram;\n patternFill: ShaderProgram;\n meshCache: GLMeshCache;\n textureCache: GLTextureCache;\n imageCache: GLImageCache;\n gradRamps: GradientRampAtlas;\n programRegistry: Map<string, ShaderProgram>;\n /** Compile-on-first-use for a registered paint kind's program. Absent when\n * a caller drives `dispatch` without a renderer behind it. */\n ensureProgram?(id: string): ShaderProgram | null;\n /** The program atlas glyphs under a texture paint draw with, compiled on\n * first use. Absent without a renderer behind the context, and then such\n * glyphs draw nothing. */\n glyphPaintProgram?(kind: GlyphPaintKind): ShaderProgram;\n quadVbo: WebGLBuffer | null;\n quadIbo: WebGLBuffer | null;\n /** Staging for the batch. Draws are deferred into it, so a caller driving\n * `dispatch` itself must `flushBatch` when the stream ends. */\n drawBatch: DrawBatch;\n /** Group state the staged run was built under, and what it samples;\n * `undefined` while nothing is staged. Written only by the push helpers\n * and `flushBatch`. */\n batchState?: StagedBatchState;\n /** 1x1 white texture, bound for a flush that samples no image so a solid\n * vertex's `texture() * color` is its color. */\n whiteTexture: WebGLTexture | null;\n state: GroupState;\n widthCss: number;\n heightCss: number;\n /**\n * Current clip nesting depth. Tracked as a flat scalar on DrawContext (not\n * part of GroupState's per-frame stack) because it must survive pop() during\n * drawGroup teardown — we decrement it manually after popClip. Starts at 0;\n * incremented/decremented symmetrically by drawGroup around cmd.clip pushes.\n */\n clipDepth: number;\n /** The clips of the groups drawing now, outermost first. See `enterClip`. */\n clipStack: ClipEntry[];\n /** Set while `enterUncut` stages an item the rect clips could not cut. */\n uncut?: boolean;\n /** Flatness tolerance for curve tessellation, in WORLD units. When set,\n * fill meshes bypass the Path-identity cache (whose key excludes\n * tolerance) and are tessellated fresh per frame via the transient pool.\n * See `WeaselRendererOptions.flattenTolerance`. */\n flattenTolerance?: number;\n /** On-screen glyph size (CSS px) at which text switches to tessellated\n * outlines. See `WeaselRendererOptions.textOutlineMinScreenSize`. */\n textOutlineMinScreenSize?: number;\n /** World→screen transform for the frame, when the caller supplied one.\n * Only `units: 'world'` gradients read it; absent, they fall back to\n * screen space. See `WeaselRenderer.render`. */\n viewMatrix?: GlMat3;\n /** Offscreen buffers for group effects. Absent when a caller drives\n * `dispatch` without a renderer behind it, in which case a group's\n * `effects` are skipped and its children draw straight through — the same\n * answer an unregistered effect program gets, and the one that keeps a\n * frame on screen. */\n effectTargets?: EffectTargets;\n /** Where this renderer is currently drawing. `null` is the default\n * framebuffer. Tracked here rather than read back with `getParameter`\n * because a group's effects nest, and each has to restore its parent's. */\n renderTarget?: EffectTarget | null;\n /** Device-pixel size of the drawing buffer, which is what an offscreen\n * target is sized to. */\n deviceWidth?: number;\n deviceHeight?: number;\n /** Put the viewport and scissor back to the renderer's own rect after a\n * group's effects have borrowed them for a full-buffer pass. The renderer\n * owns that rect — see `WeaselRenderer.applyTarget` — and a second copy of\n * its y-flip here would be a second thing to keep in step. */\n restoreTargetRect?(): void;\n /** Where a registered paint kind renders for atlas glyphs to sample. Absent\n * without a renderer behind the context, and then such glyphs draw\n * nothing. */\n paintScratch?: PaintScratch;\n /** The lifetime a registered paint kind's GPU state belongs to. Absent\n * when a caller drives `dispatch` without a renderer behind it, in which\n * case one per context stands in and is never released. */\n paintResources?: PaintResources;\n /** Per-frame counters the renderer reads back after the stream ends.\n * Absent, nothing is counted. */\n stats?: { drawCalls: number };\n}\n\n/** One clipped group's clip, while its children draw. */\nexport interface ClipEntry {\n path: Path;\n /** The group's transform, which `path` is in. */\n transform: GlMat3;\n /** Where staged geometry is cut, for a clip that is an axis-aligned rect;\n * `null` for one only the stencil can express. */\n rect: ClipRect | null;\n /** The stencil bit this clip holds, or 0 while it holds none. */\n depth: number;\n}\n\n/** The paints atlas glyphs draw through a program of their own: `texture` is\n * a registered kind, which renders into `paintScratch` for the glyphs to\n * sample. */\nexport type GlyphPaintKind = 'pattern' | 'gradient' | 'texture';\n\n/** Every GL draw the renderer issues goes through here, so the frame's\n * draw-call count cannot miss one. */\nfunction drawTriangles(ctx: DrawContext, count: number, type: number): void {\n ctx.gl.drawElements(ctx.gl.TRIANGLES, count, type, 0);\n if (ctx.stats) ctx.stats.drawCalls++;\n}\n\n/**\n * Upload the cumulative color matrix from GroupState to a shader's\n * `u_colorMatrix` (mat4) and `u_colorBias` (vec4) uniforms. Splits the 4×5\n * row-major form into a column-major mat4 + vec4 bias. Used by every shader\n * that accepts the group color matrix: pathFill, pathFillVColor, imageFill,\n * batchFill.\n */\n/**\n * Uniform values a program already holds this frame.\n *\n * GL keeps uniform state per program object, so re-sending a value the program\n * already has buys nothing. `u_proj` is constant for the whole frame and\n * `u_colorMatrix` is the identity in every scene that does not use one, yet\n * both were re-sent for every command: at a few thousand commands the two were\n * most of the frame.\n *\n * Keyed on the `DrawContext`, which `WeaselRenderer.render` builds fresh per\n * frame, so the cache cannot outlive a frame and go stale against GL state\n * that changed between them.\n *\n * **Only for uniforms this module is the sole writer of.** `u_color` and\n * `u_alpha` qualify because every write of them goes through `setColorUniform`\n * / `setAlphaUniform` — keep it that way. A `gl.uniform4f(… 'u_color' …)` added\n * anywhere else leaves the cache believing a value the program no longer has,\n * and the wrong color is drawn until something else moves it.\n */\ninterface UploadedUniforms {\n proj?: Float32Array;\n model?: Float32Array;\n colorMatrix?: Float32Array;\n colorBias?: Float32Array;\n /** Held as plain numbers, not a `Float32Array`: the caller's values are\n * doubles, and round-tripping them through float32 would compare unequal\n * every time and never skip an upload. */\n color?: [number, number, number, number];\n alpha?: number;\n}\n\nconst FRAME_UPLOADS = new WeakMap<DrawContext, WeakMap<ShaderProgram, UploadedUniforms>>();\nconst FRAME_PROJ = new WeakMap<DrawContext, GlMat3>();\n\nfunction uploadedFor(ctx: DrawContext, prog: ShaderProgram): UploadedUniforms {\n let byProgram = FRAME_UPLOADS.get(ctx);\n if (!byProgram) {\n byProgram = new WeakMap();\n FRAME_UPLOADS.set(ctx, byProgram);\n }\n let uploaded = byProgram.get(prog);\n if (!uploaded) {\n uploaded = {};\n byProgram.set(prog, uploaded);\n }\n return uploaded;\n}\n\n/** Element-wise, so a caller that mutates a shared array in place is still\n * compared by value. A NaN anywhere compares unequal and re-uploads, which is\n * the safe direction. */\nfunction sameValues(prev: Float32Array | undefined, next: ArrayLike<number>): boolean {\n if (prev === undefined || prev.length !== next.length) return false;\n for (let i = 0; i < prev.length; i++) if (prev[i] !== next[i]) return false;\n return true;\n}\n\n/**\n * `u_color`, skipped when the program already holds it.\n *\n * Every writer of `u_color` goes through here — see `UploadedUniforms`. The\n * solid batch is what makes it worth caching: it holds the uniform at white\n * forever and flushed once per state change, so a mixed document re-sent the\n * same white a few hundred times a frame.\n */\nfunction setColorUniform(\n ctx: DrawContext, prog: ShaderProgram,\n r: number, g: number, b: number, a: number,\n): void {\n const loc = prog.uniform('u_color');\n if (loc === undefined) return;\n const uploaded = uploadedFor(ctx, prog);\n const prev = uploaded.color;\n if (prev !== undefined && prev[0] === r && prev[1] === g && prev[2] === b && prev[3] === a) {\n return;\n }\n ctx.gl.uniform4f(loc, r, g, b, a);\n uploaded.color = [r, g, b, a];\n}\n\n/** `u_alpha`, on the same terms as `setColorUniform`. */\nfunction setAlphaUniform(ctx: DrawContext, prog: ShaderProgram, alpha: number): void {\n const loc = prog.uniform('u_alpha');\n if (loc === undefined) return;\n const uploaded = uploadedFor(ctx, prog);\n if (uploaded.alpha === alpha) return;\n ctx.gl.uniform1f(loc, alpha);\n uploaded.alpha = alpha;\n}\n\n/** The rect batch transforms its own corners, so it draws at model identity. */\nconst BATCH_MODEL = mat3.identity();\n\n/** The screen→clip matrix depends only on the frame's dimensions. */\nfunction projFor(ctx: DrawContext): GlMat3 {\n let proj = FRAME_PROJ.get(ctx);\n if (!proj) {\n proj = mat3.screenToClip(ctx.widthCss, ctx.heightCss);\n FRAME_PROJ.set(ctx, proj);\n }\n return proj;\n}\n\n/** Reused across draws: the transpose below rebuilt this every command. */\nconst COLOR_MATRIX_SCRATCH = new Float32Array(16);\n\nfunction setColorMatrixUniforms(\n ctx: DrawContext, prog: ShaderProgram,\n cm: Float32Array = ctx.state.colorMatrix, // row-major 4×5\n): void {\n const gl = ctx.gl;\n const uploaded = uploadedFor(ctx, prog);\n\n const mLoc = prog.uniform('u_colorMatrix');\n if (mLoc !== undefined) {\n for (let row = 0; row < 4; row++) {\n for (let col = 0; col < 4; col++) {\n COLOR_MATRIX_SCRATCH[col * 4 + row] = cm[row * 5 + col];\n }\n }\n if (!sameValues(uploaded.colorMatrix, COLOR_MATRIX_SCRATCH)) {\n gl.uniformMatrix4fv(mLoc, false, COLOR_MATRIX_SCRATCH);\n uploaded.colorMatrix = Float32Array.from(COLOR_MATRIX_SCRATCH);\n }\n }\n\n const bLoc = prog.uniform('u_colorBias');\n if (bLoc !== undefined) {\n const bias = [cm[4], cm[9], cm[14], cm[19]];\n if (!sameValues(uploaded.colorBias, bias)) {\n gl.uniform4f(bLoc, bias[0], bias[1], bias[2], bias[3]);\n uploaded.colorBias = Float32Array.from(bias);\n }\n }\n}\n\n/**\n * Tessellate a fill honoring ctx.flattenTolerance: default route is the\n * persistent Path-identity cache; a custom tolerance tessellates fresh, because\n * the persistent cache's key does not include tolerance.\n */\nfunction fillMesh(ctx: DrawContext, path: Path): Mesh {\n if (ctx.flattenTolerance !== undefined) {\n return tessellate(path, { flattenTolerance: ctx.flattenTolerance });\n }\n return getMesh(path);\n}\n\n/** Upload a mesh for its own draw. A freshly tessellated one rides the\n * transient pool, freed at end of frame. */\nfunction meshHandle(ctx: DrawContext, mesh: Mesh): GLMeshHandle {\n if (ctx.flattenTolerance !== undefined) return ctx.meshCache.uploadTransient(mesh);\n return ctx.meshCache.handleFor(mesh);\n}\n\nfunction fillMeshHandle(ctx: DrawContext, path: Path): GLMeshHandle {\n return meshHandle(ctx, fillMesh(ctx, path));\n}\n\nexport function dispatch(ctx: DrawContext, cmd: DrawCommand): void {\n switch (cmd.kind) {\n case 'group': return drawGroup(ctx, cmd);\n case 'path': return drawPath(ctx, cmd);\n case 'text': return drawText(ctx, cmd);\n case 'image': return drawImage(ctx, cmd);\n case 'sprites': return drawSprites(ctx, cmd);\n case 'shader': flushForOwnDraw(ctx); return drawShader(ctx, cmd);\n }\n}\n\nconst warnedUniforms = new Set<string>();\nfunction warnOnceUniform(programId: string, name: string): void {\n const key = `${programId}:${name}`;\n if (warnedUniforms.has(key)) return;\n warnedUniforms.add(key);\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n if (isDev) {\n console.warn(`weasel drawShader: uniform \"${name}\" not found in program \"${programId}\". ` +\n `Check spelling, ensure it's used in the shader (unused uniforms are optimized away by the driver).`);\n }\n}\n\n/**\n * Bind a single ShaderUniform value to a GL uniform location.\n *\n * Type detection order:\n * 1. TextureHandle (object with string `.id`) — bind to next tex unit, set sampler.\n * 2. Float32Array — length 9 → mat3, length 16 → mat4. Other lengths throw in dev.\n * 3. Array — uniform2fv / uniform3fv / uniform4fv based on length.\n * 4. number — uniform1f.\n */\nexport function setUniform(\n gl: WebGL2RenderingContext,\n loc: WebGLUniformLocation,\n value: ShaderUniform,\n textureCache: GLTextureCache,\n nextTexUnit: { value: number },\n): void {\n if (value !== null && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Float32Array)\n && 'id' in value && typeof (value as TextureHandle).id === 'string') {\n const handle = value as TextureHandle;\n const entry = getTexture(handle.id);\n if (!entry) {\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n if (isDev) console.warn(`weasel setUniform: TextureHandle \"${handle.id}\" not registered`);\n return;\n }\n const unit = nextTexUnit.value++;\n textureCache.upload(handle.id, entry.source);\n textureCache.bind(handle.id, unit);\n gl.uniform1i(loc, unit);\n return;\n }\n\n if (value instanceof Float32Array) {\n if (value.length === 9) {\n gl.uniformMatrix3fv(loc, false, value);\n } else if (value.length === 16) {\n gl.uniformMatrix4fv(loc, false, value);\n } else {\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n if (isDev) throw new TypeError(`weasel setUniform: Float32Array must be length 9 (mat3) or 16 (mat4), got ${value.length}`);\n }\n return;\n }\n\n if (Array.isArray(value)) {\n const arr = value as readonly number[];\n switch (arr.length) {\n case 2: gl.uniform2fv(loc, arr as [number, number]); break;\n case 3: gl.uniform3fv(loc, arr as [number, number, number]); break;\n case 4: gl.uniform4fv(loc, arr as [number, number, number, number]); break;\n default: {\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n if (isDev) throw new TypeError(`weasel setUniform: array length ${arr.length} not supported`);\n }\n }\n return;\n }\n\n if (typeof value === 'number') {\n gl.uniform1f(loc, value);\n return;\n }\n}\n\n/** How an array's element type is uploaded: the `uniform*v` call and the\n * number of components per element. */\nconst ARRAY_UPLOADS: Readonly<Record<string, { fn: string; n: number; matrix?: true }>> = {\n float: { fn: 'uniform1fv', n: 1 }, vec2: { fn: 'uniform2fv', n: 2 },\n vec3: { fn: 'uniform3fv', n: 3 }, vec4: { fn: 'uniform4fv', n: 4 },\n int: { fn: 'uniform1iv', n: 1 }, ivec2: { fn: 'uniform2iv', n: 2 },\n ivec3: { fn: 'uniform3iv', n: 3 }, ivec4: { fn: 'uniform4iv', n: 4 },\n bool: { fn: 'uniform1iv', n: 1 }, bvec2: { fn: 'uniform2iv', n: 2 },\n bvec3: { fn: 'uniform3iv', n: 3 }, bvec4: { fn: 'uniform4iv', n: 4 },\n uint: { fn: 'uniform1uiv', n: 1 }, uvec2: { fn: 'uniform2uiv', n: 2 },\n uvec3: { fn: 'uniform3uiv', n: 3 }, uvec4: { fn: 'uniform4uiv', n: 4 },\n mat2: { fn: 'uniformMatrix2fv', n: 4, matrix: true },\n mat3: { fn: 'uniformMatrix3fv', n: 9, matrix: true },\n mat4: { fn: 'uniformMatrix4fv', n: 16, matrix: true },\n mat2x2: { fn: 'uniformMatrix2fv', n: 4, matrix: true },\n mat3x3: { fn: 'uniformMatrix3fv', n: 9, matrix: true },\n mat4x4: { fn: 'uniformMatrix4fv', n: 16, matrix: true },\n mat2x3: { fn: 'uniformMatrix2x3fv', n: 6, matrix: true },\n mat2x4: { fn: 'uniformMatrix2x4fv', n: 8, matrix: true },\n mat3x2: { fn: 'uniformMatrix3x2fv', n: 6, matrix: true },\n mat3x4: { fn: 'uniformMatrix3x4fv', n: 12, matrix: true },\n mat4x2: { fn: 'uniformMatrix4x2fv', n: 8, matrix: true },\n mat4x3: { fn: 'uniformMatrix4x3fv', n: 12, matrix: true },\n};\n\ntype ArrayValue = readonly number[] | Float32Array | Int32Array | Uint32Array;\n\nfunction isArrayValue(value: ShaderUniform): value is ArrayValue {\n return Array.isArray(value) || value instanceof Float32Array\n || value instanceof Int32Array || value instanceof Uint32Array;\n}\n\n/** Fill an array uniform from slot 0 with one call. Throws in dev on a value\n * that is not a whole number of elements or overruns the declaration. */\nfunction setUniformArray(\n gl: WebGL2RenderingContext,\n name: string,\n arr: UniformArray,\n value: ArrayValue,\n): void {\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n const upload = ARRAY_UPLOADS[arr.type];\n if (!upload) {\n if (isDev) console.warn(`weasel setUniform: array uniform \"${name}\" has type ${arr.type}, which cannot be written as a whole`);\n return;\n }\n if (value.length % upload.n !== 0 || value.length > upload.n * arr.size) {\n if (isDev) {\n throw new TypeError(\n `weasel setUniform: \"${name}\" is ${arr.type}[${arr.size}], so its value must hold a multiple of ${upload.n} `\n + `numbers, at most ${upload.n * arr.size}; got ${value.length}`,\n );\n }\n return;\n }\n if (value.length === 0) return;\n const fn = (gl as unknown as Record<string, (...args: unknown[]) => void>)[upload.fn];\n if (upload.matrix) fn.call(gl, arr.location, false, value);\n else fn.call(gl, arr.location, value);\n}\n\n/** Write every entry of a command's `uniforms` map. A key naming an array\n * uniform with an array value fills the array; anything else goes to the\n * location of that exact name. */\nfunction setUniforms(\n gl: WebGL2RenderingContext,\n program: ShaderProgram,\n programId: string,\n uniforms: Record<string, ShaderUniform>,\n textureCache: GLTextureCache,\n nextTexUnit: { value: number },\n): void {\n for (const [name, value] of Object.entries(uniforms)) {\n const arr = program.uniformArray(name);\n if (arr && isArrayValue(value)) {\n setUniformArray(gl, name, arr, value);\n continue;\n }\n const loc = program.uniform(name);\n if (loc === undefined) {\n warnOnceUniform(programId, name);\n continue;\n }\n setUniform(gl, loc, value, textureCache, nextTexUnit);\n }\n}\n\nfunction drawShader(ctx: DrawContext, cmd: ShaderDrawCommand): void {\n const { gl, programRegistry, quadVbo, quadIbo, textureCache } = ctx;\n\n const program = programRegistry.get(cmd.program.id);\n if (!program) {\n console.warn(\n `weasel drawShader: program \"${cmd.program.id}\" not compiled on this renderer. ` +\n `Call renderer.registerProgram(handle) after the module-level registerProgram().`,\n );\n return;\n }\n if (!quadVbo || !quadIbo) {\n console.warn('weasel drawShader: quad geometry not initialized');\n return;\n }\n\n gl.useProgram(program.handle);\n\n const aPosLoc = program.attribute('a_position');\n const aUvLoc = program.attribute('a_uv');\n\n gl.bindBuffer(gl.ARRAY_BUFFER, quadVbo);\n if (aPosLoc !== undefined) {\n gl.enableVertexAttribArray(aPosLoc);\n gl.vertexAttribPointer(aPosLoc, 2, gl.FLOAT, false, 16, 0);\n }\n if (aUvLoc !== undefined) {\n gl.enableVertexAttribArray(aUvLoc);\n gl.vertexAttribPointer(aUvLoc, 2, gl.FLOAT, false, 16, 8);\n }\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, quadIbo);\n\n const proj = mat3.screenToClip(ctx.widthCss, ctx.heightCss);\n const uProj = program.uniform('u_proj');\n if (uProj !== undefined) gl.uniformMatrix3fv(uProj, false, proj);\n\n const uBounds = program.uniform('u_bounds');\n if (uBounds !== undefined) {\n gl.uniform4f(uBounds, cmd.bounds.x, cmd.bounds.y, cmd.bounds.w, cmd.bounds.h);\n }\n\n const uView = program.uniform('u_view');\n if (uView !== undefined) gl.uniformMatrix3fv(uView, false, ctx.state.transform);\n\n setUniforms(gl, program, cmd.program.id, cmd.uniforms, textureCache, { value: 1 });\n\n applyClipTest(ctx);\n drawTriangles(ctx, 6, ctx.gl.UNSIGNED_SHORT);\n\n if (aPosLoc !== undefined) gl.disableVertexAttribArray(aPosLoc);\n if (aUvLoc !== undefined) gl.disableVertexAttribArray(aUvLoc);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n}\n\n/**\n * Draw a group's children into a buffer of their own, run its effects over\n * that buffer, and composite the result back where the group sits.\n *\n * Three things are deliberately not inherited by the offscreen render:\n *\n * - **The clip.** A fresh buffer's stencil is empty, so a child drawn at the\n * enclosing clip depth would test against bits that were never written and\n * paint nothing. The enclosing clip belongs on the composite anyway — it\n * clips the group's result, not the pixels an effect reads — so `clipDepth`\n * restarts at 0 inside, which also hands nested clips a fresh budget.\n * - **Alpha and color**, for the same reason from the other end: fading on\n * the way in would give the effect faded pixels to read, and fade them\n * again on the way out. `pushIsolated` returns what the composite owes.\n * - **The scissor**, which belongs to the renderer's sub-rect within the\n * default framebuffer and means nothing in a buffer sized to the whole\n * drawing buffer.\n */\nfunction drawGroupWithEffects(\n ctx: DrawContext,\n cmd: GroupDrawCommand,\n targets: EffectTargets,\n width: number,\n height: number,\n): void {\n const gl = ctx.gl;\n // Anything staged belongs to the parent's buffer, not this one, and the\n // composite below draws under the parent's clips.\n flushForOwnDraw(ctx);\n\n const parentTarget = ctx.renderTarget ?? null;\n const parentClipDepth = ctx.clipDepth;\n const parentClipStack = ctx.clipStack;\n const parentBatchClip = ctx.drawBatch.clip;\n const scissorWasOn = gl.isEnabled(gl.SCISSOR_TEST);\n\n let front = targets.acquire(width, height);\n const composited = ctx.state.pushIsolated({ transform: cmd.transform });\n ctx.clipDepth = 0;\n ctx.clipStack = [];\n ctx.drawBatch.clip = null;\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, front.fbo);\n ctx.renderTarget = front;\n gl.viewport(0, 0, width, height);\n gl.disable(gl.SCISSOR_TEST);\n gl.stencilMask(0xFF);\n gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);\n\n for (const child of cmd.children) dispatch(ctx, child);\n flushBatch(ctx);\n\n // Passes replace rather than blend: each writes every texel of its target\n // from the whole of its source.\n gl.disable(gl.BLEND);\n for (const effect of cmd.effects!) {\n const program = ctx.ensureProgram?.(effect.program.id) ?? null;\n if (!program) {\n warnOnceUniform(effect.program.id, '(program)');\n continue;\n }\n const back = targets.acquire(width, height);\n gl.bindFramebuffer(gl.FRAMEBUFFER, back.fbo);\n gl.viewport(0, 0, width, height);\n gl.clear(gl.COLOR_BUFFER_BIT);\n drawFullscreenQuad(ctx, program, front.texture, width, height, effect.uniforms,\n undefined, effect.program.id);\n targets.release(front);\n front = back;\n }\n gl.enable(gl.BLEND);\n\n // Back to the parent's buffer, and back under its rules.\n ctx.state.pop();\n ctx.clipDepth = parentClipDepth;\n ctx.clipStack = parentClipStack;\n ctx.drawBatch.clip = parentBatchClip;\n ctx.renderTarget = parentTarget;\n returnToRenderTarget(ctx, width, height, scissorWasOn);\n\n const composite = ctx.ensureProgram?.(COMPOSITE_PROGRAM_ID) ?? null;\n if (composite) {\n applyClipTest(ctx);\n drawFullscreenQuad(ctx, composite, front.texture, width, height, undefined, {\n alpha: composited.alpha,\n colorMatrix: composited.colorMatrix,\n });\n }\n targets.release(front);\n}\n\n/** Rebind `ctx.renderTarget` after an offscreen pass: a pooled target takes\n * the whole `width` × `height` buffer, the default framebuffer the renderer's\n * own rect and the scissor it had. */\nfunction returnToRenderTarget(\n ctx: DrawContext, width: number, height: number, scissorWasOn: boolean,\n): void {\n const gl = ctx.gl;\n const target = ctx.renderTarget ?? null;\n gl.bindFramebuffer(gl.FRAMEBUFFER, target ? target.fbo : null);\n if (target) {\n gl.viewport(0, 0, width, height);\n } else {\n ctx.restoreTargetRect?.();\n if (scissorWasOn) gl.enable(gl.SCISSOR_TEST);\n }\n}\n\n/** One pass: the kit quad, `u_source` bound to `texture`, and whatever else\n * the caller supplies. Leaves no attribute arrays or buffers bound. */\nfunction drawFullscreenQuad(\n ctx: DrawContext,\n program: ShaderProgram,\n texture: WebGLTexture,\n width: number,\n height: number,\n uniforms?: Record<string, ShaderUniform>,\n composite?: { alpha: number; colorMatrix: Float32Array },\n programId?: string,\n): void {\n const gl = ctx.gl;\n gl.useProgram(program.handle);\n\n const aPos = program.attribute('a_position');\n const aUv = program.attribute('a_uv');\n gl.bindBuffer(gl.ARRAY_BUFFER, ctx.quadVbo);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ctx.quadIbo);\n if (aPos !== undefined && aPos >= 0) {\n gl.enableVertexAttribArray(aPos);\n gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);\n }\n if (aUv !== undefined && aUv >= 0) {\n gl.enableVertexAttribArray(aUv);\n gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);\n }\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n const source = program.uniform('u_source');\n if (source !== undefined) gl.uniform1i(source, 0);\n const resolution = program.uniform('u_resolution');\n if (resolution !== undefined) gl.uniform2f(resolution, width, height);\n const texel = program.uniform('u_texel');\n if (texel !== undefined) gl.uniform2f(texel, 1 / width, 1 / height);\n\n if (composite) {\n const alpha = program.uniform('u_alpha');\n if (alpha !== undefined) gl.uniform1f(alpha, composite.alpha);\n setColorMatrixUniforms(ctx, program, composite.colorMatrix);\n }\n\n // Unit 0 is `u_source`; a consumer texture starts above it.\n if (uniforms) setUniforms(gl, program, programId ?? 'effect', uniforms, ctx.textureCache, { value: 1 });\n\n drawTriangles(ctx, 6, ctx.gl.UNSIGNED_SHORT);\n\n if (aPos !== undefined && aPos >= 0) gl.disableVertexAttribArray(aPos);\n if (aUv !== undefined && aUv >= 0) gl.disableVertexAttribArray(aUv);\n gl.bindBuffer(gl.ARRAY_BUFFER, null);\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n}\n\nexport function drawGroup(ctx: DrawContext, cmd: GroupDrawCommand): void {\n // A group with effects is a render-target boundary rather than another\n // accumulating frame. Without a renderer's buffer pool behind the context\n // there is nowhere to draw, so the effects are skipped and the children\n // paint straight through — a frame missing its blur, not a frame missing.\n if (cmd.effects && cmd.effects.length > 0 && ctx.effectTargets\n && ctx.deviceWidth && ctx.deviceHeight) {\n drawGroupWithEffects(ctx, cmd, ctx.effectTargets, ctx.deviceWidth, ctx.deviceHeight);\n return;\n }\n ctx.state.push({\n transform: cmd.transform,\n alpha: cmd.alpha,\n colorMatrix: cmd.colorMatrix,\n });\n if (cmd.clip) {\n const pending = ctx.clipStack.reduce((n, e) => n + (e.depth === 0 ? 1 : 0), 0);\n if (ctx.clipDepth + pending + 1 > 7) {\n ctx.state.pop();\n throw new Error(\n 'weasel: clip nesting depth exceeded (max 7). You can\\'t nest more than 7 levels ' +\n 'of clipped containers in a single draw tree. Flatten the hierarchy or compose ' +\n 'poses outside the scene graph.',\n );\n }\n enterClip(ctx, cmd.clip);\n }\n for (const child of cmd.children) dispatch(ctx, child);\n if (cmd.clip) leaveClip(ctx);\n ctx.state.pop();\n}\n\n/**\n * Push a group's clip.\n *\n * A clip only the stencil can express takes its bit now. An axis-aligned rect\n * takes none: staged geometry is cut to it on the CPU (`batchClip.ts`), so\n * content inside it joins the run outside it instead of costing a flush on\n * the way in and another on the way out. It takes a bit only if something that\n * draws for itself turns up inside it — see `flushForOwnDraw`.\n */\nfunction enterClip(ctx: DrawContext, path: Path): void {\n const transform = ctx.state.transform;\n const rect = axisAlignedClipRect(path, transform);\n if (rect === null) {\n // Bits nest in stack order, so any rect clip still without one takes it\n // first.\n materializeClips(ctx);\n const depth = ctx.clipDepth + 1;\n pushClip(ctx, path, depth);\n ctx.clipDepth = depth;\n ctx.clipStack.push({ path, transform, rect: null, depth });\n } else {\n ctx.clipStack.push({ path, transform, rect, depth: 0 });\n }\n syncBatchClip(ctx);\n}\n\nfunction leaveClip(ctx: DrawContext): void {\n const entry = ctx.clipStack.pop()!;\n if (entry.depth > 0) {\n popClip(ctx, entry.path, entry.depth - 1, entry.transform);\n ctx.clipDepth = entry.depth - 1;\n }\n syncBatchClip(ctx);\n}\n\n/** Give every rect clip on the stack its stencil bit, for a draw the CPU cut\n * cannot reach. */\nfunction materializeClips(ctx: DrawContext): void {\n for (const entry of ctx.clipStack) {\n if (entry.depth !== 0) continue;\n const depth = ctx.clipDepth + 1;\n pushClip(ctx, entry.path, depth, entry.transform);\n entry.depth = depth;\n ctx.clipDepth = depth;\n }\n}\n\nfunction syncBatchClip(ctx: DrawContext): void {\n let rect: ClipRect | null = null;\n for (const entry of ctx.clipStack) {\n if (entry.rect) rect = rect ? intersectClipRects(rect, entry.rect) : entry.rect;\n }\n ctx.drawBatch.clip = rect;\n}\n\n/**\n * The clip depth a run is staged and drawn at: the innermost clip only the\n * stencil can express. Rect clips are left out whether or not they hold a bit,\n * because the CPU cut already applies them — which is what lets a run cross\n * them.\n */\nfunction runClipDepth(ctx: DrawContext): number {\n const stack = ctx.clipStack;\n if (stack.length === 0 || ctx.uncut) return ctx.clipDepth;\n for (let i = stack.length - 1; i >= 0; i--) {\n if (stack[i].rect === null) return stack[i].depth;\n }\n // Only rect clips: whatever depth held before the first of them took a bit.\n for (const entry of stack) if (entry.depth > 0) return entry.depth - 1;\n return ctx.clipDepth;\n}\n\n/**\n * Put the rect clips on the stencil and stop cutting, for an item the batch\n * refused to cut — one with a slanted edge across a clip (see\n * `DrawBatch.clipQuad`). Staged again between this and `leaveUncut`, the item\n * sees the full stencil depth and lands in a run of its own under every clip.\n * Returns the cut to hand back.\n *\n * A pair rather than a callback: the staging paths are hot, and a closure\n * over their arguments would cost an allocation on every call, refused or not.\n */\nfunction enterUncut(ctx: DrawContext): ClipRect | null {\n materializeClips(ctx);\n const cut = ctx.drawBatch.clip;\n ctx.drawBatch.clip = null;\n ctx.uncut = true;\n return cut;\n}\n\nfunction leaveUncut(ctx: DrawContext, cut: ClipRect | null): void {\n ctx.drawBatch.clip = cut;\n ctx.uncut = false;\n}\n\n/** `fn(ctx, a, b)` again, uncut — for the stage-and-push helpers, which pass\n * themselves. */\nfunction retryUncut<A, B>(\n ctx: DrawContext, a: A, b: B, fn: (ctx: DrawContext, a: A, b: B) => void,\n): void {\n const cut = enterUncut(ctx);\n fn(ctx, a, b);\n leaveUncut(ctx, cut);\n}\n\n/**\n * Drain the run before a draw that does not go through it, and give that draw\n * the stencil it tests against. Every such draw starts here or behind a\n * `tryStageFill` that returned `false`, which ends the same way.\n */\nfunction flushForOwnDraw(ctx: DrawContext): void {\n flushBatch(ctx);\n if (ctx.clipStack.length > 0) materializeClips(ctx);\n}\n\n/** A path command whose stroke actually paints something. */\ntype StrokedPathCommand = PathDrawCommand & { stroke: Stroke & { paint: FillStyle } };\n\nfunction drawPath(ctx: DrawContext, cmd: PathDrawCommand): void {\n if (cmd.fill) drawPathFill(ctx, cmd);\n // A stroke with no `paint` paints nothing, the way a node's `fill: null`\n // does. Commands arriving from a consumer painter or overlay can carry one.\n if (cmd.stroke?.paint) drawPathStroke(ctx, cmd as StrokedPathCommand);\n}\n\nfunction drawPathFill(ctx: DrawContext, cmd: PathDrawCommand): void {\n const fill = cmd.fill!;\n // Batchable: see `batchPaint`. A rect skips tessellation entirely; anything\n // else stages its mesh. Both also keep animated demos that mint a fresh Path\n // every frame from allocating a GL buffer per frame.\n const isSolid = fill.fill === undefined || fill.fill === 'solid';\n const hasVColors = !!(cmd.vertexColors && cmd.vertexColors.length > 0);\n const solid = fill as { color: string; opacity?: number };\n const paint = batchPaint(ctx, fill, hasVColors);\n if (paint === null) return;\n\n if (paint !== undefined && cmd.path.kind === 'rect') {\n if (paint.kind === 'ramp') pushRampRect(ctx, cmd.path, paint);\n else pushRect(ctx, cmd.path, paint);\n return;\n }\n\n const mesh = fillMesh(ctx, cmd.path);\n if (tryStageFill(ctx, mesh, paint)) return;\n\n const handle = meshHandle(ctx, mesh);\n if (isSolid && hasVColors) {\n drawPathFillVColor(ctx, cmd, solid, handle);\n } else if (handle.requiresStencil) {\n drawPathFillStencil(ctx, fill, handle);\n } else {\n drawPathFillByKind(ctx, fill, handle);\n }\n}\n\n/** `u_samplers[i] = i`, uploaded whole per flush. Built once: the mapping from\n * slot to texture unit is the identity and never varies. */\nconst SAMPLER_UNITS = new Int32Array(\n Array.from({ length: BATCH_TEXTURE_SLOTS }, (_, i) => i),\n);\n\n/** `u_fieldScale`, per slot: an atlas slot's `glyphFieldScale`. Slots that are\n * not atlases keep whatever a previous flush wrote, which nothing reads. */\nconst FIELD_SCALES = new Float32Array(2 * BATCH_TEXTURE_SLOTS);\n\n/**\n * The group state a staged run was built under.\n *\n * A run outlives the group it started in, so the state live when the flush\n * happens is not the state the rects belong to — the flush draws with these\n * values instead. Transform is absent because it rides the vertices; `alpha`\n * is 1 whenever it rode them too.\n */\ninterface StagedBatchState {\n alpha: number;\n colorMatrix: Float32Array;\n clipDepth: number;\n /**\n * The SDF threshold shift `u_synthBold` draws this run under.\n *\n * A uniform rather than a vertex attribute, and so a thing that breaks a run.\n * A per-vertex float costs every rect and quad in the run (see \"Mode and slot\n * share one attribute\" in `shaders/batchFill.ts`): the batch's whole point is\n * one cheap buffer write a frame, and a float only glyphs read still widens the write\n * for every rect and quad beside them. What it costs instead is a break\n * wherever faked-bold text meets text that is not, which is a fallback path:\n * a registered bold face never sets this at all.\n */\n synthBold: number;\n /** Whether group alpha folded into the vertex colors. */\n foldsAlpha: boolean;\n /**\n * The textures this run samples, in the order they joined. A quad's vertices\n * carry `index + 1`, because slot 0 is the white texel every solid samples.\n *\n * Two kinds, because two caches own them: an image quad names an\n * `ImageBitmap` that `GLImageCache` keys by identity, a glyph names the\n * string id of a font atlas in `GLTextureCache`. They share the slot list so\n * a caption and the thumbnail above it share a draw.\n *\n * A bitmap's `sampling` is per entry and set per flush rather than at upload:\n * MAG_FILTER is state on the texture object, so the same bitmap drawn at both\n * filters in one frame needs two flushes, not two slots. An atlas carries no\n * sampling because `GLTextureCache` owns its filtering — and must keep\n * owning it: filtering a distance field destroys it, so a font atlas is\n * never mipmapped and never joins a shared image atlas.\n */\n textures: BatchTexture[];\n}\n\n/** One entry in a run's slot list. */\ntype BatchTexture =\n | { kind: 'bitmap'; image: ImageBitmap; sampling: 'linear' | 'nearest' }\n | { kind: 'atlas'; id: string; fieldScale: readonly [number, number] }\n | { kind: 'ramps' };\n\n/** Identity in row-major 4×5 leaves `src` untouched *and* leaves the shader's\n * clamp with nothing to do, which is what makes the alpha fold exact. */\nfunction isIdentityColorMatrix(cm: Float32Array): boolean {\n return cm === IDENTITY_COLOR_MATRIX || sameValues(IDENTITY_COLOR_MATRIX, cm);\n}\n\n/**\n * Whether the live group state would draw the staged run identically.\n *\n * By value, not by reference: a group carrying an identity color matrix still\n * goes through `compose4x5`, which allocates a new array holding equal numbers.\n * Twenty float compares are nothing against the draw call they save.\n */\nfunction stagedStateIsLive(\n ctx: DrawContext, staged: StagedBatchState,\n image?: ImageBitmap, sampling?: 'linear' | 'nearest',\n synthBold = 0,\n): boolean {\n if (staged.clipDepth !== (ctx.clipStack.length === 0 ? ctx.clipDepth : runClipDepth(ctx))) return false;\n // Solids and image quads ask with 0, which is what a run of them carries, so\n // this only ever breaks between two kinds of glyph.\n if (staged.synthBold !== synthBold) return false;\n if (!staged.foldsAlpha && staged.alpha !== ctx.state.alpha) return false;\n if (image !== undefined && slotForBitmap(staged, image, sampling!) < 0) return false;\n const colorMatrix = ctx.state.colorMatrix;\n return staged.colorMatrix === colorMatrix || sameValues(staged.colorMatrix, colorMatrix);\n}\n\n/**\n * The slot `image` would sample from in this run, or -1 if it cannot join.\n *\n * A bitmap already in the run reuses its slot — but only at the filter it went\n * in under, since MAG_FILTER belongs to the texture object and one draw cannot\n * have it both ways. Otherwise it takes the next free slot, and a run with none\n * left is a run this quad has to break.\n */\nfunction slotForBitmap(\n staged: StagedBatchState, image: ImageBitmap, sampling: 'linear' | 'nearest',\n): number {\n for (let i = 0; i < staged.textures.length; i++) {\n const entry = staged.textures[i];\n if (entry.kind !== 'bitmap' || entry.image !== image) continue;\n return entry.sampling === sampling ? i + 1 : -1;\n }\n return nextFreeSlot(staged);\n}\n\n/** The same for the ramp atlas, of which there is one — so every gradient in a\n * run shares the slot, however many distinct ramps they are. */\nfunction slotForRamps(staged: StagedBatchState): number {\n for (let i = 0; i < staged.textures.length; i++) {\n if (staged.textures[i].kind === 'ramps') return i + 1;\n }\n return nextFreeSlot(staged);\n}\n\n/** The same for a font atlas, which has no filter to disagree about. */\nfunction slotForAtlas(staged: StagedBatchState, id: string): number {\n for (let i = 0; i < staged.textures.length; i++) {\n const entry = staged.textures[i];\n if (entry.kind === 'atlas' && entry.id === id) return i + 1;\n }\n return nextFreeSlot(staged);\n}\n\n/** The slot a texture new to this run would take, or -1 if it is full. */\nfunction nextFreeSlot(staged: StagedBatchState): number {\n return staged.textures.length + 1 < BATCH_TEXTURE_SLOTS ? staged.textures.length + 1 : -1;\n}\n\n/**\n * Vertices above which a mesh keeps its own draw.\n *\n * Batching trades a draw call for copying and re-uploading the mesh every\n * frame, where a mesh already in the persistent cache costs nothing per frame\n * beyond the draw. The cap was set near a break-even of about 200 vertices,\n * measured once in 2026-08 on an M2 Max by timing blocks of frames, a method\n * since retired (`tests/perf/README.md`, \"Timing a frame\"); no spec measures it\n * now. Near break-even, being wrong in either direction is a wash, which is\n * why it sits there rather than anywhere a big path pays a per-frame copy for a\n * draw call it barely saves.\n */\nconst MAX_BATCHED_MESH_VERTICES = 256;\n\n/** Whether a mesh can join a run. Stencil fills need their own two-pass dance,\n * and a mesh past the cap is cheaper as its own draw. */\nfunction canBatchMesh(mesh: Mesh): boolean {\n return !mesh.requiresStencil && (mesh.vertices.length >> 1) <= MAX_BATCHED_MESH_VERTICES;\n}\n\n/**\n * Open or continue a run for `vertices` more, flushing first if the run would\n * overflow or if the live group state no longer matches what it was staged\n * under. Returns the staged state, which the caller reads to resolve alpha.\n *\n * Fill opacity folds into the vertex alpha, exactly as `u_color` carried it\n * when each shape was its own draw. Group alpha folds in too, but only under an\n * identity color matrix: the shader is `a = clamp(CM * src + bias).a * u_alpha`,\n * so with a real matrix between them a pre-multiplied vertex alpha is a\n * different number. There it stays a uniform, and a differing alpha breaks the\n * run as before.\n */\nfunction stageSolid(ctx: DrawContext, vertices: number): StagedBatchState {\n if (ctx.batchState !== undefined && !stagedStateIsLive(ctx, ctx.batchState)) flushBatch(ctx);\n if (ctx.drawBatch.wouldOverflow(vertices)) flushBatch(ctx);\n return openRun(ctx);\n}\n\n/** The staged state, opening a run under the live group state if none is. */\nfunction openRun(ctx: DrawContext): StagedBatchState {\n if (ctx.batchState === undefined) {\n const colorMatrix = ctx.state.colorMatrix;\n const foldsAlpha = isIdentityColorMatrix(colorMatrix);\n ctx.batchState = {\n alpha: foldsAlpha ? 1 : ctx.state.alpha,\n colorMatrix,\n clipDepth: runClipDepth(ctx),\n synthBold: 0,\n foldsAlpha,\n textures: [],\n };\n }\n return ctx.batchState;\n}\n\n/**\n * Open or continue a run for one more image quad, flushing first if the run\n * would overflow or cannot give this bitmap a slot.\n *\n * A run adopts a bitmap it has not seen rather than breaking, which is what\n * lets a wall's ground rect and its atlas quad share a draw, and what lets a\n * cell's art and its badge share one too. Returns the staged state and the slot\n * the quad's vertices must carry.\n */\nfunction stageImage(\n ctx: DrawContext, image: ImageBitmap, sampling: 'linear' | 'nearest',\n): { staged: StagedBatchState; slot: number } {\n if (ctx.batchState !== undefined\n && !stagedStateIsLive(ctx, ctx.batchState, image, sampling)) {\n flushBatch(ctx);\n }\n if (ctx.drawBatch.wouldOverflow(4)) flushBatch(ctx);\n const staged = openRun(ctx);\n let slot = slotForBitmap(staged, image, sampling);\n if (slot > staged.textures.length) {\n staged.textures.push({ kind: 'bitmap', image, sampling });\n slot = staged.textures.length;\n }\n return { staged, slot };\n}\n\n/**\n * Open or continue a run for a glyph off the font atlas `atlasId`, flushing\n * first if the run would overflow or has no slot left for it.\n *\n * The atlas is the unit of coalescing the way a sprite sheet is: every glyph a\n * face contributes to a frame shares one texture, so a paragraph is one run\n * however many glyphs it is, and a second face costs one more slot rather than\n * a flush per word.\n */\nfunction stageGlyphs(\n ctx: DrawContext, atlasId: string, fieldScale: readonly [number, number], synthBold: number,\n): { staged: StagedBatchState; slot: number } {\n if (ctx.batchState !== undefined\n && (!stagedStateIsLive(ctx, ctx.batchState, undefined, undefined, synthBold)\n || slotForAtlas(ctx.batchState, atlasId) < 0)) {\n flushBatch(ctx);\n }\n if (ctx.drawBatch.wouldOverflow(4)) flushBatch(ctx);\n const staged = openRun(ctx);\n // An empty run adopts the threshold; one that already has vertices agreed to\n // it above, since a mismatch flushed.\n staged.synthBold = synthBold;\n let slot = slotForAtlas(staged, atlasId);\n if (slot > staged.textures.length) {\n staged.textures.push({ kind: 'atlas', id: atlasId, fieldScale });\n slot = staged.textures.length;\n }\n return { staged, slot };\n}\n\n/**\n * Open or continue a run for geometry filled from the ramp atlas, flushing\n * first if the run would overflow, has no slot left, or if baking `stops` would\n * move the rows already staged.\n *\n * **That last one is the trap.** A staged vertex names its ramp by where the\n * row sits, so growing the atlas — which changes every row's `v` — or recycling\n * a row repaints geometry already staged with somebody else's gradient. Both\n * are irreversible once done, so the question is asked before the bake, not\n * after.\n */\nfunction stageRamps(\n ctx: DrawContext, stops: GradStop[], space: ColorSpace, vertices: number,\n): { staged: StagedBatchState; slot: number; rowV: number } {\n if (ctx.gradRamps.wouldReshape(stops, space)) flushBatch(ctx);\n if (ctx.batchState !== undefined\n && (!stagedStateIsLive(ctx, ctx.batchState) || slotForRamps(ctx.batchState) < 0)) {\n flushBatch(ctx);\n }\n if (ctx.drawBatch.wouldOverflow(vertices)) flushBatch(ctx);\n const staged = openRun(ctx);\n let slot = slotForRamps(staged);\n if (slot > staged.textures.length) {\n staged.textures.push({ kind: 'ramps' });\n slot = staged.textures.length;\n }\n return { staged, slot, rowV: ctx.gradRamps.rowV(ctx.gradRamps.upload(stops, space)) };\n}\n\n/** Alpha a batched paint's vertices carry: its own opacity, and the group's\n * under an identity color matrix. */\nfunction stagedAlpha(\n ctx: DrawContext, staged: StagedBatchState, opacity: number | undefined,\n): number {\n return (opacity ?? 1) * (staged.foldsAlpha ? ctx.state.alpha : 1);\n}\n\n/** Straight-alpha rgba for a solid paint under the staged state. */\nfunction stagedColor(\n ctx: DrawContext, staged: StagedBatchState,\n paint: { color: string; opacity?: number },\n): [number, number, number, number] {\n const [r, g, b, a] = resolveColor(paint.color);\n return [r, g, b, a * stagedAlpha(ctx, staged, paint.opacity)];\n}\n\nfunction pushRect(\n ctx: DrawContext,\n rect: { x: number; y: number; width: number; height: number },\n fill: { color: string; opacity?: number },\n): void {\n const staged = stageSolid(ctx, 4);\n const [r, g, b, a] = stagedColor(ctx, staged, fill);\n if (!ctx.drawBatch.pushRect(\n rect.x, rect.y, rect.width, rect.height, ctx.state.transform, r, g, b, a,\n )) retryUncut(ctx, rect, fill, pushRect);\n}\n\nfunction pushMesh(\n ctx: DrawContext,\n mesh: Mesh,\n paint: { color: string; opacity?: number },\n): void {\n const staged = stageSolid(ctx, mesh.vertices.length >> 1);\n const [r, g, b, a] = stagedColor(ctx, staged, paint);\n if (!ctx.drawBatch.pushMesh(mesh, ctx.state.transform, r, g, b, a)) {\n retryUncut(ctx, mesh, paint, pushMesh);\n }\n}\n\n/** A paint a run can express, resolved from a `FillStyle` by `batchPaint`. */\ntype BatchPaint =\n | { kind: 'solid'; color: string; opacity?: number }\n | {\n kind: 'ramp'; stops: GradStop[]; space: ColorSpace; opacity?: number;\n /** `PAINT_MODE_PLAIN` for a linear gradient, whose ramp position a vertex\n * carries outright; `PAINT_MODE_RADIAL` / `PAINT_MODE_CONIC` otherwise. */\n mode: number;\n uv: GradientUV;\n };\n\n/**\n * `fill` as something a run can carry, or `undefined` for a paint no run can\n * express — a pattern, a shader, per-vertex colors — and `null` for a gradient\n * whose space has no inverse under this transform, which draws nothing.\n *\n * **All three gradients qualify, and for the same reason,** which is not that\n * their ramp position is affine in position — only a linear gradient's is. It\n * is that the *coordinate* the ramp position is computed from is affine in all\n * three, so a vertex can carry that and the rasterizer's interpolation across a\n * triangle is exact. A linear gradient's coordinate is the ramp position\n * itself, which is why it needs no paint mode; the other two carry a\n * gradient-space point and the shader takes a `length` or an `atan` of it.\n */\nfunction batchPaint(\n ctx: DrawContext, fill: FillStyle, hasVColors: boolean,\n): BatchPaint | undefined | null {\n if (hasVColors) return undefined;\n const kind = fill.fill ?? 'solid';\n if (kind === 'solid') {\n const solid = fill as { color: string; opacity?: number };\n return { kind: 'solid', color: solid.color, opacity: solid.opacity };\n }\n if (kind !== 'linear-gradient' && kind !== 'radial-gradient' && kind !== 'conic-gradient') {\n return undefined;\n }\n const grad = fill as Extract<FillStyle, { fill: 'linear-gradient' | 'radial-gradient' | 'conic-gradient' }>;\n const g = gradientMap(ctx, grad.units);\n if (!g) return null;\n if (grad.fill === 'linear-gradient') return ramp(grad, PAINT_MODE_PLAIN, linearRampUV(g, grad));\n if (grad.fill === 'radial-gradient') return ramp(grad, PAINT_MODE_RADIAL, radialRampUV(g, grad));\n return ramp(grad, PAINT_MODE_CONIC, conicRampUV(g, grad));\n}\n\nfunction ramp(\n fill: { stops: GradStop[]; interpolate?: ColorSpace; opacity?: number },\n mode: number, uv: GradientUV,\n): BatchPaint {\n return {\n kind: 'ramp', stops: fill.stops, space: fill.interpolate ?? 'rgb',\n opacity: fill.opacity, mode, uv,\n };\n}\n\n/**\n * Geometry-space → gradient-space, as the one matrix a vertex is measured\n * through.\n *\n * `gradientSpaceInverse` maps a screen position back into the gradient's space\n * and the batch's vertices arrive before the model transform, so the two\n * compose. This is the composition `gradFill`'s vertex shader does in two\n * steps, and the pair have to agree: a radial gradient goes through that one\n * and a linear one through this.\n */\nfunction gradientMap(ctx: DrawContext, units: GradientUnits | undefined): GlMat3 | null {\n const inverse = gradientSpaceInverse(ctx, units);\n return inverse && mat3.multiply(inverse, ctx.state.transform);\n}\n\n/**\n * The gradient shader's `dot(p - from, dir) / len` folded into `u`, with `v`\n * left for the atlas row `stageRamps` fills in.\n */\nfunction linearRampUV(\n g: GlMat3, fill: Extract<FillStyle, { fill: 'linear-gradient' }>,\n): GradientUV {\n const dx = fill.to.x - fill.from.x;\n const dy = fill.to.y - fill.from.y;\n const len = Math.hypot(dx, dy) || 1;\n // dir is (dx, dy)/len and the divisor is len, so the pair is 1/len².\n const k = 1 / (len * len);\n return {\n ux: (g[0] * dx + g[1] * dy) * k,\n uy: (g[3] * dx + g[4] * dy) * k,\n u0: ((g[6] - fill.from.x) * dx + (g[7] - fill.from.y) * dy) * k,\n vx: 0, vy: 0, v0: 0,\n };\n}\n\n/** The gradient-space point scaled so its distance from the center *is* the\n * ramp position, which is what makes the shader's half a `length`. */\nfunction radialRampUV(\n g: GlMat3, fill: Extract<FillStyle, { fill: 'radial-gradient' }>,\n): GradientUV {\n // The floor is `gradFill`'s own `max(u_gradRadius, 0.0001)`.\n const k = 1 / Math.max(fill.radius, 1e-4);\n return {\n ux: g[0] * k, uy: g[3] * k, u0: (g[6] - fill.center.x) * k,\n vx: g[1] * k, vy: g[4] * k, v0: (g[7] - fill.center.y) * k,\n };\n}\n\n/**\n * The gradient-space point about the center, turned by `-angle` so the shader's\n * half is an `atan` of it and nothing else.\n *\n * `gradFill` subtracts the angle from the arctangent instead. The two agree\n * because rotating a point turns its arctangent by the same amount, and the\n * `fract` that follows takes care of the wrap either way.\n */\nfunction conicRampUV(\n g: GlMat3, fill: Extract<FillStyle, { fill: 'conic-gradient' }>,\n): GradientUV {\n const cos = Math.cos(fill.angle);\n const sin = Math.sin(fill.angle);\n const dx0 = g[6] - fill.center.x;\n const dy0 = g[7] - fill.center.y;\n return {\n ux: cos * g[0] + sin * g[1],\n uy: cos * g[3] + sin * g[4],\n u0: cos * dx0 + sin * dy0,\n vx: cos * g[1] - sin * g[0],\n vy: cos * g[4] - sin * g[3],\n v0: cos * dy0 - sin * dx0,\n };\n}\n\n/**\n * What a gradient's vertices carry once its row is known.\n *\n * A linear gradient's `a_uv` is (ramp position, row) and its `a_post` is the\n * plain 1, because that is what the plain paint mode already samples. A radial\n * or conic one needs both `a_uv` channels for its coordinate, so its row goes\n * in `a_post` — which no gradient uses for alpha, its opacity riding the vertex\n * color instead.\n */\nfunction rampVertices(\n paint: Extract<BatchPaint, { kind: 'ramp' }>, rowV: number,\n): { uv: GradientUV; post: number } {\n return paint.mode === PAINT_MODE_PLAIN\n ? { uv: { ...paint.uv, v0: rowV }, post: 1 }\n : { uv: paint.uv, post: rowV };\n}\n\nfunction pushRampRect(\n ctx: DrawContext,\n rect: { x: number; y: number; width: number; height: number },\n paint: Extract<BatchPaint, { kind: 'ramp' }>,\n): void {\n const { staged, slot, rowV } = stageRamps(ctx, paint.stops, paint.space, 4);\n const { uv, post } = rampVertices(paint, rowV);\n // White vertices, so the ramp texel passes through as its own color and the\n // alpha channel carries what `u_opacity` and `u_alpha` used to.\n if (!ctx.drawBatch.pushGradientRect(\n rect.x, rect.y, rect.width, rect.height, ctx.state.transform,\n uv, post, slot, paint.mode, 1, 1, 1, stagedAlpha(ctx, staged, paint.opacity),\n )) retryUncut(ctx, rect, paint, pushRampRect);\n}\n\nfunction pushRampMesh(\n ctx: DrawContext, mesh: Mesh, paint: Extract<BatchPaint, { kind: 'ramp' }>,\n): void {\n const { staged, slot, rowV } = stageRamps(ctx, paint.stops, paint.space, mesh.vertices.length >> 1);\n const { uv, post } = rampVertices(paint, rowV);\n if (!ctx.drawBatch.pushGradientMesh(\n mesh, ctx.state.transform,\n uv, post, slot, paint.mode, 1, 1, 1, stagedAlpha(ctx, staged, paint.opacity),\n )) retryUncut(ctx, mesh, paint, pushRampMesh);\n}\n\n/**\n * Stage `mesh` into the run, or drain the run so the caller can draw it itself.\n *\n * `true` means the mesh is in the batch and the caller is done. `false` comes\n * back only *after* a flush, so an emitter cannot earn permission to draw for\n * itself without also draining the batch. `paint` is `undefined` when it is one\n * no run can express — see `batchPaint`.\n */\nexport function tryStageFill(\n ctx: DrawContext,\n mesh: Mesh,\n paint: BatchPaint | undefined,\n): boolean {\n if (paint !== undefined && canBatchMesh(mesh)) {\n if (paint.kind === 'ramp') pushRampMesh(ctx, mesh, paint);\n else pushMesh(ctx, mesh, paint);\n return true;\n }\n flushForOwnDraw(ctx);\n return false;\n}\n\n/**\n * Draw the staged run as one `drawElements`, under the state it was staged\n * under. Callers that are about to bind a different program, or paint anything\n * that must land on top of the run, call this first; a group that only changes\n * the color matrix does not, because `pushRect` notices and flushes then, and\n * one that only changes transform or alpha does not break the run at all.\n *\n * Stencil clips are the exception: the stencil is real GL state that the\n * staged values cannot reconstruct, so `pushClip` flushes *before* writing a\n * bit, and `popClip` before clearing one a staged run tests. Rect clips never\n * reach the stencil while only staged geometry is inside them — see\n * `enterClip`.\n *\n * `u_color` stays white: the vertex-color program multiplies it by the\n * per-vertex color, so white makes the result bit-identical to the flat\n * program's `u_color`-only math. `u_model` stays identity for the same reason —\n * the corners arrive already transformed.\n */\nexport function flushBatch(ctx: DrawContext): void {\n const batch = ctx.drawBatch;\n const staged = ctx.batchState;\n if (batch.length === 0 || staged === undefined) {\n // An empty run's state still names a clip depth, and an item refused by\n // the CPU cut is about to be staged again under a different one.\n ctx.batchState = undefined;\n return;\n }\n const gl = ctx.gl;\n const prog = ctx.batchFill;\n gl.useProgram(prog.handle);\n const indexCount = batch.uploadAndBind();\n setProjAndModel(ctx, prog, BATCH_MODEL);\n setColorUniform(ctx, prog, 1, 1, 1, 1);\n setAlphaUniform(ctx, prog, staged.alpha);\n gl.uniform1f(prog.uniform('u_synthBold')!, staged.synthBold);\n setColorMatrixUniforms(ctx, prog, staged.colorMatrix);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, ctx.whiteTexture);\n for (let i = 0; i < staged.textures.length; i++) {\n const entry = staged.textures[i];\n if (entry.kind === 'atlas') {\n ctx.textureCache.bind(entry.id, i + 1);\n FIELD_SCALES[2 * (i + 1)] = entry.fieldScale[0];\n FIELD_SCALES[2 * (i + 1) + 1] = entry.fieldScale[1];\n continue;\n }\n if (entry.kind === 'ramps') {\n ctx.gradRamps.bind(i + 1);\n continue;\n }\n ctx.imageCache.bind(entry.image, i + 1);\n // Per flush, not at upload: the same bitmap can be drawn at both filters in\n // one frame. The cache skips the write when the texture already carries the\n // value, which is most flushes.\n ctx.imageCache.setMagFilter(\n entry.image,\n entry.sampling === 'nearest' ? gl.NEAREST : gl.LINEAR,\n );\n }\n gl.uniform1iv(prog.uniform('u_samplers')!, SAMPLER_UNITS);\n gl.uniform2fv(prog.uniform('u_fieldScale')!, FIELD_SCALES);\n applyClipTest(ctx, staged.clipDepth);\n drawTriangles(ctx, indexCount, ctx.gl.UNSIGNED_INT);\n // Everything else in the renderer binds its texture to unit 0 and some of it\n // does so without an `activeTexture` of its own, so leaving unit 6 selected\n // sends the next such bind to a unit nothing samples.\n gl.activeTexture(gl.TEXTURE0);\n // Not redundant: `drawShader` binds no VAO and points attributes at whatever\n // is current, so a slot left bound here comes back corrupted a ring later.\n gl.bindVertexArray(null);\n batch.reset();\n ctx.batchState = undefined;\n}\n\nfunction expandAnchorColors(perAnchor: number[], handle: GLMeshHandle): Float32Array {\n const aA = handle.anchorA;\n const aB = handle.anchorB;\n const aT = handle.anchorT;\n if (!aA || !aB || !aT) {\n // Legacy fallback: mesh lacks anchor params (e.g. non-path mesh). Treat\n // the caller-provided array as already per-vertex.\n return new Float32Array(perAnchor);\n }\n const n = aA.length;\n const out = new Float32Array(n * 4);\n for (let i = 0; i < n; i++) {\n const a4 = aA[i] * 4;\n const b4 = aB[i] * 4;\n const t = aT[i];\n out[i * 4 + 0] = perAnchor[a4 + 0] + (perAnchor[b4 + 0] - perAnchor[a4 + 0]) * t;\n out[i * 4 + 1] = perAnchor[a4 + 1] + (perAnchor[b4 + 1] - perAnchor[a4 + 1]) * t;\n out[i * 4 + 2] = perAnchor[a4 + 2] + (perAnchor[b4 + 2] - perAnchor[a4 + 2]) * t;\n out[i * 4 + 3] = perAnchor[a4 + 3] + (perAnchor[b4 + 3] - perAnchor[a4 + 3]) * t;\n }\n return out;\n}\n\nfunction drawPathFillVColor(\n ctx: DrawContext,\n cmd: PathDrawCommand,\n fill: { color: string; opacity?: number },\n handle: GLMeshHandle,\n): void {\n const gl = ctx.gl;\n const prog = ctx.pathFillVColor;\n gl.useProgram(prog.handle);\n gl.bindVertexArray(handle.vao);\n setProjAndModel(ctx, prog);\n setSolidPaintUniforms(ctx, prog, fill.color, fill.opacity);\n setColorMatrixUniforms(ctx, prog);\n\n const expanded = expandAnchorColors(cmd.vertexColors!, handle);\n const colorVbo = gl.createBuffer();\n if (!colorVbo) throw new Error('drawPathFillVColor: createBuffer (color VBO) returned null');\n gl.bindBuffer(gl.ARRAY_BUFFER, colorVbo);\n gl.bufferData(gl.ARRAY_BUFFER, expanded, gl.DYNAMIC_DRAW);\n const aVColorLoc = prog.attribute('a_vertexColor');\n if (aVColorLoc !== undefined) {\n gl.enableVertexAttribArray(aVColorLoc);\n gl.vertexAttribPointer(aVColorLoc, 4, gl.FLOAT, false, 0, 0);\n }\n\n applyClipTest(ctx);\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n gl.bindVertexArray(null);\n // The per-vertex color VBO is freshly allocated per draw; free it now\n // (after unbinding the VAO) so we don't leak one buffer per vColor draw.\n gl.deleteBuffer(colorVbo);\n}\n\nfunction setProjAndModel(\n ctx: DrawContext, prog: ShaderProgram,\n model: GlMat3 = ctx.state.transform,\n proj: GlMat3 = projFor(ctx),\n): void {\n const gl = ctx.gl;\n const uploaded = uploadedFor(ctx, prog);\n\n if (!sameValues(uploaded.proj, proj)) {\n gl.uniformMatrix3fv(prog.uniform('u_proj')!, false, proj);\n uploaded.proj = Float32Array.from(proj);\n }\n\n if (!sameValues(uploaded.model, model)) {\n gl.uniformMatrix3fv(prog.uniform('u_model')!, false, model);\n uploaded.model = Float32Array.from(model);\n }\n}\n\nfunction setSolidPaintUniforms(\n ctx: DrawContext, prog: ShaderProgram,\n color: string, opacity: number | undefined,\n): void {\n const [r, g, b, a] = resolveColor(color);\n setColorUniform(ctx, prog, r, g, b, a * (opacity ?? 1));\n setAlphaUniform(ctx, prog, ctx.state.alpha);\n}\n\n/**\n * Bind the program, uniforms and textures for `fill`, and return the program.\n *\n * Split from the draw so a caller owning its own stencil state can paint\n * without `applyClipTest` clobbering it — `drawPathStrokeStenciled` clips a\n * doubled ribbon to one side of the silhouette, and `applyClipTest` at depth 0\n * disables the stencil test outright.\n */\nfunction bindPathFillByKind(ctx: DrawContext, fill: FillStyle): ShaderProgram | null {\n const kind = fill.fill ?? 'solid';\n if (kind === 'solid') return bindPathFillSolid(ctx, fill as { color: string; opacity?: number });\n if (kind === 'pattern') return bindPathFillPattern(ctx, fill as Extract<FillStyle, { fill: 'pattern' }>);\n if (kind === 'linear-gradient' || kind === 'radial-gradient' || kind === 'conic-gradient') {\n return bindPathFillGradient(ctx, fill as Extract<FillStyle, { fill: 'linear-gradient' | 'radial-gradient' | 'conic-gradient' }>);\n }\n const bind = getPaintKind(kind)?.bind;\n return bind ? bind(paintBindContext(ctx), fill) : null;\n}\n\n/** The narrow renderer surface a registered paint kind binds against, built\n * once per frame context. `DrawContext` is not consumer surface. */\nfunction paintBindContext(ctx: DrawContext): PaintBindContext {\n const cached = BIND_CONTEXTS.get(ctx);\n if (cached) return cached;\n const made: PaintBindContext = {\n gl: ctx.gl,\n get alpha() { return ctx.state.alpha; },\n program: (id) => ctx.ensureProgram?.(id) ?? ctx.programRegistry.get(id) ?? null,\n setProjAndModel: (prog) => setProjAndModel(ctx, prog),\n spaceInverse: (units) => gradientSpaceInverse(ctx, units),\n spaceToDevice: (units) => spaceToDevice(ctx, units),\n get maxTextureSize() { return ctx.imageCache.maxTextureSide; },\n resources: ctx.paintResources ?? unownedPaintResources(ctx.gl),\n bindRamp: (stops, unit, space) => {\n const row = ctx.gradRamps.upload(stops, space);\n ctx.gradRamps.bind(unit);\n return ctx.gradRamps.rowV(row);\n },\n };\n BIND_CONTEXTS.set(ctx, made);\n return made;\n}\n\nconst BIND_CONTEXTS = new WeakMap<DrawContext, PaintBindContext>();\n\nconst UNOWNED_RESOURCES = new WeakMap<WebGL2RenderingContext, PaintResources>();\n\nfunction unownedPaintResources(gl: WebGL2RenderingContext): PaintResources {\n let made = UNOWNED_RESOURCES.get(gl);\n if (!made) {\n made = createPaintResources();\n UNOWNED_RESOURCES.set(gl, made);\n }\n return made;\n}\n\nfunction drawPathFillByKind(ctx: DrawContext, fill: FillStyle, handle: GLMeshHandle): void {\n const prog = bindPathFillByKind(ctx, fill);\n if (!prog) return;\n const gl = ctx.gl;\n gl.bindVertexArray(handle.vao);\n applyClipTest(ctx);\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n gl.bindVertexArray(null);\n}\n\nfunction bindPathFillSolid(\n ctx: DrawContext,\n fill: { color: string; opacity?: number },\n): ShaderProgram {\n const prog = ctx.pathFill;\n ctx.gl.useProgram(prog.handle);\n setProjAndModel(ctx, prog);\n setSolidPaintUniforms(ctx, prog, fill.color, fill.opacity);\n setColorMatrixUniforms(ctx, prog);\n return prog;\n}\n\nfunction bindPathFillPattern(\n ctx: DrawContext,\n fill: Extract<FillStyle, { fill: 'pattern' }>,\n): ShaderProgram | null {\n return bindPattern(ctx, ctx.patternFill, fill, ctx.state.transform);\n}\n\n/** Bind `prog` — the path program or the glyph one, which share every paint\n * uniform — to draw `fill` under `model`. */\nfunction bindPattern(\n ctx: DrawContext,\n prog: ShaderProgram,\n fill: Extract<FillStyle, { fill: 'pattern' }>,\n model: GlMat3,\n): ShaderProgram | null {\n const tex = fill.pattern as TextureHandle;\n const entry = getTexture(tex.id);\n if (!entry) {\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n if (isDev) console.warn(`weasel: pattern TextureHandle \"${tex.id}\" not registered`);\n return null;\n }\n const inverse = gradientSpaceInverse(ctx, fill.units);\n if (!inverse) return null;\n const tileSpace = patternTileSpace(inverse, fill.origin ?? { x: 0, y: 0 }, fill.transform);\n if (!tileSpace) return null;\n ctx.textureCache.upload(tex.id, entry.source, 'repeat');\n\n // A path fill mesh carries a_position only, so the tile coordinate is\n // recovered per fragment from the screen position — the same route\n // gradients take through `u_worldInv`, and the reason this can't reuse\n // the image-fill shader, whose a_uv such a mesh leaves unbound.\n const gl = ctx.gl;\n gl.useProgram(prog.handle);\n setProjAndModel(ctx, prog, model);\n setColorMatrixUniforms(ctx, prog);\n gl.uniformMatrix3fv(prog.uniform('u_worldInv')!, false, tileSpace);\n const [tw, th] = textureSize(entry.source);\n gl.uniform2f(prog.uniform('u_tileSize')!, tw, th);\n ctx.textureCache.bind(tex.id, 0);\n gl.uniform1i(prog.uniform('u_sampler')!, 0);\n gl.uniform1f(prog.uniform('u_opacity')!, fill.opacity ?? 1);\n setAlphaUniform(ctx, prog, ctx.state.alpha);\n return prog;\n}\n\n/** Tile extent in paint-space units — one tile spans this many units of\n * whatever space `units` names. */\nfunction textureSize(source: HTMLImageElement | ImageBitmap): [number, number] {\n const w = 'naturalWidth' in source ? source.naturalWidth : source.width;\n const h = 'naturalHeight' in source ? source.naturalHeight : source.height;\n return [w || 1, h || 1];\n}\n\n/**\n * Screen→gradient-space matrix for `u_worldInv`, which the vertex shader\n * applies to each fragment's screen position to recover the coordinates the\n * gradient's geometry is expressed in.\n *\n * `'world'` silently degrades to screen space when no view matrix reached\n * the renderer — `render(commands)` without a view is a supported call, and\n * a missing view is not worth a thrown frame. `null` when the space has no\n * inverse; a paint measured in it draws nothing.\n */\nfunction gradientSpaceInverse(ctx: DrawContext, units: GradientUnits | undefined): GlMat3 | null {\n if (units === 'local') return mat3.invert(ctx.state.transform);\n if (units === 'world' && ctx.viewMatrix) return mat3.invert(ctx.viewMatrix);\n return mat3.identity();\n}\n\n/** The paint space `units` names → device pixels: the forward transform\n * `gradientSpaceInverse` undoes, scaled by the target's pixel ratio. */\nfunction spaceToDevice(ctx: DrawContext, units: GradientUnits | undefined): GlMat3 | null {\n const inverse = gradientSpaceInverse(ctx, units);\n const toScreen = inverse && mat3.invert(inverse);\n if (!toScreen) return null;\n const ratio = ctx.deviceWidth && ctx.widthCss > 0 ? ctx.deviceWidth / ctx.widthCss : 1;\n return mat3.multiply(mat3.scaled(mat3.identity(), ratio, ratio), toScreen);\n}\n\nfunction bindPathFillGradient(\n ctx: DrawContext,\n fill: Extract<FillStyle, { fill: 'linear-gradient' | 'radial-gradient' | 'conic-gradient' }>,\n): ShaderProgram | null {\n return bindGradient(ctx, ctx.gradFill, fill, ctx.state.transform);\n}\n\n/** The gradient counterpart of `bindPattern`. */\nfunction bindGradient(\n ctx: DrawContext,\n prog: ShaderProgram,\n fill: Extract<FillStyle, { fill: 'linear-gradient' | 'radial-gradient' | 'conic-gradient' }>,\n model: GlMat3,\n): ShaderProgram | null {\n const inverse = gradientSpaceInverse(ctx, fill.units);\n if (!inverse) return null;\n const gl = ctx.gl;\n const row = ctx.gradRamps.upload(fill.stops, fill.interpolate ?? 'rgb');\n\n gl.useProgram(prog.handle);\n setProjAndModel(ctx, prog, model);\n\n gl.uniformMatrix3fv(prog.uniform('u_worldInv')!, false, inverse);\n setColorMatrixUniforms(ctx, prog);\n\n ctx.gradRamps.bind(0);\n gl.uniform1i(prog.uniform('u_ramp')!, 0);\n gl.uniform1f(prog.uniform('u_rampV')!, ctx.gradRamps.rowV(row));\n setAlphaUniform(ctx, prog, ctx.state.alpha);\n gl.uniform1f(prog.uniform('u_opacity')!, fill.opacity ?? 1);\n\n if (fill.fill === 'linear-gradient') {\n gl.uniform1i(prog.uniform('u_gradKind')!, 0);\n const dx = fill.to.x - fill.from.x;\n const dy = fill.to.y - fill.from.y;\n const len = Math.hypot(dx, dy) || 1;\n gl.uniform2f(prog.uniform('u_gradP0')!, fill.from.x, fill.from.y);\n gl.uniform2f(prog.uniform('u_gradDir')!, dx / len, dy / len);\n gl.uniform1f(prog.uniform('u_gradLen')!, len);\n gl.uniform1f(prog.uniform('u_gradRadius')!, 0);\n gl.uniform1f(prog.uniform('u_gradAngle')!, 0);\n } else if (fill.fill === 'radial-gradient') {\n gl.uniform1i(prog.uniform('u_gradKind')!, 1);\n gl.uniform2f(prog.uniform('u_gradP0')!, fill.center.x, fill.center.y);\n gl.uniform2f(prog.uniform('u_gradDir')!, 0, 0);\n gl.uniform1f(prog.uniform('u_gradLen')!, 0);\n gl.uniform1f(prog.uniform('u_gradRadius')!, fill.radius);\n gl.uniform1f(prog.uniform('u_gradAngle')!, 0);\n } else {\n // conic\n gl.uniform1i(prog.uniform('u_gradKind')!, 2);\n gl.uniform2f(prog.uniform('u_gradP0')!, fill.center.x, fill.center.y);\n gl.uniform2f(prog.uniform('u_gradDir')!, 0, 0);\n gl.uniform1f(prog.uniform('u_gradLen')!, 0);\n gl.uniform1f(prog.uniform('u_gradRadius')!, 0);\n gl.uniform1f(prog.uniform('u_gradAngle')!, fill.angle);\n }\n\n return prog;\n}\n\n// ─── Per-fragment clip test ───────────────────────────────────────────────────\n\n/**\n * Set the stencil test for the current clip depth. Called by every\n * fragment-producing draw before its drawElements call when clipDepth > 0.\n * At clipDepth = 0, disables STENCIL_TEST (zero-overhead common case).\n *\n * Note: not called by drawPathFillStencil / drawPathStrokeStenciled, which\n * manage their own stencil state (evenodd / inner-outer stencil). Those paths\n * coexist with clip bits because they use bit 0 exclusively while clip levels\n * occupy bits 1-7.\n */\nfunction applyClipTest(ctx: DrawContext, depth: number = ctx.clipDepth): void {\n const gl = ctx.gl;\n if (depth === 0) {\n gl.disable(gl.STENCIL_TEST);\n return;\n }\n const mask = ancestorMask(depth);\n gl.enable(gl.STENCIL_TEST);\n gl.stencilFunc(gl.EQUAL, mask, mask);\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);\n}\n\n// ─── Clip-stencil helpers ────────────────────────────────────────────────────\n\n/**\n * Bit-mask for ancestor clip levels.\n * Returns bits 1..depth (inclusive).\n * depth=0 → 0x00; depth=1 → 0x02; depth=3 → 0x0E.\n */\nfunction ancestorMask(depth: number): number {\n return depth === 0 ? 0 : ((1 << (depth + 1)) - 1) & 0xFE;\n}\n\n/**\n * Rasterize a path into the stencil buffer using the pathFill shader geometry.\n * The caller is responsible for setting stencilFunc / stencilOp / stencilMask\n * and colorMask before calling.\n */\nfunction rasterizePathToStencil(ctx: DrawContext, path: Path, model: GlMat3): void {\n const gl = ctx.gl;\n const handle = fillMeshHandle(ctx, path);\n gl.useProgram(ctx.pathFill.handle);\n gl.bindVertexArray(handle.vao);\n setProjAndModel(ctx, ctx.pathFill, model);\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n gl.bindVertexArray(null);\n}\n\n/**\n * Push a clip level. Rasterizes the clip path into the stencil buffer,\n * setting bit `newDepth` where (a) the path's fragment passes AND (b) all\n * ancestor clip bits are already set.\n *\n * Invariant: restores stencilMask(0xFF) on exit so callers (draw functions)\n * can rely on an unnarrowed mask after clip ops complete.\n */\nexport function pushClip(\n ctx: DrawContext, path: Path, newDepth: number, model: GlMat3 = ctx.state.transform,\n): void {\n // First, not last: a run staged outside the clip would otherwise draw under\n // a mask it never had.\n flushBatch(ctx);\n const gl = ctx.gl;\n const ancestors = ancestorMask(newDepth - 1);\n const newBit = 1 << newDepth;\n const ref = ancestors | newBit;\n\n gl.enable(gl.STENCIL_TEST);\n gl.colorMask(false, false, false, false);\n gl.stencilMask(newBit);\n gl.stencilFunc(gl.EQUAL, ref, ancestors);\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);\n\n rasterizePathToStencil(ctx, path, model);\n\n gl.colorMask(true, true, true, true);\n // Restore full mask so subsequent draw functions don't inherit a narrowed mask.\n gl.stencilMask(0xFF);\n}\n\n/**\n * Pop a clip level. Rasterizes the same path again, clearing bit\n * `oldDepth + 1` where it was set during the matching push.\n *\n * Must re-enable STENCIL_TEST because child draw functions (drawPathFillStencil,\n * drawPathStrokeStenciled) call gl.disable(STENCIL_TEST) at their end. If\n * one of those was the last child before popClip runs, the test would be off\n * and rasterizePathToStencil would write nothing.\n *\n * Invariant: restores stencilMask(0xFF) on exit so callers are not left with\n * a narrowed mask.\n */\nexport function popClip(\n ctx: DrawContext, path: Path, oldDepth: number, model: GlMat3 = ctx.state.transform,\n): void {\n // First, not last: past here the mask is gone, and these pixels belonged\n // inside it. A run staged below this bit does not test it, so it lives on.\n if (ctx.batchState !== undefined && ctx.batchState.clipDepth > oldDepth) flushBatch(ctx);\n const gl = ctx.gl;\n // Re-enable stencil: child draw functions (evenodd/stenciled-stroke) disable\n // it at their end; we must set it before writing the clear pass.\n gl.enable(gl.STENCIL_TEST);\n\n const oldBit = 1 << (oldDepth + 1);\n const ref = ancestorMask(oldDepth) | oldBit;\n\n gl.colorMask(false, false, false, false);\n gl.stencilMask(oldBit);\n gl.stencilFunc(gl.EQUAL, ref, ref);\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.ZERO);\n\n rasterizePathToStencil(ctx, path, model);\n\n gl.colorMask(true, true, true, true);\n // Restore full mask so subsequent draw functions don't inherit a narrowed mask.\n gl.stencilMask(0xFF);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction drawPathFillStencil(ctx: DrawContext, fill: FillStyle, handle: GLMeshHandle): void {\n const gl = ctx.gl;\n gl.useProgram(ctx.pathFill.handle);\n gl.bindVertexArray(handle.vao);\n setProjAndModel(ctx, ctx.pathFill);\n\n gl.enable(gl.STENCIL_TEST);\n gl.colorMask(false, false, false, false);\n gl.stencilMask(0x01);\n gl.stencilFunc(gl.ALWAYS, 0, 0x01);\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.INVERT);\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n\n const clipMask = ancestorMask(ctx.clipDepth);\n gl.colorMask(true, true, true, true);\n gl.stencilFunc(gl.EQUAL, clipMask | 0x01, clipMask | 0x01);\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);\n // The paint binds here, not above: pass 1 runs under a false colorMask, so a\n // uniform missed here renders black while the GL-recorder tests still pass.\n // Not `drawPathFillByKind` — its `applyClipTest` would disable this stencil.\n if (bindPathFillByKind(ctx, fill)) {\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n }\n\n // Narrow to bit 0 first: clear only zeroes bits the mask enables, and\n // pushClip owns bits 1-7.\n gl.stencilMask(0x01);\n gl.clear(gl.STENCIL_BUFFER_BIT);\n gl.disable(gl.STENCIL_TEST);\n gl.bindVertexArray(null);\n}\n\n/** `cmd` with its `{ px }` lengths — the stroke width and any marker size —\n * resolved against the accumulated transform's quantized scale, so everything\n * downstream (the ribbon cache key, the insets, the heads) sees world units. */\nfunction withResolvedStrokeLengths(ctx: DrawContext, cmd: StrokedPathCommand): StrokedPathCommand {\n const stroke = cmd.stroke;\n const { markerStart, markerMid, markerEnd } = stroke;\n if (typeof stroke.width !== 'object' && !isPxMarker(markerStart)\n && !isPxMarker(markerMid) && !isPxMarker(markerEnd)) {\n return cmd;\n }\n const scale = mat3.meanScaleOf(ctx.state.transform);\n const resolved: Stroke & { paint: FillStyle } = { ...stroke };\n if (typeof stroke.width === 'object') {\n resolved.width = resolveStrokeWidth(stroke.width, quantizeStrokeScale(stroke.width.px, scale));\n }\n if (isPxMarker(markerStart)) resolved.markerStart = resolvedMarker(markerStart, scale);\n if (isPxMarker(markerMid)) resolved.markerMid = resolvedMarker(markerMid, scale);\n if (isPxMarker(markerEnd)) resolved.markerEnd = resolvedMarker(markerEnd, scale);\n return { ...cmd, stroke: resolved };\n}\n\ntype PxMarker = Exclude<MarkerRef, string> & { size: { px: number } };\n\nfunction isPxMarker(ref: MarkerRef | undefined): ref is PxMarker {\n return typeof ref === 'object' && typeof ref.size === 'object';\n}\n\nfunction resolvedMarker(ref: PxMarker, scale: number): MarkerRef {\n return { ...ref, size: resolveMarkerSize(ref, 0, quantizeStrokeScale(ref.size.px, scale)) };\n}\n\nfunction drawPathStroke(ctx: DrawContext, rawCmd: StrokedPathCommand): void {\n const cmd = withResolvedStrokeLengths(ctx, rawCmd);\n const stroke = cmd.stroke;\n const align = stroke.align ?? 'center';\n if (cmd.path.kind === 'polygon' && align !== 'center') {\n flushForOwnDraw(ctx);\n drawPathStrokeStenciled(ctx, cmd, align);\n } else {\n drawPathStrokeUnclipped(ctx, cmd);\n }\n // After the ribbon, so a head sits on top of the line it caps.\n const width = resolveStrokeWidth(stroke.width ?? 1, 1);\n for (const marker of cachedMarkerCommands(cmd.path, rawCmd.stroke, stroke, width, ctx.flattenTolerance)) {\n drawPath(ctx, marker);\n }\n}\n\nfunction drawPathStrokeUnclipped(ctx: DrawContext, cmd: StrokedPathCommand): void {\n const stroke = cmd.stroke;\n const paint = stroke.paint;\n const isSolid = paint.fill === undefined || paint.fill === 'solid';\n const solid = paint as { color: string; opacity?: number };\n const mesh = strokeMesh(cmd.path, stroke, ctx.flattenTolerance);\n if (mesh.indices.length === 0) return;\n\n // Staged, a ribbon allocates nothing and joins the fill it sits on.\n const hasVColors = !!(stroke.vertexColors && stroke.vertexColors.length > 0);\n const batched = batchPaint(ctx, paint, hasVColors);\n if (batched === null) return;\n if (tryStageFill(ctx, mesh, batched)) return;\n\n // The VAO records the per-draw color attribute, so a vertex-colored draw\n // cannot share a persistent one with a draw that has no vertex colors.\n const handle = hasVColors\n ? ctx.meshCache.uploadTransient(mesh)\n : ctx.meshCache.uploadRecurring(mesh);\n\n if (!isSolid && !hasVColors) {\n drawPathFillByKind(ctx, paint, handle);\n return;\n }\n\n const gl = ctx.gl;\n if (hasVColors) {\n const prog = ctx.pathFillVColor;\n gl.useProgram(prog.handle);\n gl.bindVertexArray(handle.vao);\n setProjAndModel(ctx, prog);\n // Per-vertex colors are the paint here; a non-solid base has no single\n // color to multiply by, so white leaves the vertex colors unmodified.\n setSolidPaintUniforms(ctx, prog, isSolid ? solid.color : '#ffffff', paint.opacity);\n setColorMatrixUniforms(ctx, prog);\n\n const expanded = expandAnchorColors(stroke.vertexColors!, handle);\n const colorVbo = gl.createBuffer();\n if (!colorVbo) throw new Error('drawPathStrokeUnclipped: createBuffer (color VBO) returned null');\n gl.bindBuffer(gl.ARRAY_BUFFER, colorVbo);\n gl.bufferData(gl.ARRAY_BUFFER, expanded, gl.DYNAMIC_DRAW);\n const aVColorLoc = prog.attribute('a_vertexColor');\n if (aVColorLoc !== undefined) {\n gl.enableVertexAttribArray(aVColorLoc);\n gl.vertexAttribPointer(aVColorLoc, 4, gl.FLOAT, false, 0, 0);\n }\n applyClipTest(ctx);\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n gl.bindVertexArray(null);\n // Per-draw color VBO; free after VAO unbind to avoid leak per stroke vColor draw.\n gl.deleteBuffer(colorVbo);\n return;\n }\n\n gl.useProgram(ctx.pathFill.handle);\n gl.bindVertexArray(handle.vao);\n setProjAndModel(ctx, ctx.pathFill);\n setSolidPaintUniforms(ctx, ctx.pathFill, solid.color, solid.opacity);\n setColorMatrixUniforms(ctx, ctx.pathFill);\n applyClipTest(ctx);\n drawTriangles(ctx, handle.indexCount, ctx.gl.UNSIGNED_INT);\n gl.bindVertexArray(null);\n}\n\n/** The ribbon cache compares `vertexWidths` by reference, so the doubled copy\n * has to be the same array on every frame the source array is. */\nconst DOUBLED_VERTEX_WIDTHS = new WeakMap<number[], number[]>();\n\nfunction doubledVertexWidths(widths: number[]): number[] {\n let doubled = DOUBLED_VERTEX_WIDTHS.get(widths);\n if (doubled === undefined) {\n doubled = widths.map((w) => w * 2);\n DOUBLED_VERTEX_WIDTHS.set(widths, doubled);\n }\n return doubled;\n}\n\nfunction drawPathStrokeStenciled(\n ctx: DrawContext,\n cmd: StrokedPathCommand,\n align: 'inner' | 'outer',\n): void {\n const stroke = cmd.stroke;\n const paint = stroke.paint;\n const isSolid = paint.fill === undefined || paint.fill === 'solid';\n const solid = paint as { color: string; opacity?: number };\n const widerStroke: Stroke = {\n ...stroke,\n width: resolveStrokeWidth(stroke.width ?? 1, 1) * 2,\n ...(stroke.vertexWidths ? { vertexWidths: doubledVertexWidths(stroke.vertexWidths) } : {}),\n align: 'center',\n };\n\n const useVColor = !!(stroke.vertexColors && stroke.vertexColors.length > 0);\n\n const fillHandle = fillMeshHandle(ctx, cmd.path);\n const ribbonMesh = strokeMesh(cmd.path, widerStroke, ctx.flattenTolerance);\n if (ribbonMesh.indices.length === 0) return;\n // The VAO records the per-draw color attribute, so a vertex-colored draw\n // cannot share a persistent one with a draw that has no vertex colors.\n const ribbonHandle = useVColor\n ? ctx.meshCache.uploadTransient(ribbonMesh)\n : ctx.meshCache.uploadRecurring(ribbonMesh);\n\n const gl = ctx.gl;\n const prog = useVColor ? ctx.pathFillVColor : ctx.pathFill;\n gl.useProgram(prog.handle);\n setProjAndModel(ctx, prog);\n\n gl.enable(gl.STENCIL_TEST);\n gl.colorMask(false, false, false, false);\n gl.stencilMask(0x01);\n gl.stencilFunc(gl.ALWAYS, 1, 0x01);\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);\n gl.bindVertexArray(fillHandle.vao);\n drawTriangles(ctx, fillHandle.indexCount, ctx.gl.UNSIGNED_INT);\n\n const clipMask = ancestorMask(ctx.clipDepth);\n gl.colorMask(true, true, true, true);\n if (align === 'inner') {\n gl.stencilFunc(gl.EQUAL, clipMask | 0x01, clipMask | 0x01);\n } else {\n gl.stencilFunc(gl.EQUAL, clipMask, clipMask | 0x01);\n }\n gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);\n // Bind the paint here rather than through `drawPathFillByKind`: that calls\n // `applyClipTest`, which at clip depth 0 disables the stencil test this\n // function just set up to clip the ribbon to one side.\n let ribbonProg: ShaderProgram | null = prog;\n if (useVColor) {\n // Per-vertex colors are the paint here; a non-solid base has no single\n // color to multiply by, so white leaves the vertex colors unmodified.\n setSolidPaintUniforms(ctx, prog, isSolid ? solid.color : '#ffffff', paint.opacity);\n setColorMatrixUniforms(ctx, prog);\n } else {\n ribbonProg = bindPathFillByKind(ctx, paint);\n }\n if (!ribbonProg) {\n gl.stencilMask(0x01);\n gl.clear(gl.STENCIL_BUFFER_BIT);\n gl.disable(gl.STENCIL_TEST);\n gl.bindVertexArray(null);\n return;\n }\n gl.bindVertexArray(ribbonHandle.vao);\n\n let colorVbo: WebGLBuffer | null = null;\n if (useVColor) {\n const expanded = expandAnchorColors(stroke.vertexColors!, ribbonHandle);\n colorVbo = gl.createBuffer();\n if (!colorVbo) throw new Error('drawPathStrokeStenciled: createBuffer (color VBO) returned null');\n gl.bindBuffer(gl.ARRAY_BUFFER, colorVbo);\n gl.bufferData(gl.ARRAY_BUFFER, expanded, gl.DYNAMIC_DRAW);\n const aVColorLoc = ribbonProg.attribute('a_vertexColor');\n if (aVColorLoc !== undefined) {\n gl.enableVertexAttribArray(aVColorLoc);\n gl.vertexAttribPointer(aVColorLoc, 4, gl.FLOAT, false, 0, 0);\n }\n }\n\n drawTriangles(ctx, ribbonHandle.indexCount, ctx.gl.UNSIGNED_INT);\n\n // Narrow to bit 0 first: clear only zeroes bits the mask enables, and\n // pushClip owns bits 1-7.\n gl.stencilMask(0x01);\n gl.clear(gl.STENCIL_BUFFER_BIT);\n gl.disable(gl.STENCIL_TEST);\n gl.bindVertexArray(null);\n // Delete after the unbind: deleting a bound buffer leaves its attribute\n // enabled and pointing at nothing, recorded in whatever VAO is live.\n if (colorVbo) gl.deleteBuffer(colorVbo);\n}\n\n/**\n * On-screen glyph size (CSS px) at or above which a face with registered\n * outlines is drawn as geometry instead of sampled from a distance field.\n *\n * 48 is the dynamic tier's own `BAKE_SIZE`, which makes it the size at which\n * that tier stops being an interpolation and starts being a magnification:\n * `glyphRasterizer.ts` measures coverage error bottoming out *at* the bake\n * size and rising on both sides, and past a few times it the reconstructed\n * field shows the raster as contour wobble. The same number is a safe\n * crossing for the baked MSDF atlas, which is still crisp here — outlines are\n * exact, so switching early costs nothing but the tessellation, and the\n * hinting the atlas has and outlines don't stopped mattering well below this.\n */\nexport const OUTLINE_MIN_SCREEN_PX = 48;\n\n/**\n * Uniform scale the model matrix applies, as the geometric mean of its two\n * axis lengths. Used to turn a screen-pixel threshold into the world-space\n * size layout compares against.\n *\n * The mean rather than either axis alone so a non-uniform scale answers with\n * something between the two instead of picking a side; anisotropy that\n * extreme is not a case this threshold needs to be exact about, since being\n * one glyph-size late or early only changes which of two correct renderings\n * is used.\n */\nfunction modelScale(m: Float32Array): number {\n const sx = Math.hypot(m[0], m[1]);\n const sy = Math.hypot(m[3], m[4]);\n return Math.sqrt(sx * sy) || 1;\n}\n\nfunction drawText(ctx: DrawContext, cmd: TextDrawCommand): void {\n const style = resolveTextStyle(cmd.style);\n const lineHeight = style.lineHeight;\n const align = cmd.align ?? style.align;\n const maxWidth = cmd.maxWidth ?? Infinity;\n\n // Screen threshold → world threshold. Zooming in lowers the world size that\n // qualifies, which is the whole point: a 12px label at 8× zoom is 96 screen\n // pixels of text and wants outlines exactly as much as a 96px heading does.\n const minScreen = ctx.textOutlineMinScreenSize ?? OUTLINE_MIN_SCREEN_PX;\n const outlineMinSize = Number.isFinite(minScreen)\n ? minScreen / modelScale(ctx.state.transform)\n : undefined;\n\n const laid = cachedLayoutRuns(cmd.runs, {\n maxWidth, alignWidth: cmd.width, lineHeight, align, justify: cmd.justify, outlineMinSize,\n });\n // Decorations are checked too: text whose glyphs are all ink-free — every\n // one still awaiting a dynamic-atlas bake, say — produces no groups at all\n // while still carrying a rule that has to be drawn.\n if (laid.groups.length === 0 && laid.decorations.length === 0) return;\n\n // `laid` is origin-relative, so this is the command's position plus the\n // verticalAlign shift. Applied at upload time, not baked in: the layout is\n // shared and not ours to edit — a cached layout that absorbed either offset\n // would gain another one every frame and slide off the page. Every consumer\n // below adds them while packing vertices, which costs one addition inside\n // loops that are already walking every vertex.\n const dx = cmd.x;\n const dy = cmd.y + verticalAlignOffset(cmd.verticalAlign, cmd.height, laid.bounds.height);\n\n for (const group of laid.groups) {\n if (group.source === 'outline') drawTextOutlineGroup(ctx, group, dx, dy);\n else drawTextGroup(ctx, group, dx, dy);\n }\n\n drawTextDecorations(ctx, laid.decorations, dx, dy);\n}\n\n/**\n * Paint one group of tessellated glyph outlines.\n *\n * The whole group becomes a single mesh: cached em-space triangles are\n * transformed on the CPU into world space and appended to one buffer, so a\n * paragraph set in one face and color is one draw call — the same batching\n * the atlas tier gets from packing glyphs into one texture. The alternative,\n * a model matrix per glyph, would be a draw call per glyph.\n *\n * Going through `drawPathFillByKind` rather than straight to `pathFill` is\n * what makes gradient- and pattern-filled text fall out for free: a glyph\n * here is geometry like any other, and those programs shade in world space,\n * so they need nothing from the text pipeline.\n */\nfunction drawTextOutlineGroup(ctx: DrawContext, group: LaidOutGroup, dx: number, dy: number): void {\n const fill = group.fill;\n if (fill !== null) {\n const mesh = outlineGroupMesh(group, dx, dy);\n if (mesh) drawOutlineMesh(ctx, fill, mesh);\n }\n\n // Stroke after fill — Canvas2D's fillText-then-strokeText convention, and\n // SVG's default paint-order. A second batched draw call over the same\n // group, not a call per glyph.\n const strokePaint = group.stroke?.paint;\n if (!strokePaint) return;\n const ribbon = outlineGroupStrokeMesh(group, dx, dy, mat3.meanScaleOf(ctx.state.transform));\n if (ribbon) drawOutlineMesh(ctx, strokePaint, ribbon);\n}\n\n/**\n * Paint one merged glyph-outline mesh, staging it where it fits.\n *\n * Through `tryStageFill` rather than straight to `drawPathFillByKind`,\n * because a paragraph can mix tiers: a heading drawn as outlines and a caption\n * drawn from the atlas are groups of one command, and the atlas half now\n * stages. An outline that painted itself while glyphs sat staged behind it\n * would come out under them.\n */\nfunction drawOutlineMesh(ctx: DrawContext, fill: FillStyle, mesh: Mesh): void {\n const paint = batchPaint(ctx, fill, false);\n if (paint === null) return;\n if (tryStageFill(ctx, mesh, paint)) return;\n drawPathFillByKind(ctx, fill, ctx.meshCache.uploadTransient(mesh));\n}\n\n/**\n * Merge a group's glyphs into one world-space mesh, or `null` when nothing in\n * it has area.\n *\n * Every glyph mesh here is `'nonzero'` (that is what `pathFromD` produces and\n * what a font outline means), so none of them sets `requiresStencil` and\n * concatenating their triangles is sound — an even-odd mesh would be a naive\n * per-contour fan that only resolves correctly through a stencil pass, and\n * merging one into a batch would fill its counters solid.\n */\nfunction outlineGroupMesh(group: LaidOutGroup, dx: number, dy: number): Mesh | null {\n return mergeGlyphMeshes(group, dx, dy, (glyph) => outlineMesh(glyph.key, glyph.d));\n}\n\n/**\n * The same merge for the group's stroke: one ribbon per glyph, tessellated in\n * em space and batched into one buffer, so a stroked paragraph is one extra\n * draw call rather than one per glyph.\n *\n * The width crosses into em space by dividing by the glyph's `scale`, which\n * is world units per em — so `stroke.width` stays a world-unit measure and\n * does not grow with `fontSize`, matching every other stroke in the kit.\n *\n * A synthetic oblique shears the ribbon along with the glyph. That is a real\n * (small) distortion — a sheared circle is an ellipse, so the outline is\n * marginally thicker across the lean than along it — and it is deliberate:\n * shearing the finished ribbon is what keeps the outline glued to the glyph\n * it outlines, which re-tessellating in sheared space would not.\n */\nfunction outlineGroupStrokeMesh(\n group: LaidOutGroup,\n dx: number,\n dy: number,\n scale: number,\n): Mesh | null {\n const stroke = group.stroke;\n if (!stroke) return null;\n const width = resolveStrokeWidth(stroke.width ?? 1, scale);\n if (!(width > 0)) return null;\n return mergeGlyphMeshes(group, dx, dy, (glyph) =>\n glyph.scale > 0\n ? outlineStrokeMesh(glyph.key, glyph.d, quantizeEmWidth(width / glyph.scale), stroke)\n : null);\n}\n\n/**\n * Transform each glyph's em-space mesh into world space and concatenate.\n * Shared by the fill and stroke paths, which differ only in which mesh they\n * ask for per glyph — the placement math must not fork, or an outline would\n * drift off the glyph it outlines.\n */\nfunction mergeGlyphMeshes(\n group: LaidOutGroup,\n dx: number,\n dy: number,\n meshFor: (glyph: LaidOutOutlineGlyph) => Mesh | null,\n): Mesh | null {\n const parts: { mesh: Mesh; glyph: LaidOutOutlineGlyph }[] = [];\n let vertexFloats = 0;\n let indexCount = 0;\n for (const glyph of group.glyphs) {\n const mesh = meshFor(glyph);\n if (!mesh || mesh.indices.length === 0) continue;\n parts.push({ mesh, glyph });\n vertexFloats += mesh.vertices.length;\n indexCount += mesh.indices.length;\n }\n if (parts.length === 0) return null;\n\n // Matches the SDF vertex shader's skew exactly: x moves by\n // `(baselineY - y) * tan(angle)`, and in em space `baselineY - y` is\n // `-ey * scale`, so above-baseline vertices (negative ey) lean right.\n const shear = group.synthetic.italic ? Math.tan(SYNTHETIC_ITALIC_RADIANS) : 0;\n\n const vertices = new Float32Array(vertexFloats);\n const indices = new Uint32Array(indexCount);\n let vi = 0;\n let ii = 0;\n let base = 0;\n for (const { mesh, glyph } of parts) {\n const { x, baselineY, scale } = glyph;\n for (let k = 0; k < mesh.vertices.length; k += 2) {\n const ex = mesh.vertices[k];\n const ey = mesh.vertices[k + 1];\n vertices[vi++] = x + dx + (ex - ey * shear) * scale;\n vertices[vi++] = baselineY + dy + ey * scale;\n }\n for (let k = 0; k < mesh.indices.length; k++) indices[ii++] = base + mesh.indices[k];\n base += mesh.vertices.length / 2;\n }\n return { vertices, indices };\n}\n\n/**\n * Paint underline / strikethrough rules. These are untextured solid rects, so\n * they cannot ride in a `LaidOutGroup`'s quads — those upload a 5-float\n * stride with atlas UVs into an MSDF program. They go through `pathFill`\n * instead, batched by resolved color so a whole decorated paragraph costs\n * one draw call per distinct rule color.\n *\n * Drawn after the glyphs, so a rule sits on top of glyph ink where they\n * overlap (the CSS spec allows either order).\n */\n/**\n * Stage the rules an underline, strikethrough or overline asks for.\n *\n * Color resolution matches `drawTextGroup` exactly — including its ignoring\n * of `fill.opacity` — so a rule can never disagree with the glyphs it\n * underlines. They stage as ordinary rects, which is what keeps them in the\n * run their glyphs are in. A rule under a texture paint is geometry under it,\n * the way an outline glyph is.\n */\nfunction drawTextDecorations(\n ctx: DrawContext, decorations: readonly LaidOutDecoration[], dx: number, dy: number,\n): void {\n for (const d of decorations) {\n if (glyphPaintKindOf(d.fill) !== null) {\n drawOutlineMesh(ctx, d.fill, ruleMesh(d.x0 + dx, d.y0 + dy, d.x1 + dx, d.y1 + dy));\n continue;\n }\n const [r, g, b, a] = 'color' in d.fill ? resolveColor(d.fill.color) : [0, 0, 0, 1];\n let cut: ClipRect | null | undefined;\n for (;;) {\n const staged = stageSolid(ctx, 4);\n if (ctx.drawBatch.pushRect(\n d.x0 + dx, d.y0 + dy, d.x1 - d.x0, d.y1 - d.y0, ctx.state.transform,\n r, g, b, a * (staged.foldsAlpha ? ctx.state.alpha : 1),\n )) break;\n cut = enterUncut(ctx);\n }\n if (cut !== undefined) leaveUncut(ctx, cut);\n }\n}\n\nfunction ruleMesh(x0: number, y0: number, x1: number, y1: number): Mesh {\n return {\n vertices: new Float32Array([x0, y0, x1, y0, x1, y1, x0, y1]),\n indices: new Uint32Array([0, 1, 2, 0, 2, 3]),\n };\n}\n\n/**\n * Amount `a_synthBold` shifts the SDF threshold by when the resolver fell back\n * from a missing bold variant to the regular atlas. Tuned on Inter: it\n * thickens strokes about a pixel at 16px without breaking glyph topology.\n */\nconst SYNTH_BOLD_AMOUNT = 0.08;\n\n/**\n * Stage one group of atlas glyphs into the batch.\n *\n * Everything that used to be a uniform per group rides the vertices instead —\n * the text color, and the atlas as a slot index packed with the paint mode — so\n * a run off a baked MSDF atlas and one off the runtime canvas bake belong to\n * the same draw, and so does whatever else the page put around them. The\n * synthetic-bold threshold is the exception, and `StagedBatchState.synthBold`\n * says why.\n *\n * The synthetic oblique is the one that changes shape rather than home: the\n * old program skewed in the vertex stage against `u_synthItalic`, and the\n * batch places its own corners, so `pushGlyph` shears them as it places them.\n */\nfunction drawTextGroup(\n ctx: DrawContext, group: LaidOutGroup, dx: number, dy: number,\n): void {\n if (group.source === 'canvas') {\n if (!syncDynamicPageTexture(ctx.textureCache, group.page)) return;\n } else {\n if (!ensureFontTexture(group.family, group.weight, group.style, ctx.textureCache)) return;\n }\n if (group.quads.length === 0) return;\n\n const atlasId = group.source === 'canvas'\n ? dynamicPageTextureId(group.page)\n : textureCacheKey(group.family, group.weight, group.style);\n const mode = group.source === 'canvas' ? GLYPH_MODE_R8 : GLYPH_MODE_MSDF;\n const fieldScale = glyphFieldScale(\n group.source === 'canvas' ? 'canvas' : 'atlas', group.family, group.weight, group.style,\n );\n if (!fieldScale) return;\n const bold = group.synthetic.bold ? SYNTH_BOLD_AMOUNT : 0;\n const tanItalic = group.synthetic.italic ? Math.tan(SYNTHETIC_ITALIC_RADIANS) : 0;\n const paintKind = glyphPaintKindOf(group.fill);\n if (paintKind !== null) {\n drawPaintedGlyphs(ctx, group, dx, dy, paintKind, atlasId, mode, bold, tanItalic, fieldScale);\n return;\n }\n const color = group.fill !== null && 'color' in group.fill\n ? resolveColor(group.fill.color)\n : [0, 0, 0, 1];\n\n const batch = ctx.drawBatch;\n const m = ctx.state.transform;\n let { staged, slot } = stageGlyphs(ctx, atlasId, fieldScale, bold);\n let alpha = color[3] * (staged.foldsAlpha ? ctx.state.alpha : 1);\n\n for (const q of group.quads) {\n if (batch.wouldOverflow(4)) {\n flushBatch(ctx);\n ({ staged, slot } = stageGlyphs(ctx, atlasId, fieldScale, bold));\n alpha = color[3] * (staged.foldsAlpha ? ctx.state.alpha : 1);\n }\n let cut: ClipRect | null | undefined;\n while (!batch.pushGlyph(\n q.x0 + dx, q.y0 + dy, q.x1 + dx, q.y1 + dy, q.baselineY + dy, tanItalic, m,\n q.u0, q.v0, q.u1, q.v1,\n color[0], color[1], color[2], alpha,\n slot, mode,\n )) {\n cut = enterUncut(ctx);\n ({ staged, slot } = stageGlyphs(ctx, atlasId, fieldScale, bold));\n alpha = color[3] * (staged.foldsAlpha ? ctx.state.alpha : 1);\n }\n if (cut !== undefined) {\n leaveUncut(ctx, cut);\n ({ staged, slot } = stageGlyphs(ctx, atlasId, fieldScale, bold));\n alpha = color[3] * (staged.foldsAlpha ? ctx.state.alpha : 1);\n }\n }\n}\n\n/** Which glyph-paint program `fill` needs, or `null` for a paint the batch\n * draws as one color. */\nfunction glyphPaintKindOf(fill: FillStyle | null): GlyphPaintKind | null {\n const kind = fill?.fill ?? 'solid';\n if (kind === 'pattern') return 'pattern';\n if (kind === 'linear-gradient' || kind === 'radial-gradient' || kind === 'conic-gradient') {\n return 'gradient';\n }\n return kind === 'solid' ? null : 'texture';\n}\n\n/** The atlas's unit while a glyph-paint run draws; the paint has unit 0. */\nconst GLYPH_PAINT_ATLAS_UNIT = 1;\n\n/**\n * Draw one group of atlas glyphs with a texture paint, its coverage masking\n * the paint — see `shaders/glyphPaint.ts`.\n *\n * Its own draw, as a pattern-filled path is: the glyph vertex has no room for\n * a paint coordinate beside its atlas one, and widening it would cost every\n * vertex in every run. The quads still stage through `DrawBatch`, drained\n * first, and are drawn from it here before anything else can stage behind\n * them, so no run ever holds them and nothing outside this function has to\n * know they exist.\n */\nfunction drawPaintedGlyphs(\n ctx: DrawContext, group: LaidOutGroup, dx: number, dy: number,\n kind: GlyphPaintKind, atlasId: string, mode: number, bold: number, tanItalic: number,\n fieldScale: readonly [number, number],\n): void {\n const prog = ctx.glyphPaintProgram?.(kind);\n if (!prog) return;\n flushForOwnDraw(ctx);\n const fill = group.fill!;\n const m = ctx.state.transform;\n let bound: ShaderProgram | null;\n if (kind === 'pattern') {\n bound = bindPattern(ctx, prog, fill as Extract<FillStyle, { fill: 'pattern' }>, BATCH_MODEL);\n } else if (kind === 'gradient') {\n bound = bindGradient(ctx, prog, fill as Extract<FillStyle, { fill: 'linear-gradient' | 'radial-gradient' | 'conic-gradient' }>, BATCH_MODEL);\n } else {\n const painted = renderPaintToScratch(ctx, fill, glyphScreenBounds(group, dx, dy, tanItalic, m));\n bound = painted && bindScratchPaint(ctx, prog, painted);\n }\n if (!bound) return;\n const gl = ctx.gl;\n ctx.textureCache.bind(atlasId, GLYPH_PAINT_ATLAS_UNIT);\n gl.uniform1i(prog.uniform('u_atlas')!, GLYPH_PAINT_ATLAS_UNIT);\n gl.uniform1f(prog.uniform('u_synthBold')!, bold);\n gl.uniform2f(prog.uniform('u_fieldScale')!, fieldScale[0], fieldScale[1]);\n applyClipTest(ctx);\n\n const batch = ctx.drawBatch;\n // `flushForOwnDraw` put every clip on the stencil, which this draw tests.\n const cut = batch.clip;\n batch.clip = null;\n for (const q of group.quads) {\n if (batch.wouldOverflow(4)) drawStagedGlyphs(ctx);\n batch.pushGlyph(\n q.x0 + dx, q.y0 + dy, q.x1 + dx, q.y1 + dy, q.baselineY + dy, tanItalic, m,\n q.u0, q.v0, q.u1, q.v1,\n 1, 1, 1, 1,\n GLYPH_PAINT_ATLAS_UNIT, mode,\n );\n }\n drawStagedGlyphs(ctx);\n batch.clip = cut;\n gl.activeTexture(gl.TEXTURE0);\n gl.bindVertexArray(null);\n}\n\nfunction drawStagedGlyphs(ctx: DrawContext): void {\n const batch = ctx.drawBatch;\n if (batch.length === 0) return;\n drawTriangles(ctx, batch.uploadAndBind(), ctx.gl.UNSIGNED_INT);\n batch.reset();\n}\n\ninterface ScreenRect { x0: number; y0: number; x1: number; y1: number }\n\n/** The screen-space box of a group's glyph quads, corner for corner as\n * `DrawBatch.pushGlyph` places them. */\nfunction glyphScreenBounds(\n group: LaidOutGroup, dx: number, dy: number, tanItalic: number, m: GlMat3,\n): ScreenRect {\n const b = { x0: Infinity, y0: Infinity, x1: -Infinity, y1: -Infinity };\n const add = (x: number, y: number) => {\n const sx = m[0] * x + m[3] * y + m[6];\n const sy = m[1] * x + m[4] * y + m[7];\n if (sx < b.x0) b.x0 = sx;\n if (sx > b.x1) b.x1 = sx;\n if (sy < b.y0) b.y0 = sy;\n if (sy > b.y1) b.y1 = sy;\n };\n for (const q of group.quads) {\n const x0 = q.x0 + dx, x1 = q.x1 + dx, y0 = q.y0 + dy, y1 = q.y1 + dy;\n const base = q.baselineY + dy;\n const top = (base - y0) * tanItalic;\n const bottom = (base - y1) * tanItalic;\n add(x0 + top, y0);\n add(x1 + top, y0);\n add(x1 + bottom, y1);\n add(x0 + bottom, y1);\n }\n return b;\n}\n\n/** The unit square, stretched over the region a scratch paint covers. */\nconst UNIT_QUAD: Mesh = {\n vertices: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),\n indices: new Uint32Array([0, 1, 2, 0, 2, 3]),\n};\n\ninterface ScratchPaint {\n texture: WebGLTexture;\n /** Screen position → the texture coordinate the paint landed at there. */\n uvFromScreen: GlMat3;\n}\n\n/**\n * Render a registered kind's paint over `rect` (screen px) into the renderer's\n * scratch buffer, through the kind's own `bind` — so any kind that paints a\n * path paints this, with nothing asked of it beyond what a path asks.\n *\n * The region is snapped out to the device-pixel grid and clamped to the\n * drawing buffer, so each texel is one device pixel of the target and a glyph\n * fragment reads its own. The kind sees the same transform, alpha and paint\n * space it would for a path here; only the projection differs, aimed at the\n * scratch buffer instead of the target. No clip and no scissor apply inside:\n * the glyphs that sample the result are drawn under both.\n *\n * `null` when there is no scratch buffer, the region is empty, or the kind\n * declines the paint — and the glyphs then draw nothing, as the outline tier\n * does for a paint no kind binds.\n */\nfunction renderPaintToScratch(ctx: DrawContext, fill: FillStyle, rect: ScreenRect): ScratchPaint | null {\n const scratch = ctx.paintScratch;\n const bind = getPaintKind(fill.fill)?.bind;\n if (!scratch || !bind) return null;\n const ratio = ctx.deviceWidth && ctx.widthCss > 0 ? ctx.deviceWidth / ctx.widthCss : 1;\n const deviceW = ctx.deviceWidth ?? Math.round(ctx.widthCss);\n const deviceH = ctx.deviceHeight ?? Math.round(ctx.heightCss);\n const px0 = Math.max(0, Math.floor(rect.x0 * ratio));\n const py0 = Math.max(0, Math.floor(rect.y0 * ratio));\n const maxSide = ctx.imageCache.maxTextureSide;\n const pw = Math.min(maxSide, Math.min(deviceW, Math.ceil(rect.x1 * ratio)) - px0);\n const ph = Math.min(maxSide, Math.min(deviceH, Math.ceil(rect.y1 * ratio)) - py0);\n if (!(pw > 0 && ph > 0)) return null;\n\n // The region in screen px, and the two matrices a kind's vertex stage\n // multiplies: the unit quad onto it, and it onto the whole of clip space.\n const x0 = px0 / ratio, y0 = py0 / ratio, w = pw / ratio, h = ph / ratio;\n const model = new Float32Array([w, 0, 0, 0, h, 0, x0, y0, 1]);\n const proj = new Float32Array([2 / w, 0, 0, 0, 2 / h, 0, -1 - (2 * x0) / w, -1 - (2 * y0) / h, 1]);\n const base = paintBindContext(ctx);\n const bindCtx: PaintBindContext = {\n ...base,\n alpha: ctx.state.alpha,\n maxTextureSize: base.maxTextureSize,\n setProjAndModel: (prog) => setProjAndModel(ctx, prog, model, proj),\n };\n\n const gl = ctx.gl;\n const target = scratch.acquire(pw, ph);\n const scissorWasOn = gl.isEnabled(gl.SCISSOR_TEST);\n // The last glyph pass left this texture bound to unit 0; a kind sampling a\n // unit it never binds would read the buffer it is drawing into.\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.bindFramebuffer(gl.FRAMEBUFFER, target.fbo);\n gl.viewport(0, 0, pw, ph);\n gl.disable(gl.SCISSOR_TEST);\n gl.disable(gl.STENCIL_TEST);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.disable(gl.BLEND);\n\n const prog = bind(bindCtx, fill);\n if (prog) {\n gl.bindVertexArray(ctx.meshCache.uploadRecurring(UNIT_QUAD).vao);\n drawTriangles(ctx, UNIT_QUAD.indices.length, gl.UNSIGNED_INT);\n gl.bindVertexArray(null);\n }\n\n gl.enable(gl.BLEND);\n returnToRenderTarget(ctx, deviceW, deviceH, scissorWasOn);\n if (!prog) return null;\n return {\n texture: target.texture,\n uvFromScreen: new Float32Array([\n ratio / target.width, 0, 0,\n 0, ratio / target.height, 0,\n -px0 / target.width, -py0 / target.height, 1,\n ]),\n };\n}\n\n/** Bind the glyph program to sample `painted` as its paint. */\nfunction bindScratchPaint(ctx: DrawContext, prog: ShaderProgram, painted: ScratchPaint): ShaderProgram {\n const gl = ctx.gl;\n gl.useProgram(prog.handle);\n setProjAndModel(ctx, prog, BATCH_MODEL);\n gl.uniformMatrix3fv(prog.uniform('u_worldInv')!, false, painted.uvFromScreen);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, painted.texture);\n gl.uniform1i(prog.uniform('u_sampler')!, 0);\n return prog;\n}\n\n/**\n * Stage one image quad. Nothing reaches the GPU here — `flushBatch` draws the\n * run this joins.\n *\n * The upload has to happen now rather than at flush: a run is keyed on bitmap\n * identity, and `flushBatch` binds a texture it assumes already exists.\n */\nfunction drawImage(ctx: DrawContext, cmd: ImageDrawCommand): void {\n ctx.imageCache.upload(cmd.image, cmd.image);\n const { staged, slot } = stageImage(ctx, cmd.image, cmd.sampling ?? 'linear');\n\n // Sampling window: the whole bitmap unless `source` narrows it, with the\n // flips applied by swapping the ends rather than moving the quad.\n const src = cmd.source;\n let u0 = 0, v0 = 0, u1 = 1, v1 = 1;\n if (src) {\n const tw = cmd.image.width, th = cmd.image.height;\n u0 = src.x / tw; u1 = (src.x + src.w) / tw;\n v0 = src.y / th; v1 = (src.y + src.h) / th;\n }\n if (cmd.flipX) { const t = u0; u0 = u1; u1 = t; }\n if (cmd.flipY) { const t = v0; v0 = v1; v1 = t; }\n\n if (!ctx.drawBatch.pushQuad(\n cmd.x, cmd.y, cmd.w, cmd.h, ctx.state.transform,\n u0, v0, u1, v1,\n // Group alpha rides the vertices only where it rode the solid colors too:\n // with a real color matrix in the run it is `u_alpha`, and folding it here\n // as well would apply it twice.\n (cmd.opacity ?? 1) * (staged.foldsAlpha ? ctx.state.alpha : 1),\n slot,\n )) retryUncut(ctx, cmd, undefined, drawImage);\n}\n\n/**\n * Stage a packed run of sprites. The same staging `drawImage` does, minus a\n * command object per quad — see `SpritesDrawCommand`.\n *\n * The run is opened once and reopened only when the per-flush cap forces a\n * chunk, so the state check that costs a command its own run happens twice in\n * a frame rather than twenty thousand times.\n */\nfunction drawSprites(ctx: DrawContext, cmd: SpritesDrawCommand): void {\n const data = cmd.sprites;\n const count = Math.floor(data.length / SPRITE_STRIDE);\n if (count === 0) return;\n\n ctx.imageCache.upload(cmd.image, cmd.image);\n const sampling = cmd.sampling ?? 'linear';\n let { staged, slot } = stageImage(ctx, cmd.image, sampling);\n\n const batch = ctx.drawBatch;\n const m = ctx.state.transform;\n let groupAlpha = staged.foldsAlpha ? ctx.state.alpha : 1;\n const tw = cmd.image.width;\n const th = cmd.image.height;\n\n for (let s = 0, i = 0; s < count; s++, i += SPRITE_STRIDE) {\n if (batch.wouldOverflow(4)) {\n flushBatch(ctx);\n ({ staged, slot } = stageImage(ctx, cmd.image, sampling));\n groupAlpha = staged.foldsAlpha ? ctx.state.alpha : 1;\n }\n const sx = data[i + 4], sy = data[i + 5], sw = data[i + 6], sh = data[i + 7];\n let cut: ClipRect | null | undefined;\n while (!batch.pushQuad(\n data[i], data[i + 1], data[i + 2], data[i + 3], m,\n sx / tw, sy / th, (sx + sw) / tw, (sy + sh) / th,\n data[i + 8] * groupAlpha, slot,\n )) {\n cut = enterUncut(ctx);\n ({ staged, slot } = stageImage(ctx, cmd.image, sampling));\n groupAlpha = staged.foldsAlpha ? ctx.state.alpha : 1;\n }\n if (cut !== undefined) {\n leaveUncut(ctx, cut);\n ({ staged, slot } = stageImage(ctx, cmd.image, sampling));\n groupAlpha = staged.foldsAlpha ? ctx.state.alpha : 1;\n }\n }\n}\n\nexport { mat3, getMesh };\n"],"mappings":"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"}