@pixldocs/canvas-renderer 0.5.16 → 0.5.18
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.cjs +63 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +63 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -369,6 +369,8 @@ export declare class PixldocsRenderer {
|
|
|
369
369
|
renderAllById(templateId: string, formData?: Record<string, any>, options?: Omit<RenderOptions, 'pageIndex'>): Promise<RenderResult[]>;
|
|
370
370
|
private getExpectedImageCount;
|
|
371
371
|
private waitForCanvasImages;
|
|
372
|
+
private waitForCanvasScene;
|
|
373
|
+
private waitForRelevantFonts;
|
|
372
374
|
private getNormalizedGradientStops;
|
|
373
375
|
private paintPageBackground;
|
|
374
376
|
private renderPageViaPreviewCanvas;
|
package/dist/index.js
CHANGED
|
@@ -5670,6 +5670,7 @@ const PageCanvas = forwardRef(
|
|
|
5670
5670
|
onDynamicFieldClick,
|
|
5671
5671
|
canvasUpdateVersion = 0,
|
|
5672
5672
|
pageChildren,
|
|
5673
|
+
skipFontReadyWait = false,
|
|
5673
5674
|
onReady
|
|
5674
5675
|
}, ref) => {
|
|
5675
5676
|
const isEditorMode = mode === "editor";
|
|
@@ -5955,9 +5956,11 @@ const PageCanvas = forwardRef(
|
|
|
5955
5956
|
await Promise.all(fontFamilies.map((f) => ensureFontLoaded(f)));
|
|
5956
5957
|
}
|
|
5957
5958
|
}
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5959
|
+
if (!skipFontReadyWait) {
|
|
5960
|
+
await waitForFontsReady();
|
|
5961
|
+
await waitUntilFontsAvailable(fontFamilies, { timeoutMs: 3500, pollIntervalMs: 60 });
|
|
5962
|
+
await new Promise((r) => requestAnimationFrame(() => r()));
|
|
5963
|
+
}
|
|
5961
5964
|
clearFabricCharCache();
|
|
5962
5965
|
clearMeasurementCache();
|
|
5963
5966
|
setReady(true);
|
|
@@ -9394,6 +9397,7 @@ function PreviewCanvas({
|
|
|
9394
9397
|
pageIndex = 0,
|
|
9395
9398
|
zoom = 1,
|
|
9396
9399
|
absoluteZoom = false,
|
|
9400
|
+
skipFontReadyWait = false,
|
|
9397
9401
|
className,
|
|
9398
9402
|
onDynamicFieldClick,
|
|
9399
9403
|
onReady
|
|
@@ -9548,6 +9552,7 @@ function PreviewCanvas({
|
|
|
9548
9552
|
selectedIds: [],
|
|
9549
9553
|
activeTool: "select",
|
|
9550
9554
|
mode: "preview",
|
|
9555
|
+
skipFontReadyWait,
|
|
9551
9556
|
dynamicFieldIds,
|
|
9552
9557
|
onDynamicFieldClick: handleDynamicFieldClick,
|
|
9553
9558
|
onReady
|
|
@@ -12281,6 +12286,49 @@ class PixldocsRenderer {
|
|
|
12281
12286
|
setTimeout(check, 0);
|
|
12282
12287
|
});
|
|
12283
12288
|
}
|
|
12289
|
+
waitForCanvasScene(container, config, pageIndex, maxWaitMs = 8e3, pollMs = 50) {
|
|
12290
|
+
return new Promise((resolve) => {
|
|
12291
|
+
var _a, _b;
|
|
12292
|
+
const start = Date.now();
|
|
12293
|
+
const pageHasContent = (((_b = (_a = config.pages[pageIndex]) == null ? void 0 : _a.children) == null ? void 0 : _b.length) ?? 0) > 0;
|
|
12294
|
+
const settle = () => requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
12295
|
+
const check = () => {
|
|
12296
|
+
const fabricCanvas = this.getFabricCanvasFromContainer(container);
|
|
12297
|
+
const lowerCanvas = (fabricCanvas == null ? void 0 : fabricCanvas.lowerCanvasEl) || container.querySelector("canvas.lower-canvas, canvas");
|
|
12298
|
+
const objectCount = typeof (fabricCanvas == null ? void 0 : fabricCanvas.getObjects) === "function" ? fabricCanvas.getObjects().length : 0;
|
|
12299
|
+
const ready = !!lowerCanvas && (!pageHasContent || objectCount > 0);
|
|
12300
|
+
if (ready) {
|
|
12301
|
+
console.log(`[canvas-renderer][scene-wait] ready after ${Date.now() - start}ms (objects=${objectCount})`);
|
|
12302
|
+
settle();
|
|
12303
|
+
return;
|
|
12304
|
+
}
|
|
12305
|
+
if (Date.now() - start >= maxWaitMs) {
|
|
12306
|
+
console.warn(`[canvas-renderer][scene-wait-timeout] elapsed=${Date.now() - start}ms objects=${objectCount} pageHasContent=${pageHasContent}`);
|
|
12307
|
+
settle();
|
|
12308
|
+
return;
|
|
12309
|
+
}
|
|
12310
|
+
setTimeout(check, pollMs);
|
|
12311
|
+
};
|
|
12312
|
+
setTimeout(check, 0);
|
|
12313
|
+
});
|
|
12314
|
+
}
|
|
12315
|
+
async waitForRelevantFonts(config, maxWaitMs = 1800) {
|
|
12316
|
+
if (typeof document === "undefined" || !document.fonts) return;
|
|
12317
|
+
const descriptors = collectFontDescriptorsFromConfig(config);
|
|
12318
|
+
if (descriptors.length === 0) return;
|
|
12319
|
+
const loads = Promise.all(
|
|
12320
|
+
descriptors.map((descriptor) => {
|
|
12321
|
+
const stylePrefix = descriptor.style === "italic" ? "italic " : "";
|
|
12322
|
+
const spec = `${stylePrefix}${descriptor.weight} 16px "${descriptor.family}"`;
|
|
12323
|
+
return document.fonts.load(spec).catch(() => []);
|
|
12324
|
+
})
|
|
12325
|
+
).then(() => void 0);
|
|
12326
|
+
await Promise.race([
|
|
12327
|
+
loads,
|
|
12328
|
+
new Promise((resolve) => setTimeout(resolve, maxWaitMs))
|
|
12329
|
+
]);
|
|
12330
|
+
await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(() => resolve())));
|
|
12331
|
+
}
|
|
12284
12332
|
getNormalizedGradientStops(gradient) {
|
|
12285
12333
|
const stops = Array.isArray(gradient == null ? void 0 : gradient.stops) ? gradient.stops.map((stop) => ({
|
|
12286
12334
|
offset: Math.max(0, Math.min(1, Number((stop == null ? void 0 : stop.offset) ?? 0))),
|
|
@@ -12388,16 +12436,17 @@ class PixldocsRenderer {
|
|
|
12388
12436
|
pageIndex,
|
|
12389
12437
|
zoom: pixelRatio,
|
|
12390
12438
|
absoluteZoom: true,
|
|
12439
|
+
skipFontReadyWait: true,
|
|
12391
12440
|
onReady
|
|
12392
12441
|
})
|
|
12393
12442
|
);
|
|
12394
12443
|
return;
|
|
12395
12444
|
}
|
|
12396
|
-
|
|
12397
|
-
this.waitForCanvasImages(container, expectedImageCount).then(async () => {
|
|
12445
|
+
this.waitForCanvasScene(container, config, pageIndex).then(async () => {
|
|
12398
12446
|
try {
|
|
12399
12447
|
const fabricInstance = this.getFabricCanvasFromContainer(container);
|
|
12400
|
-
|
|
12448
|
+
const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
|
|
12449
|
+
await this.waitForCanvasImages(container, expectedImageCount);
|
|
12401
12450
|
const fabricCanvas = container.querySelector("canvas.upper-canvas, canvas");
|
|
12402
12451
|
const sourceCanvas = (fabricInstance == null ? void 0 : fabricInstance.lowerCanvasEl) || container.querySelector("canvas.lower-canvas") || fabricCanvas;
|
|
12403
12452
|
if (!sourceCanvas) {
|
|
@@ -12436,6 +12485,7 @@ class PixldocsRenderer {
|
|
|
12436
12485
|
pageIndex,
|
|
12437
12486
|
zoom: pixelRatio,
|
|
12438
12487
|
absoluteZoom: true,
|
|
12488
|
+
skipFontReadyWait: true,
|
|
12439
12489
|
onReady
|
|
12440
12490
|
})
|
|
12441
12491
|
);
|
|
@@ -12482,13 +12532,13 @@ class PixldocsRenderer {
|
|
|
12482
12532
|
pageIndex,
|
|
12483
12533
|
zoom: 1,
|
|
12484
12534
|
absoluteZoom: true,
|
|
12535
|
+
skipFontReadyWait: true,
|
|
12485
12536
|
onReady
|
|
12486
12537
|
})
|
|
12487
12538
|
);
|
|
12488
12539
|
return;
|
|
12489
12540
|
}
|
|
12490
|
-
|
|
12491
|
-
this.waitForCanvasImages(container, expectedImageCount).then(async () => {
|
|
12541
|
+
this.waitForCanvasScene(container, config, pageIndex).then(async () => {
|
|
12492
12542
|
var _a, _b;
|
|
12493
12543
|
try {
|
|
12494
12544
|
const fabricInstance = this.getFabricCanvasFromContainer(container);
|
|
@@ -12497,7 +12547,8 @@ class PixldocsRenderer {
|
|
|
12497
12547
|
reject(new Error("No Fabric canvas instance found for SVG capture"));
|
|
12498
12548
|
return;
|
|
12499
12549
|
}
|
|
12500
|
-
|
|
12550
|
+
const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
|
|
12551
|
+
await this.waitForCanvasImages(container, expectedImageCount);
|
|
12501
12552
|
const prevVPT = fabricInstance.viewportTransform ? [...fabricInstance.viewportTransform] : void 0;
|
|
12502
12553
|
const prevSvgVPT = fabricInstance.svgViewportTransformation;
|
|
12503
12554
|
const prevRetina = fabricInstance.enableRetinaScaling;
|
|
@@ -12548,6 +12599,7 @@ class PixldocsRenderer {
|
|
|
12548
12599
|
zoom: 1,
|
|
12549
12600
|
// 1:1 — no UI scaling for SVG capture
|
|
12550
12601
|
absoluteZoom: true,
|
|
12602
|
+
skipFontReadyWait: true,
|
|
12551
12603
|
onReady
|
|
12552
12604
|
})
|
|
12553
12605
|
);
|
|
@@ -12621,7 +12673,8 @@ class PixldocsRenderer {
|
|
|
12621
12673
|
}
|
|
12622
12674
|
async waitForStableTextMetrics(container, config) {
|
|
12623
12675
|
if (typeof document !== "undefined") {
|
|
12624
|
-
|
|
12676
|
+
void ensureFontsForResolvedConfig(config);
|
|
12677
|
+
await this.waitForRelevantFonts(config);
|
|
12625
12678
|
}
|
|
12626
12679
|
const fabricInstance = this.getFabricCanvasFromContainer(container);
|
|
12627
12680
|
if (!(fabricInstance == null ? void 0 : fabricInstance.getObjects)) return;
|