@retikz/core 0.2.0-alpha.7 → 0.2.0-alpha.9
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/dist/es/arrows/index.d.ts +13 -0
- package/dist/es/arrows/index.d.ts.map +1 -0
- package/dist/es/arrows/index.js +118 -0
- package/dist/es/arrows/types.d.ts +43 -0
- package/dist/es/arrows/types.d.ts.map +1 -0
- package/dist/es/compile/clip.d.ts +17 -0
- package/dist/es/compile/clip.d.ts.map +1 -0
- package/dist/es/compile/clip.js +84 -0
- package/dist/es/compile/compile.d.ts +26 -1
- package/dist/es/compile/compile.d.ts.map +1 -1
- package/dist/es/compile/compile.js +60 -7
- package/dist/es/compile/marker-prim.d.ts +22 -0
- package/dist/es/compile/marker-prim.d.ts.map +1 -0
- package/dist/es/compile/marker-prim.js +63 -0
- package/dist/es/compile/node.d.ts +2 -1
- package/dist/es/compile/node.d.ts.map +1 -1
- package/dist/es/compile/node.js +3 -3
- package/dist/es/compile/paint.d.ts +6 -1
- package/dist/es/compile/paint.d.ts.map +1 -1
- package/dist/es/compile/paint.js +60 -3
- package/dist/es/compile/path/anchor.d.ts.map +1 -1
- package/dist/es/compile/path/anchor.js +12 -0
- package/dist/es/compile/path/index.d.ts +15 -0
- package/dist/es/compile/path/index.d.ts.map +1 -1
- package/dist/es/compile/path/index.js +268 -12
- package/dist/es/compile/path/relative.d.ts.map +1 -1
- package/dist/es/compile/path/relative.js +8 -0
- package/dist/es/compile/path/shrink.d.ts +19 -6
- package/dist/es/compile/path/shrink.d.ts.map +1 -1
- package/dist/es/compile/path/shrink.js +147 -25
- package/dist/es/compile/position.d.ts +8 -2
- package/dist/es/compile/position.d.ts.map +1 -1
- package/dist/es/compile/position.js +7 -1
- package/dist/es/geometry/bend.d.ts +7 -0
- package/dist/es/geometry/bend.d.ts.map +1 -1
- package/dist/es/geometry/bend.js +26 -1
- package/dist/es/index.d.ts +16 -4
- package/dist/es/index.d.ts.map +1 -1
- package/dist/es/index.js +13 -7
- package/dist/es/ir/clip.d.ts +72 -0
- package/dist/es/ir/clip.d.ts.map +1 -0
- package/dist/es/ir/clip.js +37 -0
- package/dist/es/ir/coordinate.d.ts +3 -3
- package/dist/es/ir/coordinate.d.ts.map +1 -1
- package/dist/es/ir/coordinate.js +4 -2
- package/dist/es/ir/index.d.ts +2 -0
- package/dist/es/ir/index.d.ts.map +1 -1
- package/dist/es/ir/json.d.ts +22 -0
- package/dist/es/ir/json.d.ts.map +1 -0
- package/dist/es/ir/json.js +25 -0
- package/dist/es/ir/node.d.ts +10 -10
- package/dist/es/ir/node.d.ts.map +1 -1
- package/dist/es/ir/node.js +4 -2
- package/dist/es/ir/paint.d.ts +25 -3
- package/dist/es/ir/paint.d.ts.map +1 -1
- package/dist/es/ir/paint.js +12 -6
- package/dist/es/ir/path/arrow.d.ts +40 -60
- package/dist/es/ir/path/arrow.d.ts.map +1 -1
- package/dist/es/ir/path/arrow.js +5 -5
- package/dist/es/ir/path/path.d.ts +553 -164
- package/dist/es/ir/path/path.d.ts.map +1 -1
- package/dist/es/ir/path/path.js +21 -1
- package/dist/es/ir/path/step.d.ts +483 -128
- package/dist/es/ir/path/step.d.ts.map +1 -1
- package/dist/es/ir/path/step.js +18 -5
- package/dist/es/ir/path/target.d.ts +1 -1
- package/dist/es/ir/path/target.d.ts.map +1 -1
- package/dist/es/ir/path/target.js +4 -2
- package/dist/es/ir/position/between-position.d.ts +26 -0
- package/dist/es/ir/position/between-position.d.ts.map +1 -0
- package/dist/es/ir/position/between-position.js +21 -0
- package/dist/es/ir/position/index.d.ts +1 -0
- package/dist/es/ir/position/index.d.ts.map +1 -1
- package/dist/es/ir/scene.d.ts +51 -0
- package/dist/es/ir/scene.d.ts.map +1 -1
- package/dist/es/ir/scene.js +14 -2
- package/dist/es/ir/scope.d.ts +999 -380
- package/dist/es/ir/scope.d.ts.map +1 -1
- package/dist/es/ir/scope.js +2 -0
- package/dist/es/pathGenerators/define.d.ts +16 -0
- package/dist/es/pathGenerators/define.d.ts.map +1 -0
- package/dist/es/pathGenerators/define.js +23 -0
- package/dist/es/pathGenerators/index.d.ts +9 -0
- package/dist/es/pathGenerators/index.d.ts.map +1 -0
- package/dist/es/pathGenerators/types.d.ts +45 -0
- package/dist/es/pathGenerators/types.d.ts.map +1 -0
- package/dist/es/patterns/index.d.ts +10 -0
- package/dist/es/patterns/index.d.ts.map +1 -0
- package/dist/es/patterns/index.js +83 -0
- package/dist/es/patterns/types.d.ts +38 -0
- package/dist/es/patterns/types.d.ts.map +1 -0
- package/dist/es/primitive/clip.d.ts +18 -0
- package/dist/es/primitive/clip.d.ts.map +1 -0
- package/dist/es/primitive/group.d.ts +6 -0
- package/dist/es/primitive/group.d.ts.map +1 -1
- package/dist/es/primitive/index.d.ts +2 -0
- package/dist/es/primitive/index.d.ts.map +1 -1
- package/dist/es/primitive/marker.d.ts +160 -0
- package/dist/es/primitive/marker.d.ts.map +1 -0
- package/dist/es/primitive/paint.d.ts +32 -4
- package/dist/es/primitive/paint.d.ts.map +1 -1
- package/dist/es/primitive/path.d.ts +22 -18
- package/dist/es/primitive/path.d.ts.map +1 -1
- package/dist/es/primitive/scene.d.ts +2 -1
- package/dist/es/primitive/scene.d.ts.map +1 -1
- package/dist/lib/arrows/index.cjs +118 -0
- package/dist/lib/arrows/index.d.ts +13 -0
- package/dist/lib/arrows/index.d.ts.map +1 -0
- package/dist/lib/arrows/types.d.ts +43 -0
- package/dist/lib/arrows/types.d.ts.map +1 -0
- package/dist/lib/compile/clip.cjs +84 -0
- package/dist/lib/compile/clip.d.ts +17 -0
- package/dist/lib/compile/clip.d.ts.map +1 -0
- package/dist/lib/compile/compile.cjs +62 -9
- package/dist/lib/compile/compile.d.ts +26 -1
- package/dist/lib/compile/compile.d.ts.map +1 -1
- package/dist/lib/compile/marker-prim.cjs +63 -0
- package/dist/lib/compile/marker-prim.d.ts +22 -0
- package/dist/lib/compile/marker-prim.d.ts.map +1 -0
- package/dist/lib/compile/node.cjs +3 -3
- package/dist/lib/compile/node.d.ts +2 -1
- package/dist/lib/compile/node.d.ts.map +1 -1
- package/dist/lib/compile/paint.cjs +60 -3
- package/dist/lib/compile/paint.d.ts +6 -1
- package/dist/lib/compile/paint.d.ts.map +1 -1
- package/dist/lib/compile/path/anchor.cjs +12 -0
- package/dist/lib/compile/path/anchor.d.ts.map +1 -1
- package/dist/lib/compile/path/index.cjs +266 -10
- package/dist/lib/compile/path/index.d.ts +15 -0
- package/dist/lib/compile/path/index.d.ts.map +1 -1
- package/dist/lib/compile/path/relative.cjs +8 -0
- package/dist/lib/compile/path/relative.d.ts.map +1 -1
- package/dist/lib/compile/path/shrink.cjs +147 -25
- package/dist/lib/compile/path/shrink.d.ts +19 -6
- package/dist/lib/compile/path/shrink.d.ts.map +1 -1
- package/dist/lib/compile/position.cjs +7 -1
- package/dist/lib/compile/position.d.ts +8 -2
- package/dist/lib/compile/position.d.ts.map +1 -1
- package/dist/lib/geometry/bend.cjs +26 -0
- package/dist/lib/geometry/bend.d.ts +7 -0
- package/dist/lib/geometry/bend.d.ts.map +1 -1
- package/dist/lib/index.cjs +20 -3
- package/dist/lib/index.d.ts +16 -4
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/ir/clip.cjs +37 -0
- package/dist/lib/ir/clip.d.ts +72 -0
- package/dist/lib/ir/clip.d.ts.map +1 -0
- package/dist/lib/ir/coordinate.cjs +4 -2
- package/dist/lib/ir/coordinate.d.ts +3 -3
- package/dist/lib/ir/coordinate.d.ts.map +1 -1
- package/dist/lib/ir/index.d.ts +2 -0
- package/dist/lib/ir/index.d.ts.map +1 -1
- package/dist/lib/ir/json.cjs +26 -0
- package/dist/lib/ir/json.d.ts +22 -0
- package/dist/lib/ir/json.d.ts.map +1 -0
- package/dist/lib/ir/node.cjs +4 -2
- package/dist/lib/ir/node.d.ts +10 -10
- package/dist/lib/ir/node.d.ts.map +1 -1
- package/dist/lib/ir/paint.cjs +12 -5
- package/dist/lib/ir/paint.d.ts +25 -3
- package/dist/lib/ir/paint.d.ts.map +1 -1
- package/dist/lib/ir/path/arrow.cjs +5 -5
- package/dist/lib/ir/path/arrow.d.ts +40 -60
- package/dist/lib/ir/path/arrow.d.ts.map +1 -1
- package/dist/lib/ir/path/path.cjs +20 -0
- package/dist/lib/ir/path/path.d.ts +553 -164
- package/dist/lib/ir/path/path.d.ts.map +1 -1
- package/dist/lib/ir/path/step.cjs +18 -4
- package/dist/lib/ir/path/step.d.ts +483 -128
- package/dist/lib/ir/path/step.d.ts.map +1 -1
- package/dist/lib/ir/path/target.cjs +4 -2
- package/dist/lib/ir/path/target.d.ts +1 -1
- package/dist/lib/ir/path/target.d.ts.map +1 -1
- package/dist/lib/ir/position/between-position.cjs +22 -0
- package/dist/lib/ir/position/between-position.d.ts +26 -0
- package/dist/lib/ir/position/between-position.d.ts.map +1 -0
- package/dist/lib/ir/position/index.d.ts +1 -0
- package/dist/lib/ir/position/index.d.ts.map +1 -1
- package/dist/lib/ir/scene.cjs +14 -1
- package/dist/lib/ir/scene.d.ts +51 -0
- package/dist/lib/ir/scene.d.ts.map +1 -1
- package/dist/lib/ir/scope.cjs +2 -0
- package/dist/lib/ir/scope.d.ts +999 -380
- package/dist/lib/ir/scope.d.ts.map +1 -1
- package/dist/lib/pathGenerators/define.cjs +23 -0
- package/dist/lib/pathGenerators/define.d.ts +16 -0
- package/dist/lib/pathGenerators/define.d.ts.map +1 -0
- package/dist/lib/pathGenerators/index.d.ts +9 -0
- package/dist/lib/pathGenerators/index.d.ts.map +1 -0
- package/dist/lib/pathGenerators/types.d.ts +45 -0
- package/dist/lib/pathGenerators/types.d.ts.map +1 -0
- package/dist/lib/patterns/index.cjs +83 -0
- package/dist/lib/patterns/index.d.ts +10 -0
- package/dist/lib/patterns/index.d.ts.map +1 -0
- package/dist/lib/patterns/types.d.ts +38 -0
- package/dist/lib/patterns/types.d.ts.map +1 -0
- package/dist/lib/primitive/clip.d.ts +18 -0
- package/dist/lib/primitive/clip.d.ts.map +1 -0
- package/dist/lib/primitive/group.d.ts +6 -0
- package/dist/lib/primitive/group.d.ts.map +1 -1
- package/dist/lib/primitive/index.d.ts +2 -0
- package/dist/lib/primitive/index.d.ts.map +1 -1
- package/dist/lib/primitive/marker.d.ts +160 -0
- package/dist/lib/primitive/marker.d.ts.map +1 -0
- package/dist/lib/primitive/paint.d.ts +32 -4
- package/dist/lib/primitive/paint.d.ts.map +1 -1
- package/dist/lib/primitive/path.d.ts +22 -18
- package/dist/lib/primitive/path.d.ts.map +1 -1
- package/dist/lib/primitive/scene.d.ts +2 -1
- package/dist/lib/primitive/scene.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/es/compile/path/arrow-geometry.d.ts +0 -22
- package/dist/es/compile/path/arrow-geometry.d.ts.map +0 -1
- package/dist/es/compile/path/arrow-geometry.js +0 -40
- package/dist/lib/compile/path/arrow-geometry.cjs +0 -41
- package/dist/lib/compile/path/arrow-geometry.d.ts +0 -22
- package/dist/lib/compile/path/arrow-geometry.d.ts.map +0 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
//#region src/compile/marker-prim.ts
|
|
2
|
+
/**
|
|
3
|
+
* marker 窄子集运行时栅栏(arrow + pattern 共用)
|
|
4
|
+
* @description `MarkerPrimitive` 的窄子集(type 限 path/ellipse/rect/group、fill 限 string | contextStroke、
|
|
5
|
+
* 无外部 resourceRef / text / 函数)TS 只能编译期守门;第三方 / LLM 写出的 emit 会在运行时绕过类型,
|
|
6
|
+
* 故这里做运行时校验。arrow(marker 几何)与 pattern(motif 几何)emit 产物同契约,复用本组校验。
|
|
7
|
+
* `owner` 是错误消息里的归属串(如 `Arrow 'normal'` / `Pattern 'lines'`),便于第三方 / LLM 自修。
|
|
8
|
+
*/
|
|
9
|
+
/** marker 子集允许的 primitive type(窄子集运行时栅栏) */
|
|
10
|
+
var MARKER_PRIM_TYPES = new Set([
|
|
11
|
+
"path",
|
|
12
|
+
"ellipse",
|
|
13
|
+
"rect",
|
|
14
|
+
"group"
|
|
15
|
+
]);
|
|
16
|
+
/** 深度查 emit 产物里有没有函数(守 Scene 100% JSON 可序列化) */
|
|
17
|
+
var assertNoFunction = (owner, value) => {
|
|
18
|
+
if (typeof value === "function") throw new Error(`${owner} emit produced a marker containing a function; markers must be plain JSON data.`);
|
|
19
|
+
if (Array.isArray(value)) for (const v of value) assertNoFunction(owner, v);
|
|
20
|
+
else if (value !== null && typeof value === "object") for (const v of Object.values(value)) assertNoFunction(owner, v);
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* 深度查 emit 产物里有没有非 finite 数(NaN / Infinity)
|
|
24
|
+
* @description 第三方 / LLM 的 emit 算错坐标(除零 / 溢出)会产 NaN / Infinity;`JSON.stringify` 把它们变成
|
|
25
|
+
* `null`,破坏 Scene round-trip 等价。故在此抛含 owner 的清晰错,不放任非 finite 流入 Scene(与 arrow
|
|
26
|
+
* geometry / path generator 的 finite 守卫同源)。
|
|
27
|
+
*/
|
|
28
|
+
var assertFiniteNumbers = (owner, value) => {
|
|
29
|
+
if (typeof value === "number") {
|
|
30
|
+
if (!Number.isFinite(value)) throw new Error(`${owner} emit produced a marker with a non-finite number (${String(value)}); marker coordinates must be finite.`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (Array.isArray(value)) for (const v of value) assertFiniteNumbers(owner, v);
|
|
34
|
+
else if (value !== null && typeof value === "object") for (const v of Object.values(value)) assertFiniteNumbers(owner, v);
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* 递归校验单个 emit 产物符合 `MarkerPrimitive` 窄子集(运行时栅栏,TS 只能编译期守门)
|
|
38
|
+
* @description type 限 path/ellipse/rect/group(拒 text 等);fill 限 string | contextStroke(拒 resourceRef
|
|
39
|
+
* 等外部资源引用);group 递归 children。守"marker 内无文本布局 / 无外部资源 / 无递归 marker"契约。
|
|
40
|
+
*/
|
|
41
|
+
var assertValidMarkerPrim = (owner, prim) => {
|
|
42
|
+
if (prim === null || typeof prim !== "object") throw new Error(`${owner} emit produced a non-object marker primitive.`);
|
|
43
|
+
const type = prim.type;
|
|
44
|
+
if (typeof type !== "string" || !MARKER_PRIM_TYPES.has(type)) throw new Error(`${owner} emit produced an invalid marker primitive type '${String(type)}'; allowed: group, path, ellipse, rect.`);
|
|
45
|
+
const fill = prim.fill;
|
|
46
|
+
if (fill !== void 0 && typeof fill !== "string" && !(typeof fill === "object" && fill !== null && fill.kind === "contextStroke")) throw new Error(`${owner} marker fill must be a color string or { kind: 'contextStroke' }; external paint references are not allowed inside markers.`);
|
|
47
|
+
if (type === "group") {
|
|
48
|
+
const children = prim.children;
|
|
49
|
+
if (!Array.isArray(children)) throw new Error(`${owner} marker group must have a children array.`);
|
|
50
|
+
for (const child of children) assertValidMarkerPrim(owner, child);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* 跑完整窄子集 + JSON-safe 校验(产物逐个过 `assertValidMarkerPrim` + 深度无函数检查)
|
|
55
|
+
* @description arrow / pattern 调 emit 收齐 `MarkerPrimitive[]` 后调用;任一原语违窄子集即抛含 owner 的清晰错。
|
|
56
|
+
*/
|
|
57
|
+
var validateMarkerPrimitives = (owner, marker) => {
|
|
58
|
+
for (const prim of marker) assertValidMarkerPrim(owner, prim);
|
|
59
|
+
assertNoFunction(owner, marker);
|
|
60
|
+
assertFiniteNumbers(owner, marker);
|
|
61
|
+
};
|
|
62
|
+
//#endregion
|
|
63
|
+
exports.validateMarkerPrimitives = validateMarkerPrimitives;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { MarkerPrimitive } from '../primitive/marker';
|
|
2
|
+
/** 深度查 emit 产物里有没有函数(守 Scene 100% JSON 可序列化) */
|
|
3
|
+
export declare const assertNoFunction: (owner: string, value: unknown) => void;
|
|
4
|
+
/**
|
|
5
|
+
* 深度查 emit 产物里有没有非 finite 数(NaN / Infinity)
|
|
6
|
+
* @description 第三方 / LLM 的 emit 算错坐标(除零 / 溢出)会产 NaN / Infinity;`JSON.stringify` 把它们变成
|
|
7
|
+
* `null`,破坏 Scene round-trip 等价。故在此抛含 owner 的清晰错,不放任非 finite 流入 Scene(与 arrow
|
|
8
|
+
* geometry / path generator 的 finite 守卫同源)。
|
|
9
|
+
*/
|
|
10
|
+
export declare const assertFiniteNumbers: (owner: string, value: unknown) => void;
|
|
11
|
+
/**
|
|
12
|
+
* 递归校验单个 emit 产物符合 `MarkerPrimitive` 窄子集(运行时栅栏,TS 只能编译期守门)
|
|
13
|
+
* @description type 限 path/ellipse/rect/group(拒 text 等);fill 限 string | contextStroke(拒 resourceRef
|
|
14
|
+
* 等外部资源引用);group 递归 children。守"marker 内无文本布局 / 无外部资源 / 无递归 marker"契约。
|
|
15
|
+
*/
|
|
16
|
+
export declare const assertValidMarkerPrim: (owner: string, prim: unknown) => void;
|
|
17
|
+
/**
|
|
18
|
+
* 跑完整窄子集 + JSON-safe 校验(产物逐个过 `assertValidMarkerPrim` + 深度无函数检查)
|
|
19
|
+
* @description arrow / pattern 调 emit 收齐 `MarkerPrimitive[]` 后调用;任一原语违窄子集即抛含 owner 的清晰错。
|
|
20
|
+
*/
|
|
21
|
+
export declare const validateMarkerPrimitives: (owner: string, marker: ReadonlyArray<MarkerPrimitive>) => void;
|
|
22
|
+
//# sourceMappingURL=marker-prim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marker-prim.d.ts","sourceRoot":"","sources":["../../../src/compile/marker-prim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAa3D,gDAAgD;AAChD,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,EAAE,OAAO,OAAO,KAAG,IAWhE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,EAAE,OAAO,OAAO,KAAG,IAcnE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAAI,OAAO,MAAM,EAAE,MAAM,OAAO,KAAG,IA2BpE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GACnC,OAAO,MAAM,EACb,QAAQ,aAAa,CAAC,eAAe,CAAC,KACrC,IAIF,CAAC"}
|
|
@@ -205,7 +205,7 @@ var angleBoundaryOf = (layout, angleDeg) => {
|
|
|
205
205
|
* scope 局部度量),调用方负责后续 `projectLayoutToGlobal` / `applyTransformChain` 投回全局;
|
|
206
206
|
* 笛卡尔字面量 `Position` 已在 scope 局部度量,行为延续 v0.1。
|
|
207
207
|
*/
|
|
208
|
-
var layoutNode = (node, measureText, nameStack, nodeDistance, scopeChain = [], labelDefault, shapes = require_index.BUILTIN_SHAPES) => {
|
|
208
|
+
var layoutNode = (node, measureText, nameStack, nodeDistance, scopeChain = [], labelDefault, shapes = require_index.BUILTIN_SHAPES, resolveBetweenGlobal) => {
|
|
209
209
|
const shapeName = node.shape ?? "rectangle";
|
|
210
210
|
const shapeDef = Object.prototype.hasOwnProperty.call(shapes, shapeName) ? shapes[shapeName] : void 0;
|
|
211
211
|
if (!shapeDef) throw new Error(`Unknown shape '${shapeName}'; registered shapes: ${Object.keys(shapes).sort().join(", ")}`);
|
|
@@ -263,8 +263,8 @@ var layoutNode = (node, measureText, nameStack, nodeDistance, scopeChain = [], l
|
|
|
263
263
|
const innerHalfH = Math.max(textHeight / 2 + ySep, ySep, minH / 2);
|
|
264
264
|
const { halfWidth: boundsHalfW, halfHeight: boundsHalfH } = shapeDef.circumscribe(innerHalfW, innerHalfH);
|
|
265
265
|
const rotateDeg = node.rotate ?? 0;
|
|
266
|
-
const center = require_position.resolvePosition(node.position, nameStack, nodeDistance, scopeChain);
|
|
267
|
-
if (!center) throw new Error(`Cannot resolve position for node ${node.id ?? "(unnamed)"}; polar.origin
|
|
266
|
+
const center = require_position.resolvePosition(node.position, nameStack, nodeDistance, scopeChain, resolveBetweenGlobal);
|
|
267
|
+
if (!center) throw new Error(`Cannot resolve position for node ${node.id ?? "(unnamed)"}; polar.origin / at.of / between endpoint may reference an undefined node`);
|
|
268
268
|
const labels = (node.label === void 0 ? void 0 : Array.isArray(node.label) ? node.label : [node.label])?.map((lab) => {
|
|
269
269
|
const labFont = lab.font;
|
|
270
270
|
const labFontSize = (labFont?.size ?? labelDefault?.font?.size ?? baseFontSize) * fontScale;
|
|
@@ -5,6 +5,7 @@ import { PaintResolver } from './paint';
|
|
|
5
5
|
import { ScenePrimitive, TextLine, Transform } from '../primitive';
|
|
6
6
|
import { ShapeDefinition } from '../shapes';
|
|
7
7
|
import { NameStack } from './name-stack';
|
|
8
|
+
import { ResolveBetweenGlobal } from './position';
|
|
8
9
|
import { TextMeasurer } from './text-metrics';
|
|
9
10
|
export type NodeLayout = {
|
|
10
11
|
/** 节点 id(其他位置可引用) */
|
|
@@ -116,7 +117,7 @@ export declare const angleBoundaryOf: (layout: NodeLayout, angleDeg: number) =>
|
|
|
116
117
|
* scope 局部度量),调用方负责后续 `projectLayoutToGlobal` / `applyTransformChain` 投回全局;
|
|
117
118
|
* 笛卡尔字面量 `Position` 已在 scope 局部度量,行为延续 v0.1。
|
|
118
119
|
*/
|
|
119
|
-
export declare const layoutNode: (node: IRNode, measureText: TextMeasurer, nameStack: NameStack, nodeDistance?: number, scopeChain?: ReadonlyArray<Transform>, labelDefault?: IRLabelDefault, shapes?: Record<string, ShapeDefinition
|
|
120
|
+
export declare const layoutNode: (node: IRNode, measureText: TextMeasurer, nameStack: NameStack, nodeDistance?: number, scopeChain?: ReadonlyArray<Transform>, labelDefault?: IRLabelDefault, shapes?: Record<string, ShapeDefinition>, resolveBetweenGlobal?: ResolveBetweenGlobal) => NodeLayout;
|
|
120
121
|
/**
|
|
121
122
|
* NodeLayout → Scene primitives
|
|
122
123
|
* @description shape 主体走 `shapeDef.emit`(收轴对齐 rect、可出多 primitive);text 始终走 TextPrim;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/compile/node.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAc,MAAM,EAAe,WAAW,EAAE,MAAM,OAAO,CAAC;AACvG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,KAAK,EAAa,cAAc,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEnF,OAAO,KAAK,EAAE,eAAe,EAAc,MAAM,WAAW,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/compile/node.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,65 @@
|
|
|
1
|
+
const require_marker_prim = require("./marker-prim.cjs");
|
|
1
2
|
//#region src/compile/paint.ts
|
|
3
|
+
/** 内置 / 注入都缺 defaultSize 时的 tile 周期兜底(user units) */
|
|
4
|
+
var FALLBACK_PATTERN_SIZE = 8;
|
|
5
|
+
/** motif 缺省主色:CSS `currentColor`(继承 svg color,主题反应天然) */
|
|
6
|
+
var DEFAULT_MOTIF_COLOR = "currentColor";
|
|
7
|
+
/**
|
|
8
|
+
* 查有效 pattern 表取 def;未注册名编译期 throw(消息含字母序可用名列表)
|
|
9
|
+
* @description 仿 arrow / shape 的未注册 throw 风格——错误带可用名便于第三方 / LLM 自修。
|
|
10
|
+
*/
|
|
11
|
+
var lookupPatternDef = (shape, effective) => {
|
|
12
|
+
if (Object.prototype.hasOwnProperty.call(effective, shape)) return effective[shape];
|
|
13
|
+
const available = Object.keys(effective).sort().join(", ");
|
|
14
|
+
throw new Error(`Unknown pattern shape '${shape}'; available: ${available}`);
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* 对一个 pattern spec 查表 + 调 `def.emit` 产已解析 tile
|
|
18
|
+
* @description 构 `PatternEmitContext`(size = spec.size ?? def.defaultSize ?? 8;color = spec.color ??
|
|
19
|
+
* currentColor;background 透传;lineWidth 仅 spec 显式给值时存在——让 dots 缺省半径 size/5、lines/grid
|
|
20
|
+
* 缺省描边 1)→ 调 emit 收 `MarkerPrimitive[]` → 跑共享窄子集 + JSON-safe 校验 → 组装 `ResolvedPatternTile`。
|
|
21
|
+
* emit 抛错 / 产非法原语都包成含 shape 名的清晰错(带 cause)。
|
|
22
|
+
*/
|
|
23
|
+
var resolvePatternTile = (spec, effectivePatterns, round) => {
|
|
24
|
+
const def = lookupPatternDef(spec.shape, effectivePatterns);
|
|
25
|
+
const rawSize = spec.size ?? def.defaultSize ?? FALLBACK_PATTERN_SIZE;
|
|
26
|
+
if (!Number.isFinite(rawSize) || rawSize <= 0) throw new Error(`Pattern '${spec.shape}' has an invalid size (${String(rawSize)}); it must be a finite number greater than 0.`);
|
|
27
|
+
if (spec.lineWidth !== void 0 && (!Number.isFinite(spec.lineWidth) || spec.lineWidth <= 0)) throw new Error(`Pattern '${spec.shape}' has an invalid lineWidth (${String(spec.lineWidth)}); it must be a finite number greater than 0.`);
|
|
28
|
+
if (spec.rotation !== void 0 && !Number.isFinite(spec.rotation)) throw new Error(`Pattern '${spec.shape}' has a non-finite rotation (${String(spec.rotation)}); it must be a finite number.`);
|
|
29
|
+
const size = round(rawSize);
|
|
30
|
+
const ctx = {
|
|
31
|
+
size,
|
|
32
|
+
color: spec.color ?? DEFAULT_MOTIF_COLOR,
|
|
33
|
+
round
|
|
34
|
+
};
|
|
35
|
+
if (spec.background !== void 0) ctx.background = spec.background;
|
|
36
|
+
if (spec.lineWidth !== void 0) ctx.lineWidth = spec.lineWidth;
|
|
37
|
+
if (typeof def.emit !== "function") throw new Error(`Pattern '${spec.shape}' is missing an emit function (PatternDefinition.emit is required).`);
|
|
38
|
+
let motif;
|
|
39
|
+
try {
|
|
40
|
+
motif = [...def.emit(ctx)];
|
|
41
|
+
} catch (e) {
|
|
42
|
+
throw new Error(`Pattern '${spec.shape}' emit failed: ${e instanceof Error ? e.message : String(e)}`, { cause: e });
|
|
43
|
+
}
|
|
44
|
+
require_marker_prim.validateMarkerPrimitives(`Pattern '${spec.shape}'`, motif);
|
|
45
|
+
const tile = {
|
|
46
|
+
size,
|
|
47
|
+
motif
|
|
48
|
+
};
|
|
49
|
+
if (spec.background !== void 0) tile.background = spec.background;
|
|
50
|
+
if (spec.rotation !== void 0) tile.rotation = spec.rotation;
|
|
51
|
+
return tile;
|
|
52
|
+
};
|
|
2
53
|
/**
|
|
3
54
|
* 建一个 paint 登记表
|
|
4
55
|
* @description resolve 对相同 PaintSpec(结构化 JSON 深比较)合并为一个资源、派稳定 id(`paint-1` / `paint-2`…,首见序)。
|
|
5
56
|
* 同一份 IR 编译两次 → 同 id(快照稳定、SSR / CSR 一致)。SVG id 跨实例唯一性由 react adapter 加 useId 前缀解决。
|
|
57
|
+
* pattern 资源额外查 `effectivePatterns` + 调 `PatternDefinition.emit` 产 tile 写进 `SceneResource.tile`
|
|
58
|
+
* (未注册名 throw、含可用名);gradient / image 资源只 spec。
|
|
59
|
+
* @param effectivePatterns 有效 pattern 表(内置 + 注入),供 pattern 资源查表 + emit
|
|
60
|
+
* @param round 精度取整(与 compile / render 同一 round,保 tile 几何一致)
|
|
6
61
|
*/
|
|
7
|
-
var createPaintRegistry = () => {
|
|
62
|
+
var createPaintRegistry = (effectivePatterns, round) => {
|
|
8
63
|
const idByKey = /* @__PURE__ */ new Map();
|
|
9
64
|
const list = [];
|
|
10
65
|
let counter = 0;
|
|
@@ -17,11 +72,13 @@ var createPaintRegistry = () => {
|
|
|
17
72
|
counter += 1;
|
|
18
73
|
id = `paint-${counter}`;
|
|
19
74
|
idByKey.set(key, id);
|
|
20
|
-
|
|
75
|
+
const resource = {
|
|
21
76
|
kind: "paint",
|
|
22
77
|
id,
|
|
23
78
|
spec: fill
|
|
24
|
-
}
|
|
79
|
+
};
|
|
80
|
+
if (fill.type === "pattern") resource.tile = resolvePatternTile(fill, effectivePatterns, round);
|
|
81
|
+
list.push(resource);
|
|
25
82
|
}
|
|
26
83
|
return {
|
|
27
84
|
kind: "resourceRef",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IRPaintSpec } from '../ir';
|
|
2
|
+
import { PatternDefinition } from '../patterns';
|
|
2
3
|
import { PaintValue, SceneResource } from '../primitive';
|
|
3
4
|
/** fill 解析器:纯色 string 原样返回;PaintSpec 去重 + 派稳定 id → `{ kind:'resourceRef', id }`;undefined 透传 */
|
|
4
5
|
export type PaintResolver = (fill: string | IRPaintSpec | undefined) => PaintValue | undefined;
|
|
@@ -11,6 +12,10 @@ export type PaintRegistry = {
|
|
|
11
12
|
* 建一个 paint 登记表
|
|
12
13
|
* @description resolve 对相同 PaintSpec(结构化 JSON 深比较)合并为一个资源、派稳定 id(`paint-1` / `paint-2`…,首见序)。
|
|
13
14
|
* 同一份 IR 编译两次 → 同 id(快照稳定、SSR / CSR 一致)。SVG id 跨实例唯一性由 react adapter 加 useId 前缀解决。
|
|
15
|
+
* pattern 资源额外查 `effectivePatterns` + 调 `PatternDefinition.emit` 产 tile 写进 `SceneResource.tile`
|
|
16
|
+
* (未注册名 throw、含可用名);gradient / image 资源只 spec。
|
|
17
|
+
* @param effectivePatterns 有效 pattern 表(内置 + 注入),供 pattern 资源查表 + emit
|
|
18
|
+
* @param round 精度取整(与 compile / render 同一 round,保 tile 几何一致)
|
|
14
19
|
*/
|
|
15
|
-
export declare const createPaintRegistry: () => PaintRegistry;
|
|
20
|
+
export declare const createPaintRegistry: (effectivePatterns: Record<string, PatternDefinition>, round: (n: number) => number) => PaintRegistry;
|
|
16
21
|
//# sourceMappingURL=paint.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paint.d.ts","sourceRoot":"","sources":["../../../src/compile/paint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"paint.d.ts","sourceRoot":"","sources":["../../../src/compile/paint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,KAAK,EAAE,iBAAiB,EAAsB,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAmB,UAAU,EAAuB,aAAa,EAAE,MAAM,cAAc,CAAC;AAGpG,gGAAgG;AAChG,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,KAAK,UAAU,GAAG,SAAS,CAAC;AAE/F,8DAA8D;AAC9D,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,aAAa,CAAC;IACvB,SAAS,EAAE,MAAM,KAAK,CAAC,aAAa,CAAC,CAAC;CACvC,CAAC;AA+EF;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAC9B,mBAAmB,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACpD,OAAO,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,KAC3B,aAuBF,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const require__edge = require("../../geometry/_edge.cjs");
|
|
1
2
|
const require_scope = require("../scope.cjs");
|
|
2
3
|
const require_position = require("../position.cjs");
|
|
3
4
|
const require_node = require("../node.cjs");
|
|
@@ -5,6 +6,8 @@ const require_anchor_cache = require("../anchor-cache.cjs");
|
|
|
5
6
|
//#region src/compile/path/anchor.ts
|
|
6
7
|
/** target 是否对象形态 NodeTarget(`{ id, anchor?, offset? }`);与 Position(array) / Polar / Offset(of) / Relative 区分(独有 `id`) */
|
|
7
8
|
var isNodeTarget = (t) => typeof t === "object" && !Array.isArray(t) && "id" in t;
|
|
9
|
+
/** target 是否 between 比例点(`{ between, t }`);独有 `between` 字段 */
|
|
10
|
+
var isBetween = (t) => typeof t === "object" && !Array.isArray(t) && "between" in t;
|
|
8
11
|
/** 解析 NodeTarget 的 anchor(非 undefined)到世界坐标:命名 / 角度走 resolveAnchor,`{ side, t }` 走 resolveEdgePoint */
|
|
9
12
|
var resolveAnchorRef = (node, anchor) => {
|
|
10
13
|
if (typeof anchor === "number") return require_anchor_cache.resolveAnchor(node, String(anchor));
|
|
@@ -26,6 +29,14 @@ var refPointOfTarget = (target, nameStack, scopeChain = []) => {
|
|
|
26
29
|
if (!node) return null;
|
|
27
30
|
return addOffset(target.anchor === void 0 ? [node.rect.x, node.rect.y] : resolveAnchorRef(node, target.anchor), target.offset);
|
|
28
31
|
}
|
|
32
|
+
if (isBetween(target)) {
|
|
33
|
+
const a = refPointOfTarget(target.between[0], nameStack, scopeChain);
|
|
34
|
+
const b = refPointOfTarget(target.between[1], nameStack, scopeChain);
|
|
35
|
+
if (!a || !b) return null;
|
|
36
|
+
const mid = require__edge.lerpPoint(a, b, target.t);
|
|
37
|
+
if (!Number.isFinite(mid[0]) || !Number.isFinite(mid[1])) return null;
|
|
38
|
+
return mid;
|
|
39
|
+
}
|
|
29
40
|
if (typeof target === "object" && !Array.isArray(target) && ("relative" in target || "relativeAccumulate" in target)) return null;
|
|
30
41
|
const local = require_position.resolvePosition(target, nameStack, void 0, scopeChain);
|
|
31
42
|
if (!local) return null;
|
|
@@ -45,6 +56,7 @@ var clipForTarget = (target, toward, nameStack, scopeChain = []) => {
|
|
|
45
56
|
if (!node) return null;
|
|
46
57
|
return addOffset(target.anchor === void 0 ? require_node.boundaryPointOf(node, toward) : resolveAnchorRef(node, target.anchor), target.offset);
|
|
47
58
|
}
|
|
59
|
+
if (isBetween(target)) return refPointOfTarget(target, nameStack, scopeChain);
|
|
48
60
|
if (typeof target === "object" && !Array.isArray(target) && ("relative" in target || "relativeAccumulate" in target)) return null;
|
|
49
61
|
const local = require_position.resolvePosition(target, nameStack, void 0, scopeChain);
|
|
50
62
|
if (!local) return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/anchor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/anchor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmC,UAAU,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACtF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAyB/C;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,QAAQ,EAChB,WAAW,SAAS,EACpB,aAAY,aAAa,CAAC,SAAS,CAAM,KACxC,UAAU,GAAG,IA8Bf,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,QAAQ,GACnB,MAAM,UAAU,EAChB,MAAM,UAAU,EAChB,KAAK,IAAI,GAAG,IAAI,KACf,UACqD,CAAC;AAEzD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,QAAQ,QAAQ,EAChB,QAAQ,UAAU,EAClB,WAAW,SAAS,EACpB,aAAY,aAAa,CAAC,SAAS,CAAM,KACxC,UAAU,GAAG,IAsBf,CAAC;AAEF,qCAAqC;AACrC,eAAO,MAAM,SAAS,GAAI,GAAG,UAAU,GAAG,IAAI,EAAE,GAAG,UAAU,GAAG,IAAI,KAAG,OACzB,CAAC;AAE/C,6BAA6B;AAC7B,eAAO,MAAM,WAAW,GAAI,GAAG,UAAU,EAAE,QAAQ,UAAU,EAAE,MAAM,MAAM,KAAG,UAM7E,CAAC"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
const require_rect = require("../../geometry/rect.cjs");
|
|
2
|
+
const require_json = require("../../ir/json.cjs");
|
|
3
|
+
const require_index = require("../../arrows/index.cjs");
|
|
4
|
+
const require_scope = require("../scope.cjs");
|
|
2
5
|
const require_arc = require("../../geometry/arc.cjs");
|
|
3
6
|
const require_bend = require("../../geometry/bend.cjs");
|
|
4
7
|
const require_segment = require("../../geometry/segment.cjs");
|
|
@@ -9,8 +12,56 @@ const require_relative = require("./relative.cjs");
|
|
|
9
12
|
const require_shrink = require("./shrink.cjs");
|
|
10
13
|
const require_split = require("./split.cjs");
|
|
11
14
|
//#region src/compile/path/index.ts
|
|
12
|
-
/**
|
|
13
|
-
|
|
15
|
+
/**
|
|
16
|
+
* 目标里的一个代表性节点 id——给 UNRESOLVED_NODE_REFERENCE 诊断用
|
|
17
|
+
* @description 对象 NodeTarget(`{ id, ... }`)直接取 id;between 比例点递归挖端点里第一个节点引用
|
|
18
|
+
* (端点未解析时整 between 失败,需照样报 unresolved 而非静默);其余形态返回 undefined。
|
|
19
|
+
*/
|
|
20
|
+
var nodeRefId = (t) => {
|
|
21
|
+
if (typeof t !== "object" || Array.isArray(t)) return void 0;
|
|
22
|
+
if ("id" in t) return t.id;
|
|
23
|
+
if ("between" in t) return nodeRefId(t.between[0]) ?? nodeRefId(t.between[1]);
|
|
24
|
+
};
|
|
25
|
+
/** 有限数 */
|
|
26
|
+
var isFiniteNum = (n) => typeof n === "number" && Number.isFinite(n);
|
|
27
|
+
/** 有限坐标点 `[number, number]` */
|
|
28
|
+
var isFinitePoint = (pt) => Array.isArray(pt) && pt.length >= 2 && isFiniteNum(pt[0]) && isFiniteNum(pt[1]);
|
|
29
|
+
/**
|
|
30
|
+
* 校验 path generator 产出的单条命令合法(kind 已知 + 引用坐标 / 数值有限)
|
|
31
|
+
* @description 第三方 / LLM 写的 generate 误产坏命令(NaN/Infinity 坐标、未知 kind、缺字段、字符串当命令)时
|
|
32
|
+
* 抛含 generator 名的清晰错——守 Scene 100% finite / JSON 可序列化,不放任非 finite 静默入 Scene
|
|
33
|
+
* (JSON.stringify(NaN/Infinity)=null 会让 round-trip 失真)。
|
|
34
|
+
*/
|
|
35
|
+
var assertValidGeneratedCommand = (name, cmd) => {
|
|
36
|
+
const bad = (detail) => {
|
|
37
|
+
throw new Error(`path generator '${name}' produced a ${detail}.`);
|
|
38
|
+
};
|
|
39
|
+
if (cmd === null || typeof cmd !== "object") {
|
|
40
|
+
bad(`non-object command (expected an object with a 'kind')`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const c = cmd;
|
|
44
|
+
switch (c.kind) {
|
|
45
|
+
case "move":
|
|
46
|
+
case "line":
|
|
47
|
+
if (!isFinitePoint(c.to)) bad(`non-finite coordinate in a '${String(c.kind)}' command`);
|
|
48
|
+
break;
|
|
49
|
+
case "quad":
|
|
50
|
+
if (!isFinitePoint(c.control) || !isFinitePoint(c.to)) bad(`non-finite coordinate in a 'quad' command`);
|
|
51
|
+
break;
|
|
52
|
+
case "cubic":
|
|
53
|
+
if (!isFinitePoint(c.control1) || !isFinitePoint(c.control2) || !isFinitePoint(c.to)) bad(`non-finite coordinate in a 'cubic' command`);
|
|
54
|
+
break;
|
|
55
|
+
case "arc":
|
|
56
|
+
if (!isFinitePoint(c.center) || !isFiniteNum(c.radius) || !isFiniteNum(c.startAngle) || !isFiniteNum(c.endAngle)) bad(`non-finite value in an 'arc' command`);
|
|
57
|
+
break;
|
|
58
|
+
case "ellipseArc":
|
|
59
|
+
if (!isFinitePoint(c.center) || !isFiniteNum(c.radiusX) || !isFiniteNum(c.radiusY) || !isFiniteNum(c.startAngle) || !isFiniteNum(c.endAngle)) bad(`non-finite value in an 'ellipseArc' command`);
|
|
60
|
+
break;
|
|
61
|
+
case "close": break;
|
|
62
|
+
default: bad(`command with unknown kind '${String(c.kind)}'`);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
14
65
|
/**
|
|
15
66
|
* 语义 stroke 档位 → 数值(user units)
|
|
16
67
|
* @description 对齐 TikZ 比例(thin=0.4pt→1=默认 strokeWidth):ultraThin 0.25、veryThin 0.5、thin 1、semithick 1.5、thick 2、veryThick 3、ultraThick 4。显式 strokeWidth 覆盖 thickness。
|
|
@@ -25,6 +76,93 @@ var THICKNESS_TO_WIDTH = {
|
|
|
25
76
|
veryThick: 3,
|
|
26
77
|
ultraThick: 4
|
|
27
78
|
};
|
|
79
|
+
/** 一组点的 axis-aligned 包围盒中心 */
|
|
80
|
+
var bboxCenter = (pts) => {
|
|
81
|
+
let minX = Infinity;
|
|
82
|
+
let minY = Infinity;
|
|
83
|
+
let maxX = -Infinity;
|
|
84
|
+
let maxY = -Infinity;
|
|
85
|
+
for (const [x, y] of pts) {
|
|
86
|
+
if (x < minX) minX = x;
|
|
87
|
+
if (y < minY) minY = y;
|
|
88
|
+
if (x > maxX) maxX = x;
|
|
89
|
+
if (y > maxY) maxY = y;
|
|
90
|
+
}
|
|
91
|
+
return [(minX + maxX) / 2, (minY + maxY) / 2];
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* path 整体 rotate / scale → 绕包围盒中心的 GroupPrim transforms
|
|
95
|
+
* @description rotate 写成 `{ kind:'rotate', degrees, cx, cy }`(cx/cy = bbox center),等价包一个绕同中心旋转的 Scope;
|
|
96
|
+
* scale number → `{ kind:'scale', x }`(等比,y 省略),`{x,y}` → `{ kind:'scale', x, y }`。
|
|
97
|
+
* 缩放支点同为 bbox center:用 translate(center) ∘ scale ∘ translate(-center) 三段表达。两者都缺时返回空数组。
|
|
98
|
+
* 数组顺序与 GroupPrim 渲染一致(array[0] 最外层、最后 apply):先 rotate 段再 scale 段(rotate 在外)。
|
|
99
|
+
*/
|
|
100
|
+
var buildPathTransforms = (rotate, scale, center, round) => {
|
|
101
|
+
const out = [];
|
|
102
|
+
if (rotate !== void 0) out.push({
|
|
103
|
+
kind: "rotate",
|
|
104
|
+
degrees: rotate,
|
|
105
|
+
cx: round(center[0]),
|
|
106
|
+
cy: round(center[1])
|
|
107
|
+
});
|
|
108
|
+
if (scale !== void 0) {
|
|
109
|
+
const sx = typeof scale === "number" ? scale : scale.x;
|
|
110
|
+
const sy = typeof scale === "number" ? void 0 : scale.y;
|
|
111
|
+
const scaleT = {
|
|
112
|
+
kind: "scale",
|
|
113
|
+
x: sx
|
|
114
|
+
};
|
|
115
|
+
if (sy !== void 0) scaleT.y = sy;
|
|
116
|
+
out.push({
|
|
117
|
+
kind: "translate",
|
|
118
|
+
x: round(center[0]),
|
|
119
|
+
y: round(center[1])
|
|
120
|
+
}, scaleT, {
|
|
121
|
+
kind: "translate",
|
|
122
|
+
x: round(-center[0]),
|
|
123
|
+
y: round(-center[1])
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* 把已物化的 arrow marker(局部 baseSize 坐标系,尖端 +x)按路径切线定向放到采样点
|
|
130
|
+
* @description marker 局部系:viewBox `0 0 baseSize baseSize`,参考点 (refX, baseSize/2),尖端朝 +x。
|
|
131
|
+
* GroupPrim transforms 数组语义 array[0] 最外层(最后 apply),故链 = translate(point) ∘ rotate(tangentDeg)
|
|
132
|
+
* ∘ scale(markerWidth/baseSize, markerHeight/baseSize) ∘ translate(-refX, -baseSize/2):先把参考点移到原点、
|
|
133
|
+
* 缩放到目标尺寸、绕切线角旋转、平移到采样点。marker 几何(`MarkerPrimitive[]`)是 ScenePrimitive 的结构子集,直接作 children。
|
|
134
|
+
*/
|
|
135
|
+
var buildMarkMarkerGroup = (spec, sample, round) => {
|
|
136
|
+
const angleDeg = Math.atan2(sample.tangent[1], sample.tangent[0]) * 180 / Math.PI;
|
|
137
|
+
const sx = spec.markerWidth / spec.baseSize;
|
|
138
|
+
const sy = spec.markerHeight / spec.baseSize;
|
|
139
|
+
const refY = spec.baseSize / 2;
|
|
140
|
+
return {
|
|
141
|
+
type: "group",
|
|
142
|
+
transforms: [
|
|
143
|
+
{
|
|
144
|
+
kind: "translate",
|
|
145
|
+
x: round(sample.point[0]),
|
|
146
|
+
y: round(sample.point[1])
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
kind: "rotate",
|
|
150
|
+
degrees: round(angleDeg)
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
kind: "scale",
|
|
154
|
+
x: round(sx),
|
|
155
|
+
y: round(sy)
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
kind: "translate",
|
|
159
|
+
x: round(-spec.refX),
|
|
160
|
+
y: round(-refY)
|
|
161
|
+
}
|
|
162
|
+
],
|
|
163
|
+
children: [...spec.marker]
|
|
164
|
+
};
|
|
165
|
+
};
|
|
28
166
|
/**
|
|
29
167
|
* IR Path → PathPrim
|
|
30
168
|
* @description 每个绘制段独立用节点中心算两端 boundary clip——中段节点的入/出 boundary 点通常不同,path 在该节点可见"断开"(与 TikZ `\draw (A)--(B)--(C);` 段独立 clip 一致)。仍产一个 PathPrim:commands 用多组 move/line 表达 sub-path;段起点等于上段终点时复用 cursor 省 move。cycle 段闭回最近 move 起点,起点==lastEnd && 终点==subPathStart 时输出 close,否则显式画段 line。引用未定义节点/解析失败返回 null,并通过 `warnHook.onWarn` 同步触发 warning
|
|
@@ -47,15 +185,22 @@ var emitPathPrimitive = (path, nameStack, round, measureText = require_text_metr
|
|
|
47
185
|
}
|
|
48
186
|
/** 每段 step.label 翻译出的 TextPrim(或 sloped 旋转的 group),与 path 主体同级返回 */
|
|
49
187
|
const labelPrims = [];
|
|
50
|
-
/**
|
|
188
|
+
/**
|
|
189
|
+
* 每个绘制段的几何采样器(按声明序);中段 marking 用——把整条 path 的 pos∈[0,1] 分摊到 N 段
|
|
190
|
+
* @description 与 step label 同款便宜模型:N 段等分 pos 区间,pos 落在第 ⌊pos·N⌋ 段、段内参数 = 余数;
|
|
191
|
+
* 段内 t 的几何含义随段类型(line/step 弧长、curve/cubic/bend Bezier 参数、arc 角度),由各 `*SegmentSample` 决定。
|
|
192
|
+
*/
|
|
193
|
+
const segmentSamplers = [];
|
|
194
|
+
/** 算 sample 后 emitLabelPrimitive,结果累积到 labelPrims/points;同时登记本段采样器供 marks 用 */
|
|
51
195
|
const collectLabel = (step, sampleAt) => {
|
|
196
|
+
segmentSamplers.push(sampleAt);
|
|
52
197
|
if (step.kind === "move" || step.kind === "cycle" || !("label" in step) || !step.label) return;
|
|
53
198
|
const sample = sampleAt(require_label.tForLabelPosition(step.label.position));
|
|
54
199
|
const r = require_label.emitLabelPrimitive(step.label, sample, measureText, round, path.opacity);
|
|
55
200
|
labelPrims.push(r.primitive);
|
|
56
201
|
for (const p of r.points) points.push(p);
|
|
57
202
|
};
|
|
58
|
-
const hasTo = (s) => s.kind !== "cycle" && s.kind !== "arc" && s.kind !== "circlePath" && s.kind !== "ellipsePath" && s.kind !== "rectangle";
|
|
203
|
+
const hasTo = (s) => s.kind !== "cycle" && s.kind !== "arc" && s.kind !== "circlePath" && s.kind !== "ellipsePath" && s.kind !== "rectangle" && s.kind !== "generator";
|
|
59
204
|
const anchors = steps.map((s, idx) => {
|
|
60
205
|
if (!hasTo(s)) return null;
|
|
61
206
|
const ref = require_anchor.refPointOfTarget(s.to, nameStack, scopeChain);
|
|
@@ -91,6 +236,12 @@ var emitPathPrimitive = (path, nameStack, round, measureText = require_text_metr
|
|
|
91
236
|
* @description 设置 penOverride 让下个绘制段直接用此点当 fromClip 后清空。arc=弧终点;circlePath/ellipsePath=center("画完留在圆心")
|
|
92
237
|
*/
|
|
93
238
|
let penOverride = null;
|
|
239
|
+
/**
|
|
240
|
+
* 读当前游标(生成器分支用)
|
|
241
|
+
* @description 经函数边界读 `lastEnd`,让 TS 用其声明类型(`IRPosition | null`)而非按分支位置 narrow
|
|
242
|
+
* 成字面 `null`——generator 分支在源码上位于 lastEnd 各赋值点之前,直接读会被误判恒 null
|
|
243
|
+
*/
|
|
244
|
+
const readCursor = () => lastEnd;
|
|
94
245
|
const roundPoint = (p) => [round(p[0]), round(p[1])];
|
|
95
246
|
const emitMove = (p) => {
|
|
96
247
|
const rp = roundPoint(p);
|
|
@@ -187,6 +338,72 @@ var emitPathPrimitive = (path, nameStack, round, measureText = require_text_metr
|
|
|
187
338
|
}
|
|
188
339
|
const step = steps[i];
|
|
189
340
|
if (step.kind === "move") continue;
|
|
341
|
+
if (step.kind === "generator") {
|
|
342
|
+
const generators = warnHook.effectivePathGenerators ?? {};
|
|
343
|
+
const def = Object.prototype.hasOwnProperty.call(generators, step.name) ? generators[step.name] : void 0;
|
|
344
|
+
if (!def) {
|
|
345
|
+
const available = Object.keys(generators).sort().join(", ") || "(none registered)";
|
|
346
|
+
throw new Error(`Unknown path generator '${step.name}'; available: ${available}`);
|
|
347
|
+
}
|
|
348
|
+
const parsed = def.paramsSchema.parse(step.params);
|
|
349
|
+
require_json.JsonObjectSchema.parse(parsed);
|
|
350
|
+
const paramsObj = parsed;
|
|
351
|
+
const resolvedTargets = {};
|
|
352
|
+
for (const key of def.targetParams ?? []) {
|
|
353
|
+
if (key.includes(".")) continue;
|
|
354
|
+
const raw = paramsObj[key];
|
|
355
|
+
if (raw === void 0) continue;
|
|
356
|
+
if (raw === null || typeof raw !== "string" && typeof raw !== "object") throw new Error(`path generator '${step.name}' targetParams key '${key}' must be a target (node id, coordinate, or target object); got ${raw === null ? "null" : typeof raw}.`);
|
|
357
|
+
const resolved = require_anchor.refPointOfTarget(raw, nameStack, scopeChain);
|
|
358
|
+
if (resolved) resolvedTargets[key] = resolved;
|
|
359
|
+
}
|
|
360
|
+
const prevGen = findPrev();
|
|
361
|
+
const fromGen = readCursor() ?? (prevGen ? prevGen.anchor : [0, 0]);
|
|
362
|
+
const toGen = (step.to !== void 0 ? require_anchor.refPointOfTarget(step.to, nameStack, scopeChain) : null) ?? void 0;
|
|
363
|
+
let produced;
|
|
364
|
+
try {
|
|
365
|
+
produced = def.generate({
|
|
366
|
+
from: fromGen,
|
|
367
|
+
...toGen !== void 0 ? { to: toGen } : {},
|
|
368
|
+
params: paramsObj,
|
|
369
|
+
resolvedTargets,
|
|
370
|
+
round
|
|
371
|
+
});
|
|
372
|
+
} catch (e) {
|
|
373
|
+
throw new Error(`path generator '${step.name}' threw: ${e instanceof Error ? e.message : String(e)}`, { cause: e });
|
|
374
|
+
}
|
|
375
|
+
if (!Array.isArray(produced)) throw new Error(`path generator '${step.name}' must return an array of path commands; got ${produced === null ? "null" : typeof produced}.`);
|
|
376
|
+
for (const cmd of produced) assertValidGeneratedCommand(step.name, cmd);
|
|
377
|
+
const generated = produced;
|
|
378
|
+
startSegment(fromGen);
|
|
379
|
+
for (const cmd of generated) switch (cmd.kind) {
|
|
380
|
+
case "move":
|
|
381
|
+
startSegment(cmd.to);
|
|
382
|
+
break;
|
|
383
|
+
case "line":
|
|
384
|
+
emitLine(cmd.to);
|
|
385
|
+
break;
|
|
386
|
+
case "quad":
|
|
387
|
+
emitQuad(cmd.control, cmd.to);
|
|
388
|
+
break;
|
|
389
|
+
case "cubic":
|
|
390
|
+
emitCubic(cmd.control1, cmd.control2, cmd.to);
|
|
391
|
+
break;
|
|
392
|
+
case "arc":
|
|
393
|
+
emitArc(cmd.center, cmd.radius, cmd.startAngle, cmd.endAngle);
|
|
394
|
+
break;
|
|
395
|
+
case "ellipseArc":
|
|
396
|
+
emitEllipseArc(cmd.center, cmd.radiusX, cmd.radiusY, cmd.startAngle, cmd.endAngle);
|
|
397
|
+
break;
|
|
398
|
+
case "close":
|
|
399
|
+
emitClose();
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
const genEnd = readCursor() ?? fromGen;
|
|
403
|
+
collectLabel(step, (t) => require_segment.lineSegmentSample(fromGen, genEnd, t));
|
|
404
|
+
penOverride = readCursor();
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
190
407
|
if (step.kind === "cycle") {
|
|
191
408
|
const moveTo = lastMoveTo;
|
|
192
409
|
const prev = findPrev();
|
|
@@ -351,8 +568,8 @@ var emitPathPrimitive = (path, nameStack, round, measureText = require_text_metr
|
|
|
351
568
|
continue;
|
|
352
569
|
}
|
|
353
570
|
if (step.kind === "bend") {
|
|
354
|
-
const
|
|
355
|
-
|
|
571
|
+
const [c1, c2] = step.outAngle !== void 0 || step.inAngle !== void 0 ? require_bend.outInControlPoints(prev.anchor, currAnchor, step.outAngle ?? 0, step.inAngle ?? 180, step.looseness) : require_bend.bendControlPoints(prev.anchor, currAnchor, step.bendDirection ?? "left", step.bendAngle ?? 30);
|
|
572
|
+
if (!isFinitePoint(c1) || !isFinitePoint(c2)) throw new Error("Bend produced a non-finite control point (looseness / angle too large); use smaller values.");
|
|
356
573
|
const fromClip = usedOverride ?? require_anchor.clipForTarget(prev.step.to, c1, nameStack, scopeChain);
|
|
357
574
|
const toClip = require_anchor.clipForTarget(step.to, c2, nameStack, scopeChain);
|
|
358
575
|
if (!fromClip || !toClip) return null;
|
|
@@ -383,11 +600,50 @@ var emitPathPrimitive = (path, nameStack, round, measureText = require_text_metr
|
|
|
383
600
|
fillOpacity: path.fillOpacity,
|
|
384
601
|
strokeOpacity: path.drawOpacity
|
|
385
602
|
};
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
const
|
|
603
|
+
const effectiveArrows = warnHook.effectiveArrows ?? require_index.BUILTIN_ARROWS;
|
|
604
|
+
const arrows = require_shrink.endpointArrows(path.arrow, path.arrowDetail, effectiveArrows, round);
|
|
605
|
+
const markPrims = [];
|
|
606
|
+
if (path.marks && path.marks.length > 0 && segmentSamplers.length > 0) {
|
|
607
|
+
const segCount = segmentSamplers.length;
|
|
608
|
+
for (const { pos, mark } of path.marks) {
|
|
609
|
+
const scaled = pos * segCount;
|
|
610
|
+
const segIdx = Math.min(Math.floor(scaled), segCount - 1);
|
|
611
|
+
const localT = scaled - segIdx;
|
|
612
|
+
const sample = segmentSamplers[segIdx](pos === 1 ? 1 : localT);
|
|
613
|
+
const spec = require_shrink.resolveMarkArrowSpec(mark, effectiveArrows, round);
|
|
614
|
+
markPrims.push(buildMarkMarkerGroup(spec, sample, round));
|
|
615
|
+
points.push(sample.point);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
require_shrink.applyArrowShrinks(commands, arrows.shrinkStart, arrows.shrinkEnd, strokeWidth, round);
|
|
619
|
+
const endpointSpecs = {};
|
|
620
|
+
if (arrows.arrowStart) endpointSpecs.arrowStart = arrows.arrowStart;
|
|
621
|
+
if (arrows.arrowEnd) endpointSpecs.arrowEnd = arrows.arrowEnd;
|
|
622
|
+
const { primitive } = require_split.splitSubPathsForEndpointArrows(commands, baseProps, endpointSpecs);
|
|
623
|
+
const bodyPrims = [
|
|
624
|
+
primitive,
|
|
625
|
+
...labelPrims,
|
|
626
|
+
...markPrims
|
|
627
|
+
];
|
|
628
|
+
if ((path.rotate !== void 0 || path.scale !== void 0) && points.length > 0) {
|
|
629
|
+
const center = bboxCenter(points);
|
|
630
|
+
const transforms = buildPathTransforms(path.rotate, path.scale, center, round);
|
|
631
|
+
if (transforms.length > 0) {
|
|
632
|
+
const group = {
|
|
633
|
+
type: "group",
|
|
634
|
+
transforms,
|
|
635
|
+
children: bodyPrims
|
|
636
|
+
};
|
|
637
|
+
const transformedPoints = points.map((p) => require_scope.applyTransformChain(p, transforms));
|
|
638
|
+
if (!transformedPoints.every(isFinitePoint)) throw new Error("Path rotate / scale produced a non-finite coordinate (scale too large); use a smaller scale.");
|
|
639
|
+
return {
|
|
640
|
+
primitives: [group],
|
|
641
|
+
points: transformedPoints
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
}
|
|
389
645
|
return {
|
|
390
|
-
primitives:
|
|
646
|
+
primitives: bodyPrims,
|
|
391
647
|
points
|
|
392
648
|
};
|
|
393
649
|
};
|