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