summaryrefslogtreecommitdiff
path: root/apps/web/src
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-05-02 16:38:06 +0200
committerMaze Winther <mazewinther@gmail.com>2026-05-02 16:38:06 +0200
commit8ab3aeba7c99cb634254d5c1f52fab3f5f4811b1 (patch)
treee7913d52cf35223ec95fa7c10e86b1c6b2a44cf4 /apps/web/src
parent0b7597b31fa956c7f3d4838923b545ba5e341422 (diff)
downloadopencut-8ab3aeba7c99cb634254d5c1f52fab3f5f4811b1.tar.gz
docs: move NOTES.md file
Diffstat (limited to 'apps/web/src')
-rw-r--r--apps/web/src/graphics/index.ts298
-rw-r--r--apps/web/src/rendering/NOTES.md27
2 files changed, 149 insertions, 176 deletions
diff --git a/apps/web/src/graphics/index.ts b/apps/web/src/graphics/index.ts
index 3f277d40..7f5ac08b 100644
--- a/apps/web/src/graphics/index.ts
+++ b/apps/web/src/graphics/index.ts
@@ -1,149 +1,149 @@
-import { resolveGraphicParamsAtTime } from "@/animation";
-import type { ElementAnimations } from "@/animation/types";
-import { buildDefaultParamValues } from "@/params/registry";
-import type { ParamValues } from "@/params";
-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<string, string>();
-
-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 = `
- <svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">
- <rect width="${size}" height="${size}" rx="${size * FALLBACK_CORNER_RADIUS_RATIO}" fill="white" fill-opacity="${FALLBACK_FILL_OPACITY}" />
- <text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" fill="white" font-size="${Math.max(FALLBACK_MIN_FONT_SIZE, size * FALLBACK_FONT_SIZE_RATIO)}" font-family="sans-serif">${name}</text>
- </svg>
- `;
- 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";
+import { resolveGraphicParamsAtTime } from "@/animation";
+import type { ElementAnimations } from "@/animation/types";
+import { buildDefaultParamValues } from "@/params/registry";
+import type { ParamValues } from "@/params";
+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<string, string>();
+
+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 = `
+ <svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">
+ <rect width="${size}" height="${size}" rx="${size * FALLBACK_CORNER_RADIUS_RATIO}" fill="white" fill-opacity="${FALLBACK_FILL_OPACITY}" />
+ <text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" fill="white" font-size="${Math.max(FALLBACK_MIN_FONT_SIZE, size * FALLBACK_FONT_SIZE_RATIO)}" font-family="sans-serif">${name}</text>
+ </svg>
+ `;
+ 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";
diff --git a/apps/web/src/rendering/NOTES.md b/apps/web/src/rendering/NOTES.md
deleted file mode 100644
index 38055c14..00000000
--- a/apps/web/src/rendering/NOTES.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# Notes
-
-## `Transform` is misplaced
-
-`Transform` is currently defined in `apps/web/src/rendering/index.ts`. It's
-exported from the rendering domain because rendering happens to be one of its
-consumers — but every other domain that touches scene geometry consumes it too
-(`@/timeline`, `@/preview`, `@/animation/values`, `@/text`, etc.). It's not
-"of" rendering any more than `Vector2` would be "of" math.
-
-`Transform` is closer to a primitive than a domain concept. It's infrastructure:
-a small value type with no behavior, no dependencies, no domain-specific
-invariants. Anything that wants to position something on a 2D canvas needs it.
-
-The codebase should be refactored so it's defined lower-level, rather than
-sitting in a domain. Candidate homes:
-
-- `apps/web/src/primitives/transform.ts` (new dir for these value types)
-- `apps/web/src/geometry/transform.ts` if `Vector2` and friends end up there
-- `apps/web/src/rendering/transform.ts` is acceptable only if `@/rendering`
-becomes a primitives folder rather than a domain (it's borderline today —
-it also exports `BlendMode`, which has the same problem).
-
-Side effect of fixing this: `@/rendering/animation-values.ts` (which exists
-only because `Transform` lives next to it) can move into `@/animation/values.ts`
-alongside the other resolve-at-time helpers, since `Transform` would no longer
-pull in a domain dependency. \ No newline at end of file