diff options
Diffstat (limited to 'apps/web/src/text/measure-element.ts')
| -rw-r--r-- | apps/web/src/text/measure-element.ts | 199 |
1 files changed, 186 insertions, 13 deletions
diff --git a/apps/web/src/text/measure-element.ts b/apps/web/src/text/measure-element.ts index ec14421b..d89cd2f8 100644 --- a/apps/web/src/text/measure-element.ts +++ b/apps/web/src/text/measure-element.ts @@ -8,6 +8,11 @@ import { import { measureTextLayout, type MeasuredTextLayout, + type TextAlign, + type TextDecoration, + type TextFontStyle, + type TextFontWeight, + type TextLayoutParams, } from "./primitives"; export interface ResolvedTextBackground extends TextBackground { @@ -67,23 +72,14 @@ export function measureTextElement({ localTime: number; ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D; }): MeasuredTextElement { + const text = buildTextLayoutParamsFromElement({ element }); 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, - }, + text, canvasHeight, ctx, }); - const bg = element.background; + const bg = buildTextBackgroundFromElement({ element }); const resolvedBackground: ResolvedTextBackground = { ...bg, paddingX: resolveNumberAtTime({ @@ -119,7 +115,7 @@ export function measureTextElement({ }; const visualRect = getTextVisualRect({ - textAlign: element.textAlign, + textAlign: text.textAlign, block: measuredLayout.block, background: resolvedBackground, fontSizeRatio: measuredLayout.fontSizeRatio, @@ -131,3 +127,180 @@ export function measureTextElement({ visualRect, }; } + +export function buildTextLayoutParamsFromElement({ + element, +}: { + element: TextElement; +}): TextLayoutParams { + return { + content: readStringParam({ + params: element.params, + key: "content", + fallback: "Default text", + }), + fontSize: readNumberParam({ + params: element.params, + key: "fontSize", + fallback: 15, + }), + fontFamily: readStringParam({ + params: element.params, + key: "fontFamily", + fallback: "Arial", + }), + fontWeight: readFontWeight({ + value: element.params.fontWeight, + fallback: "normal", + }), + fontStyle: readFontStyle({ + value: element.params.fontStyle, + fallback: "normal", + }), + textAlign: readTextAlign({ + value: element.params.textAlign, + fallback: "center", + }), + textDecoration: readTextDecoration({ + value: element.params.textDecoration, + fallback: "none", + }), + letterSpacing: readNumberParam({ + params: element.params, + key: "letterSpacing", + fallback: DEFAULTS.text.letterSpacing, + }), + lineHeight: readNumberParam({ + params: element.params, + key: "lineHeight", + fallback: DEFAULTS.text.lineHeight, + }), + }; +} + +export function buildTextBackgroundFromElement({ + element, +}: { + element: TextElement; +}): TextBackground { + return { + enabled: readBooleanParam({ + params: element.params, + key: "background.enabled", + fallback: DEFAULTS.text.background.enabled, + }), + color: readStringParam({ + params: element.params, + key: "background.color", + fallback: DEFAULTS.text.background.color, + }), + cornerRadius: readNumberParam({ + params: element.params, + key: "background.cornerRadius", + fallback: DEFAULTS.text.background.cornerRadius, + }), + paddingX: readNumberParam({ + params: element.params, + key: "background.paddingX", + fallback: DEFAULTS.text.background.paddingX, + }), + paddingY: readNumberParam({ + params: element.params, + key: "background.paddingY", + fallback: DEFAULTS.text.background.paddingY, + }), + offsetX: readNumberParam({ + params: element.params, + key: "background.offsetX", + fallback: DEFAULTS.text.background.offsetX, + }), + offsetY: readNumberParam({ + params: element.params, + key: "background.offsetY", + fallback: DEFAULTS.text.background.offsetY, + }), + }; +} + +function readStringParam({ + params, + key, + fallback, +}: { + params: TextElement["params"]; + key: string; + fallback: string; +}): string { + const value = params[key]; + return typeof value === "string" ? value : fallback; +} + +function readNumberParam({ + params, + key, + fallback, +}: { + params: TextElement["params"]; + key: string; + fallback: number; +}): number { + const value = params[key]; + return typeof value === "number" ? value : fallback; +} + +function readBooleanParam({ + params, + key, + fallback, +}: { + params: TextElement["params"]; + key: string; + fallback: boolean; +}): boolean { + const value = params[key]; + return typeof value === "boolean" ? value : fallback; +} + +function readTextAlign({ + value, + fallback, +}: { + value: unknown; + fallback: TextAlign; +}): TextAlign { + return value === "left" || value === "center" || value === "right" + ? value + : fallback; +} + +function readFontWeight({ + value, + fallback, +}: { + value: unknown; + fallback: TextFontWeight; +}): TextFontWeight { + return value === "bold" || value === "normal" ? value : fallback; +} + +function readFontStyle({ + value, + fallback, +}: { + value: unknown; + fallback: TextFontStyle; +}): TextFontStyle { + return value === "italic" || value === "normal" ? value : fallback; +} + +function readTextDecoration({ + value, + fallback, +}: { + value: unknown; + fallback: TextDecoration; +}): TextDecoration { + return value === "none" || value === "underline" || value === "line-through" + ? value + : fallback; +} |
