@unmade/text-renderer 1.1.0 → 1.2.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 (68) hide show
  1. package/README.md +184 -0
  2. package/dist/__vite-browser-external-oLchLuMx.js +7 -0
  3. package/dist/baselines/index.d.ts +59 -0
  4. package/dist/ce-adapter/index.cjs +1 -1
  5. package/dist/ce-adapter/index.js +154 -152
  6. package/dist/constants.d.ts +5 -0
  7. package/dist/fitting/index.d.ts +86 -0
  8. package/dist/glyph/svg-glyph-converter.d.ts +42 -0
  9. package/dist/helpers/bbox.d.ts +34 -0
  10. package/dist/helpers/point.d.ts +17 -0
  11. package/dist/helpers/xml.d.ts +1 -0
  12. package/dist/index.d.ts +17 -249
  13. package/dist/index.js +2221 -2005
  14. package/dist/loading/createLoadedFont.d.ts +53 -0
  15. package/dist/loading/index.d.ts +4 -0
  16. package/dist/measuring/conversion.d.ts +2 -0
  17. package/dist/measuring/index.d.ts +28 -0
  18. package/dist/node/baselines/index.d.ts +59 -0
  19. package/dist/node/ce-adapter/ce-types.d.ts +171 -0
  20. package/dist/node/ce-adapter/extractTextPlacements.d.ts +11 -0
  21. package/dist/node/ce-adapter/index.d.ts +12 -0
  22. package/dist/node/ce-adapter/mapStateToRendererOptions.d.ts +13 -0
  23. package/dist/node/ce-adapter/types.d.ts +56 -0
  24. package/dist/node/constants.d.ts +5 -0
  25. package/dist/node/fitting/index.d.ts +86 -0
  26. package/dist/node/glyph/svg-glyph-converter.d.ts +42 -0
  27. package/dist/node/helpers/bbox.d.ts +34 -0
  28. package/dist/node/helpers/point.d.ts +17 -0
  29. package/dist/node/helpers/xml.d.ts +1 -0
  30. package/dist/node/index.d.ts +17 -249
  31. package/dist/node/index.js +940 -948
  32. package/dist/node/loading/createLoadedFont.d.ts +53 -0
  33. package/dist/node/loading/index.d.ts +4 -0
  34. package/dist/node/measuring/conversion.d.ts +2 -0
  35. package/dist/node/measuring/index.d.ts +28 -0
  36. package/dist/node/renderText.d.ts +5 -0
  37. package/dist/node/rendering/index.d.ts +42 -0
  38. package/dist/node/svg/index.d.ts +11 -0
  39. package/dist/node/types.d.ts +75 -0
  40. package/dist/renderText.d.ts +5 -0
  41. package/dist/rendering/index.d.ts +42 -0
  42. package/dist/rolldown-runtime-DtPi1Y-2.js +13 -0
  43. package/dist/svg/index.d.ts +11 -0
  44. package/dist/types.d.ts +75 -0
  45. package/dist/worker/baselines/index.d.ts +59 -0
  46. package/dist/worker/ce-adapter/ce-types.d.ts +171 -0
  47. package/dist/worker/ce-adapter/extractTextPlacements.d.ts +11 -0
  48. package/dist/worker/ce-adapter/index.d.ts +12 -0
  49. package/dist/worker/ce-adapter/mapStateToRendererOptions.d.ts +13 -0
  50. package/dist/worker/ce-adapter/types.d.ts +56 -0
  51. package/dist/worker/constants.d.ts +5 -0
  52. package/dist/worker/fitting/index.d.ts +86 -0
  53. package/dist/worker/glyph/svg-glyph-converter.d.ts +42 -0
  54. package/dist/worker/helpers/bbox.d.ts +34 -0
  55. package/dist/worker/helpers/point.d.ts +17 -0
  56. package/dist/worker/helpers/xml.d.ts +1 -0
  57. package/dist/worker/index.d.ts +17 -249
  58. package/dist/worker/index.js +8346 -9728
  59. package/dist/worker/loading/createLoadedFont.d.ts +53 -0
  60. package/dist/worker/loading/index.d.ts +4 -0
  61. package/dist/worker/measuring/conversion.d.ts +2 -0
  62. package/dist/worker/measuring/index.d.ts +28 -0
  63. package/dist/worker/renderText.d.ts +5 -0
  64. package/dist/worker/rendering/index.d.ts +42 -0
  65. package/dist/worker/svg/index.d.ts +11 -0
  66. package/dist/worker/types.d.ts +75 -0
  67. package/package.json +19 -11
  68. package/dist/__vite-browser-external-l0sNRNKZ.js +0 -1
@@ -1,970 +1,962 @@
1
- import { Feature as nt, Buffer as At, shape as Bt, Blob as ot, Face as rt, Font as st } from "harfbuzzjs";
2
- import { svgPathProperties as Pt } from "svg-path-properties";
3
- import { DOMParser as Tt } from "linkedom";
1
+ import { Blob as e, Buffer as t, Face as n, Feature as r, Font as i, shape as a } from "harfbuzzjs";
2
+ import o from "@thednp/dommatrix";
3
+ import { DOMParser as s } from "linkedom";
4
4
  import "node:path";
5
- import Lt from "@thednp/dommatrix";
6
- function Ct(e) {
7
- let t = 1 / 0, n = 1 / 0, o = -1 / 0, l = -1 / 0, r = 0, a = 0;
8
- function s(f, d) {
9
- f < t && (t = f), f > o && (o = f), d < n && (n = d), d > l && (l = d);
10
- }
11
- function c(f, d, g) {
12
- const w = f - 2 * d + g;
13
- if (Math.abs(w) < 1e-10) return [];
14
- const m = (f - d) / w;
15
- return m > 0 && m < 1 ? [m] : [];
16
- }
17
- function h(f, d, g, w) {
18
- const m = 1 - f;
19
- return m * m * d + 2 * m * f * g + f * f * w;
20
- }
21
- function i(f, d, g, w) {
22
- const m = d - f, y = g - d, $ = w - g, v = m - 2 * y + $, M = 2 * (y - m), S = m;
23
- if (Math.abs(v) < 1e-10) {
24
- if (Math.abs(M) < 1e-10) return [];
25
- const x = -S / M;
26
- return x > 0 && x < 1 ? [x] : [];
27
- }
28
- const A = M * M - 4 * v * S;
29
- if (A < 0) return [];
30
- const k = Math.sqrt(A);
31
- return [(-M + k) / (2 * v), (-M - k) / (2 * v)].filter((x) => x > 0 && x < 1);
32
- }
33
- function b(f, d, g, w, m) {
34
- const y = 1 - f;
35
- return y * y * y * d + 3 * y * y * f * g + 3 * y * f * f * w + f * f * f * m;
36
- }
37
- const p = /([MLCQTSAZHVmlcqtsazhv])([^MLCQTSAZHVmlcqtsazhv]*)/g;
38
- let u = p.exec(e);
39
- for (; u !== null; ) {
40
- const f = u[1].toUpperCase();
41
- if (f === "Z") {
42
- u = p.exec(e);
43
- continue;
44
- }
45
- const d = u[2].trim().split(/[\s,]+/).filter(Boolean).map(Number);
46
- if (f === "M" || f === "L" || f === "T")
47
- for (let g = 0; g + 1 < d.length; g += 2)
48
- r = d[g], a = d[g + 1], s(r, a);
49
- else if (f === "H")
50
- for (const g of d)
51
- r = g, s(r, a);
52
- else if (f === "V")
53
- for (const g of d)
54
- a = g, s(r, a);
55
- else if (f === "Q")
56
- for (let g = 0; g + 3 < d.length; g += 4) {
57
- const [w, m, y, $] = d.slice(g, g + 4);
58
- s(y, $);
59
- for (const v of c(r, w, y)) s(h(v, r, w, y), h(v, a, m, $));
60
- for (const v of c(a, m, $)) s(h(v, r, w, y), h(v, a, m, $));
61
- r = y, a = $;
62
- }
63
- else if (f === "C")
64
- for (let g = 0; g + 5 < d.length; g += 6) {
65
- const [w, m, y, $, v, M] = d.slice(g, g + 6);
66
- s(v, M);
67
- for (const S of i(r, w, y, v)) s(b(S, r, w, y, v), b(S, a, m, $, M));
68
- for (const S of i(a, m, $, M)) s(b(S, r, w, y, v), b(S, a, m, $, M));
69
- r = v, a = M;
70
- }
71
- else
72
- for (let g = 0; g + 1 < d.length; g += 2)
73
- s(d[g], d[g + 1]);
74
- u = p.exec(e);
75
- }
76
- return Number.isFinite(t) ? { x1: t, y1: n, x2: o, y2: l } : null;
5
+ import { svgPathProperties as c } from "svg-path-properties";
6
+ //#region src/loading/createLoadedFont.ts
7
+ function l(e) {
8
+ let t = Infinity, n = Infinity, r = -Infinity, i = -Infinity, a = 0, o = 0;
9
+ function s(e, a) {
10
+ e < t && (t = e), e > r && (r = e), a < n && (n = a), a > i && (i = a);
11
+ }
12
+ function c(e, t, n) {
13
+ let r = e - 2 * t + n;
14
+ if (Math.abs(r) < 1e-10) return [];
15
+ let i = (e - t) / r;
16
+ return i > 0 && i < 1 ? [i] : [];
17
+ }
18
+ function l(e, t, n, r) {
19
+ let i = 1 - e;
20
+ return i * i * t + 2 * i * e * n + e * e * r;
21
+ }
22
+ function u(e, t, n, r) {
23
+ let i = t - e, a = n - t, o = r - n, s = i - 2 * a + o, c = 2 * (a - i), l = i;
24
+ if (Math.abs(s) < 1e-10) {
25
+ if (Math.abs(c) < 1e-10) return [];
26
+ let e = -l / c;
27
+ return e > 0 && e < 1 ? [e] : [];
28
+ }
29
+ let u = c * c - 4 * s * l;
30
+ if (u < 0) return [];
31
+ let d = Math.sqrt(u);
32
+ return [(-c + d) / (2 * s), (-c - d) / (2 * s)].filter((e) => e > 0 && e < 1);
33
+ }
34
+ function d(e, t, n, r, i) {
35
+ let a = 1 - e;
36
+ return a * a * a * t + 3 * a * a * e * n + 3 * a * e * e * r + e * e * e * i;
37
+ }
38
+ let f = /([MLCQTSAZHVmlcqtsazhv])([^MLCQTSAZHVmlcqtsazhv]*)/g, p = f.exec(e);
39
+ for (; p !== null;) {
40
+ let t = p[1].toUpperCase();
41
+ if (t === "Z") {
42
+ p = f.exec(e);
43
+ continue;
44
+ }
45
+ let n = p[2].trim().split(/[\s,]+/).filter(Boolean).map(Number);
46
+ if (t === "M" || t === "L" || t === "T") for (let e = 0; e + 1 < n.length; e += 2) a = n[e], o = n[e + 1], s(a, o);
47
+ else if (t === "H") for (let e of n) a = e, s(a, o);
48
+ else if (t === "V") for (let e of n) o = e, s(a, o);
49
+ else if (t === "Q") for (let e = 0; e + 3 < n.length; e += 4) {
50
+ let [t, r, i, u] = n.slice(e, e + 4);
51
+ s(i, u);
52
+ for (let e of c(a, t, i)) s(l(e, a, t, i), l(e, o, r, u));
53
+ for (let e of c(o, r, u)) s(l(e, a, t, i), l(e, o, r, u));
54
+ a = i, o = u;
55
+ }
56
+ else if (t === "C") for (let e = 0; e + 5 < n.length; e += 6) {
57
+ let [t, r, i, c, l, f] = n.slice(e, e + 6);
58
+ s(l, f);
59
+ for (let e of u(a, t, i, l)) s(d(e, a, t, i, l), d(e, o, r, c, f));
60
+ for (let e of u(o, r, c, f)) s(d(e, a, t, i, l), d(e, o, r, c, f));
61
+ a = l, o = f;
62
+ }
63
+ else for (let e = 0; e + 1 < n.length; e += 2) s(n[e], n[e + 1]);
64
+ p = f.exec(e);
65
+ }
66
+ return Number.isFinite(t) ? {
67
+ x1: t,
68
+ y1: n,
69
+ x2: r,
70
+ y2: i
71
+ } : null;
77
72
  }
78
- function Et(e, t, n, o) {
79
- return e.replace(
80
- /([MLCQTSAZHVmlcqtsazhv])([^MLCQTSAZHVmlcqtsazhv]*)/g,
81
- (l, r, a) => {
82
- const s = r.toUpperCase();
83
- if (s === "Z") return r;
84
- const c = a.trim().split(/[\s,]+/).filter(Boolean).map(Number), h = [];
85
- if (s === "M" || s === "L" || s === "T")
86
- for (let i = 0; i < c.length; i += 2)
87
- h.push(c[i] * t + o, -c[i + 1] * n);
88
- else if (s === "C")
89
- for (let i = 0; i < c.length; i += 6)
90
- h.push(
91
- c[i] * t + o,
92
- -c[i + 1] * n,
93
- c[i + 2] * t + o,
94
- -c[i + 3] * n,
95
- c[i + 4] * t + o,
96
- -c[i + 5] * n
97
- );
98
- else if (s === "Q" || s === "S")
99
- for (let i = 0; i < c.length; i += 4)
100
- h.push(
101
- c[i] * t + o,
102
- -c[i + 1] * n,
103
- c[i + 2] * t + o,
104
- -c[i + 3] * n
105
- );
106
- else if (s === "H")
107
- for (let i = 0; i < c.length; i++)
108
- h.push(c[i] * t + o);
109
- else if (s === "V")
110
- for (let i = 0; i < c.length; i++)
111
- h.push(-c[i] * n);
112
- else
113
- return r + a;
114
- return r + h.join(",");
115
- }
116
- );
73
+ function u(e, t, n, r) {
74
+ return e.replace(/([MLCQTSAZHVmlcqtsazhv])([^MLCQTSAZHVmlcqtsazhv]*)/g, (e, i, a) => {
75
+ let o = i.toUpperCase();
76
+ if (o === "Z") return i;
77
+ let s = a.trim().split(/[\s,]+/).filter(Boolean).map(Number), c = [];
78
+ if (o === "M" || o === "L" || o === "T") for (let e = 0; e < s.length; e += 2) c.push(s[e] * t + r, -s[e + 1] * n);
79
+ else if (o === "C") for (let e = 0; e < s.length; e += 6) c.push(s[e] * t + r, -s[e + 1] * n, s[e + 2] * t + r, -s[e + 3] * n, s[e + 4] * t + r, -s[e + 5] * n);
80
+ else if (o === "Q" || o === "S") for (let e = 0; e < s.length; e += 4) c.push(s[e] * t + r, -s[e + 1] * n, s[e + 2] * t + r, -s[e + 3] * n);
81
+ else if (o === "H") for (let e = 0; e < s.length; e++) c.push(s[e] * t + r);
82
+ else if (o === "V") for (let e = 0; e < s.length; e++) c.push(-s[e] * n);
83
+ else return i + a;
84
+ return i + c.join(",");
85
+ });
117
86
  }
118
- function Ut(e, t, n, o) {
119
- const l = e.upem;
120
- function r(i) {
121
- const b = i.codePointAt(0) ?? 0, p = t.glyph(b) ?? 0, u = t.glyphExtents(p);
122
- return {
123
- index: p,
124
- advanceWidth: t.glyphHAdvance(p),
125
- name: t.glyphName(p),
126
- getBoundingBox() {
127
- return u ? {
128
- x1: u.xBearing,
129
- y1: -u.yBearing,
130
- x2: u.xBearing + u.width,
131
- // height is negative in HarfBuzz (extends downward), so subtracting gives y2 >= y1
132
- y2: -(u.yBearing + u.height)
133
- } : { x1: 0, y1: 0, x2: 0, y2: 0 };
134
- }
135
- };
136
- }
137
- const a = [new nt("liga", 0), new nt("calt", 0)];
138
- function s(i, b, p, u) {
139
- const f = u / l, d = new At();
140
- d.addText(i), d.guessSegmentProperties(), Bt(t, d, a);
141
- const g = d.getGlyphInfos(), w = d.getGlyphPositions();
142
- let m = 0;
143
- return g.map((y, $) => {
144
- const v = w[$], M = y.codepoint, S = m + v.xOffset, A = t.glyphToPath(M), k = Et(A, f, f, S * f);
145
- return m += v.xAdvance, {
146
- getBoundingBox() {
147
- const x = Ct(k);
148
- return x || { x1: S * f, y1: 0, x2: S * f, y2: 0 };
149
- },
150
- toPathData(x) {
151
- return k;
152
- }
153
- };
154
- });
155
- }
156
- function c(i, b, p, u) {
157
- const f = s(i, b, p, u);
158
- return {
159
- getBoundingBox() {
160
- if (f.length === 0)
161
- return { x1: 0, y1: 0, x2: 0, y2: 0 };
162
- const d = f.map((g) => g.getBoundingBox());
163
- return {
164
- x1: Math.min(...d.map((g) => g.x1)),
165
- y1: Math.min(...d.map((g) => g.y1)),
166
- x2: Math.max(...d.map((g) => g.x2)),
167
- y2: Math.max(...d.map((g) => g.y2))
168
- };
169
- },
170
- toPathData(d) {
171
- return f.map((g) => g.toPathData()).join("");
172
- }
173
- };
174
- }
175
- return {
176
- unitsPerEm: l,
177
- names: { fontFamily: n },
178
- svgGlyphs: o,
179
- charToGlyph: r,
180
- getPath: c,
181
- getPaths: s
182
- };
87
+ function d(e, n, i, o) {
88
+ let s = e.upem;
89
+ function c(e) {
90
+ let t = e.codePointAt(0) ?? 0, r = n.glyph(t) ?? 0, i = n.glyphExtents(r);
91
+ return {
92
+ index: r,
93
+ advanceWidth: n.glyphHAdvance(r),
94
+ name: n.glyphName(r),
95
+ getBoundingBox() {
96
+ return i ? {
97
+ x1: i.xBearing,
98
+ y1: -i.yBearing,
99
+ x2: i.xBearing + i.width,
100
+ y2: -(i.yBearing + i.height)
101
+ } : {
102
+ x1: 0,
103
+ y1: 0,
104
+ x2: 0,
105
+ y2: 0
106
+ };
107
+ }
108
+ };
109
+ }
110
+ let d = [new r("liga", 0), new r("calt", 0)];
111
+ function f(e, r, i, o) {
112
+ let c = o / s, f = new t();
113
+ f.addText(e), f.guessSegmentProperties(), a(n, f, d);
114
+ let p = f.getGlyphInfos(), m = f.getGlyphPositions(), h = 0;
115
+ return p.map((e, t) => {
116
+ let r = m[t], i = e.codepoint, a = h + r.xOffset, o = u(n.glyphToPath(i), c, c, a * c);
117
+ return h += r.xAdvance, {
118
+ getBoundingBox() {
119
+ return l(o) || {
120
+ x1: a * c,
121
+ y1: 0,
122
+ x2: a * c,
123
+ y2: 0
124
+ };
125
+ },
126
+ toPathData(e) {
127
+ return o;
128
+ }
129
+ };
130
+ });
131
+ }
132
+ function p(e, t, n, r) {
133
+ let i = f(e, t, n, r);
134
+ return {
135
+ getBoundingBox() {
136
+ if (i.length === 0) return {
137
+ x1: 0,
138
+ y1: 0,
139
+ x2: 0,
140
+ y2: 0
141
+ };
142
+ let e = i.map((e) => e.getBoundingBox());
143
+ return {
144
+ x1: Math.min(...e.map((e) => e.x1)),
145
+ y1: Math.min(...e.map((e) => e.y1)),
146
+ x2: Math.max(...e.map((e) => e.x2)),
147
+ y2: Math.max(...e.map((e) => e.y2))
148
+ };
149
+ },
150
+ toPathData(e) {
151
+ return i.map((e) => e.toPathData()).join("");
152
+ }
153
+ };
154
+ }
155
+ return {
156
+ unitsPerEm: s,
157
+ names: { fontFamily: i },
158
+ svgGlyphs: o,
159
+ charToGlyph: c,
160
+ getPath: p,
161
+ getPaths: f
162
+ };
183
163
  }
184
- const X = /* @__PURE__ */ new Map(), ve = () => X;
185
- async function ut(e, t) {
186
- const n = new DecompressionStream(t), o = n.writable.getWriter(), l = n.readable.getReader();
187
- o.write(new Uint8Array(e)), o.close();
188
- const r = [];
189
- for (; ; ) {
190
- const { done: h, value: i } = await l.read();
191
- if (h) break;
192
- r.push(i);
193
- }
194
- const a = r.reduce((h, i) => h + i.length, 0), s = new Uint8Array(a);
195
- let c = 0;
196
- for (const h of r)
197
- s.set(h, c), c += h.length;
198
- return s;
164
+ //#endregion
165
+ //#region src/loading/index.ts
166
+ var f = /* @__PURE__ */ new Map(), p = () => f;
167
+ async function m(e, t) {
168
+ let n = new DecompressionStream(t), r = n.writable.getWriter(), i = n.readable.getReader();
169
+ r.write(new Uint8Array(e)), r.close();
170
+ let a = [];
171
+ for (;;) {
172
+ let { done: e, value: t } = await i.read();
173
+ if (e) break;
174
+ a.push(t);
175
+ }
176
+ let o = a.reduce((e, t) => e + t.length, 0), s = new Uint8Array(o), c = 0;
177
+ for (let e of a) s.set(e, c), c += e.length;
178
+ return s;
199
179
  }
200
- async function It(e) {
201
- return ut(e, "gzip");
180
+ async function h(e) {
181
+ return m(e, "gzip");
202
182
  }
203
- async function Wt(e) {
204
- const t = new DataView(e), n = t.getUint32(4), o = t.getUint16(12), l = [];
205
- for (let u = 0; u < o; u++) {
206
- const f = 44 + u * 20, d = String.fromCharCode(
207
- t.getUint8(f),
208
- t.getUint8(f + 1),
209
- t.getUint8(f + 2),
210
- t.getUint8(f + 3)
211
- );
212
- l.push({
213
- tag: d,
214
- offset: t.getUint32(f + 4),
215
- compLength: t.getUint32(f + 8),
216
- origLength: t.getUint32(f + 12),
217
- checksum: t.getUint32(f + 16)
218
- });
219
- }
220
- const r = [];
221
- for (const u of l) {
222
- const f = new Uint8Array(e, u.offset, u.compLength);
223
- u.compLength === u.origLength ? r.push(new Uint8Array(f)) : r.push(await ut(f, "deflate"));
224
- }
225
- const a = 2 ** Math.floor(Math.log2(o)) * 16, s = Math.floor(Math.log2(o)), c = o * 16 - a;
226
- let h = 12 + o * 16;
227
- const i = [];
228
- for (let u = 0; u < l.length; u++)
229
- i.push(h), h += l[u].origLength + 3 & -4;
230
- const b = new Uint8Array(h), p = new DataView(b.buffer);
231
- p.setUint32(0, n), p.setUint16(4, o), p.setUint16(6, a), p.setUint16(8, s), p.setUint16(10, c);
232
- for (let u = 0; u < l.length; u++) {
233
- const f = l[u], d = 12 + u * 16;
234
- for (let g = 0; g < 4; g++) b[d + g] = f.tag.charCodeAt(g);
235
- p.setUint32(d + 4, f.checksum), p.setUint32(d + 8, i[u]), p.setUint32(d + 12, f.origLength), b.set(r[u], i[u]);
236
- }
237
- return b.buffer;
183
+ async function g(e) {
184
+ let t = new DataView(e), n = t.getUint32(4), r = t.getUint16(12), i = [];
185
+ for (let e = 0; e < r; e++) {
186
+ let n = 44 + e * 20, r = String.fromCharCode(t.getUint8(n), t.getUint8(n + 1), t.getUint8(n + 2), t.getUint8(n + 3));
187
+ i.push({
188
+ tag: r,
189
+ offset: t.getUint32(n + 4),
190
+ compLength: t.getUint32(n + 8),
191
+ origLength: t.getUint32(n + 12),
192
+ checksum: t.getUint32(n + 16)
193
+ });
194
+ }
195
+ let a = [];
196
+ for (let t of i) {
197
+ let n = new Uint8Array(e, t.offset, t.compLength);
198
+ t.compLength === t.origLength ? a.push(new Uint8Array(n)) : a.push(await m(n, "deflate"));
199
+ }
200
+ let o = 2 ** Math.floor(Math.log2(r)) * 16, s = Math.floor(Math.log2(r)), c = r * 16 - o, l = 12 + r * 16, u = [];
201
+ for (let e = 0; e < i.length; e++) u.push(l), l += i[e].origLength + 3 & -4;
202
+ let d = new Uint8Array(l), f = new DataView(d.buffer);
203
+ f.setUint32(0, n), f.setUint16(4, r), f.setUint16(6, o), f.setUint16(8, s), f.setUint16(10, c);
204
+ for (let e = 0; e < i.length; e++) {
205
+ let t = i[e], n = 12 + e * 16;
206
+ for (let e = 0; e < 4; e++) d[n + e] = t.tag.charCodeAt(e);
207
+ f.setUint32(n + 4, t.checksum), f.setUint32(n + 8, u[e]), f.setUint32(n + 12, t.origLength), d.set(a[e], u[e]);
208
+ }
209
+ return d.buffer;
238
210
  }
239
- async function at(e, t, n) {
240
- const o = /* @__PURE__ */ new Map(), l = new DataView(e.buffer, e.byteOffset, e.byteLength), r = l.getUint32(2), a = l.getUint16(r), s = r;
241
- for (let c = 0; c < a; c++) {
242
- const h = r + 2 + c * 12, i = l.getUint16(h), b = l.getUint16(h + 2), p = l.getUint32(h + 4), u = l.getUint32(h + 8), f = s + p;
243
- let d = e.slice(f, f + u);
244
- d[0] === 31 && d[1] === 139 && (d = await It(d));
245
- const g = new TextDecoder().decode(d);
246
- for (let w = i; w <= b; w++) {
247
- const m = t.glyphExtents(w);
248
- let y;
249
- m ? y = `${m.xBearing} ${-m.yBearing} ${m.width} ${-m.height}` : y = "0 0 0 0", o.set(w, { svg: g, viewbox: y });
250
- }
251
- }
252
- return o;
211
+ async function _(e, t, n) {
212
+ let r = /* @__PURE__ */ new Map(), i = new DataView(e.buffer, e.byteOffset, e.byteLength), a = i.getUint32(2), o = i.getUint16(a), s = a;
213
+ for (let n = 0; n < o; n++) {
214
+ let o = a + 2 + n * 12, c = i.getUint16(o), l = i.getUint16(o + 2), u = i.getUint32(o + 4), d = i.getUint32(o + 8), f = s + u, p = e.slice(f, f + d);
215
+ p[0] === 31 && p[1] === 139 && (p = await h(p));
216
+ let m = new TextDecoder().decode(p);
217
+ for (let e = c; e <= l; e++) {
218
+ let n = t.glyphExtents(e), i;
219
+ i = n ? `${n.xBearing} ${-n.yBearing} ${n.width} ${-n.height}` : "0 0 0 0", r.set(e, {
220
+ svg: m,
221
+ viewbox: i
222
+ });
223
+ }
224
+ }
225
+ return r;
253
226
  }
254
- const Gt = 2001684038;
255
- async function Ot(e) {
256
- return e.byteLength >= 4 && new DataView(e).getUint32(0) === Gt ? Wt(e) : e;
227
+ var v = 2001684038;
228
+ async function y(e) {
229
+ return e.byteLength >= 4 && new DataView(e).getUint32(0) === v ? g(e) : e;
257
230
  }
258
- async function it(e) {
259
- const t = await fetch(e);
260
- if (!t.ok)
261
- throw new Error(
262
- `Failed to load font from ${e}: ${t.status} ${t.statusText}`
263
- );
264
- const n = await t.arrayBuffer();
265
- return Ot(n);
231
+ async function b(e) {
232
+ let t = await fetch(e);
233
+ if (!t.ok) throw Error(`Failed to load font from ${e}: ${t.status} ${t.statusText}`);
234
+ return y(await t.arrayBuffer());
266
235
  }
267
- const Dt = async (e, t = !1) => {
268
- const n = X.get(e);
269
- if (n) {
270
- if (t && !n.svgGlyphs) {
271
- const i = await it(e), b = new ot(i), p = new rt(b), u = new st(p), f = p.referenceTable("SVG "), d = f ? await at(f, u, p.upem) : /* @__PURE__ */ new Map();
272
- n.svgGlyphs = d;
273
- }
274
- return n;
275
- }
276
- const o = await it(e), l = new ot(o), r = new rt(l), a = new st(r), s = r.getName(1, "en") ?? "";
277
- let c;
278
- if (t) {
279
- const i = r.referenceTable("SVG ");
280
- c = i ? await at(i, a, r.upem) : /* @__PURE__ */ new Map();
281
- }
282
- const h = Ut(r, a, s, c);
283
- return X.set(e, h), h;
284
- }, qt = 0.03125, pt = 1.1, Nt = 0.2, G = {
285
- outlineWidth: qt,
286
- letterSpacing: 0,
287
- letterSpacingOutline: 0
236
+ var x = async (t, r = !1) => {
237
+ let a = f.get(t);
238
+ if (a) {
239
+ if (r && !a.svgGlyphs) {
240
+ let r = await b(t), o = new e(r), s = new n(o), c = new i(s), l = s.referenceTable("SVG ");
241
+ a.svgGlyphs = l ? await _(l, c, s.upem) : /* @__PURE__ */ new Map();
242
+ }
243
+ return a;
244
+ }
245
+ let o = await b(t), s = new e(o), c = new n(s), l = new i(c), u = c.getName(1, "en") ?? "", p;
246
+ if (r) {
247
+ let e = c.referenceTable("SVG ");
248
+ p = e ? await _(e, l, c.upem) : /* @__PURE__ */ new Map();
249
+ }
250
+ let m = d(c, l, u, p);
251
+ return f.set(t, m), m;
252
+ }, S = .03125, C = 1.1, w = .2, T = {
253
+ outlineWidth: S,
254
+ letterSpacing: 0,
255
+ letterSpacingOutline: 0
256
+ }, E = class {
257
+ constructor(e, t) {
258
+ this.x = e, this.y = t;
259
+ }
260
+ get X() {
261
+ return this.x;
262
+ }
263
+ get Y() {
264
+ return this.y;
265
+ }
266
+ toSVGString() {
267
+ return `${this.x} ${this.y}`;
268
+ }
288
269
  };
289
- class P {
290
- constructor(t, n) {
291
- this.x = t, this.y = n;
292
- }
293
- get X() {
294
- return this.x;
295
- }
296
- get Y() {
297
- return this.y;
298
- }
299
- toSVGString() {
300
- return `${this.x} ${this.y}`;
301
- }
270
+ function ee(e, t, n = new E(0, 0)) {
271
+ let r = e.X - n.X, i = e.Y - n.Y, a = t / 180 * Math.PI, o = Math.cos(a), s = Math.sin(a), c = r * o - i * s, l = r * s + i * o;
272
+ return new E(c + n.X, l + n.Y);
302
273
  }
303
- function _t(e, t, n = new P(0, 0)) {
304
- const o = e.X - n.X, l = e.Y - n.Y, r = t / 180 * Math.PI, a = Math.cos(r), s = Math.sin(r), c = o * a - l * s, h = o * s + l * a;
305
- return new P(c + n.X, h + n.Y);
306
- }
307
- const Vt = (e) => e === void 0 || e === "flat" ? { type: "flat" } : e === "curved" ? { type: "curved" } : e, Ht = (e) => {
308
- if (!e || !e.trim())
309
- throw new Error("Custom baseline path must be a non-empty SVG path string");
310
- if (!e.trim().startsWith("M"))
311
- throw new Error(
312
- "Custom baseline path must start with an M (moveto) command"
313
- );
314
- }, zt = ({
315
- boxDimensions: e,
316
- totalTextHeight: t,
317
- baseline: n,
318
- lineHeight: o,
319
- verticalAlignment: l = "centre",
320
- lineNumber: r = 0
321
- }) => {
322
- const { width: a, height: s } = e, c = o - n;
323
- let h = n;
324
- switch (l) {
325
- case "centre": {
326
- h = (s - t) / 2 + o - c;
327
- break;
328
- }
329
- case "bottom": {
330
- h = s - t + o - c;
331
- break;
332
- }
333
- }
334
- return h += r * (o * pt), `M 0 ${h} L ${a} ${h}`;
335
- }, mt = ({
336
- boxDimensions: e,
337
- baseline: t,
338
- textHeight: n,
339
- verticalAlignment: o
340
- }) => {
341
- const { width: l, height: r } = e, a = n * Nt, s = n + a, c = o === "top" ? 0 : r / 2 - s / 2, h = t + c, i = h + a;
342
- if (o !== "top" && (i > r || h - n < 0))
343
- return mt({
344
- boxDimensions: e,
345
- baseline: t,
346
- textHeight: n,
347
- verticalAlignment: "top"
348
- });
349
- const b = n / 4, p = new P(b, i), u = new P(l / 2, h), f = new P(l - b, i), d = l * 0.2, g = new P(
350
- d,
351
- t + c
352
- ), w = new P(
353
- l - d,
354
- t + c
355
- ), m = `M ${p.toSVGString()}`, y = `Q ${g.toSVGString()} ${u.toSVGString()}`, $ = `Q ${w.toSVGString()} ${f.toSVGString()}`;
356
- return `${m} ${y} ${$}`;
357
- }, yt = (e) => {
358
- const t = ["I", "l", "1"];
359
- for (const n of t) {
360
- const o = e.charToGlyph(n);
361
- if (o && o.name !== ".notdef")
362
- return n;
363
- }
364
- return console.error(
365
- 'No standard character found for fixed height calculation. Using "I" as default.'
366
- ), "I";
367
- }, z = 100, Rt = ({
368
- font: e,
369
- boxDimensions: t,
370
- physicalSize: n,
371
- spacing: o = G
372
- }) => {
373
- const l = n;
374
- if (l[1] !== t.physicalUnits)
375
- throw new Error(
376
- `Mismatched units between physicalFontSize (${l[1]}) and boxDimensions (${t.physicalUnits})`
377
- );
378
- const { outlineWidth: r } = o, a = yt(e), c = e.getPath(
379
- a,
380
- 0,
381
- 0,
382
- z
383
- ).getBoundingBox();
384
- let h = c.y2 - c.y1;
385
- if (r > 0) {
386
- const f = z * r;
387
- h += f * 2;
388
- }
389
- const b = h / t.height * t.physicalHeight, p = l[0] / b;
390
- return z * p;
391
- }, ct = ({
392
- font: e,
393
- text: t,
394
- fontSize: n,
395
- spacing: o = G
396
- }) => {
397
- const { outlineWidth: l, letterSpacing: r, letterSpacingOutline: a } = o, c = e.getPath(t, 0, 0, n).getBoundingBox(), h = l ? n * l * 2 : 0, i = l > 0 ? a : r, b = t.length > 1 ? i * n * (t.length - 1) : 0, p = c.x2 - c.x1 + h + b, u = c.y2 - c.y1 + h, f = c.y1 * -1 + h / 2;
398
- return {
399
- width: p,
400
- height: u,
401
- baseline: f
402
- };
403
- }, q = Tt, jt = Lt, Xt = () => new q().parseFromString("<svg></svg>", "image/svg+xml"), Zt = Xt();
404
- Zt.readyState = "complete";
405
- const Qt = {
406
- aliceblue: "#f0f8ff",
407
- antiquewhite: "#faebd7",
408
- aqua: "#00ffff",
409
- aquamarine: "#7fffd4",
410
- azure: "#f0ffff",
411
- beige: "#f5f5dc",
412
- bisque: "#ffe4c4",
413
- black: "#000000",
414
- blanchedalmond: "#ffebcd",
415
- blue: "#0000ff",
416
- blueviolet: "#8a2be2",
417
- brown: "#a52a2a",
418
- burlywood: "#deb887",
419
- cadetblue: "#5f9ea0",
420
- chartreuse: "#7fff00",
421
- chocolate: "#d2691e",
422
- coral: "#ff7f50",
423
- cornflowerblue: "#6495ed",
424
- cornsilk: "#fff8dc",
425
- crimson: "#dc143c",
426
- cyan: "#00ffff",
427
- darkblue: "#00008b",
428
- darkcyan: "#008b8b",
429
- darkgoldenrod: "#b8860b",
430
- darkgray: "#a9a9a9",
431
- darkgreen: "#006400",
432
- darkgrey: "#a9a9a9",
433
- darkkhaki: "#bdb76b",
434
- darkmagenta: "#8b008b",
435
- darkolivegreen: "#556b2f",
436
- darkorange: "#ff8c00",
437
- darkorchid: "#9932cc",
438
- darkred: "#8b0000",
439
- darksalmon: "#e9967a",
440
- darkseagreen: "#8fbc8f",
441
- darkslateblue: "#483d8b",
442
- darkslategray: "#2f4f4f",
443
- darkslategrey: "#2f4f4f",
444
- darkturquoise: "#00ced1",
445
- darkviolet: "#9400d3",
446
- deeppink: "#ff1493",
447
- deepskyblue: "#00bfff",
448
- dimgray: "#696969",
449
- dimgrey: "#696969",
450
- dodgerblue: "#1e90ff",
451
- firebrick: "#b22222",
452
- floralwhite: "#fffaf0",
453
- forestgreen: "#228b22",
454
- fuchsia: "#ff00ff",
455
- gainsboro: "#dcdcdc",
456
- ghostwhite: "#f8f8ff",
457
- gold: "#ffd700",
458
- goldenrod: "#daa520",
459
- gray: "#808080",
460
- green: "#008000",
461
- greenyellow: "#adff2f",
462
- grey: "#808080",
463
- honeydew: "#f0fff0",
464
- hotpink: "#ff69b4",
465
- indianred: "#cd5c5c",
466
- indigo: "#4b0082",
467
- ivory: "#fffff0",
468
- khaki: "#f0e68c",
469
- lavender: "#e6e6fa",
470
- lavenderblush: "#fff0f5",
471
- lawngreen: "#7cfc00",
472
- lemonchiffon: "#fffacd",
473
- lightblue: "#add8e6",
474
- lightcoral: "#f08080",
475
- lightcyan: "#e0ffff",
476
- lightgoldenrodyellow: "#fafad2",
477
- lightgray: "#d3d3d3",
478
- lightgreen: "#90ee90",
479
- lightgrey: "#d3d3d3",
480
- lightpink: "#ffb6c1",
481
- lightsalmon: "#ffa07a",
482
- lightseagreen: "#20b2aa",
483
- lightskyblue: "#87cefa",
484
- lightslategray: "#778899",
485
- lightslategrey: "#778899",
486
- lightsteelblue: "#b0c4de",
487
- lightyellow: "#ffffe0",
488
- lime: "#00ff00",
489
- limegreen: "#32cd32",
490
- linen: "#faf0e6",
491
- magenta: "#ff00ff",
492
- maroon: "#800000",
493
- mediumaquamarine: "#66cdaa",
494
- mediumblue: "#0000cd",
495
- mediumorchid: "#ba55d3",
496
- mediumpurple: "#9370db",
497
- mediumseagreen: "#3cb371",
498
- mediumslateblue: "#7b68ee",
499
- mediumspringgreen: "#00fa9a",
500
- mediumturquoise: "#48d1cc",
501
- mediumvioletred: "#c71585",
502
- midnightblue: "#191970",
503
- mintcream: "#f5fffa",
504
- mistyrose: "#ffe4e1",
505
- moccasin: "#ffe4b5",
506
- navajowhite: "#ffdead",
507
- navy: "#000080",
508
- oldlace: "#fdf5e6",
509
- olive: "#808000",
510
- olivedrab: "#6b8e23",
511
- orange: "#ffa500",
512
- orangered: "#ff4500",
513
- orchid: "#da70d6",
514
- palegoldenrod: "#eee8aa",
515
- palegreen: "#98fb98",
516
- paleturquoise: "#afeeee",
517
- palevioletred: "#db7093",
518
- papayawhip: "#ffefd5",
519
- peachpuff: "#ffdab9",
520
- peru: "#cd853f",
521
- pink: "#ffc0cb",
522
- plum: "#dda0dd",
523
- powderblue: "#b0e0e6",
524
- purple: "#800080",
525
- rebeccapurple: "#663399",
526
- red: "#ff0000",
527
- rosybrown: "#bc8f8f",
528
- royalblue: "#4169e1",
529
- saddlebrown: "#8b4513",
530
- salmon: "#fa8072",
531
- sandybrown: "#f4a460",
532
- seagreen: "#2e8b57",
533
- seashell: "#fff5ee",
534
- sienna: "#a0522d",
535
- silver: "#c0c0c0",
536
- skyblue: "#87ceeb",
537
- slateblue: "#6a5acd",
538
- slategray: "#708090",
539
- slategrey: "#708090",
540
- snow: "#fffafa",
541
- springgreen: "#00ff7f",
542
- steelblue: "#4682b4",
543
- tan: "#d2b48c",
544
- teal: "#008080",
545
- thistle: "#d8bfd8",
546
- tomato: "#ff6347",
547
- turquoise: "#40e0d0",
548
- violet: "#ee82ee",
549
- wheat: "#f5deb3",
550
- white: "#ffffff",
551
- whitesmoke: "#f5f5f5",
552
- yellow: "#ffff00",
553
- yellowgreen: "#9acd32"
554
- }, Yt = (e) => {
555
- let t = Array.from(e), n = !1;
556
- return t[0] === "#" && (t.shift(), n = !0), t.length === 3 && (t = t.map((o) => `${o}${o}`)), `${n ? "#" : ""}${t.join("").toLowerCase()}`;
557
- }, R = (e) => {
558
- const t = typeof e == "string" ? Number.parseInt(e, 10) : e;
559
- return Math.max(0, Math.min(255, Math.round(t))).toString(16).padStart(2, "0");
560
- }, lt = (...e) => {
561
- const [t, n, o] = Array.isArray(e[0]) ? e[0] : e;
562
- return `#${R(t)}${R(n)}${R(o)}`;
563
- }, Jt = (e, t, n) => {
564
- if (t === 0) {
565
- const i = Math.round(n * 255);
566
- return [i, i, i];
567
- }
568
- const o = (e % 360 + 360) % 360, l = (1 - Math.abs(2 * n - 1)) * t, r = l * (1 - Math.abs(o / 60 % 2 - 1)), a = n - l / 2;
569
- let s = 0, c = 0, h = 0;
570
- return o < 60 ? (s = l, c = r, h = 0) : o < 120 ? (s = r, c = l, h = 0) : o < 180 ? (s = 0, c = l, h = r) : o < 240 ? (s = 0, c = r, h = l) : o < 300 ? (s = r, c = 0, h = l) : (s = l, c = 0, h = r), [
571
- Math.round((s + a) * 255),
572
- Math.round((c + a) * 255),
573
- Math.round((h + a) * 255)
574
- ];
575
- }, Kt = (e) => /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.test(e), Z = (e) => {
576
- const t = e.trim().toLowerCase();
577
- if (t.startsWith("#") || /^[0-9a-f]{3}([0-9a-f]{3})?$/.test(t))
578
- return Kt(t) ? Yt(t) : void 0;
579
- if (t.startsWith("rgb")) {
580
- const o = t.match(
581
- /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*[\d.]+\s*)?\)/
582
- );
583
- return o ? lt(
584
- Number.parseInt(o[1], 10),
585
- Number.parseInt(o[2], 10),
586
- Number.parseInt(o[3], 10)
587
- ) : void 0;
588
- }
589
- if (t.startsWith("hsl")) {
590
- const o = t.match(
591
- /hsla?\(\s*(\d+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*(?:,\s*[\d.]+\s*)?\)/
592
- );
593
- if (!o) return;
594
- const l = Number.parseInt(o[1], 10), r = Number.parseFloat(o[2]) / 100, a = Number.parseFloat(o[3]) / 100, [s, c, h] = Jt(l, r, a);
595
- return lt(s, c, h);
596
- }
597
- const n = Qt[t];
598
- if (n) return n;
599
- }, E = {
600
- circle: "circle",
601
- ellipse: "ellipse",
602
- rect: "rect",
603
- line: "line",
604
- path: "path",
605
- polygon: "polygon",
606
- polyline: "polyline",
607
- stop: "stop"
608
- }, D = {
609
- fill: "fill",
610
- stroke: "stroke"
611
- }, te = {
612
- tiling: [
613
- E.circle,
614
- E.ellipse,
615
- E.rect,
616
- E.line,
617
- E.path,
618
- E.polygon,
619
- E.polyline,
620
- E.stop,
621
- `[${D.fill}]`,
622
- `[${D.stroke}]`
623
- ]
624
- }, ee = (e) => Array.from(
625
- e.querySelectorAll(
626
- te.tiling.map((t) => `*:not(clipPath) > ${t}`).join(", ")
627
- )
628
- ), ne = (e) => {
629
- const t = e.getAttribute(D.stroke);
630
- return t === "none" || !t ? !1 : t;
631
- }, j = (e) => {
632
- if (!(e === "none" || e === "transparent" || e.startsWith("url(")))
633
- return Z(e);
634
- }, oe = (e) => {
635
- const t = ee(e).reduce(
636
- (n, o) => {
637
- const l = o.getAttribute("stop-color"), r = o.getAttribute(D.fill) || "#000", a = ne(o);
638
- if (!l) {
639
- const s = j(r);
640
- s && n.add(s);
641
- }
642
- if (l) {
643
- const s = j(l);
644
- s && n.add(s);
645
- }
646
- if (a) {
647
- const s = j(a);
648
- s && n.add(s);
649
- }
650
- return n;
651
- },
652
- /* @__PURE__ */ new Set()
653
- );
654
- return Array.from(t);
655
- }, re = (e) => {
656
- const t = new q().parseFromString(e, "image/svg+xml").querySelector("svg");
657
- return t ? oe(t) : [];
274
+ //#endregion
275
+ //#region src/baselines/index.ts
276
+ var D = (e) => e === void 0 || e === "flat" ? { type: "flat" } : e === "curved" ? { type: "curved" } : e, O = (e) => {
277
+ if (!e || !e.trim()) throw Error("Custom baseline path must be a non-empty SVG path string");
278
+ if (!e.trim().startsWith("M")) throw Error("Custom baseline path must start with an M (moveto) command");
279
+ }, k = ({ boxDimensions: e, totalTextHeight: t, baseline: n, lineHeight: r, verticalAlignment: i = "centre", lineNumber: a = 0 }) => {
280
+ let { width: o, height: s } = e, c = r - n, l = n;
281
+ switch (i) {
282
+ case "centre":
283
+ l = (s - t) / 2 + r - c;
284
+ break;
285
+ case "bottom": l = s - t + r - c;
286
+ }
287
+ return l += r * C * a, `M 0 ${l} L ${o} ${l}`;
288
+ }, A = ({ boxDimensions: e, baseline: t, textHeight: n, verticalAlignment: r }) => {
289
+ let { height: i } = e, a = n * w, o = n + a, s = t + (r === "top" ? 0 : i / 2 - o / 2), c = s + a;
290
+ return r !== "top" && (c > i || s - n < 0) ? A({
291
+ boxDimensions: e,
292
+ baseline: t,
293
+ textHeight: n,
294
+ verticalAlignment: "top"
295
+ }) : {
296
+ curveTop: s,
297
+ curveBottom: c,
298
+ curveXInset: n / 4
299
+ };
300
+ }, j = ({ boxDimensions: e, baseline: t, textHeight: n, verticalAlignment: r }) => {
301
+ let { width: i } = e, { curveTop: a, curveBottom: o, curveXInset: s } = A({
302
+ boxDimensions: e,
303
+ baseline: t,
304
+ textHeight: n,
305
+ verticalAlignment: r
306
+ }), c = new E(s, o), l = new E(i / 2, a), u = new E(i - s, o), d = i * .2, f = new E(d, a), p = new E(i - d, a);
307
+ return `${`M ${c.toSVGString()}`} ${`Q ${f.toSVGString()} ${l.toSVGString()}`} ${`Q ${p.toSVGString()} ${u.toSVGString()}`}`;
308
+ }, M = (e) => {
309
+ for (let t of [
310
+ "I",
311
+ "l",
312
+ "1"
313
+ ]) {
314
+ let n = e.charToGlyph(t);
315
+ if (n && n.name !== ".notdef") return t;
316
+ }
317
+ return console.error("No standard character found for fixed height calculation. Using \"I\" as default."), "I";
318
+ }, N = 100, P = ({ font: e, boxDimensions: t, physicalSize: n, spacing: r = T }) => {
319
+ let i = n;
320
+ if (i[1] !== t.physicalUnits) throw Error(`Mismatched units between physicalFontSize (${i[1]}) and boxDimensions (${t.physicalUnits})`);
321
+ let { outlineWidth: a } = r, o = M(e), s = e.getPath(o, 0, 0, N).getBoundingBox(), c = s.y2 - s.y1;
322
+ if (a > 0) {
323
+ let e = N * a;
324
+ c += e * 2;
325
+ }
326
+ let l = c / t.height * t.physicalHeight;
327
+ return N * (i[0] / l);
328
+ }, F = ({ font: e, text: t, fontSize: n, spacing: r = T }) => {
329
+ let { outlineWidth: i, letterSpacing: a, letterSpacingOutline: o } = r, s = e.getPath(t, 0, 0, n).getBoundingBox(), c = i ? n * i * 2 : 0, l = i > 0 ? o : a, u = t.length > 1 ? l * n * (t.length - 1) : 0;
330
+ return {
331
+ width: s.x2 - s.x1 + c + u,
332
+ height: s.y2 - s.y1 + c,
333
+ baseline: s.y1 * -1 + c / 2
334
+ };
335
+ }, I = s, te = o, ne = new I().parseFromString("<svg></svg>", "image/svg+xml");
336
+ ne.readyState = "complete";
337
+ //#endregion
338
+ //#region ../svg-helpers/dist/colours/named-colours.mjs
339
+ var re = {
340
+ aliceblue: "#f0f8ff",
341
+ antiquewhite: "#faebd7",
342
+ aqua: "#00ffff",
343
+ aquamarine: "#7fffd4",
344
+ azure: "#f0ffff",
345
+ beige: "#f5f5dc",
346
+ bisque: "#ffe4c4",
347
+ black: "#000000",
348
+ blanchedalmond: "#ffebcd",
349
+ blue: "#0000ff",
350
+ blueviolet: "#8a2be2",
351
+ brown: "#a52a2a",
352
+ burlywood: "#deb887",
353
+ cadetblue: "#5f9ea0",
354
+ chartreuse: "#7fff00",
355
+ chocolate: "#d2691e",
356
+ coral: "#ff7f50",
357
+ cornflowerblue: "#6495ed",
358
+ cornsilk: "#fff8dc",
359
+ crimson: "#dc143c",
360
+ cyan: "#00ffff",
361
+ darkblue: "#00008b",
362
+ darkcyan: "#008b8b",
363
+ darkgoldenrod: "#b8860b",
364
+ darkgray: "#a9a9a9",
365
+ darkgreen: "#006400",
366
+ darkgrey: "#a9a9a9",
367
+ darkkhaki: "#bdb76b",
368
+ darkmagenta: "#8b008b",
369
+ darkolivegreen: "#556b2f",
370
+ darkorange: "#ff8c00",
371
+ darkorchid: "#9932cc",
372
+ darkred: "#8b0000",
373
+ darksalmon: "#e9967a",
374
+ darkseagreen: "#8fbc8f",
375
+ darkslateblue: "#483d8b",
376
+ darkslategray: "#2f4f4f",
377
+ darkslategrey: "#2f4f4f",
378
+ darkturquoise: "#00ced1",
379
+ darkviolet: "#9400d3",
380
+ deeppink: "#ff1493",
381
+ deepskyblue: "#00bfff",
382
+ dimgray: "#696969",
383
+ dimgrey: "#696969",
384
+ dodgerblue: "#1e90ff",
385
+ firebrick: "#b22222",
386
+ floralwhite: "#fffaf0",
387
+ forestgreen: "#228b22",
388
+ fuchsia: "#ff00ff",
389
+ gainsboro: "#dcdcdc",
390
+ ghostwhite: "#f8f8ff",
391
+ gold: "#ffd700",
392
+ goldenrod: "#daa520",
393
+ gray: "#808080",
394
+ green: "#008000",
395
+ greenyellow: "#adff2f",
396
+ grey: "#808080",
397
+ honeydew: "#f0fff0",
398
+ hotpink: "#ff69b4",
399
+ indianred: "#cd5c5c",
400
+ indigo: "#4b0082",
401
+ ivory: "#fffff0",
402
+ khaki: "#f0e68c",
403
+ lavender: "#e6e6fa",
404
+ lavenderblush: "#fff0f5",
405
+ lawngreen: "#7cfc00",
406
+ lemonchiffon: "#fffacd",
407
+ lightblue: "#add8e6",
408
+ lightcoral: "#f08080",
409
+ lightcyan: "#e0ffff",
410
+ lightgoldenrodyellow: "#fafad2",
411
+ lightgray: "#d3d3d3",
412
+ lightgreen: "#90ee90",
413
+ lightgrey: "#d3d3d3",
414
+ lightpink: "#ffb6c1",
415
+ lightsalmon: "#ffa07a",
416
+ lightseagreen: "#20b2aa",
417
+ lightskyblue: "#87cefa",
418
+ lightslategray: "#778899",
419
+ lightslategrey: "#778899",
420
+ lightsteelblue: "#b0c4de",
421
+ lightyellow: "#ffffe0",
422
+ lime: "#00ff00",
423
+ limegreen: "#32cd32",
424
+ linen: "#faf0e6",
425
+ magenta: "#ff00ff",
426
+ maroon: "#800000",
427
+ mediumaquamarine: "#66cdaa",
428
+ mediumblue: "#0000cd",
429
+ mediumorchid: "#ba55d3",
430
+ mediumpurple: "#9370db",
431
+ mediumseagreen: "#3cb371",
432
+ mediumslateblue: "#7b68ee",
433
+ mediumspringgreen: "#00fa9a",
434
+ mediumturquoise: "#48d1cc",
435
+ mediumvioletred: "#c71585",
436
+ midnightblue: "#191970",
437
+ mintcream: "#f5fffa",
438
+ mistyrose: "#ffe4e1",
439
+ moccasin: "#ffe4b5",
440
+ navajowhite: "#ffdead",
441
+ navy: "#000080",
442
+ oldlace: "#fdf5e6",
443
+ olive: "#808000",
444
+ olivedrab: "#6b8e23",
445
+ orange: "#ffa500",
446
+ orangered: "#ff4500",
447
+ orchid: "#da70d6",
448
+ palegoldenrod: "#eee8aa",
449
+ palegreen: "#98fb98",
450
+ paleturquoise: "#afeeee",
451
+ palevioletred: "#db7093",
452
+ papayawhip: "#ffefd5",
453
+ peachpuff: "#ffdab9",
454
+ peru: "#cd853f",
455
+ pink: "#ffc0cb",
456
+ plum: "#dda0dd",
457
+ powderblue: "#b0e0e6",
458
+ purple: "#800080",
459
+ rebeccapurple: "#663399",
460
+ red: "#ff0000",
461
+ rosybrown: "#bc8f8f",
462
+ royalblue: "#4169e1",
463
+ saddlebrown: "#8b4513",
464
+ salmon: "#fa8072",
465
+ sandybrown: "#f4a460",
466
+ seagreen: "#2e8b57",
467
+ seashell: "#fff5ee",
468
+ sienna: "#a0522d",
469
+ silver: "#c0c0c0",
470
+ skyblue: "#87ceeb",
471
+ slateblue: "#6a5acd",
472
+ slategray: "#708090",
473
+ slategrey: "#708090",
474
+ snow: "#fffafa",
475
+ springgreen: "#00ff7f",
476
+ steelblue: "#4682b4",
477
+ tan: "#d2b48c",
478
+ teal: "#008080",
479
+ thistle: "#d8bfd8",
480
+ tomato: "#ff6347",
481
+ turquoise: "#40e0d0",
482
+ violet: "#ee82ee",
483
+ wheat: "#f5deb3",
484
+ white: "#ffffff",
485
+ whitesmoke: "#f5f5f5",
486
+ yellow: "#ffff00",
487
+ yellowgreen: "#9acd32"
488
+ }, ie = (e) => {
489
+ let t = Array.from(e), n = !1;
490
+ return t[0] === "#" && (t.shift(), n = !0), t.length === 3 && (t = t.map((e) => `${e}${e}`)), `${n ? "#" : ""}${t.join("").toLowerCase()}`;
491
+ }, L = (e) => Math.max(0, Math.min(255, Math.round(typeof e == "string" ? Number.parseInt(e, 10) : e))).toString(16).padStart(2, "0"), R = (...e) => {
492
+ let [t, n, r] = Array.isArray(e[0]) ? e[0] : e;
493
+ return `#${L(t)}${L(n)}${L(r)}`;
494
+ }, ae = (e, t, n) => {
495
+ if (t === 0) {
496
+ let e = Math.round(n * 255);
497
+ return [
498
+ e,
499
+ e,
500
+ e
501
+ ];
502
+ }
503
+ let r = (e % 360 + 360) % 360, i = (1 - Math.abs(2 * n - 1)) * t, a = i * (1 - Math.abs(r / 60 % 2 - 1)), o = n - i / 2, s = 0, c = 0, l = 0;
504
+ return r < 60 ? (s = i, c = a, l = 0) : r < 120 ? (s = a, c = i, l = 0) : r < 180 ? (s = 0, c = i, l = a) : r < 240 ? (s = 0, c = a, l = i) : r < 300 ? (s = a, c = 0, l = i) : (s = i, c = 0, l = a), [
505
+ Math.round((s + o) * 255),
506
+ Math.round((c + o) * 255),
507
+ Math.round((l + o) * 255)
508
+ ];
509
+ }, oe = (e) => /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.test(e), z = (e) => {
510
+ let t = e.trim().toLowerCase();
511
+ if (t.startsWith("#") || /^[0-9a-f]{3}([0-9a-f]{3})?$/.test(t)) return oe(t) ? ie(t) : void 0;
512
+ if (t.startsWith("rgb")) {
513
+ let e = t.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*[\d.]+\s*)?\)/);
514
+ return e ? R(Number.parseInt(e[1], 10), Number.parseInt(e[2], 10), Number.parseInt(e[3], 10)) : void 0;
515
+ }
516
+ if (t.startsWith("hsl")) {
517
+ let e = t.match(/hsla?\(\s*(\d+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*(?:,\s*[\d.]+\s*)?\)/);
518
+ if (!e) return;
519
+ let [n, r, i] = ae(Number.parseInt(e[1], 10), Number.parseFloat(e[2]) / 100, Number.parseFloat(e[3]) / 100);
520
+ return R(n, r, i);
521
+ }
522
+ let n = re[t];
523
+ if (n) return n;
524
+ }, B = {
525
+ svg: "svg",
526
+ circle: "circle",
527
+ desc: "desc",
528
+ ellipse: "ellipse",
529
+ rect: "rect",
530
+ line: "line",
531
+ path: "path",
532
+ polygon: "polygon",
533
+ polyline: "polyline",
534
+ stop: "stop"
535
+ }, V = {
536
+ fill: "fill",
537
+ stroke: "stroke"
538
+ }, se = {
539
+ tiling: [
540
+ B.circle,
541
+ B.ellipse,
542
+ B.rect,
543
+ B.line,
544
+ B.path,
545
+ B.polygon,
546
+ B.polyline,
547
+ B.stop,
548
+ `[${V.fill}]`,
549
+ `[${V.stroke}]`
550
+ ],
551
+ nonTiling: [
552
+ B.circle,
553
+ B.desc,
554
+ B.ellipse,
555
+ B.rect,
556
+ B.line,
557
+ B.path,
558
+ B.polygon,
559
+ B.polyline,
560
+ B.stop,
561
+ `[${V.fill}]`,
562
+ `[${V.stroke}]`
563
+ ]
564
+ }, ce = (e) => Array.from(e.querySelectorAll(se.tiling.map((e) => `*:not(clipPath) > ${e}`).join(", "))), le = (e) => {
565
+ let t = e.getAttribute(V.stroke);
566
+ return t === "none" || !t ? !1 : t;
567
+ }, H = (e) => {
568
+ if (!(e === "none" || e === "transparent" || e.startsWith("url("))) return z(e);
569
+ }, ue = (e) => {
570
+ let t = ce(e).reduce((e, t) => {
571
+ let n = t.getAttribute("stop-color"), r = t.getAttribute(V.fill) || "#000", i = le(t);
572
+ if (r && !n) {
573
+ let t = H(r);
574
+ t && e.add(t);
575
+ }
576
+ if (n) {
577
+ let t = H(n);
578
+ t && e.add(t);
579
+ }
580
+ if (i) {
581
+ let t = H(i);
582
+ t && e.add(t);
583
+ }
584
+ return e;
585
+ }, /* @__PURE__ */ new Set());
586
+ return Array.from(t);
587
+ }, de = (e) => {
588
+ let t = new I().parseFromString(e, "image/svg+xml").querySelector("svg");
589
+ return t ? ue(t) : [];
658
590
  };
659
- function bt(e) {
660
- const t = e.trim(), n = t.startsWith("<svg") || t.startsWith("<?xml"), o = n ? t : `<svg>${t}</svg>`;
661
- return { doc: new q().parseFromString(o, "image/svg+xml"), wasWrapped: !n };
591
+ //#endregion
592
+ //#region src/glyph/svg-glyph-converter.ts
593
+ function U(e) {
594
+ let t = e.trim(), n = t.startsWith("<svg") || t.startsWith("<?xml"), r = n ? t : `<svg>${t}</svg>`;
595
+ return {
596
+ doc: new I().parseFromString(r, "image/svg+xml"),
597
+ wasWrapped: !n
598
+ };
662
599
  }
663
- function wt(e, t) {
664
- const n = e.querySelector("svg");
665
- return n ? t ? n.innerHTML : n.outerHTML : "";
600
+ function W(e, t) {
601
+ let n = e.querySelector("svg");
602
+ return n ? t ? n.innerHTML : n.outerHTML : "";
666
603
  }
667
- function $e(e) {
668
- const { svgGlyphs: t } = e;
669
- if (!t || t.size === 0)
670
- return [];
671
- const n = /* @__PURE__ */ new Set();
672
- for (const [, o] of t)
673
- for (const l of re(o.svg))
674
- n.add(l);
675
- return Array.from(n);
604
+ function fe(e) {
605
+ let { svgGlyphs: t } = e;
606
+ if (!t || t.size === 0) return [];
607
+ let n = /* @__PURE__ */ new Set();
608
+ for (let [, e] of t) for (let t of de(e.svg)) n.add(t);
609
+ return Array.from(n);
676
610
  }
677
- function se(e) {
678
- return !!e && e !== "none" && e !== "transparent" && !e.startsWith("url(");
611
+ function pe(e) {
612
+ return !!e && e !== "none" && e !== "transparent" && !e.startsWith("url(");
679
613
  }
680
- function ae(e) {
681
- const n = new q().parseFromString(e, "image/svg+xml").querySelector("svg");
682
- return n ? n.innerHTML.trim() : "";
614
+ function me(e) {
615
+ let t = new I().parseFromString(e, "image/svg+xml").querySelector("svg");
616
+ return t ? t.innerHTML.trim() : "";
683
617
  }
684
- const ie = ["fill", "stroke", "clip-path", "mask", "filter"];
685
- function ce(e, t) {
686
- const { doc: n, wasWrapped: o } = bt(e), l = /* @__PURE__ */ new Map();
687
- for (const r of n.querySelectorAll("[id]")) {
688
- const a = r.getAttribute("id");
689
- if (!a) continue;
690
- const s = `${t}-${a}`;
691
- l.set(a, s), r.setAttribute("id", s);
692
- }
693
- if (l.size === 0)
694
- return e;
695
- for (const r of ie)
696
- for (const a of n.querySelectorAll(`[${r}]`)) {
697
- const s = a.getAttribute(r);
698
- if (s) {
699
- const c = s.replace(/url\(#([^)]+)\)/g, (h, i) => {
700
- const b = l.get(i);
701
- return b ? `url(#${b})` : `url(#${i})`;
702
- });
703
- c !== s && a.setAttribute(r, c);
704
- }
705
- }
706
- for (const r of n.querySelectorAll("[href], [xlink\\:href]"))
707
- for (const a of ["href", "xlink:href"]) {
708
- const s = r.getAttribute(a);
709
- if (s?.startsWith("#")) {
710
- const c = s.slice(1), h = l.get(c);
711
- h && r.setAttribute(a, `#${h}`);
712
- }
713
- }
714
- return wt(n, o);
618
+ var he = [
619
+ "fill",
620
+ "stroke",
621
+ "clip-path",
622
+ "mask",
623
+ "filter"
624
+ ];
625
+ function ge(e, t) {
626
+ let { doc: n, wasWrapped: r } = U(e), i = /* @__PURE__ */ new Map();
627
+ for (let e of n.querySelectorAll("[id]")) {
628
+ let n = e.getAttribute("id");
629
+ if (!n) continue;
630
+ let r = `${t}-${n}`;
631
+ i.set(n, r), e.setAttribute("id", r);
632
+ }
633
+ if (i.size === 0) return e;
634
+ for (let e of he) for (let t of n.querySelectorAll(`[${e}]`)) {
635
+ let n = t.getAttribute(e);
636
+ if (n) {
637
+ let r = n.replace(/url\(#([^)]+)\)/g, (e, t) => {
638
+ let n = i.get(t);
639
+ return n ? `url(#${n})` : `url(#${t})`;
640
+ });
641
+ r !== n && t.setAttribute(e, r);
642
+ }
643
+ }
644
+ for (let e of n.querySelectorAll("[href], [xlink\\:href]")) for (let t of ["href", "xlink:href"]) {
645
+ let n = e.getAttribute(t);
646
+ if (n?.startsWith("#")) {
647
+ let r = n.slice(1), a = i.get(r);
648
+ a && e.setAttribute(t, `#${a}`);
649
+ }
650
+ }
651
+ return W(n, r);
715
652
  }
716
- const le = ["fill", "stroke", "stop-color"], fe = ["path", "rect", "circle", "ellipse", "polygon", "polyline", "text"];
717
- function he(e, t) {
718
- const { doc: n, wasWrapped: o } = bt(e), l = {};
719
- for (const [a, s] of Object.entries(t))
720
- l[Z(a) ?? a.toLowerCase()] = s;
721
- for (const a of le)
722
- for (const s of n.querySelectorAll(`[${a}]`)) {
723
- const c = s.getAttribute(a);
724
- if (!c || !se(c)) continue;
725
- const h = Z(c), i = h ? l[h] : void 0;
726
- i && s.setAttribute(a, i.hex);
727
- }
728
- const r = l["#000000"];
729
- if (r) {
730
- const a = fe.map((s) => `${s}:not([fill])`).join(", ");
731
- for (const s of n.querySelectorAll(a))
732
- s.setAttribute("fill", r.hex);
733
- }
734
- return wt(n, o);
653
+ var _e = [
654
+ "fill",
655
+ "stroke",
656
+ "stop-color"
657
+ ], ve = [
658
+ "path",
659
+ "rect",
660
+ "circle",
661
+ "ellipse",
662
+ "polygon",
663
+ "polyline",
664
+ "text"
665
+ ];
666
+ function ye(e, t) {
667
+ let { doc: n, wasWrapped: r } = U(e), i = {};
668
+ for (let [e, n] of Object.entries(t)) i[z(e) ?? e.toLowerCase()] = n;
669
+ for (let e of _e) for (let t of n.querySelectorAll(`[${e}]`)) {
670
+ let n = t.getAttribute(e);
671
+ if (!n || !pe(n)) continue;
672
+ let r = z(n), a = r ? i[r] : void 0;
673
+ a && t.setAttribute(e, a.hex);
674
+ }
675
+ let a = i["#000000"];
676
+ if (a) {
677
+ let e = ve.map((e) => `${e}:not([fill])`).join(", ");
678
+ for (let t of n.querySelectorAll(e)) t.setAttribute("fill", a.hex);
679
+ }
680
+ return W(n, r);
735
681
  }
736
- const de = (e = [1, 0, 0, 1, 0, 0]) => {
737
- const t = `matrix(${e.join(",")})`, n = new jt(t);
738
- if (!n)
739
- throw new Error("Your browser does not support matrices");
740
- return n;
741
- };
742
- function ge(e) {
743
- return e.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&apos;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
682
+ //#endregion
683
+ //#region src/helpers/xml.ts
684
+ function be(e) {
685
+ return e.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&apos;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
744
686
  }
745
- const ft = (e, t, n) => e / n * t, ue = ({
746
- font: e,
747
- baselinePath: t,
748
- text: n,
749
- fontSize: o,
750
- spacing: l = G,
751
- horizontalAlignment: r = "centre",
752
- colourMap: a
753
- }) => {
754
- const { outlineWidth: s, letterSpacing: c, letterSpacingOutline: h } = l, i = new Pt(t), b = s ? o * s * 2 : 0, p = i.getTotalLength(), u = e.getPaths(n, 0, 0, o, { drawSVG: !1 }), d = e.getPath(n, 0, 0, o, { drawSVG: !1 }).getBoundingBox(), g = d.x1 - b / 2, m = d.x2 + b / 2 - g, y = s > 0 ? h : c;
755
- let $ = y ? y * o : 0;
756
- r === "distributed" && ($ = n.length === 1 ? 0 : (p - m) / (n.length - 1));
757
- const v = $ * (n.length - 1), M = m + v;
758
- let S = 0 - g;
759
- r === "centre" ? S = (p - M) / 2 - g : r === "right" && (S = p - m - g - v);
760
- const A = [];
761
- for (let k = 0; k < u.length; k++) {
762
- const x = u[k], F = x.getBoundingBox(), T = e.charToGlyph(n[k]), { advanceWidth: U } = T;
763
- if (!U)
764
- throw new Error(
765
- `No advance width for character: ${n[k]} in font ${e.names.fontFamily}`
766
- );
767
- const { x1: xt, x2: vt } = T.getBoundingBox(), $t = ft(
768
- U,
769
- o,
770
- e.unitsPerEm
771
- ), Y = ft(vt - xt, o, e.unitsPerEm);
772
- let I = S + F.x1;
773
- if (k > 0 && (I += $ * k), I + Y > p)
774
- throw new Error(
775
- `TOO_WIDE: character "${n[k]}" at index ${k} exceeds baseline path length (${Math.round(I + Y)} > ${Math.round(p)})`
776
- );
777
- const St = I + $t / 2, J = i.getTangentAtLength(St), O = Math.atan2(J.y, J.x) * 180 / Math.PI, K = i.getPointAtLength(I), kt = K.x, Mt = K.y, tt = F.x2 - F.x1, Ft = new P(F.x1 + tt / 2, 0), et = _t(
778
- new P(F.x1, 0),
779
- O,
780
- Ft
781
- ), N = kt - et.X, _ = Mt - et.Y;
782
- let B = de();
783
- B = B.translate(N, _);
784
- let V;
785
- if (O) {
786
- const C = F.x1 + tt / 2;
787
- B = B.translate(C, 0), B = B.rotate(O), B = B.translate(-C, 0), V = `translate(${N} ${_}) translate(${C} 0) rotate(${O}) translate(${-C} 0)`;
788
- } else
789
- V = `translate(${N} ${_})`;
790
- let L = x.toPathData(2);
791
- L.length && !L.endsWith("Z") && (L += "Z", L = L.replace(/M/g, "ZM"), L = L.substring(1));
792
- let H;
793
- if (e.svgGlyphs) {
794
- const C = e.svgGlyphs.get(T.index);
795
- if (C) {
796
- let W = ae(C.svg);
797
- W = ce(W, `g${T.index}-${k}`), a && (W = he(W, a)), H = {
798
- content: W,
799
- viewBox: C.viewbox,
800
- x: F.x1,
801
- y: F.y1,
802
- width: F.x2 - F.x1,
803
- height: F.y2 - F.y1,
804
- glyphIndex: T.index
805
- };
806
- }
807
- }
808
- A.push({
809
- path: x,
810
- matrix: B,
811
- attributes: {
812
- d: L,
813
- "data-character": ge(n[k]),
814
- transform: V
815
- },
816
- glyphData: {
817
- index: T.index,
818
- bbox: F
819
- },
820
- ...H ? { svgGlyph: H } : {}
821
- });
822
- }
823
- return A;
824
- }, ht = { hex: "#FFFFFF" }, Q = (e, t) => {
825
- const n = `data-${e}-colour-url`, o = [`${e}="${t.hex}"`];
826
- return t.reference && o.push(`${n}="${t.reference}"`), o.join(" ");
827
- }, dt = (e, t) => {
828
- const { attributes: n, svgGlyph: o } = e;
829
- return o ? `<g transform="${n.transform}" data-character="${n["data-character"]}"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="${o.viewBox}" width="${o.width}" height="${o.height}" x="${o.x}" y="${o.y}" data-glyph-index="${o.glyphIndex}">${o.content}</svg></g>` : `<path d="${n.d}" ${Q("fill", t)} transform="${n.transform}" data-character="${n["data-character"]}"/>`;
830
- }, pe = ({
831
- boxDimensions: e,
832
- paths: t,
833
- spacing: n = G,
834
- fontSize: o = 0,
835
- fillColour: l = ht,
836
- strokeColour: r = ht
837
- }) => {
838
- const { width: a, height: s } = e, { outlineWidth: c } = n, h = c > 0 && o > 0;
839
- let i;
840
- if (h) {
841
- const p = o * c * 2, u = t.filter((d) => !d.svgGlyph).map(
842
- ({ attributes: d }) => `<path d="${d.d}" ${Q("fill", r)} ${Q("stroke", r)} stroke-width="${p}" stroke-linejoin="round" transform="${d.transform}" data-character="${d["data-character"]}"/>`
843
- ).join(`
844
- `), f = t.map((d) => dt(d, l)).join(`
845
- `);
846
- i = `${u}
847
- ${f}`;
848
- } else
849
- i = t.map((p) => dt(p, l)).join(`
850
- `);
851
- const b = i ? `
852
- ${i}
853
- ` : "";
854
- return `<svg xmlns="http://www.w3.org/2000/svg" width="${a}" height="${s}" viewBox="0 0 ${a} ${s}">${b}</svg>`;
855
- }, gt = (e) => {
856
- const {
857
- text: t,
858
- font: n,
859
- physicalSize: o,
860
- fontSize: l,
861
- boxDimensions: r,
862
- spacing: a = G,
863
- verticalAlignment: s = "centre",
864
- baseline: c = "flat",
865
- horizontalAlignment: h = "left",
866
- fillColour: i = { hex: "#FFFFFF" },
867
- strokeColour: b = { hex: "#FFFFFF" },
868
- colourMap: p
869
- } = e, { width: u, height: f, physicalWidth: d, physicalHeight: g } = r;
870
- if (u <= 0 || f <= 0)
871
- throw new Error(
872
- `boxDimensions width and height must be positive (got ${u}x${f})`
873
- );
874
- if (d <= 0 || g <= 0)
875
- throw new Error(
876
- `boxDimensions physicalWidth and physicalHeight must be positive (got ${d}x${g})`
877
- );
878
- if (o[0] <= 0)
879
- throw new Error(
880
- `physicalSize height must be positive (got ${o[0]})`
881
- );
882
- const w = l ?? Rt({
883
- font: n,
884
- boxDimensions: r,
885
- physicalSize: o,
886
- spacing: a
887
- }), m = Vt(c);
888
- let y = t.split(`
889
- `).filter((x) => x.length > 0);
890
- y.length || (y = [""]), (m.type === "curved" || m.type === "custom") && (y = [y.join("")]);
891
- const $ = y.map(
892
- (x) => ct({ font: n, text: x, fontSize: w, spacing: a })
893
- ), v = Math.max(...$.map((x) => x.baseline)), M = Math.max(...$.map((x) => x.height - x.baseline)), S = v + M, A = y.length === 1 ? S : S + S * (y.length - 1) * pt, k = [];
894
- for (let x = 0; x < y.length; x++) {
895
- let F;
896
- switch (m.type) {
897
- case "custom":
898
- Ht(m.path), F = m.path;
899
- break;
900
- case "curved": {
901
- const U = ct({
902
- font: n,
903
- text: yt(n),
904
- fontSize: w,
905
- spacing: a
906
- });
907
- F = mt({
908
- boxDimensions: r,
909
- baseline: U.baseline,
910
- textHeight: U.height,
911
- verticalAlignment: s
912
- });
913
- break;
914
- }
915
- case "flat":
916
- F = zt({
917
- boxDimensions: r,
918
- totalTextHeight: A,
919
- baseline: v,
920
- lineHeight: S,
921
- verticalAlignment: s,
922
- lineNumber: x
923
- });
924
- break;
925
- }
926
- const T = ue({
927
- font: n,
928
- baselinePath: F,
929
- text: y[x],
930
- fontSize: w,
931
- spacing: a,
932
- horizontalAlignment: h,
933
- colourMap: p
934
- });
935
- k.push(...T);
936
- }
937
- return pe({
938
- boxDimensions: r,
939
- paths: k,
940
- spacing: a,
941
- fontSize: w,
942
- fillColour: i,
943
- strokeColour: b
944
- });
945
- }, Se = async (e) => {
946
- const { fontUrl: t, fontSizeFallback: n, ...o } = e, l = !!o.colourMap, r = await Dt(t, l);
947
- try {
948
- return gt({ ...o, font: r });
949
- } catch (a) {
950
- if (n != null && a instanceof Error && a.message.startsWith("TOO_WIDE"))
951
- return gt({ ...o, font: r, fontSize: n });
952
- throw a;
953
- }
954
- };
955
- export {
956
- qt as DEFAULT_OUTLINE_FACTOR,
957
- G as DEFAULT_SPACING,
958
- pt as LINE_HEIGHT,
959
- mt as generateCurvedBaseline,
960
- zt as generateFlatBaseline,
961
- ve as getFontCache,
962
- $e as getFontColours,
963
- Rt as getFontSizeFromPhysicalSize,
964
- Se as getRenderedText,
965
- ct as getTextMetricsAtFontSize,
966
- Dt as loadFont,
967
- Vt as normaliseBaselineOption,
968
- gt as renderText,
969
- Ht as validateCustomBaselinePath
687
+ //#endregion
688
+ //#region src/rendering/index.ts
689
+ var G = (e, t, n) => e / n * t, xe = ({ font: e, baselinePath: t, text: n, fontSize: r, spacing: i = T, horizontalAlignment: a = "centre", colourMap: o }) => {
690
+ let { outlineWidth: s, letterSpacing: l, letterSpacingOutline: u } = i, d = new c(t), f = s ? r * s * 2 : 0, p = d.getTotalLength(), m = e.getPaths(n, 0, 0, r, { drawSVG: !1 }), h = e.getPath(n, 0, 0, r, { drawSVG: !1 }).getBoundingBox(), g = h.x1 - f / 2, _ = h.x2 + f / 2 - g, v = s > 0 ? u : l, y = v ? v * r : 0;
691
+ a === "distributed" && (y = n.length === 1 ? 0 : (p - _) / (n.length - 1));
692
+ let b = y * (n.length - 1), x = _ + b, S = 0 - g;
693
+ a === "centre" ? S = (p - x) / 2 - g : a === "right" && (S = p - _ - g - b);
694
+ let C = [];
695
+ for (let t = 0; t < m.length; t++) {
696
+ let i = m[t], a = i.getBoundingBox(), s = e.charToGlyph(n[t]), { advanceWidth: c } = s;
697
+ if (!c) throw Error(`No advance width for character: ${n[t]} in font ${e.names.fontFamily}`);
698
+ let { x1: l, x2: u } = s.getBoundingBox(), f = G(c, r, e.unitsPerEm), h = G(u - l, r, e.unitsPerEm), g = S + a.x1;
699
+ if (t > 0 && (g += y * t), g + h > p) throw Error(`TOO_WIDE: character "${n[t]}" at index ${t} exceeds baseline path length (${Math.round(g + h)} > ${Math.round(p)})`);
700
+ let _ = g + f / 2, v = d.getTangentAtLength(_), b = Math.atan2(v.y, v.x) * 180 / Math.PI, x = d.getPointAtLength(g), w = x.x, T = x.y, D = a.x2 - a.x1, O = new E(a.x1 + D / 2, 0), k = ee(new E(a.x1, 0), b, O), A = w - k.X, j = T - k.Y, M = new te();
701
+ M = M.translate(A, j);
702
+ let N;
703
+ if (b) {
704
+ let e = a.x1 + D / 2;
705
+ M = M.translate(e, 0), M = M.rotate(b), M = M.translate(-e, 0), N = `translate(${A} ${j}) translate(${e} 0) rotate(${b}) translate(${-e} 0)`;
706
+ } else N = `translate(${A} ${j})`;
707
+ let P = i.toPathData(2);
708
+ P.length && !P.endsWith("Z") && (P += "Z", P = P.replace(/M/g, "ZM"), P = P.substring(1));
709
+ let F;
710
+ if (e.svgGlyphs) {
711
+ let n = e.svgGlyphs.get(s.index);
712
+ if (n) {
713
+ let e = me(n.svg);
714
+ e = ge(e, `g${s.index}-${t}`), o && (e = ye(e, o)), F = {
715
+ content: e,
716
+ viewBox: n.viewbox,
717
+ x: a.x1,
718
+ y: a.y1,
719
+ width: a.x2 - a.x1,
720
+ height: a.y2 - a.y1,
721
+ glyphIndex: s.index
722
+ };
723
+ }
724
+ }
725
+ C.push({
726
+ path: i,
727
+ matrix: M,
728
+ attributes: {
729
+ d: P,
730
+ "data-character": be(n[t]),
731
+ transform: N
732
+ },
733
+ glyphData: {
734
+ index: s.index,
735
+ bbox: a
736
+ },
737
+ ...F ? { svgGlyph: F } : {}
738
+ });
739
+ }
740
+ return C;
741
+ }, K = { hex: "#FFFFFF" }, q = (e, t) => {
742
+ let n = `data-${e}-colour-url`, r = [`${e}="${t.hex}"`];
743
+ return t.reference && r.push(`${n}="${t.reference}"`), r.join(" ");
744
+ }, J = (e, t) => {
745
+ let { attributes: n, svgGlyph: r } = e;
746
+ return r ? `<g transform="${n.transform}" data-character="${n["data-character"]}"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="${r.viewBox}" width="${r.width}" height="${r.height}" x="${r.x}" y="${r.y}" data-glyph-index="${r.glyphIndex}">${r.content}</svg></g>` : `<path d="${n.d}" ${q("fill", t)} transform="${n.transform}" data-character="${n["data-character"]}"/>`;
747
+ }, Se = ({ boxDimensions: e, paths: t, spacing: n = T, fontSize: r = 0, fillColour: i = K, strokeColour: a = K }) => {
748
+ let { width: o, height: s } = e, { outlineWidth: c } = n, l = c > 0 && r > 0, u;
749
+ if (l) {
750
+ let e = r * c * 2;
751
+ u = `${t.filter((e) => !e.svgGlyph).map(({ attributes: t }) => `<path d="${t.d}" ${q("fill", a)} ${q("stroke", a)} stroke-width="${e}" stroke-linejoin="round" transform="${t.transform}" data-character="${t["data-character"]}"/>`).join("\n ")}\n ${t.map((e) => J(e, i)).join("\n ")}`;
752
+ } else u = t.map((e) => J(e, i)).join("\n ");
753
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${o}" height="${s}" viewBox="0 0 ${o} ${s}">${u ? `\n ${u}\n` : ""}</svg>`;
754
+ }, Y = (e) => {
755
+ let { text: t, font: n, physicalSize: r, fontSize: i, boxDimensions: a, spacing: o = T, verticalAlignment: s = "centre", baseline: c = "flat", horizontalAlignment: l = "left", fillColour: u = { hex: "#FFFFFF" }, strokeColour: d = { hex: "#FFFFFF" }, colourMap: f } = e, { width: p, height: m, physicalWidth: h, physicalHeight: g } = a;
756
+ if (p <= 0 || m <= 0) throw Error(`boxDimensions width and height must be positive (got ${p}x${m})`);
757
+ if (h <= 0 || g <= 0) throw Error(`boxDimensions physicalWidth and physicalHeight must be positive (got ${h}x${g})`);
758
+ if (r[0] <= 0) throw Error(`physicalSize height must be positive (got ${r[0]})`);
759
+ let _ = i ?? P({
760
+ font: n,
761
+ boxDimensions: a,
762
+ physicalSize: r,
763
+ spacing: o
764
+ }), v = D(c), y = t.split("\n").filter((e) => e.length > 0);
765
+ y.length || (y = [""]), (v.type === "curved" || v.type === "custom") && (y = [y.join("")]);
766
+ let b = y.map((e) => F({
767
+ font: n,
768
+ text: e,
769
+ fontSize: _,
770
+ spacing: o
771
+ })), x = Math.max(...b.map((e) => e.baseline)), S = x + Math.max(...b.map((e) => e.height - e.baseline)), w = y.length === 1 ? S : S + S * (y.length - 1) * C, E = [];
772
+ for (let e = 0; e < y.length; e++) {
773
+ let t;
774
+ switch (v.type) {
775
+ case "custom":
776
+ O(v.path), t = v.path;
777
+ break;
778
+ case "curved": {
779
+ let e = F({
780
+ font: n,
781
+ text: M(n),
782
+ fontSize: _,
783
+ spacing: o
784
+ });
785
+ t = j({
786
+ boxDimensions: a,
787
+ baseline: e.baseline,
788
+ textHeight: e.height,
789
+ verticalAlignment: s
790
+ });
791
+ break;
792
+ }
793
+ case "flat": t = k({
794
+ boxDimensions: a,
795
+ totalTextHeight: w,
796
+ baseline: x,
797
+ lineHeight: S,
798
+ verticalAlignment: s,
799
+ lineNumber: e
800
+ });
801
+ }
802
+ let r = xe({
803
+ font: n,
804
+ baselinePath: t,
805
+ text: y[e],
806
+ fontSize: _,
807
+ spacing: o,
808
+ horizontalAlignment: l,
809
+ colourMap: f
810
+ });
811
+ E.push(...r);
812
+ }
813
+ return Se({
814
+ boxDimensions: a,
815
+ paths: E,
816
+ spacing: o,
817
+ fontSize: _,
818
+ fillColour: u,
819
+ strokeColour: d
820
+ });
821
+ }, X = 100, Ce = (e) => {
822
+ let t = e.split("\n").filter((e) => e.length > 0);
823
+ return t.length ? t : [""];
824
+ }, we = (e) => e.split("\n").filter((e) => e.length > 0).join(""), Te = (e, t, n, r, i, a) => {
825
+ let o = F({
826
+ font: e,
827
+ text: M(e),
828
+ fontSize: n,
829
+ spacing: r
830
+ }), s = {
831
+ boxDimensions: i,
832
+ baseline: o.baseline,
833
+ textHeight: o.height,
834
+ verticalAlignment: a
835
+ }, l = new c(j(s)).getTotalLength(), { curveTop: u, curveBottom: d } = A(s), f = F({
836
+ font: e,
837
+ text: t,
838
+ fontSize: n,
839
+ spacing: r
840
+ }), p = u - f.baseline, m = d + (f.height - f.baseline);
841
+ return {
842
+ width: f.width <= l,
843
+ height: p >= 0 && m <= i.height
844
+ };
845
+ }, Z = (e) => e.width && e.height, Q = (e) => e.width ? "height" : "width", Ee = .01, De = 60, Oe = ({ font: e, text: t, boxDimensions: n, spacing: r, verticalAlignment: i, minFontSize: a, maxFontSize: o }) => {
846
+ let s = we(t);
847
+ if (!s.length) return {
848
+ fontSize: o,
849
+ fits: !0,
850
+ boundBy: "requestedSize"
851
+ };
852
+ let c = (t) => Te(e, s, t, r, n, i), l = c(a);
853
+ if (!Z(l)) return {
854
+ fontSize: a,
855
+ fits: !1,
856
+ boundBy: Q(l)
857
+ };
858
+ if (Z(c(o))) return {
859
+ fontSize: o,
860
+ fits: !0,
861
+ boundBy: "requestedSize"
862
+ };
863
+ let u = a, d = o, f = 0;
864
+ for (; d - u > Ee && f < De;) {
865
+ let e = (u + d) / 2;
866
+ Z(c(e)) ? u = e : d = e, f++;
867
+ }
868
+ return {
869
+ fontSize: u,
870
+ fits: !0,
871
+ boundBy: Q(c(d))
872
+ };
873
+ }, $ = (e) => {
874
+ let { font: t, text: n, boxDimensions: r, size: i, spacing: a = T, baseline: o = "flat", verticalAlignment: s = "centre" } = e, l = i.mode === "fitToBox" ? i.maxFontSize : i.mode === "fontSize" ? i.fontSize : P({
875
+ font: t,
876
+ boxDimensions: r,
877
+ physicalSize: i.physicalSize,
878
+ spacing: a
879
+ });
880
+ if (!n.length) return {
881
+ fontSize: l,
882
+ fits: !0,
883
+ boundBy: "requestedSize"
884
+ };
885
+ let u = D(o);
886
+ if (u.type === "curved") return Oe({
887
+ font: t,
888
+ text: n,
889
+ boxDimensions: r,
890
+ spacing: a,
891
+ verticalAlignment: s,
892
+ minFontSize: i.mode === "fitToBox" ? i.minFontSize : l,
893
+ maxFontSize: l
894
+ });
895
+ let d = Ce(n);
896
+ u.type === "custom" && (d = [d.join("")]);
897
+ let f = d.map((e) => F({
898
+ font: t,
899
+ text: e,
900
+ fontSize: X,
901
+ spacing: a
902
+ })), p = Math.max(...f.map((e) => e.baseline)) + Math.max(...f.map((e) => e.height - e.baseline)), m = d.length === 1 ? p : p + p * (d.length - 1) * C, h = Math.max(...f.map((e) => e.width)), g = (u.type === "custom" ? new c(u.path).getTotalLength() : r.width) / h, _ = r.height / m, v = g <= _ ? "width" : "height", y = X * Math.min(g, _);
903
+ return i.mode === "fitToBox" ? y < i.minFontSize ? {
904
+ fontSize: i.minFontSize,
905
+ fits: !1,
906
+ boundBy: v
907
+ } : y > i.maxFontSize ? {
908
+ fontSize: i.maxFontSize,
909
+ fits: !0,
910
+ boundBy: "requestedSize"
911
+ } : {
912
+ fontSize: y,
913
+ fits: !0,
914
+ boundBy: v
915
+ } : l <= y ? {
916
+ fontSize: l,
917
+ fits: !0,
918
+ boundBy: "requestedSize"
919
+ } : {
920
+ fontSize: l,
921
+ fits: !1,
922
+ boundBy: v
923
+ };
924
+ }, ke = (e) => {
925
+ let t = e.text, n = t, r = 0, i = 0;
926
+ for (;;) {
927
+ let a = $({
928
+ ...e,
929
+ text: n
930
+ });
931
+ if (a.fits) return {
932
+ ...a,
933
+ text: n,
934
+ truncated: n !== t,
935
+ linesDropped: r,
936
+ charactersRemoved: i
937
+ };
938
+ let o = n.split("\n");
939
+ if (o.length > 1) n = o.slice(0, -1).join("\n"), r += 1;
940
+ else {
941
+ let e = n.slice(0, -1).trim();
942
+ i += n.length - e.length, n = e;
943
+ }
944
+ }
945
+ }, Ae = async (e) => {
946
+ let { fontUrl: t, fontSizeFallback: n, ...r } = e, i = await x(t, !!r.colourMap);
947
+ try {
948
+ return Y({
949
+ ...r,
950
+ font: i
951
+ });
952
+ } catch (e) {
953
+ if (n != null && e instanceof Error && e.message.startsWith("TOO_WIDE")) return Y({
954
+ ...r,
955
+ font: i,
956
+ fontSize: n
957
+ });
958
+ throw e;
959
+ }
970
960
  };
961
+ //#endregion
962
+ export { S as DEFAULT_OUTLINE_FACTOR, T as DEFAULT_SPACING, C as LINE_HEIGHT, ke as fitAndTruncateTextToBox, j as generateCurvedBaseline, k as generateFlatBaseline, p as getFontCache, fe as getFontColours, P as getFontSizeFromPhysicalSize, $ as getFontSizeToFitBox, Ae as getRenderedText, F as getTextMetricsAtFontSize, x as loadFont, D as normaliseBaselineOption, Y as renderText, O as validateCustomBaselinePath };