@knowvah/dot-engine 1.2.3 → 1.2.5
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/README.md +15 -0
- package/dist/cdt/bag.d.ts +6 -4
- package/dist/cdt/bag.d.ts.map +1 -1
- package/dist/common/graph-init.d.ts.map +1 -1
- package/dist/common/htmltable-lex.d.ts.map +1 -1
- package/dist/common/record.d.ts.map +1 -1
- package/dist/common/splines-clip.d.ts +8 -0
- package/dist/common/splines-clip.d.ts.map +1 -1
- package/dist/common/splines-routespl.d.ts +4 -0
- package/dist/common/splines-routespl.d.ts.map +1 -1
- package/dist/index.js +2038 -2004
- package/dist/index.js.map +4 -4
- package/dist/render.js +96 -62
- package/dist/render.js.map +3 -3
- package/dist/xdot/parse.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/cdt/bag.ts +30 -52
- package/src/common/graph-init.ts +14 -9
- package/src/common/htmltable-lex.ts +17 -4
- package/src/common/htmltable-parse.ts +1 -1
- package/src/common/record.ts +3 -5
- package/src/common/splines-clip.ts +25 -0
- package/src/common/splines-routespl.ts +66 -0
- package/src/xdot/parse.ts +3 -1
- package/dist/gvc/textlayout.d.ts +0 -33
- package/dist/gvc/textlayout.d.ts.map +0 -1
- package/dist/layout/osage/layout.d.ts +0 -49
- package/dist/layout/osage/layout.d.ts.map +0 -1
- package/dist/layout/pack/test-helpers.d.ts +0 -7
- package/dist/layout/pack/test-helpers.d.ts.map +0 -1
- package/dist/layout/patchwork/tree-node.d.ts +0 -46
- package/dist/layout/patchwork/tree-node.d.ts.map +0 -1
- package/dist/xdot/lex.d.ts +0 -22
- package/dist/xdot/lex.d.ts.map +0 -1
- package/src/gvc/textlayout.ts +0 -44
- package/src/layout/osage/layout.ts +0 -254
- package/src/layout/pack/test-helpers.ts +0 -46
- package/src/layout/patchwork/tree-node.ts +0 -120
- package/src/xdot/lex.ts +0 -151
package/dist/xdot/parse.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/xdot/parse.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,IAAI,EAAU,QAAQ,EAAE,YAAY,EACf,SAAS,EACC,WAAW,EAC3C,MAAM,YAAY,CAAC;AAGpB,KAAK,EAAE,CAAC,CAAC,IAAI;IAAE,GAAG,EAAE,CAAC,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/xdot/parse.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,IAAI,EAAU,QAAQ,EAAE,YAAY,EACf,SAAS,EACC,WAAW,EAC3C,MAAM,YAAY,CAAC;AAGpB,KAAK,EAAE,CAAC,CAAC,IAAI;IAAE,GAAG,EAAE,CAAC,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC;AAoU5C,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAyC;AACxG,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,CAA6C;AACpH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,CAA2C;AAC1G,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,SAAS,CAAC,CAAgD;AACvH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAE5G;AACD,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAE1F;AACD,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAoC;AACrF,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAyC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knowvah/dot-engine",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"description": "Faithful TypeScript port of Graphviz (dot, neato, fdp, sfdp, circo, twopi, osage, patchwork) — no C: no native binary, no WASM. Oracle-verified against the C implementation, runs in the browser.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"graphviz",
|
|
@@ -98,13 +98,14 @@
|
|
|
98
98
|
"@typescript/native-preview": "^7.0.0-dev.20260622.1",
|
|
99
99
|
"@vitest/coverage-v8": "^4.1.9",
|
|
100
100
|
"@xmldom/xmldom": "^0.9.10",
|
|
101
|
-
"canvas": "^3.2.3",
|
|
102
101
|
"esbuild": "^0.28.1",
|
|
103
102
|
"fontkit": "^2.0.4",
|
|
104
103
|
"peggy": "^5.0.0",
|
|
105
104
|
"semantic-release": "^25.0.8",
|
|
105
|
+
"tsx": "^4.23.1",
|
|
106
106
|
"typedoc": "^0.28.20",
|
|
107
107
|
"typedoc-plugin-markdown": "^4.12.0",
|
|
108
|
+
"@knowvah/vitepress-plugin-dot": "^1.0.0",
|
|
108
109
|
"typedoc-vitepress-theme": "^1.1.3",
|
|
109
110
|
"typescript": "^6.0.0",
|
|
110
111
|
"vitepress": "^1.6.0",
|
package/src/cdt/bag.ts
CHANGED
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
* DtBag — ordered multiset (Dtobag) backed by a splay tree.
|
|
4
4
|
*
|
|
5
5
|
* Unlike DtSplay (DT_OSET), DtBag allows duplicate keys. On insert of a
|
|
6
|
-
* duplicate, the
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* duplicate, the matched (old) node is threaded onto the new node's RIGHT
|
|
7
|
+
* subtree — not the left, as an earlier version of this comment claimed.
|
|
8
|
+
* C dttree.c DT_INSERT's DT_OBAG found-branch does
|
|
9
|
+
* `root->left = NULL; root->right = link.left; link.left = root;`
|
|
10
|
+
* (dttree.c:223-231): the old matched node is pushed onto the head of the
|
|
11
|
+
* RIGHT partition, which becomes the new root's `.right` subtree.
|
|
10
12
|
*
|
|
11
13
|
* Iteration (first/next) produces ascending comparator order. Among
|
|
12
14
|
* equal-key nodes the sub-order is the deterministic order CDT's Dtobag
|
|
@@ -32,50 +34,20 @@ import type { SplayNode } from "./splay-core.js";
|
|
|
32
34
|
// ---------------------------------------------------------------------------
|
|
33
35
|
|
|
34
36
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
start: SplayNode<T>,
|
|
41
|
-
target: T,
|
|
42
|
-
key: K,
|
|
43
|
-
keyOf: KeyOf<T, K>,
|
|
44
|
-
compare: Comparator<K>,
|
|
45
|
-
): [SplayNode<T> | null, SplayNode<T> | null] {
|
|
46
|
-
let cur: SplayNode<T> | null = start;
|
|
47
|
-
let parent: SplayNode<T> | null = null;
|
|
48
|
-
while (cur !== null) {
|
|
49
|
-
if (cur.obj === target) return [cur, parent];
|
|
50
|
-
if (compare(key, keyOf(cur.obj)) !== 0) return [null, null];
|
|
51
|
-
parent = cur;
|
|
52
|
-
cur = cur.left;
|
|
53
|
-
}
|
|
54
|
-
return [null, null];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Unlink `cur` from the tree. `parent` is its direct parent (null → root).
|
|
37
|
+
* Remove `root` itself from the tree, joining its two subtrees. delete()
|
|
38
|
+
* always walks the equal-key duplicate group (via splay + next()) until the
|
|
39
|
+
* target identity is splayed to root, so unlinking only ever needs to
|
|
40
|
+
* handle the "match is at root" case — mirrors dttree.c:211-222 dt_delete's
|
|
41
|
+
* reassembly (`l->right = root->left; r->left = root->right; ...`).
|
|
59
42
|
* Returns the new root.
|
|
60
43
|
*/
|
|
61
|
-
function
|
|
62
|
-
root
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
let replacement: SplayNode<T> | null;
|
|
69
|
-
if (left === null) {
|
|
70
|
-
replacement = right;
|
|
71
|
-
} else {
|
|
72
|
-
const maxLeft = splayMax(left);
|
|
73
|
-
maxLeft.right = right;
|
|
74
|
-
replacement = maxLeft;
|
|
75
|
-
}
|
|
76
|
-
if (parent === null) return replacement;
|
|
77
|
-
parent.left = replacement;
|
|
78
|
-
return root;
|
|
44
|
+
function removeRoot<T>(root: SplayNode<T>): SplayNode<T> | null {
|
|
45
|
+
const left = root.left;
|
|
46
|
+
const right = root.right;
|
|
47
|
+
if (left === null) return right;
|
|
48
|
+
const maxLeft = splayMax(left);
|
|
49
|
+
maxLeft.right = right;
|
|
50
|
+
return maxLeft;
|
|
79
51
|
}
|
|
80
52
|
|
|
81
53
|
// ---------------------------------------------------------------------------
|
|
@@ -123,12 +95,18 @@ export class DtBag<T, K = T> {
|
|
|
123
95
|
const key = this._keyOf(obj);
|
|
124
96
|
this._root = splay(this._root, key, this._keyOf, this._compare);
|
|
125
97
|
if (this._compare(key, this._keyOf(this._root.obj)) !== 0) return false;
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
this._root
|
|
98
|
+
// Mirror dttree.c:67-79's DT_OBAG DELETE/DETACH pre-pass: dtsearch
|
|
99
|
+
// splays an equal-key node to root, then dtnext (also splaying) walks
|
|
100
|
+
// the equal-key duplicate group by pointer identity until it finds
|
|
101
|
+
// `obj`. Each next() call re-splays `this._root`, mirroring C's
|
|
102
|
+
// mutate-on-lookup contract.
|
|
103
|
+
while (this._root.obj !== obj) {
|
|
104
|
+
const nxt = this.next(this._root.obj);
|
|
105
|
+
if (nxt === undefined || this._compare(key, this._keyOf(nxt)) !== 0) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
this._root = removeRoot(this._root);
|
|
132
110
|
this._size--;
|
|
133
111
|
return true;
|
|
134
112
|
}
|
package/src/common/graph-init.ts
CHANGED
|
@@ -181,29 +181,34 @@ function parseRatioKind(g: Graph): RatioKind | undefined {
|
|
|
181
181
|
|
|
182
182
|
/**
|
|
183
183
|
* Populate `g.info.drawing` for the ratio kinds whose layout reshape is ported
|
|
184
|
-
* AND corpus-validated: `compress` (compressGraph x-NS, position-cluster.ts)
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
184
|
+
* AND corpus-validated: `compress` (compressGraph x-NS, position-cluster.ts),
|
|
185
|
+
* `fill` (setAspect R_FILL, position-bbox.ts), and numeric `value` (setAspect
|
|
186
|
+
* R_VALUE; corpus coverage: 2621, `ratio=0.5625` — see
|
|
187
|
+
* `.agent-notes/2621-path-structure.md`). C stores the parsed ratio only for
|
|
188
|
+
* R_VALUE (`input.c setRatio: ratio = atof(p); if > 0`). `expand` has the math
|
|
189
|
+
* in setAspect but no corpus coverage, and `auto` needs `idealsize` (unported);
|
|
190
|
+
* both stay deferred — leaving `drawing` unset keeps setAspect a no-op for
|
|
191
|
+
* them.
|
|
189
192
|
*
|
|
190
193
|
* DELIBERATE DEVIATION from C, carried over verbatim from dot's old init: C
|
|
191
194
|
* allocates GD_drawing unconditionally (`input.c:609`) and stores the parsed
|
|
192
195
|
* ratio_kind for EVERY kind. Allocating it here would flip the
|
|
193
196
|
* `drawing === undefined` guards at `dot/position-bbox.ts:142` (setAspect) and
|
|
194
|
-
* `neato/set-aspect.ts:57`, activating the unvalidated expand/
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
+
* `neato/set-aspect.ts:57`, activating the unvalidated expand/auto reshapes and
|
|
198
|
+
* changing dot output. Scope is therefore unchanged by the graph_init
|
|
199
|
+
* consolidation. See `.agent-notes/graph-init-consolidation.md`.
|
|
197
200
|
*
|
|
198
201
|
* @see lib/dotgen/position.c:set_aspect (904), compress_graph (501)
|
|
199
202
|
* @see lib/common/input.c:576 setRatio, 693-694 (size)
|
|
200
203
|
*/
|
|
201
204
|
function parseRatioDrawing(g: Graph): void {
|
|
202
205
|
const kind = parseRatioKind(g);
|
|
203
|
-
if (kind !== 'compress' && kind !== 'fill') return;
|
|
206
|
+
if (kind !== 'compress' && kind !== 'fill' && kind !== 'value') return;
|
|
204
207
|
const sz = parseSizePoints(g.attrs.get('size'));
|
|
205
208
|
g.info.drawing = makeDrawing({
|
|
206
209
|
ratioKind: kind,
|
|
210
|
+
// C: GD_drawing(g)->ratio = atof(p), set only for R_VALUE (setRatio).
|
|
211
|
+
ratio: kind === 'value' ? Number.parseFloat(g.attrs.get('ratio')!) : 0,
|
|
207
212
|
size: sz ? { x: sz.x, y: sz.y } : { x: 0, y: 0 },
|
|
208
213
|
filled: sz?.filled ?? false,
|
|
209
214
|
});
|
|
@@ -66,13 +66,25 @@ function parseAttrs(raw: string) {
|
|
|
66
66
|
return out;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
/**
|
|
70
|
+
* TH is a row-boundary synonym for TR, not a cell tag: the C lexer
|
|
71
|
+
* dispatches both open and close TH identically to TR (T_row/T_end_row).
|
|
72
|
+
* Normalizing here — the single point where tags become tokens — means
|
|
73
|
+
* every downstream consumer (parser) sees TH and TR as structurally
|
|
74
|
+
* identical, mirroring the C lexer's dispatch exactly.
|
|
75
|
+
* @see lib/common/htmllex.c:614,669 (startElement/endElement)
|
|
76
|
+
*/
|
|
77
|
+
function normalizeTag(tag: string): string {
|
|
78
|
+
return tag === 'TH' ? 'TR' : tag;
|
|
79
|
+
}
|
|
80
|
+
|
|
69
81
|
/** Parse close tag. @see lib/common/htmllex.c:endElement */
|
|
70
82
|
function parseCloseToken(inner: string) {
|
|
71
83
|
const body = inner.slice(1).trim();
|
|
72
84
|
const sp = body.search(/\s/);
|
|
73
85
|
const tag = (sp === -1 ? body : body.slice(0, sp)).toUpperCase();
|
|
74
86
|
checkTag(tag);
|
|
75
|
-
return { type: 'close' as const, tag };
|
|
87
|
+
return { type: 'close' as const, tag: normalizeTag(tag) };
|
|
76
88
|
}
|
|
77
89
|
|
|
78
90
|
/** @see lib/common/htmllex.c:characterData */
|
|
@@ -119,12 +131,13 @@ function scanTag(src: string, start: number, tokens: Token[]) {
|
|
|
119
131
|
function parseOpenToken(inner: string) {
|
|
120
132
|
const sp = inner.search(/\s/);
|
|
121
133
|
if (sp === -1) {
|
|
122
|
-
|
|
123
|
-
|
|
134
|
+
const tag = inner.toUpperCase();
|
|
135
|
+
checkTag(tag);
|
|
136
|
+
return { type: 'open' as const, tag: normalizeTag(tag), attrs: parseAttrs('') };
|
|
124
137
|
}
|
|
125
138
|
const tag = inner.slice(0, sp).toUpperCase();
|
|
126
139
|
checkTag(tag);
|
|
127
|
-
return { type: 'open' as const, tag, attrs: parseAttrs(inner.slice(sp + 1)) };
|
|
140
|
+
return { type: 'open' as const, tag: normalizeTag(tag), attrs: parseAttrs(inner.slice(sp + 1)) };
|
|
128
141
|
}
|
|
129
142
|
|
|
130
143
|
/** @see lib/common/htmllex.c:findNext */
|
|
@@ -362,7 +362,7 @@ const parseCell = (
|
|
|
362
362
|
const processRowToken = (
|
|
363
363
|
s: ParseState, t: Token, cells: HtmlCell[], fontStack: FontState[],
|
|
364
364
|
): void => {
|
|
365
|
-
if (t.type === 'open' &&
|
|
365
|
+
if (t.type === 'open' && t.tag === 'TD') {
|
|
366
366
|
consume(s);
|
|
367
367
|
cells.push(parseCell(s, t.attrs, fontStack));
|
|
368
368
|
return;
|
package/src/common/record.ts
CHANGED
|
@@ -25,6 +25,7 @@ import { renderLabel, applyNodeStyle } from './poly-gencode.js';
|
|
|
25
25
|
import { transformPoint } from '../gvc/device.js';
|
|
26
26
|
import { emitRoundedBezier } from './poly-shapes.js';
|
|
27
27
|
import { parseStyleFlags } from './style-resolve.js';
|
|
28
|
+
import { mapbool } from '../layout/dot/rank.js';
|
|
28
29
|
|
|
29
30
|
// Parse-mode bits. @see lib/common/shapes.c
|
|
30
31
|
const HASTEXT = 1;
|
|
@@ -344,12 +345,9 @@ export function posReclbl(f: FieldT, ul: Point, sides: number): void {
|
|
|
344
345
|
// record_init
|
|
345
346
|
// ---------------------------------------------------------------------------
|
|
346
347
|
|
|
347
|
-
/** mapbool for attr strings. @see lib/common/utils.c:
|
|
348
|
+
/** mapbool for attr strings. @see lib/common/utils.c:mapBool */
|
|
348
349
|
function attrBool(n: Node, g: Graph, key: string): boolean {
|
|
349
|
-
|
|
350
|
-
if (!s || s.toLowerCase() === 'false' || s.toLowerCase() === 'no') return false;
|
|
351
|
-
if (s.toLowerCase() === 'true' || s.toLowerCase() === 'yes') return true;
|
|
352
|
-
return parseInt(s, 10) !== 0;
|
|
350
|
+
return mapbool(nodeAttr(n, g, key));
|
|
353
351
|
}
|
|
354
352
|
|
|
355
353
|
function recAttrSize(n: Node, g: Graph): Point {
|
|
@@ -472,4 +472,29 @@ export function clipAndInstall(fe: Edge, hn: Node, ps: Point[], pn: number, info
|
|
|
472
472
|
SplineClipHelper.arrowClip(fe, hn, ps, bounds, newspl, info);
|
|
473
473
|
// C: update_bb_bz(&GD_bb(g), cp) — expand g's bb by each installed bezier.
|
|
474
474
|
SplineClipHelper.copyToBezier(newspl, ps, bounds.start, bounds.end, g.info.bb);
|
|
475
|
+
if (clipDump) {
|
|
476
|
+
let cur = fe;
|
|
477
|
+
while (cur.info.to_orig != null && cur.info.edge_type !== 0) cur = cur.info.to_orig;
|
|
478
|
+
clipDump('S5_CLIP', cur.tail.name, cur.head.name, {
|
|
479
|
+
inputPn: pn,
|
|
480
|
+
bounds: { start: bounds.start, end: bounds.end },
|
|
481
|
+
sflag: newspl.sflag, eflag: newspl.eflag,
|
|
482
|
+
sp: { ...newspl.sp }, ep: { ...newspl.ep },
|
|
483
|
+
size: newspl.size,
|
|
484
|
+
// emit reads bz.size, not list.length (memory: bezier-emit-size-not-length)
|
|
485
|
+
list: newspl.list.slice(0, newspl.size).map(p => ({ ...p })),
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Stage-dump hook for the clip/install output (diagnosis only; null in
|
|
492
|
+
* production — same pattern as splines-routespl.ts:setRouteDump).
|
|
493
|
+
*/
|
|
494
|
+
type ClipDumpFn = (stage: string, tail: string, head: string, payload: unknown) => void;
|
|
495
|
+
let clipDump: ClipDumpFn | null = null;
|
|
496
|
+
|
|
497
|
+
/** Install (or clear) the clip-stage dump callback. Diagnosis only. */
|
|
498
|
+
export function setClipDump(fn: ClipDumpFn | null): void {
|
|
499
|
+
clipDump = fn;
|
|
475
500
|
}
|
|
@@ -15,6 +15,50 @@ import { shortestPath, routeSpline, makePolyline } from '../pathplan/index.js';
|
|
|
15
15
|
import type { Poly } from '../pathplan/types.js';
|
|
16
16
|
import { INIT_DELTA, LOOP_TRIES, ROUTESPL_FUDGE } from './splines-constants.js';
|
|
17
17
|
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Stage-dump hook (diagnosis only; null in production — same pattern as
|
|
20
|
+
// mincross-order.ts:setMincrossTrace). The callback receives the routing
|
|
21
|
+
// stage name, the real edge's tail/head names (resolved through to_orig like
|
|
22
|
+
// C's routesplines_ realedge walk), and a stage payload; filtering and
|
|
23
|
+
// serialization are the callback's job. Browser-safe: no env reads here.
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
/** Stage payload consumer installed by a diagnosis harness. */
|
|
27
|
+
export type RouteDumpFn = (
|
|
28
|
+
stage: string, tail: string, head: string, payload: unknown,
|
|
29
|
+
) => void;
|
|
30
|
+
|
|
31
|
+
let routeDump: RouteDumpFn | null = null;
|
|
32
|
+
|
|
33
|
+
/** Install (or clear) the routing stage-dump callback. Diagnosis only. */
|
|
34
|
+
export function setRouteDump(fn: RouteDumpFn | null): void {
|
|
35
|
+
routeDump = fn;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface DumpEdgeLike {
|
|
39
|
+
tail?: { name?: string }; head?: { name?: string };
|
|
40
|
+
info?: { edge_type?: number; to_orig?: DumpEdgeLike };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function dumpIsVirtual(e: DumpEdgeLike): boolean {
|
|
44
|
+
return (e.info?.edge_type ?? 0) !== 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Resolve pp.data through to_orig to the real edge's names, as C does. */
|
|
48
|
+
function dumpEdgeNames(pp: Path): [string, string] {
|
|
49
|
+
let e = pp.data as DumpEdgeLike | null;
|
|
50
|
+
// C: for (realedge = pp->data; realedge && ED_edge_type(realedge) != NORMAL;
|
|
51
|
+
// realedge = ED_to_orig(realedge)); (NORMAL === 0)
|
|
52
|
+
while (e !== null && dumpIsVirtual(e)) e = e.info?.to_orig ?? null;
|
|
53
|
+
if (e === null) return ['?', '?'];
|
|
54
|
+
return [e.tail?.name ?? '?', e.head?.name ?? '?'];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Invoke the dump callback when installed; payload built lazily. */
|
|
58
|
+
function emitDump(stage: string, names: [string, string] | null, mk: () => unknown): void {
|
|
59
|
+
if (routeDump !== null && names !== null) routeDump(stage, names[0], names[1], mk());
|
|
60
|
+
}
|
|
61
|
+
|
|
18
62
|
// ---------------------------------------------------------------------------
|
|
19
63
|
// overlap helper
|
|
20
64
|
// ---------------------------------------------------------------------------
|
|
@@ -353,8 +397,20 @@ function runLimitLoop(
|
|
|
353
397
|
|
|
354
398
|
function routeSplinesInternal(pp: Path, polyline: boolean): Point[] | null {
|
|
355
399
|
const boxes = pp.boxes;
|
|
400
|
+
const dumpNames = routeDump ? dumpEdgeNames(pp) : null;
|
|
401
|
+
emitDump('S1_INPUT', dumpNames, () => ({
|
|
402
|
+
nbox: pp.nbox,
|
|
403
|
+
boxes: pp.boxes.slice(0, pp.nbox).map(b => ({ ll: { ...b.ll }, ur: { ...b.ur } })),
|
|
404
|
+
start: { p: { ...pp.start.p }, theta: pp.start.theta, constrained: pp.start.constrained },
|
|
405
|
+
end: { p: { ...pp.end.p }, theta: pp.end.theta, constrained: pp.end.constrained },
|
|
406
|
+
}));
|
|
356
407
|
if (checkPath(pp.nbox, boxes, pp)) return null;
|
|
357
408
|
const effectiveBoxn = pp.nbox;
|
|
409
|
+
emitDump('S2_CHECKED', dumpNames, () => ({
|
|
410
|
+
nbox: effectiveBoxn,
|
|
411
|
+
boxes: boxes.slice(0, effectiveBoxn).map(b => ({ ll: { ...b.ll }, ur: { ...b.ur } })),
|
|
412
|
+
start: { p: { ...pp.start.p } }, end: { p: { ...pp.end.p } },
|
|
413
|
+
}));
|
|
358
414
|
|
|
359
415
|
let flip = false;
|
|
360
416
|
if (effectiveBoxn > 1 && boxes[0].ll.y > boxes[1].ll.y) {
|
|
@@ -389,6 +445,11 @@ function routeSplinesInternal(pp: Path, polyline: boolean): Point[] | null {
|
|
|
389
445
|
console.warn('in routesplines, Pshortestpath failed');
|
|
390
446
|
return null;
|
|
391
447
|
}
|
|
448
|
+
emitDump('S3_POLY', dumpNames, () => ({
|
|
449
|
+
poly: polypoints.map(p => ({ ...p })),
|
|
450
|
+
eps: [{ ...eps[0] }, { ...eps[1] }],
|
|
451
|
+
pl: pl.map(p => ({ ...p })),
|
|
452
|
+
}));
|
|
392
453
|
|
|
393
454
|
let ps: Point[];
|
|
394
455
|
if (polyline) {
|
|
@@ -399,6 +460,11 @@ function routeSplinesInternal(pp: Path, polyline: boolean): Point[] | null {
|
|
|
399
460
|
ps = routeSpline(edges, pl, evs);
|
|
400
461
|
if (ps.length === 0) return null;
|
|
401
462
|
}
|
|
463
|
+
emitDump('S4_SPL', dumpNames, () => ({
|
|
464
|
+
polyline,
|
|
465
|
+
evs: polyline ? undefined : buildConstraintVectors(pp).map(v => ({ ...v })),
|
|
466
|
+
ps: ps.map(p => ({ ...p })),
|
|
467
|
+
}));
|
|
402
468
|
|
|
403
469
|
if (isTriviallyBounded(ps)) {
|
|
404
470
|
applyTrivialBounds(boxes, effectiveBoxn, ps);
|
package/src/xdot/parse.ts
CHANGED
|
@@ -122,7 +122,9 @@ class XdotParser {
|
|
|
122
122
|
let accounted = 0;
|
|
123
123
|
let j = 0;
|
|
124
124
|
while (accounted < len) {
|
|
125
|
-
|
|
125
|
+
// C fails hard the moment input runs out before the byte budget is
|
|
126
|
+
// satisfied (`s[j] == '\0'` mid-loop). @see xdot/xdot.c:139-141.
|
|
127
|
+
if (cur + j >= s.length) return null;
|
|
126
128
|
const ch = s[cur + j];
|
|
127
129
|
const prev = j > 0 ? s[cur + j - 1] : "";
|
|
128
130
|
out += ch;
|
package/dist/gvc/textlayout.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Text layout selection and measurement.
|
|
3
|
-
*
|
|
4
|
-
* Ports gvtextlayout_select and gvtextlayout from lib/gvc/gvtextlayout.c,
|
|
5
|
-
* simplified for the TypeScript model where the text-layout engine is always
|
|
6
|
-
* the context's registered TextMeasurer (no dynamic plugin loading).
|
|
7
|
-
*
|
|
8
|
-
* @see lib/gvc/gvtextlayout.c:gvtextlayout_select
|
|
9
|
-
* @see lib/gvc/gvtextlayout.c:gvtextlayout
|
|
10
|
-
*/
|
|
11
|
-
import type { GvcContext } from './context.js';
|
|
12
|
-
import type { TextMeasurer } from '../common/textmeasure.js';
|
|
13
|
-
import type { TextSpan } from '../common/emit-types.js';
|
|
14
|
-
/**
|
|
15
|
-
* Return the text measurer registered on ctx.
|
|
16
|
-
*
|
|
17
|
-
* Replaces gvtextlayout_select / plugin load with direct access to the
|
|
18
|
-
* context's measurer, per AD-2 (static registration, no libltdl).
|
|
19
|
-
*
|
|
20
|
-
* @see lib/gvc/gvtextlayout.c:gvtextlayout_select
|
|
21
|
-
*/
|
|
22
|
-
export declare function selectTextLayout(ctx: GvcContext): TextMeasurer;
|
|
23
|
-
/**
|
|
24
|
-
* Measure a text span and write the result into span.size.
|
|
25
|
-
*
|
|
26
|
-
* Mirrors gvtextlayout: calls the engine's textlayout method to populate
|
|
27
|
-
* the size field on the span. Falls back to 'Times-Roman' / 14pt when
|
|
28
|
-
* fontName or fontSize are unspecified.
|
|
29
|
-
*
|
|
30
|
-
* @see lib/gvc/gvtextlayout.c:gvtextlayout
|
|
31
|
-
*/
|
|
32
|
-
export declare function measure(span: TextSpan, ctx: GvcContext): void;
|
|
33
|
-
//# sourceMappingURL=textlayout.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"textlayout.d.ts","sourceRoot":"","sources":["../../src/gvc/textlayout.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,YAAY,CAE9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI,CAK7D"}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Osage recursive layout helpers.
|
|
3
|
-
*
|
|
4
|
-
* @see lib/osage/osageinit.c:layout
|
|
5
|
-
* @see lib/osage/osageinit.c:reposition
|
|
6
|
-
*/
|
|
7
|
-
import type { Graph } from '../../model/graph.js';
|
|
8
|
-
import type { Box, Point } from '../../model/geom.js';
|
|
9
|
-
import type { PackInfo } from '../pack/index.js';
|
|
10
|
-
import type { ChildLists } from './types.js';
|
|
11
|
-
export type { ChildLists };
|
|
12
|
-
/** Build and populate a PackInfo from graph attributes. @see lib/osage/osageinit.c:layout */
|
|
13
|
-
export declare const buildPackInfo: (g: Graph) => PackInfo;
|
|
14
|
-
/**
|
|
15
|
-
* Build child arrays for putRects.
|
|
16
|
-
* @see lib/osage/osageinit.c:layout (child list construction)
|
|
17
|
-
*/
|
|
18
|
-
export declare const buildChildLists: (g: Graph, nClust: number, nvs: number, p: PackInfo) => ChildLists;
|
|
19
|
-
/**
|
|
20
|
-
* Apply putRects offsets to child bbs/coords; return union bounding box.
|
|
21
|
-
* @see lib/osage/osageinit.c:layout (offset application loop)
|
|
22
|
-
*/
|
|
23
|
-
export declare const applyOffsets: (lists: ChildLists, pts: Point[]) => Box;
|
|
24
|
-
/**
|
|
25
|
-
* Widen union bb if the graph label is wider than packed content.
|
|
26
|
-
* @see lib/osage/osageinit.c:layout (GD_label block)
|
|
27
|
-
*/
|
|
28
|
-
export declare const applyLabelExpansion: (g: Graph, total: number, u: Box) => Box;
|
|
29
|
-
/**
|
|
30
|
-
* Add margin and label-border padding to the union bounding box.
|
|
31
|
-
* @see lib/osage/osageinit.c:layout (margin/border block)
|
|
32
|
-
*/
|
|
33
|
-
export declare const addMarginAndBorder: (g: Graph, margin: number, u: Box) => Box;
|
|
34
|
-
/**
|
|
35
|
-
* Subtract union.ll from all child positions so this cluster's LL = (0,0).
|
|
36
|
-
* @see lib/osage/osageinit.c:layout (translate-to-origin loop)
|
|
37
|
-
*/
|
|
38
|
-
export declare const translateToOrigin: (lists: ChildLists, u: Box) => void;
|
|
39
|
-
/**
|
|
40
|
-
* Recursively pack all direct children (subclusters + loose nodes) of g.
|
|
41
|
-
* @see lib/osage/osageinit.c:layout
|
|
42
|
-
*/
|
|
43
|
-
export declare const osageLayoutRec: (g: Graph, depth: number) => void;
|
|
44
|
-
/**
|
|
45
|
-
* Convert cluster-relative coordinates to absolute root-relative coordinates.
|
|
46
|
-
* @see lib/osage/osageinit.c:reposition
|
|
47
|
-
*/
|
|
48
|
-
export declare const osageReposition: (g: Graph, depth: number) => void;
|
|
49
|
-
//# sourceMappingURL=layout.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/layout/osage/layout.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,YAAY,EAAE,UAAU,EAAE,CAAC;AAsB3B,6FAA6F;AAC7F,eAAO,MAAM,aAAa,GAAI,GAAG,KAAK,KAAG,QAMxC,CAAC;AAiCF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,GAAG,KAAK,EAAE,QAAQ,MAAM,EAAE,KAAK,MAAM,EAAE,GAAG,QAAQ,KAAG,UAMpF,CAAC;AAyBF;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,UAAU,EAAE,KAAK,KAAK,EAAE,KAAG,GAQ9D,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,GAAG,KAAK,EAAE,OAAO,MAAM,EAAE,GAAG,GAAG,KAAG,GAOrE,CAAC;AAKF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,GAAG,KAAK,EAAE,QAAQ,MAAM,EAAE,GAAG,GAAG,KAAG,GAInE,CAAC;AAeJ;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,UAAU,EAAE,GAAG,GAAG,KAAG,IAG7D,CAAC;AA6BF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,GAAG,KAAK,EAAE,OAAO,MAAM,KAAG,IAQxD,CAAC;AAqBF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,GAAG,KAAK,EAAE,OAAO,MAAM,KAAG,IASzD,CAAC"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { Box, Point } from '../../model/geom.js';
|
|
2
|
-
import { type PackInfo } from './types.js';
|
|
3
|
-
export declare function box(llx: number, lly: number, urx: number, ury: number): Box;
|
|
4
|
-
export declare function defaultPackInfo(overrides?: Partial<PackInfo>): PackInfo;
|
|
5
|
-
export declare function applyPlaces(bbs: Box[], places: Point[]): Box[];
|
|
6
|
-
export declare function assertNoOverlap(placed: Box[]): void;
|
|
7
|
-
//# sourceMappingURL=test-helpers.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"test-helpers.d.ts","sourceRoot":"","sources":["../../../src/layout/pack/test-helpers.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,KAAK,QAAQ,EAAY,MAAM,YAAY,CAAC;AAErD,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,GAAG,CAE3E;AAED,wBAAgB,eAAe,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAMvE;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,EAAE,CAK9D;AAOD,wBAAgB,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAUnD"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Internal tree node and construction helpers for the patchwork layout.
|
|
3
|
-
*
|
|
4
|
-
* Mirrors treenode_t and mkTree from lib/patchwork/patchwork.c.
|
|
5
|
-
*
|
|
6
|
-
* @see lib/patchwork/patchwork.c:treenode_t
|
|
7
|
-
* @see lib/patchwork/patchwork.c:mkTree
|
|
8
|
-
*/
|
|
9
|
-
import type { Graph } from '../../model/graph.js';
|
|
10
|
-
import type { Node } from '../../model/node.js';
|
|
11
|
-
import type { Rectangle } from './tree-map.js';
|
|
12
|
-
/** @see lib/patchwork/patchwork.c:treenode_t */
|
|
13
|
-
export interface TreeNode {
|
|
14
|
-
area: number;
|
|
15
|
-
childArea: number;
|
|
16
|
-
r: Rectangle;
|
|
17
|
-
leftChild: TreeNode | null;
|
|
18
|
-
rightSib: TreeNode | null;
|
|
19
|
-
kind: 'graph' | 'node';
|
|
20
|
-
ref: Graph | Node;
|
|
21
|
-
nChildren: number;
|
|
22
|
-
}
|
|
23
|
-
/** @see lib/patchwork/patchwork.c:getArea */
|
|
24
|
-
export declare function getArea(attrs: Map<string, string>): number;
|
|
25
|
-
/** @see lib/patchwork/patchwork.c:fullArea (mp parameter) */
|
|
26
|
-
export declare function getInset(attrs: Map<string, string>): number;
|
|
27
|
-
/** wid = 2*inset + sqrt(childArea), area = wid². @see lib/patchwork/patchwork.c:fullArea */
|
|
28
|
-
export declare function fullArea(childArea: number, inset: number): number;
|
|
29
|
-
/** Mutable accumulator used during tree construction. */
|
|
30
|
-
export interface ChildAccum {
|
|
31
|
-
first: TreeNode | null;
|
|
32
|
-
prev: TreeNode | null;
|
|
33
|
-
area: number;
|
|
34
|
-
nChildren: number;
|
|
35
|
-
}
|
|
36
|
-
/** Append all cluster children of g to accum. @see lib/patchwork/patchwork.c:mkTree */
|
|
37
|
-
export declare function appendClusters(g: Graph, sparent: Map<Node, Graph>, accum: ChildAccum): void;
|
|
38
|
-
/** Append unclaimed direct nodes of g to accum. @see lib/patchwork/patchwork.c:mkTree */
|
|
39
|
-
export declare function appendNodes(g: Graph, sparent: Map<Node, Graph>, accum: ChildAccum): void;
|
|
40
|
-
/**
|
|
41
|
-
* Recursively build the internal TreeNode tree from a Graph hierarchy.
|
|
42
|
-
* Nodes already owned by a cluster (sparent set) are skipped.
|
|
43
|
-
* @see lib/patchwork/patchwork.c:mkTree
|
|
44
|
-
*/
|
|
45
|
-
export declare function mkTree(g: Graph, sparent: Map<Node, Graph>): TreeNode;
|
|
46
|
-
//# sourceMappingURL=tree-node.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tree-node.d.ts","sourceRoot":"","sources":["../../../src/layout/patchwork/tree-node.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,gDAAgD;AAChD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,EAAE,SAAS,CAAC;IACb,SAAS,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IACvB,GAAG,EAAE,KAAK,GAAG,IAAI,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAQD,6CAA6C;AAC7C,wBAAgB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAK1D;AAED,6DAA6D;AAC7D,wBAAgB,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAK3D;AAED,4FAA4F;AAC5F,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGjE;AAED,yDAAyD;AACzD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,uFAAuF;AACvF,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAS3F;AAED,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAiBxF;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,QAAQ,CAmBpE"}
|
package/dist/xdot/lex.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Low-level lexer primitives for xdot attribute string parsing.
|
|
3
|
-
* Ported from ~/git/graphviz/lib/xdot/xdot.c helper functions.
|
|
4
|
-
*/
|
|
5
|
-
import type { XdotAlign, XdotRect, XdotPolyline } from "./types.js";
|
|
6
|
-
export type PR<T> = {
|
|
7
|
-
val: T;
|
|
8
|
-
pos: number;
|
|
9
|
-
} | null;
|
|
10
|
-
export declare function isWs(c: string): boolean;
|
|
11
|
-
export declare function isDigit(c: string): boolean;
|
|
12
|
-
export declare function isAlnum(c: string): boolean;
|
|
13
|
-
export declare function skipWs(s: string, pos: number): number;
|
|
14
|
-
export declare function consumeDigits(s: string, i: number): number;
|
|
15
|
-
export declare function parseReal(s: string, pos: number): PR<number>;
|
|
16
|
-
export declare function parseInt_(s: string, pos: number): PR<number>;
|
|
17
|
-
export declare function parseUInt_(s: string, pos: number): PR<number>;
|
|
18
|
-
export declare function parseRect(s: string, pos: number): PR<XdotRect>;
|
|
19
|
-
export declare function parsePolyline(s: string, pos: number): PR<XdotPolyline>;
|
|
20
|
-
export declare function parseString(s: string, pos: number): PR<string>;
|
|
21
|
-
export declare function parseAlign(s: string, pos: number): PR<XdotAlign>;
|
|
22
|
-
//# sourceMappingURL=lex.d.ts.map
|
package/dist/xdot/lex.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lex.d.ts","sourceRoot":"","sources":["../../src/xdot/lex.ts"],"names":[],"mappings":"AACA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAa,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/E,MAAM,MAAM,EAAE,CAAC,CAAC,IAAI;IAAE,GAAG,EAAE,CAAC,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC;AAKnD,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEvC;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAE1C;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAE1C;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGrD;AAKD,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAG1D;AAaD,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,CAU5D;AAKD,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,CAQ5D;AAKD,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,CAK7D;AAKD,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,QAAQ,CAAC,CAM9D;AAWD,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,CAUtE;AAUD,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,CAiB9D;AAKD,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,SAAS,CAAC,CAIhE"}
|
package/src/gvc/textlayout.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: EPL-2.0
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Text layout selection and measurement.
|
|
5
|
-
*
|
|
6
|
-
* Ports gvtextlayout_select and gvtextlayout from lib/gvc/gvtextlayout.c,
|
|
7
|
-
* simplified for the TypeScript model where the text-layout engine is always
|
|
8
|
-
* the context's registered TextMeasurer (no dynamic plugin loading).
|
|
9
|
-
*
|
|
10
|
-
* @see lib/gvc/gvtextlayout.c:gvtextlayout_select
|
|
11
|
-
* @see lib/gvc/gvtextlayout.c:gvtextlayout
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import type { GvcContext } from './context.js';
|
|
15
|
-
import type { TextMeasurer } from '../common/textmeasure.js';
|
|
16
|
-
import type { TextSpan } from '../common/emit-types.js';
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Return the text measurer registered on ctx.
|
|
20
|
-
*
|
|
21
|
-
* Replaces gvtextlayout_select / plugin load with direct access to the
|
|
22
|
-
* context's measurer, per AD-2 (static registration, no libltdl).
|
|
23
|
-
*
|
|
24
|
-
* @see lib/gvc/gvtextlayout.c:gvtextlayout_select
|
|
25
|
-
*/
|
|
26
|
-
export function selectTextLayout(ctx: GvcContext): TextMeasurer {
|
|
27
|
-
return ctx.textMeasurer;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Measure a text span and write the result into span.size.
|
|
32
|
-
*
|
|
33
|
-
* Mirrors gvtextlayout: calls the engine's textlayout method to populate
|
|
34
|
-
* the size field on the span. Falls back to 'Times-Roman' / 14pt when
|
|
35
|
-
* fontName or fontSize are unspecified.
|
|
36
|
-
*
|
|
37
|
-
* @see lib/gvc/gvtextlayout.c:gvtextlayout
|
|
38
|
-
*/
|
|
39
|
-
export function measure(span: TextSpan, ctx: GvcContext): void {
|
|
40
|
-
const fontName = span.fontName ?? 'Times-Roman';
|
|
41
|
-
const fontSize = span.fontSize > 0 ? span.fontSize : 14;
|
|
42
|
-
const size = ctx.textMeasurer.measure(span.str, fontName, fontSize);
|
|
43
|
-
span.size = { x: size.w, y: size.h };
|
|
44
|
-
}
|