@retikz/core 0.1.0 → 0.2.0-alpha.2
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/compile/anchor-cache.d.ts +12 -0
- package/dist/es/compile/anchor-cache.d.ts.map +1 -0
- package/dist/es/compile/anchor-cache.js +41 -0
- package/dist/es/compile/compile.d.ts +2 -2
- package/dist/es/compile/compile.d.ts.map +1 -1
- package/dist/es/compile/compile.js +150 -40
- package/dist/es/compile/index.d.ts +1 -0
- package/dist/es/compile/index.d.ts.map +1 -1
- package/dist/es/compile/name-stack.d.ts +81 -0
- package/dist/es/compile/name-stack.d.ts.map +1 -0
- package/dist/es/compile/name-stack.js +104 -0
- package/dist/es/compile/node.d.ts +9 -5
- package/dist/es/compile/node.d.ts.map +1 -1
- package/dist/es/compile/node.js +19 -11
- package/dist/es/compile/path/anchor.d.ts +11 -5
- package/dist/es/compile/path/anchor.d.ts.map +1 -1
- package/dist/es/compile/path/anchor.js +24 -13
- package/dist/es/compile/path/index.d.ts +9 -3
- package/dist/es/compile/path/index.d.ts.map +1 -1
- package/dist/es/compile/path/index.js +18 -17
- package/dist/es/compile/path/label.d.ts +1 -1
- package/dist/es/compile/path/label.d.ts.map +1 -1
- package/dist/es/compile/path/label.js +17 -4
- package/dist/es/compile/path/relative.d.ts +10 -4
- package/dist/es/compile/path/relative.d.ts.map +1 -1
- package/dist/es/compile/path/relative.js +16 -8
- package/dist/es/compile/position.d.ts +19 -3
- package/dist/es/compile/position.d.ts.map +1 -1
- package/dist/es/compile/position.js +28 -8
- package/dist/es/compile/scope.d.ts +66 -0
- package/dist/es/compile/scope.d.ts.map +1 -0
- package/dist/es/compile/scope.js +256 -0
- package/dist/es/compile/style.d.ts +46 -0
- package/dist/es/compile/style.d.ts.map +1 -0
- package/dist/es/compile/style.js +259 -0
- package/dist/es/index.d.ts +2 -2
- package/dist/es/index.d.ts.map +1 -1
- package/dist/es/index.js +3 -1
- package/dist/es/ir/index.d.ts +2 -0
- package/dist/es/ir/index.d.ts.map +1 -1
- package/dist/es/ir/node.d.ts +5 -2
- package/dist/es/ir/node.d.ts.map +1 -1
- package/dist/es/ir/node.js +1 -0
- package/dist/es/ir/path/path.d.ts +531 -0
- package/dist/es/ir/path/path.d.ts.map +1 -1
- package/dist/es/ir/path/path.js +1 -0
- package/dist/es/ir/path/step.d.ts +834 -0
- package/dist/es/ir/path/step.d.ts.map +1 -1
- package/dist/es/ir/path/step.js +5 -1
- package/dist/es/ir/scene.d.ts +18 -3542
- package/dist/es/ir/scene.d.ts.map +1 -1
- package/dist/es/ir/scene.js +11 -3
- package/dist/es/ir/scope.d.ts +3690 -0
- package/dist/es/ir/scope.d.ts.map +1 -0
- package/dist/es/ir/scope.js +89 -0
- package/dist/es/ir/transform.d.ts +204 -0
- package/dist/es/ir/transform.d.ts.map +1 -0
- package/dist/es/ir/transform.js +56 -0
- package/dist/lib/compile/anchor-cache.cjs +41 -0
- package/dist/lib/compile/anchor-cache.d.ts +12 -0
- package/dist/lib/compile/anchor-cache.d.ts.map +1 -0
- package/dist/lib/compile/compile.cjs +150 -40
- package/dist/lib/compile/compile.d.ts +2 -2
- package/dist/lib/compile/compile.d.ts.map +1 -1
- package/dist/lib/compile/index.d.ts +1 -0
- package/dist/lib/compile/index.d.ts.map +1 -1
- package/dist/lib/compile/name-stack.cjs +104 -0
- package/dist/lib/compile/name-stack.d.ts +81 -0
- package/dist/lib/compile/name-stack.d.ts.map +1 -0
- package/dist/lib/compile/node.cjs +19 -11
- package/dist/lib/compile/node.d.ts +9 -5
- package/dist/lib/compile/node.d.ts.map +1 -1
- package/dist/lib/compile/path/anchor.cjs +23 -12
- package/dist/lib/compile/path/anchor.d.ts +11 -5
- package/dist/lib/compile/path/anchor.d.ts.map +1 -1
- package/dist/lib/compile/path/index.cjs +18 -17
- package/dist/lib/compile/path/index.d.ts +9 -3
- package/dist/lib/compile/path/index.d.ts.map +1 -1
- package/dist/lib/compile/path/label.cjs +17 -4
- package/dist/lib/compile/path/label.d.ts +1 -1
- package/dist/lib/compile/path/label.d.ts.map +1 -1
- package/dist/lib/compile/path/relative.cjs +16 -8
- package/dist/lib/compile/path/relative.d.ts +10 -4
- package/dist/lib/compile/path/relative.d.ts.map +1 -1
- package/dist/lib/compile/position.cjs +28 -8
- package/dist/lib/compile/position.d.ts +19 -3
- package/dist/lib/compile/position.d.ts.map +1 -1
- package/dist/lib/compile/scope.cjs +261 -0
- package/dist/lib/compile/scope.d.ts +66 -0
- package/dist/lib/compile/scope.d.ts.map +1 -0
- package/dist/lib/compile/style.cjs +262 -0
- package/dist/lib/compile/style.d.ts +46 -0
- package/dist/lib/compile/style.d.ts.map +1 -0
- package/dist/lib/index.cjs +8 -0
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/index.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/node.cjs +1 -0
- package/dist/lib/ir/node.d.ts +5 -2
- package/dist/lib/ir/node.d.ts.map +1 -1
- package/dist/lib/ir/path/path.cjs +1 -0
- package/dist/lib/ir/path/path.d.ts +531 -0
- package/dist/lib/ir/path/path.d.ts.map +1 -1
- package/dist/lib/ir/path/step.cjs +5 -1
- package/dist/lib/ir/path/step.d.ts +834 -0
- package/dist/lib/ir/path/step.d.ts.map +1 -1
- package/dist/lib/ir/scene.cjs +11 -3
- package/dist/lib/ir/scene.d.ts +18 -3542
- package/dist/lib/ir/scene.d.ts.map +1 -1
- package/dist/lib/ir/scope.cjs +94 -0
- package/dist/lib/ir/scope.d.ts +3690 -0
- package/dist/lib/ir/scope.d.ts.map +1 -0
- package/dist/lib/ir/transform.cjs +56 -0
- package/dist/lib/ir/transform.d.ts +204 -0
- package/dist/lib/ir/transform.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -1,44 +1,55 @@
|
|
|
1
|
+
const require_scope = require("../scope.cjs");
|
|
1
2
|
const require_position = require("../position.cjs");
|
|
2
3
|
const require_node = require("../node.cjs");
|
|
4
|
+
const require_anchor_cache = require("../anchor-cache.cjs");
|
|
3
5
|
const require_parseTarget = require("../parseTarget.cjs");
|
|
4
6
|
//#region src/compile/path/anchor.ts
|
|
5
7
|
/**
|
|
6
8
|
* 求 step.to 的参考点(给 boundary clip 算方向 / 折角 corner 用)
|
|
7
|
-
* @description 三态:`'A'`(auto) 节点中心;`'A.<anchor>'`/`'A.<deg>'` 显式锚点 refPoint=endpoint
|
|
9
|
+
* @description 三态:`'A'`(auto) 节点中心;`'A.<anchor>'`/`'A.<deg>'` 显式锚点 refPoint=endpoint 位置不随邻居变。直接坐标/极坐标解析为笛卡尔。
|
|
10
|
+
* string id lookup 拿到的 layout 已是全局坐标——不走 scopeChain 投影;Position / Polar /
|
|
11
|
+
* At / Offset 字面量经 `resolvePosition(..., scopeChain)` 拿到当前 scope 局部坐标后
|
|
12
|
+
* `applyTransformChain` 投回全局。`scopeChain=[]` 等价 v0.1(恒等)。
|
|
8
13
|
*/
|
|
9
|
-
var refPointOfTarget = (target,
|
|
14
|
+
var refPointOfTarget = (target, nameStack, scopeChain = []) => {
|
|
10
15
|
if (typeof target === "string") {
|
|
11
16
|
const ref = require_parseTarget.parseNodeRef(target);
|
|
12
|
-
const node =
|
|
17
|
+
const node = nameStack.lookup(ref.id);
|
|
13
18
|
if (!node) return null;
|
|
14
19
|
switch (ref.kind) {
|
|
15
20
|
case "node": return [node.rect.x, node.rect.y];
|
|
16
|
-
case "anchor": return
|
|
17
|
-
case "angle": return
|
|
21
|
+
case "anchor": return require_anchor_cache.resolveAnchor(node, ref.anchor);
|
|
22
|
+
case "angle": return require_anchor_cache.resolveAnchor(node, String(ref.angle));
|
|
18
23
|
}
|
|
19
24
|
}
|
|
20
25
|
if (typeof target === "object" && !Array.isArray(target) && ("relative" in target || "relativeAccumulate" in target)) return null;
|
|
21
|
-
|
|
26
|
+
const local = require_position.resolvePosition(target, nameStack, void 0, scopeChain);
|
|
27
|
+
if (!local) return null;
|
|
28
|
+
return scopeChain.length === 0 ? local : require_scope.applyTransformChain(local, scopeChain);
|
|
22
29
|
};
|
|
23
30
|
/** 折角中间点:`-|` → (curr.x, prev.y);`|-` → (prev.x, curr.y) */
|
|
24
31
|
var cornerOf = (prev, curr, via) => via === "-|" ? [curr[0], prev[1]] : [prev[0], curr[1]];
|
|
25
32
|
/**
|
|
26
33
|
* 在 toward 方向算 step.to 的实际绘制端点
|
|
27
|
-
* @description 节点 auto `'A'`:按 shape 走 boundaryPointOf 求中心→toward 射线交点;命名 anchor/角度:位置已定不受 toward 影响;直接坐标/极坐标:解析后返回;失败返回 null
|
|
34
|
+
* @description 节点 auto `'A'`:按 shape 走 boundaryPointOf 求中心→toward 射线交点;命名 anchor/角度:位置已定不受 toward 影响;直接坐标/极坐标:解析后返回;失败返回 null。
|
|
35
|
+
* string id lookup 拿到的 layout 已是全局坐标;Position / Polar / At / Offset 字面量经
|
|
36
|
+
* `resolvePosition(..., scopeChain)` 拿到当前 scope 局部坐标后 `applyTransformChain` 投回全局。
|
|
28
37
|
*/
|
|
29
|
-
var clipForTarget = (target, toward,
|
|
38
|
+
var clipForTarget = (target, toward, nameStack, scopeChain = []) => {
|
|
30
39
|
if (typeof target === "string") {
|
|
31
40
|
const ref = require_parseTarget.parseNodeRef(target);
|
|
32
|
-
const node =
|
|
41
|
+
const node = nameStack.lookup(ref.id);
|
|
33
42
|
if (!node) return null;
|
|
34
43
|
switch (ref.kind) {
|
|
35
44
|
case "node": return require_node.boundaryPointOf(node, toward);
|
|
36
|
-
case "anchor": return
|
|
37
|
-
case "angle": return
|
|
45
|
+
case "anchor": return require_anchor_cache.resolveAnchor(node, ref.anchor);
|
|
46
|
+
case "angle": return require_anchor_cache.resolveAnchor(node, String(ref.angle));
|
|
38
47
|
}
|
|
39
48
|
}
|
|
40
49
|
if (typeof target === "object" && !Array.isArray(target) && ("relative" in target || "relativeAccumulate" in target)) return null;
|
|
41
|
-
|
|
50
|
+
const local = require_position.resolvePosition(target, nameStack, void 0, scopeChain);
|
|
51
|
+
if (!local) return null;
|
|
52
|
+
return scopeChain.length === 0 ? local : require_scope.applyTransformChain(local, scopeChain);
|
|
42
53
|
};
|
|
43
54
|
/** 两个 IRPosition 两分量精确相等(未 round) */
|
|
44
55
|
var samePoint = (a, b) => !!a && !!b && a[0] === b[0] && a[1] === b[1];
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import { IRPosition, IRTarget } from '../../ir';
|
|
2
|
-
import {
|
|
2
|
+
import { Transform } from '../../primitive';
|
|
3
|
+
import { NameStack } from '../name-stack';
|
|
3
4
|
/**
|
|
4
5
|
* 求 step.to 的参考点(给 boundary clip 算方向 / 折角 corner 用)
|
|
5
|
-
* @description 三态:`'A'`(auto) 节点中心;`'A.<anchor>'`/`'A.<deg>'` 显式锚点 refPoint=endpoint
|
|
6
|
+
* @description 三态:`'A'`(auto) 节点中心;`'A.<anchor>'`/`'A.<deg>'` 显式锚点 refPoint=endpoint 位置不随邻居变。直接坐标/极坐标解析为笛卡尔。
|
|
7
|
+
* string id lookup 拿到的 layout 已是全局坐标——不走 scopeChain 投影;Position / Polar /
|
|
8
|
+
* At / Offset 字面量经 `resolvePosition(..., scopeChain)` 拿到当前 scope 局部坐标后
|
|
9
|
+
* `applyTransformChain` 投回全局。`scopeChain=[]` 等价 v0.1(恒等)。
|
|
6
10
|
*/
|
|
7
|
-
export declare const refPointOfTarget: (target: IRTarget,
|
|
11
|
+
export declare const refPointOfTarget: (target: IRTarget, nameStack: NameStack, scopeChain?: ReadonlyArray<Transform>) => IRPosition | null;
|
|
8
12
|
/** 折角中间点:`-|` → (curr.x, prev.y);`|-` → (prev.x, curr.y) */
|
|
9
13
|
export declare const cornerOf: (prev: IRPosition, curr: IRPosition, via: "-|" | "|-") => IRPosition;
|
|
10
14
|
/**
|
|
11
15
|
* 在 toward 方向算 step.to 的实际绘制端点
|
|
12
|
-
* @description 节点 auto `'A'`:按 shape 走 boundaryPointOf 求中心→toward 射线交点;命名 anchor/角度:位置已定不受 toward 影响;直接坐标/极坐标:解析后返回;失败返回 null
|
|
16
|
+
* @description 节点 auto `'A'`:按 shape 走 boundaryPointOf 求中心→toward 射线交点;命名 anchor/角度:位置已定不受 toward 影响;直接坐标/极坐标:解析后返回;失败返回 null。
|
|
17
|
+
* string id lookup 拿到的 layout 已是全局坐标;Position / Polar / At / Offset 字面量经
|
|
18
|
+
* `resolvePosition(..., scopeChain)` 拿到当前 scope 局部坐标后 `applyTransformChain` 投回全局。
|
|
13
19
|
*/
|
|
14
|
-
export declare const clipForTarget: (target: IRTarget, toward: IRPosition,
|
|
20
|
+
export declare const clipForTarget: (target: IRTarget, toward: IRPosition, nameStack: NameStack, scopeChain?: ReadonlyArray<Transform>) => IRPosition | null;
|
|
15
21
|
/** 两个 IRPosition 两分量精确相等(未 round) */
|
|
16
22
|
export declare const samePoint: (a: IRPosition | null, b: IRPosition | null) => boolean;
|
|
17
23
|
/** 把 p 朝 target 方向移动 dist */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/anchor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/anchor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAM/C;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,QAAQ,EAChB,WAAW,SAAS,EACpB,aAAY,aAAa,CAAC,SAAS,CAAM,KACxC,UAAU,GAAG,IAqBf,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,IAqBf,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"}
|
|
@@ -26,7 +26,7 @@ var THICKNESS_TO_WIDTH = {
|
|
|
26
26
|
* IR Path → PathPrim
|
|
27
27
|
* @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
|
|
28
28
|
*/
|
|
29
|
-
var emitPathPrimitive = (path,
|
|
29
|
+
var emitPathPrimitive = (path, nameStack, round, measureText = require_text_metrics.fallbackMeasurer, warnHook = {}) => {
|
|
30
30
|
const irPath = warnHook.irPath ?? "path";
|
|
31
31
|
const warn = (code, message, subPath = "") => {
|
|
32
32
|
warnHook.onWarn?.({
|
|
@@ -35,7 +35,8 @@ var emitPathPrimitive = (path, nodeIndex, round, measureText = require_text_metr
|
|
|
35
35
|
path: subPath ? `${irPath}.${subPath}` : irPath
|
|
36
36
|
});
|
|
37
37
|
};
|
|
38
|
-
const
|
|
38
|
+
const scopeChain = warnHook.scopeChain ?? [];
|
|
39
|
+
const steps = require_relative.normalizeRelativeTargets(path.children, nameStack, scopeChain);
|
|
39
40
|
if (steps.length < 2) {
|
|
40
41
|
warn("PATH_TOO_SHORT", `Path requires at least 2 steps (got ${steps.length}); the entire path is skipped`, "children");
|
|
41
42
|
return null;
|
|
@@ -46,14 +47,14 @@ var emitPathPrimitive = (path, nodeIndex, round, measureText = require_text_metr
|
|
|
46
47
|
const collectLabel = (step, sampleAt) => {
|
|
47
48
|
if (step.kind === "move" || step.kind === "cycle" || !("label" in step) || !step.label) return;
|
|
48
49
|
const sample = sampleAt(require_label.tForLabelPosition(step.label.position));
|
|
49
|
-
const r = require_label.emitLabelPrimitive(step.label, sample, measureText, round);
|
|
50
|
+
const r = require_label.emitLabelPrimitive(step.label, sample, measureText, round, path.opacity);
|
|
50
51
|
labelPrims.push(r.primitive);
|
|
51
52
|
for (const p of r.points) points.push(p);
|
|
52
53
|
};
|
|
53
54
|
const hasTo = (s) => s.kind !== "cycle" && s.kind !== "arc" && s.kind !== "circlePath" && s.kind !== "ellipsePath";
|
|
54
55
|
const anchors = steps.map((s, idx) => {
|
|
55
56
|
if (!hasTo(s)) return null;
|
|
56
|
-
const ref = require_anchor.refPointOfTarget(s.to,
|
|
57
|
+
const ref = require_anchor.refPointOfTarget(s.to, nameStack, scopeChain);
|
|
57
58
|
if (!ref && typeof s.to === "string") warn("UNRESOLVED_NODE_REFERENCE", `Step.to references undefined node id '${s.to}'; the entire path is skipped`, `children[${idx}].to`);
|
|
58
59
|
return ref;
|
|
59
60
|
});
|
|
@@ -179,10 +180,10 @@ var emitPathPrimitive = (path, nodeIndex, round, measureText = require_text_metr
|
|
|
179
180
|
const moveTo = lastMoveTo;
|
|
180
181
|
const prev = findPrev();
|
|
181
182
|
if (!moveTo || !prev) continue;
|
|
182
|
-
const moveAnchor = require_anchor.refPointOfTarget(moveTo,
|
|
183
|
+
const moveAnchor = require_anchor.refPointOfTarget(moveTo, nameStack, scopeChain);
|
|
183
184
|
if (!moveAnchor) return null;
|
|
184
|
-
const fromClip = require_anchor.clipForTarget(prev.step.to, moveAnchor,
|
|
185
|
-
const toClip = require_anchor.clipForTarget(moveTo, prev.anchor,
|
|
185
|
+
const fromClip = require_anchor.clipForTarget(prev.step.to, moveAnchor, nameStack, scopeChain);
|
|
186
|
+
const toClip = require_anchor.clipForTarget(moveTo, prev.anchor, nameStack, scopeChain);
|
|
186
187
|
if (!fromClip || !toClip) return null;
|
|
187
188
|
if (require_anchor.samePoint(fromClip, lastEnd) && require_anchor.samePoint(toClip, subPathStart)) {
|
|
188
189
|
emitClose();
|
|
@@ -237,8 +238,8 @@ var emitPathPrimitive = (path, nodeIndex, round, measureText = require_text_metr
|
|
|
237
238
|
const usedOverride = penOverride;
|
|
238
239
|
penOverride = null;
|
|
239
240
|
if (step.kind === "line") {
|
|
240
|
-
const fromClip = usedOverride ?? require_anchor.clipForTarget(prev.step.to, currAnchor,
|
|
241
|
-
const toClip = require_anchor.clipForTarget(step.to, prev.anchor,
|
|
241
|
+
const fromClip = usedOverride ?? require_anchor.clipForTarget(prev.step.to, currAnchor, nameStack, scopeChain);
|
|
242
|
+
const toClip = require_anchor.clipForTarget(step.to, prev.anchor, nameStack, scopeChain);
|
|
242
243
|
if (!fromClip || !toClip) return null;
|
|
243
244
|
startSegment(fromClip);
|
|
244
245
|
emitLine(toClip);
|
|
@@ -246,8 +247,8 @@ var emitPathPrimitive = (path, nodeIndex, round, measureText = require_text_metr
|
|
|
246
247
|
continue;
|
|
247
248
|
}
|
|
248
249
|
if (step.kind === "curve") {
|
|
249
|
-
const fromClip = usedOverride ?? require_anchor.clipForTarget(prev.step.to, step.control,
|
|
250
|
-
const toClip = require_anchor.clipForTarget(step.to, step.control,
|
|
250
|
+
const fromClip = usedOverride ?? require_anchor.clipForTarget(prev.step.to, step.control, nameStack, scopeChain);
|
|
251
|
+
const toClip = require_anchor.clipForTarget(step.to, step.control, nameStack, scopeChain);
|
|
251
252
|
if (!fromClip || !toClip) return null;
|
|
252
253
|
startSegment(fromClip);
|
|
253
254
|
emitQuad(step.control, toClip);
|
|
@@ -255,8 +256,8 @@ var emitPathPrimitive = (path, nodeIndex, round, measureText = require_text_metr
|
|
|
255
256
|
continue;
|
|
256
257
|
}
|
|
257
258
|
if (step.kind === "cubic") {
|
|
258
|
-
const fromClip = usedOverride ?? require_anchor.clipForTarget(prev.step.to, step.control1,
|
|
259
|
-
const toClip = require_anchor.clipForTarget(step.to, step.control2,
|
|
259
|
+
const fromClip = usedOverride ?? require_anchor.clipForTarget(prev.step.to, step.control1, nameStack, scopeChain);
|
|
260
|
+
const toClip = require_anchor.clipForTarget(step.to, step.control2, nameStack, scopeChain);
|
|
260
261
|
if (!fromClip || !toClip) return null;
|
|
261
262
|
startSegment(fromClip);
|
|
262
263
|
emitCubic(step.control1, step.control2, toClip);
|
|
@@ -266,8 +267,8 @@ var emitPathPrimitive = (path, nodeIndex, round, measureText = require_text_metr
|
|
|
266
267
|
if (step.kind === "bend") {
|
|
267
268
|
const angle = step.bendAngle ?? 30;
|
|
268
269
|
const [c1, c2] = require_bend.bendControlPoints(prev.anchor, currAnchor, step.bendDirection, angle);
|
|
269
|
-
const fromClip = usedOverride ?? require_anchor.clipForTarget(prev.step.to, c1,
|
|
270
|
-
const toClip = require_anchor.clipForTarget(step.to, c2,
|
|
270
|
+
const fromClip = usedOverride ?? require_anchor.clipForTarget(prev.step.to, c1, nameStack, scopeChain);
|
|
271
|
+
const toClip = require_anchor.clipForTarget(step.to, c2, nameStack, scopeChain);
|
|
271
272
|
if (!fromClip || !toClip) return null;
|
|
272
273
|
startSegment(fromClip);
|
|
273
274
|
emitCubic(c1, c2, toClip);
|
|
@@ -275,8 +276,8 @@ var emitPathPrimitive = (path, nodeIndex, round, measureText = require_text_metr
|
|
|
275
276
|
continue;
|
|
276
277
|
}
|
|
277
278
|
const corner = require_anchor.cornerOf(prev.anchor, currAnchor, step.via);
|
|
278
|
-
const fromClip = usedOverride ?? require_anchor.clipForTarget(prev.step.to, corner,
|
|
279
|
-
const toClip = require_anchor.clipForTarget(step.to, corner,
|
|
279
|
+
const fromClip = usedOverride ?? require_anchor.clipForTarget(prev.step.to, corner, nameStack, scopeChain);
|
|
280
|
+
const toClip = require_anchor.clipForTarget(step.to, corner, nameStack, scopeChain);
|
|
280
281
|
if (!fromClip || !toClip) return null;
|
|
281
282
|
startSegment(fromClip);
|
|
282
283
|
emitLine(corner);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IRPath, IRPosition } from '../../ir';
|
|
2
|
-
import { ScenePrimitive } from '../../primitive';
|
|
3
|
-
import {
|
|
2
|
+
import { ScenePrimitive, Transform } from '../../primitive';
|
|
3
|
+
import { NameStack } from '../name-stack';
|
|
4
4
|
import { TextMeasurer } from '../text-metrics';
|
|
5
5
|
/** emitPathPrimitive 可选 warn 钩子 */
|
|
6
6
|
export type EmitPathWarnHook = {
|
|
@@ -12,12 +12,18 @@ export type EmitPathWarnHook = {
|
|
|
12
12
|
}) => void;
|
|
13
13
|
/** 当前 path 在 IR 中的 locator 前缀(如 `'children[3].path'`) */
|
|
14
14
|
irPath?: string;
|
|
15
|
+
/**
|
|
16
|
+
* 该 path 所属 scope 的累积 Cartesian-only transform 链
|
|
17
|
+
* @description step.to 内的 polar/at/offset 字面量按"当前 scope 局部度量 + 末端 apply chain"
|
|
18
|
+
* 投影回全局;顶层 path / 无 scope chain 时为 `[]`(恒等,等价 v0.1 行为)
|
|
19
|
+
*/
|
|
20
|
+
scopeChain?: ReadonlyArray<Transform>;
|
|
15
21
|
};
|
|
16
22
|
/**
|
|
17
23
|
* IR Path → PathPrim
|
|
18
24
|
* @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
|
|
19
25
|
*/
|
|
20
|
-
export declare const emitPathPrimitive: (path: IRPath,
|
|
26
|
+
export declare const emitPathPrimitive: (path: IRPath, nameStack: NameStack, round: (n: number) => number, measureText?: TextMeasurer, warnHook?: EmitPathWarnHook) => {
|
|
21
27
|
primitives: Array<ScenePrimitive>;
|
|
22
28
|
points: Array<IRPosition>;
|
|
23
29
|
} | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/index.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EAGX,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAEV,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/index.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EAGX,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAEV,cAAc,EACd,SAAS,EACV,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,iBAAiB,CAAC;AA8BtE,mCAAmC;AACnC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,iCAAiC;IACjC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,KAAK,IAAI,CAAC;IACX,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;CACvC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,WAAW,SAAS,EACpB,OAAO,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAC5B,cAAa,YAA+B,EAC5C,WAAU,gBAAqB,KAC9B;IAAE,UAAU,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;CAAE,GAAG,IA2XrE,CAAC"}
|
|
@@ -27,13 +27,22 @@ var tForLabelPosition = (pos) => {
|
|
|
27
27
|
* step.label + 段采样 → TextPrim(sloped 时裹一层 group 旋转)
|
|
28
28
|
* @description 默认 side='above'/position='midway':above/below 锚点 y±offset、align=middle、baseline=bottom/top;left/right x±offset、align=end/start、baseline=middle;sloped 不偏移裹 group rotate(angle, cx, cy) 由切线 atan2 算(SVG y-down CW 正)。返回 primitive + layout 外接点
|
|
29
29
|
*/
|
|
30
|
-
var emitLabelPrimitive = (label, sample, measureText, round) => {
|
|
31
|
-
const fontSize = LABEL_FONT_SIZE;
|
|
30
|
+
var emitLabelPrimitive = (label, sample, measureText, round, hostOpacity) => {
|
|
31
|
+
const fontSize = label.font?.size ?? LABEL_FONT_SIZE;
|
|
32
|
+
const fontFamily = label.font?.family;
|
|
33
|
+
const fontWeight = label.font?.weight;
|
|
34
|
+
const fontStyle = label.font?.style;
|
|
32
35
|
const lineHeight = fontSize * LABEL_LINE_HEIGHT_FACTOR;
|
|
33
|
-
const m = measureText(label.text, {
|
|
36
|
+
const m = measureText(label.text, {
|
|
37
|
+
size: fontSize,
|
|
38
|
+
family: fontFamily,
|
|
39
|
+
weight: fontWeight,
|
|
40
|
+
style: fontStyle
|
|
41
|
+
});
|
|
34
42
|
const measuredWidth = m.width;
|
|
35
43
|
const measuredHeight = m.height || lineHeight;
|
|
36
44
|
const side = label.side ?? "above";
|
|
45
|
+
const labelOpacity = label.opacity !== void 0 ? hostOpacity !== void 0 ? label.opacity * hostOpacity : label.opacity : hostOpacity;
|
|
37
46
|
let x = sample.point[0];
|
|
38
47
|
let y = sample.point[1];
|
|
39
48
|
let align = "middle";
|
|
@@ -62,8 +71,12 @@ var emitLabelPrimitive = (label, sample, measureText, round) => {
|
|
|
62
71
|
lineHeight: round(lineHeight),
|
|
63
72
|
measuredWidth: round(measuredWidth),
|
|
64
73
|
measuredHeight: round(measuredHeight),
|
|
65
|
-
fill: "currentColor"
|
|
74
|
+
fill: label.textColor ?? "currentColor"
|
|
66
75
|
};
|
|
76
|
+
if (fontFamily !== void 0) text.fontFamily = fontFamily;
|
|
77
|
+
if (fontWeight !== void 0) text.fontWeight = fontWeight;
|
|
78
|
+
if (fontStyle !== void 0) text.fontStyle = fontStyle;
|
|
79
|
+
if (labelOpacity !== void 0) text.opacity = labelOpacity;
|
|
67
80
|
if (side === "sloped") {
|
|
68
81
|
const groupPrim = {
|
|
69
82
|
type: "group",
|
|
@@ -11,7 +11,7 @@ export declare const tForLabelPosition: (pos: IRStepLabel["position"]) => number
|
|
|
11
11
|
* step.label + 段采样 → TextPrim(sloped 时裹一层 group 旋转)
|
|
12
12
|
* @description 默认 side='above'/position='midway':above/below 锚点 y±offset、align=middle、baseline=bottom/top;left/right x±offset、align=end/start、baseline=middle;sloped 不偏移裹 group rotate(angle, cx, cy) 由切线 atan2 算(SVG y-down CW 正)。返回 primitive + layout 外接点
|
|
13
13
|
*/
|
|
14
|
-
export declare const emitLabelPrimitive: (label: IRStepLabel, sample: SegmentSample, measureText: TextMeasurer, round: (n: number) => number) => {
|
|
14
|
+
export declare const emitLabelPrimitive: (label: IRStepLabel, sample: SegmentSample, measureText: TextMeasurer, round: (n: number) => number, hostOpacity?: number) => {
|
|
15
15
|
primitive: ScenePrimitive;
|
|
16
16
|
points: Array<IRPosition>;
|
|
17
17
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"label.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/label.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAY,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAmBpD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,KAAK,WAAW,CAAC,UAAU,CAAC,KAAG,MAIhE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,WAAW,EAClB,QAAQ,aAAa,EACrB,aAAa,YAAY,EACzB,OAAO,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,
|
|
1
|
+
{"version":3,"file":"label.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/label.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAY,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAmBpD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,KAAK,WAAW,CAAC,UAAU,CAAC,KAAG,MAIhE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,WAAW,EAClB,QAAQ,aAAa,EACrB,aAAa,YAAY,EACzB,OAAO,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAC5B,cAAc,MAAM,KACnB;IAAE,SAAS,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;CAkGxD,CAAC"}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
const require_scope = require("../scope.cjs");
|
|
1
2
|
const require_arc = require("../../geometry/arc.cjs");
|
|
2
3
|
const require_anchor = require("./anchor.cjs");
|
|
3
4
|
//#region src/compile/path/relative.ts
|
|
4
5
|
/**
|
|
5
|
-
* relative/relativeAccumulate 目标解析为绝对 Position(step kind 不变,to
|
|
6
|
-
* @description relative 不更新 prevEnd(TikZ `+`),relativeAccumulate 更新(TikZ `++`)。prevEnd 推进:有 to 的 kind 用 refPointOfTarget(to);arc 用 arcEndPoint;circlePath/ellipsePath/cycle 不变。首步 relative 时 prevEnd 回退 [0,0];解析失败保持原 step
|
|
6
|
+
* relative/relativeAccumulate 目标解析为绝对 Position(step kind 不变,to 为局部坐标 tuple)
|
|
7
|
+
* @description relative 不更新 prevEnd(TikZ `+`),relativeAccumulate 更新(TikZ `++`)。prevEnd 推进:有 to 的 kind 用 refPointOfTarget(to);arc 用 arcEndPoint;circlePath/ellipsePath/cycle 不变。首步 relative 时 prevEnd 回退 [0,0];解析失败保持原 step。
|
|
8
|
+
* prevEnd 始终是全局坐标系下的 cursor;relative 形态 `[dx, dy]` 在**当前 scope 局部度量**——
|
|
9
|
+
* 先反向投影 prevEnd 到 scope 局部 + 加 (dx, dy) 得局部 tuple,写回 step.to。下游
|
|
10
|
+
* `refPointOfTarget` / `clipForTarget` 把 tuple 视作 scope 局部字面量,统一 `applyTransformChain` 投回全局——
|
|
11
|
+
* relative 分支只负责"折算到局部",不能在此处提前投影到全局,否则与下游 chain apply 形成 double-apply。
|
|
12
|
+
* `scopeChain=[]` 时 inverse 恒等,等价 v0.1 行为。
|
|
7
13
|
*/
|
|
8
|
-
var normalizeRelativeTargets = (steps,
|
|
14
|
+
var normalizeRelativeTargets = (steps, nameStack, scopeChain = []) => {
|
|
9
15
|
let prevEnd = null;
|
|
10
16
|
const out = [];
|
|
11
17
|
for (const step of steps) {
|
|
@@ -26,19 +32,21 @@ var normalizeRelativeTargets = (steps, nodeIndex) => {
|
|
|
26
32
|
let resolvedTo = original;
|
|
27
33
|
let updatePrevEnd = true;
|
|
28
34
|
if (typeof original === "object" && !Array.isArray(original) && "relative" in original) {
|
|
29
|
-
const
|
|
30
|
-
|
|
35
|
+
const refGlobal = prevEnd ?? [0, 0];
|
|
36
|
+
const refLocal = scopeChain.length === 0 ? refGlobal : require_scope.inverseTransformChain(refGlobal, scopeChain);
|
|
37
|
+
resolvedTo = [refLocal[0] + original.relative[0], refLocal[1] + original.relative[1]];
|
|
31
38
|
updatePrevEnd = false;
|
|
32
39
|
} else if (typeof original === "object" && !Array.isArray(original) && "relativeAccumulate" in original) {
|
|
33
|
-
const
|
|
34
|
-
|
|
40
|
+
const refGlobal = prevEnd ?? [0, 0];
|
|
41
|
+
const refLocal = scopeChain.length === 0 ? refGlobal : require_scope.inverseTransformChain(refGlobal, scopeChain);
|
|
42
|
+
resolvedTo = [refLocal[0] + original.relativeAccumulate[0], refLocal[1] + original.relativeAccumulate[1]];
|
|
35
43
|
}
|
|
36
44
|
out.push({
|
|
37
45
|
...step,
|
|
38
46
|
to: resolvedTo
|
|
39
47
|
});
|
|
40
48
|
if (updatePrevEnd) {
|
|
41
|
-
const pos = require_anchor.refPointOfTarget(resolvedTo,
|
|
49
|
+
const pos = require_anchor.refPointOfTarget(resolvedTo, nameStack, scopeChain);
|
|
42
50
|
if (pos) prevEnd = pos;
|
|
43
51
|
}
|
|
44
52
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { IRStep } from '../../ir';
|
|
2
|
-
import {
|
|
2
|
+
import { Transform } from '../../primitive';
|
|
3
|
+
import { NameStack } from '../name-stack';
|
|
3
4
|
/**
|
|
4
|
-
* relative/relativeAccumulate 目标解析为绝对 Position(step kind 不变,to
|
|
5
|
-
* @description relative 不更新 prevEnd(TikZ `+`),relativeAccumulate 更新(TikZ `++`)。prevEnd 推进:有 to 的 kind 用 refPointOfTarget(to);arc 用 arcEndPoint;circlePath/ellipsePath/cycle 不变。首步 relative 时 prevEnd 回退 [0,0];解析失败保持原 step
|
|
5
|
+
* relative/relativeAccumulate 目标解析为绝对 Position(step kind 不变,to 为局部坐标 tuple)
|
|
6
|
+
* @description relative 不更新 prevEnd(TikZ `+`),relativeAccumulate 更新(TikZ `++`)。prevEnd 推进:有 to 的 kind 用 refPointOfTarget(to);arc 用 arcEndPoint;circlePath/ellipsePath/cycle 不变。首步 relative 时 prevEnd 回退 [0,0];解析失败保持原 step。
|
|
7
|
+
* prevEnd 始终是全局坐标系下的 cursor;relative 形态 `[dx, dy]` 在**当前 scope 局部度量**——
|
|
8
|
+
* 先反向投影 prevEnd 到 scope 局部 + 加 (dx, dy) 得局部 tuple,写回 step.to。下游
|
|
9
|
+
* `refPointOfTarget` / `clipForTarget` 把 tuple 视作 scope 局部字面量,统一 `applyTransformChain` 投回全局——
|
|
10
|
+
* relative 分支只负责"折算到局部",不能在此处提前投影到全局,否则与下游 chain apply 形成 double-apply。
|
|
11
|
+
* `scopeChain=[]` 时 inverse 恒等,等价 v0.1 行为。
|
|
6
12
|
*/
|
|
7
|
-
export declare const normalizeRelativeTargets: (steps: ReadonlyArray<IRStep>,
|
|
13
|
+
export declare const normalizeRelativeTargets: (steps: ReadonlyArray<IRStep>, nameStack: NameStack, scopeChain?: ReadonlyArray<Transform>) => Array<IRStep>;
|
|
8
14
|
//# sourceMappingURL=relative.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relative.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/relative.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,MAAM,EAAY,MAAM,UAAU,CAAC;AAC7D,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"relative.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/relative.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,MAAM,EAAY,MAAM,UAAU,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,GACnC,OAAO,aAAa,CAAC,MAAM,CAAC,EAC5B,WAAW,SAAS,EACpB,aAAY,aAAa,CAAC,SAAS,CAAM,KACxC,KAAK,CAAC,MAAM,CAuEd,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const require_scope = require("./scope.cjs");
|
|
1
2
|
//#region src/compile/position.ts
|
|
2
3
|
/** 默认相对定位距离(CompileOptions.nodeDistance 未配时使用) */
|
|
3
4
|
var DEFAULT_NODE_DISTANCE = 1;
|
|
@@ -17,30 +18,49 @@ var DIRECTION_VECTOR = {
|
|
|
17
18
|
};
|
|
18
19
|
/**
|
|
19
20
|
* IR 各种位置形态(笛卡尔/极坐标/相对定位/偏移定位/节点 id)→ 笛卡尔位置
|
|
20
|
-
* @description
|
|
21
|
+
* @description
|
|
22
|
+
* - **返回值语义**:当 `scopeChain` 非空时,返回**当前 scope 局部坐标系**下的笛卡尔位置;
|
|
23
|
+
* 调用方负责走 `applyTransformChain(local, scopeChain)` 投回全局。当 `scopeChain` 为空时
|
|
24
|
+
* 等价于 v0.1 行为(全局坐标)。
|
|
25
|
+
* - **referent 处理**:node id lookup 拿到的 layout.rect 已是全局坐标;本函数内部用
|
|
26
|
+
* `inverseTransformChain` 把全局 referent 反向投影到当前 scope 局部坐标系作为"在当前
|
|
27
|
+
* scope 局部的固定点"基准。relative 部分(polar 的 angle/radius、at 的 direction/distance、
|
|
28
|
+
* offset 的 dx/dy)在当前 scope 局部度量后加到 referent 局部坐标上。
|
|
29
|
+
* - **嵌套**:PolarPosition.origin / OffsetPosition.of 是嵌套 polar 时,递归调用传同样
|
|
30
|
+
* scopeChain——整条嵌套链都在当前 scope 局部度量。
|
|
31
|
+
* - **笛卡尔字面量**:`Position` 形态直接返回(v0.1 行为延续:scope 内笛卡尔字面量在
|
|
32
|
+
* 当前 scope 局部度量;调用方走 applyTransformChain 投全局)。
|
|
33
|
+
* - 极坐标 origin / 偏移定位 of 均可递归引用节点 id 或字面坐标;relative `AtPosition` of
|
|
34
|
+
* 必须引用已定义节点/coordinate;解析失败返回 null。
|
|
35
|
+
* - 节点 id lookup 走 NameStack.lookup 进行 inside-out 搜索(内层 frame 可见外层 frame);
|
|
36
|
+
* nodeDistance 为容器 prop 注入默认距离,AtPosition 自带 distance 优先
|
|
21
37
|
*/
|
|
22
|
-
var resolvePosition = (pos,
|
|
38
|
+
var resolvePosition = (pos, nameStack, nodeDistance = DEFAULT_NODE_DISTANCE, scopeChain = []) => {
|
|
23
39
|
if (typeof pos === "string") {
|
|
24
|
-
const node =
|
|
25
|
-
|
|
40
|
+
const node = nameStack.lookup(pos);
|
|
41
|
+
if (!node) return null;
|
|
42
|
+
const global = [node.rect.x, node.rect.y];
|
|
43
|
+
return scopeChain.length === 0 ? global : require_scope.inverseTransformChain(global, scopeChain);
|
|
26
44
|
}
|
|
27
45
|
if (Array.isArray(pos)) return pos;
|
|
28
46
|
if ("direction" in pos) {
|
|
29
|
-
const ref =
|
|
47
|
+
const ref = nameStack.lookup(pos.of);
|
|
30
48
|
if (!ref) return null;
|
|
49
|
+
const refGlobal = [ref.rect.x, ref.rect.y];
|
|
50
|
+
const refLocal = scopeChain.length === 0 ? refGlobal : require_scope.inverseTransformChain(refGlobal, scopeChain);
|
|
31
51
|
const distance = pos.distance ?? nodeDistance;
|
|
32
52
|
const [dx, dy] = DIRECTION_VECTOR[pos.direction];
|
|
33
|
-
return [
|
|
53
|
+
return [refLocal[0] + dx * distance, refLocal[1] + dy * distance];
|
|
34
54
|
}
|
|
35
55
|
if ("offset" in pos) {
|
|
36
|
-
const base = resolvePosition(pos.of,
|
|
56
|
+
const base = resolvePosition(pos.of, nameStack, nodeDistance, scopeChain);
|
|
37
57
|
if (!base) return null;
|
|
38
58
|
return [base[0] + pos.offset[0], base[1] + pos.offset[1]];
|
|
39
59
|
}
|
|
40
60
|
let origin;
|
|
41
61
|
if (!pos.origin) origin = [0, 0];
|
|
42
62
|
else {
|
|
43
|
-
const resolved = resolvePosition(pos.origin,
|
|
63
|
+
const resolved = resolvePosition(pos.origin, nameStack, nodeDistance, scopeChain);
|
|
44
64
|
if (!resolved) return null;
|
|
45
65
|
origin = resolved;
|
|
46
66
|
}
|
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
import { IRAtPosition, IROffsetPosition, IRPosition, PolarPosition } from '../ir';
|
|
2
|
-
import {
|
|
2
|
+
import { Transform } from '../primitive';
|
|
3
|
+
import { NameStack } from './name-stack';
|
|
3
4
|
/**
|
|
4
5
|
* IR 各种位置形态(笛卡尔/极坐标/相对定位/偏移定位/节点 id)→ 笛卡尔位置
|
|
5
|
-
* @description
|
|
6
|
+
* @description
|
|
7
|
+
* - **返回值语义**:当 `scopeChain` 非空时,返回**当前 scope 局部坐标系**下的笛卡尔位置;
|
|
8
|
+
* 调用方负责走 `applyTransformChain(local, scopeChain)` 投回全局。当 `scopeChain` 为空时
|
|
9
|
+
* 等价于 v0.1 行为(全局坐标)。
|
|
10
|
+
* - **referent 处理**:node id lookup 拿到的 layout.rect 已是全局坐标;本函数内部用
|
|
11
|
+
* `inverseTransformChain` 把全局 referent 反向投影到当前 scope 局部坐标系作为"在当前
|
|
12
|
+
* scope 局部的固定点"基准。relative 部分(polar 的 angle/radius、at 的 direction/distance、
|
|
13
|
+
* offset 的 dx/dy)在当前 scope 局部度量后加到 referent 局部坐标上。
|
|
14
|
+
* - **嵌套**:PolarPosition.origin / OffsetPosition.of 是嵌套 polar 时,递归调用传同样
|
|
15
|
+
* scopeChain——整条嵌套链都在当前 scope 局部度量。
|
|
16
|
+
* - **笛卡尔字面量**:`Position` 形态直接返回(v0.1 行为延续:scope 内笛卡尔字面量在
|
|
17
|
+
* 当前 scope 局部度量;调用方走 applyTransformChain 投全局)。
|
|
18
|
+
* - 极坐标 origin / 偏移定位 of 均可递归引用节点 id 或字面坐标;relative `AtPosition` of
|
|
19
|
+
* 必须引用已定义节点/coordinate;解析失败返回 null。
|
|
20
|
+
* - 节点 id lookup 走 NameStack.lookup 进行 inside-out 搜索(内层 frame 可见外层 frame);
|
|
21
|
+
* nodeDistance 为容器 prop 注入默认距离,AtPosition 自带 distance 优先
|
|
6
22
|
*/
|
|
7
|
-
export declare const resolvePosition: (pos: IRPosition | PolarPosition | IRAtPosition | IROffsetPosition | string,
|
|
23
|
+
export declare const resolvePosition: (pos: IRPosition | PolarPosition | IRAtPosition | IROffsetPosition | string, nameStack: NameStack, nodeDistance?: number, scopeChain?: ReadonlyArray<Transform>) => IRPosition | null;
|
|
8
24
|
//# sourceMappingURL=position.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"position.d.ts","sourceRoot":"","sources":["../../../src/compile/position.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACpG,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"position.d.ts","sourceRoot":"","sources":["../../../src/compile/position.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACpG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAqB9C;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,eAAe,GAC1B,KAAK,UAAU,GAAG,aAAa,GAAG,YAAY,GAAG,gBAAgB,GAAG,MAAM,EAC1E,WAAW,SAAS,EACpB,eAAc,MAA8B,EAC5C,aAAY,aAAa,CAAC,SAAS,CAAM,KACxC,UAAU,GAAG,IAyCf,CAAC"}
|