@knowvah/dot-engine 1.2.2 → 1.2.4
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/cdt/bag.d.ts +6 -4
- package/dist/cdt/bag.d.ts.map +1 -1
- package/dist/common/arrows-shapes-poly.d.ts +1 -1
- package/dist/common/arrows-shapes-poly.d.ts.map +1 -1
- package/dist/common/arrows-shapes.d.ts +2 -2
- package/dist/common/arrows-shapes.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/index.js +2013 -2008
- package/dist/index.js.map +4 -4
- package/dist/layout/dot/edge-route-arrow.d.ts +8 -0
- package/dist/layout/dot/edge-route-arrow.d.ts.map +1 -1
- package/dist/model/geom.d.ts +5 -0
- package/dist/model/geom.d.ts.map +1 -1
- package/dist/render.js +95 -90
- package/dist/render.js.map +4 -4
- package/dist/xdot/parse.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/cdt/bag.ts +30 -52
- package/src/common/arrows-shapes-poly.ts +20 -1
- package/src/common/arrows-shapes.ts +6 -2
- 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/layout/dot/edge-route-arrow.ts +7 -2
- package/src/model/geom.ts +14 -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/index.js
CHANGED
|
@@ -4535,6 +4535,20 @@ function ccwrotatepf(p, ccwrot) {
|
|
|
4535
4535
|
return p;
|
|
4536
4536
|
}
|
|
4537
4537
|
}
|
|
4538
|
+
function cwrotatepf(p, cwrot) {
|
|
4539
|
+
switch (cwrot) {
|
|
4540
|
+
case 0:
|
|
4541
|
+
return p;
|
|
4542
|
+
case 90:
|
|
4543
|
+
return { x: p.y, y: -p.x };
|
|
4544
|
+
case 180:
|
|
4545
|
+
return { x: p.x, y: -p.y };
|
|
4546
|
+
case 270:
|
|
4547
|
+
return { x: p.y, y: p.x };
|
|
4548
|
+
default:
|
|
4549
|
+
return p;
|
|
4550
|
+
}
|
|
4551
|
+
}
|
|
4538
4552
|
function boxOverlap(b0, b1) {
|
|
4539
4553
|
return b0.ur.x >= b1.ll.x && b1.ur.x >= b0.ll.x && b0.ur.y >= b1.ll.y && b1.ur.y >= b0.ll.y;
|
|
4540
4554
|
}
|
|
@@ -10091,12 +10105,15 @@ function parseAttrs(raw) {
|
|
|
10091
10105
|
}
|
|
10092
10106
|
return out;
|
|
10093
10107
|
}
|
|
10108
|
+
function normalizeTag(tag) {
|
|
10109
|
+
return tag === "TH" ? "TR" : tag;
|
|
10110
|
+
}
|
|
10094
10111
|
function parseCloseToken(inner) {
|
|
10095
10112
|
const body = inner.slice(1).trim();
|
|
10096
10113
|
const sp = body.search(/\s/);
|
|
10097
10114
|
const tag = (sp === -1 ? body : body.slice(0, sp)).toUpperCase();
|
|
10098
10115
|
checkTag(tag);
|
|
10099
|
-
return { type: "close", tag };
|
|
10116
|
+
return { type: "close", tag: normalizeTag(tag) };
|
|
10100
10117
|
}
|
|
10101
10118
|
function cleanText(raw) {
|
|
10102
10119
|
const isKeep = (c) => c === " " || c === " " || c === "\n" || c === "\r";
|
|
@@ -10130,12 +10147,13 @@ function scanTag(src, start, tokens) {
|
|
|
10130
10147
|
function parseOpenToken(inner) {
|
|
10131
10148
|
const sp = inner.search(/\s/);
|
|
10132
10149
|
if (sp === -1) {
|
|
10133
|
-
|
|
10134
|
-
|
|
10150
|
+
const tag2 = inner.toUpperCase();
|
|
10151
|
+
checkTag(tag2);
|
|
10152
|
+
return { type: "open", tag: normalizeTag(tag2), attrs: parseAttrs("") };
|
|
10135
10153
|
}
|
|
10136
10154
|
const tag = inner.slice(0, sp).toUpperCase();
|
|
10137
10155
|
checkTag(tag);
|
|
10138
|
-
return { type: "open", tag, attrs: parseAttrs(inner.slice(sp + 1)) };
|
|
10156
|
+
return { type: "open", tag: normalizeTag(tag), attrs: parseAttrs(inner.slice(sp + 1)) };
|
|
10139
10157
|
}
|
|
10140
10158
|
function tokenize(src) {
|
|
10141
10159
|
const tokens = [];
|
|
@@ -10360,7 +10378,7 @@ var buildCell = (content, a) => ({
|
|
|
10360
10378
|
});
|
|
10361
10379
|
var parseCell = (s, attrs, fontStack) => buildCell(parseCellContent(s, attrs, fontStack), attrs);
|
|
10362
10380
|
var processRowToken = (s, t, cells, fontStack) => {
|
|
10363
|
-
if (t.type === "open" &&
|
|
10381
|
+
if (t.type === "open" && t.tag === "TD") {
|
|
10364
10382
|
consume(s);
|
|
10365
10383
|
cells.push(parseCell(s, t.attrs, fontStack));
|
|
10366
10384
|
return;
|
|
@@ -16866,1497 +16884,234 @@ function assembleResult(p, dimen, grown, fixedshape) {
|
|
|
16866
16884
|
};
|
|
16867
16885
|
}
|
|
16868
16886
|
|
|
16869
|
-
// src/
|
|
16870
|
-
var
|
|
16871
|
-
var
|
|
16872
|
-
var
|
|
16873
|
-
var
|
|
16874
|
-
var
|
|
16875
|
-
|
|
16876
|
-
|
|
16877
|
-
var TOP2 = 4;
|
|
16878
|
-
var LEFT2 = 8;
|
|
16879
|
-
var PAD_X = 16;
|
|
16880
|
-
var PAD_Y = 8;
|
|
16881
|
-
function makeField() {
|
|
16882
|
-
return {
|
|
16883
|
-
size: { x: 0, y: 0 },
|
|
16884
|
-
b: { ll: { x: 0, y: 0 }, ur: { x: 0, y: 0 } },
|
|
16885
|
-
n_flds: 0,
|
|
16886
|
-
lp: null,
|
|
16887
|
-
fld: null,
|
|
16888
|
-
id: null,
|
|
16889
|
-
LR: 0,
|
|
16890
|
-
sides: 0
|
|
16891
|
-
};
|
|
16887
|
+
// src/layout/dot/fastgr.ts
|
|
16888
|
+
var VIRTUAL = 1;
|
|
16889
|
+
var NORMAL = 0;
|
|
16890
|
+
var FLATORDER = 4;
|
|
16891
|
+
var REVERSED = 3;
|
|
16892
|
+
var MC_SCALE = 256;
|
|
16893
|
+
function elistAppend(el, e) {
|
|
16894
|
+
el.list[el.size++] = e;
|
|
16892
16895
|
}
|
|
16893
|
-
function
|
|
16894
|
-
|
|
16895
|
-
|
|
16896
|
-
|
|
16896
|
+
function zapinlist(el, e) {
|
|
16897
|
+
let i = 0;
|
|
16898
|
+
while (i < el.size && el.list[i] !== e) i++;
|
|
16899
|
+
if (i < el.size) {
|
|
16900
|
+
el.list[i] = el.list[--el.size];
|
|
16901
|
+
el.list[el.size] = void 0;
|
|
16902
|
+
}
|
|
16897
16903
|
}
|
|
16898
|
-
function
|
|
16899
|
-
|
|
16900
|
-
|
|
16901
|
-
|
|
16902
|
-
|
|
16903
|
-
|
|
16904
|
-
|
|
16904
|
+
function deleteFastEdge(e) {
|
|
16905
|
+
if (e.tail.info.out) zapinlist(e.tail.info.out, e);
|
|
16906
|
+
if (e.head.info.in) zapinlist(e.head.info.in, e);
|
|
16907
|
+
}
|
|
16908
|
+
function fastEdge(e) {
|
|
16909
|
+
if (!e.tail.info.out) e.tail.info.out = { list: [], size: 0 };
|
|
16910
|
+
if (!e.head.info.in) e.head.info.in = { list: [], size: 0 };
|
|
16911
|
+
elistAppend(e.tail.info.out, e);
|
|
16912
|
+
elistAppend(e.head.info.in, e);
|
|
16913
|
+
}
|
|
16914
|
+
function findFastEdge(u, v) {
|
|
16915
|
+
const uOut = u.info.out;
|
|
16916
|
+
const vIn = v.info.in;
|
|
16917
|
+
if (uOut === void 0 || vIn === void 0) return void 0;
|
|
16918
|
+
if (uOut.size <= vIn.size) {
|
|
16919
|
+
for (let i = 0; i < uOut.size; i++) {
|
|
16920
|
+
if (uOut.list[i].head === v) return uOut.list[i];
|
|
16921
|
+
}
|
|
16922
|
+
} else {
|
|
16923
|
+
for (let i = 0; i < vIn.size; i++) {
|
|
16924
|
+
if (vIn.list[i].tail === u) return vIn.list[i];
|
|
16905
16925
|
}
|
|
16906
|
-
const c = p.s[j];
|
|
16907
|
-
if (c === "{") cnt++;
|
|
16908
|
-
else if (c === "}") cnt--;
|
|
16909
|
-
else if (c === "|" && cnt === 0) maxf++;
|
|
16910
|
-
if (cnt < 0) break;
|
|
16911
16926
|
}
|
|
16912
|
-
return
|
|
16927
|
+
return void 0;
|
|
16913
16928
|
}
|
|
16914
|
-
function
|
|
16915
|
-
|
|
16916
|
-
|
|
16917
|
-
p.i++;
|
|
16918
|
-
st.pbuf = [];
|
|
16919
|
-
st.hspIdx = 0;
|
|
16920
|
-
return 0;
|
|
16929
|
+
function copyPort(p) {
|
|
16930
|
+
const bp = p.bp !== null ? { ll: { x: p.bp.ll.x, y: p.bp.ll.y }, ur: { x: p.bp.ur.x, y: p.bp.ur.y } } : null;
|
|
16931
|
+
return { p: { x: p.p.x, y: p.p.y }, theta: p.theta, bp, defined: p.defined, constrained: p.constrained, clip: p.clip, dyna: p.dyna, order: p.order, side: p.side, name: p.name };
|
|
16921
16932
|
}
|
|
16922
|
-
function
|
|
16923
|
-
if (
|
|
16924
|
-
|
|
16925
|
-
if (
|
|
16926
|
-
|
|
16927
|
-
st.mode &= ~INPORT;
|
|
16928
|
-
p.i++;
|
|
16929
|
-
return 0;
|
|
16933
|
+
function copyVirtualPorts(e, orig) {
|
|
16934
|
+
if (e.tail === orig.tail) e.info.tail_port = copyPort(orig.info.tail_port);
|
|
16935
|
+
else if (e.tail === orig.head) e.info.tail_port = copyPort(orig.info.head_port);
|
|
16936
|
+
if (e.head === orig.head) e.info.head_port = copyPort(orig.info.head_port);
|
|
16937
|
+
else if (e.head === orig.tail) e.info.head_port = copyPort(orig.info.tail_port);
|
|
16930
16938
|
}
|
|
16931
|
-
function
|
|
16932
|
-
|
|
16933
|
-
|
|
16934
|
-
|
|
16935
|
-
|
|
16936
|
-
|
|
16937
|
-
|
|
16938
|
-
|
|
16939
|
-
|
|
16939
|
+
function copyVirtualEdgeInfo(e, orig) {
|
|
16940
|
+
e.info.count = orig.info.count;
|
|
16941
|
+
e.info.xpenalty = orig.info.xpenalty;
|
|
16942
|
+
e.info.weight = orig.info.weight;
|
|
16943
|
+
e.info.minlen = orig.info.minlen;
|
|
16944
|
+
copyVirtualPorts(e, orig);
|
|
16945
|
+
e.info.label = orig.info.label;
|
|
16946
|
+
e.info.head_label = orig.info.head_label;
|
|
16947
|
+
e.info.tail_label = orig.info.tail_label;
|
|
16948
|
+
e.info.xlabel = orig.info.xlabel;
|
|
16949
|
+
if (orig.info.to_virt === void 0) orig.info.to_virt = e;
|
|
16950
|
+
e.info.to_orig = orig;
|
|
16951
|
+
e.seq = orig.seq;
|
|
16940
16952
|
}
|
|
16941
|
-
function
|
|
16942
|
-
|
|
16943
|
-
|
|
16944
|
-
|
|
16945
|
-
|
|
16946
|
-
|
|
16947
|
-
|
|
16948
|
-
|
|
16949
|
-
|
|
16950
|
-
|
|
16951
|
-
false,
|
|
16952
|
-
{ fontname: p.lbl.fontname, fontsize: p.lbl.fontsize, fontcolor: p.lbl.fontcolor },
|
|
16953
|
-
p.measurer,
|
|
16954
|
-
p.obj
|
|
16955
|
-
);
|
|
16956
|
-
st.fp.LR = 1;
|
|
16957
|
-
st.tbuf = [];
|
|
16958
|
-
st.hstIdx = 0;
|
|
16953
|
+
function newVirtualEdge(u, v, orig) {
|
|
16954
|
+
const e = new Edge(u, v, "");
|
|
16955
|
+
e.info.edge_type = VIRTUAL;
|
|
16956
|
+
if (orig) {
|
|
16957
|
+
copyVirtualEdgeInfo(e, orig);
|
|
16958
|
+
} else {
|
|
16959
|
+
e.info.weight = 1;
|
|
16960
|
+
e.info.xpenalty = 1;
|
|
16961
|
+
e.info.count = 1;
|
|
16962
|
+
e.info.minlen = 1;
|
|
16959
16963
|
}
|
|
16964
|
+
return e;
|
|
16960
16965
|
}
|
|
16961
|
-
function
|
|
16962
|
-
const
|
|
16963
|
-
|
|
16964
|
-
|
|
16965
|
-
st.fp = makeField();
|
|
16966
|
-
st.rv.fld[st.fi++] = st.fp;
|
|
16967
|
-
}
|
|
16968
|
-
if (st.tmpport !== null) {
|
|
16969
|
-
st.fp.id = st.tmpport;
|
|
16970
|
-
st.tmpport = null;
|
|
16971
|
-
}
|
|
16972
|
-
recFlushText(p, st);
|
|
16973
|
-
if (c !== "") {
|
|
16974
|
-
if (c === "}") {
|
|
16975
|
-
p.i++;
|
|
16976
|
-
st.rv.n_flds = st.fi;
|
|
16977
|
-
return 1;
|
|
16978
|
-
}
|
|
16979
|
-
st.mode = 0;
|
|
16980
|
-
p.i++;
|
|
16981
|
-
return 0;
|
|
16982
|
-
}
|
|
16983
|
-
st.rv.n_flds = st.fi;
|
|
16984
|
-
return 1;
|
|
16966
|
+
function virtualEdge(u, v, orig) {
|
|
16967
|
+
const e = newVirtualEdge(u, v, orig);
|
|
16968
|
+
fastEdge(e);
|
|
16969
|
+
return e;
|
|
16985
16970
|
}
|
|
16986
|
-
function
|
|
16987
|
-
|
|
16988
|
-
|
|
16989
|
-
|
|
16990
|
-
|
|
16991
|
-
st.ishardspace = true;
|
|
16992
|
-
} else {
|
|
16993
|
-
st.tbuf.push("\\");
|
|
16994
|
-
st.mode |= INTEXT | HASTEXT;
|
|
16995
|
-
}
|
|
16996
|
-
p.i++;
|
|
16997
|
-
}
|
|
16971
|
+
function mergeWeightsInto(f, ew, em, ex) {
|
|
16972
|
+
f.info.weight = (f.info.weight ?? 0) + ew;
|
|
16973
|
+
f.info.minlen = Math.max(f.info.minlen ?? 1, em);
|
|
16974
|
+
f.info.count = (f.info.count ?? 1) + 1;
|
|
16975
|
+
f.info.xpenalty = (f.info.xpenalty ?? 0) + ex;
|
|
16998
16976
|
}
|
|
16999
|
-
function
|
|
17000
|
-
const
|
|
17001
|
-
|
|
17002
|
-
|
|
16977
|
+
function basicMerge(e, rep) {
|
|
16978
|
+
const ew = e.info.weight ?? 1;
|
|
16979
|
+
const em = e.info.minlen ?? 1;
|
|
16980
|
+
const ex = e.info.xpenalty ?? 0;
|
|
16981
|
+
for (let f = rep; f !== void 0; f = f.info.to_virt) {
|
|
16982
|
+
mergeWeightsInto(f, ew, em, ex);
|
|
16983
|
+
}
|
|
17003
16984
|
}
|
|
17004
|
-
function
|
|
17005
|
-
|
|
17006
|
-
|
|
17007
|
-
|
|
16985
|
+
function mergeOneway(e, rep) {
|
|
16986
|
+
if (e.info.to_virt !== void 0) return;
|
|
16987
|
+
e.info.to_virt = rep;
|
|
16988
|
+
basicMerge(e, rep);
|
|
17008
16989
|
}
|
|
17009
|
-
function
|
|
17010
|
-
|
|
17011
|
-
if (
|
|
17012
|
-
if (
|
|
17013
|
-
else if (st.mode & INPORT) recPushPort(st, c);
|
|
17014
|
-
p.i++;
|
|
17015
|
-
return 0;
|
|
16990
|
+
function deleteFlatEdge(e) {
|
|
16991
|
+
e.info.to_virt = void 0;
|
|
16992
|
+
if (e.tail.info.flat_out) zapinlist(e.tail.info.flat_out, e);
|
|
16993
|
+
if (e.head.info.flat_in) zapinlist(e.head.info.flat_in, e);
|
|
17016
16994
|
}
|
|
17017
|
-
function
|
|
17018
|
-
|
|
17019
|
-
|
|
17020
|
-
|
|
17021
|
-
|
|
17022
|
-
|
|
17023
|
-
case ">":
|
|
17024
|
-
if (p.lbl.html) return recTextChar(p, st, c);
|
|
17025
|
-
return recClosePort(p, st);
|
|
17026
|
-
case "{":
|
|
17027
|
-
return recOpenTable(p, st, LR);
|
|
17028
|
-
case "}":
|
|
17029
|
-
case "|":
|
|
17030
|
-
case void 0:
|
|
17031
|
-
return recEndField(p, st, flag);
|
|
17032
|
-
case "\\":
|
|
17033
|
-
recBackslash(p, st);
|
|
17034
|
-
return recTextChar(p, st, p.s[p.i]);
|
|
17035
|
-
default:
|
|
17036
|
-
return recTextChar(p, st, c);
|
|
17037
|
-
}
|
|
16995
|
+
function flatEdge(g, e) {
|
|
16996
|
+
if (!e.tail.info.flat_out) e.tail.info.flat_out = { list: [], size: 0 };
|
|
16997
|
+
if (!e.head.info.flat_in) e.head.info.flat_in = { list: [], size: 0 };
|
|
16998
|
+
elistAppend(e.tail.info.flat_out, e);
|
|
16999
|
+
elistAppend(e.head.info.flat_in, e);
|
|
17000
|
+
g.info.has_flat_edges = true;
|
|
17038
17001
|
}
|
|
17039
|
-
function
|
|
17040
|
-
const
|
|
17041
|
-
|
|
17042
|
-
|
|
17043
|
-
|
|
17044
|
-
|
|
17045
|
-
|
|
17046
|
-
mode: 0,
|
|
17047
|
-
tbuf: [],
|
|
17048
|
-
hstIdx: 0,
|
|
17049
|
-
pbuf: [],
|
|
17050
|
-
hspIdx: 0,
|
|
17051
|
-
tmpport: null,
|
|
17052
|
-
ishardspace: false,
|
|
17053
|
-
fp: null
|
|
17054
|
-
};
|
|
17055
|
-
for (; ; ) {
|
|
17056
|
-
if (p.i < p.s.length && p.s[p.i] < " " && p.s[p.i] !== "") {
|
|
17057
|
-
p.i++;
|
|
17058
|
-
continue;
|
|
17002
|
+
function findFlatEdge(u, v) {
|
|
17003
|
+
const uOut = u.info.flat_out;
|
|
17004
|
+
const vIn = v.info.flat_in;
|
|
17005
|
+
if (uOut === void 0 || vIn === void 0) return void 0;
|
|
17006
|
+
if (uOut.size <= vIn.size) {
|
|
17007
|
+
for (let i = 0; i < uOut.size; i++) {
|
|
17008
|
+
if (uOut.list[i].head === v) return uOut.list[i];
|
|
17059
17009
|
}
|
|
17060
|
-
|
|
17061
|
-
|
|
17062
|
-
|
|
17063
|
-
if (p.i > p.s.length) break;
|
|
17064
|
-
}
|
|
17065
|
-
rv.n_flds = st.fi;
|
|
17066
|
-
return rv;
|
|
17067
|
-
}
|
|
17068
|
-
function recLabelDimen(n, g, f) {
|
|
17069
|
-
const dimen = { x: f.lp.dimen.x, y: f.lp.dimen.y };
|
|
17070
|
-
if (dimen.x > 0 || dimen.y > 0) {
|
|
17071
|
-
const m = nodeAttr(n, g, "margin");
|
|
17072
|
-
const parts = m !== void 0 ? m.split(",").map(parseFloat) : [];
|
|
17073
|
-
if (parts.length > 0 && !Number.isNaN(parts[0])) {
|
|
17074
|
-
dimen.x += 2 * parts[0] * 72;
|
|
17075
|
-
dimen.y += 2 * (parts.length > 1 && !Number.isNaN(parts[1]) ? parts[1] : parts[0]) * 72;
|
|
17076
|
-
} else {
|
|
17077
|
-
dimen.x += PAD_X;
|
|
17078
|
-
dimen.y += PAD_Y;
|
|
17010
|
+
} else {
|
|
17011
|
+
for (let i = 0; i < vIn.size; i++) {
|
|
17012
|
+
if (vIn.list[i].tail === u) return vIn.list[i];
|
|
17079
17013
|
}
|
|
17080
17014
|
}
|
|
17081
|
-
return
|
|
17015
|
+
return void 0;
|
|
17082
17016
|
}
|
|
17083
|
-
function
|
|
17084
|
-
|
|
17085
|
-
|
|
17086
|
-
|
|
17017
|
+
function reverseEdge(e) {
|
|
17018
|
+
deleteFastEdge(e);
|
|
17019
|
+
e.info.reversed = true;
|
|
17020
|
+
const f = findFastEdge(e.head, e.tail);
|
|
17021
|
+
if (f !== void 0) {
|
|
17022
|
+
mergeOneway(e, f);
|
|
17087
17023
|
} else {
|
|
17088
|
-
|
|
17089
|
-
for (let i = 0; i < f.n_flds; i++) {
|
|
17090
|
-
const d0 = sizeReclbl(n, g, f.fld[i]);
|
|
17091
|
-
if (f.LR) {
|
|
17092
|
-
d.x += d0.x;
|
|
17093
|
-
d.y = Math.max(d.y, d0.y);
|
|
17094
|
-
} else {
|
|
17095
|
-
d.y += d0.y;
|
|
17096
|
-
d.x = Math.max(d.x, d0.x);
|
|
17097
|
-
}
|
|
17098
|
-
}
|
|
17024
|
+
virtualEdge(e.head, e.tail, e);
|
|
17099
17025
|
}
|
|
17100
|
-
f.size = d;
|
|
17101
|
-
return d;
|
|
17102
17026
|
}
|
|
17103
|
-
function
|
|
17104
|
-
|
|
17105
|
-
|
|
17106
|
-
|
|
17107
|
-
|
|
17108
|
-
f.lp.space.y += d.y;
|
|
17109
|
-
}
|
|
17110
|
-
if (f.n_flds) {
|
|
17111
|
-
const inc2 = f.LR ? d.x / f.n_flds : d.y / f.n_flds;
|
|
17112
|
-
for (let i = 0; i < f.n_flds; i++) {
|
|
17113
|
-
const sf = f.fld[i];
|
|
17114
|
-
const amt = Math.trunc((i + 1) * inc2) - Math.trunc(i * inc2);
|
|
17115
|
-
const newsz = f.LR ? { x: sf.size.x + amt, y: sz.y } : { x: sz.x, y: sf.size.y + amt };
|
|
17116
|
-
resizeReclbl(sf, newsz, nojustify);
|
|
17117
|
-
}
|
|
17118
|
-
}
|
|
17027
|
+
function fastNode(g, n) {
|
|
17028
|
+
n.info.next = g.info.nlist;
|
|
17029
|
+
if (g.info.nlist !== void 0) g.info.nlist.info.prev = n;
|
|
17030
|
+
n.info.prev = void 0;
|
|
17031
|
+
g.info.nlist = n;
|
|
17119
17032
|
}
|
|
17120
|
-
function
|
|
17121
|
-
if (
|
|
17122
|
-
|
|
17123
|
-
|
|
17124
|
-
}
|
|
17125
|
-
if (i === 0) return i === last ? TOP2 | BOTTOM2 | RIGHT2 | LEFT2 : TOP2 | RIGHT2 | LEFT2;
|
|
17126
|
-
return i === last ? LEFT2 | BOTTOM2 | RIGHT2 : LEFT2 | RIGHT2;
|
|
17033
|
+
function deleteFastNode(g, n) {
|
|
17034
|
+
if (n.info.prev !== void 0) n.info.prev.info.next = n.info.next;
|
|
17035
|
+
else g.info.nlist = n.info.next;
|
|
17036
|
+
if (n.info.next !== void 0) n.info.next.info.prev = n.info.prev;
|
|
17127
17037
|
}
|
|
17128
|
-
function
|
|
17129
|
-
|
|
17130
|
-
|
|
17131
|
-
|
|
17132
|
-
|
|
17133
|
-
|
|
17134
|
-
|
|
17135
|
-
|
|
17136
|
-
|
|
17137
|
-
|
|
17138
|
-
|
|
17139
|
-
|
|
17140
|
-
|
|
17038
|
+
function removeFromRank(g, n) {
|
|
17039
|
+
const r = n.info.rank !== void 0 ? n.info.rank : 0;
|
|
17040
|
+
const rank3 = g.info.rank;
|
|
17041
|
+
if (rank3 === void 0) return;
|
|
17042
|
+
const rk = rank3[r];
|
|
17043
|
+
for (let j = 0; j < rk.n; j++) {
|
|
17044
|
+
const v = rk.v[j];
|
|
17045
|
+
if (v === n) {
|
|
17046
|
+
for (j++; j < rk.n; j++) {
|
|
17047
|
+
rk.v[j - 1] = rk.v[j];
|
|
17048
|
+
}
|
|
17049
|
+
rk.n--;
|
|
17050
|
+
break;
|
|
17051
|
+
}
|
|
17141
17052
|
}
|
|
17142
17053
|
}
|
|
17143
|
-
function
|
|
17144
|
-
const
|
|
17145
|
-
|
|
17146
|
-
|
|
17147
|
-
|
|
17054
|
+
function virtualNode(g) {
|
|
17055
|
+
const n = new Node(0, "", g.root);
|
|
17056
|
+
n.info.node_type = VIRTUAL;
|
|
17057
|
+
n.info.lw = 1;
|
|
17058
|
+
n.info.rw = 1;
|
|
17059
|
+
n.info.ht = 1;
|
|
17060
|
+
n.info.UF_size = 1;
|
|
17061
|
+
n.info.in = { list: [], size: 0 };
|
|
17062
|
+
n.info.out = { list: [], size: 0 };
|
|
17063
|
+
fastNode(g, n);
|
|
17064
|
+
return n;
|
|
17148
17065
|
}
|
|
17149
|
-
function
|
|
17150
|
-
|
|
17151
|
-
|
|
17152
|
-
return {
|
|
17153
|
-
x: (w !== void 0 ? parseFloat(w) : 0.75) * 72,
|
|
17154
|
-
y: (h !== void 0 ? parseFloat(h) : 0.5) * 72
|
|
17155
|
-
};
|
|
17066
|
+
function otherEdge(e) {
|
|
17067
|
+
if (!e.tail.info.other) e.tail.info.other = { list: [], size: 0 };
|
|
17068
|
+
elistAppend(e.tail.info.other, e);
|
|
17156
17069
|
}
|
|
17157
|
-
|
|
17158
|
-
|
|
17159
|
-
|
|
17160
|
-
|
|
17161
|
-
const
|
|
17162
|
-
return
|
|
17070
|
+
|
|
17071
|
+
// src/common/splines-geom.ts
|
|
17072
|
+
function approxEqPt(p, q, tol) {
|
|
17073
|
+
const dx = p.x - q.x;
|
|
17074
|
+
const dy = p.y - q.y;
|
|
17075
|
+
return dx * dx + dy * dy < tol * tol;
|
|
17163
17076
|
}
|
|
17164
|
-
function
|
|
17165
|
-
const
|
|
17166
|
-
const
|
|
17167
|
-
const
|
|
17168
|
-
|
|
17169
|
-
const
|
|
17170
|
-
|
|
17171
|
-
|
|
17172
|
-
|
|
17077
|
+
function evalBezier(sp, t, left, right) {
|
|
17078
|
+
const ab = { x: sp[0].x + t * (sp[1].x - sp[0].x), y: sp[0].y + t * (sp[1].y - sp[0].y) };
|
|
17079
|
+
const bc = { x: sp[1].x + t * (sp[2].x - sp[1].x), y: sp[1].y + t * (sp[2].y - sp[1].y) };
|
|
17080
|
+
const cd = { x: sp[2].x + t * (sp[3].x - sp[2].x), y: sp[2].y + t * (sp[3].y - sp[2].y) };
|
|
17081
|
+
const abbc = { x: ab.x + t * (bc.x - ab.x), y: ab.y + t * (bc.y - ab.y) };
|
|
17082
|
+
const bccd = { x: bc.x + t * (cd.x - bc.x), y: bc.y + t * (cd.y - bc.y) };
|
|
17083
|
+
const pt = { x: abbc.x + t * (bccd.x - abbc.x), y: abbc.y + t * (bccd.y - abbc.y) };
|
|
17084
|
+
if (left !== null) {
|
|
17085
|
+
left[0] = sp[0];
|
|
17086
|
+
left[1] = ab;
|
|
17087
|
+
left[2] = abbc;
|
|
17088
|
+
left[3] = pt;
|
|
17173
17089
|
}
|
|
17174
|
-
|
|
17175
|
-
|
|
17176
|
-
|
|
17177
|
-
|
|
17178
|
-
|
|
17179
|
-
|
|
17180
|
-
|
|
17181
|
-
n.info.ht = ns.ht;
|
|
17182
|
-
n.info.shape_info = info;
|
|
17090
|
+
if (right !== null) {
|
|
17091
|
+
right[0] = pt;
|
|
17092
|
+
right[1] = bccd;
|
|
17093
|
+
right[2] = cd;
|
|
17094
|
+
right[3] = sp[3];
|
|
17095
|
+
}
|
|
17096
|
+
return pt;
|
|
17183
17097
|
}
|
|
17184
|
-
|
|
17185
|
-
|
|
17186
|
-
|
|
17187
|
-
|
|
17098
|
+
var HW = 2;
|
|
17099
|
+
var SMALL = 1e-10;
|
|
17100
|
+
function ptToLine2(a, b, p) {
|
|
17101
|
+
const dx = b.x - a.x;
|
|
17102
|
+
const dy = b.y - a.y;
|
|
17103
|
+
let a2 = (p.y - a.y) * dx - (p.x - a.x) * dy;
|
|
17104
|
+
a2 *= a2;
|
|
17105
|
+
if (a2 < SMALL) return 0;
|
|
17106
|
+
return a2 / (dx * dx + dy * dy);
|
|
17188
17107
|
}
|
|
17189
|
-
function
|
|
17190
|
-
|
|
17191
|
-
|
|
17108
|
+
function checkControlPoints(cp) {
|
|
17109
|
+
const dis1 = ptToLine2(cp[0], cp[3], cp[1]);
|
|
17110
|
+
const dis2 = ptToLine2(cp[0], cp[3], cp[2]);
|
|
17111
|
+
return dis1 < HW * HW && dis2 < HW * HW;
|
|
17192
17112
|
}
|
|
17193
|
-
function
|
|
17194
|
-
|
|
17195
|
-
const coord = n.info.coord ?? { x: 0, y: 0 };
|
|
17196
|
-
if (f.lp) {
|
|
17197
|
-
const mid = {
|
|
17198
|
-
x: (f.b.ll.x + f.b.ur.x) / 2 + coord.x,
|
|
17199
|
-
y: (f.b.ll.y + f.b.ur.y) / 2 + coord.y
|
|
17200
|
-
};
|
|
17201
|
-
renderLabel(f.lp, mid, renderer, job);
|
|
17202
|
-
}
|
|
17203
|
-
for (let i = 0; i < f.n_flds; i++) {
|
|
17204
|
-
if (i > 0) genFieldSeparator(job, coord, f, f.fld[i]);
|
|
17205
|
-
genFields(job, n, f.fld[i]);
|
|
17206
|
-
}
|
|
17207
|
-
}
|
|
17208
|
-
function genFieldSeparator(job, coord, f, child) {
|
|
17209
|
-
const a = { x: 0, y: 0 };
|
|
17210
|
-
const b = { x: 0, y: 0 };
|
|
17211
|
-
if (f.LR) {
|
|
17212
|
-
a.x = child.b.ll.x;
|
|
17213
|
-
a.y = child.b.ll.y;
|
|
17214
|
-
b.x = a.x;
|
|
17215
|
-
b.y = child.b.ur.y;
|
|
17216
|
-
} else {
|
|
17217
|
-
b.x = child.b.ur.x;
|
|
17218
|
-
b.y = child.b.ur.y;
|
|
17219
|
-
a.x = child.b.ll.x;
|
|
17220
|
-
a.y = b.y;
|
|
17221
|
-
}
|
|
17222
|
-
const pts = [
|
|
17223
|
-
transformPoint({ x: a.x + coord.x, y: a.y + coord.y }, job),
|
|
17224
|
-
transformPoint({ x: b.x + coord.x, y: b.y + coord.y }, job)
|
|
17225
|
-
];
|
|
17226
|
-
job.renderer.polyline(pts, job);
|
|
17227
|
-
}
|
|
17228
|
-
function recordGencode(rawJob, rawNode) {
|
|
17229
|
-
const job = rawJob;
|
|
17230
|
-
const n = rawNode;
|
|
17231
|
-
if (!job.renderer) return;
|
|
17232
|
-
const f = n.info.shape_info;
|
|
17233
|
-
if (!f) return;
|
|
17234
|
-
const coord = n.info.coord ?? { x: 0, y: 0 };
|
|
17235
|
-
const ll = { x: f.b.ll.x + coord.x, y: f.b.ll.y + coord.y };
|
|
17236
|
-
const ur = { x: f.b.ur.x + coord.x, y: f.b.ur.y + coord.y };
|
|
17237
|
-
const filled = job.obj !== null && applyNodeStyle(job.obj, n, job);
|
|
17238
|
-
drawRecordBox(job, n, ll, ur, filled);
|
|
17239
|
-
genFields(job, n, f);
|
|
17240
|
-
}
|
|
17241
|
-
function drawRecordBox(job, n, ll, ur, filled) {
|
|
17242
|
-
const isMrecord = nodeAttr(n, n.root, "shape") === "Mrecord";
|
|
17243
|
-
const rounded = isMrecord || parseStyleFlags(nodeAttr(n, n.root, "style")).rounded;
|
|
17244
|
-
if (rounded) {
|
|
17245
|
-
const af = [{ x: ll.x, y: ll.y }, { x: ur.x, y: ll.y }, { x: ur.x, y: ur.y }, { x: ll.x, y: ur.y }];
|
|
17246
|
-
emitRoundedBezier(af, { x: 0, y: 0 }, filled, { renderer: job.renderer, job });
|
|
17247
|
-
return;
|
|
17248
|
-
}
|
|
17249
|
-
const pts = [{ x: ll.x, y: ll.y }, { x: ll.x, y: ur.y }, { x: ur.x, y: ur.y }, { x: ur.x, y: ll.y }].map((q) => transformPoint(q, job));
|
|
17250
|
-
job.renderer.polygon(pts, filled, job);
|
|
17251
|
-
}
|
|
17252
|
-
|
|
17253
|
-
// src/common/poly-init.ts
|
|
17254
|
-
var DEFAULT_LW = 27;
|
|
17255
|
-
var DEFAULT_RW = 27;
|
|
17256
|
-
var DEFAULT_HT = 36;
|
|
17257
|
-
function nodeAttr(n, g, key) {
|
|
17258
|
-
const own = n.attrs.get(key);
|
|
17259
|
-
if (own !== void 0) return own;
|
|
17260
|
-
if (n.nodeDefaultsSnapshot !== void 0) return n.nodeDefaultsSnapshot.get(key);
|
|
17261
|
-
return g.nodeDefaults.get(key) ?? (g !== g.root ? g.root.nodeDefaults.get(key) : void 0);
|
|
17262
|
-
}
|
|
17263
|
-
function readFontAttrs(n, g) {
|
|
17264
|
-
return {
|
|
17265
|
-
fontname: nodeAttr(n, g, "fontname") ?? DEFAULT_FONTNAME,
|
|
17266
|
-
fontsize: parseFloat(nodeAttr(n, g, "fontsize") ?? String(DEFAULT_FONTSIZE2)),
|
|
17267
|
-
fontcolor: nodeAttr(n, g, "fontcolor") ?? DEFAULT_COLOR2
|
|
17268
|
-
};
|
|
17269
|
-
}
|
|
17270
|
-
function assignShapeInfo(n, polyDesc) {
|
|
17271
|
-
const w = n.info.width !== void 0 ? n.info.width * 72 : (n.info.lw || DEFAULT_LW) + (n.info.rw || DEFAULT_RW);
|
|
17272
|
-
const h = n.info.height !== void 0 ? n.info.height * 72 : n.info.ht || DEFAULT_HT;
|
|
17273
|
-
const base = n.info.base_width !== void 0 && n.info.base_height !== void 0 ? { w: n.info.base_width * 72, h: n.info.base_height * 72 } : void 0;
|
|
17274
|
-
n.info.shape_info = {
|
|
17275
|
-
...polyDesc,
|
|
17276
|
-
vertices: computeVertices(polyDesc, w, h, base)
|
|
17277
|
-
};
|
|
17278
|
-
}
|
|
17279
|
-
function buildNodeLabel(n, g, measurer) {
|
|
17280
|
-
if (n.info.label !== void 0) return;
|
|
17281
|
-
const labelAttr = nodeAttr(n, g, "label");
|
|
17282
|
-
const font = readFontAttrs(n, g);
|
|
17283
|
-
const isHtml = labelAttr !== void 0 && isHtmlValue(labelAttr);
|
|
17284
|
-
const content = isHtml ? htmlValueContent(labelAttr) : labelAttr ?? n.name;
|
|
17285
|
-
n.info.label = makeAnyLabel(content, isHtml, font, measurer, n);
|
|
17286
|
-
}
|
|
17287
|
-
function polyInit(n, g, measurer) {
|
|
17288
|
-
const shapeName = nodeAttr(n, g, "shape") ?? "ellipse";
|
|
17289
|
-
const shapefile = nodeAttr(n, g, "shapefile");
|
|
17290
|
-
n.info.shape = bindShape(shapeName, shapefile);
|
|
17291
|
-
if (shapefile !== void 0 && shapefile !== "" && shapeName !== "epsf") {
|
|
17292
|
-
console.error(`Warning: No or improper shapefile="${shapefile}" for node "${n.name}"`);
|
|
17293
|
-
}
|
|
17294
|
-
if (n.info.shape.kind === 2 /* SH_RECORD */) {
|
|
17295
|
-
if (n.info.shape_info === void 0) recordNodeInit(n, g, measurer);
|
|
17296
|
-
return;
|
|
17297
|
-
}
|
|
17298
|
-
buildNodeLabel(n, g, measurer);
|
|
17299
|
-
if (n.info.shape_info !== void 0) return;
|
|
17300
|
-
const polyDesc = n.info.shape.polygon;
|
|
17301
|
-
if (polyDesc !== null) assignShapeInfo(n, polyDesc);
|
|
17302
|
-
}
|
|
17303
|
-
|
|
17304
|
-
// src/render/svg-multicolor.ts
|
|
17305
|
-
var THIN_LINE = 0.5;
|
|
17306
|
-
function rationalFunction(x, c) {
|
|
17307
|
-
return (x * (x * c[0] + c[1]) + c[2]) / (x + c[3]);
|
|
17308
|
-
}
|
|
17309
|
-
var COEFFS3LOW = [
|
|
17310
|
-
[
|
|
17311
|
-
[3.85268, -21.229, -0.330434, 0.0127842],
|
|
17312
|
-
[-1.61486, 0.706564, 0.225945, 0.263682],
|
|
17313
|
-
[-0.910164, 0.388383, 551445e-8, 671814e-8],
|
|
17314
|
-
[-0.630184, 0.192402, 98871e-7, 0.0102527]
|
|
17315
|
-
],
|
|
17316
|
-
[
|
|
17317
|
-
[-0.162211, 9.94329, 0.13723, 0.0124084],
|
|
17318
|
-
[-0.253135, 187735e-8, 0.0230286, 0.01264],
|
|
17319
|
-
[-0.0695069, -0.0437594, 0.0120636, 0.0163087],
|
|
17320
|
-
[-0.0328856, -926032e-8, -173573e-8, 527385e-8]
|
|
17321
|
-
]
|
|
17322
|
-
];
|
|
17323
|
-
var COEFFS3HIGH = [
|
|
17324
|
-
[
|
|
17325
|
-
[0.0899116, -19.2349, -4.11711, 0.183362],
|
|
17326
|
-
[0.138148, -1.45804, 1.32044, 1.38474],
|
|
17327
|
-
[0.230903, -0.450262, 0.219963, 0.414038],
|
|
17328
|
-
[0.0590565, -0.101062, 0.0430592, 0.0204699]
|
|
17329
|
-
],
|
|
17330
|
-
[
|
|
17331
|
-
[0.0164649, 9.89394, 0.0919496, 760802e-8],
|
|
17332
|
-
[0.0191603, -0.0322058, 0.0134667, -0.0825018],
|
|
17333
|
-
[0.0156192, -0.017535, 326508e-8, -0.228157],
|
|
17334
|
-
[-0.0236752, 0.0405821, -0.0173086, 0.176187]
|
|
17335
|
-
]
|
|
17336
|
-
];
|
|
17337
|
-
var SAFETY3 = [1e-3, 4.98, 0.207, 67e-4];
|
|
17338
|
-
function estimateError(a, b, etaA, etaB) {
|
|
17339
|
-
const eta = 0.5 * (etaA + etaB);
|
|
17340
|
-
const x = b / a;
|
|
17341
|
-
const dEta = etaB - etaA;
|
|
17342
|
-
const cos2 = Math.cos(2 * eta);
|
|
17343
|
-
const cos4 = Math.cos(4 * eta);
|
|
17344
|
-
const cos6 = Math.cos(6 * eta);
|
|
17345
|
-
const c = x < 0.25 ? COEFFS3LOW : COEFFS3HIGH;
|
|
17346
|
-
const c0 = rationalFunction(x, c[0][0]) + cos2 * rationalFunction(x, c[0][1]) + cos4 * rationalFunction(x, c[0][2]) + cos6 * rationalFunction(x, c[0][3]);
|
|
17347
|
-
const c1 = rationalFunction(x, c[1][0]) + cos2 * rationalFunction(x, c[1][1]) + cos4 * rationalFunction(x, c[1][2]) + cos6 * rationalFunction(x, c[1][3]);
|
|
17348
|
-
return rationalFunction(x, SAFETY3) * a * Math.exp(c0 + c1 * dEta);
|
|
17349
|
-
}
|
|
17350
|
-
function allSubdivsBelowThreshold(a, b, eta1, n, dEta) {
|
|
17351
|
-
let etaA = eta1;
|
|
17352
|
-
for (let i = 0; i < n; i++) {
|
|
17353
|
-
if (estimateError(a, b, etaA, etaA + dEta) > 1e-5) return false;
|
|
17354
|
-
etaA += dEta;
|
|
17355
|
-
}
|
|
17356
|
-
return true;
|
|
17357
|
-
}
|
|
17358
|
-
function numSubdivisions(a, b, eta1, eta2) {
|
|
17359
|
-
let n = 1;
|
|
17360
|
-
while (n < 1024) {
|
|
17361
|
-
const dEta = (eta2 - eta1) / n;
|
|
17362
|
-
if (dEta <= 0.5 * Math.PI && allSubdivsBelowThreshold(a, b, eta1, n, dEta)) break;
|
|
17363
|
-
n <<= 1;
|
|
17364
|
-
}
|
|
17365
|
-
return n;
|
|
17366
|
-
}
|
|
17367
|
-
function initArcPath(pts, e, eta1) {
|
|
17368
|
-
const cosE = Math.cos(eta1);
|
|
17369
|
-
const sinE = Math.sin(eta1);
|
|
17370
|
-
const xB = e.cx + e.xsemi * cosE;
|
|
17371
|
-
const yB = e.cy + e.ysemi * sinE;
|
|
17372
|
-
pts.push(
|
|
17373
|
-
{ x: e.cx, y: e.cy },
|
|
17374
|
-
{ x: e.cx, y: e.cy },
|
|
17375
|
-
{ x: xB, y: yB },
|
|
17376
|
-
{ x: xB, y: yB }
|
|
17377
|
-
);
|
|
17378
|
-
return { xB, yB, xBDot: -e.xsemi * sinE, yBDot: e.ysemi * cosE };
|
|
17379
|
-
}
|
|
17380
|
-
function stepBezier(pts, state3, e, sp) {
|
|
17381
|
-
const xA = state3.xB;
|
|
17382
|
-
const yA = state3.yB;
|
|
17383
|
-
const xADot = state3.xBDot;
|
|
17384
|
-
const yADot = state3.yBDot;
|
|
17385
|
-
const newEta = sp.etaB + sp.dEta;
|
|
17386
|
-
const cosE = Math.cos(newEta);
|
|
17387
|
-
const sinE = Math.sin(newEta);
|
|
17388
|
-
state3.xB = e.cx + e.xsemi * cosE;
|
|
17389
|
-
state3.yB = e.cy + e.ysemi * sinE;
|
|
17390
|
-
state3.xBDot = -e.xsemi * sinE;
|
|
17391
|
-
state3.yBDot = e.ysemi * cosE;
|
|
17392
|
-
pts.push({ x: xA + sp.alpha * xADot, y: yA + sp.alpha * yADot });
|
|
17393
|
-
pts.push({ x: state3.xB - sp.alpha * state3.xBDot, y: state3.yB - sp.alpha * state3.yBDot });
|
|
17394
|
-
pts.push({ x: state3.xB, y: state3.yB });
|
|
17395
|
-
return newEta;
|
|
17396
|
-
}
|
|
17397
|
-
function ellipticWedge(e, angle0, angle1) {
|
|
17398
|
-
const TWOPI2 = 2 * Math.PI;
|
|
17399
|
-
const eta1 = Math.atan2(Math.sin(angle0) / e.ysemi, Math.cos(angle0) / e.xsemi);
|
|
17400
|
-
let eta2 = Math.atan2(Math.sin(angle1) / e.ysemi, Math.cos(angle1) / e.xsemi);
|
|
17401
|
-
eta2 -= TWOPI2 * Math.floor((eta2 - eta1) / TWOPI2);
|
|
17402
|
-
if (angle1 - angle0 > Math.PI && eta2 - eta1 < Math.PI) eta2 += TWOPI2;
|
|
17403
|
-
const n = numSubdivisions(e.xsemi, e.ysemi, eta1, eta2);
|
|
17404
|
-
const dEta = (eta2 - eta1) / n;
|
|
17405
|
-
const t = Math.tan(0.5 * dEta);
|
|
17406
|
-
const alpha = Math.sin(dEta) * (Math.sqrt(4 + 3 * t * t) - 1) / 3;
|
|
17407
|
-
const pts = [];
|
|
17408
|
-
const state3 = initArcPath(pts, e, eta1);
|
|
17409
|
-
let sp = { etaB: eta1, dEta, alpha };
|
|
17410
|
-
for (let i = 0; i < n; i++) sp = { ...sp, etaB: stepBezier(pts, state3, e, sp) };
|
|
17411
|
-
pts.push({ x: state3.xB, y: state3.yB }, { x: e.cx, y: e.cy }, { x: e.cx, y: e.cy });
|
|
17412
|
-
return pts;
|
|
17413
|
-
}
|
|
17414
|
-
function drawWedge(seg2, e, ctx) {
|
|
17415
|
-
const TWOPI2 = 2 * Math.PI;
|
|
17416
|
-
const angle1 = seg2.isLast ? TWOPI2 : seg2.angle0 + TWOPI2 * seg2.t;
|
|
17417
|
-
const obj = ctx.job.obj;
|
|
17418
|
-
if (obj !== null) obj.fillColor = resolveRenderColor(seg2.color);
|
|
17419
|
-
const ptsUp = ellipticWedge(e, seg2.angle0, angle1);
|
|
17420
|
-
ctx.renderer.bezier(ptsUp.map((p) => ({ x: p.x, y: -p.y })), true, ctx.job);
|
|
17421
|
-
return angle1;
|
|
17422
|
-
}
|
|
17423
|
-
function wedgedEllipse(job, pf, clrs, renderer) {
|
|
17424
|
-
const { segs, error } = parseSegs(clrs);
|
|
17425
|
-
if (error === 1 || error === 2) return error;
|
|
17426
|
-
const ctrX = (pf[0].x + pf[1].x) / 2;
|
|
17427
|
-
const ctrY = (pf[0].y + pf[1].y) / 2;
|
|
17428
|
-
const e = {
|
|
17429
|
-
cx: ctrX,
|
|
17430
|
-
cy: -ctrY,
|
|
17431
|
-
xsemi: pf[1].x - ctrX,
|
|
17432
|
-
ysemi: Math.abs(pf[1].y - ctrY)
|
|
17433
|
-
};
|
|
17434
|
-
const ctx = { job, renderer };
|
|
17435
|
-
const obj = job.obj;
|
|
17436
|
-
const saved = obj !== null ? obj.penWidth : 1;
|
|
17437
|
-
if (obj !== null && saved > THIN_LINE) obj.penWidth = THIN_LINE;
|
|
17438
|
-
let angle0 = 0;
|
|
17439
|
-
for (let i = 0; i < segs.length; i++) {
|
|
17440
|
-
const s = segs[i];
|
|
17441
|
-
if (s.color === null) break;
|
|
17442
|
-
if (s.t > 0) {
|
|
17443
|
-
angle0 = drawWedge({ angle0, t: s.t, isLast: i + 1 === segs.length, color: s.color }, e, ctx);
|
|
17444
|
-
}
|
|
17445
|
-
}
|
|
17446
|
-
if (obj !== null && saved > THIN_LINE) obj.penWidth = saved;
|
|
17447
|
-
return error;
|
|
17448
|
-
}
|
|
17449
|
-
function drawBand(p, seg2, ctx) {
|
|
17450
|
-
const obj = ctx.job.obj;
|
|
17451
|
-
if (obj !== null) obj.fillColor = resolveRenderColor(seg2.color);
|
|
17452
|
-
p[1].x = p[2].x = seg2.isLast ? seg2.lastx : p[0].x + seg2.segWidth;
|
|
17453
|
-
ctx.renderer.polygon([...p], true, ctx.job);
|
|
17454
|
-
p[0].x = p[3].x = p[1].x;
|
|
17455
|
-
}
|
|
17456
|
-
function stripedBox(job, pts, clrs, rotate, renderer) {
|
|
17457
|
-
const { segs, error } = parseSegs(clrs);
|
|
17458
|
-
if (error === 1 || error === 2) return error;
|
|
17459
|
-
const p = rotate ? [{ ...pts[2] }, { ...pts[3] }, { ...pts[0] }, { ...pts[1] }] : [{ ...pts[0] }, { ...pts[1] }, { ...pts[2] }, { ...pts[3] }];
|
|
17460
|
-
const lastx = p[1].x;
|
|
17461
|
-
const xdelta = p[1].x - p[0].x;
|
|
17462
|
-
p[1].x = p[2].x = p[0].x;
|
|
17463
|
-
const ctx = { job, renderer };
|
|
17464
|
-
const obj = job.obj;
|
|
17465
|
-
const saved = obj !== null ? obj.penWidth : 1;
|
|
17466
|
-
if (obj !== null && saved > THIN_LINE) obj.penWidth = THIN_LINE;
|
|
17467
|
-
for (let i = 0; i < segs.length; i++) {
|
|
17468
|
-
const s = segs[i];
|
|
17469
|
-
if (s.color === null) break;
|
|
17470
|
-
if (s.t > 0) {
|
|
17471
|
-
drawBand(p, { color: s.color, isLast: i + 1 === segs.length, segWidth: xdelta * s.t, lastx }, ctx);
|
|
17472
|
-
}
|
|
17473
|
-
}
|
|
17474
|
-
if (obj !== null && saved > THIN_LINE) obj.penWidth = saved;
|
|
17475
|
-
return error;
|
|
17476
|
-
}
|
|
17477
|
-
|
|
17478
|
-
// src/render/xml-escape.ts
|
|
17479
|
-
var RE_DQUOTE = new RegExp('"', "g");
|
|
17480
|
-
var RE_SQUOTE = new RegExp("'", "g");
|
|
17481
|
-
var RE_AMP_NONENTITY = /&(?![A-Za-z]+;|#[0-9]+;|#x[0-9A-Fa-f]+;)/g;
|
|
17482
|
-
function escapeXml(s) {
|
|
17483
|
-
let r = s.replace(RE_AMP_NONENTITY, "&");
|
|
17484
|
-
r = r.replace(/</g, "<");
|
|
17485
|
-
r = r.replace(/>/g, ">");
|
|
17486
|
-
r = r.replace(RE_DQUOTE, """);
|
|
17487
|
-
r = r.replace(RE_SQUOTE, "'");
|
|
17488
|
-
return r;
|
|
17489
|
-
}
|
|
17490
|
-
function escapeXmlTitle(s) {
|
|
17491
|
-
let r = escapeXml(s);
|
|
17492
|
-
r = r.replace(/-/g, "-");
|
|
17493
|
-
r = r.replace(/ {2,}/g, (m) => " " + " ".repeat(m.length - 1));
|
|
17494
|
-
return r;
|
|
17495
|
-
}
|
|
17496
|
-
function escapeXmlText(s) {
|
|
17497
|
-
let r = escapeXml(s);
|
|
17498
|
-
r = r.replace(/-/g, "-");
|
|
17499
|
-
r = r.replace(/\n/g, " ");
|
|
17500
|
-
r = r.replace(/\r/g, " ");
|
|
17501
|
-
r = r.replace(/ {2,}/g, (m) => " " + " ".repeat(m.length - 1));
|
|
17502
|
-
return r;
|
|
17503
|
-
}
|
|
17504
|
-
|
|
17505
|
-
// src/gvc/device-cluster.ts
|
|
17506
|
-
function applyClusterGradient(obj, fill) {
|
|
17507
|
-
obj.fill = fill.kind === "radial" ? 3 /* Radial */ : 2 /* Linear */;
|
|
17508
|
-
obj.fillColor = resolveRenderColor(fill.fillColor);
|
|
17509
|
-
obj.stopColor = resolveRenderColor(fill.stopColor);
|
|
17510
|
-
obj.gradientFrac = fill.frac;
|
|
17511
|
-
obj.gradientAngle = fill.angle;
|
|
17512
|
-
}
|
|
17513
|
-
function clusterAttr(sg, key) {
|
|
17514
|
-
for (let g = sg; g !== null; g = g.parent) {
|
|
17515
|
-
const v = g.attrs.get(key);
|
|
17516
|
-
if (v !== void 0) return v;
|
|
17517
|
-
}
|
|
17518
|
-
return void 0;
|
|
17519
|
-
}
|
|
17520
|
-
function clusterStyle(sg) {
|
|
17521
|
-
return clusterAttr(sg, "style");
|
|
17522
|
-
}
|
|
17523
|
-
function clusterPeripheries(sg) {
|
|
17524
|
-
const raw = clusterAttr(sg, "peripheries");
|
|
17525
|
-
if (raw === void 0 || raw.length === 0) return 1;
|
|
17526
|
-
const v = parseInt(raw, 10);
|
|
17527
|
-
if (Number.isNaN(v)) return 1;
|
|
17528
|
-
return v < 0 ? 0 : v;
|
|
17529
|
-
}
|
|
17530
|
-
function applyClusterPenState(obj, sg) {
|
|
17531
|
-
const flags = parseStyleFlags(clusterStyle(sg));
|
|
17532
|
-
const pen = clusterAttr(sg, "pencolor") ?? clusterAttr(sg, "color");
|
|
17533
|
-
obj.penColor = clusterPeripheries(sg) === 0 ? resolveRenderColor("transparent") : resolveRenderColor(resolvePenColor(pen));
|
|
17534
|
-
obj.penWidth = resolvePenWidth(flags, clusterAttr(sg, "penwidth"));
|
|
17535
|
-
obj.pen = resolvePenType(flags);
|
|
17536
|
-
}
|
|
17537
|
-
function clusterAttrsOf(sg) {
|
|
17538
|
-
return {
|
|
17539
|
-
style: clusterStyle(sg),
|
|
17540
|
-
color: clusterAttr(sg, "color"),
|
|
17541
|
-
pencolor: clusterAttr(sg, "pencolor"),
|
|
17542
|
-
fillcolor: clusterAttr(sg, "fillcolor"),
|
|
17543
|
-
bgcolor: clusterAttr(sg, "bgcolor"),
|
|
17544
|
-
penwidth: clusterAttr(sg, "penwidth"),
|
|
17545
|
-
gradientangle: clusterAttr(sg, "gradientangle")
|
|
17546
|
-
};
|
|
17547
|
-
}
|
|
17548
|
-
function applyClusterObjState(sg, job) {
|
|
17549
|
-
const fillRes = resolveClusterFillEx(clusterAttrsOf(sg));
|
|
17550
|
-
if (job.obj === null) return false;
|
|
17551
|
-
const obj = job.obj;
|
|
17552
|
-
return withColorScheme(clusterAttr(sg, "colorscheme"), () => {
|
|
17553
|
-
applyClusterPenState(obj, sg);
|
|
17554
|
-
if (fillRes.kind === "none") {
|
|
17555
|
-
obj.fill = 0 /* None */;
|
|
17556
|
-
return false;
|
|
17557
|
-
}
|
|
17558
|
-
if (fillRes.kind === "solid") {
|
|
17559
|
-
obj.fill = 1 /* Solid */;
|
|
17560
|
-
obj.fillColor = resolveRenderColor(fillRes.color);
|
|
17561
|
-
return true;
|
|
17562
|
-
}
|
|
17563
|
-
applyClusterGradient(obj, fillRes);
|
|
17564
|
-
return true;
|
|
17565
|
-
});
|
|
17566
|
-
}
|
|
17567
|
-
|
|
17568
|
-
// src/render/svg-id.ts
|
|
17569
|
-
function svgClass(kind, classAttr) {
|
|
17570
|
-
return classAttr !== void 0 && classAttr.length > 0 ? 'class="' + kind + " " + escapeXmlTitle(classAttr) + '"' : 'class="' + kind + '"';
|
|
17571
|
-
}
|
|
17572
|
-
function svgNodeId(n, job) {
|
|
17573
|
-
return job.objId(n.attrs.get("id"), "node" + (n.id + 1));
|
|
17574
|
-
}
|
|
17575
|
-
function svgEdgeId(e, job) {
|
|
17576
|
-
return job.objId(e.attrs.get("id"), "edge" + e.graphSeq);
|
|
17577
|
-
}
|
|
17578
|
-
function svgClusterId(sg, job) {
|
|
17579
|
-
return job.objId(sg.attrs.get("id"), "clust" + sg.seq);
|
|
17580
|
-
}
|
|
17581
|
-
function svgGraphId(g, job) {
|
|
17582
|
-
return job.objId(g.attrs.get("id"), "graph0", true);
|
|
17583
|
-
}
|
|
17584
|
-
function svgNodeClass(n) {
|
|
17585
|
-
return svgClass("node", nodeAttr(n, n.root, "class"));
|
|
17586
|
-
}
|
|
17587
|
-
function svgEdgeClass(e) {
|
|
17588
|
-
return svgClass("edge", e.attrs.get("class"));
|
|
17589
|
-
}
|
|
17590
|
-
function svgClusterClass(sg) {
|
|
17591
|
-
return svgClass("cluster", clusterAttr(sg, "class"));
|
|
17592
|
-
}
|
|
17593
|
-
function svgGraphClass(g) {
|
|
17594
|
-
return svgClass("graph", g.attrs.get("class"));
|
|
17595
|
-
}
|
|
17596
|
-
|
|
17597
|
-
// src/common/poly-gencode.ts
|
|
17598
|
-
function isMulticolor(fillcolor) {
|
|
17599
|
-
return fillcolor.includes(":");
|
|
17600
|
-
}
|
|
17601
|
-
function renderEllipse(ring, coord, renderer, job, filled) {
|
|
17602
|
-
const rx = Math.abs((ring[1].x - ring[0].x) / 2);
|
|
17603
|
-
const ry = Math.abs((ring[1].y - ring[0].y) / 2);
|
|
17604
|
-
const center = transformPoint(coord, job);
|
|
17605
|
-
renderer.ellipse(center, rx, ry, filled, job);
|
|
17606
|
-
}
|
|
17607
|
-
function renderPolygon(ring, coord, renderer, job, filled) {
|
|
17608
|
-
const pts = ring.map((v) => transformPoint({ x: v.x + coord.x, y: v.y + coord.y }, job));
|
|
17609
|
-
renderer.polygon(pts, filled, job);
|
|
17610
|
-
}
|
|
17611
|
-
function renderEllipseRing(ring, coord, filled, j, ctx) {
|
|
17612
|
-
if (ctx.style.wedged && j === 0 && isMulticolor(ctx.fillcolor)) {
|
|
17613
|
-
const pf = ring.map(
|
|
17614
|
-
(v) => transformPoint({ x: v.x + coord.x, y: v.y + coord.y }, ctx.job)
|
|
17615
|
-
);
|
|
17616
|
-
wedgedEllipse(ctx.job, pf, ctx.fillcolor, ctx.renderer);
|
|
17617
|
-
renderEllipse(ring, coord, ctx.renderer, ctx.job, false);
|
|
17618
|
-
} else {
|
|
17619
|
-
renderEllipse(ring, coord, ctx.renderer, ctx.job, filled);
|
|
17620
|
-
}
|
|
17621
|
-
if (ctx.diagonals) mcircleHack(ring, coord, ctx);
|
|
17622
|
-
}
|
|
17623
|
-
function renderStripedRing(ring, coord, ctx) {
|
|
17624
|
-
const af = ring.map((v) => transformPoint({ x: v.x + coord.x, y: v.y + coord.y }, ctx.job));
|
|
17625
|
-
stripedBox(ctx.job, af, ctx.fillcolor, true, ctx.renderer);
|
|
17626
|
-
renderPolygon(ring, coord, ctx.renderer, ctx.job, false);
|
|
17627
|
-
}
|
|
17628
|
-
function renderPolyRing(ring, coord, filled, j, ctx) {
|
|
17629
|
-
if (ctx.style.striped && j === 0) renderStripedRing(ring, coord, ctx);
|
|
17630
|
-
else if (ctx.underline) underlineDraw(ring, coord, filled, ctx);
|
|
17631
|
-
else if (ctx.shape !== 0 && ctx.shape !== STAR || ctx.diagonals || ctx.rounded) {
|
|
17632
|
-
drawRoundCorners(ring, coord, filled, ctx);
|
|
17633
|
-
} else renderPolygon(ring, coord, ctx.renderer, ctx.job, filled);
|
|
17634
|
-
}
|
|
17635
|
-
function renderPeripheries(poly, coord, filled, ctx) {
|
|
17636
|
-
const sides = poly.sides <= 2 ? 2 : poly.sides;
|
|
17637
|
-
const verts = poly.vertices;
|
|
17638
|
-
for (let j = 0; j < poly.peripheries; j++) {
|
|
17639
|
-
const ring = verts.slice(j * sides, (j + 1) * sides);
|
|
17640
|
-
if (ring.length < sides) break;
|
|
17641
|
-
const ringFilled = j === 0 ? filled : false;
|
|
17642
|
-
if (poly.sides <= 2) {
|
|
17643
|
-
renderEllipseRing(ring, coord, ringFilled, j, ctx);
|
|
17644
|
-
} else {
|
|
17645
|
-
renderPolyRing(ring, coord, ringFilled, j, ctx);
|
|
17646
|
-
}
|
|
17647
|
-
}
|
|
17648
|
-
}
|
|
17649
|
-
function renderLabel(label, coord, renderer, job) {
|
|
17650
|
-
if (label.u.kind !== "txt" || label.u.nspans < 1) return;
|
|
17651
|
-
label.pos = coord;
|
|
17652
|
-
label.set = true;
|
|
17653
|
-
const VALIGN_TOP2 = "t".charCodeAt(0);
|
|
17654
|
-
const VALIGN_BOTTOM2 = "b".charCodeAt(0);
|
|
17655
|
-
let py = label.valign === VALIGN_TOP2 ? coord.y + label.space.y / 2 - label.fontsize : label.valign === VALIGN_BOTTOM2 ? coord.y - label.space.y / 2 + label.dimen.y - label.fontsize : coord.y + label.dimen.y / 2 - label.fontsize;
|
|
17656
|
-
for (let i = 0; i < label.u.nspans; i++) {
|
|
17657
|
-
const span = label.u.span[i];
|
|
17658
|
-
const px = span.just === "l" ? coord.x - label.space.x / 2 : span.just === "r" ? coord.x + label.space.x / 2 : coord.x;
|
|
17659
|
-
gvrenderTextspan(renderer, { x: px, y: py }, span, job);
|
|
17660
|
-
py -= span.size.y;
|
|
17661
|
-
}
|
|
17662
|
-
}
|
|
17663
|
-
function renderNodeLabel(n, coord, renderer, job) {
|
|
17664
|
-
const label = n.info.label;
|
|
17665
|
-
if (label === void 0) return;
|
|
17666
|
-
if (label.html && label.u.kind === "html") {
|
|
17667
|
-
label.pos = coord;
|
|
17668
|
-
label.set = true;
|
|
17669
|
-
const html = label.u.html;
|
|
17670
|
-
withLabelEmitState(job, () => emitHtmlLabel(html, coord, renderer, job));
|
|
17671
|
-
} else {
|
|
17672
|
-
renderLabel(label, coord, renderer, job);
|
|
17673
|
-
}
|
|
17674
|
-
}
|
|
17675
|
-
function anchorAttr2(n, key) {
|
|
17676
|
-
const v = nodeAttr(n, n.root, key);
|
|
17677
|
-
return v !== void 0 && v !== "" ? v : void 0;
|
|
17678
|
-
}
|
|
17679
|
-
function resolveTooltip(n, tooltip) {
|
|
17680
|
-
if (tooltip !== void 0) return substObjAnchor(interpretCRNL(tooltip), n);
|
|
17681
|
-
const label = n.info.label;
|
|
17682
|
-
return label?.text ?? "";
|
|
17683
|
-
}
|
|
17684
|
-
function beginNodeAnchor(n, renderer, job) {
|
|
17685
|
-
const url = anchorAttr2(n, "href") ?? anchorAttr2(n, "URL");
|
|
17686
|
-
const tooltip = anchorAttr2(n, "tooltip");
|
|
17687
|
-
if (url === void 0 && tooltip === void 0) return false;
|
|
17688
|
-
renderer.beginAnchor?.(
|
|
17689
|
-
url !== void 0 ? substObjAnchor(url, n) : "",
|
|
17690
|
-
resolveTooltip(n, tooltip),
|
|
17691
|
-
anchorAttr2(n, "target") ?? "",
|
|
17692
|
-
svgNodeId(n, job),
|
|
17693
|
-
job
|
|
17694
|
-
);
|
|
17695
|
-
return true;
|
|
17696
|
-
}
|
|
17697
|
-
function applyGradientFields(obj, fill) {
|
|
17698
|
-
obj.fill = fill.kind === "radial" ? 3 /* Radial */ : 2 /* Linear */;
|
|
17699
|
-
obj.fillColor = resolveRenderColor(fill.fillColor);
|
|
17700
|
-
obj.stopColor = resolveRenderColor(fill.stopColor);
|
|
17701
|
-
obj.gradientFrac = fill.frac;
|
|
17702
|
-
obj.gradientAngle = fill.angle;
|
|
17703
|
-
}
|
|
17704
|
-
function isPointNode(n) {
|
|
17705
|
-
return n.info.shape?.kind === 3 /* SH_POINT */;
|
|
17706
|
-
}
|
|
17707
|
-
function findFillDflt(n) {
|
|
17708
|
-
const fillcolor = nodeAttr(n, n.root, "fillcolor");
|
|
17709
|
-
if (fillcolor !== void 0 && fillcolor !== "") return fillcolor;
|
|
17710
|
-
const color = nodeAttr(n, n.root, "color");
|
|
17711
|
-
if (color !== void 0 && color !== "") return color;
|
|
17712
|
-
return "black";
|
|
17713
|
-
}
|
|
17714
|
-
function applyFillState(obj, n, job) {
|
|
17715
|
-
obj.id = svgNodeId(n, job);
|
|
17716
|
-
if (isPointNode(n)) {
|
|
17717
|
-
obj.fill = 1 /* Solid */;
|
|
17718
|
-
obj.fillColor = resolveRenderColor(findFillDflt(n));
|
|
17719
|
-
return true;
|
|
17720
|
-
}
|
|
17721
|
-
const fillRes = resolveNodeFillEx({
|
|
17722
|
-
style: nodeAttr(n, n.root, "style"),
|
|
17723
|
-
fillcolor: nodeAttr(n, n.root, "fillcolor"),
|
|
17724
|
-
color: nodeAttr(n, n.root, "color"),
|
|
17725
|
-
gradientangle: nodeAttr(n, n.root, "gradientangle")
|
|
17726
|
-
});
|
|
17727
|
-
if (fillRes.kind === "none") {
|
|
17728
|
-
obj.fill = 0 /* None */;
|
|
17729
|
-
return false;
|
|
17730
|
-
}
|
|
17731
|
-
if (fillRes.kind === "solid") {
|
|
17732
|
-
obj.fill = 1 /* Solid */;
|
|
17733
|
-
obj.fillColor = resolveRenderColor(fillRes.color);
|
|
17734
|
-
return true;
|
|
17735
|
-
}
|
|
17736
|
-
applyGradientFields(obj, fillRes);
|
|
17737
|
-
return true;
|
|
17738
|
-
}
|
|
17739
|
-
function applyPenState(obj, styleAttr, colorAttr, penwidthAttr) {
|
|
17740
|
-
const flags = parseStyleFlags(styleAttr);
|
|
17741
|
-
obj.penColor = resolveRenderColor(resolvePenColor(colorAttr));
|
|
17742
|
-
obj.pen = resolvePenType(flags);
|
|
17743
|
-
obj.penWidth = resolvePenWidth(flags, penwidthAttr);
|
|
17744
|
-
obj.rawStyle = styleTokens(styleAttr);
|
|
17745
|
-
}
|
|
17746
|
-
function applyNodeStyle(obj, n, job) {
|
|
17747
|
-
const styleAttr = nodeAttr(n, n.root, "style");
|
|
17748
|
-
const colorAttr = nodeAttr(n, n.root, "color");
|
|
17749
|
-
const filled = applyFillState(obj, n, job);
|
|
17750
|
-
applyPenState(obj, styleAttr, colorAttr, nodeAttr(n, n.root, "penwidth"));
|
|
17751
|
-
return filled;
|
|
17752
|
-
}
|
|
17753
|
-
function prepareDrawPoly(poly, filled, obj) {
|
|
17754
|
-
if (poly.peripheries !== 0 || !filled) return poly;
|
|
17755
|
-
obj.penColor = { type: "string", s: "transparent" };
|
|
17756
|
-
return { ...poly, peripheries: 1 };
|
|
17757
|
-
}
|
|
17758
|
-
function vertexScale(n, poly) {
|
|
17759
|
-
const info = n.info;
|
|
17760
|
-
if (poly.vertices == null || info.width === void 0 || info.height === void 0) {
|
|
17761
|
-
return poly;
|
|
17762
|
-
}
|
|
17763
|
-
const xsize = (info.lw + info.rw) / (info.width * 72);
|
|
17764
|
-
const ysize = info.ht / (info.height * 72);
|
|
17765
|
-
if (Math.abs(xsize - 1) < 1e-9 && Math.abs(ysize - 1) < 1e-9) return poly;
|
|
17766
|
-
return {
|
|
17767
|
-
...poly,
|
|
17768
|
-
vertices: poly.vertices.map((v) => ({ x: v.x * xsize, y: v.y * ysize }))
|
|
17769
|
-
};
|
|
17770
|
-
}
|
|
17771
|
-
function resolveNodeDrawCtx(job, n) {
|
|
17772
|
-
const rawPoly = n.info.shape_info;
|
|
17773
|
-
if (rawPoly === void 0 || rawPoly.vertices === void 0) return null;
|
|
17774
|
-
const poly = vertexScale(n, rawPoly);
|
|
17775
|
-
const coord = n.info.coord ?? { x: 0, y: 0 };
|
|
17776
|
-
const obj = job.obj;
|
|
17777
|
-
const filled = obj !== null && applyNodeStyle(obj, n, job);
|
|
17778
|
-
const drawPoly = obj !== null ? prepareDrawPoly(poly, filled, obj) : poly;
|
|
17779
|
-
const styleFlags = parseStyleFlags(nodeAttr(n, n.root, "style"));
|
|
17780
|
-
const ringCtx = {
|
|
17781
|
-
renderer: job.renderer,
|
|
17782
|
-
job,
|
|
17783
|
-
style: styleFlags,
|
|
17784
|
-
fillcolor: nodeAttr(n, n.root, "fillcolor") ?? "",
|
|
17785
|
-
...specialCornerFlags(drawPoly.option, styleFlags)
|
|
17786
|
-
};
|
|
17787
|
-
return { poly: drawPoly, coord, filled, ringCtx };
|
|
17788
|
-
}
|
|
17789
|
-
function specialCornerFlags(opt, style) {
|
|
17790
|
-
return {
|
|
17791
|
-
shape: opt.shape,
|
|
17792
|
-
diagonals: opt.diagonals || style.diagonals,
|
|
17793
|
-
rounded: opt.rounded || style.rounded,
|
|
17794
|
-
underline: opt.underline || style.underline
|
|
17795
|
-
};
|
|
17796
|
-
}
|
|
17797
|
-
function polyGencode(rawJob, rawNode) {
|
|
17798
|
-
const job = rawJob;
|
|
17799
|
-
const n = rawNode;
|
|
17800
|
-
const renderer = job.renderer;
|
|
17801
|
-
if (!renderer) return;
|
|
17802
|
-
const ctx = resolveNodeDrawCtx(job, n);
|
|
17803
|
-
if (ctx === null) return;
|
|
17804
|
-
const clustersLast = (job.flags & EMIT_CLUSTERS_LAST) !== 0;
|
|
17805
|
-
const savedShape = job.obj?.urlMapShape;
|
|
17806
|
-
const savedPts = job.obj?.urlMapPts;
|
|
17807
|
-
let inAnchor = clustersLast ? false : beginNodeAnchor(n, renderer, job);
|
|
17808
|
-
renderPeripheries(ctx.poly, ctx.coord, ctx.filled, ctx.ringCtx);
|
|
17809
|
-
if (!isPointNode(n)) renderNodeLabel(n, ctx.coord, renderer, job);
|
|
17810
|
-
if (clustersLast) {
|
|
17811
|
-
if (job.obj && savedPts !== void 0 && savedShape !== void 0) {
|
|
17812
|
-
job.obj.urlMapShape = savedShape;
|
|
17813
|
-
job.obj.urlMapPts = savedPts;
|
|
17814
|
-
}
|
|
17815
|
-
inAnchor = beginNodeAnchor(n, renderer, job);
|
|
17816
|
-
}
|
|
17817
|
-
if (inAnchor) renderer.endAnchor?.(job);
|
|
17818
|
-
}
|
|
17819
|
-
|
|
17820
|
-
// src/common/poly-inside.ts
|
|
17821
|
-
function sameSide(p0, p1, L0, L1) {
|
|
17822
|
-
const a = -(L1.y - L0.y);
|
|
17823
|
-
const b = L1.x - L0.x;
|
|
17824
|
-
const c = a * L0.x + b * L0.y;
|
|
17825
|
-
const s0 = a * p0.x + b * p0.y - c >= 0;
|
|
17826
|
-
const s1 = a * p1.x + b * p1.y - c >= 0;
|
|
17827
|
-
return s0 === s1;
|
|
17828
|
-
}
|
|
17829
|
-
function fixedShapeSize(poly) {
|
|
17830
|
-
let xmax = 0;
|
|
17831
|
-
let ymax = 0;
|
|
17832
|
-
for (const v of poly.vertices ?? []) {
|
|
17833
|
-
xmax = Math.max(xmax, Math.abs(v.x));
|
|
17834
|
-
ymax = Math.max(ymax, Math.abs(v.y));
|
|
17835
|
-
}
|
|
17836
|
-
return { w: 2 * xmax, h: 2 * ymax };
|
|
17837
|
-
}
|
|
17838
|
-
function insideDims(n, xsize, ysize) {
|
|
17839
|
-
const w = 72 * (n.info.width || xsize / 72);
|
|
17840
|
-
const h = 72 * (n.info.height || ysize / 72);
|
|
17841
|
-
return { w, h, ow: 72 * n.info.outline_width || w, oh: 72 * n.info.outline_height || h };
|
|
17842
|
-
}
|
|
17843
|
-
function insideScale(n, poly) {
|
|
17844
|
-
const flip = n.root.info.flip === true;
|
|
17845
|
-
if (poly.option.fixedshape) {
|
|
17846
|
-
const { w: w2, h: h2 } = fixedShapeSize(poly);
|
|
17847
|
-
const xsize2 = flip ? h2 : w2;
|
|
17848
|
-
const ysize2 = flip ? w2 : h2;
|
|
17849
|
-
return {
|
|
17850
|
-
scalex: xsize2 !== 0 ? w2 / xsize2 : w2,
|
|
17851
|
-
scaley: ysize2 !== 0 ? h2 / ysize2 : h2,
|
|
17852
|
-
boxURx: w2 / 2,
|
|
17853
|
-
boxURy: h2 / 2
|
|
17854
|
-
};
|
|
17855
|
-
}
|
|
17856
|
-
const lwrw = n.info.lw + n.info.rw;
|
|
17857
|
-
const xsize = flip ? n.info.ht : lwrw;
|
|
17858
|
-
const ysize = flip ? lwrw : n.info.ht;
|
|
17859
|
-
const { w, h, ow, oh } = insideDims(n, xsize, ysize);
|
|
17860
|
-
return {
|
|
17861
|
-
scalex: xsize !== 0 ? w / xsize : w,
|
|
17862
|
-
scaley: ysize !== 0 ? h / ysize : h,
|
|
17863
|
-
boxURx: ow / 2,
|
|
17864
|
-
boxURy: oh / 2
|
|
17865
|
-
};
|
|
17866
|
-
}
|
|
17867
|
-
function polygonWalk(P, vertex, sides) {
|
|
17868
|
-
const O = { x: 0, y: 0 };
|
|
17869
|
-
let i = 0;
|
|
17870
|
-
let i1 = 1 % sides;
|
|
17871
|
-
const Q = vertex[i];
|
|
17872
|
-
const R2 = vertex[i1];
|
|
17873
|
-
if (!sameSide(P, O, Q, R2)) return false;
|
|
17874
|
-
const s = sameSide(P, Q, R2, O);
|
|
17875
|
-
if (s && sameSide(P, R2, O, Q)) return true;
|
|
17876
|
-
for (let j = 1; j < sides; j++) {
|
|
17877
|
-
if (s) {
|
|
17878
|
-
i = i1;
|
|
17879
|
-
i1 = (i + 1) % sides;
|
|
17880
|
-
} else {
|
|
17881
|
-
i1 = i;
|
|
17882
|
-
i = (i + sides - 1) % sides;
|
|
17883
|
-
}
|
|
17884
|
-
if (!sameSide(P, O, vertex[i], vertex[i1])) return false;
|
|
17885
|
-
}
|
|
17886
|
-
return true;
|
|
17887
|
-
}
|
|
17888
|
-
function insideShape(n, poly, p) {
|
|
17889
|
-
const sc = insideScale(n, poly);
|
|
17890
|
-
const P = { x: p.x * sc.scalex, y: p.y * sc.scaley };
|
|
17891
|
-
if (Math.abs(P.x) > sc.boxURx || Math.abs(P.y) > sc.boxURy) return false;
|
|
17892
|
-
if (poly.sides <= 2) {
|
|
17893
|
-
return Math.hypot(P.x / sc.boxURx, P.y / sc.boxURy) < 1;
|
|
17894
|
-
}
|
|
17895
|
-
const outerStart = (Math.max(poly.peripheries, 1) - 1) * poly.sides;
|
|
17896
|
-
const outer = poly.vertices.slice(outerStart, outerStart + poly.sides);
|
|
17897
|
-
const ring = polygonOutlineRing(outer, poly.sides, poly.penwidth ?? 1);
|
|
17898
|
-
return polygonWalk(P, ring, poly.sides);
|
|
17899
|
-
}
|
|
17900
|
-
function polyInside(ctx, p) {
|
|
17901
|
-
const n = ctx.node;
|
|
17902
|
-
if (n === void 0) return false;
|
|
17903
|
-
const rankdir = (n.root.info.rankdir ?? 0) & 3;
|
|
17904
|
-
const P = rankdir === 0 ? p : ccwrotatepf(p, rankdir * 90);
|
|
17905
|
-
if (ctx.bp) {
|
|
17906
|
-
const b = ctx.bp;
|
|
17907
|
-
return P.x >= b.ll.x && P.x <= b.ur.x && P.y >= b.ll.y && P.y <= b.ur.y;
|
|
17908
|
-
}
|
|
17909
|
-
const poly = n.info.shape_info;
|
|
17910
|
-
if (poly === void 0 || poly.vertices === null) return false;
|
|
17911
|
-
return insideShape(n, poly, P);
|
|
17912
|
-
}
|
|
17913
|
-
function starInside(ctx, p) {
|
|
17914
|
-
const n = ctx.node;
|
|
17915
|
-
if (n === void 0) return false;
|
|
17916
|
-
const rankdir = (n.root.info.rankdir ?? 0) & 3;
|
|
17917
|
-
const P = rankdir === 0 ? p : ccwrotatepf(p, rankdir * 90);
|
|
17918
|
-
if (ctx.bp) {
|
|
17919
|
-
const b = ctx.bp;
|
|
17920
|
-
return P.x >= b.ll.x && P.x <= b.ur.x && P.y >= b.ll.y && P.y <= b.ur.y;
|
|
17921
|
-
}
|
|
17922
|
-
const poly = n.info.shape_info;
|
|
17923
|
-
if (poly === void 0 || poly.vertices === null) return false;
|
|
17924
|
-
const sides = poly.sides;
|
|
17925
|
-
const outerStart = (Math.max(poly.peripheries, 1) - 1) * sides;
|
|
17926
|
-
const outer = poly.vertices.slice(outerStart, outerStart + sides);
|
|
17927
|
-
const ring = polygonOutlineRing(outer, sides, poly.penwidth ?? 1);
|
|
17928
|
-
const O = { x: 0, y: 0 };
|
|
17929
|
-
let outcnt = 0;
|
|
17930
|
-
for (let i = 0; i < sides; i += 2) {
|
|
17931
|
-
const Q = ring[i];
|
|
17932
|
-
const R2 = ring[(i + 4) % sides];
|
|
17933
|
-
if (!sameSide(P, O, Q, R2)) outcnt++;
|
|
17934
|
-
if (outcnt === 2) return false;
|
|
17935
|
-
}
|
|
17936
|
-
return true;
|
|
17937
|
-
}
|
|
17938
|
-
function recordInside(ctx, p) {
|
|
17939
|
-
const n = ctx.node;
|
|
17940
|
-
if (n === void 0) return false;
|
|
17941
|
-
const rankdir = (n.root.info.rankdir ?? 0) & 3;
|
|
17942
|
-
const P = rankdir === 0 ? p : ccwrotatepf(p, rankdir * 90);
|
|
17943
|
-
let bb;
|
|
17944
|
-
if (ctx.bp) {
|
|
17945
|
-
bb = ctx.bp;
|
|
17946
|
-
} else {
|
|
17947
|
-
const fld = n.info.shape_info;
|
|
17948
|
-
if (!fld?.b) return false;
|
|
17949
|
-
bb = fld.b;
|
|
17950
|
-
}
|
|
17951
|
-
const pw = 0.5;
|
|
17952
|
-
return P.x >= bb.ll.x - pw && P.x <= bb.ur.x + pw && P.y >= bb.ll.y - pw && P.y <= bb.ur.y + pw;
|
|
17953
|
-
}
|
|
17954
|
-
|
|
17955
|
-
// src/layout/dot/fastgr.ts
|
|
17956
|
-
var VIRTUAL = 1;
|
|
17957
|
-
var NORMAL = 0;
|
|
17958
|
-
var FLATORDER = 4;
|
|
17959
|
-
var REVERSED = 3;
|
|
17960
|
-
var MC_SCALE = 256;
|
|
17961
|
-
function elistAppend(el, e) {
|
|
17962
|
-
el.list[el.size++] = e;
|
|
17963
|
-
}
|
|
17964
|
-
function zapinlist(el, e) {
|
|
17965
|
-
let i = 0;
|
|
17966
|
-
while (i < el.size && el.list[i] !== e) i++;
|
|
17967
|
-
if (i < el.size) {
|
|
17968
|
-
el.list[i] = el.list[--el.size];
|
|
17969
|
-
el.list[el.size] = void 0;
|
|
17970
|
-
}
|
|
17971
|
-
}
|
|
17972
|
-
function deleteFastEdge(e) {
|
|
17973
|
-
if (e.tail.info.out) zapinlist(e.tail.info.out, e);
|
|
17974
|
-
if (e.head.info.in) zapinlist(e.head.info.in, e);
|
|
17975
|
-
}
|
|
17976
|
-
function fastEdge(e) {
|
|
17977
|
-
if (!e.tail.info.out) e.tail.info.out = { list: [], size: 0 };
|
|
17978
|
-
if (!e.head.info.in) e.head.info.in = { list: [], size: 0 };
|
|
17979
|
-
elistAppend(e.tail.info.out, e);
|
|
17980
|
-
elistAppend(e.head.info.in, e);
|
|
17981
|
-
}
|
|
17982
|
-
function findFastEdge(u, v) {
|
|
17983
|
-
const uOut = u.info.out;
|
|
17984
|
-
const vIn = v.info.in;
|
|
17985
|
-
if (uOut === void 0 || vIn === void 0) return void 0;
|
|
17986
|
-
if (uOut.size <= vIn.size) {
|
|
17987
|
-
for (let i = 0; i < uOut.size; i++) {
|
|
17988
|
-
if (uOut.list[i].head === v) return uOut.list[i];
|
|
17989
|
-
}
|
|
17990
|
-
} else {
|
|
17991
|
-
for (let i = 0; i < vIn.size; i++) {
|
|
17992
|
-
if (vIn.list[i].tail === u) return vIn.list[i];
|
|
17993
|
-
}
|
|
17994
|
-
}
|
|
17995
|
-
return void 0;
|
|
17996
|
-
}
|
|
17997
|
-
function copyPort(p) {
|
|
17998
|
-
const bp = p.bp !== null ? { ll: { x: p.bp.ll.x, y: p.bp.ll.y }, ur: { x: p.bp.ur.x, y: p.bp.ur.y } } : null;
|
|
17999
|
-
return { p: { x: p.p.x, y: p.p.y }, theta: p.theta, bp, defined: p.defined, constrained: p.constrained, clip: p.clip, dyna: p.dyna, order: p.order, side: p.side, name: p.name };
|
|
18000
|
-
}
|
|
18001
|
-
function copyVirtualPorts(e, orig) {
|
|
18002
|
-
if (e.tail === orig.tail) e.info.tail_port = copyPort(orig.info.tail_port);
|
|
18003
|
-
else if (e.tail === orig.head) e.info.tail_port = copyPort(orig.info.head_port);
|
|
18004
|
-
if (e.head === orig.head) e.info.head_port = copyPort(orig.info.head_port);
|
|
18005
|
-
else if (e.head === orig.tail) e.info.head_port = copyPort(orig.info.tail_port);
|
|
18006
|
-
}
|
|
18007
|
-
function copyVirtualEdgeInfo(e, orig) {
|
|
18008
|
-
e.info.count = orig.info.count;
|
|
18009
|
-
e.info.xpenalty = orig.info.xpenalty;
|
|
18010
|
-
e.info.weight = orig.info.weight;
|
|
18011
|
-
e.info.minlen = orig.info.minlen;
|
|
18012
|
-
copyVirtualPorts(e, orig);
|
|
18013
|
-
e.info.label = orig.info.label;
|
|
18014
|
-
e.info.head_label = orig.info.head_label;
|
|
18015
|
-
e.info.tail_label = orig.info.tail_label;
|
|
18016
|
-
e.info.xlabel = orig.info.xlabel;
|
|
18017
|
-
if (orig.info.to_virt === void 0) orig.info.to_virt = e;
|
|
18018
|
-
e.info.to_orig = orig;
|
|
18019
|
-
e.seq = orig.seq;
|
|
18020
|
-
}
|
|
18021
|
-
function newVirtualEdge(u, v, orig) {
|
|
18022
|
-
const e = new Edge(u, v, "");
|
|
18023
|
-
e.info.edge_type = VIRTUAL;
|
|
18024
|
-
if (orig) {
|
|
18025
|
-
copyVirtualEdgeInfo(e, orig);
|
|
18026
|
-
} else {
|
|
18027
|
-
e.info.weight = 1;
|
|
18028
|
-
e.info.xpenalty = 1;
|
|
18029
|
-
e.info.count = 1;
|
|
18030
|
-
e.info.minlen = 1;
|
|
18031
|
-
}
|
|
18032
|
-
return e;
|
|
18033
|
-
}
|
|
18034
|
-
function virtualEdge(u, v, orig) {
|
|
18035
|
-
const e = newVirtualEdge(u, v, orig);
|
|
18036
|
-
fastEdge(e);
|
|
18037
|
-
return e;
|
|
18038
|
-
}
|
|
18039
|
-
function mergeWeightsInto(f, ew, em, ex) {
|
|
18040
|
-
f.info.weight = (f.info.weight ?? 0) + ew;
|
|
18041
|
-
f.info.minlen = Math.max(f.info.minlen ?? 1, em);
|
|
18042
|
-
f.info.count = (f.info.count ?? 1) + 1;
|
|
18043
|
-
f.info.xpenalty = (f.info.xpenalty ?? 0) + ex;
|
|
18044
|
-
}
|
|
18045
|
-
function basicMerge(e, rep) {
|
|
18046
|
-
const ew = e.info.weight ?? 1;
|
|
18047
|
-
const em = e.info.minlen ?? 1;
|
|
18048
|
-
const ex = e.info.xpenalty ?? 0;
|
|
18049
|
-
for (let f = rep; f !== void 0; f = f.info.to_virt) {
|
|
18050
|
-
mergeWeightsInto(f, ew, em, ex);
|
|
18051
|
-
}
|
|
18052
|
-
}
|
|
18053
|
-
function mergeOneway(e, rep) {
|
|
18054
|
-
if (e.info.to_virt !== void 0) return;
|
|
18055
|
-
e.info.to_virt = rep;
|
|
18056
|
-
basicMerge(e, rep);
|
|
18057
|
-
}
|
|
18058
|
-
function deleteFlatEdge(e) {
|
|
18059
|
-
e.info.to_virt = void 0;
|
|
18060
|
-
if (e.tail.info.flat_out) zapinlist(e.tail.info.flat_out, e);
|
|
18061
|
-
if (e.head.info.flat_in) zapinlist(e.head.info.flat_in, e);
|
|
18062
|
-
}
|
|
18063
|
-
function flatEdge(g, e) {
|
|
18064
|
-
if (!e.tail.info.flat_out) e.tail.info.flat_out = { list: [], size: 0 };
|
|
18065
|
-
if (!e.head.info.flat_in) e.head.info.flat_in = { list: [], size: 0 };
|
|
18066
|
-
elistAppend(e.tail.info.flat_out, e);
|
|
18067
|
-
elistAppend(e.head.info.flat_in, e);
|
|
18068
|
-
g.info.has_flat_edges = true;
|
|
18069
|
-
}
|
|
18070
|
-
function findFlatEdge(u, v) {
|
|
18071
|
-
const uOut = u.info.flat_out;
|
|
18072
|
-
const vIn = v.info.flat_in;
|
|
18073
|
-
if (uOut === void 0 || vIn === void 0) return void 0;
|
|
18074
|
-
if (uOut.size <= vIn.size) {
|
|
18075
|
-
for (let i = 0; i < uOut.size; i++) {
|
|
18076
|
-
if (uOut.list[i].head === v) return uOut.list[i];
|
|
18077
|
-
}
|
|
18078
|
-
} else {
|
|
18079
|
-
for (let i = 0; i < vIn.size; i++) {
|
|
18080
|
-
if (vIn.list[i].tail === u) return vIn.list[i];
|
|
18081
|
-
}
|
|
18082
|
-
}
|
|
18083
|
-
return void 0;
|
|
18084
|
-
}
|
|
18085
|
-
function reverseEdge(e) {
|
|
18086
|
-
deleteFastEdge(e);
|
|
18087
|
-
e.info.reversed = true;
|
|
18088
|
-
const f = findFastEdge(e.head, e.tail);
|
|
18089
|
-
if (f !== void 0) {
|
|
18090
|
-
mergeOneway(e, f);
|
|
18091
|
-
} else {
|
|
18092
|
-
virtualEdge(e.head, e.tail, e);
|
|
18093
|
-
}
|
|
18094
|
-
}
|
|
18095
|
-
function fastNode(g, n) {
|
|
18096
|
-
n.info.next = g.info.nlist;
|
|
18097
|
-
if (g.info.nlist !== void 0) g.info.nlist.info.prev = n;
|
|
18098
|
-
n.info.prev = void 0;
|
|
18099
|
-
g.info.nlist = n;
|
|
18100
|
-
}
|
|
18101
|
-
function deleteFastNode(g, n) {
|
|
18102
|
-
if (n.info.prev !== void 0) n.info.prev.info.next = n.info.next;
|
|
18103
|
-
else g.info.nlist = n.info.next;
|
|
18104
|
-
if (n.info.next !== void 0) n.info.next.info.prev = n.info.prev;
|
|
18105
|
-
}
|
|
18106
|
-
function removeFromRank(g, n) {
|
|
18107
|
-
const r = n.info.rank !== void 0 ? n.info.rank : 0;
|
|
18108
|
-
const rank3 = g.info.rank;
|
|
18109
|
-
if (rank3 === void 0) return;
|
|
18110
|
-
const rk = rank3[r];
|
|
18111
|
-
for (let j = 0; j < rk.n; j++) {
|
|
18112
|
-
const v = rk.v[j];
|
|
18113
|
-
if (v === n) {
|
|
18114
|
-
for (j++; j < rk.n; j++) {
|
|
18115
|
-
rk.v[j - 1] = rk.v[j];
|
|
18116
|
-
}
|
|
18117
|
-
rk.n--;
|
|
18118
|
-
break;
|
|
18119
|
-
}
|
|
18120
|
-
}
|
|
18121
|
-
}
|
|
18122
|
-
function virtualNode(g) {
|
|
18123
|
-
const n = new Node(0, "", g.root);
|
|
18124
|
-
n.info.node_type = VIRTUAL;
|
|
18125
|
-
n.info.lw = 1;
|
|
18126
|
-
n.info.rw = 1;
|
|
18127
|
-
n.info.ht = 1;
|
|
18128
|
-
n.info.UF_size = 1;
|
|
18129
|
-
n.info.in = { list: [], size: 0 };
|
|
18130
|
-
n.info.out = { list: [], size: 0 };
|
|
18131
|
-
fastNode(g, n);
|
|
18132
|
-
return n;
|
|
18133
|
-
}
|
|
18134
|
-
function otherEdge(e) {
|
|
18135
|
-
if (!e.tail.info.other) e.tail.info.other = { list: [], size: 0 };
|
|
18136
|
-
elistAppend(e.tail.info.other, e);
|
|
18137
|
-
}
|
|
18138
|
-
|
|
18139
|
-
// src/layout/dot/decomp.ts
|
|
18140
|
-
function nodesInSeq(g) {
|
|
18141
|
-
return [...g.nodes.values()].sort((a, b) => a.id - b.id);
|
|
18142
|
-
}
|
|
18143
|
-
function ufFind(n) {
|
|
18144
|
-
while (n.info.UF_parent !== void 0 && n.info.UF_parent !== n) {
|
|
18145
|
-
const gp = n.info.UF_parent.info.UF_parent;
|
|
18146
|
-
if (gp !== void 0) n.info.UF_parent = gp;
|
|
18147
|
-
n = n.info.UF_parent;
|
|
18148
|
-
}
|
|
18149
|
-
return n;
|
|
18150
|
-
}
|
|
18151
|
-
function ufUnion(u, v) {
|
|
18152
|
-
if (u === v) return u;
|
|
18153
|
-
if (u.info.UF_parent === void 0) {
|
|
18154
|
-
u.info.UF_parent = u;
|
|
18155
|
-
u.info.UF_size = 1;
|
|
18156
|
-
} else u = ufFind(u);
|
|
18157
|
-
if (v.info.UF_parent === void 0) {
|
|
18158
|
-
v.info.UF_parent = v;
|
|
18159
|
-
v.info.UF_size = 1;
|
|
18160
|
-
} else v = ufFind(v);
|
|
18161
|
-
if (u === v) return u;
|
|
18162
|
-
const us = u.info.UF_size ?? 0;
|
|
18163
|
-
const vs = v.info.UF_size ?? 0;
|
|
18164
|
-
v.info.UF_parent = u;
|
|
18165
|
-
u.info.UF_size = us + vs;
|
|
18166
|
-
return u;
|
|
18167
|
-
}
|
|
18168
|
-
function ufSingleton(u) {
|
|
18169
|
-
u.info.UF_size = 1;
|
|
18170
|
-
u.info.UF_parent = void 0;
|
|
18171
|
-
u.info.ranktype = 0;
|
|
18172
|
-
}
|
|
18173
|
-
function ufSetname(u, v) {
|
|
18174
|
-
u.info.UF_parent = v;
|
|
18175
|
-
v.info.UF_size = (v.info.UF_size ?? 0) + (u.info.UF_size ?? 0);
|
|
18176
|
-
}
|
|
18177
|
-
function decompPushNeighbors(stk, el, n, cmark) {
|
|
18178
|
-
if (!el || el.size === 0) return;
|
|
18179
|
-
for (let i = el.size - 1; i >= 0; i--) {
|
|
18180
|
-
const e = el.list[i];
|
|
18181
|
-
const other = e.head === n ? e.tail : e.head;
|
|
18182
|
-
if (other.info.mark !== cmark && other === ufFind(other)) {
|
|
18183
|
-
other.info.mark = cmark + 1;
|
|
18184
|
-
stk.push(other);
|
|
18185
|
-
}
|
|
18186
|
-
}
|
|
18187
|
-
}
|
|
18188
|
-
function decompSearch(g, start, cmark) {
|
|
18189
|
-
const stk = [];
|
|
18190
|
-
let lastNode;
|
|
18191
|
-
start.info.mark = cmark + 1;
|
|
18192
|
-
stk.push(start);
|
|
18193
|
-
g.info.nlist = void 0;
|
|
18194
|
-
let top;
|
|
18195
|
-
while ((top = stk.pop()) !== void 0) {
|
|
18196
|
-
if (top.info.mark === cmark) continue;
|
|
18197
|
-
top.info.mark = cmark;
|
|
18198
|
-
if (lastNode !== void 0) {
|
|
18199
|
-
top.info.prev = lastNode;
|
|
18200
|
-
lastNode.info.next = top;
|
|
18201
|
-
} else {
|
|
18202
|
-
top.info.prev = void 0;
|
|
18203
|
-
g.info.nlist = top;
|
|
18204
|
-
}
|
|
18205
|
-
lastNode = top;
|
|
18206
|
-
top.info.next = void 0;
|
|
18207
|
-
decompPushNeighbors(stk, top.info.flat_in, top, cmark);
|
|
18208
|
-
decompPushNeighbors(stk, top.info.flat_out, top, cmark);
|
|
18209
|
-
decompPushNeighbors(stk, top.info.in, top, cmark);
|
|
18210
|
-
decompPushNeighbors(stk, top.info.out, top, cmark);
|
|
18211
|
-
}
|
|
18212
|
-
}
|
|
18213
|
-
var _dc = { cmark: 0 };
|
|
18214
|
-
function resolveNode(n, pass) {
|
|
18215
|
-
if (pass > 0) {
|
|
18216
|
-
const subg = n.info.clust;
|
|
18217
|
-
if (subg) return subg.info.rankleader?.[n.info.rank ?? 0];
|
|
18218
|
-
}
|
|
18219
|
-
return n === ufFind(n) ? n : void 0;
|
|
18220
|
-
}
|
|
18221
|
-
function decompose(g, pass) {
|
|
18222
|
-
if (++_dc.cmark === 0) _dc.cmark = 1;
|
|
18223
|
-
const cmark = _dc.cmark;
|
|
18224
|
-
g.info.comp = [];
|
|
18225
|
-
for (const n of nodesInSeq(g)) {
|
|
18226
|
-
const v = resolveNode(n, pass);
|
|
18227
|
-
if (v !== void 0 && v.info.mark !== cmark) {
|
|
18228
|
-
decompSearch(g, v, cmark);
|
|
18229
|
-
g.info.comp.push(g.info.nlist);
|
|
18230
|
-
}
|
|
18231
|
-
}
|
|
18232
|
-
}
|
|
18233
|
-
|
|
18234
|
-
// src/layout/dot/mincross-utils.ts
|
|
18235
|
-
var CONVERGENCE = 0.995;
|
|
18236
|
-
function matrixGet(m, row, col) {
|
|
18237
|
-
if (row >= m.nrows || col >= m.ncols) return false;
|
|
18238
|
-
const idx = row * m.ncols + col;
|
|
18239
|
-
return (m.data[idx >> 3] >> (idx & 7) & 1) === 1;
|
|
18240
|
-
}
|
|
18241
|
-
function matrixSet(m, row, col) {
|
|
18242
|
-
if (row >= m.nrows || col >= m.ncols) matrixExpand(m, row, col);
|
|
18243
|
-
const idx = row * m.ncols + col;
|
|
18244
|
-
m.data[idx >> 3] |= 1 << (idx & 7);
|
|
18245
|
-
}
|
|
18246
|
-
function matrixCopyBits(m, data, ncols) {
|
|
18247
|
-
for (let r = 0; r < m.nrows; r++) {
|
|
18248
|
-
for (let c = 0; c < m.ncols; c++) {
|
|
18249
|
-
if (!matrixGet(m, r, c)) continue;
|
|
18250
|
-
const idx = r * ncols + c;
|
|
18251
|
-
data[idx >> 3] |= 1 << (idx & 7);
|
|
18252
|
-
}
|
|
18253
|
-
}
|
|
18254
|
-
}
|
|
18255
|
-
function matrixExpand(m, row, col) {
|
|
18256
|
-
const nrows = Math.max(m.nrows, row + 1);
|
|
18257
|
-
const ncols = Math.max(m.ncols, col + 1);
|
|
18258
|
-
const bits = nrows * ncols;
|
|
18259
|
-
const bytes = (bits >> 3) + (bits & 7 ? 1 : 0);
|
|
18260
|
-
const data = new Uint8Array(bytes);
|
|
18261
|
-
matrixCopyBits(m, data, ncols);
|
|
18262
|
-
m.nrows = nrows;
|
|
18263
|
-
m.ncols = ncols;
|
|
18264
|
-
m.data = data;
|
|
18265
|
-
}
|
|
18266
|
-
function newMatrix(rows, cols) {
|
|
18267
|
-
const bits = rows * cols;
|
|
18268
|
-
const bytes = (bits >> 3) + (bits & 7 ? 1 : 0);
|
|
18269
|
-
return { nrows: rows, ncols: cols, data: new Uint8Array(bytes) };
|
|
18270
|
-
}
|
|
18271
|
-
function dotRoot(g) {
|
|
18272
|
-
return g.info.dotroot ?? g.root;
|
|
18273
|
-
}
|
|
18274
|
-
function agContainsNode(g, n) {
|
|
18275
|
-
return g.nodes.get(n.name) === n;
|
|
18276
|
-
}
|
|
18277
|
-
function agContainsEdge(g, e) {
|
|
18278
|
-
return g.edges.includes(e);
|
|
18279
|
-
}
|
|
18280
|
-
function rankGet(rank3, i) {
|
|
18281
|
-
return rank3.v[(rank3.vStart ?? 0) + i];
|
|
18282
|
-
}
|
|
18283
|
-
function rankSet(rank3, i, n) {
|
|
18284
|
-
rank3.v[(rank3.vStart ?? 0) + i] = n;
|
|
18285
|
-
}
|
|
18286
|
-
function isNormalNodeOf(g, v) {
|
|
18287
|
-
return v.info.node_type === NORMAL && agContainsNode(g, v);
|
|
18288
|
-
}
|
|
18289
|
-
function isVnodeOfEdgeOf(g, v) {
|
|
18290
|
-
if (v.info.node_type !== VIRTUAL) return false;
|
|
18291
|
-
const inSz = v.info.in ? v.info.in.size : 0;
|
|
18292
|
-
const outSz = v.info.out ? v.info.out.size : 0;
|
|
18293
|
-
if (inSz !== 1 || outSz !== 1) return false;
|
|
18294
|
-
let e = v.info.out.list[0];
|
|
18295
|
-
while (e.info.edge_type !== NORMAL && e.info.to_orig) e = e.info.to_orig;
|
|
18296
|
-
return agContainsEdge(g, e);
|
|
18297
|
-
}
|
|
18298
|
-
function insideCluster(g, v) {
|
|
18299
|
-
return isNormalNodeOf(g, v) || isVnodeOfEdgeOf(g, v);
|
|
18300
|
-
}
|
|
18301
|
-
function neighborNode(ctx, v, dir) {
|
|
18302
|
-
const rk = ctx.root.info.rank?.[v.info.rank ?? 0];
|
|
18303
|
-
if (!rk) return void 0;
|
|
18304
|
-
const order = v.info.order ?? 0;
|
|
18305
|
-
return (dir < 0 ? order > 0 ? rk.v[order - 1] : void 0 : rk.v[order + 1]) ?? void 0;
|
|
18306
|
-
}
|
|
18307
|
-
function furthestNode(ctx, g, v, dir) {
|
|
18308
|
-
let rv = v;
|
|
18309
|
-
let u = v;
|
|
18310
|
-
while ((u = neighborNode(ctx, u, dir)) !== void 0) {
|
|
18311
|
-
if (isNormalNodeOf(g, u) || isVnodeOfEdgeOf(g, u)) rv = u;
|
|
18312
|
-
}
|
|
18313
|
-
return rv;
|
|
18314
|
-
}
|
|
18315
|
-
|
|
18316
|
-
// src/common/splines-geom.ts
|
|
18317
|
-
function approxEqPt(p, q, tol) {
|
|
18318
|
-
const dx = p.x - q.x;
|
|
18319
|
-
const dy = p.y - q.y;
|
|
18320
|
-
return dx * dx + dy * dy < tol * tol;
|
|
18321
|
-
}
|
|
18322
|
-
function evalBezier(sp, t, left, right) {
|
|
18323
|
-
const ab = { x: sp[0].x + t * (sp[1].x - sp[0].x), y: sp[0].y + t * (sp[1].y - sp[0].y) };
|
|
18324
|
-
const bc = { x: sp[1].x + t * (sp[2].x - sp[1].x), y: sp[1].y + t * (sp[2].y - sp[1].y) };
|
|
18325
|
-
const cd = { x: sp[2].x + t * (sp[3].x - sp[2].x), y: sp[2].y + t * (sp[3].y - sp[2].y) };
|
|
18326
|
-
const abbc = { x: ab.x + t * (bc.x - ab.x), y: ab.y + t * (bc.y - ab.y) };
|
|
18327
|
-
const bccd = { x: bc.x + t * (cd.x - bc.x), y: bc.y + t * (cd.y - bc.y) };
|
|
18328
|
-
const pt = { x: abbc.x + t * (bccd.x - abbc.x), y: abbc.y + t * (bccd.y - abbc.y) };
|
|
18329
|
-
if (left !== null) {
|
|
18330
|
-
left[0] = sp[0];
|
|
18331
|
-
left[1] = ab;
|
|
18332
|
-
left[2] = abbc;
|
|
18333
|
-
left[3] = pt;
|
|
18334
|
-
}
|
|
18335
|
-
if (right !== null) {
|
|
18336
|
-
right[0] = pt;
|
|
18337
|
-
right[1] = bccd;
|
|
18338
|
-
right[2] = cd;
|
|
18339
|
-
right[3] = sp[3];
|
|
18340
|
-
}
|
|
18341
|
-
return pt;
|
|
18342
|
-
}
|
|
18343
|
-
var HW = 2;
|
|
18344
|
-
var SMALL = 1e-10;
|
|
18345
|
-
function ptToLine2(a, b, p) {
|
|
18346
|
-
const dx = b.x - a.x;
|
|
18347
|
-
const dy = b.y - a.y;
|
|
18348
|
-
let a2 = (p.y - a.y) * dx - (p.x - a.x) * dy;
|
|
18349
|
-
a2 *= a2;
|
|
18350
|
-
if (a2 < SMALL) return 0;
|
|
18351
|
-
return a2 / (dx * dx + dy * dy);
|
|
18352
|
-
}
|
|
18353
|
-
function checkControlPoints(cp) {
|
|
18354
|
-
const dis1 = ptToLine2(cp[0], cp[3], cp[1]);
|
|
18355
|
-
const dis2 = ptToLine2(cp[0], cp[3], cp[2]);
|
|
18356
|
-
return dis1 < HW * HW && dis2 < HW * HW;
|
|
18357
|
-
}
|
|
18358
|
-
function anyOutside(bb, cp) {
|
|
18359
|
-
return cp.some((p) => p.x > bb.ur.x || p.x < bb.ll.x || p.y > bb.ur.y || p.y < bb.ll.y);
|
|
17113
|
+
function anyOutside(bb, cp) {
|
|
17114
|
+
return cp.some((p) => p.x > bb.ur.x || p.x < bb.ll.x || p.y > bb.ur.y || p.y < bb.ll.y);
|
|
18360
17115
|
}
|
|
18361
17116
|
function expandByPoints(bb, cp) {
|
|
18362
17117
|
for (const p of cp) {
|
|
@@ -18815,7 +17570,15 @@ function curveControlPoints(p, v, w, flag) {
|
|
|
18815
17570
|
const AF2 = { x: p.x - 0.95 * v.x + w.x + s * w.x * (4 / 3), y: AF3.y + s * w.y * (4 / 3) };
|
|
18816
17571
|
return [AF0, AF1, AF2, AF3];
|
|
18817
17572
|
}
|
|
18818
|
-
function genCurve(p0, u, _arrowsize, penwidth, flag) {
|
|
17573
|
+
function genCurve(p0, u, _arrowsize, penwidth, flag, rankdir = 0) {
|
|
17574
|
+
if (rankdir !== 0) {
|
|
17575
|
+
const rot = rankdir * 90;
|
|
17576
|
+
const fin = genCurve(ccwrotatepf(p0, rot), ccwrotatepf(u, rot), _arrowsize, penwidth, flag);
|
|
17577
|
+
return {
|
|
17578
|
+
ops: fin.ops.map((op) => "points" in op ? { ...op, points: op.points.map((pt) => cwrotatepf(pt, rot)) } : op),
|
|
17579
|
+
q: cwrotatepf(fin.q, rot)
|
|
17580
|
+
};
|
|
17581
|
+
}
|
|
18819
17582
|
const arrowwidth = penwidth > 4 ? 0.5 * penwidth / 4 : 0.5;
|
|
18820
17583
|
const noShift = flag & ARR_MOD_INV || u.x === 0 && u.y === 0;
|
|
18821
17584
|
const p = noShift ? p0 : vsub2(p0, backwardDelta(u, penwidth));
|
|
@@ -19030,7 +17793,7 @@ function arrowLength(comps, arrowsize, penwidth) {
|
|
|
19030
17793
|
for (let i = 0; i < n; i++) length += arrowLengthOne(comps[i], arrowsize, penwidth);
|
|
19031
17794
|
return length;
|
|
19032
17795
|
}
|
|
19033
|
-
function dispatchSimple(r, tip2, dir, arrowsize, penwidth) {
|
|
17796
|
+
function dispatchSimple(r, tip2, dir, arrowsize, penwidth, rankdir = 0) {
|
|
19034
17797
|
const flag = arrowFlag(r);
|
|
19035
17798
|
const u = componentU(dir, r.lenfact, arrowsize);
|
|
19036
17799
|
switch (r.type & ARR_TYPE_MASK) {
|
|
@@ -19044,8 +17807,10 @@ function dispatchSimple(r, tip2, dir, arrowsize, penwidth) {
|
|
|
19044
17807
|
return genDiamond(tip2, u, arrowsize, penwidth, flag);
|
|
19045
17808
|
case ARR_TYPE_DOT:
|
|
19046
17809
|
return genDot(tip2, u, arrowsize, penwidth, flag);
|
|
17810
|
+
// curve is the one generator that is not rotation-equivariant; it needs
|
|
17811
|
+
// the rankdir to reproduce C's render-time (final-frame) generation.
|
|
19047
17812
|
case ARR_TYPE_CURVE:
|
|
19048
|
-
return genCurve(tip2, u, arrowsize, penwidth, flag);
|
|
17813
|
+
return genCurve(tip2, u, arrowsize, penwidth, flag, rankdir);
|
|
19049
17814
|
case ARR_TYPE_GAP:
|
|
19050
17815
|
return genGap(tip2, u, arrowsize, penwidth, flag);
|
|
19051
17816
|
case ARR_TYPE_NORM:
|
|
@@ -19053,14 +17818,14 @@ function dispatchSimple(r, tip2, dir, arrowsize, penwidth) {
|
|
|
19053
17818
|
return genNormal(tip2, u, arrowsize, penwidth, flag);
|
|
19054
17819
|
}
|
|
19055
17820
|
}
|
|
19056
|
-
function arrowDrawOps(comps, tip2, dir, arrowsize, penwidth) {
|
|
17821
|
+
function arrowDrawOps(comps, tip2, dir, arrowsize, penwidth, rankdir = 0) {
|
|
19057
17822
|
const ops = [];
|
|
19058
17823
|
let p = tip2;
|
|
19059
17824
|
const n = Math.min(comps.length, 4);
|
|
19060
17825
|
for (let i = 0; i < n; i++) {
|
|
19061
17826
|
const r = comps[i];
|
|
19062
17827
|
if ((r.type & ARR_TYPE_MASK) === ARR_TYPE_NONE) break;
|
|
19063
|
-
const res = dispatchSimple(r, p, dir, arrowsize, penwidth);
|
|
17828
|
+
const res = dispatchSimple(r, p, dir, arrowsize, penwidth, rankdir);
|
|
19064
17829
|
ops.push(...res.ops);
|
|
19065
17830
|
p = res.q;
|
|
19066
17831
|
}
|
|
@@ -19204,7 +17969,8 @@ function edgeArrowsize(e) {
|
|
|
19204
17969
|
}
|
|
19205
17970
|
function arrowDrawOpsForEnd(e, end, tip2, dir, penwidth) {
|
|
19206
17971
|
const comps = parseArrow(edgeArrowName(e, end)).map(resolveArrowType);
|
|
19207
|
-
|
|
17972
|
+
const rankdir = (e.tail?.root?.info?.rankdir ?? 0) & 3;
|
|
17973
|
+
return arrowDrawOps(comps, tip2, dir, edgeArrowsize(e), penwidth, rankdir);
|
|
19208
17974
|
}
|
|
19209
17975
|
|
|
19210
17976
|
// src/common/splines-clip.ts
|
|
@@ -20259,6 +19025,101 @@ function doGraphLabel(sg, measurer) {
|
|
|
20259
19025
|
applyLabelBorder(sg, { x: label.dimen.x + 4 * GAP2, y: label.dimen.y + 2 * GAP2 });
|
|
20260
19026
|
}
|
|
20261
19027
|
|
|
19028
|
+
// src/layout/dot/decomp.ts
|
|
19029
|
+
function nodesInSeq(g) {
|
|
19030
|
+
return [...g.nodes.values()].sort((a, b) => a.id - b.id);
|
|
19031
|
+
}
|
|
19032
|
+
function ufFind(n) {
|
|
19033
|
+
while (n.info.UF_parent !== void 0 && n.info.UF_parent !== n) {
|
|
19034
|
+
const gp = n.info.UF_parent.info.UF_parent;
|
|
19035
|
+
if (gp !== void 0) n.info.UF_parent = gp;
|
|
19036
|
+
n = n.info.UF_parent;
|
|
19037
|
+
}
|
|
19038
|
+
return n;
|
|
19039
|
+
}
|
|
19040
|
+
function ufUnion(u, v) {
|
|
19041
|
+
if (u === v) return u;
|
|
19042
|
+
if (u.info.UF_parent === void 0) {
|
|
19043
|
+
u.info.UF_parent = u;
|
|
19044
|
+
u.info.UF_size = 1;
|
|
19045
|
+
} else u = ufFind(u);
|
|
19046
|
+
if (v.info.UF_parent === void 0) {
|
|
19047
|
+
v.info.UF_parent = v;
|
|
19048
|
+
v.info.UF_size = 1;
|
|
19049
|
+
} else v = ufFind(v);
|
|
19050
|
+
if (u === v) return u;
|
|
19051
|
+
const us = u.info.UF_size ?? 0;
|
|
19052
|
+
const vs = v.info.UF_size ?? 0;
|
|
19053
|
+
v.info.UF_parent = u;
|
|
19054
|
+
u.info.UF_size = us + vs;
|
|
19055
|
+
return u;
|
|
19056
|
+
}
|
|
19057
|
+
function ufSingleton(u) {
|
|
19058
|
+
u.info.UF_size = 1;
|
|
19059
|
+
u.info.UF_parent = void 0;
|
|
19060
|
+
u.info.ranktype = 0;
|
|
19061
|
+
}
|
|
19062
|
+
function ufSetname(u, v) {
|
|
19063
|
+
u.info.UF_parent = v;
|
|
19064
|
+
v.info.UF_size = (v.info.UF_size ?? 0) + (u.info.UF_size ?? 0);
|
|
19065
|
+
}
|
|
19066
|
+
function decompPushNeighbors(stk, el, n, cmark) {
|
|
19067
|
+
if (!el || el.size === 0) return;
|
|
19068
|
+
for (let i = el.size - 1; i >= 0; i--) {
|
|
19069
|
+
const e = el.list[i];
|
|
19070
|
+
const other = e.head === n ? e.tail : e.head;
|
|
19071
|
+
if (other.info.mark !== cmark && other === ufFind(other)) {
|
|
19072
|
+
other.info.mark = cmark + 1;
|
|
19073
|
+
stk.push(other);
|
|
19074
|
+
}
|
|
19075
|
+
}
|
|
19076
|
+
}
|
|
19077
|
+
function decompSearch(g, start, cmark) {
|
|
19078
|
+
const stk = [];
|
|
19079
|
+
let lastNode;
|
|
19080
|
+
start.info.mark = cmark + 1;
|
|
19081
|
+
stk.push(start);
|
|
19082
|
+
g.info.nlist = void 0;
|
|
19083
|
+
let top;
|
|
19084
|
+
while ((top = stk.pop()) !== void 0) {
|
|
19085
|
+
if (top.info.mark === cmark) continue;
|
|
19086
|
+
top.info.mark = cmark;
|
|
19087
|
+
if (lastNode !== void 0) {
|
|
19088
|
+
top.info.prev = lastNode;
|
|
19089
|
+
lastNode.info.next = top;
|
|
19090
|
+
} else {
|
|
19091
|
+
top.info.prev = void 0;
|
|
19092
|
+
g.info.nlist = top;
|
|
19093
|
+
}
|
|
19094
|
+
lastNode = top;
|
|
19095
|
+
top.info.next = void 0;
|
|
19096
|
+
decompPushNeighbors(stk, top.info.flat_in, top, cmark);
|
|
19097
|
+
decompPushNeighbors(stk, top.info.flat_out, top, cmark);
|
|
19098
|
+
decompPushNeighbors(stk, top.info.in, top, cmark);
|
|
19099
|
+
decompPushNeighbors(stk, top.info.out, top, cmark);
|
|
19100
|
+
}
|
|
19101
|
+
}
|
|
19102
|
+
var _dc = { cmark: 0 };
|
|
19103
|
+
function resolveNode(n, pass) {
|
|
19104
|
+
if (pass > 0) {
|
|
19105
|
+
const subg = n.info.clust;
|
|
19106
|
+
if (subg) return subg.info.rankleader?.[n.info.rank ?? 0];
|
|
19107
|
+
}
|
|
19108
|
+
return n === ufFind(n) ? n : void 0;
|
|
19109
|
+
}
|
|
19110
|
+
function decompose(g, pass) {
|
|
19111
|
+
if (++_dc.cmark === 0) _dc.cmark = 1;
|
|
19112
|
+
const cmark = _dc.cmark;
|
|
19113
|
+
g.info.comp = [];
|
|
19114
|
+
for (const n of nodesInSeq(g)) {
|
|
19115
|
+
const v = resolveNode(n, pass);
|
|
19116
|
+
if (v !== void 0 && v.info.mark !== cmark) {
|
|
19117
|
+
decompSearch(g, v, cmark);
|
|
19118
|
+
g.info.comp.push(g.info.nlist);
|
|
19119
|
+
}
|
|
19120
|
+
}
|
|
19121
|
+
}
|
|
19122
|
+
|
|
20262
19123
|
// src/layout/dot/acyclic.ts
|
|
20263
19124
|
function dfsStep(stack) {
|
|
20264
19125
|
const f = stack[stack.length - 1];
|
|
@@ -21801,6 +20662,216 @@ function dot2Rank(g) {
|
|
|
21801
20662
|
readoutLevels(g, Xg, ncc);
|
|
21802
20663
|
}
|
|
21803
20664
|
|
|
20665
|
+
// src/layout/dot/mincross-utils.ts
|
|
20666
|
+
var CONVERGENCE = 0.995;
|
|
20667
|
+
function matrixGet(m, row, col) {
|
|
20668
|
+
if (row >= m.nrows || col >= m.ncols) return false;
|
|
20669
|
+
const idx = row * m.ncols + col;
|
|
20670
|
+
return (m.data[idx >> 3] >> (idx & 7) & 1) === 1;
|
|
20671
|
+
}
|
|
20672
|
+
function matrixSet(m, row, col) {
|
|
20673
|
+
if (row >= m.nrows || col >= m.ncols) matrixExpand(m, row, col);
|
|
20674
|
+
const idx = row * m.ncols + col;
|
|
20675
|
+
m.data[idx >> 3] |= 1 << (idx & 7);
|
|
20676
|
+
}
|
|
20677
|
+
function matrixCopyBits(m, data, ncols) {
|
|
20678
|
+
for (let r = 0; r < m.nrows; r++) {
|
|
20679
|
+
for (let c = 0; c < m.ncols; c++) {
|
|
20680
|
+
if (!matrixGet(m, r, c)) continue;
|
|
20681
|
+
const idx = r * ncols + c;
|
|
20682
|
+
data[idx >> 3] |= 1 << (idx & 7);
|
|
20683
|
+
}
|
|
20684
|
+
}
|
|
20685
|
+
}
|
|
20686
|
+
function matrixExpand(m, row, col) {
|
|
20687
|
+
const nrows = Math.max(m.nrows, row + 1);
|
|
20688
|
+
const ncols = Math.max(m.ncols, col + 1);
|
|
20689
|
+
const bits = nrows * ncols;
|
|
20690
|
+
const bytes = (bits >> 3) + (bits & 7 ? 1 : 0);
|
|
20691
|
+
const data = new Uint8Array(bytes);
|
|
20692
|
+
matrixCopyBits(m, data, ncols);
|
|
20693
|
+
m.nrows = nrows;
|
|
20694
|
+
m.ncols = ncols;
|
|
20695
|
+
m.data = data;
|
|
20696
|
+
}
|
|
20697
|
+
function newMatrix(rows, cols) {
|
|
20698
|
+
const bits = rows * cols;
|
|
20699
|
+
const bytes = (bits >> 3) + (bits & 7 ? 1 : 0);
|
|
20700
|
+
return { nrows: rows, ncols: cols, data: new Uint8Array(bytes) };
|
|
20701
|
+
}
|
|
20702
|
+
function dotRoot(g) {
|
|
20703
|
+
return g.info.dotroot ?? g.root;
|
|
20704
|
+
}
|
|
20705
|
+
function agContainsNode(g, n) {
|
|
20706
|
+
return g.nodes.get(n.name) === n;
|
|
20707
|
+
}
|
|
20708
|
+
function agContainsEdge(g, e) {
|
|
20709
|
+
return g.edges.includes(e);
|
|
20710
|
+
}
|
|
20711
|
+
function rankGet(rank3, i) {
|
|
20712
|
+
return rank3.v[(rank3.vStart ?? 0) + i];
|
|
20713
|
+
}
|
|
20714
|
+
function rankSet(rank3, i, n) {
|
|
20715
|
+
rank3.v[(rank3.vStart ?? 0) + i] = n;
|
|
20716
|
+
}
|
|
20717
|
+
function isNormalNodeOf(g, v) {
|
|
20718
|
+
return v.info.node_type === NORMAL && agContainsNode(g, v);
|
|
20719
|
+
}
|
|
20720
|
+
function isVnodeOfEdgeOf(g, v) {
|
|
20721
|
+
if (v.info.node_type !== VIRTUAL) return false;
|
|
20722
|
+
const inSz = v.info.in ? v.info.in.size : 0;
|
|
20723
|
+
const outSz = v.info.out ? v.info.out.size : 0;
|
|
20724
|
+
if (inSz !== 1 || outSz !== 1) return false;
|
|
20725
|
+
let e = v.info.out.list[0];
|
|
20726
|
+
while (e.info.edge_type !== NORMAL && e.info.to_orig) e = e.info.to_orig;
|
|
20727
|
+
return agContainsEdge(g, e);
|
|
20728
|
+
}
|
|
20729
|
+
function insideCluster(g, v) {
|
|
20730
|
+
return isNormalNodeOf(g, v) || isVnodeOfEdgeOf(g, v);
|
|
20731
|
+
}
|
|
20732
|
+
function neighborNode(ctx, v, dir) {
|
|
20733
|
+
const rk = ctx.root.info.rank?.[v.info.rank ?? 0];
|
|
20734
|
+
if (!rk) return void 0;
|
|
20735
|
+
const order = v.info.order ?? 0;
|
|
20736
|
+
return (dir < 0 ? order > 0 ? rk.v[order - 1] : void 0 : rk.v[order + 1]) ?? void 0;
|
|
20737
|
+
}
|
|
20738
|
+
function furthestNode(ctx, g, v, dir) {
|
|
20739
|
+
let rv = v;
|
|
20740
|
+
let u = v;
|
|
20741
|
+
while ((u = neighborNode(ctx, u, dir)) !== void 0) {
|
|
20742
|
+
if (isNormalNodeOf(g, u) || isVnodeOfEdgeOf(g, u)) rv = u;
|
|
20743
|
+
}
|
|
20744
|
+
return rv;
|
|
20745
|
+
}
|
|
20746
|
+
|
|
20747
|
+
// src/layout/dot/cluster-path.ts
|
|
20748
|
+
var CLUSTER_EDGE = 5;
|
|
20749
|
+
function mapInterclustNode(n) {
|
|
20750
|
+
const clust = n.info.clust;
|
|
20751
|
+
if (clust === void 0 || clust.info.expanded) return n;
|
|
20752
|
+
return clust.info.rankleader[n.info.rank ?? 0];
|
|
20753
|
+
}
|
|
20754
|
+
function makeSlotsContract(root, r, pos, d) {
|
|
20755
|
+
const rk = root.info.rank[r];
|
|
20756
|
+
for (let i = pos - d + 1; i < rk.n; i++) {
|
|
20757
|
+
const v = rk.v[i];
|
|
20758
|
+
v.info.order = i + d - 1;
|
|
20759
|
+
rk.v[v.info.order] = v;
|
|
20760
|
+
}
|
|
20761
|
+
for (let i = rk.n + d - 1; i < rk.n; i++) rk.v[i] = null;
|
|
20762
|
+
}
|
|
20763
|
+
function makeSlotsExpand(root, r, pos, d) {
|
|
20764
|
+
const rk = root.info.rank[r];
|
|
20765
|
+
for (let i = rk.n - 1; i > pos; i--) {
|
|
20766
|
+
const v = rk.v[i];
|
|
20767
|
+
v.info.order = i + d - 1;
|
|
20768
|
+
rk.v[v.info.order] = v;
|
|
20769
|
+
}
|
|
20770
|
+
for (let i = pos + 1; i < pos + d; i++) rk.v[i] = null;
|
|
20771
|
+
}
|
|
20772
|
+
function makeSlots(root, r, pos, d) {
|
|
20773
|
+
if (d <= 0) makeSlotsContract(root, r, pos, d);
|
|
20774
|
+
else makeSlotsExpand(root, r, pos, d);
|
|
20775
|
+
root.info.rank[r].n += d - 1;
|
|
20776
|
+
}
|
|
20777
|
+
function cloneVn(g, vn) {
|
|
20778
|
+
const r = vn.info.rank ?? 0;
|
|
20779
|
+
makeSlots(g, r, vn.info.order, 2);
|
|
20780
|
+
const rv = virtualNode(g);
|
|
20781
|
+
rv.info.lw = vn.info.lw;
|
|
20782
|
+
rv.info.rw = vn.info.rw;
|
|
20783
|
+
rv.info.rank = r;
|
|
20784
|
+
rv.info.order = (vn.info.order ?? 0) + 1;
|
|
20785
|
+
g.info.rank[r].v[rv.info.order] = rv;
|
|
20786
|
+
return rv;
|
|
20787
|
+
}
|
|
20788
|
+
function safeOtherEdge(e) {
|
|
20789
|
+
if (!e.tail.info.other) e.tail.info.other = { list: [], size: 0 };
|
|
20790
|
+
const other = e.tail.info.other;
|
|
20791
|
+
for (let i = 0; i < other.size; i++) if (other.list[i] === e) return;
|
|
20792
|
+
other.list[other.size++] = e;
|
|
20793
|
+
}
|
|
20794
|
+
function portsEqSimple(orig, e) {
|
|
20795
|
+
const hp = orig.info.head_port;
|
|
20796
|
+
const tp = orig.info.tail_port;
|
|
20797
|
+
const ehp = e.info.head_port;
|
|
20798
|
+
const etp = e.info.tail_port;
|
|
20799
|
+
return hp.defined === ehp.defined && tp.defined === etp.defined && (!hp.defined || hp.p.x === ehp.p.x && hp.p.y === ehp.p.y) && (!tp.defined || tp.p.x === etp.p.x && tp.p.y === etp.p.y);
|
|
20800
|
+
}
|
|
20801
|
+
function mapPathAdjacentMulti(from, to, orig, ve, type) {
|
|
20802
|
+
const root = dotRoot(from.root);
|
|
20803
|
+
let u = from;
|
|
20804
|
+
for (let r = from.info.rank ?? 0; r < (to.info.rank ?? 0); r++) {
|
|
20805
|
+
const v = r < (to.info.rank ?? 0) - 1 ? cloneVn(root, ve.head) : to;
|
|
20806
|
+
const e = virtualEdge(u, v, orig);
|
|
20807
|
+
e.info.edge_type = type;
|
|
20808
|
+
u = v;
|
|
20809
|
+
ve.info.count = (ve.info.count ?? 1) - 1;
|
|
20810
|
+
ve = ve.head.info.out.list[0];
|
|
20811
|
+
}
|
|
20812
|
+
}
|
|
20813
|
+
function mapPathAdjacentSingle(from, to, orig, ve, type) {
|
|
20814
|
+
const existing = findFastEdge(from, to);
|
|
20815
|
+
if (existing !== void 0 && portsEqSimple(orig, existing)) {
|
|
20816
|
+
orig.info.to_virt = existing;
|
|
20817
|
+
existing.info.edge_type = type;
|
|
20818
|
+
existing.info.count = (existing.info.count ?? 1) + 1;
|
|
20819
|
+
if (from.info.node_type === NORMAL && to.info.node_type === NORMAL)
|
|
20820
|
+
safeOtherEdge(orig);
|
|
20821
|
+
} else {
|
|
20822
|
+
orig.info.to_virt = void 0;
|
|
20823
|
+
const e = virtualEdge(from, to, orig);
|
|
20824
|
+
e.info.edge_type = type;
|
|
20825
|
+
ve.info.count = (ve.info.count ?? 1) - 1;
|
|
20826
|
+
}
|
|
20827
|
+
}
|
|
20828
|
+
function mapPathLongSingle(from, to, orig, ve, type) {
|
|
20829
|
+
let e;
|
|
20830
|
+
if (ve.tail !== from) {
|
|
20831
|
+
orig.info.to_virt = void 0;
|
|
20832
|
+
e = orig.info.to_virt = virtualEdge(from, ve.head, orig);
|
|
20833
|
+
deleteFastEdge(ve);
|
|
20834
|
+
} else {
|
|
20835
|
+
e = ve;
|
|
20836
|
+
}
|
|
20837
|
+
while ((e.head.info.rank ?? 0) !== (to.info.rank ?? 0))
|
|
20838
|
+
e = e.head.info.out.list[0];
|
|
20839
|
+
if (e.head !== to) {
|
|
20840
|
+
const old = e;
|
|
20841
|
+
e = virtualEdge(e.tail, to, orig);
|
|
20842
|
+
e.info.edge_type = type;
|
|
20843
|
+
deleteFastEdge(old);
|
|
20844
|
+
}
|
|
20845
|
+
}
|
|
20846
|
+
function mapPathMultiEdge(from, to, orig, ve, type) {
|
|
20847
|
+
orig.info.to_virt = void 0;
|
|
20848
|
+
const span = (to.info.rank ?? 0) - (from.info.rank ?? 0);
|
|
20849
|
+
if (span === 1) {
|
|
20850
|
+
const ex = findFastEdge(from, to);
|
|
20851
|
+
if (ex !== void 0 && portsEqSimple(orig, ex)) {
|
|
20852
|
+
mergeOneway(orig, ex);
|
|
20853
|
+
if (from.info.node_type === NORMAL && to.info.node_type === NORMAL)
|
|
20854
|
+
safeOtherEdge(orig);
|
|
20855
|
+
return;
|
|
20856
|
+
}
|
|
20857
|
+
}
|
|
20858
|
+
mapPathAdjacentMulti(from, to, orig, ve, type);
|
|
20859
|
+
}
|
|
20860
|
+
function mapPath(from, to, orig, ve, type) {
|
|
20861
|
+
if (ve.tail === from && ve.head === to) return;
|
|
20862
|
+
const span = (to.info.rank ?? 0) - (from.info.rank ?? 0);
|
|
20863
|
+
const cnt = ve.info.count ?? 1;
|
|
20864
|
+
if (cnt > 1) mapPathMultiEdge(from, to, orig, ve, type);
|
|
20865
|
+
else if (span === 1) mapPathAdjacentSingle(from, to, orig, ve, type);
|
|
20866
|
+
else mapPathLongSingle(from, to, orig, ve, type);
|
|
20867
|
+
}
|
|
20868
|
+
function makeInterclustChain(from, to, orig) {
|
|
20869
|
+
const u = mapInterclustNode(from);
|
|
20870
|
+
const v = mapInterclustNode(to);
|
|
20871
|
+
const type = u === from && v === to ? VIRTUAL : CLUSTER_EDGE;
|
|
20872
|
+
mapPath(u, v, orig, orig.info.to_virt, type);
|
|
20873
|
+
}
|
|
20874
|
+
|
|
21804
20875
|
// src/layout/dot/mincross-cross.ts
|
|
21805
20876
|
var reMincross = false;
|
|
21806
20877
|
function setReMincross(b) {
|
|
@@ -22451,134 +21522,6 @@ function orderedEdges(ctx, g) {
|
|
|
22451
21522
|
doOrderingForNodes(ctx, g);
|
|
22452
21523
|
}
|
|
22453
21524
|
|
|
22454
|
-
// src/layout/dot/cluster-path.ts
|
|
22455
|
-
var CLUSTER_EDGE = 5;
|
|
22456
|
-
function mapInterclustNode(n) {
|
|
22457
|
-
const clust = n.info.clust;
|
|
22458
|
-
if (clust === void 0 || clust.info.expanded) return n;
|
|
22459
|
-
return clust.info.rankleader[n.info.rank ?? 0];
|
|
22460
|
-
}
|
|
22461
|
-
function makeSlotsContract(root, r, pos, d) {
|
|
22462
|
-
const rk = root.info.rank[r];
|
|
22463
|
-
for (let i = pos - d + 1; i < rk.n; i++) {
|
|
22464
|
-
const v = rk.v[i];
|
|
22465
|
-
v.info.order = i + d - 1;
|
|
22466
|
-
rk.v[v.info.order] = v;
|
|
22467
|
-
}
|
|
22468
|
-
for (let i = rk.n + d - 1; i < rk.n; i++) rk.v[i] = null;
|
|
22469
|
-
}
|
|
22470
|
-
function makeSlotsExpand(root, r, pos, d) {
|
|
22471
|
-
const rk = root.info.rank[r];
|
|
22472
|
-
for (let i = rk.n - 1; i > pos; i--) {
|
|
22473
|
-
const v = rk.v[i];
|
|
22474
|
-
v.info.order = i + d - 1;
|
|
22475
|
-
rk.v[v.info.order] = v;
|
|
22476
|
-
}
|
|
22477
|
-
for (let i = pos + 1; i < pos + d; i++) rk.v[i] = null;
|
|
22478
|
-
}
|
|
22479
|
-
function makeSlots(root, r, pos, d) {
|
|
22480
|
-
if (d <= 0) makeSlotsContract(root, r, pos, d);
|
|
22481
|
-
else makeSlotsExpand(root, r, pos, d);
|
|
22482
|
-
root.info.rank[r].n += d - 1;
|
|
22483
|
-
}
|
|
22484
|
-
function cloneVn(g, vn) {
|
|
22485
|
-
const r = vn.info.rank ?? 0;
|
|
22486
|
-
makeSlots(g, r, vn.info.order, 2);
|
|
22487
|
-
const rv = virtualNode(g);
|
|
22488
|
-
rv.info.lw = vn.info.lw;
|
|
22489
|
-
rv.info.rw = vn.info.rw;
|
|
22490
|
-
rv.info.rank = r;
|
|
22491
|
-
rv.info.order = (vn.info.order ?? 0) + 1;
|
|
22492
|
-
g.info.rank[r].v[rv.info.order] = rv;
|
|
22493
|
-
return rv;
|
|
22494
|
-
}
|
|
22495
|
-
function safeOtherEdge(e) {
|
|
22496
|
-
if (!e.tail.info.other) e.tail.info.other = { list: [], size: 0 };
|
|
22497
|
-
const other = e.tail.info.other;
|
|
22498
|
-
for (let i = 0; i < other.size; i++) if (other.list[i] === e) return;
|
|
22499
|
-
other.list[other.size++] = e;
|
|
22500
|
-
}
|
|
22501
|
-
function portsEqSimple(orig, e) {
|
|
22502
|
-
const hp = orig.info.head_port;
|
|
22503
|
-
const tp = orig.info.tail_port;
|
|
22504
|
-
const ehp = e.info.head_port;
|
|
22505
|
-
const etp = e.info.tail_port;
|
|
22506
|
-
return hp.defined === ehp.defined && tp.defined === etp.defined && (!hp.defined || hp.p.x === ehp.p.x && hp.p.y === ehp.p.y) && (!tp.defined || tp.p.x === etp.p.x && tp.p.y === etp.p.y);
|
|
22507
|
-
}
|
|
22508
|
-
function mapPathAdjacentMulti(from, to, orig, ve, type) {
|
|
22509
|
-
const root = dotRoot(from.root);
|
|
22510
|
-
let u = from;
|
|
22511
|
-
for (let r = from.info.rank ?? 0; r < (to.info.rank ?? 0); r++) {
|
|
22512
|
-
const v = r < (to.info.rank ?? 0) - 1 ? cloneVn(root, ve.head) : to;
|
|
22513
|
-
const e = virtualEdge(u, v, orig);
|
|
22514
|
-
e.info.edge_type = type;
|
|
22515
|
-
u = v;
|
|
22516
|
-
ve.info.count = (ve.info.count ?? 1) - 1;
|
|
22517
|
-
ve = ve.head.info.out.list[0];
|
|
22518
|
-
}
|
|
22519
|
-
}
|
|
22520
|
-
function mapPathAdjacentSingle(from, to, orig, ve, type) {
|
|
22521
|
-
const existing = findFastEdge(from, to);
|
|
22522
|
-
if (existing !== void 0 && portsEqSimple(orig, existing)) {
|
|
22523
|
-
orig.info.to_virt = existing;
|
|
22524
|
-
existing.info.edge_type = type;
|
|
22525
|
-
existing.info.count = (existing.info.count ?? 1) + 1;
|
|
22526
|
-
if (from.info.node_type === NORMAL && to.info.node_type === NORMAL)
|
|
22527
|
-
safeOtherEdge(orig);
|
|
22528
|
-
} else {
|
|
22529
|
-
orig.info.to_virt = void 0;
|
|
22530
|
-
const e = virtualEdge(from, to, orig);
|
|
22531
|
-
e.info.edge_type = type;
|
|
22532
|
-
ve.info.count = (ve.info.count ?? 1) - 1;
|
|
22533
|
-
}
|
|
22534
|
-
}
|
|
22535
|
-
function mapPathLongSingle(from, to, orig, ve, type) {
|
|
22536
|
-
let e;
|
|
22537
|
-
if (ve.tail !== from) {
|
|
22538
|
-
orig.info.to_virt = void 0;
|
|
22539
|
-
e = orig.info.to_virt = virtualEdge(from, ve.head, orig);
|
|
22540
|
-
deleteFastEdge(ve);
|
|
22541
|
-
} else {
|
|
22542
|
-
e = ve;
|
|
22543
|
-
}
|
|
22544
|
-
while ((e.head.info.rank ?? 0) !== (to.info.rank ?? 0))
|
|
22545
|
-
e = e.head.info.out.list[0];
|
|
22546
|
-
if (e.head !== to) {
|
|
22547
|
-
const old = e;
|
|
22548
|
-
e = virtualEdge(e.tail, to, orig);
|
|
22549
|
-
e.info.edge_type = type;
|
|
22550
|
-
deleteFastEdge(old);
|
|
22551
|
-
}
|
|
22552
|
-
}
|
|
22553
|
-
function mapPathMultiEdge(from, to, orig, ve, type) {
|
|
22554
|
-
orig.info.to_virt = void 0;
|
|
22555
|
-
const span = (to.info.rank ?? 0) - (from.info.rank ?? 0);
|
|
22556
|
-
if (span === 1) {
|
|
22557
|
-
const ex = findFastEdge(from, to);
|
|
22558
|
-
if (ex !== void 0 && portsEqSimple(orig, ex)) {
|
|
22559
|
-
mergeOneway(orig, ex);
|
|
22560
|
-
if (from.info.node_type === NORMAL && to.info.node_type === NORMAL)
|
|
22561
|
-
safeOtherEdge(orig);
|
|
22562
|
-
return;
|
|
22563
|
-
}
|
|
22564
|
-
}
|
|
22565
|
-
mapPathAdjacentMulti(from, to, orig, ve, type);
|
|
22566
|
-
}
|
|
22567
|
-
function mapPath(from, to, orig, ve, type) {
|
|
22568
|
-
if (ve.tail === from && ve.head === to) return;
|
|
22569
|
-
const span = (to.info.rank ?? 0) - (from.info.rank ?? 0);
|
|
22570
|
-
const cnt = ve.info.count ?? 1;
|
|
22571
|
-
if (cnt > 1) mapPathMultiEdge(from, to, orig, ve, type);
|
|
22572
|
-
else if (span === 1) mapPathAdjacentSingle(from, to, orig, ve, type);
|
|
22573
|
-
else mapPathLongSingle(from, to, orig, ve, type);
|
|
22574
|
-
}
|
|
22575
|
-
function makeInterclustChain(from, to, orig) {
|
|
22576
|
-
const u = mapInterclustNode(from);
|
|
22577
|
-
const v = mapInterclustNode(to);
|
|
22578
|
-
const type = u === from && v === to ? VIRTUAL : CLUSTER_EDGE;
|
|
22579
|
-
mapPath(u, v, orig, orig.info.to_virt, type);
|
|
22580
|
-
}
|
|
22581
|
-
|
|
22582
21525
|
// src/layout/dot/cluster.ts
|
|
22583
21526
|
function interclexpMergeable(prev, e) {
|
|
22584
21527
|
if (!prev) return false;
|
|
@@ -22858,15 +21801,325 @@ function markLowclusterBasic(g) {
|
|
|
22858
21801
|
for (let c = 1; c <= nClust; c++) markLowclusterBasic(g.info.clust[c - 1]);
|
|
22859
21802
|
const outByTail = outEdgesByTail(g.edges);
|
|
22860
21803
|
for (const n of nodesInSeq(g)) {
|
|
22861
|
-
if (n.info.clust === void 0) n.info.clust = g;
|
|
22862
|
-
const oes = outByTail.get(n);
|
|
22863
|
-
if (oes === void 0) continue;
|
|
22864
|
-
for (const orig of oes) markLowclusterChain(orig, g);
|
|
21804
|
+
if (n.info.clust === void 0) n.info.clust = g;
|
|
21805
|
+
const oes = outByTail.get(n);
|
|
21806
|
+
if (oes === void 0) continue;
|
|
21807
|
+
for (const orig of oes) markLowclusterChain(orig, g);
|
|
21808
|
+
}
|
|
21809
|
+
}
|
|
21810
|
+
function markLowclusters(root) {
|
|
21811
|
+
markLowclustersZap(root);
|
|
21812
|
+
markLowclusterBasic(root);
|
|
21813
|
+
}
|
|
21814
|
+
|
|
21815
|
+
// src/layout/dot/classify.ts
|
|
21816
|
+
function portsEq(e, f) {
|
|
21817
|
+
const ehp = e.info.head_port;
|
|
21818
|
+
const fhp = f.info.head_port;
|
|
21819
|
+
const etp = e.info.tail_port;
|
|
21820
|
+
const ftp = f.info.tail_port;
|
|
21821
|
+
const headMatch = ehp.p.x === fhp.p.x && ehp.p.y === fhp.p.y || !ehp.defined;
|
|
21822
|
+
const tailMatch = etp.p.x === ftp.p.x && etp.p.y === ftp.p.y || !etp.defined;
|
|
21823
|
+
return ehp.defined === fhp.defined && headMatch && tailMatch;
|
|
21824
|
+
}
|
|
21825
|
+
function nonconstraintEdge(e) {
|
|
21826
|
+
return e.info.constraint === false;
|
|
21827
|
+
}
|
|
21828
|
+
var WNODE_ORDINARY = 0;
|
|
21829
|
+
var WNODE_SINGLETON = 1;
|
|
21830
|
+
var WNODE_VIRTUAL = 2;
|
|
21831
|
+
var CLASSIFY_WEIGHT_TABLE = [[1, 1, 1], [1, 2, 2], [1, 2, 4]];
|
|
21832
|
+
function epClass(n) {
|
|
21833
|
+
if (n.info.node_type === VIRTUAL) return WNODE_VIRTUAL;
|
|
21834
|
+
if ((n.info.weight_class ?? 2) <= 1) return WNODE_SINGLETON;
|
|
21835
|
+
return WNODE_ORDINARY;
|
|
21836
|
+
}
|
|
21837
|
+
function applyVirtualWeight(e) {
|
|
21838
|
+
const t = CLASSIFY_WEIGHT_TABLE[epClass(e.tail)][epClass(e.head)];
|
|
21839
|
+
e.info.weight = (e.info.weight ?? 1) * t;
|
|
21840
|
+
}
|
|
21841
|
+
function interclust1TRank(e) {
|
|
21842
|
+
const clust = e.tail.info.clust;
|
|
21843
|
+
return clust ? (e.tail.info.rank ?? 0) - (clust.info.leader?.info.rank ?? 0) : 0;
|
|
21844
|
+
}
|
|
21845
|
+
function interclust1HRank(e) {
|
|
21846
|
+
const clust = e.head.info.clust;
|
|
21847
|
+
return clust ? (e.head.info.rank ?? 0) - (clust.info.leader?.info.rank ?? 0) : 0;
|
|
21848
|
+
}
|
|
21849
|
+
function interclust1Lengths(e) {
|
|
21850
|
+
const offset = (e.info.minlen ?? 1) + interclust1TRank(e) - interclust1HRank(e);
|
|
21851
|
+
return offset > 0 ? [0, offset] : [-offset, 0];
|
|
21852
|
+
}
|
|
21853
|
+
function interclust1(g, t, h, e) {
|
|
21854
|
+
const [tLen, hLen] = interclust1Lengths(e);
|
|
21855
|
+
const v = virtualNode(g);
|
|
21856
|
+
v.info.node_type = SLACKNODE;
|
|
21857
|
+
const t0 = ufFind(t);
|
|
21858
|
+
const h0 = ufFind(h);
|
|
21859
|
+
const w = e.info.weight ?? 1;
|
|
21860
|
+
const rt = makeAuxEdge(v, t0, tLen, CL_BACK * w);
|
|
21861
|
+
const rh = makeAuxEdge(v, h0, hLen, w);
|
|
21862
|
+
rt.info.to_orig = e;
|
|
21863
|
+
rh.info.to_orig = e;
|
|
21864
|
+
}
|
|
21865
|
+
function class1Edge(g, e) {
|
|
21866
|
+
if (e.info.to_virt !== void 0) return;
|
|
21867
|
+
if (nonconstraintEdge(e)) return;
|
|
21868
|
+
const t = ufFind(e.tail);
|
|
21869
|
+
const h = ufFind(e.head);
|
|
21870
|
+
if (t === h) return;
|
|
21871
|
+
if (t.info.clust || h.info.clust) {
|
|
21872
|
+
interclust1(g, e.tail, e.head, e);
|
|
21873
|
+
return;
|
|
21874
|
+
}
|
|
21875
|
+
const rep = findFastEdge(t, h);
|
|
21876
|
+
if (rep !== void 0) mergeOneway(e, rep);
|
|
21877
|
+
else virtualEdge(t, h, e);
|
|
21878
|
+
}
|
|
21879
|
+
function class1(g) {
|
|
21880
|
+
markClusters(g);
|
|
21881
|
+
for (const n of nodesInSeq(g)) {
|
|
21882
|
+
for (const e of n.outEdges(g)) class1Edge(g, e);
|
|
21883
|
+
}
|
|
21884
|
+
}
|
|
21885
|
+
function labelVnodeDimen(orig) {
|
|
21886
|
+
const lbl = orig.info.label;
|
|
21887
|
+
return lbl?.dimen;
|
|
21888
|
+
}
|
|
21889
|
+
function labelVnode(g, orig) {
|
|
21890
|
+
const dimen = labelVnodeDimen(orig);
|
|
21891
|
+
const v = virtualNode(g);
|
|
21892
|
+
v.info.label = orig.info.label;
|
|
21893
|
+
v.info.lw = dotRoot(g).info.nodesep ?? 0;
|
|
21894
|
+
if (!orig.info.label_ontop && dimen) {
|
|
21895
|
+
const flip = dotRoot(g).info.flip === true;
|
|
21896
|
+
v.info.ht = flip ? dimen.x : dimen.y;
|
|
21897
|
+
v.info.rw = flip ? dimen.y : dimen.x;
|
|
21898
|
+
}
|
|
21899
|
+
return v;
|
|
21900
|
+
}
|
|
21901
|
+
function incrWidth(g, v) {
|
|
21902
|
+
const width = Math.floor((g.info.nodesep ?? 0) / 2);
|
|
21903
|
+
v.info.lw = (v.info.lw ?? 0) + width;
|
|
21904
|
+
v.info.rw = (v.info.rw ?? 0) + width;
|
|
21905
|
+
}
|
|
21906
|
+
function plainVnode(g) {
|
|
21907
|
+
const v = virtualNode(g);
|
|
21908
|
+
incrWidth(g, v);
|
|
21909
|
+
return v;
|
|
21910
|
+
}
|
|
21911
|
+
function leaderOf(v) {
|
|
21912
|
+
if (v.info.ranktype !== CLUSTER) return ufFind(v);
|
|
21913
|
+
return v.info.clust.info.rankleader[v.info.rank ?? 0];
|
|
21914
|
+
}
|
|
21915
|
+
function chainVnode(g, orig, r, labelRank) {
|
|
21916
|
+
if (r === labelRank) return labelVnode(g, orig);
|
|
21917
|
+
return plainVnode(g);
|
|
21918
|
+
}
|
|
21919
|
+
function makeChain(g, from, to, orig) {
|
|
21920
|
+
const labelRank = orig.info.label !== void 0 ? Math.floor(((from.info.rank ?? 0) + (to.info.rank ?? 0)) / 2) : -1;
|
|
21921
|
+
let u = from;
|
|
21922
|
+
const toRank = to.info.rank ?? 0;
|
|
21923
|
+
for (let r = (from.info.rank ?? 0) + 1; r <= toRank; r++) {
|
|
21924
|
+
const v = r < toRank ? (() => {
|
|
21925
|
+
const n = chainVnode(g, orig, r, labelRank);
|
|
21926
|
+
n.info.rank = r;
|
|
21927
|
+
return n;
|
|
21928
|
+
})() : to;
|
|
21929
|
+
const e = virtualEdge(u, v, orig);
|
|
21930
|
+
applyVirtualWeight(e);
|
|
21931
|
+
u = v;
|
|
21932
|
+
}
|
|
21933
|
+
}
|
|
21934
|
+
function nodeRank3(n) {
|
|
21935
|
+
return n.info.rank ?? 0;
|
|
21936
|
+
}
|
|
21937
|
+
function edgeCount(e) {
|
|
21938
|
+
return e.info.count ?? 1;
|
|
21939
|
+
}
|
|
21940
|
+
function edgeXpenalty(e) {
|
|
21941
|
+
return e.info.xpenalty ?? 0;
|
|
21942
|
+
}
|
|
21943
|
+
function edgeWeight3(e) {
|
|
21944
|
+
return e.info.weight ?? 1;
|
|
21945
|
+
}
|
|
21946
|
+
function nextVirtEdge(e) {
|
|
21947
|
+
return e.head.info.out?.list[0];
|
|
21948
|
+
}
|
|
21949
|
+
function mergeChainStep(rep, e, updateCount) {
|
|
21950
|
+
if (updateCount) rep.info.count = edgeCount(rep) + edgeCount(e);
|
|
21951
|
+
rep.info.xpenalty = edgeXpenalty(rep) + edgeXpenalty(e);
|
|
21952
|
+
rep.info.weight = edgeWeight3(rep) + edgeWeight3(e);
|
|
21953
|
+
return nextVirtEdge(rep);
|
|
21954
|
+
}
|
|
21955
|
+
function mergeChain(g, e, f, updateCount) {
|
|
21956
|
+
const lastrank = Math.max(e.tail.info.rank ?? 0, e.head.info.rank ?? 0);
|
|
21957
|
+
e.info.to_virt = f;
|
|
21958
|
+
let rep = f;
|
|
21959
|
+
while (rep !== void 0) {
|
|
21960
|
+
if ((rep.head.info.rank ?? 0) === lastrank) {
|
|
21961
|
+
mergeChainStep(rep, e, updateCount);
|
|
21962
|
+
break;
|
|
21963
|
+
}
|
|
21964
|
+
incrWidth(g, rep.head);
|
|
21965
|
+
rep = mergeChainStep(rep, e, updateCount);
|
|
21966
|
+
}
|
|
21967
|
+
}
|
|
21968
|
+
function mergeable(e, f) {
|
|
21969
|
+
if (!e || !f) return false;
|
|
21970
|
+
return e.tail === f.tail && e.head === f.head && e.info.label === f.info.label && portsEq(e, f);
|
|
21971
|
+
}
|
|
21972
|
+
function interclrepChain(g, e, t, h) {
|
|
21973
|
+
makeChain(g, t, h, e);
|
|
21974
|
+
let cur = e.info.to_virt;
|
|
21975
|
+
while (cur !== void 0 && nodeRank3(cur.head) <= nodeRank3(h)) {
|
|
21976
|
+
cur.info.edge_type = CLUSTER_EDGE;
|
|
21977
|
+
cur = cur.head.info.out?.list[0];
|
|
21978
|
+
}
|
|
21979
|
+
}
|
|
21980
|
+
function interclrep(g, e) {
|
|
21981
|
+
let t = leaderOf(e.tail);
|
|
21982
|
+
let h = leaderOf(e.head);
|
|
21983
|
+
if (nodeRank3(t) > nodeRank3(h)) {
|
|
21984
|
+
const tmp = t;
|
|
21985
|
+
t = h;
|
|
21986
|
+
h = tmp;
|
|
21987
|
+
}
|
|
21988
|
+
if (t.info.clust === h.info.clust) return;
|
|
21989
|
+
const ve = findFastEdge(t, h);
|
|
21990
|
+
if (ve !== void 0) {
|
|
21991
|
+
mergeChain(g, e, ve, true);
|
|
21992
|
+
return;
|
|
21993
|
+
}
|
|
21994
|
+
if (nodeRank3(t) === nodeRank3(h)) return;
|
|
21995
|
+
interclrepChain(g, e, t, h);
|
|
21996
|
+
}
|
|
21997
|
+
function isClusterEdge(e) {
|
|
21998
|
+
return e.tail.info.ranktype === CLUSTER || e.head.info.ranktype === CLUSTER;
|
|
21999
|
+
}
|
|
22000
|
+
function handleClusterMergeable(g, e, prev) {
|
|
22001
|
+
if (prev.info.to_virt !== void 0) {
|
|
22002
|
+
mergeChain(g, e, prev.info.to_virt, false);
|
|
22003
|
+
otherEdge(e);
|
|
22004
|
+
} else if ((e.tail.info.rank ?? 0) === (e.head.info.rank ?? 0)) {
|
|
22005
|
+
mergeOneway(e, prev);
|
|
22006
|
+
otherEdge(e);
|
|
22007
|
+
}
|
|
22008
|
+
return prev;
|
|
22009
|
+
}
|
|
22010
|
+
function handleClusterEdge(g, e, prev) {
|
|
22011
|
+
if (mergeable(prev, e)) return handleClusterMergeable(g, e, prev);
|
|
22012
|
+
interclrep(g, e);
|
|
22013
|
+
return e;
|
|
22014
|
+
}
|
|
22015
|
+
function concentrateOrMerge(g, e, prev) {
|
|
22016
|
+
if (dotRoot(g).info.concentrate ?? false) {
|
|
22017
|
+
e.info.edge_type = IGNORED;
|
|
22018
|
+
} else if (prev.info.to_virt !== void 0) {
|
|
22019
|
+
mergeChain(g, e, prev.info.to_virt, true);
|
|
22020
|
+
otherEdge(e);
|
|
22021
|
+
}
|
|
22022
|
+
}
|
|
22023
|
+
function handleMultiSameRank(e, prev) {
|
|
22024
|
+
if ((e.tail.info.rank ?? 0) !== (e.head.info.rank ?? 0)) return false;
|
|
22025
|
+
mergeOneway(e, prev);
|
|
22026
|
+
otherEdge(e);
|
|
22027
|
+
return true;
|
|
22028
|
+
}
|
|
22029
|
+
function handleMultiParallel(g, e, prev) {
|
|
22030
|
+
if (e.info.label !== void 0 || prev.info.label !== void 0) return false;
|
|
22031
|
+
if (!portsEq(e, prev)) return false;
|
|
22032
|
+
concentrateOrMerge(g, e, prev);
|
|
22033
|
+
return true;
|
|
22034
|
+
}
|
|
22035
|
+
function handleMultiEdge(g, e, prev) {
|
|
22036
|
+
if (!prev || e.tail !== prev.tail || e.head !== prev.head) return false;
|
|
22037
|
+
if (handleMultiSameRank(e, prev)) return true;
|
|
22038
|
+
return handleMultiParallel(g, e, prev);
|
|
22039
|
+
}
|
|
22040
|
+
function oppEdgeConcOrMerge(g, e, opp) {
|
|
22041
|
+
if (e.info.label !== void 0 || opp.info.label !== void 0) return false;
|
|
22042
|
+
if (!portsEq(e, opp)) return false;
|
|
22043
|
+
if (dotRoot(g).info.concentrate ?? false) {
|
|
22044
|
+
e.info.edge_type = IGNORED;
|
|
22045
|
+
opp.info.conc_opp_flag = true;
|
|
22046
|
+
} else {
|
|
22047
|
+
otherEdge(e);
|
|
22048
|
+
mergeChain(g, e, opp.info.to_virt, true);
|
|
22049
|
+
}
|
|
22050
|
+
return true;
|
|
22051
|
+
}
|
|
22052
|
+
function tryOppEdge(g, e, opp) {
|
|
22053
|
+
if (opp.head !== e.tail) return false;
|
|
22054
|
+
if (opp.info.edge_type === IGNORED) return false;
|
|
22055
|
+
if (opp.info.to_virt === void 0) makeChain(g, opp.tail, opp.head, opp);
|
|
22056
|
+
return oppEdgeConcOrMerge(g, e, opp);
|
|
22057
|
+
}
|
|
22058
|
+
function handleBackEdge(g, e) {
|
|
22059
|
+
for (const opp of e.head.outEdges(g)) {
|
|
22060
|
+
if (tryOppEdge(g, e, opp)) return void 0;
|
|
22061
|
+
}
|
|
22062
|
+
makeChain(g, e.head, e.tail, e);
|
|
22063
|
+
return e;
|
|
22064
|
+
}
|
|
22065
|
+
function class2EdgeSameRep(g, e) {
|
|
22066
|
+
if (nodeRank3(e.tail) === nodeRank3(e.head)) {
|
|
22067
|
+
flatEdge(g, e);
|
|
22068
|
+
return e;
|
|
22069
|
+
}
|
|
22070
|
+
if (nodeRank3(e.head) > nodeRank3(e.tail)) {
|
|
22071
|
+
makeChain(g, e.tail, e.head, e);
|
|
22072
|
+
return e;
|
|
22073
|
+
}
|
|
22074
|
+
return handleBackEdge(g, e);
|
|
22075
|
+
}
|
|
22076
|
+
function class2OneEdge(g, e, prev) {
|
|
22077
|
+
if (e.info.to_virt !== void 0) return e;
|
|
22078
|
+
if (isClusterEdge(e)) return handleClusterEdge(g, e, prev);
|
|
22079
|
+
if (handleMultiEdge(g, e, prev)) return prev;
|
|
22080
|
+
if (e.tail === e.head) {
|
|
22081
|
+
otherEdge(e);
|
|
22082
|
+
return e;
|
|
22083
|
+
}
|
|
22084
|
+
const t = ufFind(e.tail);
|
|
22085
|
+
const h = ufFind(e.head);
|
|
22086
|
+
if (e.tail !== t || e.head !== h) return prev;
|
|
22087
|
+
return class2EdgeSameRep(g, e);
|
|
22088
|
+
}
|
|
22089
|
+
function class2ProcessNodeEdges(g, oes) {
|
|
22090
|
+
let prev;
|
|
22091
|
+
for (const e of oes) {
|
|
22092
|
+
const next = class2OneEdge(g, e, prev);
|
|
22093
|
+
prev = next !== void 0 ? next : prev;
|
|
22094
|
+
}
|
|
22095
|
+
}
|
|
22096
|
+
function weightClass(n) {
|
|
22097
|
+
return n.info.weight_class ?? 0;
|
|
22098
|
+
}
|
|
22099
|
+
function incrWeightClass(n) {
|
|
22100
|
+
if (weightClass(n) <= 2) n.info.weight_class = weightClass(n) + 1;
|
|
22101
|
+
}
|
|
22102
|
+
function class2WeightClasses(g) {
|
|
22103
|
+
for (const e of g.edges) {
|
|
22104
|
+
incrWeightClass(e.head);
|
|
22105
|
+
incrWeightClass(e.tail);
|
|
22106
|
+
}
|
|
22107
|
+
}
|
|
22108
|
+
function class2ProcessNodes(g) {
|
|
22109
|
+
const outIdx = buildOutEdgeIndex(g);
|
|
22110
|
+
for (const n of nodesInSeq(g)) {
|
|
22111
|
+
if (n.info.clust === void 0 && n === ufFind(n)) fastNode(g, n);
|
|
22112
|
+
class2ProcessNodeEdges(g, outIdx.get(n) ?? []);
|
|
22865
22113
|
}
|
|
22866
22114
|
}
|
|
22867
|
-
function
|
|
22868
|
-
|
|
22869
|
-
|
|
22115
|
+
function class2(g) {
|
|
22116
|
+
g.info.nlist = void 0;
|
|
22117
|
+
markClusters(g);
|
|
22118
|
+
const nClust = g.info.n_cluster ?? 0;
|
|
22119
|
+
for (let c = 1; c <= nClust; c++) buildSkeleton(g, g.info.clust[c - 1]);
|
|
22120
|
+
class2WeightClasses(g);
|
|
22121
|
+
class2ProcessNodes(g);
|
|
22122
|
+
if (g !== dotRoot(g)) g.info.comp = [g.info.nlist ?? null];
|
|
22870
22123
|
}
|
|
22871
22124
|
|
|
22872
22125
|
// src/layout/dot/rank.ts
|
|
@@ -23129,450 +22382,1223 @@ function gMaxrankVal(g) {
|
|
|
23129
22382
|
function gNCluster(g) {
|
|
23130
22383
|
return g.info.n_cluster ?? 0;
|
|
23131
22384
|
}
|
|
23132
|
-
function gClust(g) {
|
|
23133
|
-
return g.info.clust ?? [];
|
|
22385
|
+
function gClust(g) {
|
|
22386
|
+
return g.info.clust ?? [];
|
|
22387
|
+
}
|
|
22388
|
+
function nRank(n) {
|
|
22389
|
+
return n.info.rank ?? 0;
|
|
22390
|
+
}
|
|
22391
|
+
function nRanktype(n) {
|
|
22392
|
+
return n.info.ranktype ?? 0;
|
|
22393
|
+
}
|
|
22394
|
+
function gMaxrankDef(g) {
|
|
22395
|
+
return g.info.maxrank ?? -1;
|
|
22396
|
+
}
|
|
22397
|
+
function gMinrankDef(g) {
|
|
22398
|
+
return g.info.minrank ?? Number.MAX_SAFE_INTEGER;
|
|
22399
|
+
}
|
|
22400
|
+
function setMinmax(g) {
|
|
22401
|
+
const lr = gLeaderRank(g);
|
|
22402
|
+
g.info.minrank = gMinrankVal(g) + lr;
|
|
22403
|
+
g.info.maxrank = gMaxrankVal(g) + lr;
|
|
22404
|
+
const cl = gClust(g);
|
|
22405
|
+
const nc = gNCluster(g);
|
|
22406
|
+
for (let c = 1; c <= nc; c++) setMinmax(cl[c - 1]);
|
|
22407
|
+
}
|
|
22408
|
+
function minmaxEdgesReverse(n, isOut) {
|
|
22409
|
+
const rt = n.info.ranktype ?? 0;
|
|
22410
|
+
const flag = isOut ? rt === SINKRANK : rt === SOURCERANK;
|
|
22411
|
+
const list = isOut ? n.info.out : n.info.in;
|
|
22412
|
+
if (list) {
|
|
22413
|
+
while (list.size > 0) reverseEdge(list.list[0]);
|
|
22414
|
+
}
|
|
22415
|
+
return flag ? 1 : 0;
|
|
22416
|
+
}
|
|
22417
|
+
function minmaxEdges(g) {
|
|
22418
|
+
if (!g.info.maxset && !g.info.minset) return [0, 0];
|
|
22419
|
+
if (g.info.minset) g.info.minset = ufFind(g.info.minset);
|
|
22420
|
+
if (g.info.maxset) g.info.maxset = ufFind(g.info.maxset);
|
|
22421
|
+
const slenY = g.info.maxset ? minmaxEdgesReverse(g.info.maxset, true) : 0;
|
|
22422
|
+
const slenX = g.info.minset ? minmaxEdgesReverse(g.info.minset, false) : 0;
|
|
22423
|
+
return [slenX, slenY];
|
|
22424
|
+
}
|
|
22425
|
+
function nOutEdge0(n) {
|
|
22426
|
+
return n.info.out?.list[0];
|
|
22427
|
+
}
|
|
22428
|
+
function nInEdge0(n) {
|
|
22429
|
+
return n.info.in?.list[0];
|
|
22430
|
+
}
|
|
22431
|
+
function mmEdges2CheckMax(g, n, slen1) {
|
|
22432
|
+
const out = n.info.out;
|
|
22433
|
+
if ((!out || out.size === 0) && g.info.maxset && n !== g.info.maxset) {
|
|
22434
|
+
const ref = nOutEdge0(n) ?? nInEdge0(n);
|
|
22435
|
+
const e = virtualEdge(n, g.info.maxset, ref);
|
|
22436
|
+
e.info.minlen = slen1;
|
|
22437
|
+
e.info.weight = 0;
|
|
22438
|
+
return true;
|
|
22439
|
+
}
|
|
22440
|
+
return false;
|
|
22441
|
+
}
|
|
22442
|
+
function mmEdges2CheckMin(g, n, slen0) {
|
|
22443
|
+
const inp = n.info.in;
|
|
22444
|
+
if ((!inp || inp.size === 0) && g.info.minset && n !== g.info.minset) {
|
|
22445
|
+
const ref = nInEdge0(n) ?? nOutEdge0(n);
|
|
22446
|
+
const e = virtualEdge(g.info.minset, n, ref);
|
|
22447
|
+
e.info.minlen = slen0;
|
|
22448
|
+
e.info.weight = 0;
|
|
22449
|
+
return true;
|
|
22450
|
+
}
|
|
22451
|
+
return false;
|
|
22452
|
+
}
|
|
22453
|
+
function minmaxEdges2(g, slen) {
|
|
22454
|
+
if (!g.info.maxset && !g.info.minset) return false;
|
|
22455
|
+
let added = false;
|
|
22456
|
+
for (const n of nodesInSeq(g)) {
|
|
22457
|
+
if (n !== ufFind(n)) continue;
|
|
22458
|
+
if (mmEdges2CheckMax(g, n, slen[1])) added = true;
|
|
22459
|
+
if (mmEdges2CheckMin(g, n, slen[0])) added = true;
|
|
22460
|
+
}
|
|
22461
|
+
return added;
|
|
22462
|
+
}
|
|
22463
|
+
function rank1(g) {
|
|
22464
|
+
const nslimit1 = g.attrs.get("nslimit1") ?? g.graphDefaultsSnapshot?.get("nslimit1") ?? g.root.attrs.get("nslimit1");
|
|
22465
|
+
const maxiter = nslimit1 ? scaleClamp(g.nodes.size, parseFloat(nslimit1)) : Number.MAX_SAFE_INTEGER;
|
|
22466
|
+
const comp = g.info.comp ?? [];
|
|
22467
|
+
const hasClusters = (g.info.n_cluster ?? 0) > 0;
|
|
22468
|
+
for (let c = 0; c < comp.length; c++) {
|
|
22469
|
+
g.info.nlist = comp[c];
|
|
22470
|
+
rank(g, hasClusters ? 0 : 1, maxiter);
|
|
22471
|
+
}
|
|
22472
|
+
}
|
|
22473
|
+
function expandNode(g, n) {
|
|
22474
|
+
const leader = ufFind(n);
|
|
22475
|
+
if (leader !== n) n.info.rank = nRank(n) + nRank(leader);
|
|
22476
|
+
if (gMaxrankDef(g) < nRank(n)) g.info.maxrank = n.info.rank;
|
|
22477
|
+
if (gMinrankDef(g) > nRank(n)) g.info.minrank = n.info.rank;
|
|
22478
|
+
if (nRanktype(n) !== 0 && nRanktype(n) !== LEAFSET) ufSingleton(n);
|
|
22479
|
+
}
|
|
22480
|
+
function expandRankPostprocess(g) {
|
|
22481
|
+
if (clType === LOCAL) {
|
|
22482
|
+
const cl = gClust(g);
|
|
22483
|
+
for (let c = 1; c <= gNCluster(g); c++) setMinmax(cl[c - 1]);
|
|
22484
|
+
} else {
|
|
22485
|
+
findClusters(g);
|
|
22486
|
+
}
|
|
22487
|
+
}
|
|
22488
|
+
function expandRanksets(g) {
|
|
22489
|
+
const first = g.nodes.values().next().value;
|
|
22490
|
+
if (!first) {
|
|
22491
|
+
g.info.minrank = 0;
|
|
22492
|
+
g.info.maxrank = 0;
|
|
22493
|
+
return;
|
|
22494
|
+
}
|
|
22495
|
+
g.info.minrank = Number.MAX_SAFE_INTEGER;
|
|
22496
|
+
g.info.maxrank = -1;
|
|
22497
|
+
for (const n of nodesInSeq(g)) expandNode(g, n);
|
|
22498
|
+
if (g === (g.info.dotroot ?? g.root)) expandRankPostprocess(g);
|
|
22499
|
+
}
|
|
22500
|
+
function dot1Rank(g) {
|
|
22501
|
+
edgelabelRanks(g);
|
|
22502
|
+
collapseSets(g, g);
|
|
22503
|
+
class1(g);
|
|
22504
|
+
const slen = minmaxEdges(g);
|
|
22505
|
+
decompose(g, 0);
|
|
22506
|
+
acyclic(g);
|
|
22507
|
+
if (minmaxEdges2(g, slen)) decompose(g, 0);
|
|
22508
|
+
rank1(g);
|
|
22509
|
+
expandRanksets(g);
|
|
22510
|
+
cleanup1(g);
|
|
22511
|
+
}
|
|
22512
|
+
function dotRank(g) {
|
|
22513
|
+
if (mapbool2(g.attrs.get("newrank"))) {
|
|
22514
|
+
g.info.flags = (g.info.flags ?? 0) | NEW_RANK;
|
|
22515
|
+
dot2Rank(g);
|
|
22516
|
+
} else {
|
|
22517
|
+
dot1Rank(g);
|
|
22518
|
+
}
|
|
22519
|
+
}
|
|
22520
|
+
|
|
22521
|
+
// src/common/record.ts
|
|
22522
|
+
var HASTEXT = 1;
|
|
22523
|
+
var HASPORT = 2;
|
|
22524
|
+
var HASTABLE = 4;
|
|
22525
|
+
var INTEXT = 8;
|
|
22526
|
+
var INPORT = 16;
|
|
22527
|
+
var BOTTOM2 = 1;
|
|
22528
|
+
var RIGHT2 = 2;
|
|
22529
|
+
var TOP2 = 4;
|
|
22530
|
+
var LEFT2 = 8;
|
|
22531
|
+
var PAD_X = 16;
|
|
22532
|
+
var PAD_Y = 8;
|
|
22533
|
+
function makeField() {
|
|
22534
|
+
return {
|
|
22535
|
+
size: { x: 0, y: 0 },
|
|
22536
|
+
b: { ll: { x: 0, y: 0 }, ur: { x: 0, y: 0 } },
|
|
22537
|
+
n_flds: 0,
|
|
22538
|
+
lp: null,
|
|
22539
|
+
fld: null,
|
|
22540
|
+
id: null,
|
|
22541
|
+
LR: 0,
|
|
22542
|
+
sides: 0
|
|
22543
|
+
};
|
|
22544
|
+
}
|
|
22545
|
+
function recIsEscapedDelim(s, j) {
|
|
22546
|
+
if (s[j] !== "\\") return false;
|
|
22547
|
+
const nx = s[j + 1];
|
|
22548
|
+
return nx === "{" || nx === "}" || nx === "|" || nx === "\\";
|
|
22549
|
+
}
|
|
22550
|
+
function recCountFields(p) {
|
|
22551
|
+
let maxf = 1;
|
|
22552
|
+
let cnt = 0;
|
|
22553
|
+
for (let j = p.i; j < p.s.length; j++) {
|
|
22554
|
+
if (recIsEscapedDelim(p.s, j)) {
|
|
22555
|
+
j++;
|
|
22556
|
+
continue;
|
|
22557
|
+
}
|
|
22558
|
+
const c = p.s[j];
|
|
22559
|
+
if (c === "{") cnt++;
|
|
22560
|
+
else if (c === "}") cnt--;
|
|
22561
|
+
else if (c === "|" && cnt === 0) maxf++;
|
|
22562
|
+
if (cnt < 0) break;
|
|
22563
|
+
}
|
|
22564
|
+
return maxf;
|
|
22565
|
+
}
|
|
22566
|
+
function recOpenPort(p, st) {
|
|
22567
|
+
if (st.mode & (HASTABLE | HASPORT)) return -1;
|
|
22568
|
+
st.mode |= HASPORT | INPORT;
|
|
22569
|
+
p.i++;
|
|
22570
|
+
st.pbuf = [];
|
|
22571
|
+
st.hspIdx = 0;
|
|
22572
|
+
return 0;
|
|
22573
|
+
}
|
|
22574
|
+
function recClosePort(p, st) {
|
|
22575
|
+
if (!(st.mode & INPORT)) return -1;
|
|
22576
|
+
const t = st.pbuf;
|
|
22577
|
+
if (t.length > 1 && st.hspIdx !== t.length - 1 && t[t.length - 1] === " ") t.pop();
|
|
22578
|
+
st.tmpport = t.join("");
|
|
22579
|
+
st.mode &= ~INPORT;
|
|
22580
|
+
p.i++;
|
|
22581
|
+
return 0;
|
|
22582
|
+
}
|
|
22583
|
+
function recOpenTable(p, st, LR) {
|
|
22584
|
+
p.i++;
|
|
22585
|
+
if (st.mode !== 0 || p.i >= p.s.length) return -1;
|
|
22586
|
+
st.mode = HASTABLE;
|
|
22587
|
+
const sub = parseReclbl(p, LR ? 0 : 1, false);
|
|
22588
|
+
if (sub === null) return -1;
|
|
22589
|
+
st.rv.fld[st.fi++] = sub;
|
|
22590
|
+
st.fp = sub;
|
|
22591
|
+
return 0;
|
|
22592
|
+
}
|
|
22593
|
+
function recFlushText(p, st) {
|
|
22594
|
+
if (!(st.mode & (HASTEXT | HASTABLE))) {
|
|
22595
|
+
st.mode |= HASTEXT;
|
|
22596
|
+
st.tbuf.push(" ");
|
|
22597
|
+
}
|
|
22598
|
+
if (st.mode & HASTEXT) {
|
|
22599
|
+
const t = st.tbuf;
|
|
22600
|
+
if (t.length > 1 && st.hstIdx !== t.length - 1 && t[t.length - 1] === " ") t.pop();
|
|
22601
|
+
st.fp.lp = makeAnyLabel(
|
|
22602
|
+
t.join(""),
|
|
22603
|
+
false,
|
|
22604
|
+
{ fontname: p.lbl.fontname, fontsize: p.lbl.fontsize, fontcolor: p.lbl.fontcolor },
|
|
22605
|
+
p.measurer,
|
|
22606
|
+
p.obj
|
|
22607
|
+
);
|
|
22608
|
+
st.fp.LR = 1;
|
|
22609
|
+
st.tbuf = [];
|
|
22610
|
+
st.hstIdx = 0;
|
|
22611
|
+
}
|
|
22612
|
+
}
|
|
22613
|
+
function recEndField(p, st, flag) {
|
|
22614
|
+
const c = p.i < p.s.length ? p.s[p.i] : "";
|
|
22615
|
+
if (c === "" && !flag || st.mode & INPORT) return -1;
|
|
22616
|
+
if (!(st.mode & HASTABLE)) {
|
|
22617
|
+
st.fp = makeField();
|
|
22618
|
+
st.rv.fld[st.fi++] = st.fp;
|
|
22619
|
+
}
|
|
22620
|
+
if (st.tmpport !== null) {
|
|
22621
|
+
st.fp.id = st.tmpport;
|
|
22622
|
+
st.tmpport = null;
|
|
22623
|
+
}
|
|
22624
|
+
recFlushText(p, st);
|
|
22625
|
+
if (c !== "") {
|
|
22626
|
+
if (c === "}") {
|
|
22627
|
+
p.i++;
|
|
22628
|
+
st.rv.n_flds = st.fi;
|
|
22629
|
+
return 1;
|
|
22630
|
+
}
|
|
22631
|
+
st.mode = 0;
|
|
22632
|
+
p.i++;
|
|
22633
|
+
return 0;
|
|
22634
|
+
}
|
|
22635
|
+
st.rv.n_flds = st.fi;
|
|
22636
|
+
return 1;
|
|
22637
|
+
}
|
|
22638
|
+
function recBackslash(p, st) {
|
|
22639
|
+
const nx = p.s[p.i + 1];
|
|
22640
|
+
if (nx !== void 0) {
|
|
22641
|
+
if (nx < " ") {
|
|
22642
|
+
} else if (nx === " " && !p.lbl.html) {
|
|
22643
|
+
st.ishardspace = true;
|
|
22644
|
+
} else {
|
|
22645
|
+
st.tbuf.push("\\");
|
|
22646
|
+
st.mode |= INTEXT | HASTEXT;
|
|
22647
|
+
}
|
|
22648
|
+
p.i++;
|
|
22649
|
+
}
|
|
22650
|
+
}
|
|
22651
|
+
function recPushText(st, c, html) {
|
|
22652
|
+
const afterSpace = st.tbuf[st.tbuf.length - 1] === " ";
|
|
22653
|
+
if (!(c === " " && !st.ishardspace && afterSpace && !html)) st.tbuf.push(c);
|
|
22654
|
+
if (st.ishardspace) st.hstIdx = st.tbuf.length - 1;
|
|
22655
|
+
}
|
|
22656
|
+
function recPushPort(st, c) {
|
|
22657
|
+
const atStartOrSpace = st.pbuf.length === 0 || st.pbuf[st.pbuf.length - 1] === " ";
|
|
22658
|
+
if (!(c === " " && !st.ishardspace && atStartOrSpace)) st.pbuf.push(c);
|
|
22659
|
+
if (st.ishardspace) st.hspIdx = st.pbuf.length - 1;
|
|
22660
|
+
}
|
|
22661
|
+
function recTextChar(p, st, c) {
|
|
22662
|
+
if (st.mode & HASTABLE && c !== " ") return -1;
|
|
22663
|
+
if (!(st.mode & (INTEXT | INPORT)) && c !== " ") st.mode |= INTEXT | HASTEXT;
|
|
22664
|
+
if (st.mode & INTEXT) recPushText(st, c, p.lbl.html);
|
|
22665
|
+
else if (st.mode & INPORT) recPushPort(st, c);
|
|
22666
|
+
p.i++;
|
|
22667
|
+
return 0;
|
|
22668
|
+
}
|
|
22669
|
+
function recDispatch(p, st, LR, flag) {
|
|
22670
|
+
const c = p.s[p.i];
|
|
22671
|
+
switch (c) {
|
|
22672
|
+
case "<":
|
|
22673
|
+
if (p.lbl.html) return recTextChar(p, st, c);
|
|
22674
|
+
return recOpenPort(p, st);
|
|
22675
|
+
case ">":
|
|
22676
|
+
if (p.lbl.html) return recTextChar(p, st, c);
|
|
22677
|
+
return recClosePort(p, st);
|
|
22678
|
+
case "{":
|
|
22679
|
+
return recOpenTable(p, st, LR);
|
|
22680
|
+
case "}":
|
|
22681
|
+
case "|":
|
|
22682
|
+
case void 0:
|
|
22683
|
+
return recEndField(p, st, flag);
|
|
22684
|
+
case "\\":
|
|
22685
|
+
recBackslash(p, st);
|
|
22686
|
+
return recTextChar(p, st, p.s[p.i]);
|
|
22687
|
+
default:
|
|
22688
|
+
return recTextChar(p, st, c);
|
|
22689
|
+
}
|
|
22690
|
+
}
|
|
22691
|
+
function parseReclbl(p, LR, flag) {
|
|
22692
|
+
const rv = makeField();
|
|
22693
|
+
rv.fld = new Array(recCountFields(p));
|
|
22694
|
+
rv.LR = LR;
|
|
22695
|
+
const st = {
|
|
22696
|
+
rv,
|
|
22697
|
+
fi: 0,
|
|
22698
|
+
mode: 0,
|
|
22699
|
+
tbuf: [],
|
|
22700
|
+
hstIdx: 0,
|
|
22701
|
+
pbuf: [],
|
|
22702
|
+
hspIdx: 0,
|
|
22703
|
+
tmpport: null,
|
|
22704
|
+
ishardspace: false,
|
|
22705
|
+
fp: null
|
|
22706
|
+
};
|
|
22707
|
+
for (; ; ) {
|
|
22708
|
+
if (p.i < p.s.length && p.s[p.i] < " " && p.s[p.i] !== "") {
|
|
22709
|
+
p.i++;
|
|
22710
|
+
continue;
|
|
22711
|
+
}
|
|
22712
|
+
const r = recDispatch(p, st, LR, flag);
|
|
22713
|
+
if (r === -1) return null;
|
|
22714
|
+
if (r === 1) break;
|
|
22715
|
+
if (p.i > p.s.length) break;
|
|
22716
|
+
}
|
|
22717
|
+
rv.n_flds = st.fi;
|
|
22718
|
+
return rv;
|
|
22719
|
+
}
|
|
22720
|
+
function recLabelDimen(n, g, f) {
|
|
22721
|
+
const dimen = { x: f.lp.dimen.x, y: f.lp.dimen.y };
|
|
22722
|
+
if (dimen.x > 0 || dimen.y > 0) {
|
|
22723
|
+
const m = nodeAttr(n, g, "margin");
|
|
22724
|
+
const parts = m !== void 0 ? m.split(",").map(parseFloat) : [];
|
|
22725
|
+
if (parts.length > 0 && !Number.isNaN(parts[0])) {
|
|
22726
|
+
dimen.x += 2 * parts[0] * 72;
|
|
22727
|
+
dimen.y += 2 * (parts.length > 1 && !Number.isNaN(parts[1]) ? parts[1] : parts[0]) * 72;
|
|
22728
|
+
} else {
|
|
22729
|
+
dimen.x += PAD_X;
|
|
22730
|
+
dimen.y += PAD_Y;
|
|
22731
|
+
}
|
|
22732
|
+
}
|
|
22733
|
+
return dimen;
|
|
22734
|
+
}
|
|
22735
|
+
function sizeReclbl(n, g, f) {
|
|
22736
|
+
let d;
|
|
22737
|
+
if (f.lp) {
|
|
22738
|
+
d = recLabelDimen(n, g, f);
|
|
22739
|
+
} else {
|
|
22740
|
+
d = { x: 0, y: 0 };
|
|
22741
|
+
for (let i = 0; i < f.n_flds; i++) {
|
|
22742
|
+
const d0 = sizeReclbl(n, g, f.fld[i]);
|
|
22743
|
+
if (f.LR) {
|
|
22744
|
+
d.x += d0.x;
|
|
22745
|
+
d.y = Math.max(d.y, d0.y);
|
|
22746
|
+
} else {
|
|
22747
|
+
d.y += d0.y;
|
|
22748
|
+
d.x = Math.max(d.x, d0.x);
|
|
22749
|
+
}
|
|
22750
|
+
}
|
|
22751
|
+
}
|
|
22752
|
+
f.size = d;
|
|
22753
|
+
return d;
|
|
22754
|
+
}
|
|
22755
|
+
function resizeReclbl(f, sz, nojustify) {
|
|
22756
|
+
const d = { x: sz.x - f.size.x, y: sz.y - f.size.y };
|
|
22757
|
+
f.size = sz;
|
|
22758
|
+
if (f.lp && !nojustify) {
|
|
22759
|
+
f.lp.space.x += d.x;
|
|
22760
|
+
f.lp.space.y += d.y;
|
|
22761
|
+
}
|
|
22762
|
+
if (f.n_flds) {
|
|
22763
|
+
const inc2 = f.LR ? d.x / f.n_flds : d.y / f.n_flds;
|
|
22764
|
+
for (let i = 0; i < f.n_flds; i++) {
|
|
22765
|
+
const sf = f.fld[i];
|
|
22766
|
+
const amt = Math.trunc((i + 1) * inc2) - Math.trunc(i * inc2);
|
|
22767
|
+
const newsz = f.LR ? { x: sf.size.x + amt, y: sz.y } : { x: sz.x, y: sf.size.y + amt };
|
|
22768
|
+
resizeReclbl(sf, newsz, nojustify);
|
|
22769
|
+
}
|
|
22770
|
+
}
|
|
22771
|
+
}
|
|
22772
|
+
function recSideMask(f, i, last) {
|
|
22773
|
+
if (f.LR) {
|
|
22774
|
+
if (i === 0) return i === last ? TOP2 | BOTTOM2 | RIGHT2 | LEFT2 : TOP2 | BOTTOM2 | LEFT2;
|
|
22775
|
+
return i === last ? TOP2 | BOTTOM2 | RIGHT2 : TOP2 | BOTTOM2;
|
|
22776
|
+
}
|
|
22777
|
+
if (i === 0) return i === last ? TOP2 | BOTTOM2 | RIGHT2 | LEFT2 : TOP2 | RIGHT2 | LEFT2;
|
|
22778
|
+
return i === last ? LEFT2 | BOTTOM2 | RIGHT2 : LEFT2 | RIGHT2;
|
|
22779
|
+
}
|
|
22780
|
+
function posReclbl(f, ul, sides) {
|
|
22781
|
+
f.sides = sides;
|
|
22782
|
+
f.b = {
|
|
22783
|
+
ll: { x: ul.x, y: ul.y - f.size.y },
|
|
22784
|
+
ur: { x: ul.x + f.size.x, y: ul.y }
|
|
22785
|
+
};
|
|
22786
|
+
const last = f.n_flds - 1;
|
|
22787
|
+
const pos = { x: ul.x, y: ul.y };
|
|
22788
|
+
for (let i = 0; i <= last; i++) {
|
|
22789
|
+
const mask = sides ? recSideMask(f, i, last) : 0;
|
|
22790
|
+
posReclbl(f.fld[i], { x: pos.x, y: pos.y }, sides & mask);
|
|
22791
|
+
if (f.LR) pos.x += f.fld[i].size.x;
|
|
22792
|
+
else pos.y -= f.fld[i].size.y;
|
|
22793
|
+
}
|
|
22794
|
+
}
|
|
22795
|
+
function attrBool(n, g, key) {
|
|
22796
|
+
return mapbool2(nodeAttr(n, g, key));
|
|
22797
|
+
}
|
|
22798
|
+
function recAttrSize(n, g) {
|
|
22799
|
+
const w = nodeAttr(n, g, "width");
|
|
22800
|
+
const h = nodeAttr(n, g, "height");
|
|
22801
|
+
return {
|
|
22802
|
+
x: (w !== void 0 ? parseFloat(w) : 0.75) * 72,
|
|
22803
|
+
y: (h !== void 0 ? parseFloat(h) : 0.5) * 72
|
|
22804
|
+
};
|
|
22805
|
+
}
|
|
22806
|
+
function recParseOrFallback(lbl, measurer, flip, obj) {
|
|
22807
|
+
const p = { s: lbl.text, i: 0, lbl, measurer, obj };
|
|
22808
|
+
const info = parseReclbl(p, flip, true);
|
|
22809
|
+
if (info !== null) return info;
|
|
22810
|
+
const fb = { s: "\\N", i: 0, lbl, measurer, obj };
|
|
22811
|
+
return parseReclbl(fb, flip, true);
|
|
22812
|
+
}
|
|
22813
|
+
function recordInit(n, g, measurer) {
|
|
22814
|
+
const lbl = n.info.label;
|
|
22815
|
+
const flip = ((g.root.info.rankdir ?? 0) >> 2 & 1) === 1 ? 0 : 1;
|
|
22816
|
+
const info = recParseOrFallback(lbl, measurer, flip, n);
|
|
22817
|
+
sizeReclbl(n, g, info);
|
|
22818
|
+
const sz = recAttrSize(n, g);
|
|
22819
|
+
if (!attrBool(n, g, "fixedsize")) {
|
|
22820
|
+
sz.x = Math.max(info.size.x, sz.x);
|
|
22821
|
+
sz.y = Math.max(info.size.y, sz.y);
|
|
22822
|
+
}
|
|
22823
|
+
resizeReclbl(info, sz, attrBool(n, g, "nojustify"));
|
|
22824
|
+
posReclbl(info, { x: -sz.x / 2, y: sz.y / 2 }, BOTTOM2 | RIGHT2 | TOP2 | LEFT2);
|
|
22825
|
+
n.info.width = info.size.x / 72;
|
|
22826
|
+
n.info.height = (info.size.y + 1) / 72;
|
|
22827
|
+
const ns = gvNodesize(info.size.x, info.size.y + 1, g.root.info.flip === true);
|
|
22828
|
+
n.info.lw = ns.lw;
|
|
22829
|
+
n.info.rw = ns.rw;
|
|
22830
|
+
n.info.ht = ns.ht;
|
|
22831
|
+
n.info.shape_info = info;
|
|
22832
|
+
}
|
|
22833
|
+
function recordMakeLabel(n, g, measurer) {
|
|
22834
|
+
const labelText = nodeAttr(n, g, "label") ?? n.name;
|
|
22835
|
+
const { fontname, fontsize, fontcolor } = readFontAttrs(n, g);
|
|
22836
|
+
n.info.label = makeLabel(labelText, fontname, fontsize, fontcolor, measurer);
|
|
22837
|
+
}
|
|
22838
|
+
function recordNodeInit(n, g, measurer) {
|
|
22839
|
+
recordMakeLabel(n, g, measurer);
|
|
22840
|
+
recordInit(n, g, measurer);
|
|
22841
|
+
}
|
|
22842
|
+
function genFields(job, n, f) {
|
|
22843
|
+
const renderer = job.renderer;
|
|
22844
|
+
const coord = n.info.coord ?? { x: 0, y: 0 };
|
|
22845
|
+
if (f.lp) {
|
|
22846
|
+
const mid = {
|
|
22847
|
+
x: (f.b.ll.x + f.b.ur.x) / 2 + coord.x,
|
|
22848
|
+
y: (f.b.ll.y + f.b.ur.y) / 2 + coord.y
|
|
22849
|
+
};
|
|
22850
|
+
renderLabel(f.lp, mid, renderer, job);
|
|
22851
|
+
}
|
|
22852
|
+
for (let i = 0; i < f.n_flds; i++) {
|
|
22853
|
+
if (i > 0) genFieldSeparator(job, coord, f, f.fld[i]);
|
|
22854
|
+
genFields(job, n, f.fld[i]);
|
|
22855
|
+
}
|
|
22856
|
+
}
|
|
22857
|
+
function genFieldSeparator(job, coord, f, child) {
|
|
22858
|
+
const a = { x: 0, y: 0 };
|
|
22859
|
+
const b = { x: 0, y: 0 };
|
|
22860
|
+
if (f.LR) {
|
|
22861
|
+
a.x = child.b.ll.x;
|
|
22862
|
+
a.y = child.b.ll.y;
|
|
22863
|
+
b.x = a.x;
|
|
22864
|
+
b.y = child.b.ur.y;
|
|
22865
|
+
} else {
|
|
22866
|
+
b.x = child.b.ur.x;
|
|
22867
|
+
b.y = child.b.ur.y;
|
|
22868
|
+
a.x = child.b.ll.x;
|
|
22869
|
+
a.y = b.y;
|
|
22870
|
+
}
|
|
22871
|
+
const pts = [
|
|
22872
|
+
transformPoint({ x: a.x + coord.x, y: a.y + coord.y }, job),
|
|
22873
|
+
transformPoint({ x: b.x + coord.x, y: b.y + coord.y }, job)
|
|
22874
|
+
];
|
|
22875
|
+
job.renderer.polyline(pts, job);
|
|
22876
|
+
}
|
|
22877
|
+
function recordGencode(rawJob, rawNode) {
|
|
22878
|
+
const job = rawJob;
|
|
22879
|
+
const n = rawNode;
|
|
22880
|
+
if (!job.renderer) return;
|
|
22881
|
+
const f = n.info.shape_info;
|
|
22882
|
+
if (!f) return;
|
|
22883
|
+
const coord = n.info.coord ?? { x: 0, y: 0 };
|
|
22884
|
+
const ll = { x: f.b.ll.x + coord.x, y: f.b.ll.y + coord.y };
|
|
22885
|
+
const ur = { x: f.b.ur.x + coord.x, y: f.b.ur.y + coord.y };
|
|
22886
|
+
const filled = job.obj !== null && applyNodeStyle(job.obj, n, job);
|
|
22887
|
+
drawRecordBox(job, n, ll, ur, filled);
|
|
22888
|
+
genFields(job, n, f);
|
|
23134
22889
|
}
|
|
23135
|
-
function
|
|
23136
|
-
|
|
22890
|
+
function drawRecordBox(job, n, ll, ur, filled) {
|
|
22891
|
+
const isMrecord = nodeAttr(n, n.root, "shape") === "Mrecord";
|
|
22892
|
+
const rounded = isMrecord || parseStyleFlags(nodeAttr(n, n.root, "style")).rounded;
|
|
22893
|
+
if (rounded) {
|
|
22894
|
+
const af = [{ x: ll.x, y: ll.y }, { x: ur.x, y: ll.y }, { x: ur.x, y: ur.y }, { x: ll.x, y: ur.y }];
|
|
22895
|
+
emitRoundedBezier(af, { x: 0, y: 0 }, filled, { renderer: job.renderer, job });
|
|
22896
|
+
return;
|
|
22897
|
+
}
|
|
22898
|
+
const pts = [{ x: ll.x, y: ll.y }, { x: ll.x, y: ur.y }, { x: ur.x, y: ur.y }, { x: ur.x, y: ll.y }].map((q) => transformPoint(q, job));
|
|
22899
|
+
job.renderer.polygon(pts, filled, job);
|
|
23137
22900
|
}
|
|
23138
|
-
|
|
23139
|
-
|
|
22901
|
+
|
|
22902
|
+
// src/common/poly-init.ts
|
|
22903
|
+
var DEFAULT_LW = 27;
|
|
22904
|
+
var DEFAULT_RW = 27;
|
|
22905
|
+
var DEFAULT_HT = 36;
|
|
22906
|
+
function nodeAttr(n, g, key) {
|
|
22907
|
+
const own = n.attrs.get(key);
|
|
22908
|
+
if (own !== void 0) return own;
|
|
22909
|
+
if (n.nodeDefaultsSnapshot !== void 0) return n.nodeDefaultsSnapshot.get(key);
|
|
22910
|
+
return g.nodeDefaults.get(key) ?? (g !== g.root ? g.root.nodeDefaults.get(key) : void 0);
|
|
23140
22911
|
}
|
|
23141
|
-
function
|
|
23142
|
-
return
|
|
22912
|
+
function readFontAttrs(n, g) {
|
|
22913
|
+
return {
|
|
22914
|
+
fontname: nodeAttr(n, g, "fontname") ?? DEFAULT_FONTNAME,
|
|
22915
|
+
fontsize: parseFloat(nodeAttr(n, g, "fontsize") ?? String(DEFAULT_FONTSIZE2)),
|
|
22916
|
+
fontcolor: nodeAttr(n, g, "fontcolor") ?? DEFAULT_COLOR2
|
|
22917
|
+
};
|
|
23143
22918
|
}
|
|
23144
|
-
function
|
|
23145
|
-
|
|
22919
|
+
function assignShapeInfo(n, polyDesc) {
|
|
22920
|
+
const w = n.info.width !== void 0 ? n.info.width * 72 : (n.info.lw || DEFAULT_LW) + (n.info.rw || DEFAULT_RW);
|
|
22921
|
+
const h = n.info.height !== void 0 ? n.info.height * 72 : n.info.ht || DEFAULT_HT;
|
|
22922
|
+
const base = n.info.base_width !== void 0 && n.info.base_height !== void 0 ? { w: n.info.base_width * 72, h: n.info.base_height * 72 } : void 0;
|
|
22923
|
+
n.info.shape_info = {
|
|
22924
|
+
...polyDesc,
|
|
22925
|
+
vertices: computeVertices(polyDesc, w, h, base)
|
|
22926
|
+
};
|
|
23146
22927
|
}
|
|
23147
|
-
function
|
|
23148
|
-
|
|
23149
|
-
|
|
23150
|
-
|
|
23151
|
-
const
|
|
23152
|
-
const
|
|
23153
|
-
|
|
22928
|
+
function buildNodeLabel(n, g, measurer) {
|
|
22929
|
+
if (n.info.label !== void 0) return;
|
|
22930
|
+
const labelAttr = nodeAttr(n, g, "label");
|
|
22931
|
+
const font = readFontAttrs(n, g);
|
|
22932
|
+
const isHtml = labelAttr !== void 0 && isHtmlValue(labelAttr);
|
|
22933
|
+
const content = isHtml ? htmlValueContent(labelAttr) : labelAttr ?? n.name;
|
|
22934
|
+
n.info.label = makeAnyLabel(content, isHtml, font, measurer, n);
|
|
23154
22935
|
}
|
|
23155
|
-
function
|
|
23156
|
-
const
|
|
23157
|
-
const
|
|
23158
|
-
|
|
23159
|
-
if (
|
|
23160
|
-
|
|
22936
|
+
function polyInit(n, g, measurer) {
|
|
22937
|
+
const shapeName = nodeAttr(n, g, "shape") ?? "ellipse";
|
|
22938
|
+
const shapefile = nodeAttr(n, g, "shapefile");
|
|
22939
|
+
n.info.shape = bindShape(shapeName, shapefile);
|
|
22940
|
+
if (shapefile !== void 0 && shapefile !== "" && shapeName !== "epsf") {
|
|
22941
|
+
console.error(`Warning: No or improper shapefile="${shapefile}" for node "${n.name}"`);
|
|
23161
22942
|
}
|
|
23162
|
-
|
|
23163
|
-
|
|
23164
|
-
|
|
23165
|
-
|
|
23166
|
-
|
|
23167
|
-
if (
|
|
23168
|
-
const
|
|
23169
|
-
|
|
23170
|
-
return [slenX, slenY];
|
|
22943
|
+
if (n.info.shape.kind === 2 /* SH_RECORD */) {
|
|
22944
|
+
if (n.info.shape_info === void 0) recordNodeInit(n, g, measurer);
|
|
22945
|
+
return;
|
|
22946
|
+
}
|
|
22947
|
+
buildNodeLabel(n, g, measurer);
|
|
22948
|
+
if (n.info.shape_info !== void 0) return;
|
|
22949
|
+
const polyDesc = n.info.shape.polygon;
|
|
22950
|
+
if (polyDesc !== null) assignShapeInfo(n, polyDesc);
|
|
23171
22951
|
}
|
|
23172
|
-
|
|
23173
|
-
|
|
22952
|
+
|
|
22953
|
+
// src/render/svg-multicolor.ts
|
|
22954
|
+
var THIN_LINE = 0.5;
|
|
22955
|
+
function rationalFunction(x, c) {
|
|
22956
|
+
return (x * (x * c[0] + c[1]) + c[2]) / (x + c[3]);
|
|
23174
22957
|
}
|
|
23175
|
-
|
|
23176
|
-
|
|
22958
|
+
var COEFFS3LOW = [
|
|
22959
|
+
[
|
|
22960
|
+
[3.85268, -21.229, -0.330434, 0.0127842],
|
|
22961
|
+
[-1.61486, 0.706564, 0.225945, 0.263682],
|
|
22962
|
+
[-0.910164, 0.388383, 551445e-8, 671814e-8],
|
|
22963
|
+
[-0.630184, 0.192402, 98871e-7, 0.0102527]
|
|
22964
|
+
],
|
|
22965
|
+
[
|
|
22966
|
+
[-0.162211, 9.94329, 0.13723, 0.0124084],
|
|
22967
|
+
[-0.253135, 187735e-8, 0.0230286, 0.01264],
|
|
22968
|
+
[-0.0695069, -0.0437594, 0.0120636, 0.0163087],
|
|
22969
|
+
[-0.0328856, -926032e-8, -173573e-8, 527385e-8]
|
|
22970
|
+
]
|
|
22971
|
+
];
|
|
22972
|
+
var COEFFS3HIGH = [
|
|
22973
|
+
[
|
|
22974
|
+
[0.0899116, -19.2349, -4.11711, 0.183362],
|
|
22975
|
+
[0.138148, -1.45804, 1.32044, 1.38474],
|
|
22976
|
+
[0.230903, -0.450262, 0.219963, 0.414038],
|
|
22977
|
+
[0.0590565, -0.101062, 0.0430592, 0.0204699]
|
|
22978
|
+
],
|
|
22979
|
+
[
|
|
22980
|
+
[0.0164649, 9.89394, 0.0919496, 760802e-8],
|
|
22981
|
+
[0.0191603, -0.0322058, 0.0134667, -0.0825018],
|
|
22982
|
+
[0.0156192, -0.017535, 326508e-8, -0.228157],
|
|
22983
|
+
[-0.0236752, 0.0405821, -0.0173086, 0.176187]
|
|
22984
|
+
]
|
|
22985
|
+
];
|
|
22986
|
+
var SAFETY3 = [1e-3, 4.98, 0.207, 67e-4];
|
|
22987
|
+
function estimateError(a, b, etaA, etaB) {
|
|
22988
|
+
const eta = 0.5 * (etaA + etaB);
|
|
22989
|
+
const x = b / a;
|
|
22990
|
+
const dEta = etaB - etaA;
|
|
22991
|
+
const cos2 = Math.cos(2 * eta);
|
|
22992
|
+
const cos4 = Math.cos(4 * eta);
|
|
22993
|
+
const cos6 = Math.cos(6 * eta);
|
|
22994
|
+
const c = x < 0.25 ? COEFFS3LOW : COEFFS3HIGH;
|
|
22995
|
+
const c0 = rationalFunction(x, c[0][0]) + cos2 * rationalFunction(x, c[0][1]) + cos4 * rationalFunction(x, c[0][2]) + cos6 * rationalFunction(x, c[0][3]);
|
|
22996
|
+
const c1 = rationalFunction(x, c[1][0]) + cos2 * rationalFunction(x, c[1][1]) + cos4 * rationalFunction(x, c[1][2]) + cos6 * rationalFunction(x, c[1][3]);
|
|
22997
|
+
return rationalFunction(x, SAFETY3) * a * Math.exp(c0 + c1 * dEta);
|
|
23177
22998
|
}
|
|
23178
|
-
function
|
|
23179
|
-
|
|
23180
|
-
|
|
23181
|
-
|
|
23182
|
-
|
|
23183
|
-
e.info.minlen = slen1;
|
|
23184
|
-
e.info.weight = 0;
|
|
23185
|
-
return true;
|
|
22999
|
+
function allSubdivsBelowThreshold(a, b, eta1, n, dEta) {
|
|
23000
|
+
let etaA = eta1;
|
|
23001
|
+
for (let i = 0; i < n; i++) {
|
|
23002
|
+
if (estimateError(a, b, etaA, etaA + dEta) > 1e-5) return false;
|
|
23003
|
+
etaA += dEta;
|
|
23186
23004
|
}
|
|
23187
|
-
return
|
|
23005
|
+
return true;
|
|
23188
23006
|
}
|
|
23189
|
-
function
|
|
23190
|
-
|
|
23191
|
-
|
|
23192
|
-
const
|
|
23193
|
-
|
|
23194
|
-
|
|
23195
|
-
e.info.weight = 0;
|
|
23196
|
-
return true;
|
|
23007
|
+
function numSubdivisions(a, b, eta1, eta2) {
|
|
23008
|
+
let n = 1;
|
|
23009
|
+
while (n < 1024) {
|
|
23010
|
+
const dEta = (eta2 - eta1) / n;
|
|
23011
|
+
if (dEta <= 0.5 * Math.PI && allSubdivsBelowThreshold(a, b, eta1, n, dEta)) break;
|
|
23012
|
+
n <<= 1;
|
|
23197
23013
|
}
|
|
23198
|
-
return
|
|
23014
|
+
return n;
|
|
23199
23015
|
}
|
|
23200
|
-
function
|
|
23201
|
-
|
|
23202
|
-
|
|
23203
|
-
|
|
23204
|
-
|
|
23205
|
-
|
|
23206
|
-
|
|
23207
|
-
|
|
23208
|
-
|
|
23016
|
+
function initArcPath(pts, e, eta1) {
|
|
23017
|
+
const cosE = Math.cos(eta1);
|
|
23018
|
+
const sinE = Math.sin(eta1);
|
|
23019
|
+
const xB = e.cx + e.xsemi * cosE;
|
|
23020
|
+
const yB = e.cy + e.ysemi * sinE;
|
|
23021
|
+
pts.push(
|
|
23022
|
+
{ x: e.cx, y: e.cy },
|
|
23023
|
+
{ x: e.cx, y: e.cy },
|
|
23024
|
+
{ x: xB, y: yB },
|
|
23025
|
+
{ x: xB, y: yB }
|
|
23026
|
+
);
|
|
23027
|
+
return { xB, yB, xBDot: -e.xsemi * sinE, yBDot: e.ysemi * cosE };
|
|
23209
23028
|
}
|
|
23210
|
-
function
|
|
23211
|
-
const
|
|
23212
|
-
const
|
|
23213
|
-
const
|
|
23214
|
-
const
|
|
23215
|
-
|
|
23216
|
-
|
|
23217
|
-
|
|
23218
|
-
|
|
23029
|
+
function stepBezier(pts, state3, e, sp) {
|
|
23030
|
+
const xA = state3.xB;
|
|
23031
|
+
const yA = state3.yB;
|
|
23032
|
+
const xADot = state3.xBDot;
|
|
23033
|
+
const yADot = state3.yBDot;
|
|
23034
|
+
const newEta = sp.etaB + sp.dEta;
|
|
23035
|
+
const cosE = Math.cos(newEta);
|
|
23036
|
+
const sinE = Math.sin(newEta);
|
|
23037
|
+
state3.xB = e.cx + e.xsemi * cosE;
|
|
23038
|
+
state3.yB = e.cy + e.ysemi * sinE;
|
|
23039
|
+
state3.xBDot = -e.xsemi * sinE;
|
|
23040
|
+
state3.yBDot = e.ysemi * cosE;
|
|
23041
|
+
pts.push({ x: xA + sp.alpha * xADot, y: yA + sp.alpha * yADot });
|
|
23042
|
+
pts.push({ x: state3.xB - sp.alpha * state3.xBDot, y: state3.yB - sp.alpha * state3.yBDot });
|
|
23043
|
+
pts.push({ x: state3.xB, y: state3.yB });
|
|
23044
|
+
return newEta;
|
|
23219
23045
|
}
|
|
23220
|
-
function
|
|
23221
|
-
const
|
|
23222
|
-
|
|
23223
|
-
|
|
23224
|
-
|
|
23225
|
-
if (
|
|
23046
|
+
function ellipticWedge(e, angle0, angle1) {
|
|
23047
|
+
const TWOPI2 = 2 * Math.PI;
|
|
23048
|
+
const eta1 = Math.atan2(Math.sin(angle0) / e.ysemi, Math.cos(angle0) / e.xsemi);
|
|
23049
|
+
let eta2 = Math.atan2(Math.sin(angle1) / e.ysemi, Math.cos(angle1) / e.xsemi);
|
|
23050
|
+
eta2 -= TWOPI2 * Math.floor((eta2 - eta1) / TWOPI2);
|
|
23051
|
+
if (angle1 - angle0 > Math.PI && eta2 - eta1 < Math.PI) eta2 += TWOPI2;
|
|
23052
|
+
const n = numSubdivisions(e.xsemi, e.ysemi, eta1, eta2);
|
|
23053
|
+
const dEta = (eta2 - eta1) / n;
|
|
23054
|
+
const t = Math.tan(0.5 * dEta);
|
|
23055
|
+
const alpha = Math.sin(dEta) * (Math.sqrt(4 + 3 * t * t) - 1) / 3;
|
|
23056
|
+
const pts = [];
|
|
23057
|
+
const state3 = initArcPath(pts, e, eta1);
|
|
23058
|
+
let sp = { etaB: eta1, dEta, alpha };
|
|
23059
|
+
for (let i = 0; i < n; i++) sp = { ...sp, etaB: stepBezier(pts, state3, e, sp) };
|
|
23060
|
+
pts.push({ x: state3.xB, y: state3.yB }, { x: e.cx, y: e.cy }, { x: e.cx, y: e.cy });
|
|
23061
|
+
return pts;
|
|
23226
23062
|
}
|
|
23227
|
-
function
|
|
23228
|
-
|
|
23229
|
-
|
|
23230
|
-
|
|
23231
|
-
|
|
23232
|
-
|
|
23233
|
-
}
|
|
23063
|
+
function drawWedge(seg2, e, ctx) {
|
|
23064
|
+
const TWOPI2 = 2 * Math.PI;
|
|
23065
|
+
const angle1 = seg2.isLast ? TWOPI2 : seg2.angle0 + TWOPI2 * seg2.t;
|
|
23066
|
+
const obj = ctx.job.obj;
|
|
23067
|
+
if (obj !== null) obj.fillColor = resolveRenderColor(seg2.color);
|
|
23068
|
+
const ptsUp = ellipticWedge(e, seg2.angle0, angle1);
|
|
23069
|
+
ctx.renderer.bezier(ptsUp.map((p) => ({ x: p.x, y: -p.y })), true, ctx.job);
|
|
23070
|
+
return angle1;
|
|
23234
23071
|
}
|
|
23235
|
-
function
|
|
23236
|
-
const
|
|
23237
|
-
if (
|
|
23238
|
-
|
|
23239
|
-
|
|
23240
|
-
|
|
23072
|
+
function wedgedEllipse(job, pf, clrs, renderer) {
|
|
23073
|
+
const { segs, error } = parseSegs(clrs);
|
|
23074
|
+
if (error === 1 || error === 2) return error;
|
|
23075
|
+
const ctrX = (pf[0].x + pf[1].x) / 2;
|
|
23076
|
+
const ctrY = (pf[0].y + pf[1].y) / 2;
|
|
23077
|
+
const e = {
|
|
23078
|
+
cx: ctrX,
|
|
23079
|
+
cy: -ctrY,
|
|
23080
|
+
xsemi: pf[1].x - ctrX,
|
|
23081
|
+
ysemi: Math.abs(pf[1].y - ctrY)
|
|
23082
|
+
};
|
|
23083
|
+
const ctx = { job, renderer };
|
|
23084
|
+
const obj = job.obj;
|
|
23085
|
+
const saved = obj !== null ? obj.penWidth : 1;
|
|
23086
|
+
if (obj !== null && saved > THIN_LINE) obj.penWidth = THIN_LINE;
|
|
23087
|
+
let angle0 = 0;
|
|
23088
|
+
for (let i = 0; i < segs.length; i++) {
|
|
23089
|
+
const s = segs[i];
|
|
23090
|
+
if (s.color === null) break;
|
|
23091
|
+
if (s.t > 0) {
|
|
23092
|
+
angle0 = drawWedge({ angle0, t: s.t, isLast: i + 1 === segs.length, color: s.color }, e, ctx);
|
|
23093
|
+
}
|
|
23241
23094
|
}
|
|
23242
|
-
|
|
23243
|
-
|
|
23244
|
-
for (const n of nodesInSeq(g)) expandNode(g, n);
|
|
23245
|
-
if (g === (g.info.dotroot ?? g.root)) expandRankPostprocess(g);
|
|
23095
|
+
if (obj !== null && saved > THIN_LINE) obj.penWidth = saved;
|
|
23096
|
+
return error;
|
|
23246
23097
|
}
|
|
23247
|
-
function
|
|
23248
|
-
|
|
23249
|
-
|
|
23250
|
-
|
|
23251
|
-
|
|
23252
|
-
|
|
23253
|
-
acyclic(g);
|
|
23254
|
-
if (minmaxEdges2(g, slen)) decompose(g, 0);
|
|
23255
|
-
rank1(g);
|
|
23256
|
-
expandRanksets(g);
|
|
23257
|
-
cleanup1(g);
|
|
23098
|
+
function drawBand(p, seg2, ctx) {
|
|
23099
|
+
const obj = ctx.job.obj;
|
|
23100
|
+
if (obj !== null) obj.fillColor = resolveRenderColor(seg2.color);
|
|
23101
|
+
p[1].x = p[2].x = seg2.isLast ? seg2.lastx : p[0].x + seg2.segWidth;
|
|
23102
|
+
ctx.renderer.polygon([...p], true, ctx.job);
|
|
23103
|
+
p[0].x = p[3].x = p[1].x;
|
|
23258
23104
|
}
|
|
23259
|
-
function
|
|
23260
|
-
|
|
23261
|
-
|
|
23262
|
-
|
|
23263
|
-
|
|
23264
|
-
|
|
23105
|
+
function stripedBox(job, pts, clrs, rotate, renderer) {
|
|
23106
|
+
const { segs, error } = parseSegs(clrs);
|
|
23107
|
+
if (error === 1 || error === 2) return error;
|
|
23108
|
+
const p = rotate ? [{ ...pts[2] }, { ...pts[3] }, { ...pts[0] }, { ...pts[1] }] : [{ ...pts[0] }, { ...pts[1] }, { ...pts[2] }, { ...pts[3] }];
|
|
23109
|
+
const lastx = p[1].x;
|
|
23110
|
+
const xdelta = p[1].x - p[0].x;
|
|
23111
|
+
p[1].x = p[2].x = p[0].x;
|
|
23112
|
+
const ctx = { job, renderer };
|
|
23113
|
+
const obj = job.obj;
|
|
23114
|
+
const saved = obj !== null ? obj.penWidth : 1;
|
|
23115
|
+
if (obj !== null && saved > THIN_LINE) obj.penWidth = THIN_LINE;
|
|
23116
|
+
for (let i = 0; i < segs.length; i++) {
|
|
23117
|
+
const s = segs[i];
|
|
23118
|
+
if (s.color === null) break;
|
|
23119
|
+
if (s.t > 0) {
|
|
23120
|
+
drawBand(p, { color: s.color, isLast: i + 1 === segs.length, segWidth: xdelta * s.t, lastx }, ctx);
|
|
23121
|
+
}
|
|
23265
23122
|
}
|
|
23123
|
+
if (obj !== null && saved > THIN_LINE) obj.penWidth = saved;
|
|
23124
|
+
return error;
|
|
23266
23125
|
}
|
|
23267
23126
|
|
|
23268
|
-
// src/
|
|
23269
|
-
|
|
23270
|
-
|
|
23271
|
-
|
|
23272
|
-
|
|
23273
|
-
|
|
23274
|
-
|
|
23275
|
-
|
|
23276
|
-
|
|
23277
|
-
|
|
23278
|
-
|
|
23279
|
-
return e.info.constraint === false;
|
|
23280
|
-
}
|
|
23281
|
-
var WNODE_ORDINARY = 0;
|
|
23282
|
-
var WNODE_SINGLETON = 1;
|
|
23283
|
-
var WNODE_VIRTUAL = 2;
|
|
23284
|
-
var CLASSIFY_WEIGHT_TABLE = [[1, 1, 1], [1, 2, 2], [1, 2, 4]];
|
|
23285
|
-
function epClass(n) {
|
|
23286
|
-
if (n.info.node_type === VIRTUAL) return WNODE_VIRTUAL;
|
|
23287
|
-
if ((n.info.weight_class ?? 2) <= 1) return WNODE_SINGLETON;
|
|
23288
|
-
return WNODE_ORDINARY;
|
|
23127
|
+
// src/render/xml-escape.ts
|
|
23128
|
+
var RE_DQUOTE = new RegExp('"', "g");
|
|
23129
|
+
var RE_SQUOTE = new RegExp("'", "g");
|
|
23130
|
+
var RE_AMP_NONENTITY = /&(?![A-Za-z]+;|#[0-9]+;|#x[0-9A-Fa-f]+;)/g;
|
|
23131
|
+
function escapeXml(s) {
|
|
23132
|
+
let r = s.replace(RE_AMP_NONENTITY, "&");
|
|
23133
|
+
r = r.replace(/</g, "<");
|
|
23134
|
+
r = r.replace(/>/g, ">");
|
|
23135
|
+
r = r.replace(RE_DQUOTE, """);
|
|
23136
|
+
r = r.replace(RE_SQUOTE, "'");
|
|
23137
|
+
return r;
|
|
23289
23138
|
}
|
|
23290
|
-
function
|
|
23291
|
-
|
|
23292
|
-
|
|
23139
|
+
function escapeXmlTitle(s) {
|
|
23140
|
+
let r = escapeXml(s);
|
|
23141
|
+
r = r.replace(/-/g, "-");
|
|
23142
|
+
r = r.replace(/ {2,}/g, (m) => " " + " ".repeat(m.length - 1));
|
|
23143
|
+
return r;
|
|
23293
23144
|
}
|
|
23294
|
-
function
|
|
23295
|
-
|
|
23296
|
-
|
|
23145
|
+
function escapeXmlText(s) {
|
|
23146
|
+
let r = escapeXml(s);
|
|
23147
|
+
r = r.replace(/-/g, "-");
|
|
23148
|
+
r = r.replace(/\n/g, " ");
|
|
23149
|
+
r = r.replace(/\r/g, " ");
|
|
23150
|
+
r = r.replace(/ {2,}/g, (m) => " " + " ".repeat(m.length - 1));
|
|
23151
|
+
return r;
|
|
23297
23152
|
}
|
|
23298
|
-
|
|
23299
|
-
|
|
23300
|
-
|
|
23153
|
+
|
|
23154
|
+
// src/gvc/device-cluster.ts
|
|
23155
|
+
function applyClusterGradient(obj, fill) {
|
|
23156
|
+
obj.fill = fill.kind === "radial" ? 3 /* Radial */ : 2 /* Linear */;
|
|
23157
|
+
obj.fillColor = resolveRenderColor(fill.fillColor);
|
|
23158
|
+
obj.stopColor = resolveRenderColor(fill.stopColor);
|
|
23159
|
+
obj.gradientFrac = fill.frac;
|
|
23160
|
+
obj.gradientAngle = fill.angle;
|
|
23301
23161
|
}
|
|
23302
|
-
function
|
|
23303
|
-
|
|
23304
|
-
|
|
23162
|
+
function clusterAttr(sg, key) {
|
|
23163
|
+
for (let g = sg; g !== null; g = g.parent) {
|
|
23164
|
+
const v = g.attrs.get(key);
|
|
23165
|
+
if (v !== void 0) return v;
|
|
23166
|
+
}
|
|
23167
|
+
return void 0;
|
|
23305
23168
|
}
|
|
23306
|
-
function
|
|
23307
|
-
|
|
23308
|
-
const v = virtualNode(g);
|
|
23309
|
-
v.info.node_type = SLACKNODE;
|
|
23310
|
-
const t0 = ufFind(t);
|
|
23311
|
-
const h0 = ufFind(h);
|
|
23312
|
-
const w = e.info.weight ?? 1;
|
|
23313
|
-
const rt = makeAuxEdge(v, t0, tLen, CL_BACK * w);
|
|
23314
|
-
const rh = makeAuxEdge(v, h0, hLen, w);
|
|
23315
|
-
rt.info.to_orig = e;
|
|
23316
|
-
rh.info.to_orig = e;
|
|
23169
|
+
function clusterStyle(sg) {
|
|
23170
|
+
return clusterAttr(sg, "style");
|
|
23317
23171
|
}
|
|
23318
|
-
function
|
|
23319
|
-
|
|
23320
|
-
if (
|
|
23321
|
-
const
|
|
23322
|
-
|
|
23323
|
-
|
|
23324
|
-
if (t.info.clust || h.info.clust) {
|
|
23325
|
-
interclust1(g, e.tail, e.head, e);
|
|
23326
|
-
return;
|
|
23327
|
-
}
|
|
23328
|
-
const rep = findFastEdge(t, h);
|
|
23329
|
-
if (rep !== void 0) mergeOneway(e, rep);
|
|
23330
|
-
else virtualEdge(t, h, e);
|
|
23172
|
+
function clusterPeripheries(sg) {
|
|
23173
|
+
const raw = clusterAttr(sg, "peripheries");
|
|
23174
|
+
if (raw === void 0 || raw.length === 0) return 1;
|
|
23175
|
+
const v = parseInt(raw, 10);
|
|
23176
|
+
if (Number.isNaN(v)) return 1;
|
|
23177
|
+
return v < 0 ? 0 : v;
|
|
23331
23178
|
}
|
|
23332
|
-
function
|
|
23333
|
-
|
|
23334
|
-
|
|
23335
|
-
|
|
23336
|
-
|
|
23179
|
+
function applyClusterPenState(obj, sg) {
|
|
23180
|
+
const flags = parseStyleFlags(clusterStyle(sg));
|
|
23181
|
+
const pen = clusterAttr(sg, "pencolor") ?? clusterAttr(sg, "color");
|
|
23182
|
+
obj.penColor = clusterPeripheries(sg) === 0 ? resolveRenderColor("transparent") : resolveRenderColor(resolvePenColor(pen));
|
|
23183
|
+
obj.penWidth = resolvePenWidth(flags, clusterAttr(sg, "penwidth"));
|
|
23184
|
+
obj.pen = resolvePenType(flags);
|
|
23337
23185
|
}
|
|
23338
|
-
function
|
|
23339
|
-
|
|
23340
|
-
|
|
23186
|
+
function clusterAttrsOf(sg) {
|
|
23187
|
+
return {
|
|
23188
|
+
style: clusterStyle(sg),
|
|
23189
|
+
color: clusterAttr(sg, "color"),
|
|
23190
|
+
pencolor: clusterAttr(sg, "pencolor"),
|
|
23191
|
+
fillcolor: clusterAttr(sg, "fillcolor"),
|
|
23192
|
+
bgcolor: clusterAttr(sg, "bgcolor"),
|
|
23193
|
+
penwidth: clusterAttr(sg, "penwidth"),
|
|
23194
|
+
gradientangle: clusterAttr(sg, "gradientangle")
|
|
23195
|
+
};
|
|
23341
23196
|
}
|
|
23342
|
-
function
|
|
23343
|
-
const
|
|
23344
|
-
|
|
23345
|
-
|
|
23346
|
-
|
|
23347
|
-
|
|
23348
|
-
|
|
23349
|
-
|
|
23350
|
-
|
|
23351
|
-
|
|
23352
|
-
|
|
23197
|
+
function applyClusterObjState(sg, job) {
|
|
23198
|
+
const fillRes = resolveClusterFillEx(clusterAttrsOf(sg));
|
|
23199
|
+
if (job.obj === null) return false;
|
|
23200
|
+
const obj = job.obj;
|
|
23201
|
+
return withColorScheme(clusterAttr(sg, "colorscheme"), () => {
|
|
23202
|
+
applyClusterPenState(obj, sg);
|
|
23203
|
+
if (fillRes.kind === "none") {
|
|
23204
|
+
obj.fill = 0 /* None */;
|
|
23205
|
+
return false;
|
|
23206
|
+
}
|
|
23207
|
+
if (fillRes.kind === "solid") {
|
|
23208
|
+
obj.fill = 1 /* Solid */;
|
|
23209
|
+
obj.fillColor = resolveRenderColor(fillRes.color);
|
|
23210
|
+
return true;
|
|
23211
|
+
}
|
|
23212
|
+
applyClusterGradient(obj, fillRes);
|
|
23213
|
+
return true;
|
|
23214
|
+
});
|
|
23353
23215
|
}
|
|
23354
|
-
|
|
23355
|
-
|
|
23356
|
-
|
|
23357
|
-
|
|
23216
|
+
|
|
23217
|
+
// src/render/svg-id.ts
|
|
23218
|
+
function svgClass(kind, classAttr) {
|
|
23219
|
+
return classAttr !== void 0 && classAttr.length > 0 ? 'class="' + kind + " " + escapeXmlTitle(classAttr) + '"' : 'class="' + kind + '"';
|
|
23358
23220
|
}
|
|
23359
|
-
function
|
|
23360
|
-
|
|
23361
|
-
incrWidth(g, v);
|
|
23362
|
-
return v;
|
|
23221
|
+
function svgNodeId(n, job) {
|
|
23222
|
+
return job.objId(n.attrs.get("id"), "node" + (n.id + 1));
|
|
23363
23223
|
}
|
|
23364
|
-
function
|
|
23365
|
-
|
|
23366
|
-
return v.info.clust.info.rankleader[v.info.rank ?? 0];
|
|
23224
|
+
function svgEdgeId(e, job) {
|
|
23225
|
+
return job.objId(e.attrs.get("id"), "edge" + e.graphSeq);
|
|
23367
23226
|
}
|
|
23368
|
-
function
|
|
23369
|
-
|
|
23370
|
-
return plainVnode(g);
|
|
23227
|
+
function svgClusterId(sg, job) {
|
|
23228
|
+
return job.objId(sg.attrs.get("id"), "clust" + sg.seq);
|
|
23371
23229
|
}
|
|
23372
|
-
function
|
|
23373
|
-
|
|
23374
|
-
let u = from;
|
|
23375
|
-
const toRank = to.info.rank ?? 0;
|
|
23376
|
-
for (let r = (from.info.rank ?? 0) + 1; r <= toRank; r++) {
|
|
23377
|
-
const v = r < toRank ? (() => {
|
|
23378
|
-
const n = chainVnode(g, orig, r, labelRank);
|
|
23379
|
-
n.info.rank = r;
|
|
23380
|
-
return n;
|
|
23381
|
-
})() : to;
|
|
23382
|
-
const e = virtualEdge(u, v, orig);
|
|
23383
|
-
applyVirtualWeight(e);
|
|
23384
|
-
u = v;
|
|
23385
|
-
}
|
|
23230
|
+
function svgGraphId(g, job) {
|
|
23231
|
+
return job.objId(g.attrs.get("id"), "graph0", true);
|
|
23386
23232
|
}
|
|
23387
|
-
function
|
|
23388
|
-
return n.
|
|
23233
|
+
function svgNodeClass(n) {
|
|
23234
|
+
return svgClass("node", nodeAttr(n, n.root, "class"));
|
|
23389
23235
|
}
|
|
23390
|
-
function
|
|
23391
|
-
return e.
|
|
23236
|
+
function svgEdgeClass(e) {
|
|
23237
|
+
return svgClass("edge", e.attrs.get("class"));
|
|
23392
23238
|
}
|
|
23393
|
-
function
|
|
23394
|
-
return
|
|
23239
|
+
function svgClusterClass(sg) {
|
|
23240
|
+
return svgClass("cluster", clusterAttr(sg, "class"));
|
|
23395
23241
|
}
|
|
23396
|
-
function
|
|
23397
|
-
return
|
|
23242
|
+
function svgGraphClass(g) {
|
|
23243
|
+
return svgClass("graph", g.attrs.get("class"));
|
|
23398
23244
|
}
|
|
23399
|
-
|
|
23400
|
-
|
|
23245
|
+
|
|
23246
|
+
// src/common/poly-gencode.ts
|
|
23247
|
+
function isMulticolor(fillcolor) {
|
|
23248
|
+
return fillcolor.includes(":");
|
|
23401
23249
|
}
|
|
23402
|
-
function
|
|
23403
|
-
|
|
23404
|
-
|
|
23405
|
-
|
|
23406
|
-
|
|
23250
|
+
function renderEllipse(ring, coord, renderer, job, filled) {
|
|
23251
|
+
const rx = Math.abs((ring[1].x - ring[0].x) / 2);
|
|
23252
|
+
const ry = Math.abs((ring[1].y - ring[0].y) / 2);
|
|
23253
|
+
const center = transformPoint(coord, job);
|
|
23254
|
+
renderer.ellipse(center, rx, ry, filled, job);
|
|
23407
23255
|
}
|
|
23408
|
-
function
|
|
23409
|
-
const
|
|
23410
|
-
|
|
23411
|
-
|
|
23412
|
-
|
|
23413
|
-
|
|
23414
|
-
|
|
23415
|
-
|
|
23416
|
-
|
|
23417
|
-
|
|
23418
|
-
|
|
23256
|
+
function renderPolygon(ring, coord, renderer, job, filled) {
|
|
23257
|
+
const pts = ring.map((v) => transformPoint({ x: v.x + coord.x, y: v.y + coord.y }, job));
|
|
23258
|
+
renderer.polygon(pts, filled, job);
|
|
23259
|
+
}
|
|
23260
|
+
function renderEllipseRing(ring, coord, filled, j, ctx) {
|
|
23261
|
+
if (ctx.style.wedged && j === 0 && isMulticolor(ctx.fillcolor)) {
|
|
23262
|
+
const pf = ring.map(
|
|
23263
|
+
(v) => transformPoint({ x: v.x + coord.x, y: v.y + coord.y }, ctx.job)
|
|
23264
|
+
);
|
|
23265
|
+
wedgedEllipse(ctx.job, pf, ctx.fillcolor, ctx.renderer);
|
|
23266
|
+
renderEllipse(ring, coord, ctx.renderer, ctx.job, false);
|
|
23267
|
+
} else {
|
|
23268
|
+
renderEllipse(ring, coord, ctx.renderer, ctx.job, filled);
|
|
23419
23269
|
}
|
|
23270
|
+
if (ctx.diagonals) mcircleHack(ring, coord, ctx);
|
|
23420
23271
|
}
|
|
23421
|
-
function
|
|
23422
|
-
|
|
23423
|
-
|
|
23272
|
+
function renderStripedRing(ring, coord, ctx) {
|
|
23273
|
+
const af = ring.map((v) => transformPoint({ x: v.x + coord.x, y: v.y + coord.y }, ctx.job));
|
|
23274
|
+
stripedBox(ctx.job, af, ctx.fillcolor, true, ctx.renderer);
|
|
23275
|
+
renderPolygon(ring, coord, ctx.renderer, ctx.job, false);
|
|
23424
23276
|
}
|
|
23425
|
-
function
|
|
23426
|
-
|
|
23427
|
-
|
|
23428
|
-
|
|
23429
|
-
|
|
23430
|
-
|
|
23431
|
-
}
|
|
23277
|
+
function renderPolyRing(ring, coord, filled, j, ctx) {
|
|
23278
|
+
if (ctx.style.striped && j === 0) renderStripedRing(ring, coord, ctx);
|
|
23279
|
+
else if (ctx.underline) underlineDraw(ring, coord, filled, ctx);
|
|
23280
|
+
else if (ctx.shape !== 0 && ctx.shape !== STAR || ctx.diagonals || ctx.rounded) {
|
|
23281
|
+
drawRoundCorners(ring, coord, filled, ctx);
|
|
23282
|
+
} else renderPolygon(ring, coord, ctx.renderer, ctx.job, filled);
|
|
23432
23283
|
}
|
|
23433
|
-
function
|
|
23434
|
-
|
|
23435
|
-
|
|
23436
|
-
|
|
23437
|
-
const
|
|
23438
|
-
|
|
23439
|
-
|
|
23440
|
-
|
|
23441
|
-
|
|
23442
|
-
|
|
23443
|
-
|
|
23444
|
-
|
|
23445
|
-
return;
|
|
23284
|
+
function renderPeripheries(poly, coord, filled, ctx) {
|
|
23285
|
+
const sides = poly.sides <= 2 ? 2 : poly.sides;
|
|
23286
|
+
const verts = poly.vertices;
|
|
23287
|
+
for (let j = 0; j < poly.peripheries; j++) {
|
|
23288
|
+
const ring = verts.slice(j * sides, (j + 1) * sides);
|
|
23289
|
+
if (ring.length < sides) break;
|
|
23290
|
+
const ringFilled = j === 0 ? filled : false;
|
|
23291
|
+
if (poly.sides <= 2) {
|
|
23292
|
+
renderEllipseRing(ring, coord, ringFilled, j, ctx);
|
|
23293
|
+
} else {
|
|
23294
|
+
renderPolyRing(ring, coord, ringFilled, j, ctx);
|
|
23295
|
+
}
|
|
23446
23296
|
}
|
|
23447
|
-
if (nodeRank3(t) === nodeRank3(h)) return;
|
|
23448
|
-
interclrepChain(g, e, t, h);
|
|
23449
23297
|
}
|
|
23450
|
-
function
|
|
23451
|
-
|
|
23298
|
+
function renderLabel(label, coord, renderer, job) {
|
|
23299
|
+
if (label.u.kind !== "txt" || label.u.nspans < 1) return;
|
|
23300
|
+
label.pos = coord;
|
|
23301
|
+
label.set = true;
|
|
23302
|
+
const VALIGN_TOP2 = "t".charCodeAt(0);
|
|
23303
|
+
const VALIGN_BOTTOM2 = "b".charCodeAt(0);
|
|
23304
|
+
let py = label.valign === VALIGN_TOP2 ? coord.y + label.space.y / 2 - label.fontsize : label.valign === VALIGN_BOTTOM2 ? coord.y - label.space.y / 2 + label.dimen.y - label.fontsize : coord.y + label.dimen.y / 2 - label.fontsize;
|
|
23305
|
+
for (let i = 0; i < label.u.nspans; i++) {
|
|
23306
|
+
const span = label.u.span[i];
|
|
23307
|
+
const px = span.just === "l" ? coord.x - label.space.x / 2 : span.just === "r" ? coord.x + label.space.x / 2 : coord.x;
|
|
23308
|
+
gvrenderTextspan(renderer, { x: px, y: py }, span, job);
|
|
23309
|
+
py -= span.size.y;
|
|
23310
|
+
}
|
|
23452
23311
|
}
|
|
23453
|
-
function
|
|
23454
|
-
|
|
23455
|
-
|
|
23456
|
-
|
|
23457
|
-
|
|
23458
|
-
|
|
23459
|
-
|
|
23312
|
+
function renderNodeLabel(n, coord, renderer, job) {
|
|
23313
|
+
const label = n.info.label;
|
|
23314
|
+
if (label === void 0) return;
|
|
23315
|
+
if (label.html && label.u.kind === "html") {
|
|
23316
|
+
label.pos = coord;
|
|
23317
|
+
label.set = true;
|
|
23318
|
+
const html = label.u.html;
|
|
23319
|
+
withLabelEmitState(job, () => emitHtmlLabel(html, coord, renderer, job));
|
|
23320
|
+
} else {
|
|
23321
|
+
renderLabel(label, coord, renderer, job);
|
|
23460
23322
|
}
|
|
23461
|
-
return prev;
|
|
23462
23323
|
}
|
|
23463
|
-
function
|
|
23464
|
-
|
|
23465
|
-
|
|
23466
|
-
return e;
|
|
23324
|
+
function anchorAttr2(n, key) {
|
|
23325
|
+
const v = nodeAttr(n, n.root, key);
|
|
23326
|
+
return v !== void 0 && v !== "" ? v : void 0;
|
|
23467
23327
|
}
|
|
23468
|
-
function
|
|
23469
|
-
if (
|
|
23470
|
-
|
|
23471
|
-
|
|
23472
|
-
mergeChain(g, e, prev.info.to_virt, true);
|
|
23473
|
-
otherEdge(e);
|
|
23474
|
-
}
|
|
23328
|
+
function resolveTooltip(n, tooltip) {
|
|
23329
|
+
if (tooltip !== void 0) return substObjAnchor(interpretCRNL(tooltip), n);
|
|
23330
|
+
const label = n.info.label;
|
|
23331
|
+
return label?.text ?? "";
|
|
23475
23332
|
}
|
|
23476
|
-
function
|
|
23477
|
-
|
|
23478
|
-
|
|
23479
|
-
|
|
23333
|
+
function beginNodeAnchor(n, renderer, job) {
|
|
23334
|
+
const url = anchorAttr2(n, "href") ?? anchorAttr2(n, "URL");
|
|
23335
|
+
const tooltip = anchorAttr2(n, "tooltip");
|
|
23336
|
+
if (url === void 0 && tooltip === void 0) return false;
|
|
23337
|
+
renderer.beginAnchor?.(
|
|
23338
|
+
url !== void 0 ? substObjAnchor(url, n) : "",
|
|
23339
|
+
resolveTooltip(n, tooltip),
|
|
23340
|
+
anchorAttr2(n, "target") ?? "",
|
|
23341
|
+
svgNodeId(n, job),
|
|
23342
|
+
job
|
|
23343
|
+
);
|
|
23480
23344
|
return true;
|
|
23481
23345
|
}
|
|
23482
|
-
function
|
|
23483
|
-
|
|
23484
|
-
|
|
23485
|
-
|
|
23486
|
-
|
|
23346
|
+
function applyGradientFields(obj, fill) {
|
|
23347
|
+
obj.fill = fill.kind === "radial" ? 3 /* Radial */ : 2 /* Linear */;
|
|
23348
|
+
obj.fillColor = resolveRenderColor(fill.fillColor);
|
|
23349
|
+
obj.stopColor = resolveRenderColor(fill.stopColor);
|
|
23350
|
+
obj.gradientFrac = fill.frac;
|
|
23351
|
+
obj.gradientAngle = fill.angle;
|
|
23487
23352
|
}
|
|
23488
|
-
function
|
|
23489
|
-
|
|
23490
|
-
if (handleMultiSameRank(e, prev)) return true;
|
|
23491
|
-
return handleMultiParallel(g, e, prev);
|
|
23353
|
+
function isPointNode(n) {
|
|
23354
|
+
return n.info.shape?.kind === 3 /* SH_POINT */;
|
|
23492
23355
|
}
|
|
23493
|
-
function
|
|
23494
|
-
|
|
23495
|
-
if (
|
|
23496
|
-
|
|
23497
|
-
|
|
23498
|
-
|
|
23499
|
-
|
|
23500
|
-
|
|
23501
|
-
|
|
23356
|
+
function findFillDflt(n) {
|
|
23357
|
+
const fillcolor = nodeAttr(n, n.root, "fillcolor");
|
|
23358
|
+
if (fillcolor !== void 0 && fillcolor !== "") return fillcolor;
|
|
23359
|
+
const color = nodeAttr(n, n.root, "color");
|
|
23360
|
+
if (color !== void 0 && color !== "") return color;
|
|
23361
|
+
return "black";
|
|
23362
|
+
}
|
|
23363
|
+
function applyFillState(obj, n, job) {
|
|
23364
|
+
obj.id = svgNodeId(n, job);
|
|
23365
|
+
if (isPointNode(n)) {
|
|
23366
|
+
obj.fill = 1 /* Solid */;
|
|
23367
|
+
obj.fillColor = resolveRenderColor(findFillDflt(n));
|
|
23368
|
+
return true;
|
|
23369
|
+
}
|
|
23370
|
+
const fillRes = resolveNodeFillEx({
|
|
23371
|
+
style: nodeAttr(n, n.root, "style"),
|
|
23372
|
+
fillcolor: nodeAttr(n, n.root, "fillcolor"),
|
|
23373
|
+
color: nodeAttr(n, n.root, "color"),
|
|
23374
|
+
gradientangle: nodeAttr(n, n.root, "gradientangle")
|
|
23375
|
+
});
|
|
23376
|
+
if (fillRes.kind === "none") {
|
|
23377
|
+
obj.fill = 0 /* None */;
|
|
23378
|
+
return false;
|
|
23502
23379
|
}
|
|
23380
|
+
if (fillRes.kind === "solid") {
|
|
23381
|
+
obj.fill = 1 /* Solid */;
|
|
23382
|
+
obj.fillColor = resolveRenderColor(fillRes.color);
|
|
23383
|
+
return true;
|
|
23384
|
+
}
|
|
23385
|
+
applyGradientFields(obj, fillRes);
|
|
23503
23386
|
return true;
|
|
23504
23387
|
}
|
|
23505
|
-
function
|
|
23506
|
-
|
|
23507
|
-
|
|
23508
|
-
|
|
23509
|
-
|
|
23388
|
+
function applyPenState(obj, styleAttr, colorAttr, penwidthAttr) {
|
|
23389
|
+
const flags = parseStyleFlags(styleAttr);
|
|
23390
|
+
obj.penColor = resolveRenderColor(resolvePenColor(colorAttr));
|
|
23391
|
+
obj.pen = resolvePenType(flags);
|
|
23392
|
+
obj.penWidth = resolvePenWidth(flags, penwidthAttr);
|
|
23393
|
+
obj.rawStyle = styleTokens(styleAttr);
|
|
23510
23394
|
}
|
|
23511
|
-
function
|
|
23512
|
-
|
|
23513
|
-
|
|
23514
|
-
|
|
23515
|
-
|
|
23516
|
-
return
|
|
23395
|
+
function applyNodeStyle(obj, n, job) {
|
|
23396
|
+
const styleAttr = nodeAttr(n, n.root, "style");
|
|
23397
|
+
const colorAttr = nodeAttr(n, n.root, "color");
|
|
23398
|
+
const filled = applyFillState(obj, n, job);
|
|
23399
|
+
applyPenState(obj, styleAttr, colorAttr, nodeAttr(n, n.root, "penwidth"));
|
|
23400
|
+
return filled;
|
|
23517
23401
|
}
|
|
23518
|
-
function
|
|
23519
|
-
if (
|
|
23520
|
-
|
|
23521
|
-
|
|
23402
|
+
function prepareDrawPoly(poly, filled, obj) {
|
|
23403
|
+
if (poly.peripheries !== 0 || !filled) return poly;
|
|
23404
|
+
obj.penColor = { type: "string", s: "transparent" };
|
|
23405
|
+
return { ...poly, peripheries: 1 };
|
|
23406
|
+
}
|
|
23407
|
+
function vertexScale(n, poly) {
|
|
23408
|
+
const info = n.info;
|
|
23409
|
+
if (poly.vertices == null || info.width === void 0 || info.height === void 0) {
|
|
23410
|
+
return poly;
|
|
23522
23411
|
}
|
|
23523
|
-
|
|
23524
|
-
|
|
23525
|
-
|
|
23412
|
+
const xsize = (info.lw + info.rw) / (info.width * 72);
|
|
23413
|
+
const ysize = info.ht / (info.height * 72);
|
|
23414
|
+
if (Math.abs(xsize - 1) < 1e-9 && Math.abs(ysize - 1) < 1e-9) return poly;
|
|
23415
|
+
return {
|
|
23416
|
+
...poly,
|
|
23417
|
+
vertices: poly.vertices.map((v) => ({ x: v.x * xsize, y: v.y * ysize }))
|
|
23418
|
+
};
|
|
23419
|
+
}
|
|
23420
|
+
function resolveNodeDrawCtx(job, n) {
|
|
23421
|
+
const rawPoly = n.info.shape_info;
|
|
23422
|
+
if (rawPoly === void 0 || rawPoly.vertices === void 0) return null;
|
|
23423
|
+
const poly = vertexScale(n, rawPoly);
|
|
23424
|
+
const coord = n.info.coord ?? { x: 0, y: 0 };
|
|
23425
|
+
const obj = job.obj;
|
|
23426
|
+
const filled = obj !== null && applyNodeStyle(obj, n, job);
|
|
23427
|
+
const drawPoly = obj !== null ? prepareDrawPoly(poly, filled, obj) : poly;
|
|
23428
|
+
const styleFlags = parseStyleFlags(nodeAttr(n, n.root, "style"));
|
|
23429
|
+
const ringCtx = {
|
|
23430
|
+
renderer: job.renderer,
|
|
23431
|
+
job,
|
|
23432
|
+
style: styleFlags,
|
|
23433
|
+
fillcolor: nodeAttr(n, n.root, "fillcolor") ?? "",
|
|
23434
|
+
...specialCornerFlags(drawPoly.option, styleFlags)
|
|
23435
|
+
};
|
|
23436
|
+
return { poly: drawPoly, coord, filled, ringCtx };
|
|
23437
|
+
}
|
|
23438
|
+
function specialCornerFlags(opt, style) {
|
|
23439
|
+
return {
|
|
23440
|
+
shape: opt.shape,
|
|
23441
|
+
diagonals: opt.diagonals || style.diagonals,
|
|
23442
|
+
rounded: opt.rounded || style.rounded,
|
|
23443
|
+
underline: opt.underline || style.underline
|
|
23444
|
+
};
|
|
23445
|
+
}
|
|
23446
|
+
function polyGencode(rawJob, rawNode) {
|
|
23447
|
+
const job = rawJob;
|
|
23448
|
+
const n = rawNode;
|
|
23449
|
+
const renderer = job.renderer;
|
|
23450
|
+
if (!renderer) return;
|
|
23451
|
+
const ctx = resolveNodeDrawCtx(job, n);
|
|
23452
|
+
if (ctx === null) return;
|
|
23453
|
+
const clustersLast = (job.flags & EMIT_CLUSTERS_LAST) !== 0;
|
|
23454
|
+
const savedShape = job.obj?.urlMapShape;
|
|
23455
|
+
const savedPts = job.obj?.urlMapPts;
|
|
23456
|
+
let inAnchor = clustersLast ? false : beginNodeAnchor(n, renderer, job);
|
|
23457
|
+
renderPeripheries(ctx.poly, ctx.coord, ctx.filled, ctx.ringCtx);
|
|
23458
|
+
if (!isPointNode(n)) renderNodeLabel(n, ctx.coord, renderer, job);
|
|
23459
|
+
if (clustersLast) {
|
|
23460
|
+
if (job.obj && savedPts !== void 0 && savedShape !== void 0) {
|
|
23461
|
+
job.obj.urlMapShape = savedShape;
|
|
23462
|
+
job.obj.urlMapPts = savedPts;
|
|
23463
|
+
}
|
|
23464
|
+
inAnchor = beginNodeAnchor(n, renderer, job);
|
|
23526
23465
|
}
|
|
23527
|
-
|
|
23466
|
+
if (inAnchor) renderer.endAnchor?.(job);
|
|
23528
23467
|
}
|
|
23529
|
-
|
|
23530
|
-
|
|
23531
|
-
|
|
23532
|
-
|
|
23533
|
-
|
|
23534
|
-
|
|
23535
|
-
|
|
23468
|
+
|
|
23469
|
+
// src/common/poly-inside.ts
|
|
23470
|
+
function sameSide(p0, p1, L0, L1) {
|
|
23471
|
+
const a = -(L1.y - L0.y);
|
|
23472
|
+
const b = L1.x - L0.x;
|
|
23473
|
+
const c = a * L0.x + b * L0.y;
|
|
23474
|
+
const s0 = a * p0.x + b * p0.y - c >= 0;
|
|
23475
|
+
const s1 = a * p1.x + b * p1.y - c >= 0;
|
|
23476
|
+
return s0 === s1;
|
|
23477
|
+
}
|
|
23478
|
+
function fixedShapeSize(poly) {
|
|
23479
|
+
let xmax = 0;
|
|
23480
|
+
let ymax = 0;
|
|
23481
|
+
for (const v of poly.vertices ?? []) {
|
|
23482
|
+
xmax = Math.max(xmax, Math.abs(v.x));
|
|
23483
|
+
ymax = Math.max(ymax, Math.abs(v.y));
|
|
23536
23484
|
}
|
|
23537
|
-
|
|
23538
|
-
const h = ufFind(e.head);
|
|
23539
|
-
if (e.tail !== t || e.head !== h) return prev;
|
|
23540
|
-
return class2EdgeSameRep(g, e);
|
|
23485
|
+
return { w: 2 * xmax, h: 2 * ymax };
|
|
23541
23486
|
}
|
|
23542
|
-
function
|
|
23543
|
-
|
|
23544
|
-
|
|
23545
|
-
|
|
23546
|
-
|
|
23487
|
+
function insideDims(n, xsize, ysize) {
|
|
23488
|
+
const w = 72 * (n.info.width || xsize / 72);
|
|
23489
|
+
const h = 72 * (n.info.height || ysize / 72);
|
|
23490
|
+
return { w, h, ow: 72 * n.info.outline_width || w, oh: 72 * n.info.outline_height || h };
|
|
23491
|
+
}
|
|
23492
|
+
function insideScale(n, poly) {
|
|
23493
|
+
const flip = n.root.info.flip === true;
|
|
23494
|
+
if (poly.option.fixedshape) {
|
|
23495
|
+
const { w: w2, h: h2 } = fixedShapeSize(poly);
|
|
23496
|
+
const xsize2 = flip ? h2 : w2;
|
|
23497
|
+
const ysize2 = flip ? w2 : h2;
|
|
23498
|
+
return {
|
|
23499
|
+
scalex: xsize2 !== 0 ? w2 / xsize2 : w2,
|
|
23500
|
+
scaley: ysize2 !== 0 ? h2 / ysize2 : h2,
|
|
23501
|
+
boxURx: w2 / 2,
|
|
23502
|
+
boxURy: h2 / 2
|
|
23503
|
+
};
|
|
23547
23504
|
}
|
|
23505
|
+
const lwrw = n.info.lw + n.info.rw;
|
|
23506
|
+
const xsize = flip ? n.info.ht : lwrw;
|
|
23507
|
+
const ysize = flip ? lwrw : n.info.ht;
|
|
23508
|
+
const { w, h, ow, oh } = insideDims(n, xsize, ysize);
|
|
23509
|
+
return {
|
|
23510
|
+
scalex: xsize !== 0 ? w / xsize : w,
|
|
23511
|
+
scaley: ysize !== 0 ? h / ysize : h,
|
|
23512
|
+
boxURx: ow / 2,
|
|
23513
|
+
boxURy: oh / 2
|
|
23514
|
+
};
|
|
23548
23515
|
}
|
|
23549
|
-
function
|
|
23550
|
-
|
|
23516
|
+
function polygonWalk(P, vertex, sides) {
|
|
23517
|
+
const O = { x: 0, y: 0 };
|
|
23518
|
+
let i = 0;
|
|
23519
|
+
let i1 = 1 % sides;
|
|
23520
|
+
const Q = vertex[i];
|
|
23521
|
+
const R2 = vertex[i1];
|
|
23522
|
+
if (!sameSide(P, O, Q, R2)) return false;
|
|
23523
|
+
const s = sameSide(P, Q, R2, O);
|
|
23524
|
+
if (s && sameSide(P, R2, O, Q)) return true;
|
|
23525
|
+
for (let j = 1; j < sides; j++) {
|
|
23526
|
+
if (s) {
|
|
23527
|
+
i = i1;
|
|
23528
|
+
i1 = (i + 1) % sides;
|
|
23529
|
+
} else {
|
|
23530
|
+
i1 = i;
|
|
23531
|
+
i = (i + sides - 1) % sides;
|
|
23532
|
+
}
|
|
23533
|
+
if (!sameSide(P, O, vertex[i], vertex[i1])) return false;
|
|
23534
|
+
}
|
|
23535
|
+
return true;
|
|
23551
23536
|
}
|
|
23552
|
-
function
|
|
23553
|
-
|
|
23537
|
+
function insideShape(n, poly, p) {
|
|
23538
|
+
const sc = insideScale(n, poly);
|
|
23539
|
+
const P = { x: p.x * sc.scalex, y: p.y * sc.scaley };
|
|
23540
|
+
if (Math.abs(P.x) > sc.boxURx || Math.abs(P.y) > sc.boxURy) return false;
|
|
23541
|
+
if (poly.sides <= 2) {
|
|
23542
|
+
return Math.hypot(P.x / sc.boxURx, P.y / sc.boxURy) < 1;
|
|
23543
|
+
}
|
|
23544
|
+
const outerStart = (Math.max(poly.peripheries, 1) - 1) * poly.sides;
|
|
23545
|
+
const outer = poly.vertices.slice(outerStart, outerStart + poly.sides);
|
|
23546
|
+
const ring = polygonOutlineRing(outer, poly.sides, poly.penwidth ?? 1);
|
|
23547
|
+
return polygonWalk(P, ring, poly.sides);
|
|
23554
23548
|
}
|
|
23555
|
-
function
|
|
23556
|
-
|
|
23557
|
-
|
|
23558
|
-
|
|
23549
|
+
function polyInside(ctx, p) {
|
|
23550
|
+
const n = ctx.node;
|
|
23551
|
+
if (n === void 0) return false;
|
|
23552
|
+
const rankdir = (n.root.info.rankdir ?? 0) & 3;
|
|
23553
|
+
const P = rankdir === 0 ? p : ccwrotatepf(p, rankdir * 90);
|
|
23554
|
+
if (ctx.bp) {
|
|
23555
|
+
const b = ctx.bp;
|
|
23556
|
+
return P.x >= b.ll.x && P.x <= b.ur.x && P.y >= b.ll.y && P.y <= b.ur.y;
|
|
23559
23557
|
}
|
|
23558
|
+
const poly = n.info.shape_info;
|
|
23559
|
+
if (poly === void 0 || poly.vertices === null) return false;
|
|
23560
|
+
return insideShape(n, poly, P);
|
|
23560
23561
|
}
|
|
23561
|
-
function
|
|
23562
|
-
const
|
|
23563
|
-
|
|
23564
|
-
|
|
23565
|
-
|
|
23562
|
+
function starInside(ctx, p) {
|
|
23563
|
+
const n = ctx.node;
|
|
23564
|
+
if (n === void 0) return false;
|
|
23565
|
+
const rankdir = (n.root.info.rankdir ?? 0) & 3;
|
|
23566
|
+
const P = rankdir === 0 ? p : ccwrotatepf(p, rankdir * 90);
|
|
23567
|
+
if (ctx.bp) {
|
|
23568
|
+
const b = ctx.bp;
|
|
23569
|
+
return P.x >= b.ll.x && P.x <= b.ur.x && P.y >= b.ll.y && P.y <= b.ur.y;
|
|
23570
|
+
}
|
|
23571
|
+
const poly = n.info.shape_info;
|
|
23572
|
+
if (poly === void 0 || poly.vertices === null) return false;
|
|
23573
|
+
const sides = poly.sides;
|
|
23574
|
+
const outerStart = (Math.max(poly.peripheries, 1) - 1) * sides;
|
|
23575
|
+
const outer = poly.vertices.slice(outerStart, outerStart + sides);
|
|
23576
|
+
const ring = polygonOutlineRing(outer, sides, poly.penwidth ?? 1);
|
|
23577
|
+
const O = { x: 0, y: 0 };
|
|
23578
|
+
let outcnt = 0;
|
|
23579
|
+
for (let i = 0; i < sides; i += 2) {
|
|
23580
|
+
const Q = ring[i];
|
|
23581
|
+
const R2 = ring[(i + 4) % sides];
|
|
23582
|
+
if (!sameSide(P, O, Q, R2)) outcnt++;
|
|
23583
|
+
if (outcnt === 2) return false;
|
|
23566
23584
|
}
|
|
23585
|
+
return true;
|
|
23567
23586
|
}
|
|
23568
|
-
function
|
|
23569
|
-
|
|
23570
|
-
|
|
23571
|
-
const
|
|
23572
|
-
|
|
23573
|
-
|
|
23574
|
-
|
|
23575
|
-
|
|
23587
|
+
function recordInside(ctx, p) {
|
|
23588
|
+
const n = ctx.node;
|
|
23589
|
+
if (n === void 0) return false;
|
|
23590
|
+
const rankdir = (n.root.info.rankdir ?? 0) & 3;
|
|
23591
|
+
const P = rankdir === 0 ? p : ccwrotatepf(p, rankdir * 90);
|
|
23592
|
+
let bb;
|
|
23593
|
+
if (ctx.bp) {
|
|
23594
|
+
bb = ctx.bp;
|
|
23595
|
+
} else {
|
|
23596
|
+
const fld = n.info.shape_info;
|
|
23597
|
+
if (!fld?.b) return false;
|
|
23598
|
+
bb = fld.b;
|
|
23599
|
+
}
|
|
23600
|
+
const pw = 0.5;
|
|
23601
|
+
return P.x >= bb.ll.x - pw && P.x <= bb.ur.x + pw && P.y >= bb.ll.y - pw && P.y <= bb.ur.y + pw;
|
|
23576
23602
|
}
|
|
23577
23603
|
|
|
23578
23604
|
// src/common/edge-label-init.ts
|
|
@@ -23939,7 +23965,7 @@ function gdRankdir(n) {
|
|
|
23939
23965
|
function gdFlip(n) {
|
|
23940
23966
|
return (gdRankdir(n) & 1) !== 0;
|
|
23941
23967
|
}
|
|
23942
|
-
function
|
|
23968
|
+
function cwrotatepf2(p, cwrot) {
|
|
23943
23969
|
switch (cwrot) {
|
|
23944
23970
|
case 90:
|
|
23945
23971
|
return { x: p.y, y: -p.x };
|
|
@@ -24086,7 +24112,7 @@ function setOrder(pp, q) {
|
|
|
24086
24112
|
pp.order = MC_SCALE * a / (2 * Math.PI) | 0;
|
|
24087
24113
|
}
|
|
24088
24114
|
function applyDir(pp, bp, dir, rd, definedFinal) {
|
|
24089
|
-
const q =
|
|
24115
|
+
const q = cwrotatepf2(dir.p, 90 * rd);
|
|
24090
24116
|
pp.p = q;
|
|
24091
24117
|
pp.bp = bp;
|
|
24092
24118
|
pp.side = dir.dyna ? dir.side : invflipSide(dir.side, rd);
|
|
@@ -24102,7 +24128,7 @@ function nodeInsideFn(n) {
|
|
|
24102
24128
|
}
|
|
24103
24129
|
function compassPoint(n, insideFn, yArg, xArg, rd) {
|
|
24104
24130
|
let p = { x: xArg, y: yArg };
|
|
24105
|
-
if (rd) p =
|
|
24131
|
+
if (rd) p = cwrotatepf2(p, 90 * rd);
|
|
24106
24132
|
const curve = [{ x: 0, y: 0 }, { x: 0, y: 0 }, { x: p.x, y: p.y }, { x: p.x, y: p.y }];
|
|
24107
24133
|
const ctx = { nodeCoord: n.info.coord, rw: n.info.rw, bp: null, node: n };
|
|
24108
24134
|
bezierClip(ctx, insideFn, curve, true);
|
|
@@ -32109,31 +32135,13 @@ function splay(root, key, keyOf, compare) {
|
|
|
32109
32135
|
}
|
|
32110
32136
|
|
|
32111
32137
|
// src/cdt/bag.ts
|
|
32112
|
-
function
|
|
32113
|
-
|
|
32114
|
-
|
|
32115
|
-
|
|
32116
|
-
|
|
32117
|
-
|
|
32118
|
-
|
|
32119
|
-
cur = cur.left;
|
|
32120
|
-
}
|
|
32121
|
-
return [null, null];
|
|
32122
|
-
}
|
|
32123
|
-
function unlinkNode(root, cur, parent) {
|
|
32124
|
-
const left = cur.left;
|
|
32125
|
-
const right = cur.right;
|
|
32126
|
-
let replacement;
|
|
32127
|
-
if (left === null) {
|
|
32128
|
-
replacement = right;
|
|
32129
|
-
} else {
|
|
32130
|
-
const maxLeft = splayMax(left);
|
|
32131
|
-
maxLeft.right = right;
|
|
32132
|
-
replacement = maxLeft;
|
|
32133
|
-
}
|
|
32134
|
-
if (parent === null) return replacement;
|
|
32135
|
-
parent.left = replacement;
|
|
32136
|
-
return root;
|
|
32138
|
+
function removeRoot(root) {
|
|
32139
|
+
const left = root.left;
|
|
32140
|
+
const right = root.right;
|
|
32141
|
+
if (left === null) return right;
|
|
32142
|
+
const maxLeft = splayMax(left);
|
|
32143
|
+
maxLeft.right = right;
|
|
32144
|
+
return maxLeft;
|
|
32137
32145
|
}
|
|
32138
32146
|
var DtBag = class {
|
|
32139
32147
|
_root = null;
|
|
@@ -32172,16 +32180,13 @@ var DtBag = class {
|
|
|
32172
32180
|
const key = this._keyOf(obj);
|
|
32173
32181
|
this._root = splay(this._root, key, this._keyOf, this._compare);
|
|
32174
32182
|
if (this._compare(key, this._keyOf(this._root.obj)) !== 0) return false;
|
|
32175
|
-
|
|
32176
|
-
this._root
|
|
32177
|
-
|
|
32178
|
-
|
|
32179
|
-
|
|
32180
|
-
|
|
32181
|
-
);
|
|
32182
|
-
if (cur === null) return false;
|
|
32183
|
-
const newRoot = unlinkNode(this._root, cur, parent);
|
|
32184
|
-
this._root = newRoot;
|
|
32183
|
+
while (this._root.obj !== obj) {
|
|
32184
|
+
const nxt = this.next(this._root.obj);
|
|
32185
|
+
if (nxt === void 0 || this._compare(key, this._keyOf(nxt)) !== 0) {
|
|
32186
|
+
return false;
|
|
32187
|
+
}
|
|
32188
|
+
}
|
|
32189
|
+
this._root = removeRoot(this._root);
|
|
32185
32190
|
this._size--;
|
|
32186
32191
|
return true;
|
|
32187
32192
|
}
|
|
@@ -52464,7 +52469,7 @@ var XdotParser = class _XdotParser {
|
|
|
52464
52469
|
let accounted = 0;
|
|
52465
52470
|
let j = 0;
|
|
52466
52471
|
while (accounted < len) {
|
|
52467
|
-
if (cur + j >= s.length)
|
|
52472
|
+
if (cur + j >= s.length) return null;
|
|
52468
52473
|
const ch = s[cur + j];
|
|
52469
52474
|
const prev = j > 0 ? s[cur + j - 1] : "";
|
|
52470
52475
|
out += ch;
|