@knowvah/dot-engine 2.7.0 → 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 (122) 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/attr-get.d.ts +30 -0
  5. package/dist/common/attr-get.d.ts.map +1 -0
  6. package/dist/common/fma.d.ts.map +1 -1
  7. package/dist/common/htmltable-emit-fill.d.ts.map +1 -1
  8. package/dist/common/htmltable-label.d.ts +3 -0
  9. package/dist/common/htmltable-label.d.ts.map +1 -1
  10. package/dist/common/htmltable-lex-attvalue.d.ts.map +1 -1
  11. package/dist/common/htmltable.d.ts +5 -0
  12. package/dist/common/htmltable.d.ts.map +1 -1
  13. package/dist/common/layers.d.ts +12 -0
  14. package/dist/common/layers.d.ts.map +1 -1
  15. package/dist/common/layout-state.d.ts +8 -0
  16. package/dist/common/layout-state.d.ts.map +1 -0
  17. package/dist/common/make-label.d.ts.map +1 -1
  18. package/dist/common/multicolor.d.ts +6 -3
  19. package/dist/common/multicolor.d.ts.map +1 -1
  20. package/dist/common/nodeinit.d.ts.map +1 -1
  21. package/dist/common/poly-init.d.ts +13 -12
  22. package/dist/common/poly-init.d.ts.map +1 -1
  23. package/dist/common/poly-sizing.d.ts +1 -0
  24. package/dist/common/poly-sizing.d.ts.map +1 -1
  25. package/dist/common/postproc.d.ts.map +1 -1
  26. package/dist/common/style-resolve.d.ts +11 -9
  27. package/dist/common/style-resolve.d.ts.map +1 -1
  28. package/dist/gvc/device-cluster.d.ts +5 -6
  29. package/dist/gvc/device-cluster.d.ts.map +1 -1
  30. package/dist/gvc/device.d.ts.map +1 -1
  31. package/dist/gvc/first-layer.d.ts +21 -5
  32. package/dist/gvc/first-layer.d.ts.map +1 -1
  33. package/dist/gvc/gvrender-set-style.d.ts.map +1 -1
  34. package/dist/gvc/usershape.d.ts +20 -0
  35. package/dist/gvc/usershape.d.ts.map +1 -1
  36. package/dist/index.js +512 -286
  37. package/dist/index.js.map +4 -4
  38. package/dist/layout/circo/index.d.ts.map +1 -1
  39. package/dist/layout/dot/graph-label.d.ts.map +1 -1
  40. package/dist/layout/dot/init.d.ts +10 -0
  41. package/dist/layout/dot/init.d.ts.map +1 -1
  42. package/dist/layout/dot/splines.d.ts.map +1 -1
  43. package/dist/layout/fdp/init.d.ts.map +1 -1
  44. package/dist/layout/neato/conjgrad-mkernel.d.ts.map +1 -1
  45. package/dist/layout/neato/constrained-majorization.d.ts.map +1 -1
  46. package/dist/layout/neato/edge-len.d.ts +6 -2
  47. package/dist/layout/neato/edge-len.d.ts.map +1 -1
  48. package/dist/layout/neato/init.d.ts.map +1 -1
  49. package/dist/layout/neato/kk.d.ts.map +1 -1
  50. package/dist/layout/neato/make-graph-data.d.ts.map +1 -1
  51. package/dist/layout/neato/matrix-ops.d.ts +0 -6
  52. package/dist/layout/neato/matrix-ops.d.ts.map +1 -1
  53. package/dist/layout/neato/smart-ini-x.d.ts.map +1 -1
  54. package/dist/layout/neato/splines.d.ts.map +1 -1
  55. package/dist/layout/neato/start.d.ts.map +1 -1
  56. package/dist/layout/neato/stress-kernel.d.ts +2 -5
  57. package/dist/layout/neato/stress-kernel.d.ts.map +1 -1
  58. package/dist/layout/neato/stress.d.ts +6 -0
  59. package/dist/layout/neato/stress.d.ts.map +1 -1
  60. package/dist/layout/osage/index.d.ts.map +1 -1
  61. package/dist/layout/patchwork/index.d.ts.map +1 -1
  62. package/dist/layout/sfdp/init.d.ts.map +1 -1
  63. package/dist/layout/twopi/init.d.ts +12 -6
  64. package/dist/layout/twopi/init.d.ts.map +1 -1
  65. package/dist/model/cgraph-ops.d.ts +9 -0
  66. package/dist/model/cgraph-ops.d.ts.map +1 -1
  67. package/dist/render/color-resolve.d.ts +7 -0
  68. package/dist/render/color-resolve.d.ts.map +1 -1
  69. package/dist/render/json.d.ts +17 -2
  70. package/dist/render/json.d.ts.map +1 -1
  71. package/dist/render/map.d.ts +3 -5
  72. package/dist/render/map.d.ts.map +1 -1
  73. package/dist/render.js +518 -292
  74. package/dist/render.js.map +4 -4
  75. package/package.json +1 -1
  76. package/src/common/agerr.ts +69 -8
  77. package/src/common/attr-get.ts +46 -0
  78. package/src/common/fma.ts +11 -1
  79. package/src/common/htmltable-emit-fill.ts +11 -7
  80. package/src/common/htmltable-label.ts +6 -3
  81. package/src/common/htmltable-lex-attvalue.ts +17 -1
  82. package/src/common/htmltable.ts +10 -5
  83. package/src/common/layers.ts +31 -2
  84. package/src/common/layout-state.ts +35 -0
  85. package/src/common/make-label.ts +20 -4
  86. package/src/common/multicolor.ts +12 -6
  87. package/src/common/nodeinit.ts +2 -1
  88. package/src/common/poly-init.ts +22 -19
  89. package/src/common/poly-sizing.ts +4 -4
  90. package/src/common/postproc.ts +4 -1
  91. package/src/common/style-resolve.ts +118 -50
  92. package/src/gvc/device-cluster.ts +31 -39
  93. package/src/gvc/device.ts +55 -43
  94. package/src/gvc/first-layer.ts +60 -11
  95. package/src/gvc/gvrender-set-style.ts +1 -6
  96. package/src/gvc/usershape.ts +40 -0
  97. package/src/layout/circo/index.ts +4 -0
  98. package/src/layout/dot/graph-label.ts +1 -15
  99. package/src/layout/dot/init.ts +32 -0
  100. package/src/layout/dot/splines.ts +3 -0
  101. package/src/layout/fdp/init.ts +17 -0
  102. package/src/layout/neato/conjgrad-mkernel.ts +2 -3
  103. package/src/layout/neato/constrained-majorization.ts +2 -1
  104. package/src/layout/neato/edge-len.ts +39 -7
  105. package/src/layout/neato/init.ts +8 -3
  106. package/src/layout/neato/kk.ts +2 -1
  107. package/src/layout/neato/make-graph-data.ts +1 -2
  108. package/src/layout/neato/matrix-ops.ts +1 -11
  109. package/src/layout/neato/smart-ini-x.ts +1 -1
  110. package/src/layout/neato/splines.ts +3 -1
  111. package/src/layout/neato/start.ts +3 -2
  112. package/src/layout/neato/stress-kernel.ts +45 -86
  113. package/src/layout/neato/stress.ts +19 -0
  114. package/src/layout/osage/index.ts +8 -1
  115. package/src/layout/patchwork/index.ts +4 -0
  116. package/src/layout/sfdp/init.ts +3 -0
  117. package/src/layout/twopi/init.ts +21 -9
  118. package/src/layout/twopi/pipeline.ts +3 -3
  119. package/src/model/cgraph-ops.ts +19 -0
  120. package/src/render/color-resolve.ts +17 -2
  121. package/src/render/json.ts +9 -10
  122. 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 [];
@@ -10518,6 +10584,17 @@ function emitHtmlLabel(placed, pos, renderer, job) {
10518
10584
  }
10519
10585
  }
10520
10586
 
10587
+ // src/common/attr-get.ts
10588
+ function nodeAttr(n, g, key) {
10589
+ const own = n.attrs.get(key);
10590
+ if (own !== void 0) return own;
10591
+ if (n.nodeDefaultsSnapshot !== void 0) return n.nodeDefaultsSnapshot.get(key);
10592
+ return g.nodeDefaults.get(key) ?? (g !== g.root ? g.root.nodeDefaults.get(key) : void 0);
10593
+ }
10594
+ function graphAttrInherited(sg, key) {
10595
+ return sg.attrs.get(key) ?? sg.graphDefaultsSnapshot?.get(key);
10596
+ }
10597
+
10521
10598
  // src/common/htmltable-attr-warn.ts
10522
10599
  var accepted = (v) => ({ keep: v, text: [], warn: false });
10523
10600
  var ignored = (text) => ({ keep: void 0, text: [text], warn: true });
@@ -10689,8 +10766,8 @@ function checkAttrs(tag, pairs) {
10689
10766
  return { attrs, warnings, warn };
10690
10767
  }
10691
10768
  var StderrLines = class {
10692
- constructor(writeLine) {
10693
- this.writeLine = writeLine;
10769
+ constructor(writeLine2) {
10770
+ this.writeLine = writeLine2;
10694
10771
  }
10695
10772
  writeLine;
10696
10773
  pending = "";
@@ -11044,6 +11121,15 @@ var NAME_CHAR = /[\w.:\u0080-
11044
11121
  var DEC_DIGIT = /[0-9]/;
11045
11122
  var HEX_DIGIT = /[0-9A-Fa-f]/;
11046
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
+ }
11047
11133
  function scanDigits(text, i, digit) {
11048
11134
  if (i >= text.length) return { partial: true };
11049
11135
  if (!digit.test(text[i])) return { invalid: i };
@@ -11071,7 +11157,7 @@ function scanAttValue(text, j) {
11071
11157
  const c = text[k];
11072
11158
  if (c === void 0) return { partial: true };
11073
11159
  if (c === q) return { close: k };
11074
- if (c === "<" || NON_XML.test(c)) return { invalid: k };
11160
+ if (c === "<" || isNonXmlAt(text, k)) return { invalid: k };
11075
11161
  if (c !== "&") {
11076
11162
  k++;
11077
11163
  continue;
@@ -12369,6 +12455,26 @@ function imageIsSupplied(name, sizer, resolver) {
12369
12455
  function imageOpenWarning(name) {
12370
12456
  return `${STRERROR_ENOENT} while opening ${name}`;
12371
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
+ }
12372
12478
 
12373
12479
  // src/common/pointset.ts
12374
12480
  function cmpPair(a, b) {
@@ -17395,7 +17501,7 @@ function splitFamilies(fontname) {
17395
17501
  function aliasFamilies(a) {
17396
17502
  return a.svgFontFamily !== a.family ? [a.family, a.svgFontFamily] : [a.family];
17397
17503
  }
17398
- function styleToken(a, flags) {
17504
+ function styleToken2(a, flags) {
17399
17505
  if (a?.style != null) return a.style;
17400
17506
  return flags?.italic === true ? "italic" : null;
17401
17507
  }
@@ -17404,7 +17510,7 @@ function weightToken(a, flags) {
17404
17510
  return flags?.bold === true ? "bold" : null;
17405
17511
  }
17406
17512
  function variantTokens(a, flags) {
17407
- const tokens = [styleToken(a, flags), weightToken(a, flags), a?.stretch ?? null];
17513
+ const tokens = [styleToken2(a, flags), weightToken(a, flags), a?.stretch ?? null];
17408
17514
  return tokens.filter((t) => t !== null);
17409
17515
  }
17410
17516
  function canvasFont(fontname, fontsize, flags) {
@@ -17818,15 +17924,15 @@ var sizeTextContent = (texts, measurer, env = defaultSizeEnv()) => {
17818
17924
  return { w, h };
17819
17925
  };
17820
17926
  var missingImages = { set: /* @__PURE__ */ new WeakSet() };
17821
- var sizeHtmlImg = (img, { imageSizer, stderr }) => {
17927
+ var sizeHtmlImg = (img, { imageSizer, imageResolver, imageDpi, stderr }) => {
17822
17928
  if (img.width !== void 0 && img.height !== void 0) return missingImages.set.has(img) ? 1 : 0;
17823
- const sz = imageSizer !== void 0 ? imageSizer(img.src) : findImageSize(img.src);
17929
+ const sz = usershapeSizePts(img.src, imageDpi ?? DEFAULT_DPI, imageSizer);
17824
17930
  if (sz !== null) {
17825
- img.width = sz.w;
17826
- img.height = sz.h;
17931
+ img.width = sz.x;
17932
+ img.height = sz.y;
17827
17933
  return 0;
17828
17934
  }
17829
- if (!imageIsSupplied(img.src, imageSizer)) agerrLine(stderr, `Warning: ${imageOpenWarning(img.src)}`);
17935
+ if (!imageIsSupplied(img.src, imageSizer, imageResolver)) agerrLine(stderr, `Warning: ${imageOpenWarning(img.src)}`);
17830
17936
  agerrLine(stderr, `Error: No or improper image file="${img.src}"`);
17831
17937
  img.width = 0;
17832
17938
  img.height = 0;
@@ -18313,7 +18419,7 @@ function posHtmlLabel(label, finfo, measurer) {
18313
18419
  // src/common/htmltable-label.ts
18314
18420
  var HTML_PARSE_FATAL = 3;
18315
18421
  function makeHtmlLabelTo(content, finfo, measurer, stderr) {
18316
- const { fontname, fontsize, fontcolor, imageSizer, pencolor } = finfo;
18422
+ const { fontname, fontsize, fontcolor, imageSizer, imageResolver, imageDpi, pencolor } = finfo;
18317
18423
  let lbl, lexWarn;
18318
18424
  try {
18319
18425
  ({ label: lbl, warn: lexWarn } = parseHtmlLabelRv(content, stderr));
@@ -18327,6 +18433,8 @@ function makeHtmlLabelTo(content, finfo, measurer, stderr) {
18327
18433
  fontsize,
18328
18434
  fontname,
18329
18435
  imageSizer,
18436
+ imageResolver,
18437
+ imageDpi,
18330
18438
  stderr
18331
18439
  });
18332
18440
  const placed = posHtmlLabel(lbl, { fontname, fontsize, fontcolor }, measurer);
@@ -18445,12 +18553,17 @@ var DEFAULT_FONTNAME = "Times-Roman";
18445
18553
  var DEFAULT_COLOR3 = "black";
18446
18554
  function getPenColor(obj) {
18447
18555
  if (obj === void 0) return void 0;
18448
- const pc = obj.attrs.get("pencolor");
18556
+ const pc = aggetObj(obj, "pencolor");
18449
18557
  if (pc !== void 0 && pc !== "") return pc;
18450
- const c = obj.attrs.get("color");
18558
+ const c = aggetObj(obj, "color");
18451
18559
  if (c !== void 0 && c !== "") return c;
18452
18560
  return void 0;
18453
18561
  }
18562
+ function aggetObj(obj, key) {
18563
+ if (obj instanceof Node) return nodeAttr(obj, obj.root, key);
18564
+ if (obj instanceof Graph) return graphAttrInherited(obj, key);
18565
+ return obj.attrs.get(key);
18566
+ }
18454
18567
  function rootOf(obj) {
18455
18568
  return obj instanceof Edge ? obj.tail.root : obj.root;
18456
18569
  }
@@ -18528,9 +18641,12 @@ function makeLabel(text, fontname, fontsize, fontcolor, measurer) {
18528
18641
  }
18529
18642
  function makeAnyLabel(content, isHtml, font, measurer, obj) {
18530
18643
  if (isHtml && content !== "") {
18531
- 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;
18532
18648
  const stderr = labelStderr();
18533
- 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);
18534
18650
  if (rv !== 0 && obj !== void 0) stderr.write(`${inLabelOf(obj)}
18535
18651
  `);
18536
18652
  stderr.flush();
@@ -18701,6 +18817,9 @@ function computeVertices(poly, w, h, base) {
18701
18817
  var SPLIT = 134217729;
18702
18818
  function fma(a, b, c) {
18703
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
+ }
18704
18823
  const at = SPLIT * a;
18705
18824
  const ahi = at - (at - a);
18706
18825
  const alo = a - ahi;
@@ -19001,7 +19120,8 @@ function polySize(p) {
19001
19120
  const init = initialSizePts(p);
19002
19121
  const dimen = quantize(padLabelDimen(p.labelDimen, p.margin, p.isPlain), p.quantumIn);
19003
19122
  const { sides: sides2, isBox: isBox4 } = effectiveShape(p);
19004
- 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) };
19005
19125
  if (isBox4) {
19006
19126
  } else if (p.optionShape === STAR) {
19007
19127
  bb = starSize(bb);
@@ -19030,7 +19150,7 @@ function labelSpace(p, dimen, bb, minBb, isBox4, fixedshape) {
19030
19150
  } else {
19031
19151
  spaceX = dimen.x - spacex;
19032
19152
  }
19033
- 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));
19034
19154
  return { space: { x: spaceX, y: spaceY }, valign: labelValign(p) };
19035
19155
  }
19036
19156
  function effectiveShape(p) {
@@ -21168,9 +21288,6 @@ function readLabelPos(sg) {
21168
21288
  }
21169
21289
  return pos;
21170
21290
  }
21171
- function graphAttrInherited(sg, key) {
21172
- return sg.attrs.get(key) ?? sg.graphDefaultsSnapshot?.get(key);
21173
- }
21174
21291
  function readFontParams(sg) {
21175
21292
  return {
21176
21293
  fontsize: parseFloat(graphAttrInherited(sg, "fontsize") ?? "") || DEFAULT_FONTSIZE2,
@@ -25094,12 +25211,6 @@ function drawRecordBox(job, n, ll, ur, filled) {
25094
25211
  var DEFAULT_LW = 27;
25095
25212
  var DEFAULT_RW = 27;
25096
25213
  var DEFAULT_HT = 36;
25097
- function nodeAttr(n, g, key) {
25098
- const own = n.attrs.get(key);
25099
- if (own !== void 0) return own;
25100
- if (n.nodeDefaultsSnapshot !== void 0) return n.nodeDefaultsSnapshot.get(key);
25101
- return g.nodeDefaults.get(key) ?? (g !== g.root ? g.root.nodeDefaults.get(key) : void 0);
25102
- }
25103
25214
  function readFontAttrs(n, g) {
25104
25215
  return {
25105
25216
  fontname: nodeAttr(n, g, "fontname") ?? DEFAULT_FONTNAME,
@@ -25133,6 +25244,15 @@ function warnMissingImage(n, g, shapefile) {
25133
25244
  agwarningf(imageOpenWarning(image));
25134
25245
  agwarningf(`No or improper image="${image}" for node "${n.name}"`);
25135
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
+ }
25136
25256
  function polyInit(n, g, measurer) {
25137
25257
  const shapeName2 = nodeAttr(n, g, "shape") ?? "ellipse";
25138
25258
  const shapefile = nodeAttr(n, g, "shapefile");
@@ -25492,11 +25612,7 @@ function applyClusterGradient(obj, fill) {
25492
25612
  obj.gradientAngle = fill.angle;
25493
25613
  }
25494
25614
  function clusterAttr(sg, key) {
25495
- for (let g = sg; g !== null; g = g.parent) {
25496
- const v = g.attrs.get(key);
25497
- if (v !== void 0) return v;
25498
- }
25499
- return void 0;
25615
+ return graphAttrInherited(sg, key);
25500
25616
  }
25501
25617
  function clusterStyle(sg) {
25502
25618
  return clusterAttr(sg, "style");
@@ -25531,12 +25647,10 @@ function applyClusterObjState(sg, job) {
25531
25647
  if (job.obj === null) return false;
25532
25648
  const obj = job.obj;
25533
25649
  gvrenderSetStyle(checkClusterStyleTokens(styleTokens(clusterStyle(sg))));
25534
- return withColorScheme(clusterAttr(sg, "colorscheme"), () => {
25535
- const filled = applyClusterFill(obj, fillRes);
25536
- applyClusterPenState(obj, sg);
25537
- reportColorNames(stripedClusterColors(sg));
25538
- return filled;
25539
- });
25650
+ const filled = applyClusterFill(obj, fillRes);
25651
+ applyClusterPenState(obj, sg);
25652
+ reportColorNames(stripedClusterColors(sg));
25653
+ return filled;
25540
25654
  }
25541
25655
  function isStripedCluster(sg) {
25542
25656
  const flags = parseStyleFlags(clusterStyle(sg));
@@ -25557,27 +25671,25 @@ function stripedClusterColors(sg) {
25557
25671
  return segs.flatMap((seg2) => seg2.color !== null && seg2.t > 0 ? [seg2.color] : []);
25558
25672
  }
25559
25673
  function renderStripedClusterBox(sg, renderer, job) {
25560
- withColorScheme(clusterAttr(sg, "colorscheme"), () => {
25561
- const { ll, ur } = sg.info.bb;
25562
- const af = [
25563
- { x: ll.x, y: ll.y },
25564
- { x: ur.x, y: ll.y },
25565
- { x: ur.x, y: ur.y },
25566
- { x: ll.x, y: ur.y }
25567
- ].map((p) => transformPoint(p, job));
25568
- const obj = job.obj;
25569
- const savedFill = obj?.fill;
25570
- if (obj !== null && savedFill !== void 0) obj.fill = 1 /* Solid */;
25571
- stripedBox(job, af, stripedFillSpec(sg), false, renderer, () => `in cluster ${sg.name}`);
25572
- if (obj !== null && savedFill !== void 0) obj.fill = savedFill;
25573
- const rawPts = [
25574
- { x: ll.x, y: ll.y },
25575
- { x: ll.x, y: ur.y },
25576
- { x: ur.x, y: ur.y },
25577
- { x: ur.x, y: ll.y }
25578
- ];
25579
- renderer.polygon(rawPts.map((p) => transformPoint(p, job)), false, job);
25580
- });
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);
25581
25693
  }
25582
25694
  function applyClusterFill(obj, fillRes) {
25583
25695
  if (fillRes.kind === "none") {
@@ -26318,7 +26430,24 @@ function removeFill(g) {
26318
26430
  }
26319
26431
  agdelsubg(g.root, sg);
26320
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
+ }
26321
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);
26322
26451
  let n = g.info.nlist;
26323
26452
  while (n !== void 0) {
26324
26453
  const next = n.info.next;
@@ -26796,7 +26925,7 @@ var DEFAULT_NODEWIDTH = 0.75;
26796
26925
  var MIN_NODEWIDTH = 0.01;
26797
26926
  var DEFAULT_NODEHEIGHT = 0.5;
26798
26927
  var MIN_NODEHEIGHT = 0.02;
26799
- var POINTS_PER_INCH2 = 72;
26928
+ var POINTS_PER_INCH3 = 72;
26800
26929
  var DEF_POINT = 0.05;
26801
26930
  var MIN_POINT = 3e-4;
26802
26931
  var DEFAULT_NODEPENWIDTH2 = 1;
@@ -26864,6 +26993,8 @@ function polySizeParamsFromNode(n, g, shape, labelDimen, flip) {
26864
26993
  // size_gen discriminant (STAR/CYLINDER)
26865
26994
  nojustify: mapbool4(nodeAttr(n, g, "nojustify")),
26866
26995
  // shapes.c:2133
26996
+ imageSize: nodeImageSize(n, g),
26997
+ // shapes.c:2039-2051
26867
26998
  flip
26868
26999
  };
26869
27000
  }
@@ -26900,7 +27031,7 @@ function initPointSize(n, g, shape) {
26900
27031
  const flip = g.root.info.flip === true;
26901
27032
  const peripheries = lateInt(nodeAttr(n, g, "peripheries"), shape.polygon.peripheries, 0);
26902
27033
  const penwidth = lateDouble(nodeAttr(n, g, "penwidth"), DEFAULT_NODEPENWIDTH2, MIN_NODEPENWIDTH);
26903
- const sz0 = pointWidthInches(n, g) * POINTS_PER_INCH2;
27034
+ const sz0 = pointWidthInches(n, g) * POINTS_PER_INCH3;
26904
27035
  storeNodeSize(n, pointSizeResult(sz0, peripheries, penwidth), flip);
26905
27036
  assignShapeInfo(n, { ...shape.polygon, peripheries, sides: 2, penwidth, vertices: null });
26906
27037
  }
@@ -26957,8 +27088,8 @@ function storeNodeSize(n, unflipped, flip) {
26957
27088
  n.info.base_width = unflipped.baseW / 72;
26958
27089
  n.info.base_height = unflipped.baseH / 72;
26959
27090
  const size = gvNodesize(
26960
- n.info.width * POINTS_PER_INCH2,
26961
- n.info.height * POINTS_PER_INCH2,
27091
+ n.info.width * POINTS_PER_INCH3,
27092
+ n.info.height * POINTS_PER_INCH3,
26962
27093
  flip
26963
27094
  );
26964
27095
  n.info.lw = size.lw;
@@ -28540,10 +28671,13 @@ function parseLayers(g) {
28540
28671
  let listSep = g.attrs.get("layerlistsep") || DEFAULT_LAYERLISTSEP;
28541
28672
  if ([...sep].some((c) => listSep.includes(c))) listSep = "";
28542
28673
  if (p === void 0 || p === "") {
28543
- return { layerIDs: [], numLayers: 1, sep, listSep };
28674
+ return { layerIDs: [], numLayers: 1, sep, listSep, layerList: null };
28544
28675
  }
28545
28676
  const toks = splitOnSet(p, sep);
28546
- 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;
28547
28681
  }
28548
28682
  function isNaturalNumber(s) {
28549
28683
  return /^[0-9]+$/.test(s);
@@ -28599,6 +28733,19 @@ function edgeInLayer(info, layerNum, e) {
28599
28733
  return pn === "" || selectedLayer(info, layerNum, pn);
28600
28734
  });
28601
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
+ }
28602
28749
 
28603
28750
  // src/gvc/emit-walk.ts
28604
28751
  function nodeShown(info, job, n, g) {
@@ -28661,9 +28808,40 @@ var NATIVE_LANGNAME = /* @__PURE__ */ new Map([
28661
28808
  ["cmapx-np", "cmapx_np"],
28662
28809
  ["imap-np", "imap_np"]
28663
28810
  ]);
28664
- function warnLayersUnsupported(format, numLayers, doesLayers) {
28665
- if (numLayers <= 1 || doesLayers) return;
28666
- 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
+ }
28667
28845
  }
28668
28846
 
28669
28847
  // src/gvc/device-labels.ts
@@ -28797,7 +28975,7 @@ function renderNode(n, renderer, job, done) {
28797
28975
  job.popObj();
28798
28976
  }
28799
28977
  }
28800
- function setEdgePen(e, job) {
28978
+ function setEdgePen(e, job, styles) {
28801
28979
  if (job.obj === null) return;
28802
28980
  const obj = job.obj;
28803
28981
  const flags = parseStyleFlags(e.attrs.get("style"));
@@ -28807,24 +28985,24 @@ function setEdgePen(e, job) {
28807
28985
  );
28808
28986
  obj.pen = resolvePenType(flags);
28809
28987
  obj.penWidth = resolvePenWidth(flags, e.attrs.get("penwidth"));
28810
- obj.rawStyle = styleTokens(e.attrs.get("style"));
28988
+ obj.rawStyle = [...styles];
28811
28989
  if (e.info.spl !== void 0) gvrenderSetStyle(obj.rawStyle);
28812
28990
  }
28813
28991
  function renderEdge(e, renderer, job) {
28814
28992
  emitEdgeComments(e, renderer, job);
28815
28993
  const edgeStyle = e.attrs.get("style");
28994
+ const styles = styleTokens(edgeStyle);
28816
28995
  if (parseStyleFlags(edgeStyle).invis || styleHasInvisibleAlias(edgeStyle)) return;
28817
28996
  const obj = createObjState(3 /* Edge */);
28818
28997
  obj.emitState = 9 /* EDraw */;
28819
28998
  job.pushObj(obj);
28820
- setEdgePen(e, job);
28999
+ setEdgePen(e, job, styles);
28821
29000
  try {
28822
29001
  setHtmlAnchorObj(svgEdgeId(e, job), labelTextOf2(e.info.label), job.obj ?? void 0);
28823
29002
  resolveEdgeAnchor(e, svgEdgeId(e, job), obj);
28824
29003
  withColorScheme(e.attrs.get("colorscheme"), () => {
28825
29004
  renderer.beginEdge(e, job);
28826
29005
  reportEdgeColors(e);
28827
- const styles = styleTokens(e.attrs.get("style"));
28828
29006
  for (let i = edgeStyleResets(e, styles); i > 0; i--) gvrenderSetStyle(styles);
28829
29007
  reportEdgeLabelColors(e);
28830
29008
  renderer.endEdge(e, job);
@@ -28851,6 +29029,22 @@ function renderClusterBox(sg, filled, renderer, job) {
28851
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 }];
28852
29030
  renderer.polygon(rawPts.map((p) => transformPoint(p, job)), filled, job);
28853
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
+ }
28854
29048
  function renderOneCluster(sg, renderer, job) {
28855
29049
  const clustersLast = (job.flags & EMIT_CLUSTERS_LAST) !== 0;
28856
29050
  if (clustersLast) renderClusters(sg, renderer, job);
@@ -28858,20 +29052,7 @@ function renderOneCluster(sg, renderer, job) {
28858
29052
  obj.emitState = 1 /* CDraw */;
28859
29053
  job.pushObj(obj);
28860
29054
  try {
28861
- const filled = applyClusterObjState(sg, job);
28862
- renderer.beginCluster?.(sg, job);
28863
- if (job.obj !== null) job.obj.id = svgClusterId(sg, job);
28864
- setHtmlAnchorObj(svgClusterId(sg, job), labelTextOf2(sg.info.label), job.obj ?? void 0);
28865
- if (job.obj !== null) {
28866
- resolveObjAnchor(sg, labelTextOf2(sg.info.label), svgClusterId(sg, job), job.obj);
28867
- }
28868
- const anchored = beginAnchorIf(renderer, job);
28869
- if ((clusterPeripheries(sg) !== 0 || filled || isStripedCluster(sg)) && job.obj?.pen !== 0 /* None */) {
28870
- renderClusterBox(sg, filled, renderer, job);
28871
- }
28872
- renderClusterLabel(sg, renderer, job);
28873
- if (anchored) renderer.endAnchor?.(job);
28874
- renderer.endCluster?.(sg, job);
29055
+ withColorScheme(clusterAttr(sg, "colorscheme"), () => drawClusterInScheme(sg, renderer, job));
28875
29056
  } finally {
28876
29057
  job.popObj();
28877
29058
  }
@@ -28892,16 +29073,15 @@ function renderGraph(g, job, renderer) {
28892
29073
  job.pushObj(obj);
28893
29074
  try {
28894
29075
  const info = parseLayers(g);
28895
- const layered = renderer.beginLayer !== void 0 && info.numLayers > 1;
28896
- job.numLayers = layered ? info.numLayers : 1;
29076
+ job.layerNum = 0;
28897
29077
  job.layerIDs = info.layerIDs;
28898
29078
  renderer.beginGraph(g, job);
28899
- warnLayersUnsupported(job.format, info.numLayers, renderer.beginLayer !== void 0);
28900
- for (let ln = 1; ln <= job.numLayers; ln++) {
28901
- job.layerNum = ln;
28902
- 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);
28903
29083
  renderPage(g, renderer, job, info);
28904
- if (layered) renderer.endLayer(job);
29084
+ if (layered) renderer.endLayer?.(job);
28905
29085
  }
28906
29086
  renderer.endGraph(g, job);
28907
29087
  } finally {
@@ -35370,6 +35550,20 @@ function addXLabels(gp) {
35370
35550
  runPlacement(gp);
35371
35551
  }
35372
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
+
35373
35567
  // src/common/postproc.ts
35374
35568
  var IGNORED_EDGE = 6;
35375
35569
  var Rankdir = 0;
@@ -35461,6 +35655,7 @@ function translateDrawing(g) {
35461
35655
  if (!shift && !Rankdir) return;
35462
35656
  for (const v of g.nodes.values()) {
35463
35657
  mapNode(v);
35658
+ if (getState() !== GVSPLINES) continue;
35464
35659
  for (const e of g.edges) {
35465
35660
  if (e.tail !== v) continue;
35466
35661
  if (e.info.spl === void 0) {
@@ -39450,6 +39645,7 @@ function orthoDispatch(g) {
39450
39645
  } else rc = dispatchOrthoEdges(g, false);
39451
39646
  if (rc !== 0) return rc;
39452
39647
  placePortLabels(g);
39648
+ setState(GVSPLINES);
39453
39649
  g.info.edgeLabelsDone = true;
39454
39650
  return 0;
39455
39651
  }
@@ -39464,6 +39660,7 @@ function finalizeSplines(g, et, normalize) {
39464
39660
  if (normalize) edgeNormalize(g);
39465
39661
  if (et !== EDGETYPE_CURVED) routeDotEdges(g);
39466
39662
  placePortLabels(g);
39663
+ setState(GVSPLINES);
39467
39664
  g.info.edgeLabelsDone = true;
39468
39665
  }
39469
39666
  function dotSplines_(g, normalize) {
@@ -41163,10 +41360,6 @@ function gvPermutation(bound) {
41163
41360
 
41164
41361
  // src/layout/neato/matrix-ops.ts
41165
41362
  var fr = Math.fround;
41166
- function fma2(a, b, c) {
41167
- const p = a * b;
41168
- return Number.isFinite(p) && Number.isFinite(c) ? fma(a, b, c) : p + c;
41169
- }
41170
41363
  function orthog1(n, vec) {
41171
41364
  let sum = 0;
41172
41365
  for (let i = 0; i < n; i++) sum += vec[i];
@@ -41195,10 +41388,6 @@ function rightMultWithVectorFF(m, n, vector, result) {
41195
41388
  function vectorsSubtractionF(n, v1, v2, result) {
41196
41389
  for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
41197
41390
  }
41198
- function vectorsMultAdditionF(n, v1, alpha, v2) {
41199
- const a = fr(alpha);
41200
- for (let i = 0; i < n; i++) v1[i] = v1[i] + fr(a * v2[i]);
41201
- }
41202
41391
  function vectorsInnerProductF(n, v1, v2) {
41203
41392
  let result = 0;
41204
41393
  for (let i = 0; i < n; i++) result += fr(v1[i] * v2[i]);
@@ -41239,11 +41428,11 @@ function innerProduct(n, v1, v2, block) {
41239
41428
  const blocked = block === BLOCK_NONE ? 0 : n - n % block;
41240
41429
  let i = 0;
41241
41430
  for (; i < blocked; i++) result += v1[i] * v2[i];
41242
- for (; i < n; i++) result = fma2(v1[i], v2[i], result);
41431
+ for (; i < n; i++) result = fma(v1[i], v2[i], result);
41243
41432
  return result;
41244
41433
  }
41245
41434
  function scadd(vec1, end, fac, vec2) {
41246
- 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]);
41247
41436
  }
41248
41437
  function norm(vec, end, block) {
41249
41438
  return Math.sqrt(innerProduct(end + 1, vec, vec, block));
@@ -41275,7 +41464,7 @@ function rightMultWithVectorF(matrix, n, vector, result, block) {
41275
41464
  let res = 0;
41276
41465
  let j = 0;
41277
41466
  for (; j < blocked; j++) res += row[j] * vector[j];
41278
- for (; j < n; j++) res = fma2(row[j], vector[j], res);
41467
+ for (; j < n; j++) res = fma(row[j], vector[j], res);
41279
41468
  result[i] = res;
41280
41469
  }
41281
41470
  }
@@ -41283,7 +41472,7 @@ function rightMultWithVector(matrix, n, vector, result) {
41283
41472
  for (let i = 0; i < n; i++) {
41284
41473
  let res = 0;
41285
41474
  const row = matrix[i];
41286
- 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);
41287
41476
  result[i] = res;
41288
41477
  }
41289
41478
  }
@@ -41401,6 +41590,16 @@ function conjugateGradientF(A3, x, b, n, opts) {
41401
41590
  var TOLERANCE_CG = 1e-3;
41402
41591
  var DFLT_ITERATIONS = 200;
41403
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
+ }
41404
41603
  function mdsModel(graph, nG) {
41405
41604
  if (graph[0].ewgts.length === 0) return null;
41406
41605
  const Dij = computeWeightedApspPacked(graph, nG);
@@ -41500,19 +41699,40 @@ function dijkstraSgd(graph, source, terms) {
41500
41699
 
41501
41700
  // src/layout/neato/edge-len.ts
41502
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
+ }
41503
41716
  function lenattr(ep, g) {
41504
41717
  const s = ep.attrs.get("len");
41505
41718
  if (s === void 0 || s === "") return DEFAULT_EDGE_LEN;
41506
- const val2 = /^\s*[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/.exec(s);
41507
- const len = val2 === null ? Number.NaN : parseFloat(val2[0]);
41508
- if (Number.isNaN(len) || len < 0 || len === 0) {
41509
- 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)}`);
41510
41722
  return DEFAULT_EDGE_LEN;
41511
41723
  }
41512
41724
  return len;
41513
41725
  }
41514
41726
  function setEdgeLen(g) {
41515
- 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;
41516
41736
  }
41517
41737
 
41518
41738
  // src/util/mt19937.ts
@@ -41670,7 +41890,7 @@ function neatoMode(g) {
41670
41890
  if (str === void 0 || str === "") return MODE_MAJOR;
41671
41891
  const mode = modeByName().get(str);
41672
41892
  if (mode !== void 0) return mode;
41673
- 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`);
41674
41894
  return MODE_MAJOR;
41675
41895
  }
41676
41896
  function checkMode(g, mode) {
@@ -41715,7 +41935,7 @@ function warnCircuitDisconnected(g) {
41715
41935
  circuitWarned.add(g.root);
41716
41936
  agerrLineOn(
41717
41937
  "warn",
41718
- `graph ${g.root.name} is disconnected. Hence, the circuit model
41938
+ `graph ${agNameOf(g.root)} is disconnected. Hence, the circuit model
41719
41939
  is undefined. Reverting to the shortest path model.
41720
41940
  Alternatively, consider running neato using -Gpack=true or decomposing
41721
41941
  the graph into connected components.`
@@ -42326,7 +42546,7 @@ function moveNode(st, m) {
42326
42546
  function solveModel(g, st) {
42327
42547
  for (let m = chooseNode(st); m >= 0; m = chooseNode(st)) moveNode(st, m);
42328
42548
  if (st.move === st.maxIter) {
42329
- agwarningf(`Max. iterations (${st.maxIter}) reached on graph ${g.name}`);
42549
+ agwarningf(`Max. iterations (${st.maxIter}) reached on graph ${agNameOf(g)}`);
42330
42550
  }
42331
42551
  }
42332
42552
  function mdsEdges(g, nodes, lens) {
@@ -42409,7 +42629,7 @@ function addNeighbours(g, np, entry, o) {
42409
42629
  if (ep.head === ep.tail) continue;
42410
42630
  const vp = ep.tail === np ? ep.head : ep.tail;
42411
42631
  const vid = vp.info.id;
42412
- const dist5 = o.haveLen ? lateDouble(ep.attrs.get("len"), 1, 0) : 1;
42632
+ const dist5 = o.haveLen ? ep.info.dist ?? 0 : 1;
42413
42633
  const idx = seen2.get(vid);
42414
42634
  if (idx !== void 0) {
42415
42635
  if (o.haveLen) entry.ewgts[idx] = Math.max(entry.ewgts[idx], dist5);
@@ -42951,7 +43171,7 @@ function matMultVecOrthog(mat, dim, vec, result, orthog) {
42951
43171
  let sum = 0;
42952
43172
  let j = 0;
42953
43173
  for (; j < blocked; j++) sum += row[j] * vec[j];
42954
- for (; j < dim; j++) sum = fma2(row[j], vec[j], sum);
43174
+ for (; j < dim; j++) sum = fma(row[j], vec[j], sum);
42955
43175
  result[i] = sum;
42956
43176
  }
42957
43177
  const alpha = -innerProduct(dim, result, orthog, BLOCK_MAT_MULT_ORTHOG);
@@ -43050,8 +43270,8 @@ function computeAvgs(Dij, n) {
43050
43270
  sumRow += row[j] * row[j];
43051
43271
  }
43052
43272
  for (; j < n; j++) {
43053
- sum = fma2(row[j], row[j], sum);
43054
- sumRow = fma2(row[j], row[j], sumRow);
43273
+ sum = fma(row[j], row[j], sum);
43274
+ sumRow = fma(row[j], row[j], sumRow);
43055
43275
  }
43056
43276
  rowAvg[i] = fr4(fr4(sumRow) / n);
43057
43277
  }
@@ -43064,7 +43284,7 @@ function computeBij(Dij, n) {
43064
43284
  for (let i = 0; i < n; i++) {
43065
43285
  for (let j = 0; j <= i; j++) {
43066
43286
  const fD = fr4(Dij[i][j]);
43067
- const t = fr4(fma2(-fD, fD, rowAvg[i]));
43287
+ const t = fr4(fma(-fD, fD, rowAvg[i]));
43068
43288
  Bij[i][j] = fr4(fr4(t + rowAvg[j]) - allAvg);
43069
43289
  Bij[j][i] = Bij[i][j];
43070
43290
  }
@@ -43096,8 +43316,8 @@ function scaleGivenCoords(Dij, n, x) {
43096
43316
  sum1 += t1 * f;
43097
43317
  sum2 += t2 * f;
43098
43318
  } else {
43099
- sum1 = fma2(t1, f, sum1);
43100
- sum2 = fma2(t2, f, sum2);
43319
+ sum1 = fma(t1, f, sum1);
43320
+ sum2 = fma(t2, f, sum2);
43101
43321
  }
43102
43322
  }
43103
43323
  }
@@ -43127,7 +43347,7 @@ function computeResidualDistances(Dij, n, x) {
43127
43347
  for (let j = 0; j < i; j++) {
43128
43348
  const t = posI - x[j];
43129
43349
  const d = Dij[i][j];
43130
- const diff = fma2(d, d, -(t * t));
43350
+ const diff = fma(d, d, -(t * t));
43131
43351
  const v = diff > 0 ? Math.sqrt(diff) : 0;
43132
43352
  Dij[i][j] = v;
43133
43353
  Dij[j][i] = v;
@@ -43184,8 +43404,6 @@ function imdsGivenDim(graph, n, givenCoords, newCoords, conjTol) {
43184
43404
 
43185
43405
  // src/layout/neato/stress-kernel.ts
43186
43406
  var fr5 = Math.fround;
43187
- var TOLERANCE_CG2 = 1e-3;
43188
- var OPT_EXP_FLAG = 2;
43189
43407
  function computeApspPacked2(graph, n) {
43190
43408
  const Dij = new Float32Array(n * (n + 1) / 2);
43191
43409
  const Di = new Int32Array(n);
@@ -43229,51 +43447,16 @@ function initLayout(n, dim, coords, nodes) {
43229
43447
  for (let d = 0; d < dim; d++) orthog1(n, coords[d]);
43230
43448
  return pinned;
43231
43449
  }
43232
- function cgStep(st, last) {
43233
- const { n } = st;
43234
- orthog1f(n, st.p);
43235
- orthog1f(n, st.x);
43236
- orthog1f(n, st.r);
43237
- rightMultWithVectorFF(st.A, n, st.p, st.Ap);
43238
- orthog1f(n, st.Ap);
43239
- const pAp = vectorsInnerProductF(n, st.p, st.Ap);
43240
- if (pAp === 0) return true;
43241
- const alpha = st.rR / pAp;
43242
- vectorsMultAdditionF(n, st.x, alpha, st.p);
43243
- if (!last) {
43244
- vectorsMultAdditionF(n, st.r, -alpha, st.Ap);
43245
- const rRNew = vectorsInnerProductF(n, st.r, st.r);
43246
- if (st.rR === 0) return false;
43247
- const betaF = fr5(rRNew / st.rR);
43248
- st.rR = rRNew;
43249
- for (let j = 0; j < n; j++) st.p[j] = fr5(betaF * st.p[j]) + st.r[j];
43250
- }
43251
- return true;
43252
- }
43253
- function conjugateGradientMkernel2(A3, x, b, n, tol, maxIterations) {
43254
- const st = {
43255
- A: A3,
43256
- x,
43257
- b,
43258
- n,
43259
- r: new Float32Array(n),
43260
- p: new Float32Array(n),
43261
- Ap: new Float32Array(n),
43262
- rR: 0
43263
- };
43264
- orthog1f(n, x);
43265
- orthog1f(n, b);
43266
- const Ax = new Float32Array(n);
43267
- rightMultWithVectorFF(A3, n, x, Ax);
43268
- orthog1f(n, Ax);
43269
- vectorsSubtractionF(n, b, Ax, st.r);
43270
- copyVectorF(n, st.r, st.p);
43271
- st.rR = vectorsInnerProductF(n, st.r, st.r);
43272
- for (let i = 0; i < maxIterations && maxAbsF(n, st.r) > tol; i++) {
43273
- if (!cgStep(st, i >= maxIterations - 1)) return -1;
43274
- }
43275
- return 0;
43276
- }
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
+ };
43277
43460
  function buildLap2(lap2, n, exp) {
43278
43461
  const lapLength = n * (n + 1) / 2;
43279
43462
  if (exp === 2) squareVec(lapLength, lap2);
@@ -43296,7 +43479,7 @@ function buildLap2(lap2, n, exp) {
43296
43479
  }
43297
43480
  }
43298
43481
  function buildLap1(lap1, lap2, coords, shape) {
43299
- const { n, dim, exp } = shape;
43482
+ const { n, dim, exp, ops } = shape;
43300
43483
  const lapLength = n * (n + 1) / 2;
43301
43484
  const degrees = new Float64Array(n);
43302
43485
  const distAccumulator = new Float32Array(n);
@@ -43309,7 +43492,7 @@ function buildLap1(lap1, lap2, coords, shape) {
43309
43492
  const ck = coords[k];
43310
43493
  for (let x = 0; x < len; x++) {
43311
43494
  const tmp = fr5(ck[i] + fr5(-1 * ck[i + 1 + x]));
43312
- distAccumulator[x] = distAccumulator[x] + fr5(tmp * tmp);
43495
+ distAccumulator[x] = ops.squareAdd(tmp, distAccumulator[x]);
43313
43496
  }
43314
43497
  }
43315
43498
  invertSqrtVec(len, distAccumulator);
@@ -43342,24 +43525,25 @@ function buildLap1(lap1, lap2, coords, shape) {
43342
43525
  function computeStress(st) {
43343
43526
  let stress = 0;
43344
43527
  for (let k = 0; k < st.dim; k++) {
43345
- 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]);
43346
43529
  stress += vectorsInnerProductF(st.n, st.coords[k], st.b[k]);
43347
43530
  }
43348
43531
  stress *= 2;
43349
43532
  stress += st.constantTerm;
43350
43533
  for (let k = 0; k < st.dim; k++) {
43351
- rightMultWithVectorFF(st.lap2, st.n, st.coords[k], st.tmpCoords);
43534
+ st.ops.rightMult(st.lap2, st.n, st.coords[k], st.tmpCoords);
43352
43535
  stress -= vectorsInnerProductF(st.n, st.coords[k], st.tmpCoords);
43353
43536
  }
43354
43537
  return stress;
43355
43538
  }
43356
43539
  function solveAxis(st, k, havePinned, nodes) {
43540
+ const cg = { tol: TOLERANCE_CG, maxIterations: st.n };
43357
43541
  if (!havePinned) {
43358
- 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);
43359
43543
  }
43360
43544
  copyVectorF(st.n, st.coords[k], st.tmpCoords);
43361
- const rc = conjugateGradientMkernel2(st.lap2, st.tmpCoords, st.b[k], st.n, TOLERANCE_CG2, st.n);
43362
- 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;
43363
43547
  for (let i = 0; i < st.n; i++) {
43364
43548
  if (!isFixed(nodes[i])) st.coords[k][i] = st.tmpCoords[i];
43365
43549
  }
@@ -43390,20 +43574,21 @@ function stressMajorizationKDMkernel(Dij, n, dCoords, nodes, o) {
43390
43574
  coords,
43391
43575
  b: Array.from({ length: dim }, () => new Float32Array(n)),
43392
43576
  tmpCoords: new Float32Array(n),
43393
- constantTerm
43577
+ constantTerm,
43578
+ ops: o.cola === true ? COLA_OPS : FUSED_OPS
43394
43579
  };
43395
43580
  let oldStress = Number.MAX_VALUE;
43396
43581
  let converged = false;
43397
43582
  let iterations = 0;
43398
43583
  for (; iterations < maxi && !converged; iterations++) {
43399
- buildLap1(st.lap1, lap2, coords, { n, dim, exp });
43584
+ buildLap1(st.lap1, lap2, coords, { n, dim, exp, ops: st.ops });
43400
43585
  const newStress = computeStress(st);
43401
43586
  if (typeof process !== "undefined" && process.env["STRESS_DEBUG"] && iterations % 5 === 0) console.error(newStress.toFixed(3));
43402
43587
  const change = Math.abs(oldStress - newStress);
43403
43588
  converged = change / oldStress < o.epsilon || newStress < o.epsilon;
43404
43589
  oldStress = newStress;
43405
43590
  for (let k = 0; k < dim; k++) {
43406
- if (solveAxis(st, k, havePinned, nodes) < 0) return -1;
43591
+ if (solveAxis(st, k, havePinned, nodes) !== 0) return -1;
43407
43592
  }
43408
43593
  }
43409
43594
  for (let i = 0; i < dim; i++) {
@@ -43491,7 +43676,7 @@ function distanceKD(coords, dim, i, j) {
43491
43676
  let sum = 0;
43492
43677
  for (let k = 0; k < dim; k++) {
43493
43678
  const d = coords[k][i] - coords[k][j];
43494
- sum = fma2(d, d, sum);
43679
+ sum = fma(d, d, sum);
43495
43680
  }
43496
43681
  return Math.sqrt(sum);
43497
43682
  }
@@ -43668,10 +43853,10 @@ function stressMajorizationWithHierarchy(graph, n, dCoords, nodes, o) {
43668
43853
  }
43669
43854
 
43670
43855
  // src/common/utils-inputscale.ts
43671
- var POINTS_PER_INCH3 = 72;
43856
+ var POINTS_PER_INCH4 = 72;
43672
43857
  function getInputscale(g) {
43673
43858
  const d = lateDouble(g.root.attrs.get("inputscale"), -1, 0);
43674
- return d === 0 ? POINTS_PER_INCH3 : d;
43859
+ return d === 0 ? POINTS_PER_INCH4 : d;
43675
43860
  }
43676
43861
  function inputscaleDivisor(g) {
43677
43862
  const sc = getInputscale(g);
@@ -43679,7 +43864,7 @@ function inputscaleDivisor(g) {
43679
43864
  }
43680
43865
 
43681
43866
  // src/layout/neato/set-aspect.ts
43682
- var POINTS_PER_INCH4 = 72;
43867
+ var POINTS_PER_INCH5 = 72;
43683
43868
  function neatoRatioKind(g) {
43684
43869
  const p = g.attrs.get("ratio");
43685
43870
  if (p === void 0) return null;
@@ -43727,8 +43912,8 @@ function neatoTranslate(g) {
43727
43912
  const bb = g.info.bb;
43728
43913
  if (!bb) return;
43729
43914
  const ll = bb.ll;
43730
- const ox = ll.x / POINTS_PER_INCH4;
43731
- const oy = ll.y / POINTS_PER_INCH4;
43915
+ const ox = ll.x / POINTS_PER_INCH5;
43916
+ const oy = ll.y / POINTS_PER_INCH5;
43732
43917
  for (const n of g.nodes.values()) {
43733
43918
  if (!n.info.pos) n.info.pos = [0, 0];
43734
43919
  n.info.pos[0] = (n.info.pos[0] ?? 0) - ox;
@@ -43814,7 +43999,7 @@ var MODEL_CIRCUIT = 1;
43814
43999
  var MODEL_SUBSET = 2;
43815
44000
  var MODEL_MDS2 = 3;
43816
44001
  var DFLT_DIM = 2;
43817
- var POINTS_PER_INCH5 = 72;
44002
+ var POINTS_PER_INCH6 = 72;
43818
44003
  function neatoInitNode(n, dim = DFLT_DIM) {
43819
44004
  if (!n.info.pos || n.info.pos.length < dim) {
43820
44005
  const pos = [];
@@ -43875,15 +44060,17 @@ function solveStress(c, vtx, dCoords, nodeList) {
43875
44060
  dim: DFLT_DIM,
43876
44061
  opts,
43877
44062
  maxi,
43878
- epsilon
44063
+ epsilon,
44064
+ cola: mode === MODE_IPSEP
43879
44065
  });
43880
44066
  }
43881
44067
  function runMajorization(g, mode, model) {
43882
44068
  const nodeList = assignNodeIds2(g);
44069
+ setEdgeLen(g);
43883
44070
  const n = nodeList.length;
43884
44071
  const haveLen = graphHasLen(g);
43885
44072
  const init = checkStart(g, n, mode === MODE_HIER ? INIT_SELF : INIT_RANDOM);
43886
- 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);
43887
44074
  const haveDir = mode === MODE_HIER || mode === MODE_IPSEP;
43888
44075
  const vtx = makeGraphDataC(g, nodeList, haveLen, haveDir, mode);
43889
44076
  const dCoords = [new Float64Array(n), new Float64Array(n)];
@@ -43913,12 +44100,14 @@ function neatoSetAspect(g) {
43913
44100
  const pos = n.info.pos;
43914
44101
  if (!pos) continue;
43915
44102
  n.info.coord = {
43916
- x: (pos[0] ?? 0) * POINTS_PER_INCH5,
43917
- y: (pos[1] ?? 0) * POINTS_PER_INCH5
44103
+ x: (pos[0] ?? 0) * POINTS_PER_INCH6,
44104
+ y: (pos[1] ?? 0) * POINTS_PER_INCH6
43918
44105
  };
43919
44106
  }
43920
44107
  }
43921
44108
  function neatoCleanup(g) {
44109
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
44110
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
43922
44111
  for (const [, n] of g.nodes) {
43923
44112
  n.info.pos = void 0;
43924
44113
  n.info.pinned = void 0;
@@ -46155,9 +46344,11 @@ function splineEdges(g) {
46155
46344
  coalesceEdges(g);
46156
46345
  if (edgetype === EDGETYPE_LINE) {
46157
46346
  RoutingHelper.straight(g, edgetype);
46347
+ setState(GVSPLINES);
46158
46348
  return;
46159
46349
  }
46160
46350
  splineEdgesImpl(g, esepFactor(g), edgetype);
46351
+ setState(GVSPLINES);
46161
46352
  }
46162
46353
  function computeBBFromPos(g) {
46163
46354
  const bb = {
@@ -48568,6 +48759,8 @@ function getPos(g, dim) {
48568
48759
  return pos;
48569
48760
  }
48570
48761
  function sfdpCleanup(g) {
48762
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
48763
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
48571
48764
  for (const n of g.nodes.values()) {
48572
48765
  n.info.pos = void 0;
48573
48766
  n.info.id = void 0;
@@ -49476,7 +49669,7 @@ var AM_PORTHOYX = 12;
49476
49669
  var SCALE = 10;
49477
49670
  var SCALE2 = SCALE / 2;
49478
49671
  var INT_MAX3 = 2147483647;
49479
- var POINTS_PER_INCH6 = 72;
49672
+ var POINTS_PER_INCH7 = 72;
49480
49673
  function cmpitem(a, b) {
49481
49674
  if (a < b) return -1;
49482
49675
  if (a > b) return 1;
@@ -49704,18 +49897,18 @@ function overlaps(p) {
49704
49897
  return false;
49705
49898
  }
49706
49899
  function initItem(n, margin) {
49707
- const x = cround(SCALE * (n.info.pos?.[0] ?? 0) * POINTS_PER_INCH6);
49708
- 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);
49709
49902
  const width2 = n.info.width ?? 0;
49710
49903
  const height2 = n.info.height ?? 0;
49711
49904
  let w2;
49712
49905
  let h2;
49713
49906
  if (margin.doAdd) {
49714
- w2 = d2i(SCALE * (cround(width2 / 2 * POINTS_PER_INCH6) + margin.x));
49715
- 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));
49716
49909
  } else {
49717
- w2 = cround(margin.x * SCALE2 * width2 * POINTS_PER_INCH6);
49718
- 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);
49719
49912
  }
49720
49913
  return {
49721
49914
  val: 0,
@@ -49750,8 +49943,8 @@ function cAdjust(g, mode) {
49750
49943
  if (!overlaps(nlist)) return 0;
49751
49944
  runPlan(g, nlist, PLANS.get(mode) ?? PLANS.get(AM_PORTHO));
49752
49945
  for (const p of nlist) {
49753
- const x = p.pos.x / POINTS_PER_INCH6 / SCALE;
49754
- 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;
49755
49948
  if (p.np.info.pos) {
49756
49949
  p.np.info.pos[0] = x;
49757
49950
  p.np.info.pos[1] = y;
@@ -49766,10 +49959,10 @@ function cAdjust(g, mode) {
49766
49959
  var POLY_BOX = 1;
49767
49960
  var POLY_CIRCLE = 2;
49768
49961
  var DFLT_SAMPLE2 = 20;
49769
- var POINTS_PER_INCH7 = 72;
49962
+ var POINTS_PER_INCH8 = 72;
49770
49963
  var MIN_SAMPLES = 3;
49771
49964
  function ps2inch2(a) {
49772
- return a / POINTS_PER_INCH7;
49965
+ return a / POINTS_PER_INCH8;
49773
49966
  }
49774
49967
  function isBoxKind(p) {
49775
49968
  return (p.kind & POLY_BOX) !== 0;
@@ -50062,7 +50255,7 @@ function polyOverlap(p, pp, q, qp) {
50062
50255
  // src/layout/neato/adjust-info.ts
50063
50256
  var DEFAULT_VORO_MARGIN = 0.05;
50064
50257
  var INCR = 0.05;
50065
- var POINTS_PER_INCH8 = 72;
50258
+ var POINTS_PER_INCH9 = 72;
50066
50259
  function newInfoState() {
50067
50260
  return {
50068
50261
  nodeInfo: [],
@@ -50117,8 +50310,8 @@ function chkBoundBox(st, graph) {
50117
50310
  function makeInfo(st, graph) {
50118
50311
  const pmargin = { ...sepFactor(graph) };
50119
50312
  if (pmargin.doAdd) {
50120
- pmargin.x /= POINTS_PER_INCH8;
50121
- pmargin.y /= POINTS_PER_INCH8;
50313
+ pmargin.x /= POINTS_PER_INCH9;
50314
+ pmargin.y /= POINTS_PER_INCH9;
50122
50315
  }
50123
50316
  const polyf = pmargin.doAdd ? makeAddPoly : makePoly;
50124
50317
  const info = [];
@@ -51184,7 +51377,7 @@ function genYConstraints(rects, vs) {
51184
51377
  }
51185
51378
 
51186
51379
  // src/layout/neato/vpsc-adjust.ts
51187
- var POINTS_PER_INCH9 = 72;
51380
+ var POINTS_PER_INCH10 = 72;
51188
51381
  var X_PASS_SCALE = Math.fround(1.0001);
51189
51382
  function buildRects(c, size, gap, scale) {
51190
51383
  return size.map((s, i) => {
@@ -51209,8 +51402,8 @@ function solveAxis2(c, size, gap, axis) {
51209
51402
  function vpscAdjust(g) {
51210
51403
  const margin = sepFactor(g);
51211
51404
  const gap = {
51212
- x: 2 * (margin.doAdd ? margin.x : DFLT_MARGIN) / POINTS_PER_INCH9,
51213
- 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
51214
51407
  };
51215
51408
  const nodes = Array.from(g.nodes.values());
51216
51409
  const c = [new Float32Array(nodes.length), new Float32Array(nodes.length)];
@@ -51389,7 +51582,7 @@ function graphAdjustMode(g) {
51389
51582
  }
51390
51583
 
51391
51584
  // src/layout/twopi/init.ts
51392
- var POINTS_PER_INCH10 = 72;
51585
+ var POINTS_PER_INCH11 = 72;
51393
51586
  function makeRdata(INF) {
51394
51587
  return {
51395
51588
  kind: "twopi",
@@ -51441,19 +51634,24 @@ function finaliseCoords(g) {
51441
51634
  const pos = n.info.pos;
51442
51635
  if (!pos) continue;
51443
51636
  n.info.coord = {
51444
- x: (pos[0] ?? 0) * POINTS_PER_INCH10,
51445
- y: (pos[1] ?? 0) * POINTS_PER_INCH10
51637
+ x: (pos[0] ?? 0) * POINTS_PER_INCH11,
51638
+ y: (pos[1] ?? 0) * POINTS_PER_INCH11
51446
51639
  };
51447
51640
  }
51448
51641
  }
51449
51642
  function adjustNodes(g) {
51450
51643
  adjustNodesFull(g);
51451
51644
  }
51452
- function twopiCleanup(g) {
51645
+ function twopiFreeAlg(g) {
51453
51646
  const first = g.nodes.values().next().value;
51454
51647
  if (first !== void 0 && first.info.alg?.kind === "twopi") {
51455
51648
  first.info.alg = void 0;
51456
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);
51457
51655
  g.info.neato_nlist = void 0;
51458
51656
  }
51459
51657
 
@@ -51722,7 +51920,7 @@ function layoutSingle(g, comps, globalRoot, setRoot) {
51722
51920
  if (setRoot && globalRoot === null && center !== null) {
51723
51921
  g.attrs.set("root", center.name);
51724
51922
  }
51725
- twopiCleanup(g);
51923
+ twopiFreeAlg(g);
51726
51924
  splineEdgesShifted(g);
51727
51925
  finaliseCoords(g);
51728
51926
  }
@@ -51731,7 +51929,7 @@ function layoutMulti(g, comps, globalRoot, pinfo) {
51731
51929
  layoutComponent(g, sg, globalRoot);
51732
51930
  finaliseCoords(sg);
51733
51931
  }
51734
- twopiCleanup(g);
51932
+ twopiFreeAlg(g);
51735
51933
  packSubgraphs(comps.length, comps, g, pinfo);
51736
51934
  splineEdgesShifted(g);
51737
51935
  finaliseCoords(g);
@@ -52135,7 +52333,18 @@ function fdpInitNodeEdge(g) {
52135
52333
  }
52136
52334
  initialPositions3(g);
52137
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
+ }
52138
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);
52139
52348
  for (const n of g.nodes.values()) {
52140
52349
  n.info.alg = void 0;
52141
52350
  n.info.pos = void 0;
@@ -53079,7 +53288,7 @@ function expandCluster2(n, cg) {
53079
53288
  }
53080
53289
 
53081
53290
  // src/layout/fdp/layout.ts
53082
- var POINTS_PER_INCH11 = 72;
53291
+ var POINTS_PER_INCH12 = 72;
53083
53292
  var DEFAULT_NODEWIDTH_PTS = 54;
53084
53293
  var DEFAULT_NODEHEIGHT_PTS = 36;
53085
53294
  function initInfo(g) {
@@ -53174,7 +53383,7 @@ function shiftComponents(cc, pts, pt) {
53174
53383
  } else {
53175
53384
  p = pt;
53176
53385
  }
53177
- 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 };
53178
53387
  for (const n of cc[i].nodes.values()) {
53179
53388
  n.info.pos[0] += del.x;
53180
53389
  n.info.pos[1] += del.y;
@@ -53190,8 +53399,8 @@ function finalCC(g, cc, pts, rg, infop) {
53190
53399
  const pt = applyMarginAndBorder(rg, bb, margin);
53191
53400
  if (cc.length > 0) shiftComponents(cc, pts, pt);
53192
53401
  gdata(g).bb = {
53193
- ll: { x: bb.ll.x / POINTS_PER_INCH11, y: bb.ll.y / POINTS_PER_INCH11 },
53194
- 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 }
53195
53404
  };
53196
53405
  }
53197
53406
  function applyMarginAndBorder(rg, bb, margin) {
@@ -53237,8 +53446,8 @@ function translateOwnNodes(g, bb) {
53237
53446
  function setBB(g) {
53238
53447
  const bb = gdata(g).bb;
53239
53448
  g.info.bb = {
53240
- ll: { x: POINTS_PER_INCH11 * bb.ll.x, y: POINTS_PER_INCH11 * bb.ll.y },
53241
- 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 }
53242
53451
  };
53243
53452
  const nClusters = g.info.n_cluster ?? 0;
53244
53453
  for (let i = 0; i < nClusters; i++) {
@@ -53253,8 +53462,8 @@ function setClustNodes(root) {
53253
53462
  const bb = gdata(p).bb;
53254
53463
  const w = bb.ur.x - bb.ll.x;
53255
53464
  const h = bb.ur.y - bb.ll.y;
53256
- const w2 = POINTS_PER_INCH11 * (w / 2);
53257
- const h2 = POINTS_PER_INCH11 * (h / 2);
53465
+ const w2 = POINTS_PER_INCH12 * (w / 2);
53466
+ const h2 = POINTS_PER_INCH12 * (h / 2);
53258
53467
  n.info.pos[0] = w / 2;
53259
53468
  n.info.pos[1] = h / 2;
53260
53469
  n.info.width = w;
@@ -53263,7 +53472,7 @@ function setClustNodes(root) {
53263
53472
  n.info.outline_width = w + penwidth;
53264
53473
  n.info.outline_height = h + penwidth;
53265
53474
  n.info.lw = n.info.rw = w2;
53266
- n.info.ht = POINTS_PER_INCH11 * h;
53475
+ n.info.ht = POINTS_PER_INCH12 * h;
53267
53476
  const poly = n.info.shape_info;
53268
53477
  if (poly && poly.vertices) {
53269
53478
  poly.vertices[0] = { x: w2, y: h2 };
@@ -53276,8 +53485,8 @@ function setClustNodes(root) {
53276
53485
  function syncCoordFromPos(cg) {
53277
53486
  for (const n of cg.nodes.values()) {
53278
53487
  n.info.coord = {
53279
- x: POINTS_PER_INCH11 * n.info.pos[0],
53280
- 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]
53281
53490
  };
53282
53491
  }
53283
53492
  }
@@ -53289,8 +53498,8 @@ function expandComponentClusters(cg, infop, counter) {
53289
53498
  if (r !== 0) return r;
53290
53499
  n.info.width = gdata(sg).bb.ur.x;
53291
53500
  n.info.height = gdata(sg).bb.ur.y;
53292
- const ptx = POINTS_PER_INCH11 * gdata(sg).bb.ur.x;
53293
- 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;
53294
53503
  n.info.rw = n.info.lw = ptx / 2;
53295
53504
  n.info.ht = pty;
53296
53505
  } else if (isPort(n)) {
@@ -54940,6 +55149,9 @@ function circoLayoutFull(g) {
54940
55149
  gvPostprocess(g);
54941
55150
  }
54942
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);
54943
55155
  g.info.alg = void 0;
54944
55156
  g.info.neato_nlist = void 0;
54945
55157
  }
@@ -55227,11 +55439,17 @@ function osageLayout(g) {
55227
55439
  }
55228
55440
  function cleanupGraphs(g) {
55229
55441
  const nClust = g.info.n_cluster ?? 0;
55230
- 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
+ }
55231
55447
  g.info.clust = void 0;
55232
55448
  g.info.n_cluster = void 0;
55233
55449
  }
55234
55450
  function osageCleanup(g) {
55451
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
55452
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
55235
55453
  for (const n of g.nodes.values()) {
55236
55454
  if (n.info.alg?.kind === "osage") n.info.alg = void 0;
55237
55455
  }
@@ -55582,6 +55800,9 @@ function patchworkEngineLayout(g) {
55582
55800
  gvPostprocess(g);
55583
55801
  }
55584
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);
55585
55806
  g.info.clust = void 0;
55586
55807
  g.info.n_cluster = void 0;
55587
55808
  for (const n of g.nodes.values()) {
@@ -56281,7 +56502,7 @@ var PlainExtRenderer = class {
56281
56502
  }
56282
56503
  };
56283
56504
  function mapGraphName(g) {
56284
- return g.anonymous ? "%1" : g.name;
56505
+ return agNameOf(g);
56285
56506
  }
56286
56507
  function graphAttr2(g, key) {
56287
56508
  for (let s = g; s !== null; s = s.parent) {
@@ -58620,8 +58841,8 @@ function latin1Reencode(s) {
58620
58841
  for (const b of bytes) out += String.fromCharCode(b);
58621
58842
  return out;
58622
58843
  }
58623
- function buildJson(g, doXDot) {
58624
- const draws = doXDot ? collectDrawLookup(g) : void 0;
58844
+ function buildJson(g, doXDot, preDraws) {
58845
+ const draws = doXDot ? preDraws ?? collectDrawLookup(g) : void 0;
58625
58846
  const ctx = assignIds(g, doXDot, draws);
58626
58847
  const root = buildGraphObject(g, true, ctx);
58627
58848
  return JSON.stringify(root, null, 2) + "\n";
@@ -58658,10 +58879,15 @@ var JsonRenderer = class {
58658
58879
  type = "json";
58659
58880
  /** @see plugin/core/gvplugin_core.c registration table */
58660
58881
  quality = 0;
58661
- 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);
58662
58887
  }
58663
58888
  endGraph(g, job) {
58664
- job.write(buildJson(g, true));
58889
+ job.write(buildJson(g, true, this.draws));
58890
+ this.draws = void 0;
58665
58891
  }
58666
58892
  beginNode(_n, _job) {
58667
58893
  }
@@ -59409,16 +59635,16 @@ function isDoomedNode(node) {
59409
59635
  return BANNED_ELEMENTS.has(localNameOf(node)) || isHostileAnimation(node);
59410
59636
  }
59411
59637
  function scrubSvgDocument(doc) {
59412
- const pending = [doc];
59413
- while (pending.length > 0) {
59414
- const parent2 = pending.pop();
59638
+ const pending2 = [doc];
59639
+ while (pending2.length > 0) {
59640
+ const parent2 = pending2.pop();
59415
59641
  const children = Array.from(parent2.childNodes);
59416
59642
  for (const child of children) {
59417
59643
  if (isDoomedNode(child)) {
59418
59644
  parent2.removeChild(child);
59419
59645
  } else if (child.nodeType === ELEMENT_NODE) {
59420
59646
  scrubAttributes(child);
59421
- pending.push(child);
59647
+ pending2.push(child);
59422
59648
  }
59423
59649
  }
59424
59650
  }