@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/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);
@@ -5544,6 +5572,17 @@ function createMeasurer() {
5544
5572
  function setAspect(_g) {
5545
5573
  }
5546
5574
 
5575
+ // src/common/attr-get.ts
5576
+ function nodeAttr(n, g, key) {
5577
+ const own = n.attrs.get(key);
5578
+ if (own !== void 0) return own;
5579
+ if (n.nodeDefaultsSnapshot !== void 0) return n.nodeDefaultsSnapshot.get(key);
5580
+ return g.nodeDefaults.get(key) ?? (g !== g.root ? g.root.nodeDefaults.get(key) : void 0);
5581
+ }
5582
+ function graphAttrInherited(sg, key) {
5583
+ return sg.attrs.get(key) ?? sg.graphDefaultsSnapshot?.get(key);
5584
+ }
5585
+
5547
5586
  // src/common/htmltable-types.ts
5548
5587
  var HtmlParseError = class extends DotEngineError {
5549
5588
  type = "semantic";
@@ -5733,8 +5772,8 @@ function checkAttrs(tag, pairs) {
5733
5772
  return { attrs, warnings, warn };
5734
5773
  }
5735
5774
  var StderrLines = class {
5736
- constructor(writeLine) {
5737
- this.writeLine = writeLine;
5775
+ constructor(writeLine2) {
5776
+ this.writeLine = writeLine2;
5738
5777
  }
5739
5778
  writeLine;
5740
5779
  pending = "";
@@ -6088,6 +6127,15 @@ var NAME_CHAR = /[\w.:\u0080-
6088
6127
  var DEC_DIGIT = /[0-9]/;
6089
6128
  var HEX_DIGIT = /[0-9A-Fa-f]/;
6090
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
+ }
6091
6139
  function scanDigits(text, i, digit) {
6092
6140
  if (i >= text.length) return { partial: true };
6093
6141
  if (!digit.test(text[i])) return { invalid: i };
@@ -6115,7 +6163,7 @@ function scanAttValue(text, j) {
6115
6163
  const c = text[k];
6116
6164
  if (c === void 0) return { partial: true };
6117
6165
  if (c === q) return { close: k };
6118
- if (c === "<" || NON_XML.test(c)) return { invalid: k };
6166
+ if (c === "<" || isNonXmlAt(text, k)) return { invalid: k };
6119
6167
  if (c !== "&") {
6120
6168
  k++;
6121
6169
  continue;
@@ -7401,6 +7449,26 @@ function imageIsSupplied(name, sizer, resolver) {
7401
7449
  function imageOpenWarning(name) {
7402
7450
  return `${STRERROR_ENOENT} while opening ${name}`;
7403
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
+ }
7404
7472
 
7405
7473
  // src/common/pointset.ts
7406
7474
  function cmpPair(a, b) {
@@ -7695,15 +7763,15 @@ var sizeTextContent = (texts, measurer, env = defaultSizeEnv()) => {
7695
7763
  return { w, h };
7696
7764
  };
7697
7765
  var missingImages = { set: /* @__PURE__ */ new WeakSet() };
7698
- var sizeHtmlImg = (img, { imageSizer, stderr }) => {
7766
+ var sizeHtmlImg = (img, { imageSizer, imageResolver, imageDpi, stderr }) => {
7699
7767
  if (img.width !== void 0 && img.height !== void 0) return missingImages.set.has(img) ? 1 : 0;
7700
- const sz = imageSizer !== void 0 ? imageSizer(img.src) : findImageSize(img.src);
7768
+ const sz = usershapeSizePts(img.src, imageDpi ?? DEFAULT_DPI, imageSizer);
7701
7769
  if (sz !== null) {
7702
- img.width = sz.w;
7703
- img.height = sz.h;
7770
+ img.width = sz.x;
7771
+ img.height = sz.y;
7704
7772
  return 0;
7705
7773
  }
7706
- if (!imageIsSupplied(img.src, imageSizer)) agerrLine(stderr, `Warning: ${imageOpenWarning(img.src)}`);
7774
+ if (!imageIsSupplied(img.src, imageSizer, imageResolver)) agerrLine(stderr, `Warning: ${imageOpenWarning(img.src)}`);
7707
7775
  agerrLine(stderr, `Error: No or improper image file="${img.src}"`);
7708
7776
  img.width = 0;
7709
7777
  img.height = 0;
@@ -8190,7 +8258,7 @@ function posHtmlLabel(label, finfo, measurer) {
8190
8258
  // src/common/htmltable-label.ts
8191
8259
  var HTML_PARSE_FATAL = 3;
8192
8260
  function makeHtmlLabelTo(content, finfo, measurer, stderr) {
8193
- const { fontname, fontsize, fontcolor, imageSizer, pencolor } = finfo;
8261
+ const { fontname, fontsize, fontcolor, imageSizer, imageResolver, imageDpi, pencolor } = finfo;
8194
8262
  let lbl, lexWarn;
8195
8263
  try {
8196
8264
  ({ label: lbl, warn: lexWarn } = parseHtmlLabelRv(content, stderr));
@@ -8204,6 +8272,8 @@ function makeHtmlLabelTo(content, finfo, measurer, stderr) {
8204
8272
  fontsize,
8205
8273
  fontname,
8206
8274
  imageSizer,
8275
+ imageResolver,
8276
+ imageDpi,
8207
8277
  stderr
8208
8278
  });
8209
8279
  const placed = posHtmlLabel(lbl, { fontname, fontsize, fontcolor }, measurer);
@@ -8774,12 +8844,17 @@ var DEFAULT_FONTNAME = "Times-Roman";
8774
8844
  var DEFAULT_COLOR = "black";
8775
8845
  function getPenColor(obj) {
8776
8846
  if (obj === void 0) return void 0;
8777
- const pc = obj.attrs.get("pencolor");
8847
+ const pc = aggetObj(obj, "pencolor");
8778
8848
  if (pc !== void 0 && pc !== "") return pc;
8779
- const c = obj.attrs.get("color");
8849
+ const c = aggetObj(obj, "color");
8780
8850
  if (c !== void 0 && c !== "") return c;
8781
8851
  return void 0;
8782
8852
  }
8853
+ function aggetObj(obj, key) {
8854
+ if (obj instanceof Node) return nodeAttr(obj, obj.root, key);
8855
+ if (obj instanceof Graph) return graphAttrInherited(obj, key);
8856
+ return obj.attrs.get(key);
8857
+ }
8783
8858
  function rootOf(obj) {
8784
8859
  return obj instanceof Edge ? obj.tail.root : obj.root;
8785
8860
  }
@@ -8857,9 +8932,12 @@ function makeLabel(text, fontname, fontsize, fontcolor, measurer) {
8857
8932
  }
8858
8933
  function makeAnyLabel(content, isHtml, font, measurer, obj) {
8859
8934
  if (isHtml && content !== "") {
8860
- 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;
8861
8939
  const stderr = labelStderr();
8862
- 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);
8863
8941
  if (rv !== 0 && obj !== void 0) stderr.write(`${inLabelOf(obj)}
8864
8942
  `);
8865
8943
  stderr.flush();
@@ -9067,6 +9145,9 @@ function otherEdge(e) {
9067
9145
  var SPLIT = 134217729;
9068
9146
  function fma(a, b, c) {
9069
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
+ }
9070
9151
  const at = SPLIT * a;
9071
9152
  const ahi = at - (at - a);
9072
9153
  const alo = a - ahi;
@@ -9456,7 +9537,7 @@ function cwrotatepf(p, cwrot) {
9456
9537
  function boxOverlap(b0, b1) {
9457
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;
9458
9539
  }
9459
- var POINTS_PER_INCH = 72;
9540
+ var POINTS_PER_INCH2 = 72;
9460
9541
 
9461
9542
  // src/common/arrows-shapes-poly.ts
9462
9543
  var CROW_ARROWWIDTH = 0.45;
@@ -12233,7 +12314,8 @@ function polySize(p) {
12233
12314
  const init = initialSizePts(p);
12234
12315
  const dimen = quantize(padLabelDimen(p.labelDimen, p.margin, p.isPlain), p.quantumIn);
12235
12316
  const { sides: sides2, isBox: isBox4 } = effectiveShape(p);
12236
- 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) };
12237
12319
  if (isBox4) {
12238
12320
  } else if (p.optionShape === STAR) {
12239
12321
  bb = starSize(bb);
@@ -12262,7 +12344,7 @@ function labelSpace(p, dimen, bb, minBb, isBox4, fixedshape) {
12262
12344
  } else {
12263
12345
  spaceX = dimen.x - spacex;
12264
12346
  }
12265
- 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));
12266
12348
  return { space: { x: spaceX, y: spaceY }, valign: labelValign(p) };
12267
12349
  }
12268
12350
  function effectiveShape(p) {
@@ -12681,12 +12763,6 @@ function drawRecordBox(job, n, ll, ur, filled) {
12681
12763
  var DEFAULT_LW = 27;
12682
12764
  var DEFAULT_RW = 27;
12683
12765
  var DEFAULT_HT = 36;
12684
- function nodeAttr(n, g, key) {
12685
- const own = n.attrs.get(key);
12686
- if (own !== void 0) return own;
12687
- if (n.nodeDefaultsSnapshot !== void 0) return n.nodeDefaultsSnapshot.get(key);
12688
- return g.nodeDefaults.get(key) ?? (g !== g.root ? g.root.nodeDefaults.get(key) : void 0);
12689
- }
12690
12766
  function readFontAttrs(n, g) {
12691
12767
  return {
12692
12768
  fontname: nodeAttr(n, g, "fontname") ?? DEFAULT_FONTNAME,
@@ -12720,6 +12796,15 @@ function warnMissingImage(n, g, shapefile) {
12720
12796
  agwarningf(imageOpenWarning(image));
12721
12797
  agwarningf(`No or improper image="${image}" for node "${n.name}"`);
12722
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
+ }
12723
12808
  function polyInit(n, g, measurer) {
12724
12809
  const shapeName2 = nodeAttr(n, g, "shape") ?? "ellipse";
12725
12810
  const shapefile = nodeAttr(n, g, "shapefile");
@@ -12749,6 +12834,7 @@ function claimWarned() {
12749
12834
  return true;
12750
12835
  }
12751
12836
  var claimNever = () => false;
12837
+ var MSG_MANY_COLORS = "More than 2 colors specified for a gradient - ignoring remaining";
12752
12838
  var EPS = 1e-5;
12753
12839
  function aeq0(x) {
12754
12840
  return x < EPS && x > -EPS;
@@ -12814,8 +12900,8 @@ function scanSegs(colorlist, claim) {
12814
12900
  function parseSegs(colorlist, context) {
12815
12901
  const result = scanSegs(colorlist, claimWarned);
12816
12902
  if (result.error === 3) {
12817
- const tail = context === void 0 ? "" : context();
12818
- 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());
12819
12905
  } else if (result.error === 2) {
12820
12906
  agerrorf(`Illegal value in "${colorlist}" color attribute; float expected after ';'`);
12821
12907
  if (context !== void 0) agerr("prev", context());
@@ -12849,10 +12935,6 @@ var BOX_ORIENTATION_TOLERANCE = 0.5;
12849
12935
  var BOX_ORIENTATION_STEP = 90;
12850
12936
  var BOX_SIDES = 4;
12851
12937
  var ELLIPSE_MAX_SIDES = 2;
12852
- function styleName(token) {
12853
- const paren = token.indexOf("(");
12854
- return paren < 0 ? token : token.slice(0, paren);
12855
- }
12856
12938
  function gvrenderSetStyle(styles) {
12857
12939
  if (styles === null) return;
12858
12940
  for (const token of styles) {
@@ -15813,6 +15895,13 @@ function firstColor(name) {
15813
15895
  }
15814
15896
  function resolveRenderColor(raw, report = true) {
15815
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) {
15816
15905
  const known = KNOWN_COLORS.has(raw.toLowerCase());
15817
15906
  if (known && (rendererColors.hasKnownList || !report)) return { type: "string", s: raw };
15818
15907
  const color = { type: "rgba", r: 0, g: 0, b: 0, a: 0 };
@@ -15926,7 +16015,7 @@ function reportEdgeColors(e) {
15926
16015
  reportColorNames(edgeGraphicsColors({
15927
16016
  color,
15928
16017
  fillcolor: e.attrs.get("fillcolor") ?? "",
15929
- tapered: styleTokens2(e.attrs.get("style")).includes("tapered"),
16018
+ tapered: styleTokensQuiet(e.attrs.get("style")).includes("tapered"),
15930
16019
  arrows: spl.list.map((bz) => ({ sflag: bz.sflag !== 0, eflag: bz.eflag !== 0 }))
15931
16020
  }));
15932
16021
  }
@@ -16281,11 +16370,7 @@ function applyClusterGradient(obj, fill) {
16281
16370
  obj.gradientAngle = fill.angle;
16282
16371
  }
16283
16372
  function clusterAttr(sg, key) {
16284
- for (let g = sg; g !== null; g = g.parent) {
16285
- const v = g.attrs.get(key);
16286
- if (v !== void 0) return v;
16287
- }
16288
- return void 0;
16373
+ return graphAttrInherited(sg, key);
16289
16374
  }
16290
16375
  function clusterStyle(sg) {
16291
16376
  return clusterAttr(sg, "style");
@@ -16320,12 +16405,10 @@ function applyClusterObjState(sg, job) {
16320
16405
  if (job.obj === null) return false;
16321
16406
  const obj = job.obj;
16322
16407
  gvrenderSetStyle(checkClusterStyleTokens(styleTokens2(clusterStyle(sg))));
16323
- return withColorScheme(clusterAttr(sg, "colorscheme"), () => {
16324
- const filled = applyClusterFill(obj, fillRes);
16325
- applyClusterPenState(obj, sg);
16326
- reportColorNames(stripedClusterColors(sg));
16327
- return filled;
16328
- });
16408
+ const filled = applyClusterFill(obj, fillRes);
16409
+ applyClusterPenState(obj, sg);
16410
+ reportColorNames(stripedClusterColors(sg));
16411
+ return filled;
16329
16412
  }
16330
16413
  function isStripedCluster(sg) {
16331
16414
  const flags = parseStyleFlags(clusterStyle(sg));
@@ -16346,27 +16429,25 @@ function stripedClusterColors(sg) {
16346
16429
  return segs.flatMap((seg2) => seg2.color !== null && seg2.t > 0 ? [seg2.color] : []);
16347
16430
  }
16348
16431
  function renderStripedClusterBox(sg, renderer, job) {
16349
- withColorScheme(clusterAttr(sg, "colorscheme"), () => {
16350
- const { ll, ur } = sg.info.bb;
16351
- const af = [
16352
- { x: ll.x, y: ll.y },
16353
- { x: ur.x, y: ll.y },
16354
- { x: ur.x, y: ur.y },
16355
- { x: ll.x, y: ur.y }
16356
- ].map((p) => transformPoint(p, job));
16357
- const obj = job.obj;
16358
- const savedFill = obj?.fill;
16359
- if (obj !== null && savedFill !== void 0) obj.fill = 1 /* Solid */;
16360
- stripedBox(job, af, stripedFillSpec(sg), false, renderer, () => `in cluster ${sg.name}`);
16361
- if (obj !== null && savedFill !== void 0) obj.fill = savedFill;
16362
- const rawPts = [
16363
- { x: ll.x, y: ll.y },
16364
- { x: ll.x, y: ur.y },
16365
- { x: ur.x, y: ur.y },
16366
- { x: ur.x, y: ll.y }
16367
- ];
16368
- renderer.polygon(rawPts.map((p) => transformPoint(p, job)), false, job);
16369
- });
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);
16370
16451
  }
16371
16452
  function applyClusterFill(obj, fillRes) {
16372
16453
  if (fillRes.kind === "none") {
@@ -17334,6 +17415,10 @@ function ncross(ctx) {
17334
17415
 
17335
17416
  // src/model/cgraph-ops.ts
17336
17417
  var LOCALNAMEPREFIX = "%";
17418
+ var ANONYMOUS_ROOT_ID = 1;
17419
+ function agNameOf(g) {
17420
+ return g.anonymous ? `${LOCALNAMEPREFIX}${ANONYMOUS_ROOT_ID}` : g.name;
17421
+ }
17337
17422
  function freshNodeId(root) {
17338
17423
  let max = -1;
17339
17424
  for (const n of root.nodes.values()) {
@@ -18542,7 +18627,7 @@ var CHAR_UTF8 = 0;
18542
18627
  var CHAR_LATIN1 = 1;
18543
18628
  var CHAR_BIG5 = 2;
18544
18629
  function points(inches) {
18545
- return cround(inches * POINTS_PER_INCH);
18630
+ return cround(inches * POINTS_PER_INCH2);
18546
18631
  }
18547
18632
  function findCharset(g) {
18548
18633
  const raw = g.attrs.get("charset");
@@ -18737,7 +18822,24 @@ function removeFill(g) {
18737
18822
  }
18738
18823
  agdelsubg(g.root, sg);
18739
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
+ }
18740
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);
18741
18843
  let n = g.info.nlist;
18742
18844
  while (n !== void 0) {
18743
18845
  const next = n.info.next;
@@ -19215,7 +19317,7 @@ var DEFAULT_NODEWIDTH = 0.75;
19215
19317
  var MIN_NODEWIDTH = 0.01;
19216
19318
  var DEFAULT_NODEHEIGHT = 0.5;
19217
19319
  var MIN_NODEHEIGHT = 0.02;
19218
- var POINTS_PER_INCH2 = 72;
19320
+ var POINTS_PER_INCH3 = 72;
19219
19321
  var DEF_POINT = 0.05;
19220
19322
  var MIN_POINT = 3e-4;
19221
19323
  var DEFAULT_NODEPENWIDTH2 = 1;
@@ -19283,6 +19385,8 @@ function polySizeParamsFromNode(n, g, shape, labelDimen, flip) {
19283
19385
  // size_gen discriminant (STAR/CYLINDER)
19284
19386
  nojustify: mapbool4(nodeAttr(n, g, "nojustify")),
19285
19387
  // shapes.c:2133
19388
+ imageSize: nodeImageSize(n, g),
19389
+ // shapes.c:2039-2051
19286
19390
  flip
19287
19391
  };
19288
19392
  }
@@ -19319,7 +19423,7 @@ function initPointSize(n, g, shape) {
19319
19423
  const flip = g.root.info.flip === true;
19320
19424
  const peripheries = lateInt(nodeAttr(n, g, "peripheries"), shape.polygon.peripheries, 0);
19321
19425
  const penwidth = lateDouble(nodeAttr(n, g, "penwidth"), DEFAULT_NODEPENWIDTH2, MIN_NODEPENWIDTH);
19322
- const sz0 = pointWidthInches(n, g) * POINTS_PER_INCH2;
19426
+ const sz0 = pointWidthInches(n, g) * POINTS_PER_INCH3;
19323
19427
  storeNodeSize(n, pointSizeResult(sz0, peripheries, penwidth), flip);
19324
19428
  assignShapeInfo(n, { ...shape.polygon, peripheries, sides: 2, penwidth, vertices: null });
19325
19429
  }
@@ -19376,8 +19480,8 @@ function storeNodeSize(n, unflipped, flip) {
19376
19480
  n.info.base_width = unflipped.baseW / 72;
19377
19481
  n.info.base_height = unflipped.baseH / 72;
19378
19482
  const size = gvNodesize(
19379
- n.info.width * POINTS_PER_INCH2,
19380
- n.info.height * POINTS_PER_INCH2,
19483
+ n.info.width * POINTS_PER_INCH3,
19484
+ n.info.height * POINTS_PER_INCH3,
19381
19485
  flip
19382
19486
  );
19383
19487
  n.info.lw = size.lw;
@@ -20554,7 +20658,7 @@ var SIZE_X_RE2 = new RegExp(`^\\s*(${FLOAT})(.?)`);
20554
20658
  var PAD_XY_RE = new RegExp(`^\\s*(${FLOAT})\\s*,\\s*(${FLOAT})`);
20555
20659
  var PAD_X_RE = new RegExp(`^\\s*(${FLOAT})`);
20556
20660
  function toPoints(inches) {
20557
- return cround(inches * POINTS_PER_INCH);
20661
+ return cround(inches * POINTS_PER_INCH2);
20558
20662
  }
20559
20663
  function parseDrawingSize(raw) {
20560
20664
  if (raw === void 0) return null;
@@ -20575,11 +20679,11 @@ function parseGraphPad(raw) {
20575
20679
  if (raw !== void 0) {
20576
20680
  const xy = PAD_XY_RE.exec(raw);
20577
20681
  if (xy) {
20578
- 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 };
20579
20683
  }
20580
20684
  const x = PAD_X_RE.exec(raw);
20581
20685
  if (x) {
20582
- const v = Number(x[1]) * POINTS_PER_INCH;
20686
+ const v = Number(x[1]) * POINTS_PER_INCH2;
20583
20687
  return { x: v, y: v };
20584
20688
  }
20585
20689
  }
@@ -20589,11 +20693,11 @@ function parseGraphMargin(raw) {
20589
20693
  if (raw !== void 0) {
20590
20694
  const xy = PAD_XY_RE.exec(raw);
20591
20695
  if (xy) {
20592
- 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 };
20593
20697
  }
20594
20698
  const x = PAD_X_RE.exec(raw);
20595
20699
  if (x) {
20596
- const v = Number(x[1]) * POINTS_PER_INCH;
20700
+ const v = Number(x[1]) * POINTS_PER_INCH2;
20597
20701
  return { x: v, y: v };
20598
20702
  }
20599
20703
  }
@@ -20959,10 +21063,13 @@ function parseLayers(g) {
20959
21063
  let listSep = g.attrs.get("layerlistsep") || DEFAULT_LAYERLISTSEP;
20960
21064
  if ([...sep].some((c) => listSep.includes(c))) listSep = "";
20961
21065
  if (p === void 0 || p === "") {
20962
- return { layerIDs: [], numLayers: 1, sep, listSep };
21066
+ return { layerIDs: [], numLayers: 1, sep, listSep, layerList: null };
20963
21067
  }
20964
21068
  const toks = splitOnSet(p, sep);
20965
- 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;
20966
21073
  }
20967
21074
  function isNaturalNumber(s) {
20968
21075
  return /^[0-9]+$/.test(s);
@@ -21018,6 +21125,19 @@ function edgeInLayer(info, layerNum, e) {
21018
21125
  return pn === "" || selectedLayer(info, layerNum, pn);
21019
21126
  });
21020
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
+ }
21021
21141
 
21022
21142
  // src/gvc/emit-walk.ts
21023
21143
  function nodeShown(info, job, n, g) {
@@ -21080,9 +21200,40 @@ var NATIVE_LANGNAME = /* @__PURE__ */ new Map([
21080
21200
  ["cmapx-np", "cmapx_np"],
21081
21201
  ["imap-np", "imap_np"]
21082
21202
  ]);
21083
- function warnLayersUnsupported(format, numLayers, doesLayers) {
21084
- if (numLayers <= 1 || doesLayers) return;
21085
- 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
+ }
21086
21237
  }
21087
21238
 
21088
21239
  // src/gvc/device-labels.ts
@@ -21216,7 +21367,7 @@ function renderNode(n, renderer, job, done) {
21216
21367
  job.popObj();
21217
21368
  }
21218
21369
  }
21219
- function setEdgePen(e, job) {
21370
+ function setEdgePen(e, job, styles) {
21220
21371
  if (job.obj === null) return;
21221
21372
  const obj = job.obj;
21222
21373
  const flags = parseStyleFlags(e.attrs.get("style"));
@@ -21226,24 +21377,24 @@ function setEdgePen(e, job) {
21226
21377
  );
21227
21378
  obj.pen = resolvePenType(flags);
21228
21379
  obj.penWidth = resolvePenWidth(flags, e.attrs.get("penwidth"));
21229
- obj.rawStyle = styleTokens2(e.attrs.get("style"));
21380
+ obj.rawStyle = [...styles];
21230
21381
  if (e.info.spl !== void 0) gvrenderSetStyle(obj.rawStyle);
21231
21382
  }
21232
21383
  function renderEdge(e, renderer, job) {
21233
21384
  emitEdgeComments(e, renderer, job);
21234
21385
  const edgeStyle = e.attrs.get("style");
21386
+ const styles = styleTokens2(edgeStyle);
21235
21387
  if (parseStyleFlags(edgeStyle).invis || styleHasInvisibleAlias(edgeStyle)) return;
21236
21388
  const obj = createObjState(3 /* Edge */);
21237
21389
  obj.emitState = 9 /* EDraw */;
21238
21390
  job.pushObj(obj);
21239
- setEdgePen(e, job);
21391
+ setEdgePen(e, job, styles);
21240
21392
  try {
21241
21393
  setHtmlAnchorObj(svgEdgeId(e, job), labelTextOf2(e.info.label), job.obj ?? void 0);
21242
21394
  resolveEdgeAnchor(e, svgEdgeId(e, job), obj);
21243
21395
  withColorScheme(e.attrs.get("colorscheme"), () => {
21244
21396
  renderer.beginEdge(e, job);
21245
21397
  reportEdgeColors(e);
21246
- const styles = styleTokens2(e.attrs.get("style"));
21247
21398
  for (let i = edgeStyleResets(e, styles); i > 0; i--) gvrenderSetStyle(styles);
21248
21399
  reportEdgeLabelColors(e);
21249
21400
  renderer.endEdge(e, job);
@@ -21270,6 +21421,22 @@ function renderClusterBox(sg, filled, renderer, job) {
21270
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 }];
21271
21422
  renderer.polygon(rawPts.map((p) => transformPoint(p, job)), filled, job);
21272
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
+ }
21273
21440
  function renderOneCluster(sg, renderer, job) {
21274
21441
  const clustersLast = (job.flags & EMIT_CLUSTERS_LAST) !== 0;
21275
21442
  if (clustersLast) renderClusters(sg, renderer, job);
@@ -21277,20 +21444,7 @@ function renderOneCluster(sg, renderer, job) {
21277
21444
  obj.emitState = 1 /* CDraw */;
21278
21445
  job.pushObj(obj);
21279
21446
  try {
21280
- const filled = applyClusterObjState(sg, job);
21281
- renderer.beginCluster?.(sg, job);
21282
- if (job.obj !== null) job.obj.id = svgClusterId(sg, job);
21283
- setHtmlAnchorObj(svgClusterId(sg, job), labelTextOf2(sg.info.label), job.obj ?? void 0);
21284
- if (job.obj !== null) {
21285
- resolveObjAnchor(sg, labelTextOf2(sg.info.label), svgClusterId(sg, job), job.obj);
21286
- }
21287
- const anchored = beginAnchorIf(renderer, job);
21288
- if ((clusterPeripheries(sg) !== 0 || filled || isStripedCluster(sg)) && job.obj?.pen !== 0 /* None */) {
21289
- renderClusterBox(sg, filled, renderer, job);
21290
- }
21291
- renderClusterLabel(sg, renderer, job);
21292
- if (anchored) renderer.endAnchor?.(job);
21293
- renderer.endCluster?.(sg, job);
21447
+ withColorScheme(clusterAttr(sg, "colorscheme"), () => drawClusterInScheme(sg, renderer, job));
21294
21448
  } finally {
21295
21449
  job.popObj();
21296
21450
  }
@@ -21311,16 +21465,15 @@ function renderGraph(g, job, renderer) {
21311
21465
  job.pushObj(obj);
21312
21466
  try {
21313
21467
  const info = parseLayers(g);
21314
- const layered = renderer.beginLayer !== void 0 && info.numLayers > 1;
21315
- job.numLayers = layered ? info.numLayers : 1;
21468
+ job.layerNum = 0;
21316
21469
  job.layerIDs = info.layerIDs;
21317
21470
  renderer.beginGraph(g, job);
21318
- warnLayersUnsupported(job.format, info.numLayers, renderer.beginLayer !== void 0);
21319
- for (let ln = 1; ln <= job.numLayers; ln++) {
21320
- job.layerNum = ln;
21321
- 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);
21322
21475
  renderPage(g, renderer, job, info);
21323
- if (layered) renderer.endLayer(job);
21476
+ if (layered) renderer.endLayer?.(job);
21324
21477
  }
21325
21478
  renderer.endGraph(g, job);
21326
21479
  } finally {
@@ -21364,9 +21517,9 @@ function render(ctx, g, format, inlineImages = false) {
21364
21517
  lateDouble(g.attrs.get("resolution"), 0, 0),
21365
21518
  0
21366
21519
  );
21367
- const jobDpi = drawingDpi > 0 ? drawingDpi : POINTS_PER_INCH;
21520
+ const jobDpi = drawingDpi > 0 ? drawingDpi : POINTS_PER_INCH2;
21368
21521
  job.dpi = { x: jobDpi, y: jobDpi };
21369
- const dpiScale = jobDpi / POINTS_PER_INCH;
21522
+ const dpiScale = jobDpi / POINTS_PER_INCH2;
21370
21523
  job.scale = { x: z * dpiScale, y: z * dpiScale };
21371
21524
  job.rotation = parseLandscape(g) ? 90 : 0;
21372
21525
  job.renderer = renderer;
@@ -21377,7 +21530,6 @@ function render(ctx, g, format, inlineImages = false) {
21377
21530
  }
21378
21531
 
21379
21532
  // src/common/htmltable-emit-fill.ts
21380
- var MSG_MANY_COLORS = "More than 2 colors specified for a gradient - ignoring remaining";
21381
21533
  function findHtmlStopColor(color, silent = false) {
21382
21534
  const { segs, error } = silent ? parseSegsSilent(color) : parseSegs(color);
21383
21535
  const first = segs[0];
@@ -21461,7 +21613,7 @@ function penTypeOf(style2) {
21461
21613
  return 3 /* Solid */;
21462
21614
  }
21463
21615
  function withHtmlPaint(paint, job, drawFn) {
21464
- 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" };
21465
21617
  paintObj.penColor = paint.pen !== void 0 ? resolveRenderColor(paint.pen) : { type: "string", s: "transparent" };
21466
21618
  applyHtmlFill(paint);
21467
21619
  paintObj.pen = penTypeOf(paint.penStyle);
@@ -21586,7 +21738,9 @@ function emitSidedPolylines(sides2, corners, renderer, job) {
21586
21738
  var HTML_DEFAULT_COLOR = "black";
21587
21739
  function bgNames(bgcolor) {
21588
21740
  const spec = parseGradientSpec(bgcolor);
21589
- 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];
21590
21744
  }
21591
21745
  function cellNames(cell2) {
21592
21746
  if (htmlStyle(cell2.style).invisible) return [];
@@ -21642,23 +21796,68 @@ function zeroFlags() {
21642
21796
  };
21643
21797
  }
21644
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
+ }
21645
21844
  function styleTokens2(style2) {
21646
21845
  if (!style2) return [];
21647
- const out = [];
21648
- let fun = 0;
21649
- for (const raw of style2.split(",")) {
21650
- const token = raw.trim();
21651
- if (token.length === 0) continue;
21652
- if (fun === FUNLIMIT - 1) return [];
21653
- fun++;
21654
- out.push(token);
21655
- }
21656
- 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);
21657
21856
  }
21658
21857
  function parseSetLineWidth(token) {
21659
- const m = /^setlinewidth\s*\(\s*([^)]*)\)\s*$/.exec(token);
21660
- if (m === null) return null;
21661
- 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]);
21662
21861
  return Number.isNaN(v) ? 0 : v;
21663
21862
  }
21664
21863
  function applyToken(flags, token) {
@@ -21682,33 +21881,18 @@ function firstSolidColor(raw) {
21682
21881
  }
21683
21882
  function parseStyleFlags(style2) {
21684
21883
  const flags = zeroFlags();
21685
- if (!style2) return flags;
21686
- let fun = 0;
21687
- for (const raw of style2.split(",")) {
21688
- const token = raw.trim();
21689
- if (token.length === 0) continue;
21690
- if (fun === FUNLIMIT - 1) return zeroFlags();
21691
- fun++;
21884
+ for (const token of styleTokensQuiet(style2)) {
21692
21885
  const lw = parseSetLineWidth(token);
21693
21886
  if (lw !== null) {
21694
21887
  flags.setLineWidth = lw;
21695
21888
  continue;
21696
21889
  }
21697
- if (!token.includes("(")) applyToken(flags, token);
21890
+ applyToken(flags, styleName(token));
21698
21891
  }
21699
21892
  return flags;
21700
21893
  }
21701
21894
  function styleHasInvisibleAlias(style2) {
21702
- if (!style2) return false;
21703
- let fun = 0;
21704
- for (const raw of style2.split(",")) {
21705
- const token = raw.trim();
21706
- if (token.length === 0) continue;
21707
- if (fun === FUNLIMIT - 1) return false;
21708
- fun++;
21709
- if (token === "invisible") return true;
21710
- }
21711
- return false;
21895
+ return styleTokensQuiet(style2).some((token) => styleName(token) === "invisible");
21712
21896
  }
21713
21897
  function resolvePenType(flags) {
21714
21898
  if (flags.invis) return 0 /* None */;
@@ -21746,11 +21930,10 @@ function applyBgcolor(attrs, filled, fillcolor) {
21746
21930
  }
21747
21931
  function findStopColor(colorlist) {
21748
21932
  const { segs, error } = parseSegs(colorlist);
21749
- if (error === 1 || error === 2) return null;
21750
- if (segs.length < 2) return null;
21751
21933
  const seg0 = segs[0];
21752
21934
  const seg1 = segs[1];
21753
- 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);
21754
21937
  const fillColor = seg0.color;
21755
21938
  const stopColor = seg1.color ?? DEFAULT_COLOR4;
21756
21939
  const frac = seg0.hasFraction ? seg0.t : seg1.hasFraction ? 1 - seg1.t : 0;
@@ -21763,7 +21946,7 @@ function parseAngle(gradientangle2) {
21763
21946
  }
21764
21947
  function buildResolvedFill(rawColor, flags, angle) {
21765
21948
  const stop = findStopColor(rawColor);
21766
- if (stop === null) return { kind: "solid", color: rawColor };
21949
+ if (stop === null) return { kind: "solid", color: rawColor.split(":", 1)[0] };
21767
21950
  const kind = flags.radial ? "radial" : "linear";
21768
21951
  return { kind, fillColor: stop.fillColor, stopColor: stop.stopColor, frac: stop.frac, angle };
21769
21952
  }
@@ -22815,9 +22998,6 @@ function readLabelPos(sg) {
22815
22998
  }
22816
22999
  return pos;
22817
23000
  }
22818
- function graphAttrInherited(sg, key) {
22819
- return sg.attrs.get(key) ?? sg.graphDefaultsSnapshot?.get(key);
22820
- }
22821
23001
  function readFontParams(sg) {
22822
23002
  return {
22823
23003
  fontsize: parseFloat(graphAttrInherited(sg, "fontsize") ?? "") || DEFAULT_FONTSIZE2,
@@ -31150,6 +31330,20 @@ function addXLabels(gp) {
31150
31330
  runPlacement(gp);
31151
31331
  }
31152
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
+
31153
31347
  // src/common/postproc.ts
31154
31348
  var IGNORED_EDGE = 6;
31155
31349
  var Rankdir = 0;
@@ -31241,6 +31435,7 @@ function translateDrawing(g) {
31241
31435
  if (!shift && !Rankdir) return;
31242
31436
  for (const v of g.nodes.values()) {
31243
31437
  mapNode(v);
31438
+ if (getState() !== GVSPLINES) continue;
31244
31439
  for (const e of g.edges) {
31245
31440
  if (e.tail !== v) continue;
31246
31441
  if (e.info.spl === void 0) {
@@ -35230,6 +35425,7 @@ function orthoDispatch(g) {
35230
35425
  } else rc = dispatchOrthoEdges(g, false);
35231
35426
  if (rc !== 0) return rc;
35232
35427
  placePortLabels(g);
35428
+ setState(GVSPLINES);
35233
35429
  g.info.edgeLabelsDone = true;
35234
35430
  return 0;
35235
35431
  }
@@ -35244,6 +35440,7 @@ function finalizeSplines(g, et, normalize) {
35244
35440
  if (normalize) edgeNormalize(g);
35245
35441
  if (et !== EDGETYPE_CURVED) routeDotEdges(g);
35246
35442
  placePortLabels(g);
35443
+ setState(GVSPLINES);
35247
35444
  g.info.edgeLabelsDone = true;
35248
35445
  }
35249
35446
  function dotSplines_(g, normalize) {
@@ -36943,10 +37140,6 @@ function gvPermutation(bound) {
36943
37140
 
36944
37141
  // src/layout/neato/matrix-ops.ts
36945
37142
  var fr = Math.fround;
36946
- function fma2(a, b, c) {
36947
- const p = a * b;
36948
- return Number.isFinite(p) && Number.isFinite(c) ? fma(a, b, c) : p + c;
36949
- }
36950
37143
  function orthog1(n, vec) {
36951
37144
  let sum = 0;
36952
37145
  for (let i = 0; i < n; i++) sum += vec[i];
@@ -36975,10 +37168,6 @@ function rightMultWithVectorFF(m, n, vector, result) {
36975
37168
  function vectorsSubtractionF(n, v1, v2, result) {
36976
37169
  for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
36977
37170
  }
36978
- function vectorsMultAdditionF(n, v1, alpha, v2) {
36979
- const a = fr(alpha);
36980
- for (let i = 0; i < n; i++) v1[i] = v1[i] + fr(a * v2[i]);
36981
- }
36982
37171
  function vectorsInnerProductF(n, v1, v2) {
36983
37172
  let result = 0;
36984
37173
  for (let i = 0; i < n; i++) result += fr(v1[i] * v2[i]);
@@ -37019,11 +37208,11 @@ function innerProduct(n, v1, v2, block) {
37019
37208
  const blocked = block === BLOCK_NONE ? 0 : n - n % block;
37020
37209
  let i = 0;
37021
37210
  for (; i < blocked; i++) result += v1[i] * v2[i];
37022
- for (; i < n; i++) result = fma2(v1[i], v2[i], result);
37211
+ for (; i < n; i++) result = fma(v1[i], v2[i], result);
37023
37212
  return result;
37024
37213
  }
37025
37214
  function scadd(vec1, end, fac, vec2) {
37026
- 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]);
37027
37216
  }
37028
37217
  function norm(vec, end, block) {
37029
37218
  return Math.sqrt(innerProduct(end + 1, vec, vec, block));
@@ -37055,7 +37244,7 @@ function rightMultWithVectorF(matrix, n, vector, result, block) {
37055
37244
  let res = 0;
37056
37245
  let j = 0;
37057
37246
  for (; j < blocked; j++) res += row[j] * vector[j];
37058
- for (; j < n; j++) res = fma2(row[j], vector[j], res);
37247
+ for (; j < n; j++) res = fma(row[j], vector[j], res);
37059
37248
  result[i] = res;
37060
37249
  }
37061
37250
  }
@@ -37063,7 +37252,7 @@ function rightMultWithVector(matrix, n, vector, result) {
37063
37252
  for (let i = 0; i < n; i++) {
37064
37253
  let res = 0;
37065
37254
  const row = matrix[i];
37066
- 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);
37067
37256
  result[i] = res;
37068
37257
  }
37069
37258
  }
@@ -37181,6 +37370,16 @@ function conjugateGradientF(A3, x, b, n, opts) {
37181
37370
  var TOLERANCE_CG = 1e-3;
37182
37371
  var DFLT_ITERATIONS = 200;
37183
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
+ }
37184
37383
  function mdsModel(graph, nG) {
37185
37384
  if (graph[0].ewgts.length === 0) return null;
37186
37385
  const Dij = computeWeightedApspPacked(graph, nG);
@@ -37280,19 +37479,40 @@ function dijkstraSgd(graph, source, terms) {
37280
37479
 
37281
37480
  // src/layout/neato/edge-len.ts
37282
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
+ }
37283
37496
  function lenattr(ep, g) {
37284
37497
  const s = ep.attrs.get("len");
37285
37498
  if (s === void 0 || s === "") return DEFAULT_EDGE_LEN;
37286
- const val2 = /^\s*[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/.exec(s);
37287
- const len = val2 === null ? Number.NaN : parseFloat(val2[0]);
37288
- if (Number.isNaN(len) || len < 0 || len === 0) {
37289
- 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)}`);
37290
37502
  return DEFAULT_EDGE_LEN;
37291
37503
  }
37292
37504
  return len;
37293
37505
  }
37294
37506
  function setEdgeLen(g) {
37295
- 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;
37296
37516
  }
37297
37517
 
37298
37518
  // src/util/mt19937.ts
@@ -37450,7 +37670,7 @@ function neatoMode(g) {
37450
37670
  if (str === void 0 || str === "") return MODE_MAJOR;
37451
37671
  const mode = modeByName().get(str);
37452
37672
  if (mode !== void 0) return mode;
37453
- 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`);
37454
37674
  return MODE_MAJOR;
37455
37675
  }
37456
37676
  function checkMode(g, mode) {
@@ -37495,7 +37715,7 @@ function warnCircuitDisconnected(g) {
37495
37715
  circuitWarned.add(g.root);
37496
37716
  agerrLineOn(
37497
37717
  "warn",
37498
- `graph ${g.root.name} is disconnected. Hence, the circuit model
37718
+ `graph ${agNameOf(g.root)} is disconnected. Hence, the circuit model
37499
37719
  is undefined. Reverting to the shortest path model.
37500
37720
  Alternatively, consider running neato using -Gpack=true or decomposing
37501
37721
  the graph into connected components.`
@@ -38106,7 +38326,7 @@ function moveNode(st, m) {
38106
38326
  function solveModel(g, st) {
38107
38327
  for (let m = chooseNode(st); m >= 0; m = chooseNode(st)) moveNode(st, m);
38108
38328
  if (st.move === st.maxIter) {
38109
- agwarningf(`Max. iterations (${st.maxIter}) reached on graph ${g.name}`);
38329
+ agwarningf(`Max. iterations (${st.maxIter}) reached on graph ${agNameOf(g)}`);
38110
38330
  }
38111
38331
  }
38112
38332
  function mdsEdges(g, nodes, lens) {
@@ -38189,7 +38409,7 @@ function addNeighbours(g, np, entry, o) {
38189
38409
  if (ep.head === ep.tail) continue;
38190
38410
  const vp = ep.tail === np ? ep.head : ep.tail;
38191
38411
  const vid = vp.info.id;
38192
- const dist5 = o.haveLen ? lateDouble(ep.attrs.get("len"), 1, 0) : 1;
38412
+ const dist5 = o.haveLen ? ep.info.dist ?? 0 : 1;
38193
38413
  const idx = seen2.get(vid);
38194
38414
  if (idx !== void 0) {
38195
38415
  if (o.haveLen) entry.ewgts[idx] = Math.max(entry.ewgts[idx], dist5);
@@ -38731,7 +38951,7 @@ function matMultVecOrthog(mat, dim, vec, result, orthog) {
38731
38951
  let sum = 0;
38732
38952
  let j = 0;
38733
38953
  for (; j < blocked; j++) sum += row[j] * vec[j];
38734
- for (; j < dim; j++) sum = fma2(row[j], vec[j], sum);
38954
+ for (; j < dim; j++) sum = fma(row[j], vec[j], sum);
38735
38955
  result[i] = sum;
38736
38956
  }
38737
38957
  const alpha = -innerProduct(dim, result, orthog, BLOCK_MAT_MULT_ORTHOG);
@@ -38830,8 +39050,8 @@ function computeAvgs(Dij, n) {
38830
39050
  sumRow += row[j] * row[j];
38831
39051
  }
38832
39052
  for (; j < n; j++) {
38833
- sum = fma2(row[j], row[j], sum);
38834
- sumRow = fma2(row[j], row[j], sumRow);
39053
+ sum = fma(row[j], row[j], sum);
39054
+ sumRow = fma(row[j], row[j], sumRow);
38835
39055
  }
38836
39056
  rowAvg[i] = fr4(fr4(sumRow) / n);
38837
39057
  }
@@ -38844,7 +39064,7 @@ function computeBij(Dij, n) {
38844
39064
  for (let i = 0; i < n; i++) {
38845
39065
  for (let j = 0; j <= i; j++) {
38846
39066
  const fD = fr4(Dij[i][j]);
38847
- const t = fr4(fma2(-fD, fD, rowAvg[i]));
39067
+ const t = fr4(fma(-fD, fD, rowAvg[i]));
38848
39068
  Bij[i][j] = fr4(fr4(t + rowAvg[j]) - allAvg);
38849
39069
  Bij[j][i] = Bij[i][j];
38850
39070
  }
@@ -38876,8 +39096,8 @@ function scaleGivenCoords(Dij, n, x) {
38876
39096
  sum1 += t1 * f;
38877
39097
  sum2 += t2 * f;
38878
39098
  } else {
38879
- sum1 = fma2(t1, f, sum1);
38880
- sum2 = fma2(t2, f, sum2);
39099
+ sum1 = fma(t1, f, sum1);
39100
+ sum2 = fma(t2, f, sum2);
38881
39101
  }
38882
39102
  }
38883
39103
  }
@@ -38907,7 +39127,7 @@ function computeResidualDistances(Dij, n, x) {
38907
39127
  for (let j = 0; j < i; j++) {
38908
39128
  const t = posI - x[j];
38909
39129
  const d = Dij[i][j];
38910
- const diff = fma2(d, d, -(t * t));
39130
+ const diff = fma(d, d, -(t * t));
38911
39131
  const v = diff > 0 ? Math.sqrt(diff) : 0;
38912
39132
  Dij[i][j] = v;
38913
39133
  Dij[j][i] = v;
@@ -38964,8 +39184,6 @@ function imdsGivenDim(graph, n, givenCoords, newCoords, conjTol) {
38964
39184
 
38965
39185
  // src/layout/neato/stress-kernel.ts
38966
39186
  var fr5 = Math.fround;
38967
- var TOLERANCE_CG2 = 1e-3;
38968
- var OPT_EXP_FLAG = 2;
38969
39187
  function computeApspPacked2(graph, n) {
38970
39188
  const Dij = new Float32Array(n * (n + 1) / 2);
38971
39189
  const Di = new Int32Array(n);
@@ -39009,51 +39227,16 @@ function initLayout(n, dim, coords, nodes) {
39009
39227
  for (let d = 0; d < dim; d++) orthog1(n, coords[d]);
39010
39228
  return pinned;
39011
39229
  }
39012
- function cgStep(st, last) {
39013
- const { n } = st;
39014
- orthog1f(n, st.p);
39015
- orthog1f(n, st.x);
39016
- orthog1f(n, st.r);
39017
- rightMultWithVectorFF(st.A, n, st.p, st.Ap);
39018
- orthog1f(n, st.Ap);
39019
- const pAp = vectorsInnerProductF(n, st.p, st.Ap);
39020
- if (pAp === 0) return true;
39021
- const alpha = st.rR / pAp;
39022
- vectorsMultAdditionF(n, st.x, alpha, st.p);
39023
- if (!last) {
39024
- vectorsMultAdditionF(n, st.r, -alpha, st.Ap);
39025
- const rRNew = vectorsInnerProductF(n, st.r, st.r);
39026
- if (st.rR === 0) return false;
39027
- const betaF = fr5(rRNew / st.rR);
39028
- st.rR = rRNew;
39029
- for (let j = 0; j < n; j++) st.p[j] = fr5(betaF * st.p[j]) + st.r[j];
39030
- }
39031
- return true;
39032
- }
39033
- function conjugateGradientMkernel2(A3, x, b, n, tol, maxIterations) {
39034
- const st = {
39035
- A: A3,
39036
- x,
39037
- b,
39038
- n,
39039
- r: new Float32Array(n),
39040
- p: new Float32Array(n),
39041
- Ap: new Float32Array(n),
39042
- rR: 0
39043
- };
39044
- orthog1f(n, x);
39045
- orthog1f(n, b);
39046
- const Ax = new Float32Array(n);
39047
- rightMultWithVectorFF(A3, n, x, Ax);
39048
- orthog1f(n, Ax);
39049
- vectorsSubtractionF(n, b, Ax, st.r);
39050
- copyVectorF(n, st.r, st.p);
39051
- st.rR = vectorsInnerProductF(n, st.r, st.r);
39052
- for (let i = 0; i < maxIterations && maxAbsF(n, st.r) > tol; i++) {
39053
- if (!cgStep(st, i >= maxIterations - 1)) return -1;
39054
- }
39055
- return 0;
39056
- }
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
+ };
39057
39240
  function buildLap2(lap2, n, exp) {
39058
39241
  const lapLength = n * (n + 1) / 2;
39059
39242
  if (exp === 2) squareVec(lapLength, lap2);
@@ -39076,7 +39259,7 @@ function buildLap2(lap2, n, exp) {
39076
39259
  }
39077
39260
  }
39078
39261
  function buildLap1(lap1, lap2, coords, shape) {
39079
- const { n, dim, exp } = shape;
39262
+ const { n, dim, exp, ops } = shape;
39080
39263
  const lapLength = n * (n + 1) / 2;
39081
39264
  const degrees = new Float64Array(n);
39082
39265
  const distAccumulator = new Float32Array(n);
@@ -39089,7 +39272,7 @@ function buildLap1(lap1, lap2, coords, shape) {
39089
39272
  const ck = coords[k];
39090
39273
  for (let x = 0; x < len; x++) {
39091
39274
  const tmp = fr5(ck[i] + fr5(-1 * ck[i + 1 + x]));
39092
- distAccumulator[x] = distAccumulator[x] + fr5(tmp * tmp);
39275
+ distAccumulator[x] = ops.squareAdd(tmp, distAccumulator[x]);
39093
39276
  }
39094
39277
  }
39095
39278
  invertSqrtVec(len, distAccumulator);
@@ -39122,24 +39305,25 @@ function buildLap1(lap1, lap2, coords, shape) {
39122
39305
  function computeStress(st) {
39123
39306
  let stress = 0;
39124
39307
  for (let k = 0; k < st.dim; k++) {
39125
- 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]);
39126
39309
  stress += vectorsInnerProductF(st.n, st.coords[k], st.b[k]);
39127
39310
  }
39128
39311
  stress *= 2;
39129
39312
  stress += st.constantTerm;
39130
39313
  for (let k = 0; k < st.dim; k++) {
39131
- rightMultWithVectorFF(st.lap2, st.n, st.coords[k], st.tmpCoords);
39314
+ st.ops.rightMult(st.lap2, st.n, st.coords[k], st.tmpCoords);
39132
39315
  stress -= vectorsInnerProductF(st.n, st.coords[k], st.tmpCoords);
39133
39316
  }
39134
39317
  return stress;
39135
39318
  }
39136
39319
  function solveAxis(st, k, havePinned, nodes) {
39320
+ const cg = { tol: TOLERANCE_CG, maxIterations: st.n };
39137
39321
  if (!havePinned) {
39138
- 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);
39139
39323
  }
39140
39324
  copyVectorF(st.n, st.coords[k], st.tmpCoords);
39141
- const rc = conjugateGradientMkernel2(st.lap2, st.tmpCoords, st.b[k], st.n, TOLERANCE_CG2, st.n);
39142
- 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;
39143
39327
  for (let i = 0; i < st.n; i++) {
39144
39328
  if (!isFixed(nodes[i])) st.coords[k][i] = st.tmpCoords[i];
39145
39329
  }
@@ -39170,20 +39354,21 @@ function stressMajorizationKDMkernel(Dij, n, dCoords, nodes, o) {
39170
39354
  coords,
39171
39355
  b: Array.from({ length: dim }, () => new Float32Array(n)),
39172
39356
  tmpCoords: new Float32Array(n),
39173
- constantTerm
39357
+ constantTerm,
39358
+ ops: o.cola === true ? COLA_OPS : FUSED_OPS
39174
39359
  };
39175
39360
  let oldStress = Number.MAX_VALUE;
39176
39361
  let converged = false;
39177
39362
  let iterations = 0;
39178
39363
  for (; iterations < maxi && !converged; iterations++) {
39179
- buildLap1(st.lap1, lap2, coords, { n, dim, exp });
39364
+ buildLap1(st.lap1, lap2, coords, { n, dim, exp, ops: st.ops });
39180
39365
  const newStress = computeStress(st);
39181
39366
  if (typeof process !== "undefined" && process.env["STRESS_DEBUG"] && iterations % 5 === 0) console.error(newStress.toFixed(3));
39182
39367
  const change = Math.abs(oldStress - newStress);
39183
39368
  converged = change / oldStress < o.epsilon || newStress < o.epsilon;
39184
39369
  oldStress = newStress;
39185
39370
  for (let k = 0; k < dim; k++) {
39186
- if (solveAxis(st, k, havePinned, nodes) < 0) return -1;
39371
+ if (solveAxis(st, k, havePinned, nodes) !== 0) return -1;
39187
39372
  }
39188
39373
  }
39189
39374
  for (let i = 0; i < dim; i++) {
@@ -39271,7 +39456,7 @@ function distanceKD(coords, dim, i, j) {
39271
39456
  let sum = 0;
39272
39457
  for (let k = 0; k < dim; k++) {
39273
39458
  const d = coords[k][i] - coords[k][j];
39274
- sum = fma2(d, d, sum);
39459
+ sum = fma(d, d, sum);
39275
39460
  }
39276
39461
  return Math.sqrt(sum);
39277
39462
  }
@@ -39448,10 +39633,10 @@ function stressMajorizationWithHierarchy(graph, n, dCoords, nodes, o) {
39448
39633
  }
39449
39634
 
39450
39635
  // src/common/utils-inputscale.ts
39451
- var POINTS_PER_INCH3 = 72;
39636
+ var POINTS_PER_INCH4 = 72;
39452
39637
  function getInputscale(g) {
39453
39638
  const d = lateDouble(g.root.attrs.get("inputscale"), -1, 0);
39454
- return d === 0 ? POINTS_PER_INCH3 : d;
39639
+ return d === 0 ? POINTS_PER_INCH4 : d;
39455
39640
  }
39456
39641
  function inputscaleDivisor(g) {
39457
39642
  const sc = getInputscale(g);
@@ -39459,7 +39644,7 @@ function inputscaleDivisor(g) {
39459
39644
  }
39460
39645
 
39461
39646
  // src/layout/neato/set-aspect.ts
39462
- var POINTS_PER_INCH4 = 72;
39647
+ var POINTS_PER_INCH5 = 72;
39463
39648
  function neatoRatioKind(g) {
39464
39649
  const p = g.attrs.get("ratio");
39465
39650
  if (p === void 0) return null;
@@ -39507,8 +39692,8 @@ function neatoTranslate(g) {
39507
39692
  const bb = g.info.bb;
39508
39693
  if (!bb) return;
39509
39694
  const ll = bb.ll;
39510
- const ox = ll.x / POINTS_PER_INCH4;
39511
- const oy = ll.y / POINTS_PER_INCH4;
39695
+ const ox = ll.x / POINTS_PER_INCH5;
39696
+ const oy = ll.y / POINTS_PER_INCH5;
39512
39697
  for (const n of g.nodes.values()) {
39513
39698
  if (!n.info.pos) n.info.pos = [0, 0];
39514
39699
  n.info.pos[0] = (n.info.pos[0] ?? 0) - ox;
@@ -39594,7 +39779,7 @@ var MODEL_CIRCUIT = 1;
39594
39779
  var MODEL_SUBSET = 2;
39595
39780
  var MODEL_MDS2 = 3;
39596
39781
  var DFLT_DIM = 2;
39597
- var POINTS_PER_INCH5 = 72;
39782
+ var POINTS_PER_INCH6 = 72;
39598
39783
  function neatoInitNode(n, dim = DFLT_DIM) {
39599
39784
  if (!n.info.pos || n.info.pos.length < dim) {
39600
39785
  const pos = [];
@@ -39655,15 +39840,17 @@ function solveStress(c, vtx, dCoords, nodeList) {
39655
39840
  dim: DFLT_DIM,
39656
39841
  opts,
39657
39842
  maxi,
39658
- epsilon
39843
+ epsilon,
39844
+ cola: mode === MODE_IPSEP
39659
39845
  });
39660
39846
  }
39661
39847
  function runMajorization(g, mode, model) {
39662
39848
  const nodeList = assignNodeIds2(g);
39849
+ setEdgeLen(g);
39663
39850
  const n = nodeList.length;
39664
39851
  const haveLen = graphHasLen(g);
39665
39852
  const init = checkStart(g, n, mode === MODE_HIER ? INIT_SELF : INIT_RANDOM);
39666
- 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);
39667
39854
  const haveDir = mode === MODE_HIER || mode === MODE_IPSEP;
39668
39855
  const vtx = makeGraphDataC(g, nodeList, haveLen, haveDir, mode);
39669
39856
  const dCoords = [new Float64Array(n), new Float64Array(n)];
@@ -39693,12 +39880,14 @@ function neatoSetAspect(g) {
39693
39880
  const pos = n.info.pos;
39694
39881
  if (!pos) continue;
39695
39882
  n.info.coord = {
39696
- x: (pos[0] ?? 0) * POINTS_PER_INCH5,
39697
- y: (pos[1] ?? 0) * POINTS_PER_INCH5
39883
+ x: (pos[0] ?? 0) * POINTS_PER_INCH6,
39884
+ y: (pos[1] ?? 0) * POINTS_PER_INCH6
39698
39885
  };
39699
39886
  }
39700
39887
  }
39701
39888
  function neatoCleanup(g) {
39889
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
39890
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
39702
39891
  for (const [, n] of g.nodes) {
39703
39892
  n.info.pos = void 0;
39704
39893
  n.info.pinned = void 0;
@@ -41935,9 +42124,11 @@ function splineEdges(g) {
41935
42124
  coalesceEdges(g);
41936
42125
  if (edgetype === EDGETYPE_LINE) {
41937
42126
  RoutingHelper.straight(g, edgetype);
42127
+ setState(GVSPLINES);
41938
42128
  return;
41939
42129
  }
41940
42130
  splineEdgesImpl(g, esepFactor(g), edgetype);
42131
+ setState(GVSPLINES);
41941
42132
  }
41942
42133
  function computeBBFromPos(g) {
41943
42134
  const bb = {
@@ -44348,6 +44539,8 @@ function getPos(g, dim) {
44348
44539
  return pos;
44349
44540
  }
44350
44541
  function sfdpCleanup(g) {
44542
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
44543
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
44351
44544
  for (const n of g.nodes.values()) {
44352
44545
  n.info.pos = void 0;
44353
44546
  n.info.id = void 0;
@@ -45256,7 +45449,7 @@ var AM_PORTHOYX = 12;
45256
45449
  var SCALE = 10;
45257
45450
  var SCALE2 = SCALE / 2;
45258
45451
  var INT_MAX3 = 2147483647;
45259
- var POINTS_PER_INCH6 = 72;
45452
+ var POINTS_PER_INCH7 = 72;
45260
45453
  function cmpitem(a, b) {
45261
45454
  if (a < b) return -1;
45262
45455
  if (a > b) return 1;
@@ -45484,18 +45677,18 @@ function overlaps(p) {
45484
45677
  return false;
45485
45678
  }
45486
45679
  function initItem(n, margin) {
45487
- const x = cround(SCALE * (n.info.pos?.[0] ?? 0) * POINTS_PER_INCH6);
45488
- 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);
45489
45682
  const width2 = n.info.width ?? 0;
45490
45683
  const height2 = n.info.height ?? 0;
45491
45684
  let w2;
45492
45685
  let h2;
45493
45686
  if (margin.doAdd) {
45494
- w2 = d2i(SCALE * (cround(width2 / 2 * POINTS_PER_INCH6) + margin.x));
45495
- 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));
45496
45689
  } else {
45497
- w2 = cround(margin.x * SCALE2 * width2 * POINTS_PER_INCH6);
45498
- 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);
45499
45692
  }
45500
45693
  return {
45501
45694
  val: 0,
@@ -45530,8 +45723,8 @@ function cAdjust(g, mode) {
45530
45723
  if (!overlaps(nlist)) return 0;
45531
45724
  runPlan(g, nlist, PLANS.get(mode) ?? PLANS.get(AM_PORTHO));
45532
45725
  for (const p of nlist) {
45533
- const x = p.pos.x / POINTS_PER_INCH6 / SCALE;
45534
- 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;
45535
45728
  if (p.np.info.pos) {
45536
45729
  p.np.info.pos[0] = x;
45537
45730
  p.np.info.pos[1] = y;
@@ -45546,10 +45739,10 @@ function cAdjust(g, mode) {
45546
45739
  var POLY_BOX = 1;
45547
45740
  var POLY_CIRCLE = 2;
45548
45741
  var DFLT_SAMPLE2 = 20;
45549
- var POINTS_PER_INCH7 = 72;
45742
+ var POINTS_PER_INCH8 = 72;
45550
45743
  var MIN_SAMPLES = 3;
45551
45744
  function ps2inch2(a) {
45552
- return a / POINTS_PER_INCH7;
45745
+ return a / POINTS_PER_INCH8;
45553
45746
  }
45554
45747
  function isBoxKind(p) {
45555
45748
  return (p.kind & POLY_BOX) !== 0;
@@ -45842,7 +46035,7 @@ function polyOverlap(p, pp, q, qp) {
45842
46035
  // src/layout/neato/adjust-info.ts
45843
46036
  var DEFAULT_VORO_MARGIN = 0.05;
45844
46037
  var INCR = 0.05;
45845
- var POINTS_PER_INCH8 = 72;
46038
+ var POINTS_PER_INCH9 = 72;
45846
46039
  function newInfoState() {
45847
46040
  return {
45848
46041
  nodeInfo: [],
@@ -45897,8 +46090,8 @@ function chkBoundBox(st, graph) {
45897
46090
  function makeInfo(st, graph) {
45898
46091
  const pmargin = { ...sepFactor(graph) };
45899
46092
  if (pmargin.doAdd) {
45900
- pmargin.x /= POINTS_PER_INCH8;
45901
- pmargin.y /= POINTS_PER_INCH8;
46093
+ pmargin.x /= POINTS_PER_INCH9;
46094
+ pmargin.y /= POINTS_PER_INCH9;
45902
46095
  }
45903
46096
  const polyf = pmargin.doAdd ? makeAddPoly : makePoly;
45904
46097
  const info = [];
@@ -46964,7 +47157,7 @@ function genYConstraints(rects, vs) {
46964
47157
  }
46965
47158
 
46966
47159
  // src/layout/neato/vpsc-adjust.ts
46967
- var POINTS_PER_INCH9 = 72;
47160
+ var POINTS_PER_INCH10 = 72;
46968
47161
  var X_PASS_SCALE = Math.fround(1.0001);
46969
47162
  function buildRects(c, size, gap, scale) {
46970
47163
  return size.map((s, i) => {
@@ -46989,8 +47182,8 @@ function solveAxis2(c, size, gap, axis) {
46989
47182
  function vpscAdjust(g) {
46990
47183
  const margin = sepFactor(g);
46991
47184
  const gap = {
46992
- x: 2 * (margin.doAdd ? margin.x : DFLT_MARGIN) / POINTS_PER_INCH9,
46993
- 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
46994
47187
  };
46995
47188
  const nodes = Array.from(g.nodes.values());
46996
47189
  const c = [new Float32Array(nodes.length), new Float32Array(nodes.length)];
@@ -47169,7 +47362,7 @@ function graphAdjustMode(g) {
47169
47362
  }
47170
47363
 
47171
47364
  // src/layout/twopi/init.ts
47172
- var POINTS_PER_INCH10 = 72;
47365
+ var POINTS_PER_INCH11 = 72;
47173
47366
  function makeRdata(INF) {
47174
47367
  return {
47175
47368
  kind: "twopi",
@@ -47221,19 +47414,24 @@ function finaliseCoords(g) {
47221
47414
  const pos = n.info.pos;
47222
47415
  if (!pos) continue;
47223
47416
  n.info.coord = {
47224
- x: (pos[0] ?? 0) * POINTS_PER_INCH10,
47225
- y: (pos[1] ?? 0) * POINTS_PER_INCH10
47417
+ x: (pos[0] ?? 0) * POINTS_PER_INCH11,
47418
+ y: (pos[1] ?? 0) * POINTS_PER_INCH11
47226
47419
  };
47227
47420
  }
47228
47421
  }
47229
47422
  function adjustNodes(g) {
47230
47423
  adjustNodesFull(g);
47231
47424
  }
47232
- function twopiCleanup(g) {
47425
+ function twopiFreeAlg(g) {
47233
47426
  const first = g.nodes.values().next().value;
47234
47427
  if (first !== void 0 && first.info.alg?.kind === "twopi") {
47235
47428
  first.info.alg = void 0;
47236
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);
47237
47435
  g.info.neato_nlist = void 0;
47238
47436
  }
47239
47437
 
@@ -47502,7 +47700,7 @@ function layoutSingle(g, comps, globalRoot, setRoot) {
47502
47700
  if (setRoot && globalRoot === null && center !== null) {
47503
47701
  g.attrs.set("root", center.name);
47504
47702
  }
47505
- twopiCleanup(g);
47703
+ twopiFreeAlg(g);
47506
47704
  splineEdgesShifted(g);
47507
47705
  finaliseCoords(g);
47508
47706
  }
@@ -47511,7 +47709,7 @@ function layoutMulti(g, comps, globalRoot, pinfo) {
47511
47709
  layoutComponent(g, sg, globalRoot);
47512
47710
  finaliseCoords(sg);
47513
47711
  }
47514
- twopiCleanup(g);
47712
+ twopiFreeAlg(g);
47515
47713
  packSubgraphs(comps.length, comps, g, pinfo);
47516
47714
  splineEdgesShifted(g);
47517
47715
  finaliseCoords(g);
@@ -47915,7 +48113,18 @@ function fdpInitNodeEdge(g) {
47915
48113
  }
47916
48114
  initialPositions3(g);
47917
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
+ }
47918
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);
47919
48128
  for (const n of g.nodes.values()) {
47920
48129
  n.info.alg = void 0;
47921
48130
  n.info.pos = void 0;
@@ -48859,7 +49068,7 @@ function expandCluster2(n, cg) {
48859
49068
  }
48860
49069
 
48861
49070
  // src/layout/fdp/layout.ts
48862
- var POINTS_PER_INCH11 = 72;
49071
+ var POINTS_PER_INCH12 = 72;
48863
49072
  var DEFAULT_NODEWIDTH_PTS = 54;
48864
49073
  var DEFAULT_NODEHEIGHT_PTS = 36;
48865
49074
  function initInfo(g) {
@@ -48954,7 +49163,7 @@ function shiftComponents(cc, pts, pt) {
48954
49163
  } else {
48955
49164
  p = pt;
48956
49165
  }
48957
- 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 };
48958
49167
  for (const n of cc[i].nodes.values()) {
48959
49168
  n.info.pos[0] += del.x;
48960
49169
  n.info.pos[1] += del.y;
@@ -48970,8 +49179,8 @@ function finalCC(g, cc, pts, rg, infop) {
48970
49179
  const pt = applyMarginAndBorder(rg, bb, margin);
48971
49180
  if (cc.length > 0) shiftComponents(cc, pts, pt);
48972
49181
  gdata(g).bb = {
48973
- ll: { x: bb.ll.x / POINTS_PER_INCH11, y: bb.ll.y / POINTS_PER_INCH11 },
48974
- 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 }
48975
49184
  };
48976
49185
  }
48977
49186
  function applyMarginAndBorder(rg, bb, margin) {
@@ -49017,8 +49226,8 @@ function translateOwnNodes(g, bb) {
49017
49226
  function setBB(g) {
49018
49227
  const bb = gdata(g).bb;
49019
49228
  g.info.bb = {
49020
- ll: { x: POINTS_PER_INCH11 * bb.ll.x, y: POINTS_PER_INCH11 * bb.ll.y },
49021
- 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 }
49022
49231
  };
49023
49232
  const nClusters = g.info.n_cluster ?? 0;
49024
49233
  for (let i = 0; i < nClusters; i++) {
@@ -49033,8 +49242,8 @@ function setClustNodes(root) {
49033
49242
  const bb = gdata(p).bb;
49034
49243
  const w = bb.ur.x - bb.ll.x;
49035
49244
  const h = bb.ur.y - bb.ll.y;
49036
- const w2 = POINTS_PER_INCH11 * (w / 2);
49037
- const h2 = POINTS_PER_INCH11 * (h / 2);
49245
+ const w2 = POINTS_PER_INCH12 * (w / 2);
49246
+ const h2 = POINTS_PER_INCH12 * (h / 2);
49038
49247
  n.info.pos[0] = w / 2;
49039
49248
  n.info.pos[1] = h / 2;
49040
49249
  n.info.width = w;
@@ -49043,7 +49252,7 @@ function setClustNodes(root) {
49043
49252
  n.info.outline_width = w + penwidth;
49044
49253
  n.info.outline_height = h + penwidth;
49045
49254
  n.info.lw = n.info.rw = w2;
49046
- n.info.ht = POINTS_PER_INCH11 * h;
49255
+ n.info.ht = POINTS_PER_INCH12 * h;
49047
49256
  const poly = n.info.shape_info;
49048
49257
  if (poly && poly.vertices) {
49049
49258
  poly.vertices[0] = { x: w2, y: h2 };
@@ -49056,8 +49265,8 @@ function setClustNodes(root) {
49056
49265
  function syncCoordFromPos(cg) {
49057
49266
  for (const n of cg.nodes.values()) {
49058
49267
  n.info.coord = {
49059
- x: POINTS_PER_INCH11 * n.info.pos[0],
49060
- 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]
49061
49270
  };
49062
49271
  }
49063
49272
  }
@@ -49069,8 +49278,8 @@ function expandComponentClusters(cg, infop, counter) {
49069
49278
  if (r !== 0) return r;
49070
49279
  n.info.width = gdata(sg).bb.ur.x;
49071
49280
  n.info.height = gdata(sg).bb.ur.y;
49072
- const ptx = POINTS_PER_INCH11 * gdata(sg).bb.ur.x;
49073
- 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;
49074
49283
  n.info.rw = n.info.lw = ptx / 2;
49075
49284
  n.info.ht = pty;
49076
49285
  } else if (isPort(n)) {
@@ -50720,6 +50929,9 @@ function circoLayoutFull(g) {
50720
50929
  gvPostprocess(g);
50721
50930
  }
50722
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);
50723
50935
  g.info.alg = void 0;
50724
50936
  g.info.neato_nlist = void 0;
50725
50937
  }
@@ -51007,11 +51219,17 @@ function osageLayout(g) {
51007
51219
  }
51008
51220
  function cleanupGraphs(g) {
51009
51221
  const nClust = g.info.n_cluster ?? 0;
51010
- 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
+ }
51011
51227
  g.info.clust = void 0;
51012
51228
  g.info.n_cluster = void 0;
51013
51229
  }
51014
51230
  function osageCleanup(g) {
51231
+ for (const e of g.edges) gvCleanupEdgeLabels(e);
51232
+ for (const n of g.nodes.values()) gvCleanupNodeLabels(n);
51015
51233
  for (const n of g.nodes.values()) {
51016
51234
  if (n.info.alg?.kind === "osage") n.info.alg = void 0;
51017
51235
  }
@@ -51362,6 +51580,9 @@ function patchworkEngineLayout(g) {
51362
51580
  gvPostprocess(g);
51363
51581
  }
51364
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);
51365
51586
  g.info.clust = void 0;
51366
51587
  g.info.n_cluster = void 0;
51367
51588
  for (const n of g.nodes.values()) {
@@ -52061,7 +52282,7 @@ var PlainExtRenderer = class {
52061
52282
  }
52062
52283
  };
52063
52284
  function mapGraphName(g) {
52064
- return g.anonymous ? "%1" : g.name;
52285
+ return agNameOf(g);
52065
52286
  }
52066
52287
  function graphAttr2(g, key) {
52067
52288
  for (let s = g; s !== null; s = s.parent) {
@@ -52077,7 +52298,7 @@ function graphMapUrl(g) {
52077
52298
  function buildMapCtx(g, job, mapPolygon) {
52078
52299
  const drawingDpi = lateDouble(g.attrs.get("dpi"), lateDouble(g.attrs.get("resolution"), 0, 0), 0);
52079
52300
  const mapDpi = drawingDpi > 0 ? drawingDpi : 96;
52080
- const devscale = mapDpi / POINTS_PER_INCH;
52301
+ const devscale = mapDpi / POINTS_PER_INCH2;
52081
52302
  const z = initJobViewportZoom(job.bb, parseDrawingSize(g.attrs.get("size")), job.pad);
52082
52303
  const marginOff = { x: job.margin.x * devscale, y: job.margin.y * devscale };
52083
52304
  return { bb: job.bb, pad: job.pad, scale: z * devscale, marginOff, mapPolygon };
@@ -52563,8 +52784,8 @@ function graphLabelAttrs(g) {
52563
52784
  }
52564
52785
  return [
52565
52786
  'lp="' + lpStr(label.pos) + '"',
52566
- "lwidth=" + gfmt2(label.dimen.x / POINTS_PER_INCH),
52567
- "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)
52568
52789
  ];
52569
52790
  }
52570
52791
  function edgePosRaw(e) {
@@ -58596,8 +58817,8 @@ function latin1Reencode(s) {
58596
58817
  for (const b of bytes) out += String.fromCharCode(b);
58597
58818
  return out;
58598
58819
  }
58599
- function buildJson(g, doXDot) {
58600
- const draws = doXDot ? collectDrawLookup(g) : void 0;
58820
+ function buildJson(g, doXDot, preDraws) {
58821
+ const draws = doXDot ? preDraws ?? collectDrawLookup(g) : void 0;
58601
58822
  const ctx = assignIds(g, doXDot, draws);
58602
58823
  const root = buildGraphObject(g, true, ctx);
58603
58824
  return JSON.stringify(root, null, 2) + "\n";
@@ -58634,10 +58855,15 @@ var JsonRenderer = class {
58634
58855
  type = "json";
58635
58856
  /** @see plugin/core/gvplugin_core.c registration table */
58636
58857
  quality = 0;
58637
- 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);
58638
58863
  }
58639
58864
  endGraph(g, job) {
58640
- job.write(buildJson(g, true));
58865
+ job.write(buildJson(g, true, this.draws));
58866
+ this.draws = void 0;
58641
58867
  }
58642
58868
  beginNode(_n, _job) {
58643
58869
  }