@pixerate/editor 0.92.0 → 0.94.0

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 (37) hide show
  1. package/THIRD_PARTY_NOTICES.md +2 -0
  2. package/dist/{chunk-PDCITYBT.cjs → chunk-4F3YDIWW.cjs} +367 -2
  3. package/dist/chunk-4F3YDIWW.cjs.map +1 -0
  4. package/dist/chunk-73L6TROJ.cjs +3685 -0
  5. package/dist/chunk-73L6TROJ.cjs.map +1 -0
  6. package/dist/chunk-747CGOT2.js +3685 -0
  7. package/dist/chunk-747CGOT2.js.map +1 -0
  8. package/dist/{chunk-YLB2WVNA.js → chunk-ISDCJHTO.js} +367 -2
  9. package/dist/chunk-ISDCJHTO.js.map +1 -0
  10. package/dist/image-editor/index.cjs +787 -302
  11. package/dist/image-editor/index.cjs.map +1 -1
  12. package/dist/image-editor/index.d.cts +84 -18
  13. package/dist/image-editor/index.d.ts +84 -18
  14. package/dist/image-editor/index.js +560 -75
  15. package/dist/image-editor/index.js.map +1 -1
  16. package/dist/paint/index.cjs +26 -2
  17. package/dist/paint/index.cjs.map +1 -1
  18. package/dist/paint/index.d.cts +96 -2
  19. package/dist/paint/index.d.ts +96 -2
  20. package/dist/paint/index.js +25 -1
  21. package/dist/raster/index.cjs +78 -2
  22. package/dist/raster/index.cjs.map +1 -1
  23. package/dist/raster/index.d.cts +99 -348
  24. package/dist/raster/index.d.ts +99 -348
  25. package/dist/raster/index.js +78 -2
  26. package/dist/{surface-fJhkmNQn.d.cts → surface-CuBg2c6k.d.cts} +1 -1
  27. package/dist/{surface-fJhkmNQn.d.ts → surface-CuBg2c6k.d.ts} +1 -1
  28. package/dist/zlib-BJ6U7LuB.d.cts +795 -0
  29. package/dist/zlib-BjQkpMFi.d.ts +795 -0
  30. package/package.json +3 -3
  31. package/skills/pixerate-image-editor/SKILL.md +63 -4
  32. package/dist/chunk-H543GD6T.cjs +0 -1696
  33. package/dist/chunk-H543GD6T.cjs.map +0 -1
  34. package/dist/chunk-P5TPUNBZ.js +0 -1696
  35. package/dist/chunk-P5TPUNBZ.js.map +0 -1
  36. package/dist/chunk-PDCITYBT.cjs.map +0 -1
  37. package/dist/chunk-YLB2WVNA.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/home/runner/work/editor/editor/packages/core/dist/chunk-H543GD6T.cjs","../src/raster/blur.ts","../src/raster/layers.ts","../src/raster/compositor.ts","../src/raster/zlib.ts","../src/raster/png.ts"],"names":["a","key","i","c"],"mappings":"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ACD,QAAA;AACC,QAAA;AACA,QAAA;AACC,QAAA;AACH,QAAA;AACZ,MAAA;AACF,IAAA;AACF,EAAA;AACe,EAAA;AACjB;AAGwB;AACd,EAAA;AACA,EAAA;AACO,EAAA;AACP,EAAA;AACM,EAAA;AACK,IAAA;AACD,IAAA;AACH,MAAA;AACN,MAAA;AACP,IAAA;AACK,IAAA;AACA,IAAA;AACP,EAAA;AACoB,EAAA;AACtB;AAGwB;AACJ,EAAA;AACA,EAAA;AACA,EAAA;AACC,EAAA;AACL,EAAA;AACF,EAAA;AACA,EAAA;AACK,IAAA;AACA,IAAA;AACA,IAAA;AACjB,EAAA;AACO,EAAA;AACT;AAMA;AACE,EAAA;AACM,mBAAA;AACA,mBAAA;AACC,mBAAA;AACmB,EAAA;AACT,IAAA;AACjB,EAAA;AACqB,EAAA;AACF,IAAA;AACA,IAAA;AACN,IAAA;AACb,EAAA;AACsC,EAAA;AACxB,IAAA;AACC,IAAA;AACD,IAAA;AACD,MAAA;AACK,MAAA;AACA,MAAA;AACD,MAAA;AACf,IAAA;AACF,EAAA;AACc,EAAA;AACI,IAAA;AACL,MAAA;AACK,MAAA;AAChB,IAAA;AACW,IAAA;AACC,IAAA;AACd,EAAA;AACoB,EAAA;AACF,IAAA;AAClB,EAAA;AACF;AAGqB;AACH,EAAA;AACA,EAAA;AACN,EAAA;AACD,EAAA;AAC0E,IAAA;AACjE,IAAA;AACF,IAAA;AACJ,IAAA;AACA,IAAA;AACO,MAAA;AACR,MAAA;AACT,IAAA;AAEuB,IAAA;AACE,IAAA;AACX,IAAA;AACH,MAAA;AACG,QAAA;AACA,QAAA;AACF,QAAA;AACK,QAAA;AACA,QAAA;AACA,QAAA;AACH,QAAA;AACN,QAAA;AACN,MAAA;AACF,IAAA;AACY,IAAA;AACI,MAAA;AACD,QAAA;AACD,QAAA;AACA,QAAA;AACN,QAAA;AACN,MAAA;AACF,IAAA;AACc,IAAA;AACF,IAAA;AACE,MAAA;AACC,MAAA;AACJ,MAAA;AACG,QAAA;AACJ,QAAA;AACR,MAAA;AACO,MAAA;AACT,IAAA;AACY,IAAA;AACI,MAAA;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;AACD,EAAA;AACE,IAAA;AACT,IAAA;AACA,IAAA;AACO,IAAA;AACF,MAAA;AACG,MAAA;AAChB,IAAA;AACa,IAAA;AACA,MAAA;AACG,MAAA;AAChB,IAAA;AACY,IAAA;AACd,EAAA;AACkB,EAAA;AACpB;AAEgB;AACA,EAAA;AACE,IAAA;AACE,IAAA;AACJ,IAAA;AACA,IAAA;AACd,EAAA;AACY,EAAA;AACO,EAAA;AACH,EAAA;AACL,EAAA;AACD,EAAA;AACF,EAAA;AACQ,EAAA;AACE,IAAA;AACF,IAAA;AACG,IAAA;AACE,IAAA;AACX,IAAA;AACO,IAAA;AACL,MAAA;AACI,MAAA;AACd,IAAA;AACF,EAAA;AACW,EAAA;AACb;AAGgB;AACJ,EAAA;AACK,EAAA;AACE,EAAA;AACA,EAAA;AACH,EAAA;AACD,EAAA;AACK,EAAA;AACF,EAAA;AACE,EAAA;AACpB;AAE2B;AAClB,EAAA;AACT;AL0zCqB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/editor/editor/packages/core/dist/chunk-H543GD6T.cjs","sourcesContent":[null,"// Portions ported from photocraft/crates/algo/src/selection_blur.rs (MIT OR Apache-2.0, © ArtCraft Team and contributors). See THIRD_PARTY_NOTICES.md.\n\n/** Separable Gaussian blur of single-channel float planes (mask feather, selection feather). */\n\n/** Normalised Gaussian kernel of σ, truncated at ⌈3σ⌉. */\nfunction gaussianKernel(sigma: number): Float32Array {\n const r = Math.ceil(sigma * 3);\n const k = new Float32Array(2 * r + 1);\n let s = 0;\n for (let i = -r; i <= r; i++) {\n const v = Math.exp(-(i * i) / (2 * sigma * sigma));\n k[i + r] = v;\n s += v;\n }\n for (let i = 0; i < k.length; i++) k[i] /= s;\n return k;\n}\n\n/** Above this σ a Gaussian is approximated by three box passes (cost independent of σ). */\nexport const DIRECT_GAUSSIAN_MAX_SIGMA = 8;\n\n/** Box sizes of three passes whose combined variance matches σ² (Kovesi). */\nfunction boxRadii(sigma: number): [number, number, number] {\n const n = 3;\n const wIdeal = Math.sqrt((12 * sigma * sigma) / n + 1);\n let wl = Math.floor(wIdeal);\n if (wl % 2 === 0) wl--;\n const wu = wl + 2;\n const mIdeal = (12 * sigma * sigma - n * wl * wl - 4 * n * wl - 3 * n) / (-4 * wl - 4);\n const m = Math.round(mIdeal);\n const sizes = [0, 1, 2].map((i) => (i < m ? wl : wu));\n return sizes.map((s) => (s - 1) / 2) as [number, number, number];\n}\n\n/** How a blur treats pixels beyond the image: `zero`, or `clamp` (replicate the border). */\nexport type BlurEdge = 'zero' | 'clamp';\ntype Edge = BlurEdge;\n\nfunction convolveLine(src: Float32Array, off: number, stride: number, len: number, k: Float32Array, edge: Edge, dst: Float32Array) {\n const r = (k.length - 1) / 2;\n for (let i = 0; i < len; i++) {\n let a = 0;\n const lo = i - r;\n for (let j = 0; j < k.length; j++) {\n let x = lo + j;\n if (x < 0 || x >= len) {\n if (edge === 'zero') continue;\n x = x < 0 ? 0 : len - 1;\n }\n a += src[off + x * stride] * k[j];\n }\n dst[i] = a;\n }\n}\n\n/**\n * Three box passes along one line, run on the line padded by the passes' total reach (zeros or\n * replicated ends), so the result equals one convolution with the combined kernel over the\n * same outside values — clipping between passes would lose the mass that spilled out.\n */\nfunction boxesLine(\n src: Float32Array,\n off: number,\n stride: number,\n len: number,\n radii: readonly number[],\n edge: Edge,\n a: Float32Array,\n b: Float32Array,\n dst: Float32Array\n) {\n const pad = radii.reduce((s, r) => s + r, 0);\n const plen = len + 2 * pad;\n for (let i = 0; i < plen; i++) {\n const j = i - pad;\n a[i] = j < 0 ? (edge === 'zero' ? 0 : src[off]) : j >= len ? (edge === 'zero' ? 0 : src[off + (len - 1) * stride]) : src[off + j * stride];\n }\n let from = a;\n let to = b;\n for (const r of radii) {\n // Window clipped to the padded line; the padding is wide enough that the clip never\n // reaches the part that is kept.\n let sum = 0;\n for (let i = 0; i <= Math.min(r, plen - 1); i++) sum += from[i];\n const k = 2 * r + 1;\n for (let i = 0; i < plen; i++) {\n to[i] = sum / k;\n const add = i + r + 1;\n const drop = i - r;\n if (add < plen) sum += from[add];\n if (drop >= 0) sum -= from[drop];\n }\n const t = from;\n from = to;\n to = t;\n }\n for (let i = 0; i < len; i++) dst[i] = from[i + pad];\n}\n\n/**\n * Separable Gaussian blur of a single-channel float image. `edge` `zero` treats pixels beyond\n * the image as 0 (selection feather), `clamp` replicates the border (mask refinement). σ up to\n * {@link DIRECT_GAUSSIAN_MAX_SIGMA} is convolved directly; wider blurs use three box passes, so\n * the cost per pixel never grows with σ.\n */\nexport function gaussianBlur(src: ArrayLike<number>, w: number, h: number, sigma: number, edge: Edge = 'zero'): Float32Array {\n const out = Float32Array.from(src);\n if (!(sigma >= 0.1) || w <= 0 || h <= 0) return out;\n // Far beyond the image a wider blur changes nothing but cost.\n const s = Math.min(sigma, 4 * Math.max(w, h));\n const line = new Float32Array(Math.max(w, h));\n const passes: Array<(buf: Float32Array, off: number, stride: number, len: number) => void> = [];\n if (s <= DIRECT_GAUSSIAN_MAX_SIGMA) {\n const k = gaussianKernel(s);\n passes.push((buf, off, stride, len) => convolveLine(buf, off, stride, len, k, edge, line));\n } else {\n const radii = boxRadii(s);\n const plen = Math.max(w, h) + 2 * radii.reduce((a, r) => a + r, 0);\n const a = new Float32Array(plen);\n const b = new Float32Array(plen);\n passes.push((buf, off, stride, len) => boxesLine(buf, off, stride, len, radii, edge, a, b, line));\n }\n for (const pass of passes) {\n for (let y = 0; y < h; y++) {\n pass(out, y * w, 1, w);\n out.set(line.subarray(0, w), y * w);\n }\n }\n for (const pass of passes) {\n for (let x = 0; x < w; x++) {\n pass(out, x, w, h);\n for (let y = 0; y < h; y++) out[y * w + x] = line[y];\n }\n }\n return out;\n}\n","/**\n * A layer stack that is not specific to any editor: pixel layers on tiled surfaces, groups (with\n * pass-through), raster masks with density and feather, clipping, locks, opacity, fill and blend\n * modes, plus pure tree helpers. Editors extend these types with their own layer kinds (the image\n * editor adds adjustment and annotation layers, filters and parametric masks).\n *\n * Layer objects are immutable: every change builds new objects along the path from the root to\n * the changed layer and shares everything else.\n */\n\nimport type { BlendMode } from './blend';\nimport type { MaskSurface, PixelSurface } from './surface';\n\n/** Blend modes of a layer; groups also accept `pass-through`. */\nexport type GroupBlendMode = BlendMode | 'pass-through';\n\nexport interface LayerLocks {\n /** Painting and filling are refused. */\n pixels?: boolean;\n /** Painting keeps each pixel's alpha. */\n transparency?: boolean;\n /** Moving (offset) is refused. */\n position?: boolean;\n /** Everything above, plus property changes and deletion. */\n all?: boolean;\n}\n\n/**\n * A layer mask: 8-bit coverage (255 reveals, 0 hides) on a tiled surface, plus non-destructive\n * density and feather. `source` is an editor-defined parametric mask (generated instead of\n * painted; the compositor asks its profile for the coverage, and the surface is unused).\n */\nexport interface RasterMask<Source = unknown> {\n surface: MaskSurface;\n /** Value outside the painted tiles (PSD's default colour); equals `surface.defaultValue`. */\n defaultValue: 0 | 255;\n /** 0..1 (missing = 1): at 0.5 hidden areas still show half. */\n density?: number;\n /** Gaussian σ in pixels (missing = 0). */\n feather?: number;\n /** `false` keeps the mask but ignores it. */\n enabled?: boolean;\n source?: Source;\n}\n\nexport interface RasterLayerBase {\n id: string;\n name: string;\n visible: boolean;\n /** 0..1 */\n opacity: number;\n blend: BlendMode;\n /** Clip to the nearest unclipped layer below (Photoshop's clipping mask). */\n clipped?: boolean;\n mask?: RasterMask;\n locks?: LayerLocks;\n}\n\nexport interface RasterPixelLayer extends RasterLayerBase {\n type: 'pixel';\n /** Pixels in layer space; document position = layer position + `offset`. A mask moves with it. */\n surface: PixelSurface;\n /** Integer move without re-tiling. */\n offset: { x: number; y: number };\n /** 0..1, PSD \"Fill\" (missing = 1). */\n fillOpacity?: number;\n}\n\nexport interface RasterGroupLayer<L = RasterLayer> extends Omit<RasterLayerBase, 'blend'> {\n type: 'group';\n blend: GroupBlendMode;\n /** Bottom to top. */\n children: L[];\n /** UI only. */\n collapsed?: boolean;\n}\n\n/** The plain stack: pixel layers and groups. */\nexport type RasterLayer = RasterPixelLayer | RasterGroupLayer<RasterLayer>;\n\n/** What the tree helpers need of a layer: an id, a type, and `children` on groups. */\nexport interface RasterNode {\n id: string;\n type: string;\n}\n\n/** The group members of a layer union. */\nexport type GroupIn<T> = Extract<T, { type: 'group' }>;\n\nconst childrenOf = <T>(l: T): readonly T[] | null =>\n (l as { type: string }).type === 'group' ? ((l as unknown as { children: T[] }).children ?? null) : null;\n\nexport interface LayerLocation<T extends RasterNode = RasterLayer> {\n layer: T;\n /** The containing group, or `null` at the top level. */\n parent: GroupIn<T> | null;\n /** Index within the parent's children (or the top-level list). */\n index: number;\n /** Ancestors from the top level down to the parent. */\n path: GroupIn<T>[];\n}\n\n/** Every layer, depth first, bottom to top (a group comes before its children). */\nexport function flattenLayers<T extends RasterNode>(layers: readonly T[]): T[] {\n const out: T[] = [];\n const walk = (list: readonly T[]) => {\n for (const l of list) {\n out.push(l);\n const c = childrenOf(l);\n if (c) walk(c);\n }\n };\n walk(layers);\n return out;\n}\n\nexport function findLayer<T extends RasterNode>(layers: readonly T[], id: string): LayerLocation<T> | null {\n const walk = (list: readonly T[], parent: GroupIn<T> | null, path: GroupIn<T>[]): LayerLocation<T> | null => {\n for (let i = 0; i < list.length; i++) {\n const l = list[i];\n if (l.id === id) return { layer: l, parent, index: i, path };\n const c = childrenOf(l);\n if (c) {\n const g = l as GroupIn<T>;\n const hit = walk(c, g, [...path, g]);\n if (hit) return hit;\n }\n }\n return null;\n };\n return walk(layers, null, []);\n}\n\n/** Replaces the layer with `id` by `fn(layer)` (or removes it when `fn` returns `null`). */\nexport function mapLayer<T extends RasterNode>(layers: readonly T[], id: string, fn: (layer: T) => T | null): T[] {\n let changed = false;\n const walk = (list: readonly T[]): T[] => {\n let out: T[] | null = null;\n for (let i = 0; i < list.length; i++) {\n const l = list[i];\n let next: T | null = l;\n if (l.id === id) {\n next = fn(l);\n changed = true;\n } else {\n const c = childrenOf(l);\n if (c) {\n const children = walk(c);\n if (children !== c) next = { ...l, children } as T;\n }\n }\n if (next !== l) {\n if (!out) out = list.slice(0, i);\n if (next) out.push(next);\n } else if (out) out.push(l);\n }\n return out ?? (list as T[]);\n };\n const result = walk(layers);\n return changed ? result : (layers as T[]);\n}\n\n/** Inserts `layer` into `parentId`'s children (or the top level) at `index` (default: top). */\nexport function insertLayer<T extends RasterNode>(layers: readonly T[], layer: T, parentId: string | null, index?: number): T[] {\n const put = (list: readonly T[]) => {\n const at = index === undefined ? list.length : Math.max(0, Math.min(list.length, index));\n const next = list.slice();\n next.splice(at, 0, layer);\n return next;\n };\n if (!parentId) return put(layers);\n return mapLayer(layers, parentId, (g) => {\n const c = childrenOf(g);\n return c ? ({ ...g, children: put(c) } as T) : g;\n });\n}\n\nexport function isLayerLocked(layer: { locks?: LayerLocks }, what: keyof LayerLocks): boolean {\n return Boolean(layer.locks?.all || layer.locks?.[what]);\n}\n","/**\n * The per-tile layer compositor engine. Composites a layer stack (pixel layers and groups with\n * masks, clipping, blend modes, opacity, fill and pass-through) tile by tile in document space,\n * in pure TypeScript, so results are deterministic and testable in Node and Workers.\n *\n * Editors add their own layer kinds through a {@link CompositorProfile}: layers that filter\n * what is below them (adjustment layers), content layers drawn by the editor (annotations),\n * per-layer pixel filters, and parametric mask sources.\n *\n * Caches:\n * - Each top-level *step* (a content layer and the layers clipped to it, a run of filter layers,\n * a group) has a per-tile *signature*: its properties plus the identity of every surface tile\n * it reads. A tile whose signatures are unchanged returns the cached result (same buffer\n * object, so callers can skip uploading it).\n * - A prefix cache keeps the accumulator *before* the step that changed last time (and, when the\n * caller names it, before the active layer). Dragging a slider on layer k, or a stroke on layer\n * k, recomposites from step k upwards only; `dirty` rectangles limit that to where it changed.\n * - Spatial filters and feathered or parametric masks are computed once over the canvas and\n * cached by the identity of their inputs.\n */\n\nimport { blendChannel, blendRgb, isSeparableBlendMode, type BlendMode } from './blend';\nimport { gaussianBlur } from './blur';\nimport type { RasterMask, RasterNode } from './layers';\nimport {\n TILE,\n emptySurface,\n readRegion,\n surfaceFromPixels,\n tileKey,\n tilesInRect,\n type PixelSurface,\n type RasterRect,\n type TileKey,\n type TiledSurface,\n} from './surface';\n\nconst TILE_PIXELS = TILE * TILE;\nconst TILE_BYTES = TILE_PIXELS * 4;\n\n/** What the compositor needs from its host besides the layers. */\nexport interface RasterSources {\n /** Canvas (document) size: spatial filters and mask feathering clamp at this rect. */\n width: number;\n height: number;\n /** The pixels of a pixel layer (lets a host resolve layers whose pixels live elsewhere). */\n surfaceOf?(layer: CompositorLayer): PixelSurface;\n /** Changes whenever one of the host's callbacks would return something new for the same layers. */\n version?: number | string;\n}\n\n/** The fields the engine reads; editor layer types are wider. */\nexport interface CompositorLayer extends RasterNode {\n visible: boolean;\n opacity: number;\n blend: string;\n clipped?: boolean;\n mask?: RasterMask;\n /** Pixel layers. */\n surface?: PixelSurface;\n offset?: { x: number; y: number };\n fillOpacity?: number;\n /** Groups. */\n children?: readonly CompositorLayer[];\n}\n\n/** A pixel layer's filters as the engine runs them. */\nexport interface PixelFilterSpec {\n /** Identifies the settings (part of the cache key). */\n key: string;\n /** Needs neighbouring pixels: runs once over the canvas instead of per tile. */\n spatial: boolean;\n /** Filters RGBA `data` (`width × height`) in place. */\n apply(data: Uint8ClampedArray, width: number, height: number): void;\n}\n\n/** How an editor's own layer kinds composite. Every hook is optional. */\nexport interface CompositorProfile<L extends CompositorLayer, S extends RasterSources> {\n /** Layers that change what is below them; adjacent ones run as one step. */\n isFilterLayer?(layer: L): boolean;\n /** Applies a run of visible filter layers to `acc` (RGBA over `r`); `coverage` holds masked ones by id. */\n applyFilterRun?(layers: L[], acc: Uint8ClampedArray, r: RasterRect, coverage: Map<string, Float32Array> | undefined, sources: S): void;\n /** RGBA of a content layer that is neither a pixel layer nor a group, over `r`, or `null`. */\n contentTile?(layer: L, r: RasterRect, sources: S): Uint8ClampedArray | null;\n /** The blend mode a content layer draws with (default `layer.blend`). */\n contentBlend?(layer: L): BlendMode;\n /** Properties of a layer beyond the generic ones that change its pixels (part of its signature). */\n layerKey?(layer: L): unknown;\n /** Active filters of a pixel layer, or `null`. */\n pixelFilters?(layer: L): PixelFilterSpec | null;\n /** Canvas coverage (0..1, `width × height`) of a parametric mask source, or `null` to reveal all. */\n maskSourcePlane?(source: unknown, width: number, height: number, sources: S): Float32Array | null;\n}\n\nexport interface CompositorOptions {\n /** Upper bound for cached tile buffers (default 256 MiB). */\n maxCacheBytes?: number;\n}\n\nexport interface CompositeCallOptions {\n /**\n * The layer about to be edited (the active layer): every tile composited in this call keeps a\n * checkpoint below its step, so strokes and slider drags on it start there.\n */\n checkpointLayerId?: string | null;\n /**\n * Where the layers changed since the previous call, when the caller knows (a stroke's dabs).\n * Changed tiles are then recomposited only inside these rectangles. Changes outside them would\n * be missed, so pass nothing when unsure.\n */\n dirty?: RasterRect[];\n}\n\n// ---------------------------------------------------------------------------\n// Steps and signatures\n// ---------------------------------------------------------------------------\n\ntype Step<L> =\n | { kind: 'content'; layer: L; clipped: L[] }\n | { kind: 'adjust'; layers: L[] }\n | { kind: 'group'; layer: L; clipped: L[]; steps: Step<L>[] };\n\ninterface Sig {\n key: string;\n refs: unknown[];\n}\n\nfunction sameSig(a: Sig | undefined, b: Sig): boolean {\n if (!a || a.key !== b.key || a.refs.length !== b.refs.length) return false;\n for (let i = 0; i < a.refs.length; i++) if (a.refs[i] !== b.refs[i]) return false;\n return true;\n}\n\n/** The bounding box of the parts of `rects` inside tile (tx, ty), or `null` when none is. */\nfunction dirtyInTile(rects: RasterRect[], tx: number, ty: number): RasterRect | null {\n let x0 = Infinity;\n let y0 = Infinity;\n let x1 = -Infinity;\n let y1 = -Infinity;\n const ox = tx * TILE;\n const oy = ty * TILE;\n for (const r of rects) {\n const a = Math.max(ox, Math.floor(r.x));\n const b = Math.max(oy, Math.floor(r.y));\n const c = Math.min(ox + TILE, Math.ceil(r.x + r.width));\n const d = Math.min(oy + TILE, Math.ceil(r.y + r.height));\n if (c <= a || d <= b) continue;\n x0 = Math.min(x0, a);\n y0 = Math.min(y0, b);\n x1 = Math.max(x1, c);\n y1 = Math.max(y1, d);\n }\n return x0 === Infinity ? null : { x: x0, y: y0, width: x1 - x0, height: y1 - y0 };\n}\n\n// ---------------------------------------------------------------------------\n// Blending\n// ---------------------------------------------------------------------------\n\n/**\n * Blends straight-alpha `src` over `dst` (both RGBA) in place with `mode`, scaling the source\n * alpha by `alpha` and, per pixel, by `coverage`. Same maths as `blendPixel`.\n */\nexport function blendTile(\n dst: Uint8ClampedArray,\n src: ArrayLike<number>,\n mode: BlendMode,\n alpha: number,\n coverage: ArrayLike<number> | null\n): void {\n if (!(alpha > 0)) return;\n const normal = mode === 'normal';\n const lut = !normal && isSeparableBlendMode(mode) ? separableLut(mode) : null;\n const cb = [0, 0, 0];\n const cs = [0, 0, 0];\n const n = dst.length;\n for (let i = 0, p = 0; i < n; i += 4, p++) {\n const sa = src[i + 3];\n if (sa === 0) continue;\n const k = coverage ? alpha * coverage[p] : alpha;\n if (!(k > 0)) continue;\n if (normal && sa === 255 && k >= 1) {\n // Opaque normal source: the result is the source (what the general formula rounds to).\n dst[i] = src[i];\n dst[i + 1] = src[i + 1];\n dst[i + 2] = src[i + 2];\n dst[i + 3] = 255;\n continue;\n }\n const as = (sa / 255) * k;\n const ab = dst[i + 3] / 255;\n const ao = as + ab * (1 - as);\n if (ao <= 0) {\n dst[i] = dst[i + 1] = dst[i + 2] = dst[i + 3] = 0;\n continue;\n }\n const d0 = dst[i];\n const d1 = dst[i + 1];\n const d2 = dst[i + 2];\n const b0 = d0 / 255;\n const b1 = d1 / 255;\n const b2 = d2 / 255;\n const s0 = src[i] / 255;\n const s1 = src[i + 1] / 255;\n const s2 = src[i + 2] / 255;\n let m0: number;\n let m1: number;\n let m2: number;\n if (normal) {\n m0 = s0;\n m1 = s1;\n m2 = s2;\n } else if (lut) {\n m0 = lut[(d0 << 8) | src[i]];\n m1 = lut[(d1 << 8) | src[i + 1]];\n m2 = lut[(d2 << 8) | src[i + 2]];\n } else {\n cb[0] = b0;\n cb[1] = b1;\n cb[2] = b2;\n cs[0] = s0;\n cs[1] = s1;\n cs[2] = s2;\n const m = blendRgb(mode, cb, cs);\n m0 = m[0];\n m1 = m[1];\n m2 = m[2];\n }\n const wb = (1 - as) * ab;\n const ws = (1 - ab) * as;\n const wm = as * ab;\n dst[i] = Math.round(((wb * b0 + ws * s0 + wm * m0) / ao) * 255);\n dst[i + 1] = Math.round(((wb * b1 + ws * s1 + wm * m1) / ao) * 255);\n dst[i + 2] = Math.round(((wb * b2 + ws * s2 + wm * m2) / ao) * 255);\n dst[i + 3] = Math.round(ao * 255);\n }\n}\n\nconst separableLuts = new Map<BlendMode, Float64Array>();\n\n/** `B(cb, cs)` of a separable mode for every pair of 8-bit values (index `cb << 8 | cs`). */\nfunction separableLut(mode: BlendMode): Float64Array {\n let lut = separableLuts.get(mode);\n if (!lut) {\n lut = new Float64Array(65536);\n for (let b = 0; b < 256; b++) for (let c = 0; c < 256; c++) lut[(b << 8) | c] = blendChannel(mode, b / 255, c / 255);\n separableLuts.set(mode, lut);\n }\n return lut;\n}\n\n/** Composites `src` onto `dst` but keeps `dst`'s alpha (clipping: source-atop). */\nfunction blendAtop(dst: Uint8ClampedArray, src: ArrayLike<number>, mode: BlendMode, alpha: number, coverage: ArrayLike<number> | null): void {\n const keep = new Uint8ClampedArray(dst.length >> 2);\n for (let i = 3, p = 0; i < dst.length; i += 4, p++) keep[p] = dst[i];\n blendTile(dst, src, mode, alpha, coverage);\n for (let i = 3, p = 0; i < dst.length; i += 4, p++) dst[i] = keep[p];\n}\n\n/** `dst = lerp(before, dst, alpha · coverage)` per channel (pass-through groups with opacity). */\nfunction lerpTile(dst: Uint8ClampedArray, before: Uint8ClampedArray, alpha: number, coverage: ArrayLike<number> | null): void {\n for (let i = 0, p = 0; i < dst.length; i += 4, p++) {\n const k = coverage ? alpha * coverage[p] : alpha;\n if (k >= 1) continue;\n for (let c = 0; c < 4; c++) dst[i + c] = Math.round(before[i + c] + (dst[i + c] - before[i + c]) * k);\n }\n}\n\n// ---------------------------------------------------------------------------\n// The compositor\n// ---------------------------------------------------------------------------\n\ninterface TileEntry<L> {\n sigs: Sig[];\n /** Accumulator before step `index` (index 0 is the empty accumulator and is never stored). */\n checkpoints: Map<number, { data: Uint8ClampedArray; empty: boolean }>;\n result: Uint8ClampedArray;\n /** The root list the entry was computed for (sigs are only comparable per root). */\n root: readonly L[];\n stamp: number;\n}\n\ninterface CoveragePlane {\n /** Coverage over the canvas (`width × height`). */\n data: Float32Array;\n width: number;\n height: number;\n}\n\nconst ZERO_TILE = new Uint8ClampedArray(TILE_BYTES);\n\n/** Statistics of the last `composite` call (for benchmarks and tests). */\nexport interface CompositeStats {\n tiles: number;\n /** Tiles returned straight from the cache. */\n cached: number;\n /** Steps actually run, summed over tiles. */\n stepsRun: number;\n}\n\nconst isGroup = (l: CompositorLayer) => l.type === 'group';\nconst isPixel = (l: CompositorLayer) => l.type === 'pixel';\n\nexport class RasterCompositor<L extends CompositorLayer = CompositorLayer, S extends RasterSources = RasterSources> {\n private readonly tiles = new Map<TileKey, TileEntry<L>>();\n private readonly maxCacheBytes: number;\n private cacheBytes = 0;\n private stamp = 0;\n private sources: S = { width: 1, height: 1 } as S;\n private sourcesVersion: unknown = undefined;\n private filteredCache = new WeakMap<object, Map<string, PixelSurface>>();\n private planeCache = new Map<string, CoveragePlane>();\n private planeIds = new WeakMap<object, number>();\n private nextPlaneId = 1;\n private contentCache = new WeakMap<object, Map<string, Uint8ClampedArray>>();\n private readonly stepsCache = new WeakMap<readonly L[], Step<L>[]>();\n private readonly propsKeyCache = new WeakMap<object, string>();\n lastStats: CompositeStats = { tiles: 0, cached: 0, stepsRun: 0 };\n private hint = -1;\n\n constructor(\n private readonly profile: CompositorProfile<L, S> = {},\n options: CompositorOptions = {}\n ) {\n this.maxCacheBytes = options.maxCacheBytes ?? 256 * 1024 * 1024;\n }\n\n /** Drops every cached tile and plane. */\n clear(): void {\n this.tiles.clear();\n this.cacheBytes = 0;\n this.planeCache.clear();\n this.filteredCache = new WeakMap();\n this.contentCache = new WeakMap();\n }\n\n private setSources(sources: S): void {\n const version = `${sources.width}x${sources.height}:${sources.version ?? ''}`;\n if (version !== this.sourcesVersion) {\n this.clear();\n this.sourcesVersion = version;\n }\n this.sources = sources;\n }\n\n /** The composite of `layers` over `rect` as `rect.width × rect.height` RGBA (straight alpha). */\n composite(layers: readonly L[], rect: RasterRect, sources: S, options: CompositeCallOptions = {}): Uint8ClampedArray {\n const out = new Uint8ClampedArray(Math.max(0, rect.width * rect.height * 4));\n this.compositeTiles(layers, rect, sources, (tx, ty, data) => {\n const ox = tx * TILE;\n const oy = ty * TILE;\n const x0 = Math.max(rect.x, ox);\n const y0 = Math.max(rect.y, oy);\n const x1 = Math.min(rect.x + rect.width, ox + TILE);\n const y1 = Math.min(rect.y + rect.height, oy + TILE);\n const span = (x1 - x0) * 4;\n for (let y = y0; y < y1; y++) {\n const s = ((y - oy) * TILE + (x0 - ox)) * 4;\n out.set(data.subarray(s, s + span), ((y - rect.y) * rect.width + (x0 - rect.x)) * 4);\n }\n }, options);\n return out;\n }\n\n /**\n * Composites every tile intersecting `rect` and calls `onTile` with each tile's RGBA buffer\n * (TILE × TILE). A tile whose inputs did not change since the last call returns the same buffer\n * object; never mutate it.\n */\n compositeTiles(\n layers: readonly L[],\n rect: RasterRect,\n sources: S,\n onTile: (tx: number, ty: number, data: Uint8ClampedArray, changed: boolean) => void,\n options: CompositeCallOptions = {}\n ): void {\n this.setSources(sources);\n const steps = this.buildSteps(layers);\n this.hint = options.checkpointLayerId ? this.stepIndexOf(steps, options.checkpointLayerId) : -1;\n this.stamp++;\n const stats: CompositeStats = { tiles: 0, cached: 0, stepsRun: 0 };\n for (const { tx, ty } of tilesInRect(rect)) {\n stats.tiles++;\n const before = this.tiles.get(tileKey(tx, ty))?.result;\n const data = this.compositeTile(layers, steps, tx, ty, stats, options.dirty ? dirtyInTile(options.dirty, tx, ty) : null);\n onTile(tx, ty, data, data !== before);\n }\n this.lastStats = stats;\n this.evict();\n }\n\n /** The composite of one tile (cached; do not mutate the result). */\n tile(layers: readonly L[], tx: number, ty: number, sources: S): Uint8ClampedArray {\n this.setSources(sources);\n this.stamp++;\n const stats: CompositeStats = { tiles: 1, cached: 0, stepsRun: 0 };\n this.hint = -1;\n const data = this.compositeTile(layers, this.buildSteps(layers), tx, ty, stats);\n this.lastStats = stats;\n this.evict();\n return data;\n }\n\n /**\n * A layer's effective mask coverage (0..1, after density, feather or parametric evaluation)\n * over `r` in document space, or `null` when it reveals all of `r`.\n */\n maskCoverage(layer: L, r: RasterRect, sources: S): Float32Array | null {\n this.setSources(sources);\n return this.maskTile(layer, r);\n }\n\n // --- Steps -------------------------------------------------------------------\n\n private isFilter(l: L): boolean {\n return this.profile.isFilterLayer?.(l) ?? false;\n }\n\n /**\n * Groups a layer list into compositing steps: clipped layers join the nearest unclipped\n * content or group layer below; consecutive unclipped filter layers form one run.\n */\n private buildSteps(layers: readonly L[]): Step<L>[] {\n const cached = this.stepsCache.get(layers);\n if (cached) return cached;\n const steps: Step<L>[] = [];\n for (const layer of layers) {\n const last = steps[steps.length - 1];\n if (layer.clipped && last && (last.kind === 'content' || last.kind === 'group')) {\n last.clipped.push(layer);\n continue;\n }\n if (this.isFilter(layer)) {\n if (last && last.kind === 'adjust') last.layers.push(layer);\n else steps.push({ kind: 'adjust', layers: [layer] });\n } else if (isGroup(layer)) {\n steps.push({ kind: 'group', layer, clipped: [], steps: this.buildSteps((layer.children ?? []) as L[]) });\n } else {\n steps.push({ kind: 'content', layer, clipped: [] });\n }\n }\n this.stepsCache.set(layers, steps);\n return steps;\n }\n\n /** The index of the top-level step that holds layer `id` (searching groups and clipped layers), or -1. */\n private stepIndexOf(steps: Step<L>[], id: string): number {\n const holds = (l: CompositorLayer): boolean => l.id === id || (isGroup(l) && (l.children ?? []).some(holds));\n return steps.findIndex((s) => (s.kind === 'adjust' ? s.layers.some(holds) : holds(s.layer) || s.clipped.some(holds)));\n }\n\n /** Properties of a layer that change pixels, minus its surfaces (memoised per object). */\n private propsKey(layer: L): string {\n let key = this.propsKeyCache.get(layer);\n if (key !== undefined) return key;\n const mask = layer.mask\n ? [layer.mask.enabled !== false, layer.mask.density ?? 1, layer.mask.feather ?? 0, layer.mask.defaultValue, layer.mask.source ?? null]\n : null;\n const base: unknown[] = [layer.type, layer.id, layer.visible, layer.opacity, layer.blend, Boolean(layer.clipped), mask];\n if (isPixel(layer)) base.push(layer.offset?.x ?? 0, layer.offset?.y ?? 0, layer.fillOpacity ?? 1);\n const extra = this.profile.layerKey?.(layer);\n if (extra !== undefined) base.push(extra);\n key = JSON.stringify(base);\n this.propsKeyCache.set(layer, key);\n return key;\n }\n\n private compositeTile(root: readonly L[], steps: Step<L>[], tx: number, ty: number, stats: CompositeStats, dirty: RasterRect | null = null): Uint8ClampedArray {\n const key = tileKey(tx, ty);\n const entry = this.tiles.get(key);\n const sigs = steps.map((s) => this.stepSig(s, tx, ty));\n let first = 0;\n if (entry) {\n while (first < sigs.length && first < entry.sigs.length && sameSig(entry.sigs[first], sigs[first])) first++;\n if (first === sigs.length && first === entry.sigs.length) {\n entry.stamp = this.stamp;\n stats.cached++;\n return entry.result;\n }\n }\n // Resume from the best checkpoint at or below the first changed step.\n let start = 0;\n let base: { data: Uint8ClampedArray; empty: boolean } | null = null;\n if (entry) {\n for (const [index, cp] of entry.checkpoints) {\n if (index <= first && index > start) {\n start = index;\n base = cp;\n }\n }\n }\n const tileRect = { x: tx * TILE, y: ty * TILE, width: TILE, height: TILE };\n const hint = this.hint;\n const checkpoints = new Map<number, { data: Uint8ClampedArray; empty: boolean }>();\n if (entry) for (const [index, cp] of entry.checkpoints) if (index <= start) checkpoints.set(index, cp);\n let result: Uint8ClampedArray;\n\n if (entry && dirty && (dirty.width < TILE || dirty.height < TILE)) {\n // Only `dirty` changed: recomposite that part from the checkpoint and patch the previous result.\n const r = dirty;\n const sub = (data: Uint8ClampedArray | null) => {\n const out = new Uint8ClampedArray(r.width * r.height * 4);\n if (!data) return out;\n for (let y = 0; y < r.height; y++) {\n const s = ((r.y - tileRect.y + y) * TILE + (r.x - tileRect.x)) * 4;\n out.set(data.subarray(s, s + r.width * 4), y * r.width * 4);\n }\n return out;\n };\n const acc = sub(base ? base.data : null);\n let empty = base ? base.empty : true;\n for (let i = start; i < steps.length; i++) {\n empty = this.runStep(steps[i], acc, empty, r);\n stats.stepsRun++;\n }\n result = new Uint8ClampedArray(entry.result);\n for (let y = 0; y < r.height; y++) {\n result.set(acc.subarray(y * r.width * 4, (y + 1) * r.width * 4), ((r.y - tileRect.y + y) * TILE + (r.x - tileRect.x)) * 4);\n }\n } else {\n const acc = base ? new Uint8ClampedArray(base.data) : new Uint8ClampedArray(TILE_BYTES);\n let empty = base ? base.empty : true;\n for (let i = start; i < steps.length; i++) {\n if ((i === first || i === hint) && i > 0 && !checkpoints.has(i)) checkpoints.set(i, { data: new Uint8ClampedArray(acc), empty });\n empty = this.runStep(steps[i], acc, empty, tileRect);\n stats.stepsRun++;\n }\n result = empty ? ZERO_TILE : acc;\n }\n // Keep few checkpoints: below the active layer, below the step that changed, and the newest.\n if (checkpoints.size > 2) {\n const keys = [...checkpoints.keys()].sort((a, b) => a - b);\n const keep = new Set([keys[keys.length - 1], first, hint]);\n for (const k of keys) if (!keep.has(k)) checkpoints.delete(k);\n }\n const prevBytes = entry ? this.entryBytes(entry) : 0;\n const next: TileEntry<L> = { sigs, checkpoints, result, root, stamp: this.stamp };\n this.tiles.set(key, next);\n this.cacheBytes += this.entryBytes(next) - prevBytes;\n return result;\n }\n\n private entryBytes(e: TileEntry<L>): number {\n let n = e.result === ZERO_TILE ? 0 : TILE_BYTES;\n for (const cp of e.checkpoints.values()) n += cp.data.byteLength;\n return n;\n }\n\n private evict(): void {\n if (this.cacheBytes <= this.maxCacheBytes) return;\n // Drop checkpoints first (oldest tiles first), then whole entries not used this call.\n const entries = [...this.tiles.entries()].sort((a, b) => a[1].stamp - b[1].stamp);\n for (const [, e] of entries) {\n if (this.cacheBytes <= this.maxCacheBytes) return;\n for (const cp of e.checkpoints.values()) this.cacheBytes -= cp.data.byteLength;\n e.checkpoints.clear();\n }\n for (const [k, e] of entries) {\n if (this.cacheBytes <= this.maxCacheBytes) return;\n if (e.stamp === this.stamp) continue;\n this.cacheBytes -= this.entryBytes(e);\n this.tiles.delete(k);\n }\n }\n\n // --- Signatures -----------------------------------------------------------\n\n private stepSig(step: Step<L>, tx: number, ty: number): Sig {\n if (step.kind === 'adjust') {\n const refs: unknown[] = [];\n let key = 'A';\n for (const l of step.layers) {\n key += this.propsKey(l);\n refs.push(...this.maskRefs(l, tx, ty, 0, 0));\n }\n return { key, refs };\n }\n const own = step.kind === 'content' ? this.contentSig(step.layer, tx, ty) : this.groupSig(step.layer, step.steps, tx, ty);\n if (!step.clipped.length) return own;\n const refs = [...own.refs];\n let key = own.key;\n for (const c of step.clipped) {\n const s = this.layerSig(c, tx, ty);\n key += '|' + s.key;\n refs.push(...s.refs);\n }\n return { key, refs };\n }\n\n private layerSig(layer: L, tx: number, ty: number): Sig {\n if (this.isFilter(layer)) return { key: this.propsKey(layer), refs: this.maskRefs(layer, tx, ty, 0, 0) };\n if (isGroup(layer)) return this.groupSig(layer, this.buildSteps((layer.children ?? []) as L[]), tx, ty);\n return this.contentSig(layer, tx, ty);\n }\n\n private groupSig(group: L, steps: Step<L>[], tx: number, ty: number): Sig {\n let key = 'G' + this.propsKey(group);\n const refs = this.maskRefs(group, tx, ty, 0, 0);\n if (!group.visible) return { key, refs };\n for (const s of steps) {\n const sig = this.stepSig(s, tx, ty);\n key += '[' + sig.key + ']';\n refs.push(...sig.refs);\n }\n return { key, refs };\n }\n\n private contentSig(layer: L, tx: number, ty: number): Sig {\n const key = 'C' + this.propsKey(layer);\n if (!layer.visible) return { key, refs: [] };\n if (!isPixel(layer)) return { key, refs: this.maskRefs(layer, tx, ty, 0, 0) };\n const { surface, dx, dy } = this.layerPixels(layer);\n const refs: unknown[] = [surface.defaultValue];\n const r = { x: tx * TILE - dx, y: ty * TILE - dy, width: TILE, height: TILE };\n for (const t of tilesInRect(r)) refs.push(surface.getTile(t.tx, t.ty) ?? null);\n refs.push(...this.maskRefs(layer, tx, ty, layer.offset?.x ?? 0, layer.offset?.y ?? 0));\n return { key, refs };\n }\n\n private maskRefs(layer: L, tx: number, ty: number, ox: number, oy: number): unknown[] {\n const mask = layer.mask;\n if (!mask || mask.enabled === false) return [];\n if (mask.source || (mask.feather ?? 0) > 0) return [this.planeFor(mask, ox, oy)];\n const refs: unknown[] = [];\n for (const t of tilesInRect({ x: tx * TILE - ox, y: ty * TILE - oy, width: TILE, height: TILE })) {\n refs.push(mask.surface.getTile(t.tx, t.ty) ?? null);\n }\n return refs;\n }\n\n // --- Layer pixels ------------------------------------------------------------\n\n /**\n * A pixel layer's pixels after spatial filters: the surface and the offset to apply. Layers\n * with a spatial filter are filtered once over the canvas (in document space, offset 0).\n */\n private layerPixels(layer: L): { surface: PixelSurface; dx: number; dy: number; perPixel: PixelFilterSpec | null } {\n const raw = this.sources.surfaceOf ? this.sources.surfaceOf(layer) : (layer.surface as PixelSurface);\n const ox = layer.offset?.x ?? 0;\n const oy = layer.offset?.y ?? 0;\n const filters = this.profile.pixelFilters?.(layer) ?? null;\n if (!filters?.spatial) return { surface: raw, dx: ox, dy: oy, perPixel: filters };\n const fkey = `${ox},${oy}:${filters.key}`;\n let byKey = this.filteredCache.get(raw);\n if (!byKey) {\n byKey = new Map();\n this.filteredCache.set(raw, byKey);\n }\n let filtered = byKey.get(fkey);\n if (!filtered) {\n filtered = filterOverCanvas(raw, ox, oy, filters, this.sources.width, this.sources.height);\n byKey.clear();\n byKey.set(fkey, filtered);\n }\n return { surface: filtered, dx: 0, dy: 0, perPixel: null };\n }\n\n /** RGBA of a content layer over `r` (document space, inside one tile), or `null` when it has nothing there. */\n private contentTile(layer: L, r: RasterRect): Uint8ClampedArray | null {\n if (!isPixel(layer)) return this.profile.contentTile?.(layer, r, this.sources) ?? null;\n const { surface, dx, dy, perPixel } = this.layerPixels(layer);\n const src = { x: r.x - dx, y: r.y - dy, width: r.width, height: r.height };\n const covered = tilesInRect(src).map((t) => surface.getTile(t.tx, t.ty));\n if (surface.defaultValue === 0 && covered.every((t) => !t)) return null;\n const aligned = r.width === TILE && r.height === TILE && src.x % TILE === 0 && src.y % TILE === 0;\n if (!perPixel) {\n if (aligned && covered[0]) return covered[0].data;\n return readRegion(surface, src);\n }\n // Per-pixel filters: cache the filtered tile by its source tile and the filter settings.\n const fkey = `${dx},${dy}:${perPixel.key}`;\n const anchor = (covered.find(Boolean) ?? surface) as object;\n let byKey = this.contentCache.get(anchor);\n const refsKey = `${r.x},${r.y}:${fkey}`;\n if (aligned) {\n const hit = byKey?.get(refsKey);\n if (hit) return hit;\n }\n const data = readRegion(surface, src);\n perPixel.apply(data, r.width, r.height);\n if (aligned) {\n if (!byKey) {\n byKey = new Map();\n this.contentCache.set(anchor, byKey);\n }\n byKey.set(refsKey, data);\n }\n return data;\n }\n\n // --- Masks -------------------------------------------------------------------\n\n private planeKey(mask: RasterMask, ox: number, oy: number): string {\n const W = this.sources.width;\n const H = this.sources.height;\n let id = this.planeIds.get(mask.surface);\n if (id === undefined) {\n id = this.nextPlaneId++;\n this.planeIds.set(mask.surface, id);\n }\n return `${id}:${ox},${oy}:${W}x${H}:${mask.feather ?? 0}:${mask.density ?? 1}:${mask.source ? JSON.stringify(mask.source) : ''}`;\n }\n\n /** Canvas-sized coverage of a feathered or parametric mask (cached). */\n private planeFor(mask: RasterMask, ox: number, oy: number): CoveragePlane {\n const key = this.planeKey(mask, ox, oy);\n let plane = this.planeCache.get(key);\n if (plane) {\n this.planeCache.delete(key);\n this.planeCache.set(key, plane);\n return plane;\n }\n const W = this.sources.width;\n const H = this.sources.height;\n let v: Float32Array = new Float32Array(W * H);\n if (mask.source) {\n const generated = this.profile.maskSourcePlane?.(mask.source, W, H, this.sources) ?? null;\n if (!generated || generated.length !== W * H) v.fill(1);\n else v.set(generated);\n } else {\n const bytes = readRegion(mask.surface, { x: -ox, y: -oy, width: W, height: H });\n for (let i = 0; i < v.length; i++) v[i] = bytes[i] / 255;\n }\n const feather = mask.feather ?? 0;\n if (feather > 0) v = gaussianBlur(v, W, H, feather, 'clamp') as Float32Array;\n const density = mask.density ?? 1;\n if (density !== 1) for (let i = 0; i < v.length; i++) v[i] = 1 - density * (1 - v[i]);\n plane = { data: v, width: W, height: H };\n this.planeCache.set(key, plane);\n while (this.planeCache.size > 8) this.planeCache.delete(this.planeCache.keys().next().value as string);\n return plane;\n }\n\n private maskTile(layer: L, r: RasterRect): Float32Array | null {\n const mask = layer.mask;\n if (!mask || mask.enabled === false) return null;\n const ox = isPixel(layer) ? (layer.offset?.x ?? 0) : 0;\n const oy = isPixel(layer) ? (layer.offset?.y ?? 0) : 0;\n const n = r.width * r.height;\n const out = new Float32Array(n);\n const density = mask.density ?? 1;\n if (mask.source || (mask.feather ?? 0) > 0) {\n const plane = this.planeFor(mask, ox, oy);\n const W = plane.width;\n const H = plane.height;\n // Outside the canvas the mask holds its default (feathering clamps at the canvas edge).\n const outside = mask.source ? 1 : 1 - density * (1 - mask.defaultValue / 255);\n out.fill(outside);\n const x0 = Math.max(0, r.x);\n const y0 = Math.max(0, r.y);\n const x1 = Math.min(W, r.x + r.width);\n const y1 = Math.min(H, r.y + r.height);\n for (let y = y0; y < y1; y++) {\n const s = y * W;\n const d = (y - r.y) * r.width - r.x;\n for (let x = x0; x < x1; x++) out[d + x] = plane.data[s + x];\n }\n } else {\n const bytes = readRegion(mask.surface, { x: r.x - ox, y: r.y - oy, width: r.width, height: r.height });\n let all = true;\n for (let i = 0; i < n; i++) {\n out[i] = bytes[i] / 255;\n if (bytes[i] !== 255) all = false;\n }\n if (all) return null;\n if (density !== 1) for (let i = 0; i < n; i++) out[i] = 1 - density * (1 - out[i]);\n }\n return out;\n }\n\n // --- Running steps ---------------------------------------------------------\n\n /** Runs one step onto `acc`; returns whether `acc` is still empty. */\n private runStep(step: Step<L>, acc: Uint8ClampedArray, empty: boolean, r: RasterRect): boolean {\n if (step.kind === 'adjust') {\n if (empty) return true;\n this.applyFilterRun(step.layers, acc, r);\n return false;\n }\n const layer = step.layer;\n if (!layer.visible) return empty;\n const clipped = step.clipped.filter((l) => l.visible);\n const coverage = this.maskTile(layer, r);\n if (coverage && coverage.every((v) => v <= 0)) return empty;\n if (step.kind === 'group') {\n if (layer.blend === 'pass-through' && !clipped.length) {\n if (layer.opacity >= 1 && !coverage) return this.runSteps(step.steps, acc, empty, r);\n const before = new Uint8ClampedArray(acc);\n const stillEmpty = this.runSteps(step.steps, acc, empty, r);\n lerpTile(acc, before, layer.opacity, coverage);\n return empty && stillEmpty;\n }\n const buf = new Uint8ClampedArray(acc.length);\n if (this.runSteps(step.steps, buf, true, r)) return empty;\n this.applyClipped(clipped, buf, r);\n const mode = (layer.blend === 'pass-through' ? 'normal' : layer.blend) as BlendMode;\n return this.blendOnto(acc, buf, empty, mode, layer.opacity, coverage);\n }\n const content = this.contentTile(step.layer, r);\n if (!content) return empty;\n const fill = isPixel(step.layer) ? (step.layer.fillOpacity ?? 1) : 1;\n const blend = this.contentBlend(step.layer);\n if (!clipped.length) return this.blendOnto(acc, content, empty, blend, layer.opacity * fill, coverage);\n // Clipping group: the base (with its mask and fill) is the shape the clipped layers paint in.\n const buf = new Uint8ClampedArray(acc.length);\n blendTile(buf, content, 'normal', fill, coverage);\n this.applyClipped(clipped, buf, r);\n return this.blendOnto(acc, buf, empty, blend, layer.opacity, null);\n }\n\n private runSteps(steps: Step<L>[], acc: Uint8ClampedArray, empty: boolean, r: RasterRect): boolean {\n for (const s of steps) empty = this.runStep(s, acc, empty, r);\n return empty;\n }\n\n private contentBlend(layer: L): BlendMode {\n return this.profile.contentBlend?.(layer) ?? (layer.blend as BlendMode);\n }\n\n private blendOnto(acc: Uint8ClampedArray, src: Uint8ClampedArray, empty: boolean, mode: BlendMode, alpha: number, coverage: Float32Array | null): boolean {\n if (!(alpha > 0)) return empty;\n if (empty && mode === 'normal' && alpha >= 1 && !coverage) {\n // Over a transparent accumulator a normal, opaque, unmasked layer is a plain copy (which also\n // keeps the colour of transparent pixels, as a single-layer render always has).\n acc.set(src);\n return false;\n }\n blendTile(acc, src, mode, alpha, coverage);\n return false;\n }\n\n private applyClipped(clipped: L[], buf: Uint8ClampedArray, r: RasterRect): void {\n let run: L[] = [];\n const flush = () => {\n if (run.length) this.applyFilterRun(run, buf, r);\n run = [];\n };\n for (const c of clipped) {\n if (this.isFilter(c)) {\n run.push(c);\n continue;\n }\n flush();\n const coverage = this.maskTile(c, r);\n if (isGroup(c)) {\n const inner = new Uint8ClampedArray(buf.length);\n if (this.runSteps(this.buildSteps((c.children ?? []) as L[]), inner, true, r)) continue;\n const mode = (c.blend === 'pass-through' ? 'normal' : c.blend) as BlendMode;\n blendAtop(buf, inner, mode, c.opacity, coverage);\n continue;\n }\n const content = this.contentTile(c, r);\n if (!content) continue;\n const fill = isPixel(c) ? (c.fillOpacity ?? 1) : 1;\n blendAtop(buf, content, this.contentBlend(c), c.opacity * fill, coverage);\n }\n flush();\n }\n\n private applyFilterRun(layers: L[], acc: Uint8ClampedArray, r: RasterRect): void {\n const visible: L[] = [];\n let masks: Map<string, Float32Array> | undefined;\n for (const node of layers) {\n if (!node.visible) continue;\n const cov = this.maskTile(node, r);\n if (cov) {\n if (cov.every((v) => v <= 0)) continue;\n (masks ??= new Map()).set(node.id, cov);\n }\n visible.push(node);\n }\n if (visible.length) this.profile.applyFilterRun?.(visible, acc, r, masks, this.sources);\n }\n}\n\n/**\n * Applies a layer's filters over the canvas rect in document space: the result is a surface at\n * offset 0 holding only canvas pixels (spatial filters clamp at the canvas edges).\n */\nfunction filterOverCanvas(surface: PixelSurface, ox: number, oy: number, filters: PixelFilterSpec, width: number, height: number): PixelSurface {\n if (width <= 0 || height <= 0) return emptySurface(4);\n const data = readRegion(surface, { x: -ox, y: -oy, width, height });\n filters.apply(data, width, height);\n return surfaceFromPixels({ width, height, data }, 4, 0, 0);\n}\n\n/** Tiles that differ between two surfaces (by tile identity), as tile keys. */\nexport function changedTiles(a: TiledSurface, b: TiledSurface): TileKey[] {\n const out: TileKey[] = [];\n for (const [k, t] of b.tiles) if (a.tiles.get(k) !== t) out.push(k);\n for (const k of a.tiles.keys()) if (!b.tiles.has(k)) out.push(k);\n return out;\n}\n","/**\n * Synchronous zlib (RFC 1950) and raw deflate (RFC 1951), dependency-free, for the image editor's\n * layer PNGs and PSD ZIP channels. `CompressionStream` is asynchronous and not everywhere, and\n * layer pixels must serialize inside the synchronous `toJSON()`.\n *\n * - `inflate` handles stored, fixed and dynamic blocks and refuses to produce more than\n * `maxOutput` bytes (a decompression bomb guard).\n * - `deflate` is a greedy LZ77 (hash chains, 32 KiB window) with one dynamic Huffman block per\n * 64 Ki symbols. It favours simplicity over the last few percent of ratio.\n */\n\n// ---------------------------------------------------------------------------\n// Shared tables\n// ---------------------------------------------------------------------------\n\nconst LENGTH_BASE = [3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258];\nconst LENGTH_EXTRA = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0];\nconst DIST_BASE = [1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577];\nconst DIST_EXTRA = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13];\nconst CL_ORDER = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];\n\nexport class ZlibError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ZlibError';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Inflate\n// ---------------------------------------------------------------------------\n\ninterface Huffman {\n counts: Uint16Array;\n symbols: Uint16Array;\n}\n\nfunction buildHuffman(lengths: ArrayLike<number>, n: number): Huffman {\n const counts = new Uint16Array(16);\n for (let i = 0; i < n; i++) counts[lengths[i]]++;\n counts[0] = 0;\n const offs = new Uint16Array(16);\n for (let i = 1; i < 16; i++) offs[i] = offs[i - 1] + counts[i - 1];\n const symbols = new Uint16Array(n);\n for (let i = 0; i < n; i++) if (lengths[i]) symbols[offs[lengths[i]]++] = i;\n return { counts, symbols };\n}\n\nlet fixedLit: Huffman | null = null;\nlet fixedDist: Huffman | null = null;\nfunction fixedTables(): [Huffman, Huffman] {\n if (!fixedLit || !fixedDist) {\n const l = new Uint8Array(288);\n for (let i = 0; i < 144; i++) l[i] = 8;\n for (let i = 144; i < 256; i++) l[i] = 9;\n for (let i = 256; i < 280; i++) l[i] = 7;\n for (let i = 280; i < 288; i++) l[i] = 8;\n fixedLit = buildHuffman(l, 288);\n const d = new Uint8Array(30).fill(5);\n fixedDist = buildHuffman(d, 30);\n }\n return [fixedLit, fixedDist];\n}\n\nclass BitReader {\n pos = 0;\n bit = 0;\n bits = 0;\n constructor(readonly data: Uint8Array) {}\n need(n: number): number {\n while (this.bits < n) {\n if (this.pos >= this.data.length) throw new ZlibError('Unexpected end of compressed data');\n this.bit |= this.data[this.pos++] << this.bits;\n this.bits += 8;\n }\n const v = this.bit & ((1 << n) - 1);\n this.bit >>>= n;\n this.bits -= n;\n return v;\n }\n decode(h: Huffman): number {\n let code = 0;\n let first = 0;\n let index = 0;\n for (let len = 1; len < 16; len++) {\n code |= this.need(1);\n const count = h.counts[len];\n if (code - count < first) return h.symbols[index + (code - first)];\n index += count;\n first += count;\n first <<= 1;\n code <<= 1;\n }\n throw new ZlibError('Invalid Huffman code');\n }\n align(): void {\n this.bit = 0;\n this.bits = 0;\n }\n}\n\nclass Output {\n buf: Uint8Array;\n len = 0;\n constructor(hint: number, readonly max: number) {\n this.buf = new Uint8Array(Math.max(1024, Math.min(hint, max)));\n }\n ensure(n: number): void {\n if (this.len + n > this.max) throw new ZlibError(`Decompressed data exceeds ${this.max} bytes`);\n if (this.len + n <= this.buf.length) return;\n let size = this.buf.length * 2;\n while (size < this.len + n) size *= 2;\n const next = new Uint8Array(Math.min(size, Math.max(this.max, this.len + n)));\n next.set(this.buf.subarray(0, this.len));\n this.buf = next;\n }\n}\n\n/** Inflates raw deflate data (no zlib header). */\nexport function inflateRaw(data: Uint8Array, options: { maxOutput?: number; sizeHint?: number } = {}): Uint8Array {\n const max = options.maxOutput ?? 512 * 1024 * 1024;\n const out = new Output(options.sizeHint ?? data.length * 4, max);\n const br = new BitReader(data);\n let final = 0;\n while (!final) {\n final = br.need(1);\n const type = br.need(2);\n if (type === 0) {\n br.align();\n if (br.pos + 4 > data.length) throw new ZlibError('Unexpected end of compressed data');\n const len = data[br.pos] | (data[br.pos + 1] << 8);\n const nlen = data[br.pos + 2] | (data[br.pos + 3] << 8);\n br.pos += 4;\n if ((len ^ 0xffff) !== nlen) throw new ZlibError('Stored block length mismatch');\n if (br.pos + len > data.length) throw new ZlibError('Unexpected end of compressed data');\n out.ensure(len);\n out.buf.set(data.subarray(br.pos, br.pos + len), out.len);\n out.len += len;\n br.pos += len;\n continue;\n }\n let lit: Huffman;\n let dist: Huffman;\n if (type === 1) [lit, dist] = fixedTables();\n else if (type === 2) {\n const hlit = br.need(5) + 257;\n const hdist = br.need(5) + 1;\n const hclen = br.need(4) + 4;\n const cl = new Uint8Array(19);\n for (let i = 0; i < hclen; i++) cl[CL_ORDER[i]] = br.need(3);\n const clh = buildHuffman(cl, 19);\n const lengths = new Uint8Array(hlit + hdist);\n let i = 0;\n while (i < hlit + hdist) {\n const sym = br.decode(clh);\n if (sym < 16) lengths[i++] = sym;\n else {\n let rep = 0;\n let val = 0;\n if (sym === 16) {\n if (i === 0) throw new ZlibError('Repeat with no previous length');\n val = lengths[i - 1];\n rep = 3 + br.need(2);\n } else if (sym === 17) rep = 3 + br.need(3);\n else rep = 11 + br.need(7);\n if (i + rep > hlit + hdist) throw new ZlibError('Too many code lengths');\n while (rep--) lengths[i++] = val;\n }\n }\n lit = buildHuffman(lengths.subarray(0, hlit), hlit);\n dist = buildHuffman(lengths.subarray(hlit), hdist);\n } else throw new ZlibError('Invalid block type');\n for (;;) {\n const sym = br.decode(lit);\n if (sym < 256) {\n out.ensure(1);\n out.buf[out.len++] = sym;\n } else if (sym === 256) break;\n else {\n const li = sym - 257;\n if (li >= 29) throw new ZlibError('Invalid length symbol');\n const len = LENGTH_BASE[li] + br.need(LENGTH_EXTRA[li]);\n const di = br.decode(dist);\n if (di >= 30) throw new ZlibError('Invalid distance symbol');\n const d = DIST_BASE[di] + br.need(DIST_EXTRA[di]);\n if (d > out.len) throw new ZlibError('Distance too far back');\n out.ensure(len);\n const buf = out.buf;\n let p = out.len;\n for (let k = 0; k < len; k++, p++) buf[p] = buf[p - d];\n out.len = p;\n }\n }\n }\n return out.buf.slice(0, out.len);\n}\n\n/** Adler-32 checksum (zlib trailer). */\nexport function adler32(data: Uint8Array): number {\n let a = 1;\n let b = 0;\n const n = data.length;\n let i = 0;\n while (i < n) {\n const end = Math.min(n, i + 3800);\n for (; i < end; i++) {\n a += data[i];\n b += a;\n }\n a %= 65521;\n b %= 65521;\n }\n return ((b << 16) | a) >>> 0;\n}\n\n/** Inflates zlib data (header, deflate stream, Adler-32 trailer). */\nexport function inflate(data: Uint8Array, options: { maxOutput?: number; sizeHint?: number; verify?: boolean } = {}): Uint8Array {\n if (data.length < 6) throw new ZlibError('Truncated zlib stream');\n const cmf = data[0];\n const flg = data[1];\n if ((cmf & 15) !== 8 || ((cmf << 8) | flg) % 31 !== 0) throw new ZlibError('Not a zlib stream');\n if (flg & 32) throw new ZlibError('Preset dictionaries are not supported');\n const out = inflateRaw(data.subarray(2), options);\n if (options.verify !== false && data.length >= 6) {\n const t = data.length - 4;\n const want = ((data[t] << 24) | (data[t + 1] << 16) | (data[t + 2] << 8) | data[t + 3]) >>> 0;\n if (adler32(out) !== want) throw new ZlibError('Adler-32 mismatch');\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Deflate\n// ---------------------------------------------------------------------------\n\nclass BitWriter {\n buf: Uint8Array;\n len = 0;\n bit = 0;\n bits = 0;\n constructor(hint: number) {\n this.buf = new Uint8Array(Math.max(1024, hint));\n }\n private grow(): void {\n const next = new Uint8Array(this.buf.length * 2);\n next.set(this.buf);\n this.buf = next;\n }\n write(value: number, n: number): void {\n this.bit |= value << this.bits;\n this.bits += n;\n while (this.bits >= 8) {\n if (this.len >= this.buf.length) this.grow();\n this.buf[this.len++] = this.bit & 255;\n this.bit >>>= 8;\n this.bits -= 8;\n }\n }\n flush(): void {\n if (this.bits > 0) {\n if (this.len >= this.buf.length) this.grow();\n this.buf[this.len++] = this.bit & 255;\n }\n this.bit = 0;\n this.bits = 0;\n }\n bytes(): Uint8Array {\n return this.buf.slice(0, this.len);\n }\n}\n\n/** Code lengths (≤ maxBits) for symbol frequencies, by Huffman's algorithm with frequency flattening. */\nfunction codeLengths(freqs: Uint32Array, maxBits: number): Uint8Array {\n const n = freqs.length;\n const lengths = new Uint8Array(n);\n const f = Float64Array.from(freqs);\n for (;;) {\n const nodes: Array<{ w: number; sym: number; left?: number; right?: number }> = [];\n for (let i = 0; i < n; i++) if (f[i] > 0) nodes.push({ w: f[i], sym: i });\n lengths.fill(0);\n if (nodes.length === 0) return lengths;\n if (nodes.length === 1) {\n lengths[nodes[0].sym] = 1;\n return lengths;\n }\n // Simple binary heap of node indexes by weight.\n const heap: number[] = nodes.map((_, i) => i);\n const less = (a: number, b: number) => nodes[a].w < nodes[b].w || (nodes[a].w === nodes[b].w && a < b);\n const down = (i: number) => {\n for (;;) {\n const l = 2 * i + 1;\n const r = l + 1;\n let m = i;\n if (l < heap.length && less(heap[l], heap[m])) m = l;\n if (r < heap.length && less(heap[r], heap[m])) m = r;\n if (m === i) return;\n [heap[i], heap[m]] = [heap[m], heap[i]];\n i = m;\n }\n };\n const up = (i: number) => {\n while (i > 0) {\n const p = (i - 1) >> 1;\n if (!less(heap[i], heap[p])) return;\n [heap[i], heap[p]] = [heap[p], heap[i]];\n i = p;\n }\n };\n for (let i = (heap.length >> 1) - 1; i >= 0; i--) down(i);\n const pop = () => {\n const top = heap[0];\n const last = heap.pop()!;\n if (heap.length) {\n heap[0] = last;\n down(0);\n }\n return top;\n };\n while (heap.length > 1) {\n const a = pop();\n const b = pop();\n nodes.push({ w: nodes[a].w + nodes[b].w, sym: -1, left: a, right: b });\n heap.push(nodes.length - 1);\n up(heap.length - 1);\n }\n let maxLen = 0;\n const stack: Array<[number, number]> = [[heap[0], 0]];\n while (stack.length) {\n const [i, d] = stack.pop()!;\n const node = nodes[i];\n if (node.sym >= 0) {\n lengths[node.sym] = d;\n if (d > maxLen) maxLen = d;\n } else {\n stack.push([node.left!, d + 1], [node.right!, d + 1]);\n }\n }\n if (maxLen <= maxBits) return lengths;\n // Too deep: flatten the distribution and retry.\n for (let i = 0; i < n; i++) if (f[i] > 0) f[i] = Math.floor(f[i] / 2) + 1;\n }\n}\n\n/** Canonical codes for code lengths, bit-reversed for LSB-first output. */\nfunction canonicalCodes(lengths: Uint8Array): Uint16Array {\n const blCount = new Uint16Array(16);\n for (const l of lengths) blCount[l]++;\n blCount[0] = 0;\n const next = new Uint16Array(16);\n let code = 0;\n for (let bits = 1; bits < 16; bits++) {\n code = (code + blCount[bits - 1]) << 1;\n next[bits] = code;\n }\n const codes = new Uint16Array(lengths.length);\n for (let i = 0; i < lengths.length; i++) {\n const len = lengths[i];\n if (!len) continue;\n let c = next[len]++;\n let r = 0;\n for (let k = 0; k < len; k++) {\n r = (r << 1) | (c & 1);\n c >>= 1;\n }\n codes[i] = r;\n }\n return codes;\n}\n\nfunction lengthSymbol(len: number): number {\n let i = 28;\n while (LENGTH_BASE[i] > len) i--;\n return i;\n}\n\nfunction distSymbol(d: number): number {\n let i = 29;\n while (DIST_BASE[i] > d) i--;\n return i;\n}\n\nconst WINDOW = 32768;\nconst HASH_BITS = 15;\nconst HASH_SIZE = 1 << HASH_BITS;\nconst MAX_CHAIN = 24;\nconst MAX_MATCH = 258;\nconst BLOCK_SYMBOLS = 65536;\n\n/** Raw deflate (no zlib header). `level` 0 stores the data uncompressed. */\nexport function deflateRaw(data: Uint8Array, level: 0 | 1 = 1): Uint8Array {\n const w = new BitWriter(Math.ceil(data.length / 2) + 64);\n const n = data.length;\n if (level === 0 || n === 0) {\n let pos = 0;\n do {\n const len = Math.min(65535, n - pos);\n const final = pos + len >= n ? 1 : 0;\n w.write(final, 1);\n w.write(0, 2);\n w.flush();\n w.write(len & 0xffff, 16);\n w.write(~len & 0xffff, 16);\n for (let i = 0; i < len; i++) w.write(data[pos + i], 8);\n pos += len;\n } while (pos < n);\n return w.bytes();\n }\n\n const head = new Int32Array(HASH_SIZE).fill(-1);\n const prev = new Int32Array(WINDOW);\n // Symbols of the current block: literal (0..255) or length/distance pairs.\n const litLen = new Uint16Array(BLOCK_SYMBOLS);\n const dists = new Uint16Array(BLOCK_SYMBOLS);\n let count = 0;\n const hash = (i: number) => (((data[i] << 10) ^ (data[i + 1] << 5) ^ data[i + 2]) * 2654435761) >>> (32 - HASH_BITS);\n const insert = (i: number) => {\n if (i + 2 >= n) return;\n const h = hash(i);\n prev[i & (WINDOW - 1)] = head[h];\n head[h] = i;\n };\n\n const flushBlock = (final: boolean) => {\n const litFreq = new Uint32Array(286);\n const distFreq = new Uint32Array(30);\n for (let k = 0; k < count; k++) {\n if (dists[k] === 0) litFreq[litLen[k]]++;\n else {\n litFreq[257 + lengthSymbol(litLen[k])]++;\n distFreq[distSymbol(dists[k])]++;\n }\n }\n litFreq[256] = 1;\n let anyDist = false;\n for (const v of distFreq) if (v) anyDist = true;\n if (!anyDist) distFreq[0] = 1;\n const litLengths = codeLengths(litFreq, 15);\n const distLengths = codeLengths(distFreq, 15);\n let hlit = 286;\n while (hlit > 257 && !litLengths[hlit - 1]) hlit--;\n let hdist = 30;\n while (hdist > 1 && !distLengths[hdist - 1]) hdist--;\n const all = new Uint8Array(hlit + hdist);\n all.set(litLengths.subarray(0, hlit));\n all.set(distLengths.subarray(0, hdist), hlit);\n // Run-length encode the code lengths.\n const clSyms: number[] = [];\n const clExtra: number[] = [];\n for (let i = 0; i < all.length; ) {\n const v = all[i];\n let run = 1;\n while (i + run < all.length && all[i + run] === v) run++;\n if (v === 0 && run >= 3) {\n const r = Math.min(run, 138);\n if (r >= 11) {\n clSyms.push(18);\n clExtra.push(r - 11);\n } else {\n clSyms.push(17);\n clExtra.push(r - 3);\n }\n i += r;\n } else if (v !== 0 && run >= 4) {\n clSyms.push(v);\n clExtra.push(0);\n const r = Math.min(run - 1, 6);\n clSyms.push(16);\n clExtra.push(r - 3);\n i += r + 1;\n } else {\n clSyms.push(v);\n clExtra.push(0);\n i++;\n }\n }\n const clFreq = new Uint32Array(19);\n for (const s of clSyms) clFreq[s]++;\n const clLengths = codeLengths(clFreq, 7);\n let hclen = 19;\n while (hclen > 4 && !clLengths[CL_ORDER[hclen - 1]]) hclen--;\n const clCodes = canonicalCodes(clLengths);\n const litCodes = canonicalCodes(litLengths);\n const distCodes = canonicalCodes(distLengths);\n\n w.write(final ? 1 : 0, 1);\n w.write(2, 2);\n w.write(hlit - 257, 5);\n w.write(hdist - 1, 5);\n w.write(hclen - 4, 4);\n for (let i = 0; i < hclen; i++) w.write(clLengths[CL_ORDER[i]], 3);\n for (let i = 0; i < clSyms.length; i++) {\n const s = clSyms[i];\n w.write(clCodes[s], clLengths[s]);\n if (s === 16) w.write(clExtra[i], 2);\n else if (s === 17) w.write(clExtra[i], 3);\n else if (s === 18) w.write(clExtra[i], 7);\n }\n for (let k = 0; k < count; k++) {\n const d = dists[k];\n if (d === 0) {\n const s = litLen[k];\n w.write(litCodes[s], litLengths[s]);\n } else {\n const len = litLen[k];\n const li = lengthSymbol(len);\n w.write(litCodes[257 + li], litLengths[257 + li]);\n if (LENGTH_EXTRA[li]) w.write(len - LENGTH_BASE[li], LENGTH_EXTRA[li]);\n const di = distSymbol(d);\n w.write(distCodes[di], distLengths[di]);\n if (DIST_EXTRA[di]) w.write(d - DIST_BASE[di], DIST_EXTRA[di]);\n }\n }\n w.write(litCodes[256], litLengths[256]);\n count = 0;\n };\n\n let i = 0;\n while (i < n) {\n let bestLen = 0;\n let bestDist = 0;\n if (i + 2 < n) {\n let cand = head[hash(i)];\n let chain = MAX_CHAIN;\n const limit = Math.min(MAX_MATCH, n - i);\n while (cand >= 0 && i - cand <= WINDOW - 1 && chain-- > 0) {\n if (data[cand + bestLen] === data[i + bestLen]) {\n let l = 0;\n while (l < limit && data[cand + l] === data[i + l]) l++;\n if (l > bestLen) {\n bestLen = l;\n bestDist = i - cand;\n if (l === limit) break;\n }\n }\n const next = prev[cand & (WINDOW - 1)];\n if (next >= cand) break;\n cand = next;\n }\n }\n if (bestLen >= 3) {\n litLen[count] = bestLen;\n dists[count] = bestDist;\n count++;\n const end = i + bestLen;\n // Insert every position of long runs only up to a cap, which keeps solid areas fast.\n const insertEnd = bestLen > 64 ? i + 64 : end;\n for (let k = i; k < insertEnd; k++) insert(k);\n for (let k = Math.max(insertEnd, end - 3); k < end; k++) insert(k);\n i = end;\n } else {\n litLen[count] = data[i];\n dists[count] = 0;\n count++;\n insert(i);\n i++;\n }\n if (count >= BLOCK_SYMBOLS - 1 && i < n) flushBlock(false);\n }\n // The final block may hold only the end-of-block symbol.\n flushBlock(true);\n w.flush();\n return w.bytes();\n}\n\n/** zlib stream: header, raw deflate, Adler-32. */\nexport function deflate(data: Uint8Array, level: 0 | 1 = 1): Uint8Array {\n const raw = deflateRaw(data, level);\n const out = new Uint8Array(raw.length + 6);\n out[0] = 0x78;\n out[1] = 0x01;\n out.set(raw, 2);\n const a = adler32(data);\n const t = out.length - 4;\n out[t] = a >>> 24;\n out[t + 1] = (a >>> 16) & 255;\n out[t + 2] = (a >>> 8) & 255;\n out[t + 3] = a & 255;\n return out;\n}\n","/**\n * Dependency-free, synchronous PNG encode / decode for layer pixels and masks, plus base64 and\n * data-URL helpers. Canvas `toDataURL` is lossy for partly transparent pixels (it goes through\n * premultiplied alpha), so layer assets use this codec and round-trip exactly.\n *\n * Encodes 8-bit greyscale (masks) or RGBA (layers). Decodes non-interlaced 1/2/4/8/16-bit\n * greyscale, RGB, palette, grey + alpha and RGBA, always to 8-bit RGBA or grey.\n */\n\nimport { deflate, inflate } from './zlib';\n\nconst SIGNATURE = [137, 80, 78, 71, 13, 10, 26, 10];\n\nlet crcTable: Uint32Array | null = null;\nfunction crc32(bytes: Uint8Array, start: number, end: number): number {\n if (!crcTable) {\n crcTable = new Uint32Array(256);\n for (let n = 0; n < 256; n++) {\n let c = n;\n for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n crcTable[n] = c >>> 0;\n }\n }\n let c = 0xffffffff;\n for (let i = start; i < end; i++) c = crcTable[(c ^ bytes[i]) & 255] ^ (c >>> 8);\n return (c ^ 0xffffffff) >>> 0;\n}\n\nexport interface DecodedPng {\n width: number;\n height: number;\n /** 4 for RGBA output, 1 for greyscale without alpha when `keepGray` was asked for. */\n channels: 1 | 4;\n data: Uint8ClampedArray;\n}\n\nfunction paeth(a: number, b: number, c: number): number {\n const p = a + b - c;\n const pa = Math.abs(p - a);\n const pb = Math.abs(p - b);\n const pc = Math.abs(p - c);\n return pa <= pb && pa <= pc ? a : pb <= pc ? b : c;\n}\n\n/** PNG bytes for `width × height` pixels of 1 (grey) or 4 (RGBA) bytes each. */\nexport function encodePng(width: number, height: number, data: ArrayLike<number>, channels: 1 | 4 = 4): Uint8Array {\n const stride = width * channels;\n const raw = new Uint8Array((stride + 1) * height);\n const bpp = channels;\n const cand = [new Uint8Array(stride), new Uint8Array(stride), new Uint8Array(stride), new Uint8Array(stride), new Uint8Array(stride)];\n for (let y = 0; y < height; y++) {\n const row = y * stride;\n const prevRow = (y - 1) * stride;\n // Try each filter and keep the one with the smallest sum of signed residues.\n let best = 0;\n let bestScore = Infinity;\n for (let f = 0; f < 5; f++) {\n const out = cand[f];\n let score = 0;\n for (let x = 0; x < stride; x++) {\n const v = data[row + x];\n const a = x >= bpp ? data[row + x - bpp] : 0;\n const b = y > 0 ? data[prevRow + x] : 0;\n const c = x >= bpp && y > 0 ? data[prevRow + x - bpp] : 0;\n let r: number;\n switch (f) {\n case 0: r = v; break;\n case 1: r = v - a; break;\n case 2: r = v - b; break;\n case 3: r = v - ((a + b) >> 1); break;\n default: r = v - paeth(a, b, c);\n }\n r &= 255;\n out[x] = r;\n score += r < 128 ? r : 256 - r;\n if (score >= bestScore) break;\n }\n if (score < bestScore) {\n bestScore = score;\n best = f;\n }\n }\n const o = y * (stride + 1);\n raw[o] = best;\n // Only a filter whose scoring loop ran to the end can win, so its row is complete.\n raw.set(cand[best], o + 1);\n }\n const idat = deflate(raw);\n const chunks: Array<[string, Uint8Array]> = [];\n const ihdr = new Uint8Array(13);\n writeU32(ihdr, 0, width);\n writeU32(ihdr, 4, height);\n ihdr[8] = 8;\n ihdr[9] = channels === 1 ? 0 : 6;\n chunks.push(['IHDR', ihdr], ['IDAT', idat], ['IEND', new Uint8Array(0)]);\n let size = 8;\n for (const [, d] of chunks) size += 12 + d.length;\n const out = new Uint8Array(size);\n out.set(SIGNATURE, 0);\n let p = 8;\n for (const [type, d] of chunks) {\n writeU32(out, p, d.length);\n for (let i = 0; i < 4; i++) out[p + 4 + i] = type.charCodeAt(i);\n out.set(d, p + 8);\n writeU32(out, p + 8 + d.length, crc32(out, p + 4, p + 8 + d.length));\n p += 12 + d.length;\n }\n return out;\n}\n\nfunction writeU32(b: Uint8Array, o: number, v: number): void {\n b[o] = v >>> 24;\n b[o + 1] = (v >>> 16) & 255;\n b[o + 2] = (v >>> 8) & 255;\n b[o + 3] = v & 255;\n}\n\nfunction readU32(b: Uint8Array, o: number): number {\n return ((b[o] << 24) | (b[o + 1] << 16) | (b[o + 2] << 8) | b[o + 3]) >>> 0;\n}\n\nexport function isPng(bytes: Uint8Array): boolean {\n return bytes.length > 8 && SIGNATURE.every((v, i) => bytes[i] === v);\n}\n\n/**\n * Decodes a PNG. Output is RGBA (4 channels) unless `keepGray` is set and the image is\n * greyscale without alpha, in which case it is one byte per pixel.\n */\nexport function decodePng(bytes: Uint8Array, options: { keepGray?: boolean; maxPixels?: number } = {}): DecodedPng {\n if (!isPng(bytes)) throw new Error('Not a PNG image.');\n let p = 8;\n let width = 0;\n let height = 0;\n let depth = 0;\n let type = 0;\n let interlace = 0;\n let palette: Uint8Array | null = null;\n let trns: Uint8Array | null = null;\n const idat: Uint8Array[] = [];\n while (p + 8 <= bytes.length) {\n const len = readU32(bytes, p);\n const t = String.fromCharCode(bytes[p + 4], bytes[p + 5], bytes[p + 6], bytes[p + 7]);\n const body = bytes.subarray(p + 8, p + 8 + len);\n if (p + 12 + len > bytes.length) throw new Error('Truncated PNG.');\n if (t === 'IHDR') {\n width = readU32(body, 0);\n height = readU32(body, 4);\n depth = body[8];\n type = body[9];\n interlace = body[12];\n } else if (t === 'PLTE') palette = body;\n else if (t === 'tRNS') trns = body;\n else if (t === 'IDAT') idat.push(body);\n else if (t === 'IEND') break;\n p += 12 + len;\n }\n if (!width || !height) throw new Error('PNG has no image header.');\n if (interlace) throw new Error('Interlaced PNGs are not supported here; decode them with a canvas.');\n const maxPixels = options.maxPixels ?? 1 << 28;\n if (width * height > maxPixels) throw new Error(`PNG is too large (${width}×${height}).`);\n const samples = type === 0 ? 1 : type === 2 ? 3 : type === 3 ? 1 : type === 4 ? 2 : type === 6 ? 4 : 0;\n if (!samples || ![1, 2, 4, 8, 16].includes(depth)) throw new Error(`Unsupported PNG format (type ${type}, depth ${depth}).`);\n let total = 0;\n for (const c of idat) total += c.length;\n const z = new Uint8Array(total);\n let o = 0;\n for (const c of idat) {\n z.set(c, o);\n o += c.length;\n }\n const bitsPerPixel = samples * depth;\n const stride = Math.ceil((width * bitsPerPixel) / 8);\n const raw = inflate(z, { maxOutput: (stride + 1) * height, sizeHint: (stride + 1) * height });\n if (raw.length < (stride + 1) * height) throw new Error('PNG image data is truncated.');\n const bpp = Math.max(1, bitsPerPixel >> 3);\n const lines = new Uint8Array(stride * height);\n for (let y = 0; y < height; y++) {\n const f = raw[y * (stride + 1)];\n const src = y * (stride + 1) + 1;\n const dst = y * stride;\n const up = dst - stride;\n for (let x = 0; x < stride; x++) {\n const v = raw[src + x];\n const a = x >= bpp ? lines[dst + x - bpp] : 0;\n const b = y > 0 ? lines[up + x] : 0;\n const c = x >= bpp && y > 0 ? lines[up + x - bpp] : 0;\n let r: number;\n switch (f) {\n case 0: r = v; break;\n case 1: r = v + a; break;\n case 2: r = v + b; break;\n case 3: r = v + ((a + b) >> 1); break;\n case 4: r = v + paeth(a, b, c); break;\n default: throw new Error(`Invalid PNG filter ${f}.`);\n }\n lines[dst + x] = r & 255;\n }\n }\n const sample = (y: number, i: number): number => {\n // The i-th sample of row y, scaled to 8 bits.\n const row = y * stride;\n if (depth === 8) return lines[row + i];\n if (depth === 16) return lines[row + i * 2];\n const perByte = 8 / depth;\n const byte = lines[row + Math.floor(i / perByte)];\n const shift = 8 - depth * ((i % perByte) + 1);\n const v = (byte >> shift) & ((1 << depth) - 1);\n return type === 3 ? v : Math.round((v * 255) / ((1 << depth) - 1));\n };\n const gray = options.keepGray && type === 0 && !trns;\n const channels: 1 | 4 = gray ? 1 : 4;\n const out = new Uint8ClampedArray(width * height * channels);\n const trnsGray = trns && type === 0 ? (depth === 16 ? trns[0] : sample16(trns, 0, depth)) : -1;\n const trnsRgb = trns && type === 2 ? [0, 1, 2].map((k) => (depth === 16 ? trns![k * 2] : sample16(trns!, k, depth))) : null;\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const d = (y * width + x) * channels;\n if (type === 0) {\n const v = sample(y, x);\n if (gray) out[d] = v;\n else {\n out[d] = out[d + 1] = out[d + 2] = v;\n out[d + 3] = v === trnsGray && trns ? 0 : 255;\n }\n } else if (type === 2) {\n const r = sample(y, x * 3);\n const g = sample(y, x * 3 + 1);\n const b = sample(y, x * 3 + 2);\n out[d] = r;\n out[d + 1] = g;\n out[d + 2] = b;\n out[d + 3] = trnsRgb && r === trnsRgb[0] && g === trnsRgb[1] && b === trnsRgb[2] ? 0 : 255;\n } else if (type === 3) {\n const i = sample(y, x);\n if (!palette || i * 3 + 2 >= palette.length) throw new Error('PNG palette index out of range.');\n out[d] = palette[i * 3];\n out[d + 1] = palette[i * 3 + 1];\n out[d + 2] = palette[i * 3 + 2];\n out[d + 3] = trns && i < trns.length ? trns[i] : 255;\n } else if (type === 4) {\n const v = sample(y, x * 2);\n out[d] = out[d + 1] = out[d + 2] = v;\n out[d + 3] = sample(y, x * 2 + 1);\n } else {\n out[d] = sample(y, x * 4);\n out[d + 1] = sample(y, x * 4 + 1);\n out[d + 2] = sample(y, x * 4 + 2);\n out[d + 3] = sample(y, x * 4 + 3);\n }\n }\n }\n return { width, height, channels, data: out };\n}\n\n/** A tRNS sample (stored as 16-bit big endian) scaled like the image samples. */\nfunction sample16(trns: Uint8Array, k: number, depth: number): number {\n const v = (trns[k * 2] << 8) | trns[k * 2 + 1];\n if (depth === 8) return v & 255;\n return Math.round(((v & ((1 << depth) - 1)) * 255) / ((1 << depth) - 1));\n}\n\n// ---------------------------------------------------------------------------\n// Base64 / data URLs\n// ---------------------------------------------------------------------------\n\nconst B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\nlet B64_INV: Int16Array | null = null;\n\nexport function bytesToBase64(bytes: Uint8Array): string {\n const parts: string[] = [];\n const CHUNK = 3 * 4096;\n for (let start = 0; start < bytes.length; start += CHUNK) {\n const end = Math.min(bytes.length, start + CHUNK);\n let s = '';\n let i = start;\n for (; i + 2 < end; i += 3) {\n const n = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];\n s += B64[n >> 18] + B64[(n >> 12) & 63] + B64[(n >> 6) & 63] + B64[n & 63];\n }\n if (i < end) {\n const n = (bytes[i] << 16) | (i + 1 < end ? bytes[i + 1] << 8 : 0);\n s += B64[n >> 18] + B64[(n >> 12) & 63] + (i + 1 < end ? B64[(n >> 6) & 63] : '=') + '=';\n }\n parts.push(s);\n }\n return parts.join('');\n}\n\nexport function base64ToBytes(text: string): Uint8Array {\n if (!B64_INV) {\n B64_INV = new Int16Array(128).fill(-1);\n for (let i = 0; i < 64; i++) B64_INV[B64.charCodeAt(i)] = i;\n B64_INV['-'.charCodeAt(0)] = 62;\n B64_INV['_'.charCodeAt(0)] = 63;\n }\n const inv = B64_INV;\n const clean = text.replace(/[\\s=]/g, '');\n const out = new Uint8Array(Math.floor((clean.length * 3) / 4));\n let bits = 0;\n let acc = 0;\n let o = 0;\n for (let i = 0; i < clean.length; i++) {\n const c = clean.charCodeAt(i);\n const v = c < 128 ? inv[c] : -1;\n if (v < 0) throw new Error('Invalid base64 data.');\n acc = (acc << 6) | v;\n bits += 6;\n if (bits >= 8) {\n bits -= 8;\n out[o++] = (acc >> bits) & 255;\n }\n }\n return out.subarray(0, o);\n}\n\n/** The bytes and MIME type of a `data:` URL (base64 or percent-encoded). */\nexport function parseDataUrl(url: string): { mime: string; bytes: Uint8Array } | null {\n const m = /^data:([^;,]*)((?:;[^;,]*)*?),/i.exec(url);\n if (!m) return null;\n const body = url.slice(m[0].length);\n const isBase64 = /;base64/i.test(m[2]);\n if (isBase64) return { mime: m[1] || 'text/plain', bytes: base64ToBytes(body) };\n const text = decodeURIComponent(body);\n const bytes = new Uint8Array(text.length);\n for (let i = 0; i < text.length; i++) bytes[i] = text.charCodeAt(i) & 255;\n return { mime: m[1] || 'text/plain', bytes };\n}\n\nexport function pngDataUrl(width: number, height: number, data: ArrayLike<number>, channels: 1 | 4 = 4): string {\n return `data:image/png;base64,${bytesToBase64(encodePng(width, height, data, channels))}`;\n}\n"]}