@effing/canvas 0.42.0 → 0.43.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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/image.ts","../src/lottie.ts","../src/jsx/draw/utils.ts","../src/jsx/style/compute.ts","../src/jsx/font.ts","../src/jsx/font-metrics.ts","../src/jsx/language.ts","../src/jsx/text/linebreak.ts","../src/jsx/text/measure.ts","../src/jsx/text/native.ts","../src/jsx/text/index.ts","../src/jsx/draw/clip.ts","../src/jsx/draw/clip-path.ts","../src/jsx/draw/rect.ts","../src/jsx/draw/gradient.ts","../src/jsx/draw/group.ts","../src/jsx/draw/object-fit.ts","../src/jsx/draw/image.ts","../src/jsx/draw/svg/style.ts","../src/jsx/draw/svg/tree.ts","../src/jsx/draw/svg/defs.ts","../src/jsx/draw/svg/transform.ts","../src/jsx/draw/svg/path.ts","../src/jsx/draw/offscreen.ts","../src/jsx/draw/svg/filters.ts","../src/jsx/draw/svg/shapes.ts","../src/jsx/draw/svg/gradients.ts","../src/jsx/draw/svg/paint.ts","../src/jsx/draw/svg/traverse.ts","../src/jsx/draw/svg/index.ts","../src/jsx/draw/text.ts","../src/jsx/emoji.ts","../src/jsx/text/emoji-split.ts","../src/jsx/draw/index.ts","../src/jsx/style/expand.ts","../src/jsx/yoga.ts","../src/jsx/style/properties.ts","../src/jsx/layout.ts","../src/jsx/index.ts","../src/fit-text.ts"],"sourcesContent":["// Re-export canvas primitives from @effing/skia so consumers never need a\n// direct dependency on it (it's a dependency of this package, which pnpm does\n// not expose to the consuming project). Re-exporting also guarantees a single\n// native copy:\n// a Path2D from one copy of @effing/skia cannot be used with a context from\n// another.\nimport { createCanvas as _createCanvas } from \"@effing/skia\";\nexport {\n Canvas,\n type SKRSContext2D,\n GlobalFonts,\n Image,\n ImageData,\n Path2D,\n DOMMatrix,\n DOMPoint,\n DOMRect,\n PathOp,\n FillType,\n StrokeJoin,\n StrokeCap,\n} from \"@effing/skia\";\n\n// loadImage is wrapped (not re-exported) so remote URLs go through the same\n// fetch path as <img> sources — see ./image.ts.\nexport {\n loadImage,\n type ImageCache,\n type LoadImageOptions,\n type LoadImageSource,\n} from \"./image.ts\";\n\n// encode() needs no patching: it snapshots the canvas when called, so later\n// drawing can't reach a pending encode, and the Buffer it resolves with owns\n// its native memory until the Buffer itself is collected (see\n// ./encode.test.ts). This used to copy the result to the JS heap, to guard\n// against lifetime bugs in @napi-rs/canvas's async encode that were fixed\n// upstream (napi-rs/canvas#1314, #1323) before @effing/skia was forked.\nexport function createCanvas(width: number, height: number) {\n return _createCanvas(width, height);\n}\n\n// Lottie API\nexport { LottieAnimation, loadLottie, renderLottieFrame } from \"./lottie.ts\";\n\n// JSX API\nexport { renderReactElement } from \"./jsx/index.ts\";\n\n// Font management\nexport {\n registerFont,\n registerFontFromPath,\n registeredFamilies,\n} from \"./jsx/font.ts\";\n\n// Fit text\nexport {\n findLargestUsableFontSize,\n type FindLargestUsableFontSizeOptions,\n} from \"./fit-text.ts\";\n\n// Types\nexport type {\n FontData,\n RenderReactElementOptions,\n EmojiStyle,\n} from \"./types.ts\";\n","import type { Image } from \"@effing/skia\";\nimport { loadImage as nativeLoadImage } from \"@effing/skia\";\n\n/** Source types accepted by {@link loadImage}, mirroring @effing/skia. */\nexport type LoadImageSource = Parameters<typeof nativeLoadImage>[0];\n\n/** Options for {@link loadImage}. */\nexport interface LoadImageOptions {\n /**\n * User-Agent header sent on remote (http/https) fetches. Matches the\n * `userAgent` option of `renderReactElement`, so `loadImage(url)` and an\n * `<img src={url}>` behave identically. An empty string is sent as an\n * explicit empty header; values with CR/LF cause fetch to throw `TypeError`.\n * Ignored for non-remote sources (paths, Buffers, data URIs).\n */\n userAgent?: string;\n}\n\n/**\n * Load an image from a path, Buffer, data URI, or remote URL.\n *\n * Remote http/https URLs are fetched via global fetch() and passed to the\n * native loader as bytes — the same path `<img>` sources take in\n * `renderReactElement`. This keeps `loadImage(url)` and `<img src={url}>`\n * consistent: both honor a global dispatcher / proxy (undici's\n * setGlobalDispatcher) and the `userAgent` option. @effing/skia's own URL\n * loader uses Node's raw http modules, which bypass any dispatcher, so it is\n * only used for non-remote sources here.\n *\n * Note: @effing/skia's `maxRedirects` / `requestOptions` load options are\n * intentionally not exposed — they only configure its built-in URL loader,\n * which this wrapper bypasses. Control remote fetches via fetch/undici instead.\n */\nexport function loadImage(\n source: LoadImageSource,\n options?: LoadImageOptions,\n): Promise<Image> {\n const remoteUrl =\n typeof source === \"string\" && isRemoteUrl(source)\n ? source\n : source instanceof URL && isRemoteUrl(source.href)\n ? source.href\n : undefined;\n if (remoteUrl !== undefined) {\n return loadRemoteImage(remoteUrl, options?.userAgent);\n }\n return nativeLoadImage(source);\n}\n\n/**\n * Per-render cache of image load promises, keyed by source string.\n * Shared between layout and draw phases to avoid duplicate loads.\n */\nexport type ImageCache = Map<string, Promise<Image>>;\n\n/**\n * Load an image via {@link loadImage}, deduplicating by source string through\n * the cache. Buffer sources are never cached (no stable key). `userAgent`, when\n * set, is forwarded to remote (http/https) fetches. The cache key is the URL\n * alone — the userAgent of the first call for a given URL is the one that hits\n * the wire; a later call with a different userAgent reuses the cached promise.\n *\n * Failed loads are evicted, so only successful loads stay cached: callers\n * sharing one cache across many renders (`options.imageCache`) retry a\n * transiently-failed source on the next call instead of replaying the\n * rejection forever.\n */\nexport function cachedLoadImage(\n cache: ImageCache,\n src: string | Buffer,\n userAgent?: string,\n): Promise<Image> {\n if (Buffer.isBuffer(src)) return loadImage(src);\n let entry = cache.get(src);\n if (!entry) {\n const created = loadImage(\n src,\n userAgent === undefined ? undefined : { userAgent },\n );\n created.catch(() => {\n if (cache.get(src) === created) cache.delete(src);\n });\n cache.set(src, created);\n entry = created;\n }\n return entry;\n}\n\n/**\n * True for http/https URLs, which are loaded via fetch() rather than the\n * native loader. Scheme match is case-insensitive (RFC 3986 §3.1).\n */\nexport function isRemoteUrl(src: string): boolean {\n return /^https?:\\/\\//i.test(src);\n}\n\n/**\n * Fetch a remote image via global fetch() and decode the bytes with the native\n * loader. Routing through fetch (rather than @effing/skia's raw-http URL\n * loader) lets a global dispatcher / proxy and the `userAgent` apply.\n */\nexport async function loadRemoteImage(\n url: string,\n userAgent?: string,\n): Promise<Image> {\n const init: RequestInit | undefined =\n userAgent !== undefined\n ? { headers: { \"User-Agent\": userAgent } }\n : undefined;\n const response = await fetch(url, init);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch image ${url}: ${response.status} ${response.statusText}`,\n );\n }\n const buffer = Buffer.from(await response.arrayBuffer());\n return nativeLoadImage(buffer);\n}\n","import { LottieAnimation } from \"@effing/skia\";\nimport type { SKRSContext2D } from \"@effing/skia\";\n\nexport { LottieAnimation };\n\n/**\n * Load a Lottie animation from a JSON string or Buffer.\n *\n * @param data - Lottie JSON string or Buffer\n * @param options - Optional resource path for external assets\n * @returns A `LottieAnimation` handle ready for rendering\n *\n * @example\n * ```ts\n * const anim = loadLottie(fs.readFileSync(\"animation.json\", \"utf-8\"));\n * ```\n */\nexport function loadLottie(\n data: string | Buffer,\n options?: { resourcePath?: string },\n): LottieAnimation {\n const jsonString = typeof data === \"string\" ? data : data.toString(\"utf-8\");\n return LottieAnimation.loadFromData(jsonString, {\n resourcePath: options?.resourcePath,\n });\n}\n\n/**\n * Render a specific frame of a Lottie animation to a canvas context.\n *\n * Seeks the animation to the given frame, then renders it onto the\n * provided context. The canvas dimensions determine the render size.\n *\n * @param ctx - Canvas 2D rendering context to draw into\n * @param animation - Lottie animation handle (from {@link loadLottie})\n * @param frame - Zero-based frame number to render\n *\n * @example\n * ```ts\n * import { createCanvas, loadLottie, renderLottieFrame } from \"@effing/canvas\";\n *\n * const canvas = createCanvas(1080, 1080);\n * const ctx = canvas.getContext(\"2d\");\n * const anim = loadLottie(jsonString);\n *\n * renderLottieFrame(ctx, anim, 0);\n * const png = canvas.encodeSync(\"png\");\n * ```\n */\nexport function renderLottieFrame(\n ctx: SKRSContext2D,\n animation: LottieAnimation,\n frame: number,\n): void {\n animation.seekFrame(frame);\n animation.render(ctx);\n}\n","/**\n * Shared CSS utility functions used by the draw system.\n */\n\nexport function parseCSSLength(value: string, referenceSize: number): number {\n if (value.endsWith(\"%\")) return (parseFloat(value) / 100) * referenceSize;\n return parseFloat(value);\n}\n\nexport function toNumber(v: unknown): number {\n if (typeof v === \"number\") return v;\n if (v === undefined || v === null) return 0;\n const n = parseFloat(String(v));\n return isNaN(n) ? 0 : n;\n}\n\n/**\n * Resolve a box-model value (padding, border-width) that may be a percentage.\n * Per CSS spec, percentage padding/border resolves against the element's width\n * (even for top/bottom).\n */\nexport function resolveBoxValue(v: unknown, referenceWidth: number): number {\n if (typeof v === \"number\") return v;\n if (v === undefined || v === null) return 0;\n const s = String(v);\n if (s.endsWith(\"%\")) return (parseFloat(s) / 100) * referenceWidth;\n const n = parseFloat(s);\n return isNaN(n) ? 0 : n;\n}\n\n/**\n * Format a number for embedding in a CSS string. `String(n)` switches to\n * exponent notation for very small or large magnitudes (`1e-7`), which CSS\n * parsers reject, so round to six decimals and print positionally.\n */\nexport function formatCSSNumber(n: number): string {\n const fixed = n.toFixed(6).replace(/\\.?0+$/, \"\");\n return fixed === \"-0\" || fixed === \"\" ? \"0\" : fixed;\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport { formatCSSNumber } from \"../draw/utils.ts\";\n\n/**\n * Style after shorthand expansion but before unit resolution.\n * Properties like fontSize may still contain CSS unit strings (e.g. \"4em\").\n */\nexport type ExpandedStyle = Omit<ComputedStyle, \"fontSize\"> & {\n fontSize?: number | string;\n};\n\n/**\n * Normalized, computed CSS style after shorthand expansion.\n * All dimension values are numbers (pixels) or percentage strings.\n */\nexport type ComputedStyle = {\n // Display & layout\n display?: \"flex\" | \"none\";\n flexDirection?: \"row\" | \"column\" | \"row-reverse\" | \"column-reverse\";\n justifyContent?:\n | \"flex-start\"\n | \"flex-end\"\n | \"center\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\";\n alignItems?: \"flex-start\" | \"flex-end\" | \"center\" | \"stretch\" | \"baseline\";\n alignSelf?:\n \"auto\" | \"flex-start\" | \"flex-end\" | \"center\" | \"stretch\" | \"baseline\";\n alignContent?:\n | \"flex-start\"\n | \"flex-end\"\n | \"center\"\n | \"stretch\"\n | \"space-between\"\n | \"space-around\";\n flexWrap?: \"nowrap\" | \"wrap\" | \"wrap-reverse\";\n flexGrow?: number;\n flexShrink?: number;\n flexBasis?: number | string;\n\n // Dimensions\n width?: number | string;\n height?: number | string;\n minWidth?: number | string;\n minHeight?: number | string;\n maxWidth?: number | string;\n maxHeight?: number | string;\n\n // Position\n position?: \"relative\" | \"absolute\";\n top?: number | string;\n right?: number | string;\n bottom?: number | string;\n left?: number | string;\n\n // Margin\n marginTop?: number | string;\n marginRight?: number | string;\n marginBottom?: number | string;\n marginLeft?: number | string;\n\n // Padding\n paddingTop?: number | string;\n paddingRight?: number | string;\n paddingBottom?: number | string;\n paddingLeft?: number | string;\n\n // Border\n borderTopWidth?: number | string;\n borderRightWidth?: number | string;\n borderBottomWidth?: number | string;\n borderLeftWidth?: number | string;\n borderTopColor?: string;\n borderRightColor?: string;\n borderBottomColor?: string;\n borderLeftColor?: string;\n borderTopStyle?: string;\n borderRightStyle?: string;\n borderBottomStyle?: string;\n borderLeftStyle?: string;\n borderTopLeftRadius?: number | string;\n borderTopRightRadius?: number | string;\n borderBottomRightRadius?: number | string;\n borderBottomLeftRadius?: number | string;\n\n // Gap\n rowGap?: number;\n columnGap?: number;\n\n // Overflow\n overflow?: string;\n overflowX?: string;\n overflowY?: string;\n\n // Colors & background\n backgroundColor?: string;\n color?: string;\n opacity?: number;\n backgroundImage?: string;\n backgroundSize?: string;\n backgroundRepeat?:\n \"repeat\" | \"no-repeat\" | \"repeat-x\" | \"repeat-y\" | \"space\" | \"round\";\n\n // Typography\n fontSize?: number;\n fontFamily?: string;\n fontWeight?: number | string;\n fontStyle?: \"normal\" | \"italic\";\n textAlign?: \"left\" | \"center\" | \"right\" | \"justify\";\n textDecoration?: string;\n textTransform?: \"none\" | \"uppercase\" | \"lowercase\" | \"capitalize\";\n lineHeight?: number | string;\n letterSpacing?: number | string;\n whiteSpace?: \"normal\" | \"nowrap\" | \"pre\" | \"pre-wrap\" | \"pre-line\";\n wordBreak?: \"normal\" | \"break-all\" | \"break-word\" | \"keep-all\";\n textOverflow?: \"clip\" | \"ellipsis\";\n lineClamp?: number;\n\n // Box shadow\n boxShadow?: string;\n textShadow?: string;\n\n // Transform\n transform?: string;\n transformOrigin?: string;\n\n // Image\n objectFit?: \"contain\" | \"cover\" | \"fill\" | \"none\" | \"scale-down\";\n\n // Filter\n filter?: string;\n backdropFilter?: string;\n\n // Clipping\n clipPath?: string;\n\n // Text box trim\n textBoxTrim?: \"none\" | \"trim-start\" | \"trim-end\" | \"trim-both\";\n textBoxEdge?: string;\n\n // Text stroke\n WebkitTextStrokeWidth?: number | string;\n WebkitTextStrokeColor?: string;\n};\n\nconst ROOT_FONT_SIZE = 16;\n\n/**\n * Default font family. Uses concrete system font names so @effing/skia\n * resolves real font metrics instead of generic ratios for unnamed families.\n */\nexport const DEFAULT_FONT_FAMILY = \"Helvetica, Arial, sans-serif\";\n\n/**\n * Default styles for the root element.\n */\nexport const DEFAULT_STYLE: ComputedStyle = {\n display: \"flex\",\n flexDirection: \"row\",\n flexWrap: \"nowrap\",\n flexGrow: 0,\n flexShrink: 0,\n alignItems: \"stretch\",\n justifyContent: \"flex-start\",\n position: \"relative\",\n fontSize: ROOT_FONT_SIZE,\n fontWeight: 400,\n fontStyle: \"normal\",\n fontFamily: DEFAULT_FONT_FAMILY,\n color: \"black\",\n lineHeight: \"normal\",\n textAlign: \"left\",\n whiteSpace: \"normal\",\n wordBreak: \"normal\",\n textOverflow: \"clip\",\n opacity: 1,\n overflow: \"visible\",\n};\n\n/**\n * CSS properties that are inherited by child elements.\n */\nconst INHERITABLE_PROPS: (keyof ComputedStyle)[] = [\n \"color\",\n \"fontSize\",\n \"fontFamily\",\n \"fontWeight\",\n \"fontStyle\",\n \"textAlign\",\n \"textTransform\",\n \"textDecoration\",\n \"lineHeight\",\n \"letterSpacing\",\n \"whiteSpace\",\n \"wordBreak\",\n \"textOverflow\",\n \"lineClamp\",\n \"textBoxTrim\",\n \"textBoxEdge\",\n \"textShadow\",\n \"WebkitTextStrokeWidth\",\n \"WebkitTextStrokeColor\",\n];\n\n/**\n * Resolve the computed style for a node, inheriting from parent where appropriate.\n */\nexport function resolveStyle(\n rawStyle: ExpandedStyle | undefined,\n parentStyle: ComputedStyle,\n): ComputedStyle {\n const style = { ...rawStyle };\n\n // Apply inherited properties\n for (const prop of INHERITABLE_PROPS) {\n if (style[prop] === undefined && parentStyle[prop] !== undefined) {\n (style as Record<string, unknown>)[prop] = parentStyle[prop];\n }\n }\n\n // Resolve fontSize (ensure it's a number, respecting em/rem/etc units)\n if (typeof style.fontSize === \"string\") {\n const parentFontSize =\n typeof parentStyle.fontSize === \"number\"\n ? parentStyle.fontSize\n : ROOT_FONT_SIZE;\n const resolved = resolveUnit(\n style.fontSize,\n 0,\n 0,\n parentFontSize,\n ROOT_FONT_SIZE,\n );\n style.fontSize = typeof resolved === \"number\" ? resolved : parentFontSize;\n }\n\n // Resolve lineHeight: parse string values to numbers but keep multipliers\n // as-is so they're recalculated per-element in text layout (using each\n // element's own fontSize rather than the parent's).\n if (typeof style.lineHeight === \"string\") {\n const str = style.lineHeight;\n if (str.endsWith(\"%\")) {\n style.lineHeight = parseFloat(str) / 100;\n } else {\n const parsed = parseFloat(str);\n if (!isNaN(parsed)) {\n style.lineHeight = parsed;\n }\n }\n }\n\n // Resolve letterSpacing (respecting em/rem/etc units)\n if (typeof style.letterSpacing === \"string\") {\n const currentFontSize =\n typeof style.fontSize === \"number\"\n ? style.fontSize\n : typeof parentStyle.fontSize === \"number\"\n ? parentStyle.fontSize\n : ROOT_FONT_SIZE;\n const resolved = resolveUnit(\n style.letterSpacing,\n 0,\n 0,\n currentFontSize,\n ROOT_FONT_SIZE,\n );\n if (typeof resolved === \"number\") {\n style.letterSpacing = resolved;\n }\n }\n\n return style as ComputedStyle;\n}\n\n/**\n * Dimension properties that may contain CSS units needing resolution.\n */\nconst DIMENSION_PROPS: (keyof ComputedStyle)[] = [\n \"width\",\n \"height\",\n \"minWidth\",\n \"minHeight\",\n \"maxWidth\",\n \"maxHeight\",\n \"top\",\n \"right\",\n \"bottom\",\n \"left\",\n \"marginTop\",\n \"marginRight\",\n \"marginBottom\",\n \"marginLeft\",\n \"paddingTop\",\n \"paddingRight\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"rowGap\",\n \"columnGap\",\n \"flexBasis\",\n \"borderTopWidth\",\n \"borderRightWidth\",\n \"borderBottomWidth\",\n \"borderLeftWidth\",\n \"borderTopLeftRadius\",\n \"borderTopRightRadius\",\n \"borderBottomRightRadius\",\n \"borderBottomLeftRadius\",\n \"WebkitTextStrokeWidth\",\n];\n\n/**\n * Resolve a single CSS dimension string to a pixel number.\n * Returns the original value for `%` and `auto` (Yoga handles those),\n * and for values that are already numbers or unrecognised strings.\n */\nexport function resolveUnit(\n value: string,\n viewportWidth: number,\n viewportHeight: number,\n fontSize: number,\n rootFontSize: number,\n): number | string {\n // Percentages and auto are handled downstream by Yoga\n if (value.endsWith(\"%\") || value === \"auto\") return value;\n\n // Viewport-relative units\n if (value.endsWith(\"vmin\")) {\n const n = parseFloat(value);\n return isNaN(n)\n ? value\n : (n / 100) * Math.min(viewportWidth, viewportHeight);\n }\n if (value.endsWith(\"vmax\")) {\n const n = parseFloat(value);\n return isNaN(n)\n ? value\n : (n / 100) * Math.max(viewportWidth, viewportHeight);\n }\n if (value.endsWith(\"vw\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : (n / 100) * viewportWidth;\n }\n if (value.endsWith(\"vh\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : (n / 100) * viewportHeight;\n }\n\n // Font-relative units\n if (value.endsWith(\"rem\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * rootFontSize;\n }\n if (value.endsWith(\"em\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * fontSize;\n }\n\n // Absolute units (CSS reference pixel = 1/96 inch)\n if (value.endsWith(\"px\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n;\n }\n if (value.endsWith(\"pt\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * (96 / 72);\n }\n if (value.endsWith(\"pc\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * 16;\n }\n if (value.endsWith(\"in\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * 96;\n }\n if (value.endsWith(\"cm\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * (96 / 2.54);\n }\n if (value.endsWith(\"mm\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * (96 / 25.4);\n }\n\n return value;\n}\n\n/**\n * Resolve CSS units (vw, vh, vmin, vmax, em, rem, px, pt, pc, in, cm, mm)\n * in a style object to pixel values. Percentages and `auto` pass through\n * unchanged for Yoga to handle.\n */\nexport function resolveUnits(\n style: ComputedStyle,\n viewportWidth: number,\n viewportHeight: number,\n rootFontSize: number = ROOT_FONT_SIZE,\n): ComputedStyle {\n const fontSize =\n typeof style.fontSize === \"number\" ? style.fontSize : rootFontSize;\n\n for (const prop of DIMENSION_PROPS) {\n const value = style[prop];\n if (typeof value !== \"string\") continue;\n const resolved = resolveUnit(\n value,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n if (resolved !== value) {\n (style as Record<string, unknown>)[prop] = resolved;\n }\n }\n\n // Resolve CSS length units inside transform, clip-path and backdrop-filter\n // strings so that by draw time values are either bare numbers or `%` (which\n // need element dimensions).\n for (const [prop, suffix] of LENGTH_STRING_PROPS) {\n const value = style[prop];\n if (typeof value !== \"string\") continue;\n (style as Record<string, unknown>)[prop] = resolveLengthUnits(\n value,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n suffix,\n );\n }\n\n return style;\n}\n\n/**\n * String-valued properties whose embedded CSS lengths are resolved to pixels,\n * with the suffix the resolved numbers are written with. The transform parser\n * takes bare numbers; clip-path and filter strings keep an explicit `px` so\n * they stay valid CSS for the parsers downstream (Skia's filter parser\n * rejects a unitless `blur(6)`).\n */\nconst LENGTH_STRING_PROPS: [keyof ComputedStyle, string][] = [\n [\"transform\", \"\"],\n [\"transformOrigin\", \"\"],\n [\"clipPath\", \"px\"],\n [\"filter\", \"px\"],\n [\"backdropFilter\", \"px\"],\n];\n\n/**\n * Resolve CSS length units (vw, vh, em, rem, px, etc.) inside a string value\n * such as a transform, clip-path or filter. Percentages and angle units (deg,\n * rad, turn) are left untouched — percentages need element dimensions\n * (available at draw time) and angle units are not lengths.\n */\nfunction resolveLengthUnits(\n transform: string,\n viewportWidth: number,\n viewportHeight: number,\n fontSize: number,\n rootFontSize: number,\n suffix = \"\",\n): string {\n return transform.replace(\n // The lookbehind keeps a number from being matched mid-token (`1e1em`).\n /(?<![\\w.])(-?\\d*\\.?\\d+)(vw|vh|vmin|vmax|em|rem|px|pt|pc|in|cm|mm)\\b/g,\n (match) => {\n const resolved = resolveUnit(\n match,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n return typeof resolved === \"number\"\n ? `${formatCSSNumber(resolved)}${suffix}`\n : match;\n },\n );\n}\n\n/**\n * Resolve a dimension value (width, height, margin, etc.) to pixels.\n * Percentage values are resolved relative to the provided container size.\n */\nexport function resolveDimension(\n value: number | string | undefined,\n containerSize: number,\n): number | undefined {\n if (value === undefined || value === \"auto\") return undefined;\n if (typeof value === \"number\") return value;\n const s = String(value);\n if (s.endsWith(\"%\")) {\n return (parseFloat(s) / 100) * containerSize;\n }\n const n = parseFloat(s);\n return isNaN(n) ? undefined : n;\n}\n","import { GlobalFonts } from \"@effing/skia\";\n\nimport type { FontData } from \"../types.ts\";\nimport { parseFontMetrics } from \"./font-metrics.ts\";\nimport type { FontMetrics } from \"./font-metrics.ts\";\n\nconst registeredFonts = new Set<string>();\nconst metricsCache = new Map<string, FontMetrics>();\n\n/**\n * Reset internal font state (test-only).\n */\nexport function _resetForTest(): void {\n registeredFonts.clear();\n metricsCache.clear();\n}\n\n/**\n * Register a font from a FontData buffer.\n * Registration is idempotent — re-registering the same font name is a no-op.\n *\n * @param font - Font data to register\n */\nexport function registerFont(font: FontData): void {\n const key = `${font.name}:${font.weight}:${font.style}`;\n if (registeredFonts.has(key)) return;\n\n const buffer = Buffer.isBuffer(font.data)\n ? font.data\n : Buffer.from(font.data);\n\n GlobalFonts.register(buffer, font.name);\n\n const metrics = parseFontMetrics(font.data);\n if (metrics) {\n metricsCache.set(key, metrics);\n }\n\n registeredFonts.add(key);\n}\n\n/**\n * Look up cached font metrics for a given family/weight/style combination.\n * Returns the exact match if found, otherwise the first match for the family.\n */\nexport function getFontMetrics(\n family: string,\n weight: number | string,\n style: string,\n): FontMetrics | null {\n // CSS font-family may be a comma-separated fallback chain; try each name\n const families = family\n .split(\",\")\n .map((f) => f.trim().replace(/^['\"]|['\"]$/g, \"\"));\n\n for (const name of families) {\n const exact = metricsCache.get(`${name}:${weight}:${style}`);\n if (exact) return exact;\n\n for (const [key, metrics] of metricsCache) {\n if (key.startsWith(`${name}:`)) return metrics;\n }\n }\n\n return null;\n}\n\n/**\n * Register a font from a file path.\n *\n * @param path - Path to the font file\n * @param nameAlias - Optional font family name override\n */\nexport function registerFontFromPath(path: string, nameAlias?: string): void {\n GlobalFonts.registerFromPath(path, nameAlias ?? \"\");\n}\n\n/**\n * Get the list of registered font family names.\n *\n * @returns Array of font family names\n */\nexport function registeredFamilies(): string[] {\n return GlobalFonts.families.map((f: { family: string }) => f.family);\n}\n\n/**\n * Ensure all fonts from the given array are registered.\n * Called internally by `renderReactElement()`.\n */\nexport function ensureFontsRegistered(fonts: FontData[]): void {\n for (const font of fonts) {\n registerFont(font);\n }\n}\n","/**\n * Parse typographic metrics from the hhea and head tables of a font binary.\n *\n * We parse the font binary ourselves because the canvas API (skia) only\n * exposes ascent and descent — not the line gap. Some fonts split their\n * vertical spacing across three values: ascender, descender, and a separate\n * line gap (sTypoLineGap in the OS/2 table). When the canvas reports just\n * ascent + descent for these fonts, the line gap is lost, producing a\n * line-height that's too tight (e.g. 1.0× font size instead of ~1.3×).\n *\n * We read hhea metrics specifically because that's what Satori uses (via\n * opentype.js). For fonts with a separate line gap, the hhea ascender is\n * typically inflated to include it, so (ascender - descender) / unitsPerEm\n * gives the intended line-height in a single subtraction.\n *\n * Supports TrueType/OpenType (.ttf/.otf) and WOFF (.woff) formats.\n */\n\nimport { inflateSync } from \"node:zlib\";\n\nexport type FontMetrics = {\n unitsPerEm: number;\n ascender: number;\n descender: number;\n};\n\n/**\n * Convert hhea font metrics to pixel values at a given font size.\n */\nexport function fontMetricsToPx(\n metrics: FontMetrics,\n fontSize: number,\n): { ascent: number; descent: number } {\n return {\n ascent: (metrics.ascender / metrics.unitsPerEm) * fontSize,\n descent: (-metrics.descender / metrics.unitsPerEm) * fontSize,\n };\n}\n\n// WOFF signature: 'wOFF' (0x774F4646)\nconst WOFF_SIGNATURE = 0x774f4646;\n\ntype WoffTableEntry = {\n offset: number;\n compLength: number;\n origLength: number;\n};\n\n/**\n * Read the raw bytes for a table from a WOFF file,\n * decompressing with zlib if the table is compressed.\n */\nfunction readWoffTable(view: DataView, entry: WoffTableEntry): DataView | null {\n const compressed = entry.compLength < entry.origLength;\n if (compressed) {\n try {\n const compData = new Uint8Array(\n view.buffer,\n view.byteOffset + entry.offset,\n entry.compLength,\n );\n const decompressed = inflateSync(compData);\n return new DataView(\n decompressed.buffer,\n decompressed.byteOffset,\n decompressed.byteLength,\n );\n } catch {\n return null;\n }\n }\n return new DataView(\n view.buffer,\n view.byteOffset + entry.offset,\n entry.origLength,\n );\n}\n\nfunction parseWoff(view: DataView): FontMetrics | null {\n if (view.byteLength < 44) return null;\n const numTables = view.getUint16(12);\n if (view.byteLength < 44 + numTables * 20) return null;\n\n let headEntry: WoffTableEntry | null = null;\n let hheaEntry: WoffTableEntry | null = null;\n\n for (let i = 0; i < numTables; i++) {\n const r = 44 + i * 20;\n const tag =\n String.fromCharCode(view.getUint8(r)) +\n String.fromCharCode(view.getUint8(r + 1)) +\n String.fromCharCode(view.getUint8(r + 2)) +\n String.fromCharCode(view.getUint8(r + 3));\n const offset = view.getUint32(r + 4);\n const compLength = view.getUint32(r + 8);\n const origLength = view.getUint32(r + 12);\n\n if (tag === \"head\") headEntry = { offset, compLength, origLength };\n else if (tag === \"hhea\") hheaEntry = { offset, compLength, origLength };\n }\n\n if (!headEntry || !hheaEntry) return null;\n\n const headView = readWoffTable(view, headEntry);\n const hheaView = readWoffTable(view, hheaEntry);\n if (!headView || !hheaView) return null;\n\n if (headView.byteLength < 20 || hheaView.byteLength < 8) return null;\n\n const unitsPerEm = headView.getUint16(18);\n const ascender = hheaView.getInt16(4);\n const descender = hheaView.getInt16(6);\n\n return { unitsPerEm, ascender, descender };\n}\n\nfunction parseSfnt(view: DataView): FontMetrics | null {\n const numTables = view.getUint16(4);\n if (view.byteLength < 12 + numTables * 16) return null;\n\n let headOffset = -1;\n let hheaOffset = -1;\n\n for (let i = 0; i < numTables; i++) {\n const recordOffset = 12 + i * 16;\n const tag =\n String.fromCharCode(view.getUint8(recordOffset)) +\n String.fromCharCode(view.getUint8(recordOffset + 1)) +\n String.fromCharCode(view.getUint8(recordOffset + 2)) +\n String.fromCharCode(view.getUint8(recordOffset + 3));\n\n const offset = view.getUint32(recordOffset + 8);\n\n if (tag === \"head\") headOffset = offset;\n else if (tag === \"hhea\") hheaOffset = offset;\n }\n\n if (headOffset < 0 || hheaOffset < 0) return null;\n\n if (view.byteLength < headOffset + 20) return null;\n const unitsPerEm = view.getUint16(headOffset + 18);\n\n if (view.byteLength < hheaOffset + 8) return null;\n const ascender = view.getInt16(hheaOffset + 4);\n const descender = view.getInt16(hheaOffset + 6);\n\n return { unitsPerEm, ascender, descender };\n}\n\n/**\n * Parse the hhea and head tables from a TrueType/OpenType or WOFF font binary\n * to extract line spacing metrics.\n *\n * Returns `null` if the font lacks a required table (e.g. some bitmap fonts).\n */\nexport function parseFontMetrics(\n data: Buffer | ArrayBuffer,\n): FontMetrics | null {\n const buf =\n data instanceof ArrayBuffer\n ? data\n : data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);\n const view = new DataView(buf);\n\n if (buf.byteLength < 12) return null;\n\n const signature = view.getUint32(0);\n if (signature === WOFF_SIGNATURE) {\n return parseWoff(view);\n }\n return parseSfnt(view);\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\n/**\n * Detect the primary script/language of a text string.\n * Used for font selection and line-breaking behavior.\n */\nexport function detectLanguageCode(text: string): string | undefined {\n for (const char of text) {\n const cp = char.codePointAt(0);\n if (cp === undefined) continue;\n\n // CJK Unified Ideographs\n if (cp >= 0x4e00 && cp <= 0x9fff) return \"zh\";\n // CJK Extension A\n if (cp >= 0x3400 && cp <= 0x4dbf) return \"zh\";\n // Hiragana\n if (cp >= 0x3040 && cp <= 0x309f) return \"ja\";\n // Katakana\n if (cp >= 0x30a0 && cp <= 0x30ff) return \"ja\";\n // Hangul Syllables\n if (cp >= 0xac00 && cp <= 0xd7af) return \"ko\";\n // Hangul Jamo\n if (cp >= 0x1100 && cp <= 0x11ff) return \"ko\";\n // Thai\n if (cp >= 0x0e00 && cp <= 0x0e7f) return \"th\";\n // Arabic\n if (cp >= 0x0600 && cp <= 0x06ff) return \"ar\";\n // Hebrew\n if (cp >= 0x0590 && cp <= 0x05ff) return \"he\";\n // Devanagari\n if (cp >= 0x0900 && cp <= 0x097f) return \"hi\";\n // Bengali\n if (cp >= 0x0980 && cp <= 0x09ff) return \"bn\";\n // Tamil\n if (cp >= 0x0b80 && cp <= 0x0bff) return \"ta\";\n // Telugu\n if (cp >= 0x0c00 && cp <= 0x0c7f) return \"te\";\n // Kannada\n if (cp >= 0x0c80 && cp <= 0x0cff) return \"kn\";\n // Malayalam\n if (cp >= 0x0d00 && cp <= 0x0d7f) return \"ml\";\n }\n\n return undefined;\n}\n\n/**\n * Check if a character is an emoji.\n */\nexport function isEmoji(char: string): boolean {\n const cp = char.codePointAt(0);\n if (cp === undefined) return false;\n\n // Common emoji ranges\n if (cp >= 0x1f600 && cp <= 0x1f64f) return true; // Emoticons\n if (cp >= 0x1f300 && cp <= 0x1f5ff) return true; // Misc Symbols & Pictographs\n if (cp >= 0x1f680 && cp <= 0x1f6ff) return true; // Transport & Map\n if (cp >= 0x1f900 && cp <= 0x1f9ff) return true; // Supplemental Symbols\n if (cp >= 0x2600 && cp <= 0x26ff) return true; // Misc Symbols\n if (cp >= 0x2700 && cp <= 0x27bf) return true; // Dingbats\n if (cp >= 0x2b50 && cp <= 0x2b55) return true; // Misc Symbols & Arrows (star, circle)\n if (cp >= 0x200d && cp <= 0x200d) return true; // Zero Width Joiner\n if (cp >= 0xfe00 && cp <= 0xfe0f) return true; // Variation Selectors\n if (cp >= 0x1fa00 && cp <= 0x1fa6f) return true; // Chess Symbols\n if (cp >= 0x1fa70 && cp <= 0x1faff) return true; // Symbols Extended-A\n if (cp >= 0x231a && cp <= 0x23f3) return true; // Misc Technical (watch, hourglass)\n if (cp >= 0x23e9 && cp <= 0x23fa) return true; // Misc Technical (play, pause)\n if (cp >= 0x25aa && cp <= 0x25fe) return true; // Geometric Shapes\n if (cp >= 0x2934 && cp <= 0x2935) return true; // Arrows\n if (cp >= 0x2b05 && cp <= 0x2b07) return true; // Arrows\n if (cp >= 0x3030 && cp <= 0x3030) return true; // Wavy dash\n if (cp >= 0x303d && cp <= 0x303d) return true; // Part alternation mark\n if (cp >= 0x3297 && cp <= 0x3299) return true; // CJK symbols\n\n return false;\n}\n","import LineBreaker from \"linebreak\";\n\nexport type BreakOpportunity = {\n position: number;\n required: boolean;\n};\n\n/**\n * Find line-break opportunities in text using UAX #14 algorithm.\n *\n * @param text - The text to analyze\n * @returns Array of break opportunities with positions and whether they're required (hard breaks)\n */\nexport function findBreakOpportunities(text: string): BreakOpportunity[] {\n const breaker = new LineBreaker(text);\n const opportunities: BreakOpportunity[] = [];\n\n let bk = breaker.nextBreak();\n while (bk) {\n opportunities.push({\n position: bk.position,\n required: bk.required ?? false,\n });\n bk = breaker.nextBreak();\n }\n\n return opportunities;\n}\n","import { createCanvas } from \"@effing/skia\";\nimport type { SKRSContext2D } from \"@effing/skia\";\n\nimport { fontMetricsToPx } from \"../font-metrics.ts\";\nimport type { FontMetrics } from \"../font-metrics.ts\";\n\nexport type TextMetrics = {\n width: number;\n ascent: number;\n descent: number;\n height: number;\n};\n\n// Scratch canvas for text measurement when no ctx is available\nlet scratchCtx: SKRSContext2D | null = null;\n\nfunction getScratchCtx(): SKRSContext2D {\n if (!scratchCtx) {\n scratchCtx = createCanvas(1, 1).getContext(\"2d\");\n }\n return scratchCtx;\n}\n\n/**\n * Run `fn` with the context's text unhinted and unsnapped.\n *\n * Under `textRendering: \"geometricPrecision\"`, @effing/skia lays text out\n * unhinted and fills each glyph outline at its exact position, instead of\n * drawing hinted masks snapped to the pixel grid. Text then lands in the same\n * place at any scale, so nothing jumps while a transform animates. All text is\n * measured and drawn this way; the context's own setting is restored after.\n */\nexport function withUnsnappedText<T>(ctx: SKRSContext2D, fn: () => T): T {\n const previous = ctx.textRendering;\n if (previous === \"geometricPrecision\") return fn();\n ctx.textRendering = \"geometricPrecision\";\n try {\n return fn();\n } finally {\n ctx.textRendering = previous;\n }\n}\n\nconst GENERIC_FAMILIES = new Set([\n \"serif\",\n \"sans-serif\",\n \"monospace\",\n \"cursive\",\n \"fantasy\",\n \"system-ui\",\n \"ui-serif\",\n \"ui-sans-serif\",\n \"ui-monospace\",\n \"ui-rounded\",\n \"math\",\n \"emoji\",\n \"fangsong\",\n]);\n\nfunction quoteFontFamily(family: string): string {\n if (!family || GENERIC_FAMILIES.has(family)) return family;\n return `\"${family}\"`;\n}\n\n/** A font-family list with every non-generic family name quoted. */\nexport function quoteFontFamilies(fontFamily: string): string {\n return fontFamily\n .split(\",\")\n .map((f) => quoteFontFamily(f.trim()))\n .join(\", \");\n}\n\n/**\n * Set font properties on a canvas context for measurement.\n */\nexport function setFont(\n ctx: SKRSContext2D,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string = 400,\n fontStyle: string = \"normal\",\n): void {\n ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${quoteFontFamilies(fontFamily)}`;\n}\n\n/**\n * Measure text using the canvas ctx.measureText() API.\n * Returns width, ascent, descent, and total height.\n */\nexport function measureText(\n text: string,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string = 400,\n fontStyle: string = \"normal\",\n ctx?: SKRSContext2D,\n): TextMetrics {\n const c = ctx ?? getScratchCtx();\n setFont(c, fontSize, fontFamily, fontWeight, fontStyle);\n\n const m = withUnsnappedText(c, () => c.measureText(text));\n\n const ascent =\n m.fontBoundingBoxAscent ?? m.actualBoundingBoxAscent ?? fontSize * 0.8;\n const descent =\n m.fontBoundingBoxDescent ?? m.actualBoundingBoxDescent ?? fontSize * 0.2;\n\n return {\n width: m.width,\n ascent,\n descent,\n height: ascent + descent,\n };\n}\n\n/**\n * Measure how many pixels to trim from the top (overTrim) and bottom\n * (underTrim) of a line box based on `text-box-edge` keywords.\n *\n * The trim amount is the difference between the full line-height half-leading\n * and the target metric for each edge.\n */\nexport function measureTrimMetrics(\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n lineHeight: number,\n edge: string,\n ctx?: SKRSContext2D,\n fontMetrics?: FontMetrics | null,\n): { overTrim: number; underTrim: number } {\n const c = ctx ?? getScratchCtx();\n setFont(c, fontSize, fontFamily, fontWeight, fontStyle);\n const measure = (text: string) =>\n withUnsnappedText(c, () => c.measureText(text));\n\n const refMetrics = measure(\"M\");\n\n // When font metrics are available, use hhea ascender/descender for half-leading\n // so it stays consistent with the hhea-based line height.\n let fontAscent: number;\n let fontDescent: number;\n if (fontMetrics) {\n const px = fontMetricsToPx(fontMetrics, fontSize);\n fontAscent = px.ascent;\n fontDescent = px.descent;\n } else {\n fontAscent =\n refMetrics.fontBoundingBoxAscent ??\n refMetrics.actualBoundingBoxAscent ??\n fontSize * 0.8;\n fontDescent =\n refMetrics.fontBoundingBoxDescent ??\n refMetrics.actualBoundingBoxDescent ??\n fontSize * 0.2;\n }\n\n // Parse edge into over-edge and under-edge keywords\n const parts = edge.trim().split(/\\s+/);\n const overEdge = parts[0] ?? \"text\";\n const underEdge = parts.length > 1 ? parts[1]! : overEdge;\n\n // Resolve over-edge keyword → target ascent\n let targetAscent: number;\n switch (overEdge) {\n case \"cap\": {\n const capMetrics = measure(\"H\");\n targetAscent = capMetrics.actualBoundingBoxAscent ?? fontSize * 0.7;\n break;\n }\n case \"ex\": {\n const exMetrics = measure(\"x\");\n targetAscent = exMetrics.actualBoundingBoxAscent ?? fontSize * 0.5;\n break;\n }\n case \"ideographic\":\n case \"ideographic-ink\":\n case \"text\":\n default:\n targetAscent = fontAscent;\n break;\n }\n\n // Resolve under-edge keyword → target descent\n let targetDescent: number;\n switch (underEdge) {\n case \"alphabetic\":\n targetDescent = 0;\n break;\n case \"ideographic\":\n case \"ideographic-ink\":\n case \"text\":\n default:\n targetDescent = fontDescent;\n break;\n }\n\n const halfLeading = (lineHeight - (fontAscent + fontDescent)) / 2;\n const overTrim = halfLeading + (fontAscent - targetAscent);\n const underTrim = halfLeading + (fontDescent - targetDescent);\n\n return {\n overTrim: Math.max(0, overTrim),\n underTrim: Math.max(0, underTrim),\n };\n}\n\n/**\n * Measure the width of a single word.\n */\nexport function measureWord(\n word: string,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string = 400,\n fontStyle: string = \"normal\",\n ctx?: SKRSContext2D,\n letterSpacing: number = 0,\n): number {\n const base = measureText(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n ).width;\n if (letterSpacing === 0 || word.length === 0) return base;\n return base + letterSpacing * word.length;\n}\n","// Native paragraph layout through @effing/skia's `Paragraph`: Skia breaks,\n// shapes and paints the text in one place, instead of this package measuring\n// it word by word across the native boundary. The paragraph follows the CSS\n// line model (every line box exactly `lineHeight` tall, baseline placed by\n// half-leading from the font's hhea metrics) and paints unhinted, unsnapped\n// glyphs, exactly as `fillText` does under `withUnsnappedText`.\n\nimport { Paragraph } from \"@effing/skia/extensions\";\nimport type { ParagraphStyle } from \"@effing/skia/extensions\";\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { DEFAULT_FONT_FAMILY } from \"../style/compute.ts\";\nimport { isEmoji } from \"../language.ts\";\nimport type { FontMetrics } from \"../font-metrics.ts\";\nimport { measureTrimMetrics, quoteFontFamilies } from \"./measure.ts\";\nimport type { TextLayoutResult, TextSegment } from \"./index.ts\";\n\nexport type NativeParagraph = Paragraph;\n\n/**\n * Whether the native path covers this text. The TypeScript layout remains for\n * what a paragraph can't express: `word-break: break-all`, emoji drawn as\n * images, which need a position per emoji, and trailing spaces that\n * `white-space: pre` preserves, where a paragraph lets them hang.\n */\nexport function canLayoutNatively(\n text: string,\n style: ComputedStyle,\n emojiEnabled?: boolean,\n): boolean {\n // An empty paragraph has no lines; the TypeScript layout keeps one empty\n // line box for it.\n if (text === \"\") return false;\n if (style.wordBreak === \"break-all\") return false;\n if (style.whiteSpace === \"pre\" && /[ \\t](?:\\n|$)/.test(text)) return false;\n if (emojiEnabled) {\n for (const char of text) {\n if (isEmoji(char)) return false;\n }\n }\n return true;\n}\n\nfunction toWeight(weight: number | string | undefined): number {\n if (typeof weight === \"number\") return weight;\n if (weight === \"bold\") return 700;\n const parsed = parseInt(String(weight ?? \"400\"), 10);\n return isNaN(parsed) ? 400 : parsed;\n}\n\nfunction toFontStyle(\n fontStyle: string | undefined,\n): ParagraphStyle[\"fontStyle\"] {\n if (fontStyle?.startsWith(\"italic\")) return \"italic\";\n if (fontStyle?.startsWith(\"oblique\")) return \"oblique\";\n return \"normal\";\n}\n\nconst TEXT_ALIGNS = new Set([\n \"left\",\n \"right\",\n \"center\",\n \"justify\",\n \"start\",\n \"end\",\n]);\n\nfunction toTextAlign(\n textAlign: string | undefined,\n): ParagraphStyle[\"textAlign\"] {\n return textAlign !== undefined && TEXT_ALIGNS.has(textAlign)\n ? (textAlign as ParagraphStyle[\"textAlign\"])\n : \"left\";\n}\n\n// Skia treats a width of 0 as unbounded; a box with no room wraps at every\n// opportunity instead.\nconst MIN_WIDTH = 0.01;\n\n// A paragraph's native memory (some 20 KB) is released by a finalizer, and\n// Node only runs finalizers on a later turn of the event loop. A frame loop\n// that awaits nothing but microtasks never gets there, and would grow by every\n// paragraph it has built. So they are counted per turn, and a render that\n// finds too many outstanding yields one turn itself.\nconst MAX_PENDING_PARAGRAPHS = 2000;\nlet pendingParagraphs = 0;\nlet turnWatched = false;\n\nfunction countParagraph(): void {\n pendingParagraphs++;\n if (turnWatched) return;\n turnWatched = true;\n // Runs once the event loop turns, by whoever's doing.\n setImmediate(() => {\n pendingParagraphs = 0;\n turnWatched = false;\n });\n}\n\n/**\n * Give Node a turn of the event loop to release the paragraphs built so far,\n * if enough have piled up since the last one.\n */\nexport async function releaseParagraphs(): Promise<void> {\n if (pendingParagraphs < MAX_PENDING_PARAGRAPHS) return;\n await new Promise<void>((resolve) => setImmediate(resolve));\n}\n\n/**\n * Lay out already-transformed text natively. Mirrors the TypeScript layout:\n * one segment per line, CSS half-leading line boxes from the font's hhea\n * metrics, an ellipsis for nowrap + text-overflow and for line-clamp, and\n * text-box-trim.\n *\n * Returns null when a word is wider than `maxWidth`: Skia would break it\n * mid-word, where CSS (without `overflow-wrap`) lets it overflow, as the\n * TypeScript layout does.\n *\n * @param lineHeight - Line box height in px, or undefined for `normal`\n */\nexport function layoutTextNative(\n text: string,\n style: ComputedStyle,\n maxWidth: number,\n lineHeight: number | undefined,\n): TextLayoutResult | null {\n const fontSize = style.fontSize ?? 16;\n const fontFamily = style.fontFamily ?? DEFAULT_FONT_FAMILY;\n const fontWeight = style.fontWeight ?? 400;\n const fontStyle = style.fontStyle ?? \"normal\";\n const letterSpacing =\n typeof style.letterSpacing === \"number\" ? style.letterSpacing : 0;\n const whiteSpace = style.whiteSpace ?? \"normal\";\n const noWrap = whiteSpace === \"nowrap\" || whiteSpace === \"pre\";\n const lineClamp =\n style.lineClamp && style.lineClamp > 0 ? style.lineClamp : undefined;\n const ellipsis =\n lineClamp !== undefined || (noWrap && style.textOverflow === \"ellipsis\")\n ? \"…\"\n : undefined;\n const width = maxWidth > 0 ? maxWidth : MIN_WIDTH;\n\n // Skia keeps its own cache of shaped text, so building a paragraph for text\n // it has seen (the next frame of a video, or Yoga measuring a node again)\n // only breaks the lines anew.\n const paragraph = new Paragraph(text, {\n fontFamily: quoteFontFamilies(fontFamily),\n fontSize,\n fontWeight: toWeight(fontWeight),\n fontStyle: toFontStyle(fontStyle),\n letterSpacing,\n lineHeight: lineHeight ?? 0,\n textAlign: toTextAlign(style.textAlign),\n noWrap,\n maxLines: lineClamp,\n ellipsis,\n });\n countParagraph();\n const layout = paragraph.layout(width);\n if (!noWrap && layout.minIntrinsicWidth > width) return null;\n\n const segments: TextSegment[] = layout.lines.map((line, i) => ({\n // A line that ends the text at a newline reports the newline as its text.\n text: text.slice(line.startIndex, line.endIndex).replace(/\\n/g, \"\"),\n x: line.left,\n y: line.baseline,\n width: line.width,\n height: layout.lineHeight,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n color: style.color ?? \"black\",\n ascent: layout.ascent,\n textDecoration: style.textDecoration,\n letterSpacing,\n lineIndex: i,\n }));\n\n let height = layout.height;\n // As in the TypeScript layout: round auto line-height boxes up so Yoga's\n // integer rounding never clips a descender.\n if (lineHeight === undefined && segments.length > 0) {\n height = Math.ceil(height);\n }\n\n let paragraphOffsetY = 0;\n const textBoxTrim = style.textBoxTrim;\n if (textBoxTrim && textBoxTrim !== \"none\" && segments.length > 0) {\n // Express the hhea metrics as a font of unitsPerEm = fontSize, so they\n // convert back to the same px.\n const fontMetrics: FontMetrics = {\n unitsPerEm: fontSize,\n ascender: layout.ascent,\n descender: -layout.descent,\n };\n const trim = measureTrimMetrics(\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n layout.lineHeight,\n style.textBoxEdge ?? \"text\",\n undefined,\n fontMetrics,\n );\n if (textBoxTrim === \"trim-start\" || textBoxTrim === \"trim-both\") {\n for (const seg of segments) seg.y -= trim.overTrim;\n height -= trim.overTrim;\n paragraphOffsetY = -trim.overTrim;\n }\n if (textBoxTrim === \"trim-end\" || textBoxTrim === \"trim-both\") {\n height -= trim.underTrim;\n }\n }\n\n return {\n segments,\n width: segments.reduce((w, s) => Math.max(w, s.width), 0),\n height,\n paragraph,\n paragraphOffsetY,\n };\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport type { SKRSContext2D } from \"@effing/skia\";\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { DEFAULT_FONT_FAMILY, resolveUnit } from \"../style/compute.ts\";\nimport { getFontMetrics } from \"../font.ts\";\nimport { fontMetricsToPx } from \"../font-metrics.ts\";\nimport type { FontMetrics } from \"../font-metrics.ts\";\nimport { isEmoji } from \"../language.ts\";\nimport { findBreakOpportunities } from \"./linebreak.ts\";\nimport { measureText, measureTrimMetrics, measureWord } from \"./measure.ts\";\nimport type { TextMetrics } from \"./measure.ts\";\nimport { canLayoutNatively, layoutTextNative } from \"./native.ts\";\nimport type { NativeParagraph } from \"./native.ts\";\n\nexport type TextSegment = {\n text: string;\n x: number;\n y: number;\n width: number;\n height: number;\n fontSize: number;\n fontFamily: string;\n fontWeight: number | string;\n fontStyle: string;\n color: string;\n ascent: number;\n textDecoration?: string;\n letterSpacing: number;\n lineIndex: number;\n textStrokeWidth?: number;\n textStrokeColor?: string;\n};\n\nexport type TextLayoutResult = {\n segments: TextSegment[];\n width: number;\n height: number;\n /**\n * Set when the text was laid out natively: the paragraph to paint instead\n * of the segments, which still describe its lines (for decorations).\n */\n paragraph?: NativeParagraph;\n /** Vertical offset to paint `paragraph` at, relative to the text box. */\n paragraphOffsetY?: number;\n};\n\n/**\n * Measure the width of a word, accounting for emoji characters when enabled.\n * Emoji characters are treated as square images sized to fontSize.\n */\nfunction emojiAwareMeasureWord(\n word: string,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n ctx?: SKRSContext2D,\n letterSpacing: number = 0,\n): number {\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n let totalWidth = 0;\n let textBuffer = \"\";\n\n for (const { segment } of segmenter.segment(word)) {\n let isEmojiSegment = false;\n for (const char of segment) {\n if (isEmoji(char)) {\n isEmojiSegment = true;\n break;\n }\n }\n\n if (isEmojiSegment) {\n if (textBuffer) {\n totalWidth += measureWord(\n textBuffer,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n textBuffer = \"\";\n }\n totalWidth += fontSize;\n } else {\n textBuffer += segment;\n }\n }\n\n if (textBuffer) {\n totalWidth += measureWord(\n textBuffer,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n }\n\n return totalWidth;\n}\n\n/**\n * Lay out text content into positioned lines.\n *\n * Text is laid out natively, as one paragraph that Skia breaks and shapes\n * (see `./native.ts`), except where a paragraph can't express the result —\n * `word-break: break-all`, emoji drawn as images, a word wider than the box —\n * which goes through `layoutTextFallback`.\n *\n * @param text - The text to lay out\n * @param style - Computed style\n * @param maxWidth - Maximum width for wrapping\n * @param ctx - Canvas context for measurement\n * @param emojiEnabled - Whether to use emoji-aware measurement\n * @returns Text segments with positions and total dimensions\n */\nexport function layoutText(\n text: string,\n style: ComputedStyle,\n maxWidth: number,\n ctx?: SKRSContext2D,\n emojiEnabled?: boolean,\n): TextLayoutResult {\n const fontSize = style.fontSize ?? 16;\n const isAutoLineHeight =\n style.lineHeight === undefined || style.lineHeight === \"normal\";\n const lineHeight = isAutoLineHeight\n ? undefined\n : resolveLineHeight(style.lineHeight, fontSize);\n // A paragraph reads a line height of 0 as `normal`, so a line box\n // collapsed to nothing is left to the fallback.\n const hasLineBox = lineHeight === undefined || lineHeight > 0;\n if (hasLineBox && canLayoutNatively(text, style, emojiEnabled)) {\n const result = layoutTextNative(\n applyTextTransform(text, style),\n style,\n maxWidth,\n lineHeight,\n );\n if (result) {\n const textStrokeWidth = resolveTextStrokeWidth(style, fontSize);\n for (const seg of result.segments) {\n seg.textStrokeWidth = textStrokeWidth;\n seg.textStrokeColor = style.WebkitTextStrokeColor;\n }\n return result;\n }\n }\n return layoutTextFallback(text, style, maxWidth, ctx, emojiEnabled);\n}\n\n/**\n * The TypeScript layout: breaks lines by measuring the text word by word, and\n * positions each line as a segment to draw with `fillText`.\n */\nexport function layoutTextFallback(\n text: string,\n style: ComputedStyle,\n maxWidth: number,\n ctx?: SKRSContext2D,\n emojiEnabled?: boolean,\n): TextLayoutResult {\n const fontSize = style.fontSize ?? 16;\n const fontFamily = style.fontFamily ?? DEFAULT_FONT_FAMILY;\n const fontWeight = style.fontWeight ?? 400;\n const fontStyle = style.fontStyle ?? \"normal\";\n const color = style.color ?? \"black\";\n const textAlign = style.textAlign ?? \"left\";\n // Measure reference metrics for \"normal\" lineHeight (font ascent + descent)\n const refMetrics = measureText(\n \"M\",\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n );\n const fontMetrics = getFontMetrics(fontFamily, fontWeight, fontStyle);\n const lineHeightPx = resolveLineHeight(\n style.lineHeight,\n fontSize,\n refMetrics,\n fontMetrics,\n );\n const letterSpacing =\n typeof style.letterSpacing === \"number\" ? style.letterSpacing : 0;\n const whiteSpace = style.whiteSpace ?? \"normal\";\n const wordBreak = style.wordBreak ?? \"normal\";\n const textOverflow = style.textOverflow ?? \"clip\";\n const textDecoration = style.textDecoration;\n\n const textStrokeWidth = resolveTextStrokeWidth(style, fontSize);\n const textStrokeColor = style.WebkitTextStrokeColor;\n\n // Choose measurement function based on emoji mode\n const measure = emojiEnabled\n ? (word: string, ls?: number) =>\n emojiAwareMeasureWord(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n ls ?? letterSpacing,\n )\n : (word: string, ls?: number) =>\n measureWord(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n ls ?? letterSpacing,\n );\n\n const processedText = applyTextTransform(text, style);\n\n const noWrap = whiteSpace === \"nowrap\" || whiteSpace === \"pre\";\n\n // Split by explicit newlines\n const paragraphs = processedText.split(\"\\n\");\n\n const lines: string[] = [];\n\n for (const paragraph of paragraphs) {\n if (noWrap) {\n lines.push(paragraph);\n continue;\n }\n\n // Wrap text\n const wrapped = wrapText(\n paragraph,\n maxWidth,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n letterSpacing,\n wordBreak,\n ctx,\n measure,\n );\n lines.push(...wrapped);\n }\n\n // Handle text-overflow: ellipsis\n if (textOverflow === \"ellipsis\" && noWrap && lines.length === 1) {\n const line = lines[0]!;\n const lineWidth = measure(line);\n if (lineWidth > maxWidth) {\n lines[0] = truncateWithEllipsis(\n line,\n maxWidth,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n }\n }\n\n // Handle lineClamp: truncate to N lines with ellipsis on last visible line.\n // Rejoin all text from the last visible line onward so the truncation can\n // fill the last line with as much text as possible (instead of being limited\n // to what the word-wrapping placed on that line alone).\n const lineClamp = style.lineClamp;\n if (lineClamp && lineClamp > 0 && lines.length > lineClamp) {\n const lastLineText = lines.slice(lineClamp - 1).join(\" \");\n lines.length = lineClamp;\n lines[lineClamp - 1] = truncateWithEllipsis(\n lastLineText,\n maxWidth,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n }\n\n // Create positioned segments\n const segments: TextSegment[] = [];\n let totalHeight = 0;\n let maxLineWidth = 0;\n const isAutoLineHeight =\n style.lineHeight === undefined || style.lineHeight === \"normal\";\n // When font metrics are available, derive positioning ascent/descent from\n // hhea values so baseline placement is consistent with the hhea-based\n // line-height. Canvas fontBoundingBox metrics can differ from hhea values,\n // and mixing the two shifts the baseline. Satori uses hhea for both.\n const fontPx = fontMetrics ? fontMetricsToPx(fontMetrics, fontSize) : null;\n let lastPositioningDescent: number | undefined;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n const lineWidth = measure(line);\n\n // A line wider than the box is start-aligned and overflows the end edge,\n // as in CSS, whatever the alignment (and as a native paragraph does).\n const slack = Math.max(0, maxWidth - lineWidth);\n let x = 0;\n if (textAlign === \"center\") {\n x = slack / 2;\n } else if (textAlign === \"right\") {\n x = slack;\n }\n\n const metrics = measureText(\n line || \"M\",\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n );\n\n const positioningAscent = fontPx?.ascent ?? metrics.ascent;\n const positioningDescent = fontPx?.descent ?? metrics.descent;\n lastPositioningDescent = positioningDescent;\n\n // When line-height is \"normal\" and font content area exceeds the\n // hhea-based line-height, scale both proportionally so half-leading\n // becomes 0 and text stays within the line box. For explicit tight\n // lineHeight values the overflow is intentional (standard CSS half-leading).\n const contentHeight = positioningAscent + positioningDescent;\n let effectiveAscent = positioningAscent;\n let effectiveDescent = positioningDescent;\n if (isAutoLineHeight && contentHeight > lineHeightPx) {\n const scale = lineHeightPx / contentHeight;\n effectiveAscent = positioningAscent * scale;\n effectiveDescent = positioningDescent * scale;\n }\n const baselineY =\n totalHeight + (lineHeightPx + effectiveAscent - effectiveDescent) / 2;\n\n segments.push({\n text: line,\n x,\n y: baselineY,\n width: lineWidth,\n height: lineHeightPx,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n color,\n ascent: metrics.ascent,\n textDecoration,\n letterSpacing,\n lineIndex: i,\n textStrokeWidth,\n textStrokeColor,\n });\n\n totalHeight += lineHeightPx;\n maxLineWidth = Math.max(maxLineWidth, lineWidth);\n }\n\n // When auto line-height (hhea-based) is smaller than the font content\n // area, the last line's glyph descent extends below totalHeight. Add the\n // overflow so the Yoga node height accommodates the full rendered text,\n // preventing descender clipping with overflow: hidden.\n if (\n isAutoLineHeight &&\n lastPositioningDescent !== undefined &&\n segments.length > 0\n ) {\n const lastSeg = segments[segments.length - 1]!;\n const descentOverflow = lastSeg.y + lastPositioningDescent - totalHeight;\n if (descentOverflow > 0) {\n totalHeight += descentOverflow;\n }\n // Round up so Yoga's integer rounding (pointScaleFactor=1) never clips\n // the descent. Without this, a fractional totalHeight like 15.52 can\n // round to 15, cutting off glyphs whose descent reaches 15.52.\n totalHeight = Math.ceil(totalHeight);\n }\n\n // Apply text-box-trim\n const textBoxTrim = style.textBoxTrim;\n if (textBoxTrim && textBoxTrim !== \"none\" && segments.length > 0) {\n const textBoxEdge = style.textBoxEdge ?? \"text\";\n const trimMetrics = measureTrimMetrics(\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n lineHeightPx,\n textBoxEdge,\n ctx,\n fontMetrics,\n );\n\n if (textBoxTrim === \"trim-start\" || textBoxTrim === \"trim-both\") {\n for (const seg of segments) {\n seg.y -= trimMetrics.overTrim;\n }\n totalHeight -= trimMetrics.overTrim;\n }\n\n if (textBoxTrim === \"trim-end\" || textBoxTrim === \"trim-both\") {\n totalHeight -= trimMetrics.underTrim;\n }\n }\n\n return {\n segments,\n width: maxLineWidth,\n height: totalHeight,\n };\n}\n\nfunction resolveTextStrokeWidth(\n style: ComputedStyle,\n fontSize: number,\n): number | undefined {\n const raw = style.WebkitTextStrokeWidth;\n if (raw === undefined) return undefined;\n if (typeof raw === \"number\") return raw;\n const resolved = resolveUnit(String(raw), 0, 0, fontSize, 16);\n return typeof resolved === \"number\" ? resolved : undefined;\n}\n\nfunction applyTextTransform(text: string, style: ComputedStyle): string {\n if (style.textTransform === \"uppercase\") return text.toUpperCase();\n if (style.textTransform === \"lowercase\") return text.toLowerCase();\n if (style.textTransform === \"capitalize\") {\n return text.replace(/\\b\\w/g, (c) => c.toUpperCase());\n }\n return text;\n}\n\nfunction resolveLineHeight(\n lineHeight: number | string | undefined,\n fontSize: number,\n canvasMetrics?: TextMetrics,\n fontMetrics?: FontMetrics | null,\n): number {\n if (lineHeight === undefined || lineHeight === \"normal\") {\n if (fontMetrics) {\n const px = fontMetricsToPx(fontMetrics, fontSize);\n return px.ascent + px.descent;\n }\n // Fallback to canvas metrics (fontBoundingBox ascent + descent)\n return canvasMetrics\n ? canvasMetrics.ascent + canvasMetrics.descent\n : fontSize * 1.2;\n }\n if (typeof lineHeight === \"number\") {\n // Already resolved to px in compute.ts if > 5, else multiplier\n return lineHeight > 5 ? lineHeight : lineHeight * fontSize;\n }\n const parsed = parseFloat(String(lineHeight));\n return isNaN(parsed) ? fontSize * 1.2 : parsed;\n}\n\nfunction wrapText(\n text: string,\n maxWidth: number,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n letterSpacing: number,\n wordBreak: string,\n ctx?: SKRSContext2D,\n measureFn?: (word: string, ls?: number) => number,\n): string[] {\n if (!text) return [\"\"];\n\n const mw =\n measureFn ??\n ((word: string) =>\n measureWord(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n ));\n\n const breakOpps = findBreakOpportunities(text);\n const lines: string[] = [];\n let lineStart = 0;\n let lastBreak = 0;\n\n for (const opp of breakOpps) {\n // Trailing whitespace hangs (as in CSS): it doesn't count toward whether\n // the line fits. Break positions sit after the space, so trim it here.\n const segment = text.slice(lineStart, opp.position).replace(/\\s+$/, \"\");\n const segWidth = mw(segment);\n\n if (segWidth > maxWidth && lastBreak > lineStart) {\n // Line overflows — break at last opportunity\n const line = text.slice(lineStart, lastBreak).replace(/\\s+$/, \"\");\n lines.push(line);\n lineStart = lastBreak;\n } else if (segWidth > maxWidth && wordBreak === \"break-all\") {\n // Force break within word\n const broken = forceBreakWord(\n text,\n lineStart,\n opp.position,\n maxWidth,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n measureFn,\n );\n lines.push(...broken.lines);\n lineStart = broken.endPos;\n }\n\n if (opp.required) {\n // Hard break (newline)\n const line = text.slice(lineStart, opp.position).replace(/\\s+$/, \"\");\n lines.push(line);\n lineStart = opp.position;\n }\n\n lastBreak = opp.position;\n }\n\n // Remaining text\n if (lineStart < text.length) {\n const remaining = text.slice(lineStart).replace(/\\s+$/, \"\");\n if (remaining) {\n const remWidth = mw(remaining);\n if (remWidth > maxWidth && wordBreak === \"break-all\") {\n const broken = forceBreakWord(\n text,\n lineStart,\n text.length,\n maxWidth,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n measureFn,\n );\n lines.push(...broken.lines);\n } else {\n lines.push(remaining);\n }\n }\n }\n\n return lines.length > 0 ? lines : [\"\"];\n}\n\nfunction forceBreakWord(\n text: string,\n start: number,\n end: number,\n maxWidth: number,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n ctx?: SKRSContext2D,\n letterSpacing: number = 0,\n measureFn?: (word: string, ls?: number) => number,\n): { lines: string[]; endPos: number } {\n const mw =\n measureFn ??\n ((word: string) =>\n measureWord(\n word,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n ));\n const lines: string[] = [];\n let pos = start;\n\n while (pos < end) {\n let breakPos = pos + 1;\n while (breakPos < end) {\n const chunk = text.slice(pos, breakPos + 1);\n const w = mw(chunk);\n if (w > maxWidth) break;\n breakPos++;\n }\n\n const line = text.slice(pos, breakPos);\n if (line.trim()) lines.push(line);\n pos = breakPos;\n }\n\n return { lines, endPos: end };\n}\n\nfunction truncateWithEllipsis(\n text: string,\n maxWidth: number,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n ctx?: SKRSContext2D,\n letterSpacing: number = 0,\n): string {\n const ellipsis = \"\\u2026\";\n const ellipsisWidth = measureWord(\n ellipsis,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n const availWidth = maxWidth - ellipsisWidth;\n\n for (let i = text.length; i > 0; i--) {\n const truncated = text.slice(0, i);\n const w = measureWord(\n truncated,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n ctx,\n letterSpacing,\n );\n if (w <= availWidth) {\n return truncated + ellipsis;\n }\n }\n\n return ellipsis;\n}\n\n/**\n * Yoga-compatible measure function for text nodes.\n * Returns the dimensions needed for the text content.\n */\nexport function createTextMeasureFunc(\n text: string,\n style: ComputedStyle,\n ctx?: SKRSContext2D,\n emojiEnabled?: boolean,\n) {\n // Strip textOverflow during measurement so ellipsis truncation doesn't\n // shrink the reported width below the Yoga constraint. The draw phase\n // still uses the original style (with textOverflow) for rendering.\n const measureStyle = { ...style, textOverflow: \"clip\" as const };\n return (\n width: number,\n _widthMode: number,\n _height: number,\n _heightMode: number,\n ) => {\n const maxWidth = width > 0 ? width : Infinity;\n const result = layoutText(text, measureStyle, maxWidth, ctx, emojiEnabled);\n // When text wraps to multiple lines, return the constraint width (like CSS\n // block layout). This ensures the draw phase re-layout gets the same\n // maxWidth and produces identical line-breaking.\n const wrapped = result.segments.length > 1;\n const reportedWidth = wrapped\n ? Math.min(maxWidth, width > 0 ? width : result.width)\n : result.width;\n return { width: Math.min(reportedWidth, maxWidth), height: result.height };\n };\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\n\n/**\n * Apply overflow:hidden clipping to a canvas context.\n * Creates a rectangular clip path with optional border-radius.\n */\nexport function applyClip(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n borderRadius?: {\n topLeft: number;\n topRight: number;\n bottomRight: number;\n bottomLeft: number;\n },\n): void {\n ctx.beginPath();\n\n if (borderRadius && hasRadius(borderRadius)) {\n const { topLeft, topRight, bottomRight, bottomLeft } = borderRadius;\n roundedRect(\n ctx,\n x,\n y,\n width,\n height,\n topLeft,\n topRight,\n bottomRight,\n bottomLeft,\n );\n } else {\n ctx.rect(x, y, width, height);\n }\n\n ctx.clip();\n}\n\n/**\n * Draw a rounded rectangle path on the context.\n */\nexport function roundedRect(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n w: number,\n h: number,\n tl: number,\n tr: number,\n br: number,\n bl: number,\n): void {\n const maxR = maxCornerRadius(w, h);\n tl = Math.min(tl, maxR);\n tr = Math.min(tr, maxR);\n br = Math.min(br, maxR);\n bl = Math.min(bl, maxR);\n\n ctx.moveTo(x + tl, y);\n ctx.lineTo(x + w - tr, y);\n if (tr > 0) ctx.arcTo(x + w, y, x + w, y + tr, tr);\n ctx.lineTo(x + w, y + h - br);\n if (br > 0) ctx.arcTo(x + w, y + h, x + w - br, y + h, br);\n ctx.lineTo(x + bl, y + h);\n if (bl > 0) ctx.arcTo(x, y + h, x, y + h - bl, bl);\n ctx.lineTo(x, y + tl);\n if (tl > 0) ctx.arcTo(x, y, x + tl, y, tl);\n ctx.closePath();\n}\n\n/**\n * The largest corner radius a `w` × `h` box is drawn with: every radius is\n * clamped to half the shorter side. Anything that needs to line up with the\n * element's painted corners (`clip-path` geometry boxes, overflow clips) must\n * apply the same clamp.\n */\nexport function maxCornerRadius(w: number, h: number): number {\n return Math.min(w, h) / 2;\n}\n\nexport function hasRadius(r: {\n topLeft: number;\n topRight: number;\n bottomRight: number;\n bottomLeft: number;\n}): boolean {\n return (\n r.topLeft > 0 || r.topRight > 0 || r.bottomRight > 0 || r.bottomLeft > 0\n );\n}\n","import { Path2D } from \"@effing/skia\";\nimport type { SKRSContext2D } from \"@effing/skia\";\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { maxCornerRadius } from \"./clip.ts\";\nimport { getBorderRadiusFromStyle } from \"./rect.ts\";\nimport { parseCSSLength, resolveBoxValue } from \"./utils.ts\";\n\n/**\n * CSS `clip-path` support: basic shapes (`inset()`, `circle()`, `ellipse()`,\n * `polygon()`, `path()`, `rect()`, `xywh()`), the newer `shape()` function and\n * an optional geometry box (`border-box`, `padding-box`, `content-box`,\n * `margin-box`). Lengths other than `%` are already resolved to pixels by the\n * style pipeline; percentages resolve against the reference box here.\n *\n * `url(#id)` references and `calc()` are not supported — an unrecognised value\n * leaves the element unclipped, matching how a browser drops an invalid\n * declaration.\n */\n\nexport type FillRule = \"nonzero\" | \"evenodd\";\n\ntype Point = [number, number];\n\n/** Per-corner elliptical radii, in the order tl, tr, br, bl. */\nexport type CornerRadii = [Point, Point, Point, Point];\n\nexport type ReferenceBox = {\n x: number;\n y: number;\n width: number;\n height: number;\n};\n\n/**\n * A resolved clip shape in absolute canvas coordinates.\n */\nexport type ClipShape =\n | { kind: \"none\" }\n | {\n kind: \"rect\";\n x: number;\n y: number;\n width: number;\n height: number;\n radii: CornerRadii | null;\n }\n | { kind: \"circle\"; cx: number; cy: number; r: number }\n | { kind: \"ellipse\"; cx: number; cy: number; rx: number; ry: number }\n | { kind: \"polygon\"; points: Point[]; fillRule: FillRule }\n | { kind: \"path\"; d: string; dx: number; dy: number; fillRule: FillRule };\n\nconst GEOMETRY_BOXES = new Set([\n \"border-box\",\n \"padding-box\",\n \"content-box\",\n \"margin-box\",\n \"fill-box\",\n \"stroke-box\",\n \"view-box\",\n]);\n\nconst H_KEYWORDS = new Map<string, number>([\n [\"left\", 0],\n [\"x-start\", 0],\n [\"center\", 0.5],\n [\"right\", 1],\n [\"x-end\", 1],\n]);\n\nconst V_KEYWORDS = new Map<string, number>([\n [\"top\", 0],\n [\"y-start\", 0],\n [\"center\", 0.5],\n [\"bottom\", 1],\n [\"y-end\", 1],\n]);\n\nconst ARC_OPTIONS = new Set([\"of\", \"cw\", \"ccw\", \"large\", \"small\", \"rotate\"]);\n\n/**\n * Clip the context to the element's `clip-path`. Must be called after the\n * element's transform has been applied (clip-path lives in the element's own\n * coordinate space) and before anything of the element is painted — box-shadow\n * included, since clip-path clips the element's entire rendering.\n */\nexport function applyClipPath(\n ctx: SKRSContext2D,\n clipPath: string,\n style: ComputedStyle,\n x: number,\n y: number,\n width: number,\n height: number,\n): void {\n const shape = parseClipPath(clipPath, style, { x, y, width, height });\n if (!shape || shape.kind === \"none\") return;\n const path = clipShapeToPath(shape);\n if (path) ctx.clip(path, shapeFillRule(shape));\n}\n\nfunction shapeFillRule(shape: ClipShape): FillRule {\n return shape.kind === \"polygon\" || shape.kind === \"path\"\n ? shape.fillRule\n : \"nonzero\";\n}\n\n/**\n * Parse a `clip-path` value into a resolved shape in absolute coordinates.\n * `box` is the element's border box; `style` supplies the border, padding and\n * margin widths used for the other geometry boxes. Returns `null` for values\n * that can't be parsed.\n */\nexport function parseClipPath(\n value: string,\n style: ComputedStyle,\n box: ReferenceBox,\n): ClipShape | null {\n const trimmed = value.trim();\n if (trimmed === \"none\") return { kind: \"none\" };\n\n // Split into an optional shape function and an optional geometry box, in\n // either order: `circle(50%) padding-box` or `padding-box circle(50%)`.\n let fn: { name: string; args: string } | null = null;\n let geometryBox = \"border-box\";\n const fnMatch = trimmed.match(/^(.*?)([a-z]+)\\((.*)\\)(.*)$/s);\n let keywords: string[];\n if (fnMatch) {\n fn = { name: fnMatch[2]!, args: fnMatch[3]! };\n keywords = [fnMatch[1]!, fnMatch[4]!]\n .join(\" \")\n .split(/\\s+/)\n .filter(Boolean);\n } else {\n keywords = trimmed.split(/\\s+/).filter(Boolean);\n }\n for (const kw of keywords) {\n if (!GEOMETRY_BOXES.has(kw)) return null;\n geometryBox = kw;\n }\n if (!fn && keywords.length === 0) return null;\n\n const ref = resolveReferenceBox(geometryBox, style, box);\n const { width: w, height: h } = ref;\n\n if (!fn) {\n // A bare geometry box clips to that box, following the border radius\n // (reduced by the border/padding widths for the inner boxes).\n return {\n kind: \"rect\",\n x: ref.x,\n y: ref.y,\n width: w,\n height: h,\n radii: referenceBoxRadii(geometryBox, style, box, ref),\n };\n }\n\n switch (fn.name) {\n case \"inset\":\n return parseInset(fn.args, ref);\n case \"rect\":\n return parseRect(fn.args, ref);\n case \"xywh\":\n return parseXywh(fn.args, ref);\n case \"circle\":\n return parseCircle(fn.args, ref);\n case \"ellipse\":\n return parseEllipse(fn.args, ref);\n case \"polygon\":\n return parsePolygon(fn.args, ref);\n case \"path\":\n return parsePath(fn.args, ref);\n case \"shape\":\n return parseShape(fn.args, ref);\n default:\n return null;\n }\n}\n\n/**\n * Build a `Path2D` for a resolved clip shape. Returns `null` when the shape\n * is a `path()` whose data Skia cannot parse — treated like an invalid\n * declaration (the element is left unclipped) rather than a render failure.\n */\nexport function clipShapeToPath(shape: ClipShape): Path2D | null {\n const p = new Path2D();\n switch (shape.kind) {\n case \"none\":\n break;\n case \"rect\":\n if (shape.radii && shape.width > 0 && shape.height > 0) {\n roundedRectPath(\n p,\n shape.x,\n shape.y,\n shape.width,\n shape.height,\n shape.radii,\n );\n } else {\n p.rect(\n shape.x,\n shape.y,\n Math.max(0, shape.width),\n Math.max(0, shape.height),\n );\n }\n break;\n case \"circle\":\n if (shape.r > 0) p.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2);\n break;\n case \"ellipse\":\n if (shape.rx > 0 && shape.ry > 0) {\n p.ellipse(shape.cx, shape.cy, shape.rx, shape.ry, 0, 0, Math.PI * 2);\n }\n break;\n case \"polygon\":\n if (shape.points.length >= 3) {\n const [first, ...rest] = shape.points;\n p.moveTo(first![0], first![1]);\n for (const [px, py] of rest) p.lineTo(px, py);\n p.closePath();\n }\n break;\n case \"path\": {\n let inner: Path2D;\n try {\n inner = new Path2D(shape.d);\n } catch {\n return null;\n }\n if (shape.dx === 0 && shape.dy === 0) return inner;\n p.addPath(inner, { a: 1, b: 0, c: 0, d: 1, e: shape.dx, f: shape.dy });\n break;\n }\n }\n return p;\n}\n\n// ---------------------------------------------------------------------------\n// Reference boxes\n// ---------------------------------------------------------------------------\n\nfunction resolveReferenceBox(\n geometryBox: string,\n style: ComputedStyle,\n box: ReferenceBox,\n): ReferenceBox {\n const { x, y, width, height } = box;\n switch (geometryBox) {\n case \"padding-box\": {\n const t = resolveBoxValue(style.borderTopWidth, width);\n const r = resolveBoxValue(style.borderRightWidth, width);\n const b = resolveBoxValue(style.borderBottomWidth, width);\n const l = resolveBoxValue(style.borderLeftWidth, width);\n return {\n x: x + l,\n y: y + t,\n width: width - l - r,\n height: height - t - b,\n };\n }\n case \"content-box\": {\n const t =\n resolveBoxValue(style.borderTopWidth, width) +\n resolveBoxValue(style.paddingTop, width);\n const r =\n resolveBoxValue(style.borderRightWidth, width) +\n resolveBoxValue(style.paddingRight, width);\n const b =\n resolveBoxValue(style.borderBottomWidth, width) +\n resolveBoxValue(style.paddingBottom, width);\n const l =\n resolveBoxValue(style.borderLeftWidth, width) +\n resolveBoxValue(style.paddingLeft, width);\n return {\n x: x + l,\n y: y + t,\n width: width - l - r,\n height: height - t - b,\n };\n }\n case \"margin-box\": {\n const t = marginValue(style.marginTop, width);\n const r = marginValue(style.marginRight, width);\n const b = marginValue(style.marginBottom, width);\n const l = marginValue(style.marginLeft, width);\n return {\n x: x - l,\n y: y - t,\n width: width + l + r,\n height: height + t + b,\n };\n }\n default:\n return box;\n }\n}\n\nfunction marginValue(v: unknown, referenceWidth: number): number {\n if (v === \"auto\") return 0;\n return resolveBoxValue(v, referenceWidth);\n}\n\n/**\n * Border radii of a geometry box: the element's border-radius for the border\n * box (and margin box, grown by the margin), reduced by the border and padding\n * widths for the inner boxes. Returns `null` when every corner is square.\n *\n * The base radii are clamped the way the element's own corners are painted\n * (see `maxCornerRadius`) so a bare `border-box` clip traces exactly the\n * painted rounded corner instead of a different arc.\n */\nfunction referenceBoxRadii(\n geometryBox: string,\n style: ComputedStyle,\n box: ReferenceBox,\n ref: ReferenceBox,\n): CornerRadii | null {\n const br = getBorderRadiusFromStyle(style, box.width, box.height);\n const maxR = maxCornerRadius(box.width, box.height);\n const base = [br.topLeft, br.topRight, br.bottomRight, br.bottomLeft].map(\n (r) => Math.min(Math.max(0, r), maxR),\n ) as [number, number, number, number];\n if (base.every((r) => r <= 0)) return null;\n\n // Horizontal / vertical insets from the border box to the reference box, per\n // corner: (left, top), (right, top), (right, bottom), (left, bottom).\n const left = ref.x - box.x;\n const top = ref.y - box.y;\n const right = box.x + box.width - (ref.x + ref.width);\n const bottom = box.y + box.height - (ref.y + ref.height);\n const insets: [Point, Point, Point, Point] = [\n [left, top],\n [right, top],\n [right, bottom],\n [left, bottom],\n ];\n\n const radii = base.map((r, i) => {\n const [ix, iy] = insets[i]!;\n return [adjustRadius(r, ix), adjustRadius(r, iy)] as Point;\n }) as CornerRadii;\n if (radii.every(([rx, ry]) => rx <= 0 || ry <= 0)) return null;\n return normalizeRadii(radii, ref.width, ref.height);\n}\n\n/**\n * Move a border radius inward by `inset` (CSS Backgrounds: the inner radius\n * is the outer one minus the border, floored at zero) or, for a negative\n * inset, outward (CSS Shapes `margin-box`: a square corner stays square, a\n * radius `r >= m` grows to `r + m`, and a smaller one is eased between the\n * two so the corner keeps its shape).\n */\nfunction adjustRadius(r: number, inset: number): number {\n if (inset >= 0) return Math.max(0, r - inset);\n if (r <= 0) return 0;\n const m = -inset;\n if (r >= m) return r + m;\n const ratio = r / m - 1;\n return r + m * (1 + ratio * ratio * ratio);\n}\n\n// ---------------------------------------------------------------------------\n// Basic shapes\n// ---------------------------------------------------------------------------\n\nfunction parseInset(args: string, ref: ReferenceBox): ClipShape | null {\n const [insetPart, roundPart] = splitRound(args);\n const values = tokenize(insetPart);\n if (values.length < 1 || values.length > 4) return null;\n const [t, r, b, l] = expandSides(values);\n const top = parseCSSLength(t, ref.height);\n const right = parseCSSLength(r, ref.width);\n const bottom = parseCSSLength(b, ref.height);\n const left = parseCSSLength(l, ref.width);\n if ([top, right, bottom, left].some(isNaN)) return null;\n return makeRect(\n ref.x + left,\n ref.y + top,\n ref.width - left - right,\n ref.height - top - bottom,\n roundPart,\n ref,\n );\n}\n\nfunction parseRect(args: string, ref: ReferenceBox): ClipShape | null {\n const [rectPart, roundPart] = splitRound(args);\n const values = tokenize(rectPart);\n if (values.length !== 4) return null;\n const [t, r, b, l] = values as [string, string, string, string];\n const top = t === \"auto\" ? 0 : parseCSSLength(t, ref.height);\n const right = r === \"auto\" ? ref.width : parseCSSLength(r, ref.width);\n const bottom = b === \"auto\" ? ref.height : parseCSSLength(b, ref.height);\n const left = l === \"auto\" ? 0 : parseCSSLength(l, ref.width);\n if ([top, right, bottom, left].some(isNaN)) return null;\n // Per spec, right/bottom are clamped so they never precede left/top.\n const x2 = Math.max(left, right);\n const y2 = Math.max(top, bottom);\n return makeRect(\n ref.x + left,\n ref.y + top,\n x2 - left,\n y2 - top,\n roundPart,\n ref,\n );\n}\n\nfunction parseXywh(args: string, ref: ReferenceBox): ClipShape | null {\n const [xywhPart, roundPart] = splitRound(args);\n const values = tokenize(xywhPart);\n if (values.length !== 4) return null;\n const [xs, ys, ws, hs] = values as [string, string, string, string];\n const x = parseCSSLength(xs, ref.width);\n const y = parseCSSLength(ys, ref.height);\n const w = parseCSSLength(ws, ref.width);\n const h = parseCSSLength(hs, ref.height);\n if ([x, y, w, h].some(isNaN)) return null;\n return makeRect(\n ref.x + x,\n ref.y + y,\n Math.max(0, w),\n Math.max(0, h),\n roundPart,\n ref,\n );\n}\n\n/**\n * Build a rect shape with optional `round` radii. Percentage radii resolve\n * against the reference box (CSS Shapes 1 §3), not the rectangle itself.\n */\nfunction makeRect(\n x: number,\n y: number,\n width: number,\n height: number,\n roundPart: string | undefined,\n ref: ReferenceBox,\n): ClipShape | null {\n const w = Math.max(0, width);\n const h = Math.max(0, height);\n let radii: CornerRadii | null = null;\n if (roundPart !== undefined) {\n const parsed = parseRadii(roundPart, ref.width, ref.height, w, h);\n if (parsed === undefined) return null;\n radii = parsed;\n }\n return { kind: \"rect\", x, y, width: w, height: h, radii };\n}\n\nfunction parseCircle(args: string, ref: ReferenceBox): ClipShape | null {\n const [radiusPart, posPart] = splitAt(args);\n const radiusTokens = tokenize(radiusPart);\n if (radiusTokens.length > 1) return null;\n const pos = resolvePosition(tokenize(posPart ?? \"\"), ref.width, ref.height);\n if (!pos) return null;\n const [cx, cy] = pos;\n const closest = Math.min(cx, cy, ref.width - cx, ref.height - cy);\n const farthest = Math.max(cx, cy, ref.width - cx, ref.height - cy);\n const percentBase = Math.hypot(ref.width, ref.height) / Math.SQRT2;\n const r = resolveRadius(radiusTokens[0], closest, farthest, percentBase);\n if (r === undefined) return null;\n return { kind: \"circle\", cx: ref.x + cx, cy: ref.y + cy, r: Math.max(0, r) };\n}\n\nfunction parseEllipse(args: string, ref: ReferenceBox): ClipShape | null {\n const [radiusPart, posPart] = splitAt(args);\n const radiusTokens = tokenize(radiusPart);\n if (radiusTokens.length !== 0 && radiusTokens.length !== 2) return null;\n const pos = resolvePosition(tokenize(posPart ?? \"\"), ref.width, ref.height);\n if (!pos) return null;\n const [cx, cy] = pos;\n const rx = resolveRadius(\n radiusTokens[0],\n Math.min(cx, ref.width - cx),\n Math.max(cx, ref.width - cx),\n ref.width,\n );\n const ry = resolveRadius(\n radiusTokens[1],\n Math.min(cy, ref.height - cy),\n Math.max(cy, ref.height - cy),\n ref.height,\n );\n if (rx === undefined || ry === undefined) return null;\n return {\n kind: \"ellipse\",\n cx: ref.x + cx,\n cy: ref.y + cy,\n rx: Math.max(0, rx),\n ry: Math.max(0, ry),\n };\n}\n\nfunction parsePolygon(args: string, ref: ReferenceBox): ClipShape | null {\n const parts = splitArgs(args);\n let fillRule: FillRule = \"nonzero\";\n const first = parts[0]?.trim();\n if (first === \"nonzero\" || first === \"evenodd\") {\n fillRule = first;\n parts.shift();\n }\n const points: Point[] = [];\n for (const part of parts) {\n const pair = tokenize(part);\n if (pair.length !== 2) return null;\n const px = parseCSSLength(pair[0]!, ref.width);\n const py = parseCSSLength(pair[1]!, ref.height);\n if (isNaN(px) || isNaN(py)) return null;\n points.push([ref.x + px, ref.y + py]);\n }\n if (points.length === 0) return null;\n return { kind: \"polygon\", points, fillRule };\n}\n\nfunction parsePath(args: string, ref: ReferenceBox): ClipShape | null {\n const parts = splitArgs(args);\n let fillRule: FillRule = \"nonzero\";\n const first = parts[0]?.trim();\n if (first === \"nonzero\" || first === \"evenodd\") {\n fillRule = first;\n parts.shift();\n }\n if (parts.length !== 1) return null;\n const d = unquote(parts[0]!.trim());\n if (!d) return null;\n return { kind: \"path\", d, dx: ref.x, dy: ref.y, fillRule };\n}\n\n// ---------------------------------------------------------------------------\n// shape()\n// ---------------------------------------------------------------------------\n\n/**\n * Parse the `shape()` function into SVG path data. Coordinates are resolved\n * against the reference box; the resulting path is positioned at the box\n * origin via `dx`/`dy`.\n *\n * Grammar (CSS Shapes 2): `shape([<fill-rule>]? from <x> <y>, <command>#)`\n * with commands `move`, `line`, `hline`, `vline`, `curve`, `smooth`, `arc`\n * and `close`, each using `to` (absolute) or `by` (relative to the current\n * point).\n */\nfunction parseShape(args: string, ref: ReferenceBox): ClipShape | null {\n const { width: w, height: h } = ref;\n const parts = splitArgs(args);\n const first = parts.shift()?.trim();\n if (!first) return null;\n\n const startMatch = first.match(/^(?:(nonzero|evenodd)\\s+)?from\\s+(.+)$/s);\n if (!startMatch) return null;\n const fillRule = (startMatch[1] ?? \"nonzero\") as FillRule;\n\n let current = resolvePoint(tokenize(startMatch[2]!), w, h);\n if (!current) return null;\n let subpathStart = current;\n let d = `M${fmtPoint(current)}`;\n\n for (const part of parts) {\n const tokens = tokenize(part);\n const command = tokens.shift();\n\n switch (command) {\n case \"close\": {\n if (tokens.length) return null;\n d += \" Z\";\n current = subpathStart;\n break;\n }\n case \"move\":\n case \"line\": {\n const end = resolveEndpoint(tokens, current, w, h);\n if (!end) return null;\n d += ` ${command === \"move\" ? \"M\" : \"L\"}${fmtPoint(end)}`;\n current = end;\n if (command === \"move\") subpathStart = end;\n break;\n }\n case \"hline\":\n case \"vline\": {\n const [mode, token, ...rest] = tokens;\n if ((mode !== \"to\" && mode !== \"by\") || !token || rest.length) {\n return null;\n }\n const axis = command === \"hline\" ? 0 : 1;\n const base = axis === 0 ? w : h;\n const keywords = axis === 0 ? H_KEYWORDS : V_KEYWORDS;\n const kw = keywords.get(token);\n const resolved =\n mode === \"to\" && kw !== undefined\n ? kw * base\n : parseCSSLength(token, base);\n if (isNaN(resolved)) return null;\n const next: Point = [current[0], current[1]];\n next[axis] = mode === \"by\" ? current[axis] + resolved : resolved;\n d += axis === 0 ? ` H${fmt(next[0])}` : ` V${fmt(next[1])}`;\n current = next;\n break;\n }\n case \"curve\":\n case \"smooth\": {\n const withIndex = tokens.indexOf(\"with\");\n const endTokens =\n withIndex === -1 ? tokens : tokens.slice(0, withIndex);\n const controlTokens =\n withIndex === -1 ? [] : tokens.slice(withIndex + 1);\n const mode = endTokens[0];\n const end = resolveEndpoint(endTokens, current, w, h);\n if (!end) return null;\n if (command === \"curve\" && withIndex === -1) return null;\n\n const controls: Point[] = [];\n for (const control of splitAtSlash(controlTokens)) {\n const point = resolveControlPoint(control, mode, current, end, w, h);\n if (!point) return null;\n controls.push(point);\n }\n\n if (command === \"curve\") {\n if (controls.length === 1) {\n d += ` Q${fmtPoint(controls[0]!)} ${fmtPoint(end)}`;\n } else if (controls.length === 2) {\n d += ` C${fmtPoint(controls[0]!)} ${fmtPoint(controls[1]!)} ${fmtPoint(end)}`;\n } else {\n return null;\n }\n } else if (controls.length === 0) {\n d += ` T${fmtPoint(end)}`;\n } else if (controls.length === 1) {\n d += ` S${fmtPoint(controls[0]!)} ${fmtPoint(end)}`;\n } else {\n return null;\n }\n current = end;\n break;\n }\n case \"arc\": {\n const optionIndex = tokens.findIndex((t) => ARC_OPTIONS.has(t));\n const endTokens =\n optionIndex === -1 ? tokens : tokens.slice(0, optionIndex);\n const options = optionIndex === -1 ? [] : tokens.slice(optionIndex);\n const end = resolveEndpoint(endTokens, current, w, h);\n if (!end) return null;\n\n let rx = 0;\n let ry = 0;\n let rotation = 0;\n let large = 0;\n let sweep = 0;\n for (let i = 0; i < options.length; i++) {\n const option = options[i]!;\n if (option === \"of\") {\n const r1 = options[++i];\n if (!r1) return null;\n const r2 = options[i + 1];\n const hasSecond = r2 !== undefined && !ARC_OPTIONS.has(r2);\n if (hasSecond) {\n i++;\n rx = parseCSSLength(r1, w);\n ry = parseCSSLength(r2!, h);\n } else {\n rx = ry = parseCSSLength(r1, Math.hypot(w, h) / Math.SQRT2);\n }\n if (isNaN(rx) || isNaN(ry)) return null;\n } else if (option === \"cw\" || option === \"ccw\") {\n sweep = option === \"cw\" ? 1 : 0;\n } else if (option === \"large\" || option === \"small\") {\n large = option === \"large\" ? 1 : 0;\n } else if (option === \"rotate\") {\n const angle = options[++i];\n if (!angle) return null;\n rotation = parseAngleDegrees(angle);\n if (isNaN(rotation)) return null;\n } else {\n return null;\n }\n }\n d += ` A${fmt(Math.abs(rx))} ${fmt(Math.abs(ry))} ${fmt(rotation)} ${large} ${sweep} ${fmtPoint(end)}`;\n current = end;\n break;\n }\n default:\n return null;\n }\n }\n\n return { kind: \"path\", d, dx: ref.x, dy: ref.y, fillRule };\n}\n\nfunction resolveEndpoint(\n tokens: string[],\n current: Point,\n w: number,\n h: number,\n): Point | null {\n const mode = tokens[0];\n if (mode !== \"to\" && mode !== \"by\") return null;\n const point = resolvePoint(tokens.slice(1), w, h);\n if (!point) return null;\n return mode === \"by\" ? [current[0] + point[0], current[1] + point[1]] : point;\n}\n\n/**\n * A control point: `<x> <y> [from start | end | origin]?`. Without `from`,\n * `by` commands measure from the segment start and `to` commands from the\n * reference box origin.\n */\nfunction resolveControlPoint(\n tokens: string[],\n mode: string | undefined,\n start: Point,\n end: Point,\n w: number,\n h: number,\n): Point | null {\n let origin: \"start\" | \"end\" | \"origin\" = mode === \"by\" ? \"start\" : \"origin\";\n let coords = tokens;\n const fromIndex = tokens.indexOf(\"from\");\n if (fromIndex !== -1) {\n const ref = tokens[fromIndex + 1];\n if (\n (ref !== \"start\" && ref !== \"end\" && ref !== \"origin\") ||\n tokens.length !== fromIndex + 2\n ) {\n return null;\n }\n origin = ref;\n coords = tokens.slice(0, fromIndex);\n }\n const point = resolvePoint(coords, w, h);\n if (!point) return null;\n const base: Point =\n origin === \"start\" ? start : origin === \"end\" ? end : [0, 0];\n return [base[0] + point[0], base[1] + point[1]];\n}\n\n/** Resolve a `<coordinate-pair>` (lengths, percentages or position keywords). */\nfunction resolvePoint(tokens: string[], w: number, h: number): Point | null {\n if (tokens.length !== 2) return null;\n const x = resolveAxis(tokens[0]!, w, H_KEYWORDS);\n const y = resolveAxis(tokens[1]!, h, V_KEYWORDS);\n if (isNaN(x) || isNaN(y)) return null;\n return [x, y];\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a CSS `<position>` (as used after `at`) to a point relative to the\n * reference box. Defaults to the center.\n */\nfunction resolvePosition(tokens: string[], w: number, h: number): Point | null {\n if (tokens.length === 0) return [w / 2, h / 2];\n\n if (tokens.length === 1) {\n const t = tokens[0]!;\n if (V_KEYWORDS.has(t) && !H_KEYWORDS.has(t)) {\n return [w / 2, V_KEYWORDS.get(t)! * h];\n }\n const x = resolveAxis(t, w, H_KEYWORDS);\n return isNaN(x) ? null : [x, h / 2];\n }\n\n if (tokens.length === 2) {\n let [a, b] = tokens as [string, string];\n // Two keywords may come in either order (\"top left\" == \"left top\"); with\n // a length in the pair the order is fixed, so \"top 30px\" is invalid and\n // falls through to the NaN check below.\n const bothKeywords =\n (H_KEYWORDS.has(a) || V_KEYWORDS.has(a)) &&\n (H_KEYWORDS.has(b) || V_KEYWORDS.has(b));\n if (\n bothKeywords &&\n ((V_KEYWORDS.has(a) && !H_KEYWORDS.has(a)) ||\n (H_KEYWORDS.has(b) && !V_KEYWORDS.has(b)))\n ) {\n [a, b] = [b, a];\n }\n const x = resolveAxis(a, w, H_KEYWORDS);\n const y = resolveAxis(b, h, V_KEYWORDS);\n return isNaN(x) || isNaN(y) ? null : [x, y];\n }\n\n // 3–4 tokens: edge keywords with optional offsets, e.g. \"right 10px bottom 20px\".\n let x = w / 2;\n let y = h / 2;\n for (let i = 0; i < tokens.length; i++) {\n const t = tokens[i]!;\n const next = tokens[i + 1];\n const hasOffset =\n next !== undefined && !H_KEYWORDS.has(next) && !V_KEYWORDS.has(next);\n if (t === \"left\" || t === \"right\") {\n const off = hasOffset ? parseCSSLength(next!, w) : 0;\n if (isNaN(off)) return null;\n x = t === \"left\" ? off : w - off;\n } else if (t === \"top\" || t === \"bottom\") {\n const off = hasOffset ? parseCSSLength(next!, h) : 0;\n if (isNaN(off)) return null;\n y = t === \"top\" ? off : h - off;\n } else if (t !== \"center\") {\n return null;\n }\n if (hasOffset) i++;\n }\n return [x, y];\n}\n\nfunction resolveAxis(\n token: string,\n size: number,\n keywords: Map<string, number>,\n): number {\n const kw = keywords.get(token);\n if (kw !== undefined) return kw * size;\n return parseCSSLength(token, size);\n}\n\nfunction resolveRadius(\n token: string | undefined,\n closestSide: number,\n farthestSide: number,\n percentBase: number,\n): number | undefined {\n if (token === undefined || token === \"closest-side\") return closestSide;\n if (token === \"farthest-side\") return farthestSide;\n const r = parseCSSLength(token, percentBase);\n return isNaN(r) ? undefined : r;\n}\n\n/**\n * Parse `border-radius`-style radii (`r1 r2 r3 r4 / v1 v2 v3 v4`) into\n * per-corner elliptical radii. Percentages resolve against `refW` × `refH`;\n * the result is scaled down per the CSS overlap rule for a `w` × `h` box.\n * Returns `undefined` for unparsable input and `null` when all corners are\n * square.\n */\nfunction parseRadii(\n value: string,\n refW: number,\n refH: number,\n w: number,\n h: number,\n): CornerRadii | null | undefined {\n const [hPart, vPart] = value.split(\"/\");\n const hTokens = tokenize(hPart ?? \"\");\n const vTokens = vPart === undefined ? hTokens : tokenize(vPart);\n if (\n hTokens.length < 1 ||\n hTokens.length > 4 ||\n vTokens.length < 1 ||\n vTokens.length > 4\n ) {\n return undefined;\n }\n const hs = expandSides(hTokens).map((t) => parseCSSLength(t, refW));\n const vs = expandSides(vTokens).map((t) => parseCSSLength(t, refH));\n if ([...hs, ...vs].some(isNaN)) return undefined;\n const radii = hs.map((rx, i) => [\n Math.max(0, rx),\n Math.max(0, vs[i]!),\n ]) as CornerRadii;\n if (radii.every(([rx, ry]) => rx <= 0 || ry <= 0)) return null;\n return normalizeRadii(radii, w, h);\n}\n\n/**\n * CSS border-radius overlap rule: if adjacent radii along any side sum to more\n * than that side's length, scale every radius by the same factor.\n */\nfunction normalizeRadii(radii: CornerRadii, w: number, h: number): CornerRadii {\n const [tl, tr, br, bl] = radii;\n let f = 1;\n const consider = (sum: number, length: number) => {\n if (sum > 0 && length / sum < f) f = length / sum;\n };\n consider(tl[0] + tr[0], w);\n consider(bl[0] + br[0], w);\n consider(tl[1] + bl[1], h);\n consider(tr[1] + br[1], h);\n if (f >= 1) return radii;\n return radii.map(([rx, ry]) => [rx * f, ry * f]) as CornerRadii;\n}\n\n/**\n * Append a rounded rectangle with per-corner elliptical radii to a path.\n */\nfunction roundedRectPath(\n p: Path2D,\n x: number,\n y: number,\n w: number,\n h: number,\n radii: CornerRadii,\n): void {\n const [tl, tr, br, bl] = radii;\n const round = (r: Point) => r[0] > 0 && r[1] > 0;\n const HALF = Math.PI / 2;\n\n p.moveTo(x + (round(tl) ? tl[0] : 0), y);\n p.lineTo(x + w - (round(tr) ? tr[0] : 0), y);\n if (round(tr)) {\n p.ellipse(x + w - tr[0], y + tr[1], tr[0], tr[1], 0, -HALF, 0);\n }\n p.lineTo(x + w, y + h - (round(br) ? br[1] : 0));\n if (round(br)) {\n p.ellipse(x + w - br[0], y + h - br[1], br[0], br[1], 0, 0, HALF);\n }\n p.lineTo(x + (round(bl) ? bl[0] : 0), y + h);\n if (round(bl)) {\n p.ellipse(x + bl[0], y + h - bl[1], bl[0], bl[1], 0, HALF, Math.PI);\n }\n p.lineTo(x, y + (round(tl) ? tl[1] : 0));\n if (round(tl)) {\n p.ellipse(x + tl[0], y + tl[1], tl[0], tl[1], 0, Math.PI, 3 * HALF);\n }\n p.closePath();\n}\n\nfunction expandSides(values: string[]): [string, string, string, string] {\n const [a, b, c, d] = values;\n switch (values.length) {\n case 1:\n return [a!, a!, a!, a!];\n case 2:\n return [a!, b!, a!, b!];\n case 3:\n return [a!, b!, c!, b!];\n default:\n return [a!, b!, c!, d!];\n }\n}\n\n/** Split `... round <radii>` into the shape part and the optional radii part. */\nfunction splitRound(args: string): [string, string | undefined] {\n const m = args.match(/^(.*?)\\bround\\b(.*)$/s);\n if (!m) return [args, undefined];\n return [m[1]!, m[2]!];\n}\n\n/** Split `<radius> at <position>` into the radius part and the position part. */\nfunction splitAt(args: string): [string, string | undefined] {\n const m = args.match(/^(.*?)\\bat\\b(.*)$/s);\n if (!m) return [args, undefined];\n return [m[1]!, m[2]!];\n}\n\n/** Split on top-level commas, respecting parentheses and quoted strings. */\nfunction splitArgs(content: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let depth = 0;\n let quote: string | null = null;\n for (const char of content) {\n if (quote) {\n if (char === quote) quote = null;\n current += char;\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n current += char;\n continue;\n }\n if (char === \"(\") depth++;\n if (char === \")\") depth--;\n if (char === \",\" && depth === 0) {\n parts.push(current);\n current = \"\";\n } else {\n current += char;\n }\n }\n if (current.trim()) parts.push(current);\n return parts;\n}\n\nfunction splitAtSlash(tokens: string[]): string[][] {\n if (tokens.length === 0) return [];\n const slash = tokens.indexOf(\"/\");\n return slash === -1\n ? [tokens]\n : [tokens.slice(0, slash), tokens.slice(slash + 1)];\n}\n\nfunction tokenize(value: string): string[] {\n return value.trim().replace(/\\//g, \" / \").split(/\\s+/).filter(Boolean);\n}\n\nfunction unquote(s: string): string {\n if (\n s.length >= 2 &&\n ((s.startsWith('\"') && s.endsWith('\"')) ||\n (s.startsWith(\"'\") && s.endsWith(\"'\")))\n ) {\n return s.slice(1, -1);\n }\n return s;\n}\n\nfunction parseAngleDegrees(value: string): number {\n const n = parseFloat(value);\n if (isNaN(n)) return NaN;\n if (value.endsWith(\"deg\")) return n;\n if (value.endsWith(\"grad\")) return n * 0.9;\n if (value.endsWith(\"rad\")) return (n * 180) / Math.PI;\n if (value.endsWith(\"turn\")) return n * 360;\n return n;\n}\n\nfunction fmt(n: number): string {\n return String(Math.round(n * 1000) / 1000);\n}\n\nfunction fmtPoint(p: Point): string {\n return `${fmt(p[0])} ${fmt(p[1])}`;\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { hasRadius, roundedRect } from \"./clip.ts\";\nimport { parseCSSLength, toNumber, resolveBoxValue } from \"./utils.ts\";\n\n/**\n * Draw the background, borders, and box-shadow for a rectangular element.\n */\nexport function drawRect(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n style: ComputedStyle,\n): void {\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n const hasRoundedCorners = hasRadius(borderRadius);\n\n // Background\n if (style.backgroundColor) {\n ctx.fillStyle = style.backgroundColor;\n\n if (hasRoundedCorners) {\n ctx.beginPath();\n roundedRect(\n ctx,\n x,\n y,\n width,\n height,\n borderRadius.topLeft,\n borderRadius.topRight,\n borderRadius.bottomRight,\n borderRadius.bottomLeft,\n );\n ctx.fill();\n } else {\n ctx.fillRect(x, y, width, height);\n }\n }\n\n // Borders\n drawBorders(ctx, x, y, width, height, style, borderRadius);\n}\n\nfunction resolveRadius(v: unknown, width: number, height: number): number {\n if (typeof v === \"string\") return parseCSSLength(v, Math.min(width, height));\n return toNumber(v);\n}\n\nexport function getBorderRadiusFromStyle(\n style: ComputedStyle,\n width: number,\n height: number,\n) {\n return {\n topLeft: resolveRadius(style.borderTopLeftRadius, width, height),\n topRight: resolveRadius(style.borderTopRightRadius, width, height),\n bottomRight: resolveRadius(style.borderBottomRightRadius, width, height),\n bottomLeft: resolveRadius(style.borderBottomLeftRadius, width, height),\n };\n}\n\nfunction drawBorders(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n style: ComputedStyle,\n borderRadius: ReturnType<typeof getBorderRadiusFromStyle>,\n): void {\n const hasRoundedCorners = hasRadius(borderRadius);\n\n // If all borders are the same, draw as a single stroke\n const tw = resolveBoxValue(style.borderTopWidth, width);\n const rw = resolveBoxValue(style.borderRightWidth, width);\n const bw = resolveBoxValue(style.borderBottomWidth, width);\n const lw = resolveBoxValue(style.borderLeftWidth, width);\n\n if (tw === 0 && rw === 0 && bw === 0 && lw === 0) return;\n\n const allSameWidth = tw === rw && rw === bw && bw === lw && tw > 0;\n const tc = style.borderTopColor ?? \"black\";\n const rc = style.borderRightColor ?? \"black\";\n const bc = style.borderBottomColor ?? \"black\";\n const lc = style.borderLeftColor ?? \"black\";\n const allSameColor = tc === rc && rc === bc && bc === lc;\n\n if (allSameWidth && allSameColor) {\n ctx.strokeStyle = tc;\n ctx.lineWidth = tw;\n\n if (hasRoundedCorners) {\n ctx.beginPath();\n const half = tw / 2;\n roundedRect(\n ctx,\n x + half,\n y + half,\n width - tw,\n height - tw,\n Math.max(0, borderRadius.topLeft - half),\n Math.max(0, borderRadius.topRight - half),\n Math.max(0, borderRadius.bottomRight - half),\n Math.max(0, borderRadius.bottomLeft - half),\n );\n ctx.stroke();\n } else {\n ctx.strokeRect(x + tw / 2, y + tw / 2, width - tw, height - tw);\n }\n return;\n }\n\n // Draw individual borders\n if (hasRoundedCorners) {\n const maxR = Math.min(width, height) / 2;\n const tl = Math.min(borderRadius.topLeft, maxR);\n const tr = Math.min(borderRadius.topRight, maxR);\n const br = Math.min(borderRadius.bottomRight, maxR);\n const bl = Math.min(borderRadius.bottomLeft, maxR);\n\n const top = y + tw / 2;\n const right = x + width - rw / 2;\n const bottom = y + height - bw / 2;\n const left = x + lw / 2;\n\n const eTL = Math.max(0, tl - Math.max(tw, lw) / 2);\n const eTR = Math.max(0, tr - Math.max(tw, rw) / 2);\n const eBR = Math.max(0, br - Math.max(bw, rw) / 2);\n const eBL = Math.max(0, bl - Math.max(bw, lw) / 2);\n\n // Each side owns its end corner (in drawing direction) and only draws the\n // start corner arc when the adjacent owner side is not visible (width 0).\n // This prevents double-stroking of corner arcs which causes AA artifacts.\n\n // Top side (L → R): borrows TL, owns TR\n if (tw > 0) {\n ctx.strokeStyle = tc;\n ctx.lineWidth = tw;\n ctx.beginPath();\n if (eTL > 0 && lw === 0) {\n ctx.moveTo(left, top + eTL);\n ctx.arcTo(left, top, left + eTL, top, eTL);\n } else if (eTL > 0) {\n ctx.moveTo(left + eTL, top);\n } else {\n ctx.moveTo(x, top);\n }\n if (eTR > 0) {\n ctx.lineTo(right - eTR, top);\n ctx.arcTo(right, top, right, top + eTR, eTR);\n } else {\n ctx.lineTo(x + width, top);\n }\n ctx.stroke();\n }\n\n // Right side (T → B): borrows TR, owns BR\n if (rw > 0) {\n ctx.strokeStyle = rc;\n ctx.lineWidth = rw;\n ctx.beginPath();\n if (eTR > 0 && tw === 0) {\n ctx.moveTo(right - eTR, top);\n ctx.arcTo(right, top, right, top + eTR, eTR);\n } else if (eTR > 0) {\n ctx.moveTo(right, top + eTR);\n } else {\n ctx.moveTo(right, y);\n }\n if (eBR > 0) {\n ctx.lineTo(right, bottom - eBR);\n ctx.arcTo(right, bottom, right - eBR, bottom, eBR);\n } else {\n ctx.lineTo(right, y + height);\n }\n ctx.stroke();\n }\n\n // Bottom side (R → L): borrows BR, owns BL\n if (bw > 0) {\n ctx.strokeStyle = bc;\n ctx.lineWidth = bw;\n ctx.beginPath();\n if (eBR > 0 && rw === 0) {\n ctx.moveTo(right, bottom - eBR);\n ctx.arcTo(right, bottom, right - eBR, bottom, eBR);\n } else if (eBR > 0) {\n ctx.moveTo(right - eBR, bottom);\n } else {\n ctx.moveTo(x + width, bottom);\n }\n if (eBL > 0) {\n ctx.lineTo(left + eBL, bottom);\n ctx.arcTo(left, bottom, left, bottom - eBL, eBL);\n } else {\n ctx.lineTo(x, bottom);\n }\n ctx.stroke();\n }\n\n // Left side (B → T): borrows BL, owns TL\n if (lw > 0) {\n ctx.strokeStyle = lc;\n ctx.lineWidth = lw;\n ctx.beginPath();\n if (eBL > 0 && bw === 0) {\n ctx.moveTo(left + eBL, bottom);\n ctx.arcTo(left, bottom, left, bottom - eBL, eBL);\n } else if (eBL > 0) {\n ctx.moveTo(left, bottom - eBL);\n } else {\n ctx.moveTo(left, y + height);\n }\n if (eTL > 0) {\n ctx.lineTo(left, top + eTL);\n ctx.arcTo(left, top, left + eTL, top, eTL);\n } else {\n ctx.lineTo(left, y);\n }\n ctx.stroke();\n }\n } else {\n if (tw > 0) {\n ctx.strokeStyle = tc;\n ctx.lineWidth = tw;\n ctx.beginPath();\n ctx.moveTo(x, y + tw / 2);\n ctx.lineTo(x + width, y + tw / 2);\n ctx.stroke();\n }\n if (rw > 0) {\n ctx.strokeStyle = rc;\n ctx.lineWidth = rw;\n ctx.beginPath();\n ctx.moveTo(x + width - rw / 2, y);\n ctx.lineTo(x + width - rw / 2, y + height);\n ctx.stroke();\n }\n if (bw > 0) {\n ctx.strokeStyle = bc;\n ctx.lineWidth = bw;\n ctx.beginPath();\n ctx.moveTo(x, y + height - bw / 2);\n ctx.lineTo(x + width, y + height - bw / 2);\n ctx.stroke();\n }\n if (lw > 0) {\n ctx.strokeStyle = lc;\n ctx.lineWidth = lw;\n ctx.beginPath();\n ctx.moveTo(x + lw / 2, y);\n ctx.lineTo(x + lw / 2, y + height);\n ctx.stroke();\n }\n }\n}\n\n// Parse simple box-shadow: offsetX offsetY blur spread? color\nconst BOX_SHADOW_RE =\n /(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?(?:\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?)?\\s+(.*)/;\n\nexport function drawBoxShadow(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n boxShadow: string,\n borderRadius: ReturnType<typeof getBorderRadiusFromStyle>,\n): void {\n const parts = boxShadow.match(BOX_SHADOW_RE);\n if (!parts) return;\n\n const offsetX = parseFloat(parts[1]!);\n const offsetY = parseFloat(parts[2]!);\n const blur = parseFloat(parts[3]!);\n const color = parts[5]!.trim();\n\n const radii = [\n borderRadius.topLeft,\n borderRadius.topRight,\n borderRadius.bottomRight,\n borderRadius.bottomLeft,\n ];\n\n // Clip to area OUTSIDE the element so shadow renders but inner fill is hidden\n const margin = blur * 2 + Math.abs(offsetX) + Math.abs(offsetY);\n ctx.save();\n ctx.beginPath();\n ctx.rect(x - margin, y - margin, width + margin * 2, height + margin * 2);\n ctx.roundRect(x, y, width, height, radii);\n ctx.clip(\"evenodd\");\n\n // Use CSS filter blur (sigma = blur/2) instead of the canvas shadow API\n // because it matches SVG feGaussianBlur (used by satori) much more closely.\n ctx.filter = `blur(${blur / 2}px)`;\n ctx.translate(offsetX, offsetY);\n ctx.fillStyle = color;\n ctx.beginPath();\n ctx.roundRect(x, y, width, height, radii);\n ctx.fill();\n ctx.restore();\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\n\n/**\n * Parse and create a canvas gradient from a CSS gradient string.\n * Supports linear-gradient and radial-gradient.\n *\n * @returns A CanvasGradient or null if parsing fails\n */\nexport function createGradientFromCSS(\n ctx: SKRSContext2D,\n cssGradient: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): CanvasGradient | null {\n const trimmed = cssGradient.trim();\n\n if (trimmed.startsWith(\"linear-gradient\")) {\n return parseLinearGradient(ctx, trimmed, x, y, width, height);\n }\n\n if (trimmed.startsWith(\"radial-gradient\")) {\n return parseRadialGradient(ctx, trimmed, x, y, width, height);\n }\n\n return null;\n}\n\nfunction parseLinearGradient(\n ctx: SKRSContext2D,\n css: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): CanvasGradient | null {\n // Extract content between parentheses\n const match = css.match(/linear-gradient\\((.*)\\)/s);\n if (!match) return null;\n\n const content = match[1]!.trim();\n const parts = splitGradientArgs(content);\n\n let angle = 180; // default: to bottom\n let colorStartIdx = 0;\n\n // Parse direction\n const first = parts[0]?.trim();\n if (first) {\n if (first.startsWith(\"to \")) {\n angle = directionToAngle(first);\n colorStartIdx = 1;\n } else if (first.endsWith(\"deg\")) {\n angle = parseFloat(first);\n colorStartIdx = 1;\n } else if (first.endsWith(\"turn\")) {\n angle = parseFloat(first) * 360;\n colorStartIdx = 1;\n }\n }\n\n // Calculate gradient line endpoints\n const rad = ((angle - 90) * Math.PI) / 180;\n const cx = x + width / 2;\n const cy = y + height / 2;\n const halfDiag =\n Math.abs(width * Math.cos(rad)) / 2 + Math.abs(height * Math.sin(rad)) / 2;\n\n const x0 = cx - halfDiag * Math.cos(rad);\n const y0 = cy - halfDiag * Math.sin(rad);\n const x1 = cx + halfDiag * Math.cos(rad);\n const y1 = cy + halfDiag * Math.sin(rad);\n\n const gradient = ctx.createLinearGradient(x0, y0, x1, y1);\n\n // Parse color stops\n const stops = parts.slice(colorStartIdx);\n addColorStops(gradient, stops);\n\n return gradient;\n}\n\nfunction parseRadialGradient(\n ctx: SKRSContext2D,\n css: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): CanvasGradient | null {\n const match = css.match(/radial-gradient\\((.*)\\)/s);\n if (!match) return null;\n\n const content = match[1]!.trim();\n const parts = splitGradientArgs(content);\n\n const cx = x + width / 2;\n const cy = y + height / 2;\n const radius = Math.max(width, height) / 2;\n\n const gradient = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius);\n\n // Simple parsing: skip shape/size/position, just get color stops\n let colorStartIdx = 0;\n const first = parts[0]?.trim() ?? \"\";\n if (\n first.startsWith(\"circle\") ||\n first.startsWith(\"ellipse\") ||\n first.startsWith(\"closest\") ||\n first.startsWith(\"farthest\")\n ) {\n colorStartIdx = 1;\n }\n\n addColorStops(gradient, parts.slice(colorStartIdx));\n\n return gradient;\n}\n\nfunction addColorStops(gradient: CanvasGradient, stops: string[]): void {\n if (stops.length === 0) return;\n\n for (let i = 0; i < stops.length; i++) {\n const stop = stops[i]!.trim();\n const percentMatch = stop.match(/^(.+?)\\s+(\\d+(?:\\.\\d+)?%?)$/);\n\n if (percentMatch) {\n const color = percentMatch[1]!;\n const pos = percentMatch[2]!;\n const offset = pos.endsWith(\"%\")\n ? parseFloat(pos) / 100\n : parseFloat(pos);\n gradient.addColorStop(Math.max(0, Math.min(1, offset)), color);\n } else {\n // Auto-distribute\n const offset = stops.length === 1 ? 0.5 : i / (stops.length - 1);\n gradient.addColorStop(offset, stop);\n }\n }\n}\n\nfunction directionToAngle(dir: string): number {\n const map: Record<string, number> = {\n \"to top\": 0,\n \"to right\": 90,\n \"to bottom\": 180,\n \"to left\": 270,\n \"to top right\": 45,\n \"to top left\": 315,\n \"to bottom right\": 135,\n \"to bottom left\": 225,\n };\n return map[dir] ?? 180;\n}\n\nexport function splitGradientArgs(content: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let parenDepth = 0;\n\n for (const char of content) {\n if (char === \"(\") parenDepth++;\n if (char === \")\") parenDepth--;\n if (char === \",\" && parenDepth === 0) {\n parts.push(current);\n current = \"\";\n } else {\n current += char;\n }\n }\n if (current.trim()) parts.push(current);\n\n return parts;\n}\n","// Compositing groups through @effing/skia's `beginGroup` / `endGroup`:\n// everything drawn inside a group is composited as one when it ends, which is\n// what CSS `opacity`, `filter` and `backdrop-filter` mean on an element.\n// Per-draw `globalAlpha` and `ctx.filter` can't give that once draws overlap:\n// overlapping children would show through each other, and each would cast its\n// own shadow.\n//\n// A group is composited through an offscreen buffer, which @effing/skia sizes\n// to what the group draws, so a translucent element costs about as much as\n// its own area.\n\nimport type { SKRSContext2D } from \"@effing/skia\";\nimport { beginGroup, endGroup } from \"@effing/skia/extensions\";\n\nimport { applyClip } from \"./clip.ts\";\nimport type { getBorderRadiusFromStyle } from \"./rect.ts\";\n\ntype BorderRadius = ReturnType<typeof getBorderRadiusFromStyle>;\n\n/** A CSS filter value that filters nothing. */\nfunction isNoFilter(filter: string | undefined): boolean {\n if (!filter) return true;\n const normalized = filter.trim();\n return normalized === \"\" || normalized === \"none\";\n}\n\n/**\n * Start the group an element and its descendants paint into, when its\n * `opacity` or `filter` call for one. Returns whether a group was started,\n * to end with `endElementGroup`.\n */\nexport function beginElementGroup(\n ctx: SKRSContext2D,\n opacity: number,\n filter: string | undefined,\n): boolean {\n const hasFilter = !isNoFilter(filter);\n if (opacity >= 1 && !hasFilter) return false;\n beginGroup(ctx, { opacity, filter: hasFilter ? filter!.trim() : undefined });\n return true;\n}\n\nexport function endElementGroup(ctx: SKRSContext2D): void {\n endGroup(ctx);\n}\n\n/**\n * CSS `backdrop-filter`: filter whatever is already painted behind the\n * element's border box (with its radius) and composite the result back at the\n * element's opacity. Must run before the element's own painting — box-shadow\n * and background included — so nothing of the element ends up in its own\n * backdrop and its background composites on top of the filtered result.\n *\n * The filter runs in the element's own coordinate space, and the backdrop is\n * clamped at the canvas edge, as a browser does at the viewport edge, so a\n * blur near the edge doesn't fade into transparency. Skia reads the backdrop\n * from the enclosing group, so as in a browser, an ancestor with `opacity` or\n * a `filter` bounds what the element sees through: only what that ancestor\n * has painted so far.\n */\nexport function drawBackdropFilter(\n ctx: SKRSContext2D,\n filter: string,\n x: number,\n y: number,\n width: number,\n height: number,\n borderRadius: BorderRadius,\n opacity: number,\n): void {\n if (width <= 0 || height <= 0) return;\n if (isNoFilter(filter)) return;\n ctx.save();\n applyClip(ctx, x, y, width, height, borderRadius);\n beginGroup(ctx, { backdropFilter: filter.trim(), opacity });\n endGroup(ctx);\n ctx.restore();\n}\n","/**\n * Shared cover/contain sizing logic used by both `<img>` objectFit\n * and `backgroundImage` + `backgroundSize`.\n */\n\nexport interface FitRect {\n sx: number;\n sy: number;\n sw: number;\n sh: number;\n dx: number;\n dy: number;\n dw: number;\n dh: number;\n}\n\n/**\n * Compute source and destination rectangles for \"cover\" sizing.\n * The image fills the box completely, cropping the excess.\n */\nexport function computeCover(\n imgW: number,\n imgH: number,\n boxX: number,\n boxY: number,\n boxW: number,\n boxH: number,\n): FitRect {\n const imgRatio = imgW / imgH;\n const boxRatio = boxW / boxH;\n\n let sx: number, sy: number, sw: number, sh: number;\n\n if (imgRatio > boxRatio) {\n sh = imgH;\n sw = imgH * boxRatio;\n sx = (imgW - sw) / 2;\n sy = 0;\n } else {\n sw = imgW;\n sh = imgW / boxRatio;\n sx = 0;\n sy = (imgH - sh) / 2;\n }\n\n return { sx, sy, sw, sh, dx: boxX, dy: boxY, dw: boxW, dh: boxH };\n}\n\n/**\n * Compute destination rectangle for \"contain\" sizing.\n * The image fits entirely within the box, centered, with no cropping.\n */\nexport function computeContain(\n imgW: number,\n imgH: number,\n boxX: number,\n boxY: number,\n boxW: number,\n boxH: number,\n): FitRect {\n const imgRatio = imgW / imgH;\n const boxRatio = boxW / boxH;\n\n let dw: number, dh: number;\n\n if (imgRatio > boxRatio) {\n dw = boxW;\n dh = boxW / imgRatio;\n } else {\n dh = boxH;\n dw = boxH * imgRatio;\n }\n\n const dx = boxX + (boxW - dw) / 2;\n const dy = boxY + (boxH - dh) / 2;\n\n return { sx: 0, sy: 0, sw: imgW, sh: imgH, dx, dy, dw, dh };\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\n\nimport { cachedLoadImage } from \"../../image.ts\";\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport type { RenderContext } from \"../context.ts\";\nimport { computeContain, computeCover } from \"./object-fit.ts\";\n\n/**\n * Draw an image element onto the canvas.\n *\n * @param ctx - Canvas rendering context\n * @param src - Image source (URL, file path, or Buffer)\n * @param x - X position\n * @param y - Y position\n * @param width - Target width\n * @param height - Target height\n * @param context - Per-render context (image cache + fetch config)\n * @param style - Computed style (for objectFit)\n */\nexport async function drawImage(\n ctx: SKRSContext2D,\n src: string | Buffer,\n x: number,\n y: number,\n width: number,\n height: number,\n context: RenderContext,\n style?: ComputedStyle,\n): Promise<void> {\n const image = await cachedLoadImage(\n context.imageCache,\n src,\n context.userAgent,\n );\n const objectFit = style?.objectFit ?? \"fill\";\n\n if (objectFit === \"fill\") {\n ctx.drawImage(image, x, y, width, height);\n return;\n }\n\n const imgW = image.width;\n const imgH = image.height;\n\n if (objectFit === \"contain\") {\n const r = computeContain(imgW, imgH, x, y, width, height);\n ctx.drawImage(image, r.dx, r.dy, r.dw, r.dh);\n } else if (objectFit === \"cover\") {\n const r = computeCover(imgW, imgH, x, y, width, height);\n ctx.drawImage(image, r.sx, r.sy, r.sw, r.sh, r.dx, r.dy, r.dw, r.dh);\n } else if (objectFit === \"none\") {\n const dx = x + (width - imgW) / 2;\n const dy = y + (height - imgH) / 2;\n ctx.drawImage(image, dx, dy);\n } else if (objectFit === \"scale-down\") {\n if (imgW <= width && imgH <= height) {\n const dx = x + (width - imgW) / 2;\n const dy = y + (height - imgH) / 2;\n ctx.drawImage(image, dx, dy);\n } else {\n const r = computeContain(imgW, imgH, x, y, width, height);\n ctx.drawImage(image, r.dx, r.dy, r.dw, r.dh);\n }\n }\n}\n","import type { InheritedSvgStyle } from \"./types.ts\";\n\n/** Replace `\"currentColor\"` with the inherited CSS `color` value. */\nexport function resolveCurrentColor(\n value: string | undefined,\n color: string,\n): string | undefined {\n if (value?.toLowerCase() === \"currentcolor\") return color;\n return value;\n}\n\n/**\n * Merge SVG presentation properties from `props.style` into the props object.\n * Style values win over direct props, matching browser CSS specificity rules.\n */\nexport function mergeStyleIntoProps(\n props: Record<string, unknown>,\n): Record<string, unknown> {\n const style = props.style as Record<string, unknown> | undefined;\n if (!style) return props;\n return { ...props, ...style };\n}\n\n/**\n * Parse an SVG length value, resolving percentages against a reference dimension.\n * Unlike gradient-specific `parseFrac`, this returns absolute coordinates (not 0–1 fractions).\n */\nexport function svgLength(\n value: unknown,\n reference: number,\n fallback = 0,\n): number {\n if (value == null) return fallback;\n const s = String(value);\n if (s.endsWith(\"%\")) return (parseFloat(s) / 100) * reference;\n const n = Number(s);\n return isNaN(n) ? fallback : n;\n}\n\n/** Parse `url(#id)` references and return the id, or undefined. */\nexport function parseUrlRef(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const m = value.match(/^url\\(#(.+)\\)$/);\n return m?.[1];\n}\n\n/**\n * Build an `InheritedSvgStyle` from merged SVG props, falling back to `parent`\n * values when present (for nested groups) or sensible defaults (fill = \"black\").\n */\nexport function resolveInheritedStyle(\n merged: Record<string, unknown>,\n color: string,\n parent?: InheritedSvgStyle,\n): InheritedSvgStyle {\n return {\n fill:\n resolveCurrentColor(merged.fill as string | undefined, color) ??\n parent?.fill ??\n \"black\",\n stroke:\n resolveCurrentColor(merged.stroke as string | undefined, color) ??\n parent?.stroke,\n strokeWidth:\n ((merged.strokeWidth ?? merged[\"stroke-width\"]) as\n | string\n | number\n | undefined) ?? parent?.strokeWidth,\n strokeLinecap:\n ((merged.strokeLinecap ?? merged[\"stroke-linecap\"]) as\n | string\n | undefined) ?? parent?.strokeLinecap,\n strokeLinejoin:\n ((merged.strokeLinejoin ?? merged[\"stroke-linejoin\"]) as\n | string\n | undefined) ?? parent?.strokeLinejoin,\n strokeOpacity:\n ((merged.strokeOpacity ?? merged[\"stroke-opacity\"]) as\n | string\n | number\n | undefined) ?? parent?.strokeOpacity,\n };\n}\n","import type { SvgChild } from \"./types.ts\";\n\n/** Normalize children from either `.children` or `.props.children` into an array. */\nexport function normalizeChildren(node: SvgChild): SvgChild[] {\n const raw =\n node.children ?? (node.props.children as SvgChild | SvgChild[] | undefined);\n if (raw == null) return [];\n return (Array.isArray(raw) ? raw.flat(Infinity) : [raw]) as SvgChild[];\n}\n","import type { SvgChild, SvgDefs } from \"./types.ts\";\nimport { normalizeChildren } from \"./tree.ts\";\n\n/**\n * Collect `<clipPath>`, `<mask>`, `<filter>`, and gradient definitions from\n * `<defs>` elements as well as direct children of `<svg>` (both are valid per\n * the SVG spec).\n */\nexport function collectDefs(children: SvgChild[], vbW = 0, vbH = 0): SvgDefs {\n const clips = new Map<string, SvgChild[]>();\n const gradients = new Map<string, SvgChild>();\n const masks = new Map<string, SvgChild[]>();\n const filters = new Map<string, SvgChild>();\n\n function insertDef(def: SvgChild): void {\n if (!def || typeof def !== \"object\" || !(\"props\" in def) || !def.props)\n return;\n const id = def.props.id as string | undefined;\n if (!id) return;\n if (def.type === \"clipPath\") clips.set(id, normalizeChildren(def));\n else if (def.type === \"mask\") masks.set(id, normalizeChildren(def));\n else if (def.type === \"filter\") filters.set(id, def);\n else if (def.type === \"radialGradient\" || def.type === \"linearGradient\")\n gradients.set(id, def);\n }\n\n for (const child of children) {\n if (child.type === \"defs\") {\n for (const def of normalizeChildren(child)) insertDef(def);\n } else {\n // Definition elements can appear as direct children of <svg>.\n insertDef(child);\n }\n }\n return {\n clips,\n gradients,\n masks,\n filters,\n viewport: { width: vbW, height: vbH },\n };\n}\n\nexport const EMPTY_DEFS: SvgDefs = {\n clips: new Map(),\n gradients: new Map(),\n masks: new Map(),\n filters: new Map(),\n viewport: { width: 0, height: 0 },\n};\n","import type { SKRSContext2D } from \"@effing/skia\";\n\n/**\n * Save context state and apply transform + opacity if present.\n * Returns true if ctx.save() was called (caller must ctx.restore()).\n */\nexport function applyTransformAndOpacity(\n ctx: SKRSContext2D,\n transform: string | undefined,\n opacity: number,\n): boolean {\n if (!transform && opacity >= 1) return false;\n ctx.save();\n if (transform) applySvgTransform(ctx, transform);\n if (opacity < 1) ctx.globalAlpha *= opacity;\n return true;\n}\n\n/**\n * Parse an SVG `transform` attribute and apply it to the canvas context.\n *\n * Supports: translate, scale, rotate, skewX, skewY, matrix.\n * Multiple transforms are applied left-to-right (same order as SVG spec).\n */\nexport function applySvgTransform(ctx: SKRSContext2D, transform: string): void {\n const re = /\\b(translate|scale|rotate|skewX|skewY|matrix)\\s*\\(([^)]*)\\)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(transform)) !== null) {\n const fn = match[1]!;\n const args = match[2]!\n .split(/[\\s,]+/)\n .filter(Boolean)\n .map(Number);\n\n switch (fn) {\n case \"translate\":\n ctx.translate(args[0] ?? 0, args[1] ?? 0);\n break;\n case \"scale\": {\n const sx = args[0] ?? 1;\n ctx.scale(sx, args[1] ?? sx);\n break;\n }\n case \"rotate\": {\n const angle = ((args[0] ?? 0) * Math.PI) / 180;\n if (args.length >= 3) {\n const cx = args[1]!;\n const cy = args[2]!;\n ctx.translate(cx, cy);\n ctx.rotate(angle);\n ctx.translate(-cx, -cy);\n } else {\n ctx.rotate(angle);\n }\n break;\n }\n case \"skewX\":\n ctx.transform(\n 1,\n 0,\n Math.tan(((args[0] ?? 0) * Math.PI) / 180),\n 1,\n 0,\n 0,\n );\n break;\n case \"skewY\":\n ctx.transform(\n 1,\n Math.tan(((args[0] ?? 0) * Math.PI) / 180),\n 0,\n 1,\n 0,\n 0,\n );\n break;\n case \"matrix\":\n ctx.transform(\n args[0] ?? 1,\n args[1] ?? 0,\n args[2] ?? 0,\n args[3] ?? 1,\n args[4] ?? 0,\n args[5] ?? 0,\n );\n break;\n }\n }\n}\n","import { Path2D } from \"@effing/skia\";\n\nimport type { BBox, SvgChild } from \"./types.ts\";\nimport { mergeStyleIntoProps } from \"./style.ts\";\nimport { svgLength } from \"./style.ts\";\n\n/** Compute a conservative bounding box from SVG path data. */\nexport function pathBBox(d: string): BBox {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let cx = 0;\n let cy = 0;\n\n const update = (x: number, y: number) => {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n };\n\n // Tokenize: commands and numbers (including negative)\n const tokens = d.match(/[a-zA-Z]|[-+]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][-+]?\\d+)?/g);\n if (!tokens) return { x: 0, y: 0, width: 0, height: 0 };\n\n let cmd = \"\";\n let i = 0;\n const num = () => Number(tokens[i++]);\n\n while (i < tokens.length) {\n const t = tokens[i]!;\n if (/[a-zA-Z]/.test(t)) {\n cmd = t;\n i++;\n }\n\n switch (cmd) {\n case \"M\":\n cx = num();\n cy = num();\n update(cx, cy);\n cmd = \"L\"; // implicit lineTo after moveTo\n break;\n case \"m\":\n cx += num();\n cy += num();\n update(cx, cy);\n cmd = \"l\";\n break;\n case \"L\":\n cx = num();\n cy = num();\n update(cx, cy);\n break;\n case \"l\":\n cx += num();\n cy += num();\n update(cx, cy);\n break;\n case \"H\":\n cx = num();\n update(cx, cy);\n break;\n case \"h\":\n cx += num();\n update(cx, cy);\n break;\n case \"V\":\n cy = num();\n update(cx, cy);\n break;\n case \"v\":\n cy += num();\n update(cx, cy);\n break;\n case \"C\": {\n // Cubic bezier: use control points as conservative bounds\n for (let j = 0; j < 3; j++) {\n const px = num();\n const py = num();\n update(px, py);\n }\n cx = Number(tokens[i - 2]);\n cy = Number(tokens[i - 1]);\n break;\n }\n case \"c\": {\n for (let j = 0; j < 3; j++) {\n const dx = num();\n const dy = num();\n update(cx + dx, cy + dy);\n if (j === 2) {\n cx += dx;\n cy += dy;\n }\n }\n break;\n }\n case \"Q\": {\n for (let j = 0; j < 2; j++) {\n const px = num();\n const py = num();\n update(px, py);\n }\n cx = Number(tokens[i - 2]);\n cy = Number(tokens[i - 1]);\n break;\n }\n case \"q\": {\n for (let j = 0; j < 2; j++) {\n const dx = num();\n const dy = num();\n update(cx + dx, cy + dy);\n if (j === 1) {\n cx += dx;\n cy += dy;\n }\n }\n break;\n }\n case \"A\": {\n // Arc: skip rx, ry, rotation, flags; endpoint is the bound\n num();\n num();\n num();\n num();\n num(); // rx ry rot largeArc sweep\n cx = num();\n cy = num();\n update(cx, cy);\n break;\n }\n case \"a\": {\n num();\n num();\n num();\n num();\n num();\n cx += num();\n cy += num();\n update(cx, cy);\n break;\n }\n case \"Z\":\n case \"z\":\n break;\n default:\n // Unknown command — skip token to avoid infinite loop\n i++;\n break;\n }\n }\n\n if (!isFinite(minX)) return { x: 0, y: 0, width: 0, height: 0 };\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/** Compute bounding box from a points attribute (polygon/polyline). */\nexport function pointsBBox(points: [number, number][]): BBox {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const [x, y] of points) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n if (!isFinite(minX)) return { x: 0, y: 0, width: 0, height: 0 };\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/**\n * Build a `Path2D` from an SVG shape element (without drawing it).\n * Returns `undefined` for unsupported element types.\n */\nexport function buildPath(\n child: SvgChild,\n vbW: number,\n vbH: number,\n): Path2D | undefined {\n const props = mergeStyleIntoProps(child.props);\n switch (child.type) {\n case \"path\": {\n const d = props.d as string | undefined;\n if (!d) return undefined;\n return new Path2D(d);\n }\n case \"circle\": {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const r = svgLength(props.r, Math.min(vbW, vbH));\n if (r <= 0) return undefined;\n const p = new Path2D();\n p.arc(cx, cy, r, 0, Math.PI * 2);\n return p;\n }\n case \"rect\": {\n const x = svgLength(props.x, vbW);\n const y = svgLength(props.y, vbH);\n const w = svgLength(props.width, vbW);\n const h = svgLength(props.height, vbH);\n if (w <= 0 || h <= 0) return undefined;\n const rxRaw = svgLength(props.rx, vbW, -1);\n const ryRaw = svgLength(props.ry, vbH, -1);\n let rx = rxRaw >= 0 ? rxRaw : ryRaw >= 0 ? ryRaw : 0;\n let ry = ryRaw >= 0 ? ryRaw : rx;\n rx = Math.min(rx, w / 2);\n ry = Math.min(ry, h / 2);\n const p = new Path2D();\n if (rx > 0 || ry > 0) {\n p.roundRect(x, y, w, h, [rx]);\n } else {\n p.rect(x, y, w, h);\n }\n return p;\n }\n case \"ellipse\": {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const rx = svgLength(props.rx, vbW);\n const ry = svgLength(props.ry, vbH);\n if (rx <= 0 || ry <= 0) return undefined;\n const p = new Path2D();\n p.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);\n return p;\n }\n case \"polygon\": {\n const points = parsePoints(props.points as string | undefined);\n if (points.length < 2) return undefined;\n const p = new Path2D();\n p.moveTo(points[0]![0], points[0]![1]);\n for (let i = 1; i < points.length; i++) {\n p.lineTo(points[i]![0], points[i]![1]);\n }\n p.closePath();\n return p;\n }\n default:\n return undefined;\n }\n}\n\n/**\n * Build a combined `Path2D` from all children of a `<clipPath>` definition.\n */\nexport function buildClipPath(\n shapes: SvgChild[],\n vbW: number,\n vbH: number,\n): Path2D | undefined {\n let combined: Path2D | undefined;\n for (const shape of shapes) {\n const p = buildPath(shape, vbW, vbH);\n if (!p) continue;\n if (!combined) {\n combined = p;\n } else {\n combined.addPath(p);\n }\n }\n return combined;\n}\n\nexport function parsePoints(value: string | undefined): [number, number][] {\n if (!value) return [];\n const nums = value\n .trim()\n .split(/[\\s,]+/)\n .map(Number);\n const result: [number, number][] = [];\n for (let i = 0; i + 1 < nums.length; i += 2) {\n result.push([nums[i]!, nums[i + 1]!]);\n }\n return result;\n}\n","import type { Canvas, SKRSContext2D } from \"@effing/skia\";\nimport { createCanvas } from \"@effing/skia\";\n\nconst canvasPool = new Map<string, WeakRef<Canvas>[]>();\n\nexport function acquireOffscreen(\n w: number,\n h: number,\n): [Canvas, SKRSContext2D] {\n const key = `${w}x${h}`;\n const stack = canvasPool.get(key);\n if (stack) {\n while (stack.length > 0) {\n const ref = stack.pop()!;\n const canvas = ref.deref();\n if (canvas) {\n const ctx = canvas.getContext(\"2d\");\n ctx.reset();\n return [canvas, ctx];\n }\n }\n }\n const canvas = createCanvas(w, h);\n return [canvas, canvas.getContext(\"2d\")];\n}\n\nexport function releaseOffscreen(canvas: Canvas): void {\n const key = `${canvas.width}x${canvas.height}`;\n let stack = canvasPool.get(key);\n if (!stack) {\n stack = [];\n canvasPool.set(key, stack);\n }\n stack.push(new WeakRef(canvas));\n}\n","import type { Canvas } from \"@effing/skia\";\n\nimport type { SvgChild } from \"./types.ts\";\nimport { normalizeChildren } from \"./tree.ts\";\nimport { acquireOffscreen } from \"../offscreen.ts\";\n\nfunction applyFeOffset(\n input: Canvas,\n dx: number,\n dy: number,\n w: number,\n h: number,\n): Canvas {\n const [canvas, ctx] = acquireOffscreen(w, h);\n ctx.drawImage(input, dx, dy);\n return canvas;\n}\n\nfunction applyFeGaussianBlur(\n input: Canvas,\n stdDeviation: number,\n w: number,\n h: number,\n): Canvas {\n const [canvas, ctx] = acquireOffscreen(w, h);\n ctx.filter = `blur(${stdDeviation}px)`;\n ctx.drawImage(input, 0, 0);\n ctx.filter = \"none\";\n return canvas;\n}\n\nfunction applyFeColorMatrix(\n input: Canvas,\n type: string,\n values: string | undefined,\n w: number,\n h: number,\n): Canvas {\n const [canvas, ctx] = acquireOffscreen(w, h);\n ctx.drawImage(input, 0, 0);\n\n if (type === \"matrix\" && values) {\n const m = values\n .trim()\n .split(/[\\s,]+/)\n .map(Number);\n if (m.length >= 20) {\n const imageData = ctx.getImageData(0, 0, w, h);\n const d = imageData.data;\n for (let i = 0; i < d.length; i += 4) {\n const r = d[i]!;\n const g = d[i + 1]!;\n const b = d[i + 2]!;\n const a = d[i + 3]!;\n d[i] = Math.min(\n 255,\n Math.max(\n 0,\n m[0]! * r + m[1]! * g + m[2]! * b + m[3]! * a + m[4]! * 255,\n ),\n );\n d[i + 1] = Math.min(\n 255,\n Math.max(\n 0,\n m[5]! * r + m[6]! * g + m[7]! * b + m[8]! * a + m[9]! * 255,\n ),\n );\n d[i + 2] = Math.min(\n 255,\n Math.max(\n 0,\n m[10]! * r + m[11]! * g + m[12]! * b + m[13]! * a + m[14]! * 255,\n ),\n );\n d[i + 3] = Math.min(\n 255,\n Math.max(\n 0,\n m[15]! * r + m[16]! * g + m[17]! * b + m[18]! * a + m[19]! * 255,\n ),\n );\n }\n ctx.putImageData(imageData, 0, 0);\n }\n }\n\n return canvas;\n}\n\nconst BLEND_MODE_MAP: Record<string, GlobalCompositeOperation> = {\n normal: \"source-over\",\n multiply: \"multiply\",\n screen: \"screen\",\n darken: \"darken\",\n lighten: \"lighten\",\n overlay: \"overlay\",\n};\n\nfunction applyFeBlend(\n in1: Canvas,\n in2: Canvas,\n mode: string,\n w: number,\n h: number,\n): Canvas {\n const [canvas, ctx] = acquireOffscreen(w, h);\n ctx.drawImage(in2, 0, 0);\n ctx.globalCompositeOperation = BLEND_MODE_MAP[mode] ?? \"source-over\";\n ctx.drawImage(in1, 0, 0);\n ctx.globalCompositeOperation = \"source-over\";\n return canvas;\n}\n\n/**\n * Extract the alpha channel of a canvas as a new greyscale canvas.\n * The result is a canvas where each pixel's RGBA channels equal the\n * source alpha (i.e. white where opaque, black where transparent).\n */\nfunction extractSourceAlpha(input: Canvas, w: number, h: number): Canvas {\n const [canvas, ctx] = acquireOffscreen(w, h);\n ctx.fillStyle = \"black\";\n ctx.fillRect(0, 0, w, h);\n ctx.globalCompositeOperation = \"destination-in\";\n ctx.drawImage(input, 0, 0);\n ctx.globalCompositeOperation = \"source-over\";\n return canvas;\n}\n\n/**\n * Execute an SVG `<filter>` pipeline on the element canvas.\n * Returns a new canvas with the filtered result; the caller is responsible\n * for releasing all canvases.\n */\nexport function applyFilter(\n filterDef: SvgChild,\n sourceGraphic: Canvas,\n w: number,\n h: number,\n): Canvas {\n const buffers = new Map<string, Canvas>();\n buffers.set(\"SourceGraphic\", sourceGraphic);\n\n let sourceAlpha: Canvas | undefined;\n const getSourceAlpha = () => {\n if (!sourceAlpha) {\n sourceAlpha = extractSourceAlpha(sourceGraphic, w, h);\n buffers.set(\"SourceAlpha\", sourceAlpha);\n }\n return sourceAlpha;\n };\n\n const children = normalizeChildren(filterDef);\n let lastResult: Canvas = sourceGraphic;\n\n for (const prim of children) {\n const p = prim.props;\n const inName = (p.in as string | undefined) ?? \"\";\n const resolve = (name: string): Canvas => {\n if (name === \"SourceAlpha\") return getSourceAlpha();\n return buffers.get(name) ?? lastResult;\n };\n const input = inName ? resolve(inName) : lastResult;\n let output: Canvas;\n\n switch (prim.type) {\n case \"feOffset\":\n output = applyFeOffset(\n input,\n Number(p.dx ?? 0),\n Number(p.dy ?? 0),\n w,\n h,\n );\n break;\n case \"feGaussianBlur\": {\n const std = Number(p.stdDeviation ?? 0);\n output = std > 0 ? applyFeGaussianBlur(input, std, w, h) : input;\n break;\n }\n case \"feColorMatrix\":\n output = applyFeColorMatrix(\n input,\n (p.type as string) ?? \"matrix\",\n p.values as string | undefined,\n w,\n h,\n );\n break;\n case \"feBlend\": {\n const in2Name = (p.in2 as string | undefined) ?? \"\";\n const in2 = in2Name ? resolve(in2Name) : lastResult;\n output = applyFeBlend(input, in2, (p.mode as string) ?? \"normal\", w, h);\n break;\n }\n default:\n output = input;\n break;\n }\n\n const resultName = p.result as string | undefined;\n if (resultName) buffers.set(resultName, output);\n lastResult = output;\n }\n\n return lastResult;\n}\n","import { Path2D } from \"@effing/skia\";\nimport type { SKRSContext2D } from \"@effing/skia\";\n\nimport type { BBox, InheritedSvgStyle, SvgDefs } from \"./types.ts\";\nimport { applyFillAndStroke, applyStroke } from \"./paint.ts\";\nimport { pathBBox, pointsBBox, parsePoints } from \"./path.ts\";\nimport { svgLength } from \"./style.ts\";\n\nexport function drawPath(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n): void {\n const d = props.d as string | undefined;\n if (!d) return;\n\n const path = new Path2D(d);\n const bbox = pathBBox(d);\n applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function drawCircle(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const r = svgLength(props.r, Math.min(vbW, vbH));\n if (r <= 0) return;\n\n const path = new Path2D();\n path.arc(cx, cy, r, 0, Math.PI * 2);\n const bbox: BBox = { x: cx - r, y: cy - r, width: 2 * r, height: 2 * r };\n applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function drawSvgRect(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const x = svgLength(props.x, vbW);\n const y = svgLength(props.y, vbH);\n const w = svgLength(props.width, vbW);\n const h = svgLength(props.height, vbH);\n if (w <= 0 || h <= 0) return;\n\n const rxRaw = svgLength(props.rx, vbW, -1);\n const ryRaw = svgLength(props.ry, vbH, -1);\n let rx = rxRaw >= 0 ? rxRaw : ryRaw >= 0 ? ryRaw : 0;\n let ry = ryRaw >= 0 ? ryRaw : rx;\n rx = Math.min(rx, w / 2);\n ry = Math.min(ry, h / 2);\n\n const path = new Path2D();\n if (rx > 0 || ry > 0) {\n path.roundRect(x, y, w, h, [rx]);\n } else {\n path.rect(x, y, w, h);\n }\n const bbox: BBox = { x, y, width: w, height: h };\n applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function drawLine(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const x1 = svgLength(props.x1, vbW);\n const y1 = svgLength(props.y1, vbH);\n const x2 = svgLength(props.x2, vbW);\n const y2 = svgLength(props.y2, vbH);\n\n const path = new Path2D();\n path.moveTo(x1, y1);\n path.lineTo(x2, y2);\n // Lines are stroke-only\n const bbox: BBox = {\n x: Math.min(x1, x2),\n y: Math.min(y1, y2),\n width: Math.abs(x2 - x1),\n height: Math.abs(y2 - y1),\n };\n applyStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function drawEllipse(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const rx = svgLength(props.rx, vbW);\n const ry = svgLength(props.ry, vbH);\n if (rx <= 0 || ry <= 0) return;\n\n const path = new Path2D();\n path.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);\n const bbox: BBox = {\n x: cx - rx,\n y: cy - ry,\n width: 2 * rx,\n height: 2 * ry,\n };\n applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function drawPolygon(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n): void {\n const points = parsePoints(props.points as string | undefined);\n if (points.length < 2) return;\n\n const path = new Path2D();\n path.moveTo(points[0]![0], points[0]![1]);\n for (let i = 1; i < points.length; i++) {\n path.lineTo(points[i]![0], points[i]![1]);\n }\n path.closePath();\n const bbox = pointsBBox(points);\n applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function drawPolyline(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n): void {\n const points = parsePoints(props.points as string | undefined);\n if (points.length < 2) return;\n\n const path = new Path2D();\n path.moveTo(points[0]![0], points[0]![1]);\n for (let i = 1; i < points.length; i++) {\n path.lineTo(points[i]![0], points[i]![1]);\n }\n const bbox = pointsBBox(points);\n applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n","import { Path2D } from \"@effing/skia\";\nimport type {\n CanvasGradient,\n DOMMatrix2DInit,\n SKRSContext2D,\n} from \"@effing/skia\";\n\nimport parseCssColor from \"parse-css-color\";\n\nimport type { BBox, SvgChild, SvgDefs } from \"./types.ts\";\nimport { normalizeChildren } from \"./tree.ts\";\n\ntype Viewport = SvgDefs[\"viewport\"];\n\n/** Parse a gradient coordinate percentage/fraction to a 0–1 value. */\nfunction parseFrac(value: unknown, fallback: number): number {\n if (value == null) return fallback;\n const s = String(value);\n if (s.endsWith(\"%\")) return parseFloat(s) / 100;\n return Number(s);\n}\n\n/** True when the gradient declares `gradientUnits=\"userSpaceOnUse\"`. */\nfunction isUserSpaceOnUse(props: Record<string, unknown>): boolean {\n return props.gradientUnits === \"userSpaceOnUse\";\n}\n\n/**\n * Parse a user-space gradient coordinate. Percentages resolve against\n * `reference` (the relevant viewport dimension, per the SVG spec).\n */\nfunction parseUserLength(\n value: unknown,\n fallback: number,\n reference: number,\n): number {\n if (value == null) return fallback;\n const s = String(value);\n if (s.endsWith(\"%\")) return (parseFloat(s) / 100) * reference;\n return Number(s);\n}\n\n/** Apply opacity to a CSS color string. */\nexport function applyOpacity(color: string, opacity: number): string {\n if (opacity >= 1) return color;\n const parsed = parseCssColor(color);\n if (!parsed) return color;\n const [r, g, b] = parsed.values;\n return `rgba(${r}, ${g}, ${b}, ${parsed.alpha * opacity})`;\n}\n\n/** Add color stops from SVG `<stop>` children to a canvas gradient. */\nfunction addGradientStops(gradient: CanvasGradient, def: SvgChild): void {\n for (const stop of normalizeChildren(def)) {\n if (stop.type !== \"stop\") continue;\n const sp = stop.props;\n const offsetRaw = (sp.offset as string | number) ?? 0;\n const offset =\n typeof offsetRaw === \"string\" && offsetRaw.endsWith(\"%\")\n ? parseFloat(offsetRaw) / 100\n : Number(offsetRaw);\n const stopColor =\n ((sp.stopColor ?? sp[\"stop-color\"]) as string | undefined) ?? \"black\";\n const stopOpacity = Number(sp.stopOpacity ?? sp[\"stop-opacity\"] ?? 1);\n gradient.addColorStop(offset, applyOpacity(stopColor, stopOpacity));\n }\n}\n\n/** Create a linear gradient from bbox-relative coordinates with stops applied. */\nfunction createLinearGradientFromBBox(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n bbox: BBox,\n def: SvgChild,\n): CanvasGradient {\n const x1 = bbox.x + parseFrac(props.x1, 0) * bbox.width;\n const y1 = bbox.y + parseFrac(props.y1, 0) * bbox.height;\n const x2 = bbox.x + parseFrac(props.x2, 1) * bbox.width;\n const y2 = bbox.y + parseFrac(props.y2, 0) * bbox.height;\n const gradient = ctx.createLinearGradient(x1, y1, x2, y2);\n addGradientStops(gradient, def);\n return gradient;\n}\n\n/**\n * Create a linear gradient from `userSpaceOnUse` coordinates with stops\n * applied. The coordinates are in the SVG user coordinate system, which is\n * the context's current coordinate system (the viewBox transform is active),\n * so they map to canvas gradient coordinates directly.\n */\nfunction createLinearGradientUserSpace(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n viewport: Viewport,\n def: SvgChild,\n): CanvasGradient {\n const x1 = parseUserLength(props.x1, 0, viewport.width);\n const y1 = parseUserLength(props.y1, 0, viewport.height);\n const x2 = parseUserLength(props.x2, viewport.width, viewport.width);\n const y2 = parseUserLength(props.y2, 0, viewport.height);\n const gradient = ctx.createLinearGradient(x1, y1, x2, y2);\n addGradientStops(gradient, def);\n return gradient;\n}\n\n/**\n * Create a radial gradient from `userSpaceOnUse` coordinates with stops\n * applied. In user space the gradient is a true circle, so no elliptical\n * bbox transform is needed. Percentage radii resolve against the\n * viewport's normalized diagonal, per the SVG spec.\n */\nfunction createRadialGradientUserSpace(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n viewport: Viewport,\n def: SvgChild,\n): CanvasGradient {\n const diagonal = Math.hypot(viewport.width, viewport.height) / Math.SQRT2;\n const cx = parseUserLength(props.cx, viewport.width / 2, viewport.width);\n const cy = parseUserLength(props.cy, viewport.height / 2, viewport.height);\n const r = parseUserLength(props.r, diagonal / 2, diagonal);\n const fx = parseUserLength(props.fx, cx, viewport.width);\n const fy = parseUserLength(props.fy, cy, viewport.height);\n const gradient = ctx.createRadialGradient(fx, fy, 0, cx, cy, r);\n addGradientStops(gradient, def);\n return gradient;\n}\n\n/**\n * Fill `path` with a gradient defined by `def` in the coordinate space of `bbox`.\n *\n * With `gradientUnits=\"userSpaceOnUse\"` the gradient coordinates are already\n * in the SVG user coordinate system and are used as-is.\n *\n * With the default `objectBoundingBox` units, coordinates are fractions of\n * `bbox`. For `<linearGradient>` the bbox-to-canvas mapping is\n * straightforward. For `<radialGradient>` a non-square bbox produces an\n * *elliptical* gradient. Canvas only supports circular radial gradients, so\n * we apply a non-uniform scale transform to the context and fill an\n * inverse-transformed copy of the path.\n */\nexport function fillWithSvgGradient(\n ctx: SKRSContext2D,\n def: SvgChild,\n bbox: BBox,\n path: Path2D,\n fillRule: CanvasFillRule,\n viewport: Viewport,\n): boolean {\n const props = def.props;\n\n if (def.type === \"linearGradient\") {\n ctx.fillStyle = isUserSpaceOnUse(props)\n ? createLinearGradientUserSpace(ctx, props, viewport, def)\n : createLinearGradientFromBBox(ctx, props, bbox, def);\n ctx.fill(path, fillRule);\n return true;\n }\n\n if (def.type === \"radialGradient\" && isUserSpaceOnUse(props)) {\n ctx.fillStyle = createRadialGradientUserSpace(ctx, props, viewport, def);\n ctx.fill(path, fillRule);\n return true;\n }\n\n if (def.type === \"radialGradient\") {\n const cxF = parseFrac(props.cx, 0.5);\n const cyF = parseFrac(props.cy, 0.5);\n const rF = parseFrac(props.r, 0.5);\n const fxF = parseFrac(props.fx, cxF);\n const fyF = parseFrac(props.fy, cyF);\n\n // Render in a transformed space where the bbox maps to a unit square.\n // This turns canvas's circular radial gradient into the correct ellipse.\n ctx.save();\n ctx.translate(bbox.x, bbox.y);\n ctx.scale(bbox.width, bbox.height);\n\n const gradient = ctx.createRadialGradient(fxF, fyF, 0, cxF, cyF, rF);\n addGradientStops(gradient, def);\n ctx.fillStyle = gradient;\n\n // The path is in original (absolute) coordinates. Inverse-transform it\n // into the unit-square space so the fill aligns with the shape.\n // inverse of translate(bx,by) · scale(bw,bh) = scale(1/bw,1/bh) · translate(-bx,-by)\n const unitPath = new Path2D();\n const invTransform: DOMMatrix2DInit = {\n a: 1 / bbox.width,\n b: 0,\n c: 0,\n d: 1 / bbox.height,\n e: -bbox.x / bbox.width,\n f: -bbox.y / bbox.height,\n };\n unitPath.addPath(path, invTransform);\n\n ctx.fill(unitPath, fillRule);\n ctx.restore();\n return true;\n }\n\n return false;\n}\n\n/**\n * Stroke `path` with a gradient defined by `def` in the coordinate space of `bbox`.\n */\nexport function strokeWithSvgGradient(\n ctx: SKRSContext2D,\n def: SvgChild,\n bbox: BBox,\n path: Path2D,\n viewport: Viewport,\n): boolean {\n const props = def.props;\n\n if (def.type === \"linearGradient\") {\n ctx.strokeStyle = isUserSpaceOnUse(props)\n ? createLinearGradientUserSpace(ctx, props, viewport, def)\n : createLinearGradientFromBBox(ctx, props, bbox, def);\n ctx.stroke(path);\n return true;\n }\n\n if (def.type === \"radialGradient\" && isUserSpaceOnUse(props)) {\n ctx.strokeStyle = createRadialGradientUserSpace(ctx, props, viewport, def);\n ctx.stroke(path);\n return true;\n }\n\n if (def.type === \"radialGradient\") {\n // For stroke, use a simple circular approximation (geometric mean radius)\n const cxAbs = bbox.x + parseFrac(props.cx, 0.5) * bbox.width;\n const cyAbs = bbox.y + parseFrac(props.cy, 0.5) * bbox.height;\n const rAbs = parseFrac(props.r, 0.5) * Math.sqrt(bbox.width * bbox.height);\n const fxAbs = bbox.x + parseFrac(props.fx, 0.5) * bbox.width;\n const fyAbs = bbox.y + parseFrac(props.fy, 0.5) * bbox.height;\n const gradient = ctx.createRadialGradient(\n fxAbs,\n fyAbs,\n 0,\n cxAbs,\n cyAbs,\n rAbs,\n );\n addGradientStops(gradient, def);\n ctx.strokeStyle = gradient;\n ctx.stroke(path);\n return true;\n }\n\n return false;\n}\n","import type { Path2D, SKRSContext2D } from \"@effing/skia\";\n\nimport type { BBox, InheritedSvgStyle, SvgDefs } from \"./types.ts\";\nimport { resolveCurrentColor } from \"./style.ts\";\nimport { parseUrlRef } from \"./style.ts\";\nimport {\n applyOpacity,\n fillWithSvgGradient,\n strokeWithSvgGradient,\n} from \"./gradients.ts\";\n\nexport function applyFillAndStroke(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n path: Path2D,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n bbox: BBox,\n): void {\n // Use element's own fill if set, otherwise inherit from parent\n const fill =\n resolveCurrentColor(props.fill as string | undefined, color) ??\n inherited.fill;\n const fillRule = (props.fillRule ?? props[\"fill-rule\"]) as\n CanvasFillRule | undefined;\n const fillOpacity = Number(props.fillOpacity ?? props[\"fill-opacity\"] ?? 1);\n\n // Resolve url(#id) gradient reference\n const fillRef = parseUrlRef(fill);\n if (fillRef) {\n const gradientDef = defs.gradients.get(fillRef);\n if (gradientDef) {\n if (fillOpacity < 1) {\n ctx.save();\n ctx.globalAlpha *= fillOpacity;\n fillWithSvgGradient(\n ctx,\n gradientDef,\n bbox,\n path,\n fillRule ?? \"nonzero\",\n defs.viewport,\n );\n ctx.restore();\n } else {\n fillWithSvgGradient(\n ctx,\n gradientDef,\n bbox,\n path,\n fillRule ?? \"nonzero\",\n defs.viewport,\n );\n }\n }\n } else if (fill !== \"none\") {\n ctx.fillStyle = applyOpacity(fill, fillOpacity);\n ctx.fill(path, fillRule ?? \"nonzero\");\n }\n\n applyStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function applyStroke(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n path: Path2D,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n bbox: BBox,\n): void {\n const stroke =\n resolveCurrentColor(props.stroke as string | undefined, color) ??\n inherited.stroke;\n if (!stroke || stroke === \"none\") return;\n\n const strokeOpacity = Number(\n props.strokeOpacity ??\n props[\"stroke-opacity\"] ??\n inherited.strokeOpacity ??\n 1,\n );\n\n ctx.lineWidth = Number(\n props.strokeWidth ?? props[\"stroke-width\"] ?? inherited.strokeWidth ?? 1,\n );\n ctx.lineCap = (((props.strokeLinecap ??\n props[\"stroke-linecap\"]) as CanvasLineCap) ??\n inherited.strokeLinecap ??\n \"butt\") as CanvasLineCap;\n ctx.lineJoin = (((props.strokeLinejoin ??\n props[\"stroke-linejoin\"]) as CanvasLineJoin) ??\n inherited.strokeLinejoin ??\n \"miter\") as CanvasLineJoin;\n\n // Resolve url(#id) gradient reference for stroke\n const strokeRef = parseUrlRef(stroke);\n if (strokeRef) {\n const gradientDef = defs.gradients.get(strokeRef);\n if (gradientDef) {\n if (strokeOpacity < 1) {\n ctx.save();\n ctx.globalAlpha *= strokeOpacity;\n strokeWithSvgGradient(ctx, gradientDef, bbox, path, defs.viewport);\n ctx.restore();\n } else {\n strokeWithSvgGradient(ctx, gradientDef, bbox, path, defs.viewport);\n }\n return;\n }\n }\n\n ctx.strokeStyle = applyOpacity(stroke, strokeOpacity);\n ctx.stroke(path);\n}\n","import type { Canvas, SKRSContext2D } from \"@effing/skia\";\n\nimport type { InheritedSvgStyle, SvgChild, SvgDefs } from \"./types.ts\";\nimport { EMPTY_DEFS } from \"./defs.ts\";\nimport { normalizeChildren } from \"./tree.ts\";\nimport {\n mergeStyleIntoProps,\n parseUrlRef,\n resolveInheritedStyle,\n} from \"./style.ts\";\nimport { applyTransformAndOpacity } from \"./transform.ts\";\nimport { buildClipPath } from \"./path.ts\";\nimport { applyFilter } from \"./filters.ts\";\nimport { acquireOffscreen, releaseOffscreen } from \"../offscreen.ts\";\nimport {\n drawPath,\n drawCircle,\n drawSvgRect,\n drawLine,\n drawEllipse,\n drawPolygon,\n drawPolyline,\n} from \"./shapes.ts\";\n\nexport function drawSvgChild(\n ctx: SKRSContext2D,\n child: SvgChild,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs = EMPTY_DEFS,\n vbW = 0,\n vbH = 0,\n): void {\n const { type } = child;\n const props = mergeStyleIntoProps(child.props);\n\n // Skip non-drawable definition elements\n if (\n type === \"defs\" ||\n type === \"clipPath\" ||\n type === \"mask\" ||\n type === \"filter\"\n )\n return;\n\n // Apply transform and opacity on shape elements (drawGroup handles its own)\n const transform =\n type !== \"g\" ? (props.transform as string | undefined) : undefined;\n const opacity = type !== \"g\" ? Number(props.opacity ?? 1) : 1;\n const savedTransform = applyTransformAndOpacity(ctx, transform, opacity);\n\n // Check for clip-path=\"url(#id)\" reference\n const clipRef = parseUrlRef(props.clipPath ?? props[\"clip-path\"]);\n const clipShapes = clipRef ? defs.clips.get(clipRef) : undefined;\n const clipPath = clipShapes ? buildClipPath(clipShapes, vbW, vbH) : undefined;\n\n // Check for mask=\"url(#id)\" reference\n const maskRef = parseUrlRef(props.mask as string | undefined);\n const maskShapes = maskRef ? defs.masks.get(maskRef) : undefined;\n\n // Check for filter=\"url(#id)\" reference\n const filterRef = parseUrlRef(props.filter as string | undefined);\n const filterDef = filterRef ? defs.filters.get(filterRef) : undefined;\n\n if (clipPath) {\n ctx.save();\n ctx.clip(clipPath);\n }\n\n // When a mask or filter is present, render the element to an offscreen\n // canvas so we can post-process it before drawing to the main context.\n const needsOffscreen = maskShapes || filterDef;\n let elemCanvas: Canvas | undefined;\n let targetCtx: SKRSContext2D;\n if (needsOffscreen) {\n const [c, cCtx] = acquireOffscreen(Math.ceil(vbW), Math.ceil(vbH));\n elemCanvas = c;\n targetCtx = cCtx;\n } else {\n targetCtx = ctx;\n }\n\n switch (type) {\n case \"path\":\n drawPath(targetCtx, props, inherited, color, defs);\n break;\n case \"circle\":\n drawCircle(targetCtx, props, inherited, color, defs, vbW, vbH);\n break;\n case \"rect\":\n drawSvgRect(targetCtx, props, inherited, color, defs, vbW, vbH);\n break;\n case \"line\":\n drawLine(targetCtx, props, inherited, color, defs, vbW, vbH);\n break;\n case \"ellipse\":\n drawEllipse(targetCtx, props, inherited, color, defs, vbW, vbH);\n break;\n case \"polygon\":\n drawPolygon(targetCtx, props, inherited, color, defs);\n break;\n case \"polyline\":\n drawPolyline(targetCtx, props, inherited, color, defs);\n break;\n case \"g\":\n drawGroup(targetCtx, child, props, inherited, color, defs, vbW, vbH);\n break;\n }\n\n if (needsOffscreen && elemCanvas) {\n applyOffscreenEffects(\n ctx,\n elemCanvas,\n targetCtx,\n maskShapes,\n filterDef,\n color,\n defs,\n vbW,\n vbH,\n );\n }\n\n if (clipPath) ctx.restore();\n if (savedTransform) ctx.restore();\n}\n\nfunction drawGroup(\n ctx: SKRSContext2D,\n node: SvgChild,\n mergedProps: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs = EMPTY_DEFS,\n vbW = 0,\n vbH = 0,\n): void {\n const children = normalizeChildren(node);\n if (children.length === 0) return;\n const groupInherited = resolveInheritedStyle(mergedProps, color, inherited);\n\n const opacity = Number(mergedProps.opacity ?? 1);\n const transform = mergedProps.transform as string | undefined;\n const saved = applyTransformAndOpacity(ctx, transform, opacity);\n\n for (const child of children) {\n if (child != null && typeof child === \"object\") {\n drawSvgChild(ctx, child, groupInherited, color, defs, vbW, vbH);\n }\n }\n\n if (saved) ctx.restore();\n}\n\n/** Composite mask and/or filter effects from offscreen canvas onto main context. */\nfunction applyOffscreenEffects(\n ctx: SKRSContext2D,\n elemCanvas: Canvas,\n targetCtx: SKRSContext2D,\n maskShapes: SvgChild[] | undefined,\n filterDef: SvgChild | undefined,\n color: string,\n defs: SvgDefs,\n vbW: number,\n vbH: number,\n): void {\n // Apply mask if present\n if (maskShapes) {\n const [maskCanvas, maskCtx] = acquireOffscreen(\n Math.ceil(vbW),\n Math.ceil(vbH),\n );\n for (const shape of maskShapes) {\n drawSvgChild(maskCtx, shape, { fill: \"white\" }, \"white\", defs, vbW, vbH);\n }\n targetCtx.globalCompositeOperation = \"destination-in\";\n targetCtx.drawImage(maskCanvas, 0, 0);\n targetCtx.globalCompositeOperation = \"source-over\";\n releaseOffscreen(maskCanvas);\n }\n\n // Apply filter if present\n if (filterDef) {\n const filteredCanvas = applyFilter(\n filterDef,\n elemCanvas,\n Math.ceil(vbW),\n Math.ceil(vbH),\n );\n ctx.drawImage(filteredCanvas, 0, 0);\n // Release intermediates (filteredCanvas may be elemCanvas if no-op)\n if (filteredCanvas !== elemCanvas) releaseOffscreen(filteredCanvas);\n } else {\n ctx.drawImage(elemCanvas, 0, 0);\n }\n releaseOffscreen(elemCanvas);\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\n\nimport type { LayoutNode } from \"../../layout.ts\";\nimport type { SvgChild } from \"./types.ts\";\nimport { mergeStyleIntoProps, resolveInheritedStyle } from \"./style.ts\";\nimport { collectDefs } from \"./defs.ts\";\nimport { drawSvgChild } from \"./traverse.ts\";\n\n/**\n * Draw an `<svg>` container and its SVG children (path, circle, rect, etc.).\n *\n * Parses the `viewBox` prop to compute scale factors, then recurses into\n * the React children stored in `node.props.children`.\n */\nexport function drawSvgContainer(\n ctx: SKRSContext2D,\n node: LayoutNode,\n x: number,\n y: number,\n width: number,\n height: number,\n): void {\n ctx.save();\n ctx.translate(x, y);\n\n // Parse viewBox for coordinate mapping; default to rendered size when absent\n const viewBox = node.props.viewBox as string | undefined;\n let vbW = width;\n let vbH = height;\n if (viewBox) {\n const parts = viewBox.split(/[\\s,]+/).map(Number);\n if (parts.length === 4) {\n const [vbX, vbY, parsedW, parsedH] = parts as [\n number,\n number,\n number,\n number,\n ];\n vbW = parsedW;\n vbH = parsedH;\n const scaleX = width / vbW;\n const scaleY = height / vbH;\n ctx.scale(scaleX, scaleY);\n ctx.translate(-vbX, -vbY);\n }\n }\n\n // Resolve the CSS `color` property for `currentColor` references\n const color = (node.style.color as string | undefined) ?? \"black\";\n\n // Build inherited SVG style from the <svg> element\n const merged = mergeStyleIntoProps(node.props);\n const inherited = resolveInheritedStyle(merged, color);\n\n // Traverse React children\n const children = node.props.children;\n if (children != null) {\n // Deep-flatten so helpers returning arrays don't slip nested arrays through\n // to the defs collector or shape switch (both expect element-shaped nodes).\n const childArray = (\n Array.isArray(children) ? children.flat(Infinity) : [children]\n ) as unknown[];\n const svgChildren = childArray.filter(\n (c): c is SvgChild =>\n c != null && typeof c === \"object\" && !Array.isArray(c),\n );\n\n // First pass: collect definitions from <defs>\n const defs = collectDefs(svgChildren, vbW, vbH);\n\n // Second pass: draw children\n for (const child of svgChildren) {\n drawSvgChild(ctx, child, inherited, color, defs, vbW, vbH);\n }\n }\n\n ctx.restore();\n}\n","import { loadImage } from \"@effing/skia\";\nimport type { SKRSContext2D, Image } from \"@effing/skia\";\nimport { fillParagraph, strokeParagraph } from \"@effing/skia/extensions\";\n\nimport parseCssColor from \"parse-css-color\";\n\nimport type { EmojiStyle } from \"../emoji.ts\";\nimport { getEmojiCode, loadEmoji } from \"../emoji.ts\";\nimport type { TextSegment } from \"../text/index.ts\";\nimport type { NativeParagraph } from \"../text/native.ts\";\nimport { splitTextIntoRuns } from \"../text/emoji-split.ts\";\nimport { setFont } from \"../text/measure.ts\";\n\nconst emojiImageCache = new Map<string, Promise<Image | null>>();\n\nfunction loadEmojiImage(\n style: EmojiStyle,\n char: string,\n): Promise<Image | null> {\n const code = getEmojiCode(char);\n const key = style + \":\" + code;\n let cached = emojiImageCache.get(key);\n if (!cached) {\n cached = loadEmoji(style, code)\n .then((svgText) => {\n if (!svgText || !svgText.includes(\"<svg\")) return null;\n const dataUri =\n \"data:image/svg+xml;base64,\" +\n Buffer.from(svgText).toString(\"base64\");\n return loadImage(dataUri);\n })\n .catch(() => null);\n emojiImageCache.set(key, cached);\n }\n return cached;\n}\n\n/**\n * Draw text segments onto the canvas context, unhinted and unsnapped (see\n * `withUnsnappedText`).\n *\n * @param ctx - Canvas 2D rendering context\n * @param segments - Positioned text segments from the text layout engine\n * @param offsetX - X offset for the text block\n * @param offsetY - Y offset for the text block\n * @param textShadow - Optional text-shadow CSS value\n * @param emojiStyle - Optional emoji style for rendering emoji as images\n * @param native - The natively laid-out paragraph to paint instead of the\n * segments, with its vertical offset in the text block\n */\nexport async function drawText(\n ctx: SKRSContext2D,\n segments: TextSegment[],\n offsetX: number,\n offsetY: number,\n textShadow?: string,\n emojiStyle?: EmojiStyle,\n native?: { paragraph: NativeParagraph; offsetY: number },\n): Promise<void> {\n if (native) {\n drawParagraph(\n ctx,\n native.paragraph,\n segments,\n offsetX,\n offsetY,\n native.offsetY,\n textShadow,\n );\n return;\n }\n // Emoji images load asynchronously, so the setting is held across awaits\n // rather than through `withUnsnappedText`.\n const textRendering = ctx.textRendering;\n ctx.textRendering = \"geometricPrecision\";\n try {\n await drawSegments(ctx, segments, offsetX, offsetY, textShadow, emojiStyle);\n } finally {\n ctx.textRendering = textRendering;\n }\n}\n\n/**\n * Paint a natively laid-out paragraph: shadow, stroke and fill passes as for\n * segments, each a single native call for the whole paragraph. A paragraph\n * always paints unhinted and unsnapped.\n */\nfunction drawParagraph(\n ctx: SKRSContext2D,\n paragraph: NativeParagraph,\n segments: TextSegment[],\n offsetX: number,\n offsetY: number,\n paragraphOffsetY: number,\n textShadow?: string,\n): void {\n const first = segments[0];\n if (!first) return;\n const x = offsetX;\n const y = offsetY + paragraphOffsetY;\n const shadow = textShadow ? parseShadow(textShadow) : null;\n ctx.fillStyle = first.color;\n\n if (shadow) {\n drawShadowPass(ctx, shadow, getColorAlpha(first.color), () =>\n fillParagraph(ctx, paragraph, x, y),\n );\n }\n if (first.textStrokeWidth !== undefined && first.textStrokeWidth > 0) {\n ctx.save();\n ctx.lineWidth = first.textStrokeWidth;\n ctx.strokeStyle = first.textStrokeColor ?? first.color;\n ctx.lineJoin = \"round\";\n strokeParagraph(ctx, paragraph, x, y);\n ctx.restore();\n }\n fillParagraph(ctx, paragraph, x, y);\n\n for (const seg of segments) {\n if (seg.textDecoration) {\n drawTextDecoration(ctx, seg, offsetX, offsetY);\n }\n }\n}\n\nasync function drawSegments(\n ctx: SKRSContext2D,\n segments: TextSegment[],\n offsetX: number,\n offsetY: number,\n textShadow?: string,\n emojiStyle?: EmojiStyle,\n): Promise<void> {\n const shadow = textShadow ? parseShadow(textShadow) : null;\n\n for (const seg of segments) {\n if (!seg.text) continue;\n\n setFont(ctx, seg.fontSize, seg.fontFamily, seg.fontWeight, seg.fontStyle);\n ctx.fillStyle = seg.color;\n\n const x = offsetX + seg.x;\n const y = offsetY + seg.y;\n const textAlpha = shadow ? getColorAlpha(seg.color) : 1;\n\n const hasStroke =\n seg.textStrokeWidth !== undefined && seg.textStrokeWidth > 0;\n\n if (emojiStyle) {\n await drawSegmentWithEmoji(\n ctx,\n seg,\n x,\n y,\n textShadow,\n emojiStyle,\n hasStroke,\n );\n } else if (seg.letterSpacing && seg.letterSpacing !== 0) {\n if (shadow) {\n drawShadowPass(ctx, shadow, textAlpha, () =>\n drawTextWithLetterSpacing(ctx, seg.text, x, y, seg.letterSpacing),\n );\n }\n if (hasStroke) {\n drawStrokeWithLetterSpacing(\n ctx,\n seg.text,\n x,\n y,\n seg.letterSpacing,\n seg.textStrokeWidth!,\n seg.textStrokeColor ?? seg.color,\n );\n }\n drawTextWithLetterSpacing(ctx, seg.text, x, y, seg.letterSpacing);\n } else {\n if (shadow) {\n drawShadowPass(ctx, shadow, textAlpha, () =>\n ctx.fillText(seg.text, x, y),\n );\n }\n if (hasStroke) {\n ctx.save();\n ctx.lineWidth = seg.textStrokeWidth!;\n ctx.strokeStyle = seg.textStrokeColor ?? seg.color;\n ctx.lineJoin = \"round\";\n ctx.strokeText(seg.text, x, y);\n ctx.restore();\n }\n ctx.fillText(seg.text, x, y);\n }\n\n // Text decoration\n if (seg.textDecoration) {\n drawTextDecoration(ctx, seg, offsetX, offsetY);\n }\n }\n}\n\nasync function drawSegmentWithEmoji(\n ctx: SKRSContext2D,\n seg: TextSegment,\n x: number,\n y: number,\n textShadow: string | undefined,\n emojiStyle: EmojiStyle,\n hasStroke?: boolean,\n): Promise<void> {\n const letterSpacing = seg.letterSpacing ?? 0;\n const runs = splitTextIntoRuns(\n seg.text,\n (text) => {\n setFont(ctx, seg.fontSize, seg.fontFamily, seg.fontWeight, seg.fontStyle);\n return ctx.measureText(text).width;\n },\n seg.fontSize,\n letterSpacing,\n );\n\n const shadow = textShadow ? parseShadow(textShadow) : null;\n const textAlpha = shadow ? getColorAlpha(seg.color) : 1;\n\n for (const run of runs) {\n if (run.kind === \"text\") {\n if (shadow) {\n if (letterSpacing !== 0) {\n drawShadowPass(ctx, shadow, textAlpha, () =>\n drawTextWithLetterSpacing(\n ctx,\n run.text,\n x + run.x,\n y,\n letterSpacing,\n ),\n );\n } else {\n drawShadowPass(ctx, shadow, textAlpha, () =>\n ctx.fillText(run.text, x + run.x, y),\n );\n }\n }\n if (hasStroke) {\n if (letterSpacing !== 0) {\n drawStrokeWithLetterSpacing(\n ctx,\n run.text,\n x + run.x,\n y,\n letterSpacing,\n seg.textStrokeWidth!,\n seg.textStrokeColor ?? seg.color,\n );\n } else {\n ctx.save();\n ctx.lineWidth = seg.textStrokeWidth!;\n ctx.strokeStyle = seg.textStrokeColor ?? seg.color;\n ctx.lineJoin = \"round\";\n ctx.strokeText(run.text, x + run.x, y);\n ctx.restore();\n }\n }\n if (letterSpacing !== 0) {\n drawTextWithLetterSpacing(ctx, run.text, x + run.x, y, letterSpacing);\n } else {\n ctx.fillText(run.text, x + run.x, y);\n }\n } else {\n const img = await loadEmojiImage(emojiStyle, run.char);\n if (img) {\n const emojiSize = seg.fontSize;\n // Position emoji so it aligns vertically with text:\n // y is the baseline, ascent goes up from baseline\n const emojiY = y - seg.ascent + (seg.height - seg.fontSize) / 2;\n ctx.drawImage(img, x + run.x, emojiY, emojiSize, emojiSize);\n } else {\n // Emoji image unavailable — fall back to text rendering\n ctx.fillText(run.char, x + run.x, y);\n }\n }\n }\n}\n\nfunction drawTextWithLetterSpacing(\n ctx: SKRSContext2D,\n text: string,\n x: number,\n y: number,\n letterSpacing: number,\n): void {\n let currentX = x;\n for (const char of text) {\n ctx.fillText(char, currentX, y);\n const metrics = ctx.measureText(char);\n currentX += metrics.width + letterSpacing;\n }\n}\n\nfunction drawStrokeWithLetterSpacing(\n ctx: SKRSContext2D,\n text: string,\n x: number,\n y: number,\n letterSpacing: number,\n strokeWidth: number,\n strokeColor: string,\n): void {\n ctx.save();\n ctx.lineWidth = strokeWidth;\n ctx.strokeStyle = strokeColor;\n ctx.lineJoin = \"round\";\n let currentX = x;\n for (const char of text) {\n ctx.strokeText(char, currentX, y);\n const metrics = ctx.measureText(char);\n currentX += metrics.width + letterSpacing;\n }\n ctx.restore();\n}\n\ninterface ParsedShadow {\n offsetX: number;\n offsetY: number;\n blur: number;\n color: string;\n}\n\nfunction parseShadow(shadow: string): ParsedShadow | null {\n const parts = shadow.match(\n /(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(.*)/,\n );\n if (!parts) return null;\n return {\n offsetX: parseFloat(parts[1]!),\n offsetY: parseFloat(parts[2]!),\n blur: parseFloat(parts[3]!),\n color: parts[4]!.trim(),\n };\n}\n\n/** Extract the alpha component from a CSS color string. */\nfunction getColorAlpha(color: string): number {\n const parsed = parseCssColor(color);\n return parsed ? parsed.alpha : 1;\n}\n\n/**\n * Draw the text shadow manually instead of using the canvas shadow API.\n *\n * CSS text-shadow renders the shadow as if derived from the text's painted\n * appearance, so when the text color has alpha < 1 the shadow is also\n * attenuated. The canvas shadow API does NOT do this — it always renders\n * the shadow at the full specified opacity. We match CSS behavior by\n * drawing the shadow as a separate fillText at the offset, with\n * globalAlpha scaled by the text color's alpha.\n */\nfunction drawShadowPass(\n ctx: SKRSContext2D,\n shadow: ParsedShadow,\n textAlpha: number,\n drawFn: () => void,\n): void {\n ctx.save();\n ctx.fillStyle = shadow.color;\n if (textAlpha < 1) ctx.globalAlpha *= textAlpha;\n if (shadow.blur > 0) ctx.filter = `blur(${shadow.blur / 2}px)`;\n ctx.translate(shadow.offsetX, shadow.offsetY);\n drawFn();\n ctx.restore();\n}\n\nfunction drawTextDecoration(\n ctx: SKRSContext2D,\n seg: TextSegment,\n offsetX: number,\n offsetY: number,\n): void {\n const decoration = seg.textDecoration;\n if (!decoration || decoration === \"none\") return;\n\n ctx.strokeStyle = seg.color;\n ctx.lineWidth = Math.max(1, seg.fontSize * 0.1);\n\n const x = offsetX + seg.x;\n const baseY = offsetY + seg.y;\n\n if (decoration.includes(\"underline\")) {\n const y = baseY + seg.ascent * 0.1;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + seg.width, y);\n ctx.stroke();\n }\n\n if (decoration.includes(\"line-through\")) {\n const y = baseY - seg.fontSize * 0.3;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + seg.width, y);\n ctx.stroke();\n }\n\n if (decoration.includes(\"overline\")) {\n const y = baseY - seg.fontSize * 0.85;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + seg.width, y);\n ctx.stroke();\n }\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\n/**\n * Emoji style options for rendering\n */\nexport type EmojiStyle =\n | \"twemoji\"\n | \"openmoji\"\n | \"blobmoji\"\n | \"noto\"\n | \"fluent\"\n | \"fluentFlat\";\n\nexport const emojiApis: Record<\n EmojiStyle,\n string | ((code: string) => string)\n> = {\n twemoji: (code: string) =>\n `https://cdnjs.cloudflare.com/ajax/libs/twemoji/16.0.1/svg/${code.toLowerCase()}.svg`,\n openmoji: \"https://cdn.jsdelivr.net/npm/@svgmoji/openmoji@2.0.0/svg/\",\n blobmoji: \"https://cdn.jsdelivr.net/npm/@svgmoji/blob@2.0.0/svg/\",\n noto: \"https://cdn.jsdelivr.net/gh/svgmoji/svgmoji/packages/svgmoji__noto/svg/\",\n fluent: (code: string) =>\n `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${code.toLowerCase()}_color.svg`,\n fluentFlat: (code: string) =>\n `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${code.toLowerCase()}_flat.svg`,\n};\n\nconst U200D = String.fromCharCode(8205);\nconst UFE0Fg = /\\uFE0F/g;\n\nexport function getEmojiCode(char: string): string {\n return toCodePoint(char.indexOf(U200D) < 0 ? char.replace(UFE0Fg, \"\") : char);\n}\n\nexport function toCodePoint(unicodeSurrogates: string): string {\n const r: string[] = [];\n let c = 0,\n p = 0,\n i = 0;\n\n while (i < unicodeSurrogates.length) {\n c = unicodeSurrogates.charCodeAt(i++);\n if (p) {\n r.push((65536 + ((p - 55296) << 10) + (c - 56320)).toString(16));\n p = 0;\n } else if (55296 <= c && c <= 56319) {\n p = c;\n } else {\n r.push(c.toString(16));\n }\n }\n return r.join(\"-\");\n}\n\nconst emojiCache: Record<string, Promise<string>> = {};\n\nexport async function loadEmoji(\n type: EmojiStyle,\n code: string,\n): Promise<string> {\n const key = type + \":\" + code;\n if (key in emojiCache) return emojiCache[key];\n\n const api = emojiApis[type];\n const url =\n typeof api === \"function\" ? api(code) : `${api}${code.toUpperCase()}.svg`;\n return (emojiCache[key] = fetch(url).then((r) => r.text()));\n}\n","import { isEmoji } from \"../language.ts\";\n\nexport type TextRun =\n | { kind: \"text\"; text: string; x: number; width: number }\n | { kind: \"emoji\"; char: string; x: number; width: number };\n\n/**\n * Split a text string into runs of plain text and individual emoji characters.\n * Uses Intl.Segmenter for correct grapheme cluster handling (multi-codepoint emoji).\n */\nexport function splitTextIntoRuns(\n text: string,\n measureText: (text: string) => number,\n emojiSize: number,\n letterSpacing: number = 0,\n): TextRun[] {\n const runs: TextRun[] = [];\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n let currentText = \"\";\n let currentGraphemeCount = 0;\n let currentX = 0;\n let textStartX = 0;\n\n for (const { segment } of segmenter.segment(text)) {\n if (isEmojiGrapheme(segment)) {\n // Flush accumulated text\n if (currentText) {\n const textWidth = measureText(currentText);\n runs.push({\n kind: \"text\",\n text: currentText,\n x: textStartX,\n width: textWidth + letterSpacing * currentGraphemeCount,\n });\n currentX =\n textStartX + textWidth + letterSpacing * currentGraphemeCount;\n currentText = \"\";\n currentGraphemeCount = 0;\n }\n runs.push({\n kind: \"emoji\",\n char: segment,\n x: currentX,\n width: emojiSize,\n });\n currentX += emojiSize + letterSpacing;\n textStartX = currentX;\n } else {\n if (!currentText) textStartX = currentX;\n currentText += segment;\n currentGraphemeCount++;\n }\n }\n\n // Flush remaining text\n if (currentText) {\n const textWidth = measureText(currentText);\n runs.push({\n kind: \"text\",\n text: currentText,\n x: textStartX,\n width: textWidth + letterSpacing * currentGraphemeCount,\n });\n }\n\n return runs;\n}\n\n/**\n * Check if a grapheme cluster is an emoji.\n * Checks the first code point of the grapheme.\n */\nfunction isEmojiGrapheme(grapheme: string): boolean {\n for (const char of grapheme) {\n if (isEmoji(char)) return true;\n }\n return false;\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\n\nimport type { EmojiStyle } from \"../emoji.ts\";\nimport { cachedLoadImage } from \"../../image.ts\";\nimport type { LayoutNode } from \"../layout.ts\";\nimport type { RenderContext } from \"../context.ts\";\nimport { layoutText } from \"../text/index.ts\";\nimport { applyClip, hasRadius, roundedRect } from \"./clip.ts\";\nimport { applyClipPath } from \"./clip-path.ts\";\nimport { createGradientFromCSS, splitGradientArgs } from \"./gradient.ts\";\nimport {\n beginElementGroup,\n drawBackdropFilter,\n endElementGroup,\n} from \"./group.ts\";\nimport { drawImage } from \"./image.ts\";\nimport { computeContain, computeCover } from \"./object-fit.ts\";\nimport { drawBoxShadow, drawRect, getBorderRadiusFromStyle } from \"./rect.ts\";\nimport { drawSvgContainer } from \"./svg/index.ts\";\nimport { drawText } from \"./text.ts\";\nimport { parseCSSLength, resolveBoxValue } from \"./utils.ts\";\n\n/**\n * Main draw dispatcher: recursively draws the layout tree onto the canvas.\n *\n * Every node, scaled or not, is drawn straight through its transform. Text is\n * drawn unhinted and unsnapped (see `drawText`), so it lands in the same place\n * at any scale and a scaled subtree needs no supersampled offscreen buffer.\n */\nexport async function drawNode(\n ctx: SKRSContext2D,\n node: LayoutNode,\n parentX: number,\n parentY: number,\n context?: RenderContext,\n emojiStyle?: EmojiStyle,\n): Promise<void> {\n const x = parentX + node.x;\n const y = parentY + node.y;\n const { style } = node;\n\n // Resolve a context once so the whole subtree shares one image cache.\n const renderContext: RenderContext = context ?? {\n imageCache: new Map(),\n debug: false,\n };\n\n if (style.display === \"none\") return;\n\n // A numeric string counts, as it does in CSS; anything that isn't a\n // number leaves the element opaque.\n const rawOpacity = Number(style.opacity ?? 1);\n const opacity = Number.isFinite(rawOpacity) ? rawOpacity : 1;\n if (opacity <= 0) return;\n\n // Painting awaits image loads, which can fail. The group and the save are\n // closed either way, so a caller that catches the error and draws the next\n // frame on this context doesn't paint into a layer left open.\n const group = { open: false };\n ctx.save();\n try {\n await paintNode(ctx, node, x, y, opacity, renderContext, emojiStyle, group);\n } finally {\n if (group.open) endElementGroup(ctx);\n ctx.restore();\n }\n}\n\n/** Paints a node inside the save that `drawNode` opened for it. */\nasync function paintNode(\n ctx: SKRSContext2D,\n node: LayoutNode,\n x: number,\n y: number,\n opacity: number,\n renderContext: RenderContext,\n emojiStyle: EmojiStyle | undefined,\n group: { open: boolean },\n): Promise<void> {\n const { width, height, style } = node;\n\n if (style.transform) {\n applyTransform(\n ctx,\n style.transform,\n x,\n y,\n width,\n height,\n style.transformOrigin,\n );\n }\n\n // Apply clip-path — in the element's own (transformed) coordinate space, and\n // before anything is painted, since it clips the element's entire rendering\n // including its box-shadow.\n if (style.clipPath) {\n applyClipPath(ctx, style.clipPath, style, x, y, width, height);\n }\n\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n\n // Filter the backdrop behind the border box before anything of the element\n // itself is painted: its box-shadow must not end up in the backdrop, and its\n // background composites on top of the filtered result.\n if (style.backdropFilter) {\n drawBackdropFilter(\n ctx,\n style.backdropFilter,\n x,\n y,\n width,\n height,\n borderRadius,\n opacity,\n );\n }\n\n // The element's own painting and its descendants form one group, composited\n // with its opacity and filter. CSS applies clip-path after the filter, so the\n // clip above also clips the filtered result. The backdrop above stays outside\n // the group: a group's backdrop is read from the enclosing one.\n group.open = beginElementGroup(ctx, opacity, style.filter);\n\n // Draw box-shadow BEFORE overflow clip — CSS overflow:hidden clips children,\n // not the element's own box-shadow.\n if (style.boxShadow) {\n drawBoxShadow(ctx, x, y, width, height, style.boxShadow, borderRadius);\n }\n\n // Apply clipping for overflow: hidden\n const isClipped =\n style.overflow === \"hidden\" ||\n style.overflowX === \"hidden\" ||\n style.overflowY === \"hidden\";\n\n if (isClipped) {\n applyClip(ctx, x, y, width, height, borderRadius);\n }\n\n // Draw background and borders\n if (\n style.backgroundColor ||\n style.borderTopWidth ||\n style.borderRightWidth ||\n style.borderBottomWidth ||\n style.borderLeftWidth\n ) {\n drawRect(ctx, x, y, width, height, style);\n }\n\n // Draw background-image (gradient or url) — supports multiple comma-separated layers\n if (style.backgroundImage) {\n const layers = splitGradientArgs(style.backgroundImage);\n // CSS paints last layer first (bottommost)\n for (let i = layers.length - 1; i >= 0; i--) {\n const layer = layers[i]!.trim();\n const gradient = createGradientFromCSS(ctx, layer, x, y, width, height);\n if (gradient) {\n ctx.fillStyle = gradient;\n if (hasRadius(borderRadius)) {\n ctx.beginPath();\n roundedRect(\n ctx,\n x,\n y,\n width,\n height,\n borderRadius.topLeft,\n borderRadius.topRight,\n borderRadius.bottomRight,\n borderRadius.bottomLeft,\n );\n ctx.fill();\n } else {\n ctx.fillRect(x, y, width, height);\n }\n } else {\n // Try url(...) background image\n const urlMatch = layer.match(/url\\([\"']?(.*?)[\"']?\\)/);\n if (urlMatch) {\n if (hasRadius(borderRadius)) {\n applyClip(ctx, x, y, width, height, borderRadius);\n }\n\n const image = await cachedLoadImage(\n renderContext.imageCache,\n urlMatch[1]!,\n renderContext.userAgent,\n );\n const bgSize = style.backgroundSize;\n\n if (bgSize === \"cover\") {\n // Cover fills the box completely — no tiling needed\n const r = computeCover(\n image.width,\n image.height,\n x,\n y,\n width,\n height,\n );\n ctx.drawImage(\n image,\n r.sx,\n r.sy,\n r.sw,\n r.sh,\n r.dx,\n r.dy,\n r.dw,\n r.dh,\n );\n } else {\n // Compute tile dimensions based on backgroundSize\n let tileW: number, tileH: number;\n if (bgSize === \"contain\") {\n const r = computeContain(\n image.width,\n image.height,\n 0,\n 0,\n width,\n height,\n );\n tileW = r.dw;\n tileH = r.dh;\n } else if (bgSize === \"100% 100%\") {\n tileW = width;\n tileH = height;\n } else {\n // CSS default (auto): natural image size\n tileW = image.width;\n tileH = image.height;\n }\n const repeat = style.backgroundRepeat ?? \"repeat\";\n const stepX =\n repeat === \"repeat\" || repeat === \"repeat-x\" ? tileW : width;\n const stepY =\n repeat === \"repeat\" || repeat === \"repeat-y\" ? tileH : height;\n for (let ty = y; ty < y + height; ty += stepY) {\n for (let tx = x; tx < x + width; tx += stepX) {\n ctx.drawImage(image, tx, ty, tileW, tileH);\n }\n }\n }\n }\n }\n }\n }\n\n // Debug: draw bounding boxes\n if (renderContext.debug) {\n ctx.strokeStyle = \"rgba(255, 0, 0, 0.5)\";\n ctx.lineWidth = 1;\n ctx.strokeRect(x, y, width, height);\n }\n\n // Draw text content\n if (node.textContent !== undefined && node.textContent !== \"\") {\n const paddingTop = resolveBoxValue(style.paddingTop, width);\n const paddingLeft = resolveBoxValue(style.paddingLeft, width);\n const paddingRight = resolveBoxValue(style.paddingRight, width);\n\n const borderTopW = resolveBoxValue(style.borderTopWidth, width);\n const borderLeftW = resolveBoxValue(style.borderLeftWidth, width);\n const borderRightW = resolveBoxValue(style.borderRightWidth, width);\n\n const contentX = x + paddingLeft + borderLeftW;\n const contentY = y + paddingTop + borderTopW;\n const contentWidth =\n width - paddingLeft - paddingRight - borderLeftW - borderRightW;\n\n const textLayout = layoutText(\n node.textContent,\n style,\n contentWidth,\n ctx,\n !!emojiStyle,\n );\n await drawText(\n ctx,\n textLayout.segments,\n contentX,\n contentY,\n style.textShadow,\n emojiStyle,\n textLayout.paragraph && {\n paragraph: textLayout.paragraph,\n offsetY: textLayout.paragraphOffsetY ?? 0,\n },\n );\n }\n\n // Draw <img> elements\n if (node.type === \"img\" && node.props.src) {\n const paddingTop = resolveBoxValue(style.paddingTop, width);\n const paddingLeft = resolveBoxValue(style.paddingLeft, width);\n const paddingRight = resolveBoxValue(style.paddingRight, width);\n const paddingBottom = resolveBoxValue(style.paddingBottom, width);\n\n const borderTopW = resolveBoxValue(style.borderTopWidth, width);\n const borderLeftW = resolveBoxValue(style.borderLeftWidth, width);\n const borderRightW = resolveBoxValue(style.borderRightWidth, width);\n const borderBottomW = resolveBoxValue(style.borderBottomWidth, width);\n\n const imgX = x + paddingLeft + borderLeftW;\n const imgY = y + paddingTop + borderTopW;\n const imgW =\n width - paddingLeft - paddingRight - borderLeftW - borderRightW;\n const imgH =\n height - paddingTop - paddingBottom - borderTopW - borderBottomW;\n\n // Images are replaced content — borderRadius clips them directly\n // (unlike child content which requires overflow:hidden)\n if (!isClipped) {\n if (hasRadius(borderRadius)) {\n applyClip(ctx, imgX, imgY, imgW, imgH, borderRadius);\n }\n }\n\n await drawImage(\n ctx,\n node.props.src as string | Buffer,\n imgX,\n imgY,\n imgW,\n imgH,\n renderContext,\n style,\n );\n }\n\n // Draw <svg> containers (handle their own child traversal in SVG coordinate space)\n if (node.type === \"svg\") {\n drawSvgContainer(ctx, node, x, y, width, height);\n } else {\n for (const child of node.children) {\n await drawNode(ctx, child, x, y, renderContext, emojiStyle);\n }\n }\n}\n\nfunction applyTransform(\n ctx: SKRSContext2D,\n transform: string,\n x: number,\n y: number,\n width: number,\n height: number,\n transformOrigin?: string,\n): void {\n // Resolve transform-origin (default: center)\n let ox = x + width / 2;\n let oy = y + height / 2;\n\n if (transformOrigin) {\n const parts = transformOrigin.split(/\\s+/);\n ox = resolveOrigin(parts[0], x, width);\n oy = resolveOrigin(parts[1], y, height);\n }\n\n ctx.translate(ox, oy);\n\n // Parse and apply transform functions\n const funcs = transform.matchAll(/(\\w+)\\(([^)]+)\\)/g);\n\n for (const [, name, args] of funcs) {\n const values = args!.split(\",\").map((s) => s.trim());\n\n switch (name) {\n case \"translate\":\n case \"translateX\":\n case \"translateY\": {\n const tx =\n name === \"translateY\" ? 0 : parseCSSLength(values[0]!, width);\n const ty =\n name === \"translateX\"\n ? 0\n : parseCSSLength(\n values[name === \"translate\" ? 1 : 0] ?? \"0\",\n height,\n );\n ctx.translate(tx, ty);\n break;\n }\n case \"scale\":\n case \"scaleX\":\n case \"scaleY\": {\n const sx = name === \"scaleY\" ? 1 : parseFloat(values[0]!);\n const sy =\n name === \"scaleX\"\n ? 1\n : parseFloat(values[name === \"scale\" ? 1 : 0] ?? String(sx));\n ctx.scale(sx, sy);\n break;\n }\n case \"rotate\": {\n const angle = parseAngle(values[0]!);\n ctx.rotate(angle);\n break;\n }\n case \"skewX\": {\n const angle = parseAngle(values[0]!);\n ctx.transform(1, 0, Math.tan(angle), 1, 0, 0);\n break;\n }\n case \"skewY\": {\n const angle = parseAngle(values[0]!);\n ctx.transform(1, Math.tan(angle), 0, 1, 0, 0);\n break;\n }\n }\n }\n\n ctx.translate(-ox, -oy);\n}\n\nfunction resolveOrigin(\n value: string | undefined,\n base: number,\n size: number,\n): number {\n if (!value) return base + size / 2;\n if (value === \"left\" || value === \"top\") return base;\n if (value === \"right\" || value === \"bottom\") return base + size;\n if (value === \"center\") return base + size / 2;\n return base + parseCSSLength(value, size);\n}\n\nfunction parseAngle(value: string): number {\n if (value.endsWith(\"deg\")) return (parseFloat(value) * Math.PI) / 180;\n if (value.endsWith(\"rad\")) return parseFloat(value);\n if (value.endsWith(\"turn\")) return parseFloat(value) * 2 * Math.PI;\n return parseFloat(value);\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport { splitGradientArgs } from \"../draw/gradient.ts\";\nimport type { ExpandedStyle } from \"./compute.ts\";\n\ntype RawStyle = Record<string, unknown>;\n\nconst SIDES = [\"Top\", \"Right\", \"Bottom\", \"Left\"] as const;\n\n/**\n * Parse a CSS shorthand value like \"10px 20px\" into 1-4 parts.\n */\nfunction parseSides(value: string): string[] {\n const parts = value.toString().split(/\\s+/).filter(Boolean);\n switch (parts.length) {\n case 1:\n return [parts[0]!, parts[0]!, parts[0]!, parts[0]!];\n case 2:\n return [parts[0]!, parts[1]!, parts[0]!, parts[1]!];\n case 3:\n return [parts[0]!, parts[1]!, parts[2]!, parts[1]!];\n default:\n return [parts[0]!, parts[1]!, parts[2]!, parts[3]!];\n }\n}\n\nfunction parseValue(v: unknown): number | string | undefined {\n if (v === undefined || v === null) return undefined;\n const s = String(v);\n if (s === \"auto\") return \"auto\";\n const n = Number(s);\n if (s !== \"\" && !isNaN(n)) return n;\n return s;\n}\n\n/**\n * Expand CSS shorthand properties into their longhand equivalents.\n * Mutates and returns the style object.\n */\nexport function expandStyle(\n raw: RawStyle,\n fontFamilies?: string[],\n): ExpandedStyle {\n const style = { ...raw } as Record<string, unknown>;\n\n // margin shorthand\n if (style.margin !== undefined) {\n const sides = parseSides(String(style.margin));\n for (let i = 0; i < 4; i++) {\n const key = `margin${SIDES[i]}`;\n if (style[key] === undefined) style[key] = parseValue(sides[i]);\n }\n delete style.margin;\n }\n\n // padding shorthand\n if (style.padding !== undefined) {\n const sides = parseSides(String(style.padding));\n for (let i = 0; i < 4; i++) {\n const key = `padding${SIDES[i]}`;\n if (style[key] === undefined) style[key] = parseValue(sides[i]);\n }\n delete style.padding;\n }\n\n // borderRadius shorthand\n if (style.borderRadius !== undefined) {\n const sides = parseSides(String(style.borderRadius));\n const corners = [\n \"borderTopLeftRadius\",\n \"borderTopRightRadius\",\n \"borderBottomRightRadius\",\n \"borderBottomLeftRadius\",\n ];\n for (let i = 0; i < 4; i++) {\n if (style[corners[i]!] === undefined)\n style[corners[i]!] = parseValue(sides[i]);\n }\n delete style.borderRadius;\n }\n\n // borderWidth shorthand\n if (style.borderWidth !== undefined) {\n const sides = parseSides(String(style.borderWidth));\n for (let i = 0; i < 4; i++) {\n const key = `border${SIDES[i]}Width`;\n if (style[key] === undefined) style[key] = parseValue(sides[i]);\n }\n delete style.borderWidth;\n }\n\n // borderColor shorthand\n if (style.borderColor !== undefined) {\n const val = style.borderColor;\n for (const side of SIDES) {\n const key = `border${side}Color`;\n if (style[key] === undefined) style[key] = val;\n }\n delete style.borderColor;\n }\n\n // borderStyle shorthand\n if (style.borderStyle !== undefined) {\n const val = style.borderStyle;\n for (const side of SIDES) {\n const key = `border${side}Style`;\n if (style[key] === undefined) style[key] = val;\n }\n delete style.borderStyle;\n }\n\n // border shorthand (e.g. \"1px solid black\")\n if (style.border !== undefined) {\n const parts = String(style.border).split(/\\s+/);\n const width = parseValue(parts[0]);\n const borderStyle = parts[1] ?? \"solid\";\n const color = parts[2] ?? \"black\";\n for (const side of SIDES) {\n if (style[`border${side}Width`] === undefined)\n style[`border${side}Width`] = width;\n if (style[`border${side}Style`] === undefined)\n style[`border${side}Style`] = borderStyle;\n if (style[`border${side}Color`] === undefined)\n style[`border${side}Color`] = color;\n }\n delete style.border;\n }\n\n // Per-side border shorthands (e.g. borderLeft: \"3px solid white\")\n for (const side of SIDES) {\n const key = `border${side}`;\n if (style[key] !== undefined) {\n const parts = String(style[key]).split(/\\s+/);\n const width = parseValue(parts[0]);\n const borderStyle = parts[1] ?? \"solid\";\n const color = parts[2] ?? \"black\";\n if (style[`${key}Width`] === undefined) style[`${key}Width`] = width;\n if (style[`${key}Style`] === undefined)\n style[`${key}Style`] = borderStyle;\n if (style[`${key}Color`] === undefined) style[`${key}Color`] = color;\n delete style[key];\n }\n }\n\n // flex shorthand\n if (style.flex !== undefined) {\n const val = String(style.flex);\n if (val === \"none\") {\n if (style.flexGrow === undefined) style.flexGrow = 0;\n if (style.flexShrink === undefined) style.flexShrink = 0;\n if (style.flexBasis === undefined) style.flexBasis = \"auto\";\n } else {\n const parts = val.split(/\\s+/);\n if (parts.length === 1) {\n const n = parseFloat(parts[0]!);\n if (!isNaN(n)) {\n if (style.flexGrow === undefined) style.flexGrow = n;\n if (style.flexShrink === undefined) style.flexShrink = 1;\n if (style.flexBasis === undefined) style.flexBasis = 0;\n }\n } else if (parts.length === 2) {\n if (style.flexGrow === undefined)\n style.flexGrow = parseFloat(parts[0]!);\n if (style.flexShrink === undefined)\n style.flexShrink = parseFloat(parts[1]!);\n } else if (parts.length >= 3) {\n if (style.flexGrow === undefined)\n style.flexGrow = parseFloat(parts[0]!);\n if (style.flexShrink === undefined)\n style.flexShrink = parseFloat(parts[1]!);\n if (style.flexBasis === undefined)\n style.flexBasis = parseValue(parts[2]);\n }\n }\n delete style.flex;\n }\n\n // gap shorthand\n if (style.gap !== undefined) {\n const sides = parseSides(String(style.gap));\n if (style.rowGap === undefined) style.rowGap = parseValue(sides[0]);\n if (style.columnGap === undefined) style.columnGap = parseValue(sides[1]);\n delete style.gap;\n }\n\n // background shorthand\n if (style.background !== undefined) {\n const parts = parseBackgroundShorthand(String(style.background));\n if (parts.image !== undefined && style.backgroundImage === undefined)\n style.backgroundImage = parts.image;\n if (parts.repeat !== undefined && style.backgroundRepeat === undefined)\n style.backgroundRepeat = parts.repeat;\n if (parts.size !== undefined && style.backgroundSize === undefined)\n style.backgroundSize = parts.size;\n if (parts.color !== undefined && style.backgroundColor === undefined)\n style.backgroundColor = parts.color;\n delete style.background;\n }\n\n // overflow shorthand\n if (style.overflow !== undefined) {\n if (style.overflowX === undefined) style.overflowX = style.overflow;\n if (style.overflowY === undefined) style.overflowY = style.overflow;\n }\n\n // textBox shorthand (e.g. \"trim-both cap alphabetic\")\n if (style.textBox !== undefined) {\n const val = String(style.textBox);\n if (val === \"normal\" || val === \"none\") {\n style.textBoxTrim ??= \"none\";\n } else {\n const parts = val.split(/\\s+/);\n style.textBoxTrim ??= parts[0];\n if (parts.length > 1) {\n style.textBoxEdge ??= parts.slice(1).join(\" \");\n }\n }\n delete style.textBox;\n }\n\n // WebkitTextStroke shorthand (e.g. \"2px red\")\n if (style.WebkitTextStroke !== undefined) {\n const val = String(style.WebkitTextStroke).trim();\n const match = val.match(/^(\\S+)\\s+(.+)$/);\n if (match) {\n if (style.WebkitTextStrokeWidth === undefined)\n style.WebkitTextStrokeWidth = parseValue(match[1]);\n if (style.WebkitTextStrokeColor === undefined)\n style.WebkitTextStrokeColor = match[2];\n } else {\n // Single value — treat as width\n if (style.WebkitTextStrokeWidth === undefined)\n style.WebkitTextStrokeWidth = parseValue(val);\n }\n delete style.WebkitTextStroke;\n }\n\n // Vendor-prefixed aliases\n if (style.WebkitBackdropFilter !== undefined) {\n if (style.backdropFilter === undefined)\n style.backdropFilter = style.WebkitBackdropFilter;\n delete style.WebkitBackdropFilter;\n }\n if (style.WebkitClipPath !== undefined) {\n if (style.clipPath === undefined) style.clipPath = style.WebkitClipPath;\n delete style.WebkitClipPath;\n }\n\n // fontFamily normalization\n if (typeof style.fontFamily === \"string\") {\n const families = style.fontFamily\n .split(\",\")\n .map((s) => s.trim().replace(/^['\"]|['\"]$/g, \"\"))\n .filter(Boolean);\n if (fontFamilies) {\n const present = new Set(families);\n for (const name of fontFamilies) {\n if (!present.has(name)) families.push(name);\n }\n }\n style.fontFamily = families.join(\", \");\n }\n\n return style as unknown as ExpandedStyle;\n}\n\nconst BG_REPEAT_KEYWORDS = new Set([\n \"repeat\",\n \"no-repeat\",\n \"repeat-x\",\n \"repeat-y\",\n \"space\",\n \"round\",\n]);\nconst BG_POSITION_KEYWORDS = new Set([\n \"left\",\n \"right\",\n \"top\",\n \"bottom\",\n \"center\",\n]);\nconst BG_ATTACHMENT_KEYWORDS = new Set([\"scroll\", \"fixed\", \"local\"]);\nconst BG_BOX_KEYWORDS = new Set([\"border-box\", \"padding-box\", \"content-box\"]);\nconst BG_IMAGE_FN =\n /^(?:url|image-set|(?:repeating-)?(?:linear|radial|conic)-gradient)\\(/;\n\n// Whitespace-tokenize a CSS value, keeping balanced-paren blocks intact and\n// emitting `/` as its own token (the position/size separator).\nfunction tokenizeBackground(value: string): string[] {\n const tokens: string[] = [];\n let buf = \"\";\n for (let i = 0; i < value.length; i++) {\n const c = value[i]!;\n if (c === \"(\") {\n let depth = 1;\n buf += c;\n i++;\n while (i < value.length && depth > 0) {\n const ch = value[i]!;\n if (ch === \"(\") depth++;\n else if (ch === \")\") depth--;\n buf += ch;\n i++;\n }\n i--;\n } else if (/\\s/.test(c)) {\n if (buf) {\n tokens.push(buf);\n buf = \"\";\n }\n } else if (c === \"/\") {\n if (buf) {\n tokens.push(buf);\n buf = \"\";\n }\n tokens.push(\"/\");\n } else {\n buf += c;\n }\n }\n if (buf) tokens.push(buf);\n return tokens;\n}\n\ninterface BackgroundParts {\n image?: string;\n repeat?: string;\n size?: string;\n color?: string;\n}\n\nfunction parseLayer(value: string): BackgroundParts {\n const out: BackgroundParts = {};\n const sizeTokens: string[] = [];\n let afterSlash = false;\n for (const tok of tokenizeBackground(value)) {\n if (tok === \"/\") {\n afterSlash = true;\n continue;\n }\n if (afterSlash) {\n sizeTokens.push(tok);\n continue;\n }\n if (BG_IMAGE_FN.test(tok)) {\n out.image = tok;\n continue;\n }\n if (tok === \"none\") continue;\n if (BG_REPEAT_KEYWORDS.has(tok)) {\n out.repeat = tok;\n continue;\n }\n // Position/attachment/box/length tokens are recognized so they don't fall\n // through and get treated as colors; the renderer doesn't honor them yet.\n if (\n BG_POSITION_KEYWORDS.has(tok) ||\n BG_ATTACHMENT_KEYWORDS.has(tok) ||\n BG_BOX_KEYWORDS.has(tok) ||\n /^-?\\d/.test(tok)\n ) {\n continue;\n }\n out.color = tok;\n }\n if (sizeTokens.length > 0) out.size = sizeTokens.join(\" \");\n return out;\n}\n\n/**\n * Parse the CSS `background` shorthand into image/repeat/size/color longhands.\n * For multi-layer values, image is comma-joined and color is taken only from\n * the final layer (the only layer permitted a color per the CSS spec).\n */\nexport function parseBackgroundShorthand(value: string): BackgroundParts {\n const layers = splitGradientArgs(value).map((l) => l.trim());\n if (layers.length <= 1) return parseLayer(layers[0] ?? \"\");\n\n const parsed = layers.map(parseLayer);\n const out: BackgroundParts = {};\n const images = parsed.map((p) => p.image ?? \"none\");\n if (images.some((i) => i !== \"none\")) out.image = images.join(\", \");\n for (const p of parsed) {\n if (p.repeat !== undefined && out.repeat === undefined)\n out.repeat = p.repeat;\n if (p.size !== undefined && out.size === undefined) out.size = p.size;\n }\n const finalColor = parsed[parsed.length - 1]?.color;\n if (finalColor !== undefined) out.color = finalColor;\n return out;\n}\n","import Yoga, {\n Align,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n Overflow,\n PositionType,\n Wrap,\n} from \"yoga-layout\";\nimport type { Node as YogaNode } from \"yoga-layout\";\n\nexport type { YogaNode };\n\nexport {\n Yoga,\n Align,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n Overflow,\n PositionType,\n Wrap,\n};\n\nexport function createYogaNode(): YogaNode {\n return Yoga.Node.create();\n}\n\nexport function freeYogaNode(node: YogaNode): void {\n node.freeRecursive();\n}\n","import {\n Align,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n Overflow,\n PositionType,\n Wrap,\n} from \"../yoga.ts\";\nimport type { YogaNode } from \"../yoga.ts\";\nimport type { ComputedStyle } from \"./compute.ts\";\n\n/**\n * Apply computed CSS styles to a Yoga node.\n */\nexport function applyStylesToYoga(node: YogaNode, style: ComputedStyle): void {\n // Display\n if (style.display === \"none\") {\n node.setDisplay(Display.None);\n } else {\n node.setDisplay(Display.Flex);\n }\n\n // Flex direction (CSS default is \"row\", Yoga defaults to \"column\")\n {\n const map: Record<string, FlexDirection> = {\n row: FlexDirection.Row,\n \"row-reverse\": FlexDirection.RowReverse,\n column: FlexDirection.Column,\n \"column-reverse\": FlexDirection.ColumnReverse,\n };\n node.setFlexDirection(\n map[style.flexDirection ?? \"row\"] ?? FlexDirection.Row,\n );\n }\n\n // Justify content\n if (style.justifyContent) {\n const map: Record<string, Justify> = {\n \"flex-start\": Justify.FlexStart,\n \"flex-end\": Justify.FlexEnd,\n center: Justify.Center,\n \"space-between\": Justify.SpaceBetween,\n \"space-around\": Justify.SpaceAround,\n \"space-evenly\": Justify.SpaceEvenly,\n };\n const jc = map[style.justifyContent];\n if (jc !== undefined) node.setJustifyContent(jc);\n }\n\n // Align items.\n // NOTE: `baseline` does NOT produce typographic baseline alignment. The\n // bundled yoga-layout JS binding exposes no baseline function, so Yoga falls\n // back to a node's height as its baseline — which aligns box bottoms (the\n // same result as `flex-end`), correct only when all children share a font\n // size. The README documents this limitation; don't re-advertise it as full\n // baseline support without a real fix, since the engine can't express it.\n if (style.alignItems) {\n const map: Record<string, Align> = {\n \"flex-start\": Align.FlexStart,\n \"flex-end\": Align.FlexEnd,\n center: Align.Center,\n stretch: Align.Stretch,\n baseline: Align.Baseline,\n };\n const ai = map[style.alignItems];\n if (ai !== undefined) node.setAlignItems(ai);\n }\n\n // Align self (`baseline` carries the same box-bottom caveat as alignItems)\n if (style.alignSelf) {\n const map: Record<string, Align> = {\n auto: Align.Auto,\n \"flex-start\": Align.FlexStart,\n \"flex-end\": Align.FlexEnd,\n center: Align.Center,\n stretch: Align.Stretch,\n baseline: Align.Baseline,\n };\n const as_ = map[style.alignSelf];\n if (as_ !== undefined) node.setAlignSelf(as_);\n }\n\n // Align content\n if (style.alignContent) {\n const map: Record<string, Align> = {\n \"flex-start\": Align.FlexStart,\n \"flex-end\": Align.FlexEnd,\n center: Align.Center,\n stretch: Align.Stretch,\n \"space-between\": Align.SpaceBetween,\n \"space-around\": Align.SpaceAround,\n };\n const ac = map[style.alignContent];\n if (ac !== undefined) node.setAlignContent(ac);\n }\n\n // Flex wrap\n if (style.flexWrap) {\n const map: Record<string, Wrap> = {\n nowrap: Wrap.NoWrap,\n wrap: Wrap.Wrap,\n \"wrap-reverse\": Wrap.WrapReverse,\n };\n const fw = map[style.flexWrap];\n if (fw !== undefined) node.setFlexWrap(fw);\n }\n\n // Flex grow / shrink / basis\n if (style.flexGrow !== undefined) node.setFlexGrow(style.flexGrow);\n // Satori defaults flexShrink to 0 (React Native convention); match it for compatibility\n node.setFlexShrink(style.flexShrink ?? 0);\n if (style.flexBasis !== undefined) {\n if (typeof style.flexBasis === \"number\") {\n node.setFlexBasis(style.flexBasis);\n } else if (String(style.flexBasis).endsWith(\"%\")) {\n node.setFlexBasis(String(style.flexBasis) as `${number}%`);\n } else if (style.flexBasis === \"auto\") {\n node.setFlexBasis(\"auto\");\n } else {\n const n = parseFloat(String(style.flexBasis));\n if (!isNaN(n)) node.setFlexBasis(n);\n }\n }\n\n // Dimensions\n applyDimension(node, \"setWidth\", style.width);\n applyDimension(node, \"setHeight\", style.height);\n applyDimension(node, \"setMinWidth\", style.minWidth);\n applyDimension(node, \"setMinHeight\", style.minHeight);\n applyDimension(node, \"setMaxWidth\", style.maxWidth);\n applyDimension(node, \"setMaxHeight\", style.maxHeight);\n\n // Position\n if (style.position === \"absolute\") {\n node.setPositionType(PositionType.Absolute);\n } else {\n node.setPositionType(PositionType.Relative);\n }\n\n // Position edges\n applyEdgeValue(node, \"setPosition\", Edge.Top, style.top);\n applyEdgeValue(node, \"setPosition\", Edge.Right, style.right);\n applyEdgeValue(node, \"setPosition\", Edge.Bottom, style.bottom);\n applyEdgeValue(node, \"setPosition\", Edge.Left, style.left);\n\n // Margin\n applyEdgeValue(node, \"setMargin\", Edge.Top, style.marginTop);\n applyEdgeValue(node, \"setMargin\", Edge.Right, style.marginRight);\n applyEdgeValue(node, \"setMargin\", Edge.Bottom, style.marginBottom);\n applyEdgeValue(node, \"setMargin\", Edge.Left, style.marginLeft);\n\n // Padding\n applyEdgeValue(node, \"setPadding\", Edge.Top, style.paddingTop);\n applyEdgeValue(node, \"setPadding\", Edge.Right, style.paddingRight);\n applyEdgeValue(node, \"setPadding\", Edge.Bottom, style.paddingBottom);\n applyEdgeValue(node, \"setPadding\", Edge.Left, style.paddingLeft);\n\n // Border width (resolved to numbers by resolveUnits before this point)\n if (style.borderTopWidth !== undefined)\n node.setBorder(Edge.Top, style.borderTopWidth as number);\n if (style.borderRightWidth !== undefined)\n node.setBorder(Edge.Right, style.borderRightWidth as number);\n if (style.borderBottomWidth !== undefined)\n node.setBorder(Edge.Bottom, style.borderBottomWidth as number);\n if (style.borderLeftWidth !== undefined)\n node.setBorder(Edge.Left, style.borderLeftWidth as number);\n\n // Gap\n if (style.rowGap !== undefined) node.setGap(Gutter.Row, style.rowGap);\n if (style.columnGap !== undefined)\n node.setGap(Gutter.Column, style.columnGap);\n\n // Overflow\n if (\n style.overflow === \"hidden\" ||\n style.overflowX === \"hidden\" ||\n style.overflowY === \"hidden\"\n ) {\n node.setOverflow(Overflow.Hidden);\n } else {\n node.setOverflow(Overflow.Visible);\n }\n}\n\nfunction applyDimension(\n node: YogaNode,\n setter:\n | \"setWidth\"\n | \"setHeight\"\n | \"setMinWidth\"\n | \"setMinHeight\"\n | \"setMaxWidth\"\n | \"setMaxHeight\",\n value: number | string | undefined,\n): void {\n if (value === undefined) return;\n if (value === \"auto\") {\n if (setter === \"setWidth\" || setter === \"setHeight\") {\n node[setter](\"auto\");\n }\n return;\n }\n if (typeof value === \"number\") {\n node[setter](value);\n return;\n }\n const s = String(value);\n if (s.endsWith(\"%\")) {\n node[setter](s as `${number}%`);\n } else {\n const n = parseFloat(s);\n if (!isNaN(n)) node[setter](n);\n }\n}\n\nfunction applyEdgeValue(\n node: YogaNode,\n setter: \"setMargin\" | \"setPadding\" | \"setPosition\",\n edge: Edge,\n value: number | string | undefined,\n): void {\n if (value === undefined) return;\n if (value === \"auto\" && setter === \"setMargin\") {\n node.setMargin(edge, \"auto\");\n return;\n }\n if (typeof value === \"number\") {\n node[setter](edge, value);\n return;\n }\n const s = String(value);\n if (s.endsWith(\"%\")) {\n node[setter](edge, s as `${number}%`);\n } else {\n const n = parseFloat(s);\n if (!isNaN(n)) node[setter](edge, n);\n }\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport type { SKRSContext2D } from \"@effing/skia\";\nimport type { ReactElement, ReactNode } from \"react\";\n\nimport type { ImageCache } from \"../image.ts\";\nimport { cachedLoadImage } from \"../image.ts\";\nimport type { RenderContext } from \"./context.ts\";\nimport { expandStyle } from \"./style/expand.ts\";\nimport {\n resolveStyle,\n resolveUnit,\n resolveUnits,\n DEFAULT_STYLE,\n} from \"./style/compute.ts\";\nimport type { ComputedStyle } from \"./style/compute.ts\";\nimport { applyStylesToYoga } from \"./style/properties.ts\";\nimport { createTextMeasureFunc } from \"./text/index.ts\";\nimport { createYogaNode, freeYogaNode, FlexDirection } from \"./yoga.ts\";\nimport type { YogaNode } from \"./yoga.ts\";\n\n/**\n * A node in the computed layout tree, ready for drawing.\n */\nexport type LayoutNode = {\n type: string;\n style: ComputedStyle;\n children: LayoutNode[];\n textContent?: string;\n props: Record<string, unknown>;\n x: number;\n y: number;\n width: number;\n height: number;\n};\n\ntype ElementChild = string | number | ReactElement | null | undefined | boolean;\n\n/**\n * Build a layout tree from a React element tree.\n * Creates Yoga nodes, calculates layout, and returns the positioned tree.\n *\n * @param element - React element tree to lay out\n * @param containerWidth - Width of the container (from canvas)\n * @param containerHeight - Height of the container (from canvas)\n * @param ctx - Canvas context for text measurement\n * @returns Root layout node with computed positions and dimensions\n */\nexport async function buildLayoutTree(\n element: ReactNode,\n containerWidth: number,\n containerHeight: number,\n ctx?: SKRSContext2D,\n emojiEnabled?: boolean,\n fontFamilies?: string[],\n context?: RenderContext,\n): Promise<{ tree: LayoutNode; imageCache: ImageCache }> {\n const renderContext: RenderContext = context ?? {\n imageCache: new Map(),\n debug: false,\n };\n const elementYogaNode = createYogaNode();\n\n // Set font families as default on root style so all nodes inherit them\n const rootStyle = fontFamilies?.length\n ? { ...DEFAULT_STYLE, fontFamily: fontFamilies.join(\", \") }\n : DEFAULT_STYLE;\n\n // Build the tree\n const elementNode = await buildNode(\n element,\n rootStyle,\n elementYogaNode,\n containerWidth,\n containerHeight,\n ctx,\n emojiEnabled,\n fontFamilies,\n renderContext,\n );\n\n // Wrap the user element in a canvas-sized container (like Satori) so that\n // absolute positioning, percentage sizes, etc. resolve against the canvas.\n const rootYogaNode = createYogaNode();\n rootYogaNode.setWidth(containerWidth);\n rootYogaNode.setHeight(containerHeight);\n rootYogaNode.setFlexDirection(FlexDirection.Row);\n rootYogaNode.insertChild(elementYogaNode, 0);\n\n rootYogaNode.calculateLayout(containerWidth, containerHeight);\n\n const elementLayout = extractLayout(elementNode, elementYogaNode);\n freeYogaNode(rootYogaNode);\n\n const tree: LayoutNode = {\n type: \"div\",\n style: rootStyle,\n children: [elementLayout],\n props: {},\n x: 0,\n y: 0,\n width: containerWidth,\n height: containerHeight,\n };\n return { tree, imageCache: renderContext.imageCache };\n}\n\nasync function buildNode(\n element: ReactNode,\n parentStyle: ComputedStyle,\n yogaNode: YogaNode,\n viewportWidth: number,\n viewportHeight: number,\n ctx?: SKRSContext2D,\n emojiEnabled?: boolean,\n fontFamilies?: string[],\n context?: RenderContext,\n): Promise<IntermediateNode> {\n // Handle null/undefined/boolean\n if (\n element === null ||\n element === undefined ||\n typeof element === \"boolean\"\n ) {\n return {\n type: \"empty\",\n style: parentStyle,\n children: [],\n props: {},\n yogaNode,\n };\n }\n\n // Handle text/number primitives\n if (typeof element === \"string\" || typeof element === \"number\") {\n const text = String(element);\n const style = resolveStyle(undefined, parentStyle);\n\n // Set up text measurement\n const measureFunc = createTextMeasureFunc(text, style, ctx, emojiEnabled);\n yogaNode.setMeasureFunc(measureFunc);\n\n return {\n type: \"text\",\n style,\n children: [],\n textContent: text,\n props: {},\n yogaNode,\n };\n }\n\n // Handle React elements\n const el = element as ReactElement<Record<string, unknown>>;\n const type = el.type;\n\n // Expand function/class components\n if (typeof type === \"function\") {\n const rendered = (type as (props: Record<string, unknown>) => ReactNode)(\n el.props ?? {},\n );\n return await buildNode(\n rendered,\n parentStyle,\n yogaNode,\n viewportWidth,\n viewportHeight,\n ctx,\n emojiEnabled,\n fontFamilies,\n context,\n );\n }\n\n const props = (el.props ?? {}) as Record<string, unknown>;\n const rawStyle = (props.style ?? {}) as Record<string, unknown>;\n const expanded = expandStyle(rawStyle, fontFamilies);\n const style = resolveStyle(expanded, parentStyle);\n resolveUnits(style, viewportWidth, viewportHeight);\n\n const tagName = String(type);\n\n // For <svg> elements, merge width/height props into style when not set via CSS\n if (tagName === \"svg\") {\n if (props.width != null && style.width === undefined) {\n const v = props.width;\n if (typeof v === \"string\") {\n const resolved = resolveUnit(v, viewportWidth, viewportHeight, 16, 16);\n style.width =\n typeof resolved === \"string\" && resolved.endsWith(\"%\")\n ? resolved\n : Number(resolved);\n } else {\n style.width = Number(v);\n }\n }\n if (props.height != null && style.height === undefined) {\n const v = props.height;\n if (typeof v === \"string\") {\n const resolved = resolveUnit(v, viewportWidth, viewportHeight, 16, 16);\n style.height =\n typeof resolved === \"string\" && resolved.endsWith(\"%\")\n ? resolved\n : Number(resolved);\n } else {\n style.height = Number(v);\n }\n }\n\n // Derive missing dimension from viewBox aspect ratio\n const viewBox = props.viewBox as string | undefined;\n if (viewBox) {\n const parts = viewBox.split(/[\\s,]+/).map(Number);\n if (parts.length === 4) {\n const [, , vbW, vbH] = parts as [number, number, number, number];\n if (vbW > 0 && vbH > 0) {\n const wSet = style.width !== undefined;\n const hSet = style.height !== undefined;\n if (!wSet && !hSet) {\n style.width = vbW;\n style.height = vbH;\n } else if (!hSet && typeof style.width === \"number\") {\n style.height = style.width * (vbH / vbW);\n } else if (!wSet && typeof style.height === \"number\") {\n style.width = style.height * (vbW / vbH);\n }\n // When either/both are %, leave as-is for Yoga\n }\n }\n }\n }\n\n // For <img> elements, derive missing dimensions from intrinsic aspect ratio\n if (tagName === \"img\") {\n // Map HTML width/height attributes to style (like <svg>)\n if (props.width != null && style.width === undefined) {\n const v = props.width;\n style.width = typeof v === \"string\" && v.endsWith(\"%\") ? v : Number(v);\n }\n if (props.height != null && style.height === undefined) {\n const v = props.height;\n style.height = typeof v === \"string\" && v.endsWith(\"%\") ? v : Number(v);\n }\n\n const src = props.src as string | Buffer | undefined;\n if (src) {\n try {\n const image = await cachedLoadImage(\n context?.imageCache ?? new Map(),\n src,\n context?.userAgent,\n );\n const naturalW = image.width;\n const naturalH = image.height;\n\n const wSet = style.width !== undefined;\n const hSet = style.height !== undefined;\n\n if (naturalW > 0 && naturalH > 0 && !(wSet && hSet)) {\n if (!wSet && !hSet) {\n // No dimensions given — fill parent, let aspect ratio derive height.\n style.width = \"100%\";\n }\n yogaNode.setAspectRatio(naturalW / naturalH);\n }\n } catch (err) {\n // Don't fail layout when the image is unreachable — render at whatever\n // size Yoga computes. Surface the error (only in debug) so misconfigured\n // URLs and UA-gated CDNs are diagnosable instead of silently dropping\n // pixels, without spamming logs on every frame of a normal render.\n if (context?.debug) {\n const id = Buffer.isBuffer(src) ? \"<Buffer>\" : src;\n console.warn(\n `[@effing/canvas] failed to load image for layout (${id}): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n }\n }\n }\n\n // Apply styles to Yoga node\n applyStylesToYoga(yogaNode, style);\n\n // SVG containers: children use SVG coordinate space, not flex layout.\n // Skip Yoga child nodes and keep React children in props for the SVG drawer.\n if (tagName === \"svg\") {\n const resolvedChildren = resolveSvgTree(props.children as ReactNode);\n return {\n type: tagName,\n style,\n children: [],\n props: { ...props, children: resolvedChildren },\n yogaNode,\n };\n }\n\n // Collect text content from direct string children\n const textContent = extractTextContent(props.children);\n\n // If this node has only text content, create a child text node.\n // Using a child node (instead of setMeasureFunc on this node directly)\n // ensures Yoga's baseline calculation accounts for this node's padding/border\n // when a parent uses alignItems: \"baseline\".\n if (textContent !== undefined && !hasElementChildren(props.children)) {\n const childStyle = resolveStyle(undefined, style);\n const childYogaNode = createYogaNode();\n const measureFunc = createTextMeasureFunc(\n textContent,\n childStyle,\n ctx,\n emojiEnabled,\n );\n childYogaNode.setMeasureFunc(measureFunc);\n const jc = style.justifyContent;\n if (!jc || jc === \"flex-start\") {\n childYogaNode.setFlexGrow(1);\n }\n childYogaNode.setFlexShrink(1);\n yogaNode.insertChild(childYogaNode, 0);\n\n // Match satori: text-only nodes default to flexShrink=1 so they shrink to\n // fit the available flex space. Without this, text containers overflow their\n // flex parent when siblings consume part of the main axis.\n if (style.flexShrink === undefined) {\n yogaNode.setFlexShrink(1);\n }\n\n return {\n type: tagName,\n style,\n children: [\n {\n type: \"text\",\n style: childStyle,\n children: [],\n textContent,\n props: {},\n yogaNode: childYogaNode,\n },\n ],\n props,\n yogaNode,\n };\n }\n\n // Process children\n const children: IntermediateNode[] = [];\n const rawChildren = props.children;\n\n if (rawChildren !== undefined && rawChildren !== null) {\n const childArray = Array.isArray(rawChildren)\n ? rawChildren.flat(Infinity)\n : [rawChildren];\n\n // CSS Text 3 §4.1.1: collapse leading whitespace after a forced break\n const ws = style.whiteSpace;\n const collapsesWhitespace =\n ws === undefined ||\n ws === \"normal\" ||\n ws === \"nowrap\" ||\n ws === \"pre-line\";\n let prevWasBr = false;\n\n for (const child of childArray as ElementChild[]) {\n if (child === null || child === undefined || typeof child === \"boolean\")\n continue;\n\n let processedChild: ElementChild = child;\n if (prevWasBr && collapsesWhitespace && typeof child === \"string\") {\n processedChild = child.trimStart();\n }\n\n prevWasBr = isBrElement(child);\n\n const childYogaNode = createYogaNode();\n yogaNode.insertChild(childYogaNode, children.length);\n children.push(\n await buildNode(\n processedChild,\n style,\n childYogaNode,\n viewportWidth,\n viewportHeight,\n ctx,\n emojiEnabled,\n fontFamilies,\n context,\n ),\n );\n }\n }\n\n return {\n type: tagName,\n style,\n children,\n props,\n yogaNode,\n };\n}\n\ntype IntermediateNode = {\n type: string;\n style: ComputedStyle;\n children: IntermediateNode[];\n textContent?: string;\n props: Record<string, unknown>;\n yogaNode: YogaNode;\n};\n\nfunction extractLayout(node: IntermediateNode, yogaNode: YogaNode): LayoutNode {\n const layout = yogaNode.getComputedLayout();\n\n return {\n type: node.type,\n style: node.style,\n children: node.children.map((child, i) => {\n const childYoga = yogaNode.getChild(i);\n return extractLayout(child, childYoga);\n }),\n textContent: node.textContent,\n props: node.props,\n x: layout.left,\n y: layout.top,\n width: layout.width,\n height: layout.height,\n };\n}\n\n/**\n * Extract plain text content from children if they are all strings/numbers.\n */\nfunction isBrElement(child: unknown): boolean {\n if (child === null || child === undefined || typeof child !== \"object\")\n return false;\n return (child as ReactElement).type === \"br\";\n}\n\nfunction extractTextContent(children: unknown): string | undefined {\n if (children === undefined || children === null) return undefined;\n if (typeof children === \"string\") return children;\n if (typeof children === \"number\") return String(children);\n\n if (Array.isArray(children)) {\n const parts: string[] = [];\n for (const child of children) {\n if (typeof child === \"string\") {\n parts.push(child);\n } else if (typeof child === \"number\") {\n parts.push(String(child));\n } else if (\n child !== null &&\n child !== undefined &&\n typeof child !== \"boolean\"\n ) {\n return undefined; // Mixed content — not pure text\n }\n }\n return parts.join(\"\");\n }\n\n return undefined;\n}\n\n/**\n * React's `Fragment` type. A registered symbol shared by all React copies,\n * so we can detect fragments without a runtime dependency on `react`.\n */\nconst REACT_FRAGMENT = Symbol.for(\"react.fragment\");\n\n/**\n * Resolve function components, unwrap fragments, and flatten nested arrays\n * inside an `<svg>` subtree. The SVG drawer switches on primitive element\n * strings (path, rect, etc.) and does not flatten its own children, so\n * without this preprocessing (a) function components and fragments silently\n * disappear and (b) helpers returning arrays crash the defs collector.\n */\nfunction resolveSvgTree(node: ReactNode): ReactNode {\n if (node === null || node === undefined || typeof node === \"boolean\")\n return null;\n if (typeof node === \"string\" || typeof node === \"number\") return node;\n\n if (Array.isArray(node)) {\n const out: ReactNode[] = [];\n let changed = false;\n for (const child of node as ReactNode[]) {\n const resolved = resolveSvgTree(child);\n if (resolved === null || resolved === undefined) {\n changed = true;\n continue;\n }\n if (Array.isArray(resolved)) {\n changed = true;\n for (const r of resolved) out.push(r);\n } else {\n if (resolved !== child) changed = true;\n out.push(resolved);\n }\n }\n return changed ? out : node;\n }\n\n const el = node as ReactElement<Record<string, unknown>>;\n if (typeof el.type === \"function\") {\n const rendered = (el.type as (props: Record<string, unknown>) => ReactNode)(\n el.props ?? {},\n );\n return resolveSvgTree(rendered);\n }\n\n // Unwrap fragments: their children take the fragment's place in the parent\n // (callers flatten arrays), since the drawer only knows SVG element strings.\n if ((el.type as unknown) === REACT_FRAGMENT) {\n return resolveSvgTree((el.props ?? {}).children as ReactNode);\n }\n\n const elProps = (el.props ?? {}) as Record<string, unknown>;\n if (elProps.children !== undefined) {\n const resolvedChildren = resolveSvgTree(elProps.children as ReactNode);\n if (resolvedChildren !== elProps.children) {\n return { ...el, props: { ...elProps, children: resolvedChildren } };\n }\n }\n return el;\n}\n\n/**\n * Check if children contains any React elements (not just strings/numbers).\n */\nfunction hasElementChildren(children: unknown): boolean {\n if (\n children === undefined ||\n children === null ||\n typeof children === \"boolean\"\n )\n return false;\n if (typeof children === \"string\" || typeof children === \"number\")\n return false;\n\n if (Array.isArray(children)) {\n return children.some(\n (child) =>\n child !== null &&\n child !== undefined &&\n typeof child !== \"boolean\" &&\n typeof child !== \"string\" &&\n typeof child !== \"number\",\n );\n }\n\n // Single React element\n return typeof children === \"object\";\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\nimport type { ReactNode } from \"react\";\n\nimport type { RenderReactElementOptions } from \"../types.ts\";\nimport { drawNode } from \"./draw/index.ts\";\nimport { ensureFontsRegistered } from \"./font.ts\";\nimport { buildLayoutTree } from \"./layout.ts\";\nimport { releaseParagraphs } from \"./text/native.ts\";\nimport type { RenderContext } from \"./context.ts\";\n\n/**\n * Render a React element tree to a canvas context.\n *\n * Width and height default to `ctx.canvas.width` / `ctx.canvas.height` but\n * can be overridden via `options.width` and `options.height`. This is useful\n * for HiDPI rendering where the canvas is larger than the logical layout size.\n *\n * @param ctx - Canvas 2D rendering context to draw into\n * @param element - React element tree to render\n * @param options - Rendering options (fonts, dimensions, debug mode)\n *\n * @example\n * ```tsx\n * import { createCanvas, renderReactElement } from \"@effing/canvas\";\n *\n * const canvas = createCanvas(1080, 1080);\n * const ctx = canvas.getContext(\"2d\");\n *\n * await renderReactElement(ctx, <MyComponent />, { fonts: [myFont] });\n *\n * const png = await canvas.encode(\"png\");\n * ```\n *\n * @example HiDPI rendering (2x)\n * ```tsx\n * const dpr = 2;\n * const canvas = createCanvas(1080 * dpr, 1080 * dpr);\n * const ctx = canvas.getContext(\"2d\");\n * ctx.scale(dpr, dpr);\n *\n * await renderReactElement(ctx, <MyComponent />, {\n * fonts: [myFont],\n * width: 1080,\n * height: 1080,\n * });\n * ```\n *\n * @example Custom User-Agent for remote image fetches\n * ```tsx\n * await renderReactElement(ctx, <MyComponent />, {\n * userAgent: \"my-renderer/1.0\",\n * });\n * ```\n *\n * @example Persistent image cache for repeated calls (e.g. per frame)\n * ```tsx\n * const imageCache: ImageCache = new Map();\n * for (let frame = 0; frame < frameCount; frame++) {\n * await renderReactElement(ctx, <Frame n={frame} />, { fonts, imageCache });\n * }\n * ```\n */\nexport async function renderReactElement(\n ctx: SKRSContext2D,\n element: ReactNode,\n options: RenderReactElementOptions = {},\n): Promise<void> {\n const fonts = options.fonts ?? [];\n\n // Register fonts\n ensureFontsRegistered(fonts);\n\n // Get dimensions (option overrides take precedence over canvas size)\n const width = options.width ?? ctx.canvas.width;\n const height = options.height ?? ctx.canvas.height;\n\n // Per-render context: shared image cache + cross-cutting fetch/diagnostic\n // config, threaded through both the layout and draw phases. The caller may\n // supply the cache to persist image loads across calls.\n const renderContext: RenderContext = {\n imageCache: options.imageCache ?? new Map(),\n userAgent: options.userAgent,\n debug: options.debug ?? false,\n };\n\n // Build layout tree (Yoga)\n const emojiStyle =\n options.emoji === \"none\" ? undefined : (options.emoji ?? \"twemoji\");\n const fontFamilies = [...new Set(fonts.map((f) => f.name))];\n const { tree: layoutTree } = await buildLayoutTree(\n element,\n width,\n height,\n ctx,\n !!emojiStyle,\n fontFamilies,\n renderContext,\n );\n\n // Draw to canvas\n await drawNode(ctx, layoutTree, 0, 0, renderContext, emojiStyle);\n\n // Text is laid out as native paragraphs, whose memory Node releases only on\n // a turn of the event loop: take one when a caller's loop hasn't.\n await releaseParagraphs();\n}\n","import type { FontData } from \"./types.ts\";\nimport type { ComputedStyle } from \"./jsx/style/compute.ts\";\nimport { registerFont } from \"./jsx/font.ts\";\nimport { layoutText } from \"./jsx/text/index.ts\";\n\n/**\n * Options for {@link findLargestUsableFontSize}.\n */\nexport type FindLargestUsableFontSizeOptions = {\n /** The text to fit */\n text: string;\n /** Font data to use for measurement */\n font: FontData;\n /** Maximum width in pixels */\n maxWidth: number;\n /** Maximum height in pixels */\n maxHeight: number;\n /** Line height — `\"normal\"` uses font metrics, numeric values are CSS multipliers */\n lineHeight?: number | \"normal\";\n /**\n * Whitespace handling, mirroring CSS. Use `\"nowrap\"` (or `\"pre\"`) to fit text\n * on one line (per newline-separated paragraph) instead of wrapping to\n * `maxWidth` (default: `\"normal\"`).\n */\n whiteSpace?: ComputedStyle[\"whiteSpace\"];\n /** Minimum font size to consider (default: 1) */\n minFontSize?: number;\n /** Maximum font size to consider (default: 1000) */\n maxFontSize?: number;\n};\n\n/**\n * Find the largest integer font size that keeps text within the given bounds.\n *\n * Uses binary search over integer font sizes, measuring with {@link layoutText}\n * at each step. Returns `minFontSize` if even the smallest size overflows.\n *\n * By default text wraps to `maxWidth` and is fit into the `maxWidth` × `maxHeight`\n * box. Set `whiteSpace: \"nowrap\"` to fit the text on one line (per\n * newline-separated paragraph) instead, in which case `maxWidth` constrains the\n * full line width.\n */\nexport function findLargestUsableFontSize(\n options: FindLargestUsableFontSizeOptions,\n): number {\n const {\n text,\n font,\n maxWidth,\n maxHeight,\n lineHeight = \"normal\",\n whiteSpace,\n minFontSize = 1,\n maxFontSize = 1000,\n } = options;\n\n registerFont(font);\n\n let lo = minFontSize;\n let hi = maxFontSize;\n let best = minFontSize;\n\n while (lo <= hi) {\n const mid = Math.floor((lo + hi) / 2);\n const style: ComputedStyle = {\n fontSize: mid,\n fontFamily: font.name,\n fontWeight: font.weight,\n fontStyle: font.style,\n lineHeight: lineHeight === \"normal\" ? undefined : lineHeight,\n whiteSpace,\n };\n\n const result = layoutText(text, style, maxWidth);\n\n if (result.width <= maxWidth && result.height <= maxHeight) {\n best = mid;\n lo = mid + 1;\n } else {\n hi = mid - 1;\n }\n }\n\n return best;\n}\n"],"mappings":"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","names":["GlobalFonts","Path2D","resolveRadius","x","y","Path2D","Path2D","createCanvas","canvas","Path2D","Path2D","Path2D","Path2D","loadImage","parseCssColor","measureText","loadImage","parseCssColor","style","createCanvas"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/image.ts","../src/lottie.ts","../src/jsx/draw/utils.ts","../src/jsx/style/compute.ts","../src/jsx/text/native.ts","../src/jsx/language.ts","../src/jsx/text/measure.ts","../src/jsx/text/white-space.ts","../src/jsx/text/index.ts","../src/jsx/draw/clip.ts","../src/jsx/draw/clip-path.ts","../src/jsx/draw/rect.ts","../src/jsx/draw/gradient.ts","../src/jsx/draw/group.ts","../src/jsx/draw/object-fit.ts","../src/jsx/draw/image.ts","../src/jsx/draw/svg/style.ts","../src/jsx/draw/svg/tree.ts","../src/jsx/draw/svg/defs.ts","../src/jsx/draw/svg/transform.ts","../src/jsx/draw/svg/path.ts","../src/jsx/draw/offscreen.ts","../src/jsx/draw/svg/filters.ts","../src/jsx/draw/svg/shapes.ts","../src/jsx/draw/svg/gradients.ts","../src/jsx/draw/svg/paint.ts","../src/jsx/draw/svg/traverse.ts","../src/jsx/draw/svg/index.ts","../src/jsx/draw/text.ts","../src/jsx/emoji.ts","../src/jsx/draw/index.ts","../src/jsx/font.ts","../src/jsx/style/expand.ts","../src/jsx/yoga.ts","../src/jsx/style/properties.ts","../src/jsx/layout.ts","../src/jsx/index.ts","../src/fit-text.ts"],"sourcesContent":["// Re-export canvas primitives from @effing/skia so consumers never need a\n// direct dependency on it (it's a dependency of this package, which pnpm does\n// not expose to the consuming project). Re-exporting also guarantees a single\n// native copy:\n// a Path2D from one copy of @effing/skia cannot be used with a context from\n// another.\nimport { createCanvas as _createCanvas } from \"@effing/skia\";\nexport {\n Canvas,\n type SKRSContext2D,\n GlobalFonts,\n Image,\n ImageData,\n Path2D,\n DOMMatrix,\n DOMPoint,\n DOMRect,\n PathOp,\n FillType,\n StrokeJoin,\n StrokeCap,\n} from \"@effing/skia\";\n\n// loadImage is wrapped (not re-exported) so remote URLs go through the same\n// fetch path as <img> sources — see ./image.ts.\nexport {\n loadImage,\n type ImageCache,\n type LoadImageOptions,\n type LoadImageSource,\n} from \"./image.ts\";\n\n// encode() needs no patching: it snapshots the canvas when called, so later\n// drawing can't reach a pending encode, and the Buffer it resolves with owns\n// its native memory until the Buffer itself is collected (see\n// ./encode.test.ts). This used to copy the result to the JS heap, to guard\n// against lifetime bugs in @napi-rs/canvas's async encode that were fixed\n// upstream (napi-rs/canvas#1314, #1323) before @effing/skia was forked.\nexport function createCanvas(width: number, height: number) {\n return _createCanvas(width, height);\n}\n\n// Lottie API\nexport { LottieAnimation, loadLottie, renderLottieFrame } from \"./lottie.ts\";\n\n// JSX API\nexport { renderReactElement } from \"./jsx/index.ts\";\n\n// Font management\nexport {\n registerFont,\n registerFontFromPath,\n registeredFamilies,\n} from \"./jsx/font.ts\";\n\n// Fit text\nexport {\n findLargestUsableFontSize,\n type FindLargestUsableFontSizeOptions,\n} from \"./fit-text.ts\";\n\n// Types\nexport type {\n FontData,\n RenderReactElementOptions,\n EmojiStyle,\n} from \"./types.ts\";\n","import type { Image } from \"@effing/skia\";\nimport { loadImage as nativeLoadImage } from \"@effing/skia\";\n\n/** Source types accepted by {@link loadImage}, mirroring @effing/skia. */\nexport type LoadImageSource = Parameters<typeof nativeLoadImage>[0];\n\n/** Options for {@link loadImage}. */\nexport interface LoadImageOptions {\n /**\n * User-Agent header sent on remote (http/https) fetches. Matches the\n * `userAgent` option of `renderReactElement`, so `loadImage(url)` and an\n * `<img src={url}>` behave identically. An empty string is sent as an\n * explicit empty header; values with CR/LF cause fetch to throw `TypeError`.\n * Ignored for non-remote sources (paths, Buffers, data URIs).\n */\n userAgent?: string;\n}\n\n/**\n * Load an image from a path, Buffer, data URI, or remote URL.\n *\n * Remote http/https URLs are fetched via global fetch() and passed to the\n * native loader as bytes — the same path `<img>` sources take in\n * `renderReactElement`. This keeps `loadImage(url)` and `<img src={url}>`\n * consistent: both honor a global dispatcher / proxy (undici's\n * setGlobalDispatcher) and the `userAgent` option. @effing/skia's own URL\n * loader uses Node's raw http modules, which bypass any dispatcher, so it is\n * only used for non-remote sources here.\n *\n * Note: @effing/skia's `maxRedirects` / `requestOptions` load options are\n * intentionally not exposed — they only configure its built-in URL loader,\n * which this wrapper bypasses. Control remote fetches via fetch/undici instead.\n */\nexport function loadImage(\n source: LoadImageSource,\n options?: LoadImageOptions,\n): Promise<Image> {\n const remoteUrl =\n typeof source === \"string\" && isRemoteUrl(source)\n ? source\n : source instanceof URL && isRemoteUrl(source.href)\n ? source.href\n : undefined;\n if (remoteUrl !== undefined) {\n return loadRemoteImage(remoteUrl, options?.userAgent);\n }\n return nativeLoadImage(source);\n}\n\n/**\n * Per-render cache of image load promises, keyed by source string.\n * Shared between layout and draw phases to avoid duplicate loads.\n */\nexport type ImageCache = Map<string, Promise<Image>>;\n\n/**\n * Load an image via {@link loadImage}, deduplicating by source string through\n * the cache. Buffer sources are never cached (no stable key). `userAgent`, when\n * set, is forwarded to remote (http/https) fetches. The cache key is the URL\n * alone — the userAgent of the first call for a given URL is the one that hits\n * the wire; a later call with a different userAgent reuses the cached promise.\n *\n * Failed loads are evicted, so only successful loads stay cached: callers\n * sharing one cache across many renders (`options.imageCache`) retry a\n * transiently-failed source on the next call instead of replaying the\n * rejection forever.\n */\nexport function cachedLoadImage(\n cache: ImageCache,\n src: string | Buffer,\n userAgent?: string,\n): Promise<Image> {\n if (Buffer.isBuffer(src)) return loadImage(src);\n let entry = cache.get(src);\n if (!entry) {\n const created = loadImage(\n src,\n userAgent === undefined ? undefined : { userAgent },\n );\n created.catch(() => {\n if (cache.get(src) === created) cache.delete(src);\n });\n cache.set(src, created);\n entry = created;\n }\n return entry;\n}\n\n/**\n * True for http/https URLs, which are loaded via fetch() rather than the\n * native loader. Scheme match is case-insensitive (RFC 3986 §3.1).\n */\nexport function isRemoteUrl(src: string): boolean {\n return /^https?:\\/\\//i.test(src);\n}\n\n/**\n * Fetch a remote image via global fetch() and decode the bytes with the native\n * loader. Routing through fetch (rather than @effing/skia's raw-http URL\n * loader) lets a global dispatcher / proxy and the `userAgent` apply.\n */\nexport async function loadRemoteImage(\n url: string,\n userAgent?: string,\n): Promise<Image> {\n const init: RequestInit | undefined =\n userAgent !== undefined\n ? { headers: { \"User-Agent\": userAgent } }\n : undefined;\n const response = await fetch(url, init);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch image ${url}: ${response.status} ${response.statusText}`,\n );\n }\n const buffer = Buffer.from(await response.arrayBuffer());\n return nativeLoadImage(buffer);\n}\n","import { LottieAnimation } from \"@effing/skia\";\nimport type { SKRSContext2D } from \"@effing/skia\";\n\nexport { LottieAnimation };\n\n/**\n * Load a Lottie animation from a JSON string or Buffer.\n *\n * @param data - Lottie JSON string or Buffer\n * @param options - Optional resource path for external assets\n * @returns A `LottieAnimation` handle ready for rendering\n *\n * @example\n * ```ts\n * const anim = loadLottie(fs.readFileSync(\"animation.json\", \"utf-8\"));\n * ```\n */\nexport function loadLottie(\n data: string | Buffer,\n options?: { resourcePath?: string },\n): LottieAnimation {\n const jsonString = typeof data === \"string\" ? data : data.toString(\"utf-8\");\n return LottieAnimation.loadFromData(jsonString, {\n resourcePath: options?.resourcePath,\n });\n}\n\n/**\n * Render a specific frame of a Lottie animation to a canvas context.\n *\n * Seeks the animation to the given frame, then renders it onto the\n * provided context. The canvas dimensions determine the render size.\n *\n * @param ctx - Canvas 2D rendering context to draw into\n * @param animation - Lottie animation handle (from {@link loadLottie})\n * @param frame - Zero-based frame number to render\n *\n * @example\n * ```ts\n * import { createCanvas, loadLottie, renderLottieFrame } from \"@effing/canvas\";\n *\n * const canvas = createCanvas(1080, 1080);\n * const ctx = canvas.getContext(\"2d\");\n * const anim = loadLottie(jsonString);\n *\n * renderLottieFrame(ctx, anim, 0);\n * const png = canvas.encodeSync(\"png\");\n * ```\n */\nexport function renderLottieFrame(\n ctx: SKRSContext2D,\n animation: LottieAnimation,\n frame: number,\n): void {\n animation.seekFrame(frame);\n animation.render(ctx);\n}\n","/**\n * Shared CSS utility functions used by the draw system.\n */\n\nexport function parseCSSLength(value: string, referenceSize: number): number {\n if (value.endsWith(\"%\")) return (parseFloat(value) / 100) * referenceSize;\n return parseFloat(value);\n}\n\nexport function toNumber(v: unknown): number {\n if (typeof v === \"number\") return v;\n if (v === undefined || v === null) return 0;\n const n = parseFloat(String(v));\n return isNaN(n) ? 0 : n;\n}\n\n/**\n * Resolve a box-model value (padding, border-width) that may be a percentage.\n * Per CSS spec, percentage padding/border resolves against the element's width\n * (even for top/bottom).\n */\nexport function resolveBoxValue(v: unknown, referenceWidth: number): number {\n if (typeof v === \"number\") return v;\n if (v === undefined || v === null) return 0;\n const s = String(v);\n if (s.endsWith(\"%\")) return (parseFloat(s) / 100) * referenceWidth;\n const n = parseFloat(s);\n return isNaN(n) ? 0 : n;\n}\n\n/**\n * Format a number for embedding in a CSS string. `String(n)` switches to\n * exponent notation for very small or large magnitudes (`1e-7`), which CSS\n * parsers reject, so round to six decimals and print positionally.\n */\nexport function formatCSSNumber(n: number): string {\n const fixed = n.toFixed(6).replace(/\\.?0+$/, \"\");\n return fixed === \"-0\" || fixed === \"\" ? \"0\" : fixed;\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport { formatCSSNumber } from \"../draw/utils.ts\";\n\n/**\n * Style after shorthand expansion but before unit resolution.\n * Properties like fontSize may still contain CSS unit strings (e.g. \"4em\").\n */\nexport type ExpandedStyle = Omit<ComputedStyle, \"fontSize\"> & {\n fontSize?: number | string;\n};\n\n/**\n * Normalized, computed CSS style after shorthand expansion.\n * All dimension values are numbers (pixels) or percentage strings.\n */\nexport type ComputedStyle = {\n // Display & layout\n display?: \"flex\" | \"none\";\n flexDirection?: \"row\" | \"column\" | \"row-reverse\" | \"column-reverse\";\n justifyContent?:\n | \"flex-start\"\n | \"flex-end\"\n | \"center\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\";\n alignItems?: \"flex-start\" | \"flex-end\" | \"center\" | \"stretch\" | \"baseline\";\n alignSelf?:\n \"auto\" | \"flex-start\" | \"flex-end\" | \"center\" | \"stretch\" | \"baseline\";\n alignContent?:\n | \"flex-start\"\n | \"flex-end\"\n | \"center\"\n | \"stretch\"\n | \"space-between\"\n | \"space-around\";\n flexWrap?: \"nowrap\" | \"wrap\" | \"wrap-reverse\";\n flexGrow?: number;\n flexShrink?: number;\n flexBasis?: number | string;\n\n // Dimensions\n width?: number | string;\n height?: number | string;\n minWidth?: number | string;\n minHeight?: number | string;\n maxWidth?: number | string;\n maxHeight?: number | string;\n\n // Position\n position?: \"relative\" | \"absolute\";\n top?: number | string;\n right?: number | string;\n bottom?: number | string;\n left?: number | string;\n\n // Margin\n marginTop?: number | string;\n marginRight?: number | string;\n marginBottom?: number | string;\n marginLeft?: number | string;\n\n // Padding\n paddingTop?: number | string;\n paddingRight?: number | string;\n paddingBottom?: number | string;\n paddingLeft?: number | string;\n\n // Border\n borderTopWidth?: number | string;\n borderRightWidth?: number | string;\n borderBottomWidth?: number | string;\n borderLeftWidth?: number | string;\n borderTopColor?: string;\n borderRightColor?: string;\n borderBottomColor?: string;\n borderLeftColor?: string;\n borderTopStyle?: string;\n borderRightStyle?: string;\n borderBottomStyle?: string;\n borderLeftStyle?: string;\n borderTopLeftRadius?: number | string;\n borderTopRightRadius?: number | string;\n borderBottomRightRadius?: number | string;\n borderBottomLeftRadius?: number | string;\n\n // Gap\n rowGap?: number;\n columnGap?: number;\n\n // Overflow\n overflow?: string;\n overflowX?: string;\n overflowY?: string;\n\n // Colors & background\n backgroundColor?: string;\n color?: string;\n opacity?: number;\n backgroundImage?: string;\n backgroundSize?: string;\n backgroundRepeat?:\n \"repeat\" | \"no-repeat\" | \"repeat-x\" | \"repeat-y\" | \"space\" | \"round\";\n\n // Typography\n fontSize?: number;\n fontFamily?: string;\n fontWeight?: number | string;\n fontStyle?: \"normal\" | \"italic\";\n textAlign?: \"left\" | \"center\" | \"right\" | \"justify\";\n textDecoration?: string;\n textTransform?: \"none\" | \"uppercase\" | \"lowercase\" | \"capitalize\";\n lineHeight?: number | string;\n letterSpacing?: number | string;\n whiteSpace?: \"normal\" | \"nowrap\" | \"pre\" | \"pre-wrap\" | \"pre-line\";\n wordBreak?: \"normal\" | \"break-all\" | \"break-word\" | \"keep-all\";\n overflowWrap?: \"normal\" | \"break-word\" | \"anywhere\";\n textOverflow?: \"clip\" | \"ellipsis\";\n lineClamp?: number;\n\n // Box shadow\n boxShadow?: string;\n textShadow?: string;\n\n // Transform\n transform?: string;\n transformOrigin?: string;\n\n // Image\n objectFit?: \"contain\" | \"cover\" | \"fill\" | \"none\" | \"scale-down\";\n\n // Filter\n filter?: string;\n backdropFilter?: string;\n\n // Clipping\n clipPath?: string;\n\n // Text box trim\n textBoxTrim?: \"none\" | \"trim-start\" | \"trim-end\" | \"trim-both\";\n textBoxEdge?: string;\n\n // Text stroke\n WebkitTextStrokeWidth?: number | string;\n WebkitTextStrokeColor?: string;\n};\n\nconst ROOT_FONT_SIZE = 16;\n\n/**\n * Default font family. Uses concrete system font names so @effing/skia\n * resolves real font metrics instead of generic ratios for unnamed families.\n */\nexport const DEFAULT_FONT_FAMILY = \"Helvetica, Arial, sans-serif\";\n\n/**\n * Default styles for the root element.\n */\nexport const DEFAULT_STYLE: ComputedStyle = {\n display: \"flex\",\n flexDirection: \"row\",\n flexWrap: \"nowrap\",\n flexGrow: 0,\n flexShrink: 0,\n alignItems: \"stretch\",\n justifyContent: \"flex-start\",\n position: \"relative\",\n fontSize: ROOT_FONT_SIZE,\n fontWeight: 400,\n fontStyle: \"normal\",\n fontFamily: DEFAULT_FONT_FAMILY,\n color: \"black\",\n lineHeight: \"normal\",\n textAlign: \"left\",\n whiteSpace: \"normal\",\n wordBreak: \"normal\",\n textOverflow: \"clip\",\n opacity: 1,\n overflow: \"visible\",\n};\n\n/**\n * CSS properties that are inherited by child elements.\n */\nconst INHERITABLE_PROPS: (keyof ComputedStyle)[] = [\n \"color\",\n \"fontSize\",\n \"fontFamily\",\n \"fontWeight\",\n \"fontStyle\",\n \"textAlign\",\n \"textTransform\",\n \"textDecoration\",\n \"lineHeight\",\n \"letterSpacing\",\n \"whiteSpace\",\n \"wordBreak\",\n \"overflowWrap\",\n \"textOverflow\",\n \"lineClamp\",\n \"textBoxTrim\",\n \"textBoxEdge\",\n \"textShadow\",\n \"WebkitTextStrokeWidth\",\n \"WebkitTextStrokeColor\",\n];\n\n/**\n * Resolve the computed style for a node, inheriting from parent where appropriate.\n */\nexport function resolveStyle(\n rawStyle: ExpandedStyle | undefined,\n parentStyle: ComputedStyle,\n): ComputedStyle {\n const style = { ...rawStyle };\n\n // Apply inherited properties\n for (const prop of INHERITABLE_PROPS) {\n if (style[prop] === undefined && parentStyle[prop] !== undefined) {\n (style as Record<string, unknown>)[prop] = parentStyle[prop];\n }\n }\n\n // Resolve fontSize (ensure it's a number, respecting em/rem/etc units)\n if (typeof style.fontSize === \"string\") {\n const parentFontSize =\n typeof parentStyle.fontSize === \"number\"\n ? parentStyle.fontSize\n : ROOT_FONT_SIZE;\n const resolved = resolveUnit(\n style.fontSize,\n 0,\n 0,\n parentFontSize,\n ROOT_FONT_SIZE,\n );\n style.fontSize = typeof resolved === \"number\" ? resolved : parentFontSize;\n }\n\n // Resolve lineHeight: parse string values to numbers but keep multipliers\n // as-is so they're recalculated per-element in text layout (using each\n // element's own fontSize rather than the parent's).\n if (typeof style.lineHeight === \"string\") {\n const str = style.lineHeight;\n if (str.endsWith(\"%\")) {\n style.lineHeight = parseFloat(str) / 100;\n } else {\n const parsed = parseFloat(str);\n if (!isNaN(parsed)) {\n style.lineHeight = parsed;\n }\n }\n }\n\n // Resolve letterSpacing (respecting em/rem/etc units)\n if (typeof style.letterSpacing === \"string\") {\n const currentFontSize =\n typeof style.fontSize === \"number\"\n ? style.fontSize\n : typeof parentStyle.fontSize === \"number\"\n ? parentStyle.fontSize\n : ROOT_FONT_SIZE;\n const resolved = resolveUnit(\n style.letterSpacing,\n 0,\n 0,\n currentFontSize,\n ROOT_FONT_SIZE,\n );\n if (typeof resolved === \"number\") {\n style.letterSpacing = resolved;\n }\n }\n\n return style as ComputedStyle;\n}\n\n/**\n * Dimension properties that may contain CSS units needing resolution.\n */\nconst DIMENSION_PROPS: (keyof ComputedStyle)[] = [\n \"width\",\n \"height\",\n \"minWidth\",\n \"minHeight\",\n \"maxWidth\",\n \"maxHeight\",\n \"top\",\n \"right\",\n \"bottom\",\n \"left\",\n \"marginTop\",\n \"marginRight\",\n \"marginBottom\",\n \"marginLeft\",\n \"paddingTop\",\n \"paddingRight\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"rowGap\",\n \"columnGap\",\n \"flexBasis\",\n \"borderTopWidth\",\n \"borderRightWidth\",\n \"borderBottomWidth\",\n \"borderLeftWidth\",\n \"borderTopLeftRadius\",\n \"borderTopRightRadius\",\n \"borderBottomRightRadius\",\n \"borderBottomLeftRadius\",\n \"WebkitTextStrokeWidth\",\n];\n\n/**\n * Resolve a single CSS dimension string to a pixel number.\n * Returns the original value for `%` and `auto` (Yoga handles those),\n * and for values that are already numbers or unrecognised strings.\n */\nexport function resolveUnit(\n value: string,\n viewportWidth: number,\n viewportHeight: number,\n fontSize: number,\n rootFontSize: number,\n): number | string {\n // Percentages and auto are handled downstream by Yoga\n if (value.endsWith(\"%\") || value === \"auto\") return value;\n\n // Viewport-relative units\n if (value.endsWith(\"vmin\")) {\n const n = parseFloat(value);\n return isNaN(n)\n ? value\n : (n / 100) * Math.min(viewportWidth, viewportHeight);\n }\n if (value.endsWith(\"vmax\")) {\n const n = parseFloat(value);\n return isNaN(n)\n ? value\n : (n / 100) * Math.max(viewportWidth, viewportHeight);\n }\n if (value.endsWith(\"vw\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : (n / 100) * viewportWidth;\n }\n if (value.endsWith(\"vh\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : (n / 100) * viewportHeight;\n }\n\n // Font-relative units\n if (value.endsWith(\"rem\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * rootFontSize;\n }\n if (value.endsWith(\"em\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * fontSize;\n }\n\n // Absolute units (CSS reference pixel = 1/96 inch)\n if (value.endsWith(\"px\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n;\n }\n if (value.endsWith(\"pt\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * (96 / 72);\n }\n if (value.endsWith(\"pc\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * 16;\n }\n if (value.endsWith(\"in\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * 96;\n }\n if (value.endsWith(\"cm\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * (96 / 2.54);\n }\n if (value.endsWith(\"mm\")) {\n const n = parseFloat(value);\n return isNaN(n) ? value : n * (96 / 25.4);\n }\n\n return value;\n}\n\n/**\n * Resolve CSS units (vw, vh, vmin, vmax, em, rem, px, pt, pc, in, cm, mm)\n * in a style object to pixel values. Percentages and `auto` pass through\n * unchanged for Yoga to handle.\n */\nexport function resolveUnits(\n style: ComputedStyle,\n viewportWidth: number,\n viewportHeight: number,\n rootFontSize: number = ROOT_FONT_SIZE,\n): ComputedStyle {\n const fontSize =\n typeof style.fontSize === \"number\" ? style.fontSize : rootFontSize;\n\n for (const prop of DIMENSION_PROPS) {\n const value = style[prop];\n if (typeof value !== \"string\") continue;\n const resolved = resolveUnit(\n value,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n if (resolved !== value) {\n (style as Record<string, unknown>)[prop] = resolved;\n }\n }\n\n // Resolve CSS length units inside transform, clip-path and backdrop-filter\n // strings so that by draw time values are either bare numbers or `%` (which\n // need element dimensions).\n for (const [prop, suffix] of LENGTH_STRING_PROPS) {\n const value = style[prop];\n if (typeof value !== \"string\") continue;\n (style as Record<string, unknown>)[prop] = resolveLengthUnits(\n value,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n suffix,\n );\n }\n\n return style;\n}\n\n/**\n * String-valued properties whose embedded CSS lengths are resolved to pixels,\n * with the suffix the resolved numbers are written with. The transform parser\n * takes bare numbers; clip-path and filter strings keep an explicit `px` so\n * they stay valid CSS for the parsers downstream (Skia's filter parser\n * rejects a unitless `blur(6)`).\n */\nconst LENGTH_STRING_PROPS: [keyof ComputedStyle, string][] = [\n [\"transform\", \"\"],\n [\"transformOrigin\", \"\"],\n [\"clipPath\", \"px\"],\n [\"filter\", \"px\"],\n [\"backdropFilter\", \"px\"],\n];\n\n/**\n * Resolve CSS length units (vw, vh, em, rem, px, etc.) inside a string value\n * such as a transform, clip-path or filter. Percentages and angle units (deg,\n * rad, turn) are left untouched — percentages need element dimensions\n * (available at draw time) and angle units are not lengths.\n */\nfunction resolveLengthUnits(\n transform: string,\n viewportWidth: number,\n viewportHeight: number,\n fontSize: number,\n rootFontSize: number,\n suffix = \"\",\n): string {\n return transform.replace(\n // The lookbehind keeps a number from being matched mid-token (`1e1em`).\n /(?<![\\w.])(-?\\d*\\.?\\d+)(vw|vh|vmin|vmax|em|rem|px|pt|pc|in|cm|mm)\\b/g,\n (match) => {\n const resolved = resolveUnit(\n match,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n return typeof resolved === \"number\"\n ? `${formatCSSNumber(resolved)}${suffix}`\n : match;\n },\n );\n}\n\n/**\n * Resolve a dimension value (width, height, margin, etc.) to pixels.\n * Percentage values are resolved relative to the provided container size.\n */\nexport function resolveDimension(\n value: number | string | undefined,\n containerSize: number,\n): number | undefined {\n if (value === undefined || value === \"auto\") return undefined;\n if (typeof value === \"number\") return value;\n const s = String(value);\n if (s.endsWith(\"%\")) {\n return (parseFloat(s) / 100) * containerSize;\n }\n const n = parseFloat(s);\n return isNaN(n) ? undefined : n;\n}\n","// Native paragraph layout through @effing/skia's `Paragraph`: Skia breaks,\n// shapes and paints the text in one place, instead of this package measuring\n// it word by word across the native boundary. The paragraph follows the CSS\n// line model (every line box exactly `lineHeight` tall, baseline placed by\n// half-leading from the font's hhea metrics) and paints unhinted, unsnapped\n// glyphs.\n\nimport { Paragraph } from \"@effing/skia/extensions\";\nimport type {\n ParagraphLine,\n ParagraphPlaceholder,\n ParagraphStyle,\n} from \"@effing/skia/extensions\";\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { DEFAULT_FONT_FAMILY } from \"../style/compute.ts\";\nimport { isEmoji } from \"../language.ts\";\nimport { measureTrimMetrics, quoteFontFamilies } from \"./measure.ts\";\nimport type { PlacedEmoji, TextLayoutResult, TextSegment } from \"./index.ts\";\n\nexport type NativeParagraph = Paragraph;\n\nfunction toWeight(weight: number | string | undefined): number {\n if (typeof weight === \"number\") return weight;\n if (weight === \"bold\") return 700;\n const parsed = parseInt(String(weight ?? \"400\"), 10);\n return isNaN(parsed) ? 400 : parsed;\n}\n\nfunction toFontStyle(\n fontStyle: string | undefined,\n): ParagraphStyle[\"fontStyle\"] {\n if (fontStyle?.startsWith(\"italic\")) return \"italic\";\n if (fontStyle?.startsWith(\"oblique\")) return \"oblique\";\n return \"normal\";\n}\n\nconst TEXT_ALIGNS = new Set([\n \"left\",\n \"right\",\n \"center\",\n \"justify\",\n \"start\",\n \"end\",\n]);\n\nfunction toTextAlign(\n textAlign: string | undefined,\n): ParagraphStyle[\"textAlign\"] {\n return textAlign !== undefined && TEXT_ALIGNS.has(textAlign)\n ? (textAlign as ParagraphStyle[\"textAlign\"])\n : \"left\";\n}\n\n/** CSS `word-break`, as the paragraph's `wordBreak`. */\nfunction toWordBreak(style: ComputedStyle): ParagraphStyle[\"wordBreak\"] {\n const { wordBreak } = style;\n return wordBreak === \"break-all\" || wordBreak === \"keep-all\"\n ? wordBreak\n : \"normal\";\n}\n\n/**\n * CSS `overflow-wrap`, as the paragraph's `overflowWrap`. The deprecated\n * `word-break: break-word` is `overflow-wrap: anywhere`, which breaks an\n * overlong word as `break-word` does (it only adds to min-content). The\n * legacy `word-wrap` arrives as `overflowWrap` (see `expandStyle`).\n */\nfunction toOverflowWrap(style: ComputedStyle): ParagraphStyle[\"overflowWrap\"] {\n const { overflowWrap, wordBreak } = style;\n return overflowWrap === \"break-word\" ||\n overflowWrap === \"anywhere\" ||\n wordBreak === \"break-word\"\n ? \"break-word\"\n : \"normal\";\n}\n\n// Skia treats a width of 0 as unbounded; a box with no room wraps at every\n// opportunity instead.\nconst MIN_WIDTH = 0.01;\n\n// A paragraph needs a font size > 0. CSS draws `font-size: 0` text as\n// nothing, in line boxes of no height under `line-height: normal`.\nconst MIN_FONT_SIZE = 1e-3;\n\n/**\n * Where an emoji drawn as an image sits on its line: its bottom 0.1em below\n * the baseline, as CSS `vertical-align: -0.1em`. That's where Chrome draws an\n * emoji glyph (Apple Color Emoji's 🌍 ink spans 0.115em below the baseline to\n * 0.865em above it, at any line height), and what twemoji's own stylesheet\n * gives its images.\n */\nconst EMOJI_DROP = 0.1;\n\n// A paragraph's native memory (some 20 KB) is released by a finalizer, and\n// Node only runs finalizers on a later turn of the event loop. A frame loop\n// that awaits nothing but microtasks never gets there, and would grow by every\n// paragraph it has built. So they are counted per turn, and a render that\n// finds too many outstanding yields one turn itself.\nconst MAX_PENDING_PARAGRAPHS = 2000;\nlet pendingParagraphs = 0;\nlet turnWatched = false;\n\nfunction countParagraph(): void {\n pendingParagraphs++;\n if (turnWatched) return;\n turnWatched = true;\n // Runs once the event loop turns, by whoever's doing.\n setImmediate(() => {\n pendingParagraphs = 0;\n turnWatched = false;\n });\n}\n\n/**\n * Give Node a turn of the event loop to release the paragraphs built so far,\n * if enough have piled up since the last one.\n */\nexport async function releaseParagraphs(): Promise<void> {\n if (pendingParagraphs < MAX_PENDING_PARAGRAPHS) return;\n await new Promise<void>((resolve) => setImmediate(resolve));\n}\n\nconst graphemeSegmenter = new Intl.Segmenter(undefined, {\n granularity: \"grapheme\",\n});\n\n/**\n * The text as a paragraph's content, with every emoji grapheme an inline\n * placeholder for its image.\n */\ntype Content = {\n items: (string | ParagraphPlaceholder)[];\n /** The emoji, in the order of their placeholders. */\n emoji: string[];\n /**\n * Maps a UTF-16 index in the paragraph's text, where a placeholder counts\n * as one unit, to one in `text`; undefined when they're the same.\n */\n toTextIndex?: (index: number) => number;\n};\n\nfunction splitEmoji(\n text: string,\n fontSize: number,\n letterSpacing: number,\n): Content {\n const items: (string | ParagraphPlaceholder)[] = [];\n const emoji: string[] = [];\n // Paragraph index → text index, at the start of each emoji and after it.\n const marks: [number, number][] = [];\n let run = \"\";\n let paragraphIndex = 0;\n let textIndex = 0;\n for (const { segment } of graphemeSegmenter.segment(text)) {\n if (!isEmoji(segment)) {\n run += segment;\n paragraphIndex += segment.length;\n textIndex += segment.length;\n continue;\n }\n if (run) items.push(run);\n run = \"\";\n items.push({\n // Letter spacing follows every character, an emoji too, but a\n // paragraph doesn't add it to a placeholder.\n width: Math.max(0, fontSize + letterSpacing),\n height: fontSize,\n verticalAlign: \"baseline\",\n baselineOffset: fontSize * (1 - EMOJI_DROP),\n // Lines break around it as around an emoji, not an inline-block: it\n // stays with the punctuation next to it, so \"Hi 🎉! ok\" breaks as\n // \"Hi | 🎉! | ok\" and \"(🎉)\" stays whole, as in browsers.\n lineBreak: \"emoji\",\n });\n emoji.push(segment);\n marks.push([paragraphIndex, textIndex]);\n paragraphIndex += 1;\n textIndex += segment.length;\n marks.push([paragraphIndex, textIndex]);\n }\n if (run) items.push(run);\n if (emoji.length === 0) return { items: [text], emoji };\n return {\n items,\n emoji,\n toTextIndex: (index) => {\n // The last mark at or before `index`; text runs map one to one.\n let mark: [number, number] = [0, 0];\n for (const m of marks) {\n if (m[0] > index) break;\n mark = m;\n }\n return mark[1] + (index - mark[0]);\n },\n };\n}\n\n/**\n * Lay out already-transformed text natively: one segment per line, CSS\n * half-leading line boxes from the font's hhea metrics, an ellipsis for\n * nowrap + text-overflow and for line-clamp, and text-box-trim.\n *\n * @param lineHeight - Line box height in px, or undefined for `normal`\n * @param emojiEnabled - Whether emoji are drawn as images, each in an inline\n * box of its own\n */\nexport function layoutTextNative(\n text: string,\n style: ComputedStyle,\n maxWidth: number,\n lineHeight: number | undefined,\n emojiEnabled?: boolean,\n): TextLayoutResult {\n const styledFontSize = style.fontSize ?? 16;\n const fontSize = Number.isFinite(styledFontSize)\n ? Math.max(styledFontSize, MIN_FONT_SIZE)\n : 16;\n const fontFamily = style.fontFamily ?? DEFAULT_FONT_FAMILY;\n const fontWeight = style.fontWeight ?? 400;\n const fontStyle = style.fontStyle ?? \"normal\";\n const letterSpacing =\n typeof style.letterSpacing === \"number\" &&\n Number.isFinite(style.letterSpacing)\n ? style.letterSpacing\n : 0;\n const whiteSpace = style.whiteSpace ?? \"normal\";\n const noWrap = whiteSpace === \"nowrap\" || whiteSpace === \"pre\";\n const lineClamp =\n style.lineClamp && style.lineClamp >= 1\n ? Math.floor(style.lineClamp)\n : undefined;\n const ellipsis =\n lineClamp !== undefined || (noWrap && style.textOverflow === \"ellipsis\")\n ? \"…\"\n : undefined;\n const width = maxWidth > 0 ? maxWidth : MIN_WIDTH;\n\n const content = emojiEnabled\n ? splitEmoji(text, fontSize, letterSpacing)\n : { items: [text], emoji: [] };\n\n // Skia keeps its own cache of shaped text, so building a paragraph for text\n // it has seen (the next frame of a video, or Yoga measuring a node again)\n // only breaks the lines anew.\n const paragraph = new Paragraph(content.items, {\n fontFamily: quoteFontFamilies(fontFamily),\n fontSize,\n fontWeight: toWeight(fontWeight),\n fontStyle: toFontStyle(fontStyle),\n letterSpacing,\n lineHeight,\n textAlign: toTextAlign(style.textAlign),\n noWrap,\n maxLines: lineClamp,\n ellipsis,\n // `pre` and `pre-wrap` keep the spaces before a line break in the line.\n keepTrailingWhitespace: whiteSpace === \"pre\" || whiteSpace === \"pre-wrap\",\n wordBreak: toWordBreak(style),\n overflowWrap: toOverflowWrap(style),\n });\n countParagraph();\n const layout = paragraph.layout(width);\n\n // An empty paragraph has no lines, where CSS keeps one empty line box.\n const lines: ParagraphLine[] =\n layout.lines.length > 0\n ? layout.lines\n : [\n {\n left: 0,\n width: 0,\n // As Skia places a baseline: by half-leading in the line box.\n baseline: (layout.lineHeight + layout.ascent - layout.descent) / 2,\n startIndex: 0,\n endIndex: 0,\n hardBreak: true,\n },\n ];\n const toTextIndex = content.toTextIndex ?? ((index: number) => index);\n const segments: TextSegment[] = lines.map((line, i) => ({\n // A line that ends the text at a newline reports the newline as its text.\n text: text\n .slice(toTextIndex(line.startIndex), toTextIndex(line.endIndex))\n .replace(/\\n/g, \"\"),\n x: line.left,\n y: line.baseline,\n width: line.width,\n height: layout.lineHeight,\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n color: style.color ?? \"black\",\n ascent: layout.ascent,\n textDecoration: style.textDecoration,\n letterSpacing,\n lineIndex: i,\n }));\n\n const emoji: PlacedEmoji[] = [];\n layout.placeholders.forEach((box, i) => {\n // A placeholder that line-clamp or an ellipsis cut off has no box.\n if (!box) return;\n emoji.push({\n grapheme: content.emoji[i]!,\n x: box.x,\n y: box.y,\n size: fontSize,\n baseline: lines[box.line]!.baseline,\n });\n });\n\n let height = lines.length * layout.lineHeight;\n if (lineHeight === undefined) {\n // Round auto line-height boxes up so Yoga's integer rounding never clips\n // a descender. Text of no font size, laid out at MIN_FONT_SIZE, has line\n // boxes of no height, as in CSS.\n const noFontSize = Number.isFinite(styledFontSize) && styledFontSize <= 0;\n height = noFontSize ? 0 : Math.ceil(height);\n }\n\n let paragraphOffsetY = 0;\n const textBoxTrim = style.textBoxTrim;\n if (textBoxTrim && textBoxTrim !== \"none\") {\n const trim = measureTrimMetrics(\n fontSize,\n fontFamily,\n fontWeight,\n fontStyle,\n layout.lineHeight,\n style.textBoxEdge ?? \"text\",\n layout.ascent,\n layout.descent,\n );\n if (textBoxTrim === \"trim-start\" || textBoxTrim === \"trim-both\") {\n for (const seg of segments) seg.y -= trim.overTrim;\n for (const e of emoji) {\n e.y -= trim.overTrim;\n e.baseline -= trim.overTrim;\n }\n height -= trim.overTrim;\n paragraphOffsetY = -trim.overTrim;\n }\n if (textBoxTrim === \"trim-end\" || textBoxTrim === \"trim-both\") {\n height -= trim.underTrim;\n }\n }\n\n return {\n segments,\n width: segments.reduce((w, s) => Math.max(w, s.width), 0),\n height,\n paragraph,\n paragraphOffsetY,\n emoji,\n };\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\n/**\n * Detect the primary script/language of a text string.\n * Used for font selection and line-breaking behavior.\n */\nexport function detectLanguageCode(text: string): string | undefined {\n for (const char of text) {\n const cp = char.codePointAt(0);\n if (cp === undefined) continue;\n\n // CJK Unified Ideographs\n if (cp >= 0x4e00 && cp <= 0x9fff) return \"zh\";\n // CJK Extension A\n if (cp >= 0x3400 && cp <= 0x4dbf) return \"zh\";\n // Hiragana\n if (cp >= 0x3040 && cp <= 0x309f) return \"ja\";\n // Katakana\n if (cp >= 0x30a0 && cp <= 0x30ff) return \"ja\";\n // Hangul Syllables\n if (cp >= 0xac00 && cp <= 0xd7af) return \"ko\";\n // Hangul Jamo\n if (cp >= 0x1100 && cp <= 0x11ff) return \"ko\";\n // Thai\n if (cp >= 0x0e00 && cp <= 0x0e7f) return \"th\";\n // Arabic\n if (cp >= 0x0600 && cp <= 0x06ff) return \"ar\";\n // Hebrew\n if (cp >= 0x0590 && cp <= 0x05ff) return \"he\";\n // Devanagari\n if (cp >= 0x0900 && cp <= 0x097f) return \"hi\";\n // Bengali\n if (cp >= 0x0980 && cp <= 0x09ff) return \"bn\";\n // Tamil\n if (cp >= 0x0b80 && cp <= 0x0bff) return \"ta\";\n // Telugu\n if (cp >= 0x0c00 && cp <= 0x0c7f) return \"te\";\n // Kannada\n if (cp >= 0x0c80 && cp <= 0x0cff) return \"kn\";\n // Malayalam\n if (cp >= 0x0d00 && cp <= 0x0d7f) return \"ml\";\n }\n\n return undefined;\n}\n\n// Which graphemes are drawn as emoji images, following UTS #51: every emoji\n// character, with or without U+FE0F, except the few that are text by default\n// in every font (©, ®, ™, digits, # and *). Browsers draw the other\n// text-default emoji characters in the BMP, such as ❤ or ☎, as monochrome\n// text through system font fallback; canvas has no such fallback, so an\n// image beats tofu.\n\n/**\n * A code point reserved for emoji that this runtime's Unicode doesn't know\n * yet: every emoji added since Unicode 9 is presented as one by default.\n */\nexport const UNASSIGNED_PICTOGRAPHIC = String.raw`(?=\\p{Cn})\\p{Extended_Pictographic}`;\n\n/** A character with an emoji form, \\p{Emoji} or \\p{Extended_Pictographic}. */\nconst EMOJI_CHAR = String.raw`[\\p{Emoji}\\p{Extended_Pictographic}]`;\n\n/**\n * A keycap base: a digit, # or *. On its own, even before U+FE0F, it's text,\n * as in Chrome; only a keycap sequence makes it an emoji.\n */\nconst KEYCAP_BASE = \"[0-9#*]\";\n\n/**\n * An emoji character that stays text on its own: a keycap base (digits, # and\n * *), text unless a keycap follows it, and ©, ® and ™, text unless U+FE0F\n * follows them.\n */\nconst TEXT_EMOJI_CHAR = String.raw`[0-9#*\\u00A9\\u00AE\\u2122]`;\n\n/** A tag sequence's tags, as in a subdivision flag such as 🏴󠁧󠁢󠁥󠁮󠁧󠁿. */\nconst TAGS = String.raw`[\\u{E0020}-\\u{E007E}]+\\u{E007F}`;\n\n/** An emoji element drawn as an emoji, also when it stands alone. */\nconst PRESENTED_EMOJI = [\n // Keycap: 1️⃣, and the unqualified 1⃣.\n String.raw`${KEYCAP_BASE}\\uFE0F?\\u20E3`,\n // Flag: a pair of regional indicators.\n String.raw`\\p{Regional_Indicator}{2}`,\n // Emoji presentation sequence (©️), modifier sequence (👍🏽, ☝🏽) or tag\n // sequence (🏴󠁧󠁢󠁥󠁮󠁧󠁿).\n String.raw`(?!${KEYCAP_BASE})${EMOJI_CHAR}(?:\\uFE0F|\\p{Emoji_Modifier}|${TAGS})`,\n // An emoji character on its own, emoji presentation by default (🌍, ⭐) or\n // text (❤, ☎, 🕵), but not one that stays text.\n String.raw`(?!${TEXT_EMOJI_CHAR})\\p{Emoji}`,\n UNASSIGNED_PICTOGRAPHIC,\n].join(\"|\");\n\n/**\n * An element of a ZWJ sequence: any emoji element, or a character with an\n * emoji form that isn't one on its own (the © in ©‍®), but no bare keycap\n * base.\n */\nconst ZWJ_ELEMENT = `(?:${PRESENTED_EMOJI}|(?!${KEYCAP_BASE})${EMOJI_CHAR})`;\n\nconst EMOJI_RE = new RegExp(\n `^(?:${PRESENTED_EMOJI}|${ZWJ_ELEMENT}(?:\\\\u200D${ZWJ_ELEMENT})+)$`,\n \"u\",\n);\n\n/**\n * Whether a grapheme cluster is an emoji, to draw as an image: an emoji\n * character with or without U+FE0F (©, ®, ™ only with it, and digits, # and\n * * only in a keycap), a keycap, a flag, a modifier or tag sequence, or a ZWJ sequence of emoji\n * (UTS #51). U+FE0E keeps an emoji character text. A ZWJ between anything\n * else (the joiner in Arabic or Indic text, or a lone one) doesn't make an\n * emoji, and neither do symbols with no emoji form, such as ✓ or ●.\n *\n * @param grapheme - One grapheme cluster, as `Intl.Segmenter` splits text\n */\nexport function isEmoji(grapheme: string): boolean {\n return EMOJI_RE.test(grapheme);\n}\n","import { createCanvas } from \"@effing/skia\";\nimport type { SKRSContext2D } from \"@effing/skia\";\n\n// Scratch canvas for measuring glyphs\nlet scratchCtx: SKRSContext2D | null = null;\n\nfunction getScratchCtx(): SKRSContext2D {\n if (!scratchCtx) {\n scratchCtx = createCanvas(1, 1).getContext(\"2d\");\n }\n return scratchCtx;\n}\n\nconst GENERIC_FAMILIES = new Set([\n \"serif\",\n \"sans-serif\",\n \"monospace\",\n \"cursive\",\n \"fantasy\",\n \"system-ui\",\n \"ui-serif\",\n \"ui-sans-serif\",\n \"ui-monospace\",\n \"ui-rounded\",\n \"math\",\n \"emoji\",\n \"fangsong\",\n]);\n\nfunction quoteFontFamily(family: string): string {\n if (!family || GENERIC_FAMILIES.has(family)) return family;\n return `\"${family}\"`;\n}\n\n/** A font-family list with every non-generic family name quoted. */\nexport function quoteFontFamilies(fontFamily: string): string {\n return fontFamily\n .split(\",\")\n .map((f) => quoteFontFamily(f.trim()))\n .join(\", \");\n}\n\n/**\n * Set font properties on a canvas context.\n */\nexport function setFont(\n ctx: SKRSContext2D,\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string = 400,\n fontStyle: string = \"normal\",\n): void {\n ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${quoteFontFamilies(fontFamily)}`;\n}\n\n/**\n * Measure how many pixels to trim from the top (overTrim) and bottom\n * (underTrim) of a line box based on `text-box-edge` keywords.\n *\n * The trim amount is the difference between the full line-height half-leading\n * and the target metric for each edge.\n *\n * @param fontAscent - The font's hhea ascent in px\n * @param fontDescent - The font's hhea descent in px\n */\nexport function measureTrimMetrics(\n fontSize: number,\n fontFamily: string,\n fontWeight: number | string,\n fontStyle: string,\n lineHeight: number,\n edge: string,\n fontAscent: number,\n fontDescent: number,\n): { overTrim: number; underTrim: number } {\n const c = getScratchCtx();\n // Unhinted, as text is laid out and drawn.\n const measure = (text: string) => {\n setFont(c, fontSize, fontFamily, fontWeight, fontStyle);\n const previous = c.textRendering;\n c.textRendering = \"geometricPrecision\";\n try {\n return c.measureText(text);\n } finally {\n c.textRendering = previous;\n }\n };\n\n // Parse edge into over-edge and under-edge keywords\n const parts = edge.trim().split(/\\s+/);\n const overEdge = parts[0] ?? \"text\";\n const underEdge = parts.length > 1 ? parts[1]! : overEdge;\n\n // Resolve over-edge keyword → target ascent\n let targetAscent: number;\n switch (overEdge) {\n case \"cap\": {\n const capMetrics = measure(\"H\");\n targetAscent = capMetrics.actualBoundingBoxAscent ?? fontSize * 0.7;\n break;\n }\n case \"ex\": {\n const exMetrics = measure(\"x\");\n targetAscent = exMetrics.actualBoundingBoxAscent ?? fontSize * 0.5;\n break;\n }\n case \"ideographic\":\n case \"ideographic-ink\":\n case \"text\":\n default:\n targetAscent = fontAscent;\n break;\n }\n\n // Resolve under-edge keyword → target descent\n let targetDescent: number;\n switch (underEdge) {\n case \"alphabetic\":\n targetDescent = 0;\n break;\n case \"ideographic\":\n case \"ideographic-ink\":\n case \"text\":\n default:\n targetDescent = fontDescent;\n break;\n }\n\n const halfLeading = (lineHeight - (fontAscent + fontDescent)) / 2;\n const overTrim = halfLeading + (fontAscent - targetAscent);\n const underTrim = halfLeading + (fontDescent - targetDescent);\n\n return {\n overTrim: Math.max(0, overTrim),\n underTrim: Math.max(0, underTrim),\n };\n}\n","// White space processing, CSS Text 3 §4.1: the collapsing of phase I and the\n// removal of collapsible spaces at the start and end of a line of phase II,\n// for the `white-space` values that collapse spaces. Canvas lays out each run\n// of text between elements as a flex item of its own, as a flex container\n// has it, so the text of one text node is all there is to collapse across.\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\n\ntype WhiteSpace = NonNullable<ComputedStyle[\"whiteSpace\"]>;\n\n/**\n * Whether `text` is nothing but white space: spaces, tabs, segment breaks,\n * form feeds and vertical tabs, the ASCII white space Chrome checks for. CSS\n * doesn't render a run of text in a flex container that is, under any\n * `white-space` (CSS Flexbox §4), as Chrome confirms.\n */\nexport function isWhiteSpaceOnly(text: string): boolean {\n return /^[ \\t\\n\\r\\f\\v]*$/.test(text);\n}\n\n/**\n * Process the white space of a text box's text as CSS does, before it's\n * transformed and laid out (CSS Text 3 §1.3). Under `normal`, `nowrap` and\n * `pre-line`:\n *\n * - a CRLF is one segment break, and a lone CR a space, as Chrome has them;\n * - tabs are spaces;\n * - the spaces around a segment break are removed;\n * - under `normal` and `nowrap`, a run of segment breaks is one space, where\n * `pre-line` keeps each one as a forced break;\n * - a run of spaces is one space;\n * - the spaces at the start and end of the text, which start and end a line,\n * are removed.\n *\n * The paragraph hangs the space at a line's soft wrap, as CSS does, so the\n * spaces at the start and end of the other lines take care of themselves.\n * Only ASCII white space collapses: a no-break space, say, is kept.\n *\n * `pre` and `pre-wrap` keep the spaces and tabs. They drop a lone CR, which\n * Chrome lays out with no width and no break opportunity, where the paragraph\n * would draw a missing glyph for it. Under every value, a CRLF is one segment\n * break, as in Chrome (the paragraph would keep the CR in the line too, and\n * draw it before an ellipsis), and:\n *\n * - A segment break at the very end of the text ends the last line, rather\n * than starting an empty one, as in Chrome. This relies on the paragraph\n * (`@effing/skia`'s `Paragraph`) starting an empty line after a hard break\n * that ends its text: only one final break is removed, so that \"a\\n\\n\"\n * keeps the one that gives it its second, empty line, as in Chrome.\n * - The paragraph breaks the line at a line or paragraph separator (U+2028,\n * U+2029), a form feed or a vertical tab, where Chrome doesn't. Chrome sets\n * a separator as a space that neither collapses nor hangs, with a break\n * opportunity after it: a no-break space and a zero-width space are that\n * to the paragraph. A form feed or a vertical tab is removed. Chrome draws\n * a form feed as nothing under `pre` and `pre-wrap`; otherwise, and for a\n * vertical tab under any value, it draws a fallback font's glyph for the\n * control character, which this leaves out.\n */\nexport function collapseWhiteSpace(\n text: string,\n whiteSpace: WhiteSpace | undefined,\n): string {\n let result = text.replace(/[\\v\\f]/g, \"\").replace(/\\r\\n/g, \"\\n\");\n if (whiteSpace === \"pre\" || whiteSpace === \"pre-wrap\") {\n result = result.replace(/\\r/g, \"\");\n } else if (/[\\t\\n\\r]| {2}|^ | $/.test(result)) {\n // Most text has nothing to collapse: no tab, newline, CR, or space that\n // could be leading, trailing or doubled.\n result = result.replace(/[\\t\\r]/g, \" \").replace(/ *\\n */g, \"\\n\");\n if (whiteSpace !== \"pre-line\") result = result.replace(/\\n+/g, \" \");\n result = result.replace(/ {2,}/g, \" \").replace(/^ | $/g, \"\");\n }\n return result.replace(FINAL_BREAK, \"\").replace(SEPARATORS, SEPARATOR_SPACE);\n}\n\nconst FINAL_BREAK = /\\n$/;\n\nconst SEPARATORS = /[\\u2028\\u2029]/g;\n\n/**\n * A space that neither collapses nor hangs (a no-break space), followed by a\n * break opportunity (a zero-width space).\n */\nconst SEPARATOR_SPACE = \"\\u00a0\\u200b\";\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { resolveUnit } from \"../style/compute.ts\";\nimport { layoutTextNative } from \"./native.ts\";\nimport type { NativeParagraph } from \"./native.ts\";\nimport { collapseWhiteSpace } from \"./white-space.ts\";\n\nexport type TextSegment = {\n text: string;\n x: number;\n y: number;\n width: number;\n height: number;\n fontSize: number;\n fontFamily: string;\n fontWeight: number | string;\n fontStyle: string;\n color: string;\n ascent: number;\n textDecoration?: string;\n letterSpacing: number;\n lineIndex: number;\n textStrokeWidth?: number;\n textStrokeColor?: string;\n};\n\nexport type TextLayoutResult = {\n segments: TextSegment[];\n width: number;\n height: number;\n /**\n * The paragraph to paint. The segments describe its lines, for\n * decorations.\n */\n paragraph: NativeParagraph;\n /** Vertical offset to paint `paragraph` at, relative to the text box. */\n paragraphOffsetY: number;\n /** Emoji to draw as images, in the inline boxes the paragraph left them. */\n emoji: PlacedEmoji[];\n};\n\n/** An emoji drawn as an image, at its inline box in the text box. */\nexport type PlacedEmoji = {\n /** The emoji's grapheme cluster. */\n grapheme: string;\n /** Top-left corner of its box. */\n x: number;\n y: number;\n /** The image's width and height. */\n size: number;\n /** Baseline of its line, to draw the emoji as text when there's no image. */\n baseline: number;\n};\n\n/**\n * Lay out text content into positioned lines, as one native paragraph that\n * Skia breaks, shapes and paints (see `./native.ts`). White space collapses\n * as `white-space` has it, before `text-transform` applies, as in CSS.\n *\n * @param text - The text to lay out\n * @param style - Computed style\n * @param maxWidth - Maximum width for wrapping\n * @param emojiEnabled - Whether emoji are drawn as images\n * @returns Text segments with positions and total dimensions, and the\n * paragraph to paint\n */\nexport function layoutText(\n text: string,\n style: ComputedStyle,\n maxWidth: number,\n emojiEnabled?: boolean,\n): TextLayoutResult {\n const fontSize = style.fontSize ?? 16;\n const result = layoutTextNative(\n applyTextTransform(collapseWhiteSpace(text, style.whiteSpace), style),\n style,\n maxWidth,\n resolveLineHeight(style.lineHeight, fontSize),\n emojiEnabled,\n );\n const textStrokeWidth = resolveTextStrokeWidth(style, fontSize);\n for (const seg of result.segments) {\n seg.textStrokeWidth = textStrokeWidth;\n seg.textStrokeColor = style.WebkitTextStrokeColor;\n }\n return result;\n}\n\nfunction resolveTextStrokeWidth(\n style: ComputedStyle,\n fontSize: number,\n): number | undefined {\n const raw = style.WebkitTextStrokeWidth;\n if (raw === undefined) return undefined;\n if (typeof raw === \"number\") return raw;\n const resolved = resolveUnit(String(raw), 0, 0, fontSize, 16);\n return typeof resolved === \"number\" ? resolved : undefined;\n}\n\nfunction applyTextTransform(text: string, style: ComputedStyle): string {\n if (style.textTransform === \"uppercase\") return text.toUpperCase();\n if (style.textTransform === \"lowercase\") return text.toLowerCase();\n if (style.textTransform === \"capitalize\") {\n return text.replace(/\\b\\w/g, (c) => c.toUpperCase());\n }\n return text;\n}\n\n/**\n * The line box height in px, or undefined for `normal`, which the paragraph\n * takes from the font. A height of 0 collapses the line boxes, as in CSS.\n */\nfunction resolveLineHeight(\n lineHeight: number | string | undefined,\n fontSize: number,\n): number | undefined {\n if (lineHeight === undefined || lineHeight === \"normal\") return undefined;\n let px: number;\n if (typeof lineHeight === \"number\") {\n // Already resolved to px in compute.ts if > 5, else multiplier\n px = lineHeight > 5 ? lineHeight : lineHeight * fontSize;\n } else {\n px = parseFloat(lineHeight);\n }\n // A negative line height is invalid in CSS, as is anything unparsable:\n // `normal` it is.\n return Number.isFinite(px) && px >= 0 ? px : undefined;\n}\n\n/**\n * Sizes a text node for Yoga, and lays its text out for drawing at the width\n * Yoga finally gives it.\n *\n * Yoga measures a node at whatever widths its algorithm needs, and may size\n * the node (or its ancestors) from a measurement at a width other than the\n * final one — a flex basis at the available width, say, before the node\n * shrinks. Laid out again at the final width, the text can then take more or\n * fewer lines than the box was sized for. `settle` catches that: it lays the\n * text out at the final width and, when Yoga saw a different height, pins\n * every later measurement to the height drawn, for the caller to compute the\n * layout again. The widths Yoga is given, which decide the line breaks, are\n * unchanged by the pin, so the next layout normally keeps the node's width.\n */\nexport class TextMeasure {\n /** Yoga's measurements by width (Infinity for unbounded). */\n private readonly sizes = new Map<number, { width: number; height: number }>();\n /** The heights reported to Yoga since the last `settle`. */\n private readonly reported = new Set<number>();\n private pinnedHeight: number | undefined;\n private settled: { width: number; result: TextLayoutResult } | undefined;\n private readonly measureStyle: ComputedStyle;\n\n constructor(\n private readonly text: string,\n private readonly style: ComputedStyle,\n private readonly emojiEnabled?: boolean,\n ) {\n // Strip textOverflow during measurement so ellipsis truncation doesn't\n // shrink the reported width below the Yoga constraint. The draw phase\n // still uses the original style (with textOverflow) for rendering.\n this.measureStyle = { ...style, textOverflow: \"clip\" };\n }\n\n /**\n * Measure the text for Yoga.\n *\n * @param maxWidth - The width available, Infinity for unbounded\n */\n measure(maxWidth: number): { width: number; height: number } {\n let size = this.sizes.get(maxWidth);\n if (!size) {\n const result = layoutText(\n this.text,\n this.measureStyle,\n maxWidth,\n this.emojiEnabled,\n );\n // When text wraps to multiple lines, report the constraint width (like\n // CSS block layout), so that the node is drawn at the width its lines\n // were broken at.\n const wrapped = result.segments.length > 1 && maxWidth < Infinity;\n size = {\n width: wrapped ? maxWidth : Math.min(result.width, maxWidth),\n height: result.height,\n };\n this.sizes.set(maxWidth, size);\n }\n const height = this.pinnedHeight ?? size.height;\n this.reported.add(height);\n return { width: size.width, height };\n }\n\n /**\n * Lay the text out for drawing at the node's final content width, and\n * check it against the heights Yoga was given since the last call.\n *\n * @param pin - Whether to pin later measurements to the drawn height when\n * they disagree\n * @returns Whether Yoga sized the node from another height. If `pin`, the\n * node's measurements are now pinned to the drawn height, and the caller\n * should mark the node dirty and compute the layout again.\n */\n settle(width: number, pin: boolean): boolean {\n if (this.settled?.width !== width) {\n this.settled = {\n width,\n result: layoutText(this.text, this.style, width, this.emojiEnabled),\n };\n }\n const { height } = this.settled.result;\n const agrees =\n this.reported.size === 0 ||\n (this.reported.size === 1 && this.reported.has(height));\n this.reported.clear();\n if (agrees) return false;\n if (pin) this.pinnedHeight = height;\n return true;\n }\n\n /**\n * Drop the pinned height, so that Yoga sees the measured heights again.\n *\n * @returns Whether there was a pin\n */\n unpin(): boolean {\n const pinned = this.pinnedHeight !== undefined;\n this.pinnedHeight = undefined;\n this.reported.clear();\n return pinned;\n }\n\n /** The text as laid out by the last `settle`. */\n get layout(): TextLayoutResult | undefined {\n return this.settled?.result;\n }\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\n\n/**\n * Apply overflow:hidden clipping to a canvas context.\n * Creates a rectangular clip path with optional border-radius.\n */\nexport function applyClip(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n borderRadius?: {\n topLeft: number;\n topRight: number;\n bottomRight: number;\n bottomLeft: number;\n },\n): void {\n ctx.beginPath();\n\n if (borderRadius && hasRadius(borderRadius)) {\n const { topLeft, topRight, bottomRight, bottomLeft } = borderRadius;\n roundedRect(\n ctx,\n x,\n y,\n width,\n height,\n topLeft,\n topRight,\n bottomRight,\n bottomLeft,\n );\n } else {\n ctx.rect(x, y, width, height);\n }\n\n ctx.clip();\n}\n\n/**\n * Draw a rounded rectangle path on the context.\n */\nexport function roundedRect(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n w: number,\n h: number,\n tl: number,\n tr: number,\n br: number,\n bl: number,\n): void {\n const maxR = maxCornerRadius(w, h);\n tl = Math.min(tl, maxR);\n tr = Math.min(tr, maxR);\n br = Math.min(br, maxR);\n bl = Math.min(bl, maxR);\n\n ctx.moveTo(x + tl, y);\n ctx.lineTo(x + w - tr, y);\n if (tr > 0) ctx.arcTo(x + w, y, x + w, y + tr, tr);\n ctx.lineTo(x + w, y + h - br);\n if (br > 0) ctx.arcTo(x + w, y + h, x + w - br, y + h, br);\n ctx.lineTo(x + bl, y + h);\n if (bl > 0) ctx.arcTo(x, y + h, x, y + h - bl, bl);\n ctx.lineTo(x, y + tl);\n if (tl > 0) ctx.arcTo(x, y, x + tl, y, tl);\n ctx.closePath();\n}\n\n/**\n * The largest corner radius a `w` × `h` box is drawn with: every radius is\n * clamped to half the shorter side. Anything that needs to line up with the\n * element's painted corners (`clip-path` geometry boxes, overflow clips) must\n * apply the same clamp.\n */\nexport function maxCornerRadius(w: number, h: number): number {\n return Math.min(w, h) / 2;\n}\n\nexport function hasRadius(r: {\n topLeft: number;\n topRight: number;\n bottomRight: number;\n bottomLeft: number;\n}): boolean {\n return (\n r.topLeft > 0 || r.topRight > 0 || r.bottomRight > 0 || r.bottomLeft > 0\n );\n}\n","import { Path2D } from \"@effing/skia\";\nimport type { SKRSContext2D } from \"@effing/skia\";\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { maxCornerRadius } from \"./clip.ts\";\nimport { getBorderRadiusFromStyle } from \"./rect.ts\";\nimport { parseCSSLength, resolveBoxValue } from \"./utils.ts\";\n\n/**\n * CSS `clip-path` support: basic shapes (`inset()`, `circle()`, `ellipse()`,\n * `polygon()`, `path()`, `rect()`, `xywh()`), the newer `shape()` function and\n * an optional geometry box (`border-box`, `padding-box`, `content-box`,\n * `margin-box`). Lengths other than `%` are already resolved to pixels by the\n * style pipeline; percentages resolve against the reference box here.\n *\n * `url(#id)` references and `calc()` are not supported — an unrecognised value\n * leaves the element unclipped, matching how a browser drops an invalid\n * declaration.\n */\n\nexport type FillRule = \"nonzero\" | \"evenodd\";\n\ntype Point = [number, number];\n\n/** Per-corner elliptical radii, in the order tl, tr, br, bl. */\nexport type CornerRadii = [Point, Point, Point, Point];\n\nexport type ReferenceBox = {\n x: number;\n y: number;\n width: number;\n height: number;\n};\n\n/**\n * A resolved clip shape in absolute canvas coordinates.\n */\nexport type ClipShape =\n | { kind: \"none\" }\n | {\n kind: \"rect\";\n x: number;\n y: number;\n width: number;\n height: number;\n radii: CornerRadii | null;\n }\n | { kind: \"circle\"; cx: number; cy: number; r: number }\n | { kind: \"ellipse\"; cx: number; cy: number; rx: number; ry: number }\n | { kind: \"polygon\"; points: Point[]; fillRule: FillRule }\n | { kind: \"path\"; d: string; dx: number; dy: number; fillRule: FillRule };\n\nconst GEOMETRY_BOXES = new Set([\n \"border-box\",\n \"padding-box\",\n \"content-box\",\n \"margin-box\",\n \"fill-box\",\n \"stroke-box\",\n \"view-box\",\n]);\n\nconst H_KEYWORDS = new Map<string, number>([\n [\"left\", 0],\n [\"x-start\", 0],\n [\"center\", 0.5],\n [\"right\", 1],\n [\"x-end\", 1],\n]);\n\nconst V_KEYWORDS = new Map<string, number>([\n [\"top\", 0],\n [\"y-start\", 0],\n [\"center\", 0.5],\n [\"bottom\", 1],\n [\"y-end\", 1],\n]);\n\nconst ARC_OPTIONS = new Set([\"of\", \"cw\", \"ccw\", \"large\", \"small\", \"rotate\"]);\n\n/**\n * Clip the context to the element's `clip-path`. Must be called after the\n * element's transform has been applied (clip-path lives in the element's own\n * coordinate space) and before anything of the element is painted — box-shadow\n * included, since clip-path clips the element's entire rendering.\n */\nexport function applyClipPath(\n ctx: SKRSContext2D,\n clipPath: string,\n style: ComputedStyle,\n x: number,\n y: number,\n width: number,\n height: number,\n): void {\n const shape = parseClipPath(clipPath, style, { x, y, width, height });\n if (!shape || shape.kind === \"none\") return;\n const path = clipShapeToPath(shape);\n if (path) ctx.clip(path, shapeFillRule(shape));\n}\n\nfunction shapeFillRule(shape: ClipShape): FillRule {\n return shape.kind === \"polygon\" || shape.kind === \"path\"\n ? shape.fillRule\n : \"nonzero\";\n}\n\n/**\n * Parse a `clip-path` value into a resolved shape in absolute coordinates.\n * `box` is the element's border box; `style` supplies the border, padding and\n * margin widths used for the other geometry boxes. Returns `null` for values\n * that can't be parsed.\n */\nexport function parseClipPath(\n value: string,\n style: ComputedStyle,\n box: ReferenceBox,\n): ClipShape | null {\n const trimmed = value.trim();\n if (trimmed === \"none\") return { kind: \"none\" };\n\n // Split into an optional shape function and an optional geometry box, in\n // either order: `circle(50%) padding-box` or `padding-box circle(50%)`.\n let fn: { name: string; args: string } | null = null;\n let geometryBox = \"border-box\";\n const fnMatch = trimmed.match(/^(.*?)([a-z]+)\\((.*)\\)(.*)$/s);\n let keywords: string[];\n if (fnMatch) {\n fn = { name: fnMatch[2]!, args: fnMatch[3]! };\n keywords = [fnMatch[1]!, fnMatch[4]!]\n .join(\" \")\n .split(/\\s+/)\n .filter(Boolean);\n } else {\n keywords = trimmed.split(/\\s+/).filter(Boolean);\n }\n for (const kw of keywords) {\n if (!GEOMETRY_BOXES.has(kw)) return null;\n geometryBox = kw;\n }\n if (!fn && keywords.length === 0) return null;\n\n const ref = resolveReferenceBox(geometryBox, style, box);\n const { width: w, height: h } = ref;\n\n if (!fn) {\n // A bare geometry box clips to that box, following the border radius\n // (reduced by the border/padding widths for the inner boxes).\n return {\n kind: \"rect\",\n x: ref.x,\n y: ref.y,\n width: w,\n height: h,\n radii: referenceBoxRadii(geometryBox, style, box, ref),\n };\n }\n\n switch (fn.name) {\n case \"inset\":\n return parseInset(fn.args, ref);\n case \"rect\":\n return parseRect(fn.args, ref);\n case \"xywh\":\n return parseXywh(fn.args, ref);\n case \"circle\":\n return parseCircle(fn.args, ref);\n case \"ellipse\":\n return parseEllipse(fn.args, ref);\n case \"polygon\":\n return parsePolygon(fn.args, ref);\n case \"path\":\n return parsePath(fn.args, ref);\n case \"shape\":\n return parseShape(fn.args, ref);\n default:\n return null;\n }\n}\n\n/**\n * Build a `Path2D` for a resolved clip shape. Returns `null` when the shape\n * is a `path()` whose data Skia cannot parse — treated like an invalid\n * declaration (the element is left unclipped) rather than a render failure.\n */\nexport function clipShapeToPath(shape: ClipShape): Path2D | null {\n const p = new Path2D();\n switch (shape.kind) {\n case \"none\":\n break;\n case \"rect\":\n if (shape.radii && shape.width > 0 && shape.height > 0) {\n roundedRectPath(\n p,\n shape.x,\n shape.y,\n shape.width,\n shape.height,\n shape.radii,\n );\n } else {\n p.rect(\n shape.x,\n shape.y,\n Math.max(0, shape.width),\n Math.max(0, shape.height),\n );\n }\n break;\n case \"circle\":\n if (shape.r > 0) p.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2);\n break;\n case \"ellipse\":\n if (shape.rx > 0 && shape.ry > 0) {\n p.ellipse(shape.cx, shape.cy, shape.rx, shape.ry, 0, 0, Math.PI * 2);\n }\n break;\n case \"polygon\":\n if (shape.points.length >= 3) {\n const [first, ...rest] = shape.points;\n p.moveTo(first![0], first![1]);\n for (const [px, py] of rest) p.lineTo(px, py);\n p.closePath();\n }\n break;\n case \"path\": {\n let inner: Path2D;\n try {\n inner = new Path2D(shape.d);\n } catch {\n return null;\n }\n if (shape.dx === 0 && shape.dy === 0) return inner;\n p.addPath(inner, { a: 1, b: 0, c: 0, d: 1, e: shape.dx, f: shape.dy });\n break;\n }\n }\n return p;\n}\n\n// ---------------------------------------------------------------------------\n// Reference boxes\n// ---------------------------------------------------------------------------\n\nfunction resolveReferenceBox(\n geometryBox: string,\n style: ComputedStyle,\n box: ReferenceBox,\n): ReferenceBox {\n const { x, y, width, height } = box;\n switch (geometryBox) {\n case \"padding-box\": {\n const t = resolveBoxValue(style.borderTopWidth, width);\n const r = resolveBoxValue(style.borderRightWidth, width);\n const b = resolveBoxValue(style.borderBottomWidth, width);\n const l = resolveBoxValue(style.borderLeftWidth, width);\n return {\n x: x + l,\n y: y + t,\n width: width - l - r,\n height: height - t - b,\n };\n }\n case \"content-box\": {\n const t =\n resolveBoxValue(style.borderTopWidth, width) +\n resolveBoxValue(style.paddingTop, width);\n const r =\n resolveBoxValue(style.borderRightWidth, width) +\n resolveBoxValue(style.paddingRight, width);\n const b =\n resolveBoxValue(style.borderBottomWidth, width) +\n resolveBoxValue(style.paddingBottom, width);\n const l =\n resolveBoxValue(style.borderLeftWidth, width) +\n resolveBoxValue(style.paddingLeft, width);\n return {\n x: x + l,\n y: y + t,\n width: width - l - r,\n height: height - t - b,\n };\n }\n case \"margin-box\": {\n const t = marginValue(style.marginTop, width);\n const r = marginValue(style.marginRight, width);\n const b = marginValue(style.marginBottom, width);\n const l = marginValue(style.marginLeft, width);\n return {\n x: x - l,\n y: y - t,\n width: width + l + r,\n height: height + t + b,\n };\n }\n default:\n return box;\n }\n}\n\nfunction marginValue(v: unknown, referenceWidth: number): number {\n if (v === \"auto\") return 0;\n return resolveBoxValue(v, referenceWidth);\n}\n\n/**\n * Border radii of a geometry box: the element's border-radius for the border\n * box (and margin box, grown by the margin), reduced by the border and padding\n * widths for the inner boxes. Returns `null` when every corner is square.\n *\n * The base radii are clamped the way the element's own corners are painted\n * (see `maxCornerRadius`) so a bare `border-box` clip traces exactly the\n * painted rounded corner instead of a different arc.\n */\nfunction referenceBoxRadii(\n geometryBox: string,\n style: ComputedStyle,\n box: ReferenceBox,\n ref: ReferenceBox,\n): CornerRadii | null {\n const br = getBorderRadiusFromStyle(style, box.width, box.height);\n const maxR = maxCornerRadius(box.width, box.height);\n const base = [br.topLeft, br.topRight, br.bottomRight, br.bottomLeft].map(\n (r) => Math.min(Math.max(0, r), maxR),\n ) as [number, number, number, number];\n if (base.every((r) => r <= 0)) return null;\n\n // Horizontal / vertical insets from the border box to the reference box, per\n // corner: (left, top), (right, top), (right, bottom), (left, bottom).\n const left = ref.x - box.x;\n const top = ref.y - box.y;\n const right = box.x + box.width - (ref.x + ref.width);\n const bottom = box.y + box.height - (ref.y + ref.height);\n const insets: [Point, Point, Point, Point] = [\n [left, top],\n [right, top],\n [right, bottom],\n [left, bottom],\n ];\n\n const radii = base.map((r, i) => {\n const [ix, iy] = insets[i]!;\n return [adjustRadius(r, ix), adjustRadius(r, iy)] as Point;\n }) as CornerRadii;\n if (radii.every(([rx, ry]) => rx <= 0 || ry <= 0)) return null;\n return normalizeRadii(radii, ref.width, ref.height);\n}\n\n/**\n * Move a border radius inward by `inset` (CSS Backgrounds: the inner radius\n * is the outer one minus the border, floored at zero) or, for a negative\n * inset, outward (CSS Shapes `margin-box`: a square corner stays square, a\n * radius `r >= m` grows to `r + m`, and a smaller one is eased between the\n * two so the corner keeps its shape).\n */\nfunction adjustRadius(r: number, inset: number): number {\n if (inset >= 0) return Math.max(0, r - inset);\n if (r <= 0) return 0;\n const m = -inset;\n if (r >= m) return r + m;\n const ratio = r / m - 1;\n return r + m * (1 + ratio * ratio * ratio);\n}\n\n// ---------------------------------------------------------------------------\n// Basic shapes\n// ---------------------------------------------------------------------------\n\nfunction parseInset(args: string, ref: ReferenceBox): ClipShape | null {\n const [insetPart, roundPart] = splitRound(args);\n const values = tokenize(insetPart);\n if (values.length < 1 || values.length > 4) return null;\n const [t, r, b, l] = expandSides(values);\n const top = parseCSSLength(t, ref.height);\n const right = parseCSSLength(r, ref.width);\n const bottom = parseCSSLength(b, ref.height);\n const left = parseCSSLength(l, ref.width);\n if ([top, right, bottom, left].some(isNaN)) return null;\n return makeRect(\n ref.x + left,\n ref.y + top,\n ref.width - left - right,\n ref.height - top - bottom,\n roundPart,\n ref,\n );\n}\n\nfunction parseRect(args: string, ref: ReferenceBox): ClipShape | null {\n const [rectPart, roundPart] = splitRound(args);\n const values = tokenize(rectPart);\n if (values.length !== 4) return null;\n const [t, r, b, l] = values as [string, string, string, string];\n const top = t === \"auto\" ? 0 : parseCSSLength(t, ref.height);\n const right = r === \"auto\" ? ref.width : parseCSSLength(r, ref.width);\n const bottom = b === \"auto\" ? ref.height : parseCSSLength(b, ref.height);\n const left = l === \"auto\" ? 0 : parseCSSLength(l, ref.width);\n if ([top, right, bottom, left].some(isNaN)) return null;\n // Per spec, right/bottom are clamped so they never precede left/top.\n const x2 = Math.max(left, right);\n const y2 = Math.max(top, bottom);\n return makeRect(\n ref.x + left,\n ref.y + top,\n x2 - left,\n y2 - top,\n roundPart,\n ref,\n );\n}\n\nfunction parseXywh(args: string, ref: ReferenceBox): ClipShape | null {\n const [xywhPart, roundPart] = splitRound(args);\n const values = tokenize(xywhPart);\n if (values.length !== 4) return null;\n const [xs, ys, ws, hs] = values as [string, string, string, string];\n const x = parseCSSLength(xs, ref.width);\n const y = parseCSSLength(ys, ref.height);\n const w = parseCSSLength(ws, ref.width);\n const h = parseCSSLength(hs, ref.height);\n if ([x, y, w, h].some(isNaN)) return null;\n return makeRect(\n ref.x + x,\n ref.y + y,\n Math.max(0, w),\n Math.max(0, h),\n roundPart,\n ref,\n );\n}\n\n/**\n * Build a rect shape with optional `round` radii. Percentage radii resolve\n * against the reference box (CSS Shapes 1 §3), not the rectangle itself.\n */\nfunction makeRect(\n x: number,\n y: number,\n width: number,\n height: number,\n roundPart: string | undefined,\n ref: ReferenceBox,\n): ClipShape | null {\n const w = Math.max(0, width);\n const h = Math.max(0, height);\n let radii: CornerRadii | null = null;\n if (roundPart !== undefined) {\n const parsed = parseRadii(roundPart, ref.width, ref.height, w, h);\n if (parsed === undefined) return null;\n radii = parsed;\n }\n return { kind: \"rect\", x, y, width: w, height: h, radii };\n}\n\nfunction parseCircle(args: string, ref: ReferenceBox): ClipShape | null {\n const [radiusPart, posPart] = splitAt(args);\n const radiusTokens = tokenize(radiusPart);\n if (radiusTokens.length > 1) return null;\n const pos = resolvePosition(tokenize(posPart ?? \"\"), ref.width, ref.height);\n if (!pos) return null;\n const [cx, cy] = pos;\n const closest = Math.min(cx, cy, ref.width - cx, ref.height - cy);\n const farthest = Math.max(cx, cy, ref.width - cx, ref.height - cy);\n const percentBase = Math.hypot(ref.width, ref.height) / Math.SQRT2;\n const r = resolveRadius(radiusTokens[0], closest, farthest, percentBase);\n if (r === undefined) return null;\n return { kind: \"circle\", cx: ref.x + cx, cy: ref.y + cy, r: Math.max(0, r) };\n}\n\nfunction parseEllipse(args: string, ref: ReferenceBox): ClipShape | null {\n const [radiusPart, posPart] = splitAt(args);\n const radiusTokens = tokenize(radiusPart);\n if (radiusTokens.length !== 0 && radiusTokens.length !== 2) return null;\n const pos = resolvePosition(tokenize(posPart ?? \"\"), ref.width, ref.height);\n if (!pos) return null;\n const [cx, cy] = pos;\n const rx = resolveRadius(\n radiusTokens[0],\n Math.min(cx, ref.width - cx),\n Math.max(cx, ref.width - cx),\n ref.width,\n );\n const ry = resolveRadius(\n radiusTokens[1],\n Math.min(cy, ref.height - cy),\n Math.max(cy, ref.height - cy),\n ref.height,\n );\n if (rx === undefined || ry === undefined) return null;\n return {\n kind: \"ellipse\",\n cx: ref.x + cx,\n cy: ref.y + cy,\n rx: Math.max(0, rx),\n ry: Math.max(0, ry),\n };\n}\n\nfunction parsePolygon(args: string, ref: ReferenceBox): ClipShape | null {\n const parts = splitArgs(args);\n let fillRule: FillRule = \"nonzero\";\n const first = parts[0]?.trim();\n if (first === \"nonzero\" || first === \"evenodd\") {\n fillRule = first;\n parts.shift();\n }\n const points: Point[] = [];\n for (const part of parts) {\n const pair = tokenize(part);\n if (pair.length !== 2) return null;\n const px = parseCSSLength(pair[0]!, ref.width);\n const py = parseCSSLength(pair[1]!, ref.height);\n if (isNaN(px) || isNaN(py)) return null;\n points.push([ref.x + px, ref.y + py]);\n }\n if (points.length === 0) return null;\n return { kind: \"polygon\", points, fillRule };\n}\n\nfunction parsePath(args: string, ref: ReferenceBox): ClipShape | null {\n const parts = splitArgs(args);\n let fillRule: FillRule = \"nonzero\";\n const first = parts[0]?.trim();\n if (first === \"nonzero\" || first === \"evenodd\") {\n fillRule = first;\n parts.shift();\n }\n if (parts.length !== 1) return null;\n const d = unquote(parts[0]!.trim());\n if (!d) return null;\n return { kind: \"path\", d, dx: ref.x, dy: ref.y, fillRule };\n}\n\n// ---------------------------------------------------------------------------\n// shape()\n// ---------------------------------------------------------------------------\n\n/**\n * Parse the `shape()` function into SVG path data. Coordinates are resolved\n * against the reference box; the resulting path is positioned at the box\n * origin via `dx`/`dy`.\n *\n * Grammar (CSS Shapes 2): `shape([<fill-rule>]? from <x> <y>, <command>#)`\n * with commands `move`, `line`, `hline`, `vline`, `curve`, `smooth`, `arc`\n * and `close`, each using `to` (absolute) or `by` (relative to the current\n * point).\n */\nfunction parseShape(args: string, ref: ReferenceBox): ClipShape | null {\n const { width: w, height: h } = ref;\n const parts = splitArgs(args);\n const first = parts.shift()?.trim();\n if (!first) return null;\n\n const startMatch = first.match(/^(?:(nonzero|evenodd)\\s+)?from\\s+(.+)$/s);\n if (!startMatch) return null;\n const fillRule = (startMatch[1] ?? \"nonzero\") as FillRule;\n\n let current = resolvePoint(tokenize(startMatch[2]!), w, h);\n if (!current) return null;\n let subpathStart = current;\n let d = `M${fmtPoint(current)}`;\n\n for (const part of parts) {\n const tokens = tokenize(part);\n const command = tokens.shift();\n\n switch (command) {\n case \"close\": {\n if (tokens.length) return null;\n d += \" Z\";\n current = subpathStart;\n break;\n }\n case \"move\":\n case \"line\": {\n const end = resolveEndpoint(tokens, current, w, h);\n if (!end) return null;\n d += ` ${command === \"move\" ? \"M\" : \"L\"}${fmtPoint(end)}`;\n current = end;\n if (command === \"move\") subpathStart = end;\n break;\n }\n case \"hline\":\n case \"vline\": {\n const [mode, token, ...rest] = tokens;\n if ((mode !== \"to\" && mode !== \"by\") || !token || rest.length) {\n return null;\n }\n const axis = command === \"hline\" ? 0 : 1;\n const base = axis === 0 ? w : h;\n const keywords = axis === 0 ? H_KEYWORDS : V_KEYWORDS;\n const kw = keywords.get(token);\n const resolved =\n mode === \"to\" && kw !== undefined\n ? kw * base\n : parseCSSLength(token, base);\n if (isNaN(resolved)) return null;\n const next: Point = [current[0], current[1]];\n next[axis] = mode === \"by\" ? current[axis] + resolved : resolved;\n d += axis === 0 ? ` H${fmt(next[0])}` : ` V${fmt(next[1])}`;\n current = next;\n break;\n }\n case \"curve\":\n case \"smooth\": {\n const withIndex = tokens.indexOf(\"with\");\n const endTokens =\n withIndex === -1 ? tokens : tokens.slice(0, withIndex);\n const controlTokens =\n withIndex === -1 ? [] : tokens.slice(withIndex + 1);\n const mode = endTokens[0];\n const end = resolveEndpoint(endTokens, current, w, h);\n if (!end) return null;\n if (command === \"curve\" && withIndex === -1) return null;\n\n const controls: Point[] = [];\n for (const control of splitAtSlash(controlTokens)) {\n const point = resolveControlPoint(control, mode, current, end, w, h);\n if (!point) return null;\n controls.push(point);\n }\n\n if (command === \"curve\") {\n if (controls.length === 1) {\n d += ` Q${fmtPoint(controls[0]!)} ${fmtPoint(end)}`;\n } else if (controls.length === 2) {\n d += ` C${fmtPoint(controls[0]!)} ${fmtPoint(controls[1]!)} ${fmtPoint(end)}`;\n } else {\n return null;\n }\n } else if (controls.length === 0) {\n d += ` T${fmtPoint(end)}`;\n } else if (controls.length === 1) {\n d += ` S${fmtPoint(controls[0]!)} ${fmtPoint(end)}`;\n } else {\n return null;\n }\n current = end;\n break;\n }\n case \"arc\": {\n const optionIndex = tokens.findIndex((t) => ARC_OPTIONS.has(t));\n const endTokens =\n optionIndex === -1 ? tokens : tokens.slice(0, optionIndex);\n const options = optionIndex === -1 ? [] : tokens.slice(optionIndex);\n const end = resolveEndpoint(endTokens, current, w, h);\n if (!end) return null;\n\n let rx = 0;\n let ry = 0;\n let rotation = 0;\n let large = 0;\n let sweep = 0;\n for (let i = 0; i < options.length; i++) {\n const option = options[i]!;\n if (option === \"of\") {\n const r1 = options[++i];\n if (!r1) return null;\n const r2 = options[i + 1];\n const hasSecond = r2 !== undefined && !ARC_OPTIONS.has(r2);\n if (hasSecond) {\n i++;\n rx = parseCSSLength(r1, w);\n ry = parseCSSLength(r2!, h);\n } else {\n rx = ry = parseCSSLength(r1, Math.hypot(w, h) / Math.SQRT2);\n }\n if (isNaN(rx) || isNaN(ry)) return null;\n } else if (option === \"cw\" || option === \"ccw\") {\n sweep = option === \"cw\" ? 1 : 0;\n } else if (option === \"large\" || option === \"small\") {\n large = option === \"large\" ? 1 : 0;\n } else if (option === \"rotate\") {\n const angle = options[++i];\n if (!angle) return null;\n rotation = parseAngleDegrees(angle);\n if (isNaN(rotation)) return null;\n } else {\n return null;\n }\n }\n d += ` A${fmt(Math.abs(rx))} ${fmt(Math.abs(ry))} ${fmt(rotation)} ${large} ${sweep} ${fmtPoint(end)}`;\n current = end;\n break;\n }\n default:\n return null;\n }\n }\n\n return { kind: \"path\", d, dx: ref.x, dy: ref.y, fillRule };\n}\n\nfunction resolveEndpoint(\n tokens: string[],\n current: Point,\n w: number,\n h: number,\n): Point | null {\n const mode = tokens[0];\n if (mode !== \"to\" && mode !== \"by\") return null;\n const point = resolvePoint(tokens.slice(1), w, h);\n if (!point) return null;\n return mode === \"by\" ? [current[0] + point[0], current[1] + point[1]] : point;\n}\n\n/**\n * A control point: `<x> <y> [from start | end | origin]?`. Without `from`,\n * `by` commands measure from the segment start and `to` commands from the\n * reference box origin.\n */\nfunction resolveControlPoint(\n tokens: string[],\n mode: string | undefined,\n start: Point,\n end: Point,\n w: number,\n h: number,\n): Point | null {\n let origin: \"start\" | \"end\" | \"origin\" = mode === \"by\" ? \"start\" : \"origin\";\n let coords = tokens;\n const fromIndex = tokens.indexOf(\"from\");\n if (fromIndex !== -1) {\n const ref = tokens[fromIndex + 1];\n if (\n (ref !== \"start\" && ref !== \"end\" && ref !== \"origin\") ||\n tokens.length !== fromIndex + 2\n ) {\n return null;\n }\n origin = ref;\n coords = tokens.slice(0, fromIndex);\n }\n const point = resolvePoint(coords, w, h);\n if (!point) return null;\n const base: Point =\n origin === \"start\" ? start : origin === \"end\" ? end : [0, 0];\n return [base[0] + point[0], base[1] + point[1]];\n}\n\n/** Resolve a `<coordinate-pair>` (lengths, percentages or position keywords). */\nfunction resolvePoint(tokens: string[], w: number, h: number): Point | null {\n if (tokens.length !== 2) return null;\n const x = resolveAxis(tokens[0]!, w, H_KEYWORDS);\n const y = resolveAxis(tokens[1]!, h, V_KEYWORDS);\n if (isNaN(x) || isNaN(y)) return null;\n return [x, y];\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve a CSS `<position>` (as used after `at`) to a point relative to the\n * reference box. Defaults to the center.\n */\nfunction resolvePosition(tokens: string[], w: number, h: number): Point | null {\n if (tokens.length === 0) return [w / 2, h / 2];\n\n if (tokens.length === 1) {\n const t = tokens[0]!;\n if (V_KEYWORDS.has(t) && !H_KEYWORDS.has(t)) {\n return [w / 2, V_KEYWORDS.get(t)! * h];\n }\n const x = resolveAxis(t, w, H_KEYWORDS);\n return isNaN(x) ? null : [x, h / 2];\n }\n\n if (tokens.length === 2) {\n let [a, b] = tokens as [string, string];\n // Two keywords may come in either order (\"top left\" == \"left top\"); with\n // a length in the pair the order is fixed, so \"top 30px\" is invalid and\n // falls through to the NaN check below.\n const bothKeywords =\n (H_KEYWORDS.has(a) || V_KEYWORDS.has(a)) &&\n (H_KEYWORDS.has(b) || V_KEYWORDS.has(b));\n if (\n bothKeywords &&\n ((V_KEYWORDS.has(a) && !H_KEYWORDS.has(a)) ||\n (H_KEYWORDS.has(b) && !V_KEYWORDS.has(b)))\n ) {\n [a, b] = [b, a];\n }\n const x = resolveAxis(a, w, H_KEYWORDS);\n const y = resolveAxis(b, h, V_KEYWORDS);\n return isNaN(x) || isNaN(y) ? null : [x, y];\n }\n\n // 3–4 tokens: edge keywords with optional offsets, e.g. \"right 10px bottom 20px\".\n let x = w / 2;\n let y = h / 2;\n for (let i = 0; i < tokens.length; i++) {\n const t = tokens[i]!;\n const next = tokens[i + 1];\n const hasOffset =\n next !== undefined && !H_KEYWORDS.has(next) && !V_KEYWORDS.has(next);\n if (t === \"left\" || t === \"right\") {\n const off = hasOffset ? parseCSSLength(next!, w) : 0;\n if (isNaN(off)) return null;\n x = t === \"left\" ? off : w - off;\n } else if (t === \"top\" || t === \"bottom\") {\n const off = hasOffset ? parseCSSLength(next!, h) : 0;\n if (isNaN(off)) return null;\n y = t === \"top\" ? off : h - off;\n } else if (t !== \"center\") {\n return null;\n }\n if (hasOffset) i++;\n }\n return [x, y];\n}\n\nfunction resolveAxis(\n token: string,\n size: number,\n keywords: Map<string, number>,\n): number {\n const kw = keywords.get(token);\n if (kw !== undefined) return kw * size;\n return parseCSSLength(token, size);\n}\n\nfunction resolveRadius(\n token: string | undefined,\n closestSide: number,\n farthestSide: number,\n percentBase: number,\n): number | undefined {\n if (token === undefined || token === \"closest-side\") return closestSide;\n if (token === \"farthest-side\") return farthestSide;\n const r = parseCSSLength(token, percentBase);\n return isNaN(r) ? undefined : r;\n}\n\n/**\n * Parse `border-radius`-style radii (`r1 r2 r3 r4 / v1 v2 v3 v4`) into\n * per-corner elliptical radii. Percentages resolve against `refW` × `refH`;\n * the result is scaled down per the CSS overlap rule for a `w` × `h` box.\n * Returns `undefined` for unparsable input and `null` when all corners are\n * square.\n */\nfunction parseRadii(\n value: string,\n refW: number,\n refH: number,\n w: number,\n h: number,\n): CornerRadii | null | undefined {\n const [hPart, vPart] = value.split(\"/\");\n const hTokens = tokenize(hPart ?? \"\");\n const vTokens = vPart === undefined ? hTokens : tokenize(vPart);\n if (\n hTokens.length < 1 ||\n hTokens.length > 4 ||\n vTokens.length < 1 ||\n vTokens.length > 4\n ) {\n return undefined;\n }\n const hs = expandSides(hTokens).map((t) => parseCSSLength(t, refW));\n const vs = expandSides(vTokens).map((t) => parseCSSLength(t, refH));\n if ([...hs, ...vs].some(isNaN)) return undefined;\n const radii = hs.map((rx, i) => [\n Math.max(0, rx),\n Math.max(0, vs[i]!),\n ]) as CornerRadii;\n if (radii.every(([rx, ry]) => rx <= 0 || ry <= 0)) return null;\n return normalizeRadii(radii, w, h);\n}\n\n/**\n * CSS border-radius overlap rule: if adjacent radii along any side sum to more\n * than that side's length, scale every radius by the same factor.\n */\nfunction normalizeRadii(radii: CornerRadii, w: number, h: number): CornerRadii {\n const [tl, tr, br, bl] = radii;\n let f = 1;\n const consider = (sum: number, length: number) => {\n if (sum > 0 && length / sum < f) f = length / sum;\n };\n consider(tl[0] + tr[0], w);\n consider(bl[0] + br[0], w);\n consider(tl[1] + bl[1], h);\n consider(tr[1] + br[1], h);\n if (f >= 1) return radii;\n return radii.map(([rx, ry]) => [rx * f, ry * f]) as CornerRadii;\n}\n\n/**\n * Append a rounded rectangle with per-corner elliptical radii to a path.\n */\nfunction roundedRectPath(\n p: Path2D,\n x: number,\n y: number,\n w: number,\n h: number,\n radii: CornerRadii,\n): void {\n const [tl, tr, br, bl] = radii;\n const round = (r: Point) => r[0] > 0 && r[1] > 0;\n const HALF = Math.PI / 2;\n\n p.moveTo(x + (round(tl) ? tl[0] : 0), y);\n p.lineTo(x + w - (round(tr) ? tr[0] : 0), y);\n if (round(tr)) {\n p.ellipse(x + w - tr[0], y + tr[1], tr[0], tr[1], 0, -HALF, 0);\n }\n p.lineTo(x + w, y + h - (round(br) ? br[1] : 0));\n if (round(br)) {\n p.ellipse(x + w - br[0], y + h - br[1], br[0], br[1], 0, 0, HALF);\n }\n p.lineTo(x + (round(bl) ? bl[0] : 0), y + h);\n if (round(bl)) {\n p.ellipse(x + bl[0], y + h - bl[1], bl[0], bl[1], 0, HALF, Math.PI);\n }\n p.lineTo(x, y + (round(tl) ? tl[1] : 0));\n if (round(tl)) {\n p.ellipse(x + tl[0], y + tl[1], tl[0], tl[1], 0, Math.PI, 3 * HALF);\n }\n p.closePath();\n}\n\nfunction expandSides(values: string[]): [string, string, string, string] {\n const [a, b, c, d] = values;\n switch (values.length) {\n case 1:\n return [a!, a!, a!, a!];\n case 2:\n return [a!, b!, a!, b!];\n case 3:\n return [a!, b!, c!, b!];\n default:\n return [a!, b!, c!, d!];\n }\n}\n\n/** Split `... round <radii>` into the shape part and the optional radii part. */\nfunction splitRound(args: string): [string, string | undefined] {\n const m = args.match(/^(.*?)\\bround\\b(.*)$/s);\n if (!m) return [args, undefined];\n return [m[1]!, m[2]!];\n}\n\n/** Split `<radius> at <position>` into the radius part and the position part. */\nfunction splitAt(args: string): [string, string | undefined] {\n const m = args.match(/^(.*?)\\bat\\b(.*)$/s);\n if (!m) return [args, undefined];\n return [m[1]!, m[2]!];\n}\n\n/** Split on top-level commas, respecting parentheses and quoted strings. */\nfunction splitArgs(content: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let depth = 0;\n let quote: string | null = null;\n for (const char of content) {\n if (quote) {\n if (char === quote) quote = null;\n current += char;\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n current += char;\n continue;\n }\n if (char === \"(\") depth++;\n if (char === \")\") depth--;\n if (char === \",\" && depth === 0) {\n parts.push(current);\n current = \"\";\n } else {\n current += char;\n }\n }\n if (current.trim()) parts.push(current);\n return parts;\n}\n\nfunction splitAtSlash(tokens: string[]): string[][] {\n if (tokens.length === 0) return [];\n const slash = tokens.indexOf(\"/\");\n return slash === -1\n ? [tokens]\n : [tokens.slice(0, slash), tokens.slice(slash + 1)];\n}\n\nfunction tokenize(value: string): string[] {\n return value.trim().replace(/\\//g, \" / \").split(/\\s+/).filter(Boolean);\n}\n\nfunction unquote(s: string): string {\n if (\n s.length >= 2 &&\n ((s.startsWith('\"') && s.endsWith('\"')) ||\n (s.startsWith(\"'\") && s.endsWith(\"'\")))\n ) {\n return s.slice(1, -1);\n }\n return s;\n}\n\nfunction parseAngleDegrees(value: string): number {\n const n = parseFloat(value);\n if (isNaN(n)) return NaN;\n if (value.endsWith(\"deg\")) return n;\n if (value.endsWith(\"grad\")) return n * 0.9;\n if (value.endsWith(\"rad\")) return (n * 180) / Math.PI;\n if (value.endsWith(\"turn\")) return n * 360;\n return n;\n}\n\nfunction fmt(n: number): string {\n return String(Math.round(n * 1000) / 1000);\n}\n\nfunction fmtPoint(p: Point): string {\n return `${fmt(p[0])} ${fmt(p[1])}`;\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\n\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport { hasRadius, roundedRect } from \"./clip.ts\";\nimport { parseCSSLength, toNumber, resolveBoxValue } from \"./utils.ts\";\n\n/**\n * Draw the background, borders, and box-shadow for a rectangular element.\n */\nexport function drawRect(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n style: ComputedStyle,\n): void {\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n const hasRoundedCorners = hasRadius(borderRadius);\n\n // Background\n if (style.backgroundColor) {\n ctx.fillStyle = style.backgroundColor;\n\n if (hasRoundedCorners) {\n ctx.beginPath();\n roundedRect(\n ctx,\n x,\n y,\n width,\n height,\n borderRadius.topLeft,\n borderRadius.topRight,\n borderRadius.bottomRight,\n borderRadius.bottomLeft,\n );\n ctx.fill();\n } else {\n ctx.fillRect(x, y, width, height);\n }\n }\n\n // Borders\n drawBorders(ctx, x, y, width, height, style, borderRadius);\n}\n\nfunction resolveRadius(v: unknown, width: number, height: number): number {\n if (typeof v === \"string\") return parseCSSLength(v, Math.min(width, height));\n return toNumber(v);\n}\n\nexport function getBorderRadiusFromStyle(\n style: ComputedStyle,\n width: number,\n height: number,\n) {\n return {\n topLeft: resolveRadius(style.borderTopLeftRadius, width, height),\n topRight: resolveRadius(style.borderTopRightRadius, width, height),\n bottomRight: resolveRadius(style.borderBottomRightRadius, width, height),\n bottomLeft: resolveRadius(style.borderBottomLeftRadius, width, height),\n };\n}\n\nfunction drawBorders(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n style: ComputedStyle,\n borderRadius: ReturnType<typeof getBorderRadiusFromStyle>,\n): void {\n const hasRoundedCorners = hasRadius(borderRadius);\n\n // If all borders are the same, draw as a single stroke\n const tw = resolveBoxValue(style.borderTopWidth, width);\n const rw = resolveBoxValue(style.borderRightWidth, width);\n const bw = resolveBoxValue(style.borderBottomWidth, width);\n const lw = resolveBoxValue(style.borderLeftWidth, width);\n\n if (tw === 0 && rw === 0 && bw === 0 && lw === 0) return;\n\n const allSameWidth = tw === rw && rw === bw && bw === lw && tw > 0;\n const tc = style.borderTopColor ?? \"black\";\n const rc = style.borderRightColor ?? \"black\";\n const bc = style.borderBottomColor ?? \"black\";\n const lc = style.borderLeftColor ?? \"black\";\n const allSameColor = tc === rc && rc === bc && bc === lc;\n\n if (allSameWidth && allSameColor) {\n ctx.strokeStyle = tc;\n ctx.lineWidth = tw;\n\n if (hasRoundedCorners) {\n ctx.beginPath();\n const half = tw / 2;\n roundedRect(\n ctx,\n x + half,\n y + half,\n width - tw,\n height - tw,\n Math.max(0, borderRadius.topLeft - half),\n Math.max(0, borderRadius.topRight - half),\n Math.max(0, borderRadius.bottomRight - half),\n Math.max(0, borderRadius.bottomLeft - half),\n );\n ctx.stroke();\n } else {\n ctx.strokeRect(x + tw / 2, y + tw / 2, width - tw, height - tw);\n }\n return;\n }\n\n // Draw individual borders\n if (hasRoundedCorners) {\n const maxR = Math.min(width, height) / 2;\n const tl = Math.min(borderRadius.topLeft, maxR);\n const tr = Math.min(borderRadius.topRight, maxR);\n const br = Math.min(borderRadius.bottomRight, maxR);\n const bl = Math.min(borderRadius.bottomLeft, maxR);\n\n const top = y + tw / 2;\n const right = x + width - rw / 2;\n const bottom = y + height - bw / 2;\n const left = x + lw / 2;\n\n const eTL = Math.max(0, tl - Math.max(tw, lw) / 2);\n const eTR = Math.max(0, tr - Math.max(tw, rw) / 2);\n const eBR = Math.max(0, br - Math.max(bw, rw) / 2);\n const eBL = Math.max(0, bl - Math.max(bw, lw) / 2);\n\n // Each side owns its end corner (in drawing direction) and only draws the\n // start corner arc when the adjacent owner side is not visible (width 0).\n // This prevents double-stroking of corner arcs which causes AA artifacts.\n\n // Top side (L → R): borrows TL, owns TR\n if (tw > 0) {\n ctx.strokeStyle = tc;\n ctx.lineWidth = tw;\n ctx.beginPath();\n if (eTL > 0 && lw === 0) {\n ctx.moveTo(left, top + eTL);\n ctx.arcTo(left, top, left + eTL, top, eTL);\n } else if (eTL > 0) {\n ctx.moveTo(left + eTL, top);\n } else {\n ctx.moveTo(x, top);\n }\n if (eTR > 0) {\n ctx.lineTo(right - eTR, top);\n ctx.arcTo(right, top, right, top + eTR, eTR);\n } else {\n ctx.lineTo(x + width, top);\n }\n ctx.stroke();\n }\n\n // Right side (T → B): borrows TR, owns BR\n if (rw > 0) {\n ctx.strokeStyle = rc;\n ctx.lineWidth = rw;\n ctx.beginPath();\n if (eTR > 0 && tw === 0) {\n ctx.moveTo(right - eTR, top);\n ctx.arcTo(right, top, right, top + eTR, eTR);\n } else if (eTR > 0) {\n ctx.moveTo(right, top + eTR);\n } else {\n ctx.moveTo(right, y);\n }\n if (eBR > 0) {\n ctx.lineTo(right, bottom - eBR);\n ctx.arcTo(right, bottom, right - eBR, bottom, eBR);\n } else {\n ctx.lineTo(right, y + height);\n }\n ctx.stroke();\n }\n\n // Bottom side (R → L): borrows BR, owns BL\n if (bw > 0) {\n ctx.strokeStyle = bc;\n ctx.lineWidth = bw;\n ctx.beginPath();\n if (eBR > 0 && rw === 0) {\n ctx.moveTo(right, bottom - eBR);\n ctx.arcTo(right, bottom, right - eBR, bottom, eBR);\n } else if (eBR > 0) {\n ctx.moveTo(right - eBR, bottom);\n } else {\n ctx.moveTo(x + width, bottom);\n }\n if (eBL > 0) {\n ctx.lineTo(left + eBL, bottom);\n ctx.arcTo(left, bottom, left, bottom - eBL, eBL);\n } else {\n ctx.lineTo(x, bottom);\n }\n ctx.stroke();\n }\n\n // Left side (B → T): borrows BL, owns TL\n if (lw > 0) {\n ctx.strokeStyle = lc;\n ctx.lineWidth = lw;\n ctx.beginPath();\n if (eBL > 0 && bw === 0) {\n ctx.moveTo(left + eBL, bottom);\n ctx.arcTo(left, bottom, left, bottom - eBL, eBL);\n } else if (eBL > 0) {\n ctx.moveTo(left, bottom - eBL);\n } else {\n ctx.moveTo(left, y + height);\n }\n if (eTL > 0) {\n ctx.lineTo(left, top + eTL);\n ctx.arcTo(left, top, left + eTL, top, eTL);\n } else {\n ctx.lineTo(left, y);\n }\n ctx.stroke();\n }\n } else {\n if (tw > 0) {\n ctx.strokeStyle = tc;\n ctx.lineWidth = tw;\n ctx.beginPath();\n ctx.moveTo(x, y + tw / 2);\n ctx.lineTo(x + width, y + tw / 2);\n ctx.stroke();\n }\n if (rw > 0) {\n ctx.strokeStyle = rc;\n ctx.lineWidth = rw;\n ctx.beginPath();\n ctx.moveTo(x + width - rw / 2, y);\n ctx.lineTo(x + width - rw / 2, y + height);\n ctx.stroke();\n }\n if (bw > 0) {\n ctx.strokeStyle = bc;\n ctx.lineWidth = bw;\n ctx.beginPath();\n ctx.moveTo(x, y + height - bw / 2);\n ctx.lineTo(x + width, y + height - bw / 2);\n ctx.stroke();\n }\n if (lw > 0) {\n ctx.strokeStyle = lc;\n ctx.lineWidth = lw;\n ctx.beginPath();\n ctx.moveTo(x + lw / 2, y);\n ctx.lineTo(x + lw / 2, y + height);\n ctx.stroke();\n }\n }\n}\n\n// Parse simple box-shadow: offsetX offsetY blur spread? color\nconst BOX_SHADOW_RE =\n /(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?(?:\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?)?\\s+(.*)/;\n\nexport function drawBoxShadow(\n ctx: SKRSContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n boxShadow: string,\n borderRadius: ReturnType<typeof getBorderRadiusFromStyle>,\n): void {\n const parts = boxShadow.match(BOX_SHADOW_RE);\n if (!parts) return;\n\n const offsetX = parseFloat(parts[1]!);\n const offsetY = parseFloat(parts[2]!);\n const blur = parseFloat(parts[3]!);\n const color = parts[5]!.trim();\n\n const radii = [\n borderRadius.topLeft,\n borderRadius.topRight,\n borderRadius.bottomRight,\n borderRadius.bottomLeft,\n ];\n\n // Clip to area OUTSIDE the element so shadow renders but inner fill is hidden\n const margin = blur * 2 + Math.abs(offsetX) + Math.abs(offsetY);\n ctx.save();\n ctx.beginPath();\n ctx.rect(x - margin, y - margin, width + margin * 2, height + margin * 2);\n ctx.roundRect(x, y, width, height, radii);\n ctx.clip(\"evenodd\");\n\n // Use CSS filter blur (sigma = blur/2) instead of the canvas shadow API\n // because it matches SVG feGaussianBlur (used by satori) much more closely.\n ctx.filter = `blur(${blur / 2}px)`;\n ctx.translate(offsetX, offsetY);\n ctx.fillStyle = color;\n ctx.beginPath();\n ctx.roundRect(x, y, width, height, radii);\n ctx.fill();\n ctx.restore();\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\n\n/**\n * Parse and create a canvas gradient from a CSS gradient string.\n * Supports linear-gradient and radial-gradient.\n *\n * @returns A CanvasGradient or null if parsing fails\n */\nexport function createGradientFromCSS(\n ctx: SKRSContext2D,\n cssGradient: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): CanvasGradient | null {\n const trimmed = cssGradient.trim();\n\n if (trimmed.startsWith(\"linear-gradient\")) {\n return parseLinearGradient(ctx, trimmed, x, y, width, height);\n }\n\n if (trimmed.startsWith(\"radial-gradient\")) {\n return parseRadialGradient(ctx, trimmed, x, y, width, height);\n }\n\n return null;\n}\n\nfunction parseLinearGradient(\n ctx: SKRSContext2D,\n css: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): CanvasGradient | null {\n // Extract content between parentheses\n const match = css.match(/linear-gradient\\((.*)\\)/s);\n if (!match) return null;\n\n const content = match[1]!.trim();\n const parts = splitGradientArgs(content);\n\n let angle = 180; // default: to bottom\n let colorStartIdx = 0;\n\n // Parse direction\n const first = parts[0]?.trim();\n if (first) {\n if (first.startsWith(\"to \")) {\n angle = directionToAngle(first);\n colorStartIdx = 1;\n } else if (first.endsWith(\"deg\")) {\n angle = parseFloat(first);\n colorStartIdx = 1;\n } else if (first.endsWith(\"turn\")) {\n angle = parseFloat(first) * 360;\n colorStartIdx = 1;\n }\n }\n\n // Calculate gradient line endpoints\n const rad = ((angle - 90) * Math.PI) / 180;\n const cx = x + width / 2;\n const cy = y + height / 2;\n const halfDiag =\n Math.abs(width * Math.cos(rad)) / 2 + Math.abs(height * Math.sin(rad)) / 2;\n\n const x0 = cx - halfDiag * Math.cos(rad);\n const y0 = cy - halfDiag * Math.sin(rad);\n const x1 = cx + halfDiag * Math.cos(rad);\n const y1 = cy + halfDiag * Math.sin(rad);\n\n const gradient = ctx.createLinearGradient(x0, y0, x1, y1);\n\n // Parse color stops\n const stops = parts.slice(colorStartIdx);\n addColorStops(gradient, stops);\n\n return gradient;\n}\n\nfunction parseRadialGradient(\n ctx: SKRSContext2D,\n css: string,\n x: number,\n y: number,\n width: number,\n height: number,\n): CanvasGradient | null {\n const match = css.match(/radial-gradient\\((.*)\\)/s);\n if (!match) return null;\n\n const content = match[1]!.trim();\n const parts = splitGradientArgs(content);\n\n const cx = x + width / 2;\n const cy = y + height / 2;\n const radius = Math.max(width, height) / 2;\n\n const gradient = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius);\n\n // Simple parsing: skip shape/size/position, just get color stops\n let colorStartIdx = 0;\n const first = parts[0]?.trim() ?? \"\";\n if (\n first.startsWith(\"circle\") ||\n first.startsWith(\"ellipse\") ||\n first.startsWith(\"closest\") ||\n first.startsWith(\"farthest\")\n ) {\n colorStartIdx = 1;\n }\n\n addColorStops(gradient, parts.slice(colorStartIdx));\n\n return gradient;\n}\n\nfunction addColorStops(gradient: CanvasGradient, stops: string[]): void {\n if (stops.length === 0) return;\n\n for (let i = 0; i < stops.length; i++) {\n const stop = stops[i]!.trim();\n const percentMatch = stop.match(/^(.+?)\\s+(\\d+(?:\\.\\d+)?%?)$/);\n\n if (percentMatch) {\n const color = percentMatch[1]!;\n const pos = percentMatch[2]!;\n const offset = pos.endsWith(\"%\")\n ? parseFloat(pos) / 100\n : parseFloat(pos);\n gradient.addColorStop(Math.max(0, Math.min(1, offset)), color);\n } else {\n // Auto-distribute\n const offset = stops.length === 1 ? 0.5 : i / (stops.length - 1);\n gradient.addColorStop(offset, stop);\n }\n }\n}\n\nfunction directionToAngle(dir: string): number {\n const map: Record<string, number> = {\n \"to top\": 0,\n \"to right\": 90,\n \"to bottom\": 180,\n \"to left\": 270,\n \"to top right\": 45,\n \"to top left\": 315,\n \"to bottom right\": 135,\n \"to bottom left\": 225,\n };\n return map[dir] ?? 180;\n}\n\nexport function splitGradientArgs(content: string): string[] {\n const parts: string[] = [];\n let current = \"\";\n let parenDepth = 0;\n\n for (const char of content) {\n if (char === \"(\") parenDepth++;\n if (char === \")\") parenDepth--;\n if (char === \",\" && parenDepth === 0) {\n parts.push(current);\n current = \"\";\n } else {\n current += char;\n }\n }\n if (current.trim()) parts.push(current);\n\n return parts;\n}\n","// Compositing groups through @effing/skia's `beginGroup` / `endGroup`:\n// everything drawn inside a group is composited as one when it ends, which is\n// what CSS `opacity`, `filter` and `backdrop-filter` mean on an element.\n// Per-draw `globalAlpha` and `ctx.filter` can't give that once draws overlap:\n// overlapping children would show through each other, and each would cast its\n// own shadow.\n//\n// A group is composited through an offscreen buffer, which @effing/skia sizes\n// to what the group draws, so a translucent element costs about as much as\n// its own area.\n\nimport type { SKRSContext2D } from \"@effing/skia\";\nimport { beginGroup, endGroup } from \"@effing/skia/extensions\";\n\nimport { applyClip } from \"./clip.ts\";\nimport type { getBorderRadiusFromStyle } from \"./rect.ts\";\n\ntype BorderRadius = ReturnType<typeof getBorderRadiusFromStyle>;\n\n/** A CSS filter value that filters nothing. */\nfunction isNoFilter(filter: string | undefined): boolean {\n if (!filter) return true;\n const normalized = filter.trim();\n return normalized === \"\" || normalized === \"none\";\n}\n\n/**\n * Start the group an element and its descendants paint into, when its\n * `opacity` or `filter` call for one. Returns whether a group was started,\n * to end with `endElementGroup`.\n */\nexport function beginElementGroup(\n ctx: SKRSContext2D,\n opacity: number,\n filter: string | undefined,\n): boolean {\n const hasFilter = !isNoFilter(filter);\n if (opacity >= 1 && !hasFilter) return false;\n beginGroup(ctx, { opacity, filter: hasFilter ? filter!.trim() : undefined });\n return true;\n}\n\nexport function endElementGroup(ctx: SKRSContext2D): void {\n endGroup(ctx);\n}\n\n/**\n * CSS `backdrop-filter`: filter whatever is already painted behind the\n * element's border box (with its radius) and composite the result back at the\n * element's opacity. Must run before the element's own painting — box-shadow\n * and background included — so nothing of the element ends up in its own\n * backdrop and its background composites on top of the filtered result.\n *\n * The filter runs in the element's own coordinate space, and the backdrop is\n * clamped at the canvas edge, as a browser does at the viewport edge, so a\n * blur near the edge doesn't fade into transparency. Skia reads the backdrop\n * from the enclosing group, so as in a browser, an ancestor with `opacity` or\n * a `filter` bounds what the element sees through: only what that ancestor\n * has painted so far.\n */\nexport function drawBackdropFilter(\n ctx: SKRSContext2D,\n filter: string,\n x: number,\n y: number,\n width: number,\n height: number,\n borderRadius: BorderRadius,\n opacity: number,\n): void {\n if (width <= 0 || height <= 0) return;\n if (isNoFilter(filter)) return;\n ctx.save();\n applyClip(ctx, x, y, width, height, borderRadius);\n beginGroup(ctx, { backdropFilter: filter.trim(), opacity });\n endGroup(ctx);\n ctx.restore();\n}\n","/**\n * Shared cover/contain sizing logic used by both `<img>` objectFit\n * and `backgroundImage` + `backgroundSize`.\n */\n\nexport interface FitRect {\n sx: number;\n sy: number;\n sw: number;\n sh: number;\n dx: number;\n dy: number;\n dw: number;\n dh: number;\n}\n\n/**\n * Compute source and destination rectangles for \"cover\" sizing.\n * The image fills the box completely, cropping the excess.\n */\nexport function computeCover(\n imgW: number,\n imgH: number,\n boxX: number,\n boxY: number,\n boxW: number,\n boxH: number,\n): FitRect {\n const imgRatio = imgW / imgH;\n const boxRatio = boxW / boxH;\n\n let sx: number, sy: number, sw: number, sh: number;\n\n if (imgRatio > boxRatio) {\n sh = imgH;\n sw = imgH * boxRatio;\n sx = (imgW - sw) / 2;\n sy = 0;\n } else {\n sw = imgW;\n sh = imgW / boxRatio;\n sx = 0;\n sy = (imgH - sh) / 2;\n }\n\n return { sx, sy, sw, sh, dx: boxX, dy: boxY, dw: boxW, dh: boxH };\n}\n\n/**\n * Compute destination rectangle for \"contain\" sizing.\n * The image fits entirely within the box, centered, with no cropping.\n */\nexport function computeContain(\n imgW: number,\n imgH: number,\n boxX: number,\n boxY: number,\n boxW: number,\n boxH: number,\n): FitRect {\n const imgRatio = imgW / imgH;\n const boxRatio = boxW / boxH;\n\n let dw: number, dh: number;\n\n if (imgRatio > boxRatio) {\n dw = boxW;\n dh = boxW / imgRatio;\n } else {\n dh = boxH;\n dw = boxH * imgRatio;\n }\n\n const dx = boxX + (boxW - dw) / 2;\n const dy = boxY + (boxH - dh) / 2;\n\n return { sx: 0, sy: 0, sw: imgW, sh: imgH, dx, dy, dw, dh };\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\n\nimport { cachedLoadImage } from \"../../image.ts\";\nimport type { ComputedStyle } from \"../style/compute.ts\";\nimport type { RenderContext } from \"../context.ts\";\nimport { computeContain, computeCover } from \"./object-fit.ts\";\n\n/**\n * Draw an image element onto the canvas.\n *\n * @param ctx - Canvas rendering context\n * @param src - Image source (URL, file path, or Buffer)\n * @param x - X position\n * @param y - Y position\n * @param width - Target width\n * @param height - Target height\n * @param context - Per-render context (image cache + fetch config)\n * @param style - Computed style (for objectFit)\n */\nexport async function drawImage(\n ctx: SKRSContext2D,\n src: string | Buffer,\n x: number,\n y: number,\n width: number,\n height: number,\n context: RenderContext,\n style?: ComputedStyle,\n): Promise<void> {\n const image = await cachedLoadImage(\n context.imageCache,\n src,\n context.userAgent,\n );\n const objectFit = style?.objectFit ?? \"fill\";\n\n if (objectFit === \"fill\") {\n ctx.drawImage(image, x, y, width, height);\n return;\n }\n\n const imgW = image.width;\n const imgH = image.height;\n\n if (objectFit === \"contain\") {\n const r = computeContain(imgW, imgH, x, y, width, height);\n ctx.drawImage(image, r.dx, r.dy, r.dw, r.dh);\n } else if (objectFit === \"cover\") {\n const r = computeCover(imgW, imgH, x, y, width, height);\n ctx.drawImage(image, r.sx, r.sy, r.sw, r.sh, r.dx, r.dy, r.dw, r.dh);\n } else if (objectFit === \"none\") {\n const dx = x + (width - imgW) / 2;\n const dy = y + (height - imgH) / 2;\n ctx.drawImage(image, dx, dy);\n } else if (objectFit === \"scale-down\") {\n if (imgW <= width && imgH <= height) {\n const dx = x + (width - imgW) / 2;\n const dy = y + (height - imgH) / 2;\n ctx.drawImage(image, dx, dy);\n } else {\n const r = computeContain(imgW, imgH, x, y, width, height);\n ctx.drawImage(image, r.dx, r.dy, r.dw, r.dh);\n }\n }\n}\n","import type { InheritedSvgStyle } from \"./types.ts\";\n\n/** Replace `\"currentColor\"` with the inherited CSS `color` value. */\nexport function resolveCurrentColor(\n value: string | undefined,\n color: string,\n): string | undefined {\n if (value?.toLowerCase() === \"currentcolor\") return color;\n return value;\n}\n\n/**\n * Merge SVG presentation properties from `props.style` into the props object.\n * Style values win over direct props, matching browser CSS specificity rules.\n */\nexport function mergeStyleIntoProps(\n props: Record<string, unknown>,\n): Record<string, unknown> {\n const style = props.style as Record<string, unknown> | undefined;\n if (!style) return props;\n return { ...props, ...style };\n}\n\n/**\n * Parse an SVG length value, resolving percentages against a reference dimension.\n * Unlike gradient-specific `parseFrac`, this returns absolute coordinates (not 0–1 fractions).\n */\nexport function svgLength(\n value: unknown,\n reference: number,\n fallback = 0,\n): number {\n if (value == null) return fallback;\n const s = String(value);\n if (s.endsWith(\"%\")) return (parseFloat(s) / 100) * reference;\n const n = Number(s);\n return isNaN(n) ? fallback : n;\n}\n\n/** Parse `url(#id)` references and return the id, or undefined. */\nexport function parseUrlRef(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const m = value.match(/^url\\(#(.+)\\)$/);\n return m?.[1];\n}\n\n/**\n * Build an `InheritedSvgStyle` from merged SVG props, falling back to `parent`\n * values when present (for nested groups) or sensible defaults (fill = \"black\").\n */\nexport function resolveInheritedStyle(\n merged: Record<string, unknown>,\n color: string,\n parent?: InheritedSvgStyle,\n): InheritedSvgStyle {\n return {\n fill:\n resolveCurrentColor(merged.fill as string | undefined, color) ??\n parent?.fill ??\n \"black\",\n stroke:\n resolveCurrentColor(merged.stroke as string | undefined, color) ??\n parent?.stroke,\n strokeWidth:\n ((merged.strokeWidth ?? merged[\"stroke-width\"]) as\n | string\n | number\n | undefined) ?? parent?.strokeWidth,\n strokeLinecap:\n ((merged.strokeLinecap ?? merged[\"stroke-linecap\"]) as\n | string\n | undefined) ?? parent?.strokeLinecap,\n strokeLinejoin:\n ((merged.strokeLinejoin ?? merged[\"stroke-linejoin\"]) as\n | string\n | undefined) ?? parent?.strokeLinejoin,\n strokeOpacity:\n ((merged.strokeOpacity ?? merged[\"stroke-opacity\"]) as\n | string\n | number\n | undefined) ?? parent?.strokeOpacity,\n };\n}\n","import type { SvgChild } from \"./types.ts\";\n\n/** Normalize children from either `.children` or `.props.children` into an array. */\nexport function normalizeChildren(node: SvgChild): SvgChild[] {\n const raw =\n node.children ?? (node.props.children as SvgChild | SvgChild[] | undefined);\n if (raw == null) return [];\n return (Array.isArray(raw) ? raw.flat(Infinity) : [raw]) as SvgChild[];\n}\n","import type { SvgChild, SvgDefs } from \"./types.ts\";\nimport { normalizeChildren } from \"./tree.ts\";\n\n/**\n * Collect `<clipPath>`, `<mask>`, `<filter>`, and gradient definitions from\n * `<defs>` elements as well as direct children of `<svg>` (both are valid per\n * the SVG spec).\n */\nexport function collectDefs(children: SvgChild[], vbW = 0, vbH = 0): SvgDefs {\n const clips = new Map<string, SvgChild[]>();\n const gradients = new Map<string, SvgChild>();\n const masks = new Map<string, SvgChild[]>();\n const filters = new Map<string, SvgChild>();\n\n function insertDef(def: SvgChild): void {\n if (!def || typeof def !== \"object\" || !(\"props\" in def) || !def.props)\n return;\n const id = def.props.id as string | undefined;\n if (!id) return;\n if (def.type === \"clipPath\") clips.set(id, normalizeChildren(def));\n else if (def.type === \"mask\") masks.set(id, normalizeChildren(def));\n else if (def.type === \"filter\") filters.set(id, def);\n else if (def.type === \"radialGradient\" || def.type === \"linearGradient\")\n gradients.set(id, def);\n }\n\n for (const child of children) {\n if (child.type === \"defs\") {\n for (const def of normalizeChildren(child)) insertDef(def);\n } else {\n // Definition elements can appear as direct children of <svg>.\n insertDef(child);\n }\n }\n return {\n clips,\n gradients,\n masks,\n filters,\n viewport: { width: vbW, height: vbH },\n };\n}\n\nexport const EMPTY_DEFS: SvgDefs = {\n clips: new Map(),\n gradients: new Map(),\n masks: new Map(),\n filters: new Map(),\n viewport: { width: 0, height: 0 },\n};\n","import type { SKRSContext2D } from \"@effing/skia\";\n\n/**\n * Save context state and apply transform + opacity if present.\n * Returns true if ctx.save() was called (caller must ctx.restore()).\n */\nexport function applyTransformAndOpacity(\n ctx: SKRSContext2D,\n transform: string | undefined,\n opacity: number,\n): boolean {\n if (!transform && opacity >= 1) return false;\n ctx.save();\n if (transform) applySvgTransform(ctx, transform);\n if (opacity < 1) ctx.globalAlpha *= opacity;\n return true;\n}\n\n/**\n * Parse an SVG `transform` attribute and apply it to the canvas context.\n *\n * Supports: translate, scale, rotate, skewX, skewY, matrix.\n * Multiple transforms are applied left-to-right (same order as SVG spec).\n */\nexport function applySvgTransform(ctx: SKRSContext2D, transform: string): void {\n const re = /\\b(translate|scale|rotate|skewX|skewY|matrix)\\s*\\(([^)]*)\\)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(transform)) !== null) {\n const fn = match[1]!;\n const args = match[2]!\n .split(/[\\s,]+/)\n .filter(Boolean)\n .map(Number);\n\n switch (fn) {\n case \"translate\":\n ctx.translate(args[0] ?? 0, args[1] ?? 0);\n break;\n case \"scale\": {\n const sx = args[0] ?? 1;\n ctx.scale(sx, args[1] ?? sx);\n break;\n }\n case \"rotate\": {\n const angle = ((args[0] ?? 0) * Math.PI) / 180;\n if (args.length >= 3) {\n const cx = args[1]!;\n const cy = args[2]!;\n ctx.translate(cx, cy);\n ctx.rotate(angle);\n ctx.translate(-cx, -cy);\n } else {\n ctx.rotate(angle);\n }\n break;\n }\n case \"skewX\":\n ctx.transform(\n 1,\n 0,\n Math.tan(((args[0] ?? 0) * Math.PI) / 180),\n 1,\n 0,\n 0,\n );\n break;\n case \"skewY\":\n ctx.transform(\n 1,\n Math.tan(((args[0] ?? 0) * Math.PI) / 180),\n 0,\n 1,\n 0,\n 0,\n );\n break;\n case \"matrix\":\n ctx.transform(\n args[0] ?? 1,\n args[1] ?? 0,\n args[2] ?? 0,\n args[3] ?? 1,\n args[4] ?? 0,\n args[5] ?? 0,\n );\n break;\n }\n }\n}\n","import { Path2D } from \"@effing/skia\";\n\nimport type { BBox, SvgChild } from \"./types.ts\";\nimport { mergeStyleIntoProps } from \"./style.ts\";\nimport { svgLength } from \"./style.ts\";\n\n/** Compute a conservative bounding box from SVG path data. */\nexport function pathBBox(d: string): BBox {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let cx = 0;\n let cy = 0;\n\n const update = (x: number, y: number) => {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n };\n\n // Tokenize: commands and numbers (including negative)\n const tokens = d.match(/[a-zA-Z]|[-+]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][-+]?\\d+)?/g);\n if (!tokens) return { x: 0, y: 0, width: 0, height: 0 };\n\n let cmd = \"\";\n let i = 0;\n const num = () => Number(tokens[i++]);\n\n while (i < tokens.length) {\n const t = tokens[i]!;\n if (/[a-zA-Z]/.test(t)) {\n cmd = t;\n i++;\n }\n\n switch (cmd) {\n case \"M\":\n cx = num();\n cy = num();\n update(cx, cy);\n cmd = \"L\"; // implicit lineTo after moveTo\n break;\n case \"m\":\n cx += num();\n cy += num();\n update(cx, cy);\n cmd = \"l\";\n break;\n case \"L\":\n cx = num();\n cy = num();\n update(cx, cy);\n break;\n case \"l\":\n cx += num();\n cy += num();\n update(cx, cy);\n break;\n case \"H\":\n cx = num();\n update(cx, cy);\n break;\n case \"h\":\n cx += num();\n update(cx, cy);\n break;\n case \"V\":\n cy = num();\n update(cx, cy);\n break;\n case \"v\":\n cy += num();\n update(cx, cy);\n break;\n case \"C\": {\n // Cubic bezier: use control points as conservative bounds\n for (let j = 0; j < 3; j++) {\n const px = num();\n const py = num();\n update(px, py);\n }\n cx = Number(tokens[i - 2]);\n cy = Number(tokens[i - 1]);\n break;\n }\n case \"c\": {\n for (let j = 0; j < 3; j++) {\n const dx = num();\n const dy = num();\n update(cx + dx, cy + dy);\n if (j === 2) {\n cx += dx;\n cy += dy;\n }\n }\n break;\n }\n case \"Q\": {\n for (let j = 0; j < 2; j++) {\n const px = num();\n const py = num();\n update(px, py);\n }\n cx = Number(tokens[i - 2]);\n cy = Number(tokens[i - 1]);\n break;\n }\n case \"q\": {\n for (let j = 0; j < 2; j++) {\n const dx = num();\n const dy = num();\n update(cx + dx, cy + dy);\n if (j === 1) {\n cx += dx;\n cy += dy;\n }\n }\n break;\n }\n case \"A\": {\n // Arc: skip rx, ry, rotation, flags; endpoint is the bound\n num();\n num();\n num();\n num();\n num(); // rx ry rot largeArc sweep\n cx = num();\n cy = num();\n update(cx, cy);\n break;\n }\n case \"a\": {\n num();\n num();\n num();\n num();\n num();\n cx += num();\n cy += num();\n update(cx, cy);\n break;\n }\n case \"Z\":\n case \"z\":\n break;\n default:\n // Unknown command — skip token to avoid infinite loop\n i++;\n break;\n }\n }\n\n if (!isFinite(minX)) return { x: 0, y: 0, width: 0, height: 0 };\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/** Compute bounding box from a points attribute (polygon/polyline). */\nexport function pointsBBox(points: [number, number][]): BBox {\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const [x, y] of points) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n if (!isFinite(minX)) return { x: 0, y: 0, width: 0, height: 0 };\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n/**\n * Build a `Path2D` from an SVG shape element (without drawing it).\n * Returns `undefined` for unsupported element types.\n */\nexport function buildPath(\n child: SvgChild,\n vbW: number,\n vbH: number,\n): Path2D | undefined {\n const props = mergeStyleIntoProps(child.props);\n switch (child.type) {\n case \"path\": {\n const d = props.d as string | undefined;\n if (!d) return undefined;\n return new Path2D(d);\n }\n case \"circle\": {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const r = svgLength(props.r, Math.min(vbW, vbH));\n if (r <= 0) return undefined;\n const p = new Path2D();\n p.arc(cx, cy, r, 0, Math.PI * 2);\n return p;\n }\n case \"rect\": {\n const x = svgLength(props.x, vbW);\n const y = svgLength(props.y, vbH);\n const w = svgLength(props.width, vbW);\n const h = svgLength(props.height, vbH);\n if (w <= 0 || h <= 0) return undefined;\n const rxRaw = svgLength(props.rx, vbW, -1);\n const ryRaw = svgLength(props.ry, vbH, -1);\n let rx = rxRaw >= 0 ? rxRaw : ryRaw >= 0 ? ryRaw : 0;\n let ry = ryRaw >= 0 ? ryRaw : rx;\n rx = Math.min(rx, w / 2);\n ry = Math.min(ry, h / 2);\n const p = new Path2D();\n if (rx > 0 || ry > 0) {\n p.roundRect(x, y, w, h, [rx]);\n } else {\n p.rect(x, y, w, h);\n }\n return p;\n }\n case \"ellipse\": {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const rx = svgLength(props.rx, vbW);\n const ry = svgLength(props.ry, vbH);\n if (rx <= 0 || ry <= 0) return undefined;\n const p = new Path2D();\n p.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);\n return p;\n }\n case \"polygon\": {\n const points = parsePoints(props.points as string | undefined);\n if (points.length < 2) return undefined;\n const p = new Path2D();\n p.moveTo(points[0]![0], points[0]![1]);\n for (let i = 1; i < points.length; i++) {\n p.lineTo(points[i]![0], points[i]![1]);\n }\n p.closePath();\n return p;\n }\n default:\n return undefined;\n }\n}\n\n/**\n * Build a combined `Path2D` from all children of a `<clipPath>` definition.\n */\nexport function buildClipPath(\n shapes: SvgChild[],\n vbW: number,\n vbH: number,\n): Path2D | undefined {\n let combined: Path2D | undefined;\n for (const shape of shapes) {\n const p = buildPath(shape, vbW, vbH);\n if (!p) continue;\n if (!combined) {\n combined = p;\n } else {\n combined.addPath(p);\n }\n }\n return combined;\n}\n\nexport function parsePoints(value: string | undefined): [number, number][] {\n if (!value) return [];\n const nums = value\n .trim()\n .split(/[\\s,]+/)\n .map(Number);\n const result: [number, number][] = [];\n for (let i = 0; i + 1 < nums.length; i += 2) {\n result.push([nums[i]!, nums[i + 1]!]);\n }\n return result;\n}\n","import type { Canvas, SKRSContext2D } from \"@effing/skia\";\nimport { createCanvas } from \"@effing/skia\";\n\nconst canvasPool = new Map<string, WeakRef<Canvas>[]>();\n\nexport function acquireOffscreen(\n w: number,\n h: number,\n): [Canvas, SKRSContext2D] {\n const key = `${w}x${h}`;\n const stack = canvasPool.get(key);\n if (stack) {\n while (stack.length > 0) {\n const ref = stack.pop()!;\n const canvas = ref.deref();\n if (canvas) {\n const ctx = canvas.getContext(\"2d\");\n ctx.reset();\n return [canvas, ctx];\n }\n }\n }\n const canvas = createCanvas(w, h);\n return [canvas, canvas.getContext(\"2d\")];\n}\n\nexport function releaseOffscreen(canvas: Canvas): void {\n const key = `${canvas.width}x${canvas.height}`;\n let stack = canvasPool.get(key);\n if (!stack) {\n stack = [];\n canvasPool.set(key, stack);\n }\n stack.push(new WeakRef(canvas));\n}\n","import type { Canvas } from \"@effing/skia\";\n\nimport type { SvgChild } from \"./types.ts\";\nimport { normalizeChildren } from \"./tree.ts\";\nimport { acquireOffscreen } from \"../offscreen.ts\";\n\nfunction applyFeOffset(\n input: Canvas,\n dx: number,\n dy: number,\n w: number,\n h: number,\n): Canvas {\n const [canvas, ctx] = acquireOffscreen(w, h);\n ctx.drawImage(input, dx, dy);\n return canvas;\n}\n\nfunction applyFeGaussianBlur(\n input: Canvas,\n stdDeviation: number,\n w: number,\n h: number,\n): Canvas {\n const [canvas, ctx] = acquireOffscreen(w, h);\n ctx.filter = `blur(${stdDeviation}px)`;\n ctx.drawImage(input, 0, 0);\n ctx.filter = \"none\";\n return canvas;\n}\n\nfunction applyFeColorMatrix(\n input: Canvas,\n type: string,\n values: string | undefined,\n w: number,\n h: number,\n): Canvas {\n const [canvas, ctx] = acquireOffscreen(w, h);\n ctx.drawImage(input, 0, 0);\n\n if (type === \"matrix\" && values) {\n const m = values\n .trim()\n .split(/[\\s,]+/)\n .map(Number);\n if (m.length >= 20) {\n const imageData = ctx.getImageData(0, 0, w, h);\n const d = imageData.data;\n for (let i = 0; i < d.length; i += 4) {\n const r = d[i]!;\n const g = d[i + 1]!;\n const b = d[i + 2]!;\n const a = d[i + 3]!;\n d[i] = Math.min(\n 255,\n Math.max(\n 0,\n m[0]! * r + m[1]! * g + m[2]! * b + m[3]! * a + m[4]! * 255,\n ),\n );\n d[i + 1] = Math.min(\n 255,\n Math.max(\n 0,\n m[5]! * r + m[6]! * g + m[7]! * b + m[8]! * a + m[9]! * 255,\n ),\n );\n d[i + 2] = Math.min(\n 255,\n Math.max(\n 0,\n m[10]! * r + m[11]! * g + m[12]! * b + m[13]! * a + m[14]! * 255,\n ),\n );\n d[i + 3] = Math.min(\n 255,\n Math.max(\n 0,\n m[15]! * r + m[16]! * g + m[17]! * b + m[18]! * a + m[19]! * 255,\n ),\n );\n }\n ctx.putImageData(imageData, 0, 0);\n }\n }\n\n return canvas;\n}\n\nconst BLEND_MODE_MAP: Record<string, GlobalCompositeOperation> = {\n normal: \"source-over\",\n multiply: \"multiply\",\n screen: \"screen\",\n darken: \"darken\",\n lighten: \"lighten\",\n overlay: \"overlay\",\n};\n\nfunction applyFeBlend(\n in1: Canvas,\n in2: Canvas,\n mode: string,\n w: number,\n h: number,\n): Canvas {\n const [canvas, ctx] = acquireOffscreen(w, h);\n ctx.drawImage(in2, 0, 0);\n ctx.globalCompositeOperation = BLEND_MODE_MAP[mode] ?? \"source-over\";\n ctx.drawImage(in1, 0, 0);\n ctx.globalCompositeOperation = \"source-over\";\n return canvas;\n}\n\n/**\n * Extract the alpha channel of a canvas as a new greyscale canvas.\n * The result is a canvas where each pixel's RGBA channels equal the\n * source alpha (i.e. white where opaque, black where transparent).\n */\nfunction extractSourceAlpha(input: Canvas, w: number, h: number): Canvas {\n const [canvas, ctx] = acquireOffscreen(w, h);\n ctx.fillStyle = \"black\";\n ctx.fillRect(0, 0, w, h);\n ctx.globalCompositeOperation = \"destination-in\";\n ctx.drawImage(input, 0, 0);\n ctx.globalCompositeOperation = \"source-over\";\n return canvas;\n}\n\n/**\n * Execute an SVG `<filter>` pipeline on the element canvas.\n * Returns a new canvas with the filtered result; the caller is responsible\n * for releasing all canvases.\n */\nexport function applyFilter(\n filterDef: SvgChild,\n sourceGraphic: Canvas,\n w: number,\n h: number,\n): Canvas {\n const buffers = new Map<string, Canvas>();\n buffers.set(\"SourceGraphic\", sourceGraphic);\n\n let sourceAlpha: Canvas | undefined;\n const getSourceAlpha = () => {\n if (!sourceAlpha) {\n sourceAlpha = extractSourceAlpha(sourceGraphic, w, h);\n buffers.set(\"SourceAlpha\", sourceAlpha);\n }\n return sourceAlpha;\n };\n\n const children = normalizeChildren(filterDef);\n let lastResult: Canvas = sourceGraphic;\n\n for (const prim of children) {\n const p = prim.props;\n const inName = (p.in as string | undefined) ?? \"\";\n const resolve = (name: string): Canvas => {\n if (name === \"SourceAlpha\") return getSourceAlpha();\n return buffers.get(name) ?? lastResult;\n };\n const input = inName ? resolve(inName) : lastResult;\n let output: Canvas;\n\n switch (prim.type) {\n case \"feOffset\":\n output = applyFeOffset(\n input,\n Number(p.dx ?? 0),\n Number(p.dy ?? 0),\n w,\n h,\n );\n break;\n case \"feGaussianBlur\": {\n const std = Number(p.stdDeviation ?? 0);\n output = std > 0 ? applyFeGaussianBlur(input, std, w, h) : input;\n break;\n }\n case \"feColorMatrix\":\n output = applyFeColorMatrix(\n input,\n (p.type as string) ?? \"matrix\",\n p.values as string | undefined,\n w,\n h,\n );\n break;\n case \"feBlend\": {\n const in2Name = (p.in2 as string | undefined) ?? \"\";\n const in2 = in2Name ? resolve(in2Name) : lastResult;\n output = applyFeBlend(input, in2, (p.mode as string) ?? \"normal\", w, h);\n break;\n }\n default:\n output = input;\n break;\n }\n\n const resultName = p.result as string | undefined;\n if (resultName) buffers.set(resultName, output);\n lastResult = output;\n }\n\n return lastResult;\n}\n","import { Path2D } from \"@effing/skia\";\nimport type { SKRSContext2D } from \"@effing/skia\";\n\nimport type { BBox, InheritedSvgStyle, SvgDefs } from \"./types.ts\";\nimport { applyFillAndStroke, applyStroke } from \"./paint.ts\";\nimport { pathBBox, pointsBBox, parsePoints } from \"./path.ts\";\nimport { svgLength } from \"./style.ts\";\n\nexport function drawPath(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n): void {\n const d = props.d as string | undefined;\n if (!d) return;\n\n const path = new Path2D(d);\n const bbox = pathBBox(d);\n applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function drawCircle(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const r = svgLength(props.r, Math.min(vbW, vbH));\n if (r <= 0) return;\n\n const path = new Path2D();\n path.arc(cx, cy, r, 0, Math.PI * 2);\n const bbox: BBox = { x: cx - r, y: cy - r, width: 2 * r, height: 2 * r };\n applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function drawSvgRect(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const x = svgLength(props.x, vbW);\n const y = svgLength(props.y, vbH);\n const w = svgLength(props.width, vbW);\n const h = svgLength(props.height, vbH);\n if (w <= 0 || h <= 0) return;\n\n const rxRaw = svgLength(props.rx, vbW, -1);\n const ryRaw = svgLength(props.ry, vbH, -1);\n let rx = rxRaw >= 0 ? rxRaw : ryRaw >= 0 ? ryRaw : 0;\n let ry = ryRaw >= 0 ? ryRaw : rx;\n rx = Math.min(rx, w / 2);\n ry = Math.min(ry, h / 2);\n\n const path = new Path2D();\n if (rx > 0 || ry > 0) {\n path.roundRect(x, y, w, h, [rx]);\n } else {\n path.rect(x, y, w, h);\n }\n const bbox: BBox = { x, y, width: w, height: h };\n applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function drawLine(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const x1 = svgLength(props.x1, vbW);\n const y1 = svgLength(props.y1, vbH);\n const x2 = svgLength(props.x2, vbW);\n const y2 = svgLength(props.y2, vbH);\n\n const path = new Path2D();\n path.moveTo(x1, y1);\n path.lineTo(x2, y2);\n // Lines are stroke-only\n const bbox: BBox = {\n x: Math.min(x1, x2),\n y: Math.min(y1, y2),\n width: Math.abs(x2 - x1),\n height: Math.abs(y2 - y1),\n };\n applyStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function drawEllipse(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n vbW = 0,\n vbH = 0,\n): void {\n const cx = svgLength(props.cx, vbW);\n const cy = svgLength(props.cy, vbH);\n const rx = svgLength(props.rx, vbW);\n const ry = svgLength(props.ry, vbH);\n if (rx <= 0 || ry <= 0) return;\n\n const path = new Path2D();\n path.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);\n const bbox: BBox = {\n x: cx - rx,\n y: cy - ry,\n width: 2 * rx,\n height: 2 * ry,\n };\n applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function drawPolygon(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n): void {\n const points = parsePoints(props.points as string | undefined);\n if (points.length < 2) return;\n\n const path = new Path2D();\n path.moveTo(points[0]![0], points[0]![1]);\n for (let i = 1; i < points.length; i++) {\n path.lineTo(points[i]![0], points[i]![1]);\n }\n path.closePath();\n const bbox = pointsBBox(points);\n applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function drawPolyline(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n): void {\n const points = parsePoints(props.points as string | undefined);\n if (points.length < 2) return;\n\n const path = new Path2D();\n path.moveTo(points[0]![0], points[0]![1]);\n for (let i = 1; i < points.length; i++) {\n path.lineTo(points[i]![0], points[i]![1]);\n }\n const bbox = pointsBBox(points);\n applyFillAndStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n","import { Path2D } from \"@effing/skia\";\nimport type {\n CanvasGradient,\n DOMMatrix2DInit,\n SKRSContext2D,\n} from \"@effing/skia\";\n\nimport parseCssColor from \"parse-css-color\";\n\nimport type { BBox, SvgChild, SvgDefs } from \"./types.ts\";\nimport { normalizeChildren } from \"./tree.ts\";\n\ntype Viewport = SvgDefs[\"viewport\"];\n\n/** Parse a gradient coordinate percentage/fraction to a 0–1 value. */\nfunction parseFrac(value: unknown, fallback: number): number {\n if (value == null) return fallback;\n const s = String(value);\n if (s.endsWith(\"%\")) return parseFloat(s) / 100;\n return Number(s);\n}\n\n/** True when the gradient declares `gradientUnits=\"userSpaceOnUse\"`. */\nfunction isUserSpaceOnUse(props: Record<string, unknown>): boolean {\n return props.gradientUnits === \"userSpaceOnUse\";\n}\n\n/**\n * Parse a user-space gradient coordinate. Percentages resolve against\n * `reference` (the relevant viewport dimension, per the SVG spec).\n */\nfunction parseUserLength(\n value: unknown,\n fallback: number,\n reference: number,\n): number {\n if (value == null) return fallback;\n const s = String(value);\n if (s.endsWith(\"%\")) return (parseFloat(s) / 100) * reference;\n return Number(s);\n}\n\n/** Apply opacity to a CSS color string. */\nexport function applyOpacity(color: string, opacity: number): string {\n if (opacity >= 1) return color;\n const parsed = parseCssColor(color);\n if (!parsed) return color;\n const [r, g, b] = parsed.values;\n return `rgba(${r}, ${g}, ${b}, ${parsed.alpha * opacity})`;\n}\n\n/** Add color stops from SVG `<stop>` children to a canvas gradient. */\nfunction addGradientStops(gradient: CanvasGradient, def: SvgChild): void {\n for (const stop of normalizeChildren(def)) {\n if (stop.type !== \"stop\") continue;\n const sp = stop.props;\n const offsetRaw = (sp.offset as string | number) ?? 0;\n const offset =\n typeof offsetRaw === \"string\" && offsetRaw.endsWith(\"%\")\n ? parseFloat(offsetRaw) / 100\n : Number(offsetRaw);\n const stopColor =\n ((sp.stopColor ?? sp[\"stop-color\"]) as string | undefined) ?? \"black\";\n const stopOpacity = Number(sp.stopOpacity ?? sp[\"stop-opacity\"] ?? 1);\n gradient.addColorStop(offset, applyOpacity(stopColor, stopOpacity));\n }\n}\n\n/** Create a linear gradient from bbox-relative coordinates with stops applied. */\nfunction createLinearGradientFromBBox(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n bbox: BBox,\n def: SvgChild,\n): CanvasGradient {\n const x1 = bbox.x + parseFrac(props.x1, 0) * bbox.width;\n const y1 = bbox.y + parseFrac(props.y1, 0) * bbox.height;\n const x2 = bbox.x + parseFrac(props.x2, 1) * bbox.width;\n const y2 = bbox.y + parseFrac(props.y2, 0) * bbox.height;\n const gradient = ctx.createLinearGradient(x1, y1, x2, y2);\n addGradientStops(gradient, def);\n return gradient;\n}\n\n/**\n * Create a linear gradient from `userSpaceOnUse` coordinates with stops\n * applied. The coordinates are in the SVG user coordinate system, which is\n * the context's current coordinate system (the viewBox transform is active),\n * so they map to canvas gradient coordinates directly.\n */\nfunction createLinearGradientUserSpace(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n viewport: Viewport,\n def: SvgChild,\n): CanvasGradient {\n const x1 = parseUserLength(props.x1, 0, viewport.width);\n const y1 = parseUserLength(props.y1, 0, viewport.height);\n const x2 = parseUserLength(props.x2, viewport.width, viewport.width);\n const y2 = parseUserLength(props.y2, 0, viewport.height);\n const gradient = ctx.createLinearGradient(x1, y1, x2, y2);\n addGradientStops(gradient, def);\n return gradient;\n}\n\n/**\n * Create a radial gradient from `userSpaceOnUse` coordinates with stops\n * applied. In user space the gradient is a true circle, so no elliptical\n * bbox transform is needed. Percentage radii resolve against the\n * viewport's normalized diagonal, per the SVG spec.\n */\nfunction createRadialGradientUserSpace(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n viewport: Viewport,\n def: SvgChild,\n): CanvasGradient {\n const diagonal = Math.hypot(viewport.width, viewport.height) / Math.SQRT2;\n const cx = parseUserLength(props.cx, viewport.width / 2, viewport.width);\n const cy = parseUserLength(props.cy, viewport.height / 2, viewport.height);\n const r = parseUserLength(props.r, diagonal / 2, diagonal);\n const fx = parseUserLength(props.fx, cx, viewport.width);\n const fy = parseUserLength(props.fy, cy, viewport.height);\n const gradient = ctx.createRadialGradient(fx, fy, 0, cx, cy, r);\n addGradientStops(gradient, def);\n return gradient;\n}\n\n/**\n * Fill `path` with a gradient defined by `def` in the coordinate space of `bbox`.\n *\n * With `gradientUnits=\"userSpaceOnUse\"` the gradient coordinates are already\n * in the SVG user coordinate system and are used as-is.\n *\n * With the default `objectBoundingBox` units, coordinates are fractions of\n * `bbox`. For `<linearGradient>` the bbox-to-canvas mapping is\n * straightforward. For `<radialGradient>` a non-square bbox produces an\n * *elliptical* gradient. Canvas only supports circular radial gradients, so\n * we apply a non-uniform scale transform to the context and fill an\n * inverse-transformed copy of the path.\n */\nexport function fillWithSvgGradient(\n ctx: SKRSContext2D,\n def: SvgChild,\n bbox: BBox,\n path: Path2D,\n fillRule: CanvasFillRule,\n viewport: Viewport,\n): boolean {\n const props = def.props;\n\n if (def.type === \"linearGradient\") {\n ctx.fillStyle = isUserSpaceOnUse(props)\n ? createLinearGradientUserSpace(ctx, props, viewport, def)\n : createLinearGradientFromBBox(ctx, props, bbox, def);\n ctx.fill(path, fillRule);\n return true;\n }\n\n if (def.type === \"radialGradient\" && isUserSpaceOnUse(props)) {\n ctx.fillStyle = createRadialGradientUserSpace(ctx, props, viewport, def);\n ctx.fill(path, fillRule);\n return true;\n }\n\n if (def.type === \"radialGradient\") {\n const cxF = parseFrac(props.cx, 0.5);\n const cyF = parseFrac(props.cy, 0.5);\n const rF = parseFrac(props.r, 0.5);\n const fxF = parseFrac(props.fx, cxF);\n const fyF = parseFrac(props.fy, cyF);\n\n // Render in a transformed space where the bbox maps to a unit square.\n // This turns canvas's circular radial gradient into the correct ellipse.\n ctx.save();\n ctx.translate(bbox.x, bbox.y);\n ctx.scale(bbox.width, bbox.height);\n\n const gradient = ctx.createRadialGradient(fxF, fyF, 0, cxF, cyF, rF);\n addGradientStops(gradient, def);\n ctx.fillStyle = gradient;\n\n // The path is in original (absolute) coordinates. Inverse-transform it\n // into the unit-square space so the fill aligns with the shape.\n // inverse of translate(bx,by) · scale(bw,bh) = scale(1/bw,1/bh) · translate(-bx,-by)\n const unitPath = new Path2D();\n const invTransform: DOMMatrix2DInit = {\n a: 1 / bbox.width,\n b: 0,\n c: 0,\n d: 1 / bbox.height,\n e: -bbox.x / bbox.width,\n f: -bbox.y / bbox.height,\n };\n unitPath.addPath(path, invTransform);\n\n ctx.fill(unitPath, fillRule);\n ctx.restore();\n return true;\n }\n\n return false;\n}\n\n/**\n * Stroke `path` with a gradient defined by `def` in the coordinate space of `bbox`.\n */\nexport function strokeWithSvgGradient(\n ctx: SKRSContext2D,\n def: SvgChild,\n bbox: BBox,\n path: Path2D,\n viewport: Viewport,\n): boolean {\n const props = def.props;\n\n if (def.type === \"linearGradient\") {\n ctx.strokeStyle = isUserSpaceOnUse(props)\n ? createLinearGradientUserSpace(ctx, props, viewport, def)\n : createLinearGradientFromBBox(ctx, props, bbox, def);\n ctx.stroke(path);\n return true;\n }\n\n if (def.type === \"radialGradient\" && isUserSpaceOnUse(props)) {\n ctx.strokeStyle = createRadialGradientUserSpace(ctx, props, viewport, def);\n ctx.stroke(path);\n return true;\n }\n\n if (def.type === \"radialGradient\") {\n // For stroke, use a simple circular approximation (geometric mean radius)\n const cxAbs = bbox.x + parseFrac(props.cx, 0.5) * bbox.width;\n const cyAbs = bbox.y + parseFrac(props.cy, 0.5) * bbox.height;\n const rAbs = parseFrac(props.r, 0.5) * Math.sqrt(bbox.width * bbox.height);\n const fxAbs = bbox.x + parseFrac(props.fx, 0.5) * bbox.width;\n const fyAbs = bbox.y + parseFrac(props.fy, 0.5) * bbox.height;\n const gradient = ctx.createRadialGradient(\n fxAbs,\n fyAbs,\n 0,\n cxAbs,\n cyAbs,\n rAbs,\n );\n addGradientStops(gradient, def);\n ctx.strokeStyle = gradient;\n ctx.stroke(path);\n return true;\n }\n\n return false;\n}\n","import type { Path2D, SKRSContext2D } from \"@effing/skia\";\n\nimport type { BBox, InheritedSvgStyle, SvgDefs } from \"./types.ts\";\nimport { resolveCurrentColor } from \"./style.ts\";\nimport { parseUrlRef } from \"./style.ts\";\nimport {\n applyOpacity,\n fillWithSvgGradient,\n strokeWithSvgGradient,\n} from \"./gradients.ts\";\n\nexport function applyFillAndStroke(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n path: Path2D,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n bbox: BBox,\n): void {\n // Use element's own fill if set, otherwise inherit from parent\n const fill =\n resolveCurrentColor(props.fill as string | undefined, color) ??\n inherited.fill;\n const fillRule = (props.fillRule ?? props[\"fill-rule\"]) as\n CanvasFillRule | undefined;\n const fillOpacity = Number(props.fillOpacity ?? props[\"fill-opacity\"] ?? 1);\n\n // Resolve url(#id) gradient reference\n const fillRef = parseUrlRef(fill);\n if (fillRef) {\n const gradientDef = defs.gradients.get(fillRef);\n if (gradientDef) {\n if (fillOpacity < 1) {\n ctx.save();\n ctx.globalAlpha *= fillOpacity;\n fillWithSvgGradient(\n ctx,\n gradientDef,\n bbox,\n path,\n fillRule ?? \"nonzero\",\n defs.viewport,\n );\n ctx.restore();\n } else {\n fillWithSvgGradient(\n ctx,\n gradientDef,\n bbox,\n path,\n fillRule ?? \"nonzero\",\n defs.viewport,\n );\n }\n }\n } else if (fill !== \"none\") {\n ctx.fillStyle = applyOpacity(fill, fillOpacity);\n ctx.fill(path, fillRule ?? \"nonzero\");\n }\n\n applyStroke(ctx, props, path, inherited, color, defs, bbox);\n}\n\nexport function applyStroke(\n ctx: SKRSContext2D,\n props: Record<string, unknown>,\n path: Path2D,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs,\n bbox: BBox,\n): void {\n const stroke =\n resolveCurrentColor(props.stroke as string | undefined, color) ??\n inherited.stroke;\n if (!stroke || stroke === \"none\") return;\n\n const strokeOpacity = Number(\n props.strokeOpacity ??\n props[\"stroke-opacity\"] ??\n inherited.strokeOpacity ??\n 1,\n );\n\n ctx.lineWidth = Number(\n props.strokeWidth ?? props[\"stroke-width\"] ?? inherited.strokeWidth ?? 1,\n );\n ctx.lineCap = (((props.strokeLinecap ??\n props[\"stroke-linecap\"]) as CanvasLineCap) ??\n inherited.strokeLinecap ??\n \"butt\") as CanvasLineCap;\n ctx.lineJoin = (((props.strokeLinejoin ??\n props[\"stroke-linejoin\"]) as CanvasLineJoin) ??\n inherited.strokeLinejoin ??\n \"miter\") as CanvasLineJoin;\n\n // Resolve url(#id) gradient reference for stroke\n const strokeRef = parseUrlRef(stroke);\n if (strokeRef) {\n const gradientDef = defs.gradients.get(strokeRef);\n if (gradientDef) {\n if (strokeOpacity < 1) {\n ctx.save();\n ctx.globalAlpha *= strokeOpacity;\n strokeWithSvgGradient(ctx, gradientDef, bbox, path, defs.viewport);\n ctx.restore();\n } else {\n strokeWithSvgGradient(ctx, gradientDef, bbox, path, defs.viewport);\n }\n return;\n }\n }\n\n ctx.strokeStyle = applyOpacity(stroke, strokeOpacity);\n ctx.stroke(path);\n}\n","import type { Canvas, SKRSContext2D } from \"@effing/skia\";\n\nimport type { InheritedSvgStyle, SvgChild, SvgDefs } from \"./types.ts\";\nimport { EMPTY_DEFS } from \"./defs.ts\";\nimport { normalizeChildren } from \"./tree.ts\";\nimport {\n mergeStyleIntoProps,\n parseUrlRef,\n resolveInheritedStyle,\n} from \"./style.ts\";\nimport { applyTransformAndOpacity } from \"./transform.ts\";\nimport { buildClipPath } from \"./path.ts\";\nimport { applyFilter } from \"./filters.ts\";\nimport { acquireOffscreen, releaseOffscreen } from \"../offscreen.ts\";\nimport {\n drawPath,\n drawCircle,\n drawSvgRect,\n drawLine,\n drawEllipse,\n drawPolygon,\n drawPolyline,\n} from \"./shapes.ts\";\n\nexport function drawSvgChild(\n ctx: SKRSContext2D,\n child: SvgChild,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs = EMPTY_DEFS,\n vbW = 0,\n vbH = 0,\n): void {\n const { type } = child;\n const props = mergeStyleIntoProps(child.props);\n\n // Skip non-drawable definition elements\n if (\n type === \"defs\" ||\n type === \"clipPath\" ||\n type === \"mask\" ||\n type === \"filter\"\n )\n return;\n\n // Apply transform and opacity on shape elements (drawGroup handles its own)\n const transform =\n type !== \"g\" ? (props.transform as string | undefined) : undefined;\n const opacity = type !== \"g\" ? Number(props.opacity ?? 1) : 1;\n const savedTransform = applyTransformAndOpacity(ctx, transform, opacity);\n\n // Check for clip-path=\"url(#id)\" reference\n const clipRef = parseUrlRef(props.clipPath ?? props[\"clip-path\"]);\n const clipShapes = clipRef ? defs.clips.get(clipRef) : undefined;\n const clipPath = clipShapes ? buildClipPath(clipShapes, vbW, vbH) : undefined;\n\n // Check for mask=\"url(#id)\" reference\n const maskRef = parseUrlRef(props.mask as string | undefined);\n const maskShapes = maskRef ? defs.masks.get(maskRef) : undefined;\n\n // Check for filter=\"url(#id)\" reference\n const filterRef = parseUrlRef(props.filter as string | undefined);\n const filterDef = filterRef ? defs.filters.get(filterRef) : undefined;\n\n if (clipPath) {\n ctx.save();\n ctx.clip(clipPath);\n }\n\n // When a mask or filter is present, render the element to an offscreen\n // canvas so we can post-process it before drawing to the main context.\n const needsOffscreen = maskShapes || filterDef;\n let elemCanvas: Canvas | undefined;\n let targetCtx: SKRSContext2D;\n if (needsOffscreen) {\n const [c, cCtx] = acquireOffscreen(Math.ceil(vbW), Math.ceil(vbH));\n elemCanvas = c;\n targetCtx = cCtx;\n } else {\n targetCtx = ctx;\n }\n\n switch (type) {\n case \"path\":\n drawPath(targetCtx, props, inherited, color, defs);\n break;\n case \"circle\":\n drawCircle(targetCtx, props, inherited, color, defs, vbW, vbH);\n break;\n case \"rect\":\n drawSvgRect(targetCtx, props, inherited, color, defs, vbW, vbH);\n break;\n case \"line\":\n drawLine(targetCtx, props, inherited, color, defs, vbW, vbH);\n break;\n case \"ellipse\":\n drawEllipse(targetCtx, props, inherited, color, defs, vbW, vbH);\n break;\n case \"polygon\":\n drawPolygon(targetCtx, props, inherited, color, defs);\n break;\n case \"polyline\":\n drawPolyline(targetCtx, props, inherited, color, defs);\n break;\n case \"g\":\n drawGroup(targetCtx, child, props, inherited, color, defs, vbW, vbH);\n break;\n }\n\n if (needsOffscreen && elemCanvas) {\n applyOffscreenEffects(\n ctx,\n elemCanvas,\n targetCtx,\n maskShapes,\n filterDef,\n color,\n defs,\n vbW,\n vbH,\n );\n }\n\n if (clipPath) ctx.restore();\n if (savedTransform) ctx.restore();\n}\n\nfunction drawGroup(\n ctx: SKRSContext2D,\n node: SvgChild,\n mergedProps: Record<string, unknown>,\n inherited: InheritedSvgStyle,\n color: string,\n defs: SvgDefs = EMPTY_DEFS,\n vbW = 0,\n vbH = 0,\n): void {\n const children = normalizeChildren(node);\n if (children.length === 0) return;\n const groupInherited = resolveInheritedStyle(mergedProps, color, inherited);\n\n const opacity = Number(mergedProps.opacity ?? 1);\n const transform = mergedProps.transform as string | undefined;\n const saved = applyTransformAndOpacity(ctx, transform, opacity);\n\n for (const child of children) {\n if (child != null && typeof child === \"object\") {\n drawSvgChild(ctx, child, groupInherited, color, defs, vbW, vbH);\n }\n }\n\n if (saved) ctx.restore();\n}\n\n/** Composite mask and/or filter effects from offscreen canvas onto main context. */\nfunction applyOffscreenEffects(\n ctx: SKRSContext2D,\n elemCanvas: Canvas,\n targetCtx: SKRSContext2D,\n maskShapes: SvgChild[] | undefined,\n filterDef: SvgChild | undefined,\n color: string,\n defs: SvgDefs,\n vbW: number,\n vbH: number,\n): void {\n // Apply mask if present\n if (maskShapes) {\n const [maskCanvas, maskCtx] = acquireOffscreen(\n Math.ceil(vbW),\n Math.ceil(vbH),\n );\n for (const shape of maskShapes) {\n drawSvgChild(maskCtx, shape, { fill: \"white\" }, \"white\", defs, vbW, vbH);\n }\n targetCtx.globalCompositeOperation = \"destination-in\";\n targetCtx.drawImage(maskCanvas, 0, 0);\n targetCtx.globalCompositeOperation = \"source-over\";\n releaseOffscreen(maskCanvas);\n }\n\n // Apply filter if present\n if (filterDef) {\n const filteredCanvas = applyFilter(\n filterDef,\n elemCanvas,\n Math.ceil(vbW),\n Math.ceil(vbH),\n );\n ctx.drawImage(filteredCanvas, 0, 0);\n // Release intermediates (filteredCanvas may be elemCanvas if no-op)\n if (filteredCanvas !== elemCanvas) releaseOffscreen(filteredCanvas);\n } else {\n ctx.drawImage(elemCanvas, 0, 0);\n }\n releaseOffscreen(elemCanvas);\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\n\nimport type { LayoutNode } from \"../../layout.ts\";\nimport type { SvgChild } from \"./types.ts\";\nimport { mergeStyleIntoProps, resolveInheritedStyle } from \"./style.ts\";\nimport { collectDefs } from \"./defs.ts\";\nimport { drawSvgChild } from \"./traverse.ts\";\n\n/**\n * Draw an `<svg>` container and its SVG children (path, circle, rect, etc.).\n *\n * Parses the `viewBox` prop to compute scale factors, then recurses into\n * the React children stored in `node.props.children`.\n */\nexport function drawSvgContainer(\n ctx: SKRSContext2D,\n node: LayoutNode,\n x: number,\n y: number,\n width: number,\n height: number,\n): void {\n ctx.save();\n ctx.translate(x, y);\n\n // Parse viewBox for coordinate mapping; default to rendered size when absent\n const viewBox = node.props.viewBox as string | undefined;\n let vbW = width;\n let vbH = height;\n if (viewBox) {\n const parts = viewBox.split(/[\\s,]+/).map(Number);\n if (parts.length === 4) {\n const [vbX, vbY, parsedW, parsedH] = parts as [\n number,\n number,\n number,\n number,\n ];\n vbW = parsedW;\n vbH = parsedH;\n const scaleX = width / vbW;\n const scaleY = height / vbH;\n ctx.scale(scaleX, scaleY);\n ctx.translate(-vbX, -vbY);\n }\n }\n\n // Resolve the CSS `color` property for `currentColor` references\n const color = (node.style.color as string | undefined) ?? \"black\";\n\n // Build inherited SVG style from the <svg> element\n const merged = mergeStyleIntoProps(node.props);\n const inherited = resolveInheritedStyle(merged, color);\n\n // Traverse React children\n const children = node.props.children;\n if (children != null) {\n // Deep-flatten so helpers returning arrays don't slip nested arrays through\n // to the defs collector or shape switch (both expect element-shaped nodes).\n const childArray = (\n Array.isArray(children) ? children.flat(Infinity) : [children]\n ) as unknown[];\n const svgChildren = childArray.filter(\n (c): c is SvgChild =>\n c != null && typeof c === \"object\" && !Array.isArray(c),\n );\n\n // First pass: collect definitions from <defs>\n const defs = collectDefs(svgChildren, vbW, vbH);\n\n // Second pass: draw children\n for (const child of svgChildren) {\n drawSvgChild(ctx, child, inherited, color, defs, vbW, vbH);\n }\n }\n\n ctx.restore();\n}\n","import { loadImage } from \"@effing/skia\";\nimport type { SKRSContext2D, Image } from \"@effing/skia\";\nimport { fillParagraph, strokeParagraph } from \"@effing/skia/extensions\";\n\nimport parseCssColor from \"parse-css-color\";\n\nimport type { EmojiStyle } from \"../emoji.ts\";\nimport { emojiUrl, loadEmoji } from \"../emoji.ts\";\nimport type {\n PlacedEmoji,\n TextLayoutResult,\n TextSegment,\n} from \"../text/index.ts\";\nimport { setFont } from \"../text/measure.ts\";\n\nconst emojiImageCache = new Map<string, Promise<Image | null>>();\n\nfunction loadEmojiImage(\n style: EmojiStyle,\n emoji: string,\n): Promise<Image | null> {\n const key = emojiUrl(style, emoji);\n let cached = emojiImageCache.get(key);\n if (!cached) {\n cached = loadEmoji(style, emoji)\n .then((svgText) => {\n if (!svgText || !svgText.includes(\"<svg\")) return null;\n const dataUri =\n \"data:image/svg+xml;base64,\" +\n Buffer.from(svgText).toString(\"base64\");\n return loadImage(dataUri);\n })\n .catch(() => null);\n emojiImageCache.set(key, cached);\n }\n return cached;\n}\n\n/**\n * Draw laid-out text onto the canvas context: the paragraph, unhinted and\n * unsnapped, with its shadow, stroke and decorations, and the emoji drawn as\n * images in the inline boxes it left them.\n *\n * @param ctx - Canvas 2D rendering context\n * @param layout - The text as laid out by `layoutText`\n * @param offsetX - X offset for the text block\n * @param offsetY - Y offset for the text block\n * @param textShadow - Optional text-shadow CSS value\n * @param emojiStyle - The emoji style the text was laid out for, if any\n */\nexport async function drawText(\n ctx: SKRSContext2D,\n layout: TextLayoutResult,\n offsetX: number,\n offsetY: number,\n textShadow?: string,\n emojiStyle?: EmojiStyle,\n): Promise<void> {\n const { paragraph, segments, emoji } = layout;\n const first = segments[0];\n if (!first) return;\n const x = offsetX;\n const y = offsetY + layout.paragraphOffsetY;\n const shadow = textShadow ? parseShadow(textShadow) : null;\n ctx.fillStyle = first.color;\n\n // Each pass is a single native call for the whole paragraph.\n if (shadow) {\n drawShadowPass(ctx, shadow, getColorAlpha(first.color), () =>\n fillParagraph(ctx, paragraph, x, y),\n );\n }\n if (first.textStrokeWidth !== undefined && first.textStrokeWidth > 0) {\n ctx.save();\n ctx.lineWidth = first.textStrokeWidth;\n ctx.strokeStyle = first.textStrokeColor ?? first.color;\n ctx.lineJoin = \"round\";\n strokeParagraph(ctx, paragraph, x, y);\n ctx.restore();\n }\n fillParagraph(ctx, paragraph, x, y);\n\n if (emojiStyle && emoji.length > 0) {\n await drawEmoji(ctx, emoji, first, offsetX, offsetY, emojiStyle);\n }\n\n for (const seg of segments) {\n if (seg.textDecoration) {\n drawTextDecoration(ctx, seg, offsetX, offsetY);\n }\n }\n}\n\nasync function drawEmoji(\n ctx: SKRSContext2D,\n emoji: PlacedEmoji[],\n font: TextSegment,\n offsetX: number,\n offsetY: number,\n emojiStyle: EmojiStyle,\n): Promise<void> {\n const images = await Promise.all(\n emoji.map((e) => loadEmojiImage(emojiStyle, e.grapheme)),\n );\n emoji.forEach((e, i) => {\n const img = images[i];\n if (img) {\n ctx.drawImage(img, offsetX + e.x, offsetY + e.y, e.size, e.size);\n return;\n }\n // Emoji image unavailable: draw it as text, in its box on the baseline.\n setFont(\n ctx,\n font.fontSize,\n font.fontFamily,\n font.fontWeight,\n font.fontStyle,\n );\n const textRendering = ctx.textRendering;\n ctx.textRendering = \"geometricPrecision\";\n ctx.fillText(e.grapheme, offsetX + e.x, offsetY + e.baseline);\n ctx.textRendering = textRendering;\n });\n}\n\ninterface ParsedShadow {\n offsetX: number;\n offsetY: number;\n blur: number;\n color: string;\n}\n\nfunction parseShadow(shadow: string): ParsedShadow | null {\n const parts = shadow.match(\n /(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(.*)/,\n );\n if (!parts) return null;\n return {\n offsetX: parseFloat(parts[1]!),\n offsetY: parseFloat(parts[2]!),\n blur: parseFloat(parts[3]!),\n color: parts[4]!.trim(),\n };\n}\n\n/** Extract the alpha component from a CSS color string. */\nfunction getColorAlpha(color: string): number {\n const parsed = parseCssColor(color);\n return parsed ? parsed.alpha : 1;\n}\n\n/**\n * Draw the text shadow manually instead of using the canvas shadow API.\n *\n * CSS text-shadow renders the shadow as if derived from the text's painted\n * appearance, so when the text color has alpha < 1 the shadow is also\n * attenuated. The canvas shadow API does NOT do this — it always renders\n * the shadow at the full specified opacity. We match CSS behavior by\n * drawing the shadow as a separate fillText at the offset, with\n * globalAlpha scaled by the text color's alpha.\n */\nfunction drawShadowPass(\n ctx: SKRSContext2D,\n shadow: ParsedShadow,\n textAlpha: number,\n drawFn: () => void,\n): void {\n ctx.save();\n ctx.fillStyle = shadow.color;\n if (textAlpha < 1) ctx.globalAlpha *= textAlpha;\n if (shadow.blur > 0) ctx.filter = `blur(${shadow.blur / 2}px)`;\n ctx.translate(shadow.offsetX, shadow.offsetY);\n drawFn();\n ctx.restore();\n}\n\nfunction drawTextDecoration(\n ctx: SKRSContext2D,\n seg: TextSegment,\n offsetX: number,\n offsetY: number,\n): void {\n const decoration = seg.textDecoration;\n if (!decoration || decoration === \"none\") return;\n\n ctx.strokeStyle = seg.color;\n ctx.lineWidth = Math.max(1, seg.fontSize * 0.1);\n\n const x = offsetX + seg.x;\n const baseY = offsetY + seg.y;\n\n if (decoration.includes(\"underline\")) {\n const y = baseY + seg.ascent * 0.1;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + seg.width, y);\n ctx.stroke();\n }\n\n if (decoration.includes(\"line-through\")) {\n const y = baseY - seg.fontSize * 0.3;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + seg.width, y);\n ctx.stroke();\n }\n\n if (decoration.includes(\"overline\")) {\n const y = baseY - seg.fontSize * 0.85;\n ctx.beginPath();\n ctx.moveTo(x, y);\n ctx.lineTo(x + seg.width, y);\n ctx.stroke();\n }\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport { UNASSIGNED_PICTOGRAPHIC } from \"./language.ts\";\n\n/**\n * Emoji style options for rendering\n */\nexport type EmojiStyle =\n \"twemoji\" | \"openmoji\" | \"blobmoji\" | \"noto\" | \"fluent\" | \"fluentFlat\";\n\nconst FE0F = 0xfe0f;\nconst ZWJ = 0x200d;\nconst KEYCAP = 0x20e3;\n\nconst EMOJI_CHAR = /[\\p{Emoji}\\p{Extended_Pictographic}]/u;\n// Presented as an emoji without U+FE0F: by default, or (unassigned in this\n// runtime's Unicode) as every emoji added since Unicode 9 is.\nconst EMOJI_PRESENTATION = new RegExp(\n String.raw`\\p{Emoji_Presentation}|${UNASSIGNED_PICTOGRAPHIC}`,\n \"u\",\n);\nconst EMOJI_MODIFIER = /\\p{Emoji_Modifier}/u;\n\n/**\n * An emoji's code points in its fully-qualified form (UTS #51), which names\n * its image in every style: U+FE0F after each element that is text by default\n * (©️, the ♂️ in 🏃‍♂️, the 🏳️ in 🏳️‍🌈, the 1️ in 1️⃣), unless an emoji modifier\n * follows it (☝🏽).\n */\nfunction qualifiedCodePoints(emoji: string): number[] {\n const chars = [...emoji].filter((c) => c.codePointAt(0) !== FE0F);\n const codePoints: number[] = [];\n chars.forEach((char, i) => {\n codePoints.push(char.codePointAt(0)!);\n const startsElement = i === 0 || chars[i - 1] === \"\\u200D\";\n if (\n startsElement &&\n EMOJI_CHAR.test(char) &&\n !EMOJI_PRESENTATION.test(char) &&\n !EMOJI_MODIFIER.test(chars[i + 1] ?? \"\")\n ) {\n codePoints.push(FE0F);\n }\n });\n return codePoints;\n}\n\nfunction hex(codePoints: number[], pad = 0): string {\n return codePoints.map((cp) => cp.toString(16).padStart(pad, \"0\")).join(\"-\");\n}\n\n/**\n * Twemoji's file name: lowercase hex code points, with U+FE0F dropped unless\n * the emoji is a ZWJ sequence (its own `grabTheRightIcon` rule), and from\n * 👁️‍🗨️, the one ZWJ sequence it names without them.\n */\nfunction twemojiCode(codePoints: number[]): string {\n const code = hex(\n codePoints.includes(ZWJ)\n ? codePoints\n : codePoints.filter((cp) => cp !== FE0F),\n );\n return code === \"1f441-fe0f-200d-1f5e8-fe0f\" ? \"1f441-200d-1f5e8\" : code;\n}\n\n/**\n * Svgmoji's file name (OpenMoji, Blobmoji and Noto): Emojibase hexcodes,\n * uppercase and padded to four digits, with U+FE0F kept only in ZWJ and\n * keycap sequences.\n */\nfunction svgmojiCode(codePoints: number[]): string {\n const keepFE0F = codePoints.includes(ZWJ) || codePoints.includes(KEYCAP);\n return hex(\n keepFE0F ? codePoints : codePoints.filter((cp) => cp !== FE0F),\n 4,\n ).toUpperCase();\n}\n\n/**\n * Fluent's file name: the fully-qualified emoji itself. Its hex names are\n * inconsistent about U+FE0F (`1f590-fe0f`, but `2764-200d-1f525`), so they\n * miss emoji that the glyph names cover.\n */\nfunction fluentCode(codePoints: number[]): string {\n return encodeURIComponent(String.fromCodePoint(...codePoints));\n}\n\nconst emojiUrls: Record<EmojiStyle, (codePoints: number[]) => string> = {\n twemoji: (cps) =>\n `https://cdnjs.cloudflare.com/ajax/libs/twemoji/16.0.1/svg/${twemojiCode(cps)}.svg`,\n openmoji: (cps) =>\n `https://cdn.jsdelivr.net/npm/@svgmoji/openmoji@2.0.0/svg/${svgmojiCode(cps)}.svg`,\n blobmoji: (cps) =>\n `https://cdn.jsdelivr.net/npm/@svgmoji/blob@2.0.0/svg/${svgmojiCode(cps)}.svg`,\n noto: (cps) =>\n `https://cdn.jsdelivr.net/gh/svgmoji/svgmoji/packages/svgmoji__noto/svg/${svgmojiCode(cps)}.svg`,\n fluent: (cps) =>\n `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${fluentCode(cps)}_color.svg`,\n fluentFlat: (cps) =>\n `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${fluentCode(cps)}_flat.svg`,\n};\n\n/**\n * The URL of an emoji's SVG image in a style. The emoji may be fully,\n * minimally or not qualified (🏳️‍🌈, or the unqualified 🏳‍🌈): each style names its images\n * after the fully-qualified form, in its own way.\n *\n * @param style - The emoji style\n * @param emoji - One emoji grapheme cluster\n */\nexport function emojiUrl(style: EmojiStyle, emoji: string): string {\n return emojiUrls[style](qualifiedCodePoints(emoji));\n}\n\nconst emojiCache: Record<string, Promise<string>> = {};\n\n/**\n * Fetch an emoji's SVG image in a style, once per URL.\n *\n * @param style - The emoji style\n * @param emoji - One emoji grapheme cluster\n */\nexport async function loadEmoji(\n style: EmojiStyle,\n emoji: string,\n): Promise<string> {\n const url = emojiUrl(style, emoji);\n return (emojiCache[url] ??= fetch(url).then((r) => r.text()));\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\n\nimport type { EmojiStyle } from \"../emoji.ts\";\nimport { cachedLoadImage } from \"../../image.ts\";\nimport type { LayoutNode } from \"../layout.ts\";\nimport type { RenderContext } from \"../context.ts\";\nimport { layoutText } from \"../text/index.ts\";\nimport { applyClip, hasRadius, roundedRect } from \"./clip.ts\";\nimport { applyClipPath } from \"./clip-path.ts\";\nimport { createGradientFromCSS, splitGradientArgs } from \"./gradient.ts\";\nimport {\n beginElementGroup,\n drawBackdropFilter,\n endElementGroup,\n} from \"./group.ts\";\nimport { drawImage } from \"./image.ts\";\nimport { computeContain, computeCover } from \"./object-fit.ts\";\nimport { drawBoxShadow, drawRect, getBorderRadiusFromStyle } from \"./rect.ts\";\nimport { drawSvgContainer } from \"./svg/index.ts\";\nimport { drawText } from \"./text.ts\";\nimport { parseCSSLength, resolveBoxValue } from \"./utils.ts\";\n\n/**\n * Main draw dispatcher: recursively draws the layout tree onto the canvas.\n *\n * Every node, scaled or not, is drawn straight through its transform. Text is\n * drawn unhinted and unsnapped (see `drawText`), so it lands in the same place\n * at any scale and a scaled subtree needs no supersampled offscreen buffer.\n */\nexport async function drawNode(\n ctx: SKRSContext2D,\n node: LayoutNode,\n parentX: number,\n parentY: number,\n context?: RenderContext,\n emojiStyle?: EmojiStyle,\n): Promise<void> {\n const x = parentX + node.x;\n const y = parentY + node.y;\n const { style } = node;\n\n // Resolve a context once so the whole subtree shares one image cache.\n const renderContext: RenderContext = context ?? {\n imageCache: new Map(),\n debug: false,\n };\n\n if (style.display === \"none\") return;\n\n // A numeric string counts, as it does in CSS; anything that isn't a\n // number leaves the element opaque.\n const rawOpacity = Number(style.opacity ?? 1);\n const opacity = Number.isFinite(rawOpacity) ? rawOpacity : 1;\n if (opacity <= 0) return;\n\n // Painting awaits image loads, which can fail. The group and the save are\n // closed either way, so a caller that catches the error and draws the next\n // frame on this context doesn't paint into a layer left open.\n const group = { open: false };\n ctx.save();\n try {\n await paintNode(ctx, node, x, y, opacity, renderContext, emojiStyle, group);\n } finally {\n if (group.open) endElementGroup(ctx);\n ctx.restore();\n }\n}\n\n/** Paints a node inside the save that `drawNode` opened for it. */\nasync function paintNode(\n ctx: SKRSContext2D,\n node: LayoutNode,\n x: number,\n y: number,\n opacity: number,\n renderContext: RenderContext,\n emojiStyle: EmojiStyle | undefined,\n group: { open: boolean },\n): Promise<void> {\n const { width, height, style } = node;\n\n if (style.transform) {\n applyTransform(\n ctx,\n style.transform,\n x,\n y,\n width,\n height,\n style.transformOrigin,\n );\n }\n\n // Apply clip-path — in the element's own (transformed) coordinate space, and\n // before anything is painted, since it clips the element's entire rendering\n // including its box-shadow.\n if (style.clipPath) {\n applyClipPath(ctx, style.clipPath, style, x, y, width, height);\n }\n\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\n\n // Filter the backdrop behind the border box before anything of the element\n // itself is painted: its box-shadow must not end up in the backdrop, and its\n // background composites on top of the filtered result.\n if (style.backdropFilter) {\n drawBackdropFilter(\n ctx,\n style.backdropFilter,\n x,\n y,\n width,\n height,\n borderRadius,\n opacity,\n );\n }\n\n // The element's own painting and its descendants form one group, composited\n // with its opacity and filter. CSS applies clip-path after the filter, so the\n // clip above also clips the filtered result. The backdrop above stays outside\n // the group: a group's backdrop is read from the enclosing one.\n group.open = beginElementGroup(ctx, opacity, style.filter);\n\n // Draw box-shadow BEFORE overflow clip — CSS overflow:hidden clips children,\n // not the element's own box-shadow.\n if (style.boxShadow) {\n drawBoxShadow(ctx, x, y, width, height, style.boxShadow, borderRadius);\n }\n\n // Apply clipping for overflow: hidden\n const isClipped =\n style.overflow === \"hidden\" ||\n style.overflowX === \"hidden\" ||\n style.overflowY === \"hidden\";\n\n if (isClipped) {\n applyClip(ctx, x, y, width, height, borderRadius);\n }\n\n // Draw background and borders\n if (\n style.backgroundColor ||\n style.borderTopWidth ||\n style.borderRightWidth ||\n style.borderBottomWidth ||\n style.borderLeftWidth\n ) {\n drawRect(ctx, x, y, width, height, style);\n }\n\n // Draw background-image (gradient or url) — supports multiple comma-separated layers\n if (style.backgroundImage) {\n const layers = splitGradientArgs(style.backgroundImage);\n // CSS paints last layer first (bottommost)\n for (let i = layers.length - 1; i >= 0; i--) {\n const layer = layers[i]!.trim();\n const gradient = createGradientFromCSS(ctx, layer, x, y, width, height);\n if (gradient) {\n ctx.fillStyle = gradient;\n if (hasRadius(borderRadius)) {\n ctx.beginPath();\n roundedRect(\n ctx,\n x,\n y,\n width,\n height,\n borderRadius.topLeft,\n borderRadius.topRight,\n borderRadius.bottomRight,\n borderRadius.bottomLeft,\n );\n ctx.fill();\n } else {\n ctx.fillRect(x, y, width, height);\n }\n } else {\n // Try url(...) background image\n const urlMatch = layer.match(/url\\([\"']?(.*?)[\"']?\\)/);\n if (urlMatch) {\n if (hasRadius(borderRadius)) {\n applyClip(ctx, x, y, width, height, borderRadius);\n }\n\n const image = await cachedLoadImage(\n renderContext.imageCache,\n urlMatch[1]!,\n renderContext.userAgent,\n );\n const bgSize = style.backgroundSize;\n\n if (bgSize === \"cover\") {\n // Cover fills the box completely — no tiling needed\n const r = computeCover(\n image.width,\n image.height,\n x,\n y,\n width,\n height,\n );\n ctx.drawImage(\n image,\n r.sx,\n r.sy,\n r.sw,\n r.sh,\n r.dx,\n r.dy,\n r.dw,\n r.dh,\n );\n } else {\n // Compute tile dimensions based on backgroundSize\n let tileW: number, tileH: number;\n if (bgSize === \"contain\") {\n const r = computeContain(\n image.width,\n image.height,\n 0,\n 0,\n width,\n height,\n );\n tileW = r.dw;\n tileH = r.dh;\n } else if (bgSize === \"100% 100%\") {\n tileW = width;\n tileH = height;\n } else {\n // CSS default (auto): natural image size\n tileW = image.width;\n tileH = image.height;\n }\n const repeat = style.backgroundRepeat ?? \"repeat\";\n const stepX =\n repeat === \"repeat\" || repeat === \"repeat-x\" ? tileW : width;\n const stepY =\n repeat === \"repeat\" || repeat === \"repeat-y\" ? tileH : height;\n for (let ty = y; ty < y + height; ty += stepY) {\n for (let tx = x; tx < x + width; tx += stepX) {\n ctx.drawImage(image, tx, ty, tileW, tileH);\n }\n }\n }\n }\n }\n }\n }\n\n // Debug: draw bounding boxes\n if (renderContext.debug) {\n ctx.strokeStyle = \"rgba(255, 0, 0, 0.5)\";\n ctx.lineWidth = 1;\n ctx.strokeRect(x, y, width, height);\n }\n\n // Draw text content\n if (node.textContent !== undefined && node.textContent !== \"\") {\n const paddingTop = resolveBoxValue(style.paddingTop, width);\n const paddingLeft = resolveBoxValue(style.paddingLeft, width);\n const paddingRight = resolveBoxValue(style.paddingRight, width);\n\n const borderTopW = resolveBoxValue(style.borderTopWidth, width);\n const borderLeftW = resolveBoxValue(style.borderLeftWidth, width);\n const borderRightW = resolveBoxValue(style.borderRightWidth, width);\n\n const contentX = x + paddingLeft + borderLeftW;\n const contentY = y + paddingTop + borderTopW;\n const contentWidth =\n width - paddingLeft - paddingRight - borderLeftW - borderRightW;\n\n // Text nodes come laid out at their width from the layout phase.\n const textLayout =\n node.textLayout && contentWidth === node.width\n ? node.textLayout\n : layoutText(node.textContent, style, contentWidth, !!emojiStyle);\n await drawText(\n ctx,\n textLayout,\n contentX,\n contentY,\n style.textShadow,\n emojiStyle,\n );\n }\n\n // Draw <img> elements\n if (node.type === \"img\" && node.props.src) {\n const paddingTop = resolveBoxValue(style.paddingTop, width);\n const paddingLeft = resolveBoxValue(style.paddingLeft, width);\n const paddingRight = resolveBoxValue(style.paddingRight, width);\n const paddingBottom = resolveBoxValue(style.paddingBottom, width);\n\n const borderTopW = resolveBoxValue(style.borderTopWidth, width);\n const borderLeftW = resolveBoxValue(style.borderLeftWidth, width);\n const borderRightW = resolveBoxValue(style.borderRightWidth, width);\n const borderBottomW = resolveBoxValue(style.borderBottomWidth, width);\n\n const imgX = x + paddingLeft + borderLeftW;\n const imgY = y + paddingTop + borderTopW;\n const imgW =\n width - paddingLeft - paddingRight - borderLeftW - borderRightW;\n const imgH =\n height - paddingTop - paddingBottom - borderTopW - borderBottomW;\n\n // Images are replaced content — borderRadius clips them directly\n // (unlike child content which requires overflow:hidden)\n if (!isClipped) {\n if (hasRadius(borderRadius)) {\n applyClip(ctx, imgX, imgY, imgW, imgH, borderRadius);\n }\n }\n\n await drawImage(\n ctx,\n node.props.src as string | Buffer,\n imgX,\n imgY,\n imgW,\n imgH,\n renderContext,\n style,\n );\n }\n\n // Draw <svg> containers (handle their own child traversal in SVG coordinate space)\n if (node.type === \"svg\") {\n drawSvgContainer(ctx, node, x, y, width, height);\n } else {\n for (const child of node.children) {\n await drawNode(ctx, child, x, y, renderContext, emojiStyle);\n }\n }\n}\n\nfunction applyTransform(\n ctx: SKRSContext2D,\n transform: string,\n x: number,\n y: number,\n width: number,\n height: number,\n transformOrigin?: string,\n): void {\n // Resolve transform-origin (default: center)\n let ox = x + width / 2;\n let oy = y + height / 2;\n\n if (transformOrigin) {\n const parts = transformOrigin.split(/\\s+/);\n ox = resolveOrigin(parts[0], x, width);\n oy = resolveOrigin(parts[1], y, height);\n }\n\n ctx.translate(ox, oy);\n\n // Parse and apply transform functions\n const funcs = transform.matchAll(/(\\w+)\\(([^)]+)\\)/g);\n\n for (const [, name, args] of funcs) {\n const values = args!.split(\",\").map((s) => s.trim());\n\n switch (name) {\n case \"translate\":\n case \"translateX\":\n case \"translateY\": {\n const tx =\n name === \"translateY\" ? 0 : parseCSSLength(values[0]!, width);\n const ty =\n name === \"translateX\"\n ? 0\n : parseCSSLength(\n values[name === \"translate\" ? 1 : 0] ?? \"0\",\n height,\n );\n ctx.translate(tx, ty);\n break;\n }\n case \"scale\":\n case \"scaleX\":\n case \"scaleY\": {\n const sx = name === \"scaleY\" ? 1 : parseFloat(values[0]!);\n const sy =\n name === \"scaleX\"\n ? 1\n : parseFloat(values[name === \"scale\" ? 1 : 0] ?? String(sx));\n ctx.scale(sx, sy);\n break;\n }\n case \"rotate\": {\n const angle = parseAngle(values[0]!);\n ctx.rotate(angle);\n break;\n }\n case \"skewX\": {\n const angle = parseAngle(values[0]!);\n ctx.transform(1, 0, Math.tan(angle), 1, 0, 0);\n break;\n }\n case \"skewY\": {\n const angle = parseAngle(values[0]!);\n ctx.transform(1, Math.tan(angle), 0, 1, 0, 0);\n break;\n }\n }\n }\n\n ctx.translate(-ox, -oy);\n}\n\nfunction resolveOrigin(\n value: string | undefined,\n base: number,\n size: number,\n): number {\n if (!value) return base + size / 2;\n if (value === \"left\" || value === \"top\") return base;\n if (value === \"right\" || value === \"bottom\") return base + size;\n if (value === \"center\") return base + size / 2;\n return base + parseCSSLength(value, size);\n}\n\nfunction parseAngle(value: string): number {\n if (value.endsWith(\"deg\")) return (parseFloat(value) * Math.PI) / 180;\n if (value.endsWith(\"rad\")) return parseFloat(value);\n if (value.endsWith(\"turn\")) return parseFloat(value) * 2 * Math.PI;\n return parseFloat(value);\n}\n","import { GlobalFonts } from \"@effing/skia\";\n\nimport type { FontData } from \"../types.ts\";\n\nconst registeredFonts = new Set<string>();\n\n/**\n * Reset internal font state (test-only).\n */\nexport function _resetForTest(): void {\n registeredFonts.clear();\n}\n\n/**\n * Register a font from a FontData buffer.\n * Registration is idempotent — re-registering the same font name is a no-op.\n *\n * @param font - Font data to register\n */\nexport function registerFont(font: FontData): void {\n const key = `${font.name}:${font.weight}:${font.style}`;\n if (registeredFonts.has(key)) return;\n\n const buffer = Buffer.isBuffer(font.data)\n ? font.data\n : Buffer.from(font.data);\n\n GlobalFonts.register(buffer, font.name);\n\n registeredFonts.add(key);\n}\n\n/**\n * Register a font from a file path.\n *\n * @param path - Path to the font file\n * @param nameAlias - Optional font family name override\n */\nexport function registerFontFromPath(path: string, nameAlias?: string): void {\n GlobalFonts.registerFromPath(path, nameAlias ?? \"\");\n}\n\n/**\n * Get the list of registered font family names.\n *\n * @returns Array of font family names\n */\nexport function registeredFamilies(): string[] {\n return GlobalFonts.families.map((f: { family: string }) => f.family);\n}\n\n/**\n * Ensure all fonts from the given array are registered.\n * Called internally by `renderReactElement()`.\n */\nexport function ensureFontsRegistered(fonts: FontData[]): void {\n for (const font of fonts) {\n registerFont(font);\n }\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport { splitGradientArgs } from \"../draw/gradient.ts\";\nimport type { ExpandedStyle } from \"./compute.ts\";\n\ntype RawStyle = Record<string, unknown>;\n\nconst SIDES = [\"Top\", \"Right\", \"Bottom\", \"Left\"] as const;\n\n/**\n * Parse a CSS shorthand value like \"10px 20px\" into 1-4 parts.\n */\nfunction parseSides(value: string): string[] {\n const parts = value.toString().split(/\\s+/).filter(Boolean);\n switch (parts.length) {\n case 1:\n return [parts[0]!, parts[0]!, parts[0]!, parts[0]!];\n case 2:\n return [parts[0]!, parts[1]!, parts[0]!, parts[1]!];\n case 3:\n return [parts[0]!, parts[1]!, parts[2]!, parts[1]!];\n default:\n return [parts[0]!, parts[1]!, parts[2]!, parts[3]!];\n }\n}\n\nfunction parseValue(v: unknown): number | string | undefined {\n if (v === undefined || v === null) return undefined;\n const s = String(v);\n if (s === \"auto\") return \"auto\";\n const n = Number(s);\n if (s !== \"\" && !isNaN(n)) return n;\n return s;\n}\n\n/**\n * Expand CSS shorthand properties into their longhand equivalents.\n * Mutates and returns the style object.\n */\nexport function expandStyle(\n raw: RawStyle,\n fontFamilies?: string[],\n): ExpandedStyle {\n const style = { ...raw } as Record<string, unknown>;\n\n // margin shorthand\n if (style.margin !== undefined) {\n const sides = parseSides(String(style.margin));\n for (let i = 0; i < 4; i++) {\n const key = `margin${SIDES[i]}`;\n if (style[key] === undefined) style[key] = parseValue(sides[i]);\n }\n delete style.margin;\n }\n\n // padding shorthand\n if (style.padding !== undefined) {\n const sides = parseSides(String(style.padding));\n for (let i = 0; i < 4; i++) {\n const key = `padding${SIDES[i]}`;\n if (style[key] === undefined) style[key] = parseValue(sides[i]);\n }\n delete style.padding;\n }\n\n // borderRadius shorthand\n if (style.borderRadius !== undefined) {\n const sides = parseSides(String(style.borderRadius));\n const corners = [\n \"borderTopLeftRadius\",\n \"borderTopRightRadius\",\n \"borderBottomRightRadius\",\n \"borderBottomLeftRadius\",\n ];\n for (let i = 0; i < 4; i++) {\n if (style[corners[i]!] === undefined)\n style[corners[i]!] = parseValue(sides[i]);\n }\n delete style.borderRadius;\n }\n\n // borderWidth shorthand\n if (style.borderWidth !== undefined) {\n const sides = parseSides(String(style.borderWidth));\n for (let i = 0; i < 4; i++) {\n const key = `border${SIDES[i]}Width`;\n if (style[key] === undefined) style[key] = parseValue(sides[i]);\n }\n delete style.borderWidth;\n }\n\n // borderColor shorthand\n if (style.borderColor !== undefined) {\n const val = style.borderColor;\n for (const side of SIDES) {\n const key = `border${side}Color`;\n if (style[key] === undefined) style[key] = val;\n }\n delete style.borderColor;\n }\n\n // borderStyle shorthand\n if (style.borderStyle !== undefined) {\n const val = style.borderStyle;\n for (const side of SIDES) {\n const key = `border${side}Style`;\n if (style[key] === undefined) style[key] = val;\n }\n delete style.borderStyle;\n }\n\n // border shorthand (e.g. \"1px solid black\")\n if (style.border !== undefined) {\n const parts = String(style.border).split(/\\s+/);\n const width = parseValue(parts[0]);\n const borderStyle = parts[1] ?? \"solid\";\n const color = parts[2] ?? \"black\";\n for (const side of SIDES) {\n if (style[`border${side}Width`] === undefined)\n style[`border${side}Width`] = width;\n if (style[`border${side}Style`] === undefined)\n style[`border${side}Style`] = borderStyle;\n if (style[`border${side}Color`] === undefined)\n style[`border${side}Color`] = color;\n }\n delete style.border;\n }\n\n // Per-side border shorthands (e.g. borderLeft: \"3px solid white\")\n for (const side of SIDES) {\n const key = `border${side}`;\n if (style[key] !== undefined) {\n const parts = String(style[key]).split(/\\s+/);\n const width = parseValue(parts[0]);\n const borderStyle = parts[1] ?? \"solid\";\n const color = parts[2] ?? \"black\";\n if (style[`${key}Width`] === undefined) style[`${key}Width`] = width;\n if (style[`${key}Style`] === undefined)\n style[`${key}Style`] = borderStyle;\n if (style[`${key}Color`] === undefined) style[`${key}Color`] = color;\n delete style[key];\n }\n }\n\n // flex shorthand\n if (style.flex !== undefined) {\n const val = String(style.flex);\n if (val === \"none\") {\n if (style.flexGrow === undefined) style.flexGrow = 0;\n if (style.flexShrink === undefined) style.flexShrink = 0;\n if (style.flexBasis === undefined) style.flexBasis = \"auto\";\n } else {\n const parts = val.split(/\\s+/);\n if (parts.length === 1) {\n const n = parseFloat(parts[0]!);\n if (!isNaN(n)) {\n if (style.flexGrow === undefined) style.flexGrow = n;\n if (style.flexShrink === undefined) style.flexShrink = 1;\n if (style.flexBasis === undefined) style.flexBasis = 0;\n }\n } else if (parts.length === 2) {\n if (style.flexGrow === undefined)\n style.flexGrow = parseFloat(parts[0]!);\n if (style.flexShrink === undefined)\n style.flexShrink = parseFloat(parts[1]!);\n } else if (parts.length >= 3) {\n if (style.flexGrow === undefined)\n style.flexGrow = parseFloat(parts[0]!);\n if (style.flexShrink === undefined)\n style.flexShrink = parseFloat(parts[1]!);\n if (style.flexBasis === undefined)\n style.flexBasis = parseValue(parts[2]);\n }\n }\n delete style.flex;\n }\n\n // gap shorthand\n if (style.gap !== undefined) {\n const sides = parseSides(String(style.gap));\n if (style.rowGap === undefined) style.rowGap = parseValue(sides[0]);\n if (style.columnGap === undefined) style.columnGap = parseValue(sides[1]);\n delete style.gap;\n }\n\n // background shorthand\n if (style.background !== undefined) {\n const parts = parseBackgroundShorthand(String(style.background));\n if (parts.image !== undefined && style.backgroundImage === undefined)\n style.backgroundImage = parts.image;\n if (parts.repeat !== undefined && style.backgroundRepeat === undefined)\n style.backgroundRepeat = parts.repeat;\n if (parts.size !== undefined && style.backgroundSize === undefined)\n style.backgroundSize = parts.size;\n if (parts.color !== undefined && style.backgroundColor === undefined)\n style.backgroundColor = parts.color;\n delete style.background;\n }\n\n // overflow shorthand\n if (style.overflow !== undefined) {\n if (style.overflowX === undefined) style.overflowX = style.overflow;\n if (style.overflowY === undefined) style.overflowY = style.overflow;\n }\n\n // textBox shorthand (e.g. \"trim-both cap alphabetic\")\n if (style.textBox !== undefined) {\n const val = String(style.textBox);\n if (val === \"normal\" || val === \"none\") {\n style.textBoxTrim ??= \"none\";\n } else {\n const parts = val.split(/\\s+/);\n style.textBoxTrim ??= parts[0];\n if (parts.length > 1) {\n style.textBoxEdge ??= parts.slice(1).join(\" \");\n }\n }\n delete style.textBox;\n }\n\n // WebkitTextStroke shorthand (e.g. \"2px red\")\n if (style.WebkitTextStroke !== undefined) {\n const val = String(style.WebkitTextStroke).trim();\n const match = val.match(/^(\\S+)\\s+(.+)$/);\n if (match) {\n if (style.WebkitTextStrokeWidth === undefined)\n style.WebkitTextStrokeWidth = parseValue(match[1]);\n if (style.WebkitTextStrokeColor === undefined)\n style.WebkitTextStrokeColor = match[2];\n } else {\n // Single value — treat as width\n if (style.WebkitTextStrokeWidth === undefined)\n style.WebkitTextStrokeWidth = parseValue(val);\n }\n delete style.WebkitTextStroke;\n }\n\n // Vendor-prefixed aliases\n if (style.WebkitBackdropFilter !== undefined) {\n if (style.backdropFilter === undefined)\n style.backdropFilter = style.WebkitBackdropFilter;\n delete style.WebkitBackdropFilter;\n }\n // `word-wrap` is the legacy name of `overflow-wrap`.\n if (style.wordWrap !== undefined) {\n if (style.overflowWrap === undefined) style.overflowWrap = style.wordWrap;\n delete style.wordWrap;\n }\n if (style.WebkitClipPath !== undefined) {\n if (style.clipPath === undefined) style.clipPath = style.WebkitClipPath;\n delete style.WebkitClipPath;\n }\n\n // fontFamily normalization\n if (typeof style.fontFamily === \"string\") {\n const families = style.fontFamily\n .split(\",\")\n .map((s) => s.trim().replace(/^['\"]|['\"]$/g, \"\"))\n .filter(Boolean);\n if (fontFamilies) {\n const present = new Set(families);\n for (const name of fontFamilies) {\n if (!present.has(name)) families.push(name);\n }\n }\n style.fontFamily = families.join(\", \");\n }\n\n return style as unknown as ExpandedStyle;\n}\n\nconst BG_REPEAT_KEYWORDS = new Set([\n \"repeat\",\n \"no-repeat\",\n \"repeat-x\",\n \"repeat-y\",\n \"space\",\n \"round\",\n]);\nconst BG_POSITION_KEYWORDS = new Set([\n \"left\",\n \"right\",\n \"top\",\n \"bottom\",\n \"center\",\n]);\nconst BG_ATTACHMENT_KEYWORDS = new Set([\"scroll\", \"fixed\", \"local\"]);\nconst BG_BOX_KEYWORDS = new Set([\"border-box\", \"padding-box\", \"content-box\"]);\nconst BG_IMAGE_FN =\n /^(?:url|image-set|(?:repeating-)?(?:linear|radial|conic)-gradient)\\(/;\n\n// Whitespace-tokenize a CSS value, keeping balanced-paren blocks intact and\n// emitting `/` as its own token (the position/size separator).\nfunction tokenizeBackground(value: string): string[] {\n const tokens: string[] = [];\n let buf = \"\";\n for (let i = 0; i < value.length; i++) {\n const c = value[i]!;\n if (c === \"(\") {\n let depth = 1;\n buf += c;\n i++;\n while (i < value.length && depth > 0) {\n const ch = value[i]!;\n if (ch === \"(\") depth++;\n else if (ch === \")\") depth--;\n buf += ch;\n i++;\n }\n i--;\n } else if (/\\s/.test(c)) {\n if (buf) {\n tokens.push(buf);\n buf = \"\";\n }\n } else if (c === \"/\") {\n if (buf) {\n tokens.push(buf);\n buf = \"\";\n }\n tokens.push(\"/\");\n } else {\n buf += c;\n }\n }\n if (buf) tokens.push(buf);\n return tokens;\n}\n\ninterface BackgroundParts {\n image?: string;\n repeat?: string;\n size?: string;\n color?: string;\n}\n\nfunction parseLayer(value: string): BackgroundParts {\n const out: BackgroundParts = {};\n const sizeTokens: string[] = [];\n let afterSlash = false;\n for (const tok of tokenizeBackground(value)) {\n if (tok === \"/\") {\n afterSlash = true;\n continue;\n }\n if (afterSlash) {\n sizeTokens.push(tok);\n continue;\n }\n if (BG_IMAGE_FN.test(tok)) {\n out.image = tok;\n continue;\n }\n if (tok === \"none\") continue;\n if (BG_REPEAT_KEYWORDS.has(tok)) {\n out.repeat = tok;\n continue;\n }\n // Position/attachment/box/length tokens are recognized so they don't fall\n // through and get treated as colors; the renderer doesn't honor them yet.\n if (\n BG_POSITION_KEYWORDS.has(tok) ||\n BG_ATTACHMENT_KEYWORDS.has(tok) ||\n BG_BOX_KEYWORDS.has(tok) ||\n /^-?\\d/.test(tok)\n ) {\n continue;\n }\n out.color = tok;\n }\n if (sizeTokens.length > 0) out.size = sizeTokens.join(\" \");\n return out;\n}\n\n/**\n * Parse the CSS `background` shorthand into image/repeat/size/color longhands.\n * For multi-layer values, image is comma-joined and color is taken only from\n * the final layer (the only layer permitted a color per the CSS spec).\n */\nexport function parseBackgroundShorthand(value: string): BackgroundParts {\n const layers = splitGradientArgs(value).map((l) => l.trim());\n if (layers.length <= 1) return parseLayer(layers[0] ?? \"\");\n\n const parsed = layers.map(parseLayer);\n const out: BackgroundParts = {};\n const images = parsed.map((p) => p.image ?? \"none\");\n if (images.some((i) => i !== \"none\")) out.image = images.join(\", \");\n for (const p of parsed) {\n if (p.repeat !== undefined && out.repeat === undefined)\n out.repeat = p.repeat;\n if (p.size !== undefined && out.size === undefined) out.size = p.size;\n }\n const finalColor = parsed[parsed.length - 1]?.color;\n if (finalColor !== undefined) out.color = finalColor;\n return out;\n}\n","import Yoga, {\n Align,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n MeasureMode,\n Overflow,\n PositionType,\n Wrap,\n} from \"yoga-layout\";\nimport type { Node as YogaNode } from \"yoga-layout\";\n\nexport type { YogaNode };\n\nexport {\n Yoga,\n Align,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n MeasureMode,\n Overflow,\n PositionType,\n Wrap,\n};\n\nexport function createYogaNode(): YogaNode {\n return Yoga.Node.create();\n}\n\nlet textConfig: ReturnType<typeof Yoga.Config.create> | undefined;\n\n/**\n * A node for text, whose layout Yoga leaves unrounded (its parents are still\n * rounded to whole pixels). Its width is then the width the text was measured\n * at, which it's drawn at too, so a line that just fits stays on one line,\n * and a line that doesn't wraps, as in a browser.\n */\nexport function createTextYogaNode(): YogaNode {\n if (!textConfig) {\n textConfig = Yoga.Config.create();\n textConfig.setPointScaleFactor(0);\n }\n return Yoga.Node.create(textConfig);\n}\n\nexport function freeYogaNode(node: YogaNode): void {\n node.freeRecursive();\n}\n","import {\n Align,\n Display,\n Edge,\n FlexDirection,\n Gutter,\n Justify,\n Overflow,\n PositionType,\n Wrap,\n} from \"../yoga.ts\";\nimport type { YogaNode } from \"../yoga.ts\";\nimport type { ComputedStyle } from \"./compute.ts\";\n\n/**\n * Apply computed CSS styles to a Yoga node.\n */\nexport function applyStylesToYoga(node: YogaNode, style: ComputedStyle): void {\n // Display\n if (style.display === \"none\") {\n node.setDisplay(Display.None);\n } else {\n node.setDisplay(Display.Flex);\n }\n\n // Flex direction (CSS default is \"row\", Yoga defaults to \"column\")\n {\n const map: Record<string, FlexDirection> = {\n row: FlexDirection.Row,\n \"row-reverse\": FlexDirection.RowReverse,\n column: FlexDirection.Column,\n \"column-reverse\": FlexDirection.ColumnReverse,\n };\n node.setFlexDirection(\n map[style.flexDirection ?? \"row\"] ?? FlexDirection.Row,\n );\n }\n\n // Justify content\n if (style.justifyContent) {\n const map: Record<string, Justify> = {\n \"flex-start\": Justify.FlexStart,\n \"flex-end\": Justify.FlexEnd,\n center: Justify.Center,\n \"space-between\": Justify.SpaceBetween,\n \"space-around\": Justify.SpaceAround,\n \"space-evenly\": Justify.SpaceEvenly,\n };\n const jc = map[style.justifyContent];\n if (jc !== undefined) node.setJustifyContent(jc);\n }\n\n // Align items.\n // NOTE: `baseline` does NOT produce typographic baseline alignment. The\n // bundled yoga-layout JS binding exposes no baseline function, so Yoga falls\n // back to a node's height as its baseline — which aligns box bottoms (the\n // same result as `flex-end`), correct only when all children share a font\n // size. The README documents this limitation; don't re-advertise it as full\n // baseline support without a real fix, since the engine can't express it.\n if (style.alignItems) {\n const map: Record<string, Align> = {\n \"flex-start\": Align.FlexStart,\n \"flex-end\": Align.FlexEnd,\n center: Align.Center,\n stretch: Align.Stretch,\n baseline: Align.Baseline,\n };\n const ai = map[style.alignItems];\n if (ai !== undefined) node.setAlignItems(ai);\n }\n\n // Align self (`baseline` carries the same box-bottom caveat as alignItems)\n if (style.alignSelf) {\n const map: Record<string, Align> = {\n auto: Align.Auto,\n \"flex-start\": Align.FlexStart,\n \"flex-end\": Align.FlexEnd,\n center: Align.Center,\n stretch: Align.Stretch,\n baseline: Align.Baseline,\n };\n const as_ = map[style.alignSelf];\n if (as_ !== undefined) node.setAlignSelf(as_);\n }\n\n // Align content\n if (style.alignContent) {\n const map: Record<string, Align> = {\n \"flex-start\": Align.FlexStart,\n \"flex-end\": Align.FlexEnd,\n center: Align.Center,\n stretch: Align.Stretch,\n \"space-between\": Align.SpaceBetween,\n \"space-around\": Align.SpaceAround,\n };\n const ac = map[style.alignContent];\n if (ac !== undefined) node.setAlignContent(ac);\n }\n\n // Flex wrap\n if (style.flexWrap) {\n const map: Record<string, Wrap> = {\n nowrap: Wrap.NoWrap,\n wrap: Wrap.Wrap,\n \"wrap-reverse\": Wrap.WrapReverse,\n };\n const fw = map[style.flexWrap];\n if (fw !== undefined) node.setFlexWrap(fw);\n }\n\n // Flex grow / shrink / basis\n if (style.flexGrow !== undefined) node.setFlexGrow(style.flexGrow);\n // Satori defaults flexShrink to 0 (React Native convention); match it for compatibility\n node.setFlexShrink(style.flexShrink ?? 0);\n if (style.flexBasis !== undefined) {\n if (typeof style.flexBasis === \"number\") {\n node.setFlexBasis(style.flexBasis);\n } else if (String(style.flexBasis).endsWith(\"%\")) {\n node.setFlexBasis(String(style.flexBasis) as `${number}%`);\n } else if (style.flexBasis === \"auto\") {\n node.setFlexBasis(\"auto\");\n } else {\n const n = parseFloat(String(style.flexBasis));\n if (!isNaN(n)) node.setFlexBasis(n);\n }\n }\n\n // Dimensions\n applyDimension(node, \"setWidth\", style.width);\n applyDimension(node, \"setHeight\", style.height);\n applyDimension(node, \"setMinWidth\", style.minWidth);\n applyDimension(node, \"setMinHeight\", style.minHeight);\n applyDimension(node, \"setMaxWidth\", style.maxWidth);\n applyDimension(node, \"setMaxHeight\", style.maxHeight);\n\n // Position\n if (style.position === \"absolute\") {\n node.setPositionType(PositionType.Absolute);\n } else {\n node.setPositionType(PositionType.Relative);\n }\n\n // Position edges\n applyEdgeValue(node, \"setPosition\", Edge.Top, style.top);\n applyEdgeValue(node, \"setPosition\", Edge.Right, style.right);\n applyEdgeValue(node, \"setPosition\", Edge.Bottom, style.bottom);\n applyEdgeValue(node, \"setPosition\", Edge.Left, style.left);\n\n // Margin\n applyEdgeValue(node, \"setMargin\", Edge.Top, style.marginTop);\n applyEdgeValue(node, \"setMargin\", Edge.Right, style.marginRight);\n applyEdgeValue(node, \"setMargin\", Edge.Bottom, style.marginBottom);\n applyEdgeValue(node, \"setMargin\", Edge.Left, style.marginLeft);\n\n // Padding\n applyEdgeValue(node, \"setPadding\", Edge.Top, style.paddingTop);\n applyEdgeValue(node, \"setPadding\", Edge.Right, style.paddingRight);\n applyEdgeValue(node, \"setPadding\", Edge.Bottom, style.paddingBottom);\n applyEdgeValue(node, \"setPadding\", Edge.Left, style.paddingLeft);\n\n // Border width (resolved to numbers by resolveUnits before this point)\n if (style.borderTopWidth !== undefined)\n node.setBorder(Edge.Top, style.borderTopWidth as number);\n if (style.borderRightWidth !== undefined)\n node.setBorder(Edge.Right, style.borderRightWidth as number);\n if (style.borderBottomWidth !== undefined)\n node.setBorder(Edge.Bottom, style.borderBottomWidth as number);\n if (style.borderLeftWidth !== undefined)\n node.setBorder(Edge.Left, style.borderLeftWidth as number);\n\n // Gap\n if (style.rowGap !== undefined) node.setGap(Gutter.Row, style.rowGap);\n if (style.columnGap !== undefined)\n node.setGap(Gutter.Column, style.columnGap);\n\n // Overflow\n if (\n style.overflow === \"hidden\" ||\n style.overflowX === \"hidden\" ||\n style.overflowY === \"hidden\"\n ) {\n node.setOverflow(Overflow.Hidden);\n } else {\n node.setOverflow(Overflow.Visible);\n }\n}\n\nfunction applyDimension(\n node: YogaNode,\n setter:\n | \"setWidth\"\n | \"setHeight\"\n | \"setMinWidth\"\n | \"setMinHeight\"\n | \"setMaxWidth\"\n | \"setMaxHeight\",\n value: number | string | undefined,\n): void {\n if (value === undefined) return;\n if (value === \"auto\") {\n if (setter === \"setWidth\" || setter === \"setHeight\") {\n node[setter](\"auto\");\n }\n return;\n }\n if (typeof value === \"number\") {\n node[setter](value);\n return;\n }\n const s = String(value);\n if (s.endsWith(\"%\")) {\n node[setter](s as `${number}%`);\n } else {\n const n = parseFloat(s);\n if (!isNaN(n)) node[setter](n);\n }\n}\n\nfunction applyEdgeValue(\n node: YogaNode,\n setter: \"setMargin\" | \"setPadding\" | \"setPosition\",\n edge: Edge,\n value: number | string | undefined,\n): void {\n if (value === undefined) return;\n if (value === \"auto\" && setter === \"setMargin\") {\n node.setMargin(edge, \"auto\");\n return;\n }\n if (typeof value === \"number\") {\n node[setter](edge, value);\n return;\n }\n const s = String(value);\n if (s.endsWith(\"%\")) {\n node[setter](edge, s as `${number}%`);\n } else {\n const n = parseFloat(s);\n if (!isNaN(n)) node[setter](edge, n);\n }\n}\n","// This file contains code adapted from Satori (https://github.com/vercel/satori)\n// Licensed under the Mozilla Public License 2.0 (MPL-2.0)\n// See NOTICE.md in the package root for details.\n\nimport type { ReactElement, ReactNode } from \"react\";\n\nimport type { ImageCache } from \"../image.ts\";\nimport { cachedLoadImage } from \"../image.ts\";\nimport type { RenderContext } from \"./context.ts\";\nimport { expandStyle } from \"./style/expand.ts\";\nimport {\n resolveStyle,\n resolveUnit,\n resolveUnits,\n DEFAULT_STYLE,\n} from \"./style/compute.ts\";\nimport type { ComputedStyle } from \"./style/compute.ts\";\nimport { applyStylesToYoga } from \"./style/properties.ts\";\nimport { TextMeasure } from \"./text/index.ts\";\nimport { isWhiteSpaceOnly } from \"./text/white-space.ts\";\nimport type { TextLayoutResult } from \"./text/index.ts\";\nimport {\n createTextYogaNode,\n createYogaNode,\n freeYogaNode,\n FlexDirection,\n MeasureMode,\n} from \"./yoga.ts\";\nimport type { YogaNode } from \"./yoga.ts\";\n\n/**\n * A node in the computed layout tree, ready for drawing.\n */\nexport type LayoutNode = {\n type: string;\n style: ComputedStyle;\n children: LayoutNode[];\n textContent?: string;\n /** The text laid out at the node's width, for drawing. */\n textLayout?: TextLayoutResult;\n props: Record<string, unknown>;\n x: number;\n y: number;\n width: number;\n height: number;\n};\n\n/**\n * Build a layout tree from a React element tree.\n * Creates Yoga nodes, calculates layout, and returns the positioned tree.\n *\n * @param element - React element tree to lay out\n * @param containerWidth - Width of the container (from canvas)\n * @param containerHeight - Height of the container (from canvas)\n * @returns Root layout node with computed positions and dimensions\n */\nexport async function buildLayoutTree(\n element: ReactNode,\n containerWidth: number,\n containerHeight: number,\n emojiEnabled?: boolean,\n fontFamilies?: string[],\n context?: RenderContext,\n): Promise<{ tree: LayoutNode; imageCache: ImageCache }> {\n const renderContext: RenderContext = context ?? {\n imageCache: new Map(),\n debug: false,\n };\n const rootElement = renderComponents(element);\n const elementYogaNode = isText(rootElement)\n ? createTextYogaNode()\n : createYogaNode();\n\n // Set font families as default on root style so all nodes inherit them\n const rootStyle = fontFamilies?.length\n ? { ...DEFAULT_STYLE, fontFamily: fontFamilies.join(\", \") }\n : DEFAULT_STYLE;\n\n // Build the tree\n const elementNode = await buildNode(\n rootElement,\n rootStyle,\n elementYogaNode,\n containerWidth,\n containerHeight,\n emojiEnabled,\n fontFamilies,\n renderContext,\n );\n\n // Wrap the user element in a canvas-sized container (like Satori) so that\n // absolute positioning, percentage sizes, etc. resolve against the canvas.\n const rootYogaNode = createYogaNode();\n rootYogaNode.setWidth(containerWidth);\n rootYogaNode.setHeight(containerHeight);\n rootYogaNode.setFlexDirection(FlexDirection.Row);\n rootYogaNode.insertChild(elementYogaNode, 0);\n\n rootYogaNode.calculateLayout(containerWidth, containerHeight);\n settleText(\n elementNode,\n () => rootYogaNode.calculateLayout(containerWidth, containerHeight),\n renderContext.debug,\n );\n\n const elementLayout = extractLayout(elementNode, elementYogaNode);\n freeYogaNode(rootYogaNode);\n\n const tree: LayoutNode = {\n type: \"div\",\n style: rootStyle,\n children: [elementLayout],\n props: {},\n x: 0,\n y: 0,\n width: containerWidth,\n height: containerHeight,\n };\n return { tree, imageCache: renderContext.imageCache };\n}\n\n/**\n * Build the node for `element` on `yogaNode`. Function components must be\n * rendered first (`renderComponents`), so the caller can make text a text\n * node (`createTextYogaNode`).\n */\nasync function buildNode(\n element: ReactNode,\n parentStyle: ComputedStyle,\n yogaNode: YogaNode,\n viewportWidth: number,\n viewportHeight: number,\n emojiEnabled?: boolean,\n fontFamilies?: string[],\n context?: RenderContext,\n): Promise<IntermediateNode> {\n // Handle null/undefined/boolean\n if (\n element === null ||\n element === undefined ||\n typeof element === \"boolean\"\n ) {\n return {\n type: \"empty\",\n style: parentStyle,\n children: [],\n props: {},\n yogaNode,\n };\n }\n\n // Handle text/number primitives\n if (typeof element === \"string\" || typeof element === \"number\") {\n const text = String(element);\n const style = resolveStyle(undefined, parentStyle);\n\n // Set up text measurement\n const textMeasure = new TextMeasure(text, style, emojiEnabled);\n setTextMeasure(yogaNode, textMeasure);\n\n return {\n type: \"text\",\n style,\n children: [],\n textContent: text,\n textMeasure,\n props: {},\n yogaNode,\n };\n }\n\n // Handle React elements (host elements: components are rendered already)\n const el = element as ReactElement<Record<string, unknown>>;\n const type = el.type;\n\n const props = (el.props ?? {}) as Record<string, unknown>;\n const rawStyle = (props.style ?? {}) as Record<string, unknown>;\n const expanded = expandStyle(rawStyle, fontFamilies);\n const style = resolveStyle(expanded, parentStyle);\n resolveUnits(style, viewportWidth, viewportHeight);\n\n const tagName = String(type);\n\n // For <svg> elements, merge width/height props into style when not set via CSS\n if (tagName === \"svg\") {\n if (props.width != null && style.width === undefined) {\n const v = props.width;\n if (typeof v === \"string\") {\n const resolved = resolveUnit(v, viewportWidth, viewportHeight, 16, 16);\n style.width =\n typeof resolved === \"string\" && resolved.endsWith(\"%\")\n ? resolved\n : Number(resolved);\n } else {\n style.width = Number(v);\n }\n }\n if (props.height != null && style.height === undefined) {\n const v = props.height;\n if (typeof v === \"string\") {\n const resolved = resolveUnit(v, viewportWidth, viewportHeight, 16, 16);\n style.height =\n typeof resolved === \"string\" && resolved.endsWith(\"%\")\n ? resolved\n : Number(resolved);\n } else {\n style.height = Number(v);\n }\n }\n\n // Derive missing dimension from viewBox aspect ratio\n const viewBox = props.viewBox as string | undefined;\n if (viewBox) {\n const parts = viewBox.split(/[\\s,]+/).map(Number);\n if (parts.length === 4) {\n const [, , vbW, vbH] = parts as [number, number, number, number];\n if (vbW > 0 && vbH > 0) {\n const wSet = style.width !== undefined;\n const hSet = style.height !== undefined;\n if (!wSet && !hSet) {\n style.width = vbW;\n style.height = vbH;\n } else if (!hSet && typeof style.width === \"number\") {\n style.height = style.width * (vbH / vbW);\n } else if (!wSet && typeof style.height === \"number\") {\n style.width = style.height * (vbW / vbH);\n }\n // When either/both are %, leave as-is for Yoga\n }\n }\n }\n }\n\n // For <img> elements, derive missing dimensions from intrinsic aspect ratio\n if (tagName === \"img\") {\n // Map HTML width/height attributes to style (like <svg>)\n if (props.width != null && style.width === undefined) {\n const v = props.width;\n style.width = typeof v === \"string\" && v.endsWith(\"%\") ? v : Number(v);\n }\n if (props.height != null && style.height === undefined) {\n const v = props.height;\n style.height = typeof v === \"string\" && v.endsWith(\"%\") ? v : Number(v);\n }\n\n const src = props.src as string | Buffer | undefined;\n if (src) {\n try {\n const image = await cachedLoadImage(\n context?.imageCache ?? new Map(),\n src,\n context?.userAgent,\n );\n const naturalW = image.width;\n const naturalH = image.height;\n\n const wSet = style.width !== undefined;\n const hSet = style.height !== undefined;\n\n if (naturalW > 0 && naturalH > 0 && !(wSet && hSet)) {\n if (!wSet && !hSet) {\n // No dimensions given — fill parent, let aspect ratio derive height.\n style.width = \"100%\";\n }\n yogaNode.setAspectRatio(naturalW / naturalH);\n }\n } catch (err) {\n // Don't fail layout when the image is unreachable — render at whatever\n // size Yoga computes. Surface the error (only in debug) so misconfigured\n // URLs and UA-gated CDNs are diagnosable instead of silently dropping\n // pixels, without spamming logs on every frame of a normal render.\n if (context?.debug) {\n const id = Buffer.isBuffer(src) ? \"<Buffer>\" : src;\n console.warn(\n `[@effing/canvas] failed to load image for layout (${id}): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n }\n }\n }\n\n // Apply styles to Yoga node\n applyStylesToYoga(yogaNode, style);\n\n // SVG containers: children use SVG coordinate space, not flex layout.\n // Skip Yoga child nodes and keep React children in props for the SVG drawer.\n if (tagName === \"svg\") {\n const resolvedChildren = resolveSvgTree(props.children as ReactNode);\n return {\n type: tagName,\n style,\n children: [],\n props: { ...props, children: resolvedChildren },\n yogaNode,\n };\n }\n\n // The children as the DOM has them: components rendered, fragments and\n // arrays unwrapped, and adjacent text one run.\n const items = flattenChildren(props.children as ReactNode);\n\n // If this node has only text content, create a child text node.\n // Using a child node (instead of setMeasureFunc on this node directly)\n // ensures Yoga's baseline calculation accounts for this node's padding/border\n // when a parent uses alignItems: \"baseline\". Text of nothing but white space\n // is no flex item at all (see below), so the node has no line box.\n const onlyText = items.length === 1 && isText(items[0]) ? items[0] : null;\n if (onlyText !== null && !isWhiteSpaceOnly(String(onlyText))) {\n const textContent = String(onlyText);\n const childStyle = resolveStyle(undefined, style);\n const childYogaNode = createTextYogaNode();\n const textMeasure = new TextMeasure(textContent, childStyle, emojiEnabled);\n setTextMeasure(childYogaNode, textMeasure);\n const jc = style.justifyContent;\n if (!jc || jc === \"flex-start\") {\n childYogaNode.setFlexGrow(1);\n }\n childYogaNode.setFlexShrink(1);\n yogaNode.insertChild(childYogaNode, 0);\n\n // Match satori: text-only nodes default to flexShrink=1 so they shrink to\n // fit the available flex space. Without this, text containers overflow their\n // flex parent when siblings consume part of the main axis.\n if (style.flexShrink === undefined) {\n yogaNode.setFlexShrink(1);\n }\n\n return {\n type: tagName,\n style,\n children: [\n {\n type: \"text\",\n style: childStyle,\n children: [],\n textContent,\n textMeasure,\n props: {},\n yogaNode: childYogaNode,\n },\n ],\n props,\n yogaNode,\n };\n }\n\n // Process children. Each run of text between elements is a flex item of\n // its own (CSS Flexbox §4), its white space collapsed as its box's text\n // (see `layoutText`): the spaces at its start and end, after a <br> say,\n // are removed. A run of nothing but white space isn't rendered at all,\n // whatever its `white-space`.\n const children: IntermediateNode[] = [];\n for (const rendered of items) {\n if (typeof rendered === \"string\" && isWhiteSpaceOnly(rendered)) continue;\n const childYogaNode = isText(rendered)\n ? createTextYogaNode()\n : createYogaNode();\n yogaNode.insertChild(childYogaNode, children.length);\n children.push(\n await buildNode(\n rendered,\n style,\n childYogaNode,\n viewportWidth,\n viewportHeight,\n emojiEnabled,\n fontFamilies,\n context,\n ),\n );\n }\n\n return {\n type: tagName,\n style,\n children,\n props,\n yogaNode,\n };\n}\n\ntype IntermediateNode = {\n type: string;\n style: ComputedStyle;\n children: IntermediateNode[];\n textContent?: string;\n /** Set on text nodes, which Yoga measures. */\n textMeasure?: TextMeasure;\n props: Record<string, unknown>;\n yogaNode: YogaNode;\n};\n\n/**\n * How many times the layout is computed again for text that Yoga sized at\n * another width than it's drawn at (see `TextMeasure`). One normally settles\n * it; the bound is for layouts where a node's width depends on its height\n * (wrapping columns, aspect ratios), which could otherwise keep changing.\n */\nconst MAX_TEXT_RELAYOUTS = 2;\n\n/**\n * Lay every text node out at its final width, and compute the layout again\n * while Yoga sized one from a different height.\n */\nfunction settleText(\n root: IntermediateNode,\n relayout: () => void,\n debug: boolean,\n): void {\n const textNodes: IntermediateNode[] = [];\n const collect = (node: IntermediateNode) => {\n // Nothing under `display: none` is laid out or drawn.\n if (node.style.display === \"none\") return;\n if (node.textMeasure) textNodes.push(node);\n node.children.forEach(collect);\n };\n collect(root);\n // Text nodes have no padding or border: their width is the content's.\n const settle = (node: IntermediateNode, pin: boolean) =>\n node.textMeasure!.settle(node.yogaNode.getComputedWidth(), pin);\n\n for (let pass = 0; pass < MAX_TEXT_RELAYOUTS; pass++) {\n let unsettled = false;\n for (const node of textNodes) {\n if (settle(node, true)) {\n node.yogaNode.markDirty();\n unsettled = true;\n }\n }\n if (!unsettled) return;\n relayout();\n }\n if (!textNodes.some((node) => settle(node, false))) return;\n\n // Each pin moved the layout on to widths the drawn heights don't fit. Go\n // back to Yoga's own layout, as without the pins, and draw the text at the\n // widths it gives.\n for (const node of textNodes) {\n if (node.textMeasure!.unpin()) node.yogaNode.markDirty();\n }\n relayout();\n const unsettled = textNodes.filter((node) => settle(node, false)).length;\n if (debug && unsettled > 0) {\n console.warn(\n `[@effing/canvas] ${unsettled} text node(s) sized for other lines ` +\n `than drawn: the layout didn't settle in ${MAX_TEXT_RELAYOUTS} relayouts`,\n );\n }\n}\n\n/** Measure `yogaNode` with `textMeasure`. */\nfunction setTextMeasure(yogaNode: YogaNode, textMeasure: TextMeasure): void {\n yogaNode.setMeasureFunc((width, widthMode) =>\n textMeasure.measure(\n widthMode === MeasureMode.Undefined || Number.isNaN(width)\n ? Infinity\n : width,\n ),\n );\n}\n\nconst isText = (node: ReactNode): node is string | number =>\n typeof node === \"string\" || typeof node === \"number\";\n\n/** Render function components until something else is left. */\nfunction renderComponents(node: ReactNode): ReactNode {\n while (\n node !== null &&\n typeof node === \"object\" &&\n \"type\" in node &&\n typeof node.type === \"function\"\n ) {\n const el = node as ReactElement<Record<string, unknown>>;\n node = (el.type as (props: Record<string, unknown>) => ReactNode)(\n el.props ?? {},\n );\n }\n return node;\n}\n\n/**\n * The children as the DOM has them: function components rendered, fragments\n * and arrays unwrapped, null, undefined and booleans left out, and adjacent\n * text, as `Hello {name}` or a fragment of text gives, merged into one run.\n */\nfunction flattenChildren(\n node: ReactNode,\n items: ReactNode[] = [],\n): ReactNode[] {\n const rendered = renderComponents(node);\n if (\n rendered === null ||\n rendered === undefined ||\n typeof rendered === \"boolean\"\n ) {\n return items;\n }\n if (Array.isArray(rendered)) {\n for (const child of rendered as ReactNode[]) flattenChildren(child, items);\n return items;\n }\n const el = rendered as ReactElement<{ children?: ReactNode }>;\n if (typeof rendered === \"object\" && (el.type as unknown) === REACT_FRAGMENT) {\n return flattenChildren(el.props?.children, items);\n }\n const last = items[items.length - 1];\n if (isText(rendered) && items.length > 0 && isText(last)) {\n items[items.length - 1] = `${last}${rendered}`;\n } else {\n items.push(rendered);\n }\n return items;\n}\n\n/** Floor to a whole pixel, as Yoga does text (snapping values within 1e-4). */\nfunction floorToPixel(value: number): number {\n const rounded = Math.round(value);\n return Math.abs(value - rounded) < 1e-4 ? rounded : Math.floor(value);\n}\n\nfunction extractLayout(node: IntermediateNode, yogaNode: YogaNode): LayoutNode {\n const layout = yogaNode.getComputedLayout();\n // Yoga leaves text nodes unrounded (see `createTextYogaNode`) for their\n // width; they're placed on whole pixels, floored as Yoga rounds text.\n const place = node.textMeasure ? floorToPixel : (v: number) => v;\n\n return {\n type: node.type,\n style: node.style,\n children: node.children.map((child, i) => {\n const childYoga = yogaNode.getChild(i);\n return extractLayout(child, childYoga);\n }),\n textContent: node.textContent,\n textLayout: node.textMeasure?.layout,\n props: node.props,\n x: place(layout.left),\n y: place(layout.top),\n width: layout.width,\n height: layout.height,\n };\n}\n\n/**\n * React's `Fragment` type. A registered symbol shared by all React copies,\n * so we can detect fragments without a runtime dependency on `react`.\n */\nconst REACT_FRAGMENT = Symbol.for(\"react.fragment\");\n\n/**\n * Resolve function components, unwrap fragments, and flatten nested arrays\n * inside an `<svg>` subtree. The SVG drawer switches on primitive element\n * strings (path, rect, etc.) and does not flatten its own children, so\n * without this preprocessing (a) function components and fragments silently\n * disappear and (b) helpers returning arrays crash the defs collector.\n */\nfunction resolveSvgTree(node: ReactNode): ReactNode {\n if (node === null || node === undefined || typeof node === \"boolean\")\n return null;\n if (typeof node === \"string\" || typeof node === \"number\") return node;\n\n if (Array.isArray(node)) {\n const out: ReactNode[] = [];\n let changed = false;\n for (const child of node as ReactNode[]) {\n const resolved = resolveSvgTree(child);\n if (resolved === null || resolved === undefined) {\n changed = true;\n continue;\n }\n if (Array.isArray(resolved)) {\n changed = true;\n for (const r of resolved) out.push(r);\n } else {\n if (resolved !== child) changed = true;\n out.push(resolved);\n }\n }\n return changed ? out : node;\n }\n\n const el = node as ReactElement<Record<string, unknown>>;\n if (typeof el.type === \"function\") {\n const rendered = (el.type as (props: Record<string, unknown>) => ReactNode)(\n el.props ?? {},\n );\n return resolveSvgTree(rendered);\n }\n\n // Unwrap fragments: their children take the fragment's place in the parent\n // (callers flatten arrays), since the drawer only knows SVG element strings.\n if ((el.type as unknown) === REACT_FRAGMENT) {\n return resolveSvgTree((el.props ?? {}).children as ReactNode);\n }\n\n const elProps = (el.props ?? {}) as Record<string, unknown>;\n if (elProps.children !== undefined) {\n const resolvedChildren = resolveSvgTree(elProps.children as ReactNode);\n if (resolvedChildren !== elProps.children) {\n return { ...el, props: { ...elProps, children: resolvedChildren } };\n }\n }\n return el;\n}\n","import type { SKRSContext2D } from \"@effing/skia\";\nimport type { ReactNode } from \"react\";\n\nimport type { RenderReactElementOptions } from \"../types.ts\";\nimport { drawNode } from \"./draw/index.ts\";\nimport { ensureFontsRegistered } from \"./font.ts\";\nimport { buildLayoutTree } from \"./layout.ts\";\nimport { releaseParagraphs } from \"./text/native.ts\";\nimport type { RenderContext } from \"./context.ts\";\n\n/**\n * Render a React element tree to a canvas context.\n *\n * Width and height default to `ctx.canvas.width` / `ctx.canvas.height` but\n * can be overridden via `options.width` and `options.height`. This is useful\n * for HiDPI rendering where the canvas is larger than the logical layout size.\n *\n * @param ctx - Canvas 2D rendering context to draw into\n * @param element - React element tree to render\n * @param options - Rendering options (fonts, dimensions, debug mode)\n *\n * @example\n * ```tsx\n * import { createCanvas, renderReactElement } from \"@effing/canvas\";\n *\n * const canvas = createCanvas(1080, 1080);\n * const ctx = canvas.getContext(\"2d\");\n *\n * await renderReactElement(ctx, <MyComponent />, { fonts: [myFont] });\n *\n * const png = await canvas.encode(\"png\");\n * ```\n *\n * @example HiDPI rendering (2x)\n * ```tsx\n * const dpr = 2;\n * const canvas = createCanvas(1080 * dpr, 1080 * dpr);\n * const ctx = canvas.getContext(\"2d\");\n * ctx.scale(dpr, dpr);\n *\n * await renderReactElement(ctx, <MyComponent />, {\n * fonts: [myFont],\n * width: 1080,\n * height: 1080,\n * });\n * ```\n *\n * @example Custom User-Agent for remote image fetches\n * ```tsx\n * await renderReactElement(ctx, <MyComponent />, {\n * userAgent: \"my-renderer/1.0\",\n * });\n * ```\n *\n * @example Persistent image cache for repeated calls (e.g. per frame)\n * ```tsx\n * const imageCache: ImageCache = new Map();\n * for (let frame = 0; frame < frameCount; frame++) {\n * await renderReactElement(ctx, <Frame n={frame} />, { fonts, imageCache });\n * }\n * ```\n */\nexport async function renderReactElement(\n ctx: SKRSContext2D,\n element: ReactNode,\n options: RenderReactElementOptions = {},\n): Promise<void> {\n const fonts = options.fonts ?? [];\n\n // Register fonts\n ensureFontsRegistered(fonts);\n\n // Get dimensions (option overrides take precedence over canvas size)\n const width = options.width ?? ctx.canvas.width;\n const height = options.height ?? ctx.canvas.height;\n\n // Per-render context: shared image cache + cross-cutting fetch/diagnostic\n // config, threaded through both the layout and draw phases. The caller may\n // supply the cache to persist image loads across calls.\n const renderContext: RenderContext = {\n imageCache: options.imageCache ?? new Map(),\n userAgent: options.userAgent,\n debug: options.debug ?? false,\n };\n\n // Build layout tree (Yoga)\n const emojiStyle =\n options.emoji === \"none\" ? undefined : (options.emoji ?? \"twemoji\");\n const fontFamilies = [...new Set(fonts.map((f) => f.name))];\n const { tree: layoutTree } = await buildLayoutTree(\n element,\n width,\n height,\n !!emojiStyle,\n fontFamilies,\n renderContext,\n );\n\n // Draw to canvas\n await drawNode(ctx, layoutTree, 0, 0, renderContext, emojiStyle);\n\n // Text is laid out as native paragraphs, whose memory Node releases only on\n // a turn of the event loop: take one when a caller's loop hasn't.\n await releaseParagraphs();\n}\n","import type { FontData } from \"./types.ts\";\nimport type { ComputedStyle } from \"./jsx/style/compute.ts\";\nimport { registerFont } from \"./jsx/font.ts\";\nimport { layoutText } from \"./jsx/text/index.ts\";\n\n/**\n * Options for {@link findLargestUsableFontSize}.\n */\nexport type FindLargestUsableFontSizeOptions = {\n /** The text to fit */\n text: string;\n /** Font data to use for measurement */\n font: FontData;\n /** Maximum width in pixels */\n maxWidth: number;\n /** Maximum height in pixels */\n maxHeight: number;\n /** Line height — `\"normal\"` uses font metrics, numeric values are CSS multipliers */\n lineHeight?: number | \"normal\";\n /**\n * Whitespace handling, as in CSS (default: `\"normal\"`). Use `\"nowrap\"` to\n * fit the text on one line instead of wrapping to `maxWidth`, its newlines\n * collapsing to spaces, or `\"pre\"` to fit each newline-separated paragraph\n * on a line of its own.\n */\n whiteSpace?: ComputedStyle[\"whiteSpace\"];\n /** Minimum font size to consider (default: 1) */\n minFontSize?: number;\n /** Maximum font size to consider (default: 1000) */\n maxFontSize?: number;\n};\n\n/**\n * Find the largest integer font size that keeps text within the given bounds.\n *\n * Uses binary search over integer font sizes, measuring with {@link layoutText}\n * at each step. Returns `minFontSize` if even the smallest size overflows.\n *\n * By default text wraps to `maxWidth` and is fit into the `maxWidth` × `maxHeight`\n * box. Set `whiteSpace: \"nowrap\"` to fit the text on one line instead (or\n * `\"pre\"` for one line per newline-separated paragraph), in which case\n * `maxWidth` constrains the full line width.\n */\nexport function findLargestUsableFontSize(\n options: FindLargestUsableFontSizeOptions,\n): number {\n const {\n text,\n font,\n maxWidth,\n maxHeight,\n lineHeight = \"normal\",\n whiteSpace,\n minFontSize = 1,\n maxFontSize = 1000,\n } = options;\n\n registerFont(font);\n\n let lo = minFontSize;\n let hi = maxFontSize;\n let best = minFontSize;\n\n while (lo <= hi) {\n const mid = Math.floor((lo + hi) / 2);\n const style: ComputedStyle = {\n fontSize: mid,\n fontFamily: font.name,\n fontWeight: font.weight,\n fontStyle: font.style,\n lineHeight: lineHeight === \"normal\" ? undefined : lineHeight,\n whiteSpace,\n };\n\n const result = layoutText(text, style, maxWidth);\n\n if (result.width <= maxWidth && result.height <= maxHeight) {\n best = mid;\n lo = mid + 1;\n } else {\n hi = mid - 1;\n }\n }\n\n return best;\n}\n"],"mappings":"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","names":["GlobalFonts","Path2D","resolveRadius","x","y","Path2D","Path2D","createCanvas","canvas","Path2D","Path2D","Path2D","Path2D","loadImage","parseCssColor","EMOJI_CHAR","loadImage","parseCssColor","style","unsettled","createCanvas"]}