@field/cascade 0.10.0 → 0.12.0
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/AGENTS.md +25 -5
- package/ARCHITECTURE.md +5 -4
- package/CHANGELOG.md +382 -0
- package/README.md +1 -2
- package/dist/assets/AgentPanel-1JugFjE4.css +1 -0
- package/dist/assets/AgentPanel-BDL5MddA.js +5 -0
- package/dist/assets/{CodeEditor-DSZBpzdy.js → CodeEditor-C-xYG-Wn.js} +120 -120
- package/dist/assets/CodePanel-CtXd50m6.js +2 -0
- package/dist/assets/CookInfoPanel-B3NMhKJF.css +1 -0
- package/dist/assets/CookInfoPanel-DG4_TRsX.js +2 -0
- package/dist/assets/CustomNodeDialog-CHfZUs-r.js +1 -0
- package/dist/assets/DefinitionNode-CaRTXQ_b.js +1 -0
- package/dist/assets/DefinitionPanel-C3CxZY9r.js +1 -0
- package/dist/assets/DefinitionPanel-VNLnAiQD.css +1 -0
- package/dist/assets/OpenGraphDialog-BLdr6k_q.js +1 -0
- package/dist/assets/ProjectSettings-ZnvmIAir.js +2 -0
- package/dist/assets/{SettingsDialog-p25h3tj0.js → SettingsDialog-CBX3Wa87.js} +1 -1
- package/dist/assets/TimelinePanel-CDeR0arY.css +1 -0
- package/dist/assets/TimelinePanel-CWgnFH1e.js +1 -0
- package/dist/assets/{VersionHistoryDialog-DzFLUotB.js → VersionHistoryDialog-BOSoW1R-.js} +1 -1
- package/dist/assets/assert-BO2_erPD.js +1 -0
- package/dist/assets/assert-hvykGCnP.js +1 -0
- package/dist/assets/builder-BmBKcDix.js +1 -0
- package/dist/assets/camera-DFF7YA3F.js +1 -0
- package/dist/assets/checks-DAvyO9Gf.js +1 -0
- package/dist/assets/contactSheet-N1NcaWxw.js +2 -0
- package/dist/assets/{core-BICrEt0y.js → core-DB-MkGjj.js} +3 -4
- package/dist/assets/coreTypes-DtnDATZ7.js +1 -0
- package/dist/assets/{cssMode-D7TXw57I.js → cssMode-DPVckSOc.js} +1 -1
- package/dist/assets/definitions-B227e7f_.js +1 -0
- package/dist/assets/definitions-D0WOUJd7.js +1 -0
- package/dist/assets/{editor.api-DvkCO3ko.js → editor.api-Dkutg_Z1.js} +1 -1
- package/dist/assets/expressions-X-Z-GrgW.js +5 -0
- package/dist/assets/file-DAL6IfjV.js +1 -0
- package/dist/assets/filters-D3k1LRMa.js +1 -0
- package/dist/assets/{freemarker2-BA2lxsF1.js → freemarker2-CLiLKk3B.js} +1 -1
- package/dist/assets/generators-BhDxRAFC.js +1 -0
- package/dist/assets/geo-BsMImJIJ.js +1 -0
- package/dist/assets/geo-C4YngDob.js +2 -0
- package/dist/assets/{handlebars-BcDiyPd8.js → handlebars-CcD3aMeL.js} +1 -1
- package/dist/assets/{html-C7O4TyhX.js → html-DvZWGfqb.js} +1 -1
- package/dist/assets/{htmlMode-WaDGF3Mj.js → htmlMode-DUD3VaoN.js} +1 -1
- package/dist/assets/image-0SfH-snh.js +1 -0
- package/dist/assets/image-Ck-RdGU4.js +2 -0
- package/dist/assets/index-BWnrmIB9.js +137 -0
- package/dist/assets/index-DIaxEONI.css +1 -0
- package/dist/assets/io-BGmt2g0D.js +1 -0
- package/dist/assets/{javascript-CpIEK7tz.js → javascript-Cap2ahgh.js} +1 -1
- package/dist/assets/{jsonMode-B2FltW0f.js → jsonMode-B0uLjp9C.js} +1 -1
- package/dist/assets/{liquid-CN6FFHZE.js → liquid-CnxwhfLn.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-QhV9XtLp.js → lspLanguageFeatures-Dn9hlKX6.js} +1 -1
- package/dist/assets/math-GeULS-sk.js +1 -0
- package/dist/assets/{mdx-DE89pafV.js → mdx-BV3jbrVa.js} +1 -1
- package/dist/assets/pop-KMF_qloi.js +1 -0
- package/dist/assets/preload-helper-Czpn1I53.js +1 -0
- package/dist/assets/{python-ByTllTB9.js → python-CGyFk4XK.js} +1 -1
- package/dist/assets/{razor-USYlRRCE.js → razor-CQfzX3-N.js} +1 -1
- package/dist/assets/remap-5SjXQU-q.js +1 -0
- package/dist/assets/renderMarkdown-ork0Oir7.js +67 -0
- package/dist/assets/studioImages-CAyH-0Pl.js +1 -0
- package/dist/assets/text-ZpX7qNkx.js +2 -0
- package/dist/assets/time-P_OiBhcf.js +1 -0
- package/dist/assets/{tsMode-BXpN8iUz.js → tsMode-BOeXzO9H.js} +1 -1
- package/dist/assets/{typescript-DInBjGQQ.js → typescript-J1SnE_Tu.js} +1 -1
- package/dist/assets/{workers-C7Ye5B7D.js → workers-CYwwTiVF.js} +1 -1
- package/dist/assets/{xml-U0Uocqyo.js → xml-DnPRNzK9.js} +1 -1
- package/dist/assets/{yaml-CBw_PVYf.js → yaml-BmmYBNa9.js} +1 -1
- package/dist/cli/DefinitionNode-P7AA4TAU.js +15 -0
- package/dist/cli/Graph-OB6EWSGL.js +2975 -0
- package/dist/cli/assert-GROGQNCQ.js +25 -0
- package/dist/cli/checks-3WB44XBL.js +189 -0
- package/dist/cli/chunk-2JEU3MGB.js +1125 -0
- package/dist/cli/chunk-2KXB47FP.js +115 -0
- package/dist/cli/chunk-3RXL5GHB.js +816 -0
- package/dist/cli/chunk-53LGFPWX.js +138 -0
- package/dist/cli/chunk-5ORUQ6ES.js +267 -0
- package/dist/cli/chunk-73S4JZXK.js +336 -0
- package/dist/cli/chunk-7QE2ZNSN.js +121 -0
- package/dist/cli/chunk-BP7UKF36.js +376 -0
- package/dist/cli/chunk-BPODRH52.js +201 -0
- package/dist/cli/chunk-BZ63XQ3I.js +1301 -0
- package/dist/cli/chunk-CKS2FQWR.js +89 -0
- package/dist/cli/chunk-CO22XHNG.js +593 -0
- package/dist/cli/chunk-CTPLRSWF.js +2197 -0
- package/dist/cli/chunk-DEQSEFFH.js +153 -0
- package/dist/cli/chunk-EU4ZFZ7Y.js +122 -0
- package/dist/cli/chunk-EZRWJ4G2.js +104 -0
- package/dist/cli/chunk-FWMSGKEH.js +71 -0
- package/dist/cli/chunk-G23A2BZZ.js +705 -0
- package/dist/cli/chunk-GRIN2DDP.js +1465 -0
- package/dist/cli/chunk-HFHWYL55.js +139 -0
- package/dist/cli/chunk-HSNOBIVT.js +263 -0
- package/dist/cli/chunk-ICH7N5PN.js +26 -0
- package/dist/cli/chunk-J7VK7MNF.js +418 -0
- package/dist/cli/chunk-JVOCK5W4.js +83 -0
- package/dist/cli/chunk-KBGUO27Q.js +15 -0
- package/dist/cli/chunk-KH4MUBKF.js +1551 -0
- package/dist/cli/chunk-L6B6FUQP.js +330 -0
- package/dist/cli/chunk-LTXWBXOM.js +438 -0
- package/dist/cli/chunk-MI5JLQYA.js +220 -0
- package/dist/cli/chunk-MP653A5O.js +3766 -0
- package/dist/cli/chunk-NJFMDXHR.js +320 -0
- package/dist/cli/chunk-OM6BEME6.js +267 -0
- package/dist/cli/chunk-OWWBYLHC.js +136 -0
- package/dist/cli/chunk-QQPA2ZHH.js +273 -0
- package/dist/cli/chunk-RUU3YWXU.js +99 -0
- package/dist/cli/chunk-RXDIMXN5.js +98 -0
- package/dist/cli/chunk-ST6LROUG.js +267 -0
- package/dist/cli/chunk-TJW67QSI.js +225 -0
- package/dist/cli/chunk-WD62JIP6.js +118 -0
- package/dist/cli/chunk-WGKPJZDY.js +364 -0
- package/dist/cli/chunk-X4WKAOQP.js +634 -0
- package/dist/cli/chunk-X566FWBV.js +156 -0
- package/dist/cli/chunk-YH637PDL.js +317 -0
- package/dist/cli/chunk-ZL4JTG5Y.js +37 -0
- package/dist/cli/chunk-ZSCUZE6I.js +112 -0
- package/dist/cli/cliCommands-JJN5Z3ZC.js +3470 -0
- package/dist/cli/commands-PHYFYA3F.js +1374 -0
- package/dist/cli/contactSheet-2PQVRUFW.js +11 -0
- package/dist/cli/definitions-BPOPW52L.js +32 -0
- package/dist/cli/doctorCommand-ORWQRNYP.js +106 -0
- package/dist/cli/edit-S5KEQ5RA.js +28 -0
- package/dist/cli/editorCommands-NFR32JOY.js +41 -0
- package/dist/cli/encode-ICPEPMH5.js +17 -0
- package/dist/cli/file-3HTQHPYQ.js +41 -0
- package/dist/cli/filters-6ODFWYK4.js +379 -0
- package/dist/cli/frames-LSAUBZ7P.js +16 -0
- package/dist/cli/generators-YU7GB4MD.js +210 -0
- package/dist/cli/geo-6ZPGKZRU.js +43 -0
- package/dist/cli/graphCommands-EOUOBOIJ.js +184 -0
- package/dist/cli/graphFile-YTGJB5F5.js +292 -0
- package/dist/cli/headlessCanvas-ENRHC7GS.js +16 -0
- package/dist/cli/helpCommand-PULH6ZYB.js +157 -0
- package/dist/cli/image-TXELZZK5.js +55 -0
- package/dist/cli/index.js +100 -30756
- package/dist/cli/math-RSYRQ3C6.js +16 -0
- package/dist/cli/mcp-JVZFQOEX.js +164 -0
- package/dist/cli/parity-X6DEH2DV.js +334 -0
- package/dist/cli/pop-B7SIIYKN.js +39 -0
- package/dist/cli/project-VYGIA7JX.js +12 -0
- package/dist/cli/projectDefinition-F3D7UIHJ.js +27 -0
- package/dist/cli/projectRuntime-2Q4JKEH3.js +55 -0
- package/dist/cli/registerStandardNodes-BXJCB6E4.js +744 -0
- package/dist/cli/render-PT4MWI6U.js +438 -0
- package/dist/cli/runCommand-HNPQVZMS.js +198 -0
- package/dist/cli/runner-5XPXVW7J.js +43 -0
- package/dist/cli/runtime/image.ts +302 -0
- package/dist/cli/runtime/io.ts +78 -0
- package/dist/cli/runtime/stage.ts +4 -1
- package/dist/cli/share-MHF6TNRK.js +166 -0
- package/dist/cli/stageCache-TY2BFZJR.js +15 -0
- package/dist/cli/stageRunner-KY2EJP7X.js +10 -0
- package/dist/cli/text-MB3EKR4H.js +126 -0
- package/dist/cli/verbs-PI2JH5FI.js +19 -0
- package/dist/cli/webBuild-WPPMGGW7.js +44 -0
- package/dist/contracts/capabilities.d.ts +18 -1
- package/dist/contracts/color.d.ts +8 -0
- package/dist/contracts/color.js +23 -0
- package/dist/contracts/definition.d.ts +10 -0
- package/dist/contracts/documentFormat.d.ts +18 -0
- package/dist/contracts/documentFormat.js +195 -0
- package/dist/contracts/editor.d.ts +17 -0
- package/dist/contracts/index.d.ts +1 -0
- package/dist/contracts/index.js +1 -0
- package/dist/contracts/schema.d.ts +1 -1
- package/dist/contracts/schema.js +1 -0
- package/dist/contracts/validate.js +11 -1
- package/dist/contracts/values.d.ts +24 -0
- package/dist/image.d.ts +156 -0
- package/dist/image.js +161 -0
- package/dist/index.html +8 -2
- package/dist/io.d.ts +29 -0
- package/dist/io.js +40 -0
- package/dist/player/app.js +3 -2
- package/dist/player/editor.js +35 -9
- package/dist/player/editorEngine.js +3 -2
- package/dist/runtime/builtins/assert/checks.d.ts +18 -0
- package/dist/runtime/builtins/assert/checks.js +207 -0
- package/dist/runtime/builtins/assert/definitions.d.ts +130 -0
- package/dist/runtime/builtins/assert/definitions.js +54 -0
- package/dist/runtime/builtins/assert/index.d.ts +152 -0
- package/dist/runtime/builtins/assert/index.js +36 -0
- package/dist/runtime/builtins/image/contactSheet.d.ts +64 -0
- package/dist/runtime/builtins/image/contactSheet.js +150 -0
- package/dist/runtime/builtins/image/definitions.d.ts +950 -0
- package/dist/runtime/builtins/image/definitions.js +343 -0
- package/dist/runtime/builtins/image/file.d.ts +8 -0
- package/dist/runtime/builtins/image/file.js +37 -0
- package/dist/runtime/builtins/image/filters.d.ts +8 -0
- package/dist/runtime/builtins/image/filters.js +394 -0
- package/dist/runtime/builtins/image/generators.d.ts +7 -0
- package/dist/runtime/builtins/image/generators.js +144 -0
- package/dist/runtime/builtins/image/index.d.ts +952 -0
- package/dist/runtime/builtins/image/index.js +44 -0
- package/dist/runtime/builtins/image/io.d.ts +100 -0
- package/dist/runtime/builtins/image/io.js +142 -0
- package/dist/runtime/builtins/image/planar.d.ts +55 -0
- package/dist/runtime/builtins/image/planar.js +274 -0
- package/dist/runtime/builtins/image/simplex.d.ts +22 -0
- package/dist/runtime/builtins/image/simplex.js +92 -0
- package/dist/runtime/builtins/image/text.d.ts +4 -0
- package/dist/runtime/builtins/image/text.js +141 -0
- package/dist/runtime/builtins/index.d.ts +3 -0
- package/dist/runtime/builtins/index.js +7 -0
- package/dist/runtime/gpu.d.ts +25 -0
- package/dist/runtime/gpu.js +40 -0
- package/dist/runtime/runtime.d.ts +2 -0
- package/dist/runtime/runtime.js +268 -44
- package/dist/runtime/types.d.ts +30 -0
- package/dist/stage.js +4 -1
- package/doc/CLI_REFERENCE.md +91 -2
- package/doc/EDITOR_EXPORT.md +37 -2
- package/doc/MCP.md +18 -1
- package/doc/NODE_REFERENCE.md +424 -10
- package/doc/PROJECT_AUTHORING.md +222 -7
- package/package.json +19 -4
- package/dist/assets/CodePanel-sY6sZa7B.js +0 -2
- package/dist/assets/CustomNodeDialog-BRKnqZhp.js +0 -1
- package/dist/assets/ExportDialog-C7dVGua4.js +0 -358
- package/dist/assets/ExportDialog-DOq0flMV.css +0 -1
- package/dist/assets/OpenGraphDialog-ZsgL-iwr.js +0 -1
- package/dist/assets/ProjectSettings-Cw17nNe3.js +0 -2
- package/dist/assets/definitions-DUww2Rt-.js +0 -1
- package/dist/assets/geo-C2RHOVHC.js +0 -1
- package/dist/assets/image-DR4oeyJB.js +0 -2062
- package/dist/assets/index-7vae6YFC.css +0 -1
- package/dist/assets/index-DyvDC6pS.js +0 -219
- package/dist/assets/math-DaDEgWKt.js +0 -1
- package/dist/assets/pop-pLH7L0PW.js +0 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 2D simplex noise: `createNoise2D` and `buildPermutationTable` from
|
|
3
|
+
* simplex-noise 4.0.3 by Jonas Wagner (MIT), copied rather than depended on.
|
|
4
|
+
*
|
|
5
|
+
* The class `Noise` node loaded simplex-noise@latest from esm.sh at cook time,
|
|
6
|
+
* so it needed a network and could not run headless. The runtime depends on
|
|
7
|
+
* contracts alone, so the two functions it used live here, unchanged, and a
|
|
8
|
+
* seeded noise image is the same pixels it always was.
|
|
9
|
+
*
|
|
10
|
+
* Copyright (c) 2024 Jonas Wagner. Permission is hereby granted, free of
|
|
11
|
+
* charge, to any person obtaining a copy of this software and associated
|
|
12
|
+
* documentation files (the "Software"), to deal in the Software without
|
|
13
|
+
* restriction, including without limitation the rights to use, copy, modify,
|
|
14
|
+
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
|
15
|
+
* and to permit persons to whom the Software is furnished to do so, subject to
|
|
16
|
+
* the following conditions: The above copyright notice and this permission
|
|
17
|
+
* notice shall be included in all copies or substantial portions of the
|
|
18
|
+
* Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
|
|
19
|
+
*/
|
|
20
|
+
const SQRT3 = Math.sqrt(3.0);
|
|
21
|
+
const F2 = 0.5 * (SQRT3 - 1.0);
|
|
22
|
+
const G2 = (3.0 - SQRT3) / 6.0;
|
|
23
|
+
const fastFloor = (x) => Math.floor(x) | 0;
|
|
24
|
+
const grad2 = new Float64Array([1, 1, -1, 1, 1, -1, -1, -1, 1, 0, -1, 0, 1, 0, -1, 0, 0, 1, 0, -1, 0, 1, 0, -1]);
|
|
25
|
+
function buildPermutationTable(random) {
|
|
26
|
+
const tableSize = 512;
|
|
27
|
+
const p = new Uint8Array(tableSize);
|
|
28
|
+
for (let i = 0; i < tableSize / 2; i++)
|
|
29
|
+
p[i] = i;
|
|
30
|
+
for (let i = 0; i < tableSize / 2 - 1; i++) {
|
|
31
|
+
const r = i + ~~(random() * (256 - i));
|
|
32
|
+
const aux = p[i];
|
|
33
|
+
p[i] = p[r];
|
|
34
|
+
p[r] = aux;
|
|
35
|
+
}
|
|
36
|
+
for (let i = 256; i < tableSize; i++)
|
|
37
|
+
p[i] = p[i - 256];
|
|
38
|
+
return p;
|
|
39
|
+
}
|
|
40
|
+
export function createNoise2D(random) {
|
|
41
|
+
const perm = buildPermutationTable(random);
|
|
42
|
+
const permGrad2x = new Float64Array(perm).map((v) => grad2[(v % 12) * 2]);
|
|
43
|
+
const permGrad2y = new Float64Array(perm).map((v) => grad2[(v % 12) * 2 + 1]);
|
|
44
|
+
return function noise2D(x, y) {
|
|
45
|
+
let n0 = 0;
|
|
46
|
+
let n1 = 0;
|
|
47
|
+
let n2 = 0;
|
|
48
|
+
const s = (x + y) * F2;
|
|
49
|
+
const i = fastFloor(x + s);
|
|
50
|
+
const j = fastFloor(y + s);
|
|
51
|
+
const t = (i + j) * G2;
|
|
52
|
+
const X0 = i - t;
|
|
53
|
+
const Y0 = j - t;
|
|
54
|
+
const x0 = x - X0;
|
|
55
|
+
const y0 = y - Y0;
|
|
56
|
+
let i1, j1;
|
|
57
|
+
if (x0 > y0) {
|
|
58
|
+
i1 = 1;
|
|
59
|
+
j1 = 0;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
i1 = 0;
|
|
63
|
+
j1 = 1;
|
|
64
|
+
}
|
|
65
|
+
const x1 = x0 - i1 + G2;
|
|
66
|
+
const y1 = y0 - j1 + G2;
|
|
67
|
+
const x2 = x0 - 1.0 + 2.0 * G2;
|
|
68
|
+
const y2 = y0 - 1.0 + 2.0 * G2;
|
|
69
|
+
const ii = i & 255;
|
|
70
|
+
const jj = j & 255;
|
|
71
|
+
let t0 = 0.5 - x0 * x0 - y0 * y0;
|
|
72
|
+
if (t0 >= 0) {
|
|
73
|
+
const gi0 = ii + perm[jj];
|
|
74
|
+
t0 *= t0;
|
|
75
|
+
n0 = t0 * t0 * (permGrad2x[gi0] * x0 + permGrad2y[gi0] * y0);
|
|
76
|
+
}
|
|
77
|
+
let t1 = 0.5 - x1 * x1 - y1 * y1;
|
|
78
|
+
if (t1 >= 0) {
|
|
79
|
+
const gi1 = ii + i1 + perm[jj + j1];
|
|
80
|
+
t1 *= t1;
|
|
81
|
+
n1 = t1 * t1 * (permGrad2x[gi1] * x1 + permGrad2y[gi1] * y1);
|
|
82
|
+
}
|
|
83
|
+
let t2 = 0.5 - x2 * x2 - y2 * y2;
|
|
84
|
+
if (t2 >= 0) {
|
|
85
|
+
const gi2 = ii + 1 + perm[jj + 1];
|
|
86
|
+
t2 *= t2;
|
|
87
|
+
n2 = t2 * t2 * (permGrad2x[gi2] * x2 + permGrad2y[gi2] * y2);
|
|
88
|
+
}
|
|
89
|
+
return 70.0 * (n0 + n1 + n2);
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=simplex.js.map
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { colorToCss, normalizeColor, readPixelsFromCanvas, surface, writePixels } from "./io.js";
|
|
2
|
+
/**
|
|
3
|
+
* `cascade.image.Text`: lines of text on a canvas, aligned to an anchor, with
|
|
4
|
+
* tracking, rotation and opacity.
|
|
5
|
+
*
|
|
6
|
+
* Fonts follow `cascade/image`'s rules. `font` is a CSS family list and draws
|
|
7
|
+
* with whatever faces the realm has (the page's or worker's in a browser,
|
|
8
|
+
* Skia's system fonts headless), so the same family only matches across hosts
|
|
9
|
+
* when both have the same face. A project font file (`.otf`, `.ttf`, `.woff`,
|
|
10
|
+
* `.woff2`) is read through `assets` and registered with the realm, which
|
|
11
|
+
* makes it match everywhere; a file that is not there falls back to
|
|
12
|
+
* `sans-serif` rather than failing, since a licensed face an export does not
|
|
13
|
+
* ship should still draw.
|
|
14
|
+
*/
|
|
15
|
+
const FONT_FILE = /\.(otf|ttf|woff2?)$/i;
|
|
16
|
+
const HOST_KEY = "__cascadeImageHost";
|
|
17
|
+
// One registration per realm and font file contents; see `registerFont` in
|
|
18
|
+
// cascade/image, which this mirrors for a runtime that cannot import it.
|
|
19
|
+
const registered = new Set();
|
|
20
|
+
function fingerprint(bytes) {
|
|
21
|
+
let hash = 0x811c9dc5;
|
|
22
|
+
for (let index = 0; index < bytes.length; index += 1) {
|
|
23
|
+
hash ^= bytes[index];
|
|
24
|
+
hash = Math.imul(hash, 0x01000193);
|
|
25
|
+
}
|
|
26
|
+
return `${bytes.length}-${(hash >>> 0).toString(16)}`;
|
|
27
|
+
}
|
|
28
|
+
/** The family to draw with: `font` itself, or a registered face for a font file. */
|
|
29
|
+
async function fontFamily(context, font) {
|
|
30
|
+
const path = font.trim();
|
|
31
|
+
if (!FONT_FILE.test(path))
|
|
32
|
+
return font;
|
|
33
|
+
let bytes;
|
|
34
|
+
try {
|
|
35
|
+
const assets = context.capabilities.assets;
|
|
36
|
+
if (!assets)
|
|
37
|
+
throw new Error("no assets");
|
|
38
|
+
bytes = await assets.read({ path }, { signal: context.signal });
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return "sans-serif";
|
|
42
|
+
}
|
|
43
|
+
const family = `cascade-font-${fingerprint(bytes)}`;
|
|
44
|
+
const globals = globalThis;
|
|
45
|
+
const host = globals[HOST_KEY];
|
|
46
|
+
const fonts = host ? null : globals.fonts ?? globals.document?.fonts;
|
|
47
|
+
const key = `${host ? `headless:${host.renderer}` : "browser"}:${family}`;
|
|
48
|
+
if (registered.has(key))
|
|
49
|
+
return family;
|
|
50
|
+
if (host && typeof host.registerFont === "function") {
|
|
51
|
+
await host.registerFont(family, bytes, {});
|
|
52
|
+
}
|
|
53
|
+
else if (typeof globals.FontFace === "function" && fonts) {
|
|
54
|
+
const face = new globals.FontFace(family, bytes.slice().buffer);
|
|
55
|
+
fonts.add(await face.load());
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
return "sans-serif";
|
|
59
|
+
}
|
|
60
|
+
registered.add(key);
|
|
61
|
+
return family;
|
|
62
|
+
}
|
|
63
|
+
export async function executeText(context) {
|
|
64
|
+
const { props } = context;
|
|
65
|
+
const [width, height] = [props.resolution[0], props.resolution[1]];
|
|
66
|
+
const color = normalizeColor(props.color);
|
|
67
|
+
const background = normalizeColor(props.backgroundColor);
|
|
68
|
+
const [offsetX, offsetY] = props.offset;
|
|
69
|
+
const { fontSize, alignH, alignV, rotation, letterSpacing } = props;
|
|
70
|
+
const family = await fontFamily(context, props.font);
|
|
71
|
+
const { canvas, context: ctx } = surface(width, height);
|
|
72
|
+
if (background.a > 0) {
|
|
73
|
+
ctx.fillStyle = colorToCss(background);
|
|
74
|
+
ctx.fillRect(0, 0, width, height);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
ctx.clearRect(0, 0, width, height);
|
|
78
|
+
}
|
|
79
|
+
ctx.save();
|
|
80
|
+
ctx.globalAlpha = props.opacity;
|
|
81
|
+
ctx.font = `${props.fontStyle} ${props.fontWeight} ${fontSize}px ${family}`;
|
|
82
|
+
ctx.fillStyle = colorToCss(color);
|
|
83
|
+
const lines = props.text.split("\n");
|
|
84
|
+
const lineHeightPx = fontSize * props.lineHeight;
|
|
85
|
+
const totalTextHeight = lines.length * lineHeightPx;
|
|
86
|
+
let anchorX;
|
|
87
|
+
let anchorY;
|
|
88
|
+
switch (alignH) {
|
|
89
|
+
case "left":
|
|
90
|
+
ctx.textAlign = "left";
|
|
91
|
+
anchorX = 0;
|
|
92
|
+
break;
|
|
93
|
+
case "right":
|
|
94
|
+
ctx.textAlign = "right";
|
|
95
|
+
anchorX = width;
|
|
96
|
+
break;
|
|
97
|
+
default:
|
|
98
|
+
ctx.textAlign = "center";
|
|
99
|
+
anchorX = width / 2;
|
|
100
|
+
}
|
|
101
|
+
switch (alignV) {
|
|
102
|
+
case "top":
|
|
103
|
+
anchorY = fontSize;
|
|
104
|
+
break;
|
|
105
|
+
case "bottom":
|
|
106
|
+
anchorY = height - totalTextHeight + fontSize;
|
|
107
|
+
break;
|
|
108
|
+
default:
|
|
109
|
+
anchorY = (height - totalTextHeight) / 2 + fontSize;
|
|
110
|
+
}
|
|
111
|
+
anchorX += offsetX;
|
|
112
|
+
anchorY += offsetY;
|
|
113
|
+
if (rotation !== 0) {
|
|
114
|
+
const pivotY = anchorY - fontSize / 2 + totalTextHeight / 2;
|
|
115
|
+
ctx.translate(anchorX, pivotY);
|
|
116
|
+
ctx.rotate((rotation * Math.PI) / 180);
|
|
117
|
+
ctx.translate(-anchorX, -pivotY);
|
|
118
|
+
}
|
|
119
|
+
if (letterSpacing !== 0) {
|
|
120
|
+
// Tracking: one glyph at a time.
|
|
121
|
+
ctx.textAlign = "left";
|
|
122
|
+
lines.forEach((line, index) => {
|
|
123
|
+
const y = anchorY + index * lineHeightPx;
|
|
124
|
+
let lineWidth = 0;
|
|
125
|
+
for (const char of line)
|
|
126
|
+
lineWidth += ctx.measureText(char).width + letterSpacing;
|
|
127
|
+
lineWidth -= letterSpacing;
|
|
128
|
+
let x = alignH === "left" ? anchorX : alignH === "right" ? anchorX - lineWidth : anchorX - lineWidth / 2;
|
|
129
|
+
for (const char of line) {
|
|
130
|
+
ctx.fillText(char, x, y);
|
|
131
|
+
x += ctx.measureText(char).width + letterSpacing;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
lines.forEach((line, index) => ctx.fillText(line, anchorX, anchorY + index * lineHeightPx));
|
|
137
|
+
}
|
|
138
|
+
ctx.restore();
|
|
139
|
+
context.outputs.image.set(await writePixels(context, readPixelsFromCanvas(canvas)));
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -6,6 +6,9 @@ import type { DefinitionNodeRegistration } from "../types.js";
|
|
|
6
6
|
* set — which speaks the same `geometry` type as `geo`, so any of its outputs
|
|
7
7
|
* fits any geometry node's input. `cascade.scene.*` is the assembly: geometry
|
|
8
8
|
* plus a viewpoint plus lights, which is what the Viewer's 3D mode renders.
|
|
9
|
+
* `cascade.image.*` makes and filters images, and `cascade.assert.*` fails a
|
|
10
|
+
* run whose result is wrong. Those two load their bodies lazily: this list is
|
|
11
|
+
* in Studio's first-paint bundle.
|
|
9
12
|
*/
|
|
10
13
|
export declare const builtinNodeRegistrations: readonly DefinitionNodeRegistration[];
|
|
11
14
|
export declare function builtinNodeRegistration(moduleId: string): DefinitionNodeRegistration | undefined;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { assertNodeRegistrations } from "./assert/index.js";
|
|
1
2
|
import { coreNodeRegistrations } from "./core/index.js";
|
|
2
3
|
import { geoNodeRegistrations } from "./geo/index.js";
|
|
4
|
+
import { imageNodeRegistrations } from "./image/index.js";
|
|
3
5
|
import { mathNodeRegistrations } from "./math/index.js";
|
|
4
6
|
import { popNodeRegistrations } from "./pop/index.js";
|
|
5
7
|
import { sceneNodeRegistrations } from "./scene/index.js";
|
|
@@ -10,6 +12,9 @@ import { sceneNodeRegistrations } from "./scene/index.js";
|
|
|
10
12
|
* set — which speaks the same `geometry` type as `geo`, so any of its outputs
|
|
11
13
|
* fits any geometry node's input. `cascade.scene.*` is the assembly: geometry
|
|
12
14
|
* plus a viewpoint plus lights, which is what the Viewer's 3D mode renders.
|
|
15
|
+
* `cascade.image.*` makes and filters images, and `cascade.assert.*` fails a
|
|
16
|
+
* run whose result is wrong. Those two load their bodies lazily: this list is
|
|
17
|
+
* in Studio's first-paint bundle.
|
|
13
18
|
*/
|
|
14
19
|
export const builtinNodeRegistrations = Object.freeze([
|
|
15
20
|
...coreNodeRegistrations,
|
|
@@ -17,6 +22,8 @@ export const builtinNodeRegistrations = Object.freeze([
|
|
|
17
22
|
...mathNodeRegistrations,
|
|
18
23
|
...popNodeRegistrations,
|
|
19
24
|
...sceneNodeRegistrations,
|
|
25
|
+
...imageNodeRegistrations,
|
|
26
|
+
...assertNodeRegistrations,
|
|
20
27
|
]);
|
|
21
28
|
const registrationsById = new Map(builtinNodeRegistrations.map((registration) => [
|
|
22
29
|
registration.moduleId,
|
package/dist/runtime/gpu.d.ts
CHANGED
|
@@ -28,6 +28,31 @@ export interface GpuHost extends GpuCapability {
|
|
|
28
28
|
}
|
|
29
29
|
export declare function isGpuHost(value: unknown): value is GpuHost;
|
|
30
30
|
export declare function createGpuHost(options: GpuHostOptions): GpuHost;
|
|
31
|
+
interface LimitedAdapter {
|
|
32
|
+
readonly limits: unknown;
|
|
33
|
+
requestDevice(descriptor?: {
|
|
34
|
+
requiredLimits?: Record<string, number>;
|
|
35
|
+
}): Promise<GpuCapability["device"]>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The host's one device, asked for with everything the adapter allows.
|
|
39
|
+
*
|
|
40
|
+
* A bare `requestDevice()` gets WebGPU's defaults (128 MiB per storage binding,
|
|
41
|
+
* 256 invocations, 16 KiB workgroup storage, 8 storage buffers per stage)
|
|
42
|
+
* whatever the hardware is, and the device is shared, so a node cannot ask for
|
|
43
|
+
* more later. Brand + Design chunked a ribbon into four accumulator buffers on
|
|
44
|
+
* an M3 Max for that reason (3 Nov 2026). Should an adapter refuse its own
|
|
45
|
+
* ceiling, the defaults are better than no device; a node that needs more
|
|
46
|
+
* says so with `gpuLimits` and gets {@link gpuLimitShortfall}'s message.
|
|
47
|
+
*/
|
|
48
|
+
export declare function requestDeviceWithAdapterLimits(adapter: LimitedAdapter): Promise<GpuCapability["device"]>;
|
|
49
|
+
/**
|
|
50
|
+
* What a node's declared `gpuLimits` asks for that this device does not give,
|
|
51
|
+
* as one sentence, or null when it all fits. `max*` limits must reach the
|
|
52
|
+
* value; `min*Alignment` limits must be at most it (smaller is better there).
|
|
53
|
+
*/
|
|
54
|
+
export declare function gpuLimitShortfall(label: string, required: Readonly<Record<string, number>> | undefined, gpu: Pick<GpuCapability, "limits" | "adapterInfo">): string | null;
|
|
31
55
|
/** Getter-backed supported-limits objects cannot be normalized with spread. */
|
|
32
56
|
export declare function readGpuLimits(source: unknown): Record<string, number>;
|
|
57
|
+
export {};
|
|
33
58
|
//# sourceMappingURL=gpu.d.ts.map
|
package/dist/runtime/gpu.js
CHANGED
|
@@ -196,6 +196,46 @@ export function createGpuHost(options) {
|
|
|
196
196
|
}
|
|
197
197
|
return host;
|
|
198
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* The host's one device, asked for with everything the adapter allows.
|
|
201
|
+
*
|
|
202
|
+
* A bare `requestDevice()` gets WebGPU's defaults (128 MiB per storage binding,
|
|
203
|
+
* 256 invocations, 16 KiB workgroup storage, 8 storage buffers per stage)
|
|
204
|
+
* whatever the hardware is, and the device is shared, so a node cannot ask for
|
|
205
|
+
* more later. Brand + Design chunked a ribbon into four accumulator buffers on
|
|
206
|
+
* an M3 Max for that reason (3 Nov 2026). Should an adapter refuse its own
|
|
207
|
+
* ceiling, the defaults are better than no device; a node that needs more
|
|
208
|
+
* says so with `gpuLimits` and gets {@link gpuLimitShortfall}'s message.
|
|
209
|
+
*/
|
|
210
|
+
export async function requestDeviceWithAdapterLimits(adapter) {
|
|
211
|
+
const requiredLimits = readGpuLimits(adapter.limits);
|
|
212
|
+
try {
|
|
213
|
+
return await adapter.requestDevice({ requiredLimits });
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
return adapter.requestDevice();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* What a node's declared `gpuLimits` asks for that this device does not give,
|
|
221
|
+
* as one sentence, or null when it all fits. `max*` limits must reach the
|
|
222
|
+
* value; `min*Alignment` limits must be at most it (smaller is better there).
|
|
223
|
+
*/
|
|
224
|
+
export function gpuLimitShortfall(label, required, gpu) {
|
|
225
|
+
if (!required)
|
|
226
|
+
return null;
|
|
227
|
+
const short = [];
|
|
228
|
+
for (const [name, wanted] of Object.entries(required)) {
|
|
229
|
+
const have = gpu.limits[name];
|
|
230
|
+
const fits = have !== undefined && (name.startsWith("min") ? have <= wanted : have >= wanted);
|
|
231
|
+
if (!fits)
|
|
232
|
+
short.push(`${name} ${wanted} (this GPU: ${have ?? "not reported"})`);
|
|
233
|
+
}
|
|
234
|
+
if (!short.length)
|
|
235
|
+
return null;
|
|
236
|
+
const adapter = gpu.adapterInfo.description || gpu.adapterInfo.device || gpu.adapterInfo.vendor || "this adapter";
|
|
237
|
+
return `${label} needs GPU limits ${adapter} does not allow: ${short.join(", ")}.`;
|
|
238
|
+
}
|
|
199
239
|
/** Getter-backed supported-limits objects cannot be normalized with spread. */
|
|
200
240
|
export function readGpuLimits(source) {
|
|
201
241
|
if (!source || typeof source !== "object")
|
|
@@ -42,4 +42,6 @@ import type { CascadeRuntime, CreateRuntimeOptions } from "./types.js";
|
|
|
42
42
|
*/
|
|
43
43
|
export declare const PREFLIGHT_WARNING_CODES: ReadonlySet<string>;
|
|
44
44
|
export declare function createRuntime(options: CreateRuntimeOptions): CascadeRuntime;
|
|
45
|
+
/** How many plain arrays/objects the runtime has copied in this process. */
|
|
46
|
+
export declare function runtimeValueCopies(): number;
|
|
45
47
|
//# sourceMappingURL=runtime.d.ts.map
|