@mlightcad/mtext-renderer 0.13.2 → 0.13.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -30300,7 +30300,7 @@ class Oo {
30300
30300
  const Yi = /* @__PURE__ */ new I.Vector3(), Xi = /* @__PURE__ */ new I.Vector3(), Zi = /* @__PURE__ */ new I.Vector3();
30301
30301
  class V0 {
30302
30302
  constructor(e = {}) {
30303
- this.workers = [], this.inFlightPerWorker = [], this.pendingRequests = /* @__PURE__ */ new Map(), this.requestId = 0, this.readyPromise = null, this.poolSyncedFonts = /* @__PURE__ */ new Set(), this.poolFontSyncInFlight = /* @__PURE__ */ new Map(), this.poolFontLoadedDispatched = /* @__PURE__ */ new Set(), this.poolSize = e.poolSize ?? Math.max(
30303
+ this.workers = [], this.inFlightPerWorker = [], this.pendingRequests = /* @__PURE__ */ new Map(), this.requestId = 0, this.readyPromise = null, this.fontsPerWorker = [], this.poolFontLoadedDispatched = /* @__PURE__ */ new Set(), this.poolSize = e.poolSize ?? Math.max(
30304
30304
  1,
30305
30305
  navigator.hardwareConcurrency ? Math.min(4, navigator.hardwareConcurrency) : 2
30306
30306
  ), this.defaultStyleManager = new Oo();
@@ -30310,7 +30310,7 @@ class V0 {
30310
30310
  const s = new Worker(n, {
30311
30311
  type: "module"
30312
30312
  });
30313
- this.attachWorkerHandlers(s, r), this.workers.push(s), this.inFlightPerWorker.push(0);
30313
+ this.attachWorkerHandlers(s, r), this.workers.push(s), this.inFlightPerWorker.push(0), this.fontsPerWorker.push(/* @__PURE__ */ new Set());
30314
30314
  }
30315
30315
  this.isInitialized = !1;
30316
30316
  }
@@ -30330,55 +30330,42 @@ class V0 {
30330
30330
  * Handles messages coming from any worker.
30331
30331
  */
30332
30332
  handleWorkerMessage(e, n) {
30333
- var c, l, u;
30333
+ var c, l, u, f;
30334
30334
  if (e.type === "fontLoaded") {
30335
- const f = (c = e.data) == null ? void 0 : c.fontName;
30336
- f && this.syncFontToWorkerPool(f).then((h) => {
30337
- h && (j.instance.applyRemoteFontLoaded(f), j.instance.events.fontLoaded.dispatch({ fontName: f }));
30338
- }).catch((h) => {
30339
- console.warn(
30340
- `Failed to sync lazy-loaded font "${f}" across worker pool:`,
30341
- h
30342
- );
30343
- });
30335
+ const h = (c = e.data) == null ? void 0 : c.fontName;
30336
+ if (h) {
30337
+ const p = h.toLowerCase();
30338
+ (l = this.fontsPerWorker[n]) == null || l.add(p), p && !this.poolFontLoadedDispatched.has(p) && (this.poolFontLoadedDispatched.add(p), j.instance.applyRemoteFontLoaded(h), j.instance.events.fontLoaded.dispatch({ fontName: h }));
30339
+ }
30344
30340
  return;
30345
30341
  }
30346
30342
  if (e.type === "fontNotFound") {
30347
- const f = (l = e.data) == null ? void 0 : l.fontName;
30348
- f && j.instance.applyRemoteFontNotFound(
30349
- f,
30350
- ((u = e.data) == null ? void 0 : u.count) ?? 1
30343
+ const h = (u = e.data) == null ? void 0 : u.fontName;
30344
+ h && j.instance.applyRemoteFontNotFound(
30345
+ h,
30346
+ ((f = e.data) == null ? void 0 : f.count) ?? 1
30351
30347
  );
30352
30348
  return;
30353
30349
  }
30354
30350
  const { id: r, success: s, data: i, error: a } = e, o = this.pendingRequests.get(r);
30355
- o ? (this.pendingRequests.delete(r), this.inFlightPerWorker[n] = Math.max(
30356
- 0,
30357
- this.inFlightPerWorker[n] - 1
30358
- ), s ? o.resolve(i) : o.reject(new Error(a || "Unknown worker error"))) : console.warn(`No pending request found for worker response id=${r}`);
30359
- }
30360
- /**
30361
- * Ensures every worker has `fontName`, then returns whether the main thread
30362
- * should emit {@link FontManager.events.fontLoaded} for this name.
30363
- */
30364
- syncFontToWorkerPool(e) {
30365
- const n = e.toLowerCase();
30366
- if (!n || this.workers.length === 0 || this.poolFontLoadedDispatched.has(n))
30367
- return Promise.resolve(!1);
30368
- const r = this.poolFontSyncInFlight.get(n), s = r ?? (async () => {
30369
- this.poolSyncedFonts.has(n) || (await this.sendMessageToAllWorkers({
30370
- type: "loadFonts",
30371
- data: { fonts: [e] }
30372
- })).every(
30373
- (o) => {
30374
- var c;
30375
- return (c = o == null ? void 0 : o.loaded) == null ? void 0 : c.some((l) => l.toLowerCase() === n);
30351
+ if (o)
30352
+ if (this.pendingRequests.delete(r), this.inFlightPerWorker[n] = Math.max(
30353
+ 0,
30354
+ this.inFlightPerWorker[n] - 1
30355
+ ), s) {
30356
+ if (e.type === "loadFonts") {
30357
+ const h = (i == null ? void 0 : i.loaded) ?? [], p = this.fontsPerWorker[n];
30358
+ if (p)
30359
+ for (const y of h) {
30360
+ const m = y.toLowerCase();
30361
+ m && p.add(m);
30362
+ }
30376
30363
  }
30377
- ) && this.poolSyncedFonts.add(n);
30378
- })().finally(() => {
30379
- this.poolFontSyncInFlight.delete(n);
30380
- });
30381
- return r || this.poolFontSyncInFlight.set(n, s), s.then(() => !this.poolSyncedFonts.has(n) || this.poolFontLoadedDispatched.has(n) ? !1 : (this.poolFontLoadedDispatched.add(n), !0));
30364
+ o.resolve(i);
30365
+ } else
30366
+ o.reject(new Error(a || "Unknown worker error"));
30367
+ else
30368
+ console.warn(`No pending request found for worker response id=${r}`);
30382
30369
  }
30383
30370
  /**
30384
30371
  * Attaches message and error handlers to a worker.
@@ -30398,10 +30385,11 @@ class V0 {
30398
30385
  };
30399
30386
  }
30400
30387
  pickLeastLoadedWorker() {
30401
- let e = 0, n = this.inFlightPerWorker[0] ?? 0;
30402
- for (let r = 1; r < this.inFlightPerWorker.length; r++) {
30403
- const s = this.inFlightPerWorker[r] ?? 0;
30404
- s < n && (n = s, e = r);
30388
+ var s, i;
30389
+ let e = 0, n = this.inFlightPerWorker[0] ?? 0, r = ((s = this.fontsPerWorker[0]) == null ? void 0 : s.size) ?? 0;
30390
+ for (let a = 1; a < this.inFlightPerWorker.length; a++) {
30391
+ const o = this.inFlightPerWorker[a] ?? 0, c = ((i = this.fontsPerWorker[a]) == null ? void 0 : i.size) ?? 0;
30392
+ (o < n || o === n && c > r) && (n = o, r = c, e = a);
30405
30393
  }
30406
30394
  return e;
30407
30395
  }
@@ -30553,28 +30541,55 @@ class V0 {
30553
30541
  "Function 'syncRenderShape' isn't supported in 'WebWorkerRenderer'!"
30554
30542
  );
30555
30543
  }
30556
- async loadFonts(e) {
30557
- await this.ensureTasksFinished();
30558
- const n = await this.sendMessageToAllWorkers({
30559
- type: "loadFonts",
30560
- data: { fonts: [...e] }
30561
- }), r = /* @__PURE__ */ new Set();
30562
- n.forEach((s) => {
30563
- var i;
30564
- return (i = s == null ? void 0 : s.loaded) == null ? void 0 : i.forEach((a) => r.add(a));
30565
- });
30566
- for (const s of e) {
30567
- const i = s.toLowerCase();
30568
- if (!i)
30569
- continue;
30570
- n.every(
30571
- (o) => {
30572
- var c;
30573
- return (c = o == null ? void 0 : o.loaded) == null ? void 0 : c.some((l) => l.toLowerCase() === i);
30544
+ /**
30545
+ * Loads fonts into the worker pool.
30546
+ *
30547
+ * @param fonts - Logical font names (extensions stripped by workers).
30548
+ * @param options.scope - `one` (default) warms a single least-loaded /
30549
+ * already-warm worker so open-time preload does not re-parse large mesh
30550
+ * fonts into every isolate. Pass `all` only when every worker must have
30551
+ * the faces before the first draw (rare; expensive for mesh fonts).
30552
+ * @returns Fonts confirmed loaded in the target isolate(s). With
30553
+ * `scope: 'all'`, only faces present in every worker.
30554
+ */
30555
+ async loadFonts(e, n) {
30556
+ var o;
30557
+ if (await this.ensureTasksFinished(), ((n == null ? void 0 : n.scope) ?? "one") === "one") {
30558
+ const c = this.pickLeastLoadedWorker(), l = await this.sendMessageToOneWorker(
30559
+ {
30560
+ type: "loadFonts",
30561
+ data: { fonts: [...e] }
30562
+ },
30563
+ c
30564
+ ), u = (l == null ? void 0 : l.loaded) ?? [], f = this.fontsPerWorker[c];
30565
+ if (f)
30566
+ for (const h of u) {
30567
+ const p = h.toLowerCase();
30568
+ p && f.add(p);
30574
30569
  }
30575
- ) && (this.poolSyncedFonts.add(i), this.poolFontLoadedDispatched.add(i));
30570
+ for (const h of u) {
30571
+ const p = h.toLowerCase();
30572
+ p && this.poolFontLoadedDispatched.add(p);
30573
+ }
30574
+ return { loaded: [...u] };
30576
30575
  }
30577
- return { loaded: Array.from(r) };
30576
+ const s = await this.sendMessageToAllWorkers({
30577
+ type: "loadFonts",
30578
+ data: { fonts: [...e] }
30579
+ }), i = [], a = ((o = s[0]) == null ? void 0 : o.loaded) ?? [];
30580
+ if (s.length > 0)
30581
+ for (const c of a) {
30582
+ const l = c.toLowerCase();
30583
+ if (!l)
30584
+ continue;
30585
+ s.every(
30586
+ (f) => {
30587
+ var h;
30588
+ return (h = f == null ? void 0 : f.loaded) == null ? void 0 : h.some((p) => p.toLowerCase() === l);
30589
+ }
30590
+ ) && (this.poolFontLoadedDispatched.add(l), i.push(c));
30591
+ }
30592
+ return { loaded: i };
30578
30593
  }
30579
30594
  async getAvailableFonts() {
30580
30595
  return (await this.sendMessageToAllWorkers({
@@ -30748,7 +30763,7 @@ class V0 {
30748
30763
  * Terminate the worker
30749
30764
  */
30750
30765
  terminate() {
30751
- this.workers.forEach((e) => e.terminate()), this.workers = [], this.inFlightPerWorker = [], this.readyPromise = null, this.poolSyncedFonts.clear(), this.poolFontSyncInFlight.clear(), this.poolFontLoadedDispatched.clear(), this.pendingRequests.forEach(({ reject: e }) => {
30766
+ this.workers.forEach((e) => e.terminate()), this.workers = [], this.inFlightPerWorker = [], this.fontsPerWorker = [], this.readyPromise = null, this.poolFontLoadedDispatched.clear(), this.pendingRequests.forEach(({ reject: e }) => {
30752
30767
  e(new Error("Renderer terminated"));
30753
30768
  }), this.pendingRequests.clear();
30754
30769
  }
@@ -30836,9 +30851,9 @@ class q0 {
30836
30851
  /**
30837
30852
  * Load fonts in the main thread
30838
30853
  */
30839
- async loadFonts(e) {
30854
+ async loadFonts(e, n) {
30840
30855
  return await this.fontManager.loadFontsByNames(e), {
30841
- loaded: e.filter((n) => this.fontManager.isFontLoaded(n))
30856
+ loaded: e.filter((r) => this.fontManager.isFontLoaded(r))
30842
30857
  };
30843
30858
  }
30844
30859
  /**
@@ -31018,10 +31033,14 @@ class Z0 {
31018
31033
  return j.instance.getSymbolFontsPreset(e);
31019
31034
  }
31020
31035
  /**
31021
- * Load fonts using the current mode
31036
+ * Load fonts using the current mode.
31037
+ *
31038
+ * In worker mode, `options.scope` defaults to `one` (warm a single isolate).
31039
+ * Pass `{ scope: 'all' }` only when every worker must have the faces;
31040
+ * `loaded` then lists only faces confirmed in every isolate.
31022
31041
  */
31023
- async loadFonts(e) {
31024
- return this.renderer.loadFonts(e);
31042
+ async loadFonts(e, n) {
31043
+ return this.renderer.loadFonts(e, n);
31025
31044
  }
31026
31045
  /**
31027
31046
  * Get available fonts using the current mode