import { resolveGraphicParamsAtTime } from "@/animation"; import type { ElementAnimations } from "@/model/decorations/animations"; import { buildDefaultParamValues } from "@/params/registry"; import type { ParamValues } from "@/model/decorations/param-values"; import { graphicsRegistry } from "./registry"; import { registerDefaultGraphics, ellipseGraphicDefinition, polygonGraphicDefinition, rectangleGraphicDefinition, starGraphicDefinition, } from "./definitions"; import { DEFAULT_GRAPHIC_SOURCE_SIZE, type GraphicInstance, type GraphicDefinition, } from "./types"; const graphicPreviewUrlCache = new Map(); const FALLBACK_CORNER_RADIUS_RATIO = 0.2; const FALLBACK_FILL_OPACITY = 0.08; const FALLBACK_MIN_FONT_SIZE = 12; const FALLBACK_FONT_SIZE_RATIO = 0.15; function buildFallbackPreviewUrl({ name, size, }: { name: string; size: number; }): string { const svg = ` ${name} `; return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`; } export function getGraphicDefinition({ definitionId, }: { definitionId: string; }): GraphicDefinition { registerDefaultGraphics(); return graphicsRegistry.get(definitionId); } export function buildDefaultGraphicInstance({ definitionId, }: { definitionId: string; }): GraphicInstance { const definition = getGraphicDefinition({ definitionId }); return { definitionId, params: buildDefaultParamValues(definition.params), }; } export function resolveGraphicParams( definition: GraphicDefinition, params?: ParamValues, ): ParamValues { return { ...buildDefaultParamValues(definition.params), ...(params ?? {}), }; } export function resolveGraphicElementParamsAtTime({ element, localTime, }: { element: { definitionId: string; params: ParamValues; animations?: ElementAnimations; }; localTime: number; }): ParamValues { const definition = getGraphicDefinition({ definitionId: element.definitionId, }); return resolveGraphicParamsAtTime({ params: resolveGraphicParams(definition, element.params), definitions: definition.params, animations: element.animations, localTime, }); } export function buildGraphicPreviewUrl({ definitionId, params, size = DEFAULT_GRAPHIC_SOURCE_SIZE, }: { definitionId: string; params?: ParamValues; size?: number; }): string { const definition = getGraphicDefinition({ definitionId }); const resolvedParams = resolveGraphicParams(definition, params); const cacheKey = JSON.stringify({ definitionId, resolvedParams, size }); const cachedUrl = graphicPreviewUrlCache.get(cacheKey); if (cachedUrl) { return cachedUrl; } if (typeof document === "undefined") { return buildFallbackPreviewUrl({ name: definition.name, size }); } const canvas = document.createElement("canvas"); canvas.width = size; canvas.height = size; const ctx = canvas.getContext("2d"); if (!ctx) { return buildFallbackPreviewUrl({ name: definition.name, size }); } definition.render({ ctx, params: resolvedParams, width: size, height: size, }); const previewUrl = canvas.toDataURL("image/png"); graphicPreviewUrlCache.set(cacheKey, previewUrl); return previewUrl; } export { DEFAULT_GRAPHIC_SOURCE_SIZE, ellipseGraphicDefinition, graphicsRegistry, polygonGraphicDefinition, rectangleGraphicDefinition, registerDefaultGraphics, starGraphicDefinition, }; export type { GraphicDefinition, GraphicInstance, GraphicRenderContext, } from "./types";