@knowvah/dot-engine 2.7.1 → 2.8.0

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.
Files changed (117) hide show
  1. package/dist/api.js.map +2 -2
  2. package/dist/common/agerr.d.ts +8 -1
  3. package/dist/common/agerr.d.ts.map +1 -1
  4. package/dist/common/fma.d.ts.map +1 -1
  5. package/dist/common/htmltable-emit-fill.d.ts.map +1 -1
  6. package/dist/common/htmltable-label.d.ts +3 -0
  7. package/dist/common/htmltable-label.d.ts.map +1 -1
  8. package/dist/common/htmltable-lex-attvalue.d.ts.map +1 -1
  9. package/dist/common/htmltable.d.ts +5 -0
  10. package/dist/common/htmltable.d.ts.map +1 -1
  11. package/dist/common/layers.d.ts +12 -0
  12. package/dist/common/layers.d.ts.map +1 -1
  13. package/dist/common/layout-state.d.ts +8 -0
  14. package/dist/common/layout-state.d.ts.map +1 -0
  15. package/dist/common/make-label.d.ts.map +1 -1
  16. package/dist/common/multicolor.d.ts +6 -3
  17. package/dist/common/multicolor.d.ts.map +1 -1
  18. package/dist/common/nodeinit.d.ts.map +1 -1
  19. package/dist/common/poly-init.d.ts +11 -0
  20. package/dist/common/poly-init.d.ts.map +1 -1
  21. package/dist/common/poly-sizing.d.ts +1 -0
  22. package/dist/common/poly-sizing.d.ts.map +1 -1
  23. package/dist/common/postproc.d.ts.map +1 -1
  24. package/dist/common/style-resolve.d.ts +11 -9
  25. package/dist/common/style-resolve.d.ts.map +1 -1
  26. package/dist/gvc/device-cluster.d.ts +5 -6
  27. package/dist/gvc/device-cluster.d.ts.map +1 -1
  28. package/dist/gvc/device.d.ts.map +1 -1
  29. package/dist/gvc/first-layer.d.ts +21 -5
  30. package/dist/gvc/first-layer.d.ts.map +1 -1
  31. package/dist/gvc/gvrender-set-style.d.ts.map +1 -1
  32. package/dist/gvc/usershape.d.ts +20 -0
  33. package/dist/gvc/usershape.d.ts.map +1 -1
  34. package/dist/index.js +494 -275
  35. package/dist/index.js.map +4 -4
  36. package/dist/layout/circo/index.d.ts.map +1 -1
  37. package/dist/layout/dot/init.d.ts +10 -0
  38. package/dist/layout/dot/init.d.ts.map +1 -1
  39. package/dist/layout/dot/splines.d.ts.map +1 -1
  40. package/dist/layout/fdp/init.d.ts.map +1 -1
  41. package/dist/layout/neato/conjgrad-mkernel.d.ts.map +1 -1
  42. package/dist/layout/neato/constrained-majorization.d.ts.map +1 -1
  43. package/dist/layout/neato/edge-len.d.ts +6 -2
  44. package/dist/layout/neato/edge-len.d.ts.map +1 -1
  45. package/dist/layout/neato/init.d.ts.map +1 -1
  46. package/dist/layout/neato/kk.d.ts.map +1 -1
  47. package/dist/layout/neato/make-graph-data.d.ts.map +1 -1
  48. package/dist/layout/neato/matrix-ops.d.ts +0 -6
  49. package/dist/layout/neato/matrix-ops.d.ts.map +1 -1
  50. package/dist/layout/neato/smart-ini-x.d.ts.map +1 -1
  51. package/dist/layout/neato/splines.d.ts.map +1 -1
  52. package/dist/layout/neato/start.d.ts.map +1 -1
  53. package/dist/layout/neato/stress-kernel.d.ts +2 -5
  54. package/dist/layout/neato/stress-kernel.d.ts.map +1 -1
  55. package/dist/layout/neato/stress.d.ts +6 -0
  56. package/dist/layout/neato/stress.d.ts.map +1 -1
  57. package/dist/layout/osage/index.d.ts.map +1 -1
  58. package/dist/layout/patchwork/index.d.ts.map +1 -1
  59. package/dist/layout/sfdp/init.d.ts.map +1 -1
  60. package/dist/layout/twopi/init.d.ts +12 -6
  61. package/dist/layout/twopi/init.d.ts.map +1 -1
  62. package/dist/model/cgraph-ops.d.ts +9 -0
  63. package/dist/model/cgraph-ops.d.ts.map +1 -1
  64. package/dist/render/color-resolve.d.ts +7 -0
  65. package/dist/render/color-resolve.d.ts.map +1 -1
  66. package/dist/render/json.d.ts +17 -2
  67. package/dist/render/json.d.ts.map +1 -1
  68. package/dist/render/map.d.ts +3 -5
  69. package/dist/render/map.d.ts.map +1 -1
  70. package/dist/render.js +500 -281
  71. package/dist/render.js.map +4 -4
  72. package/package.json +1 -1
  73. package/src/common/agerr.ts +69 -8
  74. package/src/common/fma.ts +11 -1
  75. package/src/common/htmltable-emit-fill.ts +11 -7
  76. package/src/common/htmltable-label.ts +6 -3
  77. package/src/common/htmltable-lex-attvalue.ts +17 -1
  78. package/src/common/htmltable.ts +10 -5
  79. package/src/common/layers.ts +31 -2
  80. package/src/common/layout-state.ts +35 -0
  81. package/src/common/make-label.ts +6 -2
  82. package/src/common/multicolor.ts +12 -6
  83. package/src/common/nodeinit.ts +2 -1
  84. package/src/common/poly-init.ts +18 -1
  85. package/src/common/poly-sizing.ts +4 -4
  86. package/src/common/postproc.ts +4 -1
  87. package/src/common/style-resolve.ts +118 -50
  88. package/src/gvc/device-cluster.ts +31 -39
  89. package/src/gvc/device.ts +55 -43
  90. package/src/gvc/first-layer.ts +60 -11
  91. package/src/gvc/gvrender-set-style.ts +1 -6
  92. package/src/gvc/usershape.ts +40 -0
  93. package/src/layout/circo/index.ts +4 -0
  94. package/src/layout/dot/init.ts +32 -0
  95. package/src/layout/dot/splines.ts +3 -0
  96. package/src/layout/fdp/init.ts +17 -0
  97. package/src/layout/neato/conjgrad-mkernel.ts +2 -3
  98. package/src/layout/neato/constrained-majorization.ts +2 -1
  99. package/src/layout/neato/edge-len.ts +39 -7
  100. package/src/layout/neato/init.ts +8 -3
  101. package/src/layout/neato/kk.ts +2 -1
  102. package/src/layout/neato/make-graph-data.ts +1 -2
  103. package/src/layout/neato/matrix-ops.ts +1 -11
  104. package/src/layout/neato/smart-ini-x.ts +1 -1
  105. package/src/layout/neato/splines.ts +3 -1
  106. package/src/layout/neato/start.ts +3 -2
  107. package/src/layout/neato/stress-kernel.ts +45 -86
  108. package/src/layout/neato/stress.ts +19 -0
  109. package/src/layout/osage/index.ts +8 -1
  110. package/src/layout/patchwork/index.ts +4 -0
  111. package/src/layout/sfdp/init.ts +3 -0
  112. package/src/layout/twopi/init.ts +21 -9
  113. package/src/layout/twopi/pipeline.ts +3 -3
  114. package/src/model/cgraph-ops.ts +19 -0
  115. package/src/render/color-resolve.ts +17 -2
  116. package/src/render/json.ts +9 -10
  117. package/src/render/map.ts +5 -6
package/dist/index.js CHANGED
@@ -17,7 +17,9 @@ var WHITESPACE = /* @__PURE__ */ new Set([9, 10, 11, 12, 13]);
17
17
  var OCTAL_WIDTH = 3;
18
18
  var OCTAL_RADIX = 8;
19
19
  var lastLevel = "warning";
20
+ var pending = { line: null, channel: "warn" };
20
21
  registerRenderState(() => {
22
+ flushPending();
21
23
  lastLevel = "warning";
22
24
  });
23
25
  function escapeControl(message) {
@@ -31,17 +33,43 @@ function escapeControl(message) {
31
33
  return out;
32
34
  }
33
35
  function agerrLineOn(channel, line) {
36
+ flushPending();
37
+ writeLine(channel, line);
38
+ }
39
+ function flushPending() {
40
+ if (pending.line === null) return;
41
+ const { line, channel } = pending;
42
+ pending.line = null;
43
+ writeLine(channel, line);
44
+ }
45
+ function writeLine(channel, line) {
34
46
  if (channel === "warn") console.warn(escapeControl(line));
35
47
  else console.error(escapeControl(line));
36
48
  }
37
- function agerr(level, msg, channel) {
38
- if (level === "prev") {
39
- agerrLineOn(channel ?? (lastLevel === "warning" ? "warn" : "error"), msg);
40
- return;
41
- }
42
- lastLevel = level;
49
+ function assemble(level, msg) {
50
+ if (level === "prev") return msg;
43
51
  const prefix = level === "error" ? PREFIX_ERROR : PREFIX_WARNING;
44
- agerrLineOn(channel ?? (level === "warning" ? "warn" : "error"), `${prefix}${PREFIX_SEP}${msg}`);
52
+ return `${prefix}${PREFIX_SEP}${msg}`;
53
+ }
54
+ function channelOf(level) {
55
+ const eff = level === "prev" ? lastLevel : level;
56
+ return eff === "warning" ? "warn" : "error";
57
+ }
58
+ function emit(level, msg, channel, hold) {
59
+ const target = channel ?? channelOf(level);
60
+ if (level !== "prev") lastLevel = level;
61
+ const text = assemble(level, msg);
62
+ if (pending.line === null) {
63
+ pending.channel = target;
64
+ pending.line = text;
65
+ } else pending.line += text;
66
+ if (!hold) flushPending();
67
+ }
68
+ function agerr(level, msg, channel) {
69
+ emit(level, msg, channel, false);
70
+ }
71
+ function agerrPartial(level, msg, channel) {
72
+ emit(level, msg, channel, true);
45
73
  }
46
74
  var agerrorf = (msg, channel) => agerr("error", msg, channel);
47
75
  var agwarningf = (msg, channel) => agerr("warning", msg, channel);
@@ -3989,6 +4017,10 @@ var Edge = class _Edge {
3989
4017
 
3990
4018
  // src/model/cgraph-ops.ts
3991
4019
  var LOCALNAMEPREFIX = "%";
4020
+ var ANONYMOUS_ROOT_ID = 1;
4021
+ function agNameOf(g) {
4022
+ return g.anonymous ? `${LOCALNAMEPREFIX}${ANONYMOUS_ROOT_ID}` : g.name;
4023
+ }
3992
4024
  function freshNodeId(root) {
3993
4025
  let max = -1;
3994
4026
  for (const n of root.nodes.values()) {
@@ -8824,6 +8856,7 @@ function claimWarned() {
8824
8856
  return true;
8825
8857
  }
8826
8858
  var claimNever = () => false;
8859
+ var MSG_MANY_COLORS = "More than 2 colors specified for a gradient - ignoring remaining";
8827
8860
  var EPS = 1e-5;
8828
8861
  function aeq0(x) {
8829
8862
  return x < EPS && x > -EPS;
@@ -8889,8 +8922,8 @@ function scanSegs(colorlist, claim) {
8889
8922
  function parseSegs(colorlist, context) {
8890
8923
  const result = scanSegs(colorlist, claimWarned);
8891
8924
  if (result.error === 3) {
8892
- const tail = context === void 0 ? "" : context();
8893
- agwarningf(`Total size > 1 in "${colorlist}" color spec ${tail}`);
8925
+ agerrPartial("warning", `Total size > 1 in "${colorlist}" color spec `);
8926
+ if (context !== void 0) agerr("prev", context());
8894
8927
  } else if (result.error === 2) {
8895
8928
  agerrorf(`Illegal value in "${colorlist}" color attribute; float expected after ';'`);
8896
8929
  if (context !== void 0) agerr("prev", context());
@@ -8940,23 +8973,68 @@ function zeroFlags() {
8940
8973
  };
8941
8974
  }
8942
8975
  var FUNLIMIT = 64;
8976
+ var STYLE_SPACE = /* @__PURE__ */ new Set([" ", " ", "\n", "\v", "\f", "\r"]);
8977
+ function isStyleDelim(c) {
8978
+ return c === void 0 || c === "(" || c === ")" || c === ",";
8979
+ }
8980
+ function styleToken(s, from) {
8981
+ let p = from;
8982
+ while (p < s.length && (STYLE_SPACE.has(s[p]) || s[p] === ",")) p++;
8983
+ if (p >= s.length) return null;
8984
+ if (s[p] === "(" || s[p] === ")") return { type: s[p], text: s[p], next: p + 1 };
8985
+ const start = p;
8986
+ while (!isStyleDelim(s[p])) p++;
8987
+ return { type: "id", text: s.slice(start, p), next: p };
8988
+ }
8989
+ var NO_TOKENS = [];
8990
+ function parseStyleQuiet(s) {
8991
+ const end = s.indexOf("\0");
8992
+ const str = end < 0 ? s : s.slice(0, end);
8993
+ const names = [];
8994
+ const args = [];
8995
+ let inParens = false;
8996
+ for (let c = styleToken(str, 0); c !== null; c = styleToken(str, c.next)) {
8997
+ if (c.type === "(") {
8998
+ if (inParens) return { tokens: NO_TOKENS, fault: "nesting" };
8999
+ inParens = true;
9000
+ } else if (c.type === ")") {
9001
+ if (!inParens) return { tokens: NO_TOKENS, fault: "unmatched-close" };
9002
+ inParens = false;
9003
+ } else if (inParens) {
9004
+ args[names.length - 1]?.push(c.text);
9005
+ } else {
9006
+ if (names.length === FUNLIMIT - 1) return { tokens: NO_TOKENS, fault: "truncate" };
9007
+ names.push(c.text);
9008
+ args.push([]);
9009
+ }
9010
+ }
9011
+ if (inParens) return { tokens: NO_TOKENS, fault: "unmatched-open" };
9012
+ const tokens = names.map((n, i) => args[i].length === 0 ? n : `${n}(${args[i].join(",")})`);
9013
+ return { tokens, fault: null };
9014
+ }
9015
+ function reportStyleFault(fault, s) {
9016
+ if (fault === "nesting") agerrorf(`nesting not allowed in style: ${s}`);
9017
+ else if (fault === "unmatched-close") agerrorf(`unmatched ')' in style: ${s}`);
9018
+ else if (fault === "unmatched-open") agerrorf(`unmatched '(' in style: ${s}`);
9019
+ else agwarningf(`truncating style '${s}'`);
9020
+ }
8943
9021
  function styleTokens(style2) {
8944
9022
  if (!style2) return [];
8945
- const out = [];
8946
- let fun = 0;
8947
- for (const raw of style2.split(",")) {
8948
- const token = raw.trim();
8949
- if (token.length === 0) continue;
8950
- if (fun === FUNLIMIT - 1) return [];
8951
- fun++;
8952
- out.push(token);
8953
- }
8954
- return out;
9023
+ const { tokens, fault } = parseStyleQuiet(style2);
9024
+ if (fault !== null) reportStyleFault(fault, style2);
9025
+ return tokens;
9026
+ }
9027
+ function styleTokensQuiet(style2) {
9028
+ return style2 ? parseStyleQuiet(style2).tokens : [];
9029
+ }
9030
+ function styleName(token) {
9031
+ const paren = token.indexOf("(");
9032
+ return paren < 0 ? token : token.slice(0, paren);
8955
9033
  }
8956
9034
  function parseSetLineWidth(token) {
8957
- const m = /^setlinewidth\s*\(\s*([^)]*)\)\s*$/.exec(token);
8958
- if (m === null) return null;
8959
- const v = parseFloat(m[1]);
9035
+ if (styleName(token) !== "setlinewidth") return null;
9036
+ const m = /^[^(]*\(([^,)]*)/.exec(token);
9037
+ const v = m === null ? Number.NaN : parseFloat(m[1]);
8960
9038
  return Number.isNaN(v) ? 0 : v;
8961
9039
  }
8962
9040
  function applyToken(flags, token) {
@@ -8980,33 +9058,18 @@ function firstSolidColor(raw) {
8980
9058
  }
8981
9059
  function parseStyleFlags(style2) {
8982
9060
  const flags = zeroFlags();
8983
- if (!style2) return flags;
8984
- let fun = 0;
8985
- for (const raw of style2.split(",")) {
8986
- const token = raw.trim();
8987
- if (token.length === 0) continue;
8988
- if (fun === FUNLIMIT - 1) return zeroFlags();
8989
- fun++;
9061
+ for (const token of styleTokensQuiet(style2)) {
8990
9062
  const lw = parseSetLineWidth(token);
8991
9063
  if (lw !== null) {
8992
9064
  flags.setLineWidth = lw;
8993
9065
  continue;
8994
9066
  }
8995
- if (!token.includes("(")) applyToken(flags, token);
9067
+ applyToken(flags, styleName(token));
8996
9068
  }
8997
9069
  return flags;
8998
9070
  }
8999
9071
  function styleHasInvisibleAlias(style2) {
9000
- if (!style2) return false;
9001
- let fun = 0;
9002
- for (const raw of style2.split(",")) {
9003
- const token = raw.trim();
9004
- if (token.length === 0) continue;
9005
- if (fun === FUNLIMIT - 1) return false;
9006
- fun++;
9007
- if (token === "invisible") return true;
9008
- }
9009
- return false;
9072
+ return styleTokensQuiet(style2).some((token) => styleName(token) === "invisible");
9010
9073
  }
9011
9074
  function resolvePenType(flags) {
9012
9075
  if (flags.invis) return 0 /* None */;
@@ -9044,11 +9107,10 @@ function applyBgcolor(attrs, filled, fillcolor) {
9044
9107
  }
9045
9108
  function findStopColor(colorlist) {
9046
9109
  const { segs, error } = parseSegs(colorlist);
9047
- if (error === 1 || error === 2) return null;
9048
- if (segs.length < 2) return null;
9049
9110
  const seg0 = segs[0];
9050
9111
  const seg1 = segs[1];
9051
- if (seg0.color === null) return null;
9112
+ if (error !== 0 || seg0 === void 0 || seg1 === void 0 || seg0.color === null) return null;
9113
+ if (segs.length > 2) agwarningf(MSG_MANY_COLORS);
9052
9114
  const fillColor = seg0.color;
9053
9115
  const stopColor = seg1.color ?? DEFAULT_COLOR;
9054
9116
  const frac = seg0.hasFraction ? seg0.t : seg1.hasFraction ? 1 - seg1.t : 0;
@@ -9061,7 +9123,7 @@ function parseAngle(gradientangle2) {
9061
9123
  }
9062
9124
  function buildResolvedFill(rawColor, flags, angle) {
9063
9125
  const stop = findStopColor(rawColor);
9064
- if (stop === null) return { kind: "solid", color: rawColor };
9126
+ if (stop === null) return { kind: "solid", color: rawColor.split(":", 1)[0] };
9065
9127
  const kind = flags.radial ? "radial" : "linear";
9066
9128
  return { kind, fillColor: stop.fillColor, stopColor: stop.stopColor, frac: stop.frac, angle };
9067
9129
  }
@@ -9256,6 +9318,13 @@ function firstColor(name) {
9256
9318
  }
9257
9319
  function resolveRenderColor(raw, report = true) {
9258
9320
  if (raw === "" || raw === "none") return { type: "none" };
9321
+ return resolveColorName(raw, report);
9322
+ }
9323
+ function resolveFillColorName(raw, report = true) {
9324
+ if (raw === "none") return { type: "none" };
9325
+ return resolveColorName(raw, report);
9326
+ }
9327
+ function resolveColorName(raw, report) {
9259
9328
  const known = KNOWN_COLORS.has(raw.toLowerCase());
9260
9329
  if (known && (rendererColors.hasKnownList || !report)) return { type: "string", s: raw };
9261
9330
  const color = { type: "rgba", r: 0, g: 0, b: 0, a: 0 };
@@ -9369,7 +9438,7 @@ function reportEdgeColors(e) {
9369
9438
  reportColorNames(edgeGraphicsColors({
9370
9439
  color,
9371
9440
  fillcolor: e.attrs.get("fillcolor") ?? "",
9372
- tapered: styleTokens(e.attrs.get("style")).includes("tapered"),
9441
+ tapered: styleTokensQuiet(e.attrs.get("style")).includes("tapered"),
9373
9442
  arrows: spl.list.map((bz) => ({ sflag: bz.sflag !== 0, eflag: bz.eflag !== 0 }))
9374
9443
  }));
9375
9444
  }
@@ -9929,10 +9998,6 @@ var BOX_ORIENTATION_TOLERANCE = 0.5;
9929
9998
  var BOX_ORIENTATION_STEP = 90;
9930
9999
  var BOX_SIDES = 4;
9931
10000
  var ELLIPSE_MAX_SIDES = 2;
9932
- function styleName(token) {
9933
- const paren = token.indexOf("(");
9934
- return paren < 0 ? token : token.slice(0, paren);
9935
- }
9936
10001
  function gvrenderSetStyle(styles) {
9937
10002
  if (styles === null) return;
9938
10003
  for (const token of styles) {
@@ -9996,7 +10061,6 @@ var BORDER_BOTTOM = 1 << 13;
9996
10061
  var BORDER_MASK = BORDER_LEFT | BORDER_TOP | BORDER_RIGHT | BORDER_BOTTOM;
9997
10062
 
9998
10063
  // src/common/htmltable-emit-fill.ts
9999
- var MSG_MANY_COLORS = "More than 2 colors specified for a gradient - ignoring remaining";
10000
10064
  function findHtmlStopColor(color, silent = false) {
10001
10065
  const { segs, error } = silent ? parseSegsSilent(color) : parseSegs(color);
10002
10066
  const first = segs[0];
@@ -10080,7 +10144,7 @@ function penTypeOf(style2) {
10080
10144
  return 3 /* Solid */;
10081
10145
  }
10082
10146
  function withHtmlPaint(paint, job, drawFn) {
10083
- paintObj.fillColor = paint.fill !== void 0 ? resolveRenderColor(firstColor(paint.fill)) : { type: "none" };
10147
+ paintObj.fillColor = paint.fill !== void 0 ? resolveFillColorName(firstColor(paint.fill)) : { type: "none" };
10084
10148
  paintObj.penColor = paint.pen !== void 0 ? resolveRenderColor(paint.pen) : { type: "string", s: "transparent" };
10085
10149
  applyHtmlFill(paint);
10086
10150
  paintObj.pen = penTypeOf(paint.penStyle);
@@ -10205,7 +10269,9 @@ function emitSidedPolylines(sides2, corners, renderer, job) {
10205
10269
  var HTML_DEFAULT_COLOR = "black";
10206
10270
  function bgNames(bgcolor) {
10207
10271
  const spec = parseGradientSpec(bgcolor);
10208
- return spec === null ? [bgcolor] : [spec[0], spec[1]];
10272
+ if (spec !== null) return [spec[0], spec[1]];
10273
+ if (parseSegsSilent(bgcolor).error !== 0 || firstColor(bgcolor) === "") return [];
10274
+ return [bgcolor];
10209
10275
  }
10210
10276
  function cellNames(cell2) {
10211
10277
  if (htmlStyle(cell2.style).invisible) return [];
@@ -10700,8 +10766,8 @@ function checkAttrs(tag, pairs) {
10700
10766
  return { attrs, warnings, warn };
10701
10767
  }
10702
10768
  var StderrLines = class {
10703
- constructor(writeLine) {
10704
- this.writeLine = writeLine;
10769
+ constructor(writeLine2) {
10770
+ this.writeLine = writeLine2;
10705
10771
  }
10706
10772
  writeLine;
10707
10773
  pending = "";
@@ -11055,6 +11121,15 @@ var NAME_CHAR = /[\w.:\u0080-
11055
11121
  var DEC_DIGIT = /[0-9]/;
11056
11122
  var HEX_DIGIT = /[0-9A-Fa-f]/;
11057
11123
  var NON_XML = /[\x00-\x08\x0b\x0c\x0e-\x1f]/;
11124
+ var NON_XML_BEYOND_ASCII = /[\ufffe\uffff]/;
11125
+ var HIGH_SURROGATE = /[\ud800-\udbff]/;
11126
+ var LOW_SURROGATE = /[\udc00-\udfff]/;
11127
+ function isNonXmlAt(text, k) {
11128
+ const c = text[k];
11129
+ if (NON_XML.test(c) || NON_XML_BEYOND_ASCII.test(c)) return true;
11130
+ if (HIGH_SURROGATE.test(c)) return !LOW_SURROGATE.test(text[k + 1] ?? "");
11131
+ return LOW_SURROGATE.test(c) && !HIGH_SURROGATE.test(text[k - 1] ?? "");
11132
+ }
11058
11133
  function scanDigits(text, i, digit) {
11059
11134
  if (i >= text.length) return { partial: true };
11060
11135
  if (!digit.test(text[i])) return { invalid: i };
@@ -11082,7 +11157,7 @@ function scanAttValue(text, j) {
11082
11157
  const c = text[k];
11083
11158
  if (c === void 0) return { partial: true };
11084
11159
  if (c === q) return { close: k };
11085
- if (c === "<" || NON_XML.test(c)) return { invalid: k };
11160
+ if (c === "<" || isNonXmlAt(text, k)) return { invalid: k };
11086
11161
  if (c !== "&") {
11087
11162
  k++;
11088
11163
  continue;
@@ -12380,6 +12455,26 @@ function imageIsSupplied(name, sizer, resolver) {
12380
12455
  function imageOpenWarning(name) {
12381
12456
  return `${STRERROR_ENOENT} while opening ${name}`;
12382
12457
  }
12458
+ var DEFAULT_DPI = 96;
12459
+ var POINTS_PER_INCH2 = 72;
12460
+ function usershapeDpi(attrs) {
12461
+ const lateDouble2 = (s, dflt) => {
12462
+ if (s === void 0 || s === "") return dflt;
12463
+ const v = Number(s);
12464
+ return Number.isNaN(v) || s.trim() === "" ? dflt : Math.max(v, 0);
12465
+ };
12466
+ const dpi = lateDouble2(attrs.get("dpi"), lateDouble2(attrs.get("resolution"), 0));
12467
+ return dpi >= 1 ? dpi : DEFAULT_DPI;
12468
+ }
12469
+ function usershapeSizePts(name, dpi, sizer) {
12470
+ if (name === void 0 || name === "") return null;
12471
+ const px = sizer !== void 0 ? sizer(name) : findImageSize(name);
12472
+ if (px === null) return null;
12473
+ return {
12474
+ x: Math.trunc(px.w * POINTS_PER_INCH2 / dpi),
12475
+ y: Math.trunc(px.h * POINTS_PER_INCH2 / dpi)
12476
+ };
12477
+ }
12383
12478
 
12384
12479
  // src/common/pointset.ts
12385
12480
  function cmpPair(a, b) {
@@ -17406,7 +17501,7 @@ function splitFamilies(fontname) {
17406
17501
  function aliasFamilies(a) {
17407
17502
  return a.svgFontFamily !== a.family ? [a.family, a.svgFontFamily] : [a.family];
17408
17503
  }
17409
- function styleToken(a, flags) {
17504
+ function styleToken2(a, flags) {
17410
17505
  if (a?.style != null) return a.style;
17411
17506
  return flags?.italic === true ? "italic" : null;
17412
17507
  }
@@ -17415,7 +17510,7 @@ function weightToken(a, flags) {
17415
17510
  return flags?.bold === true ? "bold" : null;
17416
17511
  }
17417
17512
  function variantTokens(a, flags) {
17418
- const tokens = [styleToken(a, flags), weightToken(a, flags), a?.stretch ?? null];
17513
+ const tokens = [styleToken2(a, flags), weightToken(a, flags), a?.stretch ?? null];
17419
17514
  return tokens.filter((t) => t !== null);
17420
17515
  }
17421
17516
  function canvasFont(fontname, fontsize, flags) {
@@ -17829,15 +17924,15 @@ var sizeTextContent = (texts, measurer, env = defaultSizeEnv()) => {
17829
17924
  return { w, h };
17830
17925
  };
17831
17926
  var missingImages = { set: /* @__PURE__ */ new WeakSet() };
17832
- var sizeHtmlImg = (img, { imageSizer, stderr }) => {
17927
+ var sizeHtmlImg = (img, { imageSizer, imageResolver, imageDpi, stderr }) => {
17833
17928
  if (img.width !== void 0 && img.height !== void 0) return missingImages.set.has(img) ? 1 : 0;
17834
- const sz = imageSizer !== void 0 ? imageSizer(img.src) : findImageSize(img.src);
17929
+ const sz = usershapeSizePts(img.src, imageDpi ?? DEFAULT_DPI, imageSizer);
17835
17930
  if (sz !== null) {
17836
- img.width = sz.w;
17837
- img.height = sz.h;
17931
+ img.width = sz.x;
17932
+ img.height = sz.y;
17838
17933
  return 0;
17839
17934
  }
17840
- if (!imageIsSupplied(img.src, imageSizer)) agerrLine(stderr, `Warning: ${imageOpenWarning(img.src)}`);
17935
+ if (!imageIsSupplied(img.src, imageSizer, imageResolver)) agerrLine(stderr, `Warning: ${imageOpenWarning(img.src)}`);
17841
17936
  agerrLine(stderr, `Error: No or improper image file="${img.src}"`);
17842
17937
  img.width = 0;
17843
17938
  img.height = 0;
@@ -18324,7 +18419,7 @@ function posHtmlLabel(label, finfo, measurer) {
18324
18419
  // src/common/htmltable-label.ts
18325
18420
  var HTML_PARSE_FATAL = 3;
18326
18421
  function makeHtmlLabelTo(content, finfo, measurer, stderr) {
18327
- const { fontname, fontsize, fontcolor, imageSizer, pencolor } = finfo;
18422
+ const { fontname, fontsize, fontcolor, imageSizer, imageResolver, imageDpi, pencolor } = finfo;
18328
18423
  let lbl, lexWarn;
18329
18424
  try {
18330
18425
  ({ label: lbl, warn: lexWarn } = parseHtmlLabelRv(content, stderr));
@@ -18338,6 +18433,8 @@ function makeHtmlLabelTo(content, finfo, measurer, stderr) {
18338
18433
  fontsize,
18339
18434
  fontname,
18340
18435
  imageSizer,
18436
+ imageResolver,
18437
+ imageDpi,
18341
18438
  stderr
18342
18439
  });
18343
18440
  const placed = posHtmlLabel(lbl, { fontname, fontsize, fontcolor }, measurer);
@@ -18544,9 +18641,12 @@ function makeLabel(text, fontname, fontsize, fontcolor, measurer) {
18544
18641
  }
18545
18642
  function makeAnyLabel(content, isHtml, font, measurer, obj) {
18546
18643
  if (isHtml && content !== "") {
18547
- const imageSizer = obj !== void 0 ? rootOf(obj).info.gvc?.imageSizer : void 0;
18644
+ const root = obj !== void 0 ? rootOf(obj) : void 0;
18645
+ const imageSizer = root?.info.gvc?.imageSizer;
18646
+ const imageResolver = root?.info.gvc?.imageResolver;
18647
+ const imageDpi = root !== void 0 ? usershapeDpi(root.attrs) : void 0;
18548
18648
  const stderr = labelStderr();
18549
- const { label, rv } = makeHtmlLabelTo(content, { ...font, pencolor: getPenColor(obj), imageSizer }, measurer, stderr);
18649
+ const { label, rv } = makeHtmlLabelTo(content, { ...font, pencolor: getPenColor(obj), imageSizer, imageResolver, imageDpi }, measurer, stderr);
18550
18650
  if (rv !== 0 && obj !== void 0) stderr.write(`${inLabelOf(obj)}
18551
18651
  `);
18552
18652
  stderr.flush();
@@ -18717,6 +18817,9 @@ function computeVertices(poly, w, h, base) {
18717
18817
  var SPLIT = 134217729;
18718
18818
  function fma(a, b, c) {
18719
18819
  const p = a * b;
18820
+ if (!Number.isFinite(p) || !Number.isFinite(c)) {
18821
+ return Number.isFinite(a) && Number.isFinite(b) && !Number.isFinite(c) ? c : p + c;
18822
+ }
18720
18823
  const at = SPLIT * a;
18721
18824
  const ahi = at - (at - a);
18722
18825
  const alo = a - ahi;
@@ -19017,7 +19120,8 @@ function polySize(p) {
19017
19120
  const init = initialSizePts(p);
19018
19121
  const dimen = quantize(padLabelDimen(p.labelDimen, p.margin, p.isPlain), p.quantumIn);
19019
19122
  const { sides: sides2, isBox: isBox4 } = effectiveShape(p);
19020
- let bb = { x: dimen.x, y: dimen.y };
19123
+ const img = p.imageSize ?? { x: 0, y: 0 };
19124
+ let bb = { x: Math.max(dimen.x, img.x), y: Math.max(dimen.y, img.y) };
19021
19125
  if (isBox4) {
19022
19126
  } else if (p.optionShape === STAR) {
19023
19127
  bb = starSize(bb);
@@ -19046,7 +19150,7 @@ function labelSpace(p, dimen, bb, minBb, isBox4, fixedshape) {
19046
19150
  } else {
19047
19151
  spaceX = dimen.x - spacex;
19048
19152
  }
19049
- const spaceY = fixedshape ? dimen.y : dimen.y + (bb.y - minBb.y);
19153
+ const spaceY = fixedshape ? dimen.y : dimen.y + (bb.y - minBb.y + Math.max(0, (p.imageSize?.y ?? 0) - dimen.y));
19050
19154
  return { space: { x: spaceX, y: spaceY }, valign: labelValign(p) };
19051
19155
  }
19052
19156
  function effectiveShape(p) {
@@ -25140,6 +25244,15 @@ function warnMissingImage(n, g, shapefile) {
25140
25244
  agwarningf(imageOpenWarning(image));
25141
25245
  agwarningf(`No or improper image="${image}" for node "${n.name}"`);
25142
25246
  }
25247
+ function nodeImageSize(n, g) {
25248
+ const shapefile = nodeAttr(n, g, "shapefile");
25249
+ if (shapefile !== void 0 && shapefile !== "") return void 0;
25250
+ const gvc = g.root.info.gvc;
25251
+ const sz = usershapeSizePts(nodeAttr(n, g, "image"), usershapeDpi(g.root.attrs), gvc?.imageSizer);
25252
+ if (sz === null) return void 0;
25253
+ g.root.info.has_images = true;
25254
+ return { x: sz.x + 2, y: sz.y + 2 };
25255
+ }
25143
25256
  function polyInit(n, g, measurer) {
25144
25257
  const shapeName2 = nodeAttr(n, g, "shape") ?? "ellipse";
25145
25258
  const shapefile = nodeAttr(n, g, "shapefile");
@@ -25499,11 +25612,7 @@ function applyClusterGradient(obj, fill) {
25499
25612
  obj.gradientAngle = fill.angle;
25500
25613
  }
25501
25614
  function clusterAttr(sg, key) {
25502
- for (let g = sg; g !== null; g = g.parent) {
25503
- const v = g.attrs.get(key);
25504
- if (v !== void 0) return v;
25505
- }
25506
- return void 0;
25615
+ return graphAttrInherited(sg, key);
25507
25616
  }
25508
25617
  function clusterStyle(sg) {
25509
25618
  return clusterAttr(sg, "style");
@@ -25538,12 +25647,10 @@ function applyClusterObjState(sg, job) {
25538
25647
  if (job.obj === null) return false;
25539
25648
  const obj = job.obj;
25540
25649
  gvrenderSetStyle(checkClusterStyleTokens(styleTokens(clusterStyle(sg))));
25541
- return withColorScheme(clusterAttr(sg, "colorscheme"), () => {
25542
- const filled = applyClusterFill(obj, fillRes);
25543
- applyClusterPenState(obj, sg);
25544
- reportColorNames(stripedClusterColors(sg));
25545
- return filled;
25546
- });
25650
+ const filled = applyClusterFill(obj, fillRes);
25651
+ applyClusterPenState(obj, sg);
25652
+ reportColorNames(stripedClusterColors(sg));
25653
+ return filled;
25547
25654
  }
25548
25655
  function isStripedCluster(sg) {
25549
25656
  const flags = parseStyleFlags(clusterStyle(sg));
@@ -25564,27 +25671,25 @@ function stripedClusterColors(sg) {
25564
25671
  return segs.flatMap((seg2) => seg2.color !== null && seg2.t > 0 ? [seg2.color] : []);
25565
25672
  }
25566
25673
  function renderStripedClusterBox(sg, renderer, job) {
25567
- withColorScheme(clusterAttr(sg, "colorscheme"), () => {
25568
- const { ll, ur } = sg.info.bb;
25569
- const af = [
25570
- { x: ll.x, y: ll.y },
25571
- { x: ur.x, y: ll.y },
25572
- { x: ur.x, y: ur.y },
25573
- { x: ll.x, y: ur.y }
25574
- ].map((p) => transformPoint(p, job));
25575
- const obj = job.obj;
25576
- const savedFill = obj?.fill;
25577
- if (obj !== null && savedFill !== void 0) obj.fill = 1 /* Solid */;
25578
- stripedBox(job, af, stripedFillSpec(sg), false, renderer, () => `in cluster ${sg.name}`);
25579
- if (obj !== null && savedFill !== void 0) obj.fill = savedFill;
25580
- const rawPts = [
25581
- { x: ll.x, y: ll.y },
25582
- { x: ll.x, y: ur.y },
25583
- { x: ur.x, y: ur.y },
25584
- { x: ur.x, y: ll.y }
25585
- ];
25586
- renderer.polygon(rawPts.map((p) => transformPoint(p, job)), false, job);
25587
- });
25674
+ const { ll, ur } = sg.info.bb;
25675
+ const af = [
25676
+ { x: ll.x, y: ll.y },
25677
+ { x: ur.x, y: ll.y },
25678
+ { x: ur.x, y: ur.y },
25679
+ { x: ll.x, y: ur.y }
25680
+ ].map((p) => transformPoint(p, job));
25681
+ const obj = job.obj;
25682
+ const savedFill = obj?.fill;
25683
+ if (obj !== null && savedFill !== void 0) obj.fill = 1 /* Solid */;
25684
+ stripedBox(job, af, stripedFillSpec(sg), false, renderer, () => `in cluster ${sg.name}`);
25685
+ if (obj !== null && savedFill !== void 0) obj.fill = savedFill;
25686
+ const rawPts = [
25687
+ { x: ll.x, y: ll.y },
25688
+ { x: ll.x, y: ur.y },
25689
+ { x: ur.x, y: ur.y },
25690
+ { x: ur.x, y: ll.y }
25691
+ ];
25692
+ renderer.polygon(rawPts.map((p) => transformPoint(p, job)), false, job);
25588
25693
  }
25589
25694
  function applyClusterFill(obj, fillRes) {
25590
25695
  if (fillRes.kind === "none") {
@@ -26325,7 +26430,24 @@ function removeFill(g) {
26325
26430
  }
26326
26431
  agdelsubg(g.root, sg);
26327
26432
  }
26433
+ function gvCleanupEdgeLabels(e) {
26434
+ e.info.label = void 0;
26435
+ e.info.xlabel = void 0;
26436
+ e.info.head_label = void 0;
26437
+ e.info.tail_label = void 0;
26438
+ }
26439
+ function gvCleanupNodeLabels(n) {
26440
+ n.info.label = void 0;
26441
+ n.info.xlabel = void 0;
26442
+ }
26443
+ function dotCleanupGraph(g) {
26444
+ for (const subg of g.subgraphs.values()) dotCleanupGraph(subg);
26445
+ if (g !== g.root) g.info.label = void 0;
26446
+ }
26328
26447
  function dotCleanup(g) {
26448
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
26449
+ for (const n2 of g.nodes.values()) gvCleanupNodeLabels(n2);
26450
+ dotCleanupGraph(g);
26329
26451
  let n = g.info.nlist;
26330
26452
  while (n !== void 0) {
26331
26453
  const next = n.info.next;
@@ -26803,7 +26925,7 @@ var DEFAULT_NODEWIDTH = 0.75;
26803
26925
  var MIN_NODEWIDTH = 0.01;
26804
26926
  var DEFAULT_NODEHEIGHT = 0.5;
26805
26927
  var MIN_NODEHEIGHT = 0.02;
26806
- var POINTS_PER_INCH2 = 72;
26928
+ var POINTS_PER_INCH3 = 72;
26807
26929
  var DEF_POINT = 0.05;
26808
26930
  var MIN_POINT = 3e-4;
26809
26931
  var DEFAULT_NODEPENWIDTH2 = 1;
@@ -26871,6 +26993,8 @@ function polySizeParamsFromNode(n, g, shape, labelDimen, flip) {
26871
26993
  // size_gen discriminant (STAR/CYLINDER)
26872
26994
  nojustify: mapbool4(nodeAttr(n, g, "nojustify")),
26873
26995
  // shapes.c:2133
26996
+ imageSize: nodeImageSize(n, g),
26997
+ // shapes.c:2039-2051
26874
26998
  flip
26875
26999
  };
26876
27000
  }
@@ -26907,7 +27031,7 @@ function initPointSize(n, g, shape) {
26907
27031
  const flip = g.root.info.flip === true;
26908
27032
  const peripheries = lateInt(nodeAttr(n, g, "peripheries"), shape.polygon.peripheries, 0);
26909
27033
  const penwidth = lateDouble(nodeAttr(n, g, "penwidth"), DEFAULT_NODEPENWIDTH2, MIN_NODEPENWIDTH);
26910
- const sz0 = pointWidthInches(n, g) * POINTS_PER_INCH2;
27034
+ const sz0 = pointWidthInches(n, g) * POINTS_PER_INCH3;
26911
27035
  storeNodeSize(n, pointSizeResult(sz0, peripheries, penwidth), flip);
26912
27036
  assignShapeInfo(n, { ...shape.polygon, peripheries, sides: 2, penwidth, vertices: null });
26913
27037
  }
@@ -26964,8 +27088,8 @@ function storeNodeSize(n, unflipped, flip) {
26964
27088
  n.info.base_width = unflipped.baseW / 72;
26965
27089
  n.info.base_height = unflipped.baseH / 72;
26966
27090
  const size = gvNodesize(
26967
- n.info.width * POINTS_PER_INCH2,
26968
- n.info.height * POINTS_PER_INCH2,
27091
+ n.info.width * POINTS_PER_INCH3,
27092
+ n.info.height * POINTS_PER_INCH3,
26969
27093
  flip
26970
27094
  );
26971
27095
  n.info.lw = size.lw;
@@ -28547,10 +28671,13 @@ function parseLayers(g) {
28547
28671
  let listSep = g.attrs.get("layerlistsep") || DEFAULT_LAYERLISTSEP;
28548
28672
  if ([...sep].some((c) => listSep.includes(c))) listSep = "";
28549
28673
  if (p === void 0 || p === "") {
28550
- return { layerIDs: [], numLayers: 1, sep, listSep };
28674
+ return { layerIDs: [], numLayers: 1, sep, listSep, layerList: null };
28551
28675
  }
28552
28676
  const toks = splitOnSet(p, sep);
28553
- return { layerIDs: [null, ...toks], numLayers: toks.length, sep, listSep };
28677
+ const info = { layerIDs: [null, ...toks], numLayers: toks.length, sep, listSep, layerList: null };
28678
+ const sel = g.attrs.get("layerselect");
28679
+ if (sel !== void 0 && sel !== "") info.layerList = parseLayerselect(info, sel);
28680
+ return info;
28554
28681
  }
28555
28682
  function isNaturalNumber(s) {
28556
28683
  return /^[0-9]+$/.test(s);
@@ -28606,6 +28733,19 @@ function edgeInLayer(info, layerNum, e) {
28606
28733
  return pn === "" || selectedLayer(info, layerNum, pn);
28607
28734
  });
28608
28735
  }
28736
+ function parseLayerselect(info, p) {
28737
+ const picked = [];
28738
+ for (let i = 1; i <= info.numLayers; i++) {
28739
+ if (selectedLayer(info, i, p)) picked.push(i);
28740
+ }
28741
+ if (picked.length === 0) {
28742
+ agwarningf(
28743
+ `The layerselect attribute "${p}" does not match any layer specifed by the layers attribute - ignored.`
28744
+ );
28745
+ return null;
28746
+ }
28747
+ return [picked.length, ...picked, info.numLayers + 1];
28748
+ }
28609
28749
 
28610
28750
  // src/gvc/emit-walk.ts
28611
28751
  function nodeShown(info, job, n, g) {
@@ -28668,9 +28808,40 @@ var NATIVE_LANGNAME = /* @__PURE__ */ new Map([
28668
28808
  ["cmapx-np", "cmapx_np"],
28669
28809
  ["imap-np", "imap_np"]
28670
28810
  ]);
28671
- function warnLayersUnsupported(format, numLayers, doesLayers) {
28672
- if (numLayers <= 1 || doesLayers) return;
28673
- agwarningf(`layers not supported in ${NATIVE_LANGNAME.get(format) ?? format} output`);
28811
+ function warnUnsupported(job) {
28812
+ agwarningf(`layers not supported in ${NATIVE_LANGNAME.get(job.format) ?? job.format} output`);
28813
+ }
28814
+ function numPhysicalLayers(job, info) {
28815
+ return info.layerList !== null ? info.layerList[0] : job.numLayers;
28816
+ }
28817
+ function firstLayer(job, info, doesLayers) {
28818
+ job.numLayers = info.numLayers;
28819
+ const list = info.layerList;
28820
+ if (list !== null) {
28821
+ if (list[0] > 1 && !doesLayers) {
28822
+ warnUnsupported(job);
28823
+ list[2] = job.numLayers + 1;
28824
+ }
28825
+ job.layerNum = list[1];
28826
+ return { list, pos: 2 };
28827
+ }
28828
+ if (job.numLayers > 1 && !doesLayers) {
28829
+ warnUnsupported(job);
28830
+ job.numLayers = 1;
28831
+ }
28832
+ job.layerNum = 1;
28833
+ return { list: null, pos: 0 };
28834
+ }
28835
+ function validLayer(job) {
28836
+ return job.layerNum <= job.numLayers;
28837
+ }
28838
+ function nextLayer(job, cur) {
28839
+ if (cur.list !== null) {
28840
+ job.layerNum = cur.list[cur.pos];
28841
+ cur.pos++;
28842
+ } else {
28843
+ job.layerNum++;
28844
+ }
28674
28845
  }
28675
28846
 
28676
28847
  // src/gvc/device-labels.ts
@@ -28804,7 +28975,7 @@ function renderNode(n, renderer, job, done) {
28804
28975
  job.popObj();
28805
28976
  }
28806
28977
  }
28807
- function setEdgePen(e, job) {
28978
+ function setEdgePen(e, job, styles) {
28808
28979
  if (job.obj === null) return;
28809
28980
  const obj = job.obj;
28810
28981
  const flags = parseStyleFlags(e.attrs.get("style"));
@@ -28814,24 +28985,24 @@ function setEdgePen(e, job) {
28814
28985
  );
28815
28986
  obj.pen = resolvePenType(flags);
28816
28987
  obj.penWidth = resolvePenWidth(flags, e.attrs.get("penwidth"));
28817
- obj.rawStyle = styleTokens(e.attrs.get("style"));
28988
+ obj.rawStyle = [...styles];
28818
28989
  if (e.info.spl !== void 0) gvrenderSetStyle(obj.rawStyle);
28819
28990
  }
28820
28991
  function renderEdge(e, renderer, job) {
28821
28992
  emitEdgeComments(e, renderer, job);
28822
28993
  const edgeStyle = e.attrs.get("style");
28994
+ const styles = styleTokens(edgeStyle);
28823
28995
  if (parseStyleFlags(edgeStyle).invis || styleHasInvisibleAlias(edgeStyle)) return;
28824
28996
  const obj = createObjState(3 /* Edge */);
28825
28997
  obj.emitState = 9 /* EDraw */;
28826
28998
  job.pushObj(obj);
28827
- setEdgePen(e, job);
28999
+ setEdgePen(e, job, styles);
28828
29000
  try {
28829
29001
  setHtmlAnchorObj(svgEdgeId(e, job), labelTextOf2(e.info.label), job.obj ?? void 0);
28830
29002
  resolveEdgeAnchor(e, svgEdgeId(e, job), obj);
28831
29003
  withColorScheme(e.attrs.get("colorscheme"), () => {
28832
29004
  renderer.beginEdge(e, job);
28833
29005
  reportEdgeColors(e);
28834
- const styles = styleTokens(e.attrs.get("style"));
28835
29006
  for (let i = edgeStyleResets(e, styles); i > 0; i--) gvrenderSetStyle(styles);
28836
29007
  reportEdgeLabelColors(e);
28837
29008
  renderer.endEdge(e, job);
@@ -28858,6 +29029,22 @@ function renderClusterBox(sg, filled, renderer, job) {
28858
29029
  const rawPts = [{ x: ll.x, y: ll.y }, { x: ll.x, y: ur.y }, { x: ur.x, y: ur.y }, { x: ur.x, y: ll.y }];
28859
29030
  renderer.polygon(rawPts.map((p) => transformPoint(p, job)), filled, job);
28860
29031
  }
29032
+ function drawClusterInScheme(sg, renderer, job) {
29033
+ const filled = applyClusterObjState(sg, job);
29034
+ renderer.beginCluster?.(sg, job);
29035
+ if (job.obj !== null) job.obj.id = svgClusterId(sg, job);
29036
+ setHtmlAnchorObj(svgClusterId(sg, job), labelTextOf2(sg.info.label), job.obj ?? void 0);
29037
+ if (job.obj !== null) {
29038
+ resolveObjAnchor(sg, labelTextOf2(sg.info.label), svgClusterId(sg, job), job.obj);
29039
+ }
29040
+ const anchored = beginAnchorIf(renderer, job);
29041
+ if ((clusterPeripheries(sg) !== 0 || filled || isStripedCluster(sg)) && job.obj?.pen !== 0 /* None */) {
29042
+ renderClusterBox(sg, filled, renderer, job);
29043
+ }
29044
+ renderClusterLabel(sg, renderer, job);
29045
+ if (anchored) renderer.endAnchor?.(job);
29046
+ renderer.endCluster?.(sg, job);
29047
+ }
28861
29048
  function renderOneCluster(sg, renderer, job) {
28862
29049
  const clustersLast = (job.flags & EMIT_CLUSTERS_LAST) !== 0;
28863
29050
  if (clustersLast) renderClusters(sg, renderer, job);
@@ -28865,20 +29052,7 @@ function renderOneCluster(sg, renderer, job) {
28865
29052
  obj.emitState = 1 /* CDraw */;
28866
29053
  job.pushObj(obj);
28867
29054
  try {
28868
- const filled = applyClusterObjState(sg, job);
28869
- renderer.beginCluster?.(sg, job);
28870
- if (job.obj !== null) job.obj.id = svgClusterId(sg, job);
28871
- setHtmlAnchorObj(svgClusterId(sg, job), labelTextOf2(sg.info.label), job.obj ?? void 0);
28872
- if (job.obj !== null) {
28873
- resolveObjAnchor(sg, labelTextOf2(sg.info.label), svgClusterId(sg, job), job.obj);
28874
- }
28875
- const anchored = beginAnchorIf(renderer, job);
28876
- if ((clusterPeripheries(sg) !== 0 || filled || isStripedCluster(sg)) && job.obj?.pen !== 0 /* None */) {
28877
- renderClusterBox(sg, filled, renderer, job);
28878
- }
28879
- renderClusterLabel(sg, renderer, job);
28880
- if (anchored) renderer.endAnchor?.(job);
28881
- renderer.endCluster?.(sg, job);
29055
+ withColorScheme(clusterAttr(sg, "colorscheme"), () => drawClusterInScheme(sg, renderer, job));
28882
29056
  } finally {
28883
29057
  job.popObj();
28884
29058
  }
@@ -28899,16 +29073,15 @@ function renderGraph(g, job, renderer) {
28899
29073
  job.pushObj(obj);
28900
29074
  try {
28901
29075
  const info = parseLayers(g);
28902
- const layered = renderer.beginLayer !== void 0 && info.numLayers > 1;
28903
- job.numLayers = layered ? info.numLayers : 1;
29076
+ job.layerNum = 0;
28904
29077
  job.layerIDs = info.layerIDs;
28905
29078
  renderer.beginGraph(g, job);
28906
- warnLayersUnsupported(job.format, info.numLayers, renderer.beginLayer !== void 0);
28907
- for (let ln = 1; ln <= job.numLayers; ln++) {
28908
- job.layerNum = ln;
28909
- if (layered) renderer.beginLayer(info.layerIDs[ln], job);
29079
+ const cur = firstLayer(job, info, renderer.beginLayer !== void 0);
29080
+ for (; validLayer(job); nextLayer(job, cur)) {
29081
+ const layered = numPhysicalLayers(job, info) > 1;
29082
+ if (layered) renderer.beginLayer?.(info.layerIDs[job.layerNum], job);
28910
29083
  renderPage(g, renderer, job, info);
28911
- if (layered) renderer.endLayer(job);
29084
+ if (layered) renderer.endLayer?.(job);
28912
29085
  }
28913
29086
  renderer.endGraph(g, job);
28914
29087
  } finally {
@@ -35377,6 +35550,20 @@ function addXLabels(gp) {
35377
35550
  runPlacement(gp);
35378
35551
  }
35379
35552
 
35553
+ // src/common/layout-state.ts
35554
+ var GVBEGIN = 0;
35555
+ var GVSPLINES = 1;
35556
+ var layoutState = { state: GVBEGIN };
35557
+ registerRenderState(() => {
35558
+ layoutState.state = GVBEGIN;
35559
+ });
35560
+ function getState() {
35561
+ return layoutState.state;
35562
+ }
35563
+ function setState(value) {
35564
+ layoutState.state = value;
35565
+ }
35566
+
35380
35567
  // src/common/postproc.ts
35381
35568
  var IGNORED_EDGE = 6;
35382
35569
  var Rankdir = 0;
@@ -35468,6 +35655,7 @@ function translateDrawing(g) {
35468
35655
  if (!shift && !Rankdir) return;
35469
35656
  for (const v of g.nodes.values()) {
35470
35657
  mapNode(v);
35658
+ if (getState() !== GVSPLINES) continue;
35471
35659
  for (const e of g.edges) {
35472
35660
  if (e.tail !== v) continue;
35473
35661
  if (e.info.spl === void 0) {
@@ -39457,6 +39645,7 @@ function orthoDispatch(g) {
39457
39645
  } else rc = dispatchOrthoEdges(g, false);
39458
39646
  if (rc !== 0) return rc;
39459
39647
  placePortLabels(g);
39648
+ setState(GVSPLINES);
39460
39649
  g.info.edgeLabelsDone = true;
39461
39650
  return 0;
39462
39651
  }
@@ -39471,6 +39660,7 @@ function finalizeSplines(g, et, normalize) {
39471
39660
  if (normalize) edgeNormalize(g);
39472
39661
  if (et !== EDGETYPE_CURVED) routeDotEdges(g);
39473
39662
  placePortLabels(g);
39663
+ setState(GVSPLINES);
39474
39664
  g.info.edgeLabelsDone = true;
39475
39665
  }
39476
39666
  function dotSplines_(g, normalize) {
@@ -41170,10 +41360,6 @@ function gvPermutation(bound) {
41170
41360
 
41171
41361
  // src/layout/neato/matrix-ops.ts
41172
41362
  var fr = Math.fround;
41173
- function fma2(a, b, c) {
41174
- const p = a * b;
41175
- return Number.isFinite(p) && Number.isFinite(c) ? fma(a, b, c) : p + c;
41176
- }
41177
41363
  function orthog1(n, vec) {
41178
41364
  let sum = 0;
41179
41365
  for (let i = 0; i < n; i++) sum += vec[i];
@@ -41202,10 +41388,6 @@ function rightMultWithVectorFF(m, n, vector, result) {
41202
41388
  function vectorsSubtractionF(n, v1, v2, result) {
41203
41389
  for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
41204
41390
  }
41205
- function vectorsMultAdditionF(n, v1, alpha, v2) {
41206
- const a = fr(alpha);
41207
- for (let i = 0; i < n; i++) v1[i] = v1[i] + fr(a * v2[i]);
41208
- }
41209
41391
  function vectorsInnerProductF(n, v1, v2) {
41210
41392
  let result = 0;
41211
41393
  for (let i = 0; i < n; i++) result += fr(v1[i] * v2[i]);
@@ -41246,11 +41428,11 @@ function innerProduct(n, v1, v2, block) {
41246
41428
  const blocked = block === BLOCK_NONE ? 0 : n - n % block;
41247
41429
  let i = 0;
41248
41430
  for (; i < blocked; i++) result += v1[i] * v2[i];
41249
- for (; i < n; i++) result = fma2(v1[i], v2[i], result);
41431
+ for (; i < n; i++) result = fma(v1[i], v2[i], result);
41250
41432
  return result;
41251
41433
  }
41252
41434
  function scadd(vec1, end, fac, vec2) {
41253
- for (let i = 0; i <= end; i++) vec1[i] = fma2(fac, vec2[i], vec1[i]);
41435
+ for (let i = 0; i <= end; i++) vec1[i] = fma(fac, vec2[i], vec1[i]);
41254
41436
  }
41255
41437
  function norm(vec, end, block) {
41256
41438
  return Math.sqrt(innerProduct(end + 1, vec, vec, block));
@@ -41282,7 +41464,7 @@ function rightMultWithVectorF(matrix, n, vector, result, block) {
41282
41464
  let res = 0;
41283
41465
  let j = 0;
41284
41466
  for (; j < blocked; j++) res += row[j] * vector[j];
41285
- for (; j < n; j++) res = fma2(row[j], vector[j], res);
41467
+ for (; j < n; j++) res = fma(row[j], vector[j], res);
41286
41468
  result[i] = res;
41287
41469
  }
41288
41470
  }
@@ -41290,7 +41472,7 @@ function rightMultWithVector(matrix, n, vector, result) {
41290
41472
  for (let i = 0; i < n; i++) {
41291
41473
  let res = 0;
41292
41474
  const row = matrix[i];
41293
- for (let j = 0; j < row.nedges; j++) res = fma2(row.ewgts[j], vector[row.edges[j]], res);
41475
+ for (let j = 0; j < row.nedges; j++) res = fma(row.ewgts[j], vector[row.edges[j]], res);
41294
41476
  result[i] = res;
41295
41477
  }
41296
41478
  }
@@ -41408,6 +41590,16 @@ function conjugateGradientF(A3, x, b, n, opts) {
41408
41590
  var TOLERANCE_CG = 1e-3;
41409
41591
  var DFLT_ITERATIONS = 200;
41410
41592
  var OPT_SMART_INIT = 4;
41593
+ var OPT_EXP_FLAG = 3;
41594
+ var EXP_NAME = "stresswt";
41595
+ function checkExp(g) {
41596
+ const exp = lateInt(g.attrs.get(EXP_NAME), 2, 0);
41597
+ if (exp === 0 || exp > 2) {
41598
+ agwarningf(`${EXP_NAME} attribute value must be 1 or 2 - ignoring`);
41599
+ return 2;
41600
+ }
41601
+ return exp;
41602
+ }
41411
41603
  function mdsModel(graph, nG) {
41412
41604
  if (graph[0].ewgts.length === 0) return null;
41413
41605
  const Dij = computeWeightedApspPacked(graph, nG);
@@ -41507,19 +41699,40 @@ function dijkstraSgd(graph, source, terms) {
41507
41699
 
41508
41700
  // src/layout/neato/edge-len.ts
41509
41701
  var DEFAULT_EDGE_LEN = 1;
41702
+ var DOUBLE_PREFIX = /^\s*([+-]?)(0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?|inf(?:inity)?|nan(?:\([\w]*\))?)/i;
41703
+ function scanDouble(s) {
41704
+ const m = DOUBLE_PREFIX.exec(s);
41705
+ if (m === null) return null;
41706
+ const body = m[2].toLowerCase();
41707
+ const sign2 = m[1] === "-" ? -1 : 1;
41708
+ if (body.startsWith("nan")) return Number.NaN;
41709
+ if (body.startsWith("inf")) return sign2 * Infinity;
41710
+ if (!body.startsWith("0x")) return sign2 * parseFloat(body);
41711
+ const [mant, exp] = body.slice(2).split("p");
41712
+ const [ip = "", fp = ""] = mant.split(".");
41713
+ const digits = parseInt(ip + fp || "0", 16);
41714
+ return sign2 * digits * 2 ** (Number(exp ?? 0) - 4 * fp.length);
41715
+ }
41510
41716
  function lenattr(ep, g) {
41511
41717
  const s = ep.attrs.get("len");
41512
41718
  if (s === void 0 || s === "") return DEFAULT_EDGE_LEN;
41513
- const val2 = /^\s*[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/.exec(s);
41514
- const len = val2 === null ? Number.NaN : parseFloat(val2[0]);
41515
- if (Number.isNaN(len) || len < 0 || len === 0) {
41516
- agwarningf(`bad edge len "${s}" in ${g.name} - setting to ${DEFAULT_EDGE_LEN.toFixed(2)}`);
41719
+ const len = scanDouble(s);
41720
+ if (len === null || len < 0 || len === 0) {
41721
+ agwarningf(`bad edge len "${s}" in ${agNameOf(g)} - setting to ${DEFAULT_EDGE_LEN.toFixed(2)}`);
41517
41722
  return DEFAULT_EDGE_LEN;
41518
41723
  }
41519
41724
  return len;
41520
41725
  }
41521
41726
  function setEdgeLen(g) {
41522
- for (const ep of g.edges) ep.info.dist = lenattr(ep, g);
41727
+ const out = buildOutEdgeIndex(g);
41728
+ let total = 0;
41729
+ for (const np of g.nodes.values()) {
41730
+ for (const ep of out.get(np) ?? []) {
41731
+ ep.info.dist = lenattr(ep, g);
41732
+ total += ep.info.dist;
41733
+ }
41734
+ }
41735
+ return total;
41523
41736
  }
41524
41737
 
41525
41738
  // src/util/mt19937.ts
@@ -41677,7 +41890,7 @@ function neatoMode(g) {
41677
41890
  if (str === void 0 || str === "") return MODE_MAJOR;
41678
41891
  const mode = modeByName().get(str);
41679
41892
  if (mode !== void 0) return mode;
41680
- agwarningf(`Illegal value ${str} for attribute "mode" in graph ${g.root.name} - ignored`);
41893
+ agwarningf(`Illegal value ${str} for attribute "mode" in graph ${agNameOf(g.root)} - ignored`);
41681
41894
  return MODE_MAJOR;
41682
41895
  }
41683
41896
  function checkMode(g, mode) {
@@ -41722,7 +41935,7 @@ function warnCircuitDisconnected(g) {
41722
41935
  circuitWarned.add(g.root);
41723
41936
  agerrLineOn(
41724
41937
  "warn",
41725
- `graph ${g.root.name} is disconnected. Hence, the circuit model
41938
+ `graph ${agNameOf(g.root)} is disconnected. Hence, the circuit model
41726
41939
  is undefined. Reverting to the shortest path model.
41727
41940
  Alternatively, consider running neato using -Gpack=true or decomposing
41728
41941
  the graph into connected components.`
@@ -42333,7 +42546,7 @@ function moveNode(st, m) {
42333
42546
  function solveModel(g, st) {
42334
42547
  for (let m = chooseNode(st); m >= 0; m = chooseNode(st)) moveNode(st, m);
42335
42548
  if (st.move === st.maxIter) {
42336
- agwarningf(`Max. iterations (${st.maxIter}) reached on graph ${g.name}`);
42549
+ agwarningf(`Max. iterations (${st.maxIter}) reached on graph ${agNameOf(g)}`);
42337
42550
  }
42338
42551
  }
42339
42552
  function mdsEdges(g, nodes, lens) {
@@ -42416,7 +42629,7 @@ function addNeighbours(g, np, entry, o) {
42416
42629
  if (ep.head === ep.tail) continue;
42417
42630
  const vp = ep.tail === np ? ep.head : ep.tail;
42418
42631
  const vid = vp.info.id;
42419
- const dist5 = o.haveLen ? lateDouble(ep.attrs.get("len"), 1, 0) : 1;
42632
+ const dist5 = o.haveLen ? ep.info.dist ?? 0 : 1;
42420
42633
  const idx = seen2.get(vid);
42421
42634
  if (idx !== void 0) {
42422
42635
  if (o.haveLen) entry.ewgts[idx] = Math.max(entry.ewgts[idx], dist5);
@@ -42958,7 +43171,7 @@ function matMultVecOrthog(mat, dim, vec, result, orthog) {
42958
43171
  let sum = 0;
42959
43172
  let j = 0;
42960
43173
  for (; j < blocked; j++) sum += row[j] * vec[j];
42961
- for (; j < dim; j++) sum = fma2(row[j], vec[j], sum);
43174
+ for (; j < dim; j++) sum = fma(row[j], vec[j], sum);
42962
43175
  result[i] = sum;
42963
43176
  }
42964
43177
  const alpha = -innerProduct(dim, result, orthog, BLOCK_MAT_MULT_ORTHOG);
@@ -43057,8 +43270,8 @@ function computeAvgs(Dij, n) {
43057
43270
  sumRow += row[j] * row[j];
43058
43271
  }
43059
43272
  for (; j < n; j++) {
43060
- sum = fma2(row[j], row[j], sum);
43061
- sumRow = fma2(row[j], row[j], sumRow);
43273
+ sum = fma(row[j], row[j], sum);
43274
+ sumRow = fma(row[j], row[j], sumRow);
43062
43275
  }
43063
43276
  rowAvg[i] = fr4(fr4(sumRow) / n);
43064
43277
  }
@@ -43071,7 +43284,7 @@ function computeBij(Dij, n) {
43071
43284
  for (let i = 0; i < n; i++) {
43072
43285
  for (let j = 0; j <= i; j++) {
43073
43286
  const fD = fr4(Dij[i][j]);
43074
- const t = fr4(fma2(-fD, fD, rowAvg[i]));
43287
+ const t = fr4(fma(-fD, fD, rowAvg[i]));
43075
43288
  Bij[i][j] = fr4(fr4(t + rowAvg[j]) - allAvg);
43076
43289
  Bij[j][i] = Bij[i][j];
43077
43290
  }
@@ -43103,8 +43316,8 @@ function scaleGivenCoords(Dij, n, x) {
43103
43316
  sum1 += t1 * f;
43104
43317
  sum2 += t2 * f;
43105
43318
  } else {
43106
- sum1 = fma2(t1, f, sum1);
43107
- sum2 = fma2(t2, f, sum2);
43319
+ sum1 = fma(t1, f, sum1);
43320
+ sum2 = fma(t2, f, sum2);
43108
43321
  }
43109
43322
  }
43110
43323
  }
@@ -43134,7 +43347,7 @@ function computeResidualDistances(Dij, n, x) {
43134
43347
  for (let j = 0; j < i; j++) {
43135
43348
  const t = posI - x[j];
43136
43349
  const d = Dij[i][j];
43137
- const diff = fma2(d, d, -(t * t));
43350
+ const diff = fma(d, d, -(t * t));
43138
43351
  const v = diff > 0 ? Math.sqrt(diff) : 0;
43139
43352
  Dij[i][j] = v;
43140
43353
  Dij[j][i] = v;
@@ -43191,8 +43404,6 @@ function imdsGivenDim(graph, n, givenCoords, newCoords, conjTol) {
43191
43404
 
43192
43405
  // src/layout/neato/stress-kernel.ts
43193
43406
  var fr5 = Math.fround;
43194
- var TOLERANCE_CG2 = 1e-3;
43195
- var OPT_EXP_FLAG = 2;
43196
43407
  function computeApspPacked2(graph, n) {
43197
43408
  const Dij = new Float32Array(n * (n + 1) / 2);
43198
43409
  const Di = new Int32Array(n);
@@ -43236,51 +43447,16 @@ function initLayout(n, dim, coords, nodes) {
43236
43447
  for (let d = 0; d < dim; d++) orthog1(n, coords[d]);
43237
43448
  return pinned;
43238
43449
  }
43239
- function cgStep(st, last) {
43240
- const { n } = st;
43241
- orthog1f(n, st.p);
43242
- orthog1f(n, st.x);
43243
- orthog1f(n, st.r);
43244
- rightMultWithVectorFF(st.A, n, st.p, st.Ap);
43245
- orthog1f(n, st.Ap);
43246
- const pAp = vectorsInnerProductF(n, st.p, st.Ap);
43247
- if (pAp === 0) return true;
43248
- const alpha = st.rR / pAp;
43249
- vectorsMultAdditionF(n, st.x, alpha, st.p);
43250
- if (!last) {
43251
- vectorsMultAdditionF(n, st.r, -alpha, st.Ap);
43252
- const rRNew = vectorsInnerProductF(n, st.r, st.r);
43253
- if (st.rR === 0) return false;
43254
- const betaF = fr5(rRNew / st.rR);
43255
- st.rR = rRNew;
43256
- for (let j = 0; j < n; j++) st.p[j] = fr5(betaF * st.p[j]) + st.r[j];
43257
- }
43258
- return true;
43259
- }
43260
- function conjugateGradientMkernel2(A3, x, b, n, tol, maxIterations) {
43261
- const st = {
43262
- A: A3,
43263
- x,
43264
- b,
43265
- n,
43266
- r: new Float32Array(n),
43267
- p: new Float32Array(n),
43268
- Ap: new Float32Array(n),
43269
- rR: 0
43270
- };
43271
- orthog1f(n, x);
43272
- orthog1f(n, b);
43273
- const Ax = new Float32Array(n);
43274
- rightMultWithVectorFF(A3, n, x, Ax);
43275
- orthog1f(n, Ax);
43276
- vectorsSubtractionF(n, b, Ax, st.r);
43277
- copyVectorF(n, st.r, st.p);
43278
- st.rR = vectorsInnerProductF(n, st.r, st.r);
43279
- for (let i = 0; i < maxIterations && maxAbsF(n, st.r) > tol; i++) {
43280
- if (!cgStep(st, i >= maxIterations - 1)) return -1;
43281
- }
43282
- return 0;
43283
- }
43450
+ var FUSED_OPS = {
43451
+ squareAdd: (tmp, acc) => fmaf(tmp, tmp, acc),
43452
+ rightMult: rightMultWithVectorFFFused,
43453
+ cg: conjugateGradientMkernelFused
43454
+ };
43455
+ var COLA_OPS = {
43456
+ squareAdd: (tmp, acc) => acc + fr5(tmp * tmp),
43457
+ rightMult: rightMultWithVectorFF,
43458
+ cg: conjugateGradientMkernelFused
43459
+ };
43284
43460
  function buildLap2(lap2, n, exp) {
43285
43461
  const lapLength = n * (n + 1) / 2;
43286
43462
  if (exp === 2) squareVec(lapLength, lap2);
@@ -43303,7 +43479,7 @@ function buildLap2(lap2, n, exp) {
43303
43479
  }
43304
43480
  }
43305
43481
  function buildLap1(lap1, lap2, coords, shape) {
43306
- const { n, dim, exp } = shape;
43482
+ const { n, dim, exp, ops } = shape;
43307
43483
  const lapLength = n * (n + 1) / 2;
43308
43484
  const degrees = new Float64Array(n);
43309
43485
  const distAccumulator = new Float32Array(n);
@@ -43316,7 +43492,7 @@ function buildLap1(lap1, lap2, coords, shape) {
43316
43492
  const ck = coords[k];
43317
43493
  for (let x = 0; x < len; x++) {
43318
43494
  const tmp = fr5(ck[i] + fr5(-1 * ck[i + 1 + x]));
43319
- distAccumulator[x] = distAccumulator[x] + fr5(tmp * tmp);
43495
+ distAccumulator[x] = ops.squareAdd(tmp, distAccumulator[x]);
43320
43496
  }
43321
43497
  }
43322
43498
  invertSqrtVec(len, distAccumulator);
@@ -43349,24 +43525,25 @@ function buildLap1(lap1, lap2, coords, shape) {
43349
43525
  function computeStress(st) {
43350
43526
  let stress = 0;
43351
43527
  for (let k = 0; k < st.dim; k++) {
43352
- rightMultWithVectorFF(st.lap1, st.n, st.coords[k], st.b[k]);
43528
+ st.ops.rightMult(st.lap1, st.n, st.coords[k], st.b[k]);
43353
43529
  stress += vectorsInnerProductF(st.n, st.coords[k], st.b[k]);
43354
43530
  }
43355
43531
  stress *= 2;
43356
43532
  stress += st.constantTerm;
43357
43533
  for (let k = 0; k < st.dim; k++) {
43358
- rightMultWithVectorFF(st.lap2, st.n, st.coords[k], st.tmpCoords);
43534
+ st.ops.rightMult(st.lap2, st.n, st.coords[k], st.tmpCoords);
43359
43535
  stress -= vectorsInnerProductF(st.n, st.coords[k], st.tmpCoords);
43360
43536
  }
43361
43537
  return stress;
43362
43538
  }
43363
43539
  function solveAxis(st, k, havePinned, nodes) {
43540
+ const cg = { tol: TOLERANCE_CG, maxIterations: st.n };
43364
43541
  if (!havePinned) {
43365
- return conjugateGradientMkernel2(st.lap2, st.coords[k], st.b[k], st.n, TOLERANCE_CG2, st.n);
43542
+ return st.ops.cg(st.lap2, st.coords[k], st.b[k], st.n, cg);
43366
43543
  }
43367
43544
  copyVectorF(st.n, st.coords[k], st.tmpCoords);
43368
- const rc = conjugateGradientMkernel2(st.lap2, st.tmpCoords, st.b[k], st.n, TOLERANCE_CG2, st.n);
43369
- if (rc < 0) return rc;
43545
+ const rc = st.ops.cg(st.lap2, st.tmpCoords, st.b[k], st.n, cg);
43546
+ if (rc !== 0) return rc;
43370
43547
  for (let i = 0; i < st.n; i++) {
43371
43548
  if (!isFixed(nodes[i])) st.coords[k][i] = st.tmpCoords[i];
43372
43549
  }
@@ -43397,20 +43574,21 @@ function stressMajorizationKDMkernel(Dij, n, dCoords, nodes, o) {
43397
43574
  coords,
43398
43575
  b: Array.from({ length: dim }, () => new Float32Array(n)),
43399
43576
  tmpCoords: new Float32Array(n),
43400
- constantTerm
43577
+ constantTerm,
43578
+ ops: o.cola === true ? COLA_OPS : FUSED_OPS
43401
43579
  };
43402
43580
  let oldStress = Number.MAX_VALUE;
43403
43581
  let converged = false;
43404
43582
  let iterations = 0;
43405
43583
  for (; iterations < maxi && !converged; iterations++) {
43406
- buildLap1(st.lap1, lap2, coords, { n, dim, exp });
43584
+ buildLap1(st.lap1, lap2, coords, { n, dim, exp, ops: st.ops });
43407
43585
  const newStress = computeStress(st);
43408
43586
  if (typeof process !== "undefined" && process.env["STRESS_DEBUG"] && iterations % 5 === 0) console.error(newStress.toFixed(3));
43409
43587
  const change = Math.abs(oldStress - newStress);
43410
43588
  converged = change / oldStress < o.epsilon || newStress < o.epsilon;
43411
43589
  oldStress = newStress;
43412
43590
  for (let k = 0; k < dim; k++) {
43413
- if (solveAxis(st, k, havePinned, nodes) < 0) return -1;
43591
+ if (solveAxis(st, k, havePinned, nodes) !== 0) return -1;
43414
43592
  }
43415
43593
  }
43416
43594
  for (let i = 0; i < dim; i++) {
@@ -43498,7 +43676,7 @@ function distanceKD(coords, dim, i, j) {
43498
43676
  let sum = 0;
43499
43677
  for (let k = 0; k < dim; k++) {
43500
43678
  const d = coords[k][i] - coords[k][j];
43501
- sum = fma2(d, d, sum);
43679
+ sum = fma(d, d, sum);
43502
43680
  }
43503
43681
  return Math.sqrt(sum);
43504
43682
  }
@@ -43675,10 +43853,10 @@ function stressMajorizationWithHierarchy(graph, n, dCoords, nodes, o) {
43675
43853
  }
43676
43854
 
43677
43855
  // src/common/utils-inputscale.ts
43678
- var POINTS_PER_INCH3 = 72;
43856
+ var POINTS_PER_INCH4 = 72;
43679
43857
  function getInputscale(g) {
43680
43858
  const d = lateDouble(g.root.attrs.get("inputscale"), -1, 0);
43681
- return d === 0 ? POINTS_PER_INCH3 : d;
43859
+ return d === 0 ? POINTS_PER_INCH4 : d;
43682
43860
  }
43683
43861
  function inputscaleDivisor(g) {
43684
43862
  const sc = getInputscale(g);
@@ -43686,7 +43864,7 @@ function inputscaleDivisor(g) {
43686
43864
  }
43687
43865
 
43688
43866
  // src/layout/neato/set-aspect.ts
43689
- var POINTS_PER_INCH4 = 72;
43867
+ var POINTS_PER_INCH5 = 72;
43690
43868
  function neatoRatioKind(g) {
43691
43869
  const p = g.attrs.get("ratio");
43692
43870
  if (p === void 0) return null;
@@ -43734,8 +43912,8 @@ function neatoTranslate(g) {
43734
43912
  const bb = g.info.bb;
43735
43913
  if (!bb) return;
43736
43914
  const ll = bb.ll;
43737
- const ox = ll.x / POINTS_PER_INCH4;
43738
- const oy = ll.y / POINTS_PER_INCH4;
43915
+ const ox = ll.x / POINTS_PER_INCH5;
43916
+ const oy = ll.y / POINTS_PER_INCH5;
43739
43917
  for (const n of g.nodes.values()) {
43740
43918
  if (!n.info.pos) n.info.pos = [0, 0];
43741
43919
  n.info.pos[0] = (n.info.pos[0] ?? 0) - ox;
@@ -43821,7 +43999,7 @@ var MODEL_CIRCUIT = 1;
43821
43999
  var MODEL_SUBSET = 2;
43822
44000
  var MODEL_MDS2 = 3;
43823
44001
  var DFLT_DIM = 2;
43824
- var POINTS_PER_INCH5 = 72;
44002
+ var POINTS_PER_INCH6 = 72;
43825
44003
  function neatoInitNode(n, dim = DFLT_DIM) {
43826
44004
  if (!n.info.pos || n.info.pos.length < dim) {
43827
44005
  const pos = [];
@@ -43882,15 +44060,17 @@ function solveStress(c, vtx, dCoords, nodeList) {
43882
44060
  dim: DFLT_DIM,
43883
44061
  opts,
43884
44062
  maxi,
43885
- epsilon
44063
+ epsilon,
44064
+ cola: mode === MODE_IPSEP
43886
44065
  });
43887
44066
  }
43888
44067
  function runMajorization(g, mode, model) {
43889
44068
  const nodeList = assignNodeIds2(g);
44069
+ setEdgeLen(g);
43890
44070
  const n = nodeList.length;
43891
44071
  const haveLen = graphHasLen(g);
43892
44072
  const init = checkStart(g, n, mode === MODE_HIER ? INIT_SELF : INIT_RANDOM);
43893
- const opts = init === INIT_SELF ? OPT_EXP_FLAG | OPT_SMART_INIT : OPT_EXP_FLAG;
44073
+ const opts = checkExp(g) | (init === INIT_SELF ? OPT_SMART_INIT : 0);
43894
44074
  const haveDir = mode === MODE_HIER || mode === MODE_IPSEP;
43895
44075
  const vtx = makeGraphDataC(g, nodeList, haveLen, haveDir, mode);
43896
44076
  const dCoords = [new Float64Array(n), new Float64Array(n)];
@@ -43920,12 +44100,14 @@ function neatoSetAspect(g) {
43920
44100
  const pos = n.info.pos;
43921
44101
  if (!pos) continue;
43922
44102
  n.info.coord = {
43923
- x: (pos[0] ?? 0) * POINTS_PER_INCH5,
43924
- y: (pos[1] ?? 0) * POINTS_PER_INCH5
44103
+ x: (pos[0] ?? 0) * POINTS_PER_INCH6,
44104
+ y: (pos[1] ?? 0) * POINTS_PER_INCH6
43925
44105
  };
43926
44106
  }
43927
44107
  }
43928
44108
  function neatoCleanup(g) {
44109
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
44110
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
43929
44111
  for (const [, n] of g.nodes) {
43930
44112
  n.info.pos = void 0;
43931
44113
  n.info.pinned = void 0;
@@ -46162,9 +46344,11 @@ function splineEdges(g) {
46162
46344
  coalesceEdges(g);
46163
46345
  if (edgetype === EDGETYPE_LINE) {
46164
46346
  RoutingHelper.straight(g, edgetype);
46347
+ setState(GVSPLINES);
46165
46348
  return;
46166
46349
  }
46167
46350
  splineEdgesImpl(g, esepFactor(g), edgetype);
46351
+ setState(GVSPLINES);
46168
46352
  }
46169
46353
  function computeBBFromPos(g) {
46170
46354
  const bb = {
@@ -48575,6 +48759,8 @@ function getPos(g, dim) {
48575
48759
  return pos;
48576
48760
  }
48577
48761
  function sfdpCleanup(g) {
48762
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
48763
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
48578
48764
  for (const n of g.nodes.values()) {
48579
48765
  n.info.pos = void 0;
48580
48766
  n.info.id = void 0;
@@ -49483,7 +49669,7 @@ var AM_PORTHOYX = 12;
49483
49669
  var SCALE = 10;
49484
49670
  var SCALE2 = SCALE / 2;
49485
49671
  var INT_MAX3 = 2147483647;
49486
- var POINTS_PER_INCH6 = 72;
49672
+ var POINTS_PER_INCH7 = 72;
49487
49673
  function cmpitem(a, b) {
49488
49674
  if (a < b) return -1;
49489
49675
  if (a > b) return 1;
@@ -49711,18 +49897,18 @@ function overlaps(p) {
49711
49897
  return false;
49712
49898
  }
49713
49899
  function initItem(n, margin) {
49714
- const x = cround(SCALE * (n.info.pos?.[0] ?? 0) * POINTS_PER_INCH6);
49715
- const y = cround(SCALE * (n.info.pos?.[1] ?? 0) * POINTS_PER_INCH6);
49900
+ const x = cround(SCALE * (n.info.pos?.[0] ?? 0) * POINTS_PER_INCH7);
49901
+ const y = cround(SCALE * (n.info.pos?.[1] ?? 0) * POINTS_PER_INCH7);
49716
49902
  const width2 = n.info.width ?? 0;
49717
49903
  const height2 = n.info.height ?? 0;
49718
49904
  let w2;
49719
49905
  let h2;
49720
49906
  if (margin.doAdd) {
49721
- w2 = d2i(SCALE * (cround(width2 / 2 * POINTS_PER_INCH6) + margin.x));
49722
- h2 = d2i(SCALE * (cround(height2 / 2 * POINTS_PER_INCH6) + margin.y));
49907
+ w2 = d2i(SCALE * (cround(width2 / 2 * POINTS_PER_INCH7) + margin.x));
49908
+ h2 = d2i(SCALE * (cround(height2 / 2 * POINTS_PER_INCH7) + margin.y));
49723
49909
  } else {
49724
- w2 = cround(margin.x * SCALE2 * width2 * POINTS_PER_INCH6);
49725
- h2 = cround(margin.y * SCALE2 * height2 * POINTS_PER_INCH6);
49910
+ w2 = cround(margin.x * SCALE2 * width2 * POINTS_PER_INCH7);
49911
+ h2 = cround(margin.y * SCALE2 * height2 * POINTS_PER_INCH7);
49726
49912
  }
49727
49913
  return {
49728
49914
  val: 0,
@@ -49757,8 +49943,8 @@ function cAdjust(g, mode) {
49757
49943
  if (!overlaps(nlist)) return 0;
49758
49944
  runPlan(g, nlist, PLANS.get(mode) ?? PLANS.get(AM_PORTHO));
49759
49945
  for (const p of nlist) {
49760
- const x = p.pos.x / POINTS_PER_INCH6 / SCALE;
49761
- const y = p.pos.y / POINTS_PER_INCH6 / SCALE;
49946
+ const x = p.pos.x / POINTS_PER_INCH7 / SCALE;
49947
+ const y = p.pos.y / POINTS_PER_INCH7 / SCALE;
49762
49948
  if (p.np.info.pos) {
49763
49949
  p.np.info.pos[0] = x;
49764
49950
  p.np.info.pos[1] = y;
@@ -49773,10 +49959,10 @@ function cAdjust(g, mode) {
49773
49959
  var POLY_BOX = 1;
49774
49960
  var POLY_CIRCLE = 2;
49775
49961
  var DFLT_SAMPLE2 = 20;
49776
- var POINTS_PER_INCH7 = 72;
49962
+ var POINTS_PER_INCH8 = 72;
49777
49963
  var MIN_SAMPLES = 3;
49778
49964
  function ps2inch2(a) {
49779
- return a / POINTS_PER_INCH7;
49965
+ return a / POINTS_PER_INCH8;
49780
49966
  }
49781
49967
  function isBoxKind(p) {
49782
49968
  return (p.kind & POLY_BOX) !== 0;
@@ -50069,7 +50255,7 @@ function polyOverlap(p, pp, q, qp) {
50069
50255
  // src/layout/neato/adjust-info.ts
50070
50256
  var DEFAULT_VORO_MARGIN = 0.05;
50071
50257
  var INCR = 0.05;
50072
- var POINTS_PER_INCH8 = 72;
50258
+ var POINTS_PER_INCH9 = 72;
50073
50259
  function newInfoState() {
50074
50260
  return {
50075
50261
  nodeInfo: [],
@@ -50124,8 +50310,8 @@ function chkBoundBox(st, graph) {
50124
50310
  function makeInfo(st, graph) {
50125
50311
  const pmargin = { ...sepFactor(graph) };
50126
50312
  if (pmargin.doAdd) {
50127
- pmargin.x /= POINTS_PER_INCH8;
50128
- pmargin.y /= POINTS_PER_INCH8;
50313
+ pmargin.x /= POINTS_PER_INCH9;
50314
+ pmargin.y /= POINTS_PER_INCH9;
50129
50315
  }
50130
50316
  const polyf = pmargin.doAdd ? makeAddPoly : makePoly;
50131
50317
  const info = [];
@@ -51191,7 +51377,7 @@ function genYConstraints(rects, vs) {
51191
51377
  }
51192
51378
 
51193
51379
  // src/layout/neato/vpsc-adjust.ts
51194
- var POINTS_PER_INCH9 = 72;
51380
+ var POINTS_PER_INCH10 = 72;
51195
51381
  var X_PASS_SCALE = Math.fround(1.0001);
51196
51382
  function buildRects(c, size, gap, scale) {
51197
51383
  return size.map((s, i) => {
@@ -51216,8 +51402,8 @@ function solveAxis2(c, size, gap, axis) {
51216
51402
  function vpscAdjust(g) {
51217
51403
  const margin = sepFactor(g);
51218
51404
  const gap = {
51219
- x: 2 * (margin.doAdd ? margin.x : DFLT_MARGIN) / POINTS_PER_INCH9,
51220
- y: 2 * (margin.doAdd ? margin.y : DFLT_MARGIN) / POINTS_PER_INCH9
51405
+ x: 2 * (margin.doAdd ? margin.x : DFLT_MARGIN) / POINTS_PER_INCH10,
51406
+ y: 2 * (margin.doAdd ? margin.y : DFLT_MARGIN) / POINTS_PER_INCH10
51221
51407
  };
51222
51408
  const nodes = Array.from(g.nodes.values());
51223
51409
  const c = [new Float32Array(nodes.length), new Float32Array(nodes.length)];
@@ -51396,7 +51582,7 @@ function graphAdjustMode(g) {
51396
51582
  }
51397
51583
 
51398
51584
  // src/layout/twopi/init.ts
51399
- var POINTS_PER_INCH10 = 72;
51585
+ var POINTS_PER_INCH11 = 72;
51400
51586
  function makeRdata(INF) {
51401
51587
  return {
51402
51588
  kind: "twopi",
@@ -51448,19 +51634,24 @@ function finaliseCoords(g) {
51448
51634
  const pos = n.info.pos;
51449
51635
  if (!pos) continue;
51450
51636
  n.info.coord = {
51451
- x: (pos[0] ?? 0) * POINTS_PER_INCH10,
51452
- y: (pos[1] ?? 0) * POINTS_PER_INCH10
51637
+ x: (pos[0] ?? 0) * POINTS_PER_INCH11,
51638
+ y: (pos[1] ?? 0) * POINTS_PER_INCH11
51453
51639
  };
51454
51640
  }
51455
51641
  }
51456
51642
  function adjustNodes(g) {
51457
51643
  adjustNodesFull(g);
51458
51644
  }
51459
- function twopiCleanup(g) {
51645
+ function twopiFreeAlg(g) {
51460
51646
  const first = g.nodes.values().next().value;
51461
51647
  if (first !== void 0 && first.info.alg?.kind === "twopi") {
51462
51648
  first.info.alg = void 0;
51463
51649
  }
51650
+ }
51651
+ function twopiCleanup(g) {
51652
+ if (g.nodes.size === 0) return;
51653
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
51654
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
51464
51655
  g.info.neato_nlist = void 0;
51465
51656
  }
51466
51657
 
@@ -51729,7 +51920,7 @@ function layoutSingle(g, comps, globalRoot, setRoot) {
51729
51920
  if (setRoot && globalRoot === null && center !== null) {
51730
51921
  g.attrs.set("root", center.name);
51731
51922
  }
51732
- twopiCleanup(g);
51923
+ twopiFreeAlg(g);
51733
51924
  splineEdgesShifted(g);
51734
51925
  finaliseCoords(g);
51735
51926
  }
@@ -51738,7 +51929,7 @@ function layoutMulti(g, comps, globalRoot, pinfo) {
51738
51929
  layoutComponent(g, sg, globalRoot);
51739
51930
  finaliseCoords(sg);
51740
51931
  }
51741
- twopiCleanup(g);
51932
+ twopiFreeAlg(g);
51742
51933
  packSubgraphs(comps.length, comps, g, pinfo);
51743
51934
  splineEdgesShifted(g);
51744
51935
  finaliseCoords(g);
@@ -52142,7 +52333,18 @@ function fdpInitNodeEdge(g) {
52142
52333
  }
52143
52334
  initialPositions3(g);
52144
52335
  }
52336
+ function fdpCleanupSubgs(g) {
52337
+ const nClust = g.info.n_cluster ?? 0;
52338
+ for (let i = 1; i <= nClust; i++) {
52339
+ const subg = g.info.clust[i - 1];
52340
+ subg.info.label = void 0;
52341
+ fdpCleanupSubgs(subg);
52342
+ }
52343
+ }
52145
52344
  function fdpCleanup(g) {
52345
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
52346
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
52347
+ fdpCleanupSubgs(g);
52146
52348
  for (const n of g.nodes.values()) {
52147
52349
  n.info.alg = void 0;
52148
52350
  n.info.pos = void 0;
@@ -53086,7 +53288,7 @@ function expandCluster2(n, cg) {
53086
53288
  }
53087
53289
 
53088
53290
  // src/layout/fdp/layout.ts
53089
- var POINTS_PER_INCH11 = 72;
53291
+ var POINTS_PER_INCH12 = 72;
53090
53292
  var DEFAULT_NODEWIDTH_PTS = 54;
53091
53293
  var DEFAULT_NODEHEIGHT_PTS = 36;
53092
53294
  function initInfo(g) {
@@ -53181,7 +53383,7 @@ function shiftComponents(cc, pts, pt) {
53181
53383
  } else {
53182
53384
  p = pt;
53183
53385
  }
53184
- const del = { x: p.x / POINTS_PER_INCH11, y: p.y / POINTS_PER_INCH11 };
53386
+ const del = { x: p.x / POINTS_PER_INCH12, y: p.y / POINTS_PER_INCH12 };
53185
53387
  for (const n of cc[i].nodes.values()) {
53186
53388
  n.info.pos[0] += del.x;
53187
53389
  n.info.pos[1] += del.y;
@@ -53197,8 +53399,8 @@ function finalCC(g, cc, pts, rg, infop) {
53197
53399
  const pt = applyMarginAndBorder(rg, bb, margin);
53198
53400
  if (cc.length > 0) shiftComponents(cc, pts, pt);
53199
53401
  gdata(g).bb = {
53200
- ll: { x: bb.ll.x / POINTS_PER_INCH11, y: bb.ll.y / POINTS_PER_INCH11 },
53201
- ur: { x: bb.ur.x / POINTS_PER_INCH11, y: bb.ur.y / POINTS_PER_INCH11 }
53402
+ ll: { x: bb.ll.x / POINTS_PER_INCH12, y: bb.ll.y / POINTS_PER_INCH12 },
53403
+ ur: { x: bb.ur.x / POINTS_PER_INCH12, y: bb.ur.y / POINTS_PER_INCH12 }
53202
53404
  };
53203
53405
  }
53204
53406
  function applyMarginAndBorder(rg, bb, margin) {
@@ -53244,8 +53446,8 @@ function translateOwnNodes(g, bb) {
53244
53446
  function setBB(g) {
53245
53447
  const bb = gdata(g).bb;
53246
53448
  g.info.bb = {
53247
- ll: { x: POINTS_PER_INCH11 * bb.ll.x, y: POINTS_PER_INCH11 * bb.ll.y },
53248
- ur: { x: POINTS_PER_INCH11 * bb.ur.x, y: POINTS_PER_INCH11 * bb.ur.y }
53449
+ ll: { x: POINTS_PER_INCH12 * bb.ll.x, y: POINTS_PER_INCH12 * bb.ll.y },
53450
+ ur: { x: POINTS_PER_INCH12 * bb.ur.x, y: POINTS_PER_INCH12 * bb.ur.y }
53249
53451
  };
53250
53452
  const nClusters = g.info.n_cluster ?? 0;
53251
53453
  for (let i = 0; i < nClusters; i++) {
@@ -53260,8 +53462,8 @@ function setClustNodes(root) {
53260
53462
  const bb = gdata(p).bb;
53261
53463
  const w = bb.ur.x - bb.ll.x;
53262
53464
  const h = bb.ur.y - bb.ll.y;
53263
- const w2 = POINTS_PER_INCH11 * (w / 2);
53264
- const h2 = POINTS_PER_INCH11 * (h / 2);
53465
+ const w2 = POINTS_PER_INCH12 * (w / 2);
53466
+ const h2 = POINTS_PER_INCH12 * (h / 2);
53265
53467
  n.info.pos[0] = w / 2;
53266
53468
  n.info.pos[1] = h / 2;
53267
53469
  n.info.width = w;
@@ -53270,7 +53472,7 @@ function setClustNodes(root) {
53270
53472
  n.info.outline_width = w + penwidth;
53271
53473
  n.info.outline_height = h + penwidth;
53272
53474
  n.info.lw = n.info.rw = w2;
53273
- n.info.ht = POINTS_PER_INCH11 * h;
53475
+ n.info.ht = POINTS_PER_INCH12 * h;
53274
53476
  const poly = n.info.shape_info;
53275
53477
  if (poly && poly.vertices) {
53276
53478
  poly.vertices[0] = { x: w2, y: h2 };
@@ -53283,8 +53485,8 @@ function setClustNodes(root) {
53283
53485
  function syncCoordFromPos(cg) {
53284
53486
  for (const n of cg.nodes.values()) {
53285
53487
  n.info.coord = {
53286
- x: POINTS_PER_INCH11 * n.info.pos[0],
53287
- y: POINTS_PER_INCH11 * n.info.pos[1]
53488
+ x: POINTS_PER_INCH12 * n.info.pos[0],
53489
+ y: POINTS_PER_INCH12 * n.info.pos[1]
53288
53490
  };
53289
53491
  }
53290
53492
  }
@@ -53296,8 +53498,8 @@ function expandComponentClusters(cg, infop, counter) {
53296
53498
  if (r !== 0) return r;
53297
53499
  n.info.width = gdata(sg).bb.ur.x;
53298
53500
  n.info.height = gdata(sg).bb.ur.y;
53299
- const ptx = POINTS_PER_INCH11 * gdata(sg).bb.ur.x;
53300
- const pty = POINTS_PER_INCH11 * gdata(sg).bb.ur.y;
53501
+ const ptx = POINTS_PER_INCH12 * gdata(sg).bb.ur.x;
53502
+ const pty = POINTS_PER_INCH12 * gdata(sg).bb.ur.y;
53301
53503
  n.info.rw = n.info.lw = ptx / 2;
53302
53504
  n.info.ht = pty;
53303
53505
  } else if (isPort(n)) {
@@ -54947,6 +55149,9 @@ function circoLayoutFull(g) {
54947
55149
  gvPostprocess(g);
54948
55150
  }
54949
55151
  function circoCleanup(g) {
55152
+ if (g.nodes.size === 0) return;
55153
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
55154
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
54950
55155
  g.info.alg = void 0;
54951
55156
  g.info.neato_nlist = void 0;
54952
55157
  }
@@ -55234,11 +55439,17 @@ function osageLayout(g) {
55234
55439
  }
55235
55440
  function cleanupGraphs(g) {
55236
55441
  const nClust = g.info.n_cluster ?? 0;
55237
- for (let i = 1; i <= nClust; i++) cleanupGraphs(g.info.clust[i - 1]);
55442
+ for (let i = 1; i <= nClust; i++) {
55443
+ const subg = g.info.clust[i - 1];
55444
+ subg.info.label = void 0;
55445
+ cleanupGraphs(subg);
55446
+ }
55238
55447
  g.info.clust = void 0;
55239
55448
  g.info.n_cluster = void 0;
55240
55449
  }
55241
55450
  function osageCleanup(g) {
55451
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
55452
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
55242
55453
  for (const n of g.nodes.values()) {
55243
55454
  if (n.info.alg?.kind === "osage") n.info.alg = void 0;
55244
55455
  }
@@ -55589,6 +55800,9 @@ function patchworkEngineLayout(g) {
55589
55800
  gvPostprocess(g);
55590
55801
  }
55591
55802
  function patchworkEngineCleanup(g) {
55803
+ if (g.nodes.size === 0) return;
55804
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
55805
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
55592
55806
  g.info.clust = void 0;
55593
55807
  g.info.n_cluster = void 0;
55594
55808
  for (const n of g.nodes.values()) {
@@ -56288,7 +56502,7 @@ var PlainExtRenderer = class {
56288
56502
  }
56289
56503
  };
56290
56504
  function mapGraphName(g) {
56291
- return g.anonymous ? "%1" : g.name;
56505
+ return agNameOf(g);
56292
56506
  }
56293
56507
  function graphAttr2(g, key) {
56294
56508
  for (let s = g; s !== null; s = s.parent) {
@@ -58627,8 +58841,8 @@ function latin1Reencode(s) {
58627
58841
  for (const b of bytes) out += String.fromCharCode(b);
58628
58842
  return out;
58629
58843
  }
58630
- function buildJson(g, doXDot) {
58631
- const draws = doXDot ? collectDrawLookup(g) : void 0;
58844
+ function buildJson(g, doXDot, preDraws) {
58845
+ const draws = doXDot ? preDraws ?? collectDrawLookup(g) : void 0;
58632
58846
  const ctx = assignIds(g, doXDot, draws);
58633
58847
  const root = buildGraphObject(g, true, ctx);
58634
58848
  return JSON.stringify(root, null, 2) + "\n";
@@ -58665,10 +58879,15 @@ var JsonRenderer = class {
58665
58879
  type = "json";
58666
58880
  /** @see plugin/core/gvplugin_core.c registration table */
58667
58881
  quality = 0;
58668
- beginGraph(_g, _job) {
58882
+ draws;
58883
+ // set by beginGraph, cleared by endGraph
58884
+ /** @see plugin/core/gvrender_core_json.c:json_begin_graph */
58885
+ beginGraph(g, _job) {
58886
+ this.draws = collectDrawLookup(g);
58669
58887
  }
58670
58888
  endGraph(g, job) {
58671
- job.write(buildJson(g, true));
58889
+ job.write(buildJson(g, true, this.draws));
58890
+ this.draws = void 0;
58672
58891
  }
58673
58892
  beginNode(_n, _job) {
58674
58893
  }
@@ -59416,16 +59635,16 @@ function isDoomedNode(node) {
59416
59635
  return BANNED_ELEMENTS.has(localNameOf(node)) || isHostileAnimation(node);
59417
59636
  }
59418
59637
  function scrubSvgDocument(doc) {
59419
- const pending = [doc];
59420
- while (pending.length > 0) {
59421
- const parent2 = pending.pop();
59638
+ const pending2 = [doc];
59639
+ while (pending2.length > 0) {
59640
+ const parent2 = pending2.pop();
59422
59641
  const children = Array.from(parent2.childNodes);
59423
59642
  for (const child of children) {
59424
59643
  if (isDoomedNode(child)) {
59425
59644
  parent2.removeChild(child);
59426
59645
  } else if (child.nodeType === ELEMENT_NODE) {
59427
59646
  scrubAttributes(child);
59428
- pending.push(child);
59647
+ pending2.push(child);
59429
59648
  }
59430
59649
  }
59431
59650
  }