@knowvah/dot-engine 2.6.12 → 2.7.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 (190) hide show
  1. package/README.md +1 -1
  2. package/dist/api.js +18 -4
  3. package/dist/api.js.map +3 -3
  4. package/dist/common/htmltable-emit-fill.d.ts +20 -2
  5. package/dist/common/htmltable-emit-fill.d.ts.map +1 -1
  6. package/dist/common/htmltable-emit.d.ts.map +1 -1
  7. package/dist/common/htmltable-lex-expat.d.ts.map +1 -1
  8. package/dist/common/htmltable-pos-runs.d.ts +7 -4
  9. package/dist/common/htmltable-pos-runs.d.ts.map +1 -1
  10. package/dist/common/htmltable.d.ts.map +1 -1
  11. package/dist/common/libm-trig.d.ts +5 -0
  12. package/dist/common/libm-trig.d.ts.map +1 -0
  13. package/dist/common/multicolor.d.ts +21 -13
  14. package/dist/common/multicolor.d.ts.map +1 -1
  15. package/dist/common/poly-gencode.d.ts +1 -2
  16. package/dist/common/poly-gencode.d.ts.map +1 -1
  17. package/dist/common/poly-init.d.ts.map +1 -1
  18. package/dist/common/splines-clip.d.ts +7 -0
  19. package/dist/common/splines-clip.d.ts.map +1 -1
  20. package/dist/gvc/context.d.ts +6 -0
  21. package/dist/gvc/context.d.ts.map +1 -1
  22. package/dist/gvc/device-cluster.d.ts +15 -0
  23. package/dist/gvc/device-cluster.d.ts.map +1 -1
  24. package/dist/gvc/device.d.ts.map +1 -1
  25. package/dist/gvc/first-layer.d.ts +9 -0
  26. package/dist/gvc/first-layer.d.ts.map +1 -0
  27. package/dist/gvc/gvrender-set-style.d.ts +28 -0
  28. package/dist/gvc/gvrender-set-style.d.ts.map +1 -0
  29. package/dist/gvc/usershape.d.ts +18 -0
  30. package/dist/gvc/usershape.d.ts.map +1 -1
  31. package/dist/index.js +2460 -901
  32. package/dist/index.js.map +4 -4
  33. package/dist/layout/dot/compound.d.ts.map +1 -1
  34. package/dist/layout/dot/edge-route-clip.d.ts +14 -4
  35. package/dist/layout/dot/edge-route-clip.d.ts.map +1 -1
  36. package/dist/layout/dot/edge-route-routing.d.ts.map +1 -1
  37. package/dist/layout/neato/__fixtures__/dijkstra-f.d.ts +11 -0
  38. package/dist/layout/neato/__fixtures__/dijkstra-f.d.ts.map +1 -0
  39. package/dist/layout/neato/__fixtures__/hier-imds.d.ts +36 -0
  40. package/dist/layout/neato/__fixtures__/hier-imds.d.ts.map +1 -0
  41. package/dist/layout/neato/__fixtures__/hier-majorization.d.ts +32 -0
  42. package/dist/layout/neato/__fixtures__/hier-majorization.d.ts.map +1 -0
  43. package/dist/layout/neato/cdt-surface.d.ts.map +1 -1
  44. package/dist/layout/neato/compute-hierarchy.d.ts +24 -0
  45. package/dist/layout/neato/compute-hierarchy.d.ts.map +1 -0
  46. package/dist/layout/neato/conjgrad-mkernel.d.ts +20 -0
  47. package/dist/layout/neato/conjgrad-mkernel.d.ts.map +1 -0
  48. package/dist/layout/neato/conjgrad.d.ts +19 -0
  49. package/dist/layout/neato/conjgrad.d.ts.map +1 -1
  50. package/dist/layout/neato/constrained-majorization.d.ts +26 -0
  51. package/dist/layout/neato/constrained-majorization.d.ts.map +1 -0
  52. package/dist/layout/neato/dijkstra.d.ts +33 -16
  53. package/dist/layout/neato/dijkstra.d.ts.map +1 -1
  54. package/dist/layout/neato/gts-triangle.d.ts +14 -0
  55. package/dist/layout/neato/gts-triangle.d.ts.map +1 -0
  56. package/dist/layout/neato/init.d.ts +2 -12
  57. package/dist/layout/neato/init.d.ts.map +1 -1
  58. package/dist/layout/neato/kkutils.d.ts +20 -0
  59. package/dist/layout/neato/kkutils.d.ts.map +1 -0
  60. package/dist/layout/neato/make-graph-data.d.ts +43 -0
  61. package/dist/layout/neato/make-graph-data.d.ts.map +1 -0
  62. package/dist/layout/neato/matrix-ops.d.ts +46 -0
  63. package/dist/layout/neato/matrix-ops.d.ts.map +1 -1
  64. package/dist/layout/neato/opt-arrangement.d.ts +20 -0
  65. package/dist/layout/neato/opt-arrangement.d.ts.map +1 -0
  66. package/dist/layout/neato/quad-prog-solve.d.ts +44 -0
  67. package/dist/layout/neato/quad-prog-solve.d.ts.map +1 -0
  68. package/dist/layout/neato/smart-ini-x.d.ts +9 -0
  69. package/dist/layout/neato/smart-ini-x.d.ts.map +1 -0
  70. package/dist/layout/neato/splines.d.ts +1 -1
  71. package/dist/layout/neato/splines.d.ts.map +1 -1
  72. package/dist/layout/neato/start.d.ts +4 -1
  73. package/dist/layout/neato/start.d.ts.map +1 -1
  74. package/dist/layout/neato/stress.d.ts +8 -0
  75. package/dist/layout/neato/stress.d.ts.map +1 -1
  76. package/dist/model/edge.d.ts +1 -1
  77. package/dist/model/edge.d.ts.map +1 -1
  78. package/dist/model/lazy-attrs.d.ts +10 -0
  79. package/dist/model/lazy-attrs.d.ts.map +1 -0
  80. package/dist/model/node.d.ts +1 -1
  81. package/dist/model/node.d.ts.map +1 -1
  82. package/dist/ortho/index.d.ts.map +1 -1
  83. package/dist/render/dot/edge-draw.d.ts +1 -1
  84. package/dist/render/dot/edge-draw.d.ts.map +1 -1
  85. package/dist/render/svg-multicolor.d.ts +2 -2
  86. package/dist/render/svg-multicolor.d.ts.map +1 -1
  87. package/dist/render.js +2340 -781
  88. package/dist/render.js.map +4 -4
  89. package/package.json +1 -1
  90. package/src/common/graph-init.ts +1 -1
  91. package/src/common/htmltable-emit-fill.ts +56 -11
  92. package/src/common/htmltable-emit.ts +4 -3
  93. package/src/common/htmltable-lex-expat.ts +21 -3
  94. package/src/common/htmltable-pos-runs.ts +11 -6
  95. package/src/common/htmltable.ts +28 -116
  96. package/src/common/libm-trig.ts +43 -0
  97. package/src/common/multicolor.ts +88 -24
  98. package/src/common/poly-gencode.ts +16 -8
  99. package/src/common/poly-init.ts +19 -1
  100. package/src/common/postproc.ts +2 -2
  101. package/src/common/splines-clip.ts +15 -12
  102. package/src/common/splines-routespl.ts +2 -2
  103. package/src/common/textmeasure-lookup.ts +1 -1
  104. package/src/gvc/context.ts +8 -0
  105. package/src/gvc/device-cluster.ts +63 -8
  106. package/src/gvc/device.ts +16 -2
  107. package/src/gvc/first-layer.ts +26 -0
  108. package/src/gvc/gvrender-set-style.ts +114 -0
  109. package/src/gvc/usershape.ts +26 -0
  110. package/src/layout/dot/cluster.ts +1 -1
  111. package/src/layout/dot/compound.ts +3 -4
  112. package/src/layout/dot/conc.ts +1 -1
  113. package/src/layout/dot/edge-route-clip.ts +19 -7
  114. package/src/layout/dot/edge-route-routing.ts +11 -3
  115. package/src/layout/dot/fastgr.ts +2 -2
  116. package/src/layout/neato/__fixtures__/dijkstra-f.ts +17 -0
  117. package/src/layout/neato/__fixtures__/hier/c1554.gv +33 -0
  118. package/src/layout/neato/__fixtures__/hier/c1554.plain +26 -0
  119. package/src/layout/neato/__fixtures__/hier/c1554.xdot +161 -0
  120. package/src/layout/neato/__fixtures__/hier/cases/cycle.gv +1 -0
  121. package/src/layout/neato/__fixtures__/hier/cases/cycle.plain +10 -0
  122. package/src/layout/neato/__fixtures__/hier/cases/cycle.stderr +0 -0
  123. package/src/layout/neato/__fixtures__/hier/cases/dirnone.gv +1 -0
  124. package/src/layout/neato/__fixtures__/hier/cases/dirnone.plain +11 -0
  125. package/src/layout/neato/__fixtures__/hier/cases/dirnone.stderr +0 -0
  126. package/src/layout/neato/__fixtures__/hier/cases/epsilon.gv +1 -0
  127. package/src/layout/neato/__fixtures__/hier/cases/epsilon.plain +13 -0
  128. package/src/layout/neato/__fixtures__/hier/cases/epsilon.stderr +0 -0
  129. package/src/layout/neato/__fixtures__/hier/cases/levelsgap.gv +1 -0
  130. package/src/layout/neato/__fixtures__/hier/cases/levelsgap.plain +8 -0
  131. package/src/layout/neato/__fixtures__/hier/cases/levelsgap.stderr +0 -0
  132. package/src/layout/neato/__fixtures__/hier/cases/mds.gv +1 -0
  133. package/src/layout/neato/__fixtures__/hier/cases/mds.plain +10 -0
  134. package/src/layout/neato/__fixtures__/hier/cases/mds.stderr +0 -0
  135. package/src/layout/neato/__fixtures__/hier/cases/multiedge.gv +1 -0
  136. package/src/layout/neato/__fixtures__/hier/cases/multiedge.plain +10 -0
  137. package/src/layout/neato/__fixtures__/hier/cases/multiedge.stderr +0 -0
  138. package/src/layout/neato/__fixtures__/hier/cases/neglevelsgap.gv +1 -0
  139. package/src/layout/neato/__fixtures__/hier/cases/neglevelsgap.plain +8 -0
  140. package/src/layout/neato/__fixtures__/hier/cases/neglevelsgap.stderr +0 -0
  141. package/src/layout/neato/__fixtures__/hier/cases/startrandom.gv +1 -0
  142. package/src/layout/neato/__fixtures__/hier/cases/startrandom.plain +10 -0
  143. package/src/layout/neato/__fixtures__/hier/cases/startrandom.stderr +0 -0
  144. package/src/layout/neato/__fixtures__/hier/cases/startregular.gv +1 -0
  145. package/src/layout/neato/__fixtures__/hier/cases/startregular.plain +10 -0
  146. package/src/layout/neato/__fixtures__/hier/cases/startregular.stderr +0 -0
  147. package/src/layout/neato/__fixtures__/hier/cases/tdist.gv +1 -0
  148. package/src/layout/neato/__fixtures__/hier/cases/tdist.plain +13 -0
  149. package/src/layout/neato/__fixtures__/hier/cases/tdist.stderr +0 -0
  150. package/src/layout/neato/__fixtures__/hier/cases/undirected.gv +1 -0
  151. package/src/layout/neato/__fixtures__/hier/cases/undirected.plain +10 -0
  152. package/src/layout/neato/__fixtures__/hier/cases/undirected.stderr +0 -0
  153. package/src/layout/neato/__fixtures__/hier/hier-probe.gv +1 -0
  154. package/src/layout/neato/__fixtures__/hier/hier-probe.plain +16 -0
  155. package/src/layout/neato/__fixtures__/hier/hier-probe.xdot +62 -0
  156. package/src/layout/neato/__fixtures__/hier-imds.ts +151 -0
  157. package/src/layout/neato/__fixtures__/hier-majorization.ts +145 -0
  158. package/src/layout/neato/cdt-surface.ts +6 -16
  159. package/src/layout/neato/compute-hierarchy.ts +90 -0
  160. package/src/layout/neato/conjgrad-mkernel.ts +141 -0
  161. package/src/layout/neato/conjgrad.ts +208 -0
  162. package/src/layout/neato/constrained-majorization.ts +479 -0
  163. package/src/layout/neato/dijkstra.ts +218 -92
  164. package/src/layout/neato/edge-len.ts +2 -2
  165. package/src/layout/neato/fdp-adjust.ts +3 -3
  166. package/src/layout/neato/gts-triangle.ts +42 -0
  167. package/src/layout/neato/init.ts +57 -57
  168. package/src/layout/neato/kk.ts +2 -2
  169. package/src/layout/neato/kkutils.ts +96 -0
  170. package/src/layout/neato/make-graph-data.ts +166 -0
  171. package/src/layout/neato/matrix-ops.ts +138 -0
  172. package/src/layout/neato/opt-arrangement.ts +86 -0
  173. package/src/layout/neato/quad-prog-solve.ts +489 -0
  174. package/src/layout/neato/smart-ini-x.ts +503 -0
  175. package/src/layout/neato/splines.ts +4 -4
  176. package/src/layout/neato/start.ts +7 -6
  177. package/src/layout/neato/stress.ts +28 -0
  178. package/src/model/edge.ts +3 -2
  179. package/src/model/lazy-attrs.ts +36 -0
  180. package/src/model/node.ts +3 -2
  181. package/src/ortho/index.ts +2 -3
  182. package/src/parser/dot.js +1 -1
  183. package/src/parser/dot.pegjs +1 -1
  184. package/src/parser/index.ts +1 -1
  185. package/src/render/color-resolve.ts +2 -2
  186. package/src/render/dot/edge-draw.ts +6 -3
  187. package/src/render/dot.ts +1 -1
  188. package/src/render/svg-edge-split.ts +2 -2
  189. package/src/render/svg-multicolor.ts +4 -3
  190. package/src/render/svg-parallel-edge.ts +2 -2
package/dist/render.js CHANGED
@@ -1,3 +1,12 @@
1
+ // src/common/render-state.ts
2
+ var resets = [];
3
+ function registerRenderState(reset2) {
4
+ resets.push(reset2);
5
+ }
6
+ function resetRenderState() {
7
+ for (const reset2 of resets) reset2();
8
+ }
9
+
1
10
  // src/errors.ts
2
11
  var FRIENDLY_MESSAGES = {
3
12
  SYNTAX_ERROR: "There is a syntax error in the DOT source.",
@@ -214,6 +223,12 @@ var GvcContext = class {
214
223
  * rendering happens in between and must see the layout state
215
224
  * (e.g. cluster arrays).
216
225
  *
226
+ * Contract (AD-4/AD-8): first resets the C process state (RNG streams,
227
+ * sequence counters, once-only warnings), so each `layout` call behaves
228
+ * as one native run — drive one graph per `layout`. Caller-installed hooks
229
+ * (setTextMeasurer, setImageSizer, setImageResolver, the per-context
230
+ * measurer/sizer/resolver) are configuration and are not reset.
231
+ *
217
232
  * @throws TypeError (ERR_INVALID_ARG_TYPE / ERR_INVALID_ARG_VALUE) for a
218
233
  * bad `g`, or an engine argument that is not registered
219
234
  * @throws RenderError (UNKNOWN_LAYOUT) if the `layout` attribute names no
@@ -224,6 +239,7 @@ var GvcContext = class {
224
239
  * @see lib/gvc/gvlayout.c:gvLayoutJobs
225
240
  */
226
241
  layout(g, engineName) {
242
+ resetRenderState();
227
243
  const selected = this.checkLayoutArgs(g, engineName);
228
244
  const attr2 = g.attrs?.get("layout");
229
245
  let engine = selected;
@@ -5079,15 +5095,6 @@ var ALL_FONT_METRICS = [
5079
5095
  CALIBRI_FAMILY
5080
5096
  ];
5081
5097
 
5082
- // src/common/render-state.ts
5083
- var resets = [];
5084
- function registerRenderState(reset2) {
5085
- resets.push(reset2);
5086
- }
5087
- function resetRenderState() {
5088
- for (const reset2 of resets) reset2();
5089
- }
5090
-
5091
5098
  // src/common/agerr.ts
5092
5099
  var PREFIX_ERROR = "Error";
5093
5100
  var PREFIX_WARNING = "Warning";
@@ -5152,7 +5159,7 @@ function getFamilyMetrics(fontName) {
5152
5159
  if (!warnedFontNames.has(fontName)) {
5153
5160
  warnedFontNames.add(fontName);
5154
5161
  agwarningf(
5155
- `no hard-coded metrics for '${fontName}'. Falling back to 'Times' metrics`
5162
+ `Warning: no hard-coded metrics for '${fontName}'. Falling back to 'Times' metrics`
5156
5163
  );
5157
5164
  }
5158
5165
  return TIMES_FALLBACK;
@@ -6286,9 +6293,15 @@ function scanCdata(text, p, base, dataOf, tokens) {
6286
6293
  if (end > p) tokens.push({ kind: "cdata", start: base + p, end: base + end, data: dataOf(base + p, base + end) });
6287
6294
  return close < 0 ? -1 : close + CDATA_CLOSE.length;
6288
6295
  }
6296
+ var CONTENT_NON_XML = /[\x00-\x08\x0b\x0c\x0e-\x1f\ufffe\uffff]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/;
6289
6297
  function scanText(text, p, base, tokens) {
6290
6298
  const e = text.indexOf("<", p);
6291
6299
  const slice = text.slice(p, e < 0 ? text.length : e);
6300
+ const bad = CONTENT_NON_XML.exec(slice)?.index;
6301
+ if (bad !== void 0) {
6302
+ if (bad > 0) tokens.push({ kind: "text", start: base + p, end: base + p + bad });
6303
+ return { at: p + bad, held: false, invalid: p + bad };
6304
+ }
6292
6305
  const from = e < 0 ? heldRefStart(slice) : void 0;
6293
6306
  const end = from === void 0 ? p + slice.length : p + from;
6294
6307
  if (end > p) tokens.push({ kind: "text", start: base + p, end: base + end });
@@ -6308,6 +6321,7 @@ function scanContent(text, base, inCdata, dataOf) {
6308
6321
  }
6309
6322
  if (text[p] !== "<") {
6310
6323
  const scanned = scanText(text, p, base, tokens);
6324
+ if (scanned.invalid !== void 0) return { tokens, consumed: scanned.at, invalid: base + scanned.invalid, inCdata: false };
6311
6325
  if (scanned.held) return { tokens, consumed: scanned.at, inCdata: false };
6312
6326
  p = scanned.at;
6313
6327
  continue;
@@ -7314,11 +7328,79 @@ var parseHtmlLabelRv = (src, stderr) => {
7314
7328
  };
7315
7329
  var parseHtmlLabel = (src) => parseHtmlLabelRv(src, new StderrLines(() => void 0)).label;
7316
7330
 
7331
+ // src/gvc/image-resolver.ts
7332
+ var activeResolver = null;
7333
+ var EXT_MIME = {
7334
+ png: "image/png",
7335
+ jpg: "image/jpeg",
7336
+ jpeg: "image/jpeg",
7337
+ gif: "image/gif",
7338
+ svg: "image/svg+xml",
7339
+ webp: "image/webp"
7340
+ };
7341
+ var FALLBACK_MIME = "application/octet-stream";
7342
+ function inferMimeFromSrc(src) {
7343
+ const dot = src.lastIndexOf(".");
7344
+ if (dot < 0 || dot === src.length - 1) return FALLBACK_MIME;
7345
+ const ext = src.slice(dot + 1).toLowerCase();
7346
+ return EXT_MIME[ext] ?? FALLBACK_MIME;
7347
+ }
7348
+ function findImageBytes(src, resolver) {
7349
+ const active = resolver ?? activeResolver;
7350
+ if (active === null) return null;
7351
+ const result = active(src);
7352
+ if (result === null) return null;
7353
+ if (result instanceof Uint8Array) {
7354
+ return { bytes: result, mime: inferMimeFromSrc(src) };
7355
+ }
7356
+ return { bytes: result.bytes, mime: result.mime ?? inferMimeFromSrc(src) };
7357
+ }
7358
+ var B64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7359
+ function base64Encode(bytes) {
7360
+ const len = bytes.length;
7361
+ const out = [];
7362
+ let i = 0;
7363
+ for (; i + 2 < len; i += 3) {
7364
+ const n = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2];
7365
+ out.push(
7366
+ B64_CHARS[n >> 18 & 63],
7367
+ B64_CHARS[n >> 12 & 63],
7368
+ B64_CHARS[n >> 6 & 63],
7369
+ B64_CHARS[n & 63]
7370
+ );
7371
+ }
7372
+ const remaining = len - i;
7373
+ if (remaining === 1) {
7374
+ const n = bytes[i] << 16;
7375
+ out.push(B64_CHARS[n >> 18 & 63], B64_CHARS[n >> 12 & 63], "==");
7376
+ } else if (remaining === 2) {
7377
+ const n = bytes[i] << 16 | bytes[i + 1] << 8;
7378
+ out.push(
7379
+ B64_CHARS[n >> 18 & 63],
7380
+ B64_CHARS[n >> 12 & 63],
7381
+ B64_CHARS[n >> 6 & 63],
7382
+ "="
7383
+ );
7384
+ }
7385
+ return out.join("");
7386
+ }
7387
+ function toDataUri(bytes, mime) {
7388
+ return "data:" + mime + ";base64," + base64Encode(bytes);
7389
+ }
7390
+
7317
7391
  // src/gvc/usershape.ts
7318
7392
  var activeSizer = null;
7319
7393
  function findImageSize(src) {
7320
7394
  return activeSizer !== null ? activeSizer(src) : null;
7321
7395
  }
7396
+ var STRERROR_ENOENT = "No such file or directory";
7397
+ function imageIsSupplied(name, sizer, resolver) {
7398
+ const size = sizer !== void 0 ? sizer(name) : findImageSize(name);
7399
+ return size !== null || findImageBytes(name, resolver) !== null;
7400
+ }
7401
+ function imageOpenWarning(name) {
7402
+ return `${STRERROR_ENOENT} while opening ${name}`;
7403
+ }
7322
7404
 
7323
7405
  // src/common/pointset.ts
7324
7406
  function cmpPair(a, b) {
@@ -7371,6 +7453,173 @@ var PointSet = class {
7371
7453
  }
7372
7454
  };
7373
7455
 
7456
+ // src/common/emit-types.ts
7457
+ var PS2INCH = 1 / 72;
7458
+ var HTML_BF = 1 << 0;
7459
+ var HTML_IF = 1 << 1;
7460
+ var HTML_UL = 1 << 2;
7461
+ var HTML_SUP = 1 << 3;
7462
+ var HTML_SUB = 1 << 4;
7463
+ var HTML_S = 1 << 5;
7464
+ var HTML_OL = 1 << 6;
7465
+
7466
+ // src/common/htmltable-pos-runs.ts
7467
+ function itemFontFlags(item) {
7468
+ let f = 0;
7469
+ if (item.bold) f |= HTML_BF;
7470
+ if (item.italic) f |= HTML_IF;
7471
+ if (item.underline) f |= HTML_UL;
7472
+ if (item.superscript) f |= HTML_SUP;
7473
+ if (item.subscript) f |= HTML_SUB;
7474
+ if (item.strikethrough) f |= HTML_S;
7475
+ if (item.overline) f |= HTML_OL;
7476
+ return f;
7477
+ }
7478
+ function itemFace(item, finfo) {
7479
+ return {
7480
+ fs: item.fontSize !== void 0 ? item.fontSize : finfo.fontsize,
7481
+ face: item.fontFace !== void 0 ? item.fontFace : finfo.fontname
7482
+ };
7483
+ }
7484
+ function measureItem(item, finfo, measurer) {
7485
+ if (item.text === void 0) return null;
7486
+ const { fs, face } = itemFace(item, finfo);
7487
+ const flags = itemFontFlags(item);
7488
+ const sz = measurer.measure(
7489
+ item.text,
7490
+ face,
7491
+ fs,
7492
+ { bold: !!(flags & HTML_BF), italic: !!(flags & HTML_IF) }
7493
+ );
7494
+ return { w: sz.w, h: sz.h, fs, yoffsetCenterline: sz.yoffsetCenterline, yoffsetLayout: sz.yoffsetLayout };
7495
+ }
7496
+ function newRun() {
7497
+ return { items: [], width: 0, fontSize: 0, height: 0, maxOffset: 0, maxLayout: 0 };
7498
+ }
7499
+ function runLeftX(run, box, centerX) {
7500
+ if (run.just === "left") return box.ll.x;
7501
+ if (run.just === "right") return box.ur.x - run.width;
7502
+ return centerX - run.width / 2;
7503
+ }
7504
+ function accumulateItem(cur, item, m) {
7505
+ cur.items.push(item);
7506
+ cur.width += m.w;
7507
+ cur.fontSize = Math.max(cur.fontSize, m.fs);
7508
+ cur.height = Math.max(cur.height, m.h);
7509
+ cur.maxOffset = Math.max(cur.maxOffset, m.yoffsetCenterline ?? 0.05 * m.fs);
7510
+ cur.maxLayout = Math.max(cur.maxLayout, m.yoffsetLayout ?? 0);
7511
+ }
7512
+ function buildLineRuns(texts, finfo, measurer) {
7513
+ const runs = [];
7514
+ let cur = newRun();
7515
+ const flush = (br) => {
7516
+ if (cur.items.length === 0 && br !== void 0) {
7517
+ const { br: _b, brAlign: _a, ...fontProps } = br;
7518
+ const empty = { text: "", ...fontProps };
7519
+ const m = measureItem(empty, finfo, measurer);
7520
+ if (m !== null) accumulateItem(cur, empty, m);
7521
+ }
7522
+ cur.just = br?.brAlign;
7523
+ runs.push(cur);
7524
+ cur = newRun();
7525
+ };
7526
+ for (const txt of texts) {
7527
+ for (const item of txt.items) {
7528
+ if (item.br) {
7529
+ flush(item);
7530
+ continue;
7531
+ }
7532
+ const m = measureItem(item, finfo, measurer);
7533
+ if (m !== null) accumulateItem(cur, item, m);
7534
+ }
7535
+ if (cur.items.length > 0) flush();
7536
+ }
7537
+ return runs;
7538
+ }
7539
+ function runSimpleKey(run, finfo) {
7540
+ if (run.items.length > 1) return null;
7541
+ const item = run.items[0];
7542
+ if (item === void 0) return void 0;
7543
+ if (itemFontFlags(item) !== 0) return null;
7544
+ return itemFace(item, finfo);
7545
+ }
7546
+ function runsAreSimple(runs, finfo) {
7547
+ let prevFs = -1;
7548
+ let prevFace = null;
7549
+ for (const run of runs) {
7550
+ const key = runSimpleKey(run, finfo);
7551
+ if (key === null) return false;
7552
+ if (key === void 0) continue;
7553
+ if (prevFs < 0) prevFs = key.fs;
7554
+ else if (key.fs !== prevFs) return false;
7555
+ if (prevFace === null) prevFace = key.face;
7556
+ else if (key.face !== prevFace) return false;
7557
+ }
7558
+ return true;
7559
+ }
7560
+ function placeRunItems(run, startX, baseline, finfo, measurer) {
7561
+ const lines = [];
7562
+ let x = startX;
7563
+ for (const item of run.items) {
7564
+ const { fs, face } = itemFace(item, finfo);
7565
+ const flags = itemFontFlags(item);
7566
+ const sz = measurer.measure(
7567
+ item.text,
7568
+ face,
7569
+ fs,
7570
+ { bold: !!(flags & HTML_BF), italic: !!(flags & HTML_IF) }
7571
+ );
7572
+ lines.push({
7573
+ text: item.text,
7574
+ x,
7575
+ baseline,
7576
+ width: sz.w,
7577
+ fontSize: fs,
7578
+ fontName: face,
7579
+ fontColor: item.fontColor ?? finfo.fontcolor,
7580
+ fontFlags: flags
7581
+ });
7582
+ x += sz.w;
7583
+ }
7584
+ return lines;
7585
+ }
7586
+ function placeTextRuns(runs, box, finfo, measurer) {
7587
+ if (runsAreSimple(runs, finfo)) {
7588
+ return placeSimpleRuns(runs, box, finfo, measurer);
7589
+ }
7590
+ return placeComplexRuns(runs, box, finfo, measurer);
7591
+ }
7592
+ function placeSimpleRuns(runs, box, finfo, measurer) {
7593
+ const centerX = (box.ll.x + box.ur.x) / 2;
7594
+ const lines = [];
7595
+ let baseline = box.ur.y;
7596
+ for (let i = 0; i < runs.length; i++) {
7597
+ const run = runs[i];
7598
+ const ascent = run.maxLayout > 0 ? run.maxLayout : freetypeAscent(run.fontSize, finfo.fontname);
7599
+ baseline -= i === 0 ? ascent : run.height;
7600
+ lines.push(...placeRunItems(run, runLeftX(run, box, centerX), baseline, finfo, measurer));
7601
+ }
7602
+ return lines;
7603
+ }
7604
+ function placeComplexRuns(runs, box, finfo, measurer) {
7605
+ const centerX = (box.ll.x + box.ur.x) / 2;
7606
+ const lines = [];
7607
+ let curbline = 0;
7608
+ let ysize = 0;
7609
+ for (let i = 0; i < runs.length; i++) {
7610
+ const run = runs[i];
7611
+ const lfsize = i === 0 ? run.fontSize - run.maxOffset : run.fontSize + ysize - curbline - run.maxOffset;
7612
+ curbline += lfsize;
7613
+ ysize += run.fontSize;
7614
+ const baseline = box.ur.y - curbline;
7615
+ for (const pl of placeRunItems(run, runLeftX(run, box, centerX), baseline, finfo, measurer)) {
7616
+ pl.yoffsetCenterline = 1;
7617
+ lines.push(pl);
7618
+ }
7619
+ }
7620
+ return lines;
7621
+ }
7622
+
7374
7623
  // src/common/htmltable-fontinfo.ts
7375
7624
  var SIZE_SAVEF = { fontsize: 0 };
7376
7625
  var EMIT_SAVEF = { fontsize: 0 };
@@ -7432,87 +7681,33 @@ var findCol = (ps, row, startCol, colspan, rowspan) => {
7432
7681
  return col;
7433
7682
  };
7434
7683
  var defaultSizeEnv = () => ({ fontsize: DEFAULT_FONTSIZE, fontname: "" });
7435
- var itemFont = (item, env) => ({
7436
- fs: item.fontSize !== void 0 ? item.fontSize : env.fontsize,
7437
- face: item.fontFace !== void 0 ? item.fontFace : env.fontname
7438
- });
7439
- var measureItem = (item, measurer, env) => {
7440
- const { fs, face } = itemFont(item, env);
7441
- const flags = item.bold === true || item.italic === true ? { bold: item.bold === true, italic: item.italic === true } : void 0;
7442
- return measurer.measure(item.text ?? "", face, fs, flags);
7443
- };
7444
- var splitSizedLines = (texts, measurer, env) => {
7445
- const lines = [];
7446
- let cur = { items: [], width: 0, mxysize: 0, mxfsize: 0 };
7447
- const accumulate = (item) => {
7448
- const sz = measureItem(item, measurer, env);
7449
- cur.items.push(item);
7450
- cur.width += sz.w;
7451
- cur.mxysize = Math.max(cur.mxysize, sz.h);
7452
- cur.mxfsize = Math.max(cur.mxfsize, itemFont(item, env).fs);
7453
- };
7454
- const flush = (br) => {
7455
- if (cur.items.length === 0 && br !== void 0) {
7456
- const { br: _b, brAlign: _a, ...fontProps } = br;
7457
- accumulate({ text: "", ...fontProps });
7458
- }
7459
- lines.push(cur);
7460
- cur = { items: [], width: 0, mxysize: 0, mxfsize: 0 };
7461
- };
7462
- for (const txt of texts) {
7463
- for (const item of txt.items) {
7464
- if (item.br) {
7465
- flush(item);
7466
- continue;
7467
- }
7468
- if (item.text === void 0) continue;
7469
- accumulate(item);
7470
- }
7471
- if (cur.items.length > 0) flush();
7472
- }
7473
- return lines;
7474
- };
7475
- var itemHasFlags = (i) => i.bold === true || i.italic === true || i.underline === true || i.strikethrough === true || i.overline === true || i.subscript === true || i.superscript === true;
7476
- var htmlTextIsSimple = (lines, env) => {
7477
- let prevFs = -1;
7478
- let prevFace = null;
7479
- for (const ln of lines) {
7480
- const item = ln.items[0];
7481
- if (ln.items.length > 1 || itemHasFlags(item)) return false;
7482
- const { fs, face } = itemFont(item, env);
7483
- if (prevFs < 0) prevFs = fs;
7484
- else if (fs !== prevFs) return false;
7485
- if (prevFace === null) prevFace = face;
7486
- else if (face !== prevFace) return false;
7487
- }
7488
- return true;
7489
- };
7490
7684
  var sizeTextContent = (texts, measurer, env = defaultSizeEnv()) => {
7491
- const lines = splitSizedLines(texts, measurer, env);
7492
- const simple = htmlTextIsSimple(lines, env);
7685
+ const lines = buildLineRuns(texts, env, measurer);
7686
+ const simple = runsAreSimple(lines, env);
7493
7687
  let w = 0;
7494
7688
  let h = 0;
7495
7689
  for (const ln of lines) {
7496
7690
  w = Math.max(w, ln.width);
7497
- const lsize = simple ? ln.mxysize : ln.mxfsize;
7691
+ const lsize = simple ? ln.height : ln.fontSize;
7498
7692
  h += ln.items.length > 0 ? lsize : DEFAULT_FONTSIZE;
7499
7693
  }
7500
- if (lines.length === 1) h = lines[0].items.length > 0 ? lines[0].mxysize : DEFAULT_FONTSIZE;
7694
+ if (lines.length === 1) h = lines[0].items.length > 0 ? lines[0].height : DEFAULT_FONTSIZE;
7501
7695
  return { w, h };
7502
7696
  };
7503
- var missingImages = /* @__PURE__ */ new WeakSet();
7697
+ var missingImages = { set: /* @__PURE__ */ new WeakSet() };
7504
7698
  var sizeHtmlImg = (img, { imageSizer, stderr }) => {
7505
- if (img.width !== void 0 && img.height !== void 0) return missingImages.has(img) ? 1 : 0;
7699
+ if (img.width !== void 0 && img.height !== void 0) return missingImages.set.has(img) ? 1 : 0;
7506
7700
  const sz = imageSizer !== void 0 ? imageSizer(img.src) : findImageSize(img.src);
7507
7701
  if (sz !== null) {
7508
7702
  img.width = sz.w;
7509
7703
  img.height = sz.h;
7510
7704
  return 0;
7511
7705
  }
7706
+ if (!imageIsSupplied(img.src, imageSizer)) agerrLine(stderr, `Warning: ${imageOpenWarning(img.src)}`);
7512
7707
  agerrLine(stderr, `Error: No or improper image file="${img.src}"`);
7513
7708
  img.width = 0;
7514
7709
  img.height = 0;
7515
- missingImages.add(img);
7710
+ missingImages.set.add(img);
7516
7711
  return 1;
7517
7712
  };
7518
7713
  var sizeContentItem = (item, measurer, env) => {
@@ -7551,7 +7746,11 @@ var WARN_CELL_TOO_SMALL = "Warning: cell size too small for content";
7551
7746
  var WARN_CELL_UNSPECIFIED = "Warning: fixed cell size with unspecified width or height";
7552
7747
  var WARN_TABLE_TOO_SMALL = "Warning: table size too small for content";
7553
7748
  var WARN_TABLE_UNSPECIFIED = "Warning: fixed table size with unspecified width or height";
7554
- var sizeWarned = /* @__PURE__ */ new WeakSet();
7749
+ var sizeWarned = { set: /* @__PURE__ */ new WeakSet() };
7750
+ registerRenderState(() => {
7751
+ missingImages.set = /* @__PURE__ */ new WeakSet();
7752
+ sizeWarned.set = /* @__PURE__ */ new WeakSet();
7753
+ });
7555
7754
  var fixedCellCheck = (cell2, sz, warn, out) => {
7556
7755
  if (!cell2.fixedsize) return { rv: 0, zero: false };
7557
7756
  if (cell2.width && cell2.height) {
@@ -7573,8 +7772,8 @@ var getCellSize = (cell2, tbl, measurer, env) => {
7573
7772
  }
7574
7773
  let szx = cw + margin;
7575
7774
  let szy = ch + margin;
7576
- const warn = !sizeWarned.has(cell2);
7577
- sizeWarned.add(cell2);
7775
+ const warn = !sizeWarned.set.has(cell2);
7776
+ sizeWarned.set.add(cell2);
7578
7777
  const fixed = fixedCellCheck(cell2, { w: szx, h: szy }, warn, env.stderr);
7579
7778
  rv |= fixed.rv;
7580
7779
  if (fixed.zero) {
@@ -7670,8 +7869,8 @@ var layoutHtmlTable = (tbl, measurer, env = defaultSizeEnv()) => {
7670
7869
  return { entries, widths, heights, spacing, border: border2, rv };
7671
7870
  };
7672
7871
  var warnFixedTable = (tbl, dims, out) => {
7673
- const warn = !sizeWarned.has(tbl);
7674
- sizeWarned.add(tbl);
7872
+ const warn = !sizeWarned.set.has(tbl);
7873
+ sizeWarned.set.add(tbl);
7675
7874
  if (tbl.fixedsize !== true) return 0;
7676
7875
  if (tbl.width && tbl.height) {
7677
7876
  if (tbl.width >= dims.wd && tbl.height >= dims.ht) return 0;
@@ -7728,173 +7927,6 @@ var INIT_DELTA = 10;
7728
7927
  var LOOP_TRIES = 15;
7729
7928
  var ROUTESPL_FUDGE = 1e-4;
7730
7929
 
7731
- // src/common/emit-types.ts
7732
- var PS2INCH = 1 / 72;
7733
- var HTML_BF = 1 << 0;
7734
- var HTML_IF = 1 << 1;
7735
- var HTML_UL = 1 << 2;
7736
- var HTML_SUP = 1 << 3;
7737
- var HTML_SUB = 1 << 4;
7738
- var HTML_S = 1 << 5;
7739
- var HTML_OL = 1 << 6;
7740
-
7741
- // src/common/htmltable-pos-runs.ts
7742
- function itemFontFlags(item) {
7743
- let f = 0;
7744
- if (item.bold) f |= HTML_BF;
7745
- if (item.italic) f |= HTML_IF;
7746
- if (item.underline) f |= HTML_UL;
7747
- if (item.superscript) f |= HTML_SUP;
7748
- if (item.subscript) f |= HTML_SUB;
7749
- if (item.strikethrough) f |= HTML_S;
7750
- if (item.overline) f |= HTML_OL;
7751
- return f;
7752
- }
7753
- function itemFace(item, finfo) {
7754
- return {
7755
- fs: item.fontSize !== void 0 ? item.fontSize : finfo.fontsize,
7756
- face: item.fontFace !== void 0 ? item.fontFace : finfo.fontname
7757
- };
7758
- }
7759
- function measureItem2(item, finfo, measurer) {
7760
- if (item.text === void 0) return null;
7761
- const { fs, face } = itemFace(item, finfo);
7762
- const flags = itemFontFlags(item);
7763
- const sz = measurer.measure(
7764
- item.text,
7765
- face,
7766
- fs,
7767
- { bold: !!(flags & HTML_BF), italic: !!(flags & HTML_IF) }
7768
- );
7769
- return { w: sz.w, h: sz.h, fs, yoffsetCenterline: sz.yoffsetCenterline, yoffsetLayout: sz.yoffsetLayout };
7770
- }
7771
- function newRun() {
7772
- return { items: [], width: 0, fontSize: 0, height: 0, maxOffset: 0, maxLayout: 0 };
7773
- }
7774
- function runLeftX(run, box, centerX) {
7775
- if (run.just === "left") return box.ll.x;
7776
- if (run.just === "right") return box.ur.x - run.width;
7777
- return centerX - run.width / 2;
7778
- }
7779
- function accumulateItem(cur, item, m) {
7780
- cur.items.push(item);
7781
- cur.width += m.w;
7782
- cur.fontSize = Math.max(cur.fontSize, m.fs);
7783
- cur.height = Math.max(cur.height, m.h);
7784
- cur.maxOffset = Math.max(cur.maxOffset, m.yoffsetCenterline ?? 0.05 * m.fs);
7785
- cur.maxLayout = Math.max(cur.maxLayout, m.yoffsetLayout ?? 0);
7786
- }
7787
- function buildLineRuns(texts, finfo, measurer) {
7788
- const runs = [];
7789
- let cur = newRun();
7790
- const flush = (br) => {
7791
- if (cur.items.length === 0 && br !== void 0) {
7792
- const { br: _b, brAlign: _a, ...fontProps } = br;
7793
- const empty = { text: "", ...fontProps };
7794
- const m = measureItem2(empty, finfo, measurer);
7795
- if (m !== null) accumulateItem(cur, empty, m);
7796
- }
7797
- cur.just = br?.brAlign;
7798
- runs.push(cur);
7799
- cur = newRun();
7800
- };
7801
- for (const txt of texts) {
7802
- for (const item of txt.items) {
7803
- if (item.br) {
7804
- flush(item);
7805
- continue;
7806
- }
7807
- const m = measureItem2(item, finfo, measurer);
7808
- if (m !== null) accumulateItem(cur, item, m);
7809
- }
7810
- if (cur.items.length > 0) flush();
7811
- }
7812
- return runs;
7813
- }
7814
- function runSimpleKey(run, finfo) {
7815
- if (run.items.length > 1) return null;
7816
- const item = run.items[0];
7817
- if (item === void 0) return void 0;
7818
- if (itemFontFlags(item) !== 0) return null;
7819
- return itemFace(item, finfo);
7820
- }
7821
- function runsAreSimple(runs, finfo) {
7822
- let prevFs = -1;
7823
- let prevFace = null;
7824
- for (const run of runs) {
7825
- const key = runSimpleKey(run, finfo);
7826
- if (key === null) return false;
7827
- if (key === void 0) continue;
7828
- if (prevFs < 0) prevFs = key.fs;
7829
- else if (key.fs !== prevFs) return false;
7830
- if (prevFace === null) prevFace = key.face;
7831
- else if (key.face !== prevFace) return false;
7832
- }
7833
- return true;
7834
- }
7835
- function placeRunItems(run, startX, baseline, finfo, measurer) {
7836
- const lines = [];
7837
- let x = startX;
7838
- for (const item of run.items) {
7839
- const { fs, face } = itemFace(item, finfo);
7840
- const flags = itemFontFlags(item);
7841
- const sz = measurer.measure(
7842
- item.text,
7843
- face,
7844
- fs,
7845
- { bold: !!(flags & HTML_BF), italic: !!(flags & HTML_IF) }
7846
- );
7847
- lines.push({
7848
- text: item.text,
7849
- x,
7850
- baseline,
7851
- width: sz.w,
7852
- fontSize: fs,
7853
- fontName: face,
7854
- fontColor: item.fontColor ?? finfo.fontcolor,
7855
- fontFlags: flags
7856
- });
7857
- x += sz.w;
7858
- }
7859
- return lines;
7860
- }
7861
- function placeTextRuns(runs, box, finfo, measurer) {
7862
- if (runsAreSimple(runs, finfo)) {
7863
- return placeSimpleRuns(runs, box, finfo, measurer);
7864
- }
7865
- return placeComplexRuns(runs, box, finfo, measurer);
7866
- }
7867
- function placeSimpleRuns(runs, box, finfo, measurer) {
7868
- const centerX = (box.ll.x + box.ur.x) / 2;
7869
- const lines = [];
7870
- let baseline = box.ur.y;
7871
- for (let i = 0; i < runs.length; i++) {
7872
- const run = runs[i];
7873
- const ascent = run.maxLayout > 0 ? run.maxLayout : freetypeAscent(run.fontSize, finfo.fontname);
7874
- baseline -= i === 0 ? ascent : run.height;
7875
- lines.push(...placeRunItems(run, runLeftX(run, box, centerX), baseline, finfo, measurer));
7876
- }
7877
- return lines;
7878
- }
7879
- function placeComplexRuns(runs, box, finfo, measurer) {
7880
- const centerX = (box.ll.x + box.ur.x) / 2;
7881
- const lines = [];
7882
- let curbline = 0;
7883
- let ysize = 0;
7884
- for (let i = 0; i < runs.length; i++) {
7885
- const run = runs[i];
7886
- const lfsize = i === 0 ? run.fontSize - run.maxOffset : run.fontSize + ysize - curbline - run.maxOffset;
7887
- curbline += lfsize;
7888
- ysize += run.fontSize;
7889
- const baseline = box.ur.y - curbline;
7890
- for (const pl of placeRunItems(run, runLeftX(run, box, centerX), baseline, finfo, measurer)) {
7891
- pl.yoffsetCenterline = 1;
7892
- lines.push(pl);
7893
- }
7894
- }
7895
- return lines;
7896
- }
7897
-
7898
7930
  // src/common/htmltable-pos.ts
7899
7931
  function alignContentBox(box, cell2, w, h) {
7900
7932
  const out = { ll: { ...box.ll }, ur: { ...box.ur } };
@@ -8196,6 +8228,20 @@ function htmlTextLabel(text, finfo, placed, dim) {
8196
8228
  };
8197
8229
  }
8198
8230
 
8231
+ // src/model/lazy-attrs.ts
8232
+ var SharedEmptyAttrs = class extends Map {
8233
+ set(key, _value) {
8234
+ throw new Error(`attrs.set("${key}") on a shared empty map; use ownAttrs()`);
8235
+ }
8236
+ delete(key) {
8237
+ throw new Error(`attrs.delete("${key}") on a shared empty map; use ownAttrs()`);
8238
+ }
8239
+ clear() {
8240
+ throw new Error("attrs.clear() on a shared empty map; use ownAttrs()");
8241
+ }
8242
+ };
8243
+ var EMPTY_ATTRS = new SharedEmptyAttrs();
8244
+
8199
8245
  // src/model/algData.ts
8200
8246
  var THETA_UNSET = 10;
8201
8247
 
@@ -8298,10 +8344,10 @@ var Node = class {
8298
8344
  */
8299
8345
  nodeDefaultsSnapshot;
8300
8346
  /** @see lib/cgraph/node.c:agnode */
8301
- constructor(id, name, root) {
8347
+ constructor(id, name, root, lazyAttrs = false) {
8302
8348
  this.id = id;
8303
8349
  this.name = name;
8304
- this.attrs = /* @__PURE__ */ new Map();
8350
+ this.attrs = lazyAttrs ? EMPTY_ATTRS : /* @__PURE__ */ new Map();
8305
8351
  this.info = makeNodeInfo();
8306
8352
  this.root = root;
8307
8353
  }
@@ -8471,12 +8517,12 @@ var Edge = class _Edge {
8471
8517
  */
8472
8518
  info;
8473
8519
  /** @see lib/cgraph/edge.c:agedge */
8474
- constructor(tail, head, name) {
8520
+ constructor(tail, head, name, lazyAttrs = false) {
8475
8521
  this.seq = _Edge._nextSeq++;
8476
8522
  this.tail = tail;
8477
8523
  this.head = head;
8478
8524
  this.name = name;
8479
- this.attrs = /* @__PURE__ */ new Map();
8525
+ this.attrs = lazyAttrs ? EMPTY_ATTRS : /* @__PURE__ */ new Map();
8480
8526
  this.info = makeEdgeInfo(makePort(), makePort());
8481
8527
  }
8482
8528
  };
@@ -8900,7 +8946,7 @@ function copyVirtualEdgeInfo(e, orig) {
8900
8946
  e.seq = orig.seq;
8901
8947
  }
8902
8948
  function newVirtualEdge(u, v, orig) {
8903
- const e = new Edge(u, v, "");
8949
+ const e = new Edge(u, v, "", true);
8904
8950
  e.info.edge_type = VIRTUAL;
8905
8951
  if (orig) {
8906
8952
  copyVirtualEdgeInfo(e, orig);
@@ -9001,7 +9047,7 @@ function removeFromRank(g, n) {
9001
9047
  }
9002
9048
  }
9003
9049
  function virtualNode(g) {
9004
- const n = new Node(0, "", g.root);
9050
+ const n = new Node(0, "", g.root, true);
9005
9051
  n.info.node_type = VIRTUAL;
9006
9052
  n.info.lw = 1;
9007
9053
  n.info.rw = 1;
@@ -9313,10 +9359,10 @@ var ARROW_EPSILON = 1e-4;
9313
9359
  var vsub = (p, q) => ({ x: p.x - q.x, y: p.y - q.y });
9314
9360
  var vadd = (p, q) => ({ x: p.x + q.x, y: p.y + q.y });
9315
9361
  var vscale = (c, p) => ({ x: c * p.x, y: c * p.y });
9316
- var negUnit = (u, dist4) => {
9362
+ var negUnit = (u, dist5) => {
9317
9363
  if (u.x === 0 && u.y === 0) return { x: 0, y: 0 };
9318
9364
  const h = Math.hypot(u.x, u.y);
9319
- return { x: dist4 * (-u.x / h), y: dist4 * (-u.y / h) };
9365
+ return { x: dist5 * (-u.x / h), y: dist5 * (-u.y / h) };
9320
9366
  };
9321
9367
  var backwardDelta = (u, penwidth) => negUnit(u, penwidth / 2);
9322
9368
  function axialProjection(phiSrc, from, to, sign2) {
@@ -9899,9 +9945,9 @@ function makeEllipseInsideFn(rx, ry, penwidth = DEFAULT_NODEPENWIDTH) {
9899
9945
  return (lx, ly) => lx * lx / (erx * erx) + ly * ly / (ery * ery) < 1;
9900
9946
  }
9901
9947
  function tailArrowEndClip(path4, tailTip, elen) {
9902
- if (elen <= 0) return path4;
9903
- const inside = (lx, ly) => Math.hypot(lx, ly) <= elen;
9904
- return bezierClipNode(path4, tailTip.x, tailTip.y, inside, true);
9948
+ const sp = [path4[3], path4[2], path4[1], tailTip];
9949
+ const clipped = elen > 0 ? bezierClipNode(sp, 0, 0, (x, y) => distFused({ x, y }, tailTip) <= elen, false) : sp;
9950
+ return [clipped[3], clipped[2], clipped[1], clipped[0]];
9905
9951
  }
9906
9952
 
9907
9953
  // src/layout/dot/edge-route-geom.ts
@@ -11598,11 +11644,12 @@ function emitHtmlLine(line, pos, renderer, job) {
11598
11644
  }
11599
11645
  function bgFillPaint(ctx) {
11600
11646
  const penWidth = htmlFillPenWidth();
11601
- const spec = parseGradientSpec(ctx.bgcolor);
11647
+ const spec = findHtmlStopColor(ctx.bgcolor);
11602
11648
  if (spec === null) return { fill: ctx.bgcolor, penWidth };
11603
11649
  return {
11604
- fill: spec[0],
11605
- stop: spec[1],
11650
+ fill: spec.fill,
11651
+ stop: spec.stop ?? "black",
11652
+ gradientFrac: spec.frac,
11606
11653
  gradientAngle: ctx.gradientangle ?? 0,
11607
11654
  radial: htmlStyle(ctx.style).radial,
11608
11655
  penWidth
@@ -12032,7 +12079,7 @@ function transformUnitVertex(R2, g, c, bb) {
12032
12079
  const r = libmHypot(D.x, D.y);
12033
12080
  return { x: r * Math.cos(alpha) * bb.x, y: r * Math.sin(alpha) * bb.y };
12034
12081
  }
12035
- function polygonVertices(bb, g, isBox3) {
12082
+ function polygonVertices(bb, g, isBox4) {
12036
12083
  const sectorangle = 2 * Math.PI / g.sides;
12037
12084
  const sidelength = Math.sin(sectorangle / 2);
12038
12085
  const c = {
@@ -12050,7 +12097,7 @@ function polygonVertices(bb, g, isBox3) {
12050
12097
  R2.y = fma(sidelength, Math.sin(angle), R2.y);
12051
12098
  const P = transformUnitVertex(R2, g, c, bb);
12052
12099
  verts.push(P);
12053
- if (isBox3) {
12100
+ if (isBox4) {
12054
12101
  verts.push({ x: -P.x, y: P.y }, { x: -P.x, y: -P.y }, { x: P.x, y: -P.y });
12055
12102
  break;
12056
12103
  }
@@ -12141,14 +12188,14 @@ function starVertexGen(bb) {
12141
12188
  }
12142
12189
  return { verts: starVertices(bb.x, bb.y), xmax: sz.x / 2, ymax: sz.y / 2 };
12143
12190
  }
12144
- function polygonBB(bb, minSize, p, sides2, isBox3) {
12191
+ function polygonBB(bb, minSize, p, sides2, isBox4) {
12145
12192
  const geom = {
12146
12193
  sides: sides2,
12147
12194
  orientation: p.orientation,
12148
12195
  distortion: p.distortion,
12149
12196
  skew: p.skew
12150
12197
  };
12151
- const { verts, xmax, ymax } = p.optionShape === STAR ? starVertexGen(bb) : polygonVertices(bb, geom, isBox3);
12198
+ const { verts, xmax, ymax } = p.optionShape === STAR ? starVertexGen(bb) : polygonVertices(bb, geom, isBox4);
12152
12199
  const xmax2 = 2 * xmax;
12153
12200
  const ymax2 = 2 * ymax;
12154
12201
  const nbb = { x: Math.max(minSize.x, xmax2), y: Math.max(minSize.y, ymax2) };
@@ -12160,7 +12207,7 @@ function polygonBB(bb, minSize, p, sides2, isBox3) {
12160
12207
  v.x *= scalex;
12161
12208
  v.y *= scaley;
12162
12209
  }
12163
- return { ...polygonPeripheryBB(verts, isBox3 ? 4 : sides2, p, nbb), base: nbb };
12210
+ return { ...polygonPeripheryBB(verts, isBox4 ? 4 : sides2, p, nbb), base: nbb };
12164
12211
  }
12165
12212
  function gvNodesize(widthPts, heightPts, flip) {
12166
12213
  if (flip) return { lw: heightPts / 2, rw: heightPts / 2, ht: widthPts };
@@ -12185,9 +12232,9 @@ function applySizeConstraints(p, bb0, width0, height0) {
12185
12232
  function polySize(p) {
12186
12233
  const init = initialSizePts(p);
12187
12234
  const dimen = quantize(padLabelDimen(p.labelDimen, p.margin, p.isPlain), p.quantumIn);
12188
- const { sides: sides2, isBox: isBox3 } = effectiveShape(p);
12235
+ const { sides: sides2, isBox: isBox4 } = effectiveShape(p);
12189
12236
  let bb = { x: dimen.x, y: dimen.y };
12190
- if (isBox3) {
12237
+ if (isBox4) {
12191
12238
  } else if (p.optionShape === STAR) {
12192
12239
  bb = starSize(bb);
12193
12240
  } else if (p.optionShape === CYLINDER) {
@@ -12199,16 +12246,16 @@ function polySize(p) {
12199
12246
  const c = applySizeConstraints(p, bb, init.width, init.height);
12200
12247
  const penwidth = p.penwidth ?? 1;
12201
12248
  const hasOutline = penwidth > 0 || p.peripheries < 1;
12202
- const grown = sides2 < 3 ? { ...ellipsePeripheryBB(c.bb, p.peripheries, penwidth, hasOutline), base: c.bb } : polygonBB(c.bb, { x: c.width, y: c.height }, { ...p, penwidth, hasOutline }, sides2, isBox3);
12249
+ const grown = sides2 < 3 ? { ...ellipsePeripheryBB(c.bb, p.peripheries, penwidth, hasOutline), base: c.bb } : polygonBB(c.bb, { x: c.width, y: c.height }, { ...p, penwidth, hasOutline }, sides2, isBox4);
12203
12250
  const result = assembleResult(p, dimen, grown, c.fixedshape);
12204
- return { ...result, ...labelSpace(p, dimen, c.bb, minBb, isBox3, c.fixedshape) };
12251
+ return { ...result, ...labelSpace(p, dimen, c.bb, minBb, isBox4, c.fixedshape) };
12205
12252
  }
12206
- function labelSpace(p, dimen, bb, minBb, isBox3, fixedshape) {
12253
+ function labelSpace(p, dimen, bb, minBb, isBox4, fixedshape) {
12207
12254
  const spacex = dimen.x - p.labelDimen.x;
12208
12255
  let spaceX;
12209
12256
  if (p.nojustify) {
12210
12257
  spaceX = dimen.x - spacex;
12211
- } else if (isBox3) {
12258
+ } else if (isBox4) {
12212
12259
  spaceX = Math.max(dimen.x, bb.x) - spacex;
12213
12260
  } else if (dimen.y < bb.y) {
12214
12261
  spaceX = Math.max(dimen.x, bb.x * Math.sqrt(1 - dimen.y * dimen.y / (bb.y * bb.y))) - spacex;
@@ -12221,8 +12268,8 @@ function labelSpace(p, dimen, bb, minBb, isBox3, fixedshape) {
12221
12268
  function effectiveShape(p) {
12222
12269
  let sides2 = p.sides;
12223
12270
  if (sides2 <= 2 && (p.distortion !== 0 || p.skew !== 0)) sides2 = 120;
12224
- const isBox3 = sides2 === 4 && Math.abs(p.orientation % 90) < 0.5 && p.distortion === 0 && p.skew === 0;
12225
- return { sides: sides2, isBox: isBox3 };
12271
+ const isBox4 = sides2 === 4 && Math.abs(p.orientation % 90) < 0.5 && p.distortion === 0 && p.skew === 0;
12272
+ return { sides: sides2, isBox: isBox4 };
12226
12273
  }
12227
12274
  function labelValign(p) {
12228
12275
  const ll = p.labelloc?.[0];
@@ -12664,17 +12711,27 @@ function buildNodeLabel(n, g, measurer) {
12664
12711
  const content = isHtml ? htmlValueContent(labelAttr) : labelAttr ?? n.name;
12665
12712
  n.info.label = makeAnyLabel(content, isHtml, font, measurer, n);
12666
12713
  }
12714
+ function warnMissingImage(n, g, shapefile) {
12715
+ if (shapefile !== void 0 && shapefile !== "" && nodeAttr(n, g, "shape") !== "epsf") return;
12716
+ const image = nodeAttr(n, g, "image");
12717
+ if (image === void 0 || image === "") return;
12718
+ const gvc = g.root.info.gvc;
12719
+ if (imageIsSupplied(image, gvc?.imageSizer, gvc?.imageResolver)) return;
12720
+ agwarningf(imageOpenWarning(image));
12721
+ agwarningf(`No or improper image="${image}" for node "${n.name}"`);
12722
+ }
12667
12723
  function polyInit(n, g, measurer) {
12668
12724
  const shapeName2 = nodeAttr(n, g, "shape") ?? "ellipse";
12669
12725
  const shapefile = nodeAttr(n, g, "shapefile");
12670
12726
  n.info.shape = bindShape(shapeName2, shapefile);
12671
12727
  if (shapefile !== void 0 && shapefile !== "" && shapeName2 !== "epsf") {
12672
- agwarningf(`No or improper shapefile="${shapefile}" for node "${n.name}"`, "error");
12728
+ agwarningf(`No or improper shapefile="${shapefile}" for node "${n.name}"`);
12673
12729
  }
12674
12730
  if (n.info.shape.kind === 2 /* SH_RECORD */) {
12675
12731
  if (n.info.shape_info === void 0) recordNodeInit(n, g, measurer);
12676
12732
  return;
12677
12733
  }
12734
+ warnMissingImage(n, g, shapefile);
12678
12735
  buildNodeLabel(n, g, measurer);
12679
12736
  if (n.info.shape_info !== void 0) return;
12680
12737
  const polyDesc = n.info.shape.polygon;
@@ -12682,6 +12739,16 @@ function polyInit(n, g, measurer) {
12682
12739
  }
12683
12740
 
12684
12741
  // src/common/multicolor.ts
12742
+ var parseSegsState = { warned: false };
12743
+ registerRenderState(() => {
12744
+ parseSegsState.warned = false;
12745
+ });
12746
+ function claimWarned() {
12747
+ if (parseSegsState.warned) return false;
12748
+ parseSegsState.warned = true;
12749
+ return true;
12750
+ }
12751
+ var claimNever = () => false;
12685
12752
  var EPS = 1e-5;
12686
12753
  function aeq0(x) {
12687
12754
  return x < EPS && x > -EPS;
@@ -12695,17 +12762,14 @@ function getSegLen(token) {
12695
12762
  const parsed = parseFloat(rest);
12696
12763
  return !isNaN(parsed) && parsed >= 0 ? { color, v: parsed } : { color, v: -1 };
12697
12764
  }
12698
- function appendSeg(token, left2, segs, warnedExceeded) {
12765
+ function appendSeg(token, left2, segs, claim) {
12699
12766
  const { color, v } = getSegLen(token);
12700
12767
  if (v < 0) return null;
12701
12768
  let t = v;
12702
12769
  let rval = 0;
12703
12770
  const del = t - left2;
12704
12771
  if (del > 0) {
12705
- if (!aeq0(del) && !warnedExceeded.v) {
12706
- warnedExceeded.v = true;
12707
- rval = 3;
12708
- }
12772
+ if (!aeq0(del) && claim()) rval = 3;
12709
12773
  t = left2;
12710
12774
  }
12711
12775
  left2 -= t;
@@ -12729,19 +12793,13 @@ function trimTrailing(segs) {
12729
12793
  segs.pop();
12730
12794
  }
12731
12795
  }
12732
- function parseSegs(colorlist) {
12796
+ function scanSegs(colorlist, claim) {
12733
12797
  const segs = [];
12734
12798
  let left2 = 1;
12735
12799
  let rval = 0;
12736
- let badFloatCount = 0;
12737
- const warnedExceeded = { v: false };
12738
12800
  for (const token of colorlist.split(":")) {
12739
- const result = appendSeg(token, left2, segs, warnedExceeded);
12740
- if (result === null) {
12741
- const errCode = badFloatCount === 0 ? 2 : 1;
12742
- badFloatCount++;
12743
- return { segs: [], error: errCode };
12744
- }
12801
+ const result = appendSeg(token, left2, segs, claim);
12802
+ if (result === null) return { segs: [], error: claim() ? 2 : 1 };
12745
12803
  if (result.rval === 3) rval = 3;
12746
12804
  left2 = result.left;
12747
12805
  if (aeq0(left2)) {
@@ -12753,6 +12811,91 @@ function parseSegs(colorlist) {
12753
12811
  trimTrailing(segs);
12754
12812
  return { segs, error: rval };
12755
12813
  }
12814
+ function parseSegs(colorlist, context) {
12815
+ const result = scanSegs(colorlist, claimWarned);
12816
+ if (result.error === 3) {
12817
+ const tail = context === void 0 ? "" : context();
12818
+ agwarningf(`Total size > 1 in "${colorlist}" color spec ${tail}`);
12819
+ } else if (result.error === 2) {
12820
+ agerrorf(`Illegal value in "${colorlist}" color attribute; float expected after ';'`);
12821
+ if (context !== void 0) agerr("prev", context());
12822
+ }
12823
+ return result;
12824
+ }
12825
+ function parseSegsSilent(colorlist) {
12826
+ return scanSegs(colorlist, claimNever);
12827
+ }
12828
+ function edgeSegsContext(e) {
12829
+ return () => {
12830
+ const directed = !e.tail.root.kind.endsWith("undirected");
12831
+ return `in edge ${e.tail.name}${directed ? " -> " : " -- "}${e.head.name}`;
12832
+ };
12833
+ }
12834
+
12835
+ // src/gvc/gvrender-set-style.ts
12836
+ var SUPPORTED_STYLES = /* @__PURE__ */ new Set([
12837
+ "solid",
12838
+ "dashed",
12839
+ "dotted",
12840
+ "invis",
12841
+ "invisible",
12842
+ "bold",
12843
+ "setlinewidth",
12844
+ "filled",
12845
+ "unfilled",
12846
+ "tapered"
12847
+ ]);
12848
+ var BOX_ORIENTATION_TOLERANCE = 0.5;
12849
+ var BOX_ORIENTATION_STEP = 90;
12850
+ var BOX_SIDES = 4;
12851
+ 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
+ function gvrenderSetStyle(styles) {
12857
+ if (styles === null) return;
12858
+ for (const token of styles) {
12859
+ const name = styleName(token);
12860
+ if (!SUPPORTED_STYLES.has(name)) {
12861
+ agwarningf(`gvrender_set_style: unsupported style ${name} - ignoring`);
12862
+ }
12863
+ }
12864
+ }
12865
+ function isBox(p) {
12866
+ if (p === null) return false;
12867
+ return p.sides === BOX_SIDES && Math.abs(p.orientation % BOX_ORIENTATION_STEP) < BOX_ORIENTATION_TOLERANCE && p.distortion === 0 && p.skew === 0;
12868
+ }
12869
+ function isEllipse(p) {
12870
+ return p !== null && p.sides <= ELLIPSE_MAX_SIDES;
12871
+ }
12872
+ function checkStyleTokens(styles, shape) {
12873
+ return styles.filter((p) => {
12874
+ if (p === "rounded" || p === "diagonals" || p === "radial") return false;
12875
+ if (p === "striped") return !isBox(shape);
12876
+ if (p === "wedged") return !isEllipse(shape);
12877
+ return true;
12878
+ });
12879
+ }
12880
+ function checkClusterStyleTokens(styles) {
12881
+ return styles.filter((p) => p !== "radial" && p !== "striped" && p !== "rounded");
12882
+ }
12883
+ function countChar(s, ch) {
12884
+ return [...s].filter((c) => c === ch).length;
12885
+ }
12886
+ function multicolorTaken(color) {
12887
+ if (countChar(color, ";") === 0 || countChar(color, ":") === 0) return false;
12888
+ const { error } = parseSegsSilent(color);
12889
+ return error !== 1 && error !== 2;
12890
+ }
12891
+ function edgeStyleResets(e, styles) {
12892
+ const spl = e.info.spl;
12893
+ if (spl === void 0 || spl.size <= 1 || styles.length === 0) return 0;
12894
+ const color = e.attrs.get("color") ?? "";
12895
+ const otherBranch = styles.includes("tapered") || countChar(color, ":") > 0;
12896
+ if (otherBranch && !multicolorTaken(color)) return 0;
12897
+ return spl.list.filter((bz) => bz.sflag !== 0 || bz.eflag !== 0).length;
12898
+ }
12756
12899
 
12757
12900
  // src/util/math.ts
12758
12901
  var INT32_MAX = 2147483647;
@@ -15735,11 +15878,11 @@ var SEG_EPS = 1e-5;
15735
15878
  function reportColorNames(names) {
15736
15879
  for (const name of names) resolveRenderColor(firstColor(name));
15737
15880
  }
15738
- function countChar(s, ch) {
15881
+ function countChar2(s, ch) {
15739
15882
  return s.split(ch).length - 1;
15740
15883
  }
15741
15884
  function multicolorNames(color, arrows) {
15742
- const { segs, error } = parseSegs(color);
15885
+ const { segs, error } = parseSegsSilent(color);
15743
15886
  if (error === 1 || error === 2) return null;
15744
15887
  const out = [];
15745
15888
  const front = segs[0]?.color ?? null;
@@ -15761,9 +15904,9 @@ function taperedNames(color, fillcolor, hasFill) {
15761
15904
  return hasFill ? [pen, fillcolor === "" ? DEFAULT_COLOR2 : fillcolor] : [pen];
15762
15905
  }
15763
15906
  function edgeGraphicsColors(spec) {
15764
- const numc = countChar(spec.color, ":");
15907
+ const numc = countChar2(spec.color, ":");
15765
15908
  let color = spec.color;
15766
- if (countChar(color, ";") > 0 && numc > 0) {
15909
+ if (countChar2(color, ";") > 0 && numc > 0) {
15767
15910
  const multi = multicolorNames(color, spec.arrows);
15768
15911
  if (multi !== null) return multi;
15769
15912
  color = DEFAULT_COLOR2;
@@ -15916,8 +16059,8 @@ function drawWedge(seg2, e, ctx) {
15916
16059
  ctx.renderer.bezier(ptsUp.map((p) => ({ x: p.x, y: -p.y })), true, ctx.job);
15917
16060
  return angle1;
15918
16061
  }
15919
- function wedgedEllipse(job, pf, clrs, renderer) {
15920
- const { segs, error } = parseSegs(clrs);
16062
+ function wedgedEllipse(job, pf, clrs, renderer, context) {
16063
+ const { segs, error } = parseSegs(clrs, context);
15921
16064
  if (error === 1 || error === 2) return error;
15922
16065
  const ctrX = (pf[0].x + pf[1].x) / 2;
15923
16066
  const ctrY = (pf[0].y + pf[1].y) / 2;
@@ -15949,8 +16092,8 @@ function drawBand(p, seg2, ctx) {
15949
16092
  ctx.renderer.polygon([...p], true, ctx.job);
15950
16093
  p[0].x = p[3].x = p[1].x;
15951
16094
  }
15952
- function stripedBox(job, pts, clrs, rotate, renderer) {
15953
- const { segs, error } = parseSegs(clrs);
16095
+ function stripedBox(job, pts, clrs, rotate, renderer, context) {
16096
+ const { segs, error } = parseSegs(clrs, context);
15954
16097
  if (error === 1 || error === 2) return error;
15955
16098
  const p = rotate ? [{ ...pts[2] }, { ...pts[3] }, { ...pts[0] }, { ...pts[1] }] : [{ ...pts[0] }, { ...pts[1] }, { ...pts[2] }, { ...pts[3] }];
15956
16099
  const lastx = p[1].x;
@@ -16108,6 +16251,27 @@ function escapeXmlText(s) {
16108
16251
  return gvXmlEscape(s, FLAGS_TEXT);
16109
16252
  }
16110
16253
 
16254
+ // src/gvc/device-transform.ts
16255
+ function transformPoint(p, job) {
16256
+ if ((job.flags & GVRENDER_DOES_TRANSFORM) !== 0) {
16257
+ return p;
16258
+ }
16259
+ const sx = job.zoom * job.devscale.x;
16260
+ const sy = job.zoom * job.devscale.y;
16261
+ const tx = job.translation.x;
16262
+ const ty = job.translation.y;
16263
+ return applyScale(p, tx, ty, sx, sy);
16264
+ }
16265
+ function applyScale(p, tx, ty, sx, sy) {
16266
+ const x = (p.x + tx) * sx;
16267
+ const y = (p.y + ty) * sy;
16268
+ return buildPoint(x, y);
16269
+ }
16270
+ function buildPoint(x, y) {
16271
+ const pt = { x, y };
16272
+ return pt;
16273
+ }
16274
+
16111
16275
  // src/gvc/device-cluster.ts
16112
16276
  function applyClusterGradient(obj, fill) {
16113
16277
  obj.fill = fill.kind === "radial" ? 3 /* Radial */ : 2 /* Linear */;
@@ -16155,6 +16319,7 @@ function applyClusterObjState(sg, job) {
16155
16319
  const fillRes = resolveClusterFillEx(clusterAttrsOf(sg));
16156
16320
  if (job.obj === null) return false;
16157
16321
  const obj = job.obj;
16322
+ gvrenderSetStyle(checkClusterStyleTokens(styleTokens2(clusterStyle(sg))));
16158
16323
  return withColorScheme(clusterAttr(sg, "colorscheme"), () => {
16159
16324
  const filled = applyClusterFill(obj, fillRes);
16160
16325
  applyClusterPenState(obj, sg);
@@ -16162,17 +16327,47 @@ function applyClusterObjState(sg, job) {
16162
16327
  return filled;
16163
16328
  });
16164
16329
  }
16165
- function stripedClusterColors(sg) {
16330
+ function isStripedCluster(sg) {
16331
+ const flags = parseStyleFlags(clusterStyle(sg));
16332
+ return flags.striped && !flags.rounded;
16333
+ }
16334
+ function stripedFillSpec(sg) {
16166
16335
  const flags = parseStyleFlags(clusterStyle(sg));
16167
- if (!flags.striped || flags.rounded) return [];
16168
16336
  const color = clusterAttr(sg, "color") ?? "";
16169
16337
  let fill = clusterAttr(sg, "fillcolor") || color;
16170
16338
  const bg = clusterAttr(sg, "bgcolor") ?? "";
16171
16339
  if ((!flags.filled || fill === "") && bg !== "") fill = bg;
16172
- const { segs, error } = parseSegs(fill === "" ? "lightgrey" : fill);
16340
+ return fill === "" ? "lightgrey" : fill;
16341
+ }
16342
+ function stripedClusterColors(sg) {
16343
+ if (!isStripedCluster(sg)) return [];
16344
+ const { segs, error } = parseSegs(stripedFillSpec(sg), () => `in cluster ${sg.name}`);
16173
16345
  if (error === 1 || error === 2) return [];
16174
16346
  return segs.flatMap((seg2) => seg2.color !== null && seg2.t > 0 ? [seg2.color] : []);
16175
16347
  }
16348
+ 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
+ });
16370
+ }
16176
16371
  function applyClusterFill(obj, fillRes) {
16177
16372
  if (fillRes.kind === "none") {
16178
16373
  obj.fill = 0 /* None */;
@@ -16238,7 +16433,7 @@ function renderEllipseRing(ring, coord, filled, j, ctx) {
16238
16433
  const pf = ring.map(
16239
16434
  (v) => transformPoint({ x: v.x + coord.x, y: v.y + coord.y }, ctx.job)
16240
16435
  );
16241
- wedgedEllipse(ctx.job, pf, ctx.fillcolor, ctx.renderer);
16436
+ wedgedEllipse(ctx.job, pf, ctx.fillcolor, ctx.renderer, () => `in node ${ctx.nodeName}`);
16242
16437
  renderEllipse(ring, coord, ctx.renderer, ctx.job, false);
16243
16438
  } else {
16244
16439
  renderEllipse(ring, coord, ctx.renderer, ctx.job, filled);
@@ -16247,7 +16442,7 @@ function renderEllipseRing(ring, coord, filled, j, ctx) {
16247
16442
  }
16248
16443
  function renderStripedRing(ring, coord, ctx) {
16249
16444
  const af = ring.map((v) => transformPoint({ x: v.x + coord.x, y: v.y + coord.y }, ctx.job));
16250
- stripedBox(ctx.job, af, ctx.fillcolor, true, ctx.renderer);
16445
+ stripedBox(ctx.job, af, ctx.fillcolor, true, ctx.renderer, () => `in node ${ctx.nodeName}`);
16251
16446
  renderPolygon(ring, coord, ctx.renderer, ctx.job, false);
16252
16447
  }
16253
16448
  function renderPolyRing(ring, coord, filled, j, ctx) {
@@ -16373,6 +16568,10 @@ function applyPenState(obj, styleAttr, colorAttr, penwidthAttr) {
16373
16568
  function applyNodeStyle(obj, n, job) {
16374
16569
  const styleAttr = nodeAttr(n, n.root, "style");
16375
16570
  const colorAttr = nodeAttr(n, n.root, "color");
16571
+ if (!isPointNode(n)) {
16572
+ const shape = n.info.shape;
16573
+ gvrenderSetStyle(checkStyleTokens(styleTokens2(styleAttr), shape?.polygon ?? null));
16574
+ }
16376
16575
  const penwidth = nodeAttr(n, n.root, "penwidth");
16377
16576
  if (n.info.shape?.kind === 2 /* SH_RECORD */) {
16378
16577
  applyPenState(obj, styleAttr, colorAttr, penwidth);
@@ -16384,7 +16583,7 @@ function applyNodeStyle(obj, n, job) {
16384
16583
  }
16385
16584
  function prepareDrawPoly(poly, filled, obj) {
16386
16585
  if (poly.peripheries !== 0 || !filled) return poly;
16387
- obj.penColor = { type: "string", s: "transparent" };
16586
+ obj.penColor = resolveRenderColor("transparent");
16388
16587
  return { ...poly, peripheries: 1 };
16389
16588
  }
16390
16589
  function vertexScale(n, poly) {
@@ -16414,6 +16613,7 @@ function resolveNodeDrawCtx(job, n) {
16414
16613
  job,
16415
16614
  style: styleFlags,
16416
16615
  fillcolor: nodeAttr(n, n.root, "fillcolor") ?? "",
16616
+ nodeName: n.name,
16417
16617
  ...specialCornerFlags(drawPoly.option, styleFlags)
16418
16618
  };
16419
16619
  return { poly: drawPoly, coord, filled, ringCtx };
@@ -17773,7 +17973,7 @@ function pruneForeignClusterNodes(par, clust) {
17773
17973
  }
17774
17974
  function markClusterNode(clust, n, g) {
17775
17975
  if ((n.info.ranktype ?? 0) !== 0) {
17776
- agwarningf(`${n.name} was already in a rankset, deleted from cluster ${g.name}`, "error");
17976
+ agwarningf(`${n.name} was already in a rankset, deleted from cluster ${g.name}`);
17777
17977
  agDeleteFromCluster(clust, n);
17778
17978
  return;
17779
17979
  }
@@ -18352,7 +18552,7 @@ function findCharset(g) {
18352
18552
  }
18353
18553
  if (p === "big-5" || p === "big5") return CHAR_BIG5;
18354
18554
  if (p === "utf-8" || p === "utf8") return CHAR_UTF8;
18355
- agwarningf(`Unsupported charset "${raw}" - assuming utf-8`, "error");
18555
+ agwarningf(`Unsupported charset "${raw}" - assuming utf-8`);
18356
18556
  return CHAR_UTF8;
18357
18557
  }
18358
18558
  function maptoken(p, names, vals) {
@@ -18570,7 +18770,7 @@ function portToTbl(tbl, id) {
18570
18770
  }
18571
18771
 
18572
18772
  // src/common/compass-port.ts
18573
- function isBox(n) {
18773
+ function isBox2(n) {
18574
18774
  return n.info.shape?.polygon === P_BOX;
18575
18775
  }
18576
18776
  function gdRankdir(n) {
@@ -18761,7 +18961,7 @@ function compassPort(n, args, pp) {
18761
18961
  const { bp, compass, sides: sides2 } = args;
18762
18962
  const { b, p, defined: defBp } = compassBbox(n, bp);
18763
18963
  const dir = compassDirection(compass, b, p, sides2);
18764
- if (bp === null && !isBox(n)) applyIctxt(n, dir, b, p);
18964
+ if (bp === null && !isBox2(n)) applyIctxt(n, dir, b, p);
18765
18965
  const defFinal = dir.rv === 1 ? defBp : dir.defined || defBp;
18766
18966
  applyDir(pp, bp, dir, gdRankdir(n), defFinal);
18767
18967
  return dir.rv;
@@ -20043,7 +20243,7 @@ function emitParallelEdgePaths(e, job, colorList) {
20043
20243
  const spl = e.info.spl;
20044
20244
  const numc = (colorList.match(/:/g) ?? []).length;
20045
20245
  const segData = buildSegData(spl?.list ?? [], (2 + numc) / 2);
20046
- const colors = parseSegs(colorList).segs.map((s) => s.color ?? DEFAULT_COLOR3);
20246
+ const colors = parseSegsSilent(colorList).segs.map((s) => s.color ?? DEFAULT_COLOR3);
20047
20247
  emitColorPasses(segData, colors, job);
20048
20248
  return {
20049
20249
  headColor: colors[0] ?? DEFAULT_COLOR3,
@@ -20875,25 +21075,14 @@ function walkNodesAndEdges(g, renderer, job, info) {
20875
21075
  }
20876
21076
  }
20877
21077
 
20878
- // src/gvc/device-transform.ts
20879
- function transformPoint(p, job) {
20880
- if ((job.flags & GVRENDER_DOES_TRANSFORM) !== 0) {
20881
- return p;
20882
- }
20883
- const sx = job.zoom * job.devscale.x;
20884
- const sy = job.zoom * job.devscale.y;
20885
- const tx = job.translation.x;
20886
- const ty = job.translation.y;
20887
- return applyScale(p, tx, ty, sx, sy);
20888
- }
20889
- function applyScale(p, tx, ty, sx, sy) {
20890
- const x = (p.x + tx) * sx;
20891
- const y = (p.y + ty) * sy;
20892
- return buildPoint(x, y);
20893
- }
20894
- function buildPoint(x, y) {
20895
- const pt = { x, y };
20896
- return pt;
21078
+ // src/gvc/first-layer.ts
21079
+ var NATIVE_LANGNAME = /* @__PURE__ */ new Map([
21080
+ ["cmapx-np", "cmapx_np"],
21081
+ ["imap-np", "imap_np"]
21082
+ ]);
21083
+ function warnLayersUnsupported(format, numLayers, doesLayers) {
21084
+ if (numLayers <= 1 || doesLayers) return;
21085
+ agwarningf(`layers not supported in ${NATIVE_LANGNAME.get(format) ?? format} output`);
20897
21086
  }
20898
21087
 
20899
21088
  // src/gvc/device-labels.ts
@@ -21038,6 +21227,7 @@ function setEdgePen(e, job) {
21038
21227
  obj.pen = resolvePenType(flags);
21039
21228
  obj.penWidth = resolvePenWidth(flags, e.attrs.get("penwidth"));
21040
21229
  obj.rawStyle = styleTokens2(e.attrs.get("style"));
21230
+ if (e.info.spl !== void 0) gvrenderSetStyle(obj.rawStyle);
21041
21231
  }
21042
21232
  function renderEdge(e, renderer, job) {
21043
21233
  emitEdgeComments(e, renderer, job);
@@ -21053,6 +21243,8 @@ function renderEdge(e, renderer, job) {
21053
21243
  withColorScheme(e.attrs.get("colorscheme"), () => {
21054
21244
  renderer.beginEdge(e, job);
21055
21245
  reportEdgeColors(e);
21246
+ const styles = styleTokens2(e.attrs.get("style"));
21247
+ for (let i = edgeStyleResets(e, styles); i > 0; i--) gvrenderSetStyle(styles);
21056
21248
  reportEdgeLabelColors(e);
21057
21249
  renderer.endEdge(e, job);
21058
21250
  });
@@ -21066,6 +21258,10 @@ function renderGraphLabel(g, renderer, job) {
21066
21258
  }
21067
21259
  function renderClusterBox(sg, filled, renderer, job) {
21068
21260
  const { ll, ur } = sg.info.bb;
21261
+ if (isStripedCluster(sg)) {
21262
+ renderStripedClusterBox(sg, renderer, job);
21263
+ return;
21264
+ }
21069
21265
  if (parseStyleFlags(clusterStyle(sg)).rounded) {
21070
21266
  const af = [{ x: ll.x, y: ll.y }, { x: ur.x, y: ll.y }, { x: ur.x, y: ur.y }, { x: ll.x, y: ur.y }];
21071
21267
  emitRoundedBezier(af, { x: 0, y: 0 }, filled, { renderer, job });
@@ -21089,7 +21285,7 @@ function renderOneCluster(sg, renderer, job) {
21089
21285
  resolveObjAnchor(sg, labelTextOf2(sg.info.label), svgClusterId(sg, job), job.obj);
21090
21286
  }
21091
21287
  const anchored = beginAnchorIf(renderer, job);
21092
- if ((clusterPeripheries(sg) !== 0 || filled) && job.obj?.pen !== 0 /* None */) {
21288
+ if ((clusterPeripheries(sg) !== 0 || filled || isStripedCluster(sg)) && job.obj?.pen !== 0 /* None */) {
21093
21289
  renderClusterBox(sg, filled, renderer, job);
21094
21290
  }
21095
21291
  renderClusterLabel(sg, renderer, job);
@@ -21119,6 +21315,7 @@ function renderGraph(g, job, renderer) {
21119
21315
  job.numLayers = layered ? info.numLayers : 1;
21120
21316
  job.layerIDs = info.layerIDs;
21121
21317
  renderer.beginGraph(g, job);
21318
+ warnLayersUnsupported(job.format, info.numLayers, renderer.beginLayer !== void 0);
21122
21319
  for (let ln = 1; ln <= job.numLayers; ln++) {
21123
21320
  job.layerNum = ln;
21124
21321
  if (layered) renderer.beginLayer(info.layerIDs[ln], job);
@@ -21180,13 +21377,21 @@ function render(ctx, g, format, inlineImages = false) {
21180
21377
  }
21181
21378
 
21182
21379
  // src/common/htmltable-emit-fill.ts
21380
+ var MSG_MANY_COLORS = "More than 2 colors specified for a gradient - ignoring remaining";
21381
+ function findHtmlStopColor(color, silent = false) {
21382
+ const { segs, error } = silent ? parseSegsSilent(color) : parseSegs(color);
21383
+ const first = segs[0];
21384
+ const second = segs[1];
21385
+ if (error !== 0 || first === void 0 || second === void 0 || first.color === null) {
21386
+ return null;
21387
+ }
21388
+ if (segs.length > 2 && !silent) agwarningf(MSG_MANY_COLORS);
21389
+ const frac = first.hasFraction ? first.t : second.hasFraction ? 1 - second.t : 0;
21390
+ return { fill: first.color, stop: second.color, frac };
21391
+ }
21183
21392
  function parseGradientSpec(color) {
21184
- const idx = color.indexOf(":");
21185
- if (idx < 1) return null;
21186
- const c0 = color.slice(0, idx).trim();
21187
- const c1 = color.slice(idx + 1).trim();
21188
- if (c0.length === 0) return null;
21189
- return [c0, c1.length > 0 ? c1 : "black"];
21393
+ const spec = findHtmlStopColor(color, true);
21394
+ return spec === null ? null : [spec.fill, spec.stop ?? "black"];
21190
21395
  }
21191
21396
  var paintObj = {
21192
21397
  parent: null,
@@ -21243,6 +21448,12 @@ function resetHtmlFillPenWidth() {
21243
21448
  htmlFillPen = 1;
21244
21449
  }
21245
21450
  registerRenderState(resetHtmlFillPenWidth);
21451
+ var DEFAULT_LINE_STYLE = ["solid", "setlinewidth(1)"];
21452
+ function htmlBorderStyle(pen) {
21453
+ if (pen === 1 /* Dashed */) return ["dashed"];
21454
+ if (pen === 2 /* Dotted */) return ["dotted"];
21455
+ return DEFAULT_LINE_STYLE;
21456
+ }
21246
21457
  function penTypeOf(style2) {
21247
21458
  const st = htmlStyle(style2);
21248
21459
  if (st.dashed) return 1 /* Dashed */;
@@ -21250,12 +21461,13 @@ function penTypeOf(style2) {
21250
21461
  return 3 /* Solid */;
21251
21462
  }
21252
21463
  function withHtmlPaint(paint, job, drawFn) {
21253
- paintObj.fillColor = paint.fill !== void 0 ? resolveRenderColor(paint.fill) : { type: "none" };
21464
+ paintObj.fillColor = paint.fill !== void 0 ? resolveRenderColor(firstColor(paint.fill)) : { type: "none" };
21254
21465
  paintObj.penColor = paint.pen !== void 0 ? resolveRenderColor(paint.pen) : { type: "string", s: "transparent" };
21255
21466
  applyHtmlFill(paint);
21256
21467
  paintObj.pen = penTypeOf(paint.penStyle);
21257
21468
  paintObj.penWidth = paint.penWidth !== void 0 ? paint.penWidth : 1;
21258
21469
  paintObj.rawStyle = paintObj.pen === 3 /* Solid */ ? ["solid"] : [];
21470
+ gvrenderSetStyle(htmlBorderStyle(paintObj.pen));
21259
21471
  paintObj.emitState = job.obj?.emitState ?? 8 /* NDraw */;
21260
21472
  job.pushObj(paintObj);
21261
21473
  try {
@@ -21269,7 +21481,7 @@ function applyHtmlFill(paint) {
21269
21481
  paintObj.fill = paint.radial === true ? 3 /* Radial */ : 2 /* Linear */;
21270
21482
  paintObj.stopColor = resolveRenderColor(paint.stop);
21271
21483
  paintObj.gradientAngle = paint.gradientAngle ?? 0;
21272
- paintObj.gradientFrac = 0;
21484
+ paintObj.gradientFrac = paint.gradientFrac ?? 0;
21273
21485
  return;
21274
21486
  }
21275
21487
  paintObj.fill = paint.fill !== void 0 ? 1 /* Solid */ : 0 /* None */;
@@ -21572,6 +21784,7 @@ function resolveClusterFillEx(attrs) {
21572
21784
 
21573
21785
  // src/common/splines-clip.ts
21574
21786
  var ARR_NORM = 1;
21787
+ var dist = distFused;
21575
21788
  var SplineClipHelper = class _SplineClipHelper {
21576
21789
  static makeEmptySpl() {
21577
21790
  return { list: [], size: 0, bb: { ll: { x: 0, y: 0 }, ur: { x: 0, y: 0 } } };
@@ -21664,15 +21877,11 @@ var SplineClipHelper = class _SplineClipHelper {
21664
21877
  if (j) return [eflag, sflag];
21665
21878
  return [sflag, eflag];
21666
21879
  }
21667
- /** DIST(p, q). */
21668
- static dist(p, q) {
21669
- return Math.hypot(p.x - q.x, p.y - q.y);
21670
- }
21671
21880
  /** Sphere inside-fn around `tip` with radius `r` for bezierClip. */
21672
21881
  static sphereCtx(tip2, r) {
21673
21882
  return {
21674
21883
  ctx: { nodeCoord: { x: 0, y: 0 }, rw: 0, bp: null },
21675
- fn: (_c, p) => _SplineClipHelper.dist(p, tip2) <= r
21884
+ fn: (_c, p) => dist(p, tip2) <= r
21676
21885
  };
21677
21886
  }
21678
21887
  /**
@@ -21704,7 +21913,7 @@ var SplineClipHelper = class _SplineClipHelper {
21704
21913
  );
21705
21914
  spl.eflag = eflag;
21706
21915
  spl.ep = ps[endp + 3];
21707
- if (endp > startp && _SplineClipHelper.dist(ps[endp], ps[endp + 3]) < elen) {
21916
+ if (endp > startp && dist(ps[endp], ps[endp + 3]) < elen) {
21708
21917
  endp -= 3;
21709
21918
  }
21710
21919
  const sp = [spl.ep, ps[endp + 2], ps[endp + 1], ps[endp]];
@@ -21731,7 +21940,7 @@ var SplineClipHelper = class _SplineClipHelper {
21731
21940
  );
21732
21941
  spl.sflag = sflag;
21733
21942
  spl.sp = ps[startp];
21734
- if (endp > startp && _SplineClipHelper.dist(ps[startp], ps[startp + 3]) < slen) {
21943
+ if (endp > startp && dist(ps[startp], ps[startp + 3]) < slen) {
21735
21944
  startp += 3;
21736
21945
  }
21737
21946
  const sp = [ps[startp + 3], ps[startp + 2], ps[startp + 1], spl.sp];
@@ -21832,7 +22041,7 @@ var SplineClipHelper = class _SplineClipHelper {
21832
22041
  if (sflag && eflag && endp === startp) {
21833
22042
  const p = ps[endp];
21834
22043
  const q = ps[endp + 3];
21835
- const d = _SplineClipHelper.dist(p, q);
22044
+ const d = dist(p, q);
21836
22045
  let hlen = hlen0;
21837
22046
  let tlen = tlen0;
21838
22047
  if (hlen + tlen >= d) {
@@ -21875,7 +22084,7 @@ var SplineClipHelper = class _SplineClipHelper {
21875
22084
  let hlen = hlen0;
21876
22085
  const p = ps[endp];
21877
22086
  const q = ps[endp + 3];
21878
- const maxd = 0.9 * _SplineClipHelper.dist(p, q);
22087
+ const maxd = 0.9 * dist(p, q);
21879
22088
  if (hlen >= maxd) hlen = maxd;
21880
22089
  const r = { x: p.x, y: p.y };
21881
22090
  if (p.y === q.y) {
@@ -21895,7 +22104,7 @@ var SplineClipHelper = class _SplineClipHelper {
21895
22104
  let tlen = tlen0;
21896
22105
  const p = ps[startp];
21897
22106
  const q = ps[startp + 3];
21898
- const maxd = 0.9 * _SplineClipHelper.dist(p, q);
22107
+ const maxd = 0.9 * dist(p, q);
21899
22108
  if (tlen >= maxd) tlen = maxd;
21900
22109
  const r = { x: p.x, y: p.y };
21901
22110
  if (p.y === q.y) {
@@ -24029,13 +24238,13 @@ function dfsNode(Xg, v, frames) {
24029
24238
  frames.push({ v, edges: v.outEdges(Xg).slice(), i: 0 });
24030
24239
  }
24031
24240
  function dfsStep2(Xg, frames) {
24032
- const fr3 = frames[frames.length - 1];
24033
- if (fr3.i < fr3.edges.length) {
24034
- const e = fr3.edges[fr3.i++];
24241
+ const fr7 = frames[frames.length - 1];
24242
+ if (fr7.i < fr7.edges.length) {
24243
+ const e = fr7.edges[fr7.i++];
24035
24244
  if (e.head.info.onstack) reverseEdge2(Xg, e);
24036
24245
  else if (!e.head.info.mark) dfsNode(Xg, e.head, frames);
24037
24246
  } else {
24038
- fr3.v.info.onstack = 0;
24247
+ fr7.v.info.onstack = 0;
24039
24248
  frames.pop();
24040
24249
  }
24041
24250
  }
@@ -25807,7 +26016,7 @@ function fillRankVlist(g, r, root) {
25807
26016
  rankArr[r].v = rootRank.v;
25808
26017
  rankArr[r].vStart = lead.info.order ?? 0;
25809
26018
  const maxi = computeMaxi(g, r);
25810
- if (maxi === -1) agwarningf(`degenerate concentrated rank ${g.name},${r}`, "error");
26019
+ if (maxi === -1) agwarningf(`degenerate concentrated rank ${g.name},${r}`);
25811
26020
  rankArr[r].n = maxi + 1;
25812
26021
  return 0;
25813
26022
  }
@@ -28626,7 +28835,7 @@ function routeSplinesInternal(pp, polyline) {
28626
28835
  ];
28627
28836
  const pl = shortestPath(poly, eps);
28628
28837
  if (pl === null) {
28629
- agerrLineOn("warn", "in routesplines, Pshortestpath failed");
28838
+ agerrorf("in routesplines, Pshortestpath failed");
28630
28839
  return null;
28631
28840
  }
28632
28841
  emitDump("S3_POLY", dumpNames, () => ({
@@ -30632,9 +30841,9 @@ function writePortlabelPos(l, pe, pf, angleStr, distanceStr) {
30632
30841
  const angleDeg = lateDouble(angleStr, PORT_LABEL_ANGLE, -180);
30633
30842
  const angle = Math.atan2(pf.y - pe.y, pf.x - pe.x) + RADIANS(angleDeg);
30634
30843
  const distMult = lateDouble(distanceStr || void 0, 1, 0);
30635
- const dist4 = PORT_LABEL_DISTANCE * distMult;
30636
- l.pos.x = pe.x + dist4 * Math.cos(angle);
30637
- l.pos.y = pe.y + dist4 * Math.sin(angle);
30844
+ const dist5 = PORT_LABEL_DISTANCE * distMult;
30845
+ l.pos.x = pe.x + dist5 * Math.cos(angle);
30846
+ l.pos.y = pe.y + dist5 * Math.sin(angle);
30638
30847
  l.set = true;
30639
30848
  }
30640
30849
  function updateBB(g, l) {
@@ -31036,7 +31245,7 @@ function translateDrawing(g) {
31036
31245
  if (e.tail !== v) continue;
31037
31246
  if (e.info.spl === void 0) {
31038
31247
  if (!(g.info.concentrate ?? false) && (e.info.edge_type ?? 0) !== IGNORED_EDGE) {
31039
- agerrLineOn("warn", `lost ${e.tail.name} ${e.head.name} edge`);
31248
+ agerrorf(`lost ${e.tail.name} ${e.head.name} edge`);
31040
31249
  }
31041
31250
  continue;
31042
31251
  }
@@ -31799,9 +32008,14 @@ function nodeInsideFn2(box) {
31799
32008
  function clipToNodes(bezier2, tailBox, headBox, penwidth = DEFAULT_NODEPENWIDTH, clip = CLIP_BOTH) {
31800
32009
  const step1 = clip.tail ? bezierClipNode(bezier2, tailBox.center.x, tailBox.center.y, nodeInsideFn2(tailBox), true) : bezier2;
31801
32010
  const step2 = clip.head ? bezierClipNode(step1, headBox.center.x, headBox.center.y, nodeInsideFn2(headBox), false) : step1;
31802
- const arrowTip = step2[3];
32011
+ const startp = 0;
32012
+ let endp = 0;
32013
+ const arrowTip = step2[endp + 3];
31803
32014
  const elen = normalArrowLen(penwidth);
31804
- const clipped = arrowEndClip(step2, arrowTip, elen);
32015
+ if (endp > startp && distFused(step2[endp], step2[endp + 3]) < elen) {
32016
+ endp -= 3;
32017
+ }
32018
+ const clipped = arrowEndClip(step2.slice(endp, endp + 4), arrowTip, elen);
31805
32019
  const arrowDir = normalizeVec({
31806
32020
  x: clipped[3].x - arrowTip.x,
31807
32021
  y: clipped[3].y - arrowTip.y
@@ -34340,8 +34554,7 @@ function ensureDummyNodes(sg, gstart) {
34340
34554
  }
34341
34555
  function orthoEdges(g, useLbls, clipAndInstall2) {
34342
34556
  if (useLbls) {
34343
- agerrLineOn(
34344
- "warn",
34557
+ agwarningf(
34345
34558
  "Orthogonal edges do not currently handle edge labels. Try using xlabels.\n"
34346
34559
  );
34347
34560
  useLbls = false;
@@ -34476,7 +34689,7 @@ function dispatchOrthoEdges(g, useLbls) {
34476
34689
  }
34477
34690
 
34478
34691
  // src/common/arrows-geometry.ts
34479
- function dist(a, b) {
34692
+ function dist3(a, b) {
34480
34693
  return Math.hypot(a.x - b.x, a.y - b.y);
34481
34694
  }
34482
34695
 
@@ -34580,7 +34793,7 @@ function getCycleCentroid(g, edge) {
34580
34793
  }
34581
34794
  function bend(spl, centroid) {
34582
34795
  const midpt = midPointf(spl[0], spl[3]);
34583
- const distVal = dist(spl[3], spl[0]);
34796
+ const distVal = dist3(spl[3], spl[0]);
34584
34797
  const r = distVal / 5;
34585
34798
  const vX = centroid.x - midpt.x;
34586
34799
  const vY = centroid.y - midpt.y;
@@ -35193,7 +35406,7 @@ function arrowEndClipIdx(state3, endp) {
35193
35406
  const elen = arrowClipLength(edgeArrowName(e, "head"), edgeArrowsize(e), edgePenwidthAttr(e));
35194
35407
  bez.eflag = bez.eflag || 1;
35195
35408
  bez.ep = { ...bez.list[endp + 3] };
35196
- if (endp > state3.starti && dist(bez.list[endp], bez.list[endp + 3]) < elen) endp -= 3;
35409
+ if (endp > state3.starti && distFused(bez.list[endp], bez.list[endp + 3]) < elen) endp -= 3;
35197
35410
  const seg2 = [bez.list[endp], bez.list[endp + 1], bez.list[endp + 2], bez.list[endp + 3]];
35198
35411
  const clipped = arrowEndClip(seg2, bez.ep, elen);
35199
35412
  for (let k = 0; k < 4; k++) bez.list[endp + k] = clipped[k];
@@ -35204,7 +35417,7 @@ function arrowStartClipIdx(state3, startp, endp) {
35204
35417
  const slen = arrowClipLength(edgeArrowName(e, "tail"), edgeArrowsize(e), edgePenwidthAttr(e));
35205
35418
  bez.sflag = bez.sflag || 1;
35206
35419
  bez.sp = { ...bez.list[startp] };
35207
- if (endp > startp && dist(bez.list[startp], bez.list[startp + 3]) < slen) startp += 3;
35420
+ if (endp > startp && distFused(bez.list[startp], bez.list[startp + 3]) < slen) startp += 3;
35208
35421
  const seg2 = [bez.list[startp], bez.list[startp + 1], bez.list[startp + 2], bez.list[startp + 3]];
35209
35422
  const clipped = tailArrowEndClip(seg2, bez.sp, slen);
35210
35423
  for (let k = 0; k < 4; k++) bez.list[startp + k] = clipped[k];
@@ -36473,120 +36686,522 @@ var DOT_LAYOUT_ENGINE = {
36473
36686
  };
36474
36687
 
36475
36688
  // src/layout/neato/dijkstra.ts
36476
- function heapPush(heap, dist4, idx) {
36477
- let pos = heap.length;
36478
- heap.push(idx);
36479
- while (pos > 0) {
36480
- const parent2 = pos - 1 >> 1;
36481
- if (dist4[heap[parent2]] <= dist4[heap[pos]]) break;
36482
- const tmp = heap[parent2];
36483
- heap[parent2] = heap[pos];
36484
- heap[pos] = tmp;
36485
- pos = parent2;
36486
- }
36487
- }
36488
- function heapSiftDown2(heap, dist4) {
36489
- let pos = 0;
36689
+ var FLT_MAX = 34028234663852886e22;
36690
+ function greaterPriorityF(h, i, j, dist5) {
36691
+ return dist5[h.data[i]] < dist5[h.data[j]];
36692
+ }
36693
+ function heapifyF(h, start, dist5) {
36694
+ let i = start;
36490
36695
  for (; ; ) {
36491
- const l = 2 * pos + 1;
36492
- const r = 2 * pos + 2;
36493
- let smallest = pos;
36494
- if (l < heap.length && dist4[heap[l]] < dist4[heap[smallest]]) smallest = l;
36495
- if (r < heap.length && dist4[heap[r]] < dist4[heap[smallest]]) smallest = r;
36496
- if (smallest === pos) break;
36497
- const tmp = heap[smallest];
36498
- heap[smallest] = heap[pos];
36499
- heap[pos] = tmp;
36500
- pos = smallest;
36501
- }
36502
- }
36503
- function heapPop(heap, dist4) {
36504
- const top = heap[0];
36505
- const last = heap.pop();
36506
- if (heap.length === 0) return top;
36507
- heap[0] = last;
36508
- heapSiftDown2(heap, dist4);
36509
- return top;
36510
- }
36511
- function heapBuildExcluding(src, n, dist4) {
36512
- const heap = [];
36696
+ const l = ngLeft(i);
36697
+ const r = ngRight(i);
36698
+ let largest = ngInsideHeap(h, l) && greaterPriorityF(h, l, i, dist5) ? l : i;
36699
+ if (ngInsideHeap(h, r) && greaterPriorityF(h, r, largest, dist5)) largest = r;
36700
+ if (largest === i) break;
36701
+ ngExchange(h, largest, i);
36702
+ i = largest;
36703
+ }
36704
+ }
36705
+ function initHeapF(startVertex, dist5, n) {
36706
+ const h = {
36707
+ data: new Array(Math.max(n - 1, 0)).fill(0),
36708
+ heapSize: n - 1,
36709
+ index: new Int32Array(n)
36710
+ };
36711
+ let count = 0;
36513
36712
  for (let i = 0; i < n; i++) {
36514
- if (i !== src) heapPush(heap, dist4, i);
36713
+ if (i !== startVertex) {
36714
+ h.data[count] = i;
36715
+ h.index[i] = count;
36716
+ count++;
36717
+ }
36515
36718
  }
36516
- return heap;
36719
+ for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) heapifyF(h, j, dist5);
36720
+ return h;
36721
+ }
36722
+ function extractMaxF(h, dist5) {
36723
+ if (h.heapSize === 0) return -1;
36724
+ const max = h.data[0];
36725
+ h.data[0] = h.data[h.heapSize - 1];
36726
+ h.index[h.data[0]] = 0;
36727
+ h.heapSize--;
36728
+ heapifyF(h, 0, dist5);
36729
+ return max;
36730
+ }
36731
+ function increaseKeyF(h, increasedVertex, newDist, dist5) {
36732
+ if (dist5[increasedVertex] <= newDist) return;
36733
+ let i = h.index[increasedVertex];
36734
+ dist5[increasedVertex] = newDist;
36735
+ while (i > 0 && dist5[h.data[ngParent(i)]] > newDist) {
36736
+ ngAssign(h, i, ngParent(i));
36737
+ i = ngParent(i);
36738
+ }
36739
+ h.data[i] = increasedVertex;
36740
+ h.index[increasedVertex] = i;
36741
+ }
36742
+ function dijkstra(vertex, graph, n, dist5) {
36743
+ for (let i = 0; i < n; i++) dist5[i] = FLT_MAX;
36744
+ dist5[vertex] = 0;
36745
+ const vd = graph[vertex];
36746
+ for (let i = 1; i < vd.nedges; i++) dist5[vd.edges[i]] = vd.ewgts[i];
36747
+ const h = initHeapF(vertex, dist5, n);
36748
+ for (let closest = extractMaxF(h, dist5); closest >= 0; closest = extractMaxF(h, dist5)) {
36749
+ const closestDist = dist5[closest];
36750
+ if (closestDist === FLT_MAX) break;
36751
+ const cd = graph[closest];
36752
+ for (let i = 1; i < cd.nedges; i++) {
36753
+ increaseKeyF(h, cd.edges[i], Math.fround(closestDist + Math.fround(cd.ewgts[i])), dist5);
36754
+ }
36755
+ }
36756
+ }
36757
+ var MAX_DIST = 2147483647;
36758
+ function ngLeft(i) {
36759
+ return 2 * i;
36517
36760
  }
36518
- function dijkstraInitDist(src, graph, n, dist4) {
36519
- for (let i = 0; i < n; i++) dist4[i] = Infinity;
36520
- dist4[src] = 0;
36521
- const v = graph[src];
36522
- for (let i = 1; i < v.nedges; i++) dist4[v.edges[i]] = v.ewgts[i];
36761
+ function ngRight(i) {
36762
+ return 2 * i + 1;
36523
36763
  }
36524
- function dijkstraRelax(closest, closestDist, graph, dist4, heap) {
36525
- const cv = graph[closest];
36526
- for (let i = 1; i < cv.nedges; i++) {
36527
- const nb = cv.edges[i];
36528
- const nd = closestDist + cv.ewgts[i];
36529
- if (nd < dist4[nb]) {
36530
- dist4[nb] = nd;
36531
- heapPush(heap, dist4, nb);
36764
+ function ngParent(i) {
36765
+ return Math.trunc(i / 2);
36766
+ }
36767
+ function ngInsideHeap(h, i) {
36768
+ return i < h.heapSize;
36769
+ }
36770
+ function ngGreaterPriority(h, i, j, dist5) {
36771
+ return dist5[h.data[i]] < dist5[h.data[j]];
36772
+ }
36773
+ function ngAssign(h, i, j) {
36774
+ h.data[i] = h.data[j];
36775
+ h.index[h.data[i]] = i;
36776
+ }
36777
+ function ngExchange(h, i, j) {
36778
+ const t = h.data[i];
36779
+ h.data[i] = h.data[j];
36780
+ h.data[j] = t;
36781
+ h.index[h.data[i]] = i;
36782
+ h.index[h.data[j]] = j;
36783
+ }
36784
+ function ngHeapify(h, start, dist5) {
36785
+ let i = start;
36786
+ for (; ; ) {
36787
+ const l = ngLeft(i);
36788
+ const r = ngRight(i);
36789
+ let largest = ngInsideHeap(h, l) && ngGreaterPriority(h, l, i, dist5) ? l : i;
36790
+ if (ngInsideHeap(h, r) && ngGreaterPriority(h, r, largest, dist5)) largest = r;
36791
+ if (largest === i) break;
36792
+ ngExchange(h, largest, i);
36793
+ i = largest;
36794
+ }
36795
+ }
36796
+ function ngInitHeap(startVertex, dist5, n) {
36797
+ const h = {
36798
+ data: new Array(Math.max(n - 1, 0)).fill(0),
36799
+ heapSize: n - 1,
36800
+ index: new Int32Array(n)
36801
+ };
36802
+ let count = 0;
36803
+ for (let i = 0; i < n; i++) {
36804
+ if (i !== startVertex) {
36805
+ h.data[count] = i;
36806
+ h.index[i] = count;
36807
+ count++;
36532
36808
  }
36533
36809
  }
36810
+ for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) ngHeapify(h, j, dist5);
36811
+ return h;
36812
+ }
36813
+ function ngExtractMax(h, dist5) {
36814
+ if (h.heapSize === 0) return -1;
36815
+ const max = h.data[0];
36816
+ h.data[0] = h.data[h.heapSize - 1];
36817
+ h.index[h.data[0]] = 0;
36818
+ h.heapSize--;
36819
+ ngHeapify(h, 0, dist5);
36820
+ return max;
36534
36821
  }
36535
- function dijkstra(src, graph, n, dist4) {
36536
- dijkstraInitDist(src, graph, n, dist4);
36537
- const heap = heapBuildExcluding(src, n, dist4);
36538
- while (heap.length > 0) {
36539
- const closest = heapPop(heap, dist4);
36540
- const closestDist = dist4[closest];
36541
- if (!isFinite(closestDist)) break;
36542
- dijkstraRelax(closest, closestDist, graph, dist4, heap);
36822
+ function ngIncreaseKey(h, increasedVertex, newDist, dist5) {
36823
+ if (dist5[increasedVertex] <= newDist) return;
36824
+ let i = h.index[increasedVertex];
36825
+ dist5[increasedVertex] = newDist;
36826
+ while (i > 0 && dist5[h.data[ngParent(i)]] > newDist) {
36827
+ ngAssign(h, i, ngParent(i));
36828
+ i = ngParent(i);
36829
+ }
36830
+ h.data[i] = increasedVertex;
36831
+ h.index[increasedVertex] = i;
36832
+ }
36833
+ function toDistType(w) {
36834
+ return Math.trunc(Math.fround(w));
36835
+ }
36836
+ function ngdijkstra(vertex, graph, n, dist5) {
36837
+ let prevClosestDist = MAX_DIST;
36838
+ for (let i = 0; i < n; i++) dist5[i] = MAX_DIST;
36839
+ dist5[vertex] = 0;
36840
+ const vd = graph[vertex];
36841
+ for (let i = 1; i < vd.nedges; i++) dist5[vd.edges[i]] = toDistType(vd.ewgts[i]);
36842
+ const h = ngInitHeap(vertex, dist5, n);
36843
+ for (let closest = ngExtractMax(h, dist5); closest >= 0; closest = ngExtractMax(h, dist5)) {
36844
+ const closestDist = dist5[closest];
36845
+ if (closestDist === MAX_DIST) break;
36846
+ const cd = graph[closest];
36847
+ for (let i = 1; i < cd.nedges; i++) {
36848
+ ngIncreaseKey(h, cd.edges[i], closestDist + toDistType(cd.ewgts[i]) | 0, dist5);
36849
+ }
36850
+ prevClosestDist = closestDist;
36851
+ }
36852
+ for (let i = 0; i < n; i++) {
36853
+ if (dist5[i] === MAX_DIST) {
36854
+ dist5[i] = MAX_DIST - prevClosestDist < 10 ? MAX_DIST : prevClosestDist + 10;
36855
+ }
36543
36856
  }
36544
36857
  }
36545
36858
 
36546
36859
  // src/layout/neato/bfs.ts
36547
- function bfsInit(src, n, dist4) {
36548
- for (let i = 0; i < n; i++) dist4[i] = -1;
36549
- dist4[src] = 0;
36860
+ function bfsInit(src, n, dist5) {
36861
+ for (let i = 0; i < n; i++) dist5[i] = -1;
36862
+ dist5[src] = 0;
36550
36863
  return [src];
36551
36864
  }
36552
- function bfsFixDisconnected(n, dist4, closestDist) {
36865
+ function bfsFixDisconnected(n, dist5, closestDist) {
36553
36866
  for (let i = 0; i < n; i++) {
36554
- if (dist4[i] < 0) dist4[i] = closestDist + 10;
36867
+ if (dist5[i] < 0) dist5[i] = closestDist + 10;
36555
36868
  }
36556
36869
  }
36557
- function bfsVisitNeighbors(vertex, graph, dist4, queue) {
36870
+ function bfsVisitNeighbors(vertex, graph, dist5, queue) {
36558
36871
  const vd = graph[vertex];
36559
- const d = dist4[vertex];
36872
+ const d = dist5[vertex];
36560
36873
  const unit = graph[0].ewgts.length === 0;
36561
36874
  for (let i = 1; i < vd.nedges; i++) {
36562
36875
  const nb = vd.edges[i];
36563
- if (dist4[nb] < 0) {
36564
- dist4[nb] = d + (unit ? 1 : Math.trunc(Math.fround(vd.ewgts[i])));
36876
+ if (dist5[nb] < 0) {
36877
+ dist5[nb] = d + (unit ? 1 : Math.trunc(Math.fround(vd.ewgts[i])));
36565
36878
  queue.push(nb);
36566
36879
  }
36567
36880
  }
36568
36881
  return d;
36569
36882
  }
36570
- function bfs(src, graph, n, dist4) {
36571
- const queue = bfsInit(src, n, dist4);
36883
+ function bfs(src, graph, n, dist5) {
36884
+ const queue = bfsInit(src, n, dist5);
36572
36885
  let closestDist = 0;
36573
36886
  let head = 0;
36574
36887
  while (head < queue.length) {
36575
36888
  const vertex = queue[head++];
36576
- closestDist = bfsVisitNeighbors(vertex, graph, dist4, queue);
36889
+ closestDist = bfsVisitNeighbors(vertex, graph, dist5, queue);
36890
+ }
36891
+ bfsFixDisconnected(n, dist5, closestDist);
36892
+ }
36893
+ function packedIndex(i, j, n) {
36894
+ return i * (2 * n - i - 1) / 2 + j;
36895
+ }
36896
+ function computeWeightedApspPacked(graph, n) {
36897
+ const result = new Float32Array(n * (n + 1) / 2);
36898
+ const di = new Float32Array(n);
36899
+ for (let i = 0; i < n; i++) {
36900
+ dijkstra(i, graph, n, di);
36901
+ for (let j = i; j < n; j++) result[packedIndex(i, j, n)] = di[j];
36902
+ }
36903
+ return result;
36904
+ }
36905
+
36906
+ // src/common/crand.ts
36907
+ var C_RAND_MAX = 2147483647;
36908
+ var UNSEEDED_STATE2 = 1;
36909
+ var state2 = UNSEEDED_STATE2;
36910
+ registerRenderState(() => {
36911
+ state2 = UNSEEDED_STATE2;
36912
+ });
36913
+ function csrand(seed) {
36914
+ state2 = seed;
36915
+ }
36916
+ function crand() {
36917
+ state2 = state2 * 16807 % 2147483647;
36918
+ return state2;
36919
+ }
36920
+ function cdrand() {
36921
+ return crand() / C_RAND_MAX;
36922
+ }
36923
+ function gvRandom(bound) {
36924
+ const discardThreshold = C_RAND_MAX - 2147483648 % bound;
36925
+ let r;
36926
+ do {
36927
+ r = crand();
36928
+ } while (r > discardThreshold);
36929
+ return r % bound;
36930
+ }
36931
+ function gvPermutation(bound) {
36932
+ if (bound <= 0) return [];
36933
+ const p = [];
36934
+ for (let i = 0; i < bound; i++) p.push(i);
36935
+ for (let i = bound - 1; i > 0; --i) {
36936
+ const j = gvRandom(i + 1);
36937
+ const t = p[i];
36938
+ p[i] = p[j];
36939
+ p[j] = t;
36940
+ }
36941
+ return p;
36942
+ }
36943
+
36944
+ // src/layout/neato/matrix-ops.ts
36945
+ 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
+ function orthog1(n, vec) {
36951
+ let sum = 0;
36952
+ for (let i = 0; i < n; i++) sum += vec[i];
36953
+ sum /= n;
36954
+ for (let i = 0; i < n; i++) vec[i] = vec[i] - sum;
36955
+ }
36956
+ function orthog1f(n, vec) {
36957
+ let sum = fr(0);
36958
+ for (let i = 0; i < n; i++) sum = fr(sum + vec[i]);
36959
+ sum = fr(sum / n);
36960
+ for (let i = 0; i < n; i++) vec[i] = vec[i] - sum;
36961
+ }
36962
+ function rightMultWithVectorFF(m, n, vector, result) {
36963
+ for (let i = 0; i < n; i++) result[i] = 0;
36964
+ let index = 0;
36965
+ for (let i = 0; i < n; i++) {
36966
+ const vi = vector[i];
36967
+ let res = fr(m[index++] * vi);
36968
+ for (let j = i + 1; j < n; j++, index++) {
36969
+ res = fr(res + fr(m[index] * vector[j]));
36970
+ result[j] = result[j] + fr(m[index] * vi);
36971
+ }
36972
+ result[i] = result[i] + res;
36973
+ }
36974
+ }
36975
+ function vectorsSubtractionF(n, v1, v2, result) {
36976
+ for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
36977
+ }
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
+ function vectorsInnerProductF(n, v1, v2) {
36983
+ let result = 0;
36984
+ for (let i = 0; i < n; i++) result += fr(v1[i] * v2[i]);
36985
+ return result;
36986
+ }
36987
+ function copyVectorF(n, src, dst) {
36988
+ for (let i = 0; i < n; i++) dst[i] = src[i];
36989
+ }
36990
+ function maxAbsF(n, vec) {
36991
+ let max = fr(-1e30);
36992
+ for (let i = 0; i < n; i++) {
36993
+ const a = fr(Math.abs(vec[i]));
36994
+ if (a > max) max = a;
36995
+ }
36996
+ return max;
36997
+ }
36998
+ function squareVec(n, vec) {
36999
+ for (let i = 0; i < n; i++) vec[i] = vec[i] * vec[i];
37000
+ }
37001
+ function invertVec(n, vec) {
37002
+ for (let i = 0; i < n; i++) {
37003
+ if (vec[i] !== 0) vec[i] = 1 / vec[i];
37004
+ }
37005
+ }
37006
+ function sqrtVecF(n, source, target) {
37007
+ for (let i = 0; i < n; i++) {
37008
+ if (source[i] >= 0) target[i] = fr(Math.sqrt(source[i]));
37009
+ }
37010
+ }
37011
+ function invertSqrtVec(n, vec) {
37012
+ for (let i = 0; i < n; i++) {
37013
+ if (vec[i] > 0) vec[i] = 1 / fr(Math.sqrt(vec[i]));
37014
+ }
37015
+ }
37016
+ var BLOCK_NONE = 1;
37017
+ function innerProduct(n, v1, v2, block) {
37018
+ let result = 0;
37019
+ const blocked = block === BLOCK_NONE ? 0 : n - n % block;
37020
+ let i = 0;
37021
+ for (; i < blocked; i++) result += v1[i] * v2[i];
37022
+ for (; i < n; i++) result = fma2(v1[i], v2[i], result);
37023
+ return result;
37024
+ }
37025
+ function scadd(vec1, end, fac, vec2) {
37026
+ for (let i = 0; i <= end; i++) vec1[i] = fma2(fac, vec2[i], vec1[i]);
37027
+ }
37028
+ function norm(vec, end, block) {
37029
+ return Math.sqrt(innerProduct(end + 1, vec, vec, block));
37030
+ }
37031
+ function vectorsScalarMult(n, vector, alpha, result) {
37032
+ for (let i = 0; i < n; i++) result[i] = vector[i] * alpha;
37033
+ }
37034
+ function copyVector(n, source, dest) {
37035
+ for (let i = 0; i < n; i++) dest[i] = source[i];
37036
+ }
37037
+ function vectorsAddition(n, v1, v2, result) {
37038
+ for (let i = 0; i < n; i++) result[i] = v1[i] + v2[i];
37039
+ }
37040
+ function vectorsSubtraction(n, v1, v2, result) {
37041
+ for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
37042
+ }
37043
+ function maxAbs(n, vector) {
37044
+ let maxVal = -1e50;
37045
+ for (let i = 0; i < n; i++) {
37046
+ const a = Math.abs(vector[i]);
37047
+ if (a > maxVal) maxVal = a;
37048
+ }
37049
+ return maxVal;
37050
+ }
37051
+ function rightMultWithVectorF(matrix, n, vector, result, block) {
37052
+ const blocked = block === BLOCK_NONE ? 0 : n - n % block;
37053
+ for (let i = 0; i < n; i++) {
37054
+ const row = matrix[i];
37055
+ let res = 0;
37056
+ let j = 0;
37057
+ for (; j < blocked; j++) res += row[j] * vector[j];
37058
+ for (; j < n; j++) res = fma2(row[j], vector[j], res);
37059
+ result[i] = res;
37060
+ }
37061
+ }
37062
+ function rightMultWithVector(matrix, n, vector, result) {
37063
+ for (let i = 0; i < n; i++) {
37064
+ let res = 0;
37065
+ const row = matrix[i];
37066
+ for (let j = 0; j < row.nedges; j++) res = fma2(row.ewgts[j], vector[row.edges[j]], res);
37067
+ result[i] = res;
37068
+ }
37069
+ }
37070
+ var RANGE = 500;
37071
+ function initVecOrth1(n, vec) {
37072
+ for (let i = 0; i < n; i++) vec[i] = crand() % RANGE;
37073
+ orthog1(n, vec);
37074
+ }
37075
+
37076
+ // src/layout/neato/conjgrad.ts
37077
+ var BLOCK_INITIAL_RR = 4;
37078
+ var BLOCK_P_AP = 8;
37079
+ function cgNextDirection(n, w, alpha, rR) {
37080
+ vectorsScalarMult(n, w.Ap, alpha, w.Ap);
37081
+ vectorsSubtraction(n, w.r, w.Ap, w.r);
37082
+ const rRNew = innerProduct(n, w.r, w.r, BLOCK_NONE);
37083
+ if (rR === 0) {
37084
+ agerrorf("conjugate_gradient: unexpected length 0 vector\n");
37085
+ return null;
37086
+ }
37087
+ const beta = rRNew / rR;
37088
+ vectorsScalarMult(n, w.p, beta, w.p);
37089
+ vectorsAddition(n, w.r, w.p, w.p);
37090
+ return rRNew;
37091
+ }
37092
+ function cgStart(A3, x, b, n) {
37093
+ const w = {
37094
+ r: new Float64Array(n),
37095
+ p: new Float64Array(n),
37096
+ Ap: new Float64Array(n),
37097
+ alphap: new Float64Array(n)
37098
+ };
37099
+ const Ax = new Float64Array(n);
37100
+ const orthB = Float64Array.from(b.subarray(0, n));
37101
+ orthog1(n, orthB);
37102
+ orthog1(n, x);
37103
+ rightMultWithVector(A3, n, x, Ax);
37104
+ vectorsSubtraction(n, orthB, Ax, w.r);
37105
+ w.p.set(w.r.subarray(0, n));
37106
+ return w;
37107
+ }
37108
+ function conjugateGradient(A3, x, b, n, tol, maxIterations) {
37109
+ const w = cgStart(A3, x, b, n);
37110
+ let rR = innerProduct(n, w.r, w.r, BLOCK_INITIAL_RR);
37111
+ for (let i = 0; i < maxIterations && maxAbs(n, w.r) > tol; i++) {
37112
+ rightMultWithVector(A3, n, w.p, w.Ap);
37113
+ const pAp = innerProduct(n, w.p, w.Ap, BLOCK_P_AP);
37114
+ if (pAp === 0) break;
37115
+ const alpha = rR / pAp;
37116
+ vectorsScalarMult(n, w.p, alpha, w.alphap);
37117
+ vectorsAddition(n, x, w.alphap, x);
37118
+ if (i < maxIterations - 1) {
37119
+ const next = cgNextDirection(n, w, alpha, rR);
37120
+ if (next === null) return 1;
37121
+ rR = next;
37122
+ }
37123
+ }
37124
+ return 0;
37125
+ }
37126
+ var CGF_BLOCK_AX = 4;
37127
+ var CGF_BLOCK_AP = 4;
37128
+ var CGF_BLOCK_INITIAL_RR = 4;
37129
+ var CGF_BLOCK_P_AP = 8;
37130
+ function cgfInit(A3, x, b, n, ortho1) {
37131
+ const orthB = new Float64Array(n);
37132
+ copyVector(n, b, orthB);
37133
+ if (ortho1) {
37134
+ orthog1(n, orthB);
37135
+ orthog1(n, x);
37136
+ }
37137
+ const Ax = new Float64Array(n);
37138
+ rightMultWithVectorF(A3, n, x, Ax, CGF_BLOCK_AX);
37139
+ const r = new Float64Array(n);
37140
+ vectorsSubtraction(n, orthB, Ax, r);
37141
+ const p = new Float64Array(n);
37142
+ copyVector(n, r, p);
37143
+ return {
37144
+ r,
37145
+ p,
37146
+ Ap: new Float64Array(n),
37147
+ alphap: new Float64Array(n),
37148
+ rr: innerProduct(n, r, r, CGF_BLOCK_INITIAL_RR)
37149
+ };
37150
+ }
37151
+ function cgfUpdate(n, alpha, st) {
37152
+ vectorsScalarMult(n, st.Ap, alpha, st.Ap);
37153
+ vectorsSubtraction(n, st.r, st.Ap, st.r);
37154
+ const rrNew = innerProduct(n, st.r, st.r, BLOCK_NONE);
37155
+ if (st.rr === 0) {
37156
+ agerrorf("conjugate_gradient: unexpected length 0 vector\n");
37157
+ return 1;
37158
+ }
37159
+ const beta = rrNew / st.rr;
37160
+ st.rr = rrNew;
37161
+ vectorsScalarMult(n, st.p, beta, st.p);
37162
+ vectorsAddition(n, st.r, st.p, st.p);
37163
+ return 0;
37164
+ }
37165
+ function conjugateGradientF(A3, x, b, n, opts) {
37166
+ const { tol, maxIterations, ortho1 } = opts;
37167
+ const st = cgfInit(A3, x, b, n, ortho1);
37168
+ for (let i = 0; i < maxIterations && maxAbs(n, st.r) > tol; i++) {
37169
+ rightMultWithVectorF(A3, n, st.p, st.Ap, CGF_BLOCK_AP);
37170
+ const pAp = innerProduct(n, st.p, st.Ap, CGF_BLOCK_P_AP);
37171
+ if (pAp === 0) break;
37172
+ const alpha = st.rr / pAp;
37173
+ vectorsScalarMult(n, st.p, alpha, st.alphap);
37174
+ vectorsAddition(n, x, st.alphap, x);
37175
+ if (i < maxIterations - 1 && cgfUpdate(n, alpha, st) === 1) return 1;
36577
37176
  }
36578
- bfsFixDisconnected(n, dist4, closestDist);
37177
+ return 0;
36579
37178
  }
36580
37179
 
36581
37180
  // src/layout/neato/stress.ts
37181
+ var TOLERANCE_CG = 1e-3;
36582
37182
  var DFLT_ITERATIONS = 200;
37183
+ var OPT_SMART_INIT = 4;
37184
+ function mdsModel(graph, nG) {
37185
+ if (graph[0].ewgts.length === 0) return null;
37186
+ const Dij = computeWeightedApspPacked(graph, nG);
37187
+ let shift = 0;
37188
+ for (let i = 0; i < nG; i++) {
37189
+ shift += i;
37190
+ for (let e = 1; e < graph[i].nedges; e++) {
37191
+ const j = graph[i].edges[e];
37192
+ if (j < i) continue;
37193
+ Dij[i * nG + j - shift] = graph[i].ewgts[e];
37194
+ }
37195
+ }
37196
+ return Dij;
37197
+ }
36583
37198
 
36584
37199
  // src/layout/neato/sgd-dijkstra.ts
36585
- var FLT_MAX = 34028234663852886e22;
37200
+ var FLT_MAX2 = 34028234663852886e22;
36586
37201
  var left = (i) => 2 * i;
36587
37202
  var right = (i) => 2 * i + 1;
36588
37203
  var parent = (i) => Math.trunc(i / 2);
36589
- var greaterPriority = (h, i, j, dist4) => dist4[h.data[i]] < dist4[h.data[j]];
37204
+ var greaterPriority = (h, i, j, dist5) => dist5[h.data[i]] < dist5[h.data[j]];
36590
37205
  function exchange2(h, i, j) {
36591
37206
  const t = h.data[i];
36592
37207
  h.data[i] = h.data[j];
@@ -36594,19 +37209,19 @@ function exchange2(h, i, j) {
36594
37209
  h.index[h.data[i]] = i;
36595
37210
  h.index[h.data[j]] = j;
36596
37211
  }
36597
- function heapify(h, start, dist4) {
37212
+ function heapify(h, start, dist5) {
36598
37213
  let i = start;
36599
37214
  for (; ; ) {
36600
37215
  const l = left(i);
36601
37216
  const r = right(i);
36602
- let largest = l < h.heapSize && greaterPriority(h, l, i, dist4) ? l : i;
36603
- if (r < h.heapSize && greaterPriority(h, r, largest, dist4)) largest = r;
37217
+ let largest = l < h.heapSize && greaterPriority(h, l, i, dist5) ? l : i;
37218
+ if (r < h.heapSize && greaterPriority(h, r, largest, dist5)) largest = r;
36604
37219
  if (largest === i) break;
36605
37220
  exchange2(h, largest, i);
36606
37221
  i = largest;
36607
37222
  }
36608
37223
  }
36609
- function initHeap(startVertex, dist4, n) {
37224
+ function initHeap(startVertex, dist5, n) {
36610
37225
  const h = {
36611
37226
  data: new Int32Array(Math.max(n - 1, 0)),
36612
37227
  heapSize: n - 1,
@@ -36618,23 +37233,23 @@ function initHeap(startVertex, dist4, n) {
36618
37233
  h.data[count] = i;
36619
37234
  h.index[i] = count++;
36620
37235
  }
36621
- for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) heapify(h, j, dist4);
37236
+ for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) heapify(h, j, dist5);
36622
37237
  return h;
36623
37238
  }
36624
- function extractMax(h, dist4) {
37239
+ function extractMax(h, dist5) {
36625
37240
  if (h.heapSize === 0) return -1;
36626
37241
  const max = h.data[0];
36627
37242
  h.data[0] = h.data[h.heapSize - 1];
36628
37243
  h.index[h.data[0]] = 0;
36629
37244
  h.heapSize--;
36630
- heapify(h, 0, dist4);
37245
+ heapify(h, 0, dist5);
36631
37246
  return max;
36632
37247
  }
36633
- function increaseKey(h, v, newDist, dist4) {
36634
- if (dist4[v] <= newDist) return;
36635
- dist4[v] = newDist;
37248
+ function increaseKey(h, v, newDist, dist5) {
37249
+ if (dist5[v] <= newDist) return;
37250
+ dist5[v] = newDist;
36636
37251
  let i = h.index[v];
36637
- while (i > 0 && dist4[h.data[parent(i)]] > newDist) {
37252
+ while (i > 0 && dist5[h.data[parent(i)]] > newDist) {
36638
37253
  h.data[i] = h.data[parent(i)];
36639
37254
  h.index[h.data[i]] = i;
36640
37255
  i = parent(i);
@@ -36643,7 +37258,7 @@ function increaseKey(h, v, newDist, dist4) {
36643
37258
  h.index[v] = i;
36644
37259
  }
36645
37260
  function dijkstraSgd(graph, source, terms) {
36646
- const dists = new Float32Array(graph.n).fill(FLT_MAX);
37261
+ const dists = new Float32Array(graph.n).fill(FLT_MAX2);
36647
37262
  dists[source] = 0;
36648
37263
  for (let i = graph.sources[source]; i < graph.sources[source + 1]; i++) {
36649
37264
  dists[graph.targets[i]] = graph.weights[i];
@@ -36652,7 +37267,7 @@ function dijkstraSgd(graph, source, terms) {
36652
37267
  let offset = 0;
36653
37268
  for (let closest = extractMax(h, dists); closest >= 0; closest = extractMax(h, dists)) {
36654
37269
  const d = dists[closest];
36655
- if (d === FLT_MAX) break;
37270
+ if (d === FLT_MAX2) break;
36656
37271
  if (graph.pinneds[closest] || closest < source) {
36657
37272
  terms[offset++] = { i: source, j: closest, d, w: Math.fround(1 / Math.fround(d * d)) };
36658
37273
  }
@@ -36671,7 +37286,7 @@ function lenattr(ep, g) {
36671
37286
  const val2 = /^\s*[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/.exec(s);
36672
37287
  const len = val2 === null ? Number.NaN : parseFloat(val2[0]);
36673
37288
  if (Number.isNaN(len) || len < 0 || len === 0) {
36674
- agerrLineOn("warn", `bad edge len "${s}" in ${g.name} - setting to ${DEFAULT_EDGE_LEN.toFixed(2)}`);
37289
+ agwarningf(`bad edge len "${s}" in ${g.name} - setting to ${DEFAULT_EDGE_LEN.toFixed(2)}`);
36675
37290
  return DEFAULT_EDGE_LEN;
36676
37291
  }
36677
37292
  return len;
@@ -36835,12 +37450,11 @@ function neatoMode(g) {
36835
37450
  if (str === void 0 || str === "") return MODE_MAJOR;
36836
37451
  const mode = modeByName().get(str);
36837
37452
  if (mode !== void 0) return mode;
36838
- agerrLineOn("warn", `Illegal value ${str} for attribute "mode" in graph ${g.root.name} - ignored`);
37453
+ agwarningf(`Illegal value ${str} for attribute "mode" in graph ${g.root.name} - ignored`);
36839
37454
  return MODE_MAJOR;
36840
37455
  }
36841
37456
  function checkMode(g, mode) {
36842
- const value = g.root.attrs.get("mode") || (mode === MODE_HIER ? "hier" : "ipsep");
36843
- if (mode === MODE_HIER) unsupported("mode", value, "hierarchical stress majorization");
37457
+ const value = g.root.attrs.get("mode") || "ipsep";
36844
37458
  if (mode === MODE_IPSEP && ipsepHasConstraints(g)) {
36845
37459
  unsupported("mode", value, "constrained (ipsep) majorization");
36846
37460
  }
@@ -37193,10 +37807,10 @@ function solve(a, b, c, n) {
37193
37807
  }
37194
37808
 
37195
37809
  // src/layout/neato/kk-paths.ts
37196
- function newPathState(n, dist4, adj, initialDist2) {
37810
+ function newPathState(n, dist5, adj, initialDist2) {
37197
37811
  return {
37198
37812
  n,
37199
- dist: dist4,
37813
+ dist: dist5,
37200
37814
  adj,
37201
37815
  initialDist: initialDist2,
37202
37816
  heap: new Int32Array(n + 1),
@@ -37274,10 +37888,10 @@ function s1(s, src) {
37274
37888
  function shortestPath2(s) {
37275
37889
  for (let v = 0; v < s.n; v++) s1(s, v);
37276
37890
  }
37277
- function mdsModel(dist4, n, edges) {
37891
+ function mdsModel2(dist5, n, edges) {
37278
37892
  for (const { tailSeq: i, headSeq: j, len } of edges) {
37279
37893
  if (i === j) continue;
37280
- for (const k of [i * n + j, j * n + i]) if (k < dist4.length) dist4[k] = len;
37894
+ for (const k of [i * n + j, j * n + i]) if (k < dist5.length) dist5[k] = len;
37281
37895
  }
37282
37896
  }
37283
37897
 
@@ -37370,12 +37984,12 @@ function initialPositions2(g, st) {
37370
37984
  }
37371
37985
  }
37372
37986
  function distvec(p0, p1, del) {
37373
- let dist4 = 0;
37987
+ let dist5 = 0;
37374
37988
  for (let k = 0; k < NDIM; k++) {
37375
37989
  del[k] = p0[k] - p1[k];
37376
- dist4 += del[k] * del[k];
37990
+ dist5 += del[k] * del[k];
37377
37991
  }
37378
- return Math.sqrt(dist4);
37992
+ return Math.sqrt(dist5);
37379
37993
  }
37380
37994
  function springFactors(g) {
37381
37995
  const byEnds = /* @__PURE__ */ new Map();
@@ -37392,9 +38006,9 @@ function fillRow(st, i, del) {
37392
38006
  const vi = st.nodes[i];
37393
38007
  for (let j = 0; j < st.n; j++) {
37394
38008
  if (i === j) continue;
37395
- const dist4 = distvec(vi.info.pos, st.nodes[j].info.pos, del);
38009
+ const dist5 = distvec(vi.info.pos, st.nodes[j].info.pos, del);
37396
38010
  for (let k = 0; k < NDIM; k++) {
37397
- const v = st.spring[i * st.n + j] * (del[k] - st.dist[i * st.n + j] * del[k] / dist4);
38011
+ const v = st.spring[i * st.n + j] * (del[k] - st.dist[i * st.n + j] * del[k] / dist5);
37398
38012
  st.t[(i * st.n + j) * NDIM + k] = v;
37399
38013
  st.sumT[i * NDIM + k] += v;
37400
38014
  }
@@ -37423,9 +38037,9 @@ function updateArrays(st, i) {
37423
38037
  for (let k = 0; k < NDIM; k++) st.sumT[i * NDIM + k] = 0;
37424
38038
  for (let j = 0; j < n; j++) {
37425
38039
  if (i === j) continue;
37426
- const dist4 = distvec(vi.info.pos, st.nodes[j].info.pos, del);
38040
+ const dist5 = distvec(vi.info.pos, st.nodes[j].info.pos, del);
37427
38041
  for (let k = 0; k < NDIM; k++) {
37428
- const tij = st.spring[i * n + j] * (del[k] - st.dist[i * n + j] * del[k] / dist4);
38042
+ const tij = st.spring[i * n + j] * (del[k] - st.dist[i * n + j] * del[k] / dist5);
37429
38043
  st.t[(i * n + j) * NDIM + k] = tij;
37430
38044
  st.sumT[i * NDIM + k] += tij;
37431
38045
  const old = st.t[(j * n + i) * NDIM + k];
@@ -37492,7 +38106,7 @@ function moveNode(st, m) {
37492
38106
  function solveModel(g, st) {
37493
38107
  for (let m = chooseNode(st); m >= 0; m = chooseNode(st)) moveNode(st, m);
37494
38108
  if (st.move === st.maxIter) {
37495
- agerrLineOn("warn", `Max. iterations (${st.maxIter}) reached on graph ${g.name}`);
38109
+ agwarningf(`Max. iterations (${st.maxIter}) reached on graph ${g.name}`);
37496
38110
  }
37497
38111
  }
37498
38112
  function mdsEdges(g, nodes, lens) {
@@ -37505,84 +38119,852 @@ function kkNeato(g, nG, model) {
37505
38119
  if (nG < 2 || maxIter < 0) return;
37506
38120
  const { st, adj, ini, lens } = scanGraphMode(g, maxIter);
37507
38121
  shortestPath2(newPathState(st.n, st.dist, adj, ini));
37508
- if (model === MODEL_MDS2) mdsModel(st.dist, st.n, mdsEdges(g, st.nodes, lens));
38122
+ if (model === MODEL_MDS2) mdsModel2(st.dist, st.n, mdsEdges(g, st.nodes, lens));
37509
38123
  initialPositions2(g, st);
37510
38124
  diffeqModel(g, st);
37511
38125
  solveModel(g, st);
37512
38126
  }
37513
38127
 
37514
- // src/layout/neato/matrix-ops.ts
37515
- var fr = Math.fround;
37516
- function orthog1(n, vec) {
37517
- let sum = 0;
37518
- for (let i = 0; i < n; i++) sum += vec[i];
37519
- sum /= n;
37520
- for (let i = 0; i < n; i++) vec[i] = vec[i] - sum;
38128
+ // src/layout/neato/make-graph-data.ts
38129
+ var MODE_IPSEP2 = 3;
38130
+ var EDIST_IN = 1;
38131
+ var EDIST_OUT = -1;
38132
+ var EDIST_NONE = 0;
38133
+ function graphHasLen(g) {
38134
+ for (const e of g.edges) {
38135
+ if (e.attrs.has("len")) return true;
38136
+ }
38137
+ return false;
37521
38138
  }
37522
- function orthog1f(n, vec) {
37523
- let sum = fr(0);
37524
- for (let i = 0; i < n; i++) sum = fr(sum + vec[i]);
37525
- sum = fr(sum / n);
37526
- for (let i = 0; i < n; i++) vec[i] = vec[i] - sum;
38139
+ var edistsOf = (v) => v.edists;
38140
+ function reverseBackEdge(graph, i, e, mode) {
38141
+ const node = graph[i];
38142
+ const j = node.edges[e];
38143
+ edistsOf(node)[e] = mode === MODE_IPSEP2 ? EDIST_OUT : EDIST_IN;
38144
+ const target = graph[j];
38145
+ let f = 1;
38146
+ while (f < target.nedges && target.edges[f] !== i) f++;
38147
+ if (f >= target.nedges) throw new Error(`neato: edge ${i}-${j} has no reverse entry`);
38148
+ edistsOf(target)[f] = EDIST_OUT;
38149
+ }
38150
+ function dfsCycle(graph, start, st) {
38151
+ const { mode, mark, onstack } = st;
38152
+ const stack = [{ i: start, e: 1 }];
38153
+ mark[start] = 1;
38154
+ onstack[start] = 1;
38155
+ for (let frame = stack.at(-1); frame !== void 0; frame = stack.at(-1)) {
38156
+ const { i } = frame;
38157
+ const node = graph[i];
38158
+ if (frame.e >= node.nedges) {
38159
+ onstack[i] = 0;
38160
+ stack.pop();
38161
+ continue;
38162
+ }
38163
+ const e = frame.e++;
38164
+ if (edistsOf(node)[e] === EDIST_IN) continue;
38165
+ const j = node.edges[e];
38166
+ if (onstack[j]) {
38167
+ reverseBackEdge(graph, i, e, mode);
38168
+ } else if (!mark[j]) {
38169
+ mark[j] = 1;
38170
+ onstack[j] = 1;
38171
+ stack.push({ i: j, e: 1 });
38172
+ }
38173
+ }
37527
38174
  }
37528
- function rightMultWithVectorFF(m, n, vector, result) {
38175
+ function acyclic2(graph, nv, mode) {
38176
+ const st = { mode, mark: new Uint8Array(nv), onstack: new Uint8Array(nv) };
38177
+ for (let i = 0; i < nv; i++) {
38178
+ if (st.mark[i]) continue;
38179
+ dfsCycle(graph, i, st);
38180
+ }
38181
+ }
38182
+ function edgeDist2(dir, np, head) {
38183
+ if (dir !== void 0 && dir.startsWith("none")) return EDIST_NONE;
38184
+ return np === head ? EDIST_IN : EDIST_OUT;
38185
+ }
38186
+ function addNeighbours(g, np, entry, o) {
38187
+ const seen2 = /* @__PURE__ */ new Map();
38188
+ for (const ep of [...np.outEdges(g), ...np.inEdges(g)]) {
38189
+ if (ep.head === ep.tail) continue;
38190
+ const vp = ep.tail === np ? ep.head : ep.tail;
38191
+ const vid = vp.info.id;
38192
+ const dist5 = o.haveLen ? lateDouble(ep.attrs.get("len"), 1, 0) : 1;
38193
+ const idx = seen2.get(vid);
38194
+ if (idx !== void 0) {
38195
+ if (o.haveLen) entry.ewgts[idx] = Math.max(entry.ewgts[idx], dist5);
38196
+ continue;
38197
+ }
38198
+ seen2.set(vid, entry.nedges);
38199
+ entry.edges.push(vid);
38200
+ if (o.haveLen || o.haveDir) entry.ewgts.push(dist5);
38201
+ if (o.haveDir) edistsOf(entry).push(edgeDist2(ep.attrs.get("dir"), np, ep.head));
38202
+ entry.nedges++;
38203
+ }
38204
+ }
38205
+ function makeGraphDataC(g, nodeList, haveLen, haveDir, mode = -1) {
38206
+ const vtx = nodeList.map((_, i) => ({
38207
+ nedges: 1,
38208
+ edges: [i],
38209
+ ewgts: haveLen || haveDir ? [0] : [],
38210
+ ...haveDir ? { edists: [0] } : {}
38211
+ }));
38212
+ for (const np of nodeList) addNeighbours(g, np, vtx[np.info.id], { haveLen, haveDir });
38213
+ if (haveDir) acyclic2(vtx, nodeList.length, mode);
38214
+ return vtx;
38215
+ }
38216
+
38217
+ // src/layout/neato/kkutils.ts
38218
+ function compareKeys(a, b) {
38219
+ if (a < b) return -1;
38220
+ if (a > b) return 1;
38221
+ return 0;
38222
+ }
38223
+ function gvSortByPlace(place, ordering, first, count) {
38224
+ const slice = Array.from(ordering.subarray(first, first + count));
38225
+ gvQsort(slice, (x, y) => compareKeys(place[x], place[y]));
38226
+ for (let i = 0; i < count; i++) ordering[first + i] = slice[i];
38227
+ }
38228
+ function quicksortPlace(place, ordering, size) {
38229
+ gvSortByPlace(place, ordering, 0, size);
38230
+ }
38231
+ function quicksortPlacef(place, ordering, first, last) {
38232
+ if (first < last) {
38233
+ gvSortByPlace(place, ordering, first, last - first + 1);
38234
+ }
38235
+ }
38236
+ function computeApspDijkstra(graph, n) {
38237
+ const dij = [];
38238
+ for (let i = 0; i < n; i++) dij.push(new Int32Array(n));
38239
+ for (let i = 0; i < n; i++) ngdijkstra(i, graph, n, dij[i]);
38240
+ return dij;
38241
+ }
38242
+ function computeApspSimple(graph, n) {
38243
+ const dij = [];
38244
+ for (let i = 0; i < n; i++) dij.push(new Int32Array(n));
38245
+ for (let i = 0; i < n; i++) bfs(i, graph, n, dij[i]);
38246
+ return dij;
38247
+ }
38248
+ function computeApsp(graph, n) {
38249
+ return graph[0].ewgts.length > 0 ? computeApspDijkstra(graph, n) : computeApspSimple(graph, n);
38250
+ }
38251
+
38252
+ // src/layout/neato/quad-prog-solve.ts
38253
+ var fr2 = Math.fround;
38254
+ var TOLERANCE = fr2(0.01);
38255
+ var BOUND = 1e9;
38256
+ var BLOCK_EPSILON = 1e-9;
38257
+ var NO_SPLIT = -1;
38258
+ var BITS = new DataView(new ArrayBuffer(8));
38259
+ function oddNeighbour(s, awayFromZero) {
38260
+ BITS.setFloat64(0, s);
38261
+ const hi = BITS.getUint32(0);
38262
+ const lo = BITS.getUint32(4);
38263
+ if (awayFromZero) {
38264
+ BITS.setUint32(4, lo + 1);
38265
+ } else if (lo === 0) {
38266
+ BITS.setUint32(0, hi - 1);
38267
+ BITS.setUint32(4, 4294967295);
38268
+ } else {
38269
+ BITS.setUint32(4, lo - 1);
38270
+ }
38271
+ return BITS.getFloat64(0);
38272
+ }
38273
+ function fmaf(a, b, c) {
38274
+ const p = a * b;
38275
+ const s = p + c;
38276
+ const bv = s - p;
38277
+ const err = p - (s - bv) + (c - bv);
38278
+ if (err === 0 || !Number.isFinite(s)) return fr2(s);
38279
+ BITS.setFloat64(0, s);
38280
+ if ((BITS.getUint32(4) & 1) !== 0) return fr2(s);
38281
+ return fr2(oddNeighbour(s, err > 0 === s > 0));
38282
+ }
38283
+ function blockPlaceNumerator(blockDeg, desPlaceBlock, negLapTimesDesired, toBlockConnectivity, curPlace) {
38284
+ const t = fmaf(blockDeg, desPlaceBlock, negLapTimesDesired);
38285
+ return fmaf(toBlockConnectivity, curPlace, t);
38286
+ }
38287
+ function equals(a, b) {
38288
+ return Math.abs(fr2(a - b)) < TOLERANCE;
38289
+ }
38290
+ function fminf(a, b) {
38291
+ if (Number.isNaN(a)) return b;
38292
+ if (Number.isNaN(b)) return a;
38293
+ return a < b ? a : b;
38294
+ }
38295
+ function fmaxf(a, b) {
38296
+ if (Number.isNaN(a)) return b;
38297
+ if (Number.isNaN(b)) return a;
38298
+ return a > b ? a : b;
38299
+ }
38300
+ function unpackMatrix(packedMat, n) {
38301
+ const flat = new Float32Array(n * n);
38302
+ const mat = new Array(n);
38303
+ for (let i = 0; i < n; i++) mat[i] = flat.subarray(i * n, (i + 1) * n);
38304
+ for (let i = 0, k = 0; i < n; i++) {
38305
+ for (let j = i; j < n; j++, k++) {
38306
+ mat[j][i] = mat[i][j] = packedMat[k];
38307
+ }
38308
+ }
38309
+ return mat;
38310
+ }
38311
+ function ensureMonotonicOrderingWithGaps(place, n, ordering, levels, numLevels, levelsGap) {
38312
+ let lowerBound = fr2(-1e9);
38313
+ let level = -1;
38314
+ let maxInLevel = 0;
38315
+ for (let i = 0; i < n; i++) {
38316
+ if (i >= maxInLevel) {
38317
+ level++;
38318
+ maxInLevel = level === numLevels ? n : levels[level];
38319
+ lowerBound = i > 0 ? fr2(place[ordering[i - 1]] + levelsGap) : fr2(-1e9);
38320
+ quicksortPlacef(place, ordering, i, maxInLevel - 1);
38321
+ }
38322
+ const node = ordering[i];
38323
+ if (place[node] < lowerBound) place[node] = lowerBound;
38324
+ }
38325
+ }
38326
+ function computeNodeLevels(e) {
38327
+ const lev = new Int32Array(e.n);
38328
+ let level = -1;
38329
+ let maxInLevel = 0;
38330
+ for (let i = 0; i < e.n; i++) {
38331
+ if (i >= maxInLevel) {
38332
+ level++;
38333
+ maxInLevel = level === e.numLevels ? e.n : e.levels[level];
38334
+ }
38335
+ lev[e.ordering[i]] = level;
38336
+ }
38337
+ return lev;
38338
+ }
38339
+ function growBlock(c, left2, curPlace) {
38340
+ const { place, lev, levelsGap, e } = c;
38341
+ const gap = e.fArray4;
38342
+ let targetPlace = curPlace;
38343
+ gap[e.ordering[left2]] = 0;
38344
+ let right2;
38345
+ for (right2 = left2 + 1; right2 < e.n; right2++) {
38346
+ if (lev[right2] > lev[right2 - 1]) {
38347
+ targetPlace = fr2(targetPlace + levelsGap);
38348
+ }
38349
+ const node = e.ordering[right2];
38350
+ if (Math.abs(fr2(place[node] - targetPlace)) > BLOCK_EPSILON) break;
38351
+ gap[node] = fr2(place[node] - curPlace);
38352
+ }
38353
+ return right2;
38354
+ }
38355
+ function computeDesiredPlaces(c, left2, right2) {
38356
+ const { e, place, b } = c;
38357
+ for (let i = left2; i < right2; i++) {
38358
+ const node = e.ordering[i];
38359
+ let newPlaceI = -b[node];
38360
+ const lapNode = e.A[node];
38361
+ for (let j = 0; j < e.n; j++) {
38362
+ if (j === node) continue;
38363
+ newPlaceI = fmaf(lapNode[j], place[j], newPlaceI);
38364
+ }
38365
+ e.fArray1[node] = fr2(fr2(newPlaceI / -lapNode[node]) - e.fArray4[node]);
38366
+ }
38367
+ }
38368
+ function collectWhere(c, from, to, test) {
38369
+ for (let j = from; j < to; j++) {
38370
+ const node = c.e.ordering[j];
38371
+ if (test(c.e.fArray1[node])) c.block.push(node);
38372
+ }
38373
+ }
38374
+ function orderBlockByLevels(c, left2, right2, curPlace) {
38375
+ const { e } = c;
38376
+ c.block.length = 0;
38377
+ let firstNextLevel = 0;
38378
+ for (let i = left2; i < right2; i = firstNextLevel) {
38379
+ const level = c.lev[e.ordering[i]];
38380
+ firstNextLevel = level === e.numLevels ? right2 : Math.min(right2, e.levels[level]);
38381
+ collectWhere(c, i, firstNextLevel, (d) => d < curPlace);
38382
+ collectWhere(c, i, firstNextLevel, (d) => d === curPlace);
38383
+ collectWhere(c, i, firstNextLevel, (d) => d > curPlace);
38384
+ }
38385
+ }
38386
+ function computePrefixDesiredPlaces(c, curPlace) {
38387
+ const { e, block } = c;
38388
+ let desPlaceBlock = 0;
38389
+ let blockDeg = 0;
38390
+ for (let i = 0; i < block.length; i++) {
38391
+ const node = block[i];
38392
+ let toBlockConnectivity = 0;
38393
+ const lapNode = e.A[node];
38394
+ for (let j = 0; j < i; j++) {
38395
+ toBlockConnectivity = fr2(toBlockConnectivity - lapNode[block[j]]);
38396
+ }
38397
+ toBlockConnectivity = fr2(toBlockConnectivity * 2);
38398
+ const num2 = blockPlaceNumerator(
38399
+ blockDeg,
38400
+ desPlaceBlock,
38401
+ fr2(-lapNode[node] * e.fArray1[node]),
38402
+ toBlockConnectivity,
38403
+ curPlace
38404
+ );
38405
+ desPlaceBlock = fr2(num2 / fr2(fr2(blockDeg - lapNode[node]) + toBlockConnectivity));
38406
+ e.fArray2[i] = desPlaceBlock;
38407
+ blockDeg = fr2(blockDeg + fr2(toBlockConnectivity - lapNode[node]));
38408
+ }
38409
+ if (e.n >= 0 && block.length === e.n) {
38410
+ e.fArray2[e.n - 1] = curPlace;
38411
+ }
38412
+ }
38413
+ function computeSuffixDesiredPlaces(c, curPlace) {
38414
+ const { e, block } = c;
38415
+ let desPlaceBlock = 0;
38416
+ let blockDeg = 0;
38417
+ for (let i = block.length - 1; i >= 0; i--) {
38418
+ const node = block[i];
38419
+ let toBlockConnectivity = 0;
38420
+ const lapNode = e.A[node];
38421
+ for (let j = i + 1; j < block.length; j++) {
38422
+ toBlockConnectivity = fr2(toBlockConnectivity - lapNode[block[j]]);
38423
+ }
38424
+ toBlockConnectivity = fr2(toBlockConnectivity * 2);
38425
+ const num2 = blockPlaceNumerator(
38426
+ blockDeg,
38427
+ desPlaceBlock,
38428
+ fr2(-lapNode[node] * e.fArray1[node]),
38429
+ toBlockConnectivity,
38430
+ curPlace
38431
+ );
38432
+ desPlaceBlock = fr2(num2 / fr2(fr2(blockDeg - lapNode[node]) + toBlockConnectivity));
38433
+ e.fArray3[i] = desPlaceBlock;
38434
+ blockDeg = fr2(blockDeg + fr2(toBlockConnectivity - lapNode[node]));
38435
+ }
38436
+ if (e.n >= 0 && block.length === e.n) {
38437
+ e.fArray3[0] = curPlace;
38438
+ }
38439
+ }
38440
+ var LIMITED = new Float64Array(2);
38441
+ function limitMoves(prefix, suffix, curPlace) {
38442
+ if (suffix < prefix) {
38443
+ if (suffix < curPlace) {
38444
+ if (prefix > curPlace) prefix = curPlace;
38445
+ suffix = prefix;
38446
+ } else if (prefix > curPlace) {
38447
+ prefix = suffix;
38448
+ }
38449
+ }
38450
+ LIMITED[0] = prefix;
38451
+ LIMITED[1] = suffix;
38452
+ }
38453
+ function findBestSplit(c, curPlace) {
38454
+ const { e, block } = c;
38455
+ let bestI = NO_SPLIT;
38456
+ let maxMovement = 0;
38457
+ for (let i = 0; i < block.length; i++) {
38458
+ const suffixDesPlace = e.fArray3[i];
38459
+ const prefixDesPlace = i > 0 ? e.fArray2[i - 1] : suffixDesPlace;
38460
+ limitMoves(prefixDesPlace, suffixDesPlace, curPlace);
38461
+ const movement = (block.length - i) * Math.abs(fr2(LIMITED[1] - curPlace)) + i * Math.abs(fr2(LIMITED[0] - curPlace));
38462
+ if (movement > maxMovement) {
38463
+ maxMovement = movement;
38464
+ bestI = i;
38465
+ }
38466
+ }
38467
+ return bestI;
38468
+ }
38469
+ function computeUpperBound(c, right2) {
38470
+ const { e, place, lev, levelsGap, block } = c;
38471
+ if (right2 >= e.n) return BOUND;
38472
+ const lastGap = e.fArray4[block[block.length - 1]];
38473
+ const nextPlace = place[e.ordering[right2]];
38474
+ if (lev[e.ordering[right2]] > lev[e.ordering[right2 - 1]]) {
38475
+ return fr2(fr2(nextPlace - levelsGap) - lastGap);
38476
+ }
38477
+ return fr2(nextPlace - lastGap);
38478
+ }
38479
+ function nextLowerBound(c, right2) {
38480
+ const { e, place, lev, levelsGap, block } = c;
38481
+ const last = place[block[block.length - 1]];
38482
+ if (right2 < e.n && lev[e.ordering[right2]] > lev[e.ordering[right2 - 1]]) {
38483
+ return fr2(last + levelsGap);
38484
+ }
38485
+ return last;
38486
+ }
38487
+ function moveSplitBlock(c, bestI, left2, right2, curPlace) {
38488
+ const { e, place, block } = c;
38489
+ let suffixDesPlace = e.fArray3[bestI];
38490
+ let prefixDesPlace = bestI > 0 ? e.fArray2[bestI - 1] : suffixDesPlace;
38491
+ suffixDesPlace = fminf(suffixDesPlace, computeUpperBound(c, right2));
38492
+ prefixDesPlace = fmaxf(prefixDesPlace, c.lowerBound);
38493
+ limitMoves(prefixDesPlace, suffixDesPlace, curPlace);
38494
+ prefixDesPlace = LIMITED[0];
38495
+ suffixDesPlace = LIMITED[1];
38496
+ for (let i = 0; i < bestI; i++) {
38497
+ place[block[i]] = fr2(prefixDesPlace + e.fArray4[block[i]]);
38498
+ }
38499
+ for (let i = bestI; i < block.length; i++) {
38500
+ place[block[i]] = fr2(suffixDesPlace + e.fArray4[block[i]]);
38501
+ }
38502
+ c.lowerBound = nextLowerBound(c, right2);
38503
+ for (let i = left2; i < right2; i++) e.ordering[i] = block[i - left2];
38504
+ c.converged = c.converged && equals(prefixDesPlace, curPlace) && equals(suffixDesPlace, curPlace);
38505
+ }
38506
+ function processBlock(c, left2) {
38507
+ const curPlace = c.place[c.e.ordering[left2]];
38508
+ const right2 = growBlock(c, left2, curPlace);
38509
+ computeDesiredPlaces(c, left2, right2);
38510
+ orderBlockByLevels(c, left2, right2, curPlace);
38511
+ computePrefixDesiredPlaces(c, curPlace);
38512
+ computeSuffixDesiredPlaces(c, curPlace);
38513
+ const bestI = findBestSplit(c, curPlace);
38514
+ if (bestI !== NO_SPLIT) {
38515
+ moveSplitBlock(c, bestI, left2, right2, curPlace);
38516
+ } else {
38517
+ c.lowerBound = nextLowerBound(c, right2);
38518
+ }
38519
+ return right2;
38520
+ }
38521
+ function constrainedMajorizationNewWithGaps(e, b, coords, curAxis, maxIterations, levelsGap) {
38522
+ const place = coords[curAxis];
38523
+ if (maxIterations <= 0) return;
38524
+ const gap = fr2(levelsGap);
38525
+ ensureMonotonicOrderingWithGaps(place, e.n, e.ordering, e.levels, e.numLevels, gap);
38526
+ const c = {
38527
+ e,
38528
+ place,
38529
+ b,
38530
+ lev: computeNodeLevels(e),
38531
+ levelsGap: gap,
38532
+ block: [],
38533
+ lowerBound: fr2(-BOUND),
38534
+ converged: false
38535
+ };
38536
+ for (let counter = 0; counter < maxIterations && !c.converged; counter++) {
38537
+ c.converged = true;
38538
+ c.lowerBound = fr2(-BOUND);
38539
+ for (let left2 = 0, right2; left2 < e.n; left2 = right2) {
38540
+ right2 = processBlock(c, left2);
38541
+ }
38542
+ orthog1f(e.n, place);
38543
+ }
38544
+ }
38545
+ function initConstrainedMajorization(packedMat, n, ordering, levels, numLevels) {
38546
+ return {
38547
+ A: unpackMatrix(packedMat, n),
38548
+ n,
38549
+ fArray1: new Float32Array(n),
38550
+ fArray2: new Float32Array(n),
38551
+ fArray3: new Float32Array(n),
38552
+ fArray4: new Float32Array(n),
38553
+ ordering,
38554
+ levels,
38555
+ numLevels
38556
+ };
38557
+ }
38558
+
38559
+ // src/layout/neato/conjgrad-mkernel.ts
38560
+ var fr3 = Math.fround;
38561
+ var RIGHT_MULT_BLOCK = 16;
38562
+ var ZERO_LENGTH_MESSAGE = "conjugate_gradient: unexpected length 0 vector\n";
38563
+ function rightMultWithVectorFFFused(m, n, vector, result) {
37529
38564
  for (let i = 0; i < n; i++) result[i] = 0;
37530
38565
  let index = 0;
37531
38566
  for (let i = 0; i < n; i++) {
37532
38567
  const vi = vector[i];
37533
- let res = fr(m[index++] * vi);
38568
+ let res = fmaf(m[index++], vi, 0);
38569
+ const len = n - i - 1;
38570
+ const blockEnd = i + 1 + (len - len % RIGHT_MULT_BLOCK);
37534
38571
  for (let j = i + 1; j < n; j++, index++) {
37535
- res = fr(res + fr(m[index] * vector[j]));
37536
- result[j] = result[j] + fr(m[index] * vi);
38572
+ const mij = m[index];
38573
+ res = j < blockEnd ? fr3(res + fr3(mij * vector[j])) : fmaf(mij, vector[j], res);
38574
+ result[j] = fmaf(mij, vi, result[j]);
37537
38575
  }
37538
38576
  result[i] = result[i] + res;
37539
38577
  }
37540
38578
  }
37541
- function vectorsSubtractionF(n, v1, v2, result) {
37542
- for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
38579
+ function vectorsMultAdditionFused(n, v1, alpha, v2) {
38580
+ for (let i = 0; i < n; i++) v1[i] = fmaf(alpha, v2[i], v1[i]);
37543
38581
  }
37544
- function vectorsMultAdditionF(n, v1, alpha, v2) {
37545
- const a = fr(alpha);
37546
- for (let i = 0; i < n; i++) v1[i] = v1[i] + fr(a * v2[i]);
38582
+ var CgStep = { CONTINUE: 0, STOP: 1, ERROR: 2 };
38583
+ function initialState(A3, x, b, n) {
38584
+ const Ax = new Float32Array(n);
38585
+ const st = { n, r: new Float32Array(n), p: new Float32Array(n), Ap: new Float32Array(n), rR: 0 };
38586
+ orthog1f(n, x);
38587
+ orthog1f(n, b);
38588
+ rightMultWithVectorFFFused(A3, n, x, Ax);
38589
+ orthog1f(n, Ax);
38590
+ vectorsSubtractionF(n, b, Ax, st.r);
38591
+ copyVectorF(n, st.r, st.p);
38592
+ st.rR = vectorsInnerProductF(n, st.r, st.r);
38593
+ return st;
37547
38594
  }
37548
- function vectorsInnerProductF(n, v1, v2) {
37549
- let result = 0;
37550
- for (let i = 0; i < n; i++) result += fr(v1[i] * v2[i]);
37551
- return result;
38595
+ function cgIteration(A3, x, st, last) {
38596
+ const { n, r, p, Ap } = st;
38597
+ orthog1f(n, p);
38598
+ orthog1f(n, x);
38599
+ orthog1f(n, r);
38600
+ rightMultWithVectorFFFused(A3, n, p, Ap);
38601
+ orthog1f(n, Ap);
38602
+ const pAp = vectorsInnerProductF(n, p, Ap);
38603
+ if (pAp === 0) return CgStep.STOP;
38604
+ const alpha = st.rR / pAp;
38605
+ vectorsMultAdditionFused(n, x, fr3(alpha), p);
38606
+ if (last) return CgStep.CONTINUE;
38607
+ vectorsMultAdditionFused(n, r, fr3(-alpha), Ap);
38608
+ const rRNew = vectorsInnerProductF(n, r, r);
38609
+ if (st.rR === 0) {
38610
+ agerrorf(ZERO_LENGTH_MESSAGE);
38611
+ return CgStep.ERROR;
38612
+ }
38613
+ const beta = fr3(rRNew / st.rR);
38614
+ st.rR = rRNew;
38615
+ for (let j = 0; j < n; j++) p[j] = fmaf(beta, p[j], r[j]);
38616
+ return CgStep.CONTINUE;
38617
+ }
38618
+ function conjugateGradientMkernelFused(A3, x, b, n, o) {
38619
+ const st = initialState(A3, x, b, n);
38620
+ for (let i = 0; i < o.maxIterations && maxAbsF(n, st.r) > o.tol; i++) {
38621
+ const step = cgIteration(A3, x, st, i >= o.maxIterations - 1);
38622
+ if (step === CgStep.STOP) break;
38623
+ if (step === CgStep.ERROR) return 1;
38624
+ }
38625
+ return 0;
37552
38626
  }
37553
- function copyVectorF(n, src, dst) {
37554
- for (let i = 0; i < n; i++) dst[i] = src[i];
38627
+
38628
+ // src/layout/neato/opt-arrangement.ts
38629
+ var HIERARCHY_CG_TOL = 1e-3;
38630
+ function constructB(graph, n, b) {
38631
+ for (let i = 0; i < n; i++) {
38632
+ if (graph[0].edists == null) continue;
38633
+ let bI = 0;
38634
+ const node = graph[i];
38635
+ for (let j = 1; j < node.nedges; j++) {
38636
+ bI += Math.fround(Math.fround(node.ewgts[j]) * node.edists[j]);
38637
+ }
38638
+ b[i] = bI;
38639
+ }
37555
38640
  }
37556
- function maxAbsF(n, vec) {
37557
- let max = fr(-1e30);
38641
+ function setUniformWeights(graph, n) {
38642
+ const old = [];
37558
38643
  for (let i = 0; i < n; i++) {
37559
- const a = fr(Math.abs(vec[i]));
37560
- if (a > max) max = a;
38644
+ const node = graph[i];
38645
+ old.push(node.ewgts);
38646
+ const weights = new Array(node.nedges).fill(1);
38647
+ weights[0] = -(node.nedges - 1);
38648
+ node.ewgts = weights;
37561
38649
  }
37562
- return max;
38650
+ return old;
37563
38651
  }
37564
- function squareVec(n, vec) {
37565
- for (let i = 0; i < n; i++) vec[i] = vec[i] * vec[i];
38652
+ function computeYCoords(graph, n, yCoords, maxIterations) {
38653
+ let rv = 0;
38654
+ const b = new Float64Array(n);
38655
+ constructB(graph, n, b);
38656
+ initVecOrth1(n, yCoords);
38657
+ const oldEwgts = setUniformWeights(graph, n);
38658
+ if (conjugateGradient(graph, yCoords, b, n, HIERARCHY_CG_TOL, maxIterations) < 0) {
38659
+ rv = 1;
38660
+ }
38661
+ for (let i = 0; i < n; i++) graph[i].ewgts = oldEwgts[i];
38662
+ return rv;
37566
38663
  }
37567
- function invertVec(n, vec) {
38664
+
38665
+ // src/layout/neato/compute-hierarchy.ts
38666
+ function countLevels(y, ordering, n, tol) {
38667
+ let numLevels = 0;
38668
+ for (let i = 1; i < n; i++) {
38669
+ if (y[ordering[i]] - y[ordering[i - 1]] > tol) numLevels++;
38670
+ }
38671
+ return numLevels;
38672
+ }
38673
+ function fillLevels(y, ordering, n, tol, numLevels) {
38674
+ if (numLevels === 0) {
38675
+ const levels2 = new Int32Array(1);
38676
+ levels2[0] = n;
38677
+ return levels2;
38678
+ }
38679
+ const levels = new Int32Array(numLevels);
38680
+ let count = 0;
38681
+ for (let i = 1; i < n; i++) {
38682
+ if (y[ordering[i]] - y[ordering[i - 1]] > tol) levels[count++] = i;
38683
+ }
38684
+ return levels;
38685
+ }
38686
+ function computeHierarchy(graph, n, absTol, relTol, given) {
38687
+ let y;
38688
+ if (given) {
38689
+ y = given;
38690
+ } else {
38691
+ y = new Float64Array(n);
38692
+ if (computeYCoords(graph, n, y, n)) return null;
38693
+ }
38694
+ const ordering = new Int32Array(n);
38695
+ for (let i = 0; i < n; i++) ordering[i] = i;
38696
+ quicksortPlace(y, ordering, n);
38697
+ const hierarchySpan = y[ordering[n - 1]] - y[ordering[0]];
38698
+ const relative = relTol * hierarchySpan / (n - 1);
38699
+ const tol = absTol > relative ? absTol : relative;
38700
+ const numLevels = countLevels(y, ordering, n, tol);
38701
+ return { ordering, levels: fillLevels(y, ordering, n, tol, numLevels), numLevels };
38702
+ }
38703
+
38704
+ // src/layout/neato/smart-ini-x.ts
38705
+ var fr4 = Math.fround;
38706
+ var SCALE_FACTOR = 256;
38707
+ var DBL_EPSILON = 2220446049250313e-31;
38708
+ var POWER_LENGTH_FLOOR = 1e-10;
38709
+ var BLOCK_STANDARDIZE_NORM = 4;
38710
+ var BLOCK_MAT_MULT_ROW = 4;
38711
+ var BLOCK_MAT_MULT_ORTHOG = 8;
38712
+ var BLOCK_GUESS_ORTHOG = 8;
38713
+ var BLOCK_GUESS_LEN = BLOCK_NONE;
38714
+ var BLOCK_LOOP_LEN = BLOCK_NONE;
38715
+ var BLOCK_ANGLE = 8;
38716
+ var BLOCK_UNIFORM_SUMS = 4;
38717
+ var BLOCK_AVGS = 4;
38718
+ function standardize(orthog, nvtxs) {
38719
+ let avg = 0;
38720
+ for (let i = 0; i < nvtxs; i++) avg += orthog[i];
38721
+ avg /= nvtxs;
38722
+ for (let i = 0; i < nvtxs; i++) orthog[i] = orthog[i] - avg;
38723
+ const len = norm(orthog, nvtxs - 1, BLOCK_STANDARDIZE_NORM);
38724
+ if (Math.abs(len) < DBL_EPSILON) return;
38725
+ vectorsScalarMult(nvtxs, orthog, 1 / len, orthog);
38726
+ }
38727
+ function matMultVecOrthog(mat, dim, vec, result, orthog) {
38728
+ const blocked = dim - dim % BLOCK_MAT_MULT_ROW;
38729
+ for (let i = 0; i < dim; i++) {
38730
+ const row = mat[i];
38731
+ let sum = 0;
38732
+ let j = 0;
38733
+ for (; j < blocked; j++) sum += row[j] * vec[j];
38734
+ for (; j < dim; j++) sum = fma2(row[j], vec[j], sum);
38735
+ result[i] = sum;
38736
+ }
38737
+ const alpha = -innerProduct(dim, result, orthog, BLOCK_MAT_MULT_ORTHOG);
38738
+ scadd(result, dim - 1, alpha, orthog);
38739
+ }
38740
+ function orthogonalizeAgainstEigs(p, vec, count, block) {
38741
+ for (let j = 0; j < count; j++) {
38742
+ const alpha = -innerProduct(p.n, p.eigs[j], vec, block);
38743
+ scadd(vec, p.n - 1, alpha, p.eigs[j]);
38744
+ }
38745
+ }
38746
+ function chooseStartVector(p, i) {
38747
+ const curr = p.eigs[i];
38748
+ for (; ; ) {
38749
+ for (let j = 0; j < p.n; j++) curr[j] = crand() % 100;
38750
+ const alpha = -innerProduct(p.n, p.orthog, curr, BLOCK_GUESS_ORTHOG);
38751
+ scadd(curr, p.n - 1, alpha, p.orthog);
38752
+ orthogonalizeAgainstEigs(p, curr, i, BLOCK_NONE);
38753
+ const len = norm(curr, p.n - 1, BLOCK_GUESS_LEN);
38754
+ if (len < POWER_LENGTH_FLOOR) continue;
38755
+ vectorsScalarMult(p.n, curr, 1 / len, curr);
38756
+ return;
38757
+ }
38758
+ }
38759
+ function iterateEigenvector(p, i, tol, work) {
38760
+ const curr = p.eigs[i];
38761
+ for (; ; ) {
38762
+ copyVector(p.n, curr, work.last);
38763
+ matMultVecOrthog(p.mat, p.n, curr, work.tmp, p.orthog);
38764
+ copyVector(p.n, work.tmp, curr);
38765
+ orthogonalizeAgainstEigs(p, curr, i, BLOCK_NONE);
38766
+ const len = norm(curr, p.n - 1, BLOCK_LOOP_LEN);
38767
+ if (len < POWER_LENGTH_FLOOR) {
38768
+ return { nullSpace: true, eval: 0 };
38769
+ }
38770
+ vectorsScalarMult(p.n, curr, 1 / len, curr);
38771
+ const angle = innerProduct(p.n, curr, work.last, BLOCK_ANGLE);
38772
+ if (!(Math.abs(angle) < tol)) {
38773
+ return { nullSpace: false, eval: angle * len };
38774
+ }
38775
+ }
38776
+ }
38777
+ function fillNullSpaceEigenvectors(p, from, neigs) {
38778
+ for (let i = from; i < neigs; i++) {
38779
+ const curr = p.eigs[i];
38780
+ for (let j = 0; j < p.n; j++) curr[j] = crand() % 100;
38781
+ orthogonalizeAgainstEigs(p, curr, i, BLOCK_NONE);
38782
+ const len = norm(curr, p.n - 1, BLOCK_NONE);
38783
+ vectorsScalarMult(p.n, curr, 1 / len, curr);
38784
+ p.evals[i] = 0;
38785
+ }
38786
+ }
38787
+ function sortEigenvectors(p, neigs, tmp) {
38788
+ for (let i = 0; i < neigs - 1; i++) {
38789
+ let largestIndex = i;
38790
+ let largestEval = p.evals[largestIndex];
38791
+ for (let j = i + 1; j < neigs; j++) {
38792
+ if (largestEval < p.evals[j]) {
38793
+ largestIndex = j;
38794
+ largestEval = p.evals[largestIndex];
38795
+ }
38796
+ }
38797
+ if (largestIndex !== i) {
38798
+ copyVector(p.n, p.eigs[i], tmp);
38799
+ copyVector(p.n, p.eigs[largestIndex], p.eigs[i]);
38800
+ copyVector(p.n, tmp, p.eigs[largestIndex]);
38801
+ p.evals[largestIndex] = p.evals[i];
38802
+ p.evals[i] = largestEval;
38803
+ }
38804
+ }
38805
+ }
38806
+ function powerIterationOrthog(p, neigsIn, pIterationThreshold) {
38807
+ const work = { tmp: new Float64Array(p.n), last: new Float64Array(p.n) };
38808
+ const tol = 1 - pIterationThreshold;
38809
+ const neigs = neigsIn >= p.n ? p.n : neigsIn;
38810
+ let i = 0;
38811
+ for (; i < neigs; i++) {
38812
+ chooseStartVector(p, i);
38813
+ const res = iterateEigenvector(p, i, tol, work);
38814
+ if (res.nullSpace) break;
38815
+ p.evals[i] = res.eval;
38816
+ }
38817
+ fillNullSpaceEigenvectors(p, i, neigs);
38818
+ sortEigenvectors(p, neigs, work.tmp);
38819
+ }
38820
+ function computeAvgs(Dij, n) {
38821
+ const rowAvg = new Float32Array(n);
38822
+ let sum = 0;
38823
+ const blocked = n - n % BLOCK_AVGS;
37568
38824
  for (let i = 0; i < n; i++) {
37569
- if (vec[i] !== 0) vec[i] = 1 / vec[i];
38825
+ let sumRow = 0;
38826
+ const row = Dij[i];
38827
+ let j = 0;
38828
+ for (; j < blocked; j++) {
38829
+ sum += row[j] * row[j];
38830
+ sumRow += row[j] * row[j];
38831
+ }
38832
+ for (; j < n; j++) {
38833
+ sum = fma2(row[j], row[j], sum);
38834
+ sumRow = fma2(row[j], row[j], sumRow);
38835
+ }
38836
+ rowAvg[i] = fr4(fr4(sumRow) / n);
37570
38837
  }
38838
+ return { rowAvg, allAvg: fr4(fr4(sum) / (n * n)) };
37571
38839
  }
37572
- function sqrtVecF(n, source, target) {
38840
+ function computeBij(Dij, n) {
38841
+ const Bij = [];
38842
+ for (let i = 0; i < n; i++) Bij.push(new Float32Array(n));
38843
+ const { rowAvg, allAvg } = computeAvgs(Dij, n);
37573
38844
  for (let i = 0; i < n; i++) {
37574
- if (source[i] >= 0) target[i] = fr(Math.sqrt(source[i]));
38845
+ for (let j = 0; j <= i; j++) {
38846
+ const fD = fr4(Dij[i][j]);
38847
+ const t = fr4(fma2(-fD, fD, rowAvg[i]));
38848
+ Bij[i][j] = fr4(fr4(t + rowAvg[j]) - allAvg);
38849
+ Bij[j][i] = Bij[i][j];
38850
+ }
38851
+ }
38852
+ return Bij;
38853
+ }
38854
+ function cmdsOrthog(n, dim, eigs, tol, input) {
38855
+ const { orthog, Dij } = input;
38856
+ const Bij = computeBij(Dij, n);
38857
+ const evals = new Float64Array(dim);
38858
+ const orthogAux = Float64Array.from(orthog.subarray(0, n));
38859
+ standardize(orthogAux, n);
38860
+ powerIterationOrthog({ mat: Bij, n, eigs, evals, orthog: orthogAux }, dim, tol);
38861
+ for (let i = 0; i < dim; i++) {
38862
+ for (let j = 0; j < n; j++) eigs[i][j] = eigs[i][j] * Math.sqrt(Math.abs(evals[i]));
37575
38863
  }
37576
38864
  }
37577
- function invertSqrtVec(n, vec) {
38865
+ function scaleGivenCoords(Dij, n, x) {
38866
+ let sum1 = 0;
38867
+ let sum2 = 0;
38868
+ for (let i = 1; i < n; i++) {
38869
+ const blocked = i - i % BLOCK_UNIFORM_SUMS;
38870
+ for (let j = 0; j < i; j++) {
38871
+ const d = Dij[i][j];
38872
+ const f = Math.abs(x[i] - x[j]);
38873
+ const t1 = 1 / d;
38874
+ const t2 = 1 / Math.imul(d, d) * f;
38875
+ if (j < blocked) {
38876
+ sum1 += t1 * f;
38877
+ sum2 += t2 * f;
38878
+ } else {
38879
+ sum1 = fma2(t1, f, sum1);
38880
+ sum2 = fma2(t2, f, sum2);
38881
+ }
38882
+ }
38883
+ }
38884
+ const uniLength = Math.abs(sum2) === Infinity ? 0 : sum1 / sum2;
38885
+ for (let i = 0; i < n; i++) x[i] = x[i] * uniLength;
38886
+ return uniLength;
38887
+ }
38888
+ function computeLaplacian(Dij, n) {
38889
+ const lap = [];
37578
38890
  for (let i = 0; i < n; i++) {
37579
- if (vec[i] > 0) vec[i] = 1 / fr(Math.sqrt(vec[i]));
38891
+ const row = new Float32Array(n);
38892
+ let degree = fr4(0);
38893
+ for (let j = 0; j < n; j++) {
38894
+ if (j === i) continue;
38895
+ const w = fr4(fr4(-1) / fr4(fr4(Dij[i][j]) * fr4(Dij[i][j])));
38896
+ row[j] = w;
38897
+ degree = fr4(degree - w);
38898
+ }
38899
+ row[i] = degree;
38900
+ lap.push(row);
38901
+ }
38902
+ return lap;
38903
+ }
38904
+ function computeResidualDistances(Dij, n, x) {
38905
+ for (let i = 1; i < n; i++) {
38906
+ const posI = x[i];
38907
+ for (let j = 0; j < i; j++) {
38908
+ const t = posI - x[j];
38909
+ const d = Dij[i][j];
38910
+ const diff = fma2(d, d, -(t * t));
38911
+ const v = diff > 0 ? Math.sqrt(diff) : 0;
38912
+ Dij[i][j] = v;
38913
+ Dij[j][i] = v;
38914
+ }
37580
38915
  }
37581
38916
  }
38917
+ function balanceOf(i, n, y, ctx) {
38918
+ const posI = y[i];
38919
+ let b = 0;
38920
+ for (let j = 0; j < n; j++) {
38921
+ if (j === i) continue;
38922
+ const term = fr4(fr4(ctx.Dij[i][j]) * -ctx.lap[i][j]);
38923
+ if (posI >= y[j]) b += term;
38924
+ else b -= term;
38925
+ }
38926
+ return b;
38927
+ }
38928
+ function solveBalanced(ctx, n, y, balance, convTol) {
38929
+ let converged = false;
38930
+ for (let iterations2 = 0; iterations2 < 200 && !converged; iterations2++) {
38931
+ if (conjugateGradientF(ctx.lap, y, balance, n, { tol: convTol, maxIterations: n, ortho1: true }) < 0) return 1;
38932
+ converged = true;
38933
+ for (let i = 0; i < n; i++) {
38934
+ const b = balanceOf(i, n, y, ctx);
38935
+ if (b !== balance[i] && Math.abs(1 - b / balance[i]) > 1e-5) {
38936
+ converged = false;
38937
+ balance[i] = b;
38938
+ }
38939
+ }
38940
+ }
38941
+ return 0;
38942
+ }
38943
+ function imdsGivenDim(graph, n, givenCoords, newCoords, conjTol) {
38944
+ const x = givenCoords;
38945
+ const y = newCoords;
38946
+ const Dij = computeApsp(graph, n);
38947
+ for (let i = 0; i < n; i++) {
38948
+ for (let j = 0; j < n; j++) Dij[i][j] = Dij[i][j] * SCALE_FACTOR;
38949
+ }
38950
+ const uniLength = scaleGivenCoords(Dij, n, x);
38951
+ cmdsOrthog(n, 1, [y], conjTol, { orthog: x, Dij });
38952
+ const lap = computeLaplacian(Dij, n);
38953
+ computeResidualDistances(Dij, n, x);
38954
+ const ctx = { Dij, lap };
38955
+ const balance = new Float64Array(n);
38956
+ for (let i = 0; i < n; i++) balance[i] = balanceOf(i, n, y, ctx);
38957
+ if (solveBalanced(ctx, n, y, balance, conjTol) === 1) return 1;
38958
+ for (let i = 0; !(Math.abs(uniLength) < DBL_EPSILON) && i < n; i++) {
38959
+ x[i] = x[i] / uniLength;
38960
+ y[i] = y[i] / uniLength;
38961
+ }
38962
+ return 0;
38963
+ }
37582
38964
 
37583
38965
  // src/layout/neato/stress-kernel.ts
37584
- var fr2 = Math.fround;
37585
- var TOLERANCE_CG = 1e-3;
38966
+ var fr5 = Math.fround;
38967
+ var TOLERANCE_CG2 = 1e-3;
37586
38968
  var OPT_EXP_FLAG = 2;
37587
38969
  function computeApspPacked2(graph, n) {
37588
38970
  const Dij = new Float32Array(n * (n + 1) / 2);
@@ -37642,9 +39024,9 @@ function cgStep(st, last) {
37642
39024
  vectorsMultAdditionF(n, st.r, -alpha, st.Ap);
37643
39025
  const rRNew = vectorsInnerProductF(n, st.r, st.r);
37644
39026
  if (st.rR === 0) return false;
37645
- const betaF = fr2(rRNew / st.rR);
39027
+ const betaF = fr5(rRNew / st.rR);
37646
39028
  st.rR = rRNew;
37647
- for (let j = 0; j < n; j++) st.p[j] = fr2(betaF * st.p[j]) + st.r[j];
39029
+ for (let j = 0; j < n; j++) st.p[j] = fr5(betaF * st.p[j]) + st.r[j];
37648
39030
  }
37649
39031
  return true;
37650
39032
  }
@@ -37706,8 +39088,8 @@ function buildLap1(lap1, lap2, coords, shape) {
37706
39088
  for (let k = 0; k < dim; k++) {
37707
39089
  const ck = coords[k];
37708
39090
  for (let x = 0; x < len; x++) {
37709
- const tmp = fr2(ck[i] + fr2(-1 * ck[i + 1 + x]));
37710
- distAccumulator[x] = distAccumulator[x] + fr2(tmp * tmp);
39091
+ const tmp = fr5(ck[i] + fr5(-1 * ck[i + 1 + x]));
39092
+ distAccumulator[x] = distAccumulator[x] + fr5(tmp * tmp);
37711
39093
  }
37712
39094
  }
37713
39095
  invertSqrtVec(len, distAccumulator);
@@ -37719,7 +39101,7 @@ function buildLap1(lap1, lap2, coords, shape) {
37719
39101
  let degree = 0;
37720
39102
  if (exp === 2) {
37721
39103
  for (let j = 0; j < len; j++, count++) {
37722
- const val2 = lap1[count] = fr2(lap1[count] * distAccumulator[j]);
39104
+ const val2 = lap1[count] = fr5(lap1[count] * distAccumulator[j]);
37723
39105
  degree += val2;
37724
39106
  degrees[i + j + 1] = degrees[i + j + 1] - val2;
37725
39107
  }
@@ -37753,10 +39135,10 @@ function computeStress(st) {
37753
39135
  }
37754
39136
  function solveAxis(st, k, havePinned, nodes) {
37755
39137
  if (!havePinned) {
37756
- return conjugateGradientMkernel2(st.lap2, st.coords[k], st.b[k], st.n, TOLERANCE_CG, st.n);
39138
+ return conjugateGradientMkernel2(st.lap2, st.coords[k], st.b[k], st.n, TOLERANCE_CG2, st.n);
37757
39139
  }
37758
39140
  copyVectorF(st.n, st.coords[k], st.tmpCoords);
37759
- const rc = conjugateGradientMkernel2(st.lap2, st.tmpCoords, st.b[k], st.n, TOLERANCE_CG, st.n);
39141
+ const rc = conjugateGradientMkernel2(st.lap2, st.tmpCoords, st.b[k], st.n, TOLERANCE_CG2, st.n);
37760
39142
  if (rc < 0) return rc;
37761
39143
  for (let i = 0; i < st.n; i++) {
37762
39144
  if (!isFixed(nodes[i])) st.coords[k][i] = st.tmpCoords[i];
@@ -37772,10 +39154,10 @@ function stressMajorizationKDMkernel(Dij, n, dCoords, nodes, o) {
37772
39154
  const coords = [];
37773
39155
  for (let i = 0; i < dim; i++) {
37774
39156
  const c = new Float32Array(n);
37775
- for (let j = 0; j < n; j++) c[j] = fr2(dCoords[i][j]);
39157
+ for (let j = 0; j < n; j++) c[j] = fr5(dCoords[i][j]);
37776
39158
  coords.push(c);
37777
39159
  }
37778
- const constantTerm = fr2(n * (n - 1) / 2);
39160
+ const constantTerm = fr5(n * (n - 1) / 2);
37779
39161
  const lap2 = Dij;
37780
39162
  buildLap2(lap2, n, exp);
37781
39163
  const lapLength = n * (n + 1) / 2;
@@ -37810,6 +39192,261 @@ function stressMajorizationKDMkernel(Dij, n, dCoords, nodes, o) {
37810
39192
  return iterations;
37811
39193
  }
37812
39194
 
39195
+ // src/layout/neato/constrained-majorization.ts
39196
+ var fr6 = Math.fround;
39197
+ var LOCAL_CONSTR_MAJOR_ITERATIONS = 15;
39198
+ var LEVELS_SEP_TOL = 0.1;
39199
+ var ABS_TOL = 0.01;
39200
+ var SUBSPACE_ITERATIONS = 15;
39201
+ var FLT_MAX3 = 34028234663852886e22;
39202
+ var DBL_MAX = Number.MAX_VALUE;
39203
+ var MIN_LEVELS = 1;
39204
+ var Y_AXIS = 1;
39205
+ function unsupported2(what) {
39206
+ throw new RenderError(`hierarchical stress majorization: ${what} is not supported yet`, "UNSUPPORTED_FEATURE");
39207
+ }
39208
+ function modelDistances(graph, n, model) {
39209
+ if (model === MODEL_SUBSET) unsupported2("the subset distance model");
39210
+ if (model === MODEL_CIRCUIT) unsupported2("the circuit distance model");
39211
+ return model === MODEL_MDS2 ? mdsModel(graph, n) : null;
39212
+ }
39213
+ function unconstrainedMajorization(graph, n, dCoords, nodes, o) {
39214
+ if (o.maxi < 0) return 0;
39215
+ const weighted = (graph[0]?.ewgts.length ?? 0) > 0;
39216
+ const Dij = modelDistances(graph, n, o.model) ?? (weighted ? computeWeightedApspPacked2(graph, n) : computeApspPacked2(graph, n));
39217
+ if ((o.opts & OPT_SMART_INIT) !== 0 && n > 1) unsupported2("the smart initial layout");
39218
+ return stressMajorizationKDMkernel(Dij, n, dCoords, nodes, {
39219
+ dim: o.dim,
39220
+ opts: o.opts,
39221
+ maxi: o.maxi,
39222
+ epsilon: o.epsilon
39223
+ });
39224
+ }
39225
+ function hasDirectionality(graph, n) {
39226
+ if (!graph[0]?.edists) return false;
39227
+ let directionalityExist = false;
39228
+ for (let i = 0; i < n; i++) {
39229
+ const edists = graph[i].edists;
39230
+ for (let j = 1; j < graph[i].nedges; j++) {
39231
+ directionalityExist ||= edists[j] !== 0;
39232
+ }
39233
+ }
39234
+ return directionalityExist;
39235
+ }
39236
+ function separateLevels(y, h, n, levelsGap) {
39237
+ const { ordering, levels, numLevels } = h;
39238
+ let displacement = 0;
39239
+ for (let i = 0; i < numLevels; i++) {
39240
+ const shortfall = levelsGap - (y[ordering[levels[i]]] + displacement - y[ordering[levels[i] - 1]]);
39241
+ displacement += 0 > shortfall ? 0 : shortfall;
39242
+ const stop = i < numLevels - 1 ? levels[i + 1] : n;
39243
+ for (let j = levels[i]; j < stop; j++) y[ordering[j]] += displacement;
39244
+ }
39245
+ }
39246
+ function smartInitLayers(graph, n, dCoords, nodes, o) {
39247
+ const { dim } = o;
39248
+ if (dim > 2) {
39249
+ const sub = { dim: dim - 1, opts: o.opts, model: o.model, maxi: SUBSPACE_ITERATIONS, epsilon: o.epsilon };
39250
+ if (unconstrainedMajorization(graph, n, dCoords.slice(1), nodes, sub) < 0) return -1;
39251
+ dCoords[dim - 1].set(dCoords[1].subarray(0, n));
39252
+ }
39253
+ const x = dCoords[0];
39254
+ const y = dCoords[1];
39255
+ if (computeYCoords(graph, n, y, n)) return -1;
39256
+ const h = computeHierarchy(graph, n, ABS_TOL, LEVELS_SEP_TOL, y);
39257
+ if (h === null) return -1;
39258
+ if (h.numLevels < MIN_LEVELS) {
39259
+ return unconstrainedMajorization(graph, n, dCoords, nodes, o);
39260
+ }
39261
+ if (o.levelsGap > 0) separateLevels(y, h, n, o.levelsGap);
39262
+ if (dim === 2 && imdsGivenDim(graph, n, y, x, o.epsilon)) return -1;
39263
+ return h;
39264
+ }
39265
+ function plainInitLayers(graph, n, dCoords, nodes, dim) {
39266
+ initLayout(n, dim, dCoords, nodes);
39267
+ const h = computeHierarchy(graph, n, ABS_TOL, LEVELS_SEP_TOL, null);
39268
+ return h === null ? -1 : h;
39269
+ }
39270
+ function distanceKD(coords, dim, i, j) {
39271
+ let sum = 0;
39272
+ for (let k = 0; k < dim; k++) {
39273
+ const d = coords[k][i] - coords[k][j];
39274
+ sum = fma2(d, d, sum);
39275
+ }
39276
+ return Math.sqrt(sum);
39277
+ }
39278
+ function scaleDownLayout(dCoords, n, dim) {
39279
+ let max = 1;
39280
+ for (let i = 0; i < dim; i++) {
39281
+ for (let j = 0; j < n; j++) {
39282
+ const a = Math.abs(dCoords[i][j]);
39283
+ if (a > max) max = a;
39284
+ }
39285
+ }
39286
+ for (let i = 0; i < dim; i++) {
39287
+ for (let j = 0; j < n; j++) dCoords[i][j] *= 10 / max;
39288
+ }
39289
+ }
39290
+ function scaleDistances(Dij, dCoords, n, dim) {
39291
+ const length = n + Math.trunc(n * (n - 1) / 2);
39292
+ const sum1 = Math.trunc(n * (n - 1) / 2);
39293
+ let sum2 = 0;
39294
+ for (let count = 0, i = 0; i < n - 1; i++) {
39295
+ count++;
39296
+ for (let j = i + 1; j < n; j++, count++) {
39297
+ sum2 += distanceKD(dCoords, dim, i, j) / Dij[count];
39298
+ }
39299
+ }
39300
+ const scaleRatio = fr6(sum2 / sum1);
39301
+ for (let i = 0; i < length; i++) Dij[i] = Dij[i] * scaleRatio;
39302
+ }
39303
+ function centerLayout(dCoords, n, dim) {
39304
+ for (let i = 0; i < dim; i++) orthog1(n, dCoords[i]);
39305
+ const y0 = dCoords[Y_AXIS][0];
39306
+ for (let i = 0; i < n; i++) dCoords[Y_AXIS][i] -= y0;
39307
+ }
39308
+ function negatedDegrees(lap2, n) {
39309
+ const degrees = new Float64Array(n);
39310
+ for (let i = 0, count = 0; i < n - 1; i++) {
39311
+ let degree = 0;
39312
+ count++;
39313
+ for (let j = 1; j < n - i; j++, count++) {
39314
+ const val2 = lap2[count];
39315
+ degree += val2;
39316
+ degrees[i + j] -= val2;
39317
+ }
39318
+ degrees[i] -= degree;
39319
+ }
39320
+ return degrees;
39321
+ }
39322
+ function buildLap22(lap2, n) {
39323
+ const lapLength = n + Math.trunc(n * (n - 1) / 2);
39324
+ squareVec(lapLength, lap2);
39325
+ invertVec(lapLength, lap2);
39326
+ const degrees = negatedDegrees(lap2, n);
39327
+ for (let step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
39328
+ lap2[count] = degrees[i];
39329
+ }
39330
+ }
39331
+ function inverseDistances(st, i, len) {
39332
+ const { coords, tmpCoords, distAccumulator } = st;
39333
+ distAccumulator.fill(0, 0, st.n);
39334
+ for (let k = 0; k < st.dim; k++) {
39335
+ const ck = coords[k];
39336
+ for (let j = 0; j < len; j++) tmpCoords[j] = ck[i] - ck[i + 1 + j];
39337
+ for (let j = 0; j < len; j++) tmpCoords[j] = tmpCoords[j] * tmpCoords[j];
39338
+ for (let j = 0; j < len; j++) distAccumulator[j] = tmpCoords[j] + distAccumulator[j];
39339
+ }
39340
+ invertSqrtVec(len, distAccumulator);
39341
+ for (let j = 0; j < len; j++) {
39342
+ if (distAccumulator[j] >= FLT_MAX3 || distAccumulator[j] < 0) distAccumulator[j] = 0;
39343
+ }
39344
+ }
39345
+ function buildLap12(st) {
39346
+ const { n, lap1, lap2, degrees, distAccumulator } = st;
39347
+ degrees.fill(0);
39348
+ sqrtVecF(n + Math.trunc(n * (n - 1) / 2), lap2, lap1);
39349
+ let count = 0;
39350
+ for (let i = 0; i < n - 1; i++) {
39351
+ const len = n - i - 1;
39352
+ inverseDistances(st, i, len);
39353
+ count++;
39354
+ let degree = 0;
39355
+ for (let j = 0; j < len; j++, count++) {
39356
+ const val2 = fr6(lap1[count] * distAccumulator[j]);
39357
+ lap1[count] = val2;
39358
+ degree += val2;
39359
+ degrees[i + j + 1] -= val2;
39360
+ }
39361
+ degrees[i] -= degree;
39362
+ }
39363
+ for (let step = n, count2 = 0, i = 0; i < n; i++, count2 += step, step--) {
39364
+ lap1[count2] = degrees[i];
39365
+ }
39366
+ }
39367
+ function computeNewStress(st, constantTerm) {
39368
+ const { n, dim, lap1, lap2, coords, b, tmpCoords } = st;
39369
+ for (let k = 0; k < dim; k++) rightMultWithVectorFFFused(lap1, n, coords[k], b[k]);
39370
+ let newStress = 0;
39371
+ for (let k = 0; k < dim; k++) newStress += vectorsInnerProductF(n, coords[k], b[k]);
39372
+ newStress *= 2;
39373
+ newStress += constantTerm;
39374
+ for (let k = 0; k < dim; k++) {
39375
+ rightMultWithVectorFFFused(lap2, n, coords[k], tmpCoords);
39376
+ newStress -= vectorsInnerProductF(n, coords[k], tmpCoords);
39377
+ }
39378
+ return newStress;
39379
+ }
39380
+ function solveAxes(st, ctx) {
39381
+ for (let k = 0; k < st.dim; k++) {
39382
+ if (k === Y_AXIS) {
39383
+ constrainedMajorizationNewWithGaps(
39384
+ ctx.cMajEnv,
39385
+ st.b[k],
39386
+ st.coords,
39387
+ k,
39388
+ LOCAL_CONSTR_MAJOR_ITERATIONS,
39389
+ ctx.levelsGap
39390
+ );
39391
+ } else if (conjugateGradientMkernelFused(st.lap2, st.coords[k], st.b[k], st.n, { tol: TOLERANCE_CG, maxIterations: st.n })) {
39392
+ return true;
39393
+ }
39394
+ }
39395
+ return false;
39396
+ }
39397
+ function majorize(st, ctx, dCoords) {
39398
+ const constantTerm = Math.trunc(st.n * (st.n - 1) / 2);
39399
+ let oldStress = DBL_MAX;
39400
+ let iterations = 0;
39401
+ for (let converged = false; iterations < ctx.maxi && !converged; iterations++) {
39402
+ buildLap12(st);
39403
+ const newStress = computeNewStress(st, constantTerm);
39404
+ converged = Math.abs(newStress - oldStress) / Math.abs(oldStress + 1e-10) < ctx.epsilon;
39405
+ converged ||= iterations > 1 && newStress > oldStress;
39406
+ oldStress = newStress;
39407
+ if (solveAxes(st, ctx)) return -1;
39408
+ }
39409
+ for (let i = 0; i < st.dim; i++) {
39410
+ for (let j = 0; j < st.n; j++) dCoords[i][j] = st.coords[i][j];
39411
+ }
39412
+ return iterations;
39413
+ }
39414
+ function toFloatCoords(dCoords, n, dim) {
39415
+ const coords = [];
39416
+ for (let i = 0; i < dim; i++) coords.push(Float32Array.from(dCoords[i].subarray(0, n)));
39417
+ return coords;
39418
+ }
39419
+ function newLoopState(lap2, coords, n) {
39420
+ const dim = coords.length;
39421
+ return {
39422
+ n,
39423
+ dim,
39424
+ lap2,
39425
+ coords,
39426
+ lap1: new Float32Array(n + Math.trunc(n * (n - 1) / 2)),
39427
+ b: Array.from({ length: dim }, () => new Float32Array(n)),
39428
+ tmpCoords: new Float32Array(n),
39429
+ distAccumulator: new Float32Array(n),
39430
+ degrees: new Float64Array(n)
39431
+ };
39432
+ }
39433
+ function stressMajorizationWithHierarchy(graph, n, dCoords, nodes, o) {
39434
+ if (!hasDirectionality(graph, n)) return unconstrainedMajorization(graph, n, dCoords, nodes, o);
39435
+ const smartIni = (o.opts & OPT_SMART_INIT) !== 0;
39436
+ const layers = smartIni ? smartInitLayers(graph, n, dCoords, nodes, o) : plainInitLayers(graph, n, dCoords, nodes, o.dim);
39437
+ if (typeof layers === "number") return layers;
39438
+ if (n === 1) return 0;
39439
+ if (o.maxi === 0) return 0;
39440
+ const Dij = modelDistances(graph, n, o.model) ?? computeApspPacked2(graph, n);
39441
+ if (!smartIni) scaleDownLayout(dCoords, n, o.dim);
39442
+ if (o.levelsGap > 0) scaleDistances(Dij, dCoords, n, o.dim);
39443
+ centerLayout(dCoords, n, o.dim);
39444
+ const st = newLoopState(Dij, toFloatCoords(dCoords, n, o.dim), n);
39445
+ buildLap22(Dij, n);
39446
+ const cMajEnv = initConstrainedMajorization(Dij, n, layers.ordering, layers.levels, layers.numLevels);
39447
+ return majorize(st, { cMajEnv, levelsGap: o.levelsGap, maxi: o.maxi, epsilon: o.epsilon }, dCoords);
39448
+ }
39449
+
37813
39450
  // src/common/utils-inputscale.ts
37814
39451
  var POINTS_PER_INCH3 = 72;
37815
39452
  function getInputscale(g) {
@@ -37996,61 +39633,47 @@ function neatoMaxIter(maxiter, mode, n) {
37996
39633
  if (mode === MODE_MAJOR) return DFLT_ITERATIONS;
37997
39634
  return mode === MODE_SGD ? SGD_ITERATIONS : 100 * n;
37998
39635
  }
37999
- function runMajorization(g, mode, model) {
38000
- void model;
38001
- const nodeList = assignNodeIds2(g);
39636
+ var levelsGapOf = (g) => lateDouble(g.root.attrs.get("levelsgap"), 0, -Number.MAX_VALUE);
39637
+ function solveStress(c, vtx, dCoords, nodeList) {
39638
+ const { g, mode, model, haveLen, opts } = c;
38002
39639
  const n = nodeList.length;
38003
- const haveLen = graphHasLen(g);
38004
- const vtx = makeGraphDataC(g, nodeList, haveLen, mode === MODE_HIER || mode === MODE_IPSEP);
38005
- checkStart(g);
38006
39640
  const maxi = neatoMaxIter(g.attrs.get("maxiter"), mode, n);
38007
39641
  const epsilon = lateDouble(g.attrs.get("epsilon"), 1e-4, 0);
39642
+ if (mode === MODE_HIER) {
39643
+ return stressMajorizationWithHierarchy(vtx, n, dCoords, nodeList, {
39644
+ dim: DFLT_DIM,
39645
+ opts,
39646
+ model,
39647
+ maxi,
39648
+ epsilon,
39649
+ levelsGap: levelsGapOf(g)
39650
+ });
39651
+ }
38008
39652
  const weighted = haveLen && mode !== MODE_IPSEP;
38009
39653
  const Dij = weighted ? computeWeightedApspPacked2(vtx, n) : computeApspPacked2(vtx, n);
38010
- const dCoords = [new Float64Array(n), new Float64Array(n)];
38011
- stressMajorizationKDMkernel(Dij, n, dCoords, nodeList, {
39654
+ return stressMajorizationKDMkernel(Dij, n, dCoords, nodeList, {
38012
39655
  dim: DFLT_DIM,
38013
- opts: OPT_EXP_FLAG,
39656
+ opts,
38014
39657
  maxi,
38015
39658
  epsilon
38016
39659
  });
38017
- for (let i = 0; i < n; i++) {
38018
- nodeList[i].info.pos = [dCoords[0][i], dCoords[1][i]];
38019
- }
38020
39660
  }
38021
- function graphHasLen(g) {
38022
- for (const e of g.edges) {
38023
- if (e.attrs.has("len")) return true;
39661
+ function runMajorization(g, mode, model) {
39662
+ const nodeList = assignNodeIds2(g);
39663
+ const n = nodeList.length;
39664
+ const haveLen = graphHasLen(g);
39665
+ 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;
39667
+ const haveDir = mode === MODE_HIER || mode === MODE_IPSEP;
39668
+ const vtx = makeGraphDataC(g, nodeList, haveLen, haveDir, mode);
39669
+ const dCoords = [new Float64Array(n), new Float64Array(n)];
39670
+ if (solveStress({ g, mode, model, haveLen, opts }, vtx, dCoords, nodeList) < 0) {
39671
+ agerr("prev", "layout aborted");
39672
+ return;
38024
39673
  }
38025
- return false;
38026
- }
38027
- function makeGraphDataC(g, nodeList, haveLen, haveDir) {
38028
- const vtx = nodeList.map((_, i) => ({
38029
- nedges: 1,
38030
- edges: [i],
38031
- ewgts: haveLen || haveDir ? [0] : []
38032
- }));
38033
- for (const np of nodeList) {
38034
- const i = np.info.id;
38035
- const entry = vtx[i];
38036
- const seen2 = /* @__PURE__ */ new Map();
38037
- for (const ep of [...np.outEdges(g), ...np.inEdges(g)]) {
38038
- if (ep.head === ep.tail) continue;
38039
- const vp = ep.tail === np ? ep.head : ep.tail;
38040
- const vid = vp.info.id;
38041
- const dist4 = haveLen ? lateDouble(ep.attrs.get("len"), 1, 0) : 1;
38042
- const idx = seen2.get(vid);
38043
- if (idx !== void 0) {
38044
- if (haveLen) entry.ewgts[idx] = Math.max(entry.ewgts[idx], dist4);
38045
- continue;
38046
- }
38047
- seen2.set(vid, entry.nedges);
38048
- entry.edges.push(vid);
38049
- if (haveLen || haveDir) entry.ewgts.push(dist4);
38050
- entry.nedges++;
38051
- }
39674
+ for (let i = 0; i < n; i++) {
39675
+ nodeList[i].info.pos = [dCoords[0][i], dCoords[1][i]];
38052
39676
  }
38053
- return vtx;
38054
39677
  }
38055
39678
  function solveModel2(g, mode, model) {
38056
39679
  if (g.nodes.size < 2) return;
@@ -38242,6 +39865,25 @@ function esepFactor(g) {
38242
39865
  return { x: SEPFACT * DFLT_MARGIN, y: SEPFACT * DFLT_MARGIN, doAdd: true };
38243
39866
  }
38244
39867
 
39868
+ // src/common/libm-trig.ts
39869
+ var OCTAGON_TRIG = /* @__PURE__ */ new Map([
39870
+ [-0.39269908169872414, [0.9238795325112867, -0.3826834323650898]],
39871
+ [0.39269908169872414, [0.9238795325112867, 0.3826834323650898]],
39872
+ [1.1780972450961724, [0.38268343236508984, 0.9238795325112867]],
39873
+ [1.9634954084936207, [-0.3826834323650897, 0.9238795325112867]],
39874
+ [2.748893571891069, [-0.9238795325112867, 0.3826834323650899]],
39875
+ [3.5342917352885173, [-0.9238795325112868, -0.38268343236508967]],
39876
+ [4.319689898685965, [-0.38268343236509034, -0.9238795325112865]],
39877
+ [5.105088062083414, [0.38268343236509, -0.9238795325112866]],
39878
+ [5.890486225480862, [0.9238795325112865, -0.3826834323650904]]
39879
+ ]);
39880
+ function libmCos(x) {
39881
+ return OCTAGON_TRIG.get(x)?.[0] ?? Math.cos(x);
39882
+ }
39883
+ function libmSin(x) {
39884
+ return OCTAGON_TRIG.get(x)?.[1] ?? Math.sin(x);
39885
+ }
39886
+
38245
39887
  // src/layout/neato/delaunay.ts
38246
39888
  var ICCERRBOUND_A = (10 + 96 * 2 ** -53) * 2 ** -53;
38247
39889
  function ulpExp(v) {
@@ -38410,6 +40052,32 @@ function delaunayTri(xv, yv, n) {
38410
40052
  return edges;
38411
40053
  }
38412
40054
 
40055
+ // src/layout/neato/gts-triangle.ts
40056
+ var SQRT3 = 1.73205080757;
40057
+ function gtsTriangleEnclosing(px, py, n, scale) {
40058
+ let xmin = px[0];
40059
+ let xmax = px[0];
40060
+ let ymin = py[0];
40061
+ let ymax = py[0];
40062
+ for (let i = 1; i < n; i++) {
40063
+ if (px[i] > xmax) xmax = px[i];
40064
+ else if (px[i] < xmin) xmin = px[i];
40065
+ if (py[i] > ymax) ymax = py[i];
40066
+ else if (py[i] < ymin) ymin = py[i];
40067
+ }
40068
+ const xo = (xmax + xmin) / 2;
40069
+ const yo = (ymax + ymin) / 2;
40070
+ const dx = xmax - xo;
40071
+ const dy = ymax - yo;
40072
+ let r = scale * Math.sqrt(fma(dx, dx, dy * dy));
40073
+ if (r === 0) r = scale;
40074
+ return [
40075
+ [fma(r, SQRT3, xo), yo - r],
40076
+ [xo, fma(r, 2, yo)],
40077
+ [fma(-r, SQRT3, xo), yo - r]
40078
+ ];
40079
+ }
40080
+
38413
40081
  // src/layout/neato/cdt-surface.ts
38414
40082
  var pairKey = (u, v) => u < v ? u * 1048576 + v : v * 1048576 + u;
38415
40083
  var Cdt = class {
@@ -38920,27 +40588,15 @@ var Cdt = class {
38920
40588
  return { nfaces: kept.length, faces, neigh };
38921
40589
  }
38922
40590
  };
38923
- var SQRT3 = 1.7320508075688772;
38924
40591
  function mkSurface(x, y, n, segs, nsegs) {
38925
40592
  const px = x.slice(0, n);
38926
40593
  const py = y.slice(0, n);
38927
- let xmin = px[0];
38928
- let xmax = px[0];
38929
- let ymin = py[0];
38930
- let ymax = py[0];
38931
- for (let i = 1; i < n; i++) {
38932
- if (px[i] > xmax) xmax = px[i];
38933
- else if (px[i] < xmin) xmin = px[i];
38934
- if (py[i] > ymax) ymax = py[i];
38935
- else if (py[i] < ymin) ymin = py[i];
38936
- }
38937
- const xo = (xmax + xmin) / 2;
38938
- const yo = (ymax + ymin) / 2;
38939
- let r = 100 * Math.hypot(xmax - xo, ymax - yo);
38940
- if (r === 0) r = 100;
38941
40594
  const s0 = n;
38942
- px.push(xo + r * SQRT3, xo, xo - r * SQRT3);
38943
- py.push(yo - r, yo + 2 * r, yo - r);
40595
+ const enc = gtsTriangleEnclosing(px, py, n, 100);
40596
+ for (const [ex, ey] of enc) {
40597
+ px.push(ex);
40598
+ py.push(ey);
40599
+ }
38944
40600
  const cdt = new Cdt(px, py);
38945
40601
  const cons = [];
38946
40602
  for (let k = 0; k < nsegs; k++) {
@@ -38987,9 +40643,9 @@ function sharedEdge(faces, p3, q3) {
38987
40643
  return { i: p1, j: p2 };
38988
40644
  }
38989
40645
  function addTriEdge(g, t, h, seg2) {
38990
- const dist4 = Math.sqrt(dist2(g.nodes[t].ctr, g.nodes[h].ctr));
40646
+ const dist5 = Math.sqrt(dist2(g.nodes[t].ctr, g.nodes[h].ctr));
38991
40647
  const idx = g.edges.length;
38992
- g.edges.push({ t, h, seg: seg2, dist: dist4 });
40648
+ g.edges.push({ t, h, seg: seg2, dist: dist5 });
38993
40649
  g.nodes[t].edges.push(idx);
38994
40650
  g.nodes[h].edges.push(idx);
38995
40651
  }
@@ -39793,8 +41449,8 @@ function ellipseTangentSlope(a, b, p) {
39793
41449
  function circumscribedCorner(a, b, i, nsides) {
39794
41450
  const angle0 = 2 * Math.PI * (i - 0.5) / nsides;
39795
41451
  const angle1 = 2 * Math.PI * (i + 0.5) / nsides;
39796
- const p0 = { x: a * Math.cos(angle0), y: b * Math.sin(angle0) };
39797
- const p1 = { x: a * Math.cos(angle1), y: b * Math.sin(angle1) };
41452
+ const p0 = { x: a * libmCos(angle0), y: b * libmSin(angle0) };
41453
+ const p1 = { x: a * libmCos(angle1), y: b * libmSin(angle1) };
39798
41454
  const m0 = ellipseTangentSlope(a, b, p0);
39799
41455
  const m1 = ellipseTangentSlope(a, b, p1);
39800
41456
  const x = (fms(p1.x, m1, fma(m0, p0.x, -p0.y)) + p1.y) / (m0 - m1);
@@ -42130,52 +43786,14 @@ function armPow(x, y) {
42130
43786
  return expInline(ehi, elo, signBias);
42131
43787
  }
42132
43788
 
42133
- // src/common/crand.ts
42134
- var C_RAND_MAX = 2147483647;
42135
- var UNSEEDED_STATE2 = 1;
42136
- var state2 = UNSEEDED_STATE2;
42137
- registerRenderState(() => {
42138
- state2 = UNSEEDED_STATE2;
42139
- });
42140
- function csrand(seed) {
42141
- state2 = seed;
42142
- }
42143
- function crand() {
42144
- state2 = state2 * 16807 % 2147483647;
42145
- return state2;
42146
- }
42147
- function cdrand() {
42148
- return crand() / C_RAND_MAX;
42149
- }
42150
- function gvRandom(bound) {
42151
- const discardThreshold = C_RAND_MAX - 2147483648 % bound;
42152
- let r;
42153
- do {
42154
- r = crand();
42155
- } while (r > discardThreshold);
42156
- return r % bound;
42157
- }
42158
- function gvPermutation(bound) {
42159
- if (bound <= 0) return [];
42160
- const p = [];
42161
- for (let i = 0; i < bound; i++) p.push(i);
42162
- for (let i = bound - 1; i > 0; --i) {
42163
- const j = gvRandom(i + 1);
42164
- const t = p[i];
42165
- p[i] = p[j];
42166
- p[j] = t;
42167
- }
42168
- return p;
42169
- }
42170
-
42171
43789
  // src/layout/sfdp/quadtree.ts
42172
43790
  function pointDistance(p1, o1, p2, o2, dim) {
42173
- let dist4 = 0;
43791
+ let dist5 = 0;
42174
43792
  for (let i = 0; i < dim; i++) {
42175
43793
  const d = p1[o1 + i] - p2[o2 + i];
42176
- dist4 = fma(d, d, dist4);
43794
+ dist5 = fma(d, d, dist5);
42177
43795
  }
42178
- return Math.sqrt(dist4);
43796
+ return Math.sqrt(dist5);
42179
43797
  }
42180
43798
  function quadTreeNew(dim, center, width2, maxLevel) {
42181
43799
  return {
@@ -42310,8 +43928,8 @@ function getSupernodesInternal(qt, bh, pt, ptOff, nodeid, out) {
42310
43928
  l = l.next;
42311
43929
  }
42312
43930
  if (qt.qts !== null) {
42313
- const dist4 = pointDistance(qt.center, 0, pt, ptOff, dim);
42314
- if (qt.width < bh * dist4) {
43931
+ const dist5 = pointDistance(qt.center, 0, pt, ptOff, dim);
43932
+ if (qt.width < bh * dist5) {
42315
43933
  for (let i = 0; i < dim; i++) {
42316
43934
  out.center[dim * out.nsuper + i] = qt.average[i];
42317
43935
  }
@@ -42409,12 +44027,12 @@ function onedOptimizerTrain(opt, work) {
42409
44027
  else optHill(opt, i);
42410
44028
  }
42411
44029
  function distance(x, dim, i, j) {
42412
- let dist4 = 0;
44030
+ let dist5 = 0;
42413
44031
  for (let k = 0; k < dim; k++) {
42414
44032
  const d = x[i * dim + k] - x[j * dim + k];
42415
- dist4 = fma(d, d, dist4);
44033
+ dist5 = fma(d, d, dist5);
42416
44034
  }
42417
- return Math.sqrt(dist4);
44035
+ return Math.sqrt(dist5);
42418
44036
  }
42419
44037
  function distanceCropped(x, dim, i, j) {
42420
44038
  return Math.max(distance(x, dim, i, j), MINDIST);
@@ -42422,16 +44040,16 @@ function distanceCropped(x, dim, i, j) {
42422
44040
  function gatherLeaves(A3, p, checked, x, dim) {
42423
44041
  const { ia, ja } = A3;
42424
44042
  const leaves = [];
42425
- let dist4 = 0;
44043
+ let dist5 = 0;
42426
44044
  for (let j = ia[p]; j < ia[p + 1]; j++) {
42427
44045
  const c = ja[j];
42428
44046
  if (ia[c + 1] - ia[c] === 1) {
42429
44047
  checked[c] = true;
42430
- dist4 += distance(x, dim, p, c);
44048
+ dist5 += distance(x, dim, p, c);
42431
44049
  leaves.push(c);
42432
44050
  }
42433
44051
  }
42434
- return { leaves, avgDist: dist4 / leaves.length };
44052
+ return { leaves, avgDist: dist5 / leaves.length };
42435
44053
  }
42436
44054
  function beautifyLeaves(dim, A3, x) {
42437
44055
  const { ia, ja, m } = A3;
@@ -42454,7 +44072,7 @@ function beautifyLeaves(dim, A3, x) {
42454
44072
  }
42455
44073
  }
42456
44074
  function averageEdgeLength(A3, dim, coord) {
42457
- let dist4 = 0;
44075
+ let dist5 = 0;
42458
44076
  const { ia, ja } = A3;
42459
44077
  if (ia[A3.m] === 0) return 1;
42460
44078
  for (let i = 0; i < A3.m; i++) {
@@ -42464,10 +44082,10 @@ function averageEdgeLength(A3, dim, coord) {
42464
44082
  const dd = coord[dim * i + k] - coord[dim * ja[j]];
42465
44083
  d = fma(dd, dd, d);
42466
44084
  }
42467
- dist4 += Math.sqrt(d);
44085
+ dist5 += Math.sqrt(d);
42468
44086
  }
42469
44087
  }
42470
- return dist4 / ia[A3.m];
44088
+ return dist5 / ia[A3.m];
42471
44089
  }
42472
44090
  function updateStep(adaptiveCooling, step, fnorm, fnorm0) {
42473
44091
  if (!adaptiveCooling) return COOL * step;
@@ -42478,18 +44096,18 @@ function updateStep(adaptiveCooling, step, fnorm, fnorm0) {
42478
44096
  }
42479
44097
  return 0.99 * step / COOL;
42480
44098
  }
42481
- function repulsivePow(dist4, p) {
42482
- return armPow(dist4, 1 - p);
44099
+ function repulsivePow(dist5, p) {
44100
+ return armPow(dist5, 1 - p);
42483
44101
  }
42484
44102
  function attractiveForce(ctx, i) {
42485
44103
  const { A: A3, x, dim, fp, f } = ctx;
42486
44104
  const { ia, ja } = A3;
42487
44105
  for (let j = ia[i]; j < ia[i + 1]; j++) {
42488
44106
  if (ja[j] === i) continue;
42489
- const dist4 = distance(x, dim, i, ja[j]);
44107
+ const dist5 = distance(x, dim, i, ja[j]);
42490
44108
  for (let k = 0; k < dim; k++) {
42491
44109
  const t = fp.CRK * (x[i * dim + k] - x[ja[j] * dim + k]);
42492
- f[k] = fma(-t, dist4, f[k]);
44110
+ f[k] = fma(-t, dist5, f[k]);
42493
44111
  }
42494
44112
  }
42495
44113
  }
@@ -42497,9 +44115,9 @@ function repulsiveForceDirect(ctx, i) {
42497
44115
  const { x, dim, n, fp, f } = ctx;
42498
44116
  for (let j = 0; j < n; j++) {
42499
44117
  if (j === i) continue;
42500
- const dist4 = distanceCropped(x, dim, i, j);
44118
+ const dist5 = distanceCropped(x, dim, i, j);
42501
44119
  for (let k = 0; k < dim; k++) {
42502
- f[k] += fp.KP * (x[i * dim + k] - x[j * dim + k]) / repulsivePow(dist4, fp.p);
44120
+ f[k] += fp.KP * (x[i * dim + k] - x[j * dim + k]) / repulsivePow(dist5, fp.p);
42503
44121
  }
42504
44122
  }
42505
44123
  }
@@ -42509,9 +44127,9 @@ function repulsiveForceQT(ctx, qt, i, acc) {
42509
44127
  acc.countsAvg += counts;
42510
44128
  acc.nsuperAvg += nsuper;
42511
44129
  for (let j = 0; j < nsuper; j++) {
42512
- const dist4 = Math.max(distances[j], MINDIST);
44130
+ const dist5 = Math.max(distances[j], MINDIST);
42513
44131
  for (let k = 0; k < dim; k++) {
42514
- f[k] += supernodeWgts[j] * fp.KP * (x[i * dim + k] - center[j * dim + k]) / repulsivePow(dist4, fp.p);
44132
+ f[k] += supernodeWgts[j] * fp.KP * (x[i * dim + k] - center[j * dim + k]) / repulsivePow(dist5, fp.p);
42515
44133
  }
42516
44134
  }
42517
44135
  }
@@ -42767,7 +44385,7 @@ function diagPreconNew(A3) {
42767
44385
  }
42768
44386
  return diag;
42769
44387
  }
42770
- function conjugateGradient(A3, precon, n, x, rhs, tol, maxit) {
44388
+ function conjugateGradient2(A3, precon, n, x, rhs, tol, maxit) {
42771
44389
  let rho = 0;
42772
44390
  let rhoOld = 1;
42773
44391
  let iter = 0;
@@ -42808,7 +44426,7 @@ function smSolve(A3, dim, x0, rhs, tol, maxit) {
42808
44426
  x[i] = x0[i * dim + k];
42809
44427
  b[i] = rhs[i * dim + k];
42810
44428
  }
42811
- res += conjugateGradient(A3, precond, n, x, b, tol, maxit);
44429
+ res += conjugateGradient2(A3, precond, n, x, b, tol, maxit);
42812
44430
  for (let i = 0; i < n; i++) {
42813
44431
  rhs[i * dim + k] = x[i];
42814
44432
  }
@@ -43162,7 +44780,7 @@ function idealDistanceAvoidOverlap(dim, A3, x, width2, idealDistance) {
43162
44780
  for (let j = ia[i]; j < ia[i + 1]; j++) {
43163
44781
  const jj = ja[j];
43164
44782
  if (jj === i) continue;
43165
- const dist4 = distance(x, dim, i, jj);
44783
+ const dist5 = distance(x, dim, i, jj);
43166
44784
  const dx = Math.abs(x[i * dim] - x[jj * dim]);
43167
44785
  const dy = Math.abs(x[i * dim + 1] - x[jj * dim + 1]);
43168
44786
  const wx = width2[i * dim] + width2[jj * dim];
@@ -43185,9 +44803,9 @@ function idealDistanceAvoidOverlap(dim, A3, x, width2, idealDistance) {
43185
44803
  t = Math.min(expandmax, t);
43186
44804
  t = Math.max(expandmin, t);
43187
44805
  if (t > 1) {
43188
- idealDistance[j] = t * dist4;
44806
+ idealDistance[j] = t * dist5;
43189
44807
  } else {
43190
- idealDistance[j] = -t * dist4;
44808
+ idealDistance[j] = -t * dist5;
43191
44809
  }
43192
44810
  }
43193
44811
  }
@@ -43282,9 +44900,9 @@ function overlapSmootherNew(m, dim, x, width2, neighborhoodOnly, shrink) {
43282
44900
  w[j] = -1 / d[j] / d[j];
43283
44901
  d[j] = -d[j];
43284
44902
  }
43285
- const dist4 = d[j];
44903
+ const dist5 = d[j];
43286
44904
  diagW += w[j];
43287
- d[j] = w[j] * dist4;
44905
+ d[j] = w[j] * dist5;
43288
44906
  diagD += d[j];
43289
44907
  }
43290
44908
  w[jdiag] = -diagW;
@@ -43295,11 +44913,11 @@ function overlapSmootherNew(m, dim, x, width2, neighborhoodOnly, shrink) {
43295
44913
  function totalDistance(m, dim, x, y) {
43296
44914
  let total = 0;
43297
44915
  for (let i = 0; i < m; i++) {
43298
- let dist4 = 0;
44916
+ let dist5 = 0;
43299
44917
  for (let j = 0; j < dim; j++) {
43300
- dist4 += (y[i * dim + j] - x[i * dim + j]) * (y[i * dim + j] - x[i * dim + j]);
44918
+ dist5 += (y[i * dim + j] - x[i * dim + j]) * (y[i * dim + j] - x[i * dim + j]);
43301
44919
  }
43302
- total += Math.sqrt(dist4);
44920
+ total += Math.sqrt(dist5);
43303
44921
  }
43304
44922
  return total;
43305
44923
  }
@@ -43332,18 +44950,18 @@ function stressMajorizationSmooth(sm, dim, x, maxitSm) {
43332
44950
  idiag = j;
43333
44951
  continue;
43334
44952
  }
43335
- let dist4 = distance(x, dim, i, jd[j]);
44953
+ let dist5 = distance(x, dim, i, jd[j]);
43336
44954
  if (d[j] === 0) {
43337
44955
  dd[j] = 0;
43338
44956
  } else {
43339
- if (dist4 === 0) {
44957
+ if (dist5 === 0) {
43340
44958
  const dij = d[j] / Lw.a[j];
43341
44959
  for (let k = 0; k < dim; k++) {
43342
44960
  x[jd[j] * dim + k] += 1e-4 * (cdrand() + 1e-4) * dij;
43343
44961
  }
43344
- dist4 = distance(x, dim, i, jd[j]);
44962
+ dist5 = distance(x, dim, i, jd[j]);
43345
44963
  }
43346
- dd[j] = d[j] / dist4;
44964
+ dd[j] = d[j] / dist5;
43347
44965
  }
43348
44966
  diag += dd[j];
43349
44967
  }
@@ -43362,9 +44980,9 @@ function stressMajorizationSmooth(sm, dim, x, maxitSm) {
43362
44980
  return diff;
43363
44981
  }
43364
44982
  function scaleToEdgeLength(dim, A3, x, avgLabelSize) {
43365
- let dist4 = averageEdgeLength(A3, dim, x);
43366
- dist4 = avgLabelSize / Math.max(dist4, MACHINEACC);
43367
- for (let i = 0; i < dim * A3.m; i++) x[i] *= dist4;
44983
+ let dist5 = averageEdgeLength(A3, dim, x);
44984
+ dist5 = avgLabelSize / Math.max(dist5, MACHINEACC);
44985
+ for (let i = 0; i < dim * A3.m; i++) x[i] *= dist5;
43368
44986
  }
43369
44987
  function removeOverlapPrism(dim, A3, x, labelSizes, ntry, initialScaling, doShrinking) {
43370
44988
  if (!labelSizes) return;
@@ -43731,7 +45349,7 @@ function makeHasEdge(g) {
43731
45349
  }
43732
45350
  return (a, b) => pairs.get(a)?.has(b) === true || undirected && pairs.get(b)?.has(a) === true;
43733
45351
  }
43734
- function mkNConstraintG(g, list, intersect, dist4) {
45352
+ function mkNConstraintG(g, list, intersect, dist5) {
43735
45353
  const cg = newCg();
43736
45354
  const flat = flatten(list);
43737
45355
  let lastn;
@@ -43748,7 +45366,7 @@ function mkNConstraintG(g, list, intersect, dist4) {
43748
45366
  const nxp = flat[j];
43749
45367
  if (!intersect(p, nxp)) continue;
43750
45368
  const e = cgEdge(cg, cnodeOf(p), cnodeOf(nxp));
43751
- e.info.minlen = dist4(p.bb, nxp.bb);
45369
+ e.info.minlen = dist5(p.bb, nxp.bb);
43752
45370
  e.info.weight = hasEdge(p.np, nxp.np) ? 100 : 1;
43753
45371
  created.push(e);
43754
45372
  }
@@ -43795,12 +45413,12 @@ function buildVisibility(flat, intersect) {
43795
45413
  }
43796
45414
  return vg;
43797
45415
  }
43798
- function mapGraphs(vg, flat, cg, dist4) {
45416
+ function mapGraphs(vg, flat, cg, dist5) {
43799
45417
  for (let i = 0; i < flat.length; i++) {
43800
45418
  const tp = flat[i];
43801
45419
  for (const j of vg[i]) {
43802
45420
  const hp = flat[j];
43803
- const delta2 = dist4(tp.bb, hp.bb);
45421
+ const delta2 = dist5(tp.bb, hp.bb);
43804
45422
  const ce = cgEdge(cg, cnodeOf(tp), cnodeOf(hp));
43805
45423
  ce.info.weight = 1;
43806
45424
  if ((ce.info.minlen ?? 0) < delta2) {
@@ -43810,15 +45428,15 @@ function mapGraphs(vg, flat, cg, dist4) {
43810
45428
  }
43811
45429
  }
43812
45430
  }
43813
- function mkConstraintG(list, intersect, dist4) {
45431
+ function mkConstraintG(list, intersect, dist5) {
43814
45432
  const cg = newCg();
43815
45433
  const flat = flatten(list);
43816
45434
  buildChain(cg, flat);
43817
- mapGraphs(buildVisibility(flat, intersect), flat, cg, dist4);
45435
+ mapGraphs(buildVisibility(flat, intersect), flat, cg, dist5);
43818
45436
  return cg;
43819
45437
  }
43820
- function buildConstraintGraph(g, list, ifn, dist4, ortho) {
43821
- return ortho ? mkConstraintG(list, ifn, dist4) : mkNConstraintG(g, list, ifn, dist4);
45438
+ function buildConstraintGraph(g, list, ifn, dist5, ortho) {
45439
+ return ortho ? mkConstraintG(list, ifn, dist5) : mkNConstraintG(g, list, ifn, dist5);
43822
45440
  }
43823
45441
  function newItems() {
43824
45442
  return new DtBag((p) => p.val, cmpitem);
@@ -43959,7 +45577,7 @@ function inflatePts(verts, xmargin, ymargin) {
43959
45577
  v.y *= ymargin;
43960
45578
  }
43961
45579
  }
43962
- function isBox2(verts) {
45580
+ function isBox3(verts) {
43963
45581
  if (verts.length !== 4) return false;
43964
45582
  const [v0, v1, v2, v3] = verts;
43965
45583
  if (v0.y === v1.y) {
@@ -44019,7 +45637,7 @@ function clusterVerts(n, xmargin, ymargin) {
44019
45637
  function polyKind(n, poly, verts) {
44020
45638
  const name = shapeName(n);
44021
45639
  if (name === "box") return POLY_BOX;
44022
- if (name === "polygon" && isBox2(verts)) return POLY_BOX;
45640
+ if (name === "polygon" && isBox3(verts)) return POLY_BOX;
44023
45641
  if (poly.sides < 3 && poly.regular) return POLY_CIRCLE;
44024
45642
  return 0;
44025
45643
  }
@@ -44527,7 +46145,7 @@ function heapSiftUp(h, i) {
44527
46145
  i = parent2;
44528
46146
  }
44529
46147
  }
44530
- function heapSiftDown3(h, i) {
46148
+ function heapSiftDown2(h, i) {
44531
46149
  const n = h.length;
44532
46150
  for (; ; ) {
44533
46151
  let smallest = i;
@@ -44544,7 +46162,7 @@ function heapSiftDown3(h, i) {
44544
46162
  }
44545
46163
  function makeHeap(h) {
44546
46164
  for (let i = (h.length >> 1) - 1; i >= 0; i--) {
44547
- heapSiftDown3(h, i);
46165
+ heapSiftDown2(h, i);
44548
46166
  }
44549
46167
  }
44550
46168
  function heapFindMin(h) {
@@ -44553,7 +46171,7 @@ function heapFindMin(h) {
44553
46171
  function heapDeleteMin(h) {
44554
46172
  h[0] = h[h.length - 1];
44555
46173
  h.pop();
44556
- if (h.length > 0) heapSiftDown3(h, 0);
46174
+ if (h.length > 0) heapSiftDown2(h, 0);
44557
46175
  }
44558
46176
  function heapInsert(h, c) {
44559
46177
  h.push(c);
@@ -44637,27 +46255,27 @@ var Block = class _Block {
44637
46255
  * @see lib/vpsc/block.cpp: Block::merge(Block* b, Constraint* c)
44638
46256
  */
44639
46257
  mergeTwoArg(b, c) {
44640
- const dist4 = c.right.offset - c.left.offset - c.gap;
46258
+ const dist5 = c.right.offset - c.left.offset - c.gap;
44641
46259
  let l = c.left.block;
44642
46260
  let r = c.right.block;
44643
46261
  if (this.vars.length < b.vars.length) {
44644
- r.mergeInto(l, c, dist4);
46262
+ r.mergeInto(l, c, dist5);
44645
46263
  } else {
44646
- l.mergeInto(r, c, -dist4);
46264
+ l.mergeInto(r, c, -dist5);
44647
46265
  }
44648
46266
  }
44649
46267
  /**
44650
46268
  * Merge block b into this across constraint c by dist.
44651
46269
  * @see lib/vpsc/block.cpp: Block::merge(Block *b, Constraint *c, double dist)
44652
46270
  */
44653
- mergeInto(b, c, dist4) {
46271
+ mergeInto(b, c, dist5) {
44654
46272
  c.active = true;
44655
- this.wposn += b.wposn - dist4 * b.weight;
46273
+ this.wposn += b.wposn - dist5 * b.weight;
44656
46274
  this.weight += b.weight;
44657
46275
  this.posn = this.wposn / this.weight;
44658
46276
  for (const v of b.vars) {
44659
46277
  v.block = this;
44660
- v.offset += dist4;
46278
+ v.offset += dist5;
44661
46279
  this.vars.push(v);
44662
46280
  }
44663
46281
  b.deleted = true;
@@ -44946,13 +46564,13 @@ var Blocks = class {
44946
46564
  r.deleteMinInConstraint();
44947
46565
  let l = c.left.block;
44948
46566
  if (l.in.length === 0) l.setUpInConstraints();
44949
- let dist4 = c.right.offset - c.left.offset - c.gap;
46567
+ let dist5 = c.right.offset - c.left.offset - c.gap;
44950
46568
  if (r.vars.length < l.vars.length) {
44951
- dist4 = -dist4;
46569
+ dist5 = -dist5;
44952
46570
  [l, r] = [r, l];
44953
46571
  }
44954
46572
  this.timeCtr.value++;
44955
- r.mergeInto(l, c, dist4);
46573
+ r.mergeInto(l, c, dist5);
44956
46574
  r.mergeIn(l);
44957
46575
  r.timeStamp = this.timeCtr.value;
44958
46576
  this.removeBlock(l);
@@ -44970,12 +46588,12 @@ var Blocks = class {
44970
46588
  l.deleteMinOutConstraint();
44971
46589
  let r = c.right.block;
44972
46590
  r.setUpOutConstraints();
44973
- let dist4 = c.left.offset + c.gap - c.right.offset;
46591
+ let dist5 = c.left.offset + c.gap - c.right.offset;
44974
46592
  if (l.vars.length > r.vars.length) {
44975
- dist4 = -dist4;
46593
+ dist5 = -dist5;
44976
46594
  [l, r] = [r, l];
44977
46595
  }
44978
- l.mergeInto(r, c, dist4);
46596
+ l.mergeInto(r, c, dist5);
44979
46597
  l.mergeOut(r);
44980
46598
  this.removeBlock(r);
44981
46599
  c = l.findMinOutConstraint();
@@ -45491,7 +47109,7 @@ function warnUnrecognizedOverlap(flag) {
45491
47109
  const s = flag.toLowerCase();
45492
47110
  if (s.startsWith("prism") || NAMED_MODES.has(s)) return;
45493
47111
  if (mapBoolDflt(flag, false) === mapBoolDflt(flag, true)) return;
45494
- agerrLineOn("warn", `Unrecognized overlap value "${flag}" - using false`);
47112
+ agwarningf(`Unrecognized overlap value "${flag}" - using false`);
45495
47113
  }
45496
47114
  function getAdjustMode(flag) {
45497
47115
  warnUnrecognizedOverlap(flag);
@@ -45524,7 +47142,7 @@ function adjustLate(g, am) {
45524
47142
  case AM_VPSC:
45525
47143
  return vpscAdjust(g);
45526
47144
  default:
45527
- agerrLineOn("warn", `Unhandled adjust option ${am.print}`);
47145
+ agwarningf(`Unhandled adjust option ${am.print}`);
45528
47146
  return 0;
45529
47147
  }
45530
47148
  }
@@ -46498,20 +48116,20 @@ function coincidentDelta() {
46498
48116
  } while (xdelta === 0 && ydelta === 0);
46499
48117
  return { xdelta, ydelta };
46500
48118
  }
46501
- function doRep(p, q, xdelta, ydelta, dist4) {
48119
+ function doRep(p, q, xdelta, ydelta, dist5) {
46502
48120
  let force;
46503
- if (!(dist4 > 0)) {
48121
+ if (!(dist5 > 0)) {
46504
48122
  const d = coincidentDelta();
46505
48123
  xdelta = d.xdelta;
46506
48124
  ydelta = d.ydelta;
46507
- dist4 = libmHypot(xdelta, ydelta);
48125
+ dist5 = libmHypot(xdelta, ydelta);
46508
48126
  }
46509
- if (dist4 > fdpParms.Mlimit) {
48127
+ if (dist5 > fdpParms.Mlimit) {
46510
48128
  force = 0;
46511
48129
  } else if (parms.useNew) {
46512
- force = parms.K * parms.K / (dist4 * dist4 * dist4);
48130
+ force = parms.K * parms.K / (dist5 * dist5 * dist5);
46513
48131
  } else {
46514
- force = parms.K * parms.K / (dist4 * dist4);
48132
+ force = parms.K * parms.K / (dist5 * dist5);
46515
48133
  }
46516
48134
  if (isPort(p) && isPort(q)) force *= 10;
46517
48135
  const dq = disp(q);
@@ -46533,8 +48151,8 @@ function doNeighbor(grid2, i, j, nodes) {
46533
48151
  for (const q of cellp.nodes) {
46534
48152
  const xdelta = q.info.pos[0] - p.info.pos[0];
46535
48153
  const ydelta = q.info.pos[1] - p.info.pos[1];
46536
- const dist4 = libmHypot(xdelta, ydelta);
46537
- if (dist4 < parms.Cell) doRep(p, q, xdelta, ydelta, dist4);
48154
+ const dist5 = libmHypot(xdelta, ydelta);
48155
+ if (dist5 < parms.Cell) doRep(p, q, xdelta, ydelta, dist5);
46538
48156
  }
46539
48157
  }
46540
48158
  }
@@ -46566,12 +48184,12 @@ function applyAttr(p, q, e) {
46566
48184
  ydelta = d.ydelta;
46567
48185
  dist22 = fma(xdelta, xdelta, ydelta * ydelta);
46568
48186
  }
46569
- const dist4 = Math.sqrt(dist22);
48187
+ const dist5 = Math.sqrt(dist22);
46570
48188
  let force;
46571
48189
  if (parms.useNew) {
46572
- force = (e.info.factor ?? 1) * (dist4 - (e.info.dist ?? 1)) / dist4;
48190
+ force = (e.info.factor ?? 1) * (dist5 - (e.info.dist ?? 1)) / dist5;
46573
48191
  } else {
46574
- force = (e.info.factor ?? 1) * dist4 / (e.info.dist ?? 1);
48192
+ force = (e.info.factor ?? 1) * dist5 / (e.info.dist ?? 1);
46575
48193
  }
46576
48194
  const dq = disp(q);
46577
48195
  const dp = disp(p);
@@ -46746,16 +48364,16 @@ function cntOverlaps(g) {
46746
48364
  function applyRep2(p, q, rs) {
46747
48365
  let xdelta = q.info.pos[0] - p.info.pos[0];
46748
48366
  let ydelta = q.info.pos[1] - p.info.pos[1];
46749
- let dist4 = libmHypot(xdelta, ydelta);
46750
- if (!(dist4 > 0)) {
48367
+ let dist5 = libmHypot(xdelta, ydelta);
48368
+ if (!(dist5 > 0)) {
46751
48369
  const d = coincidentDelta();
46752
48370
  xdelta = d.xdelta;
46753
48371
  ydelta = d.ydelta;
46754
- dist4 = libmHypot(xdelta, ydelta);
48372
+ dist5 = libmHypot(xdelta, ydelta);
46755
48373
  }
46756
48374
  const ov = overlap4(p, q) ? 1 : 0;
46757
- let force = ov ? rs.ov / (dist4 * dist4) : rs.nonov / (dist4 * dist4);
46758
- if (dist4 > fdpParms.Mlimit) force = 0;
48375
+ let force = ov ? rs.ov / (dist5 * dist5) : rs.nonov / (dist5 * dist5);
48376
+ if (dist5 > fdpParms.Mlimit) force = 0;
46759
48377
  const dq = disp(q);
46760
48378
  const dp = disp(p);
46761
48379
  dq[0] = fma(xdelta, force, dq[0]);
@@ -46768,10 +48386,10 @@ function applyAttr2(p, q) {
46768
48386
  if (overlap4(p, q)) return;
46769
48387
  const xdelta = q.info.pos[0] - p.info.pos[0];
46770
48388
  const ydelta = q.info.pos[1] - p.info.pos[1];
46771
- const dist4 = libmHypot(xdelta, ydelta);
48389
+ const dist5 = libmHypot(xdelta, ydelta);
46772
48390
  const din = rad(p) + rad(q);
46773
- const dout = dist4 - din;
46774
- const force = dout * dout / ((xParams.K + din) * dist4);
48391
+ const dout = dist5 - din;
48392
+ const force = dout * dout / ((xParams.K + din) * dist5);
46775
48393
  const dq = disp(q);
46776
48394
  const dp = disp(p);
46777
48395
  dq[0] = fms(xdelta, force, dq[0]);
@@ -47926,9 +49544,9 @@ function pcpRotate(n, dim, x) {
47926
49544
  axis[0] = -(-y[0] + y[3] - Math.sqrt(radicand)) / (2 * y[1]);
47927
49545
  axis[1] = 1;
47928
49546
  }
47929
- const dist4 = Math.sqrt(fma(axis[0], axis[0], 1));
47930
- axis[0] = axis[0] / dist4;
47931
- axis[1] = axis[1] / dist4;
49547
+ const dist5 = Math.sqrt(fma(axis[0], axis[0], 1));
49548
+ axis[0] = axis[0] / dist5;
49549
+ axis[1] = axis[1] / dist5;
47932
49550
  for (let i = 0; i < n; i++) {
47933
49551
  const x0 = fma(x[dim * i], axis[0], x[dim * i + 1] * axis[1]);
47934
49552
  const x1 = fma(-x[dim * i], axis[1], x[dim * i + 1] * axis[0]);
@@ -48341,10 +49959,10 @@ function buildSpanTree(nodes, edges) {
48341
49959
  }
48342
49960
  return map;
48343
49961
  }
48344
- function measureDist(leaf, anc, dist4, change) {
49962
+ function measureDist(leaf, anc, dist5, change) {
48345
49963
  const p = anc.tparent;
48346
49964
  if (!p) return;
48347
- const d = dist4 + 1;
49965
+ const d = dist5 + 1;
48348
49966
  if (p.distone === 0) {
48349
49967
  p.leafone = leaf;
48350
49968
  p.distone = d;
@@ -49844,11 +51462,11 @@ var DEFAULT_COLOR5 = "black";
49844
51462
  var PENWIDTH_NORMAL4 = 1;
49845
51463
  var PENWIDTH_THRESHOLD4 = 5e-3;
49846
51464
  var EPS3 = 1e-5;
49847
- function dist3(a, b) {
51465
+ function dist4(a, b) {
49848
51466
  return Math.sqrt(dist2(a, b));
49849
51467
  }
49850
51468
  function approxLen(list, off) {
49851
- return dist3(list[off], list[off + 1]) + dist3(list[off + 1], list[off + 2]) + dist3(list[off + 2], list[off + 3]);
51469
+ return dist4(list[off], list[off + 1]) + dist4(list[off + 1], list[off + 2]) + dist4(list[off + 2], list[off + 3]);
49852
51470
  }
49853
51471
  function splitCubic(v, t) {
49854
51472
  const left2 = [];
@@ -49927,7 +51545,7 @@ function drawSplitSpline(list, segs, job) {
49927
51545
  return endColor;
49928
51546
  }
49929
51547
  function emitSplitEdgePaths(e, job, colorList) {
49930
- const segs = parseSegs(colorList).segs;
51548
+ const segs = parseSegs(colorList, edgeSegsContext(e)).segs;
49931
51549
  const firstColor2 = segs[0]?.color ?? DEFAULT_COLOR5;
49932
51550
  const spl = e.info.spl;
49933
51551
  let endColor = firstColor2;
@@ -49948,8 +51566,8 @@ var forfunc = (cur, total, init) => (1 - cur / total) * init / 2;
49948
51566
  var revfunc = (cur, total, init) => cur / total * init / 2;
49949
51567
  var nonefunc = (_cur, _total, init) => init / 2;
49950
51568
  var bothfunc = (cur, total, init) => {
49951
- const fr3 = cur / total;
49952
- return fr3 <= 0.5 ? fr3 * init : (1 - fr3) * init;
51569
+ const fr7 = cur / total;
51570
+ return fr7 <= 0.5 ? fr7 * init : (1 - fr7) * init;
49953
51571
  };
49954
51572
  function taperfun(dir, directed) {
49955
51573
  if (dir === "forward") return forfunc;
@@ -51383,7 +53001,7 @@ var DotWriterBase = class {
51383
53001
 
51384
53002
  // src/render/dot/edge-draw.ts
51385
53003
  var DEFAULT_COLOR6 = "black";
51386
- var DEFAULT_LINE_STYLE = ["solid", "setlinewidth(1)"];
53004
+ var DEFAULT_LINE_STYLE2 = ["solid", "setlinewidth(1)"];
51387
53005
  function emitArrowOp(buf, op, pen) {
51388
53006
  switch (op.kind) {
51389
53007
  case "polygon":
@@ -51418,8 +53036,9 @@ var EdgeDrawBase = class extends DotWriterBase {
51418
53036
  */
51419
53037
  attachmentPolyline(pts, pencolor, job) {
51420
53038
  const obj = job.obj;
53039
+ gvrenderSetStyle(DEFAULT_LINE_STYLE2);
51421
53040
  if (obj !== null) {
51422
- obj.rawStyle = [...DEFAULT_LINE_STYLE];
53041
+ obj.rawStyle = [...DEFAULT_LINE_STYLE2];
51423
53042
  obj.pen = 3 /* Solid */;
51424
53043
  obj.penWidth = 1;
51425
53044
  obj.penColor = resolveRenderColor(pencolor.split(":")[0]);
@@ -51473,8 +53092,8 @@ var EdgeDrawBase = class extends DotWriterBase {
51473
53092
  * under that segment's pen. Reuses the same split geometry
51474
53093
  * (splitSplineByColor) as the SVG path. @see lib/common/emit.c:1975 multicolor
51475
53094
  */
51476
- emitSplitSpline(bzList, colorAttr, edraw, job) {
51477
- const segs = parseSegs(colorAttr).segs;
53095
+ emitSplitSpline(bzList, e, colorAttr, edraw, job) {
53096
+ const segs = parseSegs(colorAttr, edgeSegsContext(e)).segs;
51478
53097
  const firstColor2 = segs[0]?.color ?? DEFAULT_COLOR6;
51479
53098
  let endColor = firstColor2;
51480
53099
  for (const bz of bzList) {
@@ -51497,7 +53116,7 @@ var EdgeDrawBase = class extends DotWriterBase {
51497
53116
  const segData = bzList.map(
51498
53117
  (bz) => bz !== void 0 && bz.size >= 4 ? buildOffsetLists(bz.list, (2 + numc) / 2) : { offlist: [], tmplist: [] }
51499
53118
  );
51500
- const colors = parseSegs(colorAttr).segs.map((s) => s.color ?? DEFAULT_COLOR6);
53119
+ const colors = parseSegsSilent(colorAttr).segs.map((s) => s.color ?? DEFAULT_COLOR6);
51501
53120
  for (const color of colors) {
51502
53121
  const pen = xdotPenColor(resolveRenderColor(color));
51503
53122
  for (const sd of segData) {
@@ -51653,7 +53272,7 @@ var XdotRenderer = class extends EdgeDrawBase {
51653
53272
  let tailArrowColor;
51654
53273
  let headArrowColor;
51655
53274
  if (numsemi > 0 && numc > 0) {
51656
- const c = this.emitSplitSpline(spl.list, colorAttr, edraw, job);
53275
+ const c = this.emitSplitSpline(spl.list, e, colorAttr, edraw, job);
51657
53276
  tailArrowColor = c.firstColor;
51658
53277
  headArrowColor = c.endColor;
51659
53278
  } else if (edgeIsTapered(e)) {
@@ -51889,66 +53508,6 @@ function svgTaperedEdge(e, job) {
51889
53508
  svgArrowPolygons(e, job);
51890
53509
  }
51891
53510
 
51892
- // src/gvc/image-resolver.ts
51893
- var activeResolver = null;
51894
- var EXT_MIME = {
51895
- png: "image/png",
51896
- jpg: "image/jpeg",
51897
- jpeg: "image/jpeg",
51898
- gif: "image/gif",
51899
- svg: "image/svg+xml",
51900
- webp: "image/webp"
51901
- };
51902
- var FALLBACK_MIME = "application/octet-stream";
51903
- function inferMimeFromSrc(src) {
51904
- const dot = src.lastIndexOf(".");
51905
- if (dot < 0 || dot === src.length - 1) return FALLBACK_MIME;
51906
- const ext = src.slice(dot + 1).toLowerCase();
51907
- return EXT_MIME[ext] ?? FALLBACK_MIME;
51908
- }
51909
- function findImageBytes(src, resolver) {
51910
- const active = resolver ?? activeResolver;
51911
- if (active === null) return null;
51912
- const result = active(src);
51913
- if (result === null) return null;
51914
- if (result instanceof Uint8Array) {
51915
- return { bytes: result, mime: inferMimeFromSrc(src) };
51916
- }
51917
- return { bytes: result.bytes, mime: result.mime ?? inferMimeFromSrc(src) };
51918
- }
51919
- var B64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
51920
- function base64Encode(bytes) {
51921
- const len = bytes.length;
51922
- const out = [];
51923
- let i = 0;
51924
- for (; i + 2 < len; i += 3) {
51925
- const n = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2];
51926
- out.push(
51927
- B64_CHARS[n >> 18 & 63],
51928
- B64_CHARS[n >> 12 & 63],
51929
- B64_CHARS[n >> 6 & 63],
51930
- B64_CHARS[n & 63]
51931
- );
51932
- }
51933
- const remaining = len - i;
51934
- if (remaining === 1) {
51935
- const n = bytes[i] << 16;
51936
- out.push(B64_CHARS[n >> 18 & 63], B64_CHARS[n >> 12 & 63], "==");
51937
- } else if (remaining === 2) {
51938
- const n = bytes[i] << 16 | bytes[i + 1] << 8;
51939
- out.push(
51940
- B64_CHARS[n >> 18 & 63],
51941
- B64_CHARS[n >> 12 & 63],
51942
- B64_CHARS[n >> 6 & 63],
51943
- "="
51944
- );
51945
- }
51946
- return out.join("");
51947
- }
51948
- function toDataUri(bytes, mime) {
51949
- return "data:" + mime + ";base64," + base64Encode(bytes);
51950
- }
51951
-
51952
53511
  // src/render/svg.ts
51953
53512
  function emitMulticolorArrows(e, job, headColor, tailColor) {
51954
53513
  const obj = job.obj;
@@ -52364,7 +53923,7 @@ function peg$parse(input, options) {
52364
53923
  return s;
52365
53924
  }
52366
53925
  function peg$f13(t, m, attrs) {
52367
- if (m) agwarningf("attribute macros not implemented", "error");
53926
+ if (m) agwarningf("attribute macros not implemented");
52368
53927
  return { type: "attr", target: t, attrs };
52369
53928
  }
52370
53929
  function peg$f14(a) {
@@ -56263,7 +57822,7 @@ function isPeggyError(err) {
56263
57822
  function warnNumberAmbiguities(src, upTo) {
56264
57823
  for (const a of scanNumberAmbiguities(src, Stripper.strip(src))) {
56265
57824
  if (a.offset > upTo) break;
56266
- agerrFinished(numberAmbiguityMessage(a), "error");
57825
+ agerrFinished(numberAmbiguityMessage(a));
56267
57826
  }
56268
57827
  }
56269
57828
  function parse(src) {