diff options
Diffstat (limited to 'apps/web/src/text')
| -rw-r--r-- | apps/web/src/text/components/assets-view.tsx | 2 | ||||
| -rw-r--r-- | apps/web/src/text/components/text-tab.tsx | 0 | ||||
| -rw-r--r-- | apps/web/src/text/layout.ts | 9 | ||||
| -rw-r--r-- | apps/web/src/text/measure-element.ts | 199 | ||||
| -rw-r--r-- | apps/web/src/text/primitives.ts | 2 |
5 files changed, 193 insertions, 19 deletions
diff --git a/apps/web/src/text/components/assets-view.tsx b/apps/web/src/text/components/assets-view.tsx index 82a8e46c..036bc898 100644 --- a/apps/web/src/text/components/assets-view.tsx +++ b/apps/web/src/text/components/assets-view.tsx @@ -36,7 +36,7 @@ export function TextView() { id: "temp-text-id", type: DEFAULTS.text.element.type, name: DEFAULTS.text.element.name, - content: DEFAULTS.text.element.content, + content: "Default text", }} aspectRatio={1} onAddToTimeline={handleAddToTimeline} diff --git a/apps/web/src/text/components/text-tab.tsx b/apps/web/src/text/components/text-tab.tsx deleted file mode 100644 index e69de29b..00000000 --- a/apps/web/src/text/components/text-tab.tsx +++ /dev/null diff --git a/apps/web/src/text/layout.ts b/apps/web/src/text/layout.ts index aabf5ca9..65e17291 100644 --- a/apps/web/src/text/layout.ts +++ b/apps/web/src/text/layout.ts @@ -1,5 +1,6 @@ -import type { TextBackground, TextElement } from "@/timeline"; +import type { TextBackground } from "@/timeline"; import { DEFAULTS } from "@/timeline/defaults"; +import type { TextAlign } from "@/text/primitives"; type TextRect = { left: number; @@ -78,7 +79,7 @@ function getTextRect({ textAlign, block, }: { - textAlign: TextElement["textAlign"]; + textAlign: TextAlign; block: TextBlockMeasurement; }): TextRect { const textAlignToLeft: Record<typeof textAlign, number> = { @@ -114,7 +115,7 @@ export function getTextBackgroundRect({ background, fontSizeRatio = 1, }: { - textAlign: TextElement["textAlign"]; + textAlign: TextAlign; block: TextBlockMeasurement; background: TextBackground; fontSizeRatio?: number; @@ -145,7 +146,7 @@ export function getTextVisualRect({ background, fontSizeRatio = 1, }: { - textAlign: TextElement["textAlign"]; + textAlign: TextAlign; block: TextBlockMeasurement; background: TextBackground; fontSizeRatio?: number; 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; +} diff --git a/apps/web/src/text/primitives.ts b/apps/web/src/text/primitives.ts index 9a9262a4..b2eefa95 100644 --- a/apps/web/src/text/primitives.ts +++ b/apps/web/src/text/primitives.ts @@ -85,7 +85,7 @@ export function resolveTextLayout({ const letterSpacing = text.letterSpacing ?? DEFAULTS.text.letterSpacing; const lineHeightPx = scaledFontSize * (text.lineHeight ?? DEFAULTS.text.lineHeight); - const fontSizeRatio = text.fontSize / DEFAULTS.text.element.fontSize; + const fontSizeRatio = text.fontSize / 15; return { scaledFontSize, |
