@shotstack/shotstack-canvas 1.0.7 → 1.0.9

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/schema/asset-schema.ts","../src/config/canvas-constants.ts","../src/wasm/hb-loader.ts","../src/core/font-registry.ts","../src/core/layout.ts","../src/core/gradients.ts","../src/core/decoration.ts","../src/core/drawops.ts","../src/core/animations.ts","../src/core/colors.ts","../src/painters/web.ts","../src/io/web.ts","../src/env/entry.web.ts"],"sourcesContent":["import Joi from \"joi\";\r\nimport { CANVAS_CONFIG } from \"../config/canvas-constants\";\r\n\r\nconst HEX6 = /^#[A-Fa-f0-9]{6}$/;\r\n\r\nconst gradientSchema = Joi.object({\r\n type: Joi.string().valid(\"linear\", \"radial\").default(\"linear\"),\r\n angle: Joi.number().min(0).max(360).default(0),\r\n stops: Joi.array()\r\n .items(\r\n Joi.object({\r\n offset: Joi.number().min(0).max(1).required(),\r\n color: Joi.string().pattern(HEX6).required()\r\n }).unknown(false)\r\n )\r\n .min(2)\r\n .required()\r\n}).unknown(false);\r\n\r\nconst shadowSchema = Joi.object({\r\n offsetX: Joi.number().default(0),\r\n offsetY: Joi.number().default(0),\r\n blur: Joi.number().min(0).default(0),\r\n color: Joi.string().pattern(HEX6).default(\"#000000\"),\r\n opacity: Joi.number().min(0).max(1).default(0.5)\r\n}).unknown(false);\r\n\r\nconst strokeSchema = Joi.object({\r\n width: Joi.number().min(0).default(0),\r\n color: Joi.string().pattern(HEX6).default(\"#000000\"),\r\n opacity: Joi.number().min(0).max(1).default(1)\r\n}).unknown(false);\r\n\r\nconst fontSchema = Joi.object({\r\n family: Joi.string().default(CANVAS_CONFIG.DEFAULTS.fontFamily),\r\n size: Joi.number()\r\n .min(CANVAS_CONFIG.LIMITS.minFontSize)\r\n .max(CANVAS_CONFIG.LIMITS.maxFontSize)\r\n .default(CANVAS_CONFIG.DEFAULTS.fontSize),\r\n weight: Joi.alternatives().try(Joi.string(), Joi.number()).default(\"400\"),\r\n style: Joi.string().valid(\"normal\", \"italic\", \"oblique\").default(\"normal\"),\r\n color: Joi.string().pattern(HEX6).default(CANVAS_CONFIG.DEFAULTS.color),\r\n opacity: Joi.number().min(0).max(1).default(1)\r\n}).unknown(false);\r\n\r\nconst styleSchema = Joi.object({\r\n letterSpacing: Joi.number().default(0),\r\n lineHeight: Joi.number().min(0).max(10).default(1.2),\r\n textTransform: Joi.string().valid(\"none\", \"uppercase\", \"lowercase\", \"capitalize\").default(\"none\"),\r\n textDecoration: Joi.string().valid(\"none\", \"underline\", \"line-through\").default(\"none\"),\r\n gradient: gradientSchema.optional()\r\n}).unknown(false);\r\n\r\nconst alignmentSchema = Joi.object({\r\n horizontal: Joi.string()\r\n .valid(\"left\", \"center\", \"right\")\r\n .default(CANVAS_CONFIG.DEFAULTS.textAlign),\r\n vertical: Joi.string().valid(\"top\", \"middle\", \"bottom\").default(\"middle\")\r\n}).unknown(false);\r\n\r\nconst animationSchema = Joi.object({\r\n preset: Joi.string().valid(...CANVAS_CONFIG.ANIMATION_TYPES as readonly string[]),\r\n speed: Joi.number().min(0.1).max(10).default(1),\r\n duration: Joi.number()\r\n .min(CANVAS_CONFIG.LIMITS.minDuration)\r\n .max(CANVAS_CONFIG.LIMITS.maxDuration)\r\n .optional(),\r\n style: Joi.string()\r\n .valid(\"character\", \"word\")\r\n .optional()\r\n .when(\"preset\", {\r\n is: Joi.valid(\"typewriter\", \"shift\"),\r\n then: Joi.optional(),\r\n otherwise: Joi.forbidden()\r\n }),\r\n direction: Joi.string()\r\n .optional()\r\n .when(\"preset\", {\r\n switch: [\r\n { is: \"ascend\", then: Joi.valid(\"up\", \"down\") },\r\n { is: \"shift\", then: Joi.valid(\"left\", \"right\", \"up\", \"down\") },\r\n { is: \"slideIn\", then: Joi.valid(\"left\", \"right\", \"up\", \"down\") },\r\n { is: \"movingLetters\", then: Joi.valid(\"left\", \"right\", \"up\", \"down\") }\r\n ],\r\n otherwise: Joi.forbidden()\r\n })\r\n}).unknown(false);\r\n\r\nconst backgroundSchema = Joi.object({\r\n color: Joi.string().pattern(HEX6).optional(),\r\n opacity: Joi.number().min(0).max(1).default(1),\r\n borderRadius: Joi.number().min(0).default(0)\r\n}).unknown(false);\r\n\r\nconst customFontSchema = Joi.object({\r\n src: Joi.string().uri().required(),\r\n family: Joi.string().required(),\r\n weight: Joi.alternatives().try(Joi.string(), Joi.number()).optional(),\r\n style: Joi.string().optional(),\r\n originalFamily: Joi.string().optional()\r\n}).unknown(false);\r\n\r\nexport const RichTextAssetSchema = Joi.object({\r\n type: Joi.string().valid(\"rich-text\").required(),\r\n text: Joi.string().allow(\"\").max(CANVAS_CONFIG.LIMITS.maxTextLength).default(\"\"),\r\n width: Joi.number()\r\n .min(CANVAS_CONFIG.LIMITS.minWidth)\r\n .max(CANVAS_CONFIG.LIMITS.maxWidth)\r\n .default(CANVAS_CONFIG.DEFAULTS.width)\r\n .optional(),\r\n height: Joi.number()\r\n .min(CANVAS_CONFIG.LIMITS.minHeight)\r\n .max(CANVAS_CONFIG.LIMITS.maxHeight)\r\n .default(CANVAS_CONFIG.DEFAULTS.height)\r\n .optional(),\r\n font: fontSchema.optional(),\r\n style: styleSchema.optional(),\r\n stroke: strokeSchema.optional(),\r\n shadow: shadowSchema.optional(),\r\n background: backgroundSchema.optional(),\r\n align: alignmentSchema.optional(),\r\n animation: animationSchema.optional(),\r\n customFonts: Joi.array().items(customFontSchema).optional(),\r\n cacheEnabled: Joi.boolean().default(true),\r\n pixelRatio: Joi.number().min(1).max(3).default(CANVAS_CONFIG.DEFAULTS.pixelRatio)\r\n}).unknown(false);\r\n\r\nexport type RichTextValidated = Required<{\r\n type: \"rich-text\";\r\n text: string;\r\n width?: number;\r\n height?: number;\r\n font?: {\r\n family: string;\r\n size: number;\r\n weight: string | number;\r\n style: \"normal\" | \"italic\" | \"oblique\";\r\n color: string;\r\n opacity: number;\r\n };\r\n style?: {\r\n letterSpacing: number;\r\n lineHeight: number;\r\n textTransform: \"none\" | \"uppercase\" | \"lowercase\" | \"capitalize\";\r\n textDecoration: \"none\" | \"underline\" | \"line-through\";\r\n gradient?: {\r\n type: \"linear\" | \"radial\";\r\n angle: number;\r\n stops: { offset: number; color: string }[];\r\n };\r\n };\r\n stroke?: { width: number; color: string; opacity: number };\r\n shadow?: { offsetX: number; offsetY: number; blur: number; color: string; opacity: number };\r\n background?: { color?: string; opacity: number; borderRadius: number };\r\n align?: { horizontal: \"left\" | \"center\" | \"right\"; vertical: \"top\" | \"middle\" | \"bottom\" };\r\n animation?: {\r\n preset: typeof CANVAS_CONFIG.ANIMATION_TYPES[number];\r\n speed: number;\r\n duration?: number;\r\n style?: \"character\" | \"word\";\r\n direction?: \"left\" | \"right\" | \"up\" | \"down\";\r\n };\r\n customFonts?: { src: string; family: string; weight?: string | number; style?: string; originalFamily?: string }[];\r\n cacheEnabled: boolean;\r\n pixelRatio: number;\r\n}>;\r\n","export const CANVAS_CONFIG = {\r\n DEFAULTS: {\r\n width: 800,\r\n height: 400,\r\n pixelRatio: 2,\r\n fontFamily: \"Roboto\",\r\n fontSize: 48,\r\n color: \"#000000\",\r\n textAlign: \"left\" as const\r\n },\r\n LIMITS: {\r\n minWidth: 1,\r\n maxWidth: 4096,\r\n minHeight: 1,\r\n maxHeight: 4096,\r\n minFontSize: 1,\r\n maxFontSize: 512,\r\n minDuration: 0.1,\r\n maxDuration: 120,\r\n maxTextLength: 10000\r\n },\r\n ANIMATION_TYPES: [\r\n \"typewriter\",\r\n \"fadeIn\",\r\n \"slideIn\",\r\n \"shift\",\r\n \"ascend\",\r\n \"movingLetters\"\r\n ] as const\r\n};\r\n","// src/wasm/hb-loader.ts\r\n/* eslint-disable @typescript-eslint/no-explicit-any */\r\n\r\nlet hbSingleton: any | null = null;\r\n\r\nexport async function initHB(wasmBaseURL?: string): Promise<any> {\r\n if (hbSingleton) return hbSingleton;\r\n\r\n // Simply import harfbuzzjs and let it handle WASM loading\r\n const harfbuzzjs = await import('harfbuzzjs');\r\n \r\n // harfbuzzjs default export is a Promise that resolves to the hb object\r\n const hbPromise = harfbuzzjs.default;\r\n \r\n if (typeof hbPromise === 'function') {\r\n hbSingleton = await hbPromise();\r\n } else if (hbPromise && typeof hbPromise.then === 'function') {\r\n hbSingleton = await hbPromise;\r\n } else {\r\n hbSingleton = hbPromise;\r\n }\r\n\r\n // Validate the API\r\n if (!hbSingleton || typeof hbSingleton.createBuffer !== \"function\") {\r\n throw new Error(\"Failed to initialize HarfBuzz: invalid API\");\r\n }\r\n\r\n return hbSingleton;\r\n}\r\n\r\nexport type HB = any;","import { initHB, type HB } from \"../wasm/hb-loader\";\r\n\r\nexport type FontDescriptor = { family: string; weight?: string | number; style?: string };\r\n\r\nexport class FontRegistry {\r\n private hb!: HB;\r\n private faces = new Map<string, any>();\r\n private fonts = new Map<string, any>();\r\n private blobs = new Map<string, any>();\r\n private wasmBaseURL?: string;\r\n\r\n constructor(wasmBaseURL?: string) {\r\n this.wasmBaseURL = wasmBaseURL;\r\n }\r\n\r\n async init() {\r\n if (!this.hb) this.hb = await initHB(this.wasmBaseURL);\r\n }\r\n\r\n getHB(): HB {\r\n if (!this.hb) throw new Error(\"FontRegistry not initialized - call init() first\");\r\n return this.hb;\r\n }\r\n\r\n private key(desc: FontDescriptor) {\r\n return `${desc.family}__${desc.weight ?? \"400\"}__${desc.style ?? \"normal\"}`;\r\n }\r\n\r\n async registerFromBytes(bytes: ArrayBuffer, desc: FontDescriptor): Promise<void> {\r\n if (!this.hb) await this.init();\r\n const k = this.key(desc);\r\n if (this.fonts.has(k)) return;\r\n\r\n const blob = this.hb.createBlob(bytes);\r\n const face = this.hb.createFace(blob, 0);\r\n const font = this.hb.createFont(face);\r\n\r\n // Keep HarfBuzz in font-units; we scale during painting\r\n const upem = face.upem || 1000;\r\n font.setScale(upem, upem);\r\n\r\n this.blobs.set(k, blob);\r\n this.faces.set(k, face);\r\n this.fonts.set(k, font);\r\n }\r\n\r\n getFont(desc: FontDescriptor): any {\r\n const k = this.key(desc);\r\n const f = this.fonts.get(k);\r\n if (!f) throw new Error(`Font not registered for ${k}`);\r\n return f;\r\n }\r\n\r\n getFace(desc: FontDescriptor): any {\r\n const k = this.key(desc);\r\n return this.faces.get(k);\r\n }\r\n\r\n /** NEW: expose units-per-em for scaling glyph paths to px */\r\n getUnitsPerEm(desc: FontDescriptor): number {\r\n const face = this.getFace(desc);\r\n return face?.upem || 1000;\r\n }\r\n\r\n glyphPath(desc: FontDescriptor, glyphId: number): string {\r\n const font = this.getFont(desc);\r\n const path = font.glyphToPath(glyphId);\r\n return path && path !== \"\" ? path : \"M 0 0\";\r\n }\r\n\r\n destroy() {\r\n for (const [, f] of this.fonts) f.destroy?.();\r\n for (const [, f] of this.faces) f.destroy?.();\r\n for (const [, b] of this.blobs) b.destroy?.();\r\n this.fonts.clear(); this.faces.clear(); this.blobs.clear();\r\n }\r\n}\r\n","import { FontRegistry, FontDescriptor } from \"./font-registry\";\r\nimport { Glyph, ShapedLine } from \"../types\";\r\n\r\nexport type ShapeParams = {\r\n text: string;\r\n width: number;\r\n letterSpacing: number;\r\n fontSize: number;\r\n lineHeight: number;\r\n desc: FontDescriptor;\r\n textTransform: \"none\" | \"uppercase\" | \"lowercase\" | \"capitalize\";\r\n};\r\n\r\ntype HBRunGlyph = { g: number; ax: number; ay: number; dx: number; dy: number; cl: number };\r\n\r\nexport class LayoutEngine {\r\n constructor(private fonts: FontRegistry) {}\r\n\r\n private transformText(t: string, tr: ShapeParams[\"textTransform\"]) {\r\n switch (tr) {\r\n case \"uppercase\":\r\n return t.toUpperCase();\r\n case \"lowercase\":\r\n return t.toLowerCase();\r\n case \"capitalize\":\r\n return t.replace(/\\b\\w/g, (c) => c.toUpperCase());\r\n default:\r\n return t;\r\n }\r\n }\r\n\r\n private shapeFull(text: string, desc: FontDescriptor): HBRunGlyph[] {\r\n const hb = this.fonts.getHB();\r\n const buffer = hb.createBuffer();\r\n\r\n buffer.addText(text);\r\n buffer.guessSegmentProperties();\r\n\r\n const font = this.fonts.getFont(desc);\r\n const face = this.fonts.getFace(desc);\r\n\r\n // Set proper scale for shaping\r\n const upem = face?.upem || 1000;\r\n font.setScale(upem, upem);\r\n\r\n hb.shape(font, buffer);\r\n\r\n const result = buffer.json();\r\n buffer.destroy();\r\n\r\n return result;\r\n }\r\n\r\n layout(params: ShapeParams): ShapedLine[] {\r\n const { textTransform, desc, fontSize, letterSpacing, width } = params;\r\n const input = this.transformText(params.text, textTransform);\r\n\r\n if (!input || input.length === 0) {\r\n return [];\r\n }\r\n\r\n // Shape the text\r\n const shaped = this.shapeFull(input, desc);\r\n\r\n // Get font metrics for proper scaling\r\n const face = this.fonts.getFace(desc);\r\n const upem = face?.upem || 1000;\r\n const scale = fontSize / upem;\r\n\r\n // Convert shaped glyphs to our format\r\n const glyphs: Glyph[] = shaped.map((g, i) => {\r\n // Get the actual character from the input text using the cluster index\r\n const charIndex = g.cl;\r\n let char: string | undefined;\r\n\r\n // Cluster index tells us which character in the original text this glyph represents\r\n if (charIndex >= 0 && charIndex < input.length) {\r\n char = input[charIndex];\r\n }\r\n\r\n return {\r\n id: g.g,\r\n xAdvance: g.ax * scale + letterSpacing,\r\n xOffset: g.dx * scale,\r\n yOffset: -g.dy * scale,\r\n cluster: g.cl,\r\n char: char, // This now correctly maps to the original character\r\n };\r\n });\r\n\r\n // Line breaking logic\r\n const lines: ShapedLine[] = [];\r\n let currentLine: Glyph[] = [];\r\n let currentWidth = 0;\r\n\r\n // Identify space positions\r\n const spaceIndices = new Set<number>();\r\n for (let i = 0; i < input.length; i++) {\r\n if (input[i] === \" \") {\r\n spaceIndices.add(i);\r\n }\r\n }\r\n\r\n let lastBreakIndex = -1;\r\n\r\n for (let i = 0; i < glyphs.length; i++) {\r\n const glyph = glyphs[i];\r\n const glyphWidth = glyph.xAdvance;\r\n\r\n // Check for newline\r\n if (glyph.char === \"\\n\") {\r\n if (currentLine.length > 0) {\r\n lines.push({\r\n glyphs: currentLine,\r\n width: currentWidth,\r\n y: 0,\r\n });\r\n }\r\n currentLine = [];\r\n currentWidth = 0;\r\n lastBreakIndex = i;\r\n continue;\r\n }\r\n\r\n // Check if adding this glyph would exceed width\r\n if (currentWidth + glyphWidth > width && currentLine.length > 0) {\r\n // Try to break at last space\r\n if (lastBreakIndex > -1) {\r\n // Move glyphs after last space to new line\r\n const breakPoint = lastBreakIndex - (i - currentLine.length) + 1;\r\n const nextLine = currentLine.splice(breakPoint);\r\n\r\n // Recalculate current line width\r\n const lineWidth = currentLine.reduce((sum, g) => sum + g.xAdvance, 0);\r\n\r\n lines.push({\r\n glyphs: currentLine,\r\n width: lineWidth,\r\n y: 0,\r\n });\r\n\r\n currentLine = nextLine;\r\n currentWidth = nextLine.reduce((sum, g) => sum + g.xAdvance, 0);\r\n } else {\r\n // No space found, break at current position\r\n lines.push({\r\n glyphs: currentLine,\r\n width: currentWidth,\r\n y: 0,\r\n });\r\n currentLine = [];\r\n currentWidth = 0;\r\n }\r\n lastBreakIndex = -1;\r\n }\r\n\r\n // Add glyph to current line\r\n currentLine.push(glyph);\r\n currentWidth += glyphWidth;\r\n\r\n // Track spaces for line breaking\r\n if (spaceIndices.has(glyph.cluster)) {\r\n lastBreakIndex = i;\r\n }\r\n }\r\n\r\n // Add remaining glyphs\r\n if (currentLine.length > 0) {\r\n lines.push({\r\n glyphs: currentLine,\r\n width: currentWidth,\r\n y: 0,\r\n });\r\n }\r\n\r\n // Set line Y positions\r\n const lineHeight = params.lineHeight * fontSize;\r\n for (let i = 0; i < lines.length; i++) {\r\n lines[i].y = (i + 1) * lineHeight;\r\n }\r\n\r\n return lines;\r\n }\r\n}\r\n","import { GradientSpec } from \"../types\";\r\n\r\nexport function gradientSpecFrom(\r\n g: { type: \"linear\" | \"radial\"; angle: number; stops: { offset: number; color: string }[] },\r\n opacity: number\r\n): GradientSpec {\r\n if (g.type === \"linear\") {\r\n return { kind: \"linear\", angle: g.angle, stops: g.stops, opacity };\r\n } else {\r\n return { kind: \"radial\", stops: g.stops, opacity };\r\n }\r\n}\r\n","export function decorationGeometry(\r\n kind: \"underline\" | \"line-through\",\r\n p: { baselineY: number; fontSize: number; lineWidth: number; xStart: number }\r\n) {\r\n const thickness = Math.max(1, Math.round(p.fontSize * 0.05));\r\n let y = p.baselineY + Math.round(p.fontSize * 0.1);\r\n if (kind === \"line-through\") y = p.baselineY - Math.round(p.fontSize * 0.3);\r\n return { x1: p.xStart, x2: p.xStart + p.lineWidth, y, width: thickness };\r\n}\r\n","import { DrawOp, GradientSpec, ShapedLine } from \"../types\";\r\nimport { gradientSpecFrom } from \"./gradients\";\r\nimport { decorationGeometry } from \"./decoration\";\r\n\r\nexport type PaintParams = {\r\n canvas: { width: number; height: number; pixelRatio: number };\r\n textRect: { x: number; y: number; width: number; height: number };\r\n lines: ShapedLine[];\r\n font: { family: string; size: number; weight: string | number; style: string; color: string; opacity: number };\r\n style: {\r\n lineHeight: number;\r\n textDecoration: \"none\" | \"underline\" | \"line-through\";\r\n gradient?: { type: \"linear\" | \"radial\"; angle: number; stops: { offset: number; color: string }[] };\r\n };\r\n stroke?: { width: number; color: string; opacity: number };\r\n shadow?: { offsetX: number; offsetY: number; blur: number; color: string; opacity: number };\r\n align: { horizontal: \"left\" | \"center\" | \"right\"; vertical: \"top\" | \"middle\" | \"bottom\" };\r\n background?: { color?: string; opacity: number; borderRadius: number };\r\n glyphPathProvider: (glyphId: number) => string;\r\n /** UPEM for scaling glyph paths from font units → px */\r\n getUnitsPerEm?: () => number;\r\n};\r\n\r\nexport function buildDrawOps(p: PaintParams): DrawOp[] {\r\n const ops: DrawOp[] = [];\r\n\r\n // Begin frame / background\r\n ops.push({\r\n op: \"BeginFrame\",\r\n width: p.canvas.width,\r\n height: p.canvas.height,\r\n pixelRatio: p.canvas.pixelRatio,\r\n clear: true,\r\n bg: p.background\r\n ? { color: p.background.color, opacity: p.background.opacity, radius: p.background.borderRadius }\r\n : undefined\r\n });\r\n\r\n if (p.lines.length === 0) return ops;\r\n\r\n // Font units → px\r\n const upem = Math.max(1, p.getUnitsPerEm?.() ?? 1000);\r\n const scale = p.font.size / upem;\r\n\r\n // Block metrics\r\n const blockHeight = p.lines[p.lines.length - 1].y;\r\n\r\n // Vertical anchor\r\n let blockY: number;\r\n switch (p.align.vertical) {\r\n case \"top\": blockY = p.font.size; break;\r\n case \"bottom\": blockY = p.textRect.height - blockHeight + p.font.size; break;\r\n case \"middle\":\r\n default: blockY = (p.textRect.height - blockHeight) / 2 + p.font.size; break;\r\n }\r\n\r\n // Fill style (solid or gradient)\r\n const fill: GradientSpec = p.style.gradient\r\n ? gradientSpecFrom(p.style.gradient, 1)\r\n : { kind: \"solid\", color: p.font.color, opacity: p.font.opacity };\r\n\r\n // Decoration/cursor color should match text (for gradient, use the last stop as a representative color)\r\n const decoColor = p.style.gradient\r\n ? p.style.gradient.stops[p.style.gradient.stops.length - 1]?.color ?? p.font.color\r\n : p.font.color;\r\n\r\n // Track global text bounds in world space so painters can build a single gradient\r\n let gMinX = Infinity, gMinY = Infinity, gMaxX = -Infinity, gMaxY = -Infinity;\r\n\r\n for (const line of p.lines) {\r\n // Horizontal anchor\r\n let lineX: number;\r\n switch (p.align.horizontal) {\r\n case \"left\": lineX = 0; break;\r\n case \"right\": lineX = p.textRect.width - line.width; break;\r\n case \"center\":\r\n default: lineX = (p.textRect.width - line.width) / 2; break;\r\n }\r\n\r\n let xCursor = lineX;\r\n const baselineY = blockY + line.y - p.font.size;\r\n\r\n for (const glyph of line.glyphs) {\r\n const path = p.glyphPathProvider(glyph.id);\r\n if (!path || path === \"M 0 0\") {\r\n xCursor += glyph.xAdvance;\r\n continue;\r\n }\r\n\r\n const glyphX = xCursor + glyph.xOffset;\r\n const glyphY = baselineY + glyph.yOffset;\r\n\r\n // Update global bbox using path's local bounds mapped to world (scale s, flip Y)\r\n const pb = computePathBounds(path);\r\n const x1 = glyphX + scale * pb.x;\r\n const x2 = glyphX + scale * (pb.x + pb.w);\r\n const y1 = glyphY - scale * (pb.y + pb.h);\r\n const y2 = glyphY - scale * pb.y;\r\n if (x1 < gMinX) gMinX = x1;\r\n if (y1 < gMinY) gMinY = y1;\r\n if (x2 > gMaxX) gMaxX = x2;\r\n if (y2 > gMaxY) gMaxY = y2;\r\n\r\n // 1) Shadow (under everything)\r\n if (p.shadow && p.shadow.blur > 0) {\r\n ops.push({\r\n isShadow: true,\r\n op: \"FillPath\",\r\n path,\r\n x: glyphX + p.shadow.offsetX,\r\n y: glyphY + p.shadow.offsetY,\r\n // @ts-ignore scale propagated to painters\r\n scale,\r\n fill: { kind: \"solid\", color: p.shadow.color, opacity: p.shadow.opacity }\r\n } as any);\r\n }\r\n\r\n // 2) Stroke (under fill)\r\n if (p.stroke && p.stroke.width > 0) {\r\n ops.push({\r\n op: \"StrokePath\",\r\n path,\r\n x: glyphX,\r\n y: glyphY,\r\n // @ts-ignore scale propagated to painters\r\n scale,\r\n width: p.stroke.width,\r\n color: p.stroke.color,\r\n opacity: p.stroke.opacity\r\n } as any);\r\n }\r\n\r\n // 3) Fill (on top)\r\n ops.push({\r\n op: \"FillPath\",\r\n path,\r\n x: glyphX,\r\n y: glyphY,\r\n // @ts-ignore scale propagated to painters\r\n scale,\r\n fill\r\n } as any);\r\n\r\n xCursor += glyph.xAdvance;\r\n }\r\n\r\n // Decoration lines (use text/deco color)\r\n if (p.style.textDecoration !== \"none\") {\r\n const deco = decorationGeometry(p.style.textDecoration, {\r\n baselineY,\r\n fontSize: p.font.size,\r\n lineWidth: line.width,\r\n xStart: lineX\r\n });\r\n\r\n ops.push({\r\n op: \"DecorationLine\",\r\n from: { x: deco.x1, y: deco.y },\r\n to: { x: deco.x2, y: deco.y },\r\n width: deco.width,\r\n color: decoColor,\r\n opacity: p.font.opacity\r\n });\r\n }\r\n }\r\n\r\n // Attach a full-text gradient bbox to all glyph fills (stable across typewriter)\r\n if (gMinX !== Infinity) {\r\n const gbox = { x: gMinX, y: gMinY, w: Math.max(1, gMaxX - gMinX), h: Math.max(1, gMaxY - gMinY) };\r\n for (const op of ops) {\r\n if (op.op === \"FillPath\" && !(op as any).isShadow) {\r\n (op as any).gradientBBox = gbox;\r\n }\r\n }\r\n }\r\n\r\n return ops;\r\n}\r\n\r\n/* ----------------- local helpers ----------------- */\r\nfunction tokenizePath(d: string): string[] {\r\n return d.match(/[MLCQZ]|-?\\d*\\.?\\d+(?:e[-+]?\\d+)?/gi) ?? [];\r\n}\r\nfunction computePathBounds(d: string) {\r\n const t = tokenizePath(d);\r\n let i = 0;\r\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\r\n const touch = (x: number, y: number) => { if (x < minX) minX = x; if (y < minY) minY = y; if (x > maxX) maxX = x; if (y > maxY) maxY = y; };\r\n while (i < t.length) {\r\n const cmd = t[i++];\r\n switch (cmd) {\r\n case \"M\":\r\n case \"L\": { const x = parseFloat(t[i++]); const y = parseFloat(t[i++]); touch(x, y); break; }\r\n case \"C\": {\r\n const c1x = parseFloat(t[i++]); const c1y = parseFloat(t[i++]);\r\n const c2x = parseFloat(t[i++]); const c2y = parseFloat(t[i++]);\r\n const x = parseFloat(t[i++]); const y = parseFloat(t[i++]);\r\n touch(c1x, c1y); touch(c2x, c2y); touch(x, y); break;\r\n }\r\n case \"Q\": { const cx = parseFloat(t[i++]); const cy = parseFloat(t[i++]); const x = parseFloat(t[i++]); const y = parseFloat(t[i++]); touch(cx, cy); touch(x, y); break; }\r\n case \"Z\": break;\r\n }\r\n }\r\n if (minX === Infinity) return { x: 0, y: 0, w: 0, h: 0 };\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n","import { DrawOp, Glyph, ShapedLine } from \"../types\";\r\n\r\nexport type AnimationInput = {\r\n preset?: \"typewriter\" | \"fadeIn\" | \"slideIn\" | \"shift\" | \"ascend\" | \"movingLetters\";\r\n speed: number;\r\n duration?: number;\r\n style?: \"character\" | \"word\";\r\n direction?: \"left\" | \"right\" | \"up\" | \"down\";\r\n};\r\n\r\nconst DECORATION_DONE_THRESHOLD = 0.999;\r\n\r\nexport function applyAnimation(\r\n ops: DrawOp[],\r\n lines: ShapedLine[],\r\n p: { t: number; fontSize: number; anim?: AnimationInput }\r\n): DrawOp[] {\r\n if (!p.anim || !p.anim.preset) return ops;\r\n\r\n const { preset } = p.anim;\r\n const totalGlyphs = lines.reduce((s, l) => s + l.glyphs.length, 0);\r\n const duration = p.anim.duration ?? Math.max(0.3, totalGlyphs / 30 / p.anim.speed);\r\n const progress = Math.max(0, Math.min(1, p.t / duration));\r\n\r\n switch (preset) {\r\n case \"typewriter\":\r\n return applyTypewriterAnimation(\r\n ops,\r\n lines,\r\n progress,\r\n p.anim.style,\r\n p.fontSize,\r\n p.t,\r\n duration\r\n );\r\n case \"fadeIn\":\r\n return applyFadeInAnimation(ops, progress);\r\n case \"slideIn\":\r\n return applySlideInAnimation(ops, progress, p.anim.direction ?? \"left\", p.fontSize);\r\n case \"shift\":\r\n return applyShiftAnimation(\r\n ops,\r\n lines,\r\n progress,\r\n p.anim.direction ?? \"left\",\r\n p.fontSize,\r\n p.anim.style,\r\n duration\r\n );\r\n case \"ascend\":\r\n return applyAscendAnimation(\r\n ops,\r\n lines,\r\n progress,\r\n p.anim.direction ?? \"up\",\r\n p.fontSize,\r\n duration\r\n );\r\n case \"movingLetters\":\r\n return applyMovingLettersAnimation(ops, progress, p.anim.direction ?? \"up\", p.fontSize);\r\n default:\r\n return ops;\r\n }\r\n}\r\n\r\n// ---- helpers\r\nconst isShadowFill = (op: DrawOp) => op.op === \"FillPath\" && (op as any).isShadow === true;\r\nconst isGlyphFill = (op: DrawOp) => op.op === \"FillPath\" && !(op as any).isShadow === true;\r\n\r\n// Try to derive a text color from the first fill we find\r\nfunction getTextColorFromOps(ops: DrawOp[]): string {\r\n for (const op of ops) {\r\n if (op.op === \"FillPath\") {\r\n const fill: any = (op as any).fill;\r\n if (fill?.kind === \"solid\") return fill.color;\r\n if (\r\n (fill?.kind === \"linear\" || fill?.kind === \"radial\") &&\r\n Array.isArray(fill.stops) &&\r\n fill.stops.length\r\n ) {\r\n return fill.stops[fill.stops.length - 1].color || \"#000000\";\r\n }\r\n }\r\n }\r\n return \"#000000\";\r\n}\r\n\r\n// ---------- TYPEWRITER ----------\r\nfunction applyTypewriterAnimation(\r\n ops: DrawOp[],\r\n lines: ShapedLine[],\r\n progress: number,\r\n style: \"character\" | \"word\" | undefined,\r\n fontSize: number,\r\n time: number,\r\n duration: number\r\n): DrawOp[] {\r\n const byWord = style === \"word\";\r\n\r\n if (byWord) {\r\n const wordSegments = getWordSegments(lines);\r\n const totalWords = wordSegments.length;\r\n const visibleWords = Math.floor(progress * totalWords);\r\n if (visibleWords === 0) return ops.filter((x) => x.op === \"BeginFrame\");\r\n\r\n let totalVisibleGlyphs = 0;\r\n for (let i = 0; i < Math.min(visibleWords, wordSegments.length); i++) {\r\n totalVisibleGlyphs += wordSegments[i].glyphCount;\r\n }\r\n const visibleOpsRaw = sliceGlyphOps(ops, totalVisibleGlyphs);\r\n\r\n const visibleOps =\r\n progress >= DECORATION_DONE_THRESHOLD\r\n ? visibleOpsRaw\r\n : visibleOpsRaw.filter((o) => o.op !== \"DecorationLine\");\r\n\r\n if (progress < 1 && totalVisibleGlyphs > 0) {\r\n return addTypewriterCursor(visibleOps, totalVisibleGlyphs, fontSize, time);\r\n }\r\n return visibleOps;\r\n } else {\r\n const totalGlyphs = lines.reduce((s, l) => s + l.glyphs.length, 0);\r\n const visibleGlyphs = Math.floor(progress * totalGlyphs);\r\n if (visibleGlyphs === 0) return ops.filter((x) => x.op === \"BeginFrame\");\r\n\r\n const visibleOpsRaw = sliceGlyphOps(ops, visibleGlyphs);\r\n\r\n const visibleOps =\r\n progress >= DECORATION_DONE_THRESHOLD\r\n ? visibleOpsRaw\r\n : visibleOpsRaw.filter((o) => o.op !== \"DecorationLine\");\r\n\r\n if (progress < 1 && visibleGlyphs > 0) {\r\n return addTypewriterCursor(visibleOps, visibleGlyphs, fontSize, time);\r\n }\r\n return visibleOps;\r\n }\r\n}\r\n\r\n// ---------- ASCEND ----------\r\nfunction applyAscendAnimation(\r\n ops: DrawOp[],\r\n lines: ShapedLine[],\r\n progress: number,\r\n direction: \"left\" | \"right\" | \"up\" | \"down\",\r\n fontSize: number,\r\n duration: number\r\n): DrawOp[] {\r\n const wordSegments = getWordSegments(lines);\r\n const totalWords = wordSegments.length;\r\n if (totalWords === 0) return ops;\r\n\r\n const result: DrawOp[] = [];\r\n let glyphIndex = 0;\r\n\r\n for (const op of ops) {\r\n if (op.op === \"BeginFrame\") {\r\n result.push(op);\r\n break;\r\n }\r\n }\r\n\r\n for (const op of ops) {\r\n if (op.op === \"FillPath\" || op.op === \"StrokePath\") {\r\n // which word owns this glyph\r\n let wordIndex = -1,\r\n acc = 0;\r\n for (let i = 0; i < wordSegments.length; i++) {\r\n const gcount = wordSegments[i].glyphCount;\r\n if (glyphIndex >= acc && glyphIndex < acc + gcount) {\r\n wordIndex = i;\r\n break;\r\n }\r\n acc += gcount;\r\n }\r\n if (wordIndex >= 0) {\r\n const startF = (wordIndex / Math.max(1, totalWords)) * (duration / duration);\r\n const endF = Math.min(1, startF + 0.3);\r\n if (progress >= endF) {\r\n result.push(op);\r\n } else if (progress > startF) {\r\n const local = (progress - startF) / Math.max(1e-6, endF - startF);\r\n const ease = easeOutCubic(Math.min(1, local));\r\n const startOffset = direction === \"up\" ? fontSize * 0.4 : -fontSize * 0.4;\r\n const animated: any = { ...op, y: op.y + startOffset * (1 - ease) };\r\n if (op.op === \"FillPath\") {\r\n if (animated.fill.kind === \"solid\")\r\n animated.fill = { ...animated.fill, opacity: animated.fill.opacity * ease };\r\n else animated.fill = { ...animated.fill, opacity: (animated.fill.opacity ?? 1) * ease };\r\n } else {\r\n animated.opacity = animated.opacity * ease;\r\n }\r\n result.push(animated);\r\n }\r\n }\r\n if (isGlyphFill(op)) glyphIndex++;\r\n } else if (op.op === \"DecorationLine\") {\r\n if (progress >= DECORATION_DONE_THRESHOLD) {\r\n result.push(op);\r\n }\r\n }\r\n }\r\n return result;\r\n}\r\n\r\n// ---------- SHIFT ----------\r\nfunction applyShiftAnimation(\r\n ops: DrawOp[],\r\n lines: ShapedLine[],\r\n progress: number,\r\n direction: \"left\" | \"right\" | \"up\" | \"down\",\r\n fontSize: number,\r\n style: \"character\" | \"word\" | undefined,\r\n duration: number\r\n): DrawOp[] {\r\n const byWord = style === \"word\";\r\n const startOffsets = {\r\n left: { x: fontSize * 0.6, y: 0 },\r\n right: { x: -fontSize * 0.6, y: 0 },\r\n up: { x: 0, y: fontSize * 0.6 },\r\n down: { x: 0, y: -fontSize * 0.6 },\r\n };\r\n const offset = startOffsets[direction];\r\n\r\n const wordSegments = byWord ? getWordSegments(lines) : [];\r\n const totalGlyphs = lines.reduce((s, l) => s + l.glyphs.length, 0);\r\n const totalUnits = byWord ? wordSegments.length : totalGlyphs;\r\n if (totalUnits === 0) return ops;\r\n\r\n const result: DrawOp[] = [];\r\n for (const op of ops) {\r\n if (op.op === \"BeginFrame\") {\r\n result.push(op);\r\n break;\r\n }\r\n }\r\n\r\n const windowDuration = 0.3; // each unit animates for 0.3s of total duration\r\n const overlapFactor = 0.7; // overlapping reveal\r\n const staggerDelay = (duration * overlapFactor) / Math.max(1, totalUnits - 1);\r\n\r\n const windowFor = (unitIdx: number) => {\r\n const startTime = unitIdx * staggerDelay;\r\n const startF = startTime / duration;\r\n const endF = Math.min(1, (startTime + windowDuration) / duration);\r\n return { startF, endF };\r\n };\r\n\r\n let glyphIndex = 0;\r\n for (const op of ops) {\r\n if (op.op !== \"FillPath\" && op.op !== \"StrokePath\") {\r\n if (op.op === \"DecorationLine\" && progress > 0.8) result.push(op);\r\n continue;\r\n }\r\n\r\n let unitIndex: number;\r\n if (!byWord) {\r\n unitIndex = glyphIndex;\r\n } else {\r\n let wordIndex = -1,\r\n acc = 0;\r\n for (let i = 0; i < wordSegments.length; i++) {\r\n const gcount = wordSegments[i].glyphCount;\r\n if (glyphIndex >= acc && glyphIndex < acc + gcount) {\r\n wordIndex = i;\r\n break;\r\n }\r\n acc += gcount;\r\n }\r\n unitIndex = Math.max(0, wordIndex);\r\n }\r\n\r\n const { startF, endF } = windowFor(unitIndex);\r\n\r\n if (progress <= startF) {\r\n const animated: any = { ...op, x: op.x + offset.x, y: op.y + offset.y };\r\n if (op.op === \"FillPath\") {\r\n if (animated.fill.kind === \"solid\") animated.fill = { ...animated.fill, opacity: 0 };\r\n else animated.fill = { ...animated.fill, opacity: 0 };\r\n } else {\r\n animated.opacity = 0;\r\n }\r\n result.push(animated);\r\n } else if (progress >= endF) {\r\n result.push(op);\r\n } else {\r\n const local = (progress - startF) / Math.max(1e-6, endF - startF);\r\n const ease = easeOutCubic(Math.min(1, local));\r\n const dx = offset.x * (1 - ease);\r\n const dy = offset.y * (1 - ease);\r\n const animated: any = { ...op, x: op.x + dx, y: op.y + dy };\r\n\r\n if (op.op === \"FillPath\") {\r\n const targetOpacity =\r\n animated.fill.kind === \"solid\" ? animated.fill.opacity : animated.fill.opacity ?? 1;\r\n if (animated.fill.kind === \"solid\")\r\n animated.fill = { ...animated.fill, opacity: targetOpacity * ease };\r\n else animated.fill = { ...animated.fill, opacity: targetOpacity * ease };\r\n } else {\r\n animated.opacity = animated.opacity * ease;\r\n }\r\n result.push(animated);\r\n }\r\n\r\n if (isGlyphFill(op)) glyphIndex++;\r\n }\r\n return result;\r\n}\r\n\r\n// ---------- FADE / SLIDE / WAVE ----------\r\nfunction applyFadeInAnimation(ops: DrawOp[], progress: number): DrawOp[] {\r\n const alpha = easeOutQuad(progress);\r\n const scale = 0.95 + 0.05 * alpha;\r\n return scaleAndFade(ops, alpha, scale);\r\n}\r\nfunction applySlideInAnimation(\r\n ops: DrawOp[],\r\n progress: number,\r\n direction: \"left\" | \"right\" | \"up\" | \"down\",\r\n fontSize: number\r\n): DrawOp[] {\r\n const easeProgress = easeOutCubic(progress);\r\n const shift = shiftFor(1 - easeProgress, direction, fontSize * 2);\r\n const alpha = easeOutQuad(progress);\r\n return translateGlyphOps(ops, shift.dx, shift.dy, alpha);\r\n}\r\nfunction applyMovingLettersAnimation(\r\n ops: DrawOp[],\r\n progress: number,\r\n direction: \"left\" | \"right\" | \"up\" | \"down\",\r\n fontSize: number\r\n): DrawOp[] {\r\n const amp = fontSize * 0.3;\r\n return waveTransform(ops, direction, amp, progress);\r\n}\r\n\r\n// ---------- word segmentation / slicing ----------\r\nfunction getWordSegments(lines: ShapedLine[]) {\r\n const segments: any = [];\r\n let totalGlyphIndex = 0;\r\n for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {\r\n const line = lines[lineIndex];\r\n const words = segmentLineBySpaces(line);\r\n for (const word of words) {\r\n if (word.length > 0)\r\n segments.push({ startGlyph: totalGlyphIndex, glyphCount: word.length, lineIndex });\r\n totalGlyphIndex += word.length;\r\n }\r\n }\r\n return segments;\r\n}\r\nfunction segmentLineBySpaces(line: ShapedLine): Glyph[][] {\r\n const words: Glyph[][] = [];\r\n let current: Glyph[] = [];\r\n for (const g of line.glyphs) {\r\n const isSpace = g.char === \" \" || g.char === \"\\t\" || g.char === \"\\n\";\r\n if (isSpace) {\r\n if (current.length) {\r\n words.push([...current]);\r\n current = [];\r\n }\r\n } else {\r\n current.push(g);\r\n }\r\n }\r\n if (current.length) words.push(current);\r\n return words;\r\n}\r\n\r\n/** Include BOTH stroke+fill for the first `maxGlyphs` glyphs; nothing from later glyphs.\r\n * Stroke is only included if its corresponding fill will be shown (so it never appears early). */\r\nfunction sliceGlyphOps(ops: DrawOp[], maxGlyphs: number): DrawOp[] {\r\n const result: DrawOp[] = [];\r\n let glyphCount = 0;\r\n let foundGlyphs = false;\r\n\r\n for (const op of ops) {\r\n if (op.op === \"BeginFrame\") {\r\n result.push(op);\r\n continue;\r\n }\r\n\r\n if (op.op === \"FillPath\" && !isShadowFill(op)) {\r\n if (glyphCount < maxGlyphs) {\r\n result.push(op);\r\n foundGlyphs = true;\r\n }\r\n glyphCount++; // count only real glyph fills\r\n continue;\r\n }\r\n\r\n if (op.op === \"StrokePath\") {\r\n // Include stroke only if the upcoming fill is within range\r\n if (glyphCount < maxGlyphs) result.push(op);\r\n continue;\r\n }\r\n\r\n if (op.op === \"FillPath\" && isShadowFill(op)) {\r\n if (glyphCount < maxGlyphs) result.push(op);\r\n continue;\r\n }\r\n\r\n if (op.op === \"DecorationLine\" && foundGlyphs) {\r\n result.push(op);\r\n continue;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction addTypewriterCursor(\r\n ops: DrawOp[],\r\n glyphCount: number,\r\n fontSize: number,\r\n time: number\r\n): DrawOp[] {\r\n const blinkRate = 2;\r\n const cursorVisible = Math.floor(time * blinkRate * 2) % 2 === 0;\r\n if (!cursorVisible || glyphCount === 0) return ops;\r\n\r\n let last: DrawOp | null = null;\r\n let count = 0;\r\n for (const op of ops) {\r\n if (op.op === \"FillPath\" && !isShadowFill(op)) {\r\n count++;\r\n if (count === glyphCount) {\r\n last = op;\r\n break;\r\n }\r\n }\r\n }\r\n if (last && last.op === \"FillPath\") {\r\n const color = getTextColorFromOps(ops);\r\n const cursorX = last.x + fontSize * 0.5;\r\n const cursorY = last.y;\r\n\r\n const cursorOp: DrawOp = {\r\n op: \"DecorationLine\",\r\n from: { x: cursorX, y: cursorY - fontSize * 0.7 },\r\n to: { x: cursorX, y: cursorY + fontSize * 0.1 },\r\n width: Math.max(2, fontSize / 25),\r\n color,\r\n opacity: 1,\r\n };\r\n return [...ops, cursorOp];\r\n }\r\n return ops;\r\n}\r\n\r\n// ---------- transforms ----------\r\nfunction scaleAndFade(ops: DrawOp[], alpha: number, scale: number): DrawOp[] {\r\n let cx = 0,\r\n cy = 0,\r\n n = 0;\r\n ops.forEach((op) => {\r\n if (op.op === \"FillPath\") {\r\n cx += op.x;\r\n cy += op.y;\r\n n++;\r\n }\r\n });\r\n if (n > 0) {\r\n cx /= n;\r\n cy /= n;\r\n }\r\n\r\n return ops.map((op) => {\r\n if (op.op === \"FillPath\") {\r\n const out: any = { ...op };\r\n if (out.fill.kind === \"solid\") out.fill = { ...out.fill, opacity: out.fill.opacity * alpha };\r\n else out.fill = { ...out.fill, opacity: (out.fill.opacity ?? 1) * alpha };\r\n if (scale !== 1 && n > 0) {\r\n const dx = op.x - cx,\r\n dy = op.y - cy;\r\n out.x = cx + dx * scale;\r\n out.y = cy + dy * scale;\r\n }\r\n return out;\r\n }\r\n if (op.op === \"StrokePath\") {\r\n const out: any = { ...op, opacity: op.opacity * alpha };\r\n if (scale !== 1 && n > 0) {\r\n const dx = op.x - cx,\r\n dy = op.y - cy;\r\n out.x = cx + dx * scale;\r\n out.y = cy + dy * scale;\r\n }\r\n return out;\r\n }\r\n if (op.op === \"DecorationLine\") return { ...op, opacity: op.opacity * alpha };\r\n return op;\r\n });\r\n}\r\n\r\nfunction translateGlyphOps(ops: DrawOp[], dx: number, dy: number, alpha: number = 1): DrawOp[] {\r\n return ops.map((op) => {\r\n if (op.op === \"FillPath\") {\r\n const out: any = { ...op, x: op.x + dx, y: op.y + dy };\r\n if (alpha < 1) {\r\n if (out.fill.kind === \"solid\")\r\n out.fill = { ...out.fill, opacity: out.fill.opacity * alpha };\r\n else out.fill = { ...out.fill, opacity: (out.fill.opacity ?? 1) * alpha };\r\n }\r\n return out;\r\n }\r\n if (op.op === \"StrokePath\")\r\n return { ...op, x: op.x + dx, y: op.y + dy, opacity: op.opacity * alpha };\r\n if (op.op === \"DecorationLine\") {\r\n return {\r\n ...op,\r\n from: { x: op.from.x + dx, y: op.from.y + dy },\r\n to: { x: op.to.x + dx, y: op.to.y + dy },\r\n opacity: op.opacity * alpha,\r\n };\r\n }\r\n return op;\r\n });\r\n}\r\n\r\nfunction waveTransform(\r\n ops: DrawOp[],\r\n dir: \"left\" | \"right\" | \"up\" | \"down\",\r\n amp: number,\r\n p: number\r\n): DrawOp[] {\r\n let glyphIndex = 0;\r\n return ops.map((op) => {\r\n if (op.op === \"FillPath\" || op.op === \"StrokePath\") {\r\n const phase = Math.sin((glyphIndex / 5) * Math.PI + p * Math.PI * 4);\r\n const dx = dir === \"left\" || dir === \"right\" ? phase * amp * (dir === \"left\" ? -1 : 1) : 0;\r\n const dy = dir === \"up\" || dir === \"down\" ? phase * amp * (dir === \"up\" ? -1 : 1) : 0;\r\n const waveAlpha = Math.min(1, p * 2);\r\n if (op.op === \"FillPath\") {\r\n if (!isShadowFill(op)) glyphIndex++;\r\n const out: any = { ...op, x: op.x + dx, y: op.y + dy };\r\n if (out.fill.kind === \"solid\")\r\n out.fill = { ...out.fill, opacity: out.fill.opacity * waveAlpha };\r\n else out.fill = { ...out.fill, opacity: (out.fill.opacity ?? 1) * waveAlpha };\r\n return out;\r\n }\r\n return { ...op, x: op.x + dx, y: op.y + dy, opacity: op.opacity * waveAlpha };\r\n }\r\n return op;\r\n });\r\n}\r\n\r\n// ---------- misc ----------\r\nfunction shiftFor(progress: number, dir: \"left\" | \"right\" | \"up\" | \"down\", dist: number) {\r\n const d = progress * dist;\r\n switch (dir) {\r\n case \"left\":\r\n return { dx: -d, dy: 0 };\r\n case \"right\":\r\n return { dx: d, dy: 0 };\r\n case \"up\":\r\n return { dx: 0, dy: -d };\r\n case \"down\":\r\n return { dx: 0, dy: d };\r\n }\r\n}\r\nfunction easeOutQuad(t: number) {\r\n return t * (2 - t);\r\n}\r\nfunction easeOutCubic(t: number) {\r\n return 1 - Math.pow(1 - t, 3);\r\n}\r\nfunction easeInOutQuad(t: number) {\r\n return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;\r\n}\r\n","import { RGBA } from \"../types\";\r\n\r\nexport function parseHex6(hex: string, alpha = 1): RGBA {\r\n const m = /^#?([a-f0-9]{6})$/i.exec(hex);\r\n if (!m) throw new Error(`Invalid color ${hex}`);\r\n const n = parseInt(m[1], 16);\r\n const r = (n >> 16) & 0xff;\r\n const g = (n >> 8) & 0xff;\r\n const b = n & 0xff;\r\n return { r, g, b, a: alpha };\r\n}\r\n","import type { DrawOp, GradientSpec } from \"../types\";\r\nimport { parseHex6 } from \"../core/colors\";\r\n\r\n/* eslint-disable @typescript-eslint/no-explicit-any */\r\n\r\nexport function createWebPainter(canvas: HTMLCanvasElement | OffscreenCanvas) {\r\n // @ts-ignore\r\n const ctx: CanvasRenderingContext2D = (canvas as any).getContext(\"2d\");\r\n if (!ctx) throw new Error(\"2D context unavailable\");\r\n\r\n return {\r\n async render(ops: DrawOp[]) {\r\n const globalBox = computeGlobalTextBounds(ops);\r\n\r\n for (const op of ops) {\r\n if (op.op === \"BeginFrame\") {\r\n const dpr = op.pixelRatio;\r\n const w = op.width,\r\n h = op.height;\r\n\r\n if (\"width\" in canvas && \"height\" in canvas) {\r\n (canvas as any).width = Math.floor(w * dpr);\r\n (canvas as any).height = Math.floor(h * dpr);\r\n }\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n\r\n if (op.clear) ctx.clearRect(0, 0, w, h);\r\n if (op.bg) {\r\n const { color, opacity, radius } = op.bg;\r\n if (color) {\r\n const c = parseHex6(color, opacity);\r\n ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;\r\n if (radius && radius > 0) {\r\n drawRoundedRect(ctx, 0, 0, w, h, radius);\r\n ctx.fill();\r\n } else {\r\n ctx.fillRect(0, 0, w, h);\r\n }\r\n }\r\n }\r\n continue;\r\n }\r\n\r\n if (op.op === \"FillPath\") {\r\n const p = new Path2D(op.path);\r\n ctx.save();\r\n ctx.translate(op.x, op.y);\r\n\r\n const s = (op as any).scale ?? 1;\r\n ctx.scale(s, -s);\r\n\r\n const bbox = (op as any).gradientBBox ?? globalBox;\r\n const fill = makeGradientFromBBox(ctx, op.fill, bbox);\r\n ctx.fillStyle = fill as any;\r\n ctx.fill(p);\r\n ctx.restore();\r\n continue;\r\n }\r\n\r\n if (op.op === \"StrokePath\") {\r\n const p = new Path2D(op.path);\r\n ctx.save();\r\n ctx.translate(op.x, op.y);\r\n\r\n const s = (op as any).scale ?? 1;\r\n ctx.scale(s, -s);\r\n const invAbs = 1 / Math.abs(s);\r\n\r\n const c = parseHex6((op as any).color, (op as any).opacity);\r\n ctx.strokeStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;\r\n ctx.lineWidth = (op as any).width * invAbs;\r\n ctx.lineJoin = \"round\";\r\n ctx.lineCap = \"round\";\r\n ctx.stroke(p);\r\n ctx.restore();\r\n continue;\r\n }\r\n\r\n if (op.op === \"DecorationLine\") {\r\n ctx.save();\r\n const c = parseHex6((op as any).color, (op as any).opacity);\r\n ctx.strokeStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;\r\n ctx.lineWidth = (op as any).width;\r\n ctx.beginPath();\r\n ctx.moveTo((op as any).from.x, (op as any).from.y);\r\n ctx.lineTo((op as any).to.x, (op as any).to.y);\r\n ctx.stroke();\r\n ctx.restore();\r\n continue;\r\n }\r\n }\r\n },\r\n };\r\n}\r\n\r\nfunction drawRoundedRect(\r\n ctx: CanvasRenderingContext2D,\r\n x: number,\r\n y: number,\r\n w: number,\r\n h: number,\r\n r: number\r\n) {\r\n const p = new Path2D();\r\n p.moveTo(x + r, y);\r\n p.arcTo(x + w, y, x + w, y + h, r);\r\n p.arcTo(x + w, y + h, x, y + h, r);\r\n p.arcTo(x, y + h, x, y, r);\r\n p.arcTo(x, y, x + w, y, r);\r\n p.closePath();\r\n ctx.save();\r\n ctx.fill(p);\r\n ctx.restore();\r\n}\r\n\r\nfunction makeGradientFromBBox(\r\n ctx: CanvasRenderingContext2D,\r\n spec: GradientSpec,\r\n box: { x: number; y: number; w: number; h: number }\r\n): CanvasGradient | string {\r\n if (spec.kind === \"solid\") {\r\n const c = parseHex6((spec as any).color, (spec as any).opacity);\r\n return `rgba(${c.r},${c.g},${c.b},${c.a})`;\r\n }\r\n const cx = box.x + box.w / 2,\r\n cy = box.y + box.h / 2,\r\n r = Math.max(box.w, box.h) / 2;\r\n const addStops = (g: CanvasGradient) => {\r\n const op = (spec as any).opacity ?? 1;\r\n for (const s of (spec as any).stops) {\r\n const c = parseHex6(s.color, op);\r\n g.addColorStop(s.offset, `rgba(${c.r},${c.g},${c.b},${c.a})`);\r\n }\r\n return g;\r\n };\r\n if (spec.kind === \"linear\") {\r\n const rad = (((spec as any).angle || 0) * Math.PI) / 180;\r\n const x1 = cx + Math.cos(rad + Math.PI) * r;\r\n const y1 = cy + Math.sin(rad + Math.PI) * r;\r\n const x2 = cx + Math.cos(rad) * r;\r\n const y2 = cy + Math.sin(rad) * r;\r\n return addStops(ctx.createLinearGradient(x1, y1, x2, y2));\r\n } else {\r\n return addStops(ctx.createRadialGradient(cx, cy, 0, cx, cy, r));\r\n }\r\n}\r\n\r\nfunction computeGlobalTextBounds(ops: DrawOp[]) {\r\n let minX = Infinity,\r\n minY = Infinity,\r\n maxX = -Infinity,\r\n maxY = -Infinity;\r\n for (const op of ops) {\r\n if (op.op !== \"FillPath\" || (op as any).isShadow) continue;\r\n const b = computePathBounds(op.path);\r\n const s = (op as any).scale ?? 1;\r\n const x1 = op.x + s * b.x;\r\n const x2 = op.x + s * (b.x + b.w);\r\n const y1 = op.y - s * (b.y + b.h);\r\n const y2 = op.y - s * b.y;\r\n if (x1 < minX) minX = x1;\r\n if (y1 < minY) minY = y1;\r\n if (x2 > maxX) maxX = x2;\r\n if (y2 > maxY) maxY = y2;\r\n }\r\n if (minX === Infinity) return { x: 0, y: 0, w: 1, h: 1 };\r\n return { x: minX, y: minY, w: Math.max(1, maxX - minX), h: Math.max(1, maxY - minY) };\r\n}\r\n\r\nfunction computePathBounds(d: string) {\r\n const tokens = tokenizePath(d);\r\n let i = 0;\r\n let minX = Infinity,\r\n minY = Infinity,\r\n maxX = -Infinity,\r\n maxY = -Infinity;\r\n const touch = (x: number, y: number) => {\r\n if (x < minX) minX = x;\r\n if (y < minY) minY = y;\r\n if (x > maxX) maxX = x;\r\n if (y > maxY) maxY = y;\r\n };\r\n while (i < tokens.length) {\r\n const t = tokens[i++];\r\n switch (t) {\r\n case \"M\":\r\n case \"L\": {\r\n const x = parseFloat(tokens[i++]);\r\n const y = parseFloat(tokens[i++]);\r\n touch(x, y);\r\n break;\r\n }\r\n case \"C\": {\r\n const c1x = parseFloat(tokens[i++]);\r\n const c1y = parseFloat(tokens[i++]);\r\n const c2x = parseFloat(tokens[i++]);\r\n const c2y = parseFloat(tokens[i++]);\r\n const x = parseFloat(tokens[i++]);\r\n const y = parseFloat(tokens[i++]);\r\n touch(c1x, c1y);\r\n touch(c2x, c2y);\r\n touch(x, y);\r\n break;\r\n }\r\n case \"Q\": {\r\n const cx = parseFloat(tokens[i++]);\r\n const cy = parseFloat(tokens[i++]);\r\n const x = parseFloat(tokens[i++]);\r\n const y = parseFloat(tokens[i++]);\r\n touch(cx, cy);\r\n touch(x, y);\r\n break;\r\n }\r\n case \"Z\":\r\n break;\r\n }\r\n }\r\n if (minX === Infinity) return { x: 0, y: 0, w: 0, h: 0 };\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\nfunction tokenizePath(d: string): string[] {\r\n return d.match(/[MLCQZ]|-?\\d*\\.?\\d+(?:e[-+]?\\d+)?/gi) ?? [];\r\n}\r\n","export async function fetchToArrayBuffer(url: string): Promise<ArrayBuffer> {\r\n const res = await fetch(url);\r\n if (!res.ok) throw new Error(`Failed to fetch ${url}: ${res.status}`);\r\n return await res.arrayBuffer();\r\n}\r\n","// src/env/entry.web.ts\r\nimport { RichTextAssetSchema, type RichTextValidated } from \"../schema/asset-schema\";\r\nimport { CANVAS_CONFIG } from \"../config/canvas-constants\";\r\nimport { FontRegistry } from \"../core/font-registry\";\r\nimport { LayoutEngine } from \"../core/layout\";\r\nimport { buildDrawOps } from \"../core/drawops\";\r\nimport { applyAnimation } from \"../core/animations\";\r\nimport { createWebPainter } from \"../painters/web\";\r\nimport { fetchToArrayBuffer } from \"../io/web\";\r\n\r\nexport async function createTextEngine(\r\n opts: {\r\n width?: number;\r\n height?: number;\r\n pixelRatio?: number;\r\n fps?: number;\r\n wasmBaseURL?: string;\r\n } = {}\r\n) {\r\n const width = opts.width ?? CANVAS_CONFIG.DEFAULTS.width;\r\n const height = opts.height ?? CANVAS_CONFIG.DEFAULTS.height;\r\n const pixelRatio = opts.pixelRatio ?? CANVAS_CONFIG.DEFAULTS.pixelRatio;\r\n const wasmBaseURL = opts.wasmBaseURL;\r\n\r\n const fonts = new FontRegistry(wasmBaseURL);\r\n // initHB via registry as needed\r\n const layout = new LayoutEngine(fonts);\r\n\r\n async function ensureFonts(asset: RichTextValidated) {\r\n // Load custom fonts (bytes) if provided\r\n if (asset.customFonts) {\r\n for (const cf of asset.customFonts) {\r\n const bytes = await fetchToArrayBuffer(cf.src);\r\n await fonts.registerFromBytes(bytes, {\r\n family: cf.family,\r\n weight: cf.weight ?? \"400\",\r\n style: cf.style ?? \"normal\",\r\n });\r\n }\r\n }\r\n // Ensure main font is loaded (if same as custom, already there)\r\n const main = asset.font ?? {\r\n family: \"Roboto\",\r\n weight: \"400\",\r\n style: \"normal\",\r\n size: 48,\r\n color: \"#000000\",\r\n opacity: 1,\r\n };\r\n // No system fonts: require the user to register customFonts for deterministic results.\r\n return main;\r\n }\r\n\r\n return {\r\n validate(input: unknown): { value: RichTextValidated } {\r\n const { value, error } = RichTextAssetSchema.validate(input, {\r\n abortEarly: false,\r\n convert: true,\r\n });\r\n if (error) throw error;\r\n return { value: value as RichTextValidated };\r\n },\r\n async registerFontFromUrl(\r\n url: string,\r\n desc: { family: string; weight?: string | number; style?: string }\r\n ) {\r\n const bytes = await fetchToArrayBuffer(url);\r\n await fonts.registerFromBytes(bytes, desc);\r\n },\r\n async registerFontFromFile(\r\n source: string | Blob,\r\n desc: { family: string; weight?: string | number; style?: string }\r\n ) {\r\n let bytes: ArrayBuffer;\r\n if (typeof source === \"string\") {\r\n bytes = await fetchToArrayBuffer(source);\r\n } else {\r\n bytes = await source.arrayBuffer();\r\n }\r\n await fonts.registerFromBytes(bytes, desc);\r\n },\r\n\r\n async renderFrame(asset: RichTextValidated, tSeconds: number) {\r\n const main = await ensureFonts(asset);\r\n const desc = { family: main.family, weight: `${main.weight}`, style: main.style };\r\n\r\n const lines = layout.layout({\r\n text: asset.text,\r\n width: asset.width ?? width,\r\n letterSpacing: asset.style?.letterSpacing ?? 0,\r\n fontSize: main.size,\r\n lineHeight: asset.style?.lineHeight ?? 1.2,\r\n desc,\r\n textTransform: asset.style?.textTransform ?? \"none\",\r\n });\r\n\r\n const textRect = { x: 0, y: 0, width: asset.width ?? width, height: asset.height ?? height };\r\n const ops0 = buildDrawOps({\r\n canvas: { width, height, pixelRatio },\r\n textRect,\r\n lines,\r\n font: {\r\n family: main.family,\r\n size: main.size,\r\n weight: `${main.weight}`,\r\n style: main.style,\r\n color: main.color,\r\n opacity: main.opacity,\r\n },\r\n style: {\r\n lineHeight: asset.style?.lineHeight ?? 1.2,\r\n textDecoration: asset.style?.textDecoration ?? \"none\",\r\n gradient: asset.style?.gradient,\r\n },\r\n stroke: asset.stroke,\r\n shadow: asset.shadow,\r\n align: asset.align ?? { horizontal: \"left\", vertical: \"middle\" },\r\n background: asset.background,\r\n glyphPathProvider: (gid) => fonts.glyphPath(desc, gid),\r\n /** NEW: provide UPEM so drawops can compute scale */\r\n getUnitsPerEm: () => fonts.getUnitsPerEm(desc),\r\n });\r\n\r\n const ops = applyAnimation(ops0, lines, {\r\n t: tSeconds,\r\n fontSize: main.size,\r\n anim: asset.animation\r\n ? {\r\n preset: asset.animation.preset as any,\r\n speed: asset.animation.speed,\r\n duration: asset.animation.duration,\r\n style: asset.animation.style as any,\r\n direction: asset.animation.direction as any,\r\n }\r\n : undefined,\r\n });\r\n\r\n return ops;\r\n },\r\n createRenderer(canvas: HTMLCanvasElement | OffscreenCanvas) {\r\n return createWebPainter(canvas);\r\n },\r\n };\r\n}\r\n\r\nexport * from \"../types\";\r\n"],"mappings":"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","names":["computePathBounds","tokenizePath"]}
1
+ {"version":3,"sources":["../src/schema/asset-schema.ts","../src/config/canvas-constants.ts","../src/wasm/hb-loader.ts","../src/core/font-registry.ts","../src/core/layout.ts","../src/core/gradients.ts","../src/core/decoration.ts","../src/core/drawops.ts","../src/core/animations.ts","../src/core/colors.ts","../src/painters/web.ts","../src/io/web.ts","../src/env/entry.web.ts"],"sourcesContent":["import Joi from \"joi\";\r\nimport { CANVAS_CONFIG } from \"../config/canvas-constants\";\r\n\r\nconst HEX6 = /^#[A-Fa-f0-9]{6}$/;\r\n\r\nconst gradientSchema = Joi.object({\r\n type: Joi.string().valid(\"linear\", \"radial\").default(\"linear\"),\r\n angle: Joi.number().min(0).max(360).default(0),\r\n stops: Joi.array()\r\n .items(\r\n Joi.object({\r\n offset: Joi.number().min(0).max(1).required(),\r\n color: Joi.string().pattern(HEX6).required()\r\n }).unknown(false)\r\n )\r\n .min(2)\r\n .required()\r\n}).unknown(false);\r\n\r\nconst shadowSchema = Joi.object({\r\n offsetX: Joi.number().default(0),\r\n offsetY: Joi.number().default(0),\r\n blur: Joi.number().min(0).default(0),\r\n color: Joi.string().pattern(HEX6).default(\"#000000\"),\r\n opacity: Joi.number().min(0).max(1).default(0.5)\r\n}).unknown(false);\r\n\r\nconst strokeSchema = Joi.object({\r\n width: Joi.number().min(0).default(0),\r\n color: Joi.string().pattern(HEX6).default(\"#000000\"),\r\n opacity: Joi.number().min(0).max(1).default(1)\r\n}).unknown(false);\r\n\r\nconst fontSchema = Joi.object({\r\n family: Joi.string().default(CANVAS_CONFIG.DEFAULTS.fontFamily),\r\n size: Joi.number()\r\n .min(CANVAS_CONFIG.LIMITS.minFontSize)\r\n .max(CANVAS_CONFIG.LIMITS.maxFontSize)\r\n .default(CANVAS_CONFIG.DEFAULTS.fontSize),\r\n weight: Joi.alternatives().try(Joi.string(), Joi.number()).default(\"400\"),\r\n style: Joi.string().valid(\"normal\", \"italic\", \"oblique\").default(\"normal\"),\r\n color: Joi.string().pattern(HEX6).default(CANVAS_CONFIG.DEFAULTS.color),\r\n opacity: Joi.number().min(0).max(1).default(1)\r\n}).unknown(false);\r\n\r\nconst styleSchema = Joi.object({\r\n letterSpacing: Joi.number().default(0),\r\n lineHeight: Joi.number().min(0).max(10).default(1.2),\r\n textTransform: Joi.string().valid(\"none\", \"uppercase\", \"lowercase\", \"capitalize\").default(\"none\"),\r\n textDecoration: Joi.string().valid(\"none\", \"underline\", \"line-through\").default(\"none\"),\r\n gradient: gradientSchema.optional()\r\n}).unknown(false);\r\n\r\nconst alignmentSchema = Joi.object({\r\n horizontal: Joi.string()\r\n .valid(\"left\", \"center\", \"right\")\r\n .default(CANVAS_CONFIG.DEFAULTS.textAlign),\r\n vertical: Joi.string().valid(\"top\", \"middle\", \"bottom\").default(\"middle\")\r\n}).unknown(false);\r\n\r\nconst animationSchema = Joi.object({\r\n preset: Joi.string().valid(...CANVAS_CONFIG.ANIMATION_TYPES as readonly string[]),\r\n speed: Joi.number().min(0.1).max(10).default(1),\r\n duration: Joi.number()\r\n .min(CANVAS_CONFIG.LIMITS.minDuration)\r\n .max(CANVAS_CONFIG.LIMITS.maxDuration)\r\n .optional(),\r\n style: Joi.string()\r\n .valid(\"character\", \"word\")\r\n .optional()\r\n .when(\"preset\", {\r\n is: Joi.valid(\"typewriter\", \"shift\"),\r\n then: Joi.optional(),\r\n otherwise: Joi.forbidden()\r\n }),\r\n direction: Joi.string()\r\n .optional()\r\n .when(\"preset\", {\r\n switch: [\r\n { is: \"ascend\", then: Joi.valid(\"up\", \"down\") },\r\n { is: \"shift\", then: Joi.valid(\"left\", \"right\", \"up\", \"down\") },\r\n { is: \"slideIn\", then: Joi.valid(\"left\", \"right\", \"up\", \"down\") },\r\n { is: \"movingLetters\", then: Joi.valid(\"left\", \"right\", \"up\", \"down\") }\r\n ],\r\n otherwise: Joi.forbidden()\r\n })\r\n}).unknown(false);\r\n\r\nconst backgroundSchema = Joi.object({\r\n color: Joi.string().pattern(HEX6).optional(),\r\n opacity: Joi.number().min(0).max(1).default(1),\r\n borderRadius: Joi.number().min(0).default(0)\r\n}).unknown(false);\r\n\r\nconst customFontSchema = Joi.object({\r\n src: Joi.string().uri().required(),\r\n family: Joi.string().required(),\r\n weight: Joi.alternatives().try(Joi.string(), Joi.number()).optional(),\r\n style: Joi.string().optional(),\r\n originalFamily: Joi.string().optional()\r\n}).unknown(false);\r\n\r\nexport const RichTextAssetSchema = Joi.object({\r\n type: Joi.string().valid(\"rich-text\").required(),\r\n text: Joi.string().allow(\"\").max(CANVAS_CONFIG.LIMITS.maxTextLength).default(\"\"),\r\n width: Joi.number()\r\n .min(CANVAS_CONFIG.LIMITS.minWidth)\r\n .max(CANVAS_CONFIG.LIMITS.maxWidth)\r\n .default(CANVAS_CONFIG.DEFAULTS.width)\r\n .optional(),\r\n height: Joi.number()\r\n .min(CANVAS_CONFIG.LIMITS.minHeight)\r\n .max(CANVAS_CONFIG.LIMITS.maxHeight)\r\n .default(CANVAS_CONFIG.DEFAULTS.height)\r\n .optional(),\r\n font: fontSchema.optional(),\r\n style: styleSchema.optional(),\r\n stroke: strokeSchema.optional(),\r\n shadow: shadowSchema.optional(),\r\n background: backgroundSchema.optional(),\r\n align: alignmentSchema.optional(),\r\n animation: animationSchema.optional(),\r\n customFonts: Joi.array().items(customFontSchema).optional(),\r\n cacheEnabled: Joi.boolean().default(true),\r\n pixelRatio: Joi.number().min(1).max(3).default(CANVAS_CONFIG.DEFAULTS.pixelRatio)\r\n}).unknown(false);\r\n\r\nexport type RichTextValidated = Required<{\r\n type: \"rich-text\";\r\n text: string;\r\n width?: number;\r\n height?: number;\r\n font?: {\r\n family: string;\r\n size: number;\r\n weight: string | number;\r\n style: \"normal\" | \"italic\" | \"oblique\";\r\n color: string;\r\n opacity: number;\r\n };\r\n style?: {\r\n letterSpacing: number;\r\n lineHeight: number;\r\n textTransform: \"none\" | \"uppercase\" | \"lowercase\" | \"capitalize\";\r\n textDecoration: \"none\" | \"underline\" | \"line-through\";\r\n gradient?: {\r\n type: \"linear\" | \"radial\";\r\n angle: number;\r\n stops: { offset: number; color: string }[];\r\n };\r\n };\r\n stroke?: { width: number; color: string; opacity: number };\r\n shadow?: { offsetX: number; offsetY: number; blur: number; color: string; opacity: number };\r\n background?: { color?: string; opacity: number; borderRadius: number };\r\n align?: { horizontal: \"left\" | \"center\" | \"right\"; vertical: \"top\" | \"middle\" | \"bottom\" };\r\n animation?: {\r\n preset: typeof CANVAS_CONFIG.ANIMATION_TYPES[number];\r\n speed: number;\r\n duration?: number;\r\n style?: \"character\" | \"word\";\r\n direction?: \"left\" | \"right\" | \"up\" | \"down\";\r\n };\r\n customFonts?: { src: string; family: string; weight?: string | number; style?: string; originalFamily?: string }[];\r\n cacheEnabled: boolean;\r\n pixelRatio: number;\r\n}>;\r\n","export const CANVAS_CONFIG = {\r\n DEFAULTS: {\r\n width: 800,\r\n height: 400,\r\n pixelRatio: 2,\r\n fontFamily: \"Roboto\",\r\n fontSize: 48,\r\n color: \"#000000\",\r\n textAlign: \"left\" as const\r\n },\r\n LIMITS: {\r\n minWidth: 1,\r\n maxWidth: 4096,\r\n minHeight: 1,\r\n maxHeight: 4096,\r\n minFontSize: 1,\r\n maxFontSize: 512,\r\n minDuration: 0.1,\r\n maxDuration: 120,\r\n maxTextLength: 10000\r\n },\r\n ANIMATION_TYPES: [\r\n \"typewriter\",\r\n \"fadeIn\",\r\n \"slideIn\",\r\n \"shift\",\r\n \"ascend\",\r\n \"movingLetters\"\r\n ] as const\r\n};\r\n","// src/wasm/hb-loader.ts\r\n/* eslint-disable @typescript-eslint/no-explicit-any */\r\n\r\nlet hbSingleton: any | null = null;\r\n\r\n/**\r\n * Initialize HarfBuzz, ensuring the WASM is fetched from the right place.\r\n * Pass `wasmBaseURL` like \"/wasm\" if hb.wasm is served at \"/wasm/hb.wasm\".\r\n * With Vite you can also rely on `import 'harfbuzzjs/hb.wasm?url'`.\r\n */\r\nexport async function initHB(wasmBaseURL?: string): Promise<any> {\r\n if (hbSingleton) return hbSingleton;\r\n\r\n // 1) Load module factory from harfbuzzjs (Emscripten build).\r\n const harfbuzzjs = await import('harfbuzzjs');\r\n const factory = harfbuzzjs.default as (opts?: any) => Promise<any> | any;\r\n\r\n // 2) Try to resolve an emitted asset URL via Vite (works in dev & build).\r\n // If this import fails (other bundlers), we just ignore it.\r\n let hbUrlFromImport: string | undefined;\r\n try {\r\n // @ts-ignore: Vite's '?url' returns a string\r\n hbUrlFromImport = (await import('harfbuzzjs/hb.wasm?url')).default as string;\r\n } catch {\r\n /* noop */\r\n }\r\n\r\n // 3) Decide final base URL to serve the wasm from.\r\n // order: explicit param -> vite-import dirname -> current module dir\r\n const base = (() => {\r\n if (wasmBaseURL) return wasmBaseURL.replace(/\\/$/, '');\r\n if (hbUrlFromImport) return hbUrlFromImport.replace(/hb\\.wasm(?:\\?.*)?$/, '');\r\n // default: same directory as this loader (will likely not work unless you copy hb.wasm there)\r\n return new URL('.', import.meta.url).toString().replace(/\\/$/, '');\r\n })();\r\n\r\n // 4) Emscripten hook that tells the runtime where to fetch hb.wasm.\r\n const locateFile = (path: string, scriptDir: string) => {\r\n if (path.endsWith('.wasm')) {\r\n // ensure one slash between base and filename\r\n return `${base}/${path}`.replace(/([^:])\\/{2,}/g, '$1/');\r\n }\r\n // anything else keep default resolution\r\n return scriptDir ? scriptDir + path : path;\r\n };\r\n\r\n // 5) Initialize module\r\n const initArg = { locateFile };\r\n const maybePromise = typeof factory === 'function' ? factory(initArg) : factory;\r\n hbSingleton = (maybePromise && typeof (maybePromise as any).then === 'function')\r\n ? await (maybePromise as Promise<any>)\r\n : maybePromise;\r\n\r\n // 6) Sanity check\r\n if (!hbSingleton || typeof hbSingleton.createBuffer !== 'function') {\r\n throw new Error('Failed to initialize HarfBuzz: invalid API');\r\n }\r\n return hbSingleton;\r\n}\r\n\r\nexport type HB = any;\r\n","import { initHB, type HB } from \"../wasm/hb-loader\";\r\n\r\nexport type FontDescriptor = { family: string; weight?: string | number; style?: string };\r\n\r\nexport class FontRegistry {\r\n private hb!: HB;\r\n private faces = new Map<string, any>();\r\n private fonts = new Map<string, any>();\r\n private blobs = new Map<string, any>();\r\n private wasmBaseURL?: string;\r\n private initPromise?: Promise<void>;\r\n\r\n constructor(wasmBaseURL?: string) {\r\n this.wasmBaseURL = wasmBaseURL;\r\n }\r\n\r\n async init() {\r\n if (this.initPromise) {\r\n await this.initPromise;\r\n return;\r\n }\r\n\r\n if (this.hb) {\r\n return;\r\n }\r\n\r\n this.initPromise = this._doInit();\r\n await this.initPromise;\r\n }\r\n\r\n private async _doInit() {\r\n try {\r\n this.hb = await initHB(this.wasmBaseURL);\r\n } catch (error) {\r\n this.initPromise = undefined;\r\n throw error;\r\n }\r\n }\r\n\r\n async getHB(): Promise<HB> {\r\n if (!this.hb) {\r\n await this.init();\r\n }\r\n return this.hb;\r\n }\r\n\r\n private key(desc: FontDescriptor) {\r\n return `${desc.family}__${desc.weight ?? \"400\"}__${desc.style ?? \"normal\"}`;\r\n }\r\n\r\n async registerFromBytes(bytes: ArrayBuffer, desc: FontDescriptor): Promise<void> {\r\n if (!this.hb) await this.init();\r\n const k = this.key(desc);\r\n if (this.fonts.has(k)) return;\r\n\r\n const blob = this.hb.createBlob(bytes);\r\n const face = this.hb.createFace(blob, 0);\r\n const font = this.hb.createFont(face);\r\n\r\n // Keep HarfBuzz in font-units; we scale during painting\r\n const upem = face.upem || 1000;\r\n font.setScale(upem, upem);\r\n\r\n this.blobs.set(k, blob);\r\n this.faces.set(k, face);\r\n this.fonts.set(k, font);\r\n }\r\n\r\n async getFont(desc: FontDescriptor): Promise<any> {\r\n if (!this.hb) await this.init();\r\n const k = this.key(desc);\r\n const f = this.fonts.get(k);\r\n if (!f) throw new Error(`Font not registered for ${k}`);\r\n return f;\r\n }\r\n\r\n async getFace(desc: FontDescriptor): Promise<any> {\r\n if (!this.hb) await this.init();\r\n const k = this.key(desc);\r\n return this.faces.get(k);\r\n }\r\n\r\n async getUnitsPerEm(desc: FontDescriptor): Promise<number> {\r\n const face = await this.getFace(desc);\r\n return face?.upem || 1000;\r\n }\r\n\r\n async glyphPath(desc: FontDescriptor, glyphId: number): Promise<string> {\r\n const font = await this.getFont(desc);\r\n const path = font.glyphToPath(glyphId);\r\n return path && path !== \"\" ? path : \"M 0 0\";\r\n }\r\n\r\n destroy() {\r\n for (const [, f] of this.fonts) f.destroy?.();\r\n for (const [, f] of this.faces) f.destroy?.();\r\n for (const [, b] of this.blobs) b.destroy?.();\r\n this.fonts.clear();\r\n this.faces.clear();\r\n this.blobs.clear();\r\n this.hb = undefined!;\r\n this.initPromise = undefined;\r\n }\r\n}\r\n","import { FontRegistry, FontDescriptor } from \"./font-registry\";\r\nimport { Glyph, ShapedLine } from \"../types\";\r\n\r\nexport type ShapeParams = {\r\n text: string;\r\n width: number;\r\n letterSpacing: number;\r\n fontSize: number;\r\n lineHeight: number;\r\n desc: FontDescriptor;\r\n textTransform: \"none\" | \"uppercase\" | \"lowercase\" | \"capitalize\";\r\n};\r\n\r\ntype HBRunGlyph = { g: number; ax: number; ay: number; dx: number; dy: number; cl: number };\r\n\r\nexport class LayoutEngine {\r\n constructor(private fonts: FontRegistry) {}\r\n\r\n private transformText(t: string, tr: ShapeParams[\"textTransform\"]) {\r\n switch (tr) {\r\n case \"uppercase\":\r\n return t.toUpperCase();\r\n case \"lowercase\":\r\n return t.toLowerCase();\r\n case \"capitalize\":\r\n return t.replace(/\\b\\w/g, (c) => c.toUpperCase());\r\n default:\r\n return t;\r\n }\r\n }\r\n\r\n private async shapeFull(text: string, desc: FontDescriptor): Promise<HBRunGlyph[]> {\r\n const hb = await this.fonts.getHB();\r\n const buffer = hb.createBuffer();\r\n\r\n buffer.addText(text);\r\n buffer.guessSegmentProperties();\r\n\r\n const font = await this.fonts.getFont(desc);\r\n const face = await this.fonts.getFace(desc);\r\n\r\n // Set proper scale for shaping\r\n const upem = face?.upem || 1000;\r\n font.setScale(upem, upem);\r\n\r\n hb.shape(font, buffer);\r\n\r\n const result = buffer.json();\r\n buffer.destroy();\r\n\r\n return result;\r\n }\r\n\r\n async layout(params: ShapeParams): Promise<ShapedLine[]> {\r\n const { textTransform, desc, fontSize, letterSpacing, width } = params;\r\n const input = this.transformText(params.text, textTransform);\r\n\r\n if (!input || input.length === 0) {\r\n return [];\r\n }\r\n\r\n // Shape the text\r\n const shaped = await this.shapeFull(input, desc);\r\n\r\n // Get font metrics for proper scaling\r\n const face = await this.fonts.getFace(desc);\r\n const upem = face?.upem || 1000;\r\n const scale = fontSize / upem;\r\n\r\n // Convert shaped glyphs to our format\r\n const glyphs: Glyph[] = shaped.map((g) => {\r\n // Get the actual character from the input text using the cluster index\r\n const charIndex = g.cl;\r\n let char: string | undefined;\r\n\r\n // Cluster index tells us which character in the original text this glyph represents\r\n if (charIndex >= 0 && charIndex < input.length) {\r\n char = input[charIndex];\r\n }\r\n\r\n return {\r\n id: g.g,\r\n xAdvance: g.ax * scale + letterSpacing,\r\n xOffset: g.dx * scale,\r\n yOffset: -g.dy * scale,\r\n cluster: g.cl,\r\n char: char, // This now correctly maps to the original character\r\n };\r\n });\r\n\r\n // Line breaking logic\r\n const lines: ShapedLine[] = [];\r\n let currentLine: Glyph[] = [];\r\n let currentWidth = 0;\r\n\r\n // Identify space positions\r\n const spaceIndices = new Set<number>();\r\n for (let i = 0; i < input.length; i++) {\r\n if (input[i] === \" \") {\r\n spaceIndices.add(i);\r\n }\r\n }\r\n\r\n let lastBreakIndex = -1;\r\n\r\n for (let i = 0; i < glyphs.length; i++) {\r\n const glyph = glyphs[i];\r\n const glyphWidth = glyph.xAdvance;\r\n\r\n // Check for newline\r\n if (glyph.char === \"\\n\") {\r\n if (currentLine.length > 0) {\r\n lines.push({\r\n glyphs: currentLine,\r\n width: currentWidth,\r\n y: 0,\r\n });\r\n }\r\n currentLine = [];\r\n currentWidth = 0;\r\n lastBreakIndex = i;\r\n continue;\r\n }\r\n\r\n // Check if adding this glyph would exceed width\r\n if (currentWidth + glyphWidth > width && currentLine.length > 0) {\r\n // Try to break at last space\r\n if (lastBreakIndex > -1) {\r\n // Move glyphs after last space to new line\r\n const breakPoint = lastBreakIndex - (i - currentLine.length) + 1;\r\n const nextLine = currentLine.splice(breakPoint);\r\n\r\n // Recalculate current line width\r\n const lineWidth = currentLine.reduce((sum, g) => sum + g.xAdvance, 0);\r\n\r\n lines.push({\r\n glyphs: currentLine,\r\n width: lineWidth,\r\n y: 0,\r\n });\r\n\r\n currentLine = nextLine;\r\n currentWidth = nextLine.reduce((sum, g) => sum + g.xAdvance, 0);\r\n } else {\r\n // No space found, break at current position\r\n lines.push({\r\n glyphs: currentLine,\r\n width: currentWidth,\r\n y: 0,\r\n });\r\n currentLine = [];\r\n currentWidth = 0;\r\n }\r\n lastBreakIndex = -1;\r\n }\r\n\r\n // Add glyph to current line\r\n currentLine.push(glyph);\r\n currentWidth += glyphWidth;\r\n\r\n // Track spaces for line breaking\r\n if (spaceIndices.has(glyph.cluster)) {\r\n lastBreakIndex = i;\r\n }\r\n }\r\n\r\n // Add remaining glyphs\r\n if (currentLine.length > 0) {\r\n lines.push({\r\n glyphs: currentLine,\r\n width: currentWidth,\r\n y: 0,\r\n });\r\n }\r\n\r\n // Set line Y positions\r\n const lineHeight = params.lineHeight * fontSize;\r\n for (let i = 0; i < lines.length; i++) {\r\n lines[i].y = (i + 1) * lineHeight;\r\n }\r\n\r\n return lines;\r\n }\r\n}\r\n","import { GradientSpec } from \"../types\";\r\n\r\nexport function gradientSpecFrom(\r\n g: { type: \"linear\" | \"radial\"; angle: number; stops: { offset: number; color: string }[] },\r\n opacity: number\r\n): GradientSpec {\r\n if (g.type === \"linear\") {\r\n return { kind: \"linear\", angle: g.angle, stops: g.stops, opacity };\r\n } else {\r\n return { kind: \"radial\", stops: g.stops, opacity };\r\n }\r\n}\r\n","export function decorationGeometry(\r\n kind: \"underline\" | \"line-through\",\r\n p: { baselineY: number; fontSize: number; lineWidth: number; xStart: number }\r\n) {\r\n const thickness = Math.max(1, Math.round(p.fontSize * 0.05));\r\n let y = p.baselineY + Math.round(p.fontSize * 0.1);\r\n if (kind === \"line-through\") y = p.baselineY - Math.round(p.fontSize * 0.3);\r\n return { x1: p.xStart, x2: p.xStart + p.lineWidth, y, width: thickness };\r\n}\r\n","import { DrawOp, GradientSpec, ShapedLine } from \"../types\";\r\nimport { gradientSpecFrom } from \"./gradients\";\r\nimport { decorationGeometry } from \"./decoration\";\r\n\r\nexport type PaintParams = {\r\n canvas: { width: number; height: number; pixelRatio: number };\r\n textRect: { x: number; y: number; width: number; height: number };\r\n lines: ShapedLine[];\r\n font: { family: string; size: number; weight: string | number; style: string; color: string; opacity: number };\r\n style: {\r\n lineHeight: number;\r\n textDecoration: \"none\" | \"underline\" | \"line-through\";\r\n gradient?: { type: \"linear\" | \"radial\"; angle: number; stops: { offset: number; color: string }[] };\r\n };\r\n stroke?: { width: number; color: string; opacity: number };\r\n shadow?: { offsetX: number; offsetY: number; blur: number; color: string; opacity: number };\r\n align: { horizontal: \"left\" | \"center\" | \"right\"; vertical: \"top\" | \"middle\" | \"bottom\" };\r\n background?: { color?: string; opacity: number; borderRadius: number };\r\n glyphPathProvider: (glyphId: number) => Promise<string>;\r\n /** UPEM for scaling glyph paths from font units → px */\r\n getUnitsPerEm: () => Promise<number>;\r\n};\r\n\r\nexport async function buildDrawOps(p: PaintParams): Promise<DrawOp[]> {\r\n const ops: DrawOp[] = [];\r\n\r\n // Begin frame / background\r\n ops.push({\r\n op: \"BeginFrame\",\r\n width: p.canvas.width,\r\n height: p.canvas.height,\r\n pixelRatio: p.canvas.pixelRatio,\r\n clear: true,\r\n bg: p.background\r\n ? { color: p.background.color, opacity: p.background.opacity, radius: p.background.borderRadius }\r\n : undefined\r\n });\r\n\r\n if (p.lines.length === 0) return ops;\r\n\r\n // Font units → px\r\n const upem = Math.max(1, await p.getUnitsPerEm());\r\n const scale = p.font.size / upem;\r\n\r\n // Block metrics\r\n const blockHeight = p.lines[p.lines.length - 1].y;\r\n\r\n // Vertical anchor\r\n let blockY: number;\r\n switch (p.align.vertical) {\r\n case \"top\": blockY = p.font.size; break;\r\n case \"bottom\": blockY = p.textRect.height - blockHeight + p.font.size; break;\r\n case \"middle\":\r\n default: blockY = (p.textRect.height - blockHeight) / 2 + p.font.size; break;\r\n }\r\n\r\n // Fill style (solid or gradient)\r\n const fill: GradientSpec = p.style.gradient\r\n ? gradientSpecFrom(p.style.gradient, 1)\r\n : { kind: \"solid\", color: p.font.color, opacity: p.font.opacity };\r\n\r\n // Decoration/cursor color should match text (for gradient, use the last stop as a representative color)\r\n const decoColor = p.style.gradient\r\n ? p.style.gradient.stops[p.style.gradient.stops.length - 1]?.color ?? p.font.color\r\n : p.font.color;\r\n\r\n // Track global text bounds in world space so painters can build a single gradient\r\n let gMinX = Infinity, gMinY = Infinity, gMaxX = -Infinity, gMaxY = -Infinity;\r\n\r\n for (const line of p.lines) {\r\n // Horizontal anchor\r\n let lineX: number;\r\n switch (p.align.horizontal) {\r\n case \"left\": lineX = 0; break;\r\n case \"right\": lineX = p.textRect.width - line.width; break;\r\n case \"center\":\r\n default: lineX = (p.textRect.width - line.width) / 2; break;\r\n }\r\n\r\n let xCursor = lineX;\r\n const baselineY = blockY + line.y - p.font.size;\r\n\r\n for (const glyph of line.glyphs) {\r\n const path = await p.glyphPathProvider(glyph.id);\r\n if (!path || path === \"M 0 0\") {\r\n xCursor += glyph.xAdvance;\r\n continue;\r\n }\r\n\r\n const glyphX = xCursor + glyph.xOffset;\r\n const glyphY = baselineY + glyph.yOffset;\r\n\r\n // Update global bbox using path's local bounds mapped to world (scale s, flip Y)\r\n const pb = computePathBounds(path);\r\n const x1 = glyphX + scale * pb.x;\r\n const x2 = glyphX + scale * (pb.x + pb.w);\r\n const y1 = glyphY - scale * (pb.y + pb.h);\r\n const y2 = glyphY - scale * pb.y;\r\n if (x1 < gMinX) gMinX = x1;\r\n if (y1 < gMinY) gMinY = y1;\r\n if (x2 > gMaxX) gMaxX = x2;\r\n if (y2 > gMaxY) gMaxY = y2;\r\n\r\n // 1) Shadow (under everything)\r\n if (p.shadow && p.shadow.blur > 0) {\r\n ops.push({\r\n isShadow: true,\r\n op: \"FillPath\",\r\n path,\r\n x: glyphX + p.shadow.offsetX,\r\n y: glyphY + p.shadow.offsetY,\r\n // @ts-ignore scale propagated to painters\r\n scale,\r\n fill: { kind: \"solid\", color: p.shadow.color, opacity: p.shadow.opacity }\r\n } as any);\r\n }\r\n\r\n // 2) Stroke (under fill)\r\n if (p.stroke && p.stroke.width > 0) {\r\n ops.push({\r\n op: \"StrokePath\",\r\n path,\r\n x: glyphX,\r\n y: glyphY,\r\n // @ts-ignore scale propagated to painters\r\n scale,\r\n width: p.stroke.width,\r\n color: p.stroke.color,\r\n opacity: p.stroke.opacity\r\n } as any);\r\n }\r\n\r\n // 3) Fill (on top)\r\n ops.push({\r\n op: \"FillPath\",\r\n path,\r\n x: glyphX,\r\n y: glyphY,\r\n // @ts-ignore scale propagated to painters\r\n scale,\r\n fill\r\n } as any);\r\n\r\n xCursor += glyph.xAdvance;\r\n }\r\n\r\n // Decoration lines (use text/deco color)\r\n if (p.style.textDecoration !== \"none\") {\r\n const deco = decorationGeometry(p.style.textDecoration, {\r\n baselineY,\r\n fontSize: p.font.size,\r\n lineWidth: line.width,\r\n xStart: lineX\r\n });\r\n\r\n ops.push({\r\n op: \"DecorationLine\",\r\n from: { x: deco.x1, y: deco.y },\r\n to: { x: deco.x2, y: deco.y },\r\n width: deco.width,\r\n color: decoColor,\r\n opacity: p.font.opacity\r\n });\r\n }\r\n }\r\n\r\n // Attach a full-text gradient bbox to all glyph fills (stable across typewriter)\r\n if (gMinX !== Infinity) {\r\n const gbox = { x: gMinX, y: gMinY, w: Math.max(1, gMaxX - gMinX), h: Math.max(1, gMaxY - gMinY) };\r\n for (const op of ops) {\r\n if (op.op === \"FillPath\" && !(op as any).isShadow) {\r\n (op as any).gradientBBox = gbox;\r\n }\r\n }\r\n }\r\n\r\n return ops;\r\n}\r\n\r\n/* ----------------- local helpers ----------------- */\r\nfunction tokenizePath(d: string): string[] {\r\n return d.match(/[MLCQZ]|-?\\d*\\.?\\d+(?:e[-+]?\\d+)?/gi) ?? [];\r\n}\r\nfunction computePathBounds(d: string) {\r\n const t = tokenizePath(d);\r\n let i = 0;\r\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\r\n const touch = (x: number, y: number) => { if (x < minX) minX = x; if (y < minY) minY = y; if (x > maxX) maxX = x; if (y > maxY) maxY = y; };\r\n while (i < t.length) {\r\n const cmd = t[i++];\r\n switch (cmd) {\r\n case \"M\":\r\n case \"L\": { const x = parseFloat(t[i++]); const y = parseFloat(t[i++]); touch(x, y); break; }\r\n case \"C\": {\r\n const c1x = parseFloat(t[i++]); const c1y = parseFloat(t[i++]);\r\n const c2x = parseFloat(t[i++]); const c2y = parseFloat(t[i++]);\r\n const x = parseFloat(t[i++]); const y = parseFloat(t[i++]);\r\n touch(c1x, c1y); touch(c2x, c2y); touch(x, y); break;\r\n }\r\n case \"Q\": { const cx = parseFloat(t[i++]); const cy = parseFloat(t[i++]); const x = parseFloat(t[i++]); const y = parseFloat(t[i++]); touch(cx, cy); touch(x, y); break; }\r\n case \"Z\": break;\r\n }\r\n }\r\n if (minX === Infinity) return { x: 0, y: 0, w: 0, h: 0 };\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}","import { DrawOp, Glyph, ShapedLine } from \"../types\";\r\n\r\nexport type AnimationInput = {\r\n preset?: \"typewriter\" | \"fadeIn\" | \"slideIn\" | \"shift\" | \"ascend\" | \"movingLetters\";\r\n speed: number;\r\n duration?: number;\r\n style?: \"character\" | \"word\";\r\n direction?: \"left\" | \"right\" | \"up\" | \"down\";\r\n};\r\n\r\nconst DECORATION_DONE_THRESHOLD = 0.999;\r\n\r\nexport function applyAnimation(\r\n ops: DrawOp[],\r\n lines: ShapedLine[],\r\n p: { t: number; fontSize: number; anim?: AnimationInput }\r\n): DrawOp[] {\r\n if (!p.anim || !p.anim.preset) return ops;\r\n\r\n const { preset } = p.anim;\r\n const totalGlyphs = lines.reduce((s, l) => s + l.glyphs.length, 0);\r\n const duration = p.anim.duration ?? Math.max(0.3, totalGlyphs / 30 / p.anim.speed);\r\n const progress = Math.max(0, Math.min(1, p.t / duration));\r\n\r\n switch (preset) {\r\n case \"typewriter\":\r\n return applyTypewriterAnimation(\r\n ops,\r\n lines,\r\n progress,\r\n p.anim.style,\r\n p.fontSize,\r\n p.t,\r\n duration\r\n );\r\n case \"fadeIn\":\r\n return applyFadeInAnimation(ops, progress);\r\n case \"slideIn\":\r\n return applySlideInAnimation(ops, progress, p.anim.direction ?? \"left\", p.fontSize);\r\n case \"shift\":\r\n return applyShiftAnimation(\r\n ops,\r\n lines,\r\n progress,\r\n p.anim.direction ?? \"left\",\r\n p.fontSize,\r\n p.anim.style,\r\n duration\r\n );\r\n case \"ascend\":\r\n return applyAscendAnimation(\r\n ops,\r\n lines,\r\n progress,\r\n p.anim.direction ?? \"up\",\r\n p.fontSize,\r\n duration\r\n );\r\n case \"movingLetters\":\r\n return applyMovingLettersAnimation(ops, progress, p.anim.direction ?? \"up\", p.fontSize);\r\n default:\r\n return ops;\r\n }\r\n}\r\n\r\n// ---- helpers\r\nconst isShadowFill = (op: DrawOp) => op.op === \"FillPath\" && (op as any).isShadow === true;\r\nconst isGlyphFill = (op: DrawOp) => op.op === \"FillPath\" && !(op as any).isShadow === true;\r\n\r\n// Try to derive a text color from the first fill we find\r\nfunction getTextColorFromOps(ops: DrawOp[]): string {\r\n for (const op of ops) {\r\n if (op.op === \"FillPath\") {\r\n const fill: any = (op as any).fill;\r\n if (fill?.kind === \"solid\") return fill.color;\r\n if (\r\n (fill?.kind === \"linear\" || fill?.kind === \"radial\") &&\r\n Array.isArray(fill.stops) &&\r\n fill.stops.length\r\n ) {\r\n return fill.stops[fill.stops.length - 1].color || \"#000000\";\r\n }\r\n }\r\n }\r\n return \"#000000\";\r\n}\r\n\r\n// ---------- TYPEWRITER ----------\r\nfunction applyTypewriterAnimation(\r\n ops: DrawOp[],\r\n lines: ShapedLine[],\r\n progress: number,\r\n style: \"character\" | \"word\" | undefined,\r\n fontSize: number,\r\n time: number,\r\n duration: number\r\n): DrawOp[] {\r\n const byWord = style === \"word\";\r\n\r\n if (byWord) {\r\n const wordSegments = getWordSegments(lines);\r\n const totalWords = wordSegments.length;\r\n const visibleWords = Math.floor(progress * totalWords);\r\n if (visibleWords === 0) return ops.filter((x) => x.op === \"BeginFrame\");\r\n\r\n let totalVisibleGlyphs = 0;\r\n for (let i = 0; i < Math.min(visibleWords, wordSegments.length); i++) {\r\n totalVisibleGlyphs += wordSegments[i].glyphCount;\r\n }\r\n const visibleOpsRaw = sliceGlyphOps(ops, totalVisibleGlyphs);\r\n\r\n const visibleOps =\r\n progress >= DECORATION_DONE_THRESHOLD\r\n ? visibleOpsRaw\r\n : visibleOpsRaw.filter((o) => o.op !== \"DecorationLine\");\r\n\r\n if (progress < 1 && totalVisibleGlyphs > 0) {\r\n return addTypewriterCursor(visibleOps, totalVisibleGlyphs, fontSize, time);\r\n }\r\n return visibleOps;\r\n } else {\r\n const totalGlyphs = lines.reduce((s, l) => s + l.glyphs.length, 0);\r\n const visibleGlyphs = Math.floor(progress * totalGlyphs);\r\n if (visibleGlyphs === 0) return ops.filter((x) => x.op === \"BeginFrame\");\r\n\r\n const visibleOpsRaw = sliceGlyphOps(ops, visibleGlyphs);\r\n\r\n const visibleOps =\r\n progress >= DECORATION_DONE_THRESHOLD\r\n ? visibleOpsRaw\r\n : visibleOpsRaw.filter((o) => o.op !== \"DecorationLine\");\r\n\r\n if (progress < 1 && visibleGlyphs > 0) {\r\n return addTypewriterCursor(visibleOps, visibleGlyphs, fontSize, time);\r\n }\r\n return visibleOps;\r\n }\r\n}\r\n\r\n// ---------- ASCEND ----------\r\nfunction applyAscendAnimation(\r\n ops: DrawOp[],\r\n lines: ShapedLine[],\r\n progress: number,\r\n direction: \"left\" | \"right\" | \"up\" | \"down\",\r\n fontSize: number,\r\n duration: number\r\n): DrawOp[] {\r\n const wordSegments = getWordSegments(lines);\r\n const totalWords = wordSegments.length;\r\n if (totalWords === 0) return ops;\r\n\r\n const result: DrawOp[] = [];\r\n let glyphIndex = 0;\r\n\r\n for (const op of ops) {\r\n if (op.op === \"BeginFrame\") {\r\n result.push(op);\r\n break;\r\n }\r\n }\r\n\r\n for (const op of ops) {\r\n if (op.op === \"FillPath\" || op.op === \"StrokePath\") {\r\n // which word owns this glyph\r\n let wordIndex = -1,\r\n acc = 0;\r\n for (let i = 0; i < wordSegments.length; i++) {\r\n const gcount = wordSegments[i].glyphCount;\r\n if (glyphIndex >= acc && glyphIndex < acc + gcount) {\r\n wordIndex = i;\r\n break;\r\n }\r\n acc += gcount;\r\n }\r\n if (wordIndex >= 0) {\r\n const startF = (wordIndex / Math.max(1, totalWords)) * (duration / duration);\r\n const endF = Math.min(1, startF + 0.3);\r\n if (progress >= endF) {\r\n result.push(op);\r\n } else if (progress > startF) {\r\n const local = (progress - startF) / Math.max(1e-6, endF - startF);\r\n const ease = easeOutCubic(Math.min(1, local));\r\n const startOffset = direction === \"up\" ? fontSize * 0.4 : -fontSize * 0.4;\r\n const animated: any = { ...op, y: op.y + startOffset * (1 - ease) };\r\n if (op.op === \"FillPath\") {\r\n if (animated.fill.kind === \"solid\")\r\n animated.fill = { ...animated.fill, opacity: animated.fill.opacity * ease };\r\n else animated.fill = { ...animated.fill, opacity: (animated.fill.opacity ?? 1) * ease };\r\n } else {\r\n animated.opacity = animated.opacity * ease;\r\n }\r\n result.push(animated);\r\n }\r\n }\r\n if (isGlyphFill(op)) glyphIndex++;\r\n } else if (op.op === \"DecorationLine\") {\r\n if (progress >= DECORATION_DONE_THRESHOLD) {\r\n result.push(op);\r\n }\r\n }\r\n }\r\n return result;\r\n}\r\n\r\n// ---------- SHIFT ----------\r\nfunction applyShiftAnimation(\r\n ops: DrawOp[],\r\n lines: ShapedLine[],\r\n progress: number,\r\n direction: \"left\" | \"right\" | \"up\" | \"down\",\r\n fontSize: number,\r\n style: \"character\" | \"word\" | undefined,\r\n duration: number\r\n): DrawOp[] {\r\n const byWord = style === \"word\";\r\n const startOffsets = {\r\n left: { x: fontSize * 0.6, y: 0 },\r\n right: { x: -fontSize * 0.6, y: 0 },\r\n up: { x: 0, y: fontSize * 0.6 },\r\n down: { x: 0, y: -fontSize * 0.6 },\r\n };\r\n const offset = startOffsets[direction];\r\n\r\n const wordSegments = byWord ? getWordSegments(lines) : [];\r\n const totalGlyphs = lines.reduce((s, l) => s + l.glyphs.length, 0);\r\n const totalUnits = byWord ? wordSegments.length : totalGlyphs;\r\n if (totalUnits === 0) return ops;\r\n\r\n const result: DrawOp[] = [];\r\n for (const op of ops) {\r\n if (op.op === \"BeginFrame\") {\r\n result.push(op);\r\n break;\r\n }\r\n }\r\n\r\n const windowDuration = 0.3; // each unit animates for 0.3s of total duration\r\n const overlapFactor = 0.7; // overlapping reveal\r\n const staggerDelay = (duration * overlapFactor) / Math.max(1, totalUnits - 1);\r\n\r\n const windowFor = (unitIdx: number) => {\r\n const startTime = unitIdx * staggerDelay;\r\n const startF = startTime / duration;\r\n const endF = Math.min(1, (startTime + windowDuration) / duration);\r\n return { startF, endF };\r\n };\r\n\r\n let glyphIndex = 0;\r\n for (const op of ops) {\r\n if (op.op !== \"FillPath\" && op.op !== \"StrokePath\") {\r\n if (op.op === \"DecorationLine\" && progress > 0.8) result.push(op);\r\n continue;\r\n }\r\n\r\n let unitIndex: number;\r\n if (!byWord) {\r\n unitIndex = glyphIndex;\r\n } else {\r\n let wordIndex = -1,\r\n acc = 0;\r\n for (let i = 0; i < wordSegments.length; i++) {\r\n const gcount = wordSegments[i].glyphCount;\r\n if (glyphIndex >= acc && glyphIndex < acc + gcount) {\r\n wordIndex = i;\r\n break;\r\n }\r\n acc += gcount;\r\n }\r\n unitIndex = Math.max(0, wordIndex);\r\n }\r\n\r\n const { startF, endF } = windowFor(unitIndex);\r\n\r\n if (progress <= startF) {\r\n const animated: any = { ...op, x: op.x + offset.x, y: op.y + offset.y };\r\n if (op.op === \"FillPath\") {\r\n if (animated.fill.kind === \"solid\") animated.fill = { ...animated.fill, opacity: 0 };\r\n else animated.fill = { ...animated.fill, opacity: 0 };\r\n } else {\r\n animated.opacity = 0;\r\n }\r\n result.push(animated);\r\n } else if (progress >= endF) {\r\n result.push(op);\r\n } else {\r\n const local = (progress - startF) / Math.max(1e-6, endF - startF);\r\n const ease = easeOutCubic(Math.min(1, local));\r\n const dx = offset.x * (1 - ease);\r\n const dy = offset.y * (1 - ease);\r\n const animated: any = { ...op, x: op.x + dx, y: op.y + dy };\r\n\r\n if (op.op === \"FillPath\") {\r\n const targetOpacity =\r\n animated.fill.kind === \"solid\" ? animated.fill.opacity : animated.fill.opacity ?? 1;\r\n if (animated.fill.kind === \"solid\")\r\n animated.fill = { ...animated.fill, opacity: targetOpacity * ease };\r\n else animated.fill = { ...animated.fill, opacity: targetOpacity * ease };\r\n } else {\r\n animated.opacity = animated.opacity * ease;\r\n }\r\n result.push(animated);\r\n }\r\n\r\n if (isGlyphFill(op)) glyphIndex++;\r\n }\r\n return result;\r\n}\r\n\r\n// ---------- FADE / SLIDE / WAVE ----------\r\nfunction applyFadeInAnimation(ops: DrawOp[], progress: number): DrawOp[] {\r\n const alpha = easeOutQuad(progress);\r\n const scale = 0.95 + 0.05 * alpha;\r\n return scaleAndFade(ops, alpha, scale);\r\n}\r\nfunction applySlideInAnimation(\r\n ops: DrawOp[],\r\n progress: number,\r\n direction: \"left\" | \"right\" | \"up\" | \"down\",\r\n fontSize: number\r\n): DrawOp[] {\r\n const easeProgress = easeOutCubic(progress);\r\n const shift = shiftFor(1 - easeProgress, direction, fontSize * 2);\r\n const alpha = easeOutQuad(progress);\r\n return translateGlyphOps(ops, shift.dx, shift.dy, alpha);\r\n}\r\nfunction applyMovingLettersAnimation(\r\n ops: DrawOp[],\r\n progress: number,\r\n direction: \"left\" | \"right\" | \"up\" | \"down\",\r\n fontSize: number\r\n): DrawOp[] {\r\n const amp = fontSize * 0.3;\r\n return waveTransform(ops, direction, amp, progress);\r\n}\r\n\r\n// ---------- word segmentation / slicing ----------\r\nfunction getWordSegments(lines: ShapedLine[]) {\r\n const segments: any = [];\r\n let totalGlyphIndex = 0;\r\n for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {\r\n const line = lines[lineIndex];\r\n const words = segmentLineBySpaces(line);\r\n for (const word of words) {\r\n if (word.length > 0)\r\n segments.push({ startGlyph: totalGlyphIndex, glyphCount: word.length, lineIndex });\r\n totalGlyphIndex += word.length;\r\n }\r\n }\r\n return segments;\r\n}\r\nfunction segmentLineBySpaces(line: ShapedLine): Glyph[][] {\r\n const words: Glyph[][] = [];\r\n let current: Glyph[] = [];\r\n for (const g of line.glyphs) {\r\n const isSpace = g.char === \" \" || g.char === \"\\t\" || g.char === \"\\n\";\r\n if (isSpace) {\r\n if (current.length) {\r\n words.push([...current]);\r\n current = [];\r\n }\r\n } else {\r\n current.push(g);\r\n }\r\n }\r\n if (current.length) words.push(current);\r\n return words;\r\n}\r\n\r\n/** Include BOTH stroke+fill for the first `maxGlyphs` glyphs; nothing from later glyphs.\r\n * Stroke is only included if its corresponding fill will be shown (so it never appears early). */\r\nfunction sliceGlyphOps(ops: DrawOp[], maxGlyphs: number): DrawOp[] {\r\n const result: DrawOp[] = [];\r\n let glyphCount = 0;\r\n let foundGlyphs = false;\r\n\r\n for (const op of ops) {\r\n if (op.op === \"BeginFrame\") {\r\n result.push(op);\r\n continue;\r\n }\r\n\r\n if (op.op === \"FillPath\" && !isShadowFill(op)) {\r\n if (glyphCount < maxGlyphs) {\r\n result.push(op);\r\n foundGlyphs = true;\r\n }\r\n glyphCount++; // count only real glyph fills\r\n continue;\r\n }\r\n\r\n if (op.op === \"StrokePath\") {\r\n // Include stroke only if the upcoming fill is within range\r\n if (glyphCount < maxGlyphs) result.push(op);\r\n continue;\r\n }\r\n\r\n if (op.op === \"FillPath\" && isShadowFill(op)) {\r\n if (glyphCount < maxGlyphs) result.push(op);\r\n continue;\r\n }\r\n\r\n if (op.op === \"DecorationLine\" && foundGlyphs) {\r\n result.push(op);\r\n continue;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction addTypewriterCursor(\r\n ops: DrawOp[],\r\n glyphCount: number,\r\n fontSize: number,\r\n time: number\r\n): DrawOp[] {\r\n const blinkRate = 2;\r\n const cursorVisible = Math.floor(time * blinkRate * 2) % 2 === 0;\r\n if (!cursorVisible || glyphCount === 0) return ops;\r\n\r\n let last: DrawOp | null = null;\r\n let count = 0;\r\n for (const op of ops) {\r\n if (op.op === \"FillPath\" && !isShadowFill(op)) {\r\n count++;\r\n if (count === glyphCount) {\r\n last = op;\r\n break;\r\n }\r\n }\r\n }\r\n if (last && last.op === \"FillPath\") {\r\n const color = getTextColorFromOps(ops);\r\n const cursorX = last.x + fontSize * 0.5;\r\n const cursorY = last.y;\r\n\r\n const cursorOp: DrawOp = {\r\n op: \"DecorationLine\",\r\n from: { x: cursorX, y: cursorY - fontSize * 0.7 },\r\n to: { x: cursorX, y: cursorY + fontSize * 0.1 },\r\n width: Math.max(2, fontSize / 25),\r\n color,\r\n opacity: 1,\r\n };\r\n return [...ops, cursorOp];\r\n }\r\n return ops;\r\n}\r\n\r\n// ---------- transforms ----------\r\nfunction scaleAndFade(ops: DrawOp[], alpha: number, scale: number): DrawOp[] {\r\n let cx = 0,\r\n cy = 0,\r\n n = 0;\r\n ops.forEach((op) => {\r\n if (op.op === \"FillPath\") {\r\n cx += op.x;\r\n cy += op.y;\r\n n++;\r\n }\r\n });\r\n if (n > 0) {\r\n cx /= n;\r\n cy /= n;\r\n }\r\n\r\n return ops.map((op) => {\r\n if (op.op === \"FillPath\") {\r\n const out: any = { ...op };\r\n if (out.fill.kind === \"solid\") out.fill = { ...out.fill, opacity: out.fill.opacity * alpha };\r\n else out.fill = { ...out.fill, opacity: (out.fill.opacity ?? 1) * alpha };\r\n if (scale !== 1 && n > 0) {\r\n const dx = op.x - cx,\r\n dy = op.y - cy;\r\n out.x = cx + dx * scale;\r\n out.y = cy + dy * scale;\r\n }\r\n return out;\r\n }\r\n if (op.op === \"StrokePath\") {\r\n const out: any = { ...op, opacity: op.opacity * alpha };\r\n if (scale !== 1 && n > 0) {\r\n const dx = op.x - cx,\r\n dy = op.y - cy;\r\n out.x = cx + dx * scale;\r\n out.y = cy + dy * scale;\r\n }\r\n return out;\r\n }\r\n if (op.op === \"DecorationLine\") return { ...op, opacity: op.opacity * alpha };\r\n return op;\r\n });\r\n}\r\n\r\nfunction translateGlyphOps(ops: DrawOp[], dx: number, dy: number, alpha: number = 1): DrawOp[] {\r\n return ops.map((op) => {\r\n if (op.op === \"FillPath\") {\r\n const out: any = { ...op, x: op.x + dx, y: op.y + dy };\r\n if (alpha < 1) {\r\n if (out.fill.kind === \"solid\")\r\n out.fill = { ...out.fill, opacity: out.fill.opacity * alpha };\r\n else out.fill = { ...out.fill, opacity: (out.fill.opacity ?? 1) * alpha };\r\n }\r\n return out;\r\n }\r\n if (op.op === \"StrokePath\")\r\n return { ...op, x: op.x + dx, y: op.y + dy, opacity: op.opacity * alpha };\r\n if (op.op === \"DecorationLine\") {\r\n return {\r\n ...op,\r\n from: { x: op.from.x + dx, y: op.from.y + dy },\r\n to: { x: op.to.x + dx, y: op.to.y + dy },\r\n opacity: op.opacity * alpha,\r\n };\r\n }\r\n return op;\r\n });\r\n}\r\n\r\nfunction waveTransform(\r\n ops: DrawOp[],\r\n dir: \"left\" | \"right\" | \"up\" | \"down\",\r\n amp: number,\r\n p: number\r\n): DrawOp[] {\r\n let glyphIndex = 0;\r\n return ops.map((op) => {\r\n if (op.op === \"FillPath\" || op.op === \"StrokePath\") {\r\n const phase = Math.sin((glyphIndex / 5) * Math.PI + p * Math.PI * 4);\r\n const dx = dir === \"left\" || dir === \"right\" ? phase * amp * (dir === \"left\" ? -1 : 1) : 0;\r\n const dy = dir === \"up\" || dir === \"down\" ? phase * amp * (dir === \"up\" ? -1 : 1) : 0;\r\n const waveAlpha = Math.min(1, p * 2);\r\n if (op.op === \"FillPath\") {\r\n if (!isShadowFill(op)) glyphIndex++;\r\n const out: any = { ...op, x: op.x + dx, y: op.y + dy };\r\n if (out.fill.kind === \"solid\")\r\n out.fill = { ...out.fill, opacity: out.fill.opacity * waveAlpha };\r\n else out.fill = { ...out.fill, opacity: (out.fill.opacity ?? 1) * waveAlpha };\r\n return out;\r\n }\r\n return { ...op, x: op.x + dx, y: op.y + dy, opacity: op.opacity * waveAlpha };\r\n }\r\n return op;\r\n });\r\n}\r\n\r\n// ---------- misc ----------\r\nfunction shiftFor(progress: number, dir: \"left\" | \"right\" | \"up\" | \"down\", dist: number) {\r\n const d = progress * dist;\r\n switch (dir) {\r\n case \"left\":\r\n return { dx: -d, dy: 0 };\r\n case \"right\":\r\n return { dx: d, dy: 0 };\r\n case \"up\":\r\n return { dx: 0, dy: -d };\r\n case \"down\":\r\n return { dx: 0, dy: d };\r\n }\r\n}\r\nfunction easeOutQuad(t: number) {\r\n return t * (2 - t);\r\n}\r\nfunction easeOutCubic(t: number) {\r\n return 1 - Math.pow(1 - t, 3);\r\n}\r\nfunction easeInOutQuad(t: number) {\r\n return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;\r\n}\r\n","import { RGBA } from \"../types\";\r\n\r\nexport function parseHex6(hex: string, alpha = 1): RGBA {\r\n const m = /^#?([a-f0-9]{6})$/i.exec(hex);\r\n if (!m) throw new Error(`Invalid color ${hex}`);\r\n const n = parseInt(m[1], 16);\r\n const r = (n >> 16) & 0xff;\r\n const g = (n >> 8) & 0xff;\r\n const b = n & 0xff;\r\n return { r, g, b, a: alpha };\r\n}\r\n","import type { DrawOp, GradientSpec } from \"../types\";\r\nimport { parseHex6 } from \"../core/colors\";\r\n\r\n/* eslint-disable @typescript-eslint/no-explicit-any */\r\n\r\nexport function createWebPainter(canvas: HTMLCanvasElement | OffscreenCanvas) {\r\n // @ts-ignore\r\n const ctx: CanvasRenderingContext2D = (canvas as any).getContext(\"2d\");\r\n if (!ctx) throw new Error(\"2D context unavailable\");\r\n\r\n return {\r\n async render(ops: DrawOp[]) {\r\n const globalBox = computeGlobalTextBounds(ops);\r\n\r\n for (const op of ops) {\r\n if (op.op === \"BeginFrame\") {\r\n const dpr = op.pixelRatio;\r\n const w = op.width,\r\n h = op.height;\r\n\r\n if (\"width\" in canvas && \"height\" in canvas) {\r\n (canvas as any).width = Math.floor(w * dpr);\r\n (canvas as any).height = Math.floor(h * dpr);\r\n }\r\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\r\n\r\n if (op.clear) ctx.clearRect(0, 0, w, h);\r\n if (op.bg) {\r\n const { color, opacity, radius } = op.bg;\r\n if (color) {\r\n const c = parseHex6(color, opacity);\r\n ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;\r\n if (radius && radius > 0) {\r\n drawRoundedRect(ctx, 0, 0, w, h, radius);\r\n ctx.fill();\r\n } else {\r\n ctx.fillRect(0, 0, w, h);\r\n }\r\n }\r\n }\r\n continue;\r\n }\r\n\r\n if (op.op === \"FillPath\") {\r\n const p = new Path2D(op.path);\r\n ctx.save();\r\n ctx.translate(op.x, op.y);\r\n\r\n const s = (op as any).scale ?? 1;\r\n ctx.scale(s, -s);\r\n\r\n const bbox = (op as any).gradientBBox ?? globalBox;\r\n const fill = makeGradientFromBBox(ctx, op.fill, bbox);\r\n ctx.fillStyle = fill as any;\r\n ctx.fill(p);\r\n ctx.restore();\r\n continue;\r\n }\r\n\r\n if (op.op === \"StrokePath\") {\r\n const p = new Path2D(op.path);\r\n ctx.save();\r\n ctx.translate(op.x, op.y);\r\n\r\n const s = (op as any).scale ?? 1;\r\n ctx.scale(s, -s);\r\n const invAbs = 1 / Math.abs(s);\r\n\r\n const c = parseHex6((op as any).color, (op as any).opacity);\r\n ctx.strokeStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;\r\n ctx.lineWidth = (op as any).width * invAbs;\r\n ctx.lineJoin = \"round\";\r\n ctx.lineCap = \"round\";\r\n ctx.stroke(p);\r\n ctx.restore();\r\n continue;\r\n }\r\n\r\n if (op.op === \"DecorationLine\") {\r\n ctx.save();\r\n const c = parseHex6((op as any).color, (op as any).opacity);\r\n ctx.strokeStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;\r\n ctx.lineWidth = (op as any).width;\r\n ctx.beginPath();\r\n ctx.moveTo((op as any).from.x, (op as any).from.y);\r\n ctx.lineTo((op as any).to.x, (op as any).to.y);\r\n ctx.stroke();\r\n ctx.restore();\r\n continue;\r\n }\r\n }\r\n },\r\n };\r\n}\r\n\r\nfunction drawRoundedRect(\r\n ctx: CanvasRenderingContext2D,\r\n x: number,\r\n y: number,\r\n w: number,\r\n h: number,\r\n r: number\r\n) {\r\n const p = new Path2D();\r\n p.moveTo(x + r, y);\r\n p.arcTo(x + w, y, x + w, y + h, r);\r\n p.arcTo(x + w, y + h, x, y + h, r);\r\n p.arcTo(x, y + h, x, y, r);\r\n p.arcTo(x, y, x + w, y, r);\r\n p.closePath();\r\n ctx.save();\r\n ctx.fill(p);\r\n ctx.restore();\r\n}\r\n\r\nfunction makeGradientFromBBox(\r\n ctx: CanvasRenderingContext2D,\r\n spec: GradientSpec,\r\n box: { x: number; y: number; w: number; h: number }\r\n): CanvasGradient | string {\r\n if (spec.kind === \"solid\") {\r\n const c = parseHex6((spec as any).color, (spec as any).opacity);\r\n return `rgba(${c.r},${c.g},${c.b},${c.a})`;\r\n }\r\n const cx = box.x + box.w / 2,\r\n cy = box.y + box.h / 2,\r\n r = Math.max(box.w, box.h) / 2;\r\n const addStops = (g: CanvasGradient) => {\r\n const op = (spec as any).opacity ?? 1;\r\n for (const s of (spec as any).stops) {\r\n const c = parseHex6(s.color, op);\r\n g.addColorStop(s.offset, `rgba(${c.r},${c.g},${c.b},${c.a})`);\r\n }\r\n return g;\r\n };\r\n if (spec.kind === \"linear\") {\r\n const rad = (((spec as any).angle || 0) * Math.PI) / 180;\r\n const x1 = cx + Math.cos(rad + Math.PI) * r;\r\n const y1 = cy + Math.sin(rad + Math.PI) * r;\r\n const x2 = cx + Math.cos(rad) * r;\r\n const y2 = cy + Math.sin(rad) * r;\r\n return addStops(ctx.createLinearGradient(x1, y1, x2, y2));\r\n } else {\r\n return addStops(ctx.createRadialGradient(cx, cy, 0, cx, cy, r));\r\n }\r\n}\r\n\r\nfunction computeGlobalTextBounds(ops: DrawOp[]) {\r\n let minX = Infinity,\r\n minY = Infinity,\r\n maxX = -Infinity,\r\n maxY = -Infinity;\r\n for (const op of ops) {\r\n if (op.op !== \"FillPath\" || (op as any).isShadow) continue;\r\n const b = computePathBounds(op.path);\r\n const s = (op as any).scale ?? 1;\r\n const x1 = op.x + s * b.x;\r\n const x2 = op.x + s * (b.x + b.w);\r\n const y1 = op.y - s * (b.y + b.h);\r\n const y2 = op.y - s * b.y;\r\n if (x1 < minX) minX = x1;\r\n if (y1 < minY) minY = y1;\r\n if (x2 > maxX) maxX = x2;\r\n if (y2 > maxY) maxY = y2;\r\n }\r\n if (minX === Infinity) return { x: 0, y: 0, w: 1, h: 1 };\r\n return { x: minX, y: minY, w: Math.max(1, maxX - minX), h: Math.max(1, maxY - minY) };\r\n}\r\n\r\nfunction computePathBounds(d: string) {\r\n const tokens = tokenizePath(d);\r\n let i = 0;\r\n let minX = Infinity,\r\n minY = Infinity,\r\n maxX = -Infinity,\r\n maxY = -Infinity;\r\n const touch = (x: number, y: number) => {\r\n if (x < minX) minX = x;\r\n if (y < minY) minY = y;\r\n if (x > maxX) maxX = x;\r\n if (y > maxY) maxY = y;\r\n };\r\n while (i < tokens.length) {\r\n const t = tokens[i++];\r\n switch (t) {\r\n case \"M\":\r\n case \"L\": {\r\n const x = parseFloat(tokens[i++]);\r\n const y = parseFloat(tokens[i++]);\r\n touch(x, y);\r\n break;\r\n }\r\n case \"C\": {\r\n const c1x = parseFloat(tokens[i++]);\r\n const c1y = parseFloat(tokens[i++]);\r\n const c2x = parseFloat(tokens[i++]);\r\n const c2y = parseFloat(tokens[i++]);\r\n const x = parseFloat(tokens[i++]);\r\n const y = parseFloat(tokens[i++]);\r\n touch(c1x, c1y);\r\n touch(c2x, c2y);\r\n touch(x, y);\r\n break;\r\n }\r\n case \"Q\": {\r\n const cx = parseFloat(tokens[i++]);\r\n const cy = parseFloat(tokens[i++]);\r\n const x = parseFloat(tokens[i++]);\r\n const y = parseFloat(tokens[i++]);\r\n touch(cx, cy);\r\n touch(x, y);\r\n break;\r\n }\r\n case \"Z\":\r\n break;\r\n }\r\n }\r\n if (minX === Infinity) return { x: 0, y: 0, w: 0, h: 0 };\r\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\r\n}\r\n\r\nfunction tokenizePath(d: string): string[] {\r\n return d.match(/[MLCQZ]|-?\\d*\\.?\\d+(?:e[-+]?\\d+)?/gi) ?? [];\r\n}\r\n","export async function fetchToArrayBuffer(url: string): Promise<ArrayBuffer> {\r\n const res = await fetch(url);\r\n if (!res.ok) throw new Error(`Failed to fetch ${url}: ${res.status}`);\r\n return await res.arrayBuffer();\r\n}\r\n","import { RichTextAssetSchema, type RichTextValidated } from \"../schema/asset-schema\";\r\nimport { CANVAS_CONFIG } from \"../config/canvas-constants\";\r\nimport { FontRegistry } from \"../core/font-registry\";\r\nimport { LayoutEngine } from \"../core/layout\";\r\nimport { buildDrawOps } from \"../core/drawops\";\r\nimport { applyAnimation } from \"../core/animations\";\r\nimport { createWebPainter } from \"../painters/web\";\r\nimport { fetchToArrayBuffer } from \"../io/web\";\r\n\r\nexport async function createTextEngine(\r\n opts: {\r\n width?: number;\r\n height?: number;\r\n pixelRatio?: number;\r\n fps?: number;\r\n wasmBaseURL?: string;\r\n } = {}\r\n) {\r\n const width = opts.width ?? CANVAS_CONFIG.DEFAULTS.width;\r\n const height = opts.height ?? CANVAS_CONFIG.DEFAULTS.height;\r\n const pixelRatio = opts.pixelRatio ?? CANVAS_CONFIG.DEFAULTS.pixelRatio;\r\n const wasmBaseURL = opts.wasmBaseURL;\r\n\r\n const fonts = new FontRegistry(wasmBaseURL);\r\n const layout = new LayoutEngine(fonts);\r\n\r\n await fonts.init();\r\n\r\n async function ensureFonts(asset: RichTextValidated) {\r\n // Load custom fonts (bytes) if provided\r\n if (asset.customFonts) {\r\n for (const cf of asset.customFonts) {\r\n const bytes = await fetchToArrayBuffer(cf.src);\r\n await fonts.registerFromBytes(bytes, {\r\n family: cf.family,\r\n weight: cf.weight ?? \"400\",\r\n style: cf.style ?? \"normal\",\r\n });\r\n }\r\n }\r\n // Ensure main font is loaded (if same as custom, already there)\r\n const main = asset.font ?? {\r\n family: \"Roboto\",\r\n weight: \"400\",\r\n style: \"normal\",\r\n size: 48,\r\n color: \"#000000\",\r\n opacity: 1,\r\n };\r\n // No system fonts: require the user to register customFonts for deterministic results.\r\n return main;\r\n }\r\n\r\n return {\r\n validate(input: unknown): { value: RichTextValidated } {\r\n const { value, error } = RichTextAssetSchema.validate(input, {\r\n abortEarly: false,\r\n convert: true,\r\n });\r\n if (error) throw error;\r\n return { value: value as RichTextValidated };\r\n },\r\n async registerFontFromUrl(\r\n url: string,\r\n desc: { family: string; weight?: string | number; style?: string }\r\n ) {\r\n const bytes = await fetchToArrayBuffer(url);\r\n await fonts.registerFromBytes(bytes, desc);\r\n },\r\n async registerFontFromFile(\r\n source: string | Blob,\r\n desc: { family: string; weight?: string | number; style?: string }\r\n ) {\r\n let bytes: ArrayBuffer;\r\n if (typeof source === \"string\") {\r\n bytes = await fetchToArrayBuffer(source);\r\n } else {\r\n bytes = await source.arrayBuffer();\r\n }\r\n await fonts.registerFromBytes(bytes, desc);\r\n },\r\n\r\n async renderFrame(asset: RichTextValidated, tSeconds: number) {\r\n const main = await ensureFonts(asset);\r\n const desc = { family: main.family, weight: `${main.weight}`, style: main.style };\r\n\r\n const lines = await layout.layout({\r\n text: asset.text,\r\n width: asset.width ?? width,\r\n letterSpacing: asset.style?.letterSpacing ?? 0,\r\n fontSize: main.size,\r\n lineHeight: asset.style?.lineHeight ?? 1.2,\r\n desc,\r\n textTransform: asset.style?.textTransform ?? \"none\",\r\n });\r\n\r\n const textRect = { x: 0, y: 0, width: asset.width ?? width, height: asset.height ?? height };\r\n const ops0 = await buildDrawOps({\r\n canvas: { width, height, pixelRatio },\r\n textRect,\r\n lines,\r\n font: {\r\n family: main.family,\r\n size: main.size,\r\n weight: `${main.weight}`,\r\n style: main.style,\r\n color: main.color,\r\n opacity: main.opacity,\r\n },\r\n style: {\r\n lineHeight: asset.style?.lineHeight ?? 1.2,\r\n textDecoration: asset.style?.textDecoration ?? \"none\",\r\n gradient: asset.style?.gradient,\r\n },\r\n stroke: asset.stroke,\r\n shadow: asset.shadow,\r\n align: asset.align ?? { horizontal: \"left\", vertical: \"middle\" },\r\n background: asset.background,\r\n glyphPathProvider: (gid) => fonts.glyphPath(desc, gid),\r\n getUnitsPerEm: () => fonts.getUnitsPerEm(desc),\r\n });\r\n\r\n const ops = applyAnimation(ops0, lines, {\r\n t: tSeconds,\r\n fontSize: main.size,\r\n anim: asset.animation\r\n ? {\r\n preset: asset.animation.preset as any,\r\n speed: asset.animation.speed,\r\n duration: asset.animation.duration,\r\n style: asset.animation.style as any,\r\n direction: asset.animation.direction as any,\r\n }\r\n : undefined,\r\n });\r\n\r\n return ops;\r\n },\r\n\r\n createRenderer(canvas: HTMLCanvasElement | OffscreenCanvas) {\r\n return createWebPainter(canvas);\r\n },\r\n\r\n destroy() {\r\n fonts.destroy();\r\n },\r\n };\r\n}\r\n\r\nexport * from \"../types\";\r\n"],"mappings":"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","names":["computePathBounds","tokenizePath"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shotstack/shotstack-canvas",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Text layout & animation engine (HarfBuzz) for Node & Web.",
5
5
  "type": "module",
6
6
  "main": "./dist/entry.node.cjs",