59 lines
1.6 KiB
TypeScript
59 lines
1.6 KiB
TypeScript
import { BaseNode } from "./base-node";
|
|
import type { TextElement } from "@/model";
|
|
import type { EffectPass } from "@/model/decorations/effect";
|
|
import type { Transform } from "@/model/rendering";
|
|
import { drawMeasuredTextLayout } from "@/text/primitives";
|
|
import type { MeasuredTextElement } from "@/text/measure-element";
|
|
|
|
export type TextNodeParams = TextElement & {
|
|
canvasCenter: { x: number; y: number };
|
|
canvasHeight: number;
|
|
textBaseline?: CanvasTextBaseline;
|
|
};
|
|
|
|
export interface ResolvedTextNodeState {
|
|
transform: Transform;
|
|
opacity: number;
|
|
textColor: string;
|
|
backgroundColor: string;
|
|
effectPasses: EffectPass[][];
|
|
measuredText: MeasuredTextElement;
|
|
}
|
|
|
|
export class TextNode extends BaseNode<TextNodeParams, ResolvedTextNodeState> {}
|
|
|
|
export function renderTextToContext({
|
|
node,
|
|
ctx,
|
|
}: {
|
|
node: TextNode;
|
|
ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;
|
|
}): void {
|
|
const resolved = node.resolved;
|
|
if (!resolved) {
|
|
return;
|
|
}
|
|
|
|
const x = resolved.transform.position.x + node.params.canvasCenter.x;
|
|
const y = resolved.transform.position.y + node.params.canvasCenter.y;
|
|
const baseline = node.params.textBaseline ?? "middle";
|
|
|
|
ctx.save();
|
|
ctx.translate(x, y);
|
|
ctx.scale(resolved.transform.scaleX, resolved.transform.scaleY);
|
|
if (resolved.transform.rotate) {
|
|
ctx.rotate((resolved.transform.rotate * Math.PI) / 180);
|
|
}
|
|
|
|
drawMeasuredTextLayout({
|
|
ctx,
|
|
layout: resolved.measuredText,
|
|
textColor: resolved.textColor,
|
|
background: resolved.measuredText.resolvedBackground,
|
|
backgroundColor: resolved.backgroundColor,
|
|
textBaseline: baseline,
|
|
});
|
|
|
|
ctx.restore();
|
|
}
|