summaryrefslogtreecommitdiff
path: root/apps/web/src/text
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-04-29 01:28:50 +0200
committerMaze Winther <mazewinther@gmail.com>2026-05-02 03:27:23 +0200
commit2ee0a44735d2b930348e9774909638b2c1909738 (patch)
treee73e60097338ed411739f3b04808dad86f7bb192 /apps/web/src/text
parenta9b9cf6bf50f08723896659634f2e6afc17bcd42 (diff)
downloadopencut-2ee0a44735d2b930348e9774909638b2c1909738.tar.gz
refactor: unify element params
Diffstat (limited to 'apps/web/src/text')
-rw-r--r--apps/web/src/text/components/assets-view.tsx2
-rw-r--r--apps/web/src/text/components/text-tab.tsx0
-rw-r--r--apps/web/src/text/layout.ts9
-rw-r--r--apps/web/src/text/measure-element.ts199
-rw-r--r--apps/web/src/text/primitives.ts2
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,