@effing/canvas 0.28.0 → 0.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/lottie.ts","../src/jsx/image-cache.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/index.ts","../src/jsx/draw/clip.ts","../src/jsx/draw/gradient.ts","../src/jsx/draw/object-fit.ts","../src/jsx/draw/image.ts","../src/jsx/draw/offscreen.ts","../src/jsx/draw/utils.ts","../src/jsx/draw/rect.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/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 @napi-rs/canvas\nimport { createCanvas as _createCanvas } from \"@napi-rs/canvas\";\nexport {\n Canvas,\n type SKRSContext2D,\n GlobalFonts,\n loadImage,\n Image,\n} from \"@napi-rs/canvas\";\n\nexport function createCanvas(width: number, height: number) {\n const canvas = _createCanvas(width, height);\n const origEncode = canvas.encode.bind(canvas);\n type Encode = typeof canvas.encode;\n\n // The native @napi-rs/canvas encode() returns Buffers backed by Rust/Skia\n // memory that can be freed before downstream consumers finish reading (e.g.\n // when streaming frames concurrently). We patch encode to copy the result\n // to the JS heap so the data remains valid regardless of native GC timing.\n canvas.encode = (async (...args: unknown[]) =>\n Buffer.from(await origEncode(...(args as Parameters<Encode>)))) as Encode;\n\n return canvas;\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 { LottieAnimation } from \"@napi-rs/canvas\";\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\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","import type { Image } from \"@napi-rs/canvas\";\nimport { loadImage } from \"@napi-rs/canvas\";\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, deduplicating by source string via the cache.\n * Buffer sources are never cached (no stable key).\n */\nexport function cachedLoadImage(\n cache: ImageCache,\n src: string | Buffer,\n): Promise<Image> {\n if (Buffer.isBuffer(src)) return loadImage(src);\n let entry = cache.get(src);\n if (!entry) {\n entry = loadImage(src);\n cache.set(src, entry);\n }\n return entry;\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 * 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\"\n | \"flex-start\"\n | \"flex-end\"\n | \"center\"\n | \"stretch\"\n | \"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\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\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 @napi-rs/canvas\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 strings so that by draw time\n // values are either bare numbers or `%` (which need element dimensions).\n if (style.transform) {\n style.transform = resolveTransformUnits(\n style.transform,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n }\n if (style.transformOrigin) {\n style.transformOrigin = resolveTransformUnits(\n style.transformOrigin,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n }\n\n return style;\n}\n\n/**\n * Resolve CSS length units (vw, vh, em, rem, px, etc.) inside a transform or\n * transformOrigin string. Percentages and angle units (deg, rad, turn) are\n * left untouched — percentages need element dimensions (available at draw time)\n * and angle units are not lengths.\n */\nfunction resolveTransformUnits(\n transform: string,\n viewportWidth: number,\n viewportHeight: number,\n fontSize: number,\n rootFontSize: number,\n): string {\n return transform.replace(\n /(-?\\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\" ? String(resolved) : 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 \"@napi-rs/canvas\";\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 \"@napi-rs/canvas\";\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\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\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/**\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 const quoted = fontFamily\n .split(\",\")\n .map((f) => quoteFontFamily(f.trim()))\n .join(\", \");\n ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${quoted}`;\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 = 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\n const refMetrics = c.measureText(\"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 = c.measureText(\"H\");\n targetAscent = capMetrics.actualBoundingBoxAscent ?? fontSize * 0.7;\n break;\n }\n case \"ex\": {\n const exMetrics = c.measureText(\"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","// 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 \"@napi-rs/canvas\";\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\";\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\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 segments with line-breaking.\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 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 // Resolve text stroke properties\n let textStrokeWidth: number | undefined;\n const rawStrokeWidth = style.WebkitTextStrokeWidth;\n if (rawStrokeWidth !== undefined) {\n if (typeof rawStrokeWidth === \"number\") {\n textStrokeWidth = rawStrokeWidth;\n } else {\n const resolved = resolveUnit(String(rawStrokeWidth), 0, 0, fontSize, 16);\n textStrokeWidth = typeof resolved === \"number\" ? resolved : undefined;\n }\n }\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 // Apply text transform\n let processedText = text;\n if (style.textTransform === \"uppercase\") {\n processedText = text.toUpperCase();\n } else if (style.textTransform === \"lowercase\") {\n processedText = text.toLowerCase();\n } else if (style.textTransform === \"capitalize\") {\n processedText = text.replace(/\\b\\w/g, (c) => c.toUpperCase());\n }\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 let x = 0;\n if (textAlign === \"center\") {\n x = (maxWidth - lineWidth) / 2;\n } else if (textAlign === \"right\") {\n x = maxWidth - lineWidth;\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 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 const segment = text.slice(lineStart, opp.position);\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. Without this, the\n // measured content width (widest trimmed line) can be narrower than what\n // the wrapping algorithm needs (it checks untrimmed segments), causing the\n // draw phase to wrap differently.\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 \"@napi-rs/canvas\";\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 // Clamp radii to half the smallest dimension\n const maxR = Math.min(w, h) / 2;\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\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 type { SKRSContext2D } from \"@napi-rs/canvas\";\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","/**\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 \"@napi-rs/canvas\";\n\nimport type { ImageCache } from \"../image-cache.ts\";\nimport { cachedLoadImage } from \"../image-cache.ts\";\nimport type { ComputedStyle } from \"../style/compute.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 imageCache - Image load cache\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 imageCache: ImageCache,\n style?: ComputedStyle,\n): Promise<void> {\n const image = await cachedLoadImage(imageCache, src);\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 { Canvas, SKRSContext2D } from \"@napi-rs/canvas\";\nimport { createCanvas } from \"@napi-rs/canvas\";\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","/**\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","import type { SKRSContext2D } from \"@napi-rs/canvas\";\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\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 // Parse simple box-shadow: offsetX offsetY blur spread? color\n const parts = boxShadow.match(\n /(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?(?:\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?)?\\s+(.*)/,\n );\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 { 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 : [raw];\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[]): 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 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 { clips, gradients, masks, filters };\n}\n\nexport const EMPTY_DEFS: SvgDefs = {\n clips: new Map(),\n gradients: new Map(),\n masks: new Map(),\n filters: new Map(),\n};\n","import type { SKRSContext2D } from \"@napi-rs/canvas\";\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 \"@napi-rs/canvas\";\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 } from \"@napi-rs/canvas\";\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 \"@napi-rs/canvas\";\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\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 \"@napi-rs/canvas\";\nimport type {\n CanvasGradient,\n DOMMatrix2DInit,\n SKRSContext2D,\n} from \"@napi-rs/canvas\";\n\nimport parseCssColor from \"parse-css-color\";\n\nimport type { BBox, SvgChild } from \"./types.ts\";\nimport { normalizeChildren } from \"./tree.ts\";\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/** 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 * Fill `path` with a gradient defined by `def` in the coordinate space of `bbox`.\n *\n * For `<linearGradient>` the bbox-to-canvas mapping is straightforward.\n * For `<radialGradient>` the SVG default `objectBoundingBox` produces an\n * *elliptical* gradient when the bbox is non-square. Canvas only supports\n * circular radial gradients, so we apply a non-uniform scale transform to\n * the context and fill an 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): boolean {\n const props = def.props;\n\n if (def.type === \"linearGradient\") {\n ctx.fillStyle = createLinearGradientFromBBox(ctx, props, bbox, 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): boolean {\n const props = def.props;\n\n if (def.type === \"linearGradient\") {\n ctx.strokeStyle = createLinearGradientFromBBox(ctx, props, bbox, 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 \"@napi-rs/canvas\";\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\n | 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 );\n ctx.restore();\n } else {\n fillWithSvgGradient(\n ctx,\n gradientDef,\n bbox,\n path,\n fillRule ?? \"nonzero\",\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);\n ctx.restore();\n } else {\n strokeWithSvgGradient(ctx, gradientDef, bbox, path);\n }\n return;\n }\n }\n\n ctx.strokeStyle = applyOpacity(stroke, strokeOpacity);\n ctx.stroke(path);\n}\n","import type { Canvas, SKRSContext2D } from \"@napi-rs/canvas\";\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 \"@napi-rs/canvas\";\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 const childArray = Array.isArray(children) ? children : [children];\n const svgChildren = childArray.filter(\n (c): c is SvgChild => c != null && typeof c === \"object\",\n );\n\n // First pass: collect definitions from <defs>\n const defs = collectDefs(svgChildren);\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 \"@napi-rs/canvas\";\nimport type { SKRSContext2D, Image } from \"@napi-rs/canvas\";\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 { 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.\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 */\nexport async function drawText(\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 if (typeof api === \"function\") {\n return (emojiCache[key] = fetch(api(code)).then((r) => r.text()));\n }\n return (emojiCache[key] = fetch(`${api}${code.toUpperCase()}.svg`).then((r) =>\n r.text(),\n ));\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 \"@napi-rs/canvas\";\n\nimport type { EmojiStyle } from \"../emoji.ts\";\nimport type { ImageCache } from \"../image-cache.ts\";\nimport { cachedLoadImage } from \"../image-cache.ts\";\nimport type { LayoutNode } from \"../layout.ts\";\nimport { layoutText } from \"../text/index.ts\";\nimport { applyClip, hasRadius, roundedRect } from \"./clip.ts\";\nimport { createGradientFromCSS, splitGradientArgs } from \"./gradient.ts\";\nimport { drawImage } from \"./image.ts\";\nimport { computeContain, computeCover } from \"./object-fit.ts\";\nimport { acquireOffscreen, releaseOffscreen } from \"./offscreen.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 */\nexport async function drawNode(\n ctx: SKRSContext2D,\n node: LayoutNode,\n parentX: number,\n parentY: number,\n debug: boolean,\n emojiStyle?: EmojiStyle,\n imageCache?: ImageCache,\n): Promise<void> {\n const x = parentX + node.x;\n const y = parentY + node.y;\n const { width, height, style } = node;\n\n if (style.display === \"none\") return;\n\n const opacity = style.opacity ?? 1;\n if (opacity <= 0) return;\n\n // Detect scale in transform — if present, render to offscreen buffer at 1x\n // then composite scaled. This avoids Skia re-rasterizing glyphs per-frame.\n const scaleInfo = style.transform ? extractScale(style.transform) : null;\n if (scaleInfo && (scaleInfo.sx !== 1 || scaleInfo.sy !== 1)) {\n const sx = scaleInfo.sx;\n const sy = scaleInfo.sy;\n const transformWithoutScale = scaleInfo.remaining;\n\n // Quantize to ceil(|scale|) — buffer resolution only changes at\n // integer boundaries (no jitter), and composite is always ≤1x (sharp).\n const qx = Math.max(1, Math.ceil(Math.abs(sx)));\n const qy = Math.max(1, Math.ceil(Math.abs(sy)));\n\n const bufW = Math.ceil((width + 2) * qx);\n const bufH = Math.ceil((height + 2) * qy);\n if (bufW > 0 && bufH > 0) {\n const [offscreen, offCtx] = acquireOffscreen(bufW, bufH);\n\n // Render at qx×qy resolution — logical coords produce more pixels\n offCtx.save();\n offCtx.scale(qx, qy);\n const cache: ImageCache = imageCache ?? new Map();\n await drawNodeCore(\n offCtx,\n node,\n parentX,\n parentY,\n 1 - x,\n 1 - y,\n debug,\n emojiStyle,\n cache,\n transformWithoutScale,\n );\n offCtx.restore();\n\n ctx.save();\n if (opacity < 1) {\n ctx.globalAlpha *= opacity;\n }\n\n let ox = x + width / 2;\n let oy = y + height / 2;\n if (style.transformOrigin) {\n const parts = style.transformOrigin.split(/\\s+/);\n ox = resolveOrigin(parts[0], x, width);\n oy = resolveOrigin(parts[1], y, height);\n }\n\n // Apply the original scale — drawImage maps the high-res buffer\n // back to logical size, so the transform needs the full scale value.\n ctx.translate(ox, oy);\n ctx.scale(sx, sy);\n ctx.translate(-ox, -oy);\n\n // Draw high-res buffer back at logical size (qx→1x downscale happens here)\n ctx.drawImage(\n offscreen,\n 0,\n 0,\n bufW,\n bufH,\n x - 1,\n y - 1,\n width + 2,\n height + 2,\n );\n releaseOffscreen(offscreen);\n ctx.restore();\n return;\n }\n }\n\n const cache: ImageCache = imageCache ?? new Map();\n await drawNodeCore(\n ctx,\n node,\n parentX,\n parentY,\n 0,\n 0,\n debug,\n emojiStyle,\n cache,\n );\n}\n\n/**\n * Extract scale(sx, sy) from a transform string, returning the scale values\n * and the remaining transform with scale removed.\n */\nfunction extractScale(\n transform: string,\n): { sx: number; sy: number; remaining: string } | null {\n const scaleMatch = transform.match(/\\b(scale|scaleX|scaleY)\\(([^)]+)\\)/);\n if (!scaleMatch) return null;\n\n const [fullMatch, name, args] = scaleMatch;\n const values = args!.split(\",\").map((s) => s.trim());\n\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\n const remaining = transform.replace(fullMatch!, \"\").trim();\n return { sx, sy, remaining };\n}\n\n/**\n * Core draw logic shared by both the normal path and the offscreen-buffer path.\n * offsetX/offsetY shift all coordinates so the node renders at a buffer-local position.\n * overrideTransform replaces the node's transform (used to strip scale for offscreen).\n */\nasync function drawNodeCore(\n ctx: SKRSContext2D,\n node: LayoutNode,\n parentX: number,\n parentY: number,\n offsetX: number,\n offsetY: number,\n debug: boolean,\n emojiStyle: EmojiStyle | undefined,\n imageCache: ImageCache,\n overrideTransform?: string,\n): Promise<void> {\n const x = parentX + node.x + offsetX;\n const y = parentY + node.y + offsetY;\n const { width, height, style } = node;\n\n if (style.display === \"none\") return;\n\n const opacity = style.opacity ?? 1;\n if (opacity <= 0) return;\n\n ctx.save();\n\n // Apply opacity\n if (opacity < 1) {\n ctx.globalAlpha *= opacity;\n }\n\n // Apply CSS filter\n if (style.filter) {\n ctx.filter = style.filter;\n }\n\n // Apply transform (use override when provided, e.g. scale stripped)\n const transformToApply =\n overrideTransform !== undefined ? overrideTransform : style.transform;\n if (transformToApply) {\n applyTransform(\n ctx,\n transformToApply,\n x,\n y,\n width,\n height,\n style.transformOrigin,\n );\n }\n\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\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(imageCache, urlMatch[1]!);\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 // Tile the image to fill the box (CSS background-repeat: repeat)\n for (let ty = y; ty < y + height; ty += tileH) {\n for (let tx = x; tx < x + width; tx += tileW) {\n ctx.drawImage(image, tx, ty, tileW, tileH);\n }\n }\n }\n }\n }\n }\n }\n\n // Debug: draw bounding boxes\n if (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 );\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 imageCache,\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 // Recursively draw children\n // When rendering via offset (offscreen buffer), children use offset 0\n // since x,y already incorporates the offset.\n for (const child of node.children) {\n if (offsetX === 0 && offsetY === 0) {\n await drawNode(ctx, child, x, y, debug, emojiStyle, imageCache);\n } else {\n await drawNodeCore(\n ctx,\n child,\n x,\n y,\n 0,\n 0,\n debug,\n emojiStyle,\n imageCache,\n );\n }\n }\n }\n\n ctx.restore();\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 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 bg = String(style.background);\n if (bg.includes(\"gradient(\") || bg.includes(\"url(\")) {\n if (style.backgroundImage === undefined) style.backgroundImage = bg;\n } else {\n if (style.backgroundColor === undefined) style.backgroundColor = bg;\n }\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 // 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","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 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\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 \"@napi-rs/canvas\";\nimport type { ReactElement, ReactNode } from \"react\";\n\nimport type { ImageCache } from \"./image-cache.ts\";\nimport { cachedLoadImage } from \"./image-cache.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): Promise<{ tree: LayoutNode; imageCache: ImageCache }> {\n const imageCache: ImageCache = new Map();\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 imageCache,\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 };\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 imageCache?: ImageCache,\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 imageCache,\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(imageCache ?? new Map(), src);\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 {\n // Silent fail — image will render at whatever size Yoga computes\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 return {\n type: tagName,\n style,\n children: [],\n props,\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 imageCache,\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 * 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 \"@napi-rs/canvas\";\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\";\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 */\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 // 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, imageCache } = await buildLayoutTree(\n element,\n width,\n height,\n ctx,\n !!emojiStyle,\n fontFamilies,\n );\n\n // Draw to canvas\n await drawNode(\n ctx,\n layoutTree,\n 0,\n 0,\n options.debug ?? false,\n emojiStyle,\n imageCache,\n );\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 /** 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 */\nexport function findLargestUsableFontSize(\n options: FindLargestUsableFontSizeOptions,\n): number {\n const {\n text,\n font,\n maxWidth,\n maxHeight,\n lineHeight = \"normal\",\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 };\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","loadImage","createCanvas","canvas","Path2D","Path2D","Path2D","Path2D","loadImage","parseCssColor","measureText","loadImage","parseCssColor","cache","style","createCanvas"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/lottie.ts","../src/jsx/image-cache.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/index.ts","../src/jsx/draw/clip.ts","../src/jsx/draw/gradient.ts","../src/jsx/draw/object-fit.ts","../src/jsx/draw/image.ts","../src/jsx/draw/offscreen.ts","../src/jsx/draw/utils.ts","../src/jsx/draw/rect.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/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 @napi-rs/canvas\nimport { createCanvas as _createCanvas } from \"@napi-rs/canvas\";\nexport {\n Canvas,\n type SKRSContext2D,\n GlobalFonts,\n loadImage,\n Image,\n} from \"@napi-rs/canvas\";\n\nexport function createCanvas(width: number, height: number) {\n const canvas = _createCanvas(width, height);\n const origEncode = canvas.encode.bind(canvas);\n type Encode = typeof canvas.encode;\n\n // The native @napi-rs/canvas encode() returns Buffers backed by Rust/Skia\n // memory that can be freed before downstream consumers finish reading (e.g.\n // when streaming frames concurrently). We patch encode to copy the result\n // to the JS heap so the data remains valid regardless of native GC timing.\n canvas.encode = (async (...args: unknown[]) =>\n Buffer.from(await origEncode(...(args as Parameters<Encode>)))) as Encode;\n\n return canvas;\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 { LottieAnimation } from \"@napi-rs/canvas\";\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\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","import type { Image } from \"@napi-rs/canvas\";\nimport { loadImage } from \"@napi-rs/canvas\";\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, deduplicating by source string via the cache.\n * Buffer sources are never cached (no stable key).\n *\n * Remote URLs (http/https) are fetched via global fetch() and passed to\n * loadImage as bytes. This lets callers install a global dispatcher\n * (e.g. undici's setGlobalDispatcher) to route image traffic through a\n * proxy — @napi-rs/canvas's own URL loader uses Node's raw http modules,\n * which bypass any dispatcher.\n */\nexport function cachedLoadImage(\n cache: ImageCache,\n src: string | Buffer,\n): Promise<Image> {\n if (Buffer.isBuffer(src)) return loadImage(src);\n let entry = cache.get(src);\n if (!entry) {\n entry = isRemoteUrl(src) ? loadRemoteImage(src) : loadImage(src);\n cache.set(src, entry);\n }\n return entry;\n}\n\nfunction isRemoteUrl(src: string): boolean {\n return src.startsWith(\"http://\") || src.startsWith(\"https://\");\n}\n\nasync function loadRemoteImage(url: string): Promise<Image> {\n const response = await fetch(url);\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 loadImage(buffer);\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 * 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\"\n | \"flex-start\"\n | \"flex-end\"\n | \"center\"\n | \"stretch\"\n | \"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\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\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 @napi-rs/canvas\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 strings so that by draw time\n // values are either bare numbers or `%` (which need element dimensions).\n if (style.transform) {\n style.transform = resolveTransformUnits(\n style.transform,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n }\n if (style.transformOrigin) {\n style.transformOrigin = resolveTransformUnits(\n style.transformOrigin,\n viewportWidth,\n viewportHeight,\n fontSize,\n rootFontSize,\n );\n }\n\n return style;\n}\n\n/**\n * Resolve CSS length units (vw, vh, em, rem, px, etc.) inside a transform or\n * transformOrigin string. Percentages and angle units (deg, rad, turn) are\n * left untouched — percentages need element dimensions (available at draw time)\n * and angle units are not lengths.\n */\nfunction resolveTransformUnits(\n transform: string,\n viewportWidth: number,\n viewportHeight: number,\n fontSize: number,\n rootFontSize: number,\n): string {\n return transform.replace(\n /(-?\\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\" ? String(resolved) : 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 \"@napi-rs/canvas\";\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 \"@napi-rs/canvas\";\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\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\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/**\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 const quoted = fontFamily\n .split(\",\")\n .map((f) => quoteFontFamily(f.trim()))\n .join(\", \");\n ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${quoted}`;\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 = 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\n const refMetrics = c.measureText(\"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 = c.measureText(\"H\");\n targetAscent = capMetrics.actualBoundingBoxAscent ?? fontSize * 0.7;\n break;\n }\n case \"ex\": {\n const exMetrics = c.measureText(\"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","// 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 \"@napi-rs/canvas\";\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\";\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\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 segments with line-breaking.\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 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 // Resolve text stroke properties\n let textStrokeWidth: number | undefined;\n const rawStrokeWidth = style.WebkitTextStrokeWidth;\n if (rawStrokeWidth !== undefined) {\n if (typeof rawStrokeWidth === \"number\") {\n textStrokeWidth = rawStrokeWidth;\n } else {\n const resolved = resolveUnit(String(rawStrokeWidth), 0, 0, fontSize, 16);\n textStrokeWidth = typeof resolved === \"number\" ? resolved : undefined;\n }\n }\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 // Apply text transform\n let processedText = text;\n if (style.textTransform === \"uppercase\") {\n processedText = text.toUpperCase();\n } else if (style.textTransform === \"lowercase\") {\n processedText = text.toLowerCase();\n } else if (style.textTransform === \"capitalize\") {\n processedText = text.replace(/\\b\\w/g, (c) => c.toUpperCase());\n }\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 let x = 0;\n if (textAlign === \"center\") {\n x = (maxWidth - lineWidth) / 2;\n } else if (textAlign === \"right\") {\n x = maxWidth - lineWidth;\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 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 const segment = text.slice(lineStart, opp.position);\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. Without this, the\n // measured content width (widest trimmed line) can be narrower than what\n // the wrapping algorithm needs (it checks untrimmed segments), causing the\n // draw phase to wrap differently.\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 \"@napi-rs/canvas\";\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 // Clamp radii to half the smallest dimension\n const maxR = Math.min(w, h) / 2;\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\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 type { SKRSContext2D } from \"@napi-rs/canvas\";\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","/**\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 \"@napi-rs/canvas\";\n\nimport type { ImageCache } from \"../image-cache.ts\";\nimport { cachedLoadImage } from \"../image-cache.ts\";\nimport type { ComputedStyle } from \"../style/compute.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 imageCache - Image load cache\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 imageCache: ImageCache,\n style?: ComputedStyle,\n): Promise<void> {\n const image = await cachedLoadImage(imageCache, src);\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 { Canvas, SKRSContext2D } from \"@napi-rs/canvas\";\nimport { createCanvas } from \"@napi-rs/canvas\";\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","/**\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","import type { SKRSContext2D } from \"@napi-rs/canvas\";\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\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 // Parse simple box-shadow: offsetX offsetY blur spread? color\n const parts = boxShadow.match(\n /(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?(?:\\s+(-?\\d+(?:\\.\\d+)?)\\s*(?:px)?)?\\s+(.*)/,\n );\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 { 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 : [raw];\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[]): 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 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 { clips, gradients, masks, filters };\n}\n\nexport const EMPTY_DEFS: SvgDefs = {\n clips: new Map(),\n gradients: new Map(),\n masks: new Map(),\n filters: new Map(),\n};\n","import type { SKRSContext2D } from \"@napi-rs/canvas\";\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 \"@napi-rs/canvas\";\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 } from \"@napi-rs/canvas\";\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 \"@napi-rs/canvas\";\nimport type { SKRSContext2D } from \"@napi-rs/canvas\";\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 \"@napi-rs/canvas\";\nimport type {\n CanvasGradient,\n DOMMatrix2DInit,\n SKRSContext2D,\n} from \"@napi-rs/canvas\";\n\nimport parseCssColor from \"parse-css-color\";\n\nimport type { BBox, SvgChild } from \"./types.ts\";\nimport { normalizeChildren } from \"./tree.ts\";\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/** 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 * Fill `path` with a gradient defined by `def` in the coordinate space of `bbox`.\n *\n * For `<linearGradient>` the bbox-to-canvas mapping is straightforward.\n * For `<radialGradient>` the SVG default `objectBoundingBox` produces an\n * *elliptical* gradient when the bbox is non-square. Canvas only supports\n * circular radial gradients, so we apply a non-uniform scale transform to\n * the context and fill an 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): boolean {\n const props = def.props;\n\n if (def.type === \"linearGradient\") {\n ctx.fillStyle = createLinearGradientFromBBox(ctx, props, bbox, 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): boolean {\n const props = def.props;\n\n if (def.type === \"linearGradient\") {\n ctx.strokeStyle = createLinearGradientFromBBox(ctx, props, bbox, 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 \"@napi-rs/canvas\";\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\n | 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 );\n ctx.restore();\n } else {\n fillWithSvgGradient(\n ctx,\n gradientDef,\n bbox,\n path,\n fillRule ?? \"nonzero\",\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);\n ctx.restore();\n } else {\n strokeWithSvgGradient(ctx, gradientDef, bbox, path);\n }\n return;\n }\n }\n\n ctx.strokeStyle = applyOpacity(stroke, strokeOpacity);\n ctx.stroke(path);\n}\n","import type { Canvas, SKRSContext2D } from \"@napi-rs/canvas\";\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 \"@napi-rs/canvas\";\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 const childArray = Array.isArray(children) ? children : [children];\n const svgChildren = childArray.filter(\n (c): c is SvgChild => c != null && typeof c === \"object\",\n );\n\n // First pass: collect definitions from <defs>\n const defs = collectDefs(svgChildren);\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 \"@napi-rs/canvas\";\nimport type { SKRSContext2D, Image } from \"@napi-rs/canvas\";\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 { 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.\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 */\nexport async function drawText(\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 if (typeof api === \"function\") {\n return (emojiCache[key] = fetch(api(code)).then((r) => r.text()));\n }\n return (emojiCache[key] = fetch(`${api}${code.toUpperCase()}.svg`).then((r) =>\n r.text(),\n ));\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 \"@napi-rs/canvas\";\n\nimport type { EmojiStyle } from \"../emoji.ts\";\nimport type { ImageCache } from \"../image-cache.ts\";\nimport { cachedLoadImage } from \"../image-cache.ts\";\nimport type { LayoutNode } from \"../layout.ts\";\nimport { layoutText } from \"../text/index.ts\";\nimport { applyClip, hasRadius, roundedRect } from \"./clip.ts\";\nimport { createGradientFromCSS, splitGradientArgs } from \"./gradient.ts\";\nimport { drawImage } from \"./image.ts\";\nimport { computeContain, computeCover } from \"./object-fit.ts\";\nimport { acquireOffscreen, releaseOffscreen } from \"./offscreen.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 */\nexport async function drawNode(\n ctx: SKRSContext2D,\n node: LayoutNode,\n parentX: number,\n parentY: number,\n debug: boolean,\n emojiStyle?: EmojiStyle,\n imageCache?: ImageCache,\n): Promise<void> {\n const x = parentX + node.x;\n const y = parentY + node.y;\n const { width, height, style } = node;\n\n if (style.display === \"none\") return;\n\n const opacity = style.opacity ?? 1;\n if (opacity <= 0) return;\n\n // Detect scale in transform — if present, render to offscreen buffer at 1x\n // then composite scaled. This avoids Skia re-rasterizing glyphs per-frame.\n const scaleInfo = style.transform ? extractScale(style.transform) : null;\n if (scaleInfo && (scaleInfo.sx !== 1 || scaleInfo.sy !== 1)) {\n const sx = scaleInfo.sx;\n const sy = scaleInfo.sy;\n const transformWithoutScale = scaleInfo.remaining;\n\n // Quantize to ceil(|scale|) — buffer resolution only changes at\n // integer boundaries (no jitter), and composite is always ≤1x (sharp).\n const qx = Math.max(1, Math.ceil(Math.abs(sx)));\n const qy = Math.max(1, Math.ceil(Math.abs(sy)));\n\n const bufW = Math.ceil((width + 2) * qx);\n const bufH = Math.ceil((height + 2) * qy);\n if (bufW > 0 && bufH > 0) {\n const [offscreen, offCtx] = acquireOffscreen(bufW, bufH);\n\n // Render at qx×qy resolution — logical coords produce more pixels\n offCtx.save();\n offCtx.scale(qx, qy);\n const cache: ImageCache = imageCache ?? new Map();\n await drawNodeCore(\n offCtx,\n node,\n parentX,\n parentY,\n 1 - x,\n 1 - y,\n debug,\n emojiStyle,\n cache,\n transformWithoutScale,\n );\n offCtx.restore();\n\n ctx.save();\n if (opacity < 1) {\n ctx.globalAlpha *= opacity;\n }\n\n let ox = x + width / 2;\n let oy = y + height / 2;\n if (style.transformOrigin) {\n const parts = style.transformOrigin.split(/\\s+/);\n ox = resolveOrigin(parts[0], x, width);\n oy = resolveOrigin(parts[1], y, height);\n }\n\n // Apply the original scale — drawImage maps the high-res buffer\n // back to logical size, so the transform needs the full scale value.\n ctx.translate(ox, oy);\n ctx.scale(sx, sy);\n ctx.translate(-ox, -oy);\n\n // Draw high-res buffer back at logical size (qx→1x downscale happens here)\n ctx.drawImage(\n offscreen,\n 0,\n 0,\n bufW,\n bufH,\n x - 1,\n y - 1,\n width + 2,\n height + 2,\n );\n releaseOffscreen(offscreen);\n ctx.restore();\n return;\n }\n }\n\n const cache: ImageCache = imageCache ?? new Map();\n await drawNodeCore(\n ctx,\n node,\n parentX,\n parentY,\n 0,\n 0,\n debug,\n emojiStyle,\n cache,\n );\n}\n\n/**\n * Extract scale(sx, sy) from a transform string, returning the scale values\n * and the remaining transform with scale removed.\n */\nfunction extractScale(\n transform: string,\n): { sx: number; sy: number; remaining: string } | null {\n const scaleMatch = transform.match(/\\b(scale|scaleX|scaleY)\\(([^)]+)\\)/);\n if (!scaleMatch) return null;\n\n const [fullMatch, name, args] = scaleMatch;\n const values = args!.split(\",\").map((s) => s.trim());\n\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\n const remaining = transform.replace(fullMatch!, \"\").trim();\n return { sx, sy, remaining };\n}\n\n/**\n * Core draw logic shared by both the normal path and the offscreen-buffer path.\n * offsetX/offsetY shift all coordinates so the node renders at a buffer-local position.\n * overrideTransform replaces the node's transform (used to strip scale for offscreen).\n */\nasync function drawNodeCore(\n ctx: SKRSContext2D,\n node: LayoutNode,\n parentX: number,\n parentY: number,\n offsetX: number,\n offsetY: number,\n debug: boolean,\n emojiStyle: EmojiStyle | undefined,\n imageCache: ImageCache,\n overrideTransform?: string,\n): Promise<void> {\n const x = parentX + node.x + offsetX;\n const y = parentY + node.y + offsetY;\n const { width, height, style } = node;\n\n if (style.display === \"none\") return;\n\n const opacity = style.opacity ?? 1;\n if (opacity <= 0) return;\n\n ctx.save();\n\n // Apply opacity\n if (opacity < 1) {\n ctx.globalAlpha *= opacity;\n }\n\n // Apply CSS filter\n if (style.filter) {\n ctx.filter = style.filter;\n }\n\n // Apply transform (use override when provided, e.g. scale stripped)\n const transformToApply =\n overrideTransform !== undefined ? overrideTransform : style.transform;\n if (transformToApply) {\n applyTransform(\n ctx,\n transformToApply,\n x,\n y,\n width,\n height,\n style.transformOrigin,\n );\n }\n\n const borderRadius = getBorderRadiusFromStyle(style, width, height);\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(imageCache, urlMatch[1]!);\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 // Tile the image to fill the box (CSS background-repeat: repeat)\n for (let ty = y; ty < y + height; ty += tileH) {\n for (let tx = x; tx < x + width; tx += tileW) {\n ctx.drawImage(image, tx, ty, tileW, tileH);\n }\n }\n }\n }\n }\n }\n }\n\n // Debug: draw bounding boxes\n if (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 );\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 imageCache,\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 // Recursively draw children\n // When rendering via offset (offscreen buffer), children use offset 0\n // since x,y already incorporates the offset.\n for (const child of node.children) {\n if (offsetX === 0 && offsetY === 0) {\n await drawNode(ctx, child, x, y, debug, emojiStyle, imageCache);\n } else {\n await drawNodeCore(\n ctx,\n child,\n x,\n y,\n 0,\n 0,\n debug,\n emojiStyle,\n imageCache,\n );\n }\n }\n }\n\n ctx.restore();\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 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 bg = String(style.background);\n if (bg.includes(\"gradient(\") || bg.includes(\"url(\")) {\n if (style.backgroundImage === undefined) style.backgroundImage = bg;\n } else {\n if (style.backgroundColor === undefined) style.backgroundColor = bg;\n }\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 // 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","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 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\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 \"@napi-rs/canvas\";\nimport type { ReactElement, ReactNode } from \"react\";\n\nimport type { ImageCache } from \"./image-cache.ts\";\nimport { cachedLoadImage } from \"./image-cache.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): Promise<{ tree: LayoutNode; imageCache: ImageCache }> {\n const imageCache: ImageCache = new Map();\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 imageCache,\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 };\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 imageCache?: ImageCache,\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 imageCache,\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(imageCache ?? new Map(), src);\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 {\n // Silent fail — image will render at whatever size Yoga computes\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 return {\n type: tagName,\n style,\n children: [],\n props,\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 imageCache,\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 * 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 \"@napi-rs/canvas\";\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\";\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 */\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 // 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, imageCache } = await buildLayoutTree(\n element,\n width,\n height,\n ctx,\n !!emojiStyle,\n fontFamilies,\n );\n\n // Draw to canvas\n await drawNode(\n ctx,\n layoutTree,\n 0,\n 0,\n options.debug ?? false,\n emojiStyle,\n imageCache,\n );\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 /** 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 */\nexport function findLargestUsableFontSize(\n options: FindLargestUsableFontSizeOptions,\n): number {\n const {\n text,\n font,\n maxWidth,\n maxHeight,\n lineHeight = \"normal\",\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 };\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","loadImage","createCanvas","canvas","Path2D","Path2D","Path2D","Path2D","loadImage","parseCssColor","measureText","loadImage","parseCssColor","cache","style","createCanvas"]}
|