@pixldocs/canvas-renderer 0.5.61 → 0.5.63
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 +108 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +108 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -12561,7 +12561,7 @@ function PixldocsPreview(props) {
|
|
|
12561
12561
|
!canvasSettled && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) })
|
|
12562
12562
|
] });
|
|
12563
12563
|
}
|
|
12564
|
-
const PACKAGE_VERSION = "0.5.
|
|
12564
|
+
const PACKAGE_VERSION = "0.5.63";
|
|
12565
12565
|
let __underlineFixInstalled = false;
|
|
12566
12566
|
function installUnderlineFix(fab) {
|
|
12567
12567
|
var _a;
|
|
@@ -13277,6 +13277,7 @@ class PixldocsRenderer {
|
|
|
13277
13277
|
captureSvgViaPreviewCanvas(config, pageIndex, canvasWidth, canvasHeight) {
|
|
13278
13278
|
return new Promise(async (resolve, reject) => {
|
|
13279
13279
|
const { PreviewCanvas: PreviewCanvas2 } = await Promise.resolve().then(() => PreviewCanvas$1);
|
|
13280
|
+
const hasAutoShrink = configHasAutoShrinkText(config);
|
|
13280
13281
|
const container = document.createElement("div");
|
|
13281
13282
|
container.style.cssText = `
|
|
13282
13283
|
position: fixed; left: -99999px; top: -99999px;
|
|
@@ -13288,28 +13289,74 @@ class PixldocsRenderer {
|
|
|
13288
13289
|
cleanup();
|
|
13289
13290
|
reject(new Error("SVG render timeout (30s)"));
|
|
13290
13291
|
}, 3e4);
|
|
13292
|
+
let root = null;
|
|
13293
|
+
let mountKey = 0;
|
|
13294
|
+
let didAutoShrinkParityRemount = false;
|
|
13291
13295
|
const cleanup = () => {
|
|
13292
13296
|
clearTimeout(timeout);
|
|
13293
13297
|
try {
|
|
13294
|
-
root.unmount();
|
|
13298
|
+
root == null ? void 0 : root.unmount();
|
|
13295
13299
|
} catch {
|
|
13296
13300
|
}
|
|
13297
13301
|
container.remove();
|
|
13298
13302
|
};
|
|
13303
|
+
const remountForAutoShrinkParity = async () => {
|
|
13304
|
+
didAutoShrinkParityRemount = true;
|
|
13305
|
+
mountKey += 1;
|
|
13306
|
+
try {
|
|
13307
|
+
clearMeasurementCache();
|
|
13308
|
+
} catch {
|
|
13309
|
+
}
|
|
13310
|
+
try {
|
|
13311
|
+
clearFabricCharCache();
|
|
13312
|
+
} catch {
|
|
13313
|
+
}
|
|
13314
|
+
try {
|
|
13315
|
+
root == null ? void 0 : root.unmount();
|
|
13316
|
+
} catch {
|
|
13317
|
+
}
|
|
13318
|
+
root = client.createRoot(container);
|
|
13319
|
+
await new Promise((settle) => {
|
|
13320
|
+
const onReadyOnce = () => {
|
|
13321
|
+
this.waitForCanvasScene(container, config, pageIndex).then(async () => {
|
|
13322
|
+
const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
|
|
13323
|
+
await this.waitForCanvasImages(container, expectedImageCount);
|
|
13324
|
+
await this.waitForStableTextMetrics(container, config);
|
|
13325
|
+
await this.waitForCanvasScene(container, config, pageIndex);
|
|
13326
|
+
settle();
|
|
13327
|
+
}).catch(() => settle());
|
|
13328
|
+
};
|
|
13329
|
+
root.render(
|
|
13330
|
+
react.createElement(PreviewCanvas2, {
|
|
13331
|
+
key: `svg-auto-shrink-remount-${mountKey}`,
|
|
13332
|
+
config,
|
|
13333
|
+
pageIndex,
|
|
13334
|
+
zoom: 1,
|
|
13335
|
+
absoluteZoom: true,
|
|
13336
|
+
skipFontReadyWait: false,
|
|
13337
|
+
onReady: onReadyOnce
|
|
13338
|
+
})
|
|
13339
|
+
);
|
|
13340
|
+
});
|
|
13341
|
+
};
|
|
13299
13342
|
const onReady = () => {
|
|
13300
13343
|
this.waitForCanvasScene(container, config, pageIndex).then(async () => {
|
|
13301
13344
|
var _a, _b;
|
|
13302
13345
|
try {
|
|
13346
|
+
const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
|
|
13347
|
+
await this.waitForCanvasImages(container, expectedImageCount);
|
|
13348
|
+
await this.waitForStableTextMetrics(container, config);
|
|
13349
|
+
await this.waitForCanvasScene(container, config, pageIndex);
|
|
13350
|
+
if (hasAutoShrink && !didAutoShrinkParityRemount) {
|
|
13351
|
+
console.log("[canvas-renderer][svg-parity] remounting auto-shrink text before PDF SVG capture");
|
|
13352
|
+
await remountForAutoShrinkParity();
|
|
13353
|
+
}
|
|
13303
13354
|
const fabricInstance = this.getFabricCanvasFromContainer(container);
|
|
13304
13355
|
if (!fabricInstance) {
|
|
13305
13356
|
cleanup();
|
|
13306
13357
|
reject(new Error("No Fabric canvas instance found for SVG capture"));
|
|
13307
13358
|
return;
|
|
13308
13359
|
}
|
|
13309
|
-
const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
|
|
13310
|
-
await this.waitForCanvasImages(container, expectedImageCount);
|
|
13311
|
-
await this.waitForStableTextMetrics(container, config);
|
|
13312
|
-
await this.waitForCanvasScene(container, config, pageIndex);
|
|
13313
13360
|
const prevVPT = fabricInstance.viewportTransform ? [...fabricInstance.viewportTransform] : void 0;
|
|
13314
13361
|
const prevSvgVPT = fabricInstance.svgViewportTransformation;
|
|
13315
13362
|
const prevRetina = fabricInstance.enableRetinaScaling;
|
|
@@ -13322,6 +13369,7 @@ class PixldocsRenderer {
|
|
|
13322
13369
|
{ width: canvasWidth, height: canvasHeight },
|
|
13323
13370
|
{ cssOnly: false, backstoreOnly: false }
|
|
13324
13371
|
);
|
|
13372
|
+
this.resyncTextMetricsForSvgExport(fabricInstance);
|
|
13325
13373
|
const rawSvgString = fabricInstance.toSVG();
|
|
13326
13374
|
const svgString = this.normalizeSvgDimensions(
|
|
13327
13375
|
rawSvgString,
|
|
@@ -13352,7 +13400,7 @@ class PixldocsRenderer {
|
|
|
13352
13400
|
}
|
|
13353
13401
|
});
|
|
13354
13402
|
};
|
|
13355
|
-
|
|
13403
|
+
root = client.createRoot(container);
|
|
13356
13404
|
root.render(
|
|
13357
13405
|
react.createElement(PreviewCanvas2, {
|
|
13358
13406
|
config,
|
|
@@ -13432,6 +13480,59 @@ class PixldocsRenderer {
|
|
|
13432
13480
|
}
|
|
13433
13481
|
return null;
|
|
13434
13482
|
}
|
|
13483
|
+
resyncTextMetricsForSvgExport(fabricInstance) {
|
|
13484
|
+
if (typeof document === "undefined" || !(fabricInstance == null ? void 0 : fabricInstance.getObjects)) return;
|
|
13485
|
+
const ctx = document.createElement("canvas").getContext("2d");
|
|
13486
|
+
if (!ctx) return;
|
|
13487
|
+
const syncTextbox = (textbox) => {
|
|
13488
|
+
const tb = textbox;
|
|
13489
|
+
const rawLines = tb._textLines ?? textbox.textLines ?? [];
|
|
13490
|
+
if (!Array.isArray(rawLines) || rawLines.length === 0) return;
|
|
13491
|
+
const nextCharBounds = [];
|
|
13492
|
+
const nextLineWidths = [];
|
|
13493
|
+
rawLines.forEach((rawLine, lineIndex) => {
|
|
13494
|
+
const graphemes = Array.isArray(rawLine) ? rawLine.map((part) => String(part ?? "")) : Array.from(String(rawLine ?? ""));
|
|
13495
|
+
const bounds = [];
|
|
13496
|
+
let left = 0;
|
|
13497
|
+
graphemes.forEach((grapheme, charIndex) => {
|
|
13498
|
+
var _a, _b, _c, _d, _e, _f;
|
|
13499
|
+
const fontSize = Number(((_a = tb.getValueOfPropertyAt) == null ? void 0 : _a.call(tb, lineIndex, charIndex, "fontSize")) ?? textbox.fontSize ?? 16);
|
|
13500
|
+
const fontStyle = String(((_b = tb.getValueOfPropertyAt) == null ? void 0 : _b.call(tb, lineIndex, charIndex, "fontStyle")) ?? textbox.fontStyle ?? "normal");
|
|
13501
|
+
const fontWeight = String(((_c = tb.getValueOfPropertyAt) == null ? void 0 : _c.call(tb, lineIndex, charIndex, "fontWeight")) ?? textbox.fontWeight ?? "400");
|
|
13502
|
+
const fontFamily = String(((_d = tb.getValueOfPropertyAt) == null ? void 0 : _d.call(tb, lineIndex, charIndex, "fontFamily")) ?? textbox.fontFamily ?? "sans-serif");
|
|
13503
|
+
const charSpacing = Number(((_e = tb.getValueOfPropertyAt) == null ? void 0 : _e.call(tb, lineIndex, charIndex, "charSpacing")) ?? textbox.charSpacing ?? 0);
|
|
13504
|
+
const deltaY = Number(((_f = tb.getValueOfPropertyAt) == null ? void 0 : _f.call(tb, lineIndex, charIndex, "deltaY")) ?? 0);
|
|
13505
|
+
ctx.font = `${fontStyle} normal ${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
13506
|
+
const charWidth = Math.max(0, ctx.measureText(grapheme).width);
|
|
13507
|
+
let kernedWidth = charWidth;
|
|
13508
|
+
const previous = charIndex > 0 ? graphemes[charIndex - 1] : "";
|
|
13509
|
+
if (previous) {
|
|
13510
|
+
const pairWidth = ctx.measureText(previous + grapheme).width;
|
|
13511
|
+
const previousWidth = ctx.measureText(previous).width;
|
|
13512
|
+
if (Number.isFinite(pairWidth) && Number.isFinite(previousWidth)) {
|
|
13513
|
+
kernedWidth = Math.max(0, pairWidth - previousWidth);
|
|
13514
|
+
}
|
|
13515
|
+
}
|
|
13516
|
+
if (charIndex < graphemes.length - 1 && charSpacing) {
|
|
13517
|
+
kernedWidth += charSpacing / 1e3 * fontSize;
|
|
13518
|
+
}
|
|
13519
|
+
bounds[charIndex] = { left, width: charWidth, kernedWidth, height: fontSize, deltaY };
|
|
13520
|
+
left += kernedWidth;
|
|
13521
|
+
});
|
|
13522
|
+
bounds[graphemes.length] = { left, width: 0, kernedWidth: 0, height: Number(textbox.fontSize ?? 16), deltaY: 0 };
|
|
13523
|
+
nextCharBounds[lineIndex] = bounds;
|
|
13524
|
+
nextLineWidths[lineIndex] = Math.max(0, left);
|
|
13525
|
+
});
|
|
13526
|
+
tb.__charBounds = nextCharBounds;
|
|
13527
|
+
tb.__lineWidths = nextLineWidths;
|
|
13528
|
+
textbox.dirty = true;
|
|
13529
|
+
};
|
|
13530
|
+
const visit = (obj) => {
|
|
13531
|
+
if (obj instanceof fabric__namespace.Textbox) syncTextbox(obj);
|
|
13532
|
+
else if (obj instanceof fabric__namespace.Group) obj.getObjects().forEach(visit);
|
|
13533
|
+
};
|
|
13534
|
+
fabricInstance.getObjects().forEach(visit);
|
|
13535
|
+
}
|
|
13435
13536
|
async waitForStableTextMetrics(container, config) {
|
|
13436
13537
|
var _a, _b, _c;
|
|
13437
13538
|
if (typeof document !== "undefined") {
|