@onodocs/canvas 0.5.0 → 0.5.1

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 (2) hide show
  1. package/index.js +50 -16
  2. package/package.json +2 -2
package/index.js CHANGED
@@ -2546,7 +2546,11 @@ function createDocument(source, options = {}) {
2546
2546
  const lifetime = new AbortController();
2547
2547
  const views = /* @__PURE__ */ new Set();
2548
2548
  const faces = /* @__PURE__ */ new Map();
2549
- const ownedFaces = /* @__PURE__ */ new Set();
2549
+ const fontCleanup = /* @__PURE__ */ new Set();
2550
+ const fontFinalizer = new FinalizationRegistry((close) => {
2551
+ close();
2552
+ fontCleanup.delete(close);
2553
+ });
2550
2554
  let pages = [];
2551
2555
  let disposed = false;
2552
2556
  let mounted;
@@ -2569,6 +2573,9 @@ function createDocument(source, options = {}) {
2569
2573
  },
2570
2574
  refresh() {
2571
2575
  checkOpen();
2576
+ const fonts = createFontResources(faces, checkOpen);
2577
+ fontCleanup.add(fonts.dispose);
2578
+ fontFinalizer.register(fonts, fonts.dispose);
2572
2579
  pages = source.pages.map((page) => ({ index: page.index, size: page.size, get interaction() {
2573
2580
  return page.interaction;
2574
2581
  }, async render(canvas, options2 = {}) {
@@ -2579,7 +2586,7 @@ function createDocument(source, options = {}) {
2579
2586
  if (!Number.isFinite(dpi) || dpi <= 0) throw new RangeError("dpi must be positive and finite.");
2580
2587
  const data = await page.load(signal);
2581
2588
  signal.throwIfAborted();
2582
- await Promise.all((data.fonts ?? []).map(loadFont));
2589
+ await Promise.all((data.fonts ?? []).map((resource) => fonts.load(resource)));
2583
2590
  signal.throwIfAborted();
2584
2591
  const images = data.images && await materializeImageResources(data.images, signal);
2585
2592
  try {
@@ -2608,10 +2615,9 @@ function createDocument(source, options = {}) {
2608
2615
  lifetime.abort();
2609
2616
  unsubscribe?.();
2610
2617
  for (const view of views) view.dispose();
2611
- for (const face of ownedFaces) document.fonts.delete(face);
2618
+ for (const close of fontCleanup) close();
2612
2619
  views.clear();
2613
- ownedFaces.clear();
2614
- faces.clear();
2620
+ fontCleanup.clear();
2615
2621
  }
2616
2622
  };
2617
2623
  unsubscribe = source.subscribe?.(() => source.disposed ? result.dispose() : result.refresh());
@@ -2627,24 +2633,52 @@ function createDocument(source, options = {}) {
2627
2633
  if (disposed || source.disposed) throw new Error("Canvas document is disposed.");
2628
2634
  }
2629
2635
  __name(checkOpen, "checkOpen");
2630
- function loadFont(resource) {
2636
+ }
2637
+ __name(createDocument, "createDocument");
2638
+ function createFontResources(faces, checkOpen) {
2639
+ const acquired = /* @__PURE__ */ new Map();
2640
+ let disposed = false;
2641
+ function load(resource) {
2642
+ checkOpen();
2643
+ if (disposed) return Promise.reject(new Error("Canvas font resources are disposed."));
2631
2644
  const key = JSON.stringify([resource.family, resource.descriptors]);
2632
- let pending = faces.get(key);
2633
- if (!pending) {
2645
+ let entry = faces.get(key);
2646
+ if (!entry) {
2634
2647
  const face = new FontFace(resource.family, typeof resource.source === "string" ? resource.source : resource.source.slice().buffer, resource.descriptors);
2635
- pending = face.load().then(() => {
2648
+ const pending = { face, users: 0, ready: face.load().then(() => {
2636
2649
  checkOpen();
2637
- document.fonts.add(face);
2638
- ownedFaces.add(face);
2639
- });
2650
+ if (pending.users) document.fonts.add(face);
2651
+ }) };
2640
2652
  faces.set(key, pending);
2641
- void pending.catch(() => faces.delete(key));
2653
+ entry = pending;
2654
+ void pending.ready.catch(() => {
2655
+ if (faces.get(key) === pending) faces.delete(key);
2656
+ });
2657
+ }
2658
+ const previous = acquired.get(key);
2659
+ if (previous !== entry) {
2660
+ if (previous) release(key, previous);
2661
+ acquired.set(key, entry);
2662
+ entry.users++;
2642
2663
  }
2643
- return pending;
2664
+ return entry.ready;
2644
2665
  }
2645
- __name(loadFont, "loadFont");
2666
+ __name(load, "load");
2667
+ function release(key, entry) {
2668
+ if (--entry.users === 0) {
2669
+ document.fonts.delete(entry.face);
2670
+ if (faces.get(key) === entry) faces.delete(key);
2671
+ }
2672
+ }
2673
+ __name(release, "release");
2674
+ return { load, dispose() {
2675
+ if (disposed) return;
2676
+ disposed = true;
2677
+ for (const [key, entry] of acquired) release(key, entry);
2678
+ acquired.clear();
2679
+ } };
2646
2680
  }
2647
- __name(createDocument, "createDocument");
2681
+ __name(createFontResources, "createFontResources");
2648
2682
  async function openDocument(url, options = {}) {
2649
2683
  const endpoint = new URL(url, document.baseURI);
2650
2684
  const manifest = await load(endpoint, options.signal);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onodocs/canvas",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "private": false,
5
5
  "description": "OnoDocs canvas viewer, selection and HTML attachments for prepared Word document pages.",
6
6
  "homepage": "https://onodocs.com/developers/",
@@ -49,5 +49,5 @@
49
49
  "type": "git",
50
50
  "url": "https://github.com/onodocs/onodocs.git"
51
51
  },
52
- "gitHead": "9eab22dd958dbf90e88fe039a087684760034356"
52
+ "gitHead": "a4043b6b334e0090f9cc2439d74120357a59aa76"
53
53
  }