@pixldocs/canvas-renderer 0.5.21 → 0.5.23

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.d.ts CHANGED
@@ -100,8 +100,8 @@ export declare function embedFontsInPdf(pdf: jsPDF, fontFamilies: Set<string>, f
100
100
  * 1. Walks ALL text nodes (including clones/repeatables) collecting
101
101
  * fontFamily + fontWeight + fontStyle.
102
102
  * 2. Loads each unique family via Google Fonts CSS v1 (idempotent).
103
- * 3. Kicks off each weight+style combo via `document.fonts.load()` without
104
- * blocking render completion; late font load reflow handles final metrics.
103
+ * 3. Waits for each weight+style combo via `document.fonts.load()` so export
104
+ * capture never uses fallback font decoration metrics.
105
105
  *
106
106
  * Idempotent — safe to call multiple times for the same config.
107
107
  */
package/dist/index.js CHANGED
@@ -11833,41 +11833,19 @@ async function ensureFontsForResolvedConfig(config) {
11833
11833
  if (typeof document === "undefined") return;
11834
11834
  const descriptors = collectFontDescriptorsFromConfig(config);
11835
11835
  const families = new Set(descriptors.map((d) => d.family));
11836
- void withTimeout(Promise.all([...families].map((f) => loadGoogleFontCSS(f))), 2500);
11836
+ await withTimeout(Promise.all([...families].map((f) => loadGoogleFontCSS(f))), 6e3);
11837
11837
  if (document.fonts) {
11838
- descriptors.forEach((d) => {
11838
+ await withTimeout(Promise.all(descriptors.map((d) => {
11839
11839
  const stylePrefix = d.style === "italic" ? "italic " : "";
11840
11840
  const weightStr = String(d.weight);
11841
11841
  const spec = `${stylePrefix}${weightStr} 16px "${d.family}"`;
11842
- document.fonts.load(spec).catch(() => {
11842
+ return document.fonts.load(spec).catch(() => {
11843
11843
  });
11844
- });
11844
+ })), 6e3);
11845
+ await withTimeout(document.fonts.ready, 6e3);
11845
11846
  }
11846
11847
  }
11847
11848
  const TEXT_TYPES = /* @__PURE__ */ new Set(["textbox", "text", "i-text"]);
11848
- function getTextLines(obj) {
11849
- const lines = Array.isArray(obj.textLines) && obj.textLines.length ? obj.textLines : String(obj.text || "").split("\n");
11850
- return lines.map((line) => Array.isArray(line) ? line.join("") : String(line ?? ""));
11851
- }
11852
- function measureLineWidth(obj, line) {
11853
- if (typeof document === "undefined") return 0;
11854
- const canvas = document.createElement("canvas");
11855
- const ctx = canvas.getContext("2d");
11856
- if (!ctx) return 0;
11857
- const fontStyle = obj.fontStyle || "normal";
11858
- const fontWeight = obj.fontWeight || 400;
11859
- const fontSize = obj.fontSize || 16;
11860
- const fontFamily = obj.fontFamily || "sans-serif";
11861
- ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
11862
- const charSpacing = Number(obj.charSpacing || 0) / 1e3 * fontSize;
11863
- return ctx.measureText(line).width + Math.max(0, line.length - 1) * charSpacing;
11864
- }
11865
- function getDecorationPadding(obj) {
11866
- var _a;
11867
- const strokeWidth = Number(obj.strokeWidth || 0);
11868
- const shadowBlur = Number(((_a = obj.shadow) == null ? void 0 : _a.blur) || 0);
11869
- return Math.max(0, strokeWidth) + Math.max(0, shadowBlur * 0.25);
11870
- }
11871
11849
  function getFabricCanvasFromContainer(container) {
11872
11850
  const registry2 = window.__fabricCanvasRegistry;
11873
11851
  if (registry2 instanceof Map) {
@@ -11914,10 +11892,6 @@ function stabilizeFabricTextObjects(fabricInstance) {
11914
11892
  obj.initDimensions();
11915
11893
  (_b2 = obj.set) == null ? void 0 : _b2.call(obj, { width: saved.width, scaleX: saved.scaleX, scaleY: saved.scaleY });
11916
11894
  }
11917
- if (obj.underline || obj.linethrough) {
11918
- const decorationPadding = getDecorationPadding(obj);
11919
- obj.__lineWidths = getTextLines(obj).map((line) => Math.max(0, measureLineWidth(obj, line) + decorationPadding));
11920
- }
11921
11895
  obj.dirty = true;
11922
11896
  (_c2 = obj._clearCache) == null ? void 0 : _c2.call(obj);
11923
11897
  (_d = obj.setCoords) == null ? void 0 : _d.call(obj);
@@ -12563,7 +12537,7 @@ class PixldocsRenderer {
12563
12537
  container.style.cssText = `
12564
12538
  position: fixed; left: -99999px; top: -99999px;
12565
12539
  width: ${canvasWidth}px; height: ${canvasHeight}px;
12566
- overflow: hidden; pointer-events: none; opacity: 0;
12540
+ overflow: hidden; pointer-events: none; visibility: hidden;
12567
12541
  `;
12568
12542
  document.body.appendChild(container);
12569
12543
  const timeout = setTimeout(() => {
@@ -12584,7 +12558,7 @@ class PixldocsRenderer {
12584
12558
  finished = true;
12585
12559
  this.waitForCanvasScene(container, config, pageIndex).then(async () => {
12586
12560
  try {
12587
- await this.waitForStableTextMetrics(container, config);
12561
+ await this.waitForStableTextMetrics(container, config, true);
12588
12562
  await this.waitForCanvasScene(container, config, pageIndex, 2500, 50);
12589
12563
  const fabricInstance = this.getFabricCanvasFromContainer(container);
12590
12564
  const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
@@ -12648,7 +12622,7 @@ class PixldocsRenderer {
12648
12622
  container.style.cssText = `
12649
12623
  position: fixed; left: -99999px; top: -99999px;
12650
12624
  width: ${canvasWidth}px; height: ${canvasHeight}px;
12651
- overflow: hidden; pointer-events: none; opacity: 0;
12625
+ overflow: hidden; pointer-events: none; visibility: hidden;
12652
12626
  `;
12653
12627
  document.body.appendChild(container);
12654
12628
  const timeout = setTimeout(() => {
@@ -12670,7 +12644,7 @@ class PixldocsRenderer {
12670
12644
  this.waitForCanvasScene(container, config, pageIndex).then(async () => {
12671
12645
  var _a, _b;
12672
12646
  try {
12673
- await this.waitForStableTextMetrics(container, config);
12647
+ await this.waitForStableTextMetrics(container, config, true);
12674
12648
  await this.waitForCanvasScene(container, config, pageIndex, 2500, 50);
12675
12649
  const fabricInstance = this.getFabricCanvasFromContainer(container);
12676
12650
  if (!fabricInstance) {
@@ -12792,10 +12766,10 @@ class PixldocsRenderer {
12792
12766
  getFabricCanvasFromContainer(container) {
12793
12767
  return getFabricCanvasFromContainer(container);
12794
12768
  }
12795
- async waitForStableTextMetrics(container, config) {
12769
+ async waitForStableTextMetrics(container, config, strictFontWait = false) {
12796
12770
  if (typeof document !== "undefined") {
12797
- void ensureFontsForResolvedConfig(config);
12798
- await this.waitForRelevantFonts(config);
12771
+ await ensureFontsForResolvedConfig(config);
12772
+ await this.waitForRelevantFonts(config, strictFontWait ? 6e3 : 1800);
12799
12773
  }
12800
12774
  const fabricInstance = this.getFabricCanvasFromContainer(container);
12801
12775
  if (!(fabricInstance == null ? void 0 : fabricInstance.getObjects)) return;
@@ -14553,19 +14527,21 @@ function convertTextDecorationsToLines(svg) {
14553
14527
  const fontFamily = tspan.getAttribute("font-family") || textEl.getAttribute("font-family") || "sans-serif";
14554
14528
  const fontWeight = tspan.getAttribute("font-weight") || textEl.getAttribute("font-weight") || "normal";
14555
14529
  const fill = tspan.getAttribute("fill") || textEl.getAttribute("fill") || "#000000";
14556
- let textWidth;
14557
- if (ctx) {
14558
- ctx.font = `${fontWeight} ${fontSize}px ${fontFamily.replace(/'/g, "")}`;
14559
- textWidth = ctx.measureText(content).width;
14560
- } else {
14561
- textWidth = content.length * fontSize * 0.6;
14562
- }
14530
+ let textWidth = 0;
14563
14531
  if (typeof tspan.getComputedTextLength === "function") {
14564
14532
  try {
14565
- textWidth = Math.max(textWidth, tspan.getComputedTextLength());
14533
+ textWidth = tspan.getComputedTextLength();
14566
14534
  } catch {
14567
14535
  }
14568
14536
  }
14537
+ if (!Number.isFinite(textWidth) || textWidth <= 0) {
14538
+ if (ctx) {
14539
+ ctx.font = `${fontWeight} ${fontSize}px ${fontFamily.replace(/'/g, "")}`;
14540
+ textWidth = ctx.measureText(content).width;
14541
+ } else {
14542
+ textWidth = content.length * fontSize * 0.6;
14543
+ }
14544
+ }
14569
14545
  const underlineY = y + fontSize * 0.15;
14570
14546
  const thickness = Math.max(0.5, fontSize * 0.066667);
14571
14547
  const line = doc.createElementNS("http://www.w3.org/2000/svg", "line");