@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/README.md CHANGED
@@ -290,12 +290,14 @@ from the canonical C Graphviz. New behavior is pinned to the C source — see
290
290
  `patchwork`) or is characterized at a looser ±0.5 tolerance for the
291
291
  iterative force-directed engines (`neato`, `fdp`, `sfdp`) — never literal
292
292
  byte equality. Full definition: [Conformance](./docs/conformance.md).
293
- - **Current parity:** `dot` SVG 762/788 conformant (0 unaccepted tracked gaps —
293
+ - **Current parity:** `dot` SVG 910/927 conformant (0 unaccepted tracked gaps —
294
294
  every remaining non-conformant graph is a documented, accepted divergence);
295
- `dot` xdot 761/761; `patchwork` xdot 762/762; `osage` xdot 755/762; `circo`
296
- xdot 752/762; `twopi` xdot 746/762 (all deterministic, ±0.01).
297
- `neato`/`fdp`/`sfdp` are characterized at ±0.5 rather than gated at the
298
- deterministic bar, per the tolerance split above. These figures are a
295
+ `dot` xdot 905/905; `patchwork` xdot 905/905; `osage` xdot 897/905; `circo`
296
+ xdot 902/907; `twopi` xdot 893/910 (all deterministic, ±0.01). Denominators
297
+ leave out inputs the C oracle itself cannot render; port errors and
298
+ timeouts stay in as failures. `neato`/`fdp`/`sfdp` (826/910, 703/907,
299
+ 619/910) are characterized at ±0.5 rather than gated at the deterministic
300
+ bar, per the tolerance split above. These figures are a
299
301
  snapshot of one row each from [`test/corpus/PARITY.md`](./test/corpus/PARITY.md),
300
302
  which is generated by `test/corpus/parity-report.ts` and covers every
301
303
  engine × surface track (SVG, xdot, json, plain, imagemap); read it, or the
@@ -0,0 +1,9 @@
1
+ import type { TextVariantFlags } from './textmeasure.js';
2
+ /**
3
+ * CSS `font` shorthand (`[style] [weight] [stretch] <size>px <families>`)
4
+ * naming the face svg_textspan renders `fontname` with. Pure; always
5
+ * syntactically valid CSS.
6
+ * @see plugin/core/gvrender_core_svg.c:462-500 svg_textspan (family/weight/style selection)
7
+ */
8
+ export declare function canvasFont(fontname: string | null, fontsize: number, flags?: TextVariantFlags): string;
9
+ //# sourceMappingURL=css-font.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css-font.d.ts","sourceRoot":"","sources":["../../src/common/css-font.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAkFzD;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,gBAAgB,GACvB,MAAM,CAMR"}
@@ -96,13 +96,23 @@ export declare class LutTextMeasurer implements TextMeasurer {
96
96
  }
97
97
  /**
98
98
  * Canvas-based TextMeasurer via CanvasRenderingContext2D.
99
- * Height is fontsize (matches C behavior).
99
+ * The font is the face the SVG emitter renders with (canvasFont), so browser
100
+ * measurement and rendering agree. Height is fontsize (matches C behavior).
100
101
  * @see lib/common/textspan.c:estimate_textspan_size
101
102
  */
102
103
  export declare class CanvasTextMeasurer implements TextMeasurer {
103
104
  private readonly ctx;
105
+ /**
106
+ * fontname|fontsize|bold|italic → accepted font string. Mirrors pango's
107
+ * font reuse (plugin/pango/gvtextlayout_pango.c:99-100).
108
+ */
109
+ private readonly fonts;
104
110
  constructor(ctx: CanvasRenderingContext2D);
105
111
  measure(text: string, fontname: string, fontsize: number, flags?: TextVariantFlags): TextSize;
112
+ /** Cached font string; built and validated once per distinct font. */
113
+ private fontFor;
114
+ /** True when the context accepts `font` as a `ctx.font` value. */
115
+ private accepts;
106
116
  }
107
117
  /** graphviz estimate_textspan_size line spacing. @see lib/common/const.h:70 */
108
118
  export declare const LINESPACING = 1.2;
@@ -1 +1 @@
1
- {"version":3,"file":"textmeasure.d.ts","sourceRoot":"","sources":["../../src/common/textmeasure.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAKH,qDAAqD;AACrD,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,iDAAiD;AACjD,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,gBAAgB,GACvB,QAAQ,CAAC;CACb;AA8CD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,OAAO,GACd,MAAM,CASR;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,QAAY,CAAC;AAW/C;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,UAAQ,EACZ,MAAM,UAAQ,GACb,MAAM,CAWR;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,QAAc,CAAC;AAEjD,+DAA+D;AAC/D,eAAO,MAAM,sBAAsB,QAAa,CAAC;AAgDjD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAG1E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAK9E;AAED;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,YAAY;IAClD,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,gBAAgB,GACvB,QAAQ;CAMZ;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,YAAY;IACzC,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,wBAAwB;IAE1D,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,gBAAgB,GACvB,QAAQ;CAWZ;AAED,+EAA+E;AAC/E,eAAO,MAAM,WAAW,MAAO,CAAC;AAEhC;;;;;;;GAOG;AACH,qBAAa,oBAAqB,YAAW,YAAY;IACvD,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,gBAAgB,GACvB,QAAQ;CAWZ"}
1
+ {"version":3,"file":"textmeasure.d.ts","sourceRoot":"","sources":["../../src/common/textmeasure.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAMH,qDAAqD;AACrD,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,iDAAiD;AACjD,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,gBAAgB,GACvB,QAAQ,CAAC;CACb;AA8CD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,OAAO,GACd,MAAM,CASR;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,QAAY,CAAC;AAW/C;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,IAAI,UAAQ,EACZ,MAAM,UAAQ,GACb,MAAM,CAWR;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,QAAc,CAAC;AAEjD,+DAA+D;AAC/D,eAAO,MAAM,sBAAsB,QAAa,CAAC;AAgDjD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAG1E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAK9E;AAED;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,YAAY;IAClD,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,gBAAgB,GACvB,QAAQ;CAMZ;AASD;;;;;GAKG;AACH,qBAAa,kBAAmB,YAAW,YAAY;IAOzC,OAAO,CAAC,QAAQ,CAAC,GAAG;IANhC;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6B;gBAEtB,GAAG,EAAE,wBAAwB;IAE1D,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,gBAAgB,GACvB,QAAQ;IAMX,sEAAsE;IACtE,OAAO,CAAC,OAAO;IAaf,kEAAkE;IAClE,OAAO,CAAC,OAAO;CAQhB;AAED,+EAA+E;AAC/E,eAAO,MAAM,WAAW,MAAO,CAAC;AAEhC;;;;;;;GAOG;AACH,qBAAa,oBAAqB,YAAW,YAAY;IACvD,OAAO,CACL,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,gBAAgB,GACvB,QAAQ;CAWZ"}
package/dist/index.js CHANGED
@@ -15644,6 +15644,151 @@ function getFamilyMetrics(fontName) {
15644
15644
  return TIMES_FALLBACK;
15645
15645
  }
15646
15646
 
15647
+ // src/common/ps-fontalias.ts
15648
+ var ALIAS_ROWS = [
15649
+ ["AvantGarde-Book", "URW Gothic L", "book", null, null, "sans-Serif", null, null],
15650
+ ["AvantGarde-BookOblique", "URW Gothic L", "book", null, "oblique", "sans-Serif", null, "italic"],
15651
+ ["AvantGarde-Demi", "URW Gothic L", "demi", null, null, "sans-Serif", "bold", null],
15652
+ ["AvantGarde-DemiOblique", "URW Gothic L", "demi", null, "oblique", "sans-Serif", "bold", "italic"],
15653
+ ["Bookman-Demi", "URW Bookman L", "demi", null, null, "serif", "bold", null],
15654
+ ["Bookman-DemiItalic", "URW Bookman L", "demi", null, "italic", "serif", "bold", "italic"],
15655
+ ["Bookman-Light", "URW Bookman L", "light", null, null, "serif", null, null],
15656
+ ["Bookman-LightItalic", "URW Bookman L", "light", null, "italic", "serif", null, "italic"],
15657
+ ["Courier", "Courier", null, null, null, "monospace", null, null],
15658
+ ["Courier-Bold", "Courier", "bold", null, null, "monospace", "bold", null],
15659
+ ["Courier-BoldOblique", "Courier", "bold", null, "oblique", "monospace", "bold", "italic"],
15660
+ ["Courier-Oblique", "Courier", null, null, "oblique", "monospace", null, "italic"],
15661
+ ["Helvetica", "Helvetica", null, null, null, "sans-Serif", null, null],
15662
+ ["Helvetica-Bold", "Helvetica", "bold", null, null, "sans-Serif", "bold", null],
15663
+ ["Helvetica-BoldOblique", "Helvetica", "bold", null, "oblique", "sans-Serif", "bold", "italic"],
15664
+ ["Helvetica-Narrow", "Helvetica", null, "condensed", null, "sans-Serif", null, null],
15665
+ ["Helvetica-Narrow-Bold", "Helvetica", "bold", "condensed", null, "sans-Serif", "bold", null],
15666
+ ["Helvetica-Narrow-BoldOblique", "Helvetica", "bold", "condensed", "oblique", "sans-Serif", "bold", "italic"],
15667
+ ["Helvetica-Narrow-Oblique", "Helvetica", null, "condensed", "oblique", "sans-Serif", null, "italic"],
15668
+ ["Helvetica-Oblique", "Helvetica", null, null, "oblique", "sans-Serif", null, "italic"],
15669
+ ["NewCenturySchlbk-Bold", "Century Schoolbook L", "bold", null, null, "serif", "bold", null],
15670
+ ["NewCenturySchlbk-BoldItalic", "Century Schoolbook L", "bold", null, "italic", "serif", "bold", "italic"],
15671
+ ["NewCenturySchlbk-Italic", "Century Schoolbook L", null, null, "italic", "serif", null, "italic"],
15672
+ ["NewCenturySchlbk-Roman", "Century Schoolbook L", "roman", null, null, "serif", null, null],
15673
+ ["Palatino-Bold", "Palatino Linotype", "bold", null, null, "serif", "bold", null],
15674
+ ["Palatino-BoldItalic", "Palatino Linotype", "bold", null, "italic", "serif", "bold", "italic"],
15675
+ ["Palatino-Italic", "Palatino Linotype", null, null, "italic", "serif", null, "italic"],
15676
+ ["Palatino-Roman", "Palatino Linotype", "roman", null, null, "serif", null, null],
15677
+ ["Symbol", "Symbol", null, null, null, "fantasy", null, null],
15678
+ ["Times-Bold", "Times", "bold", null, null, "serif", "bold", null],
15679
+ ["Times-BoldItalic", "Times", "bold", null, "italic", "serif", "bold", "italic"],
15680
+ ["Times-Italic", "Times", null, null, "italic", "serif", null, "italic"],
15681
+ ["Times-Roman", "Times", null, null, null, "serif", null, null],
15682
+ ["ZapfChancery-MediumItalic", "URW Chancery L", "medium", null, "italic", "serif", null, "italic"],
15683
+ ["ZapfDingbats", "Dingbats", null, null, null, "fantasy", null, null]
15684
+ ];
15685
+ var ALIAS_BY_NAME = new Map(
15686
+ ALIAS_ROWS.map((r) => [
15687
+ r[0].toLowerCase(),
15688
+ {
15689
+ name: r[0],
15690
+ family: r[1],
15691
+ weight: r[2],
15692
+ stretch: r[3],
15693
+ style: r[4],
15694
+ svgFontFamily: r[5],
15695
+ svgFontWeight: r[6],
15696
+ svgFontStyle: r[7]
15697
+ }
15698
+ ])
15699
+ );
15700
+ function translatePostscriptFontname(name) {
15701
+ return ALIAS_BY_NAME.get(name.toLowerCase()) ?? null;
15702
+ }
15703
+ function fontFamilyAttrs(fontName, mode = FontnameKind.NativeFonts) {
15704
+ const a = fontName !== null ? translatePostscriptFontname(fontName) : null;
15705
+ if (a === null) return null;
15706
+ let family;
15707
+ let weight;
15708
+ let style;
15709
+ switch (mode) {
15710
+ case FontnameKind.PsFonts:
15711
+ family = a.name;
15712
+ weight = a.weight;
15713
+ style = a.style;
15714
+ break;
15715
+ case FontnameKind.SvgFonts:
15716
+ family = a.svgFontFamily;
15717
+ weight = a.svgFontWeight;
15718
+ style = a.svgFontStyle;
15719
+ break;
15720
+ default:
15721
+ family = a.family;
15722
+ weight = a.weight;
15723
+ style = a.style;
15724
+ break;
15725
+ }
15726
+ const fam = a.svgFontFamily !== family ? family + "," + a.svgFontFamily : family;
15727
+ let attrs = ' font-family="' + fam + '"';
15728
+ if (weight !== null) attrs += ' font-weight="' + weight + '"';
15729
+ if (a.stretch !== null) attrs += ' font-stretch="' + a.stretch + '"';
15730
+ if (style !== null) attrs += ' font-style="' + style + '"';
15731
+ return { attrs, weight: weight !== null, style: style !== null };
15732
+ }
15733
+
15734
+ // src/common/css-font.ts
15735
+ var DEFAULT_FAMILIES = ["Times", "serif"];
15736
+ var CSS_GENERIC_FAMILIES = /* @__PURE__ */ new Set([
15737
+ "serif",
15738
+ "sans-serif",
15739
+ "monospace",
15740
+ "cursive",
15741
+ "fantasy",
15742
+ "system-ui"
15743
+ ]);
15744
+ var CSS_WEIGHT_KEYWORDS = /* @__PURE__ */ new Set([
15745
+ "normal",
15746
+ "bold",
15747
+ "bolder",
15748
+ "lighter"
15749
+ ]);
15750
+ var DQ = '"';
15751
+ var SQ = "'";
15752
+ var BACKSLASH = "\\";
15753
+ function isCssWeight(w) {
15754
+ return CSS_WEIGHT_KEYWORDS.has(w.toLowerCase());
15755
+ }
15756
+ function stripQuotes(f) {
15757
+ const q = f.charAt(0);
15758
+ if (f.length >= 2 && (q === DQ || q === SQ) && f.endsWith(q)) return f.slice(1, -1);
15759
+ return f;
15760
+ }
15761
+ function quoteFamily(f) {
15762
+ if (CSS_GENERIC_FAMILIES.has(f.toLowerCase())) return f;
15763
+ const escaped = f.split(BACKSLASH).join(BACKSLASH + BACKSLASH).split(DQ).join(BACKSLASH + DQ);
15764
+ return DQ + escaped + DQ;
15765
+ }
15766
+ function splitFamilies(fontname) {
15767
+ const entries = (fontname ?? "").split(",").map((f) => stripQuotes(f.trim()).trim()).filter((f) => f !== "");
15768
+ return entries.length > 0 ? entries : DEFAULT_FAMILIES;
15769
+ }
15770
+ function aliasFamilies(a) {
15771
+ return a.svgFontFamily !== a.family ? [a.family, a.svgFontFamily] : [a.family];
15772
+ }
15773
+ function styleToken(a, flags) {
15774
+ if (a?.style != null) return a.style;
15775
+ return flags?.italic === true ? "italic" : null;
15776
+ }
15777
+ function weightToken(a, flags) {
15778
+ if (a?.weight != null) return isCssWeight(a.weight) ? a.weight : null;
15779
+ return flags?.bold === true ? "bold" : null;
15780
+ }
15781
+ function variantTokens(a, flags) {
15782
+ const tokens = [styleToken(a, flags), weightToken(a, flags), a?.stretch ?? null];
15783
+ return tokens.filter((t) => t !== null);
15784
+ }
15785
+ function canvasFont(fontname, fontsize, flags) {
15786
+ const a = fontname !== null ? translatePostscriptFontname(fontname) : null;
15787
+ const families = a !== null ? aliasFamilies(a) : splitFamilies(fontname);
15788
+ const tokens = [...variantTokens(a, flags), `${fontsize}px`];
15789
+ return `${tokens.join(" ")} ${families.map(quoteFamily).join(", ")}`;
15790
+ }
15791
+
15647
15792
  // src/common/textmeasure.ts
15648
15793
  function getVariantWidths(family, bold, italic) {
15649
15794
  if (bold && italic) return family.boldItalic;
@@ -15724,19 +15869,42 @@ var LutTextMeasurer = class {
15724
15869
  return { w, h: freetypeLineHeight(fontsize, fontname) };
15725
15870
  }
15726
15871
  };
15872
+ var FONT_PROBES = ["1px serif", "2px monospace"];
15727
15873
  var CanvasTextMeasurer = class {
15728
15874
  constructor(ctx) {
15729
15875
  this.ctx = ctx;
15730
15876
  }
15731
15877
  ctx;
15878
+ /**
15879
+ * fontname|fontsize|bold|italic → accepted font string. Mirrors pango's
15880
+ * font reuse (plugin/pango/gvtextlayout_pango.c:99-100).
15881
+ */
15882
+ fonts = /* @__PURE__ */ new Map();
15732
15883
  measure(text, fontname, fontsize, flags) {
15733
- const bold = flags?.bold === true;
15734
- const italic = flags?.italic === true;
15735
- const style = bold && italic ? "bold italic" : bold ? "bold" : italic ? "italic" : "";
15736
- this.ctx.font = style ? `${style} ${fontsize}px ${fontname}` : `${fontsize}px ${fontname}`;
15884
+ this.ctx.font = this.fontFor(fontname, fontsize, flags);
15737
15885
  const m = this.ctx.measureText(text);
15738
15886
  return { w: m.width, h: fontsize };
15739
15887
  }
15888
+ /** Cached font string; built and validated once per distinct font. */
15889
+ fontFor(fontname, fontsize, flags) {
15890
+ const key = `${fontname}|${fontsize}|${flags?.bold === true}|${flags?.italic === true}`;
15891
+ let font = this.fonts.get(key);
15892
+ if (font === void 0) {
15893
+ font = canvasFont(fontname, fontsize, flags);
15894
+ if (!this.accepts(font)) font = canvasFont(null, fontsize, flags);
15895
+ this.fonts.set(key, font);
15896
+ }
15897
+ return font;
15898
+ }
15899
+ /** True when the context accepts `font` as a `ctx.font` value. */
15900
+ accepts(font) {
15901
+ return FONT_PROBES.some((probe) => {
15902
+ this.ctx.font = probe;
15903
+ const before = this.ctx.font;
15904
+ this.ctx.font = font;
15905
+ return this.ctx.font !== before;
15906
+ });
15907
+ }
15740
15908
  };
15741
15909
  var LINESPACING = 1.2;
15742
15910
  var EstimateTextMeasurer = class {
@@ -24607,93 +24775,6 @@ function commonInitNodeEdge(g) {
24607
24775
  for (const n of g.nodes.values()) commonInitNode(n, g);
24608
24776
  }
24609
24777
 
24610
- // src/common/ps-fontalias.ts
24611
- var ALIAS_ROWS = [
24612
- ["AvantGarde-Book", "URW Gothic L", "book", null, null, "sans-Serif", null, null],
24613
- ["AvantGarde-BookOblique", "URW Gothic L", "book", null, "oblique", "sans-Serif", null, "italic"],
24614
- ["AvantGarde-Demi", "URW Gothic L", "demi", null, null, "sans-Serif", "bold", null],
24615
- ["AvantGarde-DemiOblique", "URW Gothic L", "demi", null, "oblique", "sans-Serif", "bold", "italic"],
24616
- ["Bookman-Demi", "URW Bookman L", "demi", null, null, "serif", "bold", null],
24617
- ["Bookman-DemiItalic", "URW Bookman L", "demi", null, "italic", "serif", "bold", "italic"],
24618
- ["Bookman-Light", "URW Bookman L", "light", null, null, "serif", null, null],
24619
- ["Bookman-LightItalic", "URW Bookman L", "light", null, "italic", "serif", null, "italic"],
24620
- ["Courier", "Courier", null, null, null, "monospace", null, null],
24621
- ["Courier-Bold", "Courier", "bold", null, null, "monospace", "bold", null],
24622
- ["Courier-BoldOblique", "Courier", "bold", null, "oblique", "monospace", "bold", "italic"],
24623
- ["Courier-Oblique", "Courier", null, null, "oblique", "monospace", null, "italic"],
24624
- ["Helvetica", "Helvetica", null, null, null, "sans-Serif", null, null],
24625
- ["Helvetica-Bold", "Helvetica", "bold", null, null, "sans-Serif", "bold", null],
24626
- ["Helvetica-BoldOblique", "Helvetica", "bold", null, "oblique", "sans-Serif", "bold", "italic"],
24627
- ["Helvetica-Narrow", "Helvetica", null, "condensed", null, "sans-Serif", null, null],
24628
- ["Helvetica-Narrow-Bold", "Helvetica", "bold", "condensed", null, "sans-Serif", "bold", null],
24629
- ["Helvetica-Narrow-BoldOblique", "Helvetica", "bold", "condensed", "oblique", "sans-Serif", "bold", "italic"],
24630
- ["Helvetica-Narrow-Oblique", "Helvetica", null, "condensed", "oblique", "sans-Serif", null, "italic"],
24631
- ["Helvetica-Oblique", "Helvetica", null, null, "oblique", "sans-Serif", null, "italic"],
24632
- ["NewCenturySchlbk-Bold", "Century Schoolbook L", "bold", null, null, "serif", "bold", null],
24633
- ["NewCenturySchlbk-BoldItalic", "Century Schoolbook L", "bold", null, "italic", "serif", "bold", "italic"],
24634
- ["NewCenturySchlbk-Italic", "Century Schoolbook L", null, null, "italic", "serif", null, "italic"],
24635
- ["NewCenturySchlbk-Roman", "Century Schoolbook L", "roman", null, null, "serif", null, null],
24636
- ["Palatino-Bold", "Palatino Linotype", "bold", null, null, "serif", "bold", null],
24637
- ["Palatino-BoldItalic", "Palatino Linotype", "bold", null, "italic", "serif", "bold", "italic"],
24638
- ["Palatino-Italic", "Palatino Linotype", null, null, "italic", "serif", null, "italic"],
24639
- ["Palatino-Roman", "Palatino Linotype", "roman", null, null, "serif", null, null],
24640
- ["Symbol", "Symbol", null, null, null, "fantasy", null, null],
24641
- ["Times-Bold", "Times", "bold", null, null, "serif", "bold", null],
24642
- ["Times-BoldItalic", "Times", "bold", null, "italic", "serif", "bold", "italic"],
24643
- ["Times-Italic", "Times", null, null, "italic", "serif", null, "italic"],
24644
- ["Times-Roman", "Times", null, null, null, "serif", null, null],
24645
- ["ZapfChancery-MediumItalic", "URW Chancery L", "medium", null, "italic", "serif", null, "italic"],
24646
- ["ZapfDingbats", "Dingbats", null, null, null, "fantasy", null, null]
24647
- ];
24648
- var ALIAS_BY_NAME = new Map(
24649
- ALIAS_ROWS.map((r) => [
24650
- r[0].toLowerCase(),
24651
- {
24652
- name: r[0],
24653
- family: r[1],
24654
- weight: r[2],
24655
- stretch: r[3],
24656
- style: r[4],
24657
- svgFontFamily: r[5],
24658
- svgFontWeight: r[6],
24659
- svgFontStyle: r[7]
24660
- }
24661
- ])
24662
- );
24663
- function translatePostscriptFontname(name) {
24664
- return ALIAS_BY_NAME.get(name.toLowerCase()) ?? null;
24665
- }
24666
- function fontFamilyAttrs(fontName, mode = FontnameKind.NativeFonts) {
24667
- const a = fontName !== null ? translatePostscriptFontname(fontName) : null;
24668
- if (a === null) return null;
24669
- let family;
24670
- let weight;
24671
- let style;
24672
- switch (mode) {
24673
- case FontnameKind.PsFonts:
24674
- family = a.name;
24675
- weight = a.weight;
24676
- style = a.style;
24677
- break;
24678
- case FontnameKind.SvgFonts:
24679
- family = a.svgFontFamily;
24680
- weight = a.svgFontWeight;
24681
- style = a.svgFontStyle;
24682
- break;
24683
- default:
24684
- family = a.family;
24685
- weight = a.weight;
24686
- style = a.style;
24687
- break;
24688
- }
24689
- const fam = a.svgFontFamily !== family ? family + "," + a.svgFontFamily : family;
24690
- let attrs = ' font-family="' + fam + '"';
24691
- if (weight !== null) attrs += ' font-weight="' + weight + '"';
24692
- if (a.stretch !== null) attrs += ' font-stretch="' + a.stretch + '"';
24693
- if (style !== null) attrs += ' font-style="' + style + '"';
24694
- return { attrs, weight: weight !== null, style: style !== null };
24695
- }
24696
-
24697
24778
  // src/render/svg-gradient.ts
24698
24779
  function bboxFrom2(A3) {
24699
24780
  const rx = A3[1].x - A3[0].x;
@@ -50405,7 +50486,7 @@ function taper(bez, radfunc, initwid) {
50405
50486
  }
50406
50487
 
50407
50488
  // src/render/map.ts
50408
- var DQ = '"';
50489
+ var DQ2 = '"';
50409
50490
  function exactDecimalDigits2(v) {
50410
50491
  const dv = new DataView(new ArrayBuffer(8));
50411
50492
  dv.setFloat64(0, Math.abs(v));
@@ -50701,16 +50782,16 @@ function cmapxCoords(shape, pts) {
50701
50782
  return cmapxCoordsPoly(pts);
50702
50783
  }
50703
50784
  function mapCmapxAttrs(a, out) {
50704
- if (a.id) out.push(" id=" + DQ + escapeXml(a.id) + DQ);
50705
- if (a.url) out.push(" href=" + DQ + escapeXml(a.url) + DQ);
50706
- if (a.target) out.push(" target=" + DQ + escapeXmlTitle(a.target) + DQ);
50707
- if (a.tooltip) out.push(" title=" + DQ + escapeXmlTitle(a.tooltip) + DQ);
50785
+ if (a.id) out.push(" id=" + DQ2 + escapeXml(a.id) + DQ2);
50786
+ if (a.url) out.push(" href=" + DQ2 + escapeXml(a.url) + DQ2);
50787
+ if (a.target) out.push(" target=" + DQ2 + escapeXmlTitle(a.target) + DQ2);
50788
+ if (a.tooltip) out.push(" title=" + DQ2 + escapeXmlTitle(a.tooltip) + DQ2);
50708
50789
  }
50709
50790
  function mapOutputCmapx(shape, pts, a, isXml, out) {
50710
- out.push("<area shape=" + DQ + cmapxShape(shape) + DQ);
50791
+ out.push("<area shape=" + DQ2 + cmapxShape(shape) + DQ2);
50711
50792
  mapCmapxAttrs(a, out);
50712
- out.push(" alt=" + DQ + DQ);
50713
- out.push(" coords=" + DQ + cmapxCoords(shape, pts) + DQ);
50793
+ out.push(" alt=" + DQ2 + DQ2);
50794
+ out.push(" coords=" + DQ2 + cmapxCoords(shape, pts) + DQ2);
50714
50795
  out.push(isXml ? "/>\n" : ">\n");
50715
50796
  }
50716
50797
  function mapOutputImap(shape, pts, url, out) {
@@ -50812,7 +50893,7 @@ var MapRendererBase = class {
50812
50893
  this.mapCtx = buildMapCtx(g, job, this.mapPolygon);
50813
50894
  if (this.isCmapx) {
50814
50895
  const name = escapeXml(mapGraphName(g));
50815
- job.write("<map id=" + DQ + name + DQ + " name=" + DQ + name + DQ + ">\n");
50896
+ job.write("<map id=" + DQ2 + name + DQ2 + " name=" + DQ2 + name + DQ2 + ">\n");
50816
50897
  return;
50817
50898
  }
50818
50899
  job.write("base referer\n");