@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/index.js CHANGED
@@ -299,7 +299,7 @@ function peg$parse(input, options) {
299
299
  return s;
300
300
  }
301
301
  function peg$f13(t, m, attrs) {
302
- if (m) agwarningf("attribute macros not implemented", "error");
302
+ if (m) agwarningf("attribute macros not implemented");
303
303
  return { type: "attr", target: t, attrs };
304
304
  }
305
305
  function peg$f14(a) {
@@ -3688,6 +3688,20 @@ var Graph = class {
3688
3688
  }
3689
3689
  };
3690
3690
 
3691
+ // src/model/lazy-attrs.ts
3692
+ var SharedEmptyAttrs = class extends Map {
3693
+ set(key, _value) {
3694
+ throw new Error(`attrs.set("${key}") on a shared empty map; use ownAttrs()`);
3695
+ }
3696
+ delete(key) {
3697
+ throw new Error(`attrs.delete("${key}") on a shared empty map; use ownAttrs()`);
3698
+ }
3699
+ clear() {
3700
+ throw new Error("attrs.clear() on a shared empty map; use ownAttrs()");
3701
+ }
3702
+ };
3703
+ var EMPTY_ATTRS = new SharedEmptyAttrs();
3704
+
3691
3705
  // src/model/algData.ts
3692
3706
  var THETA_UNSET = 10;
3693
3707
 
@@ -3790,10 +3804,10 @@ var Node = class {
3790
3804
  */
3791
3805
  nodeDefaultsSnapshot;
3792
3806
  /** @see lib/cgraph/node.c:agnode */
3793
- constructor(id, name, root) {
3807
+ constructor(id, name, root, lazyAttrs = false) {
3794
3808
  this.id = id;
3795
3809
  this.name = name;
3796
- this.attrs = /* @__PURE__ */ new Map();
3810
+ this.attrs = lazyAttrs ? EMPTY_ATTRS : /* @__PURE__ */ new Map();
3797
3811
  this.info = makeNodeInfo();
3798
3812
  this.root = root;
3799
3813
  }
@@ -3963,12 +3977,12 @@ var Edge = class _Edge {
3963
3977
  */
3964
3978
  info;
3965
3979
  /** @see lib/cgraph/edge.c:agedge */
3966
- constructor(tail, head, name) {
3980
+ constructor(tail, head, name, lazyAttrs = false) {
3967
3981
  this.seq = _Edge._nextSeq++;
3968
3982
  this.tail = tail;
3969
3983
  this.head = head;
3970
3984
  this.name = name;
3971
- this.attrs = /* @__PURE__ */ new Map();
3985
+ this.attrs = lazyAttrs ? EMPTY_ATTRS : /* @__PURE__ */ new Map();
3972
3986
  this.info = makeEdgeInfo(makePort(), makePort());
3973
3987
  }
3974
3988
  };
@@ -4854,7 +4868,7 @@ function isPeggyError(err) {
4854
4868
  function warnNumberAmbiguities(src, upTo) {
4855
4869
  for (const a of scanNumberAmbiguities(src, Stripper.strip(src))) {
4856
4870
  if (a.offset > upTo) break;
4857
- agerrFinished(numberAmbiguityMessage(a), "error");
4871
+ agerrFinished(numberAmbiguityMessage(a));
4858
4872
  }
4859
4873
  }
4860
4874
  function parse(src) {
@@ -5627,6 +5641,12 @@ var GvcContext = class {
5627
5641
  * rendering happens in between and must see the layout state
5628
5642
  * (e.g. cluster arrays).
5629
5643
  *
5644
+ * Contract (AD-4/AD-8): first resets the C process state (RNG streams,
5645
+ * sequence counters, once-only warnings), so each `layout` call behaves
5646
+ * as one native run — drive one graph per `layout`. Caller-installed hooks
5647
+ * (setTextMeasurer, setImageSizer, setImageResolver, the per-context
5648
+ * measurer/sizer/resolver) are configuration and are not reset.
5649
+ *
5630
5650
  * @throws TypeError (ERR_INVALID_ARG_TYPE / ERR_INVALID_ARG_VALUE) for a
5631
5651
  * bad `g`, or an engine argument that is not registered
5632
5652
  * @throws RenderError (UNKNOWN_LAYOUT) if the `layout` attribute names no
@@ -5637,6 +5657,7 @@ var GvcContext = class {
5637
5657
  * @see lib/gvc/gvlayout.c:gvLayoutJobs
5638
5658
  */
5639
5659
  layout(g, engineName) {
5660
+ resetRenderState();
5640
5661
  const selected = this.checkLayoutArgs(g, engineName);
5641
5662
  const attr2 = g.attrs?.get("layout");
5642
5663
  let engine = selected;
@@ -8793,6 +8814,16 @@ function colorxlate(str, color, targetType) {
8793
8814
  }
8794
8815
 
8795
8816
  // src/common/multicolor.ts
8817
+ var parseSegsState = { warned: false };
8818
+ registerRenderState(() => {
8819
+ parseSegsState.warned = false;
8820
+ });
8821
+ function claimWarned() {
8822
+ if (parseSegsState.warned) return false;
8823
+ parseSegsState.warned = true;
8824
+ return true;
8825
+ }
8826
+ var claimNever = () => false;
8796
8827
  var EPS = 1e-5;
8797
8828
  function aeq0(x) {
8798
8829
  return x < EPS && x > -EPS;
@@ -8806,17 +8837,14 @@ function getSegLen(token) {
8806
8837
  const parsed = parseFloat(rest);
8807
8838
  return !isNaN(parsed) && parsed >= 0 ? { color, v: parsed } : { color, v: -1 };
8808
8839
  }
8809
- function appendSeg(token, left2, segs, warnedExceeded) {
8840
+ function appendSeg(token, left2, segs, claim) {
8810
8841
  const { color, v } = getSegLen(token);
8811
8842
  if (v < 0) return null;
8812
8843
  let t = v;
8813
8844
  let rval = 0;
8814
8845
  const del = t - left2;
8815
8846
  if (del > 0) {
8816
- if (!aeq0(del) && !warnedExceeded.v) {
8817
- warnedExceeded.v = true;
8818
- rval = 3;
8819
- }
8847
+ if (!aeq0(del) && claim()) rval = 3;
8820
8848
  t = left2;
8821
8849
  }
8822
8850
  left2 -= t;
@@ -8840,19 +8868,13 @@ function trimTrailing(segs) {
8840
8868
  segs.pop();
8841
8869
  }
8842
8870
  }
8843
- function parseSegs(colorlist) {
8871
+ function scanSegs(colorlist, claim) {
8844
8872
  const segs = [];
8845
8873
  let left2 = 1;
8846
8874
  let rval = 0;
8847
- let badFloatCount = 0;
8848
- const warnedExceeded = { v: false };
8849
8875
  for (const token of colorlist.split(":")) {
8850
- const result = appendSeg(token, left2, segs, warnedExceeded);
8851
- if (result === null) {
8852
- const errCode = badFloatCount === 0 ? 2 : 1;
8853
- badFloatCount++;
8854
- return { segs: [], error: errCode };
8855
- }
8876
+ const result = appendSeg(token, left2, segs, claim);
8877
+ if (result === null) return { segs: [], error: claim() ? 2 : 1 };
8856
8878
  if (result.rval === 3) rval = 3;
8857
8879
  left2 = result.left;
8858
8880
  if (aeq0(left2)) {
@@ -8864,6 +8886,26 @@ function parseSegs(colorlist) {
8864
8886
  trimTrailing(segs);
8865
8887
  return { segs, error: rval };
8866
8888
  }
8889
+ function parseSegs(colorlist, context) {
8890
+ const result = scanSegs(colorlist, claimWarned);
8891
+ if (result.error === 3) {
8892
+ const tail = context === void 0 ? "" : context();
8893
+ agwarningf(`Total size > 1 in "${colorlist}" color spec ${tail}`);
8894
+ } else if (result.error === 2) {
8895
+ agerrorf(`Illegal value in "${colorlist}" color attribute; float expected after ';'`);
8896
+ if (context !== void 0) agerr("prev", context());
8897
+ }
8898
+ return result;
8899
+ }
8900
+ function parseSegsSilent(colorlist) {
8901
+ return scanSegs(colorlist, claimNever);
8902
+ }
8903
+ function edgeSegsContext(e) {
8904
+ return () => {
8905
+ const directed = !e.tail.root.kind.endsWith("undirected");
8906
+ return `in edge ${e.tail.name}${directed ? " -> " : " -- "}${e.head.name}`;
8907
+ };
8908
+ }
8867
8909
 
8868
8910
  // src/common/style-resolve.ts
8869
8911
  var DEFAULT_COLOR = "black";
@@ -9283,7 +9325,7 @@ function countChar(s, ch) {
9283
9325
  return s.split(ch).length - 1;
9284
9326
  }
9285
9327
  function multicolorNames(color, arrows) {
9286
- const { segs, error } = parseSegs(color);
9328
+ const { segs, error } = parseSegsSilent(color);
9287
9329
  if (error === 1 || error === 2) return null;
9288
9330
  const out = [];
9289
9331
  const front = segs[0]?.color ?? null;
@@ -9870,6 +9912,71 @@ function htmlStyle(style2) {
9870
9912
  return s;
9871
9913
  }
9872
9914
 
9915
+ // src/gvc/gvrender-set-style.ts
9916
+ var SUPPORTED_STYLES = /* @__PURE__ */ new Set([
9917
+ "solid",
9918
+ "dashed",
9919
+ "dotted",
9920
+ "invis",
9921
+ "invisible",
9922
+ "bold",
9923
+ "setlinewidth",
9924
+ "filled",
9925
+ "unfilled",
9926
+ "tapered"
9927
+ ]);
9928
+ var BOX_ORIENTATION_TOLERANCE = 0.5;
9929
+ var BOX_ORIENTATION_STEP = 90;
9930
+ var BOX_SIDES = 4;
9931
+ var ELLIPSE_MAX_SIDES = 2;
9932
+ function styleName(token) {
9933
+ const paren = token.indexOf("(");
9934
+ return paren < 0 ? token : token.slice(0, paren);
9935
+ }
9936
+ function gvrenderSetStyle(styles) {
9937
+ if (styles === null) return;
9938
+ for (const token of styles) {
9939
+ const name = styleName(token);
9940
+ if (!SUPPORTED_STYLES.has(name)) {
9941
+ agwarningf(`gvrender_set_style: unsupported style ${name} - ignoring`);
9942
+ }
9943
+ }
9944
+ }
9945
+ function isBox(p) {
9946
+ if (p === null) return false;
9947
+ return p.sides === BOX_SIDES && Math.abs(p.orientation % BOX_ORIENTATION_STEP) < BOX_ORIENTATION_TOLERANCE && p.distortion === 0 && p.skew === 0;
9948
+ }
9949
+ function isEllipse(p) {
9950
+ return p !== null && p.sides <= ELLIPSE_MAX_SIDES;
9951
+ }
9952
+ function checkStyleTokens(styles, shape) {
9953
+ return styles.filter((p) => {
9954
+ if (p === "rounded" || p === "diagonals" || p === "radial") return false;
9955
+ if (p === "striped") return !isBox(shape);
9956
+ if (p === "wedged") return !isEllipse(shape);
9957
+ return true;
9958
+ });
9959
+ }
9960
+ function checkClusterStyleTokens(styles) {
9961
+ return styles.filter((p) => p !== "radial" && p !== "striped" && p !== "rounded");
9962
+ }
9963
+ function countChar2(s, ch) {
9964
+ return [...s].filter((c) => c === ch).length;
9965
+ }
9966
+ function multicolorTaken(color) {
9967
+ if (countChar2(color, ";") === 0 || countChar2(color, ":") === 0) return false;
9968
+ const { error } = parseSegsSilent(color);
9969
+ return error !== 1 && error !== 2;
9970
+ }
9971
+ function edgeStyleResets(e, styles) {
9972
+ const spl = e.info.spl;
9973
+ if (spl === void 0 || spl.size <= 1 || styles.length === 0) return 0;
9974
+ const color = e.attrs.get("color") ?? "";
9975
+ const otherBranch = styles.includes("tapered") || countChar2(color, ":") > 0;
9976
+ if (otherBranch && !multicolorTaken(color)) return 0;
9977
+ return spl.list.filter((bz) => bz.sflag !== 0 || bz.eflag !== 0).length;
9978
+ }
9979
+
9873
9980
  // src/common/htmltable-types.ts
9874
9981
  var HtmlParseError = class extends DotEngineError {
9875
9982
  type = "semantic";
@@ -9889,13 +9996,21 @@ var BORDER_BOTTOM = 1 << 13;
9889
9996
  var BORDER_MASK = BORDER_LEFT | BORDER_TOP | BORDER_RIGHT | BORDER_BOTTOM;
9890
9997
 
9891
9998
  // src/common/htmltable-emit-fill.ts
9999
+ var MSG_MANY_COLORS = "More than 2 colors specified for a gradient - ignoring remaining";
10000
+ function findHtmlStopColor(color, silent = false) {
10001
+ const { segs, error } = silent ? parseSegsSilent(color) : parseSegs(color);
10002
+ const first = segs[0];
10003
+ const second = segs[1];
10004
+ if (error !== 0 || first === void 0 || second === void 0 || first.color === null) {
10005
+ return null;
10006
+ }
10007
+ if (segs.length > 2 && !silent) agwarningf(MSG_MANY_COLORS);
10008
+ const frac = first.hasFraction ? first.t : second.hasFraction ? 1 - second.t : 0;
10009
+ return { fill: first.color, stop: second.color, frac };
10010
+ }
9892
10011
  function parseGradientSpec(color) {
9893
- const idx = color.indexOf(":");
9894
- if (idx < 1) return null;
9895
- const c0 = color.slice(0, idx).trim();
9896
- const c1 = color.slice(idx + 1).trim();
9897
- if (c0.length === 0) return null;
9898
- return [c0, c1.length > 0 ? c1 : "black"];
10012
+ const spec = findHtmlStopColor(color, true);
10013
+ return spec === null ? null : [spec.fill, spec.stop ?? "black"];
9899
10014
  }
9900
10015
  var paintObj = {
9901
10016
  parent: null,
@@ -9952,6 +10067,12 @@ function resetHtmlFillPenWidth() {
9952
10067
  htmlFillPen = 1;
9953
10068
  }
9954
10069
  registerRenderState(resetHtmlFillPenWidth);
10070
+ var DEFAULT_LINE_STYLE = ["solid", "setlinewidth(1)"];
10071
+ function htmlBorderStyle(pen) {
10072
+ if (pen === 1 /* Dashed */) return ["dashed"];
10073
+ if (pen === 2 /* Dotted */) return ["dotted"];
10074
+ return DEFAULT_LINE_STYLE;
10075
+ }
9955
10076
  function penTypeOf(style2) {
9956
10077
  const st = htmlStyle(style2);
9957
10078
  if (st.dashed) return 1 /* Dashed */;
@@ -9959,12 +10080,13 @@ function penTypeOf(style2) {
9959
10080
  return 3 /* Solid */;
9960
10081
  }
9961
10082
  function withHtmlPaint(paint, job, drawFn) {
9962
- paintObj.fillColor = paint.fill !== void 0 ? resolveRenderColor(paint.fill) : { type: "none" };
10083
+ paintObj.fillColor = paint.fill !== void 0 ? resolveRenderColor(firstColor(paint.fill)) : { type: "none" };
9963
10084
  paintObj.penColor = paint.pen !== void 0 ? resolveRenderColor(paint.pen) : { type: "string", s: "transparent" };
9964
10085
  applyHtmlFill(paint);
9965
10086
  paintObj.pen = penTypeOf(paint.penStyle);
9966
10087
  paintObj.penWidth = paint.penWidth !== void 0 ? paint.penWidth : 1;
9967
10088
  paintObj.rawStyle = paintObj.pen === 3 /* Solid */ ? ["solid"] : [];
10089
+ gvrenderSetStyle(htmlBorderStyle(paintObj.pen));
9968
10090
  paintObj.emitState = job.obj?.emitState ?? 8 /* NDraw */;
9969
10091
  job.pushObj(paintObj);
9970
10092
  try {
@@ -9978,7 +10100,7 @@ function applyHtmlFill(paint) {
9978
10100
  paintObj.fill = paint.radial === true ? 3 /* Radial */ : 2 /* Linear */;
9979
10101
  paintObj.stopColor = resolveRenderColor(paint.stop);
9980
10102
  paintObj.gradientAngle = paint.gradientAngle ?? 0;
9981
- paintObj.gradientFrac = 0;
10103
+ paintObj.gradientFrac = paint.gradientFrac ?? 0;
9982
10104
  return;
9983
10105
  }
9984
10106
  paintObj.fill = paint.fill !== void 0 ? 1 /* Solid */ : 0 /* None */;
@@ -10247,11 +10369,12 @@ function emitHtmlLine(line, pos, renderer, job) {
10247
10369
  }
10248
10370
  function bgFillPaint(ctx) {
10249
10371
  const penWidth = htmlFillPenWidth();
10250
- const spec = parseGradientSpec(ctx.bgcolor);
10372
+ const spec = findHtmlStopColor(ctx.bgcolor);
10251
10373
  if (spec === null) return { fill: ctx.bgcolor, penWidth };
10252
10374
  return {
10253
- fill: spec[0],
10254
- stop: spec[1],
10375
+ fill: spec.fill,
10376
+ stop: spec.stop ?? "black",
10377
+ gradientFrac: spec.frac,
10255
10378
  gradientAngle: ctx.gradientangle ?? 0,
10256
10379
  radial: htmlStyle(ctx.style).radial,
10257
10380
  penWidth
@@ -11126,9 +11249,15 @@ function scanCdata(text, p, base, dataOf, tokens) {
11126
11249
  if (end > p) tokens.push({ kind: "cdata", start: base + p, end: base + end, data: dataOf(base + p, base + end) });
11127
11250
  return close < 0 ? -1 : close + CDATA_CLOSE.length;
11128
11251
  }
11252
+ var CONTENT_NON_XML = /[\x00-\x08\x0b\x0c\x0e-\x1f\ufffe\uffff]|[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/;
11129
11253
  function scanText(text, p, base, tokens) {
11130
11254
  const e = text.indexOf("<", p);
11131
11255
  const slice = text.slice(p, e < 0 ? text.length : e);
11256
+ const bad = CONTENT_NON_XML.exec(slice)?.index;
11257
+ if (bad !== void 0) {
11258
+ if (bad > 0) tokens.push({ kind: "text", start: base + p, end: base + p + bad });
11259
+ return { at: p + bad, held: false, invalid: p + bad };
11260
+ }
11132
11261
  const from = e < 0 ? heldRefStart(slice) : void 0;
11133
11262
  const end = from === void 0 ? p + slice.length : p + from;
11134
11263
  if (end > p) tokens.push({ kind: "text", start: base + p, end: base + end });
@@ -11148,6 +11277,7 @@ function scanContent(text, base, inCdata, dataOf) {
11148
11277
  }
11149
11278
  if (text[p] !== "<") {
11150
11279
  const scanned = scanText(text, p, base, tokens);
11280
+ if (scanned.invalid !== void 0) return { tokens, consumed: scanned.at, invalid: base + scanned.invalid, inCdata: false };
11151
11281
  if (scanned.held) return { tokens, consumed: scanned.at, inCdata: false };
11152
11282
  p = scanned.at;
11153
11283
  continue;
@@ -12154,6 +12284,72 @@ var parseHtmlLabelRv = (src, stderr) => {
12154
12284
  };
12155
12285
  var parseHtmlLabel = (src) => parseHtmlLabelRv(src, new StderrLines(() => void 0)).label;
12156
12286
 
12287
+ // src/gvc/image-resolver.ts
12288
+ var activeResolver = null;
12289
+ function setImageResolver(fn) {
12290
+ if (fn !== null && typeof fn !== "function") {
12291
+ throw invalidArgType("resolver", "function or null", fn);
12292
+ }
12293
+ activeResolver = fn;
12294
+ }
12295
+ var EXT_MIME = {
12296
+ png: "image/png",
12297
+ jpg: "image/jpeg",
12298
+ jpeg: "image/jpeg",
12299
+ gif: "image/gif",
12300
+ svg: "image/svg+xml",
12301
+ webp: "image/webp"
12302
+ };
12303
+ var FALLBACK_MIME = "application/octet-stream";
12304
+ function inferMimeFromSrc(src) {
12305
+ const dot = src.lastIndexOf(".");
12306
+ if (dot < 0 || dot === src.length - 1) return FALLBACK_MIME;
12307
+ const ext = src.slice(dot + 1).toLowerCase();
12308
+ return EXT_MIME[ext] ?? FALLBACK_MIME;
12309
+ }
12310
+ function findImageBytes(src, resolver) {
12311
+ const active = resolver ?? activeResolver;
12312
+ if (active === null) return null;
12313
+ const result = active(src);
12314
+ if (result === null) return null;
12315
+ if (result instanceof Uint8Array) {
12316
+ return { bytes: result, mime: inferMimeFromSrc(src) };
12317
+ }
12318
+ return { bytes: result.bytes, mime: result.mime ?? inferMimeFromSrc(src) };
12319
+ }
12320
+ var B64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
12321
+ function base64Encode(bytes) {
12322
+ const len = bytes.length;
12323
+ const out = [];
12324
+ let i = 0;
12325
+ for (; i + 2 < len; i += 3) {
12326
+ const n = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2];
12327
+ out.push(
12328
+ B64_CHARS[n >> 18 & 63],
12329
+ B64_CHARS[n >> 12 & 63],
12330
+ B64_CHARS[n >> 6 & 63],
12331
+ B64_CHARS[n & 63]
12332
+ );
12333
+ }
12334
+ const remaining = len - i;
12335
+ if (remaining === 1) {
12336
+ const n = bytes[i] << 16;
12337
+ out.push(B64_CHARS[n >> 18 & 63], B64_CHARS[n >> 12 & 63], "==");
12338
+ } else if (remaining === 2) {
12339
+ const n = bytes[i] << 16 | bytes[i + 1] << 8;
12340
+ out.push(
12341
+ B64_CHARS[n >> 18 & 63],
12342
+ B64_CHARS[n >> 12 & 63],
12343
+ B64_CHARS[n >> 6 & 63],
12344
+ "="
12345
+ );
12346
+ }
12347
+ return out.join("");
12348
+ }
12349
+ function toDataUri(bytes, mime) {
12350
+ return "data:" + mime + ";base64," + base64Encode(bytes);
12351
+ }
12352
+
12157
12353
  // src/gvc/usershape.ts
12158
12354
  var activeSizer = null;
12159
12355
  function setImageSizer(sizer) {
@@ -12165,6 +12361,14 @@ function setImageSizer(sizer) {
12165
12361
  function findImageSize(src) {
12166
12362
  return activeSizer !== null ? activeSizer(src) : null;
12167
12363
  }
12364
+ var STRERROR_ENOENT = "No such file or directory";
12365
+ function imageIsSupplied(name, sizer, resolver) {
12366
+ const size = sizer !== void 0 ? sizer(name) : findImageSize(name);
12367
+ return size !== null || findImageBytes(name, resolver) !== null;
12368
+ }
12369
+ function imageOpenWarning(name) {
12370
+ return `${STRERROR_ENOENT} while opening ${name}`;
12371
+ }
12168
12372
 
12169
12373
  // src/common/pointset.ts
12170
12374
  function cmpPair(a, b) {
@@ -12217,363 +12421,6 @@ var PointSet = class {
12217
12421
  }
12218
12422
  };
12219
12423
 
12220
- // src/common/htmltable-fontinfo.ts
12221
- var SIZE_SAVEF = { fontsize: 0 };
12222
- var EMIT_SAVEF = { fontsize: 0 };
12223
- var pushFontInfo = (env, fp, savp) => {
12224
- if (fp.fontFace !== void 0) {
12225
- savp.fontname = env.fontname;
12226
- env.fontname = fp.fontFace;
12227
- } else savp.fontname = void 0;
12228
- if (env.fontcolor !== void 0) {
12229
- if (fp.fontColor !== void 0) {
12230
- savp.fontcolor = env.fontcolor;
12231
- env.fontcolor = fp.fontColor;
12232
- } else savp.fontcolor = void 0;
12233
- }
12234
- if (env.fontsize >= 0) {
12235
- if (fp.fontSize !== void 0 && fp.fontSize >= 0) {
12236
- savp.fontsize = env.fontsize;
12237
- env.fontsize = fp.fontSize;
12238
- } else savp.fontsize = -1;
12239
- }
12240
- };
12241
- var popFontInfo = (env, savp) => {
12242
- if (savp.fontname !== void 0) env.fontname = savp.fontname;
12243
- if (savp.fontcolor !== void 0) env.fontcolor = savp.fontcolor;
12244
- if (savp.fontsize >= 0) env.fontsize = savp.fontsize;
12245
- };
12246
- var withTableFont = (env, font, slot, fn) => {
12247
- if (font === void 0) return fn();
12248
- const savp = slot === "size" ? SIZE_SAVEF : EMIT_SAVEF;
12249
- pushFontInfo(env, font, savp);
12250
- const r = fn();
12251
- popFontInfo(env, savp);
12252
- return r;
12253
- };
12254
-
12255
- // src/common/htmltable.ts
12256
- var DEFAULT_BORDER = 1;
12257
- var DEFAULT_CELLPADDING = 2;
12258
- var DEFAULT_CELLSPACING = 2;
12259
- var DEFAULT_FONTSIZE = 14;
12260
- var findCol = (ps, row, startCol, colspan, rowspan) => {
12261
- let col = startCol;
12262
- let notFound = true;
12263
- const end = colspan - 1;
12264
- while (notFound) {
12265
- const lastc = col + end;
12266
- let c;
12267
- for (c = lastc; c >= col; c--) {
12268
- if (ps.isInPS(c, row)) break;
12269
- }
12270
- if (c >= col) col = c + 1;
12271
- else notFound = false;
12272
- }
12273
- for (let j = col; j < col + colspan; j++) {
12274
- for (let i = row; i < row + rowspan; i++) {
12275
- ps.addPS(j, i);
12276
- }
12277
- }
12278
- return col;
12279
- };
12280
- var defaultSizeEnv = () => ({ fontsize: DEFAULT_FONTSIZE, fontname: "" });
12281
- var itemFont = (item, env) => ({
12282
- fs: item.fontSize !== void 0 ? item.fontSize : env.fontsize,
12283
- face: item.fontFace !== void 0 ? item.fontFace : env.fontname
12284
- });
12285
- var measureItem = (item, measurer, env) => {
12286
- const { fs, face } = itemFont(item, env);
12287
- const flags = item.bold === true || item.italic === true ? { bold: item.bold === true, italic: item.italic === true } : void 0;
12288
- return measurer.measure(item.text ?? "", face, fs, flags);
12289
- };
12290
- var splitSizedLines = (texts, measurer, env) => {
12291
- const lines = [];
12292
- let cur = { items: [], width: 0, mxysize: 0, mxfsize: 0 };
12293
- const accumulate = (item) => {
12294
- const sz = measureItem(item, measurer, env);
12295
- cur.items.push(item);
12296
- cur.width += sz.w;
12297
- cur.mxysize = Math.max(cur.mxysize, sz.h);
12298
- cur.mxfsize = Math.max(cur.mxfsize, itemFont(item, env).fs);
12299
- };
12300
- const flush = (br) => {
12301
- if (cur.items.length === 0 && br !== void 0) {
12302
- const { br: _b, brAlign: _a, ...fontProps } = br;
12303
- accumulate({ text: "", ...fontProps });
12304
- }
12305
- lines.push(cur);
12306
- cur = { items: [], width: 0, mxysize: 0, mxfsize: 0 };
12307
- };
12308
- for (const txt of texts) {
12309
- for (const item of txt.items) {
12310
- if (item.br) {
12311
- flush(item);
12312
- continue;
12313
- }
12314
- if (item.text === void 0) continue;
12315
- accumulate(item);
12316
- }
12317
- if (cur.items.length > 0) flush();
12318
- }
12319
- return lines;
12320
- };
12321
- var itemHasFlags = (i) => i.bold === true || i.italic === true || i.underline === true || i.strikethrough === true || i.overline === true || i.subscript === true || i.superscript === true;
12322
- var htmlTextIsSimple = (lines, env) => {
12323
- let prevFs = -1;
12324
- let prevFace = null;
12325
- for (const ln of lines) {
12326
- const item = ln.items[0];
12327
- if (ln.items.length > 1 || itemHasFlags(item)) return false;
12328
- const { fs, face } = itemFont(item, env);
12329
- if (prevFs < 0) prevFs = fs;
12330
- else if (fs !== prevFs) return false;
12331
- if (prevFace === null) prevFace = face;
12332
- else if (face !== prevFace) return false;
12333
- }
12334
- return true;
12335
- };
12336
- var sizeTextContent = (texts, measurer, env = defaultSizeEnv()) => {
12337
- const lines = splitSizedLines(texts, measurer, env);
12338
- const simple = htmlTextIsSimple(lines, env);
12339
- let w = 0;
12340
- let h = 0;
12341
- for (const ln of lines) {
12342
- w = Math.max(w, ln.width);
12343
- const lsize = simple ? ln.mxysize : ln.mxfsize;
12344
- h += ln.items.length > 0 ? lsize : DEFAULT_FONTSIZE;
12345
- }
12346
- if (lines.length === 1) h = lines[0].items.length > 0 ? lines[0].mxysize : DEFAULT_FONTSIZE;
12347
- return { w, h };
12348
- };
12349
- var missingImages = /* @__PURE__ */ new WeakSet();
12350
- var sizeHtmlImg = (img, { imageSizer, stderr }) => {
12351
- if (img.width !== void 0 && img.height !== void 0) return missingImages.has(img) ? 1 : 0;
12352
- const sz = imageSizer !== void 0 ? imageSizer(img.src) : findImageSize(img.src);
12353
- if (sz !== null) {
12354
- img.width = sz.w;
12355
- img.height = sz.h;
12356
- return 0;
12357
- }
12358
- agerrLine(stderr, `Error: No or improper image file="${img.src}"`);
12359
- img.width = 0;
12360
- img.height = 0;
12361
- missingImages.add(img);
12362
- return 1;
12363
- };
12364
- var sizeContentItem = (item, measurer, env) => {
12365
- if (item.kind === "text") return { ...sizeTextContent([item], measurer, env), rv: 0 };
12366
- if (item.kind === "table") {
12367
- const rv = sizeTableInner(item, measurer, env);
12368
- return { ...item.dimen !== void 0 ? item.dimen : { w: 0, h: 0 }, rv };
12369
- }
12370
- if (item.kind === "image") {
12371
- const rv = sizeHtmlImg(item, env);
12372
- return { w: item.width ?? 0, h: item.height ?? 0, rv };
12373
- }
12374
- return { w: 0, h: 0, rv: 0 };
12375
- };
12376
- var cellPad = (cell2, tbl) => cell2.cellpadding !== void 0 ? cell2.cellpadding : tbl.cellpadding !== void 0 ? tbl.cellpadding : DEFAULT_CELLPADDING;
12377
- var cellBorder = (cell2, tbl) => {
12378
- if (cell2.border !== void 0) return cell2.border;
12379
- const cb = tbl.cellborder;
12380
- if (cb !== void 0 && cb >= 0) return cb;
12381
- if (tbl.border !== void 0) return tbl.border;
12382
- return DEFAULT_BORDER;
12383
- };
12384
- function inheritTablePenColor(tbl, parentColor) {
12385
- if (tbl.color === void 0) tbl.color = parentColor;
12386
- const tblColor = tbl.color;
12387
- for (const row of tbl.rows) {
12388
- for (const cell2 of row.cells) {
12389
- if (cell2.color === void 0) cell2.color = tblColor;
12390
- for (const item of cell2.content) {
12391
- if (item.kind === "table") inheritTablePenColor(item, cell2.color);
12392
- }
12393
- }
12394
- }
12395
- }
12396
- var WARN_CELL_TOO_SMALL = "Warning: cell size too small for content";
12397
- var WARN_CELL_UNSPECIFIED = "Warning: fixed cell size with unspecified width or height";
12398
- var WARN_TABLE_TOO_SMALL = "Warning: table size too small for content";
12399
- var WARN_TABLE_UNSPECIFIED = "Warning: fixed table size with unspecified width or height";
12400
- var sizeWarned = /* @__PURE__ */ new WeakSet();
12401
- var fixedCellCheck = (cell2, sz, warn, out) => {
12402
- if (!cell2.fixedsize) return { rv: 0, zero: false };
12403
- if (cell2.width && cell2.height) {
12404
- const small = (cell2.width < sz.w || cell2.height < sz.h) && cell2.content[0]?.kind !== "image";
12405
- if (small && warn) agerrLine(out, WARN_CELL_TOO_SMALL);
12406
- return { rv: small ? 1 : 0, zero: true };
12407
- }
12408
- if (warn) agerrLine(out, WARN_CELL_UNSPECIFIED);
12409
- return { rv: 1, zero: false };
12410
- };
12411
- var getCellSize = (cell2, tbl, measurer, env) => {
12412
- const margin = 2 * (cellPad(cell2, tbl) + cellBorder(cell2, tbl));
12413
- let cw = 0, ch = 0, rv = 0;
12414
- for (const item of cell2.content) {
12415
- const s = sizeContentItem(item, measurer, env);
12416
- cw = Math.max(cw, s.w);
12417
- ch += s.h;
12418
- rv |= s.rv;
12419
- }
12420
- let szx = cw + margin;
12421
- let szy = ch + margin;
12422
- const warn = !sizeWarned.has(cell2);
12423
- sizeWarned.add(cell2);
12424
- const fixed = fixedCellCheck(cell2, { w: szx, h: szy }, warn, env.stderr);
12425
- rv |= fixed.rv;
12426
- if (fixed.zero) {
12427
- szx = 0;
12428
- szy = 0;
12429
- }
12430
- const bw = cell2.width !== void 0 ? cell2.width : 0;
12431
- const bh = cell2.height !== void 0 ? cell2.height : 0;
12432
- return { w: Math.max(szx, bw), h: Math.max(szy, bh), rv };
12433
- };
12434
- var buildLayouts = (tbl, measurer, env) => {
12435
- const entries = [];
12436
- let rv = 0;
12437
- const ps = new PointSet();
12438
- let rowIdx = 0;
12439
- for (const row of tbl.rows) {
12440
- let col = 0;
12441
- for (const c of row.cells) {
12442
- if (c.kind !== "cell") {
12443
- continue;
12444
- }
12445
- const colspan = c.colspan !== void 0 ? c.colspan : 1;
12446
- const rowspan = c.rowspan !== void 0 ? c.rowspan : 1;
12447
- const { w, h, rv: cellRv } = getCellSize(c, tbl, measurer, env);
12448
- rv |= cellRv;
12449
- col = findCol(ps, rowIdx, col, colspan, rowspan);
12450
- entries.push({ cell: c, row: rowIdx, col, colspan, rowspan, w, h });
12451
- col += colspan;
12452
- }
12453
- rowIdx++;
12454
- }
12455
- return { entries, rv };
12456
- };
12457
- var setColWidths = (entries, ncols, spacing) => {
12458
- const widths = new Array(ncols + 1).fill(0);
12459
- for (const e of entries)
12460
- if (e.colspan === 1) widths[e.col] = Math.max(widths[e.col], e.w);
12461
- for (const e of entries) {
12462
- if (e.colspan === 1) continue;
12463
- const spanW = widths.slice(e.col, e.col + e.colspan).reduce((a, v) => a + v, 0);
12464
- const need = e.w - spanW - (e.colspan - 1) * spacing;
12465
- if (need > 0) {
12466
- const add2 = need / e.colspan;
12467
- for (let j = 0; j < e.colspan; j++) widths[e.col + j] += add2;
12468
- }
12469
- }
12470
- for (const e of entries) {
12471
- const spanW = widths.slice(e.col, e.col + e.colspan).reduce((a, v) => a + v, 0);
12472
- e.w = Math.max(e.w, spanW + (e.colspan - 1) * spacing);
12473
- }
12474
- return widths;
12475
- };
12476
- var setRowHeights = (entries, nrows, spacing) => {
12477
- const heights = new Array(nrows + 1).fill(0);
12478
- for (const e of entries)
12479
- if (e.rowspan === 1) heights[e.row] = Math.max(heights[e.row], e.h);
12480
- for (const e of entries) {
12481
- if (e.rowspan === 1) continue;
12482
- const spanH = heights.slice(e.row, e.row + e.rowspan).reduce((a, v) => a + v, 0);
12483
- const need = e.h - spanH - (e.rowspan - 1) * spacing;
12484
- if (need > 0) {
12485
- const add2 = need / e.rowspan;
12486
- for (let j = 0; j < e.rowspan; j++) heights[e.row + j] += add2;
12487
- }
12488
- }
12489
- for (const e of entries) {
12490
- const spanH = heights.slice(e.row, e.row + e.rowspan).reduce((a, v) => a + v, 0);
12491
- e.h = Math.max(e.h, spanH + (e.rowspan - 1) * spacing);
12492
- }
12493
- return heights;
12494
- };
12495
- var getSpacing = (tbl) => tbl.cellspacing !== void 0 ? tbl.cellspacing : DEFAULT_CELLSPACING;
12496
- var getBorder = (tbl) => tbl.border !== void 0 ? tbl.border : DEFAULT_BORDER;
12497
- var isTblFixed = (tbl) => tbl.fixedsize === true && tbl.width !== void 0 && tbl.height !== void 0;
12498
- var sumTableDims = (a) => {
12499
- let wd = (a.ncols + 1) * a.spacing + 2 * a.border;
12500
- let ht = (a.nrows + 1) * a.spacing + 2 * a.border;
12501
- for (let i = 0; i < a.ncols; i++) wd += a.widths[i];
12502
- for (let i = 0; i < a.nrows; i++) ht += a.heights[i];
12503
- return { wd, ht };
12504
- };
12505
- var layoutHtmlTable = (tbl, measurer, env = defaultSizeEnv()) => {
12506
- const spacing = getSpacing(tbl);
12507
- const border2 = getBorder(tbl);
12508
- const { entries, rv } = buildLayouts(tbl, measurer, env);
12509
- if (entries.length === 0) {
12510
- return { entries, widths: [], heights: [], spacing, border: border2, rv };
12511
- }
12512
- const ncols = Math.max(...entries.map((e) => e.col + e.colspan));
12513
- const nrows = Math.max(...entries.map((e) => e.row + e.rowspan));
12514
- const widths = setColWidths(entries, ncols, spacing);
12515
- const heights = setRowHeights(entries, nrows, spacing);
12516
- return { entries, widths, heights, spacing, border: border2, rv };
12517
- };
12518
- var warnFixedTable = (tbl, dims, out) => {
12519
- const warn = !sizeWarned.has(tbl);
12520
- sizeWarned.add(tbl);
12521
- if (tbl.fixedsize !== true) return 0;
12522
- if (tbl.width && tbl.height) {
12523
- if (tbl.width >= dims.wd && tbl.height >= dims.ht) return 0;
12524
- if (warn) agerrLine(out, WARN_TABLE_TOO_SMALL);
12525
- return 1;
12526
- }
12527
- if (warn) agerrLine(out, WARN_TABLE_UNSPECIFIED);
12528
- return 1;
12529
- };
12530
- var sizeTableBody = (tbl, measurer, env) => {
12531
- const { entries, widths, heights, spacing, border: border2, rv } = layoutHtmlTable(tbl, measurer, env);
12532
- if (entries.length === 0) {
12533
- const fixed2 = warnFixedTable(tbl, sumTableDims({ widths, heights, ncols: 0, nrows: 0, spacing, border: border2 }), env.stderr);
12534
- tbl.dimen = { w: 0, h: 0 };
12535
- return rv | fixed2;
12536
- }
12537
- const ncols = Math.max(...entries.map((e) => e.col + e.colspan));
12538
- const nrows = Math.max(...entries.map((e) => e.row + e.rowspan));
12539
- for (const e of entries) e.cell.dimen = { w: e.w, h: e.h };
12540
- const { wd, ht } = sumTableDims({ widths, heights, ncols, nrows, spacing, border: border2 });
12541
- const baseWd = tbl.width !== void 0 ? tbl.width : 0;
12542
- const baseHt = tbl.height !== void 0 ? tbl.height : 0;
12543
- const fixed = warnFixedTable(tbl, { wd, ht }, env.stderr);
12544
- const zeroContent = isTblFixed(tbl) && baseWd !== 0 && baseHt !== 0;
12545
- tbl.dimen = {
12546
- w: Math.max(zeroContent ? 0 : wd, baseWd),
12547
- h: Math.max(zeroContent ? 0 : ht, baseHt)
12548
- };
12549
- return rv | fixed;
12550
- };
12551
- var sizeTableInner = (tbl, measurer, env) => withTableFont(env, tbl.font, "size", () => sizeTableBody(tbl, measurer, env));
12552
- var sizeHtmlLabel = (label, measurer, env = defaultSizeEnv()) => {
12553
- if (label.kind === "table") {
12554
- const rv = sizeTableInner(label.table, measurer, env);
12555
- label.dimen = label.table.dimen;
12556
- return rv;
12557
- }
12558
- label.dimen = sizeTextContent(label.texts, measurer, env);
12559
- return 0;
12560
- };
12561
-
12562
- // src/common/splines-constants.ts
12563
- var REGULAREDGE = 1;
12564
- var FLATEDGE = 2;
12565
- var ARR_NONE = 0;
12566
- var BOTTOM = 1 << 0;
12567
- var RIGHT = 1 << 1;
12568
- var TOP = 1 << 2;
12569
- var LEFT = 1 << 3;
12570
- var SELF_EDGE_SIZE = 18;
12571
- var MILLIPOINT = 1e-3;
12572
- var FUDGE = 2;
12573
- var INIT_DELTA = 10;
12574
- var LOOP_TRIES = 15;
12575
- var ROUTESPL_FUDGE = 1e-4;
12576
-
12577
12424
  // src/common/textmeasure-lut-data-a.ts
12578
12425
  var TR = [
12579
12426
  -1,
@@ -17416,7 +17263,7 @@ function getFamilyMetrics(fontName) {
17416
17263
  if (!warnedFontNames.has(fontName)) {
17417
17264
  warnedFontNames.add(fontName);
17418
17265
  agwarningf(
17419
- `no hard-coded metrics for '${fontName}'. Falling back to 'Times' metrics`
17266
+ `Warning: no hard-coded metrics for '${fontName}'. Falling back to 'Times' metrics`
17420
17267
  );
17421
17268
  }
17422
17269
  return TIMES_FALLBACK;
@@ -17757,7 +17604,7 @@ function itemFace(item, finfo) {
17757
17604
  face: item.fontFace !== void 0 ? item.fontFace : finfo.fontname
17758
17605
  };
17759
17606
  }
17760
- function measureItem2(item, finfo, measurer) {
17607
+ function measureItem(item, finfo, measurer) {
17761
17608
  if (item.text === void 0) return null;
17762
17609
  const { fs, face } = itemFace(item, finfo);
17763
17610
  const flags = itemFontFlags(item);
@@ -17792,7 +17639,7 @@ function buildLineRuns(texts, finfo, measurer) {
17792
17639
  if (cur.items.length === 0 && br !== void 0) {
17793
17640
  const { br: _b, brAlign: _a, ...fontProps } = br;
17794
17641
  const empty = { text: "", ...fontProps };
17795
- const m = measureItem2(empty, finfo, measurer);
17642
+ const m = measureItem(empty, finfo, measurer);
17796
17643
  if (m !== null) accumulateItem(cur, empty, m);
17797
17644
  }
17798
17645
  cur.just = br?.brAlign;
@@ -17805,7 +17652,7 @@ function buildLineRuns(texts, finfo, measurer) {
17805
17652
  flush(item);
17806
17653
  continue;
17807
17654
  }
17808
- const m = measureItem2(item, finfo, measurer);
17655
+ const m = measureItem(item, finfo, measurer);
17809
17656
  if (m !== null) accumulateItem(cur, item, m);
17810
17657
  }
17811
17658
  if (cur.items.length > 0) flush();
@@ -17896,6 +17743,313 @@ function placeComplexRuns(runs, box, finfo, measurer) {
17896
17743
  return lines;
17897
17744
  }
17898
17745
 
17746
+ // src/common/htmltable-fontinfo.ts
17747
+ var SIZE_SAVEF = { fontsize: 0 };
17748
+ var EMIT_SAVEF = { fontsize: 0 };
17749
+ var pushFontInfo = (env, fp, savp) => {
17750
+ if (fp.fontFace !== void 0) {
17751
+ savp.fontname = env.fontname;
17752
+ env.fontname = fp.fontFace;
17753
+ } else savp.fontname = void 0;
17754
+ if (env.fontcolor !== void 0) {
17755
+ if (fp.fontColor !== void 0) {
17756
+ savp.fontcolor = env.fontcolor;
17757
+ env.fontcolor = fp.fontColor;
17758
+ } else savp.fontcolor = void 0;
17759
+ }
17760
+ if (env.fontsize >= 0) {
17761
+ if (fp.fontSize !== void 0 && fp.fontSize >= 0) {
17762
+ savp.fontsize = env.fontsize;
17763
+ env.fontsize = fp.fontSize;
17764
+ } else savp.fontsize = -1;
17765
+ }
17766
+ };
17767
+ var popFontInfo = (env, savp) => {
17768
+ if (savp.fontname !== void 0) env.fontname = savp.fontname;
17769
+ if (savp.fontcolor !== void 0) env.fontcolor = savp.fontcolor;
17770
+ if (savp.fontsize >= 0) env.fontsize = savp.fontsize;
17771
+ };
17772
+ var withTableFont = (env, font, slot, fn) => {
17773
+ if (font === void 0) return fn();
17774
+ const savp = slot === "size" ? SIZE_SAVEF : EMIT_SAVEF;
17775
+ pushFontInfo(env, font, savp);
17776
+ const r = fn();
17777
+ popFontInfo(env, savp);
17778
+ return r;
17779
+ };
17780
+
17781
+ // src/common/htmltable.ts
17782
+ var DEFAULT_BORDER = 1;
17783
+ var DEFAULT_CELLPADDING = 2;
17784
+ var DEFAULT_CELLSPACING = 2;
17785
+ var DEFAULT_FONTSIZE = 14;
17786
+ var findCol = (ps, row, startCol, colspan, rowspan) => {
17787
+ let col = startCol;
17788
+ let notFound = true;
17789
+ const end = colspan - 1;
17790
+ while (notFound) {
17791
+ const lastc = col + end;
17792
+ let c;
17793
+ for (c = lastc; c >= col; c--) {
17794
+ if (ps.isInPS(c, row)) break;
17795
+ }
17796
+ if (c >= col) col = c + 1;
17797
+ else notFound = false;
17798
+ }
17799
+ for (let j = col; j < col + colspan; j++) {
17800
+ for (let i = row; i < row + rowspan; i++) {
17801
+ ps.addPS(j, i);
17802
+ }
17803
+ }
17804
+ return col;
17805
+ };
17806
+ var defaultSizeEnv = () => ({ fontsize: DEFAULT_FONTSIZE, fontname: "" });
17807
+ var sizeTextContent = (texts, measurer, env = defaultSizeEnv()) => {
17808
+ const lines = buildLineRuns(texts, env, measurer);
17809
+ const simple = runsAreSimple(lines, env);
17810
+ let w = 0;
17811
+ let h = 0;
17812
+ for (const ln of lines) {
17813
+ w = Math.max(w, ln.width);
17814
+ const lsize = simple ? ln.height : ln.fontSize;
17815
+ h += ln.items.length > 0 ? lsize : DEFAULT_FONTSIZE;
17816
+ }
17817
+ if (lines.length === 1) h = lines[0].items.length > 0 ? lines[0].height : DEFAULT_FONTSIZE;
17818
+ return { w, h };
17819
+ };
17820
+ var missingImages = { set: /* @__PURE__ */ new WeakSet() };
17821
+ var sizeHtmlImg = (img, { imageSizer, stderr }) => {
17822
+ if (img.width !== void 0 && img.height !== void 0) return missingImages.set.has(img) ? 1 : 0;
17823
+ const sz = imageSizer !== void 0 ? imageSizer(img.src) : findImageSize(img.src);
17824
+ if (sz !== null) {
17825
+ img.width = sz.w;
17826
+ img.height = sz.h;
17827
+ return 0;
17828
+ }
17829
+ if (!imageIsSupplied(img.src, imageSizer)) agerrLine(stderr, `Warning: ${imageOpenWarning(img.src)}`);
17830
+ agerrLine(stderr, `Error: No or improper image file="${img.src}"`);
17831
+ img.width = 0;
17832
+ img.height = 0;
17833
+ missingImages.set.add(img);
17834
+ return 1;
17835
+ };
17836
+ var sizeContentItem = (item, measurer, env) => {
17837
+ if (item.kind === "text") return { ...sizeTextContent([item], measurer, env), rv: 0 };
17838
+ if (item.kind === "table") {
17839
+ const rv = sizeTableInner(item, measurer, env);
17840
+ return { ...item.dimen !== void 0 ? item.dimen : { w: 0, h: 0 }, rv };
17841
+ }
17842
+ if (item.kind === "image") {
17843
+ const rv = sizeHtmlImg(item, env);
17844
+ return { w: item.width ?? 0, h: item.height ?? 0, rv };
17845
+ }
17846
+ return { w: 0, h: 0, rv: 0 };
17847
+ };
17848
+ var cellPad = (cell2, tbl) => cell2.cellpadding !== void 0 ? cell2.cellpadding : tbl.cellpadding !== void 0 ? tbl.cellpadding : DEFAULT_CELLPADDING;
17849
+ var cellBorder = (cell2, tbl) => {
17850
+ if (cell2.border !== void 0) return cell2.border;
17851
+ const cb = tbl.cellborder;
17852
+ if (cb !== void 0 && cb >= 0) return cb;
17853
+ if (tbl.border !== void 0) return tbl.border;
17854
+ return DEFAULT_BORDER;
17855
+ };
17856
+ function inheritTablePenColor(tbl, parentColor) {
17857
+ if (tbl.color === void 0) tbl.color = parentColor;
17858
+ const tblColor = tbl.color;
17859
+ for (const row of tbl.rows) {
17860
+ for (const cell2 of row.cells) {
17861
+ if (cell2.color === void 0) cell2.color = tblColor;
17862
+ for (const item of cell2.content) {
17863
+ if (item.kind === "table") inheritTablePenColor(item, cell2.color);
17864
+ }
17865
+ }
17866
+ }
17867
+ }
17868
+ var WARN_CELL_TOO_SMALL = "Warning: cell size too small for content";
17869
+ var WARN_CELL_UNSPECIFIED = "Warning: fixed cell size with unspecified width or height";
17870
+ var WARN_TABLE_TOO_SMALL = "Warning: table size too small for content";
17871
+ var WARN_TABLE_UNSPECIFIED = "Warning: fixed table size with unspecified width or height";
17872
+ var sizeWarned = { set: /* @__PURE__ */ new WeakSet() };
17873
+ registerRenderState(() => {
17874
+ missingImages.set = /* @__PURE__ */ new WeakSet();
17875
+ sizeWarned.set = /* @__PURE__ */ new WeakSet();
17876
+ });
17877
+ var fixedCellCheck = (cell2, sz, warn, out) => {
17878
+ if (!cell2.fixedsize) return { rv: 0, zero: false };
17879
+ if (cell2.width && cell2.height) {
17880
+ const small = (cell2.width < sz.w || cell2.height < sz.h) && cell2.content[0]?.kind !== "image";
17881
+ if (small && warn) agerrLine(out, WARN_CELL_TOO_SMALL);
17882
+ return { rv: small ? 1 : 0, zero: true };
17883
+ }
17884
+ if (warn) agerrLine(out, WARN_CELL_UNSPECIFIED);
17885
+ return { rv: 1, zero: false };
17886
+ };
17887
+ var getCellSize = (cell2, tbl, measurer, env) => {
17888
+ const margin = 2 * (cellPad(cell2, tbl) + cellBorder(cell2, tbl));
17889
+ let cw = 0, ch = 0, rv = 0;
17890
+ for (const item of cell2.content) {
17891
+ const s = sizeContentItem(item, measurer, env);
17892
+ cw = Math.max(cw, s.w);
17893
+ ch += s.h;
17894
+ rv |= s.rv;
17895
+ }
17896
+ let szx = cw + margin;
17897
+ let szy = ch + margin;
17898
+ const warn = !sizeWarned.set.has(cell2);
17899
+ sizeWarned.set.add(cell2);
17900
+ const fixed = fixedCellCheck(cell2, { w: szx, h: szy }, warn, env.stderr);
17901
+ rv |= fixed.rv;
17902
+ if (fixed.zero) {
17903
+ szx = 0;
17904
+ szy = 0;
17905
+ }
17906
+ const bw = cell2.width !== void 0 ? cell2.width : 0;
17907
+ const bh = cell2.height !== void 0 ? cell2.height : 0;
17908
+ return { w: Math.max(szx, bw), h: Math.max(szy, bh), rv };
17909
+ };
17910
+ var buildLayouts = (tbl, measurer, env) => {
17911
+ const entries = [];
17912
+ let rv = 0;
17913
+ const ps = new PointSet();
17914
+ let rowIdx = 0;
17915
+ for (const row of tbl.rows) {
17916
+ let col = 0;
17917
+ for (const c of row.cells) {
17918
+ if (c.kind !== "cell") {
17919
+ continue;
17920
+ }
17921
+ const colspan = c.colspan !== void 0 ? c.colspan : 1;
17922
+ const rowspan = c.rowspan !== void 0 ? c.rowspan : 1;
17923
+ const { w, h, rv: cellRv } = getCellSize(c, tbl, measurer, env);
17924
+ rv |= cellRv;
17925
+ col = findCol(ps, rowIdx, col, colspan, rowspan);
17926
+ entries.push({ cell: c, row: rowIdx, col, colspan, rowspan, w, h });
17927
+ col += colspan;
17928
+ }
17929
+ rowIdx++;
17930
+ }
17931
+ return { entries, rv };
17932
+ };
17933
+ var setColWidths = (entries, ncols, spacing) => {
17934
+ const widths = new Array(ncols + 1).fill(0);
17935
+ for (const e of entries)
17936
+ if (e.colspan === 1) widths[e.col] = Math.max(widths[e.col], e.w);
17937
+ for (const e of entries) {
17938
+ if (e.colspan === 1) continue;
17939
+ const spanW = widths.slice(e.col, e.col + e.colspan).reduce((a, v) => a + v, 0);
17940
+ const need = e.w - spanW - (e.colspan - 1) * spacing;
17941
+ if (need > 0) {
17942
+ const add2 = need / e.colspan;
17943
+ for (let j = 0; j < e.colspan; j++) widths[e.col + j] += add2;
17944
+ }
17945
+ }
17946
+ for (const e of entries) {
17947
+ const spanW = widths.slice(e.col, e.col + e.colspan).reduce((a, v) => a + v, 0);
17948
+ e.w = Math.max(e.w, spanW + (e.colspan - 1) * spacing);
17949
+ }
17950
+ return widths;
17951
+ };
17952
+ var setRowHeights = (entries, nrows, spacing) => {
17953
+ const heights = new Array(nrows + 1).fill(0);
17954
+ for (const e of entries)
17955
+ if (e.rowspan === 1) heights[e.row] = Math.max(heights[e.row], e.h);
17956
+ for (const e of entries) {
17957
+ if (e.rowspan === 1) continue;
17958
+ const spanH = heights.slice(e.row, e.row + e.rowspan).reduce((a, v) => a + v, 0);
17959
+ const need = e.h - spanH - (e.rowspan - 1) * spacing;
17960
+ if (need > 0) {
17961
+ const add2 = need / e.rowspan;
17962
+ for (let j = 0; j < e.rowspan; j++) heights[e.row + j] += add2;
17963
+ }
17964
+ }
17965
+ for (const e of entries) {
17966
+ const spanH = heights.slice(e.row, e.row + e.rowspan).reduce((a, v) => a + v, 0);
17967
+ e.h = Math.max(e.h, spanH + (e.rowspan - 1) * spacing);
17968
+ }
17969
+ return heights;
17970
+ };
17971
+ var getSpacing = (tbl) => tbl.cellspacing !== void 0 ? tbl.cellspacing : DEFAULT_CELLSPACING;
17972
+ var getBorder = (tbl) => tbl.border !== void 0 ? tbl.border : DEFAULT_BORDER;
17973
+ var isTblFixed = (tbl) => tbl.fixedsize === true && tbl.width !== void 0 && tbl.height !== void 0;
17974
+ var sumTableDims = (a) => {
17975
+ let wd = (a.ncols + 1) * a.spacing + 2 * a.border;
17976
+ let ht = (a.nrows + 1) * a.spacing + 2 * a.border;
17977
+ for (let i = 0; i < a.ncols; i++) wd += a.widths[i];
17978
+ for (let i = 0; i < a.nrows; i++) ht += a.heights[i];
17979
+ return { wd, ht };
17980
+ };
17981
+ var layoutHtmlTable = (tbl, measurer, env = defaultSizeEnv()) => {
17982
+ const spacing = getSpacing(tbl);
17983
+ const border2 = getBorder(tbl);
17984
+ const { entries, rv } = buildLayouts(tbl, measurer, env);
17985
+ if (entries.length === 0) {
17986
+ return { entries, widths: [], heights: [], spacing, border: border2, rv };
17987
+ }
17988
+ const ncols = Math.max(...entries.map((e) => e.col + e.colspan));
17989
+ const nrows = Math.max(...entries.map((e) => e.row + e.rowspan));
17990
+ const widths = setColWidths(entries, ncols, spacing);
17991
+ const heights = setRowHeights(entries, nrows, spacing);
17992
+ return { entries, widths, heights, spacing, border: border2, rv };
17993
+ };
17994
+ var warnFixedTable = (tbl, dims, out) => {
17995
+ const warn = !sizeWarned.set.has(tbl);
17996
+ sizeWarned.set.add(tbl);
17997
+ if (tbl.fixedsize !== true) return 0;
17998
+ if (tbl.width && tbl.height) {
17999
+ if (tbl.width >= dims.wd && tbl.height >= dims.ht) return 0;
18000
+ if (warn) agerrLine(out, WARN_TABLE_TOO_SMALL);
18001
+ return 1;
18002
+ }
18003
+ if (warn) agerrLine(out, WARN_TABLE_UNSPECIFIED);
18004
+ return 1;
18005
+ };
18006
+ var sizeTableBody = (tbl, measurer, env) => {
18007
+ const { entries, widths, heights, spacing, border: border2, rv } = layoutHtmlTable(tbl, measurer, env);
18008
+ if (entries.length === 0) {
18009
+ const fixed2 = warnFixedTable(tbl, sumTableDims({ widths, heights, ncols: 0, nrows: 0, spacing, border: border2 }), env.stderr);
18010
+ tbl.dimen = { w: 0, h: 0 };
18011
+ return rv | fixed2;
18012
+ }
18013
+ const ncols = Math.max(...entries.map((e) => e.col + e.colspan));
18014
+ const nrows = Math.max(...entries.map((e) => e.row + e.rowspan));
18015
+ for (const e of entries) e.cell.dimen = { w: e.w, h: e.h };
18016
+ const { wd, ht } = sumTableDims({ widths, heights, ncols, nrows, spacing, border: border2 });
18017
+ const baseWd = tbl.width !== void 0 ? tbl.width : 0;
18018
+ const baseHt = tbl.height !== void 0 ? tbl.height : 0;
18019
+ const fixed = warnFixedTable(tbl, { wd, ht }, env.stderr);
18020
+ const zeroContent = isTblFixed(tbl) && baseWd !== 0 && baseHt !== 0;
18021
+ tbl.dimen = {
18022
+ w: Math.max(zeroContent ? 0 : wd, baseWd),
18023
+ h: Math.max(zeroContent ? 0 : ht, baseHt)
18024
+ };
18025
+ return rv | fixed;
18026
+ };
18027
+ var sizeTableInner = (tbl, measurer, env) => withTableFont(env, tbl.font, "size", () => sizeTableBody(tbl, measurer, env));
18028
+ var sizeHtmlLabel = (label, measurer, env = defaultSizeEnv()) => {
18029
+ if (label.kind === "table") {
18030
+ const rv = sizeTableInner(label.table, measurer, env);
18031
+ label.dimen = label.table.dimen;
18032
+ return rv;
18033
+ }
18034
+ label.dimen = sizeTextContent(label.texts, measurer, env);
18035
+ return 0;
18036
+ };
18037
+
18038
+ // src/common/splines-constants.ts
18039
+ var REGULAREDGE = 1;
18040
+ var FLATEDGE = 2;
18041
+ var ARR_NONE = 0;
18042
+ var BOTTOM = 1 << 0;
18043
+ var RIGHT = 1 << 1;
18044
+ var TOP = 1 << 2;
18045
+ var LEFT = 1 << 3;
18046
+ var SELF_EDGE_SIZE = 18;
18047
+ var MILLIPOINT = 1e-3;
18048
+ var FUDGE = 2;
18049
+ var INIT_DELTA = 10;
18050
+ var LOOP_TRIES = 15;
18051
+ var ROUTESPL_FUDGE = 1e-4;
18052
+
17899
18053
  // src/common/htmltable-pos.ts
17900
18054
  function alignContentBox(box, cell2, w, h) {
17901
18055
  const out = { ll: { ...box.ll }, ur: { ...box.ur } };
@@ -18693,7 +18847,7 @@ function transformUnitVertex(R2, g, c, bb) {
18693
18847
  const r = libmHypot(D.x, D.y);
18694
18848
  return { x: r * Math.cos(alpha) * bb.x, y: r * Math.sin(alpha) * bb.y };
18695
18849
  }
18696
- function polygonVertices(bb, g, isBox3) {
18850
+ function polygonVertices(bb, g, isBox4) {
18697
18851
  const sectorangle = 2 * Math.PI / g.sides;
18698
18852
  const sidelength = Math.sin(sectorangle / 2);
18699
18853
  const c = {
@@ -18711,7 +18865,7 @@ function polygonVertices(bb, g, isBox3) {
18711
18865
  R2.y = fma(sidelength, Math.sin(angle), R2.y);
18712
18866
  const P = transformUnitVertex(R2, g, c, bb);
18713
18867
  verts.push(P);
18714
- if (isBox3) {
18868
+ if (isBox4) {
18715
18869
  verts.push({ x: -P.x, y: P.y }, { x: -P.x, y: -P.y }, { x: P.x, y: -P.y });
18716
18870
  break;
18717
18871
  }
@@ -18802,14 +18956,14 @@ function starVertexGen(bb) {
18802
18956
  }
18803
18957
  return { verts: starVertices(bb.x, bb.y), xmax: sz.x / 2, ymax: sz.y / 2 };
18804
18958
  }
18805
- function polygonBB(bb, minSize, p, sides2, isBox3) {
18959
+ function polygonBB(bb, minSize, p, sides2, isBox4) {
18806
18960
  const geom = {
18807
18961
  sides: sides2,
18808
18962
  orientation: p.orientation,
18809
18963
  distortion: p.distortion,
18810
18964
  skew: p.skew
18811
18965
  };
18812
- const { verts, xmax, ymax } = p.optionShape === STAR ? starVertexGen(bb) : polygonVertices(bb, geom, isBox3);
18966
+ const { verts, xmax, ymax } = p.optionShape === STAR ? starVertexGen(bb) : polygonVertices(bb, geom, isBox4);
18813
18967
  const xmax2 = 2 * xmax;
18814
18968
  const ymax2 = 2 * ymax;
18815
18969
  const nbb = { x: Math.max(minSize.x, xmax2), y: Math.max(minSize.y, ymax2) };
@@ -18821,7 +18975,7 @@ function polygonBB(bb, minSize, p, sides2, isBox3) {
18821
18975
  v.x *= scalex;
18822
18976
  v.y *= scaley;
18823
18977
  }
18824
- return { ...polygonPeripheryBB(verts, isBox3 ? 4 : sides2, p, nbb), base: nbb };
18978
+ return { ...polygonPeripheryBB(verts, isBox4 ? 4 : sides2, p, nbb), base: nbb };
18825
18979
  }
18826
18980
  function gvNodesize(widthPts, heightPts, flip) {
18827
18981
  if (flip) return { lw: heightPts / 2, rw: heightPts / 2, ht: widthPts };
@@ -18846,9 +19000,9 @@ function applySizeConstraints(p, bb0, width0, height0) {
18846
19000
  function polySize(p) {
18847
19001
  const init = initialSizePts(p);
18848
19002
  const dimen = quantize(padLabelDimen(p.labelDimen, p.margin, p.isPlain), p.quantumIn);
18849
- const { sides: sides2, isBox: isBox3 } = effectiveShape(p);
19003
+ const { sides: sides2, isBox: isBox4 } = effectiveShape(p);
18850
19004
  let bb = { x: dimen.x, y: dimen.y };
18851
- if (isBox3) {
19005
+ if (isBox4) {
18852
19006
  } else if (p.optionShape === STAR) {
18853
19007
  bb = starSize(bb);
18854
19008
  } else if (p.optionShape === CYLINDER) {
@@ -18860,16 +19014,16 @@ function polySize(p) {
18860
19014
  const c = applySizeConstraints(p, bb, init.width, init.height);
18861
19015
  const penwidth = p.penwidth ?? 1;
18862
19016
  const hasOutline = penwidth > 0 || p.peripheries < 1;
18863
- 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);
19017
+ 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);
18864
19018
  const result = assembleResult(p, dimen, grown, c.fixedshape);
18865
- return { ...result, ...labelSpace(p, dimen, c.bb, minBb, isBox3, c.fixedshape) };
19019
+ return { ...result, ...labelSpace(p, dimen, c.bb, minBb, isBox4, c.fixedshape) };
18866
19020
  }
18867
- function labelSpace(p, dimen, bb, minBb, isBox3, fixedshape) {
19021
+ function labelSpace(p, dimen, bb, minBb, isBox4, fixedshape) {
18868
19022
  const spacex = dimen.x - p.labelDimen.x;
18869
19023
  let spaceX;
18870
19024
  if (p.nojustify) {
18871
19025
  spaceX = dimen.x - spacex;
18872
- } else if (isBox3) {
19026
+ } else if (isBox4) {
18873
19027
  spaceX = Math.max(dimen.x, bb.x) - spacex;
18874
19028
  } else if (dimen.y < bb.y) {
18875
19029
  spaceX = Math.max(dimen.x, bb.x * Math.sqrt(1 - dimen.y * dimen.y / (bb.y * bb.y))) - spacex;
@@ -18882,8 +19036,8 @@ function labelSpace(p, dimen, bb, minBb, isBox3, fixedshape) {
18882
19036
  function effectiveShape(p) {
18883
19037
  let sides2 = p.sides;
18884
19038
  if (sides2 <= 2 && (p.distortion !== 0 || p.skew !== 0)) sides2 = 120;
18885
- const isBox3 = sides2 === 4 && Math.abs(p.orientation % 90) < 0.5 && p.distortion === 0 && p.skew === 0;
18886
- return { sides: sides2, isBox: isBox3 };
19039
+ const isBox4 = sides2 === 4 && Math.abs(p.orientation % 90) < 0.5 && p.distortion === 0 && p.skew === 0;
19040
+ return { sides: sides2, isBox: isBox4 };
18887
19041
  }
18888
19042
  function labelValign(p) {
18889
19043
  const ll = p.labelloc?.[0];
@@ -18977,7 +19131,7 @@ function copyVirtualEdgeInfo(e, orig) {
18977
19131
  e.seq = orig.seq;
18978
19132
  }
18979
19133
  function newVirtualEdge(u, v, orig) {
18980
- const e = new Edge(u, v, "");
19134
+ const e = new Edge(u, v, "", true);
18981
19135
  e.info.edge_type = VIRTUAL;
18982
19136
  if (orig) {
18983
19137
  copyVirtualEdgeInfo(e, orig);
@@ -19078,7 +19232,7 @@ function removeFromRank(g, n) {
19078
19232
  }
19079
19233
  }
19080
19234
  function virtualNode(g) {
19081
- const n = new Node(0, "", g.root);
19235
+ const n = new Node(0, "", g.root, true);
19082
19236
  n.info.node_type = VIRTUAL;
19083
19237
  n.info.lw = 1;
19084
19238
  n.info.rw = 1;
@@ -19370,10 +19524,10 @@ var ARROW_EPSILON = 1e-4;
19370
19524
  var vsub2 = (p, q) => ({ x: p.x - q.x, y: p.y - q.y });
19371
19525
  var vadd2 = (p, q) => ({ x: p.x + q.x, y: p.y + q.y });
19372
19526
  var vscale = (c, p) => ({ x: c * p.x, y: c * p.y });
19373
- var negUnit = (u, dist4) => {
19527
+ var negUnit = (u, dist5) => {
19374
19528
  if (u.x === 0 && u.y === 0) return { x: 0, y: 0 };
19375
19529
  const h = Math.hypot(u.x, u.y);
19376
- return { x: dist4 * (-u.x / h), y: dist4 * (-u.y / h) };
19530
+ return { x: dist5 * (-u.x / h), y: dist5 * (-u.y / h) };
19377
19531
  };
19378
19532
  var backwardDelta = (u, penwidth) => negUnit(u, penwidth / 2);
19379
19533
  function axialProjection(phiSrc, from, to, sign2) {
@@ -19922,9 +20076,9 @@ function makeEllipseInsideFn(rx, ry, penwidth = DEFAULT_NODEPENWIDTH) {
19922
20076
  return (lx, ly) => lx * lx / (erx * erx) + ly * ly / (ery * ery) < 1;
19923
20077
  }
19924
20078
  function tailArrowEndClip(path4, tailTip, elen) {
19925
- if (elen <= 0) return path4;
19926
- const inside = (lx, ly) => Math.hypot(lx, ly) <= elen;
19927
- return bezierClipNode(path4, tailTip.x, tailTip.y, inside, true);
20079
+ const sp = [path4[3], path4[2], path4[1], tailTip];
20080
+ const clipped = elen > 0 ? bezierClipNode(sp, 0, 0, (x, y) => distFused({ x, y }, tailTip) <= elen, false) : sp;
20081
+ return [clipped[3], clipped[2], clipped[1], clipped[0]];
19928
20082
  }
19929
20083
 
19930
20084
  // src/layout/dot/edge-route-geom.ts
@@ -19983,6 +20137,7 @@ function arrowDrawOpsForEnd(e, end, tip2, dir, penwidth) {
19983
20137
 
19984
20138
  // src/common/splines-clip.ts
19985
20139
  var ARR_NORM = 1;
20140
+ var dist = distFused;
19986
20141
  var SplineClipHelper = class _SplineClipHelper {
19987
20142
  static makeEmptySpl() {
19988
20143
  return { list: [], size: 0, bb: { ll: { x: 0, y: 0 }, ur: { x: 0, y: 0 } } };
@@ -20075,15 +20230,11 @@ var SplineClipHelper = class _SplineClipHelper {
20075
20230
  if (j) return [eflag, sflag];
20076
20231
  return [sflag, eflag];
20077
20232
  }
20078
- /** DIST(p, q). */
20079
- static dist(p, q) {
20080
- return Math.hypot(p.x - q.x, p.y - q.y);
20081
- }
20082
20233
  /** Sphere inside-fn around `tip` with radius `r` for bezierClip. */
20083
20234
  static sphereCtx(tip2, r) {
20084
20235
  return {
20085
20236
  ctx: { nodeCoord: { x: 0, y: 0 }, rw: 0, bp: null },
20086
- fn: (_c, p) => _SplineClipHelper.dist(p, tip2) <= r
20237
+ fn: (_c, p) => dist(p, tip2) <= r
20087
20238
  };
20088
20239
  }
20089
20240
  /**
@@ -20115,7 +20266,7 @@ var SplineClipHelper = class _SplineClipHelper {
20115
20266
  );
20116
20267
  spl.eflag = eflag;
20117
20268
  spl.ep = ps[endp + 3];
20118
- if (endp > startp && _SplineClipHelper.dist(ps[endp], ps[endp + 3]) < elen) {
20269
+ if (endp > startp && dist(ps[endp], ps[endp + 3]) < elen) {
20119
20270
  endp -= 3;
20120
20271
  }
20121
20272
  const sp = [spl.ep, ps[endp + 2], ps[endp + 1], ps[endp]];
@@ -20142,7 +20293,7 @@ var SplineClipHelper = class _SplineClipHelper {
20142
20293
  );
20143
20294
  spl.sflag = sflag;
20144
20295
  spl.sp = ps[startp];
20145
- if (endp > startp && _SplineClipHelper.dist(ps[startp], ps[startp + 3]) < slen) {
20296
+ if (endp > startp && dist(ps[startp], ps[startp + 3]) < slen) {
20146
20297
  startp += 3;
20147
20298
  }
20148
20299
  const sp = [ps[startp + 3], ps[startp + 2], ps[startp + 1], spl.sp];
@@ -20243,7 +20394,7 @@ var SplineClipHelper = class _SplineClipHelper {
20243
20394
  if (sflag && eflag && endp === startp) {
20244
20395
  const p = ps[endp];
20245
20396
  const q = ps[endp + 3];
20246
- const d = _SplineClipHelper.dist(p, q);
20397
+ const d = dist(p, q);
20247
20398
  let hlen = hlen0;
20248
20399
  let tlen = tlen0;
20249
20400
  if (hlen + tlen >= d) {
@@ -20286,7 +20437,7 @@ var SplineClipHelper = class _SplineClipHelper {
20286
20437
  let hlen = hlen0;
20287
20438
  const p = ps[endp];
20288
20439
  const q = ps[endp + 3];
20289
- const maxd = 0.9 * _SplineClipHelper.dist(p, q);
20440
+ const maxd = 0.9 * dist(p, q);
20290
20441
  if (hlen >= maxd) hlen = maxd;
20291
20442
  const r = { x: p.x, y: p.y };
20292
20443
  if (p.y === q.y) {
@@ -20306,7 +20457,7 @@ var SplineClipHelper = class _SplineClipHelper {
20306
20457
  let tlen = tlen0;
20307
20458
  const p = ps[startp];
20308
20459
  const q = ps[startp + 3];
20309
- const maxd = 0.9 * _SplineClipHelper.dist(p, q);
20460
+ const maxd = 0.9 * dist(p, q);
20310
20461
  if (tlen >= maxd) tlen = maxd;
20311
20462
  const r = { x: p.x, y: p.y };
20312
20463
  if (p.y === q.y) {
@@ -22538,13 +22689,13 @@ function dfsNode(Xg, v, frames) {
22538
22689
  frames.push({ v, edges: v.outEdges(Xg).slice(), i: 0 });
22539
22690
  }
22540
22691
  function dfsStep2(Xg, frames) {
22541
- const fr3 = frames[frames.length - 1];
22542
- if (fr3.i < fr3.edges.length) {
22543
- const e = fr3.edges[fr3.i++];
22692
+ const fr7 = frames[frames.length - 1];
22693
+ if (fr7.i < fr7.edges.length) {
22694
+ const e = fr7.edges[fr7.i++];
22544
22695
  if (e.head.info.onstack) reverseEdge2(Xg, e);
22545
22696
  else if (!e.head.info.mark) dfsNode(Xg, e.head, frames);
22546
22697
  } else {
22547
- fr3.v.info.onstack = 0;
22698
+ fr7.v.info.onstack = 0;
22548
22699
  frames.pop();
22549
22700
  }
22550
22701
  }
@@ -23718,7 +23869,7 @@ function pruneForeignClusterNodes(par, clust) {
23718
23869
  }
23719
23870
  function markClusterNode(clust, n, g) {
23720
23871
  if ((n.info.ranktype ?? 0) !== 0) {
23721
- agwarningf(`${n.name} was already in a rankset, deleted from cluster ${g.name}`, "error");
23872
+ agwarningf(`${n.name} was already in a rankset, deleted from cluster ${g.name}`);
23722
23873
  agDeleteFromCluster(clust, n);
23723
23874
  return;
23724
23875
  }
@@ -24973,17 +25124,27 @@ function buildNodeLabel(n, g, measurer) {
24973
25124
  const content = isHtml ? htmlValueContent(labelAttr) : labelAttr ?? n.name;
24974
25125
  n.info.label = makeAnyLabel(content, isHtml, font, measurer, n);
24975
25126
  }
25127
+ function warnMissingImage(n, g, shapefile) {
25128
+ if (shapefile !== void 0 && shapefile !== "" && nodeAttr(n, g, "shape") !== "epsf") return;
25129
+ const image = nodeAttr(n, g, "image");
25130
+ if (image === void 0 || image === "") return;
25131
+ const gvc = g.root.info.gvc;
25132
+ if (imageIsSupplied(image, gvc?.imageSizer, gvc?.imageResolver)) return;
25133
+ agwarningf(imageOpenWarning(image));
25134
+ agwarningf(`No or improper image="${image}" for node "${n.name}"`);
25135
+ }
24976
25136
  function polyInit(n, g, measurer) {
24977
25137
  const shapeName2 = nodeAttr(n, g, "shape") ?? "ellipse";
24978
25138
  const shapefile = nodeAttr(n, g, "shapefile");
24979
25139
  n.info.shape = bindShape(shapeName2, shapefile);
24980
25140
  if (shapefile !== void 0 && shapefile !== "" && shapeName2 !== "epsf") {
24981
- agwarningf(`No or improper shapefile="${shapefile}" for node "${n.name}"`, "error");
25141
+ agwarningf(`No or improper shapefile="${shapefile}" for node "${n.name}"`);
24982
25142
  }
24983
25143
  if (n.info.shape.kind === 2 /* SH_RECORD */) {
24984
25144
  if (n.info.shape_info === void 0) recordNodeInit(n, g, measurer);
24985
25145
  return;
24986
25146
  }
25147
+ warnMissingImage(n, g, shapefile);
24987
25148
  buildNodeLabel(n, g, measurer);
24988
25149
  if (n.info.shape_info !== void 0) return;
24989
25150
  const polyDesc = n.info.shape.polygon;
@@ -25109,8 +25270,8 @@ function drawWedge(seg2, e, ctx) {
25109
25270
  ctx.renderer.bezier(ptsUp.map((p) => ({ x: p.x, y: -p.y })), true, ctx.job);
25110
25271
  return angle1;
25111
25272
  }
25112
- function wedgedEllipse(job, pf, clrs, renderer) {
25113
- const { segs, error } = parseSegs(clrs);
25273
+ function wedgedEllipse(job, pf, clrs, renderer, context) {
25274
+ const { segs, error } = parseSegs(clrs, context);
25114
25275
  if (error === 1 || error === 2) return error;
25115
25276
  const ctrX = (pf[0].x + pf[1].x) / 2;
25116
25277
  const ctrY = (pf[0].y + pf[1].y) / 2;
@@ -25142,8 +25303,8 @@ function drawBand(p, seg2, ctx) {
25142
25303
  ctx.renderer.polygon([...p], true, ctx.job);
25143
25304
  p[0].x = p[3].x = p[1].x;
25144
25305
  }
25145
- function stripedBox(job, pts, clrs, rotate, renderer) {
25146
- const { segs, error } = parseSegs(clrs);
25306
+ function stripedBox(job, pts, clrs, rotate, renderer, context) {
25307
+ const { segs, error } = parseSegs(clrs, context);
25147
25308
  if (error === 1 || error === 2) return error;
25148
25309
  const p = rotate ? [{ ...pts[2] }, { ...pts[3] }, { ...pts[0] }, { ...pts[1] }] : [{ ...pts[0] }, { ...pts[1] }, { ...pts[2] }, { ...pts[3] }];
25149
25310
  const lastx = p[1].x;
@@ -25301,6 +25462,27 @@ function escapeXmlText(s) {
25301
25462
  return gvXmlEscape(s, FLAGS_TEXT);
25302
25463
  }
25303
25464
 
25465
+ // src/gvc/device-transform.ts
25466
+ function transformPoint(p, job) {
25467
+ if ((job.flags & GVRENDER_DOES_TRANSFORM) !== 0) {
25468
+ return p;
25469
+ }
25470
+ const sx = job.zoom * job.devscale.x;
25471
+ const sy = job.zoom * job.devscale.y;
25472
+ const tx = job.translation.x;
25473
+ const ty = job.translation.y;
25474
+ return applyScale(p, tx, ty, sx, sy);
25475
+ }
25476
+ function applyScale(p, tx, ty, sx, sy) {
25477
+ const x = (p.x + tx) * sx;
25478
+ const y = (p.y + ty) * sy;
25479
+ return buildPoint(x, y);
25480
+ }
25481
+ function buildPoint(x, y) {
25482
+ const pt = { x, y };
25483
+ return pt;
25484
+ }
25485
+
25304
25486
  // src/gvc/device-cluster.ts
25305
25487
  function applyClusterGradient(obj, fill) {
25306
25488
  obj.fill = fill.kind === "radial" ? 3 /* Radial */ : 2 /* Linear */;
@@ -25348,6 +25530,7 @@ function applyClusterObjState(sg, job) {
25348
25530
  const fillRes = resolveClusterFillEx(clusterAttrsOf(sg));
25349
25531
  if (job.obj === null) return false;
25350
25532
  const obj = job.obj;
25533
+ gvrenderSetStyle(checkClusterStyleTokens(styleTokens(clusterStyle(sg))));
25351
25534
  return withColorScheme(clusterAttr(sg, "colorscheme"), () => {
25352
25535
  const filled = applyClusterFill(obj, fillRes);
25353
25536
  applyClusterPenState(obj, sg);
@@ -25355,17 +25538,47 @@ function applyClusterObjState(sg, job) {
25355
25538
  return filled;
25356
25539
  });
25357
25540
  }
25358
- function stripedClusterColors(sg) {
25541
+ function isStripedCluster(sg) {
25542
+ const flags = parseStyleFlags(clusterStyle(sg));
25543
+ return flags.striped && !flags.rounded;
25544
+ }
25545
+ function stripedFillSpec(sg) {
25359
25546
  const flags = parseStyleFlags(clusterStyle(sg));
25360
- if (!flags.striped || flags.rounded) return [];
25361
25547
  const color = clusterAttr(sg, "color") ?? "";
25362
25548
  let fill = clusterAttr(sg, "fillcolor") || color;
25363
25549
  const bg = clusterAttr(sg, "bgcolor") ?? "";
25364
25550
  if ((!flags.filled || fill === "") && bg !== "") fill = bg;
25365
- const { segs, error } = parseSegs(fill === "" ? "lightgrey" : fill);
25551
+ return fill === "" ? "lightgrey" : fill;
25552
+ }
25553
+ function stripedClusterColors(sg) {
25554
+ if (!isStripedCluster(sg)) return [];
25555
+ const { segs, error } = parseSegs(stripedFillSpec(sg), () => `in cluster ${sg.name}`);
25366
25556
  if (error === 1 || error === 2) return [];
25367
25557
  return segs.flatMap((seg2) => seg2.color !== null && seg2.t > 0 ? [seg2.color] : []);
25368
25558
  }
25559
+ function renderStripedClusterBox(sg, renderer, job) {
25560
+ withColorScheme(clusterAttr(sg, "colorscheme"), () => {
25561
+ const { ll, ur } = sg.info.bb;
25562
+ const af = [
25563
+ { x: ll.x, y: ll.y },
25564
+ { x: ur.x, y: ll.y },
25565
+ { x: ur.x, y: ur.y },
25566
+ { x: ll.x, y: ur.y }
25567
+ ].map((p) => transformPoint(p, job));
25568
+ const obj = job.obj;
25569
+ const savedFill = obj?.fill;
25570
+ if (obj !== null && savedFill !== void 0) obj.fill = 1 /* Solid */;
25571
+ stripedBox(job, af, stripedFillSpec(sg), false, renderer, () => `in cluster ${sg.name}`);
25572
+ if (obj !== null && savedFill !== void 0) obj.fill = savedFill;
25573
+ const rawPts = [
25574
+ { x: ll.x, y: ll.y },
25575
+ { x: ll.x, y: ur.y },
25576
+ { x: ur.x, y: ur.y },
25577
+ { x: ur.x, y: ll.y }
25578
+ ];
25579
+ renderer.polygon(rawPts.map((p) => transformPoint(p, job)), false, job);
25580
+ });
25581
+ }
25369
25582
  function applyClusterFill(obj, fillRes) {
25370
25583
  if (fillRes.kind === "none") {
25371
25584
  obj.fill = 0 /* None */;
@@ -25431,7 +25644,7 @@ function renderEllipseRing(ring, coord, filled, j, ctx) {
25431
25644
  const pf = ring.map(
25432
25645
  (v) => transformPoint({ x: v.x + coord.x, y: v.y + coord.y }, ctx.job)
25433
25646
  );
25434
- wedgedEllipse(ctx.job, pf, ctx.fillcolor, ctx.renderer);
25647
+ wedgedEllipse(ctx.job, pf, ctx.fillcolor, ctx.renderer, () => `in node ${ctx.nodeName}`);
25435
25648
  renderEllipse(ring, coord, ctx.renderer, ctx.job, false);
25436
25649
  } else {
25437
25650
  renderEllipse(ring, coord, ctx.renderer, ctx.job, filled);
@@ -25440,7 +25653,7 @@ function renderEllipseRing(ring, coord, filled, j, ctx) {
25440
25653
  }
25441
25654
  function renderStripedRing(ring, coord, ctx) {
25442
25655
  const af = ring.map((v) => transformPoint({ x: v.x + coord.x, y: v.y + coord.y }, ctx.job));
25443
- stripedBox(ctx.job, af, ctx.fillcolor, true, ctx.renderer);
25656
+ stripedBox(ctx.job, af, ctx.fillcolor, true, ctx.renderer, () => `in node ${ctx.nodeName}`);
25444
25657
  renderPolygon(ring, coord, ctx.renderer, ctx.job, false);
25445
25658
  }
25446
25659
  function renderPolyRing(ring, coord, filled, j, ctx) {
@@ -25566,6 +25779,10 @@ function applyPenState(obj, styleAttr, colorAttr, penwidthAttr) {
25566
25779
  function applyNodeStyle(obj, n, job) {
25567
25780
  const styleAttr = nodeAttr(n, n.root, "style");
25568
25781
  const colorAttr = nodeAttr(n, n.root, "color");
25782
+ if (!isPointNode(n)) {
25783
+ const shape = n.info.shape;
25784
+ gvrenderSetStyle(checkStyleTokens(styleTokens(styleAttr), shape?.polygon ?? null));
25785
+ }
25569
25786
  const penwidth = nodeAttr(n, n.root, "penwidth");
25570
25787
  if (n.info.shape?.kind === 2 /* SH_RECORD */) {
25571
25788
  applyPenState(obj, styleAttr, colorAttr, penwidth);
@@ -25577,7 +25794,7 @@ function applyNodeStyle(obj, n, job) {
25577
25794
  }
25578
25795
  function prepareDrawPoly(poly, filled, obj) {
25579
25796
  if (poly.peripheries !== 0 || !filled) return poly;
25580
- obj.penColor = { type: "string", s: "transparent" };
25797
+ obj.penColor = resolveRenderColor("transparent");
25581
25798
  return { ...poly, peripheries: 1 };
25582
25799
  }
25583
25800
  function vertexScale(n, poly) {
@@ -25607,6 +25824,7 @@ function resolveNodeDrawCtx(job, n) {
25607
25824
  job,
25608
25825
  style: styleFlags,
25609
25826
  fillcolor: nodeAttr(n, n.root, "fillcolor") ?? "",
25827
+ nodeName: n.name,
25610
25828
  ...specialCornerFlags(drawPoly.option, styleFlags)
25611
25829
  };
25612
25830
  return { poly: drawPoly, coord, filled, ringCtx };
@@ -25915,7 +26133,7 @@ function findCharset(g) {
25915
26133
  }
25916
26134
  if (p === "big-5" || p === "big5") return CHAR_BIG5;
25917
26135
  if (p === "utf-8" || p === "utf8") return CHAR_UTF8;
25918
- agwarningf(`Unsupported charset "${raw}" - assuming utf-8`, "error");
26136
+ agwarningf(`Unsupported charset "${raw}" - assuming utf-8`);
25919
26137
  return CHAR_UTF8;
25920
26138
  }
25921
26139
  function maptoken(p, names, vals) {
@@ -26133,7 +26351,7 @@ function portToTbl(tbl, id) {
26133
26351
  }
26134
26352
 
26135
26353
  // src/common/compass-port.ts
26136
- function isBox(n) {
26354
+ function isBox2(n) {
26137
26355
  return n.info.shape?.polygon === P_BOX;
26138
26356
  }
26139
26357
  function gdRankdir(n) {
@@ -26324,7 +26542,7 @@ function compassPort(n, args, pp) {
26324
26542
  const { bp, compass, sides: sides2 } = args;
26325
26543
  const { b, p, defined: defBp } = compassBbox(n, bp);
26326
26544
  const dir = compassDirection(compass, b, p, sides2);
26327
- if (bp === null && !isBox(n)) applyIctxt(n, dir, b, p);
26545
+ if (bp === null && !isBox2(n)) applyIctxt(n, dir, b, p);
26328
26546
  const defFinal = dir.rv === 1 ? defBp : dir.defined || defBp;
26329
26547
  applyDir(pp, bp, dir, gdRankdir(n), defFinal);
26330
26548
  return dir.rv;
@@ -27606,7 +27824,7 @@ function emitParallelEdgePaths(e, job, colorList) {
27606
27824
  const spl = e.info.spl;
27607
27825
  const numc = (colorList.match(/:/g) ?? []).length;
27608
27826
  const segData = buildSegData(spl?.list ?? [], (2 + numc) / 2);
27609
- const colors = parseSegs(colorList).segs.map((s) => s.color ?? DEFAULT_COLOR4);
27827
+ const colors = parseSegsSilent(colorList).segs.map((s) => s.color ?? DEFAULT_COLOR4);
27610
27828
  emitColorPasses(segData, colors, job);
27611
27829
  return {
27612
27830
  headColor: colors[0] ?? DEFAULT_COLOR4,
@@ -28438,25 +28656,14 @@ function walkNodesAndEdges(g, renderer, job, info) {
28438
28656
  }
28439
28657
  }
28440
28658
 
28441
- // src/gvc/device-transform.ts
28442
- function transformPoint(p, job) {
28443
- if ((job.flags & GVRENDER_DOES_TRANSFORM) !== 0) {
28444
- return p;
28445
- }
28446
- const sx = job.zoom * job.devscale.x;
28447
- const sy = job.zoom * job.devscale.y;
28448
- const tx = job.translation.x;
28449
- const ty = job.translation.y;
28450
- return applyScale(p, tx, ty, sx, sy);
28451
- }
28452
- function applyScale(p, tx, ty, sx, sy) {
28453
- const x = (p.x + tx) * sx;
28454
- const y = (p.y + ty) * sy;
28455
- return buildPoint(x, y);
28456
- }
28457
- function buildPoint(x, y) {
28458
- const pt = { x, y };
28459
- return pt;
28659
+ // src/gvc/first-layer.ts
28660
+ var NATIVE_LANGNAME = /* @__PURE__ */ new Map([
28661
+ ["cmapx-np", "cmapx_np"],
28662
+ ["imap-np", "imap_np"]
28663
+ ]);
28664
+ function warnLayersUnsupported(format, numLayers, doesLayers) {
28665
+ if (numLayers <= 1 || doesLayers) return;
28666
+ agwarningf(`layers not supported in ${NATIVE_LANGNAME.get(format) ?? format} output`);
28460
28667
  }
28461
28668
 
28462
28669
  // src/gvc/device-labels.ts
@@ -28601,6 +28808,7 @@ function setEdgePen(e, job) {
28601
28808
  obj.pen = resolvePenType(flags);
28602
28809
  obj.penWidth = resolvePenWidth(flags, e.attrs.get("penwidth"));
28603
28810
  obj.rawStyle = styleTokens(e.attrs.get("style"));
28811
+ if (e.info.spl !== void 0) gvrenderSetStyle(obj.rawStyle);
28604
28812
  }
28605
28813
  function renderEdge(e, renderer, job) {
28606
28814
  emitEdgeComments(e, renderer, job);
@@ -28616,6 +28824,8 @@ function renderEdge(e, renderer, job) {
28616
28824
  withColorScheme(e.attrs.get("colorscheme"), () => {
28617
28825
  renderer.beginEdge(e, job);
28618
28826
  reportEdgeColors(e);
28827
+ const styles = styleTokens(e.attrs.get("style"));
28828
+ for (let i = edgeStyleResets(e, styles); i > 0; i--) gvrenderSetStyle(styles);
28619
28829
  reportEdgeLabelColors(e);
28620
28830
  renderer.endEdge(e, job);
28621
28831
  });
@@ -28629,6 +28839,10 @@ function renderGraphLabel(g, renderer, job) {
28629
28839
  }
28630
28840
  function renderClusterBox(sg, filled, renderer, job) {
28631
28841
  const { ll, ur } = sg.info.bb;
28842
+ if (isStripedCluster(sg)) {
28843
+ renderStripedClusterBox(sg, renderer, job);
28844
+ return;
28845
+ }
28632
28846
  if (parseStyleFlags(clusterStyle(sg)).rounded) {
28633
28847
  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 }];
28634
28848
  emitRoundedBezier(af, { x: 0, y: 0 }, filled, { renderer, job });
@@ -28652,7 +28866,7 @@ function renderOneCluster(sg, renderer, job) {
28652
28866
  resolveObjAnchor(sg, labelTextOf2(sg.info.label), svgClusterId(sg, job), job.obj);
28653
28867
  }
28654
28868
  const anchored = beginAnchorIf(renderer, job);
28655
- if ((clusterPeripheries(sg) !== 0 || filled) && job.obj?.pen !== 0 /* None */) {
28869
+ if ((clusterPeripheries(sg) !== 0 || filled || isStripedCluster(sg)) && job.obj?.pen !== 0 /* None */) {
28656
28870
  renderClusterBox(sg, filled, renderer, job);
28657
28871
  }
28658
28872
  renderClusterLabel(sg, renderer, job);
@@ -28682,6 +28896,7 @@ function renderGraph(g, job, renderer) {
28682
28896
  job.numLayers = layered ? info.numLayers : 1;
28683
28897
  job.layerIDs = info.layerIDs;
28684
28898
  renderer.beginGraph(g, job);
28899
+ warnLayersUnsupported(job.format, info.numLayers, renderer.beginLayer !== void 0);
28685
28900
  for (let ln = 1; ln <= job.numLayers; ln++) {
28686
28901
  job.layerNum = ln;
28687
28902
  if (layered) renderer.beginLayer(info.layerIDs[ln], job);
@@ -30021,7 +30236,7 @@ function fillRankVlist(g, r, root) {
30021
30236
  rankArr[r].v = rootRank.v;
30022
30237
  rankArr[r].vStart = lead.info.order ?? 0;
30023
30238
  const maxi = computeMaxi(g, r);
30024
- if (maxi === -1) agwarningf(`degenerate concentrated rank ${g.name},${r}`, "error");
30239
+ if (maxi === -1) agwarningf(`degenerate concentrated rank ${g.name},${r}`);
30025
30240
  rankArr[r].n = maxi + 1;
30026
30241
  return 0;
30027
30242
  }
@@ -32840,7 +33055,7 @@ function routeSplinesInternal(pp, polyline) {
32840
33055
  ];
32841
33056
  const pl = shortestPath(poly, eps);
32842
33057
  if (pl === null) {
32843
- agerrLineOn("warn", "in routesplines, Pshortestpath failed");
33058
+ agerrorf("in routesplines, Pshortestpath failed");
32844
33059
  return null;
32845
33060
  }
32846
33061
  emitDump("S3_POLY", dumpNames, () => ({
@@ -34846,9 +35061,9 @@ function writePortlabelPos(l, pe, pf, angleStr, distanceStr) {
34846
35061
  const angleDeg = lateDouble(angleStr, PORT_LABEL_ANGLE, -180);
34847
35062
  const angle = Math.atan2(pf.y - pe.y, pf.x - pe.x) + RADIANS(angleDeg);
34848
35063
  const distMult = lateDouble(distanceStr || void 0, 1, 0);
34849
- const dist4 = PORT_LABEL_DISTANCE * distMult;
34850
- l.pos.x = pe.x + dist4 * Math.cos(angle);
34851
- l.pos.y = pe.y + dist4 * Math.sin(angle);
35064
+ const dist5 = PORT_LABEL_DISTANCE * distMult;
35065
+ l.pos.x = pe.x + dist5 * Math.cos(angle);
35066
+ l.pos.y = pe.y + dist5 * Math.sin(angle);
34852
35067
  l.set = true;
34853
35068
  }
34854
35069
  function updateBB(g, l) {
@@ -35250,7 +35465,7 @@ function translateDrawing(g) {
35250
35465
  if (e.tail !== v) continue;
35251
35466
  if (e.info.spl === void 0) {
35252
35467
  if (!(g.info.concentrate ?? false) && (e.info.edge_type ?? 0) !== IGNORED_EDGE) {
35253
- agerrLineOn("warn", `lost ${e.tail.name} ${e.head.name} edge`);
35468
+ agerrorf(`lost ${e.tail.name} ${e.head.name} edge`);
35254
35469
  }
35255
35470
  continue;
35256
35471
  }
@@ -36013,9 +36228,14 @@ function nodeInsideFn2(box) {
36013
36228
  function clipToNodes(bezier2, tailBox, headBox, penwidth = DEFAULT_NODEPENWIDTH, clip = CLIP_BOTH) {
36014
36229
  const step1 = clip.tail ? bezierClipNode(bezier2, tailBox.center.x, tailBox.center.y, nodeInsideFn2(tailBox), true) : bezier2;
36015
36230
  const step2 = clip.head ? bezierClipNode(step1, headBox.center.x, headBox.center.y, nodeInsideFn2(headBox), false) : step1;
36016
- const arrowTip = step2[3];
36231
+ const startp = 0;
36232
+ let endp = 0;
36233
+ const arrowTip = step2[endp + 3];
36017
36234
  const elen = normalArrowLen(penwidth);
36018
- const clipped = arrowEndClip(step2, arrowTip, elen);
36235
+ if (endp > startp && distFused(step2[endp], step2[endp + 3]) < elen) {
36236
+ endp -= 3;
36237
+ }
36238
+ const clipped = arrowEndClip(step2.slice(endp, endp + 4), arrowTip, elen);
36019
36239
  const arrowDir = normalizeVec({
36020
36240
  x: clipped[3].x - arrowTip.x,
36021
36241
  y: clipped[3].y - arrowTip.y
@@ -38554,8 +38774,7 @@ function ensureDummyNodes(sg, gstart) {
38554
38774
  }
38555
38775
  function orthoEdges(g, useLbls, clipAndInstall2) {
38556
38776
  if (useLbls) {
38557
- agerrLineOn(
38558
- "warn",
38777
+ agwarningf(
38559
38778
  "Orthogonal edges do not currently handle edge labels. Try using xlabels.\n"
38560
38779
  );
38561
38780
  useLbls = false;
@@ -38690,7 +38909,7 @@ function dispatchOrthoEdges(g, useLbls) {
38690
38909
  }
38691
38910
 
38692
38911
  // src/common/arrows-geometry.ts
38693
- function dist(a, b) {
38912
+ function dist3(a, b) {
38694
38913
  return Math.hypot(a.x - b.x, a.y - b.y);
38695
38914
  }
38696
38915
 
@@ -38794,7 +39013,7 @@ function getCycleCentroid(g, edge) {
38794
39013
  }
38795
39014
  function bend(spl, centroid) {
38796
39015
  const midpt = midPointf(spl[0], spl[3]);
38797
- const distVal = dist(spl[3], spl[0]);
39016
+ const distVal = dist3(spl[3], spl[0]);
38798
39017
  const r = distVal / 5;
38799
39018
  const vX = centroid.x - midpt.x;
38800
39019
  const vY = centroid.y - midpt.y;
@@ -39407,7 +39626,7 @@ function arrowEndClipIdx(state3, endp) {
39407
39626
  const elen = arrowClipLength(edgeArrowName(e, "head"), edgeArrowsize(e), edgePenwidthAttr(e));
39408
39627
  bez.eflag = bez.eflag || 1;
39409
39628
  bez.ep = { ...bez.list[endp + 3] };
39410
- if (endp > state3.starti && dist(bez.list[endp], bez.list[endp + 3]) < elen) endp -= 3;
39629
+ if (endp > state3.starti && distFused(bez.list[endp], bez.list[endp + 3]) < elen) endp -= 3;
39411
39630
  const seg2 = [bez.list[endp], bez.list[endp + 1], bez.list[endp + 2], bez.list[endp + 3]];
39412
39631
  const clipped = arrowEndClip(seg2, bez.ep, elen);
39413
39632
  for (let k = 0; k < 4; k++) bez.list[endp + k] = clipped[k];
@@ -39418,7 +39637,7 @@ function arrowStartClipIdx(state3, startp, endp) {
39418
39637
  const slen = arrowClipLength(edgeArrowName(e, "tail"), edgeArrowsize(e), edgePenwidthAttr(e));
39419
39638
  bez.sflag = bez.sflag || 1;
39420
39639
  bez.sp = { ...bez.list[startp] };
39421
- if (endp > startp && dist(bez.list[startp], bez.list[startp + 3]) < slen) startp += 3;
39640
+ if (endp > startp && distFused(bez.list[startp], bez.list[startp + 3]) < slen) startp += 3;
39422
39641
  const seg2 = [bez.list[startp], bez.list[startp + 1], bez.list[startp + 2], bez.list[startp + 3]];
39423
39642
  const clipped = tailArrowEndClip(seg2, bez.sp, slen);
39424
39643
  for (let k = 0; k < 4; k++) bez.list[startp + k] = clipped[k];
@@ -40687,120 +40906,522 @@ var DOT_LAYOUT_ENGINE = {
40687
40906
  };
40688
40907
 
40689
40908
  // src/layout/neato/dijkstra.ts
40690
- function heapPush(heap, dist4, idx) {
40691
- let pos = heap.length;
40692
- heap.push(idx);
40693
- while (pos > 0) {
40694
- const parent2 = pos - 1 >> 1;
40695
- if (dist4[heap[parent2]] <= dist4[heap[pos]]) break;
40696
- const tmp = heap[parent2];
40697
- heap[parent2] = heap[pos];
40698
- heap[pos] = tmp;
40699
- pos = parent2;
40700
- }
40701
- }
40702
- function heapSiftDown2(heap, dist4) {
40703
- let pos = 0;
40909
+ var FLT_MAX = 34028234663852886e22;
40910
+ function greaterPriorityF(h, i, j, dist5) {
40911
+ return dist5[h.data[i]] < dist5[h.data[j]];
40912
+ }
40913
+ function heapifyF(h, start, dist5) {
40914
+ let i = start;
40704
40915
  for (; ; ) {
40705
- const l = 2 * pos + 1;
40706
- const r = 2 * pos + 2;
40707
- let smallest = pos;
40708
- if (l < heap.length && dist4[heap[l]] < dist4[heap[smallest]]) smallest = l;
40709
- if (r < heap.length && dist4[heap[r]] < dist4[heap[smallest]]) smallest = r;
40710
- if (smallest === pos) break;
40711
- const tmp = heap[smallest];
40712
- heap[smallest] = heap[pos];
40713
- heap[pos] = tmp;
40714
- pos = smallest;
40715
- }
40716
- }
40717
- function heapPop(heap, dist4) {
40718
- const top = heap[0];
40719
- const last = heap.pop();
40720
- if (heap.length === 0) return top;
40721
- heap[0] = last;
40722
- heapSiftDown2(heap, dist4);
40723
- return top;
40724
- }
40725
- function heapBuildExcluding(src, n, dist4) {
40726
- const heap = [];
40916
+ const l = ngLeft(i);
40917
+ const r = ngRight(i);
40918
+ let largest = ngInsideHeap(h, l) && greaterPriorityF(h, l, i, dist5) ? l : i;
40919
+ if (ngInsideHeap(h, r) && greaterPriorityF(h, r, largest, dist5)) largest = r;
40920
+ if (largest === i) break;
40921
+ ngExchange(h, largest, i);
40922
+ i = largest;
40923
+ }
40924
+ }
40925
+ function initHeapF(startVertex, dist5, n) {
40926
+ const h = {
40927
+ data: new Array(Math.max(n - 1, 0)).fill(0),
40928
+ heapSize: n - 1,
40929
+ index: new Int32Array(n)
40930
+ };
40931
+ let count = 0;
40727
40932
  for (let i = 0; i < n; i++) {
40728
- if (i !== src) heapPush(heap, dist4, i);
40933
+ if (i !== startVertex) {
40934
+ h.data[count] = i;
40935
+ h.index[i] = count;
40936
+ count++;
40937
+ }
40729
40938
  }
40730
- return heap;
40939
+ for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) heapifyF(h, j, dist5);
40940
+ return h;
40731
40941
  }
40732
- function dijkstraInitDist(src, graph, n, dist4) {
40733
- for (let i = 0; i < n; i++) dist4[i] = Infinity;
40734
- dist4[src] = 0;
40735
- const v = graph[src];
40736
- for (let i = 1; i < v.nedges; i++) dist4[v.edges[i]] = v.ewgts[i];
40942
+ function extractMaxF(h, dist5) {
40943
+ if (h.heapSize === 0) return -1;
40944
+ const max = h.data[0];
40945
+ h.data[0] = h.data[h.heapSize - 1];
40946
+ h.index[h.data[0]] = 0;
40947
+ h.heapSize--;
40948
+ heapifyF(h, 0, dist5);
40949
+ return max;
40737
40950
  }
40738
- function dijkstraRelax(closest, closestDist, graph, dist4, heap) {
40739
- const cv = graph[closest];
40740
- for (let i = 1; i < cv.nedges; i++) {
40741
- const nb = cv.edges[i];
40742
- const nd = closestDist + cv.ewgts[i];
40743
- if (nd < dist4[nb]) {
40744
- dist4[nb] = nd;
40745
- heapPush(heap, dist4, nb);
40951
+ function increaseKeyF(h, increasedVertex, newDist, dist5) {
40952
+ if (dist5[increasedVertex] <= newDist) return;
40953
+ let i = h.index[increasedVertex];
40954
+ dist5[increasedVertex] = newDist;
40955
+ while (i > 0 && dist5[h.data[ngParent(i)]] > newDist) {
40956
+ ngAssign(h, i, ngParent(i));
40957
+ i = ngParent(i);
40958
+ }
40959
+ h.data[i] = increasedVertex;
40960
+ h.index[increasedVertex] = i;
40961
+ }
40962
+ function dijkstra(vertex, graph, n, dist5) {
40963
+ for (let i = 0; i < n; i++) dist5[i] = FLT_MAX;
40964
+ dist5[vertex] = 0;
40965
+ const vd = graph[vertex];
40966
+ for (let i = 1; i < vd.nedges; i++) dist5[vd.edges[i]] = vd.ewgts[i];
40967
+ const h = initHeapF(vertex, dist5, n);
40968
+ for (let closest = extractMaxF(h, dist5); closest >= 0; closest = extractMaxF(h, dist5)) {
40969
+ const closestDist = dist5[closest];
40970
+ if (closestDist === FLT_MAX) break;
40971
+ const cd = graph[closest];
40972
+ for (let i = 1; i < cd.nedges; i++) {
40973
+ increaseKeyF(h, cd.edges[i], Math.fround(closestDist + Math.fround(cd.ewgts[i])), dist5);
40746
40974
  }
40747
40975
  }
40748
40976
  }
40749
- function dijkstra(src, graph, n, dist4) {
40750
- dijkstraInitDist(src, graph, n, dist4);
40751
- const heap = heapBuildExcluding(src, n, dist4);
40752
- while (heap.length > 0) {
40753
- const closest = heapPop(heap, dist4);
40754
- const closestDist = dist4[closest];
40755
- if (!isFinite(closestDist)) break;
40756
- dijkstraRelax(closest, closestDist, graph, dist4, heap);
40977
+ var MAX_DIST = 2147483647;
40978
+ function ngLeft(i) {
40979
+ return 2 * i;
40980
+ }
40981
+ function ngRight(i) {
40982
+ return 2 * i + 1;
40983
+ }
40984
+ function ngParent(i) {
40985
+ return Math.trunc(i / 2);
40986
+ }
40987
+ function ngInsideHeap(h, i) {
40988
+ return i < h.heapSize;
40989
+ }
40990
+ function ngGreaterPriority(h, i, j, dist5) {
40991
+ return dist5[h.data[i]] < dist5[h.data[j]];
40992
+ }
40993
+ function ngAssign(h, i, j) {
40994
+ h.data[i] = h.data[j];
40995
+ h.index[h.data[i]] = i;
40996
+ }
40997
+ function ngExchange(h, i, j) {
40998
+ const t = h.data[i];
40999
+ h.data[i] = h.data[j];
41000
+ h.data[j] = t;
41001
+ h.index[h.data[i]] = i;
41002
+ h.index[h.data[j]] = j;
41003
+ }
41004
+ function ngHeapify(h, start, dist5) {
41005
+ let i = start;
41006
+ for (; ; ) {
41007
+ const l = ngLeft(i);
41008
+ const r = ngRight(i);
41009
+ let largest = ngInsideHeap(h, l) && ngGreaterPriority(h, l, i, dist5) ? l : i;
41010
+ if (ngInsideHeap(h, r) && ngGreaterPriority(h, r, largest, dist5)) largest = r;
41011
+ if (largest === i) break;
41012
+ ngExchange(h, largest, i);
41013
+ i = largest;
41014
+ }
41015
+ }
41016
+ function ngInitHeap(startVertex, dist5, n) {
41017
+ const h = {
41018
+ data: new Array(Math.max(n - 1, 0)).fill(0),
41019
+ heapSize: n - 1,
41020
+ index: new Int32Array(n)
41021
+ };
41022
+ let count = 0;
41023
+ for (let i = 0; i < n; i++) {
41024
+ if (i !== startVertex) {
41025
+ h.data[count] = i;
41026
+ h.index[i] = count;
41027
+ count++;
41028
+ }
41029
+ }
41030
+ for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) ngHeapify(h, j, dist5);
41031
+ return h;
41032
+ }
41033
+ function ngExtractMax(h, dist5) {
41034
+ if (h.heapSize === 0) return -1;
41035
+ const max = h.data[0];
41036
+ h.data[0] = h.data[h.heapSize - 1];
41037
+ h.index[h.data[0]] = 0;
41038
+ h.heapSize--;
41039
+ ngHeapify(h, 0, dist5);
41040
+ return max;
41041
+ }
41042
+ function ngIncreaseKey(h, increasedVertex, newDist, dist5) {
41043
+ if (dist5[increasedVertex] <= newDist) return;
41044
+ let i = h.index[increasedVertex];
41045
+ dist5[increasedVertex] = newDist;
41046
+ while (i > 0 && dist5[h.data[ngParent(i)]] > newDist) {
41047
+ ngAssign(h, i, ngParent(i));
41048
+ i = ngParent(i);
41049
+ }
41050
+ h.data[i] = increasedVertex;
41051
+ h.index[increasedVertex] = i;
41052
+ }
41053
+ function toDistType(w) {
41054
+ return Math.trunc(Math.fround(w));
41055
+ }
41056
+ function ngdijkstra(vertex, graph, n, dist5) {
41057
+ let prevClosestDist = MAX_DIST;
41058
+ for (let i = 0; i < n; i++) dist5[i] = MAX_DIST;
41059
+ dist5[vertex] = 0;
41060
+ const vd = graph[vertex];
41061
+ for (let i = 1; i < vd.nedges; i++) dist5[vd.edges[i]] = toDistType(vd.ewgts[i]);
41062
+ const h = ngInitHeap(vertex, dist5, n);
41063
+ for (let closest = ngExtractMax(h, dist5); closest >= 0; closest = ngExtractMax(h, dist5)) {
41064
+ const closestDist = dist5[closest];
41065
+ if (closestDist === MAX_DIST) break;
41066
+ const cd = graph[closest];
41067
+ for (let i = 1; i < cd.nedges; i++) {
41068
+ ngIncreaseKey(h, cd.edges[i], closestDist + toDistType(cd.ewgts[i]) | 0, dist5);
41069
+ }
41070
+ prevClosestDist = closestDist;
41071
+ }
41072
+ for (let i = 0; i < n; i++) {
41073
+ if (dist5[i] === MAX_DIST) {
41074
+ dist5[i] = MAX_DIST - prevClosestDist < 10 ? MAX_DIST : prevClosestDist + 10;
41075
+ }
40757
41076
  }
40758
41077
  }
40759
41078
 
40760
41079
  // src/layout/neato/bfs.ts
40761
- function bfsInit(src, n, dist4) {
40762
- for (let i = 0; i < n; i++) dist4[i] = -1;
40763
- dist4[src] = 0;
41080
+ function bfsInit(src, n, dist5) {
41081
+ for (let i = 0; i < n; i++) dist5[i] = -1;
41082
+ dist5[src] = 0;
40764
41083
  return [src];
40765
41084
  }
40766
- function bfsFixDisconnected(n, dist4, closestDist) {
41085
+ function bfsFixDisconnected(n, dist5, closestDist) {
40767
41086
  for (let i = 0; i < n; i++) {
40768
- if (dist4[i] < 0) dist4[i] = closestDist + 10;
41087
+ if (dist5[i] < 0) dist5[i] = closestDist + 10;
40769
41088
  }
40770
41089
  }
40771
- function bfsVisitNeighbors(vertex, graph, dist4, queue) {
41090
+ function bfsVisitNeighbors(vertex, graph, dist5, queue) {
40772
41091
  const vd = graph[vertex];
40773
- const d = dist4[vertex];
41092
+ const d = dist5[vertex];
40774
41093
  const unit = graph[0].ewgts.length === 0;
40775
41094
  for (let i = 1; i < vd.nedges; i++) {
40776
41095
  const nb = vd.edges[i];
40777
- if (dist4[nb] < 0) {
40778
- dist4[nb] = d + (unit ? 1 : Math.trunc(Math.fround(vd.ewgts[i])));
41096
+ if (dist5[nb] < 0) {
41097
+ dist5[nb] = d + (unit ? 1 : Math.trunc(Math.fround(vd.ewgts[i])));
40779
41098
  queue.push(nb);
40780
41099
  }
40781
41100
  }
40782
41101
  return d;
40783
41102
  }
40784
- function bfs(src, graph, n, dist4) {
40785
- const queue = bfsInit(src, n, dist4);
41103
+ function bfs(src, graph, n, dist5) {
41104
+ const queue = bfsInit(src, n, dist5);
40786
41105
  let closestDist = 0;
40787
41106
  let head = 0;
40788
41107
  while (head < queue.length) {
40789
41108
  const vertex = queue[head++];
40790
- closestDist = bfsVisitNeighbors(vertex, graph, dist4, queue);
41109
+ closestDist = bfsVisitNeighbors(vertex, graph, dist5, queue);
41110
+ }
41111
+ bfsFixDisconnected(n, dist5, closestDist);
41112
+ }
41113
+ function packedIndex(i, j, n) {
41114
+ return i * (2 * n - i - 1) / 2 + j;
41115
+ }
41116
+ function computeWeightedApspPacked(graph, n) {
41117
+ const result = new Float32Array(n * (n + 1) / 2);
41118
+ const di = new Float32Array(n);
41119
+ for (let i = 0; i < n; i++) {
41120
+ dijkstra(i, graph, n, di);
41121
+ for (let j = i; j < n; j++) result[packedIndex(i, j, n)] = di[j];
41122
+ }
41123
+ return result;
41124
+ }
41125
+
41126
+ // src/common/crand.ts
41127
+ var C_RAND_MAX = 2147483647;
41128
+ var UNSEEDED_STATE2 = 1;
41129
+ var state2 = UNSEEDED_STATE2;
41130
+ registerRenderState(() => {
41131
+ state2 = UNSEEDED_STATE2;
41132
+ });
41133
+ function csrand(seed) {
41134
+ state2 = seed;
41135
+ }
41136
+ function crand() {
41137
+ state2 = state2 * 16807 % 2147483647;
41138
+ return state2;
41139
+ }
41140
+ function cdrand() {
41141
+ return crand() / C_RAND_MAX;
41142
+ }
41143
+ function gvRandom(bound) {
41144
+ const discardThreshold = C_RAND_MAX - 2147483648 % bound;
41145
+ let r;
41146
+ do {
41147
+ r = crand();
41148
+ } while (r > discardThreshold);
41149
+ return r % bound;
41150
+ }
41151
+ function gvPermutation(bound) {
41152
+ if (bound <= 0) return [];
41153
+ const p = [];
41154
+ for (let i = 0; i < bound; i++) p.push(i);
41155
+ for (let i = bound - 1; i > 0; --i) {
41156
+ const j = gvRandom(i + 1);
41157
+ const t = p[i];
41158
+ p[i] = p[j];
41159
+ p[j] = t;
40791
41160
  }
40792
- bfsFixDisconnected(n, dist4, closestDist);
41161
+ return p;
41162
+ }
41163
+
41164
+ // src/layout/neato/matrix-ops.ts
41165
+ var fr = Math.fround;
41166
+ function fma2(a, b, c) {
41167
+ const p = a * b;
41168
+ return Number.isFinite(p) && Number.isFinite(c) ? fma(a, b, c) : p + c;
41169
+ }
41170
+ function orthog1(n, vec) {
41171
+ let sum = 0;
41172
+ for (let i = 0; i < n; i++) sum += vec[i];
41173
+ sum /= n;
41174
+ for (let i = 0; i < n; i++) vec[i] = vec[i] - sum;
41175
+ }
41176
+ function orthog1f(n, vec) {
41177
+ let sum = fr(0);
41178
+ for (let i = 0; i < n; i++) sum = fr(sum + vec[i]);
41179
+ sum = fr(sum / n);
41180
+ for (let i = 0; i < n; i++) vec[i] = vec[i] - sum;
41181
+ }
41182
+ function rightMultWithVectorFF(m, n, vector, result) {
41183
+ for (let i = 0; i < n; i++) result[i] = 0;
41184
+ let index = 0;
41185
+ for (let i = 0; i < n; i++) {
41186
+ const vi = vector[i];
41187
+ let res = fr(m[index++] * vi);
41188
+ for (let j = i + 1; j < n; j++, index++) {
41189
+ res = fr(res + fr(m[index] * vector[j]));
41190
+ result[j] = result[j] + fr(m[index] * vi);
41191
+ }
41192
+ result[i] = result[i] + res;
41193
+ }
41194
+ }
41195
+ function vectorsSubtractionF(n, v1, v2, result) {
41196
+ for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
41197
+ }
41198
+ function vectorsMultAdditionF(n, v1, alpha, v2) {
41199
+ const a = fr(alpha);
41200
+ for (let i = 0; i < n; i++) v1[i] = v1[i] + fr(a * v2[i]);
41201
+ }
41202
+ function vectorsInnerProductF(n, v1, v2) {
41203
+ let result = 0;
41204
+ for (let i = 0; i < n; i++) result += fr(v1[i] * v2[i]);
41205
+ return result;
41206
+ }
41207
+ function copyVectorF(n, src, dst) {
41208
+ for (let i = 0; i < n; i++) dst[i] = src[i];
41209
+ }
41210
+ function maxAbsF(n, vec) {
41211
+ let max = fr(-1e30);
41212
+ for (let i = 0; i < n; i++) {
41213
+ const a = fr(Math.abs(vec[i]));
41214
+ if (a > max) max = a;
41215
+ }
41216
+ return max;
41217
+ }
41218
+ function squareVec(n, vec) {
41219
+ for (let i = 0; i < n; i++) vec[i] = vec[i] * vec[i];
41220
+ }
41221
+ function invertVec(n, vec) {
41222
+ for (let i = 0; i < n; i++) {
41223
+ if (vec[i] !== 0) vec[i] = 1 / vec[i];
41224
+ }
41225
+ }
41226
+ function sqrtVecF(n, source, target) {
41227
+ for (let i = 0; i < n; i++) {
41228
+ if (source[i] >= 0) target[i] = fr(Math.sqrt(source[i]));
41229
+ }
41230
+ }
41231
+ function invertSqrtVec(n, vec) {
41232
+ for (let i = 0; i < n; i++) {
41233
+ if (vec[i] > 0) vec[i] = 1 / fr(Math.sqrt(vec[i]));
41234
+ }
41235
+ }
41236
+ var BLOCK_NONE = 1;
41237
+ function innerProduct(n, v1, v2, block) {
41238
+ let result = 0;
41239
+ const blocked = block === BLOCK_NONE ? 0 : n - n % block;
41240
+ let i = 0;
41241
+ for (; i < blocked; i++) result += v1[i] * v2[i];
41242
+ for (; i < n; i++) result = fma2(v1[i], v2[i], result);
41243
+ return result;
41244
+ }
41245
+ function scadd(vec1, end, fac, vec2) {
41246
+ for (let i = 0; i <= end; i++) vec1[i] = fma2(fac, vec2[i], vec1[i]);
41247
+ }
41248
+ function norm(vec, end, block) {
41249
+ return Math.sqrt(innerProduct(end + 1, vec, vec, block));
41250
+ }
41251
+ function vectorsScalarMult(n, vector, alpha, result) {
41252
+ for (let i = 0; i < n; i++) result[i] = vector[i] * alpha;
41253
+ }
41254
+ function copyVector(n, source, dest) {
41255
+ for (let i = 0; i < n; i++) dest[i] = source[i];
41256
+ }
41257
+ function vectorsAddition(n, v1, v2, result) {
41258
+ for (let i = 0; i < n; i++) result[i] = v1[i] + v2[i];
41259
+ }
41260
+ function vectorsSubtraction(n, v1, v2, result) {
41261
+ for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
41262
+ }
41263
+ function maxAbs(n, vector) {
41264
+ let maxVal = -1e50;
41265
+ for (let i = 0; i < n; i++) {
41266
+ const a = Math.abs(vector[i]);
41267
+ if (a > maxVal) maxVal = a;
41268
+ }
41269
+ return maxVal;
41270
+ }
41271
+ function rightMultWithVectorF(matrix, n, vector, result, block) {
41272
+ const blocked = block === BLOCK_NONE ? 0 : n - n % block;
41273
+ for (let i = 0; i < n; i++) {
41274
+ const row = matrix[i];
41275
+ let res = 0;
41276
+ let j = 0;
41277
+ for (; j < blocked; j++) res += row[j] * vector[j];
41278
+ for (; j < n; j++) res = fma2(row[j], vector[j], res);
41279
+ result[i] = res;
41280
+ }
41281
+ }
41282
+ function rightMultWithVector(matrix, n, vector, result) {
41283
+ for (let i = 0; i < n; i++) {
41284
+ let res = 0;
41285
+ const row = matrix[i];
41286
+ for (let j = 0; j < row.nedges; j++) res = fma2(row.ewgts[j], vector[row.edges[j]], res);
41287
+ result[i] = res;
41288
+ }
41289
+ }
41290
+ var RANGE = 500;
41291
+ function initVecOrth1(n, vec) {
41292
+ for (let i = 0; i < n; i++) vec[i] = crand() % RANGE;
41293
+ orthog1(n, vec);
41294
+ }
41295
+
41296
+ // src/layout/neato/conjgrad.ts
41297
+ var BLOCK_INITIAL_RR = 4;
41298
+ var BLOCK_P_AP = 8;
41299
+ function cgNextDirection(n, w, alpha, rR) {
41300
+ vectorsScalarMult(n, w.Ap, alpha, w.Ap);
41301
+ vectorsSubtraction(n, w.r, w.Ap, w.r);
41302
+ const rRNew = innerProduct(n, w.r, w.r, BLOCK_NONE);
41303
+ if (rR === 0) {
41304
+ agerrorf("conjugate_gradient: unexpected length 0 vector\n");
41305
+ return null;
41306
+ }
41307
+ const beta = rRNew / rR;
41308
+ vectorsScalarMult(n, w.p, beta, w.p);
41309
+ vectorsAddition(n, w.r, w.p, w.p);
41310
+ return rRNew;
41311
+ }
41312
+ function cgStart(A3, x, b, n) {
41313
+ const w = {
41314
+ r: new Float64Array(n),
41315
+ p: new Float64Array(n),
41316
+ Ap: new Float64Array(n),
41317
+ alphap: new Float64Array(n)
41318
+ };
41319
+ const Ax = new Float64Array(n);
41320
+ const orthB = Float64Array.from(b.subarray(0, n));
41321
+ orthog1(n, orthB);
41322
+ orthog1(n, x);
41323
+ rightMultWithVector(A3, n, x, Ax);
41324
+ vectorsSubtraction(n, orthB, Ax, w.r);
41325
+ w.p.set(w.r.subarray(0, n));
41326
+ return w;
41327
+ }
41328
+ function conjugateGradient(A3, x, b, n, tol, maxIterations) {
41329
+ const w = cgStart(A3, x, b, n);
41330
+ let rR = innerProduct(n, w.r, w.r, BLOCK_INITIAL_RR);
41331
+ for (let i = 0; i < maxIterations && maxAbs(n, w.r) > tol; i++) {
41332
+ rightMultWithVector(A3, n, w.p, w.Ap);
41333
+ const pAp = innerProduct(n, w.p, w.Ap, BLOCK_P_AP);
41334
+ if (pAp === 0) break;
41335
+ const alpha = rR / pAp;
41336
+ vectorsScalarMult(n, w.p, alpha, w.alphap);
41337
+ vectorsAddition(n, x, w.alphap, x);
41338
+ if (i < maxIterations - 1) {
41339
+ const next = cgNextDirection(n, w, alpha, rR);
41340
+ if (next === null) return 1;
41341
+ rR = next;
41342
+ }
41343
+ }
41344
+ return 0;
41345
+ }
41346
+ var CGF_BLOCK_AX = 4;
41347
+ var CGF_BLOCK_AP = 4;
41348
+ var CGF_BLOCK_INITIAL_RR = 4;
41349
+ var CGF_BLOCK_P_AP = 8;
41350
+ function cgfInit(A3, x, b, n, ortho1) {
41351
+ const orthB = new Float64Array(n);
41352
+ copyVector(n, b, orthB);
41353
+ if (ortho1) {
41354
+ orthog1(n, orthB);
41355
+ orthog1(n, x);
41356
+ }
41357
+ const Ax = new Float64Array(n);
41358
+ rightMultWithVectorF(A3, n, x, Ax, CGF_BLOCK_AX);
41359
+ const r = new Float64Array(n);
41360
+ vectorsSubtraction(n, orthB, Ax, r);
41361
+ const p = new Float64Array(n);
41362
+ copyVector(n, r, p);
41363
+ return {
41364
+ r,
41365
+ p,
41366
+ Ap: new Float64Array(n),
41367
+ alphap: new Float64Array(n),
41368
+ rr: innerProduct(n, r, r, CGF_BLOCK_INITIAL_RR)
41369
+ };
41370
+ }
41371
+ function cgfUpdate(n, alpha, st) {
41372
+ vectorsScalarMult(n, st.Ap, alpha, st.Ap);
41373
+ vectorsSubtraction(n, st.r, st.Ap, st.r);
41374
+ const rrNew = innerProduct(n, st.r, st.r, BLOCK_NONE);
41375
+ if (st.rr === 0) {
41376
+ agerrorf("conjugate_gradient: unexpected length 0 vector\n");
41377
+ return 1;
41378
+ }
41379
+ const beta = rrNew / st.rr;
41380
+ st.rr = rrNew;
41381
+ vectorsScalarMult(n, st.p, beta, st.p);
41382
+ vectorsAddition(n, st.r, st.p, st.p);
41383
+ return 0;
41384
+ }
41385
+ function conjugateGradientF(A3, x, b, n, opts) {
41386
+ const { tol, maxIterations, ortho1 } = opts;
41387
+ const st = cgfInit(A3, x, b, n, ortho1);
41388
+ for (let i = 0; i < maxIterations && maxAbs(n, st.r) > tol; i++) {
41389
+ rightMultWithVectorF(A3, n, st.p, st.Ap, CGF_BLOCK_AP);
41390
+ const pAp = innerProduct(n, st.p, st.Ap, CGF_BLOCK_P_AP);
41391
+ if (pAp === 0) break;
41392
+ const alpha = st.rr / pAp;
41393
+ vectorsScalarMult(n, st.p, alpha, st.alphap);
41394
+ vectorsAddition(n, x, st.alphap, x);
41395
+ if (i < maxIterations - 1 && cgfUpdate(n, alpha, st) === 1) return 1;
41396
+ }
41397
+ return 0;
40793
41398
  }
40794
41399
 
40795
41400
  // src/layout/neato/stress.ts
41401
+ var TOLERANCE_CG = 1e-3;
40796
41402
  var DFLT_ITERATIONS = 200;
41403
+ var OPT_SMART_INIT = 4;
41404
+ function mdsModel(graph, nG) {
41405
+ if (graph[0].ewgts.length === 0) return null;
41406
+ const Dij = computeWeightedApspPacked(graph, nG);
41407
+ let shift = 0;
41408
+ for (let i = 0; i < nG; i++) {
41409
+ shift += i;
41410
+ for (let e = 1; e < graph[i].nedges; e++) {
41411
+ const j = graph[i].edges[e];
41412
+ if (j < i) continue;
41413
+ Dij[i * nG + j - shift] = graph[i].ewgts[e];
41414
+ }
41415
+ }
41416
+ return Dij;
41417
+ }
40797
41418
 
40798
41419
  // src/layout/neato/sgd-dijkstra.ts
40799
- var FLT_MAX = 34028234663852886e22;
41420
+ var FLT_MAX2 = 34028234663852886e22;
40800
41421
  var left = (i) => 2 * i;
40801
41422
  var right = (i) => 2 * i + 1;
40802
41423
  var parent = (i) => Math.trunc(i / 2);
40803
- var greaterPriority = (h, i, j, dist4) => dist4[h.data[i]] < dist4[h.data[j]];
41424
+ var greaterPriority = (h, i, j, dist5) => dist5[h.data[i]] < dist5[h.data[j]];
40804
41425
  function exchange2(h, i, j) {
40805
41426
  const t = h.data[i];
40806
41427
  h.data[i] = h.data[j];
@@ -40808,19 +41429,19 @@ function exchange2(h, i, j) {
40808
41429
  h.index[h.data[i]] = i;
40809
41430
  h.index[h.data[j]] = j;
40810
41431
  }
40811
- function heapify(h, start, dist4) {
41432
+ function heapify(h, start, dist5) {
40812
41433
  let i = start;
40813
41434
  for (; ; ) {
40814
41435
  const l = left(i);
40815
41436
  const r = right(i);
40816
- let largest = l < h.heapSize && greaterPriority(h, l, i, dist4) ? l : i;
40817
- if (r < h.heapSize && greaterPriority(h, r, largest, dist4)) largest = r;
41437
+ let largest = l < h.heapSize && greaterPriority(h, l, i, dist5) ? l : i;
41438
+ if (r < h.heapSize && greaterPriority(h, r, largest, dist5)) largest = r;
40818
41439
  if (largest === i) break;
40819
41440
  exchange2(h, largest, i);
40820
41441
  i = largest;
40821
41442
  }
40822
41443
  }
40823
- function initHeap(startVertex, dist4, n) {
41444
+ function initHeap(startVertex, dist5, n) {
40824
41445
  const h = {
40825
41446
  data: new Int32Array(Math.max(n - 1, 0)),
40826
41447
  heapSize: n - 1,
@@ -40832,23 +41453,23 @@ function initHeap(startVertex, dist4, n) {
40832
41453
  h.data[count] = i;
40833
41454
  h.index[i] = count++;
40834
41455
  }
40835
- for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) heapify(h, j, dist4);
41456
+ for (let j = Math.trunc((n - 1) / 2); j >= 0; j--) heapify(h, j, dist5);
40836
41457
  return h;
40837
41458
  }
40838
- function extractMax(h, dist4) {
41459
+ function extractMax(h, dist5) {
40839
41460
  if (h.heapSize === 0) return -1;
40840
41461
  const max = h.data[0];
40841
41462
  h.data[0] = h.data[h.heapSize - 1];
40842
41463
  h.index[h.data[0]] = 0;
40843
41464
  h.heapSize--;
40844
- heapify(h, 0, dist4);
41465
+ heapify(h, 0, dist5);
40845
41466
  return max;
40846
41467
  }
40847
- function increaseKey(h, v, newDist, dist4) {
40848
- if (dist4[v] <= newDist) return;
40849
- dist4[v] = newDist;
41468
+ function increaseKey(h, v, newDist, dist5) {
41469
+ if (dist5[v] <= newDist) return;
41470
+ dist5[v] = newDist;
40850
41471
  let i = h.index[v];
40851
- while (i > 0 && dist4[h.data[parent(i)]] > newDist) {
41472
+ while (i > 0 && dist5[h.data[parent(i)]] > newDist) {
40852
41473
  h.data[i] = h.data[parent(i)];
40853
41474
  h.index[h.data[i]] = i;
40854
41475
  i = parent(i);
@@ -40857,7 +41478,7 @@ function increaseKey(h, v, newDist, dist4) {
40857
41478
  h.index[v] = i;
40858
41479
  }
40859
41480
  function dijkstraSgd(graph, source, terms) {
40860
- const dists = new Float32Array(graph.n).fill(FLT_MAX);
41481
+ const dists = new Float32Array(graph.n).fill(FLT_MAX2);
40861
41482
  dists[source] = 0;
40862
41483
  for (let i = graph.sources[source]; i < graph.sources[source + 1]; i++) {
40863
41484
  dists[graph.targets[i]] = graph.weights[i];
@@ -40866,7 +41487,7 @@ function dijkstraSgd(graph, source, terms) {
40866
41487
  let offset = 0;
40867
41488
  for (let closest = extractMax(h, dists); closest >= 0; closest = extractMax(h, dists)) {
40868
41489
  const d = dists[closest];
40869
- if (d === FLT_MAX) break;
41490
+ if (d === FLT_MAX2) break;
40870
41491
  if (graph.pinneds[closest] || closest < source) {
40871
41492
  terms[offset++] = { i: source, j: closest, d, w: Math.fround(1 / Math.fround(d * d)) };
40872
41493
  }
@@ -40885,7 +41506,7 @@ function lenattr(ep, g) {
40885
41506
  const val2 = /^\s*[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/.exec(s);
40886
41507
  const len = val2 === null ? Number.NaN : parseFloat(val2[0]);
40887
41508
  if (Number.isNaN(len) || len < 0 || len === 0) {
40888
- agerrLineOn("warn", `bad edge len "${s}" in ${g.name} - setting to ${DEFAULT_EDGE_LEN.toFixed(2)}`);
41509
+ agwarningf(`bad edge len "${s}" in ${g.name} - setting to ${DEFAULT_EDGE_LEN.toFixed(2)}`);
40889
41510
  return DEFAULT_EDGE_LEN;
40890
41511
  }
40891
41512
  return len;
@@ -41049,12 +41670,11 @@ function neatoMode(g) {
41049
41670
  if (str === void 0 || str === "") return MODE_MAJOR;
41050
41671
  const mode = modeByName().get(str);
41051
41672
  if (mode !== void 0) return mode;
41052
- agerrLineOn("warn", `Illegal value ${str} for attribute "mode" in graph ${g.root.name} - ignored`);
41673
+ agwarningf(`Illegal value ${str} for attribute "mode" in graph ${g.root.name} - ignored`);
41053
41674
  return MODE_MAJOR;
41054
41675
  }
41055
41676
  function checkMode(g, mode) {
41056
- const value = g.root.attrs.get("mode") || (mode === MODE_HIER ? "hier" : "ipsep");
41057
- if (mode === MODE_HIER) unsupported("mode", value, "hierarchical stress majorization");
41677
+ const value = g.root.attrs.get("mode") || "ipsep";
41058
41678
  if (mode === MODE_IPSEP && ipsepHasConstraints(g)) {
41059
41679
  unsupported("mode", value, "constrained (ipsep) majorization");
41060
41680
  }
@@ -41407,10 +42027,10 @@ function solve(a, b, c, n) {
41407
42027
  }
41408
42028
 
41409
42029
  // src/layout/neato/kk-paths.ts
41410
- function newPathState(n, dist4, adj, initialDist2) {
42030
+ function newPathState(n, dist5, adj, initialDist2) {
41411
42031
  return {
41412
42032
  n,
41413
- dist: dist4,
42033
+ dist: dist5,
41414
42034
  adj,
41415
42035
  initialDist: initialDist2,
41416
42036
  heap: new Int32Array(n + 1),
@@ -41488,10 +42108,10 @@ function s1(s, src) {
41488
42108
  function shortestPath2(s) {
41489
42109
  for (let v = 0; v < s.n; v++) s1(s, v);
41490
42110
  }
41491
- function mdsModel(dist4, n, edges) {
42111
+ function mdsModel2(dist5, n, edges) {
41492
42112
  for (const { tailSeq: i, headSeq: j, len } of edges) {
41493
42113
  if (i === j) continue;
41494
- for (const k of [i * n + j, j * n + i]) if (k < dist4.length) dist4[k] = len;
42114
+ for (const k of [i * n + j, j * n + i]) if (k < dist5.length) dist5[k] = len;
41495
42115
  }
41496
42116
  }
41497
42117
 
@@ -41584,12 +42204,12 @@ function initialPositions2(g, st) {
41584
42204
  }
41585
42205
  }
41586
42206
  function distvec(p0, p1, del) {
41587
- let dist4 = 0;
42207
+ let dist5 = 0;
41588
42208
  for (let k = 0; k < NDIM; k++) {
41589
42209
  del[k] = p0[k] - p1[k];
41590
- dist4 += del[k] * del[k];
42210
+ dist5 += del[k] * del[k];
41591
42211
  }
41592
- return Math.sqrt(dist4);
42212
+ return Math.sqrt(dist5);
41593
42213
  }
41594
42214
  function springFactors(g) {
41595
42215
  const byEnds = /* @__PURE__ */ new Map();
@@ -41606,9 +42226,9 @@ function fillRow(st, i, del) {
41606
42226
  const vi = st.nodes[i];
41607
42227
  for (let j = 0; j < st.n; j++) {
41608
42228
  if (i === j) continue;
41609
- const dist4 = distvec(vi.info.pos, st.nodes[j].info.pos, del);
42229
+ const dist5 = distvec(vi.info.pos, st.nodes[j].info.pos, del);
41610
42230
  for (let k = 0; k < NDIM; k++) {
41611
- const v = st.spring[i * st.n + j] * (del[k] - st.dist[i * st.n + j] * del[k] / dist4);
42231
+ const v = st.spring[i * st.n + j] * (del[k] - st.dist[i * st.n + j] * del[k] / dist5);
41612
42232
  st.t[(i * st.n + j) * NDIM + k] = v;
41613
42233
  st.sumT[i * NDIM + k] += v;
41614
42234
  }
@@ -41637,9 +42257,9 @@ function updateArrays(st, i) {
41637
42257
  for (let k = 0; k < NDIM; k++) st.sumT[i * NDIM + k] = 0;
41638
42258
  for (let j = 0; j < n; j++) {
41639
42259
  if (i === j) continue;
41640
- const dist4 = distvec(vi.info.pos, st.nodes[j].info.pos, del);
42260
+ const dist5 = distvec(vi.info.pos, st.nodes[j].info.pos, del);
41641
42261
  for (let k = 0; k < NDIM; k++) {
41642
- const tij = st.spring[i * n + j] * (del[k] - st.dist[i * n + j] * del[k] / dist4);
42262
+ const tij = st.spring[i * n + j] * (del[k] - st.dist[i * n + j] * del[k] / dist5);
41643
42263
  st.t[(i * n + j) * NDIM + k] = tij;
41644
42264
  st.sumT[i * NDIM + k] += tij;
41645
42265
  const old = st.t[(j * n + i) * NDIM + k];
@@ -41706,7 +42326,7 @@ function moveNode(st, m) {
41706
42326
  function solveModel(g, st) {
41707
42327
  for (let m = chooseNode(st); m >= 0; m = chooseNode(st)) moveNode(st, m);
41708
42328
  if (st.move === st.maxIter) {
41709
- agerrLineOn("warn", `Max. iterations (${st.maxIter}) reached on graph ${g.name}`);
42329
+ agwarningf(`Max. iterations (${st.maxIter}) reached on graph ${g.name}`);
41710
42330
  }
41711
42331
  }
41712
42332
  function mdsEdges(g, nodes, lens) {
@@ -41719,84 +42339,852 @@ function kkNeato(g, nG, model) {
41719
42339
  if (nG < 2 || maxIter < 0) return;
41720
42340
  const { st, adj, ini, lens } = scanGraphMode(g, maxIter);
41721
42341
  shortestPath2(newPathState(st.n, st.dist, adj, ini));
41722
- if (model === MODEL_MDS2) mdsModel(st.dist, st.n, mdsEdges(g, st.nodes, lens));
42342
+ if (model === MODEL_MDS2) mdsModel2(st.dist, st.n, mdsEdges(g, st.nodes, lens));
41723
42343
  initialPositions2(g, st);
41724
42344
  diffeqModel(g, st);
41725
42345
  solveModel(g, st);
41726
42346
  }
41727
42347
 
41728
- // src/layout/neato/matrix-ops.ts
41729
- var fr = Math.fround;
41730
- function orthog1(n, vec) {
41731
- let sum = 0;
41732
- for (let i = 0; i < n; i++) sum += vec[i];
41733
- sum /= n;
41734
- for (let i = 0; i < n; i++) vec[i] = vec[i] - sum;
42348
+ // src/layout/neato/make-graph-data.ts
42349
+ var MODE_IPSEP2 = 3;
42350
+ var EDIST_IN = 1;
42351
+ var EDIST_OUT = -1;
42352
+ var EDIST_NONE = 0;
42353
+ function graphHasLen(g) {
42354
+ for (const e of g.edges) {
42355
+ if (e.attrs.has("len")) return true;
42356
+ }
42357
+ return false;
41735
42358
  }
41736
- function orthog1f(n, vec) {
41737
- let sum = fr(0);
41738
- for (let i = 0; i < n; i++) sum = fr(sum + vec[i]);
41739
- sum = fr(sum / n);
41740
- for (let i = 0; i < n; i++) vec[i] = vec[i] - sum;
42359
+ var edistsOf = (v) => v.edists;
42360
+ function reverseBackEdge(graph, i, e, mode) {
42361
+ const node = graph[i];
42362
+ const j = node.edges[e];
42363
+ edistsOf(node)[e] = mode === MODE_IPSEP2 ? EDIST_OUT : EDIST_IN;
42364
+ const target = graph[j];
42365
+ let f = 1;
42366
+ while (f < target.nedges && target.edges[f] !== i) f++;
42367
+ if (f >= target.nedges) throw new Error(`neato: edge ${i}-${j} has no reverse entry`);
42368
+ edistsOf(target)[f] = EDIST_OUT;
42369
+ }
42370
+ function dfsCycle(graph, start, st) {
42371
+ const { mode, mark, onstack } = st;
42372
+ const stack = [{ i: start, e: 1 }];
42373
+ mark[start] = 1;
42374
+ onstack[start] = 1;
42375
+ for (let frame = stack.at(-1); frame !== void 0; frame = stack.at(-1)) {
42376
+ const { i } = frame;
42377
+ const node = graph[i];
42378
+ if (frame.e >= node.nedges) {
42379
+ onstack[i] = 0;
42380
+ stack.pop();
42381
+ continue;
42382
+ }
42383
+ const e = frame.e++;
42384
+ if (edistsOf(node)[e] === EDIST_IN) continue;
42385
+ const j = node.edges[e];
42386
+ if (onstack[j]) {
42387
+ reverseBackEdge(graph, i, e, mode);
42388
+ } else if (!mark[j]) {
42389
+ mark[j] = 1;
42390
+ onstack[j] = 1;
42391
+ stack.push({ i: j, e: 1 });
42392
+ }
42393
+ }
41741
42394
  }
41742
- function rightMultWithVectorFF(m, n, vector, result) {
42395
+ function acyclic2(graph, nv, mode) {
42396
+ const st = { mode, mark: new Uint8Array(nv), onstack: new Uint8Array(nv) };
42397
+ for (let i = 0; i < nv; i++) {
42398
+ if (st.mark[i]) continue;
42399
+ dfsCycle(graph, i, st);
42400
+ }
42401
+ }
42402
+ function edgeDist2(dir, np, head) {
42403
+ if (dir !== void 0 && dir.startsWith("none")) return EDIST_NONE;
42404
+ return np === head ? EDIST_IN : EDIST_OUT;
42405
+ }
42406
+ function addNeighbours(g, np, entry, o) {
42407
+ const seen2 = /* @__PURE__ */ new Map();
42408
+ for (const ep of [...np.outEdges(g), ...np.inEdges(g)]) {
42409
+ if (ep.head === ep.tail) continue;
42410
+ const vp = ep.tail === np ? ep.head : ep.tail;
42411
+ const vid = vp.info.id;
42412
+ const dist5 = o.haveLen ? lateDouble(ep.attrs.get("len"), 1, 0) : 1;
42413
+ const idx = seen2.get(vid);
42414
+ if (idx !== void 0) {
42415
+ if (o.haveLen) entry.ewgts[idx] = Math.max(entry.ewgts[idx], dist5);
42416
+ continue;
42417
+ }
42418
+ seen2.set(vid, entry.nedges);
42419
+ entry.edges.push(vid);
42420
+ if (o.haveLen || o.haveDir) entry.ewgts.push(dist5);
42421
+ if (o.haveDir) edistsOf(entry).push(edgeDist2(ep.attrs.get("dir"), np, ep.head));
42422
+ entry.nedges++;
42423
+ }
42424
+ }
42425
+ function makeGraphDataC(g, nodeList, haveLen, haveDir, mode = -1) {
42426
+ const vtx = nodeList.map((_, i) => ({
42427
+ nedges: 1,
42428
+ edges: [i],
42429
+ ewgts: haveLen || haveDir ? [0] : [],
42430
+ ...haveDir ? { edists: [0] } : {}
42431
+ }));
42432
+ for (const np of nodeList) addNeighbours(g, np, vtx[np.info.id], { haveLen, haveDir });
42433
+ if (haveDir) acyclic2(vtx, nodeList.length, mode);
42434
+ return vtx;
42435
+ }
42436
+
42437
+ // src/layout/neato/kkutils.ts
42438
+ function compareKeys(a, b) {
42439
+ if (a < b) return -1;
42440
+ if (a > b) return 1;
42441
+ return 0;
42442
+ }
42443
+ function gvSortByPlace(place, ordering, first, count) {
42444
+ const slice = Array.from(ordering.subarray(first, first + count));
42445
+ gvQsort(slice, (x, y) => compareKeys(place[x], place[y]));
42446
+ for (let i = 0; i < count; i++) ordering[first + i] = slice[i];
42447
+ }
42448
+ function quicksortPlace(place, ordering, size) {
42449
+ gvSortByPlace(place, ordering, 0, size);
42450
+ }
42451
+ function quicksortPlacef(place, ordering, first, last) {
42452
+ if (first < last) {
42453
+ gvSortByPlace(place, ordering, first, last - first + 1);
42454
+ }
42455
+ }
42456
+ function computeApspDijkstra(graph, n) {
42457
+ const dij = [];
42458
+ for (let i = 0; i < n; i++) dij.push(new Int32Array(n));
42459
+ for (let i = 0; i < n; i++) ngdijkstra(i, graph, n, dij[i]);
42460
+ return dij;
42461
+ }
42462
+ function computeApspSimple(graph, n) {
42463
+ const dij = [];
42464
+ for (let i = 0; i < n; i++) dij.push(new Int32Array(n));
42465
+ for (let i = 0; i < n; i++) bfs(i, graph, n, dij[i]);
42466
+ return dij;
42467
+ }
42468
+ function computeApsp(graph, n) {
42469
+ return graph[0].ewgts.length > 0 ? computeApspDijkstra(graph, n) : computeApspSimple(graph, n);
42470
+ }
42471
+
42472
+ // src/layout/neato/quad-prog-solve.ts
42473
+ var fr2 = Math.fround;
42474
+ var TOLERANCE = fr2(0.01);
42475
+ var BOUND = 1e9;
42476
+ var BLOCK_EPSILON = 1e-9;
42477
+ var NO_SPLIT = -1;
42478
+ var BITS = new DataView(new ArrayBuffer(8));
42479
+ function oddNeighbour(s, awayFromZero) {
42480
+ BITS.setFloat64(0, s);
42481
+ const hi = BITS.getUint32(0);
42482
+ const lo = BITS.getUint32(4);
42483
+ if (awayFromZero) {
42484
+ BITS.setUint32(4, lo + 1);
42485
+ } else if (lo === 0) {
42486
+ BITS.setUint32(0, hi - 1);
42487
+ BITS.setUint32(4, 4294967295);
42488
+ } else {
42489
+ BITS.setUint32(4, lo - 1);
42490
+ }
42491
+ return BITS.getFloat64(0);
42492
+ }
42493
+ function fmaf(a, b, c) {
42494
+ const p = a * b;
42495
+ const s = p + c;
42496
+ const bv = s - p;
42497
+ const err = p - (s - bv) + (c - bv);
42498
+ if (err === 0 || !Number.isFinite(s)) return fr2(s);
42499
+ BITS.setFloat64(0, s);
42500
+ if ((BITS.getUint32(4) & 1) !== 0) return fr2(s);
42501
+ return fr2(oddNeighbour(s, err > 0 === s > 0));
42502
+ }
42503
+ function blockPlaceNumerator(blockDeg, desPlaceBlock, negLapTimesDesired, toBlockConnectivity, curPlace) {
42504
+ const t = fmaf(blockDeg, desPlaceBlock, negLapTimesDesired);
42505
+ return fmaf(toBlockConnectivity, curPlace, t);
42506
+ }
42507
+ function equals(a, b) {
42508
+ return Math.abs(fr2(a - b)) < TOLERANCE;
42509
+ }
42510
+ function fminf(a, b) {
42511
+ if (Number.isNaN(a)) return b;
42512
+ if (Number.isNaN(b)) return a;
42513
+ return a < b ? a : b;
42514
+ }
42515
+ function fmaxf(a, b) {
42516
+ if (Number.isNaN(a)) return b;
42517
+ if (Number.isNaN(b)) return a;
42518
+ return a > b ? a : b;
42519
+ }
42520
+ function unpackMatrix(packedMat, n) {
42521
+ const flat = new Float32Array(n * n);
42522
+ const mat = new Array(n);
42523
+ for (let i = 0; i < n; i++) mat[i] = flat.subarray(i * n, (i + 1) * n);
42524
+ for (let i = 0, k = 0; i < n; i++) {
42525
+ for (let j = i; j < n; j++, k++) {
42526
+ mat[j][i] = mat[i][j] = packedMat[k];
42527
+ }
42528
+ }
42529
+ return mat;
42530
+ }
42531
+ function ensureMonotonicOrderingWithGaps(place, n, ordering, levels, numLevels, levelsGap) {
42532
+ let lowerBound = fr2(-1e9);
42533
+ let level = -1;
42534
+ let maxInLevel = 0;
42535
+ for (let i = 0; i < n; i++) {
42536
+ if (i >= maxInLevel) {
42537
+ level++;
42538
+ maxInLevel = level === numLevels ? n : levels[level];
42539
+ lowerBound = i > 0 ? fr2(place[ordering[i - 1]] + levelsGap) : fr2(-1e9);
42540
+ quicksortPlacef(place, ordering, i, maxInLevel - 1);
42541
+ }
42542
+ const node = ordering[i];
42543
+ if (place[node] < lowerBound) place[node] = lowerBound;
42544
+ }
42545
+ }
42546
+ function computeNodeLevels(e) {
42547
+ const lev = new Int32Array(e.n);
42548
+ let level = -1;
42549
+ let maxInLevel = 0;
42550
+ for (let i = 0; i < e.n; i++) {
42551
+ if (i >= maxInLevel) {
42552
+ level++;
42553
+ maxInLevel = level === e.numLevels ? e.n : e.levels[level];
42554
+ }
42555
+ lev[e.ordering[i]] = level;
42556
+ }
42557
+ return lev;
42558
+ }
42559
+ function growBlock(c, left2, curPlace) {
42560
+ const { place, lev, levelsGap, e } = c;
42561
+ const gap = e.fArray4;
42562
+ let targetPlace = curPlace;
42563
+ gap[e.ordering[left2]] = 0;
42564
+ let right2;
42565
+ for (right2 = left2 + 1; right2 < e.n; right2++) {
42566
+ if (lev[right2] > lev[right2 - 1]) {
42567
+ targetPlace = fr2(targetPlace + levelsGap);
42568
+ }
42569
+ const node = e.ordering[right2];
42570
+ if (Math.abs(fr2(place[node] - targetPlace)) > BLOCK_EPSILON) break;
42571
+ gap[node] = fr2(place[node] - curPlace);
42572
+ }
42573
+ return right2;
42574
+ }
42575
+ function computeDesiredPlaces(c, left2, right2) {
42576
+ const { e, place, b } = c;
42577
+ for (let i = left2; i < right2; i++) {
42578
+ const node = e.ordering[i];
42579
+ let newPlaceI = -b[node];
42580
+ const lapNode = e.A[node];
42581
+ for (let j = 0; j < e.n; j++) {
42582
+ if (j === node) continue;
42583
+ newPlaceI = fmaf(lapNode[j], place[j], newPlaceI);
42584
+ }
42585
+ e.fArray1[node] = fr2(fr2(newPlaceI / -lapNode[node]) - e.fArray4[node]);
42586
+ }
42587
+ }
42588
+ function collectWhere(c, from, to, test) {
42589
+ for (let j = from; j < to; j++) {
42590
+ const node = c.e.ordering[j];
42591
+ if (test(c.e.fArray1[node])) c.block.push(node);
42592
+ }
42593
+ }
42594
+ function orderBlockByLevels(c, left2, right2, curPlace) {
42595
+ const { e } = c;
42596
+ c.block.length = 0;
42597
+ let firstNextLevel = 0;
42598
+ for (let i = left2; i < right2; i = firstNextLevel) {
42599
+ const level = c.lev[e.ordering[i]];
42600
+ firstNextLevel = level === e.numLevels ? right2 : Math.min(right2, e.levels[level]);
42601
+ collectWhere(c, i, firstNextLevel, (d) => d < curPlace);
42602
+ collectWhere(c, i, firstNextLevel, (d) => d === curPlace);
42603
+ collectWhere(c, i, firstNextLevel, (d) => d > curPlace);
42604
+ }
42605
+ }
42606
+ function computePrefixDesiredPlaces(c, curPlace) {
42607
+ const { e, block } = c;
42608
+ let desPlaceBlock = 0;
42609
+ let blockDeg = 0;
42610
+ for (let i = 0; i < block.length; i++) {
42611
+ const node = block[i];
42612
+ let toBlockConnectivity = 0;
42613
+ const lapNode = e.A[node];
42614
+ for (let j = 0; j < i; j++) {
42615
+ toBlockConnectivity = fr2(toBlockConnectivity - lapNode[block[j]]);
42616
+ }
42617
+ toBlockConnectivity = fr2(toBlockConnectivity * 2);
42618
+ const num2 = blockPlaceNumerator(
42619
+ blockDeg,
42620
+ desPlaceBlock,
42621
+ fr2(-lapNode[node] * e.fArray1[node]),
42622
+ toBlockConnectivity,
42623
+ curPlace
42624
+ );
42625
+ desPlaceBlock = fr2(num2 / fr2(fr2(blockDeg - lapNode[node]) + toBlockConnectivity));
42626
+ e.fArray2[i] = desPlaceBlock;
42627
+ blockDeg = fr2(blockDeg + fr2(toBlockConnectivity - lapNode[node]));
42628
+ }
42629
+ if (e.n >= 0 && block.length === e.n) {
42630
+ e.fArray2[e.n - 1] = curPlace;
42631
+ }
42632
+ }
42633
+ function computeSuffixDesiredPlaces(c, curPlace) {
42634
+ const { e, block } = c;
42635
+ let desPlaceBlock = 0;
42636
+ let blockDeg = 0;
42637
+ for (let i = block.length - 1; i >= 0; i--) {
42638
+ const node = block[i];
42639
+ let toBlockConnectivity = 0;
42640
+ const lapNode = e.A[node];
42641
+ for (let j = i + 1; j < block.length; j++) {
42642
+ toBlockConnectivity = fr2(toBlockConnectivity - lapNode[block[j]]);
42643
+ }
42644
+ toBlockConnectivity = fr2(toBlockConnectivity * 2);
42645
+ const num2 = blockPlaceNumerator(
42646
+ blockDeg,
42647
+ desPlaceBlock,
42648
+ fr2(-lapNode[node] * e.fArray1[node]),
42649
+ toBlockConnectivity,
42650
+ curPlace
42651
+ );
42652
+ desPlaceBlock = fr2(num2 / fr2(fr2(blockDeg - lapNode[node]) + toBlockConnectivity));
42653
+ e.fArray3[i] = desPlaceBlock;
42654
+ blockDeg = fr2(blockDeg + fr2(toBlockConnectivity - lapNode[node]));
42655
+ }
42656
+ if (e.n >= 0 && block.length === e.n) {
42657
+ e.fArray3[0] = curPlace;
42658
+ }
42659
+ }
42660
+ var LIMITED = new Float64Array(2);
42661
+ function limitMoves(prefix, suffix, curPlace) {
42662
+ if (suffix < prefix) {
42663
+ if (suffix < curPlace) {
42664
+ if (prefix > curPlace) prefix = curPlace;
42665
+ suffix = prefix;
42666
+ } else if (prefix > curPlace) {
42667
+ prefix = suffix;
42668
+ }
42669
+ }
42670
+ LIMITED[0] = prefix;
42671
+ LIMITED[1] = suffix;
42672
+ }
42673
+ function findBestSplit(c, curPlace) {
42674
+ const { e, block } = c;
42675
+ let bestI = NO_SPLIT;
42676
+ let maxMovement = 0;
42677
+ for (let i = 0; i < block.length; i++) {
42678
+ const suffixDesPlace = e.fArray3[i];
42679
+ const prefixDesPlace = i > 0 ? e.fArray2[i - 1] : suffixDesPlace;
42680
+ limitMoves(prefixDesPlace, suffixDesPlace, curPlace);
42681
+ const movement = (block.length - i) * Math.abs(fr2(LIMITED[1] - curPlace)) + i * Math.abs(fr2(LIMITED[0] - curPlace));
42682
+ if (movement > maxMovement) {
42683
+ maxMovement = movement;
42684
+ bestI = i;
42685
+ }
42686
+ }
42687
+ return bestI;
42688
+ }
42689
+ function computeUpperBound(c, right2) {
42690
+ const { e, place, lev, levelsGap, block } = c;
42691
+ if (right2 >= e.n) return BOUND;
42692
+ const lastGap = e.fArray4[block[block.length - 1]];
42693
+ const nextPlace = place[e.ordering[right2]];
42694
+ if (lev[e.ordering[right2]] > lev[e.ordering[right2 - 1]]) {
42695
+ return fr2(fr2(nextPlace - levelsGap) - lastGap);
42696
+ }
42697
+ return fr2(nextPlace - lastGap);
42698
+ }
42699
+ function nextLowerBound(c, right2) {
42700
+ const { e, place, lev, levelsGap, block } = c;
42701
+ const last = place[block[block.length - 1]];
42702
+ if (right2 < e.n && lev[e.ordering[right2]] > lev[e.ordering[right2 - 1]]) {
42703
+ return fr2(last + levelsGap);
42704
+ }
42705
+ return last;
42706
+ }
42707
+ function moveSplitBlock(c, bestI, left2, right2, curPlace) {
42708
+ const { e, place, block } = c;
42709
+ let suffixDesPlace = e.fArray3[bestI];
42710
+ let prefixDesPlace = bestI > 0 ? e.fArray2[bestI - 1] : suffixDesPlace;
42711
+ suffixDesPlace = fminf(suffixDesPlace, computeUpperBound(c, right2));
42712
+ prefixDesPlace = fmaxf(prefixDesPlace, c.lowerBound);
42713
+ limitMoves(prefixDesPlace, suffixDesPlace, curPlace);
42714
+ prefixDesPlace = LIMITED[0];
42715
+ suffixDesPlace = LIMITED[1];
42716
+ for (let i = 0; i < bestI; i++) {
42717
+ place[block[i]] = fr2(prefixDesPlace + e.fArray4[block[i]]);
42718
+ }
42719
+ for (let i = bestI; i < block.length; i++) {
42720
+ place[block[i]] = fr2(suffixDesPlace + e.fArray4[block[i]]);
42721
+ }
42722
+ c.lowerBound = nextLowerBound(c, right2);
42723
+ for (let i = left2; i < right2; i++) e.ordering[i] = block[i - left2];
42724
+ c.converged = c.converged && equals(prefixDesPlace, curPlace) && equals(suffixDesPlace, curPlace);
42725
+ }
42726
+ function processBlock(c, left2) {
42727
+ const curPlace = c.place[c.e.ordering[left2]];
42728
+ const right2 = growBlock(c, left2, curPlace);
42729
+ computeDesiredPlaces(c, left2, right2);
42730
+ orderBlockByLevels(c, left2, right2, curPlace);
42731
+ computePrefixDesiredPlaces(c, curPlace);
42732
+ computeSuffixDesiredPlaces(c, curPlace);
42733
+ const bestI = findBestSplit(c, curPlace);
42734
+ if (bestI !== NO_SPLIT) {
42735
+ moveSplitBlock(c, bestI, left2, right2, curPlace);
42736
+ } else {
42737
+ c.lowerBound = nextLowerBound(c, right2);
42738
+ }
42739
+ return right2;
42740
+ }
42741
+ function constrainedMajorizationNewWithGaps(e, b, coords, curAxis, maxIterations, levelsGap) {
42742
+ const place = coords[curAxis];
42743
+ if (maxIterations <= 0) return;
42744
+ const gap = fr2(levelsGap);
42745
+ ensureMonotonicOrderingWithGaps(place, e.n, e.ordering, e.levels, e.numLevels, gap);
42746
+ const c = {
42747
+ e,
42748
+ place,
42749
+ b,
42750
+ lev: computeNodeLevels(e),
42751
+ levelsGap: gap,
42752
+ block: [],
42753
+ lowerBound: fr2(-BOUND),
42754
+ converged: false
42755
+ };
42756
+ for (let counter = 0; counter < maxIterations && !c.converged; counter++) {
42757
+ c.converged = true;
42758
+ c.lowerBound = fr2(-BOUND);
42759
+ for (let left2 = 0, right2; left2 < e.n; left2 = right2) {
42760
+ right2 = processBlock(c, left2);
42761
+ }
42762
+ orthog1f(e.n, place);
42763
+ }
42764
+ }
42765
+ function initConstrainedMajorization(packedMat, n, ordering, levels, numLevels) {
42766
+ return {
42767
+ A: unpackMatrix(packedMat, n),
42768
+ n,
42769
+ fArray1: new Float32Array(n),
42770
+ fArray2: new Float32Array(n),
42771
+ fArray3: new Float32Array(n),
42772
+ fArray4: new Float32Array(n),
42773
+ ordering,
42774
+ levels,
42775
+ numLevels
42776
+ };
42777
+ }
42778
+
42779
+ // src/layout/neato/conjgrad-mkernel.ts
42780
+ var fr3 = Math.fround;
42781
+ var RIGHT_MULT_BLOCK = 16;
42782
+ var ZERO_LENGTH_MESSAGE = "conjugate_gradient: unexpected length 0 vector\n";
42783
+ function rightMultWithVectorFFFused(m, n, vector, result) {
41743
42784
  for (let i = 0; i < n; i++) result[i] = 0;
41744
42785
  let index = 0;
41745
42786
  for (let i = 0; i < n; i++) {
41746
42787
  const vi = vector[i];
41747
- let res = fr(m[index++] * vi);
42788
+ let res = fmaf(m[index++], vi, 0);
42789
+ const len = n - i - 1;
42790
+ const blockEnd = i + 1 + (len - len % RIGHT_MULT_BLOCK);
41748
42791
  for (let j = i + 1; j < n; j++, index++) {
41749
- res = fr(res + fr(m[index] * vector[j]));
41750
- result[j] = result[j] + fr(m[index] * vi);
42792
+ const mij = m[index];
42793
+ res = j < blockEnd ? fr3(res + fr3(mij * vector[j])) : fmaf(mij, vector[j], res);
42794
+ result[j] = fmaf(mij, vi, result[j]);
41751
42795
  }
41752
42796
  result[i] = result[i] + res;
41753
42797
  }
41754
42798
  }
41755
- function vectorsSubtractionF(n, v1, v2, result) {
41756
- for (let i = 0; i < n; i++) result[i] = v1[i] - v2[i];
42799
+ function vectorsMultAdditionFused(n, v1, alpha, v2) {
42800
+ for (let i = 0; i < n; i++) v1[i] = fmaf(alpha, v2[i], v1[i]);
41757
42801
  }
41758
- function vectorsMultAdditionF(n, v1, alpha, v2) {
41759
- const a = fr(alpha);
41760
- for (let i = 0; i < n; i++) v1[i] = v1[i] + fr(a * v2[i]);
42802
+ var CgStep = { CONTINUE: 0, STOP: 1, ERROR: 2 };
42803
+ function initialState(A3, x, b, n) {
42804
+ const Ax = new Float32Array(n);
42805
+ const st = { n, r: new Float32Array(n), p: new Float32Array(n), Ap: new Float32Array(n), rR: 0 };
42806
+ orthog1f(n, x);
42807
+ orthog1f(n, b);
42808
+ rightMultWithVectorFFFused(A3, n, x, Ax);
42809
+ orthog1f(n, Ax);
42810
+ vectorsSubtractionF(n, b, Ax, st.r);
42811
+ copyVectorF(n, st.r, st.p);
42812
+ st.rR = vectorsInnerProductF(n, st.r, st.r);
42813
+ return st;
41761
42814
  }
41762
- function vectorsInnerProductF(n, v1, v2) {
41763
- let result = 0;
41764
- for (let i = 0; i < n; i++) result += fr(v1[i] * v2[i]);
41765
- return result;
42815
+ function cgIteration(A3, x, st, last) {
42816
+ const { n, r, p, Ap } = st;
42817
+ orthog1f(n, p);
42818
+ orthog1f(n, x);
42819
+ orthog1f(n, r);
42820
+ rightMultWithVectorFFFused(A3, n, p, Ap);
42821
+ orthog1f(n, Ap);
42822
+ const pAp = vectorsInnerProductF(n, p, Ap);
42823
+ if (pAp === 0) return CgStep.STOP;
42824
+ const alpha = st.rR / pAp;
42825
+ vectorsMultAdditionFused(n, x, fr3(alpha), p);
42826
+ if (last) return CgStep.CONTINUE;
42827
+ vectorsMultAdditionFused(n, r, fr3(-alpha), Ap);
42828
+ const rRNew = vectorsInnerProductF(n, r, r);
42829
+ if (st.rR === 0) {
42830
+ agerrorf(ZERO_LENGTH_MESSAGE);
42831
+ return CgStep.ERROR;
42832
+ }
42833
+ const beta = fr3(rRNew / st.rR);
42834
+ st.rR = rRNew;
42835
+ for (let j = 0; j < n; j++) p[j] = fmaf(beta, p[j], r[j]);
42836
+ return CgStep.CONTINUE;
42837
+ }
42838
+ function conjugateGradientMkernelFused(A3, x, b, n, o) {
42839
+ const st = initialState(A3, x, b, n);
42840
+ for (let i = 0; i < o.maxIterations && maxAbsF(n, st.r) > o.tol; i++) {
42841
+ const step = cgIteration(A3, x, st, i >= o.maxIterations - 1);
42842
+ if (step === CgStep.STOP) break;
42843
+ if (step === CgStep.ERROR) return 1;
42844
+ }
42845
+ return 0;
41766
42846
  }
41767
- function copyVectorF(n, src, dst) {
41768
- for (let i = 0; i < n; i++) dst[i] = src[i];
42847
+
42848
+ // src/layout/neato/opt-arrangement.ts
42849
+ var HIERARCHY_CG_TOL = 1e-3;
42850
+ function constructB(graph, n, b) {
42851
+ for (let i = 0; i < n; i++) {
42852
+ if (graph[0].edists == null) continue;
42853
+ let bI = 0;
42854
+ const node = graph[i];
42855
+ for (let j = 1; j < node.nedges; j++) {
42856
+ bI += Math.fround(Math.fround(node.ewgts[j]) * node.edists[j]);
42857
+ }
42858
+ b[i] = bI;
42859
+ }
41769
42860
  }
41770
- function maxAbsF(n, vec) {
41771
- let max = fr(-1e30);
42861
+ function setUniformWeights(graph, n) {
42862
+ const old = [];
41772
42863
  for (let i = 0; i < n; i++) {
41773
- const a = fr(Math.abs(vec[i]));
41774
- if (a > max) max = a;
42864
+ const node = graph[i];
42865
+ old.push(node.ewgts);
42866
+ const weights = new Array(node.nedges).fill(1);
42867
+ weights[0] = -(node.nedges - 1);
42868
+ node.ewgts = weights;
41775
42869
  }
41776
- return max;
42870
+ return old;
41777
42871
  }
41778
- function squareVec(n, vec) {
41779
- for (let i = 0; i < n; i++) vec[i] = vec[i] * vec[i];
42872
+ function computeYCoords(graph, n, yCoords, maxIterations) {
42873
+ let rv = 0;
42874
+ const b = new Float64Array(n);
42875
+ constructB(graph, n, b);
42876
+ initVecOrth1(n, yCoords);
42877
+ const oldEwgts = setUniformWeights(graph, n);
42878
+ if (conjugateGradient(graph, yCoords, b, n, HIERARCHY_CG_TOL, maxIterations) < 0) {
42879
+ rv = 1;
42880
+ }
42881
+ for (let i = 0; i < n; i++) graph[i].ewgts = oldEwgts[i];
42882
+ return rv;
41780
42883
  }
41781
- function invertVec(n, vec) {
42884
+
42885
+ // src/layout/neato/compute-hierarchy.ts
42886
+ function countLevels(y, ordering, n, tol) {
42887
+ let numLevels = 0;
42888
+ for (let i = 1; i < n; i++) {
42889
+ if (y[ordering[i]] - y[ordering[i - 1]] > tol) numLevels++;
42890
+ }
42891
+ return numLevels;
42892
+ }
42893
+ function fillLevels(y, ordering, n, tol, numLevels) {
42894
+ if (numLevels === 0) {
42895
+ const levels2 = new Int32Array(1);
42896
+ levels2[0] = n;
42897
+ return levels2;
42898
+ }
42899
+ const levels = new Int32Array(numLevels);
42900
+ let count = 0;
42901
+ for (let i = 1; i < n; i++) {
42902
+ if (y[ordering[i]] - y[ordering[i - 1]] > tol) levels[count++] = i;
42903
+ }
42904
+ return levels;
42905
+ }
42906
+ function computeHierarchy(graph, n, absTol, relTol, given) {
42907
+ let y;
42908
+ if (given) {
42909
+ y = given;
42910
+ } else {
42911
+ y = new Float64Array(n);
42912
+ if (computeYCoords(graph, n, y, n)) return null;
42913
+ }
42914
+ const ordering = new Int32Array(n);
42915
+ for (let i = 0; i < n; i++) ordering[i] = i;
42916
+ quicksortPlace(y, ordering, n);
42917
+ const hierarchySpan = y[ordering[n - 1]] - y[ordering[0]];
42918
+ const relative = relTol * hierarchySpan / (n - 1);
42919
+ const tol = absTol > relative ? absTol : relative;
42920
+ const numLevels = countLevels(y, ordering, n, tol);
42921
+ return { ordering, levels: fillLevels(y, ordering, n, tol, numLevels), numLevels };
42922
+ }
42923
+
42924
+ // src/layout/neato/smart-ini-x.ts
42925
+ var fr4 = Math.fround;
42926
+ var SCALE_FACTOR = 256;
42927
+ var DBL_EPSILON = 2220446049250313e-31;
42928
+ var POWER_LENGTH_FLOOR = 1e-10;
42929
+ var BLOCK_STANDARDIZE_NORM = 4;
42930
+ var BLOCK_MAT_MULT_ROW = 4;
42931
+ var BLOCK_MAT_MULT_ORTHOG = 8;
42932
+ var BLOCK_GUESS_ORTHOG = 8;
42933
+ var BLOCK_GUESS_LEN = BLOCK_NONE;
42934
+ var BLOCK_LOOP_LEN = BLOCK_NONE;
42935
+ var BLOCK_ANGLE = 8;
42936
+ var BLOCK_UNIFORM_SUMS = 4;
42937
+ var BLOCK_AVGS = 4;
42938
+ function standardize(orthog, nvtxs) {
42939
+ let avg = 0;
42940
+ for (let i = 0; i < nvtxs; i++) avg += orthog[i];
42941
+ avg /= nvtxs;
42942
+ for (let i = 0; i < nvtxs; i++) orthog[i] = orthog[i] - avg;
42943
+ const len = norm(orthog, nvtxs - 1, BLOCK_STANDARDIZE_NORM);
42944
+ if (Math.abs(len) < DBL_EPSILON) return;
42945
+ vectorsScalarMult(nvtxs, orthog, 1 / len, orthog);
42946
+ }
42947
+ function matMultVecOrthog(mat, dim, vec, result, orthog) {
42948
+ const blocked = dim - dim % BLOCK_MAT_MULT_ROW;
42949
+ for (let i = 0; i < dim; i++) {
42950
+ const row = mat[i];
42951
+ let sum = 0;
42952
+ let j = 0;
42953
+ for (; j < blocked; j++) sum += row[j] * vec[j];
42954
+ for (; j < dim; j++) sum = fma2(row[j], vec[j], sum);
42955
+ result[i] = sum;
42956
+ }
42957
+ const alpha = -innerProduct(dim, result, orthog, BLOCK_MAT_MULT_ORTHOG);
42958
+ scadd(result, dim - 1, alpha, orthog);
42959
+ }
42960
+ function orthogonalizeAgainstEigs(p, vec, count, block) {
42961
+ for (let j = 0; j < count; j++) {
42962
+ const alpha = -innerProduct(p.n, p.eigs[j], vec, block);
42963
+ scadd(vec, p.n - 1, alpha, p.eigs[j]);
42964
+ }
42965
+ }
42966
+ function chooseStartVector(p, i) {
42967
+ const curr = p.eigs[i];
42968
+ for (; ; ) {
42969
+ for (let j = 0; j < p.n; j++) curr[j] = crand() % 100;
42970
+ const alpha = -innerProduct(p.n, p.orthog, curr, BLOCK_GUESS_ORTHOG);
42971
+ scadd(curr, p.n - 1, alpha, p.orthog);
42972
+ orthogonalizeAgainstEigs(p, curr, i, BLOCK_NONE);
42973
+ const len = norm(curr, p.n - 1, BLOCK_GUESS_LEN);
42974
+ if (len < POWER_LENGTH_FLOOR) continue;
42975
+ vectorsScalarMult(p.n, curr, 1 / len, curr);
42976
+ return;
42977
+ }
42978
+ }
42979
+ function iterateEigenvector(p, i, tol, work) {
42980
+ const curr = p.eigs[i];
42981
+ for (; ; ) {
42982
+ copyVector(p.n, curr, work.last);
42983
+ matMultVecOrthog(p.mat, p.n, curr, work.tmp, p.orthog);
42984
+ copyVector(p.n, work.tmp, curr);
42985
+ orthogonalizeAgainstEigs(p, curr, i, BLOCK_NONE);
42986
+ const len = norm(curr, p.n - 1, BLOCK_LOOP_LEN);
42987
+ if (len < POWER_LENGTH_FLOOR) {
42988
+ return { nullSpace: true, eval: 0 };
42989
+ }
42990
+ vectorsScalarMult(p.n, curr, 1 / len, curr);
42991
+ const angle = innerProduct(p.n, curr, work.last, BLOCK_ANGLE);
42992
+ if (!(Math.abs(angle) < tol)) {
42993
+ return { nullSpace: false, eval: angle * len };
42994
+ }
42995
+ }
42996
+ }
42997
+ function fillNullSpaceEigenvectors(p, from, neigs) {
42998
+ for (let i = from; i < neigs; i++) {
42999
+ const curr = p.eigs[i];
43000
+ for (let j = 0; j < p.n; j++) curr[j] = crand() % 100;
43001
+ orthogonalizeAgainstEigs(p, curr, i, BLOCK_NONE);
43002
+ const len = norm(curr, p.n - 1, BLOCK_NONE);
43003
+ vectorsScalarMult(p.n, curr, 1 / len, curr);
43004
+ p.evals[i] = 0;
43005
+ }
43006
+ }
43007
+ function sortEigenvectors(p, neigs, tmp) {
43008
+ for (let i = 0; i < neigs - 1; i++) {
43009
+ let largestIndex = i;
43010
+ let largestEval = p.evals[largestIndex];
43011
+ for (let j = i + 1; j < neigs; j++) {
43012
+ if (largestEval < p.evals[j]) {
43013
+ largestIndex = j;
43014
+ largestEval = p.evals[largestIndex];
43015
+ }
43016
+ }
43017
+ if (largestIndex !== i) {
43018
+ copyVector(p.n, p.eigs[i], tmp);
43019
+ copyVector(p.n, p.eigs[largestIndex], p.eigs[i]);
43020
+ copyVector(p.n, tmp, p.eigs[largestIndex]);
43021
+ p.evals[largestIndex] = p.evals[i];
43022
+ p.evals[i] = largestEval;
43023
+ }
43024
+ }
43025
+ }
43026
+ function powerIterationOrthog(p, neigsIn, pIterationThreshold) {
43027
+ const work = { tmp: new Float64Array(p.n), last: new Float64Array(p.n) };
43028
+ const tol = 1 - pIterationThreshold;
43029
+ const neigs = neigsIn >= p.n ? p.n : neigsIn;
43030
+ let i = 0;
43031
+ for (; i < neigs; i++) {
43032
+ chooseStartVector(p, i);
43033
+ const res = iterateEigenvector(p, i, tol, work);
43034
+ if (res.nullSpace) break;
43035
+ p.evals[i] = res.eval;
43036
+ }
43037
+ fillNullSpaceEigenvectors(p, i, neigs);
43038
+ sortEigenvectors(p, neigs, work.tmp);
43039
+ }
43040
+ function computeAvgs(Dij, n) {
43041
+ const rowAvg = new Float32Array(n);
43042
+ let sum = 0;
43043
+ const blocked = n - n % BLOCK_AVGS;
41782
43044
  for (let i = 0; i < n; i++) {
41783
- if (vec[i] !== 0) vec[i] = 1 / vec[i];
43045
+ let sumRow = 0;
43046
+ const row = Dij[i];
43047
+ let j = 0;
43048
+ for (; j < blocked; j++) {
43049
+ sum += row[j] * row[j];
43050
+ sumRow += row[j] * row[j];
43051
+ }
43052
+ for (; j < n; j++) {
43053
+ sum = fma2(row[j], row[j], sum);
43054
+ sumRow = fma2(row[j], row[j], sumRow);
43055
+ }
43056
+ rowAvg[i] = fr4(fr4(sumRow) / n);
41784
43057
  }
43058
+ return { rowAvg, allAvg: fr4(fr4(sum) / (n * n)) };
41785
43059
  }
41786
- function sqrtVecF(n, source, target) {
43060
+ function computeBij(Dij, n) {
43061
+ const Bij = [];
43062
+ for (let i = 0; i < n; i++) Bij.push(new Float32Array(n));
43063
+ const { rowAvg, allAvg } = computeAvgs(Dij, n);
41787
43064
  for (let i = 0; i < n; i++) {
41788
- if (source[i] >= 0) target[i] = fr(Math.sqrt(source[i]));
43065
+ for (let j = 0; j <= i; j++) {
43066
+ const fD = fr4(Dij[i][j]);
43067
+ const t = fr4(fma2(-fD, fD, rowAvg[i]));
43068
+ Bij[i][j] = fr4(fr4(t + rowAvg[j]) - allAvg);
43069
+ Bij[j][i] = Bij[i][j];
43070
+ }
43071
+ }
43072
+ return Bij;
43073
+ }
43074
+ function cmdsOrthog(n, dim, eigs, tol, input) {
43075
+ const { orthog, Dij } = input;
43076
+ const Bij = computeBij(Dij, n);
43077
+ const evals = new Float64Array(dim);
43078
+ const orthogAux = Float64Array.from(orthog.subarray(0, n));
43079
+ standardize(orthogAux, n);
43080
+ powerIterationOrthog({ mat: Bij, n, eigs, evals, orthog: orthogAux }, dim, tol);
43081
+ for (let i = 0; i < dim; i++) {
43082
+ for (let j = 0; j < n; j++) eigs[i][j] = eigs[i][j] * Math.sqrt(Math.abs(evals[i]));
41789
43083
  }
41790
43084
  }
41791
- function invertSqrtVec(n, vec) {
43085
+ function scaleGivenCoords(Dij, n, x) {
43086
+ let sum1 = 0;
43087
+ let sum2 = 0;
43088
+ for (let i = 1; i < n; i++) {
43089
+ const blocked = i - i % BLOCK_UNIFORM_SUMS;
43090
+ for (let j = 0; j < i; j++) {
43091
+ const d = Dij[i][j];
43092
+ const f = Math.abs(x[i] - x[j]);
43093
+ const t1 = 1 / d;
43094
+ const t2 = 1 / Math.imul(d, d) * f;
43095
+ if (j < blocked) {
43096
+ sum1 += t1 * f;
43097
+ sum2 += t2 * f;
43098
+ } else {
43099
+ sum1 = fma2(t1, f, sum1);
43100
+ sum2 = fma2(t2, f, sum2);
43101
+ }
43102
+ }
43103
+ }
43104
+ const uniLength = Math.abs(sum2) === Infinity ? 0 : sum1 / sum2;
43105
+ for (let i = 0; i < n; i++) x[i] = x[i] * uniLength;
43106
+ return uniLength;
43107
+ }
43108
+ function computeLaplacian(Dij, n) {
43109
+ const lap = [];
41792
43110
  for (let i = 0; i < n; i++) {
41793
- if (vec[i] > 0) vec[i] = 1 / fr(Math.sqrt(vec[i]));
43111
+ const row = new Float32Array(n);
43112
+ let degree = fr4(0);
43113
+ for (let j = 0; j < n; j++) {
43114
+ if (j === i) continue;
43115
+ const w = fr4(fr4(-1) / fr4(fr4(Dij[i][j]) * fr4(Dij[i][j])));
43116
+ row[j] = w;
43117
+ degree = fr4(degree - w);
43118
+ }
43119
+ row[i] = degree;
43120
+ lap.push(row);
43121
+ }
43122
+ return lap;
43123
+ }
43124
+ function computeResidualDistances(Dij, n, x) {
43125
+ for (let i = 1; i < n; i++) {
43126
+ const posI = x[i];
43127
+ for (let j = 0; j < i; j++) {
43128
+ const t = posI - x[j];
43129
+ const d = Dij[i][j];
43130
+ const diff = fma2(d, d, -(t * t));
43131
+ const v = diff > 0 ? Math.sqrt(diff) : 0;
43132
+ Dij[i][j] = v;
43133
+ Dij[j][i] = v;
43134
+ }
43135
+ }
43136
+ }
43137
+ function balanceOf(i, n, y, ctx) {
43138
+ const posI = y[i];
43139
+ let b = 0;
43140
+ for (let j = 0; j < n; j++) {
43141
+ if (j === i) continue;
43142
+ const term = fr4(fr4(ctx.Dij[i][j]) * -ctx.lap[i][j]);
43143
+ if (posI >= y[j]) b += term;
43144
+ else b -= term;
41794
43145
  }
43146
+ return b;
43147
+ }
43148
+ function solveBalanced(ctx, n, y, balance, convTol) {
43149
+ let converged = false;
43150
+ for (let iterations2 = 0; iterations2 < 200 && !converged; iterations2++) {
43151
+ if (conjugateGradientF(ctx.lap, y, balance, n, { tol: convTol, maxIterations: n, ortho1: true }) < 0) return 1;
43152
+ converged = true;
43153
+ for (let i = 0; i < n; i++) {
43154
+ const b = balanceOf(i, n, y, ctx);
43155
+ if (b !== balance[i] && Math.abs(1 - b / balance[i]) > 1e-5) {
43156
+ converged = false;
43157
+ balance[i] = b;
43158
+ }
43159
+ }
43160
+ }
43161
+ return 0;
43162
+ }
43163
+ function imdsGivenDim(graph, n, givenCoords, newCoords, conjTol) {
43164
+ const x = givenCoords;
43165
+ const y = newCoords;
43166
+ const Dij = computeApsp(graph, n);
43167
+ for (let i = 0; i < n; i++) {
43168
+ for (let j = 0; j < n; j++) Dij[i][j] = Dij[i][j] * SCALE_FACTOR;
43169
+ }
43170
+ const uniLength = scaleGivenCoords(Dij, n, x);
43171
+ cmdsOrthog(n, 1, [y], conjTol, { orthog: x, Dij });
43172
+ const lap = computeLaplacian(Dij, n);
43173
+ computeResidualDistances(Dij, n, x);
43174
+ const ctx = { Dij, lap };
43175
+ const balance = new Float64Array(n);
43176
+ for (let i = 0; i < n; i++) balance[i] = balanceOf(i, n, y, ctx);
43177
+ if (solveBalanced(ctx, n, y, balance, conjTol) === 1) return 1;
43178
+ for (let i = 0; !(Math.abs(uniLength) < DBL_EPSILON) && i < n; i++) {
43179
+ x[i] = x[i] / uniLength;
43180
+ y[i] = y[i] / uniLength;
43181
+ }
43182
+ return 0;
41795
43183
  }
41796
43184
 
41797
43185
  // src/layout/neato/stress-kernel.ts
41798
- var fr2 = Math.fround;
41799
- var TOLERANCE_CG = 1e-3;
43186
+ var fr5 = Math.fround;
43187
+ var TOLERANCE_CG2 = 1e-3;
41800
43188
  var OPT_EXP_FLAG = 2;
41801
43189
  function computeApspPacked2(graph, n) {
41802
43190
  const Dij = new Float32Array(n * (n + 1) / 2);
@@ -41856,9 +43244,9 @@ function cgStep(st, last) {
41856
43244
  vectorsMultAdditionF(n, st.r, -alpha, st.Ap);
41857
43245
  const rRNew = vectorsInnerProductF(n, st.r, st.r);
41858
43246
  if (st.rR === 0) return false;
41859
- const betaF = fr2(rRNew / st.rR);
43247
+ const betaF = fr5(rRNew / st.rR);
41860
43248
  st.rR = rRNew;
41861
- for (let j = 0; j < n; j++) st.p[j] = fr2(betaF * st.p[j]) + st.r[j];
43249
+ for (let j = 0; j < n; j++) st.p[j] = fr5(betaF * st.p[j]) + st.r[j];
41862
43250
  }
41863
43251
  return true;
41864
43252
  }
@@ -41920,8 +43308,8 @@ function buildLap1(lap1, lap2, coords, shape) {
41920
43308
  for (let k = 0; k < dim; k++) {
41921
43309
  const ck = coords[k];
41922
43310
  for (let x = 0; x < len; x++) {
41923
- const tmp = fr2(ck[i] + fr2(-1 * ck[i + 1 + x]));
41924
- distAccumulator[x] = distAccumulator[x] + fr2(tmp * tmp);
43311
+ const tmp = fr5(ck[i] + fr5(-1 * ck[i + 1 + x]));
43312
+ distAccumulator[x] = distAccumulator[x] + fr5(tmp * tmp);
41925
43313
  }
41926
43314
  }
41927
43315
  invertSqrtVec(len, distAccumulator);
@@ -41933,7 +43321,7 @@ function buildLap1(lap1, lap2, coords, shape) {
41933
43321
  let degree = 0;
41934
43322
  if (exp === 2) {
41935
43323
  for (let j = 0; j < len; j++, count++) {
41936
- const val2 = lap1[count] = fr2(lap1[count] * distAccumulator[j]);
43324
+ const val2 = lap1[count] = fr5(lap1[count] * distAccumulator[j]);
41937
43325
  degree += val2;
41938
43326
  degrees[i + j + 1] = degrees[i + j + 1] - val2;
41939
43327
  }
@@ -41967,10 +43355,10 @@ function computeStress(st) {
41967
43355
  }
41968
43356
  function solveAxis(st, k, havePinned, nodes) {
41969
43357
  if (!havePinned) {
41970
- return conjugateGradientMkernel2(st.lap2, st.coords[k], st.b[k], st.n, TOLERANCE_CG, st.n);
43358
+ return conjugateGradientMkernel2(st.lap2, st.coords[k], st.b[k], st.n, TOLERANCE_CG2, st.n);
41971
43359
  }
41972
43360
  copyVectorF(st.n, st.coords[k], st.tmpCoords);
41973
- const rc = conjugateGradientMkernel2(st.lap2, st.tmpCoords, st.b[k], st.n, TOLERANCE_CG, st.n);
43361
+ const rc = conjugateGradientMkernel2(st.lap2, st.tmpCoords, st.b[k], st.n, TOLERANCE_CG2, st.n);
41974
43362
  if (rc < 0) return rc;
41975
43363
  for (let i = 0; i < st.n; i++) {
41976
43364
  if (!isFixed(nodes[i])) st.coords[k][i] = st.tmpCoords[i];
@@ -41986,10 +43374,10 @@ function stressMajorizationKDMkernel(Dij, n, dCoords, nodes, o) {
41986
43374
  const coords = [];
41987
43375
  for (let i = 0; i < dim; i++) {
41988
43376
  const c = new Float32Array(n);
41989
- for (let j = 0; j < n; j++) c[j] = fr2(dCoords[i][j]);
43377
+ for (let j = 0; j < n; j++) c[j] = fr5(dCoords[i][j]);
41990
43378
  coords.push(c);
41991
43379
  }
41992
- const constantTerm = fr2(n * (n - 1) / 2);
43380
+ const constantTerm = fr5(n * (n - 1) / 2);
41993
43381
  const lap2 = Dij;
41994
43382
  buildLap2(lap2, n, exp);
41995
43383
  const lapLength = n * (n + 1) / 2;
@@ -42024,6 +43412,261 @@ function stressMajorizationKDMkernel(Dij, n, dCoords, nodes, o) {
42024
43412
  return iterations;
42025
43413
  }
42026
43414
 
43415
+ // src/layout/neato/constrained-majorization.ts
43416
+ var fr6 = Math.fround;
43417
+ var LOCAL_CONSTR_MAJOR_ITERATIONS = 15;
43418
+ var LEVELS_SEP_TOL = 0.1;
43419
+ var ABS_TOL = 0.01;
43420
+ var SUBSPACE_ITERATIONS = 15;
43421
+ var FLT_MAX3 = 34028234663852886e22;
43422
+ var DBL_MAX = Number.MAX_VALUE;
43423
+ var MIN_LEVELS = 1;
43424
+ var Y_AXIS = 1;
43425
+ function unsupported2(what) {
43426
+ throw new RenderError(`hierarchical stress majorization: ${what} is not supported yet`, "UNSUPPORTED_FEATURE");
43427
+ }
43428
+ function modelDistances(graph, n, model) {
43429
+ if (model === MODEL_SUBSET) unsupported2("the subset distance model");
43430
+ if (model === MODEL_CIRCUIT) unsupported2("the circuit distance model");
43431
+ return model === MODEL_MDS2 ? mdsModel(graph, n) : null;
43432
+ }
43433
+ function unconstrainedMajorization(graph, n, dCoords, nodes, o) {
43434
+ if (o.maxi < 0) return 0;
43435
+ const weighted = (graph[0]?.ewgts.length ?? 0) > 0;
43436
+ const Dij = modelDistances(graph, n, o.model) ?? (weighted ? computeWeightedApspPacked2(graph, n) : computeApspPacked2(graph, n));
43437
+ if ((o.opts & OPT_SMART_INIT) !== 0 && n > 1) unsupported2("the smart initial layout");
43438
+ return stressMajorizationKDMkernel(Dij, n, dCoords, nodes, {
43439
+ dim: o.dim,
43440
+ opts: o.opts,
43441
+ maxi: o.maxi,
43442
+ epsilon: o.epsilon
43443
+ });
43444
+ }
43445
+ function hasDirectionality(graph, n) {
43446
+ if (!graph[0]?.edists) return false;
43447
+ let directionalityExist = false;
43448
+ for (let i = 0; i < n; i++) {
43449
+ const edists = graph[i].edists;
43450
+ for (let j = 1; j < graph[i].nedges; j++) {
43451
+ directionalityExist ||= edists[j] !== 0;
43452
+ }
43453
+ }
43454
+ return directionalityExist;
43455
+ }
43456
+ function separateLevels(y, h, n, levelsGap) {
43457
+ const { ordering, levels, numLevels } = h;
43458
+ let displacement = 0;
43459
+ for (let i = 0; i < numLevels; i++) {
43460
+ const shortfall = levelsGap - (y[ordering[levels[i]]] + displacement - y[ordering[levels[i] - 1]]);
43461
+ displacement += 0 > shortfall ? 0 : shortfall;
43462
+ const stop = i < numLevels - 1 ? levels[i + 1] : n;
43463
+ for (let j = levels[i]; j < stop; j++) y[ordering[j]] += displacement;
43464
+ }
43465
+ }
43466
+ function smartInitLayers(graph, n, dCoords, nodes, o) {
43467
+ const { dim } = o;
43468
+ if (dim > 2) {
43469
+ const sub = { dim: dim - 1, opts: o.opts, model: o.model, maxi: SUBSPACE_ITERATIONS, epsilon: o.epsilon };
43470
+ if (unconstrainedMajorization(graph, n, dCoords.slice(1), nodes, sub) < 0) return -1;
43471
+ dCoords[dim - 1].set(dCoords[1].subarray(0, n));
43472
+ }
43473
+ const x = dCoords[0];
43474
+ const y = dCoords[1];
43475
+ if (computeYCoords(graph, n, y, n)) return -1;
43476
+ const h = computeHierarchy(graph, n, ABS_TOL, LEVELS_SEP_TOL, y);
43477
+ if (h === null) return -1;
43478
+ if (h.numLevels < MIN_LEVELS) {
43479
+ return unconstrainedMajorization(graph, n, dCoords, nodes, o);
43480
+ }
43481
+ if (o.levelsGap > 0) separateLevels(y, h, n, o.levelsGap);
43482
+ if (dim === 2 && imdsGivenDim(graph, n, y, x, o.epsilon)) return -1;
43483
+ return h;
43484
+ }
43485
+ function plainInitLayers(graph, n, dCoords, nodes, dim) {
43486
+ initLayout(n, dim, dCoords, nodes);
43487
+ const h = computeHierarchy(graph, n, ABS_TOL, LEVELS_SEP_TOL, null);
43488
+ return h === null ? -1 : h;
43489
+ }
43490
+ function distanceKD(coords, dim, i, j) {
43491
+ let sum = 0;
43492
+ for (let k = 0; k < dim; k++) {
43493
+ const d = coords[k][i] - coords[k][j];
43494
+ sum = fma2(d, d, sum);
43495
+ }
43496
+ return Math.sqrt(sum);
43497
+ }
43498
+ function scaleDownLayout(dCoords, n, dim) {
43499
+ let max = 1;
43500
+ for (let i = 0; i < dim; i++) {
43501
+ for (let j = 0; j < n; j++) {
43502
+ const a = Math.abs(dCoords[i][j]);
43503
+ if (a > max) max = a;
43504
+ }
43505
+ }
43506
+ for (let i = 0; i < dim; i++) {
43507
+ for (let j = 0; j < n; j++) dCoords[i][j] *= 10 / max;
43508
+ }
43509
+ }
43510
+ function scaleDistances(Dij, dCoords, n, dim) {
43511
+ const length = n + Math.trunc(n * (n - 1) / 2);
43512
+ const sum1 = Math.trunc(n * (n - 1) / 2);
43513
+ let sum2 = 0;
43514
+ for (let count = 0, i = 0; i < n - 1; i++) {
43515
+ count++;
43516
+ for (let j = i + 1; j < n; j++, count++) {
43517
+ sum2 += distanceKD(dCoords, dim, i, j) / Dij[count];
43518
+ }
43519
+ }
43520
+ const scaleRatio = fr6(sum2 / sum1);
43521
+ for (let i = 0; i < length; i++) Dij[i] = Dij[i] * scaleRatio;
43522
+ }
43523
+ function centerLayout(dCoords, n, dim) {
43524
+ for (let i = 0; i < dim; i++) orthog1(n, dCoords[i]);
43525
+ const y0 = dCoords[Y_AXIS][0];
43526
+ for (let i = 0; i < n; i++) dCoords[Y_AXIS][i] -= y0;
43527
+ }
43528
+ function negatedDegrees(lap2, n) {
43529
+ const degrees = new Float64Array(n);
43530
+ for (let i = 0, count = 0; i < n - 1; i++) {
43531
+ let degree = 0;
43532
+ count++;
43533
+ for (let j = 1; j < n - i; j++, count++) {
43534
+ const val2 = lap2[count];
43535
+ degree += val2;
43536
+ degrees[i + j] -= val2;
43537
+ }
43538
+ degrees[i] -= degree;
43539
+ }
43540
+ return degrees;
43541
+ }
43542
+ function buildLap22(lap2, n) {
43543
+ const lapLength = n + Math.trunc(n * (n - 1) / 2);
43544
+ squareVec(lapLength, lap2);
43545
+ invertVec(lapLength, lap2);
43546
+ const degrees = negatedDegrees(lap2, n);
43547
+ for (let step = n, count = 0, i = 0; i < n; i++, count += step, step--) {
43548
+ lap2[count] = degrees[i];
43549
+ }
43550
+ }
43551
+ function inverseDistances(st, i, len) {
43552
+ const { coords, tmpCoords, distAccumulator } = st;
43553
+ distAccumulator.fill(0, 0, st.n);
43554
+ for (let k = 0; k < st.dim; k++) {
43555
+ const ck = coords[k];
43556
+ for (let j = 0; j < len; j++) tmpCoords[j] = ck[i] - ck[i + 1 + j];
43557
+ for (let j = 0; j < len; j++) tmpCoords[j] = tmpCoords[j] * tmpCoords[j];
43558
+ for (let j = 0; j < len; j++) distAccumulator[j] = tmpCoords[j] + distAccumulator[j];
43559
+ }
43560
+ invertSqrtVec(len, distAccumulator);
43561
+ for (let j = 0; j < len; j++) {
43562
+ if (distAccumulator[j] >= FLT_MAX3 || distAccumulator[j] < 0) distAccumulator[j] = 0;
43563
+ }
43564
+ }
43565
+ function buildLap12(st) {
43566
+ const { n, lap1, lap2, degrees, distAccumulator } = st;
43567
+ degrees.fill(0);
43568
+ sqrtVecF(n + Math.trunc(n * (n - 1) / 2), lap2, lap1);
43569
+ let count = 0;
43570
+ for (let i = 0; i < n - 1; i++) {
43571
+ const len = n - i - 1;
43572
+ inverseDistances(st, i, len);
43573
+ count++;
43574
+ let degree = 0;
43575
+ for (let j = 0; j < len; j++, count++) {
43576
+ const val2 = fr6(lap1[count] * distAccumulator[j]);
43577
+ lap1[count] = val2;
43578
+ degree += val2;
43579
+ degrees[i + j + 1] -= val2;
43580
+ }
43581
+ degrees[i] -= degree;
43582
+ }
43583
+ for (let step = n, count2 = 0, i = 0; i < n; i++, count2 += step, step--) {
43584
+ lap1[count2] = degrees[i];
43585
+ }
43586
+ }
43587
+ function computeNewStress(st, constantTerm) {
43588
+ const { n, dim, lap1, lap2, coords, b, tmpCoords } = st;
43589
+ for (let k = 0; k < dim; k++) rightMultWithVectorFFFused(lap1, n, coords[k], b[k]);
43590
+ let newStress = 0;
43591
+ for (let k = 0; k < dim; k++) newStress += vectorsInnerProductF(n, coords[k], b[k]);
43592
+ newStress *= 2;
43593
+ newStress += constantTerm;
43594
+ for (let k = 0; k < dim; k++) {
43595
+ rightMultWithVectorFFFused(lap2, n, coords[k], tmpCoords);
43596
+ newStress -= vectorsInnerProductF(n, coords[k], tmpCoords);
43597
+ }
43598
+ return newStress;
43599
+ }
43600
+ function solveAxes(st, ctx) {
43601
+ for (let k = 0; k < st.dim; k++) {
43602
+ if (k === Y_AXIS) {
43603
+ constrainedMajorizationNewWithGaps(
43604
+ ctx.cMajEnv,
43605
+ st.b[k],
43606
+ st.coords,
43607
+ k,
43608
+ LOCAL_CONSTR_MAJOR_ITERATIONS,
43609
+ ctx.levelsGap
43610
+ );
43611
+ } else if (conjugateGradientMkernelFused(st.lap2, st.coords[k], st.b[k], st.n, { tol: TOLERANCE_CG, maxIterations: st.n })) {
43612
+ return true;
43613
+ }
43614
+ }
43615
+ return false;
43616
+ }
43617
+ function majorize(st, ctx, dCoords) {
43618
+ const constantTerm = Math.trunc(st.n * (st.n - 1) / 2);
43619
+ let oldStress = DBL_MAX;
43620
+ let iterations = 0;
43621
+ for (let converged = false; iterations < ctx.maxi && !converged; iterations++) {
43622
+ buildLap12(st);
43623
+ const newStress = computeNewStress(st, constantTerm);
43624
+ converged = Math.abs(newStress - oldStress) / Math.abs(oldStress + 1e-10) < ctx.epsilon;
43625
+ converged ||= iterations > 1 && newStress > oldStress;
43626
+ oldStress = newStress;
43627
+ if (solveAxes(st, ctx)) return -1;
43628
+ }
43629
+ for (let i = 0; i < st.dim; i++) {
43630
+ for (let j = 0; j < st.n; j++) dCoords[i][j] = st.coords[i][j];
43631
+ }
43632
+ return iterations;
43633
+ }
43634
+ function toFloatCoords(dCoords, n, dim) {
43635
+ const coords = [];
43636
+ for (let i = 0; i < dim; i++) coords.push(Float32Array.from(dCoords[i].subarray(0, n)));
43637
+ return coords;
43638
+ }
43639
+ function newLoopState(lap2, coords, n) {
43640
+ const dim = coords.length;
43641
+ return {
43642
+ n,
43643
+ dim,
43644
+ lap2,
43645
+ coords,
43646
+ lap1: new Float32Array(n + Math.trunc(n * (n - 1) / 2)),
43647
+ b: Array.from({ length: dim }, () => new Float32Array(n)),
43648
+ tmpCoords: new Float32Array(n),
43649
+ distAccumulator: new Float32Array(n),
43650
+ degrees: new Float64Array(n)
43651
+ };
43652
+ }
43653
+ function stressMajorizationWithHierarchy(graph, n, dCoords, nodes, o) {
43654
+ if (!hasDirectionality(graph, n)) return unconstrainedMajorization(graph, n, dCoords, nodes, o);
43655
+ const smartIni = (o.opts & OPT_SMART_INIT) !== 0;
43656
+ const layers = smartIni ? smartInitLayers(graph, n, dCoords, nodes, o) : plainInitLayers(graph, n, dCoords, nodes, o.dim);
43657
+ if (typeof layers === "number") return layers;
43658
+ if (n === 1) return 0;
43659
+ if (o.maxi === 0) return 0;
43660
+ const Dij = modelDistances(graph, n, o.model) ?? computeApspPacked2(graph, n);
43661
+ if (!smartIni) scaleDownLayout(dCoords, n, o.dim);
43662
+ if (o.levelsGap > 0) scaleDistances(Dij, dCoords, n, o.dim);
43663
+ centerLayout(dCoords, n, o.dim);
43664
+ const st = newLoopState(Dij, toFloatCoords(dCoords, n, o.dim), n);
43665
+ buildLap22(Dij, n);
43666
+ const cMajEnv = initConstrainedMajorization(Dij, n, layers.ordering, layers.levels, layers.numLevels);
43667
+ return majorize(st, { cMajEnv, levelsGap: o.levelsGap, maxi: o.maxi, epsilon: o.epsilon }, dCoords);
43668
+ }
43669
+
42027
43670
  // src/common/utils-inputscale.ts
42028
43671
  var POINTS_PER_INCH3 = 72;
42029
43672
  function getInputscale(g) {
@@ -42210,61 +43853,47 @@ function neatoMaxIter(maxiter, mode, n) {
42210
43853
  if (mode === MODE_MAJOR) return DFLT_ITERATIONS;
42211
43854
  return mode === MODE_SGD ? SGD_ITERATIONS : 100 * n;
42212
43855
  }
42213
- function runMajorization(g, mode, model) {
42214
- void model;
42215
- const nodeList = assignNodeIds2(g);
43856
+ var levelsGapOf = (g) => lateDouble(g.root.attrs.get("levelsgap"), 0, -Number.MAX_VALUE);
43857
+ function solveStress(c, vtx, dCoords, nodeList) {
43858
+ const { g, mode, model, haveLen, opts } = c;
42216
43859
  const n = nodeList.length;
42217
- const haveLen = graphHasLen(g);
42218
- const vtx = makeGraphDataC(g, nodeList, haveLen, mode === MODE_HIER || mode === MODE_IPSEP);
42219
- checkStart(g);
42220
43860
  const maxi = neatoMaxIter(g.attrs.get("maxiter"), mode, n);
42221
43861
  const epsilon = lateDouble(g.attrs.get("epsilon"), 1e-4, 0);
43862
+ if (mode === MODE_HIER) {
43863
+ return stressMajorizationWithHierarchy(vtx, n, dCoords, nodeList, {
43864
+ dim: DFLT_DIM,
43865
+ opts,
43866
+ model,
43867
+ maxi,
43868
+ epsilon,
43869
+ levelsGap: levelsGapOf(g)
43870
+ });
43871
+ }
42222
43872
  const weighted = haveLen && mode !== MODE_IPSEP;
42223
43873
  const Dij = weighted ? computeWeightedApspPacked2(vtx, n) : computeApspPacked2(vtx, n);
42224
- const dCoords = [new Float64Array(n), new Float64Array(n)];
42225
- stressMajorizationKDMkernel(Dij, n, dCoords, nodeList, {
43874
+ return stressMajorizationKDMkernel(Dij, n, dCoords, nodeList, {
42226
43875
  dim: DFLT_DIM,
42227
- opts: OPT_EXP_FLAG,
43876
+ opts,
42228
43877
  maxi,
42229
43878
  epsilon
42230
43879
  });
42231
- for (let i = 0; i < n; i++) {
42232
- nodeList[i].info.pos = [dCoords[0][i], dCoords[1][i]];
42233
- }
42234
43880
  }
42235
- function graphHasLen(g) {
42236
- for (const e of g.edges) {
42237
- if (e.attrs.has("len")) return true;
43881
+ function runMajorization(g, mode, model) {
43882
+ const nodeList = assignNodeIds2(g);
43883
+ const n = nodeList.length;
43884
+ const haveLen = graphHasLen(g);
43885
+ const init = checkStart(g, n, mode === MODE_HIER ? INIT_SELF : INIT_RANDOM);
43886
+ const opts = init === INIT_SELF ? OPT_EXP_FLAG | OPT_SMART_INIT : OPT_EXP_FLAG;
43887
+ const haveDir = mode === MODE_HIER || mode === MODE_IPSEP;
43888
+ const vtx = makeGraphDataC(g, nodeList, haveLen, haveDir, mode);
43889
+ const dCoords = [new Float64Array(n), new Float64Array(n)];
43890
+ if (solveStress({ g, mode, model, haveLen, opts }, vtx, dCoords, nodeList) < 0) {
43891
+ agerr("prev", "layout aborted");
43892
+ return;
42238
43893
  }
42239
- return false;
42240
- }
42241
- function makeGraphDataC(g, nodeList, haveLen, haveDir) {
42242
- const vtx = nodeList.map((_, i) => ({
42243
- nedges: 1,
42244
- edges: [i],
42245
- ewgts: haveLen || haveDir ? [0] : []
42246
- }));
42247
- for (const np of nodeList) {
42248
- const i = np.info.id;
42249
- const entry = vtx[i];
42250
- const seen2 = /* @__PURE__ */ new Map();
42251
- for (const ep of [...np.outEdges(g), ...np.inEdges(g)]) {
42252
- if (ep.head === ep.tail) continue;
42253
- const vp = ep.tail === np ? ep.head : ep.tail;
42254
- const vid = vp.info.id;
42255
- const dist4 = haveLen ? lateDouble(ep.attrs.get("len"), 1, 0) : 1;
42256
- const idx = seen2.get(vid);
42257
- if (idx !== void 0) {
42258
- if (haveLen) entry.ewgts[idx] = Math.max(entry.ewgts[idx], dist4);
42259
- continue;
42260
- }
42261
- seen2.set(vid, entry.nedges);
42262
- entry.edges.push(vid);
42263
- if (haveLen || haveDir) entry.ewgts.push(dist4);
42264
- entry.nedges++;
42265
- }
43894
+ for (let i = 0; i < n; i++) {
43895
+ nodeList[i].info.pos = [dCoords[0][i], dCoords[1][i]];
42266
43896
  }
42267
- return vtx;
42268
43897
  }
42269
43898
  function solveModel2(g, mode, model) {
42270
43899
  if (g.nodes.size < 2) return;
@@ -42456,6 +44085,25 @@ function esepFactor(g) {
42456
44085
  return { x: SEPFACT * DFLT_MARGIN, y: SEPFACT * DFLT_MARGIN, doAdd: true };
42457
44086
  }
42458
44087
 
44088
+ // src/common/libm-trig.ts
44089
+ var OCTAGON_TRIG = /* @__PURE__ */ new Map([
44090
+ [-0.39269908169872414, [0.9238795325112867, -0.3826834323650898]],
44091
+ [0.39269908169872414, [0.9238795325112867, 0.3826834323650898]],
44092
+ [1.1780972450961724, [0.38268343236508984, 0.9238795325112867]],
44093
+ [1.9634954084936207, [-0.3826834323650897, 0.9238795325112867]],
44094
+ [2.748893571891069, [-0.9238795325112867, 0.3826834323650899]],
44095
+ [3.5342917352885173, [-0.9238795325112868, -0.38268343236508967]],
44096
+ [4.319689898685965, [-0.38268343236509034, -0.9238795325112865]],
44097
+ [5.105088062083414, [0.38268343236509, -0.9238795325112866]],
44098
+ [5.890486225480862, [0.9238795325112865, -0.3826834323650904]]
44099
+ ]);
44100
+ function libmCos(x) {
44101
+ return OCTAGON_TRIG.get(x)?.[0] ?? Math.cos(x);
44102
+ }
44103
+ function libmSin(x) {
44104
+ return OCTAGON_TRIG.get(x)?.[1] ?? Math.sin(x);
44105
+ }
44106
+
42459
44107
  // src/layout/neato/delaunay.ts
42460
44108
  var ICCERRBOUND_A = (10 + 96 * 2 ** -53) * 2 ** -53;
42461
44109
  function ulpExp(v) {
@@ -42624,6 +44272,32 @@ function delaunayTri(xv, yv, n) {
42624
44272
  return edges;
42625
44273
  }
42626
44274
 
44275
+ // src/layout/neato/gts-triangle.ts
44276
+ var SQRT3 = 1.73205080757;
44277
+ function gtsTriangleEnclosing(px, py, n, scale) {
44278
+ let xmin = px[0];
44279
+ let xmax = px[0];
44280
+ let ymin = py[0];
44281
+ let ymax = py[0];
44282
+ for (let i = 1; i < n; i++) {
44283
+ if (px[i] > xmax) xmax = px[i];
44284
+ else if (px[i] < xmin) xmin = px[i];
44285
+ if (py[i] > ymax) ymax = py[i];
44286
+ else if (py[i] < ymin) ymin = py[i];
44287
+ }
44288
+ const xo = (xmax + xmin) / 2;
44289
+ const yo = (ymax + ymin) / 2;
44290
+ const dx = xmax - xo;
44291
+ const dy = ymax - yo;
44292
+ let r = scale * Math.sqrt(fma(dx, dx, dy * dy));
44293
+ if (r === 0) r = scale;
44294
+ return [
44295
+ [fma(r, SQRT3, xo), yo - r],
44296
+ [xo, fma(r, 2, yo)],
44297
+ [fma(-r, SQRT3, xo), yo - r]
44298
+ ];
44299
+ }
44300
+
42627
44301
  // src/layout/neato/cdt-surface.ts
42628
44302
  var pairKey = (u, v) => u < v ? u * 1048576 + v : v * 1048576 + u;
42629
44303
  var Cdt = class {
@@ -43134,27 +44808,15 @@ var Cdt = class {
43134
44808
  return { nfaces: kept.length, faces, neigh };
43135
44809
  }
43136
44810
  };
43137
- var SQRT3 = 1.7320508075688772;
43138
44811
  function mkSurface(x, y, n, segs, nsegs) {
43139
44812
  const px = x.slice(0, n);
43140
44813
  const py = y.slice(0, n);
43141
- let xmin = px[0];
43142
- let xmax = px[0];
43143
- let ymin = py[0];
43144
- let ymax = py[0];
43145
- for (let i = 1; i < n; i++) {
43146
- if (px[i] > xmax) xmax = px[i];
43147
- else if (px[i] < xmin) xmin = px[i];
43148
- if (py[i] > ymax) ymax = py[i];
43149
- else if (py[i] < ymin) ymin = py[i];
43150
- }
43151
- const xo = (xmax + xmin) / 2;
43152
- const yo = (ymax + ymin) / 2;
43153
- let r = 100 * Math.hypot(xmax - xo, ymax - yo);
43154
- if (r === 0) r = 100;
43155
44814
  const s0 = n;
43156
- px.push(xo + r * SQRT3, xo, xo - r * SQRT3);
43157
- py.push(yo - r, yo + 2 * r, yo - r);
44815
+ const enc = gtsTriangleEnclosing(px, py, n, 100);
44816
+ for (const [ex, ey] of enc) {
44817
+ px.push(ex);
44818
+ py.push(ey);
44819
+ }
43158
44820
  const cdt = new Cdt(px, py);
43159
44821
  const cons = [];
43160
44822
  for (let k = 0; k < nsegs; k++) {
@@ -43201,9 +44863,9 @@ function sharedEdge(faces, p3, q3) {
43201
44863
  return { i: p1, j: p2 };
43202
44864
  }
43203
44865
  function addTriEdge(g, t, h, seg2) {
43204
- const dist4 = Math.sqrt(dist2(g.nodes[t].ctr, g.nodes[h].ctr));
44866
+ const dist5 = Math.sqrt(dist2(g.nodes[t].ctr, g.nodes[h].ctr));
43205
44867
  const idx = g.edges.length;
43206
- g.edges.push({ t, h, seg: seg2, dist: dist4 });
44868
+ g.edges.push({ t, h, seg: seg2, dist: dist5 });
43207
44869
  g.nodes[t].edges.push(idx);
43208
44870
  g.nodes[h].edges.push(idx);
43209
44871
  }
@@ -44007,8 +45669,8 @@ function ellipseTangentSlope(a, b, p) {
44007
45669
  function circumscribedCorner(a, b, i, nsides) {
44008
45670
  const angle0 = 2 * Math.PI * (i - 0.5) / nsides;
44009
45671
  const angle1 = 2 * Math.PI * (i + 0.5) / nsides;
44010
- const p0 = { x: a * Math.cos(angle0), y: b * Math.sin(angle0) };
44011
- const p1 = { x: a * Math.cos(angle1), y: b * Math.sin(angle1) };
45672
+ const p0 = { x: a * libmCos(angle0), y: b * libmSin(angle0) };
45673
+ const p1 = { x: a * libmCos(angle1), y: b * libmSin(angle1) };
44012
45674
  const m0 = ellipseTangentSlope(a, b, p0);
44013
45675
  const m1 = ellipseTangentSlope(a, b, p1);
44014
45676
  const x = (fms(p1.x, m1, fma(m0, p0.x, -p0.y)) + p1.y) / (m0 - m1);
@@ -46344,52 +48006,14 @@ function armPow(x, y) {
46344
48006
  return expInline(ehi, elo, signBias);
46345
48007
  }
46346
48008
 
46347
- // src/common/crand.ts
46348
- var C_RAND_MAX = 2147483647;
46349
- var UNSEEDED_STATE2 = 1;
46350
- var state2 = UNSEEDED_STATE2;
46351
- registerRenderState(() => {
46352
- state2 = UNSEEDED_STATE2;
46353
- });
46354
- function csrand(seed) {
46355
- state2 = seed;
46356
- }
46357
- function crand() {
46358
- state2 = state2 * 16807 % 2147483647;
46359
- return state2;
46360
- }
46361
- function cdrand() {
46362
- return crand() / C_RAND_MAX;
46363
- }
46364
- function gvRandom(bound) {
46365
- const discardThreshold = C_RAND_MAX - 2147483648 % bound;
46366
- let r;
46367
- do {
46368
- r = crand();
46369
- } while (r > discardThreshold);
46370
- return r % bound;
46371
- }
46372
- function gvPermutation(bound) {
46373
- if (bound <= 0) return [];
46374
- const p = [];
46375
- for (let i = 0; i < bound; i++) p.push(i);
46376
- for (let i = bound - 1; i > 0; --i) {
46377
- const j = gvRandom(i + 1);
46378
- const t = p[i];
46379
- p[i] = p[j];
46380
- p[j] = t;
46381
- }
46382
- return p;
46383
- }
46384
-
46385
48009
  // src/layout/sfdp/quadtree.ts
46386
48010
  function pointDistance(p1, o1, p2, o2, dim) {
46387
- let dist4 = 0;
48011
+ let dist5 = 0;
46388
48012
  for (let i = 0; i < dim; i++) {
46389
48013
  const d = p1[o1 + i] - p2[o2 + i];
46390
- dist4 = fma(d, d, dist4);
48014
+ dist5 = fma(d, d, dist5);
46391
48015
  }
46392
- return Math.sqrt(dist4);
48016
+ return Math.sqrt(dist5);
46393
48017
  }
46394
48018
  function quadTreeNew(dim, center, width2, maxLevel) {
46395
48019
  return {
@@ -46524,8 +48148,8 @@ function getSupernodesInternal(qt, bh, pt, ptOff, nodeid, out) {
46524
48148
  l = l.next;
46525
48149
  }
46526
48150
  if (qt.qts !== null) {
46527
- const dist4 = pointDistance(qt.center, 0, pt, ptOff, dim);
46528
- if (qt.width < bh * dist4) {
48151
+ const dist5 = pointDistance(qt.center, 0, pt, ptOff, dim);
48152
+ if (qt.width < bh * dist5) {
46529
48153
  for (let i = 0; i < dim; i++) {
46530
48154
  out.center[dim * out.nsuper + i] = qt.average[i];
46531
48155
  }
@@ -46623,12 +48247,12 @@ function onedOptimizerTrain(opt, work) {
46623
48247
  else optHill(opt, i);
46624
48248
  }
46625
48249
  function distance(x, dim, i, j) {
46626
- let dist4 = 0;
48250
+ let dist5 = 0;
46627
48251
  for (let k = 0; k < dim; k++) {
46628
48252
  const d = x[i * dim + k] - x[j * dim + k];
46629
- dist4 = fma(d, d, dist4);
48253
+ dist5 = fma(d, d, dist5);
46630
48254
  }
46631
- return Math.sqrt(dist4);
48255
+ return Math.sqrt(dist5);
46632
48256
  }
46633
48257
  function distanceCropped(x, dim, i, j) {
46634
48258
  return Math.max(distance(x, dim, i, j), MINDIST);
@@ -46636,16 +48260,16 @@ function distanceCropped(x, dim, i, j) {
46636
48260
  function gatherLeaves(A3, p, checked, x, dim) {
46637
48261
  const { ia, ja } = A3;
46638
48262
  const leaves = [];
46639
- let dist4 = 0;
48263
+ let dist5 = 0;
46640
48264
  for (let j = ia[p]; j < ia[p + 1]; j++) {
46641
48265
  const c = ja[j];
46642
48266
  if (ia[c + 1] - ia[c] === 1) {
46643
48267
  checked[c] = true;
46644
- dist4 += distance(x, dim, p, c);
48268
+ dist5 += distance(x, dim, p, c);
46645
48269
  leaves.push(c);
46646
48270
  }
46647
48271
  }
46648
- return { leaves, avgDist: dist4 / leaves.length };
48272
+ return { leaves, avgDist: dist5 / leaves.length };
46649
48273
  }
46650
48274
  function beautifyLeaves(dim, A3, x) {
46651
48275
  const { ia, ja, m } = A3;
@@ -46668,7 +48292,7 @@ function beautifyLeaves(dim, A3, x) {
46668
48292
  }
46669
48293
  }
46670
48294
  function averageEdgeLength(A3, dim, coord) {
46671
- let dist4 = 0;
48295
+ let dist5 = 0;
46672
48296
  const { ia, ja } = A3;
46673
48297
  if (ia[A3.m] === 0) return 1;
46674
48298
  for (let i = 0; i < A3.m; i++) {
@@ -46678,10 +48302,10 @@ function averageEdgeLength(A3, dim, coord) {
46678
48302
  const dd = coord[dim * i + k] - coord[dim * ja[j]];
46679
48303
  d = fma(dd, dd, d);
46680
48304
  }
46681
- dist4 += Math.sqrt(d);
48305
+ dist5 += Math.sqrt(d);
46682
48306
  }
46683
48307
  }
46684
- return dist4 / ia[A3.m];
48308
+ return dist5 / ia[A3.m];
46685
48309
  }
46686
48310
  function updateStep(adaptiveCooling, step, fnorm, fnorm0) {
46687
48311
  if (!adaptiveCooling) return COOL * step;
@@ -46692,18 +48316,18 @@ function updateStep(adaptiveCooling, step, fnorm, fnorm0) {
46692
48316
  }
46693
48317
  return 0.99 * step / COOL;
46694
48318
  }
46695
- function repulsivePow(dist4, p) {
46696
- return armPow(dist4, 1 - p);
48319
+ function repulsivePow(dist5, p) {
48320
+ return armPow(dist5, 1 - p);
46697
48321
  }
46698
48322
  function attractiveForce(ctx, i) {
46699
48323
  const { A: A3, x, dim, fp, f } = ctx;
46700
48324
  const { ia, ja } = A3;
46701
48325
  for (let j = ia[i]; j < ia[i + 1]; j++) {
46702
48326
  if (ja[j] === i) continue;
46703
- const dist4 = distance(x, dim, i, ja[j]);
48327
+ const dist5 = distance(x, dim, i, ja[j]);
46704
48328
  for (let k = 0; k < dim; k++) {
46705
48329
  const t = fp.CRK * (x[i * dim + k] - x[ja[j] * dim + k]);
46706
- f[k] = fma(-t, dist4, f[k]);
48330
+ f[k] = fma(-t, dist5, f[k]);
46707
48331
  }
46708
48332
  }
46709
48333
  }
@@ -46711,9 +48335,9 @@ function repulsiveForceDirect(ctx, i) {
46711
48335
  const { x, dim, n, fp, f } = ctx;
46712
48336
  for (let j = 0; j < n; j++) {
46713
48337
  if (j === i) continue;
46714
- const dist4 = distanceCropped(x, dim, i, j);
48338
+ const dist5 = distanceCropped(x, dim, i, j);
46715
48339
  for (let k = 0; k < dim; k++) {
46716
- f[k] += fp.KP * (x[i * dim + k] - x[j * dim + k]) / repulsivePow(dist4, fp.p);
48340
+ f[k] += fp.KP * (x[i * dim + k] - x[j * dim + k]) / repulsivePow(dist5, fp.p);
46717
48341
  }
46718
48342
  }
46719
48343
  }
@@ -46723,9 +48347,9 @@ function repulsiveForceQT(ctx, qt, i, acc) {
46723
48347
  acc.countsAvg += counts;
46724
48348
  acc.nsuperAvg += nsuper;
46725
48349
  for (let j = 0; j < nsuper; j++) {
46726
- const dist4 = Math.max(distances[j], MINDIST);
48350
+ const dist5 = Math.max(distances[j], MINDIST);
46727
48351
  for (let k = 0; k < dim; k++) {
46728
- f[k] += supernodeWgts[j] * fp.KP * (x[i * dim + k] - center[j * dim + k]) / repulsivePow(dist4, fp.p);
48352
+ f[k] += supernodeWgts[j] * fp.KP * (x[i * dim + k] - center[j * dim + k]) / repulsivePow(dist5, fp.p);
46729
48353
  }
46730
48354
  }
46731
48355
  }
@@ -46981,7 +48605,7 @@ function diagPreconNew(A3) {
46981
48605
  }
46982
48606
  return diag;
46983
48607
  }
46984
- function conjugateGradient(A3, precon, n, x, rhs, tol, maxit) {
48608
+ function conjugateGradient2(A3, precon, n, x, rhs, tol, maxit) {
46985
48609
  let rho = 0;
46986
48610
  let rhoOld = 1;
46987
48611
  let iter = 0;
@@ -47022,7 +48646,7 @@ function smSolve(A3, dim, x0, rhs, tol, maxit) {
47022
48646
  x[i] = x0[i * dim + k];
47023
48647
  b[i] = rhs[i * dim + k];
47024
48648
  }
47025
- res += conjugateGradient(A3, precond, n, x, b, tol, maxit);
48649
+ res += conjugateGradient2(A3, precond, n, x, b, tol, maxit);
47026
48650
  for (let i = 0; i < n; i++) {
47027
48651
  rhs[i * dim + k] = x[i];
47028
48652
  }
@@ -47376,7 +49000,7 @@ function idealDistanceAvoidOverlap(dim, A3, x, width2, idealDistance) {
47376
49000
  for (let j = ia[i]; j < ia[i + 1]; j++) {
47377
49001
  const jj = ja[j];
47378
49002
  if (jj === i) continue;
47379
- const dist4 = distance(x, dim, i, jj);
49003
+ const dist5 = distance(x, dim, i, jj);
47380
49004
  const dx = Math.abs(x[i * dim] - x[jj * dim]);
47381
49005
  const dy = Math.abs(x[i * dim + 1] - x[jj * dim + 1]);
47382
49006
  const wx = width2[i * dim] + width2[jj * dim];
@@ -47399,9 +49023,9 @@ function idealDistanceAvoidOverlap(dim, A3, x, width2, idealDistance) {
47399
49023
  t = Math.min(expandmax, t);
47400
49024
  t = Math.max(expandmin, t);
47401
49025
  if (t > 1) {
47402
- idealDistance[j] = t * dist4;
49026
+ idealDistance[j] = t * dist5;
47403
49027
  } else {
47404
- idealDistance[j] = -t * dist4;
49028
+ idealDistance[j] = -t * dist5;
47405
49029
  }
47406
49030
  }
47407
49031
  }
@@ -47496,9 +49120,9 @@ function overlapSmootherNew(m, dim, x, width2, neighborhoodOnly, shrink) {
47496
49120
  w[j] = -1 / d[j] / d[j];
47497
49121
  d[j] = -d[j];
47498
49122
  }
47499
- const dist4 = d[j];
49123
+ const dist5 = d[j];
47500
49124
  diagW += w[j];
47501
- d[j] = w[j] * dist4;
49125
+ d[j] = w[j] * dist5;
47502
49126
  diagD += d[j];
47503
49127
  }
47504
49128
  w[jdiag] = -diagW;
@@ -47509,11 +49133,11 @@ function overlapSmootherNew(m, dim, x, width2, neighborhoodOnly, shrink) {
47509
49133
  function totalDistance(m, dim, x, y) {
47510
49134
  let total = 0;
47511
49135
  for (let i = 0; i < m; i++) {
47512
- let dist4 = 0;
49136
+ let dist5 = 0;
47513
49137
  for (let j = 0; j < dim; j++) {
47514
- dist4 += (y[i * dim + j] - x[i * dim + j]) * (y[i * dim + j] - x[i * dim + j]);
49138
+ dist5 += (y[i * dim + j] - x[i * dim + j]) * (y[i * dim + j] - x[i * dim + j]);
47515
49139
  }
47516
- total += Math.sqrt(dist4);
49140
+ total += Math.sqrt(dist5);
47517
49141
  }
47518
49142
  return total;
47519
49143
  }
@@ -47546,18 +49170,18 @@ function stressMajorizationSmooth(sm, dim, x, maxitSm) {
47546
49170
  idiag = j;
47547
49171
  continue;
47548
49172
  }
47549
- let dist4 = distance(x, dim, i, jd[j]);
49173
+ let dist5 = distance(x, dim, i, jd[j]);
47550
49174
  if (d[j] === 0) {
47551
49175
  dd[j] = 0;
47552
49176
  } else {
47553
- if (dist4 === 0) {
49177
+ if (dist5 === 0) {
47554
49178
  const dij = d[j] / Lw.a[j];
47555
49179
  for (let k = 0; k < dim; k++) {
47556
49180
  x[jd[j] * dim + k] += 1e-4 * (cdrand() + 1e-4) * dij;
47557
49181
  }
47558
- dist4 = distance(x, dim, i, jd[j]);
49182
+ dist5 = distance(x, dim, i, jd[j]);
47559
49183
  }
47560
- dd[j] = d[j] / dist4;
49184
+ dd[j] = d[j] / dist5;
47561
49185
  }
47562
49186
  diag += dd[j];
47563
49187
  }
@@ -47576,9 +49200,9 @@ function stressMajorizationSmooth(sm, dim, x, maxitSm) {
47576
49200
  return diff;
47577
49201
  }
47578
49202
  function scaleToEdgeLength(dim, A3, x, avgLabelSize) {
47579
- let dist4 = averageEdgeLength(A3, dim, x);
47580
- dist4 = avgLabelSize / Math.max(dist4, MACHINEACC);
47581
- for (let i = 0; i < dim * A3.m; i++) x[i] *= dist4;
49203
+ let dist5 = averageEdgeLength(A3, dim, x);
49204
+ dist5 = avgLabelSize / Math.max(dist5, MACHINEACC);
49205
+ for (let i = 0; i < dim * A3.m; i++) x[i] *= dist5;
47582
49206
  }
47583
49207
  function removeOverlapPrism(dim, A3, x, labelSizes, ntry, initialScaling, doShrinking) {
47584
49208
  if (!labelSizes) return;
@@ -47945,7 +49569,7 @@ function makeHasEdge(g) {
47945
49569
  }
47946
49570
  return (a, b) => pairs.get(a)?.has(b) === true || undirected && pairs.get(b)?.has(a) === true;
47947
49571
  }
47948
- function mkNConstraintG(g, list, intersect, dist4) {
49572
+ function mkNConstraintG(g, list, intersect, dist5) {
47949
49573
  const cg = newCg();
47950
49574
  const flat = flatten(list);
47951
49575
  let lastn;
@@ -47962,7 +49586,7 @@ function mkNConstraintG(g, list, intersect, dist4) {
47962
49586
  const nxp = flat[j];
47963
49587
  if (!intersect(p, nxp)) continue;
47964
49588
  const e = cgEdge(cg, cnodeOf(p), cnodeOf(nxp));
47965
- e.info.minlen = dist4(p.bb, nxp.bb);
49589
+ e.info.minlen = dist5(p.bb, nxp.bb);
47966
49590
  e.info.weight = hasEdge(p.np, nxp.np) ? 100 : 1;
47967
49591
  created.push(e);
47968
49592
  }
@@ -48009,12 +49633,12 @@ function buildVisibility(flat, intersect) {
48009
49633
  }
48010
49634
  return vg;
48011
49635
  }
48012
- function mapGraphs(vg, flat, cg, dist4) {
49636
+ function mapGraphs(vg, flat, cg, dist5) {
48013
49637
  for (let i = 0; i < flat.length; i++) {
48014
49638
  const tp = flat[i];
48015
49639
  for (const j of vg[i]) {
48016
49640
  const hp = flat[j];
48017
- const delta2 = dist4(tp.bb, hp.bb);
49641
+ const delta2 = dist5(tp.bb, hp.bb);
48018
49642
  const ce = cgEdge(cg, cnodeOf(tp), cnodeOf(hp));
48019
49643
  ce.info.weight = 1;
48020
49644
  if ((ce.info.minlen ?? 0) < delta2) {
@@ -48024,15 +49648,15 @@ function mapGraphs(vg, flat, cg, dist4) {
48024
49648
  }
48025
49649
  }
48026
49650
  }
48027
- function mkConstraintG(list, intersect, dist4) {
49651
+ function mkConstraintG(list, intersect, dist5) {
48028
49652
  const cg = newCg();
48029
49653
  const flat = flatten(list);
48030
49654
  buildChain(cg, flat);
48031
- mapGraphs(buildVisibility(flat, intersect), flat, cg, dist4);
49655
+ mapGraphs(buildVisibility(flat, intersect), flat, cg, dist5);
48032
49656
  return cg;
48033
49657
  }
48034
- function buildConstraintGraph(g, list, ifn, dist4, ortho) {
48035
- return ortho ? mkConstraintG(list, ifn, dist4) : mkNConstraintG(g, list, ifn, dist4);
49658
+ function buildConstraintGraph(g, list, ifn, dist5, ortho) {
49659
+ return ortho ? mkConstraintG(list, ifn, dist5) : mkNConstraintG(g, list, ifn, dist5);
48036
49660
  }
48037
49661
  function newItems() {
48038
49662
  return new DtBag((p) => p.val, cmpitem);
@@ -48173,7 +49797,7 @@ function inflatePts(verts, xmargin, ymargin) {
48173
49797
  v.y *= ymargin;
48174
49798
  }
48175
49799
  }
48176
- function isBox2(verts) {
49800
+ function isBox3(verts) {
48177
49801
  if (verts.length !== 4) return false;
48178
49802
  const [v0, v1, v2, v3] = verts;
48179
49803
  if (v0.y === v1.y) {
@@ -48233,7 +49857,7 @@ function clusterVerts(n, xmargin, ymargin) {
48233
49857
  function polyKind(n, poly, verts) {
48234
49858
  const name = shapeName(n);
48235
49859
  if (name === "box") return POLY_BOX;
48236
- if (name === "polygon" && isBox2(verts)) return POLY_BOX;
49860
+ if (name === "polygon" && isBox3(verts)) return POLY_BOX;
48237
49861
  if (poly.sides < 3 && poly.regular) return POLY_CIRCLE;
48238
49862
  return 0;
48239
49863
  }
@@ -48741,7 +50365,7 @@ function heapSiftUp(h, i) {
48741
50365
  i = parent2;
48742
50366
  }
48743
50367
  }
48744
- function heapSiftDown3(h, i) {
50368
+ function heapSiftDown2(h, i) {
48745
50369
  const n = h.length;
48746
50370
  for (; ; ) {
48747
50371
  let smallest = i;
@@ -48758,7 +50382,7 @@ function heapSiftDown3(h, i) {
48758
50382
  }
48759
50383
  function makeHeap(h) {
48760
50384
  for (let i = (h.length >> 1) - 1; i >= 0; i--) {
48761
- heapSiftDown3(h, i);
50385
+ heapSiftDown2(h, i);
48762
50386
  }
48763
50387
  }
48764
50388
  function heapFindMin(h) {
@@ -48767,7 +50391,7 @@ function heapFindMin(h) {
48767
50391
  function heapDeleteMin(h) {
48768
50392
  h[0] = h[h.length - 1];
48769
50393
  h.pop();
48770
- if (h.length > 0) heapSiftDown3(h, 0);
50394
+ if (h.length > 0) heapSiftDown2(h, 0);
48771
50395
  }
48772
50396
  function heapInsert(h, c) {
48773
50397
  h.push(c);
@@ -48851,27 +50475,27 @@ var Block = class _Block {
48851
50475
  * @see lib/vpsc/block.cpp: Block::merge(Block* b, Constraint* c)
48852
50476
  */
48853
50477
  mergeTwoArg(b, c) {
48854
- const dist4 = c.right.offset - c.left.offset - c.gap;
50478
+ const dist5 = c.right.offset - c.left.offset - c.gap;
48855
50479
  let l = c.left.block;
48856
50480
  let r = c.right.block;
48857
50481
  if (this.vars.length < b.vars.length) {
48858
- r.mergeInto(l, c, dist4);
50482
+ r.mergeInto(l, c, dist5);
48859
50483
  } else {
48860
- l.mergeInto(r, c, -dist4);
50484
+ l.mergeInto(r, c, -dist5);
48861
50485
  }
48862
50486
  }
48863
50487
  /**
48864
50488
  * Merge block b into this across constraint c by dist.
48865
50489
  * @see lib/vpsc/block.cpp: Block::merge(Block *b, Constraint *c, double dist)
48866
50490
  */
48867
- mergeInto(b, c, dist4) {
50491
+ mergeInto(b, c, dist5) {
48868
50492
  c.active = true;
48869
- this.wposn += b.wposn - dist4 * b.weight;
50493
+ this.wposn += b.wposn - dist5 * b.weight;
48870
50494
  this.weight += b.weight;
48871
50495
  this.posn = this.wposn / this.weight;
48872
50496
  for (const v of b.vars) {
48873
50497
  v.block = this;
48874
- v.offset += dist4;
50498
+ v.offset += dist5;
48875
50499
  this.vars.push(v);
48876
50500
  }
48877
50501
  b.deleted = true;
@@ -49160,13 +50784,13 @@ var Blocks = class {
49160
50784
  r.deleteMinInConstraint();
49161
50785
  let l = c.left.block;
49162
50786
  if (l.in.length === 0) l.setUpInConstraints();
49163
- let dist4 = c.right.offset - c.left.offset - c.gap;
50787
+ let dist5 = c.right.offset - c.left.offset - c.gap;
49164
50788
  if (r.vars.length < l.vars.length) {
49165
- dist4 = -dist4;
50789
+ dist5 = -dist5;
49166
50790
  [l, r] = [r, l];
49167
50791
  }
49168
50792
  this.timeCtr.value++;
49169
- r.mergeInto(l, c, dist4);
50793
+ r.mergeInto(l, c, dist5);
49170
50794
  r.mergeIn(l);
49171
50795
  r.timeStamp = this.timeCtr.value;
49172
50796
  this.removeBlock(l);
@@ -49184,12 +50808,12 @@ var Blocks = class {
49184
50808
  l.deleteMinOutConstraint();
49185
50809
  let r = c.right.block;
49186
50810
  r.setUpOutConstraints();
49187
- let dist4 = c.left.offset + c.gap - c.right.offset;
50811
+ let dist5 = c.left.offset + c.gap - c.right.offset;
49188
50812
  if (l.vars.length > r.vars.length) {
49189
- dist4 = -dist4;
50813
+ dist5 = -dist5;
49190
50814
  [l, r] = [r, l];
49191
50815
  }
49192
- l.mergeInto(r, c, dist4);
50816
+ l.mergeInto(r, c, dist5);
49193
50817
  l.mergeOut(r);
49194
50818
  this.removeBlock(r);
49195
50819
  c = l.findMinOutConstraint();
@@ -49705,7 +51329,7 @@ function warnUnrecognizedOverlap(flag) {
49705
51329
  const s = flag.toLowerCase();
49706
51330
  if (s.startsWith("prism") || NAMED_MODES.has(s)) return;
49707
51331
  if (mapBoolDflt(flag, false) === mapBoolDflt(flag, true)) return;
49708
- agerrLineOn("warn", `Unrecognized overlap value "${flag}" - using false`);
51332
+ agwarningf(`Unrecognized overlap value "${flag}" - using false`);
49709
51333
  }
49710
51334
  function getAdjustMode(flag) {
49711
51335
  warnUnrecognizedOverlap(flag);
@@ -49738,7 +51362,7 @@ function adjustLate(g, am) {
49738
51362
  case AM_VPSC:
49739
51363
  return vpscAdjust(g);
49740
51364
  default:
49741
- agerrLineOn("warn", `Unhandled adjust option ${am.print}`);
51365
+ agwarningf(`Unhandled adjust option ${am.print}`);
49742
51366
  return 0;
49743
51367
  }
49744
51368
  }
@@ -50712,20 +52336,20 @@ function coincidentDelta() {
50712
52336
  } while (xdelta === 0 && ydelta === 0);
50713
52337
  return { xdelta, ydelta };
50714
52338
  }
50715
- function doRep(p, q, xdelta, ydelta, dist4) {
52339
+ function doRep(p, q, xdelta, ydelta, dist5) {
50716
52340
  let force;
50717
- if (!(dist4 > 0)) {
52341
+ if (!(dist5 > 0)) {
50718
52342
  const d = coincidentDelta();
50719
52343
  xdelta = d.xdelta;
50720
52344
  ydelta = d.ydelta;
50721
- dist4 = libmHypot(xdelta, ydelta);
52345
+ dist5 = libmHypot(xdelta, ydelta);
50722
52346
  }
50723
- if (dist4 > fdpParms.Mlimit) {
52347
+ if (dist5 > fdpParms.Mlimit) {
50724
52348
  force = 0;
50725
52349
  } else if (parms.useNew) {
50726
- force = parms.K * parms.K / (dist4 * dist4 * dist4);
52350
+ force = parms.K * parms.K / (dist5 * dist5 * dist5);
50727
52351
  } else {
50728
- force = parms.K * parms.K / (dist4 * dist4);
52352
+ force = parms.K * parms.K / (dist5 * dist5);
50729
52353
  }
50730
52354
  if (isPort(p) && isPort(q)) force *= 10;
50731
52355
  const dq = disp(q);
@@ -50747,8 +52371,8 @@ function doNeighbor(grid2, i, j, nodes) {
50747
52371
  for (const q of cellp.nodes) {
50748
52372
  const xdelta = q.info.pos[0] - p.info.pos[0];
50749
52373
  const ydelta = q.info.pos[1] - p.info.pos[1];
50750
- const dist4 = libmHypot(xdelta, ydelta);
50751
- if (dist4 < parms.Cell) doRep(p, q, xdelta, ydelta, dist4);
52374
+ const dist5 = libmHypot(xdelta, ydelta);
52375
+ if (dist5 < parms.Cell) doRep(p, q, xdelta, ydelta, dist5);
50752
52376
  }
50753
52377
  }
50754
52378
  }
@@ -50780,12 +52404,12 @@ function applyAttr(p, q, e) {
50780
52404
  ydelta = d.ydelta;
50781
52405
  dist22 = fma(xdelta, xdelta, ydelta * ydelta);
50782
52406
  }
50783
- const dist4 = Math.sqrt(dist22);
52407
+ const dist5 = Math.sqrt(dist22);
50784
52408
  let force;
50785
52409
  if (parms.useNew) {
50786
- force = (e.info.factor ?? 1) * (dist4 - (e.info.dist ?? 1)) / dist4;
52410
+ force = (e.info.factor ?? 1) * (dist5 - (e.info.dist ?? 1)) / dist5;
50787
52411
  } else {
50788
- force = (e.info.factor ?? 1) * dist4 / (e.info.dist ?? 1);
52412
+ force = (e.info.factor ?? 1) * dist5 / (e.info.dist ?? 1);
50789
52413
  }
50790
52414
  const dq = disp(q);
50791
52415
  const dp = disp(p);
@@ -50960,16 +52584,16 @@ function cntOverlaps(g) {
50960
52584
  function applyRep2(p, q, rs) {
50961
52585
  let xdelta = q.info.pos[0] - p.info.pos[0];
50962
52586
  let ydelta = q.info.pos[1] - p.info.pos[1];
50963
- let dist4 = libmHypot(xdelta, ydelta);
50964
- if (!(dist4 > 0)) {
52587
+ let dist5 = libmHypot(xdelta, ydelta);
52588
+ if (!(dist5 > 0)) {
50965
52589
  const d = coincidentDelta();
50966
52590
  xdelta = d.xdelta;
50967
52591
  ydelta = d.ydelta;
50968
- dist4 = libmHypot(xdelta, ydelta);
52592
+ dist5 = libmHypot(xdelta, ydelta);
50969
52593
  }
50970
52594
  const ov = overlap4(p, q) ? 1 : 0;
50971
- let force = ov ? rs.ov / (dist4 * dist4) : rs.nonov / (dist4 * dist4);
50972
- if (dist4 > fdpParms.Mlimit) force = 0;
52595
+ let force = ov ? rs.ov / (dist5 * dist5) : rs.nonov / (dist5 * dist5);
52596
+ if (dist5 > fdpParms.Mlimit) force = 0;
50973
52597
  const dq = disp(q);
50974
52598
  const dp = disp(p);
50975
52599
  dq[0] = fma(xdelta, force, dq[0]);
@@ -50982,10 +52606,10 @@ function applyAttr2(p, q) {
50982
52606
  if (overlap4(p, q)) return;
50983
52607
  const xdelta = q.info.pos[0] - p.info.pos[0];
50984
52608
  const ydelta = q.info.pos[1] - p.info.pos[1];
50985
- const dist4 = libmHypot(xdelta, ydelta);
52609
+ const dist5 = libmHypot(xdelta, ydelta);
50986
52610
  const din = rad(p) + rad(q);
50987
- const dout = dist4 - din;
50988
- const force = dout * dout / ((xParams.K + din) * dist4);
52611
+ const dout = dist5 - din;
52612
+ const force = dout * dout / ((xParams.K + din) * dist5);
50989
52613
  const dq = disp(q);
50990
52614
  const dp = disp(p);
50991
52615
  dq[0] = fms(xdelta, force, dq[0]);
@@ -52140,9 +53764,9 @@ function pcpRotate(n, dim, x) {
52140
53764
  axis[0] = -(-y[0] + y[3] - Math.sqrt(radicand)) / (2 * y[1]);
52141
53765
  axis[1] = 1;
52142
53766
  }
52143
- const dist4 = Math.sqrt(fma(axis[0], axis[0], 1));
52144
- axis[0] = axis[0] / dist4;
52145
- axis[1] = axis[1] / dist4;
53767
+ const dist5 = Math.sqrt(fma(axis[0], axis[0], 1));
53768
+ axis[0] = axis[0] / dist5;
53769
+ axis[1] = axis[1] / dist5;
52146
53770
  for (let i = 0; i < n; i++) {
52147
53771
  const x0 = fma(x[dim * i], axis[0], x[dim * i + 1] * axis[1]);
52148
53772
  const x1 = fma(-x[dim * i], axis[1], x[dim * i + 1] * axis[0]);
@@ -52555,10 +54179,10 @@ function buildSpanTree(nodes, edges) {
52555
54179
  }
52556
54180
  return map;
52557
54181
  }
52558
- function measureDist(leaf, anc, dist4, change) {
54182
+ function measureDist(leaf, anc, dist5, change) {
52559
54183
  const p = anc.tparent;
52560
54184
  if (!p) return;
52561
- const d = dist4 + 1;
54185
+ const d = dist5 + 1;
52562
54186
  if (p.distone === 0) {
52563
54187
  p.leafone = leaf;
52564
54188
  p.distone = d;
@@ -54058,11 +55682,11 @@ var DEFAULT_COLOR5 = "black";
54058
55682
  var PENWIDTH_NORMAL4 = 1;
54059
55683
  var PENWIDTH_THRESHOLD4 = 5e-3;
54060
55684
  var EPS3 = 1e-5;
54061
- function dist3(a, b) {
55685
+ function dist4(a, b) {
54062
55686
  return Math.sqrt(dist2(a, b));
54063
55687
  }
54064
55688
  function approxLen(list, off) {
54065
- return dist3(list[off], list[off + 1]) + dist3(list[off + 1], list[off + 2]) + dist3(list[off + 2], list[off + 3]);
55689
+ return dist4(list[off], list[off + 1]) + dist4(list[off + 1], list[off + 2]) + dist4(list[off + 2], list[off + 3]);
54066
55690
  }
54067
55691
  function splitCubic(v, t) {
54068
55692
  const left2 = [];
@@ -54141,7 +55765,7 @@ function drawSplitSpline(list, segs, job) {
54141
55765
  return endColor;
54142
55766
  }
54143
55767
  function emitSplitEdgePaths(e, job, colorList) {
54144
- const segs = parseSegs(colorList).segs;
55768
+ const segs = parseSegs(colorList, edgeSegsContext(e)).segs;
54145
55769
  const firstColor2 = segs[0]?.color ?? DEFAULT_COLOR5;
54146
55770
  const spl = e.info.spl;
54147
55771
  let endColor = firstColor2;
@@ -54162,8 +55786,8 @@ var forfunc = (cur, total, init) => (1 - cur / total) * init / 2;
54162
55786
  var revfunc = (cur, total, init) => cur / total * init / 2;
54163
55787
  var nonefunc = (_cur, _total, init) => init / 2;
54164
55788
  var bothfunc = (cur, total, init) => {
54165
- const fr3 = cur / total;
54166
- return fr3 <= 0.5 ? fr3 * init : (1 - fr3) * init;
55789
+ const fr7 = cur / total;
55790
+ return fr7 <= 0.5 ? fr7 * init : (1 - fr7) * init;
54167
55791
  };
54168
55792
  function taperfun(dir, directed) {
54169
55793
  if (dir === "forward") return forfunc;
@@ -55597,7 +57221,7 @@ var DotWriterBase = class {
55597
57221
 
55598
57222
  // src/render/dot/edge-draw.ts
55599
57223
  var DEFAULT_COLOR6 = "black";
55600
- var DEFAULT_LINE_STYLE = ["solid", "setlinewidth(1)"];
57224
+ var DEFAULT_LINE_STYLE2 = ["solid", "setlinewidth(1)"];
55601
57225
  function emitArrowOp(buf, op, pen) {
55602
57226
  switch (op.kind) {
55603
57227
  case "polygon":
@@ -55632,8 +57256,9 @@ var EdgeDrawBase = class extends DotWriterBase {
55632
57256
  */
55633
57257
  attachmentPolyline(pts, pencolor, job) {
55634
57258
  const obj = job.obj;
57259
+ gvrenderSetStyle(DEFAULT_LINE_STYLE2);
55635
57260
  if (obj !== null) {
55636
- obj.rawStyle = [...DEFAULT_LINE_STYLE];
57261
+ obj.rawStyle = [...DEFAULT_LINE_STYLE2];
55637
57262
  obj.pen = 3 /* Solid */;
55638
57263
  obj.penWidth = 1;
55639
57264
  obj.penColor = resolveRenderColor(pencolor.split(":")[0]);
@@ -55687,8 +57312,8 @@ var EdgeDrawBase = class extends DotWriterBase {
55687
57312
  * under that segment's pen. Reuses the same split geometry
55688
57313
  * (splitSplineByColor) as the SVG path. @see lib/common/emit.c:1975 multicolor
55689
57314
  */
55690
- emitSplitSpline(bzList, colorAttr, edraw, job) {
55691
- const segs = parseSegs(colorAttr).segs;
57315
+ emitSplitSpline(bzList, e, colorAttr, edraw, job) {
57316
+ const segs = parseSegs(colorAttr, edgeSegsContext(e)).segs;
55692
57317
  const firstColor2 = segs[0]?.color ?? DEFAULT_COLOR6;
55693
57318
  let endColor = firstColor2;
55694
57319
  for (const bz of bzList) {
@@ -55711,7 +57336,7 @@ var EdgeDrawBase = class extends DotWriterBase {
55711
57336
  const segData = bzList.map(
55712
57337
  (bz) => bz !== void 0 && bz.size >= 4 ? buildOffsetLists(bz.list, (2 + numc) / 2) : { offlist: [], tmplist: [] }
55713
57338
  );
55714
- const colors = parseSegs(colorAttr).segs.map((s) => s.color ?? DEFAULT_COLOR6);
57339
+ const colors = parseSegsSilent(colorAttr).segs.map((s) => s.color ?? DEFAULT_COLOR6);
55715
57340
  for (const color of colors) {
55716
57341
  const pen = xdotPenColor(resolveRenderColor(color));
55717
57342
  for (const sd of segData) {
@@ -55867,7 +57492,7 @@ var XdotRenderer = class extends EdgeDrawBase {
55867
57492
  let tailArrowColor;
55868
57493
  let headArrowColor;
55869
57494
  if (numsemi > 0 && numc > 0) {
55870
- const c = this.emitSplitSpline(spl.list, colorAttr, edraw, job);
57495
+ const c = this.emitSplitSpline(spl.list, e, colorAttr, edraw, job);
55871
57496
  tailArrowColor = c.firstColor;
55872
57497
  headArrowColor = c.endColor;
55873
57498
  } else if (edgeIsTapered(e)) {
@@ -56103,72 +57728,6 @@ function svgTaperedEdge(e, job) {
56103
57728
  svgArrowPolygons(e, job);
56104
57729
  }
56105
57730
 
56106
- // src/gvc/image-resolver.ts
56107
- var activeResolver = null;
56108
- function setImageResolver(fn) {
56109
- if (fn !== null && typeof fn !== "function") {
56110
- throw invalidArgType("resolver", "function or null", fn);
56111
- }
56112
- activeResolver = fn;
56113
- }
56114
- var EXT_MIME = {
56115
- png: "image/png",
56116
- jpg: "image/jpeg",
56117
- jpeg: "image/jpeg",
56118
- gif: "image/gif",
56119
- svg: "image/svg+xml",
56120
- webp: "image/webp"
56121
- };
56122
- var FALLBACK_MIME = "application/octet-stream";
56123
- function inferMimeFromSrc(src) {
56124
- const dot = src.lastIndexOf(".");
56125
- if (dot < 0 || dot === src.length - 1) return FALLBACK_MIME;
56126
- const ext = src.slice(dot + 1).toLowerCase();
56127
- return EXT_MIME[ext] ?? FALLBACK_MIME;
56128
- }
56129
- function findImageBytes(src, resolver) {
56130
- const active = resolver ?? activeResolver;
56131
- if (active === null) return null;
56132
- const result = active(src);
56133
- if (result === null) return null;
56134
- if (result instanceof Uint8Array) {
56135
- return { bytes: result, mime: inferMimeFromSrc(src) };
56136
- }
56137
- return { bytes: result.bytes, mime: result.mime ?? inferMimeFromSrc(src) };
56138
- }
56139
- var B64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
56140
- function base64Encode(bytes) {
56141
- const len = bytes.length;
56142
- const out = [];
56143
- let i = 0;
56144
- for (; i + 2 < len; i += 3) {
56145
- const n = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2];
56146
- out.push(
56147
- B64_CHARS[n >> 18 & 63],
56148
- B64_CHARS[n >> 12 & 63],
56149
- B64_CHARS[n >> 6 & 63],
56150
- B64_CHARS[n & 63]
56151
- );
56152
- }
56153
- const remaining = len - i;
56154
- if (remaining === 1) {
56155
- const n = bytes[i] << 16;
56156
- out.push(B64_CHARS[n >> 18 & 63], B64_CHARS[n >> 12 & 63], "==");
56157
- } else if (remaining === 2) {
56158
- const n = bytes[i] << 16 | bytes[i + 1] << 8;
56159
- out.push(
56160
- B64_CHARS[n >> 18 & 63],
56161
- B64_CHARS[n >> 12 & 63],
56162
- B64_CHARS[n >> 6 & 63],
56163
- "="
56164
- );
56165
- }
56166
- return out.join("");
56167
- }
56168
- function toDataUri(bytes, mime) {
56169
- return "data:" + mime + ";base64," + base64Encode(bytes);
56170
- }
56171
-
56172
57731
  // src/render/svg.ts
56173
57732
  function emitMulticolorArrows(e, job, headColor, tailColor) {
56174
57733
  const obj = job.obj;