summaryrefslogtreecommitdiff
path: root/apps/web/src/text/measure-element.ts
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/text/measure-element.ts')
-rw-r--r--apps/web/src/text/measure-element.ts199
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;
+}