@retikz/core 0.1.0-alpha.5 → 0.1.0-beta.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/compile.d.ts +20 -3
- package/dist/es/compile/compile.d.ts.map +1 -1
- package/dist/es/compile/compile.js +44 -19
- package/dist/es/compile/index.d.ts +2 -2
- package/dist/es/compile/index.d.ts.map +1 -1
- package/dist/es/compile/layout.d.ts +5 -0
- package/dist/es/compile/layout.d.ts.map +1 -0
- package/dist/es/compile/{view-box.js → layout.js} +4 -4
- package/dist/es/compile/node.d.ts +4 -4
- package/dist/es/compile/node.d.ts.map +1 -1
- package/dist/es/compile/node.js +7 -7
- package/dist/es/compile/path/anchor.d.ts +19 -0
- package/dist/es/compile/path/anchor.d.ts.map +1 -0
- package/dist/es/compile/path/anchor.js +54 -0
- package/dist/es/compile/path/arrow-geometry.d.ts +22 -0
- package/dist/es/compile/path/arrow-geometry.d.ts.map +1 -0
- package/dist/es/compile/path/arrow-geometry.js +40 -0
- package/dist/es/compile/{path.d.ts → path/index.d.ts} +18 -7
- package/dist/es/compile/path/index.d.ts.map +1 -0
- package/dist/es/compile/path/index.js +308 -0
- package/dist/es/compile/path/label.d.ts +18 -0
- package/dist/es/compile/path/label.d.ts.map +1 -0
- package/dist/es/compile/path/label.js +102 -0
- package/dist/es/compile/path/relative.d.ts +8 -0
- package/dist/es/compile/path/relative.d.ts.map +1 -0
- package/dist/es/compile/path/relative.js +48 -0
- package/dist/es/compile/path/shrink.d.ts +18 -0
- package/dist/es/compile/path/shrink.d.ts.map +1 -0
- package/dist/es/compile/path/shrink.js +126 -0
- package/dist/es/compile/path/split.d.ts +15 -0
- package/dist/es/compile/path/split.d.ts.map +1 -0
- package/dist/es/compile/path/split.js +46 -0
- package/dist/es/compile/text-metrics.d.ts +4 -1
- package/dist/es/compile/text-metrics.d.ts.map +1 -1
- package/dist/es/compile/text-metrics.js +11 -5
- package/dist/es/geometry/_transform.d.ts +21 -0
- package/dist/es/geometry/_transform.d.ts.map +1 -0
- package/dist/es/geometry/_transform.js +27 -0
- package/dist/es/geometry/bend.d.ts +1 -1
- package/dist/es/geometry/bend.js +1 -1
- package/dist/es/geometry/circle.d.ts +2 -3
- package/dist/es/geometry/circle.d.ts.map +1 -1
- package/dist/es/geometry/circle.js +1 -16
- package/dist/es/geometry/diamond.d.ts +2 -3
- package/dist/es/geometry/diamond.d.ts.map +1 -1
- package/dist/es/geometry/diamond.js +1 -16
- package/dist/es/geometry/ellipse.d.ts +2 -3
- package/dist/es/geometry/ellipse.d.ts.map +1 -1
- package/dist/es/geometry/ellipse.js +1 -16
- package/dist/es/geometry/polar.d.ts +2 -2
- package/dist/es/geometry/polar.d.ts.map +1 -1
- package/dist/es/geometry/polar.js +2 -6
- package/dist/es/geometry/rect.d.ts.map +1 -1
- package/dist/es/geometry/rect.js +1 -18
- package/dist/es/geometry/segment.d.ts +5 -1
- package/dist/es/geometry/segment.d.ts.map +1 -1
- package/dist/es/index.d.ts +11 -7
- package/dist/es/index.d.ts.map +1 -1
- package/dist/es/index.js +5 -2
- package/dist/es/ir/coordinate.d.ts +1 -1
- package/dist/es/ir/coordinate.js +1 -1
- package/dist/es/ir/font.d.ts +21 -0
- package/dist/es/ir/font.d.ts.map +1 -0
- package/dist/es/ir/font.js +15 -0
- 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 +32 -143
- package/dist/es/ir/node.d.ts.map +1 -1
- package/dist/es/ir/node.js +7 -31
- package/dist/es/ir/path/arrow.d.ts +14 -14
- 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 +19 -19
- package/dist/es/ir/path/path.d.ts.map +1 -1
- package/dist/es/ir/path/path.js +4 -4
- package/dist/es/ir/path/step.d.ts +1 -1
- package/dist/es/ir/path/step.d.ts.map +1 -1
- package/dist/es/ir/path/step.js +8 -8
- package/dist/es/ir/position/at-position.js +1 -1
- package/dist/es/ir/position/offset-position.js +1 -1
- package/dist/es/ir/position/polar-position.d.ts.map +1 -1
- package/dist/es/ir/position/polar-position.js +2 -2
- package/dist/es/ir/position/position.d.ts.map +1 -1
- package/dist/es/ir/position/position.js +1 -1
- package/dist/es/ir/scene.d.ts +128 -128
- package/dist/es/ir/text.d.ts +96 -0
- package/dist/es/ir/text.d.ts.map +1 -0
- package/dist/es/ir/text.js +20 -0
- package/dist/es/parsers/parseTargetSugar.d.ts +4 -0
- package/dist/es/parsers/parseTargetSugar.d.ts.map +1 -1
- package/dist/es/parsers/parseTargetSugar.js +3 -2
- package/dist/es/primitive/ellipse.d.ts +3 -3
- package/dist/es/primitive/ellipse.d.ts.map +1 -1
- package/dist/es/primitive/group.d.ts +23 -7
- package/dist/es/primitive/group.d.ts.map +1 -1
- package/dist/es/primitive/index.d.ts +1 -1
- package/dist/es/primitive/index.d.ts.map +1 -1
- package/dist/es/primitive/layout.d.ts +12 -0
- package/dist/es/primitive/layout.d.ts.map +1 -0
- package/dist/es/primitive/path.d.ts +55 -15
- package/dist/es/primitive/path.d.ts.map +1 -1
- package/dist/es/primitive/rect.d.ts +3 -3
- package/dist/es/primitive/rect.d.ts.map +1 -1
- package/dist/es/primitive/scene.d.ts +4 -4
- package/dist/es/primitive/scene.d.ts.map +1 -1
- package/dist/es/primitive/text.d.ts +10 -3
- package/dist/es/primitive/text.d.ts.map +1 -1
- package/dist/es/types.d.ts +8 -0
- package/dist/es/types.d.ts.map +1 -1
- package/dist/lib/compile/compile.cjs +44 -19
- package/dist/lib/compile/compile.d.ts +20 -3
- package/dist/lib/compile/compile.d.ts.map +1 -1
- package/dist/lib/compile/index.d.ts +2 -2
- package/dist/lib/compile/index.d.ts.map +1 -1
- package/dist/lib/compile/{view-box.cjs → layout.cjs} +4 -4
- package/dist/lib/compile/layout.d.ts +5 -0
- package/dist/lib/compile/layout.d.ts.map +1 -0
- package/dist/lib/compile/node.cjs +7 -7
- package/dist/lib/compile/node.d.ts +4 -4
- package/dist/lib/compile/node.d.ts.map +1 -1
- package/dist/lib/compile/path/anchor.cjs +58 -0
- package/dist/lib/compile/path/anchor.d.ts +19 -0
- package/dist/lib/compile/path/anchor.d.ts.map +1 -0
- package/dist/lib/compile/path/arrow-geometry.cjs +41 -0
- package/dist/lib/compile/path/arrow-geometry.d.ts +22 -0
- package/dist/lib/compile/path/arrow-geometry.d.ts.map +1 -0
- package/dist/lib/compile/path/index.cjs +308 -0
- package/dist/lib/compile/{path.d.ts → path/index.d.ts} +18 -7
- package/dist/lib/compile/path/index.d.ts.map +1 -0
- package/dist/lib/compile/path/label.cjs +103 -0
- package/dist/lib/compile/path/label.d.ts +18 -0
- package/dist/lib/compile/path/label.d.ts.map +1 -0
- package/dist/lib/compile/path/relative.cjs +48 -0
- package/dist/lib/compile/path/relative.d.ts +8 -0
- package/dist/lib/compile/path/relative.d.ts.map +1 -0
- package/dist/lib/compile/path/shrink.cjs +128 -0
- package/dist/lib/compile/path/shrink.d.ts +18 -0
- package/dist/lib/compile/path/shrink.d.ts.map +1 -0
- package/dist/lib/compile/path/split.cjs +46 -0
- package/dist/lib/compile/path/split.d.ts +15 -0
- package/dist/lib/compile/path/split.d.ts.map +1 -0
- package/dist/lib/compile/text-metrics.cjs +11 -5
- package/dist/lib/compile/text-metrics.d.ts +4 -1
- package/dist/lib/compile/text-metrics.d.ts.map +1 -1
- package/dist/lib/geometry/_transform.cjs +28 -0
- package/dist/lib/geometry/_transform.d.ts +21 -0
- package/dist/lib/geometry/_transform.d.ts.map +1 -0
- package/dist/lib/geometry/bend.cjs +1 -1
- package/dist/lib/geometry/bend.d.ts +1 -1
- package/dist/lib/geometry/circle.cjs +5 -20
- package/dist/lib/geometry/circle.d.ts +2 -3
- package/dist/lib/geometry/circle.d.ts.map +1 -1
- package/dist/lib/geometry/diamond.cjs +5 -20
- package/dist/lib/geometry/diamond.d.ts +2 -3
- package/dist/lib/geometry/diamond.d.ts.map +1 -1
- package/dist/lib/geometry/ellipse.cjs +5 -20
- package/dist/lib/geometry/ellipse.d.ts +2 -3
- package/dist/lib/geometry/ellipse.d.ts.map +1 -1
- package/dist/lib/geometry/polar.cjs +2 -6
- package/dist/lib/geometry/polar.d.ts +2 -2
- package/dist/lib/geometry/polar.d.ts.map +1 -1
- package/dist/lib/geometry/rect.cjs +5 -22
- package/dist/lib/geometry/rect.d.ts.map +1 -1
- package/dist/lib/geometry/segment.d.ts +5 -1
- package/dist/lib/geometry/segment.d.ts.map +1 -1
- package/dist/lib/index.cjs +7 -3
- package/dist/lib/index.d.ts +11 -7
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/ir/coordinate.cjs +1 -1
- package/dist/lib/ir/coordinate.d.ts +1 -1
- package/dist/lib/ir/font.cjs +15 -0
- package/dist/lib/ir/font.d.ts +21 -0
- package/dist/lib/ir/font.d.ts.map +1 -0
- 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 +8 -35
- package/dist/lib/ir/node.d.ts +32 -143
- package/dist/lib/ir/node.d.ts.map +1 -1
- package/dist/lib/ir/path/arrow.cjs +5 -5
- package/dist/lib/ir/path/arrow.d.ts +14 -14
- package/dist/lib/ir/path/arrow.d.ts.map +1 -1
- package/dist/lib/ir/path/path.cjs +4 -4
- package/dist/lib/ir/path/path.d.ts +19 -19
- package/dist/lib/ir/path/path.d.ts.map +1 -1
- package/dist/lib/ir/path/step.cjs +8 -8
- package/dist/lib/ir/path/step.d.ts +1 -1
- package/dist/lib/ir/path/step.d.ts.map +1 -1
- package/dist/lib/ir/position/at-position.cjs +1 -1
- package/dist/lib/ir/position/offset-position.cjs +1 -1
- package/dist/lib/ir/position/polar-position.cjs +2 -2
- package/dist/lib/ir/position/polar-position.d.ts.map +1 -1
- package/dist/lib/ir/position/position.cjs +1 -1
- package/dist/lib/ir/position/position.d.ts.map +1 -1
- package/dist/lib/ir/scene.d.ts +128 -128
- package/dist/lib/ir/text.cjs +21 -0
- package/dist/lib/ir/text.d.ts +96 -0
- package/dist/lib/ir/text.d.ts.map +1 -0
- package/dist/lib/parsers/parseTargetSugar.cjs +3 -2
- package/dist/lib/parsers/parseTargetSugar.d.ts +4 -0
- package/dist/lib/parsers/parseTargetSugar.d.ts.map +1 -1
- package/dist/lib/primitive/ellipse.d.ts +3 -3
- package/dist/lib/primitive/ellipse.d.ts.map +1 -1
- package/dist/lib/primitive/group.d.ts +23 -7
- package/dist/lib/primitive/group.d.ts.map +1 -1
- package/dist/lib/primitive/index.d.ts +1 -1
- package/dist/lib/primitive/index.d.ts.map +1 -1
- package/dist/lib/primitive/layout.d.ts +12 -0
- package/dist/lib/primitive/layout.d.ts.map +1 -0
- package/dist/lib/primitive/path.d.ts +55 -15
- package/dist/lib/primitive/path.d.ts.map +1 -1
- package/dist/lib/primitive/rect.d.ts +3 -3
- package/dist/lib/primitive/rect.d.ts.map +1 -1
- package/dist/lib/primitive/scene.d.ts +4 -4
- package/dist/lib/primitive/scene.d.ts.map +1 -1
- package/dist/lib/primitive/text.d.ts +10 -3
- package/dist/lib/primitive/text.d.ts.map +1 -1
- package/dist/lib/types.d.ts +8 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/package.json +12 -4
- package/dist/es/compile/path.d.ts.map +0 -1
- package/dist/es/compile/path.js +0 -636
- package/dist/es/compile/view-box.d.ts +0 -5
- package/dist/es/compile/view-box.d.ts.map +0 -1
- package/dist/es/primitive/view-box.d.ts +0 -12
- package/dist/es/primitive/view-box.d.ts.map +0 -1
- package/dist/lib/compile/path.cjs +0 -636
- package/dist/lib/compile/path.d.ts.map +0 -1
- package/dist/lib/compile/view-box.d.ts +0 -5
- package/dist/lib/compile/view-box.d.ts.map +0 -1
- package/dist/lib/primitive/view-box.d.ts +0 -12
- package/dist/lib/primitive/view-box.d.ts.map +0 -1
|
@@ -1,13 +1,24 @@
|
|
|
1
|
-
import { IRPath, IRPosition } from '
|
|
2
|
-
import { ScenePrimitive } from '
|
|
3
|
-
import { NodeLayout } from '
|
|
4
|
-
import { TextMeasurer } from '
|
|
1
|
+
import { IRPath, IRPosition } from '../../ir';
|
|
2
|
+
import { ScenePrimitive } from '../../primitive';
|
|
3
|
+
import { NodeLayout } from '../node';
|
|
4
|
+
import { TextMeasurer } from '../text-metrics';
|
|
5
|
+
/** emitPathPrimitive 可选 warn 钩子 */
|
|
6
|
+
export type EmitPathWarnHook = {
|
|
7
|
+
/** 警告收集器(由 compileToScene 传入) */
|
|
8
|
+
onWarn?: (warning: {
|
|
9
|
+
code: string;
|
|
10
|
+
message: string;
|
|
11
|
+
path: string;
|
|
12
|
+
}) => void;
|
|
13
|
+
/** 当前 path 在 IR 中的 locator 前缀(如 `'children[3].path'`) */
|
|
14
|
+
irPath?: string;
|
|
15
|
+
};
|
|
5
16
|
/**
|
|
6
17
|
* IR Path → PathPrim
|
|
7
|
-
* @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
|
|
18
|
+
* @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
|
|
8
19
|
*/
|
|
9
|
-
export declare const emitPathPrimitive: (path: IRPath, nodeIndex: Map<string, NodeLayout>, round: (n: number) => number, measureText?: TextMeasurer) => {
|
|
20
|
+
export declare const emitPathPrimitive: (path: IRPath, nodeIndex: Map<string, NodeLayout>, round: (n: number) => number, measureText?: TextMeasurer, warnHook?: EmitPathWarnHook) => {
|
|
10
21
|
primitives: Array<ScenePrimitive>;
|
|
11
22
|
points: Array<IRPosition>;
|
|
12
23
|
} | null;
|
|
13
|
-
//# sourceMappingURL=
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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,EACf,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,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;CACjB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,WAAW,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EAClC,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,IA0XrE,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
//#region src/compile/path/label.ts
|
|
2
|
+
/** 边标注默认字号 / 偏移量 */
|
|
3
|
+
var LABEL_FONT_SIZE = 14;
|
|
4
|
+
var LABEL_LINE_HEIGHT_FACTOR = 1.2;
|
|
5
|
+
var LABEL_SIDE_OFFSET = 4;
|
|
6
|
+
var RAD_TO_DEG = 180 / Math.PI;
|
|
7
|
+
/** keyword → t 数值映射;含旧 3 keyword(midway/near-start/near-end)+ 新 4 keyword */
|
|
8
|
+
var KEYWORD_TO_T = {
|
|
9
|
+
"at-start": 0,
|
|
10
|
+
"very-near-start": .125,
|
|
11
|
+
"near-start": .25,
|
|
12
|
+
midway: .5,
|
|
13
|
+
"near-end": .75,
|
|
14
|
+
"very-near-end": .875,
|
|
15
|
+
"at-end": 1
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* label.position → 段参数 t∈[0,1]
|
|
19
|
+
* @description 数值原样返回(schema 已 clamp 0..1);keyword 走 KEYWORD_TO_T 映射;undefined 退默认 midway (0.5)
|
|
20
|
+
*/
|
|
21
|
+
var tForLabelPosition = (pos) => {
|
|
22
|
+
if (typeof pos === "number") return pos;
|
|
23
|
+
if (typeof pos === "string" && pos in KEYWORD_TO_T) return KEYWORD_TO_T[pos];
|
|
24
|
+
return .5;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* step.label + 段采样 → TextPrim(sloped 时裹一层 group 旋转)
|
|
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
|
+
*/
|
|
30
|
+
var emitLabelPrimitive = (label, sample, measureText, round) => {
|
|
31
|
+
const fontSize = LABEL_FONT_SIZE;
|
|
32
|
+
const lineHeight = fontSize * LABEL_LINE_HEIGHT_FACTOR;
|
|
33
|
+
const m = measureText(label.text, { size: fontSize });
|
|
34
|
+
const measuredWidth = m.width;
|
|
35
|
+
const measuredHeight = m.height || lineHeight;
|
|
36
|
+
const side = label.side ?? "above";
|
|
37
|
+
let x = sample.point[0];
|
|
38
|
+
let y = sample.point[1];
|
|
39
|
+
let align = "middle";
|
|
40
|
+
let baseline = "middle";
|
|
41
|
+
if (side === "above") {
|
|
42
|
+
y -= LABEL_SIDE_OFFSET;
|
|
43
|
+
baseline = "bottom";
|
|
44
|
+
} else if (side === "below") {
|
|
45
|
+
y += LABEL_SIDE_OFFSET;
|
|
46
|
+
baseline = "top";
|
|
47
|
+
} else if (side === "left") {
|
|
48
|
+
x -= LABEL_SIDE_OFFSET;
|
|
49
|
+
align = "end";
|
|
50
|
+
} else if (side === "right") {
|
|
51
|
+
x += LABEL_SIDE_OFFSET;
|
|
52
|
+
align = "start";
|
|
53
|
+
} else baseline = "bottom";
|
|
54
|
+
const text = {
|
|
55
|
+
type: "text",
|
|
56
|
+
x: round(x),
|
|
57
|
+
y: round(y),
|
|
58
|
+
lines: [{ text: label.text }],
|
|
59
|
+
fontSize,
|
|
60
|
+
align,
|
|
61
|
+
baseline,
|
|
62
|
+
lineHeight: round(lineHeight),
|
|
63
|
+
measuredWidth: round(measuredWidth),
|
|
64
|
+
measuredHeight: round(measuredHeight),
|
|
65
|
+
fill: "currentColor"
|
|
66
|
+
};
|
|
67
|
+
if (side === "sloped") {
|
|
68
|
+
const groupPrim = {
|
|
69
|
+
type: "group",
|
|
70
|
+
transforms: [{
|
|
71
|
+
kind: "rotate",
|
|
72
|
+
degrees: round(Math.atan2(sample.tangent[1], sample.tangent[0]) * RAD_TO_DEG),
|
|
73
|
+
cx: round(x),
|
|
74
|
+
cy: round(y)
|
|
75
|
+
}],
|
|
76
|
+
children: [text]
|
|
77
|
+
};
|
|
78
|
+
const r = Math.max(measuredWidth / 2, measuredHeight / 2);
|
|
79
|
+
return {
|
|
80
|
+
primitive: groupPrim,
|
|
81
|
+
points: [
|
|
82
|
+
[x - r, y - r],
|
|
83
|
+
[x + r, y - r],
|
|
84
|
+
[x - r, y + r],
|
|
85
|
+
[x + r, y + r]
|
|
86
|
+
]
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const halfW = measuredWidth / 2;
|
|
90
|
+
const halfH = measuredHeight / 2;
|
|
91
|
+
return {
|
|
92
|
+
primitive: text,
|
|
93
|
+
points: [
|
|
94
|
+
[x - halfW, y - halfH],
|
|
95
|
+
[x + halfW, y - halfH],
|
|
96
|
+
[x - halfW, y + halfH],
|
|
97
|
+
[x + halfW, y + halfH]
|
|
98
|
+
]
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
//#endregion
|
|
102
|
+
exports.emitLabelPrimitive = emitLabelPrimitive;
|
|
103
|
+
exports.tForLabelPosition = tForLabelPosition;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SegmentSample } from '../../geometry/segment';
|
|
2
|
+
import { IRPosition, IRStepLabel } from '../../ir';
|
|
3
|
+
import { ScenePrimitive } from '../../primitive';
|
|
4
|
+
import { TextMeasurer } from '../text-metrics';
|
|
5
|
+
/**
|
|
6
|
+
* label.position → 段参数 t∈[0,1]
|
|
7
|
+
* @description 数值原样返回(schema 已 clamp 0..1);keyword 走 KEYWORD_TO_T 映射;undefined 退默认 midway (0.5)
|
|
8
|
+
*/
|
|
9
|
+
export declare const tForLabelPosition: (pos: IRStepLabel["position"]) => number;
|
|
10
|
+
/**
|
|
11
|
+
* step.label + 段采样 → TextPrim(sloped 时裹一层 group 旋转)
|
|
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
|
+
*/
|
|
14
|
+
export declare const emitLabelPrimitive: (label: IRStepLabel, sample: SegmentSample, measureText: TextMeasurer, round: (n: number) => number) => {
|
|
15
|
+
primitive: ScenePrimitive;
|
|
16
|
+
points: Array<IRPosition>;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=label.d.ts.map
|
|
@@ -0,0 +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,KAC3B;IAAE,SAAS,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;CA8ExD,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const require_arc = require("../../geometry/arc.cjs");
|
|
2
|
+
const require_anchor = require("./anchor.cjs");
|
|
3
|
+
//#region src/compile/path/relative.ts
|
|
4
|
+
/**
|
|
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
|
|
7
|
+
*/
|
|
8
|
+
var normalizeRelativeTargets = (steps, nodeIndex) => {
|
|
9
|
+
let prevEnd = null;
|
|
10
|
+
const out = [];
|
|
11
|
+
for (const step of steps) {
|
|
12
|
+
if (step.kind === "cycle") {
|
|
13
|
+
out.push(step);
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (step.kind === "circlePath" || step.kind === "ellipsePath") {
|
|
17
|
+
out.push(step);
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (step.kind === "arc") {
|
|
21
|
+
out.push(step);
|
|
22
|
+
if (prevEnd) prevEnd = require_arc.arcEndPoint(prevEnd, step.radius, step.endAngle);
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const original = step.to;
|
|
26
|
+
let resolvedTo = original;
|
|
27
|
+
let updatePrevEnd = true;
|
|
28
|
+
if (typeof original === "object" && !Array.isArray(original) && "relative" in original) {
|
|
29
|
+
const ref = prevEnd ?? [0, 0];
|
|
30
|
+
resolvedTo = [ref[0] + original.relative[0], ref[1] + original.relative[1]];
|
|
31
|
+
updatePrevEnd = false;
|
|
32
|
+
} else if (typeof original === "object" && !Array.isArray(original) && "relativeAccumulate" in original) {
|
|
33
|
+
const ref = prevEnd ?? [0, 0];
|
|
34
|
+
resolvedTo = [ref[0] + original.relativeAccumulate[0], ref[1] + original.relativeAccumulate[1]];
|
|
35
|
+
}
|
|
36
|
+
out.push({
|
|
37
|
+
...step,
|
|
38
|
+
to: resolvedTo
|
|
39
|
+
});
|
|
40
|
+
if (updatePrevEnd) {
|
|
41
|
+
const pos = require_anchor.refPointOfTarget(resolvedTo, nodeIndex);
|
|
42
|
+
if (pos) prevEnd = pos;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
};
|
|
47
|
+
//#endregion
|
|
48
|
+
exports.normalizeRelativeTargets = normalizeRelativeTargets;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IRStep } from '../../ir';
|
|
2
|
+
import { NodeLayout } from '../node';
|
|
3
|
+
/**
|
|
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
|
|
6
|
+
*/
|
|
7
|
+
export declare const normalizeRelativeTargets: (steps: ReadonlyArray<IRStep>, nodeIndex: Map<string, NodeLayout>) => Array<IRStep>;
|
|
8
|
+
//# sourceMappingURL=relative.d.ts.map
|
|
@@ -0,0 +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,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GACnC,OAAO,aAAa,CAAC,MAAM,CAAC,EAC5B,WAAW,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,KACjC,KAAK,CAAC,MAAM,CA0Dd,CAAC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
const require_anchor = require("./anchor.cjs");
|
|
2
|
+
const require_arrow_geometry = require("./arrow-geometry.cjs");
|
|
3
|
+
//#region src/compile/path/shrink.ts
|
|
4
|
+
/**
|
|
5
|
+
* 端点级 spec:顶层默认 ⊕ end-side override(逐字段 merge)
|
|
6
|
+
* @description 缺省字段继承顶层(不是"完全替换");空心 shape 上 fill 字段被丢(silent no-op)
|
|
7
|
+
*/
|
|
8
|
+
var resolveArrowEndSpec = (topLevel, endSide) => {
|
|
9
|
+
const baseShape = endSide?.shape ?? topLevel.shape ?? "normal";
|
|
10
|
+
const out = { shape: baseShape };
|
|
11
|
+
const scale = endSide?.scale ?? topLevel.scale;
|
|
12
|
+
if (scale !== void 0) out.scale = scale;
|
|
13
|
+
const length = endSide?.length ?? topLevel.length;
|
|
14
|
+
if (length !== void 0) out.length = length;
|
|
15
|
+
const width = endSide?.width ?? topLevel.width;
|
|
16
|
+
if (width !== void 0) out.width = width;
|
|
17
|
+
const color = endSide?.color ?? topLevel.color;
|
|
18
|
+
if (color !== void 0) out.color = color;
|
|
19
|
+
const opacity = endSide?.opacity ?? topLevel.opacity;
|
|
20
|
+
if (opacity !== void 0) out.opacity = opacity;
|
|
21
|
+
const lineWidth = endSide?.lineWidth ?? topLevel.lineWidth;
|
|
22
|
+
if (lineWidth !== void 0) out.lineWidth = lineWidth;
|
|
23
|
+
if (!require_arrow_geometry.isHollowArrowShape(baseShape)) {
|
|
24
|
+
const fill = endSide?.fill ?? topLevel.fill;
|
|
25
|
+
if (fill !== void 0) out.fill = fill;
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
};
|
|
29
|
+
/** IR path-level `arrow` + `arrowDetail` → PathPrim 起末端点箭头规格 */
|
|
30
|
+
var endpointArrows = (arrow, detail) => {
|
|
31
|
+
if (!arrow || arrow === "none") return {};
|
|
32
|
+
const top = detail ?? {};
|
|
33
|
+
const startSpec = resolveArrowEndSpec(top, top.start);
|
|
34
|
+
const endSpec = resolveArrowEndSpec(top, top.end);
|
|
35
|
+
switch (arrow) {
|
|
36
|
+
case "->": return { arrowEnd: endSpec };
|
|
37
|
+
case "<-": return { arrowStart: startSpec };
|
|
38
|
+
case "<->": return {
|
|
39
|
+
arrowStart: startSpec,
|
|
40
|
+
arrowEnd: endSpec
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* 端点级 shrink(strokeWidth 倍):line 末端朝起点缩这么多,让箭头尖端落回原 target
|
|
46
|
+
* @description 不分实心 / 空心:路径端点接在箭头尾部或凹口,箭头尖端仍贴原 target。低 opacity 下不会再透出 line。
|
|
47
|
+
*/
|
|
48
|
+
var computeShrink = (spec) => {
|
|
49
|
+
const geometry = require_arrow_geometry.resolveArrowShapeGeometry(spec);
|
|
50
|
+
const length = (spec.length ?? geometry.defaultLength) * (spec.scale ?? 1);
|
|
51
|
+
return (geometry.tipX - geometry.lineContactX) * length / geometry.baseSize;
|
|
52
|
+
};
|
|
53
|
+
/** 取一个 PathCommand 末端 endpoint(move/line/quad/cubic → to;arc/ellipseArc → polar(end);close 无端点) */
|
|
54
|
+
var endpointOf = (cmd) => {
|
|
55
|
+
switch (cmd.kind) {
|
|
56
|
+
case "move":
|
|
57
|
+
case "line":
|
|
58
|
+
case "quad":
|
|
59
|
+
case "cubic": return [cmd.to[0], cmd.to[1]];
|
|
60
|
+
case "arc": {
|
|
61
|
+
const rad = cmd.endAngle * Math.PI / 180;
|
|
62
|
+
return [cmd.center[0] + Math.cos(rad) * cmd.radius, cmd.center[1] + Math.sin(rad) * cmd.radius];
|
|
63
|
+
}
|
|
64
|
+
case "ellipseArc": {
|
|
65
|
+
const rad = cmd.endAngle * Math.PI / 180;
|
|
66
|
+
return [cmd.center[0] + Math.cos(rad) * cmd.radiusX, cmd.center[1] + Math.sin(rad) * cmd.radiusY];
|
|
67
|
+
}
|
|
68
|
+
case "close": return null;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
/** 改写一个 PathCommand 的 endpoint(用于 shrink) */
|
|
72
|
+
var setEndpoint = (commands, idx, newPt, round) => {
|
|
73
|
+
const cmd = commands[idx];
|
|
74
|
+
if (cmd.kind === "close") return;
|
|
75
|
+
const rp = [round(newPt[0]), round(newPt[1])];
|
|
76
|
+
if (cmd.kind === "move" || cmd.kind === "line") commands[idx] = {
|
|
77
|
+
...cmd,
|
|
78
|
+
to: rp
|
|
79
|
+
};
|
|
80
|
+
else if (cmd.kind === "quad") commands[idx] = {
|
|
81
|
+
...cmd,
|
|
82
|
+
to: rp
|
|
83
|
+
};
|
|
84
|
+
else if (cmd.kind === "cubic") commands[idx] = {
|
|
85
|
+
...cmd,
|
|
86
|
+
to: rp
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* 按 shape + spec(length / scale / lineWidth)把首/末段端点向内缩短
|
|
91
|
+
* @description 让 line 端点接在 hollow arrow 尾部外缘、不贯穿 back outline;shrink=0 的实心 shape 跳过。in-place 改写 commands 数组
|
|
92
|
+
*/
|
|
93
|
+
var applyArrowShrinks = (commands, shrinkStart, shrinkEnd, strokeWidth, round) => {
|
|
94
|
+
if (shrinkStart > 0) {
|
|
95
|
+
const firstIdx = commands.findIndex((o) => o.kind === "move");
|
|
96
|
+
if (firstIdx >= 0) {
|
|
97
|
+
const cur = commands[firstIdx];
|
|
98
|
+
const nextIdx = commands.findIndex((o, idx) => idx > firstIdx && o.kind !== "close");
|
|
99
|
+
if (cur.kind === "move" && nextIdx >= 0) {
|
|
100
|
+
const nextPt = endpointOf(commands[nextIdx]);
|
|
101
|
+
if (nextPt) setEndpoint(commands, firstIdx, require_anchor.shiftToward([cur.to[0], cur.to[1]], nextPt, shrinkStart * strokeWidth), round);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (shrinkEnd > 0) {
|
|
106
|
+
let lastIdx = -1;
|
|
107
|
+
for (let i = commands.length - 1; i >= 0; i--) if (commands[i].kind !== "close") {
|
|
108
|
+
lastIdx = i;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
if (lastIdx > 0) {
|
|
112
|
+
let prevIdx = lastIdx - 1;
|
|
113
|
+
while (prevIdx >= 0 && commands[prevIdx].kind === "close") prevIdx--;
|
|
114
|
+
if (prevIdx >= 0) {
|
|
115
|
+
const curPt = endpointOf(commands[lastIdx]);
|
|
116
|
+
const prevPt = endpointOf(commands[prevIdx]);
|
|
117
|
+
if (curPt && prevPt) {
|
|
118
|
+
const shifted = require_anchor.shiftToward(curPt, prevPt, shrinkEnd * strokeWidth);
|
|
119
|
+
setEndpoint(commands, lastIdx, shifted, round);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
//#endregion
|
|
126
|
+
exports.applyArrowShrinks = applyArrowShrinks;
|
|
127
|
+
exports.computeShrink = computeShrink;
|
|
128
|
+
exports.endpointArrows = endpointArrows;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { IRArrowDetail } from '../../ir';
|
|
2
|
+
import { ArrowEndSpec, PathCommand } from '../../primitive';
|
|
3
|
+
/** IR path-level `arrow` + `arrowDetail` → PathPrim 起末端点箭头规格 */
|
|
4
|
+
export declare const endpointArrows: (arrow: "none" | "->" | "<-" | "<->" | undefined, detail: IRArrowDetail | undefined) => {
|
|
5
|
+
arrowStart?: ArrowEndSpec;
|
|
6
|
+
arrowEnd?: ArrowEndSpec;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* 端点级 shrink(strokeWidth 倍):line 末端朝起点缩这么多,让箭头尖端落回原 target
|
|
10
|
+
* @description 不分实心 / 空心:路径端点接在箭头尾部或凹口,箭头尖端仍贴原 target。低 opacity 下不会再透出 line。
|
|
11
|
+
*/
|
|
12
|
+
export declare const computeShrink: (spec: ArrowEndSpec) => number;
|
|
13
|
+
/**
|
|
14
|
+
* 按 shape + spec(length / scale / lineWidth)把首/末段端点向内缩短
|
|
15
|
+
* @description 让 line 端点接在 hollow arrow 尾部外缘、不贯穿 back outline;shrink=0 的实心 shape 跳过。in-place 改写 commands 数组
|
|
16
|
+
*/
|
|
17
|
+
export declare const applyArrowShrinks: (commands: Array<PathCommand>, shrinkStart: number, shrinkEnd: number, strokeWidth: number, round: (n: number) => number) => void;
|
|
18
|
+
//# sourceMappingURL=shrink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shrink.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/shrink.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAgC,MAAM,UAAU,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAmCjE,gEAAgE;AAChE,eAAO,MAAM,cAAc,GACzB,OAAO,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,SAAS,EAC/C,QAAQ,aAAa,GAAG,SAAS,KAChC;IAAE,UAAU,CAAC,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;CAatD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,YAAY,KAAG,MAIlD,CAAC;AAiDF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,KAAK,CAAC,WAAW,CAAC,EAC5B,aAAa,MAAM,EACnB,WAAW,MAAM,EACjB,aAAa,MAAM,EACnB,OAAO,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,KAC3B,IA4CF,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//#region src/compile/path/split.ts
|
|
2
|
+
/**
|
|
3
|
+
* 多 sub-path + 有端点箭头:按 sub-path split 成多个 PathPrim
|
|
4
|
+
* @description 端点箭头只属于整条 path 的首端和末端;单 sub-path 或无箭头时直接产一个 PathPrim。
|
|
5
|
+
*/
|
|
6
|
+
var splitSubPathsForEndpointArrows = (commands, baseProps, endpointArrows) => {
|
|
7
|
+
const hasArrows = !!endpointArrows.arrowStart || !!endpointArrows.arrowEnd;
|
|
8
|
+
const subPathStarts = [];
|
|
9
|
+
commands.forEach((cmd, idx) => {
|
|
10
|
+
if (cmd.kind === "move") subPathStarts.push(idx);
|
|
11
|
+
});
|
|
12
|
+
if (!hasArrows || subPathStarts.length <= 1) return {
|
|
13
|
+
primitive: {
|
|
14
|
+
type: "path",
|
|
15
|
+
commands,
|
|
16
|
+
...baseProps,
|
|
17
|
+
...endpointArrows
|
|
18
|
+
},
|
|
19
|
+
isGrouped: false
|
|
20
|
+
};
|
|
21
|
+
const subPathSlices = [];
|
|
22
|
+
for (let s = 0; s < subPathStarts.length; s++) {
|
|
23
|
+
const start = subPathStarts[s];
|
|
24
|
+
const end = s + 1 < subPathStarts.length ? subPathStarts[s + 1] : commands.length;
|
|
25
|
+
subPathSlices.push(commands.slice(start, end));
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
primitive: {
|
|
29
|
+
type: "group",
|
|
30
|
+
children: subPathSlices.map((sub, i) => {
|
|
31
|
+
const isFirst = i === 0;
|
|
32
|
+
const isLast = i === subPathSlices.length - 1;
|
|
33
|
+
return {
|
|
34
|
+
type: "path",
|
|
35
|
+
commands: sub,
|
|
36
|
+
...baseProps,
|
|
37
|
+
...isFirst && endpointArrows.arrowStart ? { arrowStart: endpointArrows.arrowStart } : {},
|
|
38
|
+
...isLast && endpointArrows.arrowEnd ? { arrowEnd: endpointArrows.arrowEnd } : {}
|
|
39
|
+
};
|
|
40
|
+
})
|
|
41
|
+
},
|
|
42
|
+
isGrouped: true
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
//#endregion
|
|
46
|
+
exports.splitSubPathsForEndpointArrows = splitSubPathsForEndpointArrows;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ArrowEndSpec, PathCommand, PathPrim, ScenePrimitive } from '../../primitive';
|
|
2
|
+
/** baseProps:除 commands / endpoint arrows 外 PathPrim 公共属性集合(多 sub-path 复用) */
|
|
3
|
+
export type PathBaseProps = Omit<PathPrim, 'type' | 'commands' | 'arrowStart' | 'arrowEnd'>;
|
|
4
|
+
/**
|
|
5
|
+
* 多 sub-path + 有端点箭头:按 sub-path split 成多个 PathPrim
|
|
6
|
+
* @description 端点箭头只属于整条 path 的首端和末端;单 sub-path 或无箭头时直接产一个 PathPrim。
|
|
7
|
+
*/
|
|
8
|
+
export declare const splitSubPathsForEndpointArrows: (commands: Array<PathCommand>, baseProps: PathBaseProps, endpointArrows: {
|
|
9
|
+
arrowStart?: ArrowEndSpec;
|
|
10
|
+
arrowEnd?: ArrowEndSpec;
|
|
11
|
+
}) => {
|
|
12
|
+
primitive: ScenePrimitive;
|
|
13
|
+
isGrouped: boolean;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=split.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/split.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE3F,8EAA8E;AAC9E,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,UAAU,CAAC,CAAC;AAE5F;;;GAGG;AACH,eAAO,MAAM,8BAA8B,GACzC,UAAU,KAAK,CAAC,WAAW,CAAC,EAC5B,WAAW,aAAa,EACxB,gBAAgB;IAAE,UAAU,CAAC,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;CAAE,KACrE;IAAE,SAAS,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CA2CjD,CAAC"}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
//#region src/compile/text-metrics.ts
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
/**
|
|
3
|
+
* 默认 fallback 度量:基于平均字宽估算,不准但保证可运行
|
|
4
|
+
* @description size=0 → 退化返回 (0, 0)(与 text='' 一致);负 size 或 NaN size → throw(非法输入早 fail,避免 NaN 噪音传播到 Scene)
|
|
5
|
+
*/
|
|
6
|
+
var fallbackMeasurer = (text, font) => {
|
|
7
|
+
if (Number.isNaN(font.size) || font.size < 0) throw new Error(`fallbackMeasurer: invalid font.size '${font.size}'; must be a non-negative finite number`);
|
|
8
|
+
return {
|
|
9
|
+
width: text.length * font.size * .55,
|
|
10
|
+
height: font.size * 1.2
|
|
11
|
+
};
|
|
12
|
+
};
|
|
7
13
|
//#endregion
|
|
8
14
|
exports.fallbackMeasurer = fallbackMeasurer;
|
|
@@ -25,6 +25,9 @@ export type TextMetrics = {
|
|
|
25
25
|
* @description @retikz/react: canvas measureText;@retikz/ssr: opentype.js/fontkit;@retikz/canvas: ctx.measureText
|
|
26
26
|
*/
|
|
27
27
|
export type TextMeasurer = (text: string, font: FontSpec) => TextMetrics;
|
|
28
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* 默认 fallback 度量:基于平均字宽估算,不准但保证可运行
|
|
30
|
+
* @description size=0 → 退化返回 (0, 0)(与 text='' 一致);负 size 或 NaN size → throw(非法输入早 fail,避免 NaN 噪音传播到 Scene)
|
|
31
|
+
*/
|
|
29
32
|
export declare const fallbackMeasurer: TextMeasurer;
|
|
30
33
|
//# sourceMappingURL=text-metrics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-metrics.d.ts","sourceRoot":"","sources":["../../../src/compile/text-metrics.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,MAAM,MAAM,QAAQ,GAAG;IACrB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,mCAAmC;IACnC,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;CACzC,CAAC;AAEF,uCAAuC;AACvC,MAAM,MAAM,WAAW,GAAG;IACxB,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,WAAW,CAAC;AAEzE
|
|
1
|
+
{"version":3,"file":"text-metrics.d.ts","sourceRoot":"","sources":["../../../src/compile/text-metrics.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,MAAM,MAAM,QAAQ,GAAG;IACrB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,mCAAmC;IACnC,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;CACzC,CAAC;AAEF,uCAAuC;AACvC,MAAM,MAAM,WAAW,GAAG;IACxB,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,WAAW,CAAC;AAEzE;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,YAU9B,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/geometry/_transform.ts
|
|
2
|
+
/**
|
|
3
|
+
* 本地坐标(以中心为原点)→ 世界坐标
|
|
4
|
+
* @description rotate=0 / 缺省时退化为平移;非零时按右手系绕中心旋转后再平移
|
|
5
|
+
*/
|
|
6
|
+
var localToWorld = (s, local) => {
|
|
7
|
+
const angle = s.rotate ?? 0;
|
|
8
|
+
if (angle === 0) return [s.x + local[0], s.y + local[1]];
|
|
9
|
+
const cos = Math.cos(angle);
|
|
10
|
+
const sin = Math.sin(angle);
|
|
11
|
+
return [s.x + local[0] * cos - local[1] * sin, s.y + local[0] * sin + local[1] * cos];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* 世界坐标 → 本地坐标(`localToWorld` 逆变换)
|
|
15
|
+
* @description 先反平移到中心、再反旋转回本地基;旋转矩阵转置即逆
|
|
16
|
+
*/
|
|
17
|
+
var worldToLocal = (s, world) => {
|
|
18
|
+
const tx = world[0] - s.x;
|
|
19
|
+
const ty = world[1] - s.y;
|
|
20
|
+
const angle = s.rotate ?? 0;
|
|
21
|
+
if (angle === 0) return [tx, ty];
|
|
22
|
+
const cos = Math.cos(angle);
|
|
23
|
+
const sin = Math.sin(angle);
|
|
24
|
+
return [tx * cos + ty * sin, -tx * sin + ty * cos];
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
exports.localToWorld = localToWorld;
|
|
28
|
+
exports.worldToLocal = worldToLocal;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Position } from './point';
|
|
2
|
+
/** 任何"中心 + 可选旋转"形状的几何契约(rect / circle / ellipse / diamond 共用) */
|
|
3
|
+
export type CenteredShape = {
|
|
4
|
+
/** 中心横坐标 */
|
|
5
|
+
x: number;
|
|
6
|
+
/** 中心纵坐标 */
|
|
7
|
+
y: number;
|
|
8
|
+
/** 绕中心旋转弧度(可选,0 / 缺省 = 不旋转) */
|
|
9
|
+
rotate?: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* 本地坐标(以中心为原点)→ 世界坐标
|
|
13
|
+
* @description rotate=0 / 缺省时退化为平移;非零时按右手系绕中心旋转后再平移
|
|
14
|
+
*/
|
|
15
|
+
export declare const localToWorld: (s: CenteredShape, local: Position) => Position;
|
|
16
|
+
/**
|
|
17
|
+
* 世界坐标 → 本地坐标(`localToWorld` 逆变换)
|
|
18
|
+
* @description 先反平移到中心、再反旋转回本地基;旋转矩阵转置即逆
|
|
19
|
+
*/
|
|
20
|
+
export declare const worldToLocal: (s: CenteredShape, world: Position) => Position;
|
|
21
|
+
//# sourceMappingURL=_transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_transform.d.ts","sourceRoot":"","sources":["../../../src/geometry/_transform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,iEAAiE;AACjE,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY;IACZ,CAAC,EAAE,MAAM,CAAC;IACV,YAAY;IACZ,CAAC,EAAE,MAAM,CAAC;IACV,+BAA+B;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,GAAG,aAAa,EAAE,OAAO,QAAQ,KAAG,QAShE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,GAAG,aAAa,EAAE,OAAO,QAAQ,KAAG,QAQhE,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//#region src/geometry/bend.ts
|
|
2
2
|
/**
|
|
3
3
|
* cubic Bezier 拟合 from→to 的弧形 bend
|
|
4
|
-
* @description apex offset = chord × tan(bendAngle/2);控制点取 chord 1/3 与 2/3 处沿法向偏移,让 cubic 在 t=0.5 穿过 apex 故 ctlOffset = 4/3 × apexOffset
|
|
4
|
+
* @description apex offset = chord × tan(bendAngle/2);控制点取 chord 1/3 与 2/3 处沿法向偏移,让 cubic 在 t=0.5 穿过 apex 故 ctlOffset = 4/3 × apexOffset。法向(screen y-down):visual-left=(dy,-dx)/|chord|,visual-right=(-dy,dx)/|chord|。chord=0 时两控制点都返回 from
|
|
5
5
|
*/
|
|
6
6
|
var bendControlPoints = (from, to, direction, bendAngle) => {
|
|
7
7
|
const dx = to[0] - from[0];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Position } from './point';
|
|
2
2
|
/**
|
|
3
3
|
* cubic Bezier 拟合 from→to 的弧形 bend
|
|
4
|
-
* @description apex offset = chord × tan(bendAngle/2);控制点取 chord 1/3 与 2/3 处沿法向偏移,让 cubic 在 t=0.5 穿过 apex 故 ctlOffset = 4/3 × apexOffset
|
|
4
|
+
* @description apex offset = chord × tan(bendAngle/2);控制点取 chord 1/3 与 2/3 处沿法向偏移,让 cubic 在 t=0.5 穿过 apex 故 ctlOffset = 4/3 × apexOffset。法向(screen y-down):visual-left=(dy,-dx)/|chord|,visual-right=(-dy,dx)/|chord|。chord=0 时两控制点都返回 from
|
|
5
5
|
*/
|
|
6
6
|
export declare const bendControlPoints: (from: Position, to: Position, direction: "left" | "right", bendAngle: number) => [Position, Position];
|
|
7
7
|
//# sourceMappingURL=bend.d.ts.map
|
|
@@ -1,28 +1,13 @@
|
|
|
1
|
+
const require__transform = require("./_transform.cjs");
|
|
1
2
|
//#region src/geometry/circle.ts
|
|
2
3
|
var SQRT_HALF = Math.SQRT1_2;
|
|
3
|
-
var localToWorld = (c, local) => {
|
|
4
|
-
const angle = c.rotate ?? 0;
|
|
5
|
-
if (angle === 0) return [c.x + local[0], c.y + local[1]];
|
|
6
|
-
const cos = Math.cos(angle);
|
|
7
|
-
const sin = Math.sin(angle);
|
|
8
|
-
return [c.x + local[0] * cos - local[1] * sin, c.y + local[0] * sin + local[1] * cos];
|
|
9
|
-
};
|
|
10
|
-
var worldToLocal = (c, world) => {
|
|
11
|
-
const tx = world[0] - c.x;
|
|
12
|
-
const ty = world[1] - c.y;
|
|
13
|
-
const angle = c.rotate ?? 0;
|
|
14
|
-
if (angle === 0) return [tx, ty];
|
|
15
|
-
const cos = Math.cos(angle);
|
|
16
|
-
const sin = Math.sin(angle);
|
|
17
|
-
return [tx * cos + ty * sin, -tx * sin + ty * cos];
|
|
18
|
-
};
|
|
19
4
|
/** 圆形相关基础工具 */
|
|
20
5
|
var circle = {
|
|
21
6
|
/** 圆心 */
|
|
22
7
|
center: (c) => [c.x, c.y],
|
|
23
8
|
/** 判断点是否在圆内(含边界) */
|
|
24
9
|
contains: (c, p) => {
|
|
25
|
-
const [lx, ly] = worldToLocal(c, p);
|
|
10
|
+
const [lx, ly] = require__transform.worldToLocal(c, p);
|
|
26
11
|
return lx * lx + ly * ly <= c.radius * c.radius;
|
|
27
12
|
},
|
|
28
13
|
/** 9 个标准 anchor 之一的世界坐标 */
|
|
@@ -61,15 +46,15 @@ var circle = {
|
|
|
61
46
|
ly = r * SQRT_HALF;
|
|
62
47
|
break;
|
|
63
48
|
}
|
|
64
|
-
return localToWorld(c, [lx, ly]);
|
|
49
|
+
return require__transform.localToWorld(c, [lx, ly]);
|
|
65
50
|
},
|
|
66
51
|
/** 从圆心向 toward 方向射线与圆周交点(Path 端点贴 Node 边界用) */
|
|
67
52
|
boundaryPoint: (c, toward) => {
|
|
68
|
-
const [lx, ly] = worldToLocal(c, toward);
|
|
53
|
+
const [lx, ly] = require__transform.worldToLocal(c, toward);
|
|
69
54
|
const len = Math.sqrt(lx * lx + ly * ly);
|
|
70
55
|
if (len === 0) return [c.x, c.y];
|
|
71
56
|
const t = c.radius / len;
|
|
72
|
-
return localToWorld(c, [lx * t, ly * t]);
|
|
57
|
+
return require__transform.localToWorld(c, [lx * t, ly * t]);
|
|
73
58
|
}
|
|
74
59
|
};
|
|
75
60
|
//#endregion
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Position } from './point';
|
|
2
|
+
import { RectAnchor } from './rect';
|
|
2
3
|
/** 圆形:几何中心 + 半径,预留旋转字段保持与 Rect 同形 API */
|
|
3
4
|
export type Circle = {
|
|
4
5
|
x: number;
|
|
@@ -8,8 +9,6 @@ export type Circle = {
|
|
|
8
9
|
/** 绕中心旋转弧度(圆视觉不变,与 Rect 同形保留) */
|
|
9
10
|
rotate?: number;
|
|
10
11
|
};
|
|
11
|
-
/** 圆形 9 个标准 anchor(与 RECT_ANCHORS 同名同义,圆周每 45° 等距分布) */
|
|
12
|
-
export type CircleAnchor = 'center' | 'north' | 'south' | 'east' | 'west' | 'north-east' | 'north-west' | 'south-east' | 'south-west';
|
|
13
12
|
/** 圆形相关基础工具 */
|
|
14
13
|
export declare const circle: {
|
|
15
14
|
/** 圆心 */
|
|
@@ -17,7 +16,7 @@ export declare const circle: {
|
|
|
17
16
|
/** 判断点是否在圆内(含边界) */
|
|
18
17
|
contains: (c: Circle, p: Position) => boolean;
|
|
19
18
|
/** 9 个标准 anchor 之一的世界坐标 */
|
|
20
|
-
anchor: (c: Circle, name:
|
|
19
|
+
anchor: (c: Circle, name: RectAnchor) => Position;
|
|
21
20
|
/** 从圆心向 toward 方向射线与圆周交点(Path 端点贴 Node 边界用) */
|
|
22
21
|
boundaryPoint: (c: Circle, toward: Position) => Position;
|
|
23
22
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"circle.d.ts","sourceRoot":"","sources":["../../../src/geometry/circle.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"circle.d.ts","sourceRoot":"","sources":["../../../src/geometry/circle.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEzC,yCAAyC;AACzC,MAAM,MAAM,MAAM,GAAG;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,SAAS;IACT,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,eAAe;AACf,eAAO,MAAM,MAAM;IACjB,SAAS;gBACG,MAAM,KAAG,QAAQ;IAC7B,oBAAoB;kBACN,MAAM,KAAK,QAAQ,KAAG,OAAO;IAI3C,2BAA2B;gBACf,MAAM,QAAQ,UAAU,KAAG,QAAQ;IAsC/C,+CAA+C;uBAC5B,MAAM,UAAU,QAAQ,KAAG,QAAQ;CAOvD,CAAC"}
|