From 3e89d2998588f8e35c524e523ba2ee853f0f6475 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 20 Apr 2026 11:31:17 +0200 Subject: refactor: restructure files to their domains, new preview overlay system, and dep graph --- apps/web/src/text/measure-element.ts | 133 +++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 apps/web/src/text/measure-element.ts (limited to 'apps/web/src/text/measure-element.ts') diff --git a/apps/web/src/text/measure-element.ts b/apps/web/src/text/measure-element.ts new file mode 100644 index 00000000..3a49696f --- /dev/null +++ b/apps/web/src/text/measure-element.ts @@ -0,0 +1,133 @@ +import { CORNER_RADIUS_MIN } from "@/text/background"; +import { resolveNumberAtTime } from "@/animation"; +import { DEFAULTS } from "@/timeline/defaults"; +import type { TextBackground, TextElement } from "@/timeline"; +import { + getTextVisualRect, +} from "./layout"; +import { + measureTextLayout, + type MeasuredTextLayout, +} from "./primitives"; + +export interface ResolvedTextBackground extends TextBackground { + paddingX: number; + paddingY: number; + offsetX: number; + offsetY: number; + cornerRadius: number; +} + +export interface MeasuredTextElement extends MeasuredTextLayout { + resolvedBackground: ResolvedTextBackground; + visualRect: { left: number; top: number; width: number; height: number }; +} + +let textMeasurementContext: + | CanvasRenderingContext2D + | OffscreenCanvasRenderingContext2D + | null = null; + +export function getTextMeasurementContext(): + | CanvasRenderingContext2D + | OffscreenCanvasRenderingContext2D { + if (textMeasurementContext) { + return textMeasurementContext; + } + + if (typeof OffscreenCanvas !== "undefined") { + const canvas = new OffscreenCanvas(1, 1); + const context = canvas.getContext("2d"); + if (context) { + textMeasurementContext = context; + return context; + } + } + + if (typeof document !== "undefined") { + const canvas = document.createElement("canvas"); + const context = canvas.getContext("2d"); + if (context) { + textMeasurementContext = context; + return context; + } + } + + throw new Error("Failed to create text measurement context"); +} + +export function measureTextElement({ + element, + canvasHeight, + localTime, + ctx, +}: { + element: TextElement; + canvasHeight: number; + localTime: number; + ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D; +}): MeasuredTextElement { + const measuredLayout = measureTextLayout({ + text: { + content: element.content, + fontSize: element.fontSize, + fontFamily: element.fontFamily, + fontWeight: element.fontWeight, + fontStyle: element.fontStyle, + textAlign: element.textAlign, + textDecoration: element.textDecoration, + letterSpacing: element.letterSpacing, + lineHeight: element.lineHeight, + }, + canvasHeight, + ctx, + }); + + const bg = element.background; + const resolvedBackground: ResolvedTextBackground = { + ...bg, + paddingX: resolveNumberAtTime({ + baseValue: bg.paddingX ?? DEFAULTS.text.background.paddingX, + animations: element.animations, + propertyPath: "background.paddingX", + localTime, + }), + paddingY: resolveNumberAtTime({ + baseValue: bg.paddingY ?? DEFAULTS.text.background.paddingY, + animations: element.animations, + propertyPath: "background.paddingY", + localTime, + }), + offsetX: resolveNumberAtTime({ + baseValue: bg.offsetX ?? DEFAULTS.text.background.offsetX, + animations: element.animations, + propertyPath: "background.offsetX", + localTime, + }), + offsetY: resolveNumberAtTime({ + baseValue: bg.offsetY ?? DEFAULTS.text.background.offsetY, + animations: element.animations, + propertyPath: "background.offsetY", + localTime, + }), + cornerRadius: resolveNumberAtTime({ + baseValue: bg.cornerRadius ?? CORNER_RADIUS_MIN, + animations: element.animations, + propertyPath: "background.cornerRadius", + localTime, + }), + }; + + const visualRect = getTextVisualRect({ + textAlign: element.textAlign, + block: measuredLayout.block, + background: resolvedBackground, + fontSizeRatio: measuredLayout.fontSizeRatio, + }); + + return { + ...measuredLayout, + resolvedBackground, + visualRect, + }; +} -- cgit v1.3.1