@knowvah/dot-engine 1.8.0 → 1.9.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.
package/dist/render.js CHANGED
@@ -4933,6 +4933,177 @@ function getFamilyMetrics(fontName) {
4933
4933
  return TIMES_FALLBACK;
4934
4934
  }
4935
4935
 
4936
+ // src/model/layoutParams.ts
4937
+ var FontnameKind = {
4938
+ NativeFonts: 0,
4939
+ PsFonts: 1,
4940
+ SvgFonts: 2
4941
+ };
4942
+ function makeDrawing(overrides) {
4943
+ const zero = { x: 0, y: 0 };
4944
+ return {
4945
+ quantum: 0,
4946
+ scale: 0,
4947
+ ratio: 0,
4948
+ dpi: 0,
4949
+ margin: { ...zero },
4950
+ page: { ...zero },
4951
+ size: { ...zero },
4952
+ filled: false,
4953
+ landscape: false,
4954
+ centered: false,
4955
+ ratioKind: "none",
4956
+ xdots: null,
4957
+ id: null,
4958
+ ...overrides
4959
+ };
4960
+ }
4961
+
4962
+ // src/common/ps-fontalias.ts
4963
+ var ALIAS_ROWS = [
4964
+ ["AvantGarde-Book", "URW Gothic L", "book", null, null, "sans-Serif", null, null],
4965
+ ["AvantGarde-BookOblique", "URW Gothic L", "book", null, "oblique", "sans-Serif", null, "italic"],
4966
+ ["AvantGarde-Demi", "URW Gothic L", "demi", null, null, "sans-Serif", "bold", null],
4967
+ ["AvantGarde-DemiOblique", "URW Gothic L", "demi", null, "oblique", "sans-Serif", "bold", "italic"],
4968
+ ["Bookman-Demi", "URW Bookman L", "demi", null, null, "serif", "bold", null],
4969
+ ["Bookman-DemiItalic", "URW Bookman L", "demi", null, "italic", "serif", "bold", "italic"],
4970
+ ["Bookman-Light", "URW Bookman L", "light", null, null, "serif", null, null],
4971
+ ["Bookman-LightItalic", "URW Bookman L", "light", null, "italic", "serif", null, "italic"],
4972
+ ["Courier", "Courier", null, null, null, "monospace", null, null],
4973
+ ["Courier-Bold", "Courier", "bold", null, null, "monospace", "bold", null],
4974
+ ["Courier-BoldOblique", "Courier", "bold", null, "oblique", "monospace", "bold", "italic"],
4975
+ ["Courier-Oblique", "Courier", null, null, "oblique", "monospace", null, "italic"],
4976
+ ["Helvetica", "Helvetica", null, null, null, "sans-Serif", null, null],
4977
+ ["Helvetica-Bold", "Helvetica", "bold", null, null, "sans-Serif", "bold", null],
4978
+ ["Helvetica-BoldOblique", "Helvetica", "bold", null, "oblique", "sans-Serif", "bold", "italic"],
4979
+ ["Helvetica-Narrow", "Helvetica", null, "condensed", null, "sans-Serif", null, null],
4980
+ ["Helvetica-Narrow-Bold", "Helvetica", "bold", "condensed", null, "sans-Serif", "bold", null],
4981
+ ["Helvetica-Narrow-BoldOblique", "Helvetica", "bold", "condensed", "oblique", "sans-Serif", "bold", "italic"],
4982
+ ["Helvetica-Narrow-Oblique", "Helvetica", null, "condensed", "oblique", "sans-Serif", null, "italic"],
4983
+ ["Helvetica-Oblique", "Helvetica", null, null, "oblique", "sans-Serif", null, "italic"],
4984
+ ["NewCenturySchlbk-Bold", "Century Schoolbook L", "bold", null, null, "serif", "bold", null],
4985
+ ["NewCenturySchlbk-BoldItalic", "Century Schoolbook L", "bold", null, "italic", "serif", "bold", "italic"],
4986
+ ["NewCenturySchlbk-Italic", "Century Schoolbook L", null, null, "italic", "serif", null, "italic"],
4987
+ ["NewCenturySchlbk-Roman", "Century Schoolbook L", "roman", null, null, "serif", null, null],
4988
+ ["Palatino-Bold", "Palatino Linotype", "bold", null, null, "serif", "bold", null],
4989
+ ["Palatino-BoldItalic", "Palatino Linotype", "bold", null, "italic", "serif", "bold", "italic"],
4990
+ ["Palatino-Italic", "Palatino Linotype", null, null, "italic", "serif", null, "italic"],
4991
+ ["Palatino-Roman", "Palatino Linotype", "roman", null, null, "serif", null, null],
4992
+ ["Symbol", "Symbol", null, null, null, "fantasy", null, null],
4993
+ ["Times-Bold", "Times", "bold", null, null, "serif", "bold", null],
4994
+ ["Times-BoldItalic", "Times", "bold", null, "italic", "serif", "bold", "italic"],
4995
+ ["Times-Italic", "Times", null, null, "italic", "serif", null, "italic"],
4996
+ ["Times-Roman", "Times", null, null, null, "serif", null, null],
4997
+ ["ZapfChancery-MediumItalic", "URW Chancery L", "medium", null, "italic", "serif", null, "italic"],
4998
+ ["ZapfDingbats", "Dingbats", null, null, null, "fantasy", null, null]
4999
+ ];
5000
+ var ALIAS_BY_NAME = new Map(
5001
+ ALIAS_ROWS.map((r) => [
5002
+ r[0].toLowerCase(),
5003
+ {
5004
+ name: r[0],
5005
+ family: r[1],
5006
+ weight: r[2],
5007
+ stretch: r[3],
5008
+ style: r[4],
5009
+ svgFontFamily: r[5],
5010
+ svgFontWeight: r[6],
5011
+ svgFontStyle: r[7]
5012
+ }
5013
+ ])
5014
+ );
5015
+ function translatePostscriptFontname(name) {
5016
+ return ALIAS_BY_NAME.get(name.toLowerCase()) ?? null;
5017
+ }
5018
+ function fontFamilyAttrs(fontName, mode = FontnameKind.NativeFonts) {
5019
+ const a = fontName !== null ? translatePostscriptFontname(fontName) : null;
5020
+ if (a === null) return null;
5021
+ let family;
5022
+ let weight;
5023
+ let style;
5024
+ switch (mode) {
5025
+ case FontnameKind.PsFonts:
5026
+ family = a.name;
5027
+ weight = a.weight;
5028
+ style = a.style;
5029
+ break;
5030
+ case FontnameKind.SvgFonts:
5031
+ family = a.svgFontFamily;
5032
+ weight = a.svgFontWeight;
5033
+ style = a.svgFontStyle;
5034
+ break;
5035
+ default:
5036
+ family = a.family;
5037
+ weight = a.weight;
5038
+ style = a.style;
5039
+ break;
5040
+ }
5041
+ const fam = a.svgFontFamily !== family ? family + "," + a.svgFontFamily : family;
5042
+ let attrs = ' font-family="' + fam + '"';
5043
+ if (weight !== null) attrs += ' font-weight="' + weight + '"';
5044
+ if (a.stretch !== null) attrs += ' font-stretch="' + a.stretch + '"';
5045
+ if (style !== null) attrs += ' font-style="' + style + '"';
5046
+ return { attrs, weight: weight !== null, style: style !== null };
5047
+ }
5048
+
5049
+ // src/common/css-font.ts
5050
+ var DEFAULT_FAMILIES = ["Times", "serif"];
5051
+ var CSS_GENERIC_FAMILIES = /* @__PURE__ */ new Set([
5052
+ "serif",
5053
+ "sans-serif",
5054
+ "monospace",
5055
+ "cursive",
5056
+ "fantasy",
5057
+ "system-ui"
5058
+ ]);
5059
+ var CSS_WEIGHT_KEYWORDS = /* @__PURE__ */ new Set([
5060
+ "normal",
5061
+ "bold",
5062
+ "bolder",
5063
+ "lighter"
5064
+ ]);
5065
+ var DQ = '"';
5066
+ var SQ = "'";
5067
+ var BACKSLASH = "\\";
5068
+ function isCssWeight(w) {
5069
+ return CSS_WEIGHT_KEYWORDS.has(w.toLowerCase());
5070
+ }
5071
+ function stripQuotes(f) {
5072
+ const q = f.charAt(0);
5073
+ if (f.length >= 2 && (q === DQ || q === SQ) && f.endsWith(q)) return f.slice(1, -1);
5074
+ return f;
5075
+ }
5076
+ function quoteFamily(f) {
5077
+ if (CSS_GENERIC_FAMILIES.has(f.toLowerCase())) return f;
5078
+ const escaped = f.split(BACKSLASH).join(BACKSLASH + BACKSLASH).split(DQ).join(BACKSLASH + DQ);
5079
+ return DQ + escaped + DQ;
5080
+ }
5081
+ function splitFamilies(fontname) {
5082
+ const entries = (fontname ?? "").split(",").map((f) => stripQuotes(f.trim()).trim()).filter((f) => f !== "");
5083
+ return entries.length > 0 ? entries : DEFAULT_FAMILIES;
5084
+ }
5085
+ function aliasFamilies(a) {
5086
+ return a.svgFontFamily !== a.family ? [a.family, a.svgFontFamily] : [a.family];
5087
+ }
5088
+ function styleToken(a, flags) {
5089
+ if (a?.style != null) return a.style;
5090
+ return flags?.italic === true ? "italic" : null;
5091
+ }
5092
+ function weightToken(a, flags) {
5093
+ if (a?.weight != null) return isCssWeight(a.weight) ? a.weight : null;
5094
+ return flags?.bold === true ? "bold" : null;
5095
+ }
5096
+ function variantTokens(a, flags) {
5097
+ const tokens = [styleToken(a, flags), weightToken(a, flags), a?.stretch ?? null];
5098
+ return tokens.filter((t) => t !== null);
5099
+ }
5100
+ function canvasFont(fontname, fontsize, flags) {
5101
+ const a = fontname !== null ? translatePostscriptFontname(fontname) : null;
5102
+ const families = a !== null ? aliasFamilies(a) : splitFamilies(fontname);
5103
+ const tokens = [...variantTokens(a, flags), `${fontsize}px`];
5104
+ return `${tokens.join(" ")} ${families.map(quoteFamily).join(", ")}`;
5105
+ }
5106
+
4936
5107
  // src/common/textmeasure.ts
4937
5108
  function getVariantWidths(family, bold, italic) {
4938
5109
  if (bold && italic) return family.boldItalic;
@@ -5013,19 +5184,42 @@ var LutTextMeasurer = class {
5013
5184
  return { w, h: freetypeLineHeight(fontsize, fontname) };
5014
5185
  }
5015
5186
  };
5187
+ var FONT_PROBES = ["1px serif", "2px monospace"];
5016
5188
  var CanvasTextMeasurer = class {
5017
5189
  constructor(ctx) {
5018
5190
  this.ctx = ctx;
5019
5191
  }
5020
5192
  ctx;
5193
+ /**
5194
+ * fontname|fontsize|bold|italic → accepted font string. Mirrors pango's
5195
+ * font reuse (plugin/pango/gvtextlayout_pango.c:99-100).
5196
+ */
5197
+ fonts = /* @__PURE__ */ new Map();
5021
5198
  measure(text, fontname, fontsize, flags) {
5022
- const bold = flags?.bold === true;
5023
- const italic = flags?.italic === true;
5024
- const style = bold && italic ? "bold italic" : bold ? "bold" : italic ? "italic" : "";
5025
- this.ctx.font = style ? `${style} ${fontsize}px ${fontname}` : `${fontsize}px ${fontname}`;
5199
+ this.ctx.font = this.fontFor(fontname, fontsize, flags);
5026
5200
  const m = this.ctx.measureText(text);
5027
5201
  return { w: m.width, h: fontsize };
5028
5202
  }
5203
+ /** Cached font string; built and validated once per distinct font. */
5204
+ fontFor(fontname, fontsize, flags) {
5205
+ const key = `${fontname}|${fontsize}|${flags?.bold === true}|${flags?.italic === true}`;
5206
+ let font = this.fonts.get(key);
5207
+ if (font === void 0) {
5208
+ font = canvasFont(fontname, fontsize, flags);
5209
+ if (!this.accepts(font)) font = canvasFont(null, fontsize, flags);
5210
+ this.fonts.set(key, font);
5211
+ }
5212
+ return font;
5213
+ }
5214
+ /** True when the context accepts `font` as a `ctx.font` value. */
5215
+ accepts(font) {
5216
+ return FONT_PROBES.some((probe) => {
5217
+ this.ctx.font = probe;
5218
+ const before = this.ctx.font;
5219
+ this.ctx.font = font;
5220
+ return this.ctx.font !== before;
5221
+ });
5222
+ }
5029
5223
  };
5030
5224
  var LINESPACING = 1.2;
5031
5225
  var EstimateTextMeasurer = class {
@@ -8199,32 +8393,6 @@ function arrowDrawOpsForEnd(e, end, tip2, dir, penwidth) {
8199
8393
  return arrowDrawOps(comps, tip2, dir, edgeArrowsize(e), penwidth, rankdir);
8200
8394
  }
8201
8395
 
8202
- // src/model/layoutParams.ts
8203
- var FontnameKind = {
8204
- NativeFonts: 0,
8205
- PsFonts: 1,
8206
- SvgFonts: 2
8207
- };
8208
- function makeDrawing(overrides) {
8209
- const zero = { x: 0, y: 0 };
8210
- return {
8211
- quantum: 0,
8212
- scale: 0,
8213
- ratio: 0,
8214
- dpi: 0,
8215
- margin: { ...zero },
8216
- page: { ...zero },
8217
- size: { ...zero },
8218
- filled: false,
8219
- landscape: false,
8220
- centered: false,
8221
- ratioKind: "none",
8222
- xdots: null,
8223
- id: null,
8224
- ...overrides
8225
- };
8226
- }
8227
-
8228
8396
  // src/util/printf-round.ts
8229
8397
  function decomposeFloat64(v) {
8230
8398
  const buf = new DataView(new ArrayBuffer(8));
@@ -17315,93 +17483,6 @@ function commonInitNodeEdge(g) {
17315
17483
  for (const n of g.nodes.values()) commonInitNode(n, g);
17316
17484
  }
17317
17485
 
17318
- // src/common/ps-fontalias.ts
17319
- var ALIAS_ROWS = [
17320
- ["AvantGarde-Book", "URW Gothic L", "book", null, null, "sans-Serif", null, null],
17321
- ["AvantGarde-BookOblique", "URW Gothic L", "book", null, "oblique", "sans-Serif", null, "italic"],
17322
- ["AvantGarde-Demi", "URW Gothic L", "demi", null, null, "sans-Serif", "bold", null],
17323
- ["AvantGarde-DemiOblique", "URW Gothic L", "demi", null, "oblique", "sans-Serif", "bold", "italic"],
17324
- ["Bookman-Demi", "URW Bookman L", "demi", null, null, "serif", "bold", null],
17325
- ["Bookman-DemiItalic", "URW Bookman L", "demi", null, "italic", "serif", "bold", "italic"],
17326
- ["Bookman-Light", "URW Bookman L", "light", null, null, "serif", null, null],
17327
- ["Bookman-LightItalic", "URW Bookman L", "light", null, "italic", "serif", null, "italic"],
17328
- ["Courier", "Courier", null, null, null, "monospace", null, null],
17329
- ["Courier-Bold", "Courier", "bold", null, null, "monospace", "bold", null],
17330
- ["Courier-BoldOblique", "Courier", "bold", null, "oblique", "monospace", "bold", "italic"],
17331
- ["Courier-Oblique", "Courier", null, null, "oblique", "monospace", null, "italic"],
17332
- ["Helvetica", "Helvetica", null, null, null, "sans-Serif", null, null],
17333
- ["Helvetica-Bold", "Helvetica", "bold", null, null, "sans-Serif", "bold", null],
17334
- ["Helvetica-BoldOblique", "Helvetica", "bold", null, "oblique", "sans-Serif", "bold", "italic"],
17335
- ["Helvetica-Narrow", "Helvetica", null, "condensed", null, "sans-Serif", null, null],
17336
- ["Helvetica-Narrow-Bold", "Helvetica", "bold", "condensed", null, "sans-Serif", "bold", null],
17337
- ["Helvetica-Narrow-BoldOblique", "Helvetica", "bold", "condensed", "oblique", "sans-Serif", "bold", "italic"],
17338
- ["Helvetica-Narrow-Oblique", "Helvetica", null, "condensed", "oblique", "sans-Serif", null, "italic"],
17339
- ["Helvetica-Oblique", "Helvetica", null, null, "oblique", "sans-Serif", null, "italic"],
17340
- ["NewCenturySchlbk-Bold", "Century Schoolbook L", "bold", null, null, "serif", "bold", null],
17341
- ["NewCenturySchlbk-BoldItalic", "Century Schoolbook L", "bold", null, "italic", "serif", "bold", "italic"],
17342
- ["NewCenturySchlbk-Italic", "Century Schoolbook L", null, null, "italic", "serif", null, "italic"],
17343
- ["NewCenturySchlbk-Roman", "Century Schoolbook L", "roman", null, null, "serif", null, null],
17344
- ["Palatino-Bold", "Palatino Linotype", "bold", null, null, "serif", "bold", null],
17345
- ["Palatino-BoldItalic", "Palatino Linotype", "bold", null, "italic", "serif", "bold", "italic"],
17346
- ["Palatino-Italic", "Palatino Linotype", null, null, "italic", "serif", null, "italic"],
17347
- ["Palatino-Roman", "Palatino Linotype", "roman", null, null, "serif", null, null],
17348
- ["Symbol", "Symbol", null, null, null, "fantasy", null, null],
17349
- ["Times-Bold", "Times", "bold", null, null, "serif", "bold", null],
17350
- ["Times-BoldItalic", "Times", "bold", null, "italic", "serif", "bold", "italic"],
17351
- ["Times-Italic", "Times", null, null, "italic", "serif", null, "italic"],
17352
- ["Times-Roman", "Times", null, null, null, "serif", null, null],
17353
- ["ZapfChancery-MediumItalic", "URW Chancery L", "medium", null, "italic", "serif", null, "italic"],
17354
- ["ZapfDingbats", "Dingbats", null, null, null, "fantasy", null, null]
17355
- ];
17356
- var ALIAS_BY_NAME = new Map(
17357
- ALIAS_ROWS.map((r) => [
17358
- r[0].toLowerCase(),
17359
- {
17360
- name: r[0],
17361
- family: r[1],
17362
- weight: r[2],
17363
- stretch: r[3],
17364
- style: r[4],
17365
- svgFontFamily: r[5],
17366
- svgFontWeight: r[6],
17367
- svgFontStyle: r[7]
17368
- }
17369
- ])
17370
- );
17371
- function translatePostscriptFontname(name) {
17372
- return ALIAS_BY_NAME.get(name.toLowerCase()) ?? null;
17373
- }
17374
- function fontFamilyAttrs(fontName, mode = FontnameKind.NativeFonts) {
17375
- const a = fontName !== null ? translatePostscriptFontname(fontName) : null;
17376
- if (a === null) return null;
17377
- let family;
17378
- let weight;
17379
- let style;
17380
- switch (mode) {
17381
- case FontnameKind.PsFonts:
17382
- family = a.name;
17383
- weight = a.weight;
17384
- style = a.style;
17385
- break;
17386
- case FontnameKind.SvgFonts:
17387
- family = a.svgFontFamily;
17388
- weight = a.svgFontWeight;
17389
- style = a.svgFontStyle;
17390
- break;
17391
- default:
17392
- family = a.family;
17393
- weight = a.weight;
17394
- style = a.style;
17395
- break;
17396
- }
17397
- const fam = a.svgFontFamily !== family ? family + "," + a.svgFontFamily : family;
17398
- let attrs = ' font-family="' + fam + '"';
17399
- if (weight !== null) attrs += ' font-weight="' + weight + '"';
17400
- if (a.stretch !== null) attrs += ' font-stretch="' + a.stretch + '"';
17401
- if (style !== null) attrs += ' font-style="' + style + '"';
17402
- return { attrs, weight: weight !== null, style: style !== null };
17403
- }
17404
-
17405
17486
  // src/render/svg-gradient.ts
17406
17487
  function bboxFrom2(A3) {
17407
17488
  const rx = A3[1].x - A3[0].x;
@@ -46438,7 +46519,7 @@ function taper(bez, radfunc, initwid) {
46438
46519
  }
46439
46520
 
46440
46521
  // src/render/map.ts
46441
- var DQ = '"';
46522
+ var DQ2 = '"';
46442
46523
  function exactDecimalDigits2(v) {
46443
46524
  const dv = new DataView(new ArrayBuffer(8));
46444
46525
  dv.setFloat64(0, Math.abs(v));
@@ -46734,16 +46815,16 @@ function cmapxCoords(shape, pts) {
46734
46815
  return cmapxCoordsPoly(pts);
46735
46816
  }
46736
46817
  function mapCmapxAttrs(a, out) {
46737
- if (a.id) out.push(" id=" + DQ + escapeXml(a.id) + DQ);
46738
- if (a.url) out.push(" href=" + DQ + escapeXml(a.url) + DQ);
46739
- if (a.target) out.push(" target=" + DQ + escapeXmlTitle(a.target) + DQ);
46740
- if (a.tooltip) out.push(" title=" + DQ + escapeXmlTitle(a.tooltip) + DQ);
46818
+ if (a.id) out.push(" id=" + DQ2 + escapeXml(a.id) + DQ2);
46819
+ if (a.url) out.push(" href=" + DQ2 + escapeXml(a.url) + DQ2);
46820
+ if (a.target) out.push(" target=" + DQ2 + escapeXmlTitle(a.target) + DQ2);
46821
+ if (a.tooltip) out.push(" title=" + DQ2 + escapeXmlTitle(a.tooltip) + DQ2);
46741
46822
  }
46742
46823
  function mapOutputCmapx(shape, pts, a, isXml, out) {
46743
- out.push("<area shape=" + DQ + cmapxShape(shape) + DQ);
46824
+ out.push("<area shape=" + DQ2 + cmapxShape(shape) + DQ2);
46744
46825
  mapCmapxAttrs(a, out);
46745
- out.push(" alt=" + DQ + DQ);
46746
- out.push(" coords=" + DQ + cmapxCoords(shape, pts) + DQ);
46826
+ out.push(" alt=" + DQ2 + DQ2);
46827
+ out.push(" coords=" + DQ2 + cmapxCoords(shape, pts) + DQ2);
46747
46828
  out.push(isXml ? "/>\n" : ">\n");
46748
46829
  }
46749
46830
  function mapOutputImap(shape, pts, url, out) {
@@ -46845,7 +46926,7 @@ var MapRendererBase = class {
46845
46926
  this.mapCtx = buildMapCtx(g, job, this.mapPolygon);
46846
46927
  if (this.isCmapx) {
46847
46928
  const name = escapeXml(mapGraphName(g));
46848
- job.write("<map id=" + DQ + name + DQ + " name=" + DQ + name + DQ + ">\n");
46929
+ job.write("<map id=" + DQ2 + name + DQ2 + " name=" + DQ2 + name + DQ2 + ">\n");
46849
46930
  return;
46850
46931
  }
46851
46932
  job.write("base referer\n");