@pixldocs/canvas-renderer 0.5.9 → 0.5.11

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
@@ -387,6 +387,7 @@ export declare class PixldocsRenderer {
387
387
  * using the global __fabricCanvasRegistry (set by PageCanvas).
388
388
  */
389
389
  private getFabricCanvasFromContainer;
390
+ private waitForStableTextMetrics;
390
391
  }
391
392
 
392
393
  export declare interface RendererConfig {
package/dist/index.js CHANGED
@@ -2671,10 +2671,12 @@ const waitForFontsReady = async () => {
2671
2671
  if (!document.fonts) return;
2672
2672
  await document.fonts.ready;
2673
2673
  };
2674
+ const DEFAULT_FONT_CHECK_TIMEOUT_MS = 3500;
2675
+ const FONT_CHECK_POLL_MS = 60;
2674
2676
  const waitUntilFontsAvailable = async (fontFamilies, options) => {
2675
2677
  if (!document.fonts || fontFamilies.length === 0) return;
2676
- const timeoutMs = options == null ? void 0 : options.timeoutMs;
2677
- const pollMs = options == null ? void 0 : options.pollIntervalMs;
2678
+ const timeoutMs = (options == null ? void 0 : options.timeoutMs) ?? DEFAULT_FONT_CHECK_TIMEOUT_MS;
2679
+ const pollMs = (options == null ? void 0 : options.pollIntervalMs) ?? FONT_CHECK_POLL_MS;
2678
2680
  const deadline = Date.now() + timeoutMs;
2679
2681
  const check = () => fontFamilies.every(
2680
2682
  (f) => document.fonts.check(`16px "${f}"`) && document.fonts.check(`bold 16px "${f}"`)
@@ -12318,16 +12320,17 @@ class PixldocsRenderer {
12318
12320
  };
12319
12321
  const onReady = () => {
12320
12322
  const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
12321
- this.waitForCanvasImages(container, expectedImageCount).then(() => {
12323
+ this.waitForCanvasImages(container, expectedImageCount).then(async () => {
12322
12324
  try {
12325
+ const fabricInstance = this.getFabricCanvasFromContainer(container);
12326
+ await this.waitForStableTextMetrics(container, config);
12323
12327
  const fabricCanvas = container.querySelector("canvas.upper-canvas, canvas");
12324
- if (!fabricCanvas) {
12328
+ const sourceCanvas = (fabricInstance == null ? void 0 : fabricInstance.lowerCanvasEl) || container.querySelector("canvas.lower-canvas") || fabricCanvas;
12329
+ if (!sourceCanvas) {
12325
12330
  cleanup();
12326
12331
  reject(new Error("No canvas element found after render"));
12327
12332
  return;
12328
12333
  }
12329
- const lowerCanvas = container.querySelector("canvas.lower-canvas");
12330
- const sourceCanvas = lowerCanvas || fabricCanvas;
12331
12334
  const exportCanvas = document.createElement("canvas");
12332
12335
  exportCanvas.width = sourceCanvas.width;
12333
12336
  exportCanvas.height = sourceCanvas.height;
@@ -12397,7 +12400,7 @@ class PixldocsRenderer {
12397
12400
  };
12398
12401
  const onReady = () => {
12399
12402
  const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
12400
- this.waitForCanvasImages(container, expectedImageCount).then(() => {
12403
+ this.waitForCanvasImages(container, expectedImageCount).then(async () => {
12401
12404
  var _a, _b;
12402
12405
  try {
12403
12406
  const fabricInstance = this.getFabricCanvasFromContainer(container);
@@ -12406,6 +12409,7 @@ class PixldocsRenderer {
12406
12409
  reject(new Error("No Fabric canvas instance found for SVG capture"));
12407
12410
  return;
12408
12411
  }
12412
+ await this.waitForStableTextMetrics(container, config);
12409
12413
  const prevVPT = fabricInstance.viewportTransform ? [...fabricInstance.viewportTransform] : void 0;
12410
12414
  const prevSvgVPT = fabricInstance.svgViewportTransformation;
12411
12415
  const prevRetina = fabricInstance.enableRetinaScaling;
@@ -12527,6 +12531,70 @@ class PixldocsRenderer {
12527
12531
  }
12528
12532
  return null;
12529
12533
  }
12534
+ async waitForStableTextMetrics(container, config) {
12535
+ var _a;
12536
+ if (typeof document !== "undefined") {
12537
+ await ensureFontsForResolvedConfig(config);
12538
+ await ((_a = document.fonts) == null ? void 0 : _a.ready);
12539
+ const fontFamilies = [...collectFontsFromConfig(config)].filter(Boolean);
12540
+ if (fontFamilies.length > 0) {
12541
+ await waitUntilFontsAvailable(fontFamilies, { timeoutMs: 4e3, pollIntervalMs: 50 });
12542
+ }
12543
+ }
12544
+ const fabricInstance = this.getFabricCanvasFromContainer(container);
12545
+ if (!(fabricInstance == null ? void 0 : fabricInstance.getObjects)) return;
12546
+ const waitForPaint = () => new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(() => r())));
12547
+ const clearTextMetricCaches = () => {
12548
+ clearFabricCharCache();
12549
+ clearMeasurementCache();
12550
+ };
12551
+ const reflowTextboxes = () => {
12552
+ var _a2, _b, _c;
12553
+ const walk = (obj) => {
12554
+ var _a3, _b2, _c2, _d;
12555
+ if (!obj) return;
12556
+ const children = Array.isArray(obj._objects) ? obj._objects : Array.isArray(obj.objects) ? obj.objects : [];
12557
+ if (children.length) children.forEach(walk);
12558
+ const isTextObject = typeof obj.text === "string" && typeof obj.initDimensions === "function" && (obj.type === "textbox" || obj.type === "text" || obj.type === "i-text" || obj.isEditing !== void 0);
12559
+ if (isTextObject) {
12560
+ const saved = {
12561
+ width: obj.width,
12562
+ scaleX: obj.scaleX,
12563
+ scaleY: obj.scaleY
12564
+ };
12565
+ (_a3 = obj._clearCache) == null ? void 0 : _a3.call(obj);
12566
+ obj.__charBounds = [];
12567
+ obj.__lineWidths = [];
12568
+ obj.__lineHeights = [];
12569
+ obj._textLines = [];
12570
+ obj.textLines = [];
12571
+ obj.dirty = true;
12572
+ obj.initDimensions();
12573
+ (_b2 = obj.set) == null ? void 0 : _b2.call(obj, {
12574
+ width: saved.width,
12575
+ scaleX: saved.scaleX,
12576
+ scaleY: saved.scaleY,
12577
+ dirty: true
12578
+ });
12579
+ (_c2 = obj._clearCache) == null ? void 0 : _c2.call(obj);
12580
+ (_d = obj.setCoords) == null ? void 0 : _d.call(obj);
12581
+ }
12582
+ };
12583
+ fabricInstance.getObjects().forEach(walk);
12584
+ (_a2 = fabricInstance.calcOffset) == null ? void 0 : _a2.call(fabricInstance);
12585
+ (_b = fabricInstance.renderAll) == null ? void 0 : _b.call(fabricInstance);
12586
+ (_c = fabricInstance.requestRenderAll) == null ? void 0 : _c.call(fabricInstance);
12587
+ };
12588
+ clearTextMetricCaches();
12589
+ await waitForPaint();
12590
+ reflowTextboxes();
12591
+ await waitForPaint();
12592
+ clearTextMetricCaches();
12593
+ reflowTextboxes();
12594
+ await waitForPaint();
12595
+ reflowTextboxes();
12596
+ await waitForPaint();
12597
+ }
12530
12598
  }
12531
12599
  const FONT_WEIGHT_LABELS = {
12532
12600
  300: "Light",