codeboard-studio 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE +23 -0
- package/README.md +54 -0
- package/dist/src/animation/camera-plane.d.ts +8 -0
- package/dist/src/animation/camera-plane.d.ts.map +1 -0
- package/dist/src/animation/camera-plane.js +16 -0
- package/dist/src/animation/camera-plane.js.map +1 -0
- package/dist/src/animation/drawing-neighbors.d.ts +4 -0
- package/dist/src/animation/drawing-neighbors.d.ts.map +1 -0
- package/dist/src/animation/drawing-neighbors.js +38 -0
- package/dist/src/animation/drawing-neighbors.js.map +1 -0
- package/dist/src/animation/evaluate.d.ts +17 -0
- package/dist/src/animation/evaluate.d.ts.map +1 -0
- package/dist/src/animation/evaluate.js +70 -0
- package/dist/src/animation/evaluate.js.map +1 -0
- package/dist/src/animation/frame.d.ts +8 -0
- package/dist/src/animation/frame.d.ts.map +1 -0
- package/dist/src/animation/frame.js +16 -0
- package/dist/src/animation/frame.js.map +1 -0
- package/dist/src/animation/ik.d.ts +26 -0
- package/dist/src/animation/ik.d.ts.map +1 -0
- package/dist/src/animation/ik.js +47 -0
- package/dist/src/animation/ik.js.map +1 -0
- package/dist/src/animation/retime.d.ts +4 -0
- package/dist/src/animation/retime.d.ts.map +1 -0
- package/dist/src/animation/retime.js +116 -0
- package/dist/src/animation/retime.js.map +1 -0
- package/dist/src/audio/wav.d.ts +11 -0
- package/dist/src/audio/wav.d.ts.map +1 -0
- package/dist/src/audio/wav.js +58 -0
- package/dist/src/audio/wav.js.map +1 -0
- package/dist/src/authoring-runner.d.ts +2 -0
- package/dist/src/authoring-runner.d.ts.map +1 -0
- package/dist/src/authoring-runner.js +24 -0
- package/dist/src/authoring-runner.js.map +1 -0
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +127 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/core/coordinates.d.ts +16 -0
- package/dist/src/core/coordinates.d.ts.map +1 -0
- package/dist/src/core/coordinates.js +48 -0
- package/dist/src/core/coordinates.js.map +1 -0
- package/dist/src/core/handles.d.ts +93 -0
- package/dist/src/core/handles.d.ts.map +1 -0
- package/dist/src/core/handles.js +190 -0
- package/dist/src/core/handles.js.map +1 -0
- package/dist/src/core/history.d.ts +14 -0
- package/dist/src/core/history.d.ts.map +1 -0
- package/dist/src/core/history.js +80 -0
- package/dist/src/core/history.js.map +1 -0
- package/dist/src/core/inspection.d.ts +51 -0
- package/dist/src/core/inspection.d.ts.map +1 -0
- package/dist/src/core/inspection.js +72 -0
- package/dist/src/core/inspection.js.map +1 -0
- package/dist/src/core/production.d.ts +208 -0
- package/dist/src/core/production.d.ts.map +1 -0
- package/dist/src/core/production.js +894 -0
- package/dist/src/core/production.js.map +1 -0
- package/dist/src/core/project.d.ts +146 -0
- package/dist/src/core/project.d.ts.map +1 -0
- package/dist/src/core/project.js +700 -0
- package/dist/src/core/project.js.map +1 -0
- package/dist/src/drawing/brush-authoring.d.ts +6 -0
- package/dist/src/drawing/brush-authoring.d.ts.map +1 -0
- package/dist/src/drawing/brush-authoring.js +12 -0
- package/dist/src/drawing/brush-authoring.js.map +1 -0
- package/dist/src/drawing/brushes.d.ts +157 -0
- package/dist/src/drawing/brushes.d.ts.map +1 -0
- package/dist/src/drawing/brushes.js +50 -0
- package/dist/src/drawing/brushes.js.map +1 -0
- package/dist/src/drawing/color.d.ts +5 -0
- package/dist/src/drawing/color.d.ts.map +1 -0
- package/dist/src/drawing/color.js +63 -0
- package/dist/src/drawing/color.js.map +1 -0
- package/dist/src/drawing/curves.d.ts +27 -0
- package/dist/src/drawing/curves.d.ts.map +1 -0
- package/dist/src/drawing/curves.js +170 -0
- package/dist/src/drawing/curves.js.map +1 -0
- package/dist/src/drawing/math.d.ts +10 -0
- package/dist/src/drawing/math.d.ts.map +1 -0
- package/dist/src/drawing/math.js +40 -0
- package/dist/src/drawing/math.js.map +1 -0
- package/dist/src/drawing/path-geometry.d.ts +18 -0
- package/dist/src/drawing/path-geometry.d.ts.map +1 -0
- package/dist/src/drawing/path-geometry.js +115 -0
- package/dist/src/drawing/path-geometry.js.map +1 -0
- package/dist/src/drawing/path-sampling.d.ts +10 -0
- package/dist/src/drawing/path-sampling.d.ts.map +1 -0
- package/dist/src/drawing/path-sampling.js +64 -0
- package/dist/src/drawing/path-sampling.js.map +1 -0
- package/dist/src/drawing/path.d.ts +4 -0
- package/dist/src/drawing/path.d.ts.map +1 -0
- package/dist/src/drawing/path.js +27 -0
- package/dist/src/drawing/path.js.map +1 -0
- package/dist/src/drawing/pen-input.d.ts +5 -0
- package/dist/src/drawing/pen-input.d.ts.map +1 -0
- package/dist/src/drawing/pen-input.js +30 -0
- package/dist/src/drawing/pen-input.js.map +1 -0
- package/dist/src/drawing/pixel-selection.d.ts +23 -0
- package/dist/src/drawing/pixel-selection.d.ts.map +1 -0
- package/dist/src/drawing/pixel-selection.js +142 -0
- package/dist/src/drawing/pixel-selection.js.map +1 -0
- package/dist/src/drawing/pixels.d.ts +22 -0
- package/dist/src/drawing/pixels.d.ts.map +1 -0
- package/dist/src/drawing/pixels.js +79 -0
- package/dist/src/drawing/pixels.js.map +1 -0
- package/dist/src/drawing/resource-binary.d.ts +23 -0
- package/dist/src/drawing/resource-binary.d.ts.map +1 -0
- package/dist/src/drawing/resource-binary.js +135 -0
- package/dist/src/drawing/resource-binary.js.map +1 -0
- package/dist/src/drawing/resources.d.ts +51 -0
- package/dist/src/drawing/resources.d.ts.map +1 -0
- package/dist/src/drawing/resources.js +239 -0
- package/dist/src/drawing/resources.js.map +1 -0
- package/dist/src/drawing/stroke-outline.d.ts +5 -0
- package/dist/src/drawing/stroke-outline.d.ts.map +1 -0
- package/dist/src/drawing/stroke-outline.js +53 -0
- package/dist/src/drawing/stroke-outline.js.map +1 -0
- package/dist/src/drawing/swatch.d.ts +6 -0
- package/dist/src/drawing/swatch.d.ts.map +1 -0
- package/dist/src/drawing/swatch.js +15 -0
- package/dist/src/drawing/swatch.js.map +1 -0
- package/dist/src/export/animatic-export.d.ts +11 -0
- package/dist/src/export/animatic-export.d.ts.map +1 -0
- package/dist/src/export/animatic-export.js +52 -0
- package/dist/src/export/animatic-export.js.map +1 -0
- package/dist/src/export/movie-export.d.ts +16 -0
- package/dist/src/export/movie-export.d.ts.map +1 -0
- package/dist/src/export/movie-export.js +108 -0
- package/dist/src/export/movie-export.js.map +1 -0
- package/dist/src/export/sheet-layout.d.ts +27 -0
- package/dist/src/export/sheet-layout.d.ts.map +1 -0
- package/dist/src/export/sheet-layout.js +72 -0
- package/dist/src/export/sheet-layout.js.map +1 -0
- package/dist/src/export/storyboard-export.d.ts +8 -0
- package/dist/src/export/storyboard-export.d.ts.map +1 -0
- package/dist/src/export/storyboard-export.js +76 -0
- package/dist/src/export/storyboard-export.js.map +1 -0
- package/dist/src/index.d.ts +36 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +27 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/model/query.d.ts +6 -0
- package/dist/src/model/query.d.ts.map +1 -0
- package/dist/src/model/query.js +7 -0
- package/dist/src/model/query.js.map +1 -0
- package/dist/src/model/schema.d.ts +754 -0
- package/dist/src/model/schema.d.ts.map +1 -0
- package/dist/src/model/schema.js +205 -0
- package/dist/src/model/schema.js.map +1 -0
- package/dist/src/model/types.d.ts +537 -0
- package/dist/src/model/types.d.ts.map +1 -0
- package/dist/src/model/types.js +8 -0
- package/dist/src/model/types.js.map +1 -0
- package/dist/src/model/validate.d.ts +12 -0
- package/dist/src/model/validate.d.ts.map +1 -0
- package/dist/src/model/validate.js +183 -0
- package/dist/src/model/validate.js.map +1 -0
- package/dist/src/preview/server.d.ts +6 -0
- package/dist/src/preview/server.d.ts.map +1 -0
- package/dist/src/preview/server.js +71 -0
- package/dist/src/preview/server.js.map +1 -0
- package/dist/src/render/annotations.d.ts +4 -0
- package/dist/src/render/annotations.d.ts.map +1 -0
- package/dist/src/render/annotations.js +27 -0
- package/dist/src/render/annotations.js.map +1 -0
- package/dist/src/render/brush-engine.d.ts +14 -0
- package/dist/src/render/brush-engine.d.ts.map +1 -0
- package/dist/src/render/brush-engine.js +230 -0
- package/dist/src/render/brush-engine.js.map +1 -0
- package/dist/src/render/layer-compositor.d.ts +33 -0
- package/dist/src/render/layer-compositor.d.ts.map +1 -0
- package/dist/src/render/layer-compositor.js +296 -0
- package/dist/src/render/layer-compositor.js.map +1 -0
- package/dist/src/render/panel-renderer.d.ts +33 -0
- package/dist/src/render/panel-renderer.d.ts.map +1 -0
- package/dist/src/render/panel-renderer.js +118 -0
- package/dist/src/render/panel-renderer.js.map +1 -0
- package/dist/src/render/png.d.ts +4 -0
- package/dist/src/render/png.d.ts.map +1 -0
- package/dist/src/render/png.js +10 -0
- package/dist/src/render/png.js.map +1 -0
- package/dist/src/render/review.d.ts +42 -0
- package/dist/src/render/review.d.ts.map +1 -0
- package/dist/src/render/review.js +192 -0
- package/dist/src/render/review.js.map +1 -0
- package/dist/src/render/vector-renderer.d.ts +5 -0
- package/dist/src/render/vector-renderer.d.ts.map +1 -0
- package/dist/src/render/vector-renderer.js +98 -0
- package/dist/src/render/vector-renderer.js.map +1 -0
- package/dist/src/starter.d.ts +2 -0
- package/dist/src/starter.d.ts.map +1 -0
- package/dist/src/starter.js +23 -0
- package/dist/src/starter.js.map +1 -0
- package/dist/src/storage/codec.d.ts +20 -0
- package/dist/src/storage/codec.d.ts.map +1 -0
- package/dist/src/storage/codec.js +203 -0
- package/dist/src/storage/codec.js.map +1 -0
- package/dist/src/storage/store.d.ts +89 -0
- package/dist/src/storage/store.d.ts.map +1 -0
- package/dist/src/storage/store.js +392 -0
- package/dist/src/storage/store.js.map +1 -0
- package/dist/src/updates.d.ts +10 -0
- package/dist/src/updates.d.ts.map +1 -0
- package/dist/src/updates.js +134 -0
- package/dist/src/updates.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { isDrawingColor } from "../drawing/color.js";
|
|
2
|
+
import { Canvas } from "skia-canvas";
|
|
3
|
+
import { StoryboardProject } from "../core/project.js";
|
|
4
|
+
import { createRenderSession, renderPanelCanvas, renderFrameCanvas } from "./panel-renderer.js";
|
|
5
|
+
import { assertRenderFrame } from "../animation/frame.js";
|
|
6
|
+
import { encodePNG } from "./png.js";
|
|
7
|
+
export async function renderCompositionGuides(source, panelId, options = {}) {
|
|
8
|
+
if (options.thirds !== undefined && typeof options.thirds !== "boolean")
|
|
9
|
+
throw new Error("Guide thirds must be boolean");
|
|
10
|
+
if (options.frame !== undefined)
|
|
11
|
+
assertRenderFrame(options.frame);
|
|
12
|
+
if (options.safeInset !== undefined && (!Number.isFinite(options.safeInset) || options.safeInset < 0 || options.safeInset >= .5))
|
|
13
|
+
throw new Error("Guide safeInset must be within 0 inclusive and 0.5 exclusive");
|
|
14
|
+
if (options.horizonY !== undefined && !Number.isFinite(options.horizonY))
|
|
15
|
+
throw new Error("Guide horizonY must be finite");
|
|
16
|
+
if (options.vanishingPoints?.some(point => !Number.isFinite(point.x) || !Number.isFinite(point.y)))
|
|
17
|
+
throw new Error("Guide vanishing points must have finite coordinates");
|
|
18
|
+
const canvas = renderPanelCanvas(source, panelId, { annotations: false, ...(options.frame === undefined ? {} : { frame: options.frame }) });
|
|
19
|
+
const ctx = canvas.getContext("2d"), w = canvas.width, h = canvas.height;
|
|
20
|
+
ctx.beginPath();
|
|
21
|
+
const line = (x0, y0, x1, y1) => { ctx.moveTo(x0, y0); ctx.lineTo(x1, y1); };
|
|
22
|
+
if (options.thirds ?? true)
|
|
23
|
+
for (const part of [1 / 3, 2 / 3]) {
|
|
24
|
+
line(w * part, 0, w * part, h);
|
|
25
|
+
line(0, h * part, w, h * part);
|
|
26
|
+
}
|
|
27
|
+
if (options.safeInset !== undefined) {
|
|
28
|
+
const inset = options.safeInset;
|
|
29
|
+
ctx.rect(w * inset, h * inset, w * (1 - 2 * inset), h * (1 - 2 * inset));
|
|
30
|
+
}
|
|
31
|
+
if (options.horizonY !== undefined)
|
|
32
|
+
line(0, options.horizonY, w, options.horizonY);
|
|
33
|
+
for (const point of options.vanishingPoints ?? []) {
|
|
34
|
+
for (const [x, y] of [[0, 0], [w, 0], [w, h], [0, h]])
|
|
35
|
+
line(point.x, point.y, x, y);
|
|
36
|
+
ctx.moveTo(point.x + 5, point.y);
|
|
37
|
+
ctx.arc(point.x, point.y, 5, 0, Math.PI * 2);
|
|
38
|
+
}
|
|
39
|
+
ctx.strokeStyle = "#10191d";
|
|
40
|
+
ctx.lineWidth = 3;
|
|
41
|
+
ctx.stroke();
|
|
42
|
+
ctx.strokeStyle = "#50e3ff";
|
|
43
|
+
ctx.lineWidth = 1;
|
|
44
|
+
ctx.stroke();
|
|
45
|
+
return encodePNG(canvas);
|
|
46
|
+
}
|
|
47
|
+
export async function renderContactSheet(source, options = {}) {
|
|
48
|
+
const doc = source instanceof StoryboardProject ? source.toJSON() : source;
|
|
49
|
+
const columns = options.columns ?? 3, width = options.thumbnailWidth ?? 400;
|
|
50
|
+
if (!Number.isInteger(columns) || columns < 1 || columns > 12 || !Number.isInteger(width) || width < 80 || width > 1920)
|
|
51
|
+
throw new Error("Contact sheet columns must be 1..12; thumbnail width 80..1920");
|
|
52
|
+
const byId = new Map(doc.panels.map(panel => [panel.id, panel]));
|
|
53
|
+
if (options.panelIds !== undefined && (!Array.isArray(options.panelIds) || !options.panelIds.length || new Set(options.panelIds).size !== options.panelIds.length))
|
|
54
|
+
throw new Error("Contact sheet panelIds must be a nonempty list of unique panel IDs");
|
|
55
|
+
const ids = options.panelIds ?? doc.scenes.flatMap(scene => scene.shotIds.flatMap(id => doc.shots.find(shot => shot.id === id).panelIds));
|
|
56
|
+
const panels = ids.map(id => { const panel = byId.get(id); if (!panel)
|
|
57
|
+
throw new Error(`Panel not found: ${id}`); return panel; });
|
|
58
|
+
const height = Math.round(width * doc.canvas.height / doc.canvas.width), rows = Math.ceil(panels.length / columns), gap = 16;
|
|
59
|
+
const canvasWidth = columns * (width + gap) + gap, canvasHeight = Math.max(1, rows) * (height + 55) + gap;
|
|
60
|
+
if (canvasWidth * canvasHeight > 32 * 1024 * 1024)
|
|
61
|
+
throw new Error("Contact sheet exceeds 32 megapixels; reduce thumbnail size or select fewer panels");
|
|
62
|
+
const canvas = new Canvas(canvasWidth, canvasHeight);
|
|
63
|
+
const ctx = canvas.getContext("2d"), session = createRenderSession(doc);
|
|
64
|
+
ctx.fillStyle = "#e8e0cd";
|
|
65
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
66
|
+
panels.forEach((p, i) => {
|
|
67
|
+
const x = gap + (i % columns) * (width + gap), y = gap + Math.floor(i / columns) * (height + 55);
|
|
68
|
+
const panel = session.panel(p.id, p.startFrame + Math.floor(p.durationFrames * .6));
|
|
69
|
+
try {
|
|
70
|
+
ctx.drawImage(panel, x, y, width, height);
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
panel.getContext("2d").reset();
|
|
74
|
+
}
|
|
75
|
+
ctx.fillStyle = "#171c20";
|
|
76
|
+
ctx.font = "14px sans-serif";
|
|
77
|
+
ctx.fillText(`${p.number} ${p.title}`, x, y + height + 20, width);
|
|
78
|
+
ctx.font = "12px sans-serif";
|
|
79
|
+
ctx.fillText(`${p.startFrame}f / ${p.durationFrames}f`, x, y + height + 37, width);
|
|
80
|
+
});
|
|
81
|
+
return encodePNG(canvas);
|
|
82
|
+
}
|
|
83
|
+
export async function renderDetail(source, panelId, crop, frame) {
|
|
84
|
+
if (Object.values(crop).some(v => !Number.isFinite(v)) || crop.width < 1 || crop.height < 1 || crop.width * crop.height > 16 * 1024 * 1024)
|
|
85
|
+
throw new Error("Invalid detail crop");
|
|
86
|
+
const art = renderPanelCanvas(source, panelId, { annotations: false, ...(frame === undefined ? {} : { frame }) });
|
|
87
|
+
try {
|
|
88
|
+
const canvas = new Canvas(crop.width, crop.height), ctx = canvas.getContext("2d");
|
|
89
|
+
try {
|
|
90
|
+
ctx.drawImage(art, -crop.x, -crop.y);
|
|
91
|
+
art.getContext("2d").reset();
|
|
92
|
+
return await canvas.toBuffer("png");
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
ctx.reset();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
art.getContext("2d").reset();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export async function renderOnionSkin(source, samples, options = {}) {
|
|
103
|
+
const opacity = options.opacity ?? .3;
|
|
104
|
+
if (!samples.length || samples.length > 8 || !Number.isFinite(opacity) || opacity < 0 || opacity > 1)
|
|
105
|
+
throw new Error("Onion skin requires 1..8 samples and opacity 0..1");
|
|
106
|
+
for (const sample of samples) {
|
|
107
|
+
if (sample.frame !== undefined)
|
|
108
|
+
assertRenderFrame(sample.frame);
|
|
109
|
+
if (sample.tint !== undefined && !isDrawingColor(sample.tint))
|
|
110
|
+
throw new Error("Invalid onion skin tint");
|
|
111
|
+
if (sample.opacity !== undefined && (!Number.isFinite(sample.opacity) || sample.opacity < 0 || sample.opacity > 1))
|
|
112
|
+
throw new Error("Onion skin sample opacity must be between 0 and 1");
|
|
113
|
+
}
|
|
114
|
+
const doc = source instanceof StoryboardProject ? source._readRenderPanels(samples.map(sample => sample.panelId)) : source;
|
|
115
|
+
const panels = samples.map(sample => {
|
|
116
|
+
const panel = doc.panels.find(panel => panel.id === sample.panelId);
|
|
117
|
+
if (!panel)
|
|
118
|
+
throw new Error(`Panel not found: ${sample.panelId}`);
|
|
119
|
+
return panel;
|
|
120
|
+
});
|
|
121
|
+
const first = panels[0];
|
|
122
|
+
if (panels.some(panel => panel.width !== first.width || panel.height !== first.height))
|
|
123
|
+
throw new Error("Onion skin panels must have matching dimensions");
|
|
124
|
+
const canvas = new Canvas(first.width, first.height), ctx = canvas.getContext("2d");
|
|
125
|
+
const transparent = { ...doc, canvas: { ...doc.canvas, background: "transparent" } };
|
|
126
|
+
try {
|
|
127
|
+
for (const [i, sample] of samples.entries()) {
|
|
128
|
+
ctx.globalAlpha = sample.opacity ?? (i === 0 ? 1 : opacity);
|
|
129
|
+
const isolated = sample.tint !== undefined || sample.layerIds !== undefined;
|
|
130
|
+
const art = renderPanelCanvas(i === 0 && !isolated ? doc : transparent, sample.panelId, { annotations: false, camera: options.camera ?? false, ...(sample.frame === undefined ? {} : { frame: sample.frame }), ...(sample.layerIds ? { layerIds: sample.layerIds } : {}) });
|
|
131
|
+
try {
|
|
132
|
+
if (sample.tint !== undefined) {
|
|
133
|
+
const tint = art.getContext("2d");
|
|
134
|
+
tint.globalCompositeOperation = "source-in";
|
|
135
|
+
tint.fillStyle = sample.tint;
|
|
136
|
+
tint.fillRect(0, 0, art.width, art.height);
|
|
137
|
+
}
|
|
138
|
+
ctx.drawImage(art, 0, 0);
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
art.getContext("2d").reset();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return await canvas.toBuffer("png");
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
ctx.reset();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** Timeline samples in caller order, including drawing substitutions and shot transitions. */
|
|
151
|
+
export async function renderFrameSheet(source, frames, options = {}) {
|
|
152
|
+
const columns = options.columns ?? 4, width = options.thumbnailWidth ?? 320, gap = 16, caption = 28;
|
|
153
|
+
if (!Array.isArray(frames) || !frames.length)
|
|
154
|
+
throw new Error("Frame sheet requires a nonempty frame list");
|
|
155
|
+
for (const frame of frames)
|
|
156
|
+
assertRenderFrame(frame);
|
|
157
|
+
if (!Number.isInteger(columns) || columns < 1 || columns > 12 || !Number.isInteger(width) || width < 80 || width > 1920)
|
|
158
|
+
throw new Error("Frame sheet columns must be 1..12; thumbnail width 80..1920");
|
|
159
|
+
const first = renderFrameCanvas(source, frames[0]);
|
|
160
|
+
try {
|
|
161
|
+
const height = Math.round(width * first.height / first.width), rows = Math.ceil(frames.length / columns);
|
|
162
|
+
const canvasWidth = columns * (width + gap) + gap, canvasHeight = rows * (height + caption + gap) + gap;
|
|
163
|
+
if (canvasWidth * canvasHeight > 32 * 1024 * 1024)
|
|
164
|
+
throw new Error("Frame sheet exceeds 32 megapixels; reduce thumbnail size or select fewer frames");
|
|
165
|
+
const canvas = new Canvas(canvasWidth, canvasHeight), ctx = canvas.getContext("2d");
|
|
166
|
+
try {
|
|
167
|
+
ctx.fillStyle = "#e8e0cd";
|
|
168
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
169
|
+
for (const [index, frame] of frames.entries()) {
|
|
170
|
+
const art = index === 0 ? first : renderFrameCanvas(source, frame);
|
|
171
|
+
try {
|
|
172
|
+
const x = gap + (index % columns) * (width + gap), y = gap + Math.floor(index / columns) * (height + caption + gap);
|
|
173
|
+
ctx.drawImage(art, x, y, width, height);
|
|
174
|
+
ctx.fillStyle = "#171c20";
|
|
175
|
+
ctx.font = "14px sans-serif";
|
|
176
|
+
ctx.fillText(`${frame}f`, x, y + height + 20, width);
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
art.getContext("2d").reset();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return await canvas.toBuffer("png");
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
ctx.reset();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
first.getContext("2d").reset();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../../src/render/review.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,iBAAiB,EAAqB,MAAM,qBAAqB,CAAC;AACnH,OAAO,EAAC,iBAAiB,EAAC,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAC,SAAS,EAAC,MAAM,UAAU,CAAC;AAYnC,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,MAAmB,EAAC,OAAc,EAAC,UAA0B,EAAE;IAC3G,IAAG,OAAO,CAAC,MAAM,KAAG,SAAS,IAAE,OAAO,OAAO,CAAC,MAAM,KAAG,SAAS;QAAC,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IACjH,IAAG,OAAO,CAAC,KAAK,KAAG,SAAS;QAAC,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9D,IAAG,OAAO,CAAC,SAAS,KAAG,SAAS,IAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,IAAE,OAAO,CAAC,SAAS,GAAC,CAAC,IAAE,OAAO,CAAC,SAAS,IAAE,EAAE,CAAC;QAAC,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;IACpM,IAAG,OAAO,CAAC,QAAQ,KAAG,SAAS,IAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;QAAC,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACrH,IAAG,OAAO,CAAC,eAAe,EAAE,IAAI,CAAC,KAAK,CAAA,EAAE,CAAA,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAAC,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACrK,MAAM,MAAM,GAAC,iBAAiB,CAAC,MAAM,EAAC,OAAO,EAAC,EAAC,WAAW,EAAC,KAAK,EAAC,GAAG,CAAC,OAAO,CAAC,KAAK,KAAG,SAAS,CAAA,CAAC,CAAA,EAAE,CAAA,CAAC,CAAA,EAAC,KAAK,EAAC,OAAO,CAAC,KAAK,EAAC,CAAC,EAAC,CAAC,CAAC;IAC3H,MAAM,GAAG,GAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,EAAC,CAAC,GAAC,MAAM,CAAC,KAAK,EAAC,CAAC,GAAC,MAAM,CAAC,MAAM,CAAC;IACjE,GAAG,CAAC,SAAS,EAAE,CAAC;IAChB,MAAM,IAAI,GAAC,CAAC,EAAS,EAAC,EAAS,EAAC,EAAS,EAAC,EAAS,EAAC,EAAE,GAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAC,EAAE,CAAC,CAAC,CAAA,GAAG,CAAC,MAAM,CAAC,EAAE,EAAC,EAAE,CAAC,CAAC,CAAA,CAAC,CAAC;IAC7F,IAAG,OAAO,CAAC,MAAM,IAAE,IAAI;QAAC,KAAI,MAAM,IAAI,IAAI,CAAC,CAAC,GAAC,CAAC,EAAC,CAAC,GAAC,CAAC,CAAC,EAAC,CAAC;YAAA,IAAI,CAAC,CAAC,GAAC,IAAI,EAAC,CAAC,EAAC,CAAC,GAAC,IAAI,EAAC,CAAC,CAAC,CAAC;YAAA,IAAI,CAAC,CAAC,EAAC,CAAC,GAAC,IAAI,EAAC,CAAC,EAAC,CAAC,GAAC,IAAI,CAAC,CAAC;QAAA,CAAC;IACtG,IAAG,OAAO,CAAC,SAAS,KAAG,SAAS,EAAC,CAAC;QAAA,MAAM,KAAK,GAAC,OAAO,CAAC,SAAS,CAAC;QAAA,GAAG,CAAC,IAAI,CAAC,CAAC,GAAC,KAAK,EAAC,CAAC,GAAC,KAAK,EAAC,CAAC,GAAC,CAAC,CAAC,GAAC,CAAC,GAAC,KAAK,CAAC,EAAC,CAAC,GAAC,CAAC,CAAC,GAAC,CAAC,GAAC,KAAK,CAAC,CAAC,CAAC;IAAA,CAAC;IACvH,IAAG,OAAO,CAAC,QAAQ,KAAG,SAAS;QAAC,IAAI,CAAC,CAAC,EAAC,OAAO,CAAC,QAAQ,EAAC,CAAC,EAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5E,KAAI,MAAM,KAAK,IAAI,OAAO,CAAC,eAAe,IAAE,EAAE,EAAC,CAAC;QAC9C,KAAI,MAAM,CAAC,CAAC,EAAC,CAAC,CAAC,IAAG,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC,EAAC,CAAC,CAAC,EAAC,CAAC,CAAC,EAAC,CAAC,CAAC,EAAC,CAAC,CAAC,EAAC,CAAC,CAAC,EAAC,CAAC,CAAC,CAAC;YAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAC,KAAK,CAAC,CAAC,EAAC,CAAE,EAAC,CAAE,CAAC,CAAC;QACxE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAC,CAAC,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAAA,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAC,KAAK,CAAC,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC,IAAI,CAAC,EAAE,GAAC,CAAC,CAAC,CAAC;IACvE,CAAC;IACD,GAAG,CAAC,WAAW,GAAC,SAAS,CAAC;IAAA,GAAG,CAAC,SAAS,GAAC,CAAC,CAAC;IAAA,GAAG,CAAC,MAAM,EAAE,CAAC;IACvD,GAAG,CAAC,WAAW,GAAC,SAAS,CAAC;IAAA,GAAG,CAAC,SAAS,GAAC,CAAC,CAAC;IAAA,GAAG,CAAC,MAAM,EAAE,CAAC;IACvD,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAAmB,EAAC,UAA6E,EAAE;IAC1I,MAAM,GAAG,GAAC,MAAM,YAAY,iBAAiB,CAAA,CAAC,CAAA,MAAM,CAAC,MAAM,EAAE,CAAA,CAAC,CAAA,MAAM,CAAC;IACrE,MAAM,OAAO,GAAC,OAAO,CAAC,OAAO,IAAE,CAAC,EAAC,KAAK,GAAC,OAAO,CAAC,cAAc,IAAE,GAAG,CAAC;IACnE,IAAG,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAE,OAAO,GAAC,CAAC,IAAE,OAAO,GAAC,EAAE,IAAE,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAE,KAAK,GAAC,EAAE,IAAE,KAAK,GAAC,IAAI;QAAC,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACtL,MAAM,IAAI,GAAC,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAA,EAAE,CAAA,CAAC,KAAK,CAAC,EAAE,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5D,IAAG,OAAO,CAAC,QAAQ,KAAG,SAAS,IAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,IAAE,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,KAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAC,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;IAC9O,MAAM,GAAG,GAAC,OAAO,CAAC,QAAQ,IAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAA,EAAE,CAAA,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAA,EAAE,CAAA,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAA,EAAE,CAAA,IAAI,CAAC,EAAE,KAAG,EAAE,CAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/H,MAAM,MAAM,GAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAA,EAAE,GAAC,MAAM,KAAK,GAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA,IAAG,CAAC,KAAK;QAAC,MAAM,IAAI,KAAK,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC,CAAA,OAAO,KAAK,CAAC,CAAA,CAAC,CAAC,CAAC;IACvH,MAAM,MAAM,GAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAC,GAAG,CAAC,MAAM,CAAC,MAAM,GAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAC,IAAI,GAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAC,OAAO,CAAC,EAAC,GAAG,GAAC,EAAE,CAAC;IAC/G,MAAM,WAAW,GAAC,OAAO,GAAC,CAAC,KAAK,GAAC,GAAG,CAAC,GAAC,GAAG,EAAC,YAAY,GAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAC,IAAI,CAAC,GAAC,CAAC,MAAM,GAAC,EAAE,CAAC,GAAC,GAAG,CAAC;IACxF,IAAG,WAAW,GAAC,YAAY,GAAC,EAAE,GAAC,IAAI,GAAC,IAAI;QAAC,MAAM,IAAI,KAAK,CAAC,mFAAmF,CAAC,CAAC;IAC9I,MAAM,MAAM,GAAC,IAAI,MAAM,CAAC,WAAW,EAAC,YAAY,CAAC,CAAC;IAClD,MAAM,GAAG,GAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,EAAC,OAAO,GAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAAA,GAAG,CAAC,SAAS,GAAC,SAAS,CAAC;IAAA,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAC,CAAC,EAAC,MAAM,CAAC,KAAK,EAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACxI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAC,CAAC,EAAC,EAAE;QACpB,MAAM,CAAC,GAAC,GAAG,GAAC,CAAC,CAAC,GAAC,OAAO,CAAC,GAAC,CAAC,KAAK,GAAC,GAAG,CAAC,EAAC,CAAC,GAAC,GAAG,GAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAC,OAAO,CAAC,GAAC,CAAC,MAAM,GAAC,EAAE,CAAC,CAAC;QAC5E,MAAM,KAAK,GAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAC,CAAC,CAAC,UAAU,GAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,GAAC,EAAE,CAAC,CAAC,CAAC;QAC7E,IAAG,CAAC;YAAA,GAAG,CAAC,SAAS,CAAC,KAAK,EAAC,CAAC,EAAC,CAAC,EAAC,KAAK,EAAC,MAAM,CAAC,CAAC;QAAA,CAAC;gBAAO,CAAC;YAAA,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;QAAA,CAAC;QACnF,GAAG,CAAC,SAAS,GAAC,SAAS,CAAC;QAAA,GAAG,CAAC,IAAI,GAAC,iBAAiB,CAAC;QACnD,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,KAAK,EAAE,EAAC,CAAC,EAAC,CAAC,GAAC,MAAM,GAAC,EAAE,EAAC,KAAK,CAAC,CAAC;QAC5D,GAAG,CAAC,IAAI,GAAC,iBAAiB,CAAC;QAAA,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,UAAU,OAAO,CAAC,CAAC,cAAc,GAAG,EAAC,CAAC,EAAC,CAAC,GAAC,MAAM,GAAC,EAAE,EAAC,KAAK,CAAC,CAAC;IACzG,CAAC,CAAC,CAAC;IACH,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAmB,EAAC,OAAc,EAAC,IAAmD,EAAC,KAAa;IACrI,IAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA,EAAE,CAAA,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAE,IAAI,CAAC,KAAK,GAAC,CAAC,IAAE,IAAI,CAAC,MAAM,GAAC,CAAC,IAAE,IAAI,CAAC,KAAK,GAAC,IAAI,CAAC,MAAM,GAAC,EAAE,GAAC,IAAI,GAAC,IAAI;QAAC,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC7J,MAAM,GAAG,GAAC,iBAAiB,CAAC,MAAM,EAAC,OAAO,EAAC,EAAC,WAAW,EAAC,KAAK,EAAC,GAAG,CAAC,KAAK,KAAG,SAAS,CAAA,CAAC,CAAA,EAAE,CAAA,CAAC,CAAA,EAAC,KAAK,EAAC,CAAC,EAAC,CAAC,CAAC;IAClG,IAAG,CAAC;QACF,MAAM,MAAM,GAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,EAAC,IAAI,CAAC,MAAM,CAAC,EAAC,GAAG,GAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC5E,IAAG,CAAC;YACF,GAAG,CAAC,SAAS,CAAC,GAAG,EAAC,CAAC,IAAI,CAAC,CAAC,EAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACnC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YAC7B,OAAO,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;gBAAO,CAAC;YAAA,GAAG,CAAC,KAAK,EAAE,CAAC;QAAA,CAAC;IACxB,CAAC;YAAO,CAAC;QAAA,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;IAAA,CAAC;AACzC,CAAC;AAID,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAmB,EAAC,OAAkC,EAAC,UAA0C,EAAE;IACvI,MAAM,OAAO,GAAC,OAAO,CAAC,OAAO,IAAE,EAAE,CAAC;IAClC,IAAG,CAAC,OAAO,CAAC,MAAM,IAAE,OAAO,CAAC,MAAM,GAAC,CAAC,IAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAE,OAAO,GAAC,CAAC,IAAE,OAAO,GAAC,CAAC;QAAC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IAC3J,KAAI,MAAM,MAAM,IAAI,OAAO,EAAC,CAAC;QAC3B,IAAG,MAAM,CAAC,KAAK,KAAG,SAAS;YAAC,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5D,IAAG,MAAM,CAAC,IAAI,KAAG,SAAS,IAAE,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC;YAAC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACpG,IAAG,MAAM,CAAC,OAAO,KAAG,SAAS,IAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,IAAE,MAAM,CAAC,OAAO,GAAC,CAAC,IAAE,MAAM,CAAC,OAAO,GAAC,CAAC,CAAC;YAAC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IAC7K,CAAC;IACD,MAAM,GAAG,GAAC,MAAM,YAAY,iBAAiB,CAAA,CAAC,CAAA,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAA,EAAE,CAAA,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA,CAAC,CAAA,MAAM,CAAC;IACnH,MAAM,MAAM,GAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAA,EAAE;QAC/B,MAAM,KAAK,GAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAA,EAAE,CAAA,KAAK,CAAC,EAAE,KAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9D,IAAG,CAAC,KAAK;YAAC,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAChE,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,GAAC,MAAM,CAAC,CAAC,CAAE,CAAC;IACvB,IAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAA,EAAE,CAAA,KAAK,CAAC,KAAK,KAAG,KAAK,CAAC,KAAK,IAAE,KAAK,CAAC,MAAM,KAAG,KAAK,CAAC,MAAM,CAAC;QAAC,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACjJ,MAAM,MAAM,GAAC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAC,KAAK,CAAC,MAAM,CAAC,EAAC,GAAG,GAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9E,MAAM,WAAW,GAAC,EAAC,GAAG,GAAG,EAAC,MAAM,EAAC,EAAC,GAAG,GAAG,CAAC,MAAM,EAAC,UAAU,EAAC,aAAa,EAAC,EAAC,CAAC;IAC3E,IAAG,CAAC;QACH,KAAI,MAAM,CAAC,CAAC,EAAC,MAAM,CAAC,IAAG,OAAO,CAAC,OAAO,EAAE,EAAC,CAAC;YACzC,GAAG,CAAC,WAAW,GAAC,MAAM,CAAC,OAAO,IAAE,CAAC,CAAC,KAAG,CAAC,CAAA,CAAC,CAAA,CAAC,CAAA,CAAC,CAAA,OAAO,CAAC,CAAC;YAClD,MAAM,QAAQ,GAAC,MAAM,CAAC,IAAI,KAAG,SAAS,IAAE,MAAM,CAAC,QAAQ,KAAG,SAAS,CAAC;YACpE,MAAM,GAAG,GAAC,iBAAiB,CAAC,CAAC,KAAG,CAAC,IAAE,CAAC,QAAQ,CAAA,CAAC,CAAA,GAAG,CAAA,CAAC,CAAA,WAAW,EAAC,MAAM,CAAC,OAAO,EAAC,EAAC,WAAW,EAAC,KAAK,EAAC,MAAM,EAAC,OAAO,CAAC,MAAM,IAAE,KAAK,EAAC,GAAG,CAAC,MAAM,CAAC,KAAK,KAAG,SAAS,CAAA,CAAC,CAAA,EAAE,CAAA,CAAC,CAAA,EAAC,KAAK,EAAC,MAAM,CAAC,KAAK,EAAC,CAAC,EAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAA,CAAC,CAAA,EAAC,QAAQ,EAAC,MAAM,CAAC,QAAQ,EAAC,CAAA,CAAC,CAAA,EAAE,CAAC,EAAC,CAAC,CAAC;YACvO,IAAG,CAAC;gBACF,IAAG,MAAM,CAAC,IAAI,KAAG,SAAS,EAAC,CAAC;oBAAA,MAAM,IAAI,GAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;oBAAA,IAAI,CAAC,wBAAwB,GAAC,WAAW,CAAC;oBAAA,IAAI,CAAC,SAAS,GAAC,MAAM,CAAC,IAAI,CAAC;oBAAA,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAC,CAAC,EAAC,GAAG,CAAC,KAAK,EAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAAA,CAAC;gBAC1K,GAAG,CAAC,SAAS,CAAC,GAAG,EAAC,CAAC,EAAC,CAAC,CAAC,CAAC;YACzB,CAAC;oBAAO,CAAC;gBAAA,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YAAA,CAAC;QACxC,CAAC;QACD,OAAO,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;YAAO,CAAC;QAAA,GAAG,CAAC,KAAK,EAAE,CAAC;IAAA,CAAC;AACxB,CAAC;AAED,8FAA8F;AAC9F,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAmB,EAAC,MAAwB,EAAC,UAAiD,EAAE;IACrI,MAAM,OAAO,GAAC,OAAO,CAAC,OAAO,IAAE,CAAC,EAAC,KAAK,GAAC,OAAO,CAAC,cAAc,IAAE,GAAG,EAAC,GAAG,GAAC,EAAE,EAAC,OAAO,GAAC,EAAE,CAAC;IACrF,IAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAE,CAAC,MAAM,CAAC,MAAM;QAAC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IACxG,KAAI,MAAM,KAAK,IAAI,MAAM;QAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACnD,IAAG,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAE,OAAO,GAAC,CAAC,IAAE,OAAO,GAAC,EAAE,IAAE,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAE,KAAK,GAAC,EAAE,IAAE,KAAK,GAAC,IAAI;QAAC,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACpL,MAAM,KAAK,GAAC,iBAAiB,CAAC,MAAM,EAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC;IACjD,IAAG,CAAC;QACF,MAAM,MAAM,GAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAC,KAAK,CAAC,MAAM,GAAC,KAAK,CAAC,KAAK,CAAC,EAAC,IAAI,GAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAC,OAAO,CAAC,CAAC;QAC9F,MAAM,WAAW,GAAC,OAAO,GAAC,CAAC,KAAK,GAAC,GAAG,CAAC,GAAC,GAAG,EAAC,YAAY,GAAC,IAAI,GAAC,CAAC,MAAM,GAAC,OAAO,GAAC,GAAG,CAAC,GAAC,GAAG,CAAC;QACrF,IAAG,WAAW,GAAC,YAAY,GAAC,EAAE,GAAC,IAAI,GAAC,IAAI;YAAC,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAC;QAC5I,MAAM,MAAM,GAAC,IAAI,MAAM,CAAC,WAAW,EAAC,YAAY,CAAC,EAAC,GAAG,GAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC9E,IAAG,CAAC;YACF,GAAG,CAAC,SAAS,GAAC,SAAS,CAAC;YAAA,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAC,CAAC,EAAC,MAAM,CAAC,KAAK,EAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACrE,KAAI,MAAM,CAAC,KAAK,EAAC,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,EAAC,CAAC;gBAC3C,MAAM,GAAG,GAAC,KAAK,KAAG,CAAC,CAAA,CAAC,CAAA,KAAK,CAAA,CAAC,CAAA,iBAAiB,CAAC,MAAM,EAAC,KAAK,CAAC,CAAC;gBAC1D,IAAG,CAAC;oBACF,MAAM,CAAC,GAAC,GAAG,GAAC,CAAC,KAAK,GAAC,OAAO,CAAC,GAAC,CAAC,KAAK,GAAC,GAAG,CAAC,EAAC,CAAC,GAAC,GAAG,GAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAC,OAAO,CAAC,GAAC,CAAC,MAAM,GAAC,OAAO,GAAC,GAAG,CAAC,CAAC;oBAC7F,GAAG,CAAC,SAAS,CAAC,GAAG,EAAC,CAAC,EAAC,CAAC,EAAC,KAAK,EAAC,MAAM,CAAC,CAAC;oBACpC,GAAG,CAAC,SAAS,GAAC,SAAS,CAAC;oBAAA,GAAG,CAAC,IAAI,GAAC,iBAAiB,CAAC;oBAAA,GAAG,CAAC,QAAQ,CAAC,GAAG,KAAK,GAAG,EAAC,CAAC,EAAC,CAAC,GAAC,MAAM,GAAC,EAAE,EAAC,KAAK,CAAC,CAAC;gBACnG,CAAC;wBAAO,CAAC;oBAAA,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;gBAAA,CAAC;YACzC,CAAC;YACD,OAAO,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACtC,CAAC;gBAAO,CAAC;YAAA,GAAG,CAAC,KAAK,EAAE,CAAC;QAAA,CAAC;IACxB,CAAC;YAAO,CAAC;QAAA,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;IAAA,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type CanvasRenderingContext2D } from "skia-canvas";
|
|
2
|
+
import type { DrawingElement, VectorStroke } from "../model/types.js";
|
|
3
|
+
export declare function drawVectorStroke(ctx: CanvasRenderingContext2D, stroke: VectorStroke): void;
|
|
4
|
+
export declare function drawElement(ctx: CanvasRenderingContext2D, element: DrawingElement, frame?: number): void;
|
|
5
|
+
//# sourceMappingURL=vector-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector-renderer.d.ts","sourceRoot":"","sources":["../../../src/render/vector-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvF,OAAO,KAAK,EAAE,cAAc,EAAc,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAMlF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,wBAAwB,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAkB1F;AASD,wBAAgB,WAAW,CAAC,GAAG,EAAE,wBAAwB,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,SAAW,GAAG,IAAI,CAyC1G"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Canvas, ImageData } from "skia-canvas";
|
|
2
|
+
import { drawRasterStroke } from "./brush-engine.js";
|
|
3
|
+
import { contourPath } from "../drawing/path-geometry.js";
|
|
4
|
+
import { traceVectorStroke } from "../drawing/stroke-outline.js";
|
|
5
|
+
import { assertDrawingColors } from "../drawing/color.js";
|
|
6
|
+
export function drawVectorStroke(ctx, stroke) {
|
|
7
|
+
if (stroke.points.length === 0)
|
|
8
|
+
return;
|
|
9
|
+
ctx.save();
|
|
10
|
+
ctx.globalAlpha = stroke.opacity;
|
|
11
|
+
ctx.strokeStyle = stroke.color;
|
|
12
|
+
ctx.lineCap = "round";
|
|
13
|
+
ctx.lineJoin = "round";
|
|
14
|
+
if (stroke.fill && stroke.closed) {
|
|
15
|
+
ctx.fillStyle = stroke.fill;
|
|
16
|
+
ctx.beginPath();
|
|
17
|
+
ctx.moveTo(stroke.points[0].x, stroke.points[0].y);
|
|
18
|
+
for (const point of stroke.points.slice(1))
|
|
19
|
+
ctx.lineTo(point.x, point.y);
|
|
20
|
+
ctx.closePath();
|
|
21
|
+
ctx.fill();
|
|
22
|
+
}
|
|
23
|
+
ctx.fillStyle = stroke.color;
|
|
24
|
+
ctx.beginPath();
|
|
25
|
+
traceVectorStroke(ctx, stroke);
|
|
26
|
+
ctx.fill();
|
|
27
|
+
ctx.restore();
|
|
28
|
+
}
|
|
29
|
+
const pathCache = new WeakMap();
|
|
30
|
+
function buildPath(element) {
|
|
31
|
+
const signature = JSON.stringify(element.commands), cached = pathCache.get(element);
|
|
32
|
+
if (cached?.signature === signature)
|
|
33
|
+
return cached.path;
|
|
34
|
+
const path = contourPath(element.commands);
|
|
35
|
+
pathCache.set(element, { signature, path });
|
|
36
|
+
return path;
|
|
37
|
+
}
|
|
38
|
+
export function drawElement(ctx, element, frame = Infinity) {
|
|
39
|
+
if (!element.visible)
|
|
40
|
+
return;
|
|
41
|
+
assertDrawingColors(element);
|
|
42
|
+
ctx.save();
|
|
43
|
+
if (element.matrix)
|
|
44
|
+
ctx.transform(...element.matrix);
|
|
45
|
+
try {
|
|
46
|
+
if (element.kind === "raster-stroke")
|
|
47
|
+
drawRasterStroke(ctx, element, frame);
|
|
48
|
+
else if (element.kind === "raster-surface") {
|
|
49
|
+
const surface = new Canvas(element.width, element.height), surfaceContext = surface.getContext("2d");
|
|
50
|
+
try {
|
|
51
|
+
surfaceContext.putImageData(new ImageData(new Uint8ClampedArray(element.pixels), element.width, element.height), 0, 0);
|
|
52
|
+
ctx.globalAlpha = element.opacity;
|
|
53
|
+
ctx.drawImage(surface, 0, 0);
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
surfaceContext.reset();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else if (element.kind === "vector-stroke")
|
|
60
|
+
drawVectorStroke(ctx, element);
|
|
61
|
+
else if (element.kind === "vector-path") {
|
|
62
|
+
const path = buildPath(element);
|
|
63
|
+
ctx.save();
|
|
64
|
+
ctx.globalAlpha = element.opacity;
|
|
65
|
+
if (element.fill) {
|
|
66
|
+
const fill = element.fill;
|
|
67
|
+
if (typeof fill === 'string')
|
|
68
|
+
ctx.fillStyle = fill;
|
|
69
|
+
else {
|
|
70
|
+
const gradient = fill.kind === 'linear' ? ctx.createLinearGradient(fill.from.x, fill.from.y, fill.to.x, fill.to.y) : ctx.createRadialGradient(fill.from.x, fill.from.y, fill.from.radius, fill.to.x, fill.to.y, fill.to.radius);
|
|
71
|
+
for (const stop of fill.stops)
|
|
72
|
+
gradient.addColorStop(stop.offset, stop.color);
|
|
73
|
+
ctx.fillStyle = gradient;
|
|
74
|
+
}
|
|
75
|
+
ctx.fill(path);
|
|
76
|
+
}
|
|
77
|
+
if (element.stroke && element.strokeWidth > 0) {
|
|
78
|
+
ctx.strokeStyle = element.stroke;
|
|
79
|
+
ctx.lineWidth = element.strokeWidth;
|
|
80
|
+
ctx.stroke(path);
|
|
81
|
+
}
|
|
82
|
+
ctx.restore();
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
ctx.save();
|
|
86
|
+
ctx.globalAlpha = element.opacity;
|
|
87
|
+
ctx.fillStyle = element.color;
|
|
88
|
+
ctx.font = element.font;
|
|
89
|
+
ctx.textAlign = element.align;
|
|
90
|
+
ctx.fillText(element.text, element.x, element.y);
|
|
91
|
+
ctx.restore();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
ctx.restore();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=vector-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector-renderer.js","sourceRoot":"","sources":["../../../src/render/vector-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const starter = "import { StoryboardProject, brushes, catmullRom, renderFramePNG } from 'codeboard-studio';\nimport { mkdir, writeFile } from 'node:fs/promises';\n\nconst project = StoryboardProject.create({\n title: 'First stroke', width: 960, height: 540, frameRate: 24,\n background: '#f3eddf',\n});\nconst panel = project.addScene('Scene').addShot('A rising mark')\n .addPanel({ id: 'first', durationFrames: 48 });\npanel.addRasterLayer('Ink', { id: 'ink' }).rasterStroke(catmullRom([\n { x: 150, y: 390, pressure: .2, time: 0 },\n { x: 360, y: 230, pressure: 1, time: 260 },\n { x: 600, y: 300, pressure: .8, time: 520 },\n { x: 800, y: 140, pressure: .12, time: 800 },\n], 32), { ...brushes.cleanInk, size: 44 }, { color: '#191916', seed: 12 });\n\nawait mkdir('output', { recursive: true });\n// This script owns these generated files. Keep later revisions in separate files.\nawait project.save('output/first.cboard', { overwrite: true });\nawait writeFile('output/first.png', await renderFramePNG(project, 0));\nconsole.log('Created output/first.cboard and output/first.png');\n";
|
|
2
|
+
//# sourceMappingURL=starter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"starter.d.ts","sourceRoot":"","sources":["../../src/starter.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,0jCAqBnB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const starter = `import { StoryboardProject, brushes, catmullRom, renderFramePNG } from 'codeboard-studio';
|
|
2
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
3
|
+
|
|
4
|
+
const project = StoryboardProject.create({
|
|
5
|
+
title: 'First stroke', width: 960, height: 540, frameRate: 24,
|
|
6
|
+
background: '#f3eddf',
|
|
7
|
+
});
|
|
8
|
+
const panel = project.addScene('Scene').addShot('A rising mark')
|
|
9
|
+
.addPanel({ id: 'first', durationFrames: 48 });
|
|
10
|
+
panel.addRasterLayer('Ink', { id: 'ink' }).rasterStroke(catmullRom([
|
|
11
|
+
{ x: 150, y: 390, pressure: .2, time: 0 },
|
|
12
|
+
{ x: 360, y: 230, pressure: 1, time: 260 },
|
|
13
|
+
{ x: 600, y: 300, pressure: .8, time: 520 },
|
|
14
|
+
{ x: 800, y: 140, pressure: .12, time: 800 },
|
|
15
|
+
], 32), { ...brushes.cleanInk, size: 44 }, { color: '#191916', seed: 12 });
|
|
16
|
+
|
|
17
|
+
await mkdir('output', { recursive: true });
|
|
18
|
+
// This script owns these generated files. Keep later revisions in separate files.
|
|
19
|
+
await project.save('output/first.cboard', { overwrite: true });
|
|
20
|
+
await writeFile('output/first.png', await renderFramePNG(project, 0));
|
|
21
|
+
console.log('Created output/first.cboard and output/first.png');
|
|
22
|
+
`;
|
|
23
|
+
//# sourceMappingURL=starter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"starter.js","sourceRoot":"","sources":["../../src/starter.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;CAqBtB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DatabaseSync } from "node:sqlite";
|
|
2
|
+
export declare const digest: (bytes: Uint8Array) => string;
|
|
3
|
+
/** Payload references are internal tagged tuples; user objects are always escaped. */
|
|
4
|
+
export declare class PayloadCodec {
|
|
5
|
+
private db;
|
|
6
|
+
private select;
|
|
7
|
+
private exists;
|
|
8
|
+
private reading;
|
|
9
|
+
private decoded;
|
|
10
|
+
private raw;
|
|
11
|
+
constructor(db: DatabaseSync);
|
|
12
|
+
put(kind: string, bytes: Buffer): string;
|
|
13
|
+
get(hash: string, kind?: string): Buffer;
|
|
14
|
+
write(value: unknown): string;
|
|
15
|
+
retain(parent: string, children: Iterable<string>): void;
|
|
16
|
+
read<T>(hash: string): T;
|
|
17
|
+
private encode;
|
|
18
|
+
private decode;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../../src/storage/codec.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,eAAO,MAAM,MAAM,GAAI,OAAO,UAAU,WAAqD,CAAC;AAE9F,sFAAsF;AACtF,qBAAa,YAAY;IAMX,OAAO,CAAC,EAAE;IALtB,OAAO,CAAC,MAAM,CAAsC;IACpD,OAAO,CAAC,MAAM,CAAsC;IACpD,OAAO,CAAC,OAAO,CAAG;IAClB,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,GAAG,CAA0B;gBACjB,EAAE,EAAE,YAAY;IAKpC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAmBxC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IAYxC,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM;IAI7B,MAAM,CAAC,MAAM,EAAC,MAAM,EAAE,QAAQ,EAAC,QAAQ,CAAC,MAAM,CAAC,GAAE,IAAI;IAKrD,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC;IAUxB,OAAO,CAAC,MAAM;IAgDd,OAAO,CAAC,MAAM;CAiCf"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { brotliCompressSync, brotliDecompressSync, constants } from "node:zlib";
|
|
3
|
+
export const digest = (bytes) => createHash("sha256").update(bytes).digest("hex");
|
|
4
|
+
/** Payload references are internal tagged tuples; user objects are always escaped. */
|
|
5
|
+
export class PayloadCodec {
|
|
6
|
+
db;
|
|
7
|
+
select;
|
|
8
|
+
exists;
|
|
9
|
+
reading = 0;
|
|
10
|
+
decoded = new Map();
|
|
11
|
+
raw = new Map();
|
|
12
|
+
constructor(db) {
|
|
13
|
+
this.db = db;
|
|
14
|
+
this.select = db.prepare("SELECT kind,codec,raw_size,data FROM payloads WHERE hash=?");
|
|
15
|
+
this.exists = db.prepare("SELECT 1 FROM payloads WHERE hash=?");
|
|
16
|
+
}
|
|
17
|
+
put(kind, bytes) {
|
|
18
|
+
const hash = digest(Buffer.concat([Buffer.from(`${kind}\0`), bytes]));
|
|
19
|
+
if (!this.exists.get(hash)) {
|
|
20
|
+
const compressed = brotliCompressSync(bytes, { params: { [constants.BROTLI_PARAM_QUALITY]: 5 } });
|
|
21
|
+
const codec = compressed.length < bytes.length ? "br" : "raw";
|
|
22
|
+
this.db.prepare("INSERT INTO payloads VALUES(?,?,?,?,?)").run(hash, kind, codec, bytes.length, codec === "br" ? compressed : bytes);
|
|
23
|
+
if (kind === "tree") {
|
|
24
|
+
const visit = (node) => {
|
|
25
|
+
if (!Array.isArray(node))
|
|
26
|
+
return;
|
|
27
|
+
const child = node[0] === "$ref" || node[0] === "$commands" || node[0] === "$bytes" ? node[1] : node[0] === "$numbers" || node[0] === "$points" ? node[2] : undefined;
|
|
28
|
+
if (child)
|
|
29
|
+
this.db.prepare("INSERT OR IGNORE INTO payload_links VALUES(?,?)").run(hash, child);
|
|
30
|
+
else
|
|
31
|
+
for (const item of node)
|
|
32
|
+
visit(item);
|
|
33
|
+
};
|
|
34
|
+
visit(JSON.parse(bytes.toString()));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return hash;
|
|
38
|
+
}
|
|
39
|
+
get(hash, kind) {
|
|
40
|
+
const cacheKey = `${kind ?? ""}:${hash}`;
|
|
41
|
+
if (this.reading && this.raw.has(cacheKey))
|
|
42
|
+
return this.raw.get(cacheKey);
|
|
43
|
+
const row = this.select.get(hash);
|
|
44
|
+
if (!row || (kind && row.kind !== kind))
|
|
45
|
+
throw new Error(`Missing or invalid payload ${hash}`);
|
|
46
|
+
const data = Buffer.from(row.data);
|
|
47
|
+
const raw = row.codec === "br" ? brotliDecompressSync(data, { maxOutputLength: Number(row.raw_size) }) : data;
|
|
48
|
+
if (raw.length !== row.raw_size || digest(Buffer.concat([Buffer.from(`${row.kind}\0`), raw])) !== hash)
|
|
49
|
+
throw new Error(`Corrupt payload ${hash}`);
|
|
50
|
+
if (this.reading)
|
|
51
|
+
this.raw.set(cacheKey, raw);
|
|
52
|
+
return raw;
|
|
53
|
+
}
|
|
54
|
+
write(value) {
|
|
55
|
+
return this.put("tree", Buffer.from(JSON.stringify(this.encode(value))));
|
|
56
|
+
}
|
|
57
|
+
retain(parent, children) {
|
|
58
|
+
const insert = this.db.prepare("INSERT OR IGNORE INTO payload_links VALUES(?,?)");
|
|
59
|
+
for (const child of children)
|
|
60
|
+
insert.run(parent, child);
|
|
61
|
+
}
|
|
62
|
+
read(hash) {
|
|
63
|
+
this.reading++;
|
|
64
|
+
try {
|
|
65
|
+
if (this.decoded.has(hash))
|
|
66
|
+
return structuredClone(this.decoded.get(hash));
|
|
67
|
+
const value = this.decode(JSON.parse(this.get(hash, "tree").toString()));
|
|
68
|
+
this.decoded.set(hash, value);
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
if (--this.reading === 0) {
|
|
73
|
+
this.decoded.clear();
|
|
74
|
+
this.raw.clear();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
encode(value, key = "") {
|
|
79
|
+
if (value instanceof Uint8Array) {
|
|
80
|
+
const blocks = [];
|
|
81
|
+
for (let offset = 0; offset < value.length; offset += 65536)
|
|
82
|
+
blocks.push(["$bytes", this.put("bytes", Buffer.from(value.subarray(offset, offset + 65536)))]);
|
|
83
|
+
return ["$byteChunks", value.length, blocks];
|
|
84
|
+
}
|
|
85
|
+
if (Array.isArray(value)) {
|
|
86
|
+
if (key === "elements") {
|
|
87
|
+
// Small blocks keep local edits bounded without a database row for every mark.
|
|
88
|
+
const blocks = [];
|
|
89
|
+
for (let i = 0; i < value.length; i += 32)
|
|
90
|
+
blocks.push(["$ref", this.write(value.slice(i, i + 32))]);
|
|
91
|
+
return ["$ref", this.put("tree", Buffer.from(JSON.stringify(["$elementChunks", blocks])))];
|
|
92
|
+
}
|
|
93
|
+
if (key === "commands" && value.length) {
|
|
94
|
+
const fields = { M: ["x", "y"], L: ["x", "y"], C: ["x1", "y1", "x2", "y2", "x", "y"], Q: ["x1", "y1", "x", "y"], Z: [] };
|
|
95
|
+
const ops = Object.keys(fields), bytes = Buffer.alloc(value.reduce((n, c) => n + 1 + fields[c.op].length * 8, 0));
|
|
96
|
+
let at = 0;
|
|
97
|
+
for (const command of value) {
|
|
98
|
+
bytes[at++] = ops.indexOf(command.op);
|
|
99
|
+
for (const field of fields[command.op]) {
|
|
100
|
+
bytes.writeDoubleLE(command[field], at);
|
|
101
|
+
at += 8;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return ["$commands", this.put("path-f64", bytes)];
|
|
105
|
+
}
|
|
106
|
+
if (value.length && value.every(v => typeof v === "number" && Number.isFinite(v))) {
|
|
107
|
+
// Alpha masks are bytes only when every source value is exactly representable.
|
|
108
|
+
const byte = key === "alpha" && value.every(v => Number.isInteger(v) && v >= 0 && v <= 255);
|
|
109
|
+
const buffer = Buffer.alloc(value.length * (byte ? 1 : 8));
|
|
110
|
+
value.forEach((n, i) => byte ? buffer.writeUInt8(n, i) : buffer.writeDoubleLE(n, i * 8));
|
|
111
|
+
return ["$numbers", byte ? "u8" : "f64", this.put(byte ? "u8" : "f64", buffer)];
|
|
112
|
+
}
|
|
113
|
+
if (key === "points" && value.length) {
|
|
114
|
+
const keys = [...new Set(value.flatMap(p => Object.keys(p)))].sort();
|
|
115
|
+
if (value.every(p => keys.every(k => p[k] === undefined || typeof p[k] === "number"))) {
|
|
116
|
+
const bytes = Buffer.alloc(value.length * keys.length * 9);
|
|
117
|
+
value.forEach((p, i) => keys.forEach((k, j) => {
|
|
118
|
+
const at = (i * keys.length + j) * 9;
|
|
119
|
+
if (p[k] !== undefined) {
|
|
120
|
+
bytes[at] = 1;
|
|
121
|
+
bytes.writeDoubleLE(p[k], at + 1);
|
|
122
|
+
}
|
|
123
|
+
}));
|
|
124
|
+
return ["$points", keys, this.put("points-f64", bytes)];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return ["$array", value.map(v => this.encode(v))];
|
|
128
|
+
}
|
|
129
|
+
if (value && typeof value === "object") {
|
|
130
|
+
const pairs = Object.entries(value).filter(([, v]) => v !== undefined)
|
|
131
|
+
.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, v]) => [k, this.encode(v, k)]);
|
|
132
|
+
if (key === "brush" || key === "tip" || key === "paperTexture")
|
|
133
|
+
return ["$ref", this.put("tree", Buffer.from(JSON.stringify(["$object", pairs])))];
|
|
134
|
+
return ["$object", pairs];
|
|
135
|
+
}
|
|
136
|
+
return Object.is(value, -0) ? ["$negativeZero"] : value;
|
|
137
|
+
}
|
|
138
|
+
decode(value) {
|
|
139
|
+
if (!Array.isArray(value))
|
|
140
|
+
return value;
|
|
141
|
+
if (value[0] === "$negativeZero")
|
|
142
|
+
return -0;
|
|
143
|
+
if (value[0] === "$bytes")
|
|
144
|
+
return new Uint8Array(this.get(value[1], "bytes"));
|
|
145
|
+
if (value[0] === "$byteChunks") {
|
|
146
|
+
const length = value[1];
|
|
147
|
+
if (!Number.isSafeInteger(length) || length < 0 || length > 128 * 1024 * 1024)
|
|
148
|
+
throw new Error("Invalid byte surface length");
|
|
149
|
+
const result = new Uint8Array(length);
|
|
150
|
+
let offset = 0;
|
|
151
|
+
for (const block of value[2]) {
|
|
152
|
+
const bytes = this.decode(block);
|
|
153
|
+
if (!(bytes instanceof Uint8Array) || offset + bytes.length > length)
|
|
154
|
+
throw new Error("Invalid byte block");
|
|
155
|
+
result.set(bytes, offset);
|
|
156
|
+
offset += bytes.length;
|
|
157
|
+
}
|
|
158
|
+
if (offset !== length)
|
|
159
|
+
throw new Error("Truncated byte surface");
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
if (value[0] === "$commands") {
|
|
163
|
+
const bytes = this.get(value[1], "path-f64"), fields = [["x", "y"], ["x", "y"], ["x1", "y1", "x2", "y2", "x", "y"], ["x1", "y1", "x", "y"], []], ops = ["M", "L", "C", "Q", "Z"], commands = [];
|
|
164
|
+
let at = 0;
|
|
165
|
+
while (at < bytes.length) {
|
|
166
|
+
const op = bytes[at++];
|
|
167
|
+
if (!fields[op] || at + fields[op].length * 8 > bytes.length)
|
|
168
|
+
throw new Error("Corrupt path payload");
|
|
169
|
+
const command = { op: ops[op] };
|
|
170
|
+
for (const field of fields[op]) {
|
|
171
|
+
command[field] = bytes.readDoubleLE(at);
|
|
172
|
+
at += 8;
|
|
173
|
+
}
|
|
174
|
+
commands.push(command);
|
|
175
|
+
}
|
|
176
|
+
return commands;
|
|
177
|
+
}
|
|
178
|
+
if (value[0] === "$ref")
|
|
179
|
+
return this.read(value[1]);
|
|
180
|
+
if (value[0] === "$elementChunks")
|
|
181
|
+
return value[1].flatMap((v) => this.decode(v));
|
|
182
|
+
if (value[0] === "$array")
|
|
183
|
+
return value[1].map((v) => this.decode(v));
|
|
184
|
+
if (value[0] === "$object")
|
|
185
|
+
return Object.fromEntries(value[1].map(([k, v]) => [k, this.decode(v)]));
|
|
186
|
+
if (value[0] === "$numbers") {
|
|
187
|
+
const bytes = this.get(value[2], value[1]);
|
|
188
|
+
if (value[1] === "u8")
|
|
189
|
+
return [...bytes];
|
|
190
|
+
if (bytes.length % 8)
|
|
191
|
+
throw new Error("Invalid Float64 payload length");
|
|
192
|
+
return Array.from({ length: bytes.length / 8 }, (_, i) => bytes.readDoubleLE(i * 8));
|
|
193
|
+
}
|
|
194
|
+
if (value[0] === "$points") {
|
|
195
|
+
const keys = value[1], bytes = this.get(value[2], "points-f64"), stride = keys.length * 9;
|
|
196
|
+
if (!stride || bytes.length % stride)
|
|
197
|
+
throw new Error("Invalid point payload length");
|
|
198
|
+
return Array.from({ length: bytes.length / stride }, (_, i) => Object.fromEntries(keys.flatMap((k, j) => bytes[i * stride + j * 9] ? [[k, bytes.readDoubleLE(i * stride + j * 9 + 1)]] : [])));
|
|
199
|
+
}
|
|
200
|
+
throw new Error("Unknown payload tag");
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.js","sourceRoot":"","sources":["../../../src/storage/codec.ts"],"names":[],"mappings":"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"}
|