@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/render.js CHANGED
@@ -5105,7 +5105,9 @@ var WHITESPACE = /* @__PURE__ */ new Set([9, 10, 11, 12, 13]);
5105
5105
  var OCTAL_WIDTH = 3;
5106
5106
  var OCTAL_RADIX = 8;
5107
5107
  var lastLevel = "warning";
5108
+ var pending = { line: null, channel: "warn" };
5108
5109
  registerRenderState(() => {
5110
+ flushPending();
5109
5111
  lastLevel = "warning";
5110
5112
  });
5111
5113
  function escapeControl(message) {
@@ -5119,17 +5121,43 @@ function escapeControl(message) {
5119
5121
  return out;
5120
5122
  }
5121
5123
  function agerrLineOn(channel, line) {
5124
+ flushPending();
5125
+ writeLine(channel, line);
5126
+ }
5127
+ function flushPending() {
5128
+ if (pending.line === null) return;
5129
+ const { line, channel } = pending;
5130
+ pending.line = null;
5131
+ writeLine(channel, line);
5132
+ }
5133
+ function writeLine(channel, line) {
5122
5134
  if (channel === "warn") console.warn(escapeControl(line));
5123
5135
  else console.error(escapeControl(line));
5124
5136
  }
5125
- function agerr(level, msg, channel) {
5126
- if (level === "prev") {
5127
- agerrLineOn(channel ?? (lastLevel === "warning" ? "warn" : "error"), msg);
5128
- return;
5129
- }
5130
- lastLevel = level;
5137
+ function assemble(level, msg) {
5138
+ if (level === "prev") return msg;
5131
5139
  const prefix = level === "error" ? PREFIX_ERROR : PREFIX_WARNING;
5132
- agerrLineOn(channel ?? (level === "warning" ? "warn" : "error"), `${prefix}${PREFIX_SEP}${msg}`);
5140
+ return `${prefix}${PREFIX_SEP}${msg}`;
5141
+ }
5142
+ function channelOf(level) {
5143
+ const eff = level === "prev" ? lastLevel : level;
5144
+ return eff === "warning" ? "warn" : "error";
5145
+ }
5146
+ function emit(level, msg, channel, hold) {
5147
+ const target = channel ?? channelOf(level);
5148
+ if (level !== "prev") lastLevel = level;
5149
+ const text = assemble(level, msg);
5150
+ if (pending.line === null) {
5151
+ pending.channel = target;
5152
+ pending.line = text;
5153
+ } else pending.line += text;
5154
+ if (!hold) flushPending();
5155
+ }
5156
+ function agerr(level, msg, channel) {
5157
+ emit(level, msg, channel, false);
5158
+ }
5159
+ function agerrPartial(level, msg, channel) {
5160
+ emit(level, msg, channel, true);
5133
5161
  }
5134
5162
  var agerrorf = (msg, channel) => agerr("error", msg, channel);
5135
5163
  var agwarningf = (msg, channel) => agerr("warning", msg, channel);
@@ -5744,8 +5772,8 @@ function checkAttrs(tag, pairs) {
5744
5772
  return { attrs, warnings, warn };
5745
5773
  }
5746
5774
  var StderrLines = class {
5747
- constructor(writeLine) {
5748
- this.writeLine = writeLine;
5775
+ constructor(writeLine2) {
5776
+ this.writeLine = writeLine2;
5749
5777
  }
5750
5778
  writeLine;
5751
5779
  pending = "";
@@ -6099,6 +6127,15 @@ var NAME_CHAR = /[\w.:\u0080-
6099
6127
  var DEC_DIGIT = /[0-9]/;
6100
6128
  var HEX_DIGIT = /[0-9A-Fa-f]/;
6101
6129
  var NON_XML = /[\x00-\x08\x0b\x0c\x0e-\x1f]/;
6130
+ var NON_XML_BEYOND_ASCII = /[\ufffe\uffff]/;
6131
+ var HIGH_SURROGATE = /[\ud800-\udbff]/;
6132
+ var LOW_SURROGATE = /[\udc00-\udfff]/;
6133
+ function isNonXmlAt(text, k) {
6134
+ const c = text[k];
6135
+ if (NON_XML.test(c) || NON_XML_BEYOND_ASCII.test(c)) return true;
6136
+ if (HIGH_SURROGATE.test(c)) return !LOW_SURROGATE.test(text[k + 1] ?? "");
6137
+ return LOW_SURROGATE.test(c) && !HIGH_SURROGATE.test(text[k - 1] ?? "");
6138
+ }
6102
6139
  function scanDigits(text, i, digit) {
6103
6140
  if (i >= text.length) return { partial: true };
6104
6141
  if (!digit.test(text[i])) return { invalid: i };
@@ -6126,7 +6163,7 @@ function scanAttValue(text, j) {
6126
6163
  const c = text[k];
6127
6164
  if (c === void 0) return { partial: true };
6128
6165
  if (c === q) return { close: k };
6129
- if (c === "<" || NON_XML.test(c)) return { invalid: k };
6166
+ if (c === "<" || isNonXmlAt(text, k)) return { invalid: k };
6130
6167
  if (c !== "&") {
6131
6168
  k++;
6132
6169
  continue;
@@ -7412,6 +7449,26 @@ function imageIsSupplied(name, sizer, resolver) {
7412
7449
  function imageOpenWarning(name) {
7413
7450
  return `${STRERROR_ENOENT} while opening ${name}`;
7414
7451
  }
7452
+ var DEFAULT_DPI = 96;
7453
+ var POINTS_PER_INCH = 72;
7454
+ function usershapeDpi(attrs) {
7455
+ const lateDouble2 = (s, dflt) => {
7456
+ if (s === void 0 || s === "") return dflt;
7457
+ const v = Number(s);
7458
+ return Number.isNaN(v) || s.trim() === "" ? dflt : Math.max(v, 0);
7459
+ };
7460
+ const dpi = lateDouble2(attrs.get("dpi"), lateDouble2(attrs.get("resolution"), 0));
7461
+ return dpi >= 1 ? dpi : DEFAULT_DPI;
7462
+ }
7463
+ function usershapeSizePts(name, dpi, sizer) {
7464
+ if (name === void 0 || name === "") return null;
7465
+ const px = sizer !== void 0 ? sizer(name) : findImageSize(name);
7466
+ if (px === null) return null;
7467
+ return {
7468
+ x: Math.trunc(px.w * POINTS_PER_INCH / dpi),
7469
+ y: Math.trunc(px.h * POINTS_PER_INCH / dpi)
7470
+ };
7471
+ }
7415
7472
 
7416
7473
  // src/common/pointset.ts
7417
7474
  function cmpPair(a, b) {
@@ -7706,15 +7763,15 @@ var sizeTextContent = (texts, measurer, env = defaultSizeEnv()) => {
7706
7763
  return { w, h };
7707
7764
  };
7708
7765
  var missingImages = { set: /* @__PURE__ */ new WeakSet() };
7709
- var sizeHtmlImg = (img, { imageSizer, stderr }) => {
7766
+ var sizeHtmlImg = (img, { imageSizer, imageResolver, imageDpi, stderr }) => {
7710
7767
  if (img.width !== void 0 && img.height !== void 0) return missingImages.set.has(img) ? 1 : 0;
7711
- const sz = imageSizer !== void 0 ? imageSizer(img.src) : findImageSize(img.src);
7768
+ const sz = usershapeSizePts(img.src, imageDpi ?? DEFAULT_DPI, imageSizer);
7712
7769
  if (sz !== null) {
7713
- img.width = sz.w;
7714
- img.height = sz.h;
7770
+ img.width = sz.x;
7771
+ img.height = sz.y;
7715
7772
  return 0;
7716
7773
  }
7717
- if (!imageIsSupplied(img.src, imageSizer)) agerrLine(stderr, `Warning: ${imageOpenWarning(img.src)}`);
7774
+ if (!imageIsSupplied(img.src, imageSizer, imageResolver)) agerrLine(stderr, `Warning: ${imageOpenWarning(img.src)}`);
7718
7775
  agerrLine(stderr, `Error: No or improper image file="${img.src}"`);
7719
7776
  img.width = 0;
7720
7777
  img.height = 0;
@@ -8201,7 +8258,7 @@ function posHtmlLabel(label, finfo, measurer) {
8201
8258
  // src/common/htmltable-label.ts
8202
8259
  var HTML_PARSE_FATAL = 3;
8203
8260
  function makeHtmlLabelTo(content, finfo, measurer, stderr) {
8204
- const { fontname, fontsize, fontcolor, imageSizer, pencolor } = finfo;
8261
+ const { fontname, fontsize, fontcolor, imageSizer, imageResolver, imageDpi, pencolor } = finfo;
8205
8262
  let lbl, lexWarn;
8206
8263
  try {
8207
8264
  ({ label: lbl, warn: lexWarn } = parseHtmlLabelRv(content, stderr));
@@ -8215,6 +8272,8 @@ function makeHtmlLabelTo(content, finfo, measurer, stderr) {
8215
8272
  fontsize,
8216
8273
  fontname,
8217
8274
  imageSizer,
8275
+ imageResolver,
8276
+ imageDpi,
8218
8277
  stderr
8219
8278
  });
8220
8279
  const placed = posHtmlLabel(lbl, { fontname, fontsize, fontcolor }, measurer);
@@ -8873,9 +8932,12 @@ function makeLabel(text, fontname, fontsize, fontcolor, measurer) {
8873
8932
  }
8874
8933
  function makeAnyLabel(content, isHtml, font, measurer, obj) {
8875
8934
  if (isHtml && content !== "") {
8876
- const imageSizer = obj !== void 0 ? rootOf(obj).info.gvc?.imageSizer : void 0;
8935
+ const root = obj !== void 0 ? rootOf(obj) : void 0;
8936
+ const imageSizer = root?.info.gvc?.imageSizer;
8937
+ const imageResolver = root?.info.gvc?.imageResolver;
8938
+ const imageDpi = root !== void 0 ? usershapeDpi(root.attrs) : void 0;
8877
8939
  const stderr = labelStderr();
8878
- const { label, rv } = makeHtmlLabelTo(content, { ...font, pencolor: getPenColor(obj), imageSizer }, measurer, stderr);
8940
+ const { label, rv } = makeHtmlLabelTo(content, { ...font, pencolor: getPenColor(obj), imageSizer, imageResolver, imageDpi }, measurer, stderr);
8879
8941
  if (rv !== 0 && obj !== void 0) stderr.write(`${inLabelOf(obj)}
8880
8942
  `);
8881
8943
  stderr.flush();
@@ -9083,6 +9145,9 @@ function otherEdge(e) {
9083
9145
  var SPLIT = 134217729;
9084
9146
  function fma(a, b, c) {
9085
9147
  const p = a * b;
9148
+ if (!Number.isFinite(p) || !Number.isFinite(c)) {
9149
+ return Number.isFinite(a) && Number.isFinite(b) && !Number.isFinite(c) ? c : p + c;
9150
+ }
9086
9151
  const at = SPLIT * a;
9087
9152
  const ahi = at - (at - a);
9088
9153
  const alo = a - ahi;
@@ -9472,7 +9537,7 @@ function cwrotatepf(p, cwrot) {
9472
9537
  function boxOverlap(b0, b1) {
9473
9538
  return b0.ur.x >= b1.ll.x && b1.ur.x >= b0.ll.x && b0.ur.y >= b1.ll.y && b1.ur.y >= b0.ll.y;
9474
9539
  }
9475
- var POINTS_PER_INCH = 72;
9540
+ var POINTS_PER_INCH2 = 72;
9476
9541
 
9477
9542
  // src/common/arrows-shapes-poly.ts
9478
9543
  var CROW_ARROWWIDTH = 0.45;
@@ -12249,7 +12314,8 @@ function polySize(p) {
12249
12314
  const init = initialSizePts(p);
12250
12315
  const dimen = quantize(padLabelDimen(p.labelDimen, p.margin, p.isPlain), p.quantumIn);
12251
12316
  const { sides: sides2, isBox: isBox4 } = effectiveShape(p);
12252
- let bb = { x: dimen.x, y: dimen.y };
12317
+ const img = p.imageSize ?? { x: 0, y: 0 };
12318
+ let bb = { x: Math.max(dimen.x, img.x), y: Math.max(dimen.y, img.y) };
12253
12319
  if (isBox4) {
12254
12320
  } else if (p.optionShape === STAR) {
12255
12321
  bb = starSize(bb);
@@ -12278,7 +12344,7 @@ function labelSpace(p, dimen, bb, minBb, isBox4, fixedshape) {
12278
12344
  } else {
12279
12345
  spaceX = dimen.x - spacex;
12280
12346
  }
12281
- const spaceY = fixedshape ? dimen.y : dimen.y + (bb.y - minBb.y);
12347
+ const spaceY = fixedshape ? dimen.y : dimen.y + (bb.y - minBb.y + Math.max(0, (p.imageSize?.y ?? 0) - dimen.y));
12282
12348
  return { space: { x: spaceX, y: spaceY }, valign: labelValign(p) };
12283
12349
  }
12284
12350
  function effectiveShape(p) {
@@ -12730,6 +12796,15 @@ function warnMissingImage(n, g, shapefile) {
12730
12796
  agwarningf(imageOpenWarning(image));
12731
12797
  agwarningf(`No or improper image="${image}" for node "${n.name}"`);
12732
12798
  }
12799
+ function nodeImageSize(n, g) {
12800
+ const shapefile = nodeAttr(n, g, "shapefile");
12801
+ if (shapefile !== void 0 && shapefile !== "") return void 0;
12802
+ const gvc = g.root.info.gvc;
12803
+ const sz = usershapeSizePts(nodeAttr(n, g, "image"), usershapeDpi(g.root.attrs), gvc?.imageSizer);
12804
+ if (sz === null) return void 0;
12805
+ g.root.info.has_images = true;
12806
+ return { x: sz.x + 2, y: sz.y + 2 };
12807
+ }
12733
12808
  function polyInit(n, g, measurer) {
12734
12809
  const shapeName2 = nodeAttr(n, g, "shape") ?? "ellipse";
12735
12810
  const shapefile = nodeAttr(n, g, "shapefile");
@@ -12759,6 +12834,7 @@ function claimWarned() {
12759
12834
  return true;
12760
12835
  }
12761
12836
  var claimNever = () => false;
12837
+ var MSG_MANY_COLORS = "More than 2 colors specified for a gradient - ignoring remaining";
12762
12838
  var EPS = 1e-5;
12763
12839
  function aeq0(x) {
12764
12840
  return x < EPS && x > -EPS;
@@ -12824,8 +12900,8 @@ function scanSegs(colorlist, claim) {
12824
12900
  function parseSegs(colorlist, context) {
12825
12901
  const result = scanSegs(colorlist, claimWarned);
12826
12902
  if (result.error === 3) {
12827
- const tail = context === void 0 ? "" : context();
12828
- agwarningf(`Total size > 1 in "${colorlist}" color spec ${tail}`);
12903
+ agerrPartial("warning", `Total size > 1 in "${colorlist}" color spec `);
12904
+ if (context !== void 0) agerr("prev", context());
12829
12905
  } else if (result.error === 2) {
12830
12906
  agerrorf(`Illegal value in "${colorlist}" color attribute; float expected after ';'`);
12831
12907
  if (context !== void 0) agerr("prev", context());
@@ -12859,10 +12935,6 @@ var BOX_ORIENTATION_TOLERANCE = 0.5;
12859
12935
  var BOX_ORIENTATION_STEP = 90;
12860
12936
  var BOX_SIDES = 4;
12861
12937
  var ELLIPSE_MAX_SIDES = 2;
12862
- function styleName(token) {
12863
- const paren = token.indexOf("(");
12864
- return paren < 0 ? token : token.slice(0, paren);
12865
- }
12866
12938
  function gvrenderSetStyle(styles) {
12867
12939
  if (styles === null) return;
12868
12940
  for (const token of styles) {
@@ -15823,6 +15895,13 @@ function firstColor(name) {
15823
15895
  }
15824
15896
  function resolveRenderColor(raw, report = true) {
15825
15897
  if (raw === "" || raw === "none") return { type: "none" };
15898
+ return resolveColorName(raw, report);
15899
+ }
15900
+ function resolveFillColorName(raw, report = true) {
15901
+ if (raw === "none") return { type: "none" };
15902
+ return resolveColorName(raw, report);
15903
+ }
15904
+ function resolveColorName(raw, report) {
15826
15905
  const known = KNOWN_COLORS.has(raw.toLowerCase());
15827
15906
  if (known && (rendererColors.hasKnownList || !report)) return { type: "string", s: raw };
15828
15907
  const color = { type: "rgba", r: 0, g: 0, b: 0, a: 0 };
@@ -15936,7 +16015,7 @@ function reportEdgeColors(e) {
15936
16015
  reportColorNames(edgeGraphicsColors({
15937
16016
  color,
15938
16017
  fillcolor: e.attrs.get("fillcolor") ?? "",
15939
- tapered: styleTokens2(e.attrs.get("style")).includes("tapered"),
16018
+ tapered: styleTokensQuiet(e.attrs.get("style")).includes("tapered"),
15940
16019
  arrows: spl.list.map((bz) => ({ sflag: bz.sflag !== 0, eflag: bz.eflag !== 0 }))
15941
16020
  }));
15942
16021
  }
@@ -16291,11 +16370,7 @@ function applyClusterGradient(obj, fill) {
16291
16370
  obj.gradientAngle = fill.angle;
16292
16371
  }
16293
16372
  function clusterAttr(sg, key) {
16294
- for (let g = sg; g !== null; g = g.parent) {
16295
- const v = g.attrs.get(key);
16296
- if (v !== void 0) return v;
16297
- }
16298
- return void 0;
16373
+ return graphAttrInherited(sg, key);
16299
16374
  }
16300
16375
  function clusterStyle(sg) {
16301
16376
  return clusterAttr(sg, "style");
@@ -16330,12 +16405,10 @@ function applyClusterObjState(sg, job) {
16330
16405
  if (job.obj === null) return false;
16331
16406
  const obj = job.obj;
16332
16407
  gvrenderSetStyle(checkClusterStyleTokens(styleTokens2(clusterStyle(sg))));
16333
- return withColorScheme(clusterAttr(sg, "colorscheme"), () => {
16334
- const filled = applyClusterFill(obj, fillRes);
16335
- applyClusterPenState(obj, sg);
16336
- reportColorNames(stripedClusterColors(sg));
16337
- return filled;
16338
- });
16408
+ const filled = applyClusterFill(obj, fillRes);
16409
+ applyClusterPenState(obj, sg);
16410
+ reportColorNames(stripedClusterColors(sg));
16411
+ return filled;
16339
16412
  }
16340
16413
  function isStripedCluster(sg) {
16341
16414
  const flags = parseStyleFlags(clusterStyle(sg));
@@ -16356,27 +16429,25 @@ function stripedClusterColors(sg) {
16356
16429
  return segs.flatMap((seg2) => seg2.color !== null && seg2.t > 0 ? [seg2.color] : []);
16357
16430
  }
16358
16431
  function renderStripedClusterBox(sg, renderer, job) {
16359
- withColorScheme(clusterAttr(sg, "colorscheme"), () => {
16360
- const { ll, ur } = sg.info.bb;
16361
- const af = [
16362
- { x: ll.x, y: ll.y },
16363
- { x: ur.x, y: ll.y },
16364
- { x: ur.x, y: ur.y },
16365
- { x: ll.x, y: ur.y }
16366
- ].map((p) => transformPoint(p, job));
16367
- const obj = job.obj;
16368
- const savedFill = obj?.fill;
16369
- if (obj !== null && savedFill !== void 0) obj.fill = 1 /* Solid */;
16370
- stripedBox(job, af, stripedFillSpec(sg), false, renderer, () => `in cluster ${sg.name}`);
16371
- if (obj !== null && savedFill !== void 0) obj.fill = savedFill;
16372
- const rawPts = [
16373
- { x: ll.x, y: ll.y },
16374
- { x: ll.x, y: ur.y },
16375
- { x: ur.x, y: ur.y },
16376
- { x: ur.x, y: ll.y }
16377
- ];
16378
- renderer.polygon(rawPts.map((p) => transformPoint(p, job)), false, job);
16379
- });
16432
+ const { ll, ur } = sg.info.bb;
16433
+ const af = [
16434
+ { x: ll.x, y: ll.y },
16435
+ { x: ur.x, y: ll.y },
16436
+ { x: ur.x, y: ur.y },
16437
+ { x: ll.x, y: ur.y }
16438
+ ].map((p) => transformPoint(p, job));
16439
+ const obj = job.obj;
16440
+ const savedFill = obj?.fill;
16441
+ if (obj !== null && savedFill !== void 0) obj.fill = 1 /* Solid */;
16442
+ stripedBox(job, af, stripedFillSpec(sg), false, renderer, () => `in cluster ${sg.name}`);
16443
+ if (obj !== null && savedFill !== void 0) obj.fill = savedFill;
16444
+ const rawPts = [
16445
+ { x: ll.x, y: ll.y },
16446
+ { x: ll.x, y: ur.y },
16447
+ { x: ur.x, y: ur.y },
16448
+ { x: ur.x, y: ll.y }
16449
+ ];
16450
+ renderer.polygon(rawPts.map((p) => transformPoint(p, job)), false, job);
16380
16451
  }
16381
16452
  function applyClusterFill(obj, fillRes) {
16382
16453
  if (fillRes.kind === "none") {
@@ -17344,6 +17415,10 @@ function ncross(ctx) {
17344
17415
 
17345
17416
  // src/model/cgraph-ops.ts
17346
17417
  var LOCALNAMEPREFIX = "%";
17418
+ var ANONYMOUS_ROOT_ID = 1;
17419
+ function agNameOf(g) {
17420
+ return g.anonymous ? `${LOCALNAMEPREFIX}${ANONYMOUS_ROOT_ID}` : g.name;
17421
+ }
17347
17422
  function freshNodeId(root) {
17348
17423
  let max = -1;
17349
17424
  for (const n of root.nodes.values()) {
@@ -18552,7 +18627,7 @@ var CHAR_UTF8 = 0;
18552
18627
  var CHAR_LATIN1 = 1;
18553
18628
  var CHAR_BIG5 = 2;
18554
18629
  function points(inches) {
18555
- return cround(inches * POINTS_PER_INCH);
18630
+ return cround(inches * POINTS_PER_INCH2);
18556
18631
  }
18557
18632
  function findCharset(g) {
18558
18633
  const raw = g.attrs.get("charset");
@@ -18747,7 +18822,24 @@ function removeFill(g) {
18747
18822
  }
18748
18823
  agdelsubg(g.root, sg);
18749
18824
  }
18825
+ function gvCleanupEdgeLabels(e) {
18826
+ e.info.label = void 0;
18827
+ e.info.xlabel = void 0;
18828
+ e.info.head_label = void 0;
18829
+ e.info.tail_label = void 0;
18830
+ }
18831
+ function gvCleanupNodeLabels(n) {
18832
+ n.info.label = void 0;
18833
+ n.info.xlabel = void 0;
18834
+ }
18835
+ function dotCleanupGraph(g) {
18836
+ for (const subg of g.subgraphs.values()) dotCleanupGraph(subg);
18837
+ if (g !== g.root) g.info.label = void 0;
18838
+ }
18750
18839
  function dotCleanup(g) {
18840
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
18841
+ for (const n2 of g.nodes.values()) gvCleanupNodeLabels(n2);
18842
+ dotCleanupGraph(g);
18751
18843
  let n = g.info.nlist;
18752
18844
  while (n !== void 0) {
18753
18845
  const next = n.info.next;
@@ -19225,7 +19317,7 @@ var DEFAULT_NODEWIDTH = 0.75;
19225
19317
  var MIN_NODEWIDTH = 0.01;
19226
19318
  var DEFAULT_NODEHEIGHT = 0.5;
19227
19319
  var MIN_NODEHEIGHT = 0.02;
19228
- var POINTS_PER_INCH2 = 72;
19320
+ var POINTS_PER_INCH3 = 72;
19229
19321
  var DEF_POINT = 0.05;
19230
19322
  var MIN_POINT = 3e-4;
19231
19323
  var DEFAULT_NODEPENWIDTH2 = 1;
@@ -19293,6 +19385,8 @@ function polySizeParamsFromNode(n, g, shape, labelDimen, flip) {
19293
19385
  // size_gen discriminant (STAR/CYLINDER)
19294
19386
  nojustify: mapbool4(nodeAttr(n, g, "nojustify")),
19295
19387
  // shapes.c:2133
19388
+ imageSize: nodeImageSize(n, g),
19389
+ // shapes.c:2039-2051
19296
19390
  flip
19297
19391
  };
19298
19392
  }
@@ -19329,7 +19423,7 @@ function initPointSize(n, g, shape) {
19329
19423
  const flip = g.root.info.flip === true;
19330
19424
  const peripheries = lateInt(nodeAttr(n, g, "peripheries"), shape.polygon.peripheries, 0);
19331
19425
  const penwidth = lateDouble(nodeAttr(n, g, "penwidth"), DEFAULT_NODEPENWIDTH2, MIN_NODEPENWIDTH);
19332
- const sz0 = pointWidthInches(n, g) * POINTS_PER_INCH2;
19426
+ const sz0 = pointWidthInches(n, g) * POINTS_PER_INCH3;
19333
19427
  storeNodeSize(n, pointSizeResult(sz0, peripheries, penwidth), flip);
19334
19428
  assignShapeInfo(n, { ...shape.polygon, peripheries, sides: 2, penwidth, vertices: null });
19335
19429
  }
@@ -19386,8 +19480,8 @@ function storeNodeSize(n, unflipped, flip) {
19386
19480
  n.info.base_width = unflipped.baseW / 72;
19387
19481
  n.info.base_height = unflipped.baseH / 72;
19388
19482
  const size = gvNodesize(
19389
- n.info.width * POINTS_PER_INCH2,
19390
- n.info.height * POINTS_PER_INCH2,
19483
+ n.info.width * POINTS_PER_INCH3,
19484
+ n.info.height * POINTS_PER_INCH3,
19391
19485
  flip
19392
19486
  );
19393
19487
  n.info.lw = size.lw;
@@ -20564,7 +20658,7 @@ var SIZE_X_RE2 = new RegExp(`^\\s*(${FLOAT})(.?)`);
20564
20658
  var PAD_XY_RE = new RegExp(`^\\s*(${FLOAT})\\s*,\\s*(${FLOAT})`);
20565
20659
  var PAD_X_RE = new RegExp(`^\\s*(${FLOAT})`);
20566
20660
  function toPoints(inches) {
20567
- return cround(inches * POINTS_PER_INCH);
20661
+ return cround(inches * POINTS_PER_INCH2);
20568
20662
  }
20569
20663
  function parseDrawingSize(raw) {
20570
20664
  if (raw === void 0) return null;
@@ -20585,11 +20679,11 @@ function parseGraphPad(raw) {
20585
20679
  if (raw !== void 0) {
20586
20680
  const xy = PAD_XY_RE.exec(raw);
20587
20681
  if (xy) {
20588
- return { x: Number(xy[1]) * POINTS_PER_INCH, y: Number(xy[2]) * POINTS_PER_INCH };
20682
+ return { x: Number(xy[1]) * POINTS_PER_INCH2, y: Number(xy[2]) * POINTS_PER_INCH2 };
20589
20683
  }
20590
20684
  const x = PAD_X_RE.exec(raw);
20591
20685
  if (x) {
20592
- const v = Number(x[1]) * POINTS_PER_INCH;
20686
+ const v = Number(x[1]) * POINTS_PER_INCH2;
20593
20687
  return { x: v, y: v };
20594
20688
  }
20595
20689
  }
@@ -20599,11 +20693,11 @@ function parseGraphMargin(raw) {
20599
20693
  if (raw !== void 0) {
20600
20694
  const xy = PAD_XY_RE.exec(raw);
20601
20695
  if (xy) {
20602
- return { x: Number(xy[1]) * POINTS_PER_INCH, y: Number(xy[2]) * POINTS_PER_INCH };
20696
+ return { x: Number(xy[1]) * POINTS_PER_INCH2, y: Number(xy[2]) * POINTS_PER_INCH2 };
20603
20697
  }
20604
20698
  const x = PAD_X_RE.exec(raw);
20605
20699
  if (x) {
20606
- const v = Number(x[1]) * POINTS_PER_INCH;
20700
+ const v = Number(x[1]) * POINTS_PER_INCH2;
20607
20701
  return { x: v, y: v };
20608
20702
  }
20609
20703
  }
@@ -20969,10 +21063,13 @@ function parseLayers(g) {
20969
21063
  let listSep = g.attrs.get("layerlistsep") || DEFAULT_LAYERLISTSEP;
20970
21064
  if ([...sep].some((c) => listSep.includes(c))) listSep = "";
20971
21065
  if (p === void 0 || p === "") {
20972
- return { layerIDs: [], numLayers: 1, sep, listSep };
21066
+ return { layerIDs: [], numLayers: 1, sep, listSep, layerList: null };
20973
21067
  }
20974
21068
  const toks = splitOnSet(p, sep);
20975
- return { layerIDs: [null, ...toks], numLayers: toks.length, sep, listSep };
21069
+ const info = { layerIDs: [null, ...toks], numLayers: toks.length, sep, listSep, layerList: null };
21070
+ const sel = g.attrs.get("layerselect");
21071
+ if (sel !== void 0 && sel !== "") info.layerList = parseLayerselect(info, sel);
21072
+ return info;
20976
21073
  }
20977
21074
  function isNaturalNumber(s) {
20978
21075
  return /^[0-9]+$/.test(s);
@@ -21028,6 +21125,19 @@ function edgeInLayer(info, layerNum, e) {
21028
21125
  return pn === "" || selectedLayer(info, layerNum, pn);
21029
21126
  });
21030
21127
  }
21128
+ function parseLayerselect(info, p) {
21129
+ const picked = [];
21130
+ for (let i = 1; i <= info.numLayers; i++) {
21131
+ if (selectedLayer(info, i, p)) picked.push(i);
21132
+ }
21133
+ if (picked.length === 0) {
21134
+ agwarningf(
21135
+ `The layerselect attribute "${p}" does not match any layer specifed by the layers attribute - ignored.`
21136
+ );
21137
+ return null;
21138
+ }
21139
+ return [picked.length, ...picked, info.numLayers + 1];
21140
+ }
21031
21141
 
21032
21142
  // src/gvc/emit-walk.ts
21033
21143
  function nodeShown(info, job, n, g) {
@@ -21090,9 +21200,40 @@ var NATIVE_LANGNAME = /* @__PURE__ */ new Map([
21090
21200
  ["cmapx-np", "cmapx_np"],
21091
21201
  ["imap-np", "imap_np"]
21092
21202
  ]);
21093
- function warnLayersUnsupported(format, numLayers, doesLayers) {
21094
- if (numLayers <= 1 || doesLayers) return;
21095
- agwarningf(`layers not supported in ${NATIVE_LANGNAME.get(format) ?? format} output`);
21203
+ function warnUnsupported(job) {
21204
+ agwarningf(`layers not supported in ${NATIVE_LANGNAME.get(job.format) ?? job.format} output`);
21205
+ }
21206
+ function numPhysicalLayers(job, info) {
21207
+ return info.layerList !== null ? info.layerList[0] : job.numLayers;
21208
+ }
21209
+ function firstLayer(job, info, doesLayers) {
21210
+ job.numLayers = info.numLayers;
21211
+ const list = info.layerList;
21212
+ if (list !== null) {
21213
+ if (list[0] > 1 && !doesLayers) {
21214
+ warnUnsupported(job);
21215
+ list[2] = job.numLayers + 1;
21216
+ }
21217
+ job.layerNum = list[1];
21218
+ return { list, pos: 2 };
21219
+ }
21220
+ if (job.numLayers > 1 && !doesLayers) {
21221
+ warnUnsupported(job);
21222
+ job.numLayers = 1;
21223
+ }
21224
+ job.layerNum = 1;
21225
+ return { list: null, pos: 0 };
21226
+ }
21227
+ function validLayer(job) {
21228
+ return job.layerNum <= job.numLayers;
21229
+ }
21230
+ function nextLayer(job, cur) {
21231
+ if (cur.list !== null) {
21232
+ job.layerNum = cur.list[cur.pos];
21233
+ cur.pos++;
21234
+ } else {
21235
+ job.layerNum++;
21236
+ }
21096
21237
  }
21097
21238
 
21098
21239
  // src/gvc/device-labels.ts
@@ -21226,7 +21367,7 @@ function renderNode(n, renderer, job, done) {
21226
21367
  job.popObj();
21227
21368
  }
21228
21369
  }
21229
- function setEdgePen(e, job) {
21370
+ function setEdgePen(e, job, styles) {
21230
21371
  if (job.obj === null) return;
21231
21372
  const obj = job.obj;
21232
21373
  const flags = parseStyleFlags(e.attrs.get("style"));
@@ -21236,24 +21377,24 @@ function setEdgePen(e, job) {
21236
21377
  );
21237
21378
  obj.pen = resolvePenType(flags);
21238
21379
  obj.penWidth = resolvePenWidth(flags, e.attrs.get("penwidth"));
21239
- obj.rawStyle = styleTokens2(e.attrs.get("style"));
21380
+ obj.rawStyle = [...styles];
21240
21381
  if (e.info.spl !== void 0) gvrenderSetStyle(obj.rawStyle);
21241
21382
  }
21242
21383
  function renderEdge(e, renderer, job) {
21243
21384
  emitEdgeComments(e, renderer, job);
21244
21385
  const edgeStyle = e.attrs.get("style");
21386
+ const styles = styleTokens2(edgeStyle);
21245
21387
  if (parseStyleFlags(edgeStyle).invis || styleHasInvisibleAlias(edgeStyle)) return;
21246
21388
  const obj = createObjState(3 /* Edge */);
21247
21389
  obj.emitState = 9 /* EDraw */;
21248
21390
  job.pushObj(obj);
21249
- setEdgePen(e, job);
21391
+ setEdgePen(e, job, styles);
21250
21392
  try {
21251
21393
  setHtmlAnchorObj(svgEdgeId(e, job), labelTextOf2(e.info.label), job.obj ?? void 0);
21252
21394
  resolveEdgeAnchor(e, svgEdgeId(e, job), obj);
21253
21395
  withColorScheme(e.attrs.get("colorscheme"), () => {
21254
21396
  renderer.beginEdge(e, job);
21255
21397
  reportEdgeColors(e);
21256
- const styles = styleTokens2(e.attrs.get("style"));
21257
21398
  for (let i = edgeStyleResets(e, styles); i > 0; i--) gvrenderSetStyle(styles);
21258
21399
  reportEdgeLabelColors(e);
21259
21400
  renderer.endEdge(e, job);
@@ -21280,6 +21421,22 @@ function renderClusterBox(sg, filled, renderer, job) {
21280
21421
  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 }];
21281
21422
  renderer.polygon(rawPts.map((p) => transformPoint(p, job)), filled, job);
21282
21423
  }
21424
+ function drawClusterInScheme(sg, renderer, job) {
21425
+ const filled = applyClusterObjState(sg, job);
21426
+ renderer.beginCluster?.(sg, job);
21427
+ if (job.obj !== null) job.obj.id = svgClusterId(sg, job);
21428
+ setHtmlAnchorObj(svgClusterId(sg, job), labelTextOf2(sg.info.label), job.obj ?? void 0);
21429
+ if (job.obj !== null) {
21430
+ resolveObjAnchor(sg, labelTextOf2(sg.info.label), svgClusterId(sg, job), job.obj);
21431
+ }
21432
+ const anchored = beginAnchorIf(renderer, job);
21433
+ if ((clusterPeripheries(sg) !== 0 || filled || isStripedCluster(sg)) && job.obj?.pen !== 0 /* None */) {
21434
+ renderClusterBox(sg, filled, renderer, job);
21435
+ }
21436
+ renderClusterLabel(sg, renderer, job);
21437
+ if (anchored) renderer.endAnchor?.(job);
21438
+ renderer.endCluster?.(sg, job);
21439
+ }
21283
21440
  function renderOneCluster(sg, renderer, job) {
21284
21441
  const clustersLast = (job.flags & EMIT_CLUSTERS_LAST) !== 0;
21285
21442
  if (clustersLast) renderClusters(sg, renderer, job);
@@ -21287,20 +21444,7 @@ function renderOneCluster(sg, renderer, job) {
21287
21444
  obj.emitState = 1 /* CDraw */;
21288
21445
  job.pushObj(obj);
21289
21446
  try {
21290
- const filled = applyClusterObjState(sg, job);
21291
- renderer.beginCluster?.(sg, job);
21292
- if (job.obj !== null) job.obj.id = svgClusterId(sg, job);
21293
- setHtmlAnchorObj(svgClusterId(sg, job), labelTextOf2(sg.info.label), job.obj ?? void 0);
21294
- if (job.obj !== null) {
21295
- resolveObjAnchor(sg, labelTextOf2(sg.info.label), svgClusterId(sg, job), job.obj);
21296
- }
21297
- const anchored = beginAnchorIf(renderer, job);
21298
- if ((clusterPeripheries(sg) !== 0 || filled || isStripedCluster(sg)) && job.obj?.pen !== 0 /* None */) {
21299
- renderClusterBox(sg, filled, renderer, job);
21300
- }
21301
- renderClusterLabel(sg, renderer, job);
21302
- if (anchored) renderer.endAnchor?.(job);
21303
- renderer.endCluster?.(sg, job);
21447
+ withColorScheme(clusterAttr(sg, "colorscheme"), () => drawClusterInScheme(sg, renderer, job));
21304
21448
  } finally {
21305
21449
  job.popObj();
21306
21450
  }
@@ -21321,16 +21465,15 @@ function renderGraph(g, job, renderer) {
21321
21465
  job.pushObj(obj);
21322
21466
  try {
21323
21467
  const info = parseLayers(g);
21324
- const layered = renderer.beginLayer !== void 0 && info.numLayers > 1;
21325
- job.numLayers = layered ? info.numLayers : 1;
21468
+ job.layerNum = 0;
21326
21469
  job.layerIDs = info.layerIDs;
21327
21470
  renderer.beginGraph(g, job);
21328
- warnLayersUnsupported(job.format, info.numLayers, renderer.beginLayer !== void 0);
21329
- for (let ln = 1; ln <= job.numLayers; ln++) {
21330
- job.layerNum = ln;
21331
- if (layered) renderer.beginLayer(info.layerIDs[ln], job);
21471
+ const cur = firstLayer(job, info, renderer.beginLayer !== void 0);
21472
+ for (; validLayer(job); nextLayer(job, cur)) {
21473
+ const layered = numPhysicalLayers(job, info) > 1;
21474
+ if (layered) renderer.beginLayer?.(info.layerIDs[job.layerNum], job);
21332
21475
  renderPage(g, renderer, job, info);
21333
- if (layered) renderer.endLayer(job);
21476
+ if (layered) renderer.endLayer?.(job);
21334
21477
  }
21335
21478
  renderer.endGraph(g, job);
21336
21479
  } finally {
@@ -21374,9 +21517,9 @@ function render(ctx, g, format, inlineImages = false) {
21374
21517
  lateDouble(g.attrs.get("resolution"), 0, 0),
21375
21518
  0
21376
21519
  );
21377
- const jobDpi = drawingDpi > 0 ? drawingDpi : POINTS_PER_INCH;
21520
+ const jobDpi = drawingDpi > 0 ? drawingDpi : POINTS_PER_INCH2;
21378
21521
  job.dpi = { x: jobDpi, y: jobDpi };
21379
- const dpiScale = jobDpi / POINTS_PER_INCH;
21522
+ const dpiScale = jobDpi / POINTS_PER_INCH2;
21380
21523
  job.scale = { x: z * dpiScale, y: z * dpiScale };
21381
21524
  job.rotation = parseLandscape(g) ? 90 : 0;
21382
21525
  job.renderer = renderer;
@@ -21387,7 +21530,6 @@ function render(ctx, g, format, inlineImages = false) {
21387
21530
  }
21388
21531
 
21389
21532
  // src/common/htmltable-emit-fill.ts
21390
- var MSG_MANY_COLORS = "More than 2 colors specified for a gradient - ignoring remaining";
21391
21533
  function findHtmlStopColor(color, silent = false) {
21392
21534
  const { segs, error } = silent ? parseSegsSilent(color) : parseSegs(color);
21393
21535
  const first = segs[0];
@@ -21471,7 +21613,7 @@ function penTypeOf(style2) {
21471
21613
  return 3 /* Solid */;
21472
21614
  }
21473
21615
  function withHtmlPaint(paint, job, drawFn) {
21474
- paintObj.fillColor = paint.fill !== void 0 ? resolveRenderColor(firstColor(paint.fill)) : { type: "none" };
21616
+ paintObj.fillColor = paint.fill !== void 0 ? resolveFillColorName(firstColor(paint.fill)) : { type: "none" };
21475
21617
  paintObj.penColor = paint.pen !== void 0 ? resolveRenderColor(paint.pen) : { type: "string", s: "transparent" };
21476
21618
  applyHtmlFill(paint);
21477
21619
  paintObj.pen = penTypeOf(paint.penStyle);
@@ -21596,7 +21738,9 @@ function emitSidedPolylines(sides2, corners, renderer, job) {
21596
21738
  var HTML_DEFAULT_COLOR = "black";
21597
21739
  function bgNames(bgcolor) {
21598
21740
  const spec = parseGradientSpec(bgcolor);
21599
- return spec === null ? [bgcolor] : [spec[0], spec[1]];
21741
+ if (spec !== null) return [spec[0], spec[1]];
21742
+ if (parseSegsSilent(bgcolor).error !== 0 || firstColor(bgcolor) === "") return [];
21743
+ return [bgcolor];
21600
21744
  }
21601
21745
  function cellNames(cell2) {
21602
21746
  if (htmlStyle(cell2.style).invisible) return [];
@@ -21652,23 +21796,68 @@ function zeroFlags() {
21652
21796
  };
21653
21797
  }
21654
21798
  var FUNLIMIT = 64;
21799
+ var STYLE_SPACE = /* @__PURE__ */ new Set([" ", " ", "\n", "\v", "\f", "\r"]);
21800
+ function isStyleDelim(c) {
21801
+ return c === void 0 || c === "(" || c === ")" || c === ",";
21802
+ }
21803
+ function styleToken2(s, from) {
21804
+ let p = from;
21805
+ while (p < s.length && (STYLE_SPACE.has(s[p]) || s[p] === ",")) p++;
21806
+ if (p >= s.length) return null;
21807
+ if (s[p] === "(" || s[p] === ")") return { type: s[p], text: s[p], next: p + 1 };
21808
+ const start = p;
21809
+ while (!isStyleDelim(s[p])) p++;
21810
+ return { type: "id", text: s.slice(start, p), next: p };
21811
+ }
21812
+ var NO_TOKENS = [];
21813
+ function parseStyleQuiet(s) {
21814
+ const end = s.indexOf("\0");
21815
+ const str = end < 0 ? s : s.slice(0, end);
21816
+ const names = [];
21817
+ const args = [];
21818
+ let inParens = false;
21819
+ for (let c = styleToken2(str, 0); c !== null; c = styleToken2(str, c.next)) {
21820
+ if (c.type === "(") {
21821
+ if (inParens) return { tokens: NO_TOKENS, fault: "nesting" };
21822
+ inParens = true;
21823
+ } else if (c.type === ")") {
21824
+ if (!inParens) return { tokens: NO_TOKENS, fault: "unmatched-close" };
21825
+ inParens = false;
21826
+ } else if (inParens) {
21827
+ args[names.length - 1]?.push(c.text);
21828
+ } else {
21829
+ if (names.length === FUNLIMIT - 1) return { tokens: NO_TOKENS, fault: "truncate" };
21830
+ names.push(c.text);
21831
+ args.push([]);
21832
+ }
21833
+ }
21834
+ if (inParens) return { tokens: NO_TOKENS, fault: "unmatched-open" };
21835
+ const tokens = names.map((n, i) => args[i].length === 0 ? n : `${n}(${args[i].join(",")})`);
21836
+ return { tokens, fault: null };
21837
+ }
21838
+ function reportStyleFault(fault, s) {
21839
+ if (fault === "nesting") agerrorf(`nesting not allowed in style: ${s}`);
21840
+ else if (fault === "unmatched-close") agerrorf(`unmatched ')' in style: ${s}`);
21841
+ else if (fault === "unmatched-open") agerrorf(`unmatched '(' in style: ${s}`);
21842
+ else agwarningf(`truncating style '${s}'`);
21843
+ }
21655
21844
  function styleTokens2(style2) {
21656
21845
  if (!style2) return [];
21657
- const out = [];
21658
- let fun = 0;
21659
- for (const raw of style2.split(",")) {
21660
- const token = raw.trim();
21661
- if (token.length === 0) continue;
21662
- if (fun === FUNLIMIT - 1) return [];
21663
- fun++;
21664
- out.push(token);
21665
- }
21666
- return out;
21846
+ const { tokens, fault } = parseStyleQuiet(style2);
21847
+ if (fault !== null) reportStyleFault(fault, style2);
21848
+ return tokens;
21849
+ }
21850
+ function styleTokensQuiet(style2) {
21851
+ return style2 ? parseStyleQuiet(style2).tokens : [];
21852
+ }
21853
+ function styleName(token) {
21854
+ const paren = token.indexOf("(");
21855
+ return paren < 0 ? token : token.slice(0, paren);
21667
21856
  }
21668
21857
  function parseSetLineWidth(token) {
21669
- const m = /^setlinewidth\s*\(\s*([^)]*)\)\s*$/.exec(token);
21670
- if (m === null) return null;
21671
- const v = parseFloat(m[1]);
21858
+ if (styleName(token) !== "setlinewidth") return null;
21859
+ const m = /^[^(]*\(([^,)]*)/.exec(token);
21860
+ const v = m === null ? Number.NaN : parseFloat(m[1]);
21672
21861
  return Number.isNaN(v) ? 0 : v;
21673
21862
  }
21674
21863
  function applyToken(flags, token) {
@@ -21692,33 +21881,18 @@ function firstSolidColor(raw) {
21692
21881
  }
21693
21882
  function parseStyleFlags(style2) {
21694
21883
  const flags = zeroFlags();
21695
- if (!style2) return flags;
21696
- let fun = 0;
21697
- for (const raw of style2.split(",")) {
21698
- const token = raw.trim();
21699
- if (token.length === 0) continue;
21700
- if (fun === FUNLIMIT - 1) return zeroFlags();
21701
- fun++;
21884
+ for (const token of styleTokensQuiet(style2)) {
21702
21885
  const lw = parseSetLineWidth(token);
21703
21886
  if (lw !== null) {
21704
21887
  flags.setLineWidth = lw;
21705
21888
  continue;
21706
21889
  }
21707
- if (!token.includes("(")) applyToken(flags, token);
21890
+ applyToken(flags, styleName(token));
21708
21891
  }
21709
21892
  return flags;
21710
21893
  }
21711
21894
  function styleHasInvisibleAlias(style2) {
21712
- if (!style2) return false;
21713
- let fun = 0;
21714
- for (const raw of style2.split(",")) {
21715
- const token = raw.trim();
21716
- if (token.length === 0) continue;
21717
- if (fun === FUNLIMIT - 1) return false;
21718
- fun++;
21719
- if (token === "invisible") return true;
21720
- }
21721
- return false;
21895
+ return styleTokensQuiet(style2).some((token) => styleName(token) === "invisible");
21722
21896
  }
21723
21897
  function resolvePenType(flags) {
21724
21898
  if (flags.invis) return 0 /* None */;
@@ -21756,11 +21930,10 @@ function applyBgcolor(attrs, filled, fillcolor) {
21756
21930
  }
21757
21931
  function findStopColor(colorlist) {
21758
21932
  const { segs, error } = parseSegs(colorlist);
21759
- if (error === 1 || error === 2) return null;
21760
- if (segs.length < 2) return null;
21761
21933
  const seg0 = segs[0];
21762
21934
  const seg1 = segs[1];
21763
- if (seg0.color === null) return null;
21935
+ if (error !== 0 || seg0 === void 0 || seg1 === void 0 || seg0.color === null) return null;
21936
+ if (segs.length > 2) agwarningf(MSG_MANY_COLORS);
21764
21937
  const fillColor = seg0.color;
21765
21938
  const stopColor = seg1.color ?? DEFAULT_COLOR4;
21766
21939
  const frac = seg0.hasFraction ? seg0.t : seg1.hasFraction ? 1 - seg1.t : 0;
@@ -21773,7 +21946,7 @@ function parseAngle(gradientangle2) {
21773
21946
  }
21774
21947
  function buildResolvedFill(rawColor, flags, angle) {
21775
21948
  const stop = findStopColor(rawColor);
21776
- if (stop === null) return { kind: "solid", color: rawColor };
21949
+ if (stop === null) return { kind: "solid", color: rawColor.split(":", 1)[0] };
21777
21950
  const kind = flags.radial ? "radial" : "linear";
21778
21951
  return { kind, fillColor: stop.fillColor, stopColor: stop.stopColor, frac: stop.frac, angle };
21779
21952
  }
@@ -31157,6 +31330,20 @@ function addXLabels(gp) {
31157
31330
  runPlacement(gp);
31158
31331
  }
31159
31332
 
31333
+ // src/common/layout-state.ts
31334
+ var GVBEGIN = 0;
31335
+ var GVSPLINES = 1;
31336
+ var layoutState = { state: GVBEGIN };
31337
+ registerRenderState(() => {
31338
+ layoutState.state = GVBEGIN;
31339
+ });
31340
+ function getState() {
31341
+ return layoutState.state;
31342
+ }
31343
+ function setState(value) {
31344
+ layoutState.state = value;
31345
+ }
31346
+
31160
31347
  // src/common/postproc.ts
31161
31348
  var IGNORED_EDGE = 6;
31162
31349
  var Rankdir = 0;
@@ -31248,6 +31435,7 @@ function translateDrawing(g) {
31248
31435
  if (!shift && !Rankdir) return;
31249
31436
  for (const v of g.nodes.values()) {
31250
31437
  mapNode(v);
31438
+ if (getState() !== GVSPLINES) continue;
31251
31439
  for (const e of g.edges) {
31252
31440
  if (e.tail !== v) continue;
31253
31441
  if (e.info.spl === void 0) {
@@ -35237,6 +35425,7 @@ function orthoDispatch(g) {
35237
35425
  } else rc = dispatchOrthoEdges(g, false);
35238
35426
  if (rc !== 0) return rc;
35239
35427
  placePortLabels(g);
35428
+ setState(GVSPLINES);
35240
35429
  g.info.edgeLabelsDone = true;
35241
35430
  return 0;
35242
35431
  }
@@ -35251,6 +35440,7 @@ function finalizeSplines(g, et, normalize) {
35251
35440
  if (normalize) edgeNormalize(g);
35252
35441
  if (et !== EDGETYPE_CURVED) routeDotEdges(g);
35253
35442
  placePortLabels(g);
35443
+ setState(GVSPLINES);
35254
35444
  g.info.edgeLabelsDone = true;
35255
35445
  }
35256
35446
  function dotSplines_(g, normalize) {
@@ -36950,10 +37140,6 @@ function gvPermutation(bound) {
36950
37140
 
36951
37141
  // src/layout/neato/matrix-ops.ts
36952
37142
  var fr = Math.fround;
36953
- function fma2(a, b, c) {
36954
- const p = a * b;
36955
- return Number.isFinite(p) && Number.isFinite(c) ? fma(a, b, c) : p + c;
36956
- }
36957
37143
  function orthog1(n, vec) {
36958
37144
  let sum = 0;
36959
37145
  for (let i = 0; i < n; i++) sum += vec[i];
@@ -36982,10 +37168,6 @@ function rightMultWithVectorFF(m, n, vector, result) {
36982
37168
  function vectorsSubtractionF(n, v1, v2, result) {
36983
37169
  for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
36984
37170
  }
36985
- function vectorsMultAdditionF(n, v1, alpha, v2) {
36986
- const a = fr(alpha);
36987
- for (let i = 0; i < n; i++) v1[i] = v1[i] + fr(a * v2[i]);
36988
- }
36989
37171
  function vectorsInnerProductF(n, v1, v2) {
36990
37172
  let result = 0;
36991
37173
  for (let i = 0; i < n; i++) result += fr(v1[i] * v2[i]);
@@ -37026,11 +37208,11 @@ function innerProduct(n, v1, v2, block) {
37026
37208
  const blocked = block === BLOCK_NONE ? 0 : n - n % block;
37027
37209
  let i = 0;
37028
37210
  for (; i < blocked; i++) result += v1[i] * v2[i];
37029
- for (; i < n; i++) result = fma2(v1[i], v2[i], result);
37211
+ for (; i < n; i++) result = fma(v1[i], v2[i], result);
37030
37212
  return result;
37031
37213
  }
37032
37214
  function scadd(vec1, end, fac, vec2) {
37033
- for (let i = 0; i <= end; i++) vec1[i] = fma2(fac, vec2[i], vec1[i]);
37215
+ for (let i = 0; i <= end; i++) vec1[i] = fma(fac, vec2[i], vec1[i]);
37034
37216
  }
37035
37217
  function norm(vec, end, block) {
37036
37218
  return Math.sqrt(innerProduct(end + 1, vec, vec, block));
@@ -37062,7 +37244,7 @@ function rightMultWithVectorF(matrix, n, vector, result, block) {
37062
37244
  let res = 0;
37063
37245
  let j = 0;
37064
37246
  for (; j < blocked; j++) res += row[j] * vector[j];
37065
- for (; j < n; j++) res = fma2(row[j], vector[j], res);
37247
+ for (; j < n; j++) res = fma(row[j], vector[j], res);
37066
37248
  result[i] = res;
37067
37249
  }
37068
37250
  }
@@ -37070,7 +37252,7 @@ function rightMultWithVector(matrix, n, vector, result) {
37070
37252
  for (let i = 0; i < n; i++) {
37071
37253
  let res = 0;
37072
37254
  const row = matrix[i];
37073
- for (let j = 0; j < row.nedges; j++) res = fma2(row.ewgts[j], vector[row.edges[j]], res);
37255
+ for (let j = 0; j < row.nedges; j++) res = fma(row.ewgts[j], vector[row.edges[j]], res);
37074
37256
  result[i] = res;
37075
37257
  }
37076
37258
  }
@@ -37188,6 +37370,16 @@ function conjugateGradientF(A3, x, b, n, opts) {
37188
37370
  var TOLERANCE_CG = 1e-3;
37189
37371
  var DFLT_ITERATIONS = 200;
37190
37372
  var OPT_SMART_INIT = 4;
37373
+ var OPT_EXP_FLAG = 3;
37374
+ var EXP_NAME = "stresswt";
37375
+ function checkExp(g) {
37376
+ const exp = lateInt(g.attrs.get(EXP_NAME), 2, 0);
37377
+ if (exp === 0 || exp > 2) {
37378
+ agwarningf(`${EXP_NAME} attribute value must be 1 or 2 - ignoring`);
37379
+ return 2;
37380
+ }
37381
+ return exp;
37382
+ }
37191
37383
  function mdsModel(graph, nG) {
37192
37384
  if (graph[0].ewgts.length === 0) return null;
37193
37385
  const Dij = computeWeightedApspPacked(graph, nG);
@@ -37287,19 +37479,40 @@ function dijkstraSgd(graph, source, terms) {
37287
37479
 
37288
37480
  // src/layout/neato/edge-len.ts
37289
37481
  var DEFAULT_EDGE_LEN = 1;
37482
+ var DOUBLE_PREFIX = /^\s*([+-]?)(0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?|inf(?:inity)?|nan(?:\([\w]*\))?)/i;
37483
+ function scanDouble(s) {
37484
+ const m = DOUBLE_PREFIX.exec(s);
37485
+ if (m === null) return null;
37486
+ const body = m[2].toLowerCase();
37487
+ const sign2 = m[1] === "-" ? -1 : 1;
37488
+ if (body.startsWith("nan")) return Number.NaN;
37489
+ if (body.startsWith("inf")) return sign2 * Infinity;
37490
+ if (!body.startsWith("0x")) return sign2 * parseFloat(body);
37491
+ const [mant, exp] = body.slice(2).split("p");
37492
+ const [ip = "", fp = ""] = mant.split(".");
37493
+ const digits = parseInt(ip + fp || "0", 16);
37494
+ return sign2 * digits * 2 ** (Number(exp ?? 0) - 4 * fp.length);
37495
+ }
37290
37496
  function lenattr(ep, g) {
37291
37497
  const s = ep.attrs.get("len");
37292
37498
  if (s === void 0 || s === "") return DEFAULT_EDGE_LEN;
37293
- const val2 = /^\s*[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/.exec(s);
37294
- const len = val2 === null ? Number.NaN : parseFloat(val2[0]);
37295
- if (Number.isNaN(len) || len < 0 || len === 0) {
37296
- agwarningf(`bad edge len "${s}" in ${g.name} - setting to ${DEFAULT_EDGE_LEN.toFixed(2)}`);
37499
+ const len = scanDouble(s);
37500
+ if (len === null || len < 0 || len === 0) {
37501
+ agwarningf(`bad edge len "${s}" in ${agNameOf(g)} - setting to ${DEFAULT_EDGE_LEN.toFixed(2)}`);
37297
37502
  return DEFAULT_EDGE_LEN;
37298
37503
  }
37299
37504
  return len;
37300
37505
  }
37301
37506
  function setEdgeLen(g) {
37302
- for (const ep of g.edges) ep.info.dist = lenattr(ep, g);
37507
+ const out = buildOutEdgeIndex(g);
37508
+ let total = 0;
37509
+ for (const np of g.nodes.values()) {
37510
+ for (const ep of out.get(np) ?? []) {
37511
+ ep.info.dist = lenattr(ep, g);
37512
+ total += ep.info.dist;
37513
+ }
37514
+ }
37515
+ return total;
37303
37516
  }
37304
37517
 
37305
37518
  // src/util/mt19937.ts
@@ -37457,7 +37670,7 @@ function neatoMode(g) {
37457
37670
  if (str === void 0 || str === "") return MODE_MAJOR;
37458
37671
  const mode = modeByName().get(str);
37459
37672
  if (mode !== void 0) return mode;
37460
- agwarningf(`Illegal value ${str} for attribute "mode" in graph ${g.root.name} - ignored`);
37673
+ agwarningf(`Illegal value ${str} for attribute "mode" in graph ${agNameOf(g.root)} - ignored`);
37461
37674
  return MODE_MAJOR;
37462
37675
  }
37463
37676
  function checkMode(g, mode) {
@@ -37502,7 +37715,7 @@ function warnCircuitDisconnected(g) {
37502
37715
  circuitWarned.add(g.root);
37503
37716
  agerrLineOn(
37504
37717
  "warn",
37505
- `graph ${g.root.name} is disconnected. Hence, the circuit model
37718
+ `graph ${agNameOf(g.root)} is disconnected. Hence, the circuit model
37506
37719
  is undefined. Reverting to the shortest path model.
37507
37720
  Alternatively, consider running neato using -Gpack=true or decomposing
37508
37721
  the graph into connected components.`
@@ -38113,7 +38326,7 @@ function moveNode(st, m) {
38113
38326
  function solveModel(g, st) {
38114
38327
  for (let m = chooseNode(st); m >= 0; m = chooseNode(st)) moveNode(st, m);
38115
38328
  if (st.move === st.maxIter) {
38116
- agwarningf(`Max. iterations (${st.maxIter}) reached on graph ${g.name}`);
38329
+ agwarningf(`Max. iterations (${st.maxIter}) reached on graph ${agNameOf(g)}`);
38117
38330
  }
38118
38331
  }
38119
38332
  function mdsEdges(g, nodes, lens) {
@@ -38196,7 +38409,7 @@ function addNeighbours(g, np, entry, o) {
38196
38409
  if (ep.head === ep.tail) continue;
38197
38410
  const vp = ep.tail === np ? ep.head : ep.tail;
38198
38411
  const vid = vp.info.id;
38199
- const dist5 = o.haveLen ? lateDouble(ep.attrs.get("len"), 1, 0) : 1;
38412
+ const dist5 = o.haveLen ? ep.info.dist ?? 0 : 1;
38200
38413
  const idx = seen2.get(vid);
38201
38414
  if (idx !== void 0) {
38202
38415
  if (o.haveLen) entry.ewgts[idx] = Math.max(entry.ewgts[idx], dist5);
@@ -38738,7 +38951,7 @@ function matMultVecOrthog(mat, dim, vec, result, orthog) {
38738
38951
  let sum = 0;
38739
38952
  let j = 0;
38740
38953
  for (; j < blocked; j++) sum += row[j] * vec[j];
38741
- for (; j < dim; j++) sum = fma2(row[j], vec[j], sum);
38954
+ for (; j < dim; j++) sum = fma(row[j], vec[j], sum);
38742
38955
  result[i] = sum;
38743
38956
  }
38744
38957
  const alpha = -innerProduct(dim, result, orthog, BLOCK_MAT_MULT_ORTHOG);
@@ -38837,8 +39050,8 @@ function computeAvgs(Dij, n) {
38837
39050
  sumRow += row[j] * row[j];
38838
39051
  }
38839
39052
  for (; j < n; j++) {
38840
- sum = fma2(row[j], row[j], sum);
38841
- sumRow = fma2(row[j], row[j], sumRow);
39053
+ sum = fma(row[j], row[j], sum);
39054
+ sumRow = fma(row[j], row[j], sumRow);
38842
39055
  }
38843
39056
  rowAvg[i] = fr4(fr4(sumRow) / n);
38844
39057
  }
@@ -38851,7 +39064,7 @@ function computeBij(Dij, n) {
38851
39064
  for (let i = 0; i < n; i++) {
38852
39065
  for (let j = 0; j <= i; j++) {
38853
39066
  const fD = fr4(Dij[i][j]);
38854
- const t = fr4(fma2(-fD, fD, rowAvg[i]));
39067
+ const t = fr4(fma(-fD, fD, rowAvg[i]));
38855
39068
  Bij[i][j] = fr4(fr4(t + rowAvg[j]) - allAvg);
38856
39069
  Bij[j][i] = Bij[i][j];
38857
39070
  }
@@ -38883,8 +39096,8 @@ function scaleGivenCoords(Dij, n, x) {
38883
39096
  sum1 += t1 * f;
38884
39097
  sum2 += t2 * f;
38885
39098
  } else {
38886
- sum1 = fma2(t1, f, sum1);
38887
- sum2 = fma2(t2, f, sum2);
39099
+ sum1 = fma(t1, f, sum1);
39100
+ sum2 = fma(t2, f, sum2);
38888
39101
  }
38889
39102
  }
38890
39103
  }
@@ -38914,7 +39127,7 @@ function computeResidualDistances(Dij, n, x) {
38914
39127
  for (let j = 0; j < i; j++) {
38915
39128
  const t = posI - x[j];
38916
39129
  const d = Dij[i][j];
38917
- const diff = fma2(d, d, -(t * t));
39130
+ const diff = fma(d, d, -(t * t));
38918
39131
  const v = diff > 0 ? Math.sqrt(diff) : 0;
38919
39132
  Dij[i][j] = v;
38920
39133
  Dij[j][i] = v;
@@ -38971,8 +39184,6 @@ function imdsGivenDim(graph, n, givenCoords, newCoords, conjTol) {
38971
39184
 
38972
39185
  // src/layout/neato/stress-kernel.ts
38973
39186
  var fr5 = Math.fround;
38974
- var TOLERANCE_CG2 = 1e-3;
38975
- var OPT_EXP_FLAG = 2;
38976
39187
  function computeApspPacked2(graph, n) {
38977
39188
  const Dij = new Float32Array(n * (n + 1) / 2);
38978
39189
  const Di = new Int32Array(n);
@@ -39016,51 +39227,16 @@ function initLayout(n, dim, coords, nodes) {
39016
39227
  for (let d = 0; d < dim; d++) orthog1(n, coords[d]);
39017
39228
  return pinned;
39018
39229
  }
39019
- function cgStep(st, last) {
39020
- const { n } = st;
39021
- orthog1f(n, st.p);
39022
- orthog1f(n, st.x);
39023
- orthog1f(n, st.r);
39024
- rightMultWithVectorFF(st.A, n, st.p, st.Ap);
39025
- orthog1f(n, st.Ap);
39026
- const pAp = vectorsInnerProductF(n, st.p, st.Ap);
39027
- if (pAp === 0) return true;
39028
- const alpha = st.rR / pAp;
39029
- vectorsMultAdditionF(n, st.x, alpha, st.p);
39030
- if (!last) {
39031
- vectorsMultAdditionF(n, st.r, -alpha, st.Ap);
39032
- const rRNew = vectorsInnerProductF(n, st.r, st.r);
39033
- if (st.rR === 0) return false;
39034
- const betaF = fr5(rRNew / st.rR);
39035
- st.rR = rRNew;
39036
- for (let j = 0; j < n; j++) st.p[j] = fr5(betaF * st.p[j]) + st.r[j];
39037
- }
39038
- return true;
39039
- }
39040
- function conjugateGradientMkernel2(A3, x, b, n, tol, maxIterations) {
39041
- const st = {
39042
- A: A3,
39043
- x,
39044
- b,
39045
- n,
39046
- r: new Float32Array(n),
39047
- p: new Float32Array(n),
39048
- Ap: new Float32Array(n),
39049
- rR: 0
39050
- };
39051
- orthog1f(n, x);
39052
- orthog1f(n, b);
39053
- const Ax = new Float32Array(n);
39054
- rightMultWithVectorFF(A3, n, x, Ax);
39055
- orthog1f(n, Ax);
39056
- vectorsSubtractionF(n, b, Ax, st.r);
39057
- copyVectorF(n, st.r, st.p);
39058
- st.rR = vectorsInnerProductF(n, st.r, st.r);
39059
- for (let i = 0; i < maxIterations && maxAbsF(n, st.r) > tol; i++) {
39060
- if (!cgStep(st, i >= maxIterations - 1)) return -1;
39061
- }
39062
- return 0;
39063
- }
39230
+ var FUSED_OPS = {
39231
+ squareAdd: (tmp, acc) => fmaf(tmp, tmp, acc),
39232
+ rightMult: rightMultWithVectorFFFused,
39233
+ cg: conjugateGradientMkernelFused
39234
+ };
39235
+ var COLA_OPS = {
39236
+ squareAdd: (tmp, acc) => acc + fr5(tmp * tmp),
39237
+ rightMult: rightMultWithVectorFF,
39238
+ cg: conjugateGradientMkernelFused
39239
+ };
39064
39240
  function buildLap2(lap2, n, exp) {
39065
39241
  const lapLength = n * (n + 1) / 2;
39066
39242
  if (exp === 2) squareVec(lapLength, lap2);
@@ -39083,7 +39259,7 @@ function buildLap2(lap2, n, exp) {
39083
39259
  }
39084
39260
  }
39085
39261
  function buildLap1(lap1, lap2, coords, shape) {
39086
- const { n, dim, exp } = shape;
39262
+ const { n, dim, exp, ops } = shape;
39087
39263
  const lapLength = n * (n + 1) / 2;
39088
39264
  const degrees = new Float64Array(n);
39089
39265
  const distAccumulator = new Float32Array(n);
@@ -39096,7 +39272,7 @@ function buildLap1(lap1, lap2, coords, shape) {
39096
39272
  const ck = coords[k];
39097
39273
  for (let x = 0; x < len; x++) {
39098
39274
  const tmp = fr5(ck[i] + fr5(-1 * ck[i + 1 + x]));
39099
- distAccumulator[x] = distAccumulator[x] + fr5(tmp * tmp);
39275
+ distAccumulator[x] = ops.squareAdd(tmp, distAccumulator[x]);
39100
39276
  }
39101
39277
  }
39102
39278
  invertSqrtVec(len, distAccumulator);
@@ -39129,24 +39305,25 @@ function buildLap1(lap1, lap2, coords, shape) {
39129
39305
  function computeStress(st) {
39130
39306
  let stress = 0;
39131
39307
  for (let k = 0; k < st.dim; k++) {
39132
- rightMultWithVectorFF(st.lap1, st.n, st.coords[k], st.b[k]);
39308
+ st.ops.rightMult(st.lap1, st.n, st.coords[k], st.b[k]);
39133
39309
  stress += vectorsInnerProductF(st.n, st.coords[k], st.b[k]);
39134
39310
  }
39135
39311
  stress *= 2;
39136
39312
  stress += st.constantTerm;
39137
39313
  for (let k = 0; k < st.dim; k++) {
39138
- rightMultWithVectorFF(st.lap2, st.n, st.coords[k], st.tmpCoords);
39314
+ st.ops.rightMult(st.lap2, st.n, st.coords[k], st.tmpCoords);
39139
39315
  stress -= vectorsInnerProductF(st.n, st.coords[k], st.tmpCoords);
39140
39316
  }
39141
39317
  return stress;
39142
39318
  }
39143
39319
  function solveAxis(st, k, havePinned, nodes) {
39320
+ const cg = { tol: TOLERANCE_CG, maxIterations: st.n };
39144
39321
  if (!havePinned) {
39145
- return conjugateGradientMkernel2(st.lap2, st.coords[k], st.b[k], st.n, TOLERANCE_CG2, st.n);
39322
+ return st.ops.cg(st.lap2, st.coords[k], st.b[k], st.n, cg);
39146
39323
  }
39147
39324
  copyVectorF(st.n, st.coords[k], st.tmpCoords);
39148
- const rc = conjugateGradientMkernel2(st.lap2, st.tmpCoords, st.b[k], st.n, TOLERANCE_CG2, st.n);
39149
- if (rc < 0) return rc;
39325
+ const rc = st.ops.cg(st.lap2, st.tmpCoords, st.b[k], st.n, cg);
39326
+ if (rc !== 0) return rc;
39150
39327
  for (let i = 0; i < st.n; i++) {
39151
39328
  if (!isFixed(nodes[i])) st.coords[k][i] = st.tmpCoords[i];
39152
39329
  }
@@ -39177,20 +39354,21 @@ function stressMajorizationKDMkernel(Dij, n, dCoords, nodes, o) {
39177
39354
  coords,
39178
39355
  b: Array.from({ length: dim }, () => new Float32Array(n)),
39179
39356
  tmpCoords: new Float32Array(n),
39180
- constantTerm
39357
+ constantTerm,
39358
+ ops: o.cola === true ? COLA_OPS : FUSED_OPS
39181
39359
  };
39182
39360
  let oldStress = Number.MAX_VALUE;
39183
39361
  let converged = false;
39184
39362
  let iterations = 0;
39185
39363
  for (; iterations < maxi && !converged; iterations++) {
39186
- buildLap1(st.lap1, lap2, coords, { n, dim, exp });
39364
+ buildLap1(st.lap1, lap2, coords, { n, dim, exp, ops: st.ops });
39187
39365
  const newStress = computeStress(st);
39188
39366
  if (typeof process !== "undefined" && process.env["STRESS_DEBUG"] && iterations % 5 === 0) console.error(newStress.toFixed(3));
39189
39367
  const change = Math.abs(oldStress - newStress);
39190
39368
  converged = change / oldStress < o.epsilon || newStress < o.epsilon;
39191
39369
  oldStress = newStress;
39192
39370
  for (let k = 0; k < dim; k++) {
39193
- if (solveAxis(st, k, havePinned, nodes) < 0) return -1;
39371
+ if (solveAxis(st, k, havePinned, nodes) !== 0) return -1;
39194
39372
  }
39195
39373
  }
39196
39374
  for (let i = 0; i < dim; i++) {
@@ -39278,7 +39456,7 @@ function distanceKD(coords, dim, i, j) {
39278
39456
  let sum = 0;
39279
39457
  for (let k = 0; k < dim; k++) {
39280
39458
  const d = coords[k][i] - coords[k][j];
39281
- sum = fma2(d, d, sum);
39459
+ sum = fma(d, d, sum);
39282
39460
  }
39283
39461
  return Math.sqrt(sum);
39284
39462
  }
@@ -39455,10 +39633,10 @@ function stressMajorizationWithHierarchy(graph, n, dCoords, nodes, o) {
39455
39633
  }
39456
39634
 
39457
39635
  // src/common/utils-inputscale.ts
39458
- var POINTS_PER_INCH3 = 72;
39636
+ var POINTS_PER_INCH4 = 72;
39459
39637
  function getInputscale(g) {
39460
39638
  const d = lateDouble(g.root.attrs.get("inputscale"), -1, 0);
39461
- return d === 0 ? POINTS_PER_INCH3 : d;
39639
+ return d === 0 ? POINTS_PER_INCH4 : d;
39462
39640
  }
39463
39641
  function inputscaleDivisor(g) {
39464
39642
  const sc = getInputscale(g);
@@ -39466,7 +39644,7 @@ function inputscaleDivisor(g) {
39466
39644
  }
39467
39645
 
39468
39646
  // src/layout/neato/set-aspect.ts
39469
- var POINTS_PER_INCH4 = 72;
39647
+ var POINTS_PER_INCH5 = 72;
39470
39648
  function neatoRatioKind(g) {
39471
39649
  const p = g.attrs.get("ratio");
39472
39650
  if (p === void 0) return null;
@@ -39514,8 +39692,8 @@ function neatoTranslate(g) {
39514
39692
  const bb = g.info.bb;
39515
39693
  if (!bb) return;
39516
39694
  const ll = bb.ll;
39517
- const ox = ll.x / POINTS_PER_INCH4;
39518
- const oy = ll.y / POINTS_PER_INCH4;
39695
+ const ox = ll.x / POINTS_PER_INCH5;
39696
+ const oy = ll.y / POINTS_PER_INCH5;
39519
39697
  for (const n of g.nodes.values()) {
39520
39698
  if (!n.info.pos) n.info.pos = [0, 0];
39521
39699
  n.info.pos[0] = (n.info.pos[0] ?? 0) - ox;
@@ -39601,7 +39779,7 @@ var MODEL_CIRCUIT = 1;
39601
39779
  var MODEL_SUBSET = 2;
39602
39780
  var MODEL_MDS2 = 3;
39603
39781
  var DFLT_DIM = 2;
39604
- var POINTS_PER_INCH5 = 72;
39782
+ var POINTS_PER_INCH6 = 72;
39605
39783
  function neatoInitNode(n, dim = DFLT_DIM) {
39606
39784
  if (!n.info.pos || n.info.pos.length < dim) {
39607
39785
  const pos = [];
@@ -39662,15 +39840,17 @@ function solveStress(c, vtx, dCoords, nodeList) {
39662
39840
  dim: DFLT_DIM,
39663
39841
  opts,
39664
39842
  maxi,
39665
- epsilon
39843
+ epsilon,
39844
+ cola: mode === MODE_IPSEP
39666
39845
  });
39667
39846
  }
39668
39847
  function runMajorization(g, mode, model) {
39669
39848
  const nodeList = assignNodeIds2(g);
39849
+ setEdgeLen(g);
39670
39850
  const n = nodeList.length;
39671
39851
  const haveLen = graphHasLen(g);
39672
39852
  const init = checkStart(g, n, mode === MODE_HIER ? INIT_SELF : INIT_RANDOM);
39673
- const opts = init === INIT_SELF ? OPT_EXP_FLAG | OPT_SMART_INIT : OPT_EXP_FLAG;
39853
+ const opts = checkExp(g) | (init === INIT_SELF ? OPT_SMART_INIT : 0);
39674
39854
  const haveDir = mode === MODE_HIER || mode === MODE_IPSEP;
39675
39855
  const vtx = makeGraphDataC(g, nodeList, haveLen, haveDir, mode);
39676
39856
  const dCoords = [new Float64Array(n), new Float64Array(n)];
@@ -39700,12 +39880,14 @@ function neatoSetAspect(g) {
39700
39880
  const pos = n.info.pos;
39701
39881
  if (!pos) continue;
39702
39882
  n.info.coord = {
39703
- x: (pos[0] ?? 0) * POINTS_PER_INCH5,
39704
- y: (pos[1] ?? 0) * POINTS_PER_INCH5
39883
+ x: (pos[0] ?? 0) * POINTS_PER_INCH6,
39884
+ y: (pos[1] ?? 0) * POINTS_PER_INCH6
39705
39885
  };
39706
39886
  }
39707
39887
  }
39708
39888
  function neatoCleanup(g) {
39889
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
39890
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
39709
39891
  for (const [, n] of g.nodes) {
39710
39892
  n.info.pos = void 0;
39711
39893
  n.info.pinned = void 0;
@@ -41942,9 +42124,11 @@ function splineEdges(g) {
41942
42124
  coalesceEdges(g);
41943
42125
  if (edgetype === EDGETYPE_LINE) {
41944
42126
  RoutingHelper.straight(g, edgetype);
42127
+ setState(GVSPLINES);
41945
42128
  return;
41946
42129
  }
41947
42130
  splineEdgesImpl(g, esepFactor(g), edgetype);
42131
+ setState(GVSPLINES);
41948
42132
  }
41949
42133
  function computeBBFromPos(g) {
41950
42134
  const bb = {
@@ -44355,6 +44539,8 @@ function getPos(g, dim) {
44355
44539
  return pos;
44356
44540
  }
44357
44541
  function sfdpCleanup(g) {
44542
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
44543
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
44358
44544
  for (const n of g.nodes.values()) {
44359
44545
  n.info.pos = void 0;
44360
44546
  n.info.id = void 0;
@@ -45263,7 +45449,7 @@ var AM_PORTHOYX = 12;
45263
45449
  var SCALE = 10;
45264
45450
  var SCALE2 = SCALE / 2;
45265
45451
  var INT_MAX3 = 2147483647;
45266
- var POINTS_PER_INCH6 = 72;
45452
+ var POINTS_PER_INCH7 = 72;
45267
45453
  function cmpitem(a, b) {
45268
45454
  if (a < b) return -1;
45269
45455
  if (a > b) return 1;
@@ -45491,18 +45677,18 @@ function overlaps(p) {
45491
45677
  return false;
45492
45678
  }
45493
45679
  function initItem(n, margin) {
45494
- const x = cround(SCALE * (n.info.pos?.[0] ?? 0) * POINTS_PER_INCH6);
45495
- const y = cround(SCALE * (n.info.pos?.[1] ?? 0) * POINTS_PER_INCH6);
45680
+ const x = cround(SCALE * (n.info.pos?.[0] ?? 0) * POINTS_PER_INCH7);
45681
+ const y = cround(SCALE * (n.info.pos?.[1] ?? 0) * POINTS_PER_INCH7);
45496
45682
  const width2 = n.info.width ?? 0;
45497
45683
  const height2 = n.info.height ?? 0;
45498
45684
  let w2;
45499
45685
  let h2;
45500
45686
  if (margin.doAdd) {
45501
- w2 = d2i(SCALE * (cround(width2 / 2 * POINTS_PER_INCH6) + margin.x));
45502
- h2 = d2i(SCALE * (cround(height2 / 2 * POINTS_PER_INCH6) + margin.y));
45687
+ w2 = d2i(SCALE * (cround(width2 / 2 * POINTS_PER_INCH7) + margin.x));
45688
+ h2 = d2i(SCALE * (cround(height2 / 2 * POINTS_PER_INCH7) + margin.y));
45503
45689
  } else {
45504
- w2 = cround(margin.x * SCALE2 * width2 * POINTS_PER_INCH6);
45505
- h2 = cround(margin.y * SCALE2 * height2 * POINTS_PER_INCH6);
45690
+ w2 = cround(margin.x * SCALE2 * width2 * POINTS_PER_INCH7);
45691
+ h2 = cround(margin.y * SCALE2 * height2 * POINTS_PER_INCH7);
45506
45692
  }
45507
45693
  return {
45508
45694
  val: 0,
@@ -45537,8 +45723,8 @@ function cAdjust(g, mode) {
45537
45723
  if (!overlaps(nlist)) return 0;
45538
45724
  runPlan(g, nlist, PLANS.get(mode) ?? PLANS.get(AM_PORTHO));
45539
45725
  for (const p of nlist) {
45540
- const x = p.pos.x / POINTS_PER_INCH6 / SCALE;
45541
- const y = p.pos.y / POINTS_PER_INCH6 / SCALE;
45726
+ const x = p.pos.x / POINTS_PER_INCH7 / SCALE;
45727
+ const y = p.pos.y / POINTS_PER_INCH7 / SCALE;
45542
45728
  if (p.np.info.pos) {
45543
45729
  p.np.info.pos[0] = x;
45544
45730
  p.np.info.pos[1] = y;
@@ -45553,10 +45739,10 @@ function cAdjust(g, mode) {
45553
45739
  var POLY_BOX = 1;
45554
45740
  var POLY_CIRCLE = 2;
45555
45741
  var DFLT_SAMPLE2 = 20;
45556
- var POINTS_PER_INCH7 = 72;
45742
+ var POINTS_PER_INCH8 = 72;
45557
45743
  var MIN_SAMPLES = 3;
45558
45744
  function ps2inch2(a) {
45559
- return a / POINTS_PER_INCH7;
45745
+ return a / POINTS_PER_INCH8;
45560
45746
  }
45561
45747
  function isBoxKind(p) {
45562
45748
  return (p.kind & POLY_BOX) !== 0;
@@ -45849,7 +46035,7 @@ function polyOverlap(p, pp, q, qp) {
45849
46035
  // src/layout/neato/adjust-info.ts
45850
46036
  var DEFAULT_VORO_MARGIN = 0.05;
45851
46037
  var INCR = 0.05;
45852
- var POINTS_PER_INCH8 = 72;
46038
+ var POINTS_PER_INCH9 = 72;
45853
46039
  function newInfoState() {
45854
46040
  return {
45855
46041
  nodeInfo: [],
@@ -45904,8 +46090,8 @@ function chkBoundBox(st, graph) {
45904
46090
  function makeInfo(st, graph) {
45905
46091
  const pmargin = { ...sepFactor(graph) };
45906
46092
  if (pmargin.doAdd) {
45907
- pmargin.x /= POINTS_PER_INCH8;
45908
- pmargin.y /= POINTS_PER_INCH8;
46093
+ pmargin.x /= POINTS_PER_INCH9;
46094
+ pmargin.y /= POINTS_PER_INCH9;
45909
46095
  }
45910
46096
  const polyf = pmargin.doAdd ? makeAddPoly : makePoly;
45911
46097
  const info = [];
@@ -46971,7 +47157,7 @@ function genYConstraints(rects, vs) {
46971
47157
  }
46972
47158
 
46973
47159
  // src/layout/neato/vpsc-adjust.ts
46974
- var POINTS_PER_INCH9 = 72;
47160
+ var POINTS_PER_INCH10 = 72;
46975
47161
  var X_PASS_SCALE = Math.fround(1.0001);
46976
47162
  function buildRects(c, size, gap, scale) {
46977
47163
  return size.map((s, i) => {
@@ -46996,8 +47182,8 @@ function solveAxis2(c, size, gap, axis) {
46996
47182
  function vpscAdjust(g) {
46997
47183
  const margin = sepFactor(g);
46998
47184
  const gap = {
46999
- x: 2 * (margin.doAdd ? margin.x : DFLT_MARGIN) / POINTS_PER_INCH9,
47000
- y: 2 * (margin.doAdd ? margin.y : DFLT_MARGIN) / POINTS_PER_INCH9
47185
+ x: 2 * (margin.doAdd ? margin.x : DFLT_MARGIN) / POINTS_PER_INCH10,
47186
+ y: 2 * (margin.doAdd ? margin.y : DFLT_MARGIN) / POINTS_PER_INCH10
47001
47187
  };
47002
47188
  const nodes = Array.from(g.nodes.values());
47003
47189
  const c = [new Float32Array(nodes.length), new Float32Array(nodes.length)];
@@ -47176,7 +47362,7 @@ function graphAdjustMode(g) {
47176
47362
  }
47177
47363
 
47178
47364
  // src/layout/twopi/init.ts
47179
- var POINTS_PER_INCH10 = 72;
47365
+ var POINTS_PER_INCH11 = 72;
47180
47366
  function makeRdata(INF) {
47181
47367
  return {
47182
47368
  kind: "twopi",
@@ -47228,19 +47414,24 @@ function finaliseCoords(g) {
47228
47414
  const pos = n.info.pos;
47229
47415
  if (!pos) continue;
47230
47416
  n.info.coord = {
47231
- x: (pos[0] ?? 0) * POINTS_PER_INCH10,
47232
- y: (pos[1] ?? 0) * POINTS_PER_INCH10
47417
+ x: (pos[0] ?? 0) * POINTS_PER_INCH11,
47418
+ y: (pos[1] ?? 0) * POINTS_PER_INCH11
47233
47419
  };
47234
47420
  }
47235
47421
  }
47236
47422
  function adjustNodes(g) {
47237
47423
  adjustNodesFull(g);
47238
47424
  }
47239
- function twopiCleanup(g) {
47425
+ function twopiFreeAlg(g) {
47240
47426
  const first = g.nodes.values().next().value;
47241
47427
  if (first !== void 0 && first.info.alg?.kind === "twopi") {
47242
47428
  first.info.alg = void 0;
47243
47429
  }
47430
+ }
47431
+ function twopiCleanup(g) {
47432
+ if (g.nodes.size === 0) return;
47433
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
47434
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
47244
47435
  g.info.neato_nlist = void 0;
47245
47436
  }
47246
47437
 
@@ -47509,7 +47700,7 @@ function layoutSingle(g, comps, globalRoot, setRoot) {
47509
47700
  if (setRoot && globalRoot === null && center !== null) {
47510
47701
  g.attrs.set("root", center.name);
47511
47702
  }
47512
- twopiCleanup(g);
47703
+ twopiFreeAlg(g);
47513
47704
  splineEdgesShifted(g);
47514
47705
  finaliseCoords(g);
47515
47706
  }
@@ -47518,7 +47709,7 @@ function layoutMulti(g, comps, globalRoot, pinfo) {
47518
47709
  layoutComponent(g, sg, globalRoot);
47519
47710
  finaliseCoords(sg);
47520
47711
  }
47521
- twopiCleanup(g);
47712
+ twopiFreeAlg(g);
47522
47713
  packSubgraphs(comps.length, comps, g, pinfo);
47523
47714
  splineEdgesShifted(g);
47524
47715
  finaliseCoords(g);
@@ -47922,7 +48113,18 @@ function fdpInitNodeEdge(g) {
47922
48113
  }
47923
48114
  initialPositions3(g);
47924
48115
  }
48116
+ function fdpCleanupSubgs(g) {
48117
+ const nClust = g.info.n_cluster ?? 0;
48118
+ for (let i = 1; i <= nClust; i++) {
48119
+ const subg = g.info.clust[i - 1];
48120
+ subg.info.label = void 0;
48121
+ fdpCleanupSubgs(subg);
48122
+ }
48123
+ }
47925
48124
  function fdpCleanup(g) {
48125
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
48126
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
48127
+ fdpCleanupSubgs(g);
47926
48128
  for (const n of g.nodes.values()) {
47927
48129
  n.info.alg = void 0;
47928
48130
  n.info.pos = void 0;
@@ -48866,7 +49068,7 @@ function expandCluster2(n, cg) {
48866
49068
  }
48867
49069
 
48868
49070
  // src/layout/fdp/layout.ts
48869
- var POINTS_PER_INCH11 = 72;
49071
+ var POINTS_PER_INCH12 = 72;
48870
49072
  var DEFAULT_NODEWIDTH_PTS = 54;
48871
49073
  var DEFAULT_NODEHEIGHT_PTS = 36;
48872
49074
  function initInfo(g) {
@@ -48961,7 +49163,7 @@ function shiftComponents(cc, pts, pt) {
48961
49163
  } else {
48962
49164
  p = pt;
48963
49165
  }
48964
- const del = { x: p.x / POINTS_PER_INCH11, y: p.y / POINTS_PER_INCH11 };
49166
+ const del = { x: p.x / POINTS_PER_INCH12, y: p.y / POINTS_PER_INCH12 };
48965
49167
  for (const n of cc[i].nodes.values()) {
48966
49168
  n.info.pos[0] += del.x;
48967
49169
  n.info.pos[1] += del.y;
@@ -48977,8 +49179,8 @@ function finalCC(g, cc, pts, rg, infop) {
48977
49179
  const pt = applyMarginAndBorder(rg, bb, margin);
48978
49180
  if (cc.length > 0) shiftComponents(cc, pts, pt);
48979
49181
  gdata(g).bb = {
48980
- ll: { x: bb.ll.x / POINTS_PER_INCH11, y: bb.ll.y / POINTS_PER_INCH11 },
48981
- ur: { x: bb.ur.x / POINTS_PER_INCH11, y: bb.ur.y / POINTS_PER_INCH11 }
49182
+ ll: { x: bb.ll.x / POINTS_PER_INCH12, y: bb.ll.y / POINTS_PER_INCH12 },
49183
+ ur: { x: bb.ur.x / POINTS_PER_INCH12, y: bb.ur.y / POINTS_PER_INCH12 }
48982
49184
  };
48983
49185
  }
48984
49186
  function applyMarginAndBorder(rg, bb, margin) {
@@ -49024,8 +49226,8 @@ function translateOwnNodes(g, bb) {
49024
49226
  function setBB(g) {
49025
49227
  const bb = gdata(g).bb;
49026
49228
  g.info.bb = {
49027
- ll: { x: POINTS_PER_INCH11 * bb.ll.x, y: POINTS_PER_INCH11 * bb.ll.y },
49028
- ur: { x: POINTS_PER_INCH11 * bb.ur.x, y: POINTS_PER_INCH11 * bb.ur.y }
49229
+ ll: { x: POINTS_PER_INCH12 * bb.ll.x, y: POINTS_PER_INCH12 * bb.ll.y },
49230
+ ur: { x: POINTS_PER_INCH12 * bb.ur.x, y: POINTS_PER_INCH12 * bb.ur.y }
49029
49231
  };
49030
49232
  const nClusters = g.info.n_cluster ?? 0;
49031
49233
  for (let i = 0; i < nClusters; i++) {
@@ -49040,8 +49242,8 @@ function setClustNodes(root) {
49040
49242
  const bb = gdata(p).bb;
49041
49243
  const w = bb.ur.x - bb.ll.x;
49042
49244
  const h = bb.ur.y - bb.ll.y;
49043
- const w2 = POINTS_PER_INCH11 * (w / 2);
49044
- const h2 = POINTS_PER_INCH11 * (h / 2);
49245
+ const w2 = POINTS_PER_INCH12 * (w / 2);
49246
+ const h2 = POINTS_PER_INCH12 * (h / 2);
49045
49247
  n.info.pos[0] = w / 2;
49046
49248
  n.info.pos[1] = h / 2;
49047
49249
  n.info.width = w;
@@ -49050,7 +49252,7 @@ function setClustNodes(root) {
49050
49252
  n.info.outline_width = w + penwidth;
49051
49253
  n.info.outline_height = h + penwidth;
49052
49254
  n.info.lw = n.info.rw = w2;
49053
- n.info.ht = POINTS_PER_INCH11 * h;
49255
+ n.info.ht = POINTS_PER_INCH12 * h;
49054
49256
  const poly = n.info.shape_info;
49055
49257
  if (poly && poly.vertices) {
49056
49258
  poly.vertices[0] = { x: w2, y: h2 };
@@ -49063,8 +49265,8 @@ function setClustNodes(root) {
49063
49265
  function syncCoordFromPos(cg) {
49064
49266
  for (const n of cg.nodes.values()) {
49065
49267
  n.info.coord = {
49066
- x: POINTS_PER_INCH11 * n.info.pos[0],
49067
- y: POINTS_PER_INCH11 * n.info.pos[1]
49268
+ x: POINTS_PER_INCH12 * n.info.pos[0],
49269
+ y: POINTS_PER_INCH12 * n.info.pos[1]
49068
49270
  };
49069
49271
  }
49070
49272
  }
@@ -49076,8 +49278,8 @@ function expandComponentClusters(cg, infop, counter) {
49076
49278
  if (r !== 0) return r;
49077
49279
  n.info.width = gdata(sg).bb.ur.x;
49078
49280
  n.info.height = gdata(sg).bb.ur.y;
49079
- const ptx = POINTS_PER_INCH11 * gdata(sg).bb.ur.x;
49080
- const pty = POINTS_PER_INCH11 * gdata(sg).bb.ur.y;
49281
+ const ptx = POINTS_PER_INCH12 * gdata(sg).bb.ur.x;
49282
+ const pty = POINTS_PER_INCH12 * gdata(sg).bb.ur.y;
49081
49283
  n.info.rw = n.info.lw = ptx / 2;
49082
49284
  n.info.ht = pty;
49083
49285
  } else if (isPort(n)) {
@@ -50727,6 +50929,9 @@ function circoLayoutFull(g) {
50727
50929
  gvPostprocess(g);
50728
50930
  }
50729
50931
  function circoCleanup(g) {
50932
+ if (g.nodes.size === 0) return;
50933
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
50934
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
50730
50935
  g.info.alg = void 0;
50731
50936
  g.info.neato_nlist = void 0;
50732
50937
  }
@@ -51014,11 +51219,17 @@ function osageLayout(g) {
51014
51219
  }
51015
51220
  function cleanupGraphs(g) {
51016
51221
  const nClust = g.info.n_cluster ?? 0;
51017
- for (let i = 1; i <= nClust; i++) cleanupGraphs(g.info.clust[i - 1]);
51222
+ for (let i = 1; i <= nClust; i++) {
51223
+ const subg = g.info.clust[i - 1];
51224
+ subg.info.label = void 0;
51225
+ cleanupGraphs(subg);
51226
+ }
51018
51227
  g.info.clust = void 0;
51019
51228
  g.info.n_cluster = void 0;
51020
51229
  }
51021
51230
  function osageCleanup(g) {
51231
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
51232
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
51022
51233
  for (const n of g.nodes.values()) {
51023
51234
  if (n.info.alg?.kind === "osage") n.info.alg = void 0;
51024
51235
  }
@@ -51369,6 +51580,9 @@ function patchworkEngineLayout(g) {
51369
51580
  gvPostprocess(g);
51370
51581
  }
51371
51582
  function patchworkEngineCleanup(g) {
51583
+ if (g.nodes.size === 0) return;
51584
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
51585
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
51372
51586
  g.info.clust = void 0;
51373
51587
  g.info.n_cluster = void 0;
51374
51588
  for (const n of g.nodes.values()) {
@@ -52068,7 +52282,7 @@ var PlainExtRenderer = class {
52068
52282
  }
52069
52283
  };
52070
52284
  function mapGraphName(g) {
52071
- return g.anonymous ? "%1" : g.name;
52285
+ return agNameOf(g);
52072
52286
  }
52073
52287
  function graphAttr2(g, key) {
52074
52288
  for (let s = g; s !== null; s = s.parent) {
@@ -52084,7 +52298,7 @@ function graphMapUrl(g) {
52084
52298
  function buildMapCtx(g, job, mapPolygon) {
52085
52299
  const drawingDpi = lateDouble(g.attrs.get("dpi"), lateDouble(g.attrs.get("resolution"), 0, 0), 0);
52086
52300
  const mapDpi = drawingDpi > 0 ? drawingDpi : 96;
52087
- const devscale = mapDpi / POINTS_PER_INCH;
52301
+ const devscale = mapDpi / POINTS_PER_INCH2;
52088
52302
  const z = initJobViewportZoom(job.bb, parseDrawingSize(g.attrs.get("size")), job.pad);
52089
52303
  const marginOff = { x: job.margin.x * devscale, y: job.margin.y * devscale };
52090
52304
  return { bb: job.bb, pad: job.pad, scale: z * devscale, marginOff, mapPolygon };
@@ -52570,8 +52784,8 @@ function graphLabelAttrs(g) {
52570
52784
  }
52571
52785
  return [
52572
52786
  'lp="' + lpStr(label.pos) + '"',
52573
- "lwidth=" + gfmt2(label.dimen.x / POINTS_PER_INCH),
52574
- "lheight=" + gfmt2(label.dimen.y / POINTS_PER_INCH)
52787
+ "lwidth=" + gfmt2(label.dimen.x / POINTS_PER_INCH2),
52788
+ "lheight=" + gfmt2(label.dimen.y / POINTS_PER_INCH2)
52575
52789
  ];
52576
52790
  }
52577
52791
  function edgePosRaw(e) {
@@ -58603,8 +58817,8 @@ function latin1Reencode(s) {
58603
58817
  for (const b of bytes) out += String.fromCharCode(b);
58604
58818
  return out;
58605
58819
  }
58606
- function buildJson(g, doXDot) {
58607
- const draws = doXDot ? collectDrawLookup(g) : void 0;
58820
+ function buildJson(g, doXDot, preDraws) {
58821
+ const draws = doXDot ? preDraws ?? collectDrawLookup(g) : void 0;
58608
58822
  const ctx = assignIds(g, doXDot, draws);
58609
58823
  const root = buildGraphObject(g, true, ctx);
58610
58824
  return JSON.stringify(root, null, 2) + "\n";
@@ -58641,10 +58855,15 @@ var JsonRenderer = class {
58641
58855
  type = "json";
58642
58856
  /** @see plugin/core/gvplugin_core.c registration table */
58643
58857
  quality = 0;
58644
- beginGraph(_g, _job) {
58858
+ draws;
58859
+ // set by beginGraph, cleared by endGraph
58860
+ /** @see plugin/core/gvrender_core_json.c:json_begin_graph */
58861
+ beginGraph(g, _job) {
58862
+ this.draws = collectDrawLookup(g);
58645
58863
  }
58646
58864
  endGraph(g, job) {
58647
- job.write(buildJson(g, true));
58865
+ job.write(buildJson(g, true, this.draws));
58866
+ this.draws = void 0;
58648
58867
  }
58649
58868
  beginNode(_n, _job) {
58650
58869
  }