@pixldocs/canvas-renderer 0.5.18 → 0.5.20
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 +177 -106
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +177 -106
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -11863,6 +11863,83 @@ async function ensureFontsForResolvedConfig(config) {
|
|
|
11863
11863
|
});
|
|
11864
11864
|
}
|
|
11865
11865
|
}
|
|
11866
|
+
const TEXT_TYPES = /* @__PURE__ */ new Set(["textbox", "text", "i-text"]);
|
|
11867
|
+
function getTextLines(obj) {
|
|
11868
|
+
const lines = Array.isArray(obj.textLines) && obj.textLines.length ? obj.textLines : String(obj.text || "").split("\n");
|
|
11869
|
+
return lines.map((line) => Array.isArray(line) ? line.join("") : String(line ?? ""));
|
|
11870
|
+
}
|
|
11871
|
+
function measureLineWidth(obj, line) {
|
|
11872
|
+
if (typeof document === "undefined") return 0;
|
|
11873
|
+
const canvas = document.createElement("canvas");
|
|
11874
|
+
const ctx = canvas.getContext("2d");
|
|
11875
|
+
if (!ctx) return 0;
|
|
11876
|
+
const fontStyle = obj.fontStyle || "normal";
|
|
11877
|
+
const fontWeight = obj.fontWeight || 400;
|
|
11878
|
+
const fontSize = obj.fontSize || 16;
|
|
11879
|
+
const fontFamily = obj.fontFamily || "sans-serif";
|
|
11880
|
+
ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
11881
|
+
const charSpacing = Number(obj.charSpacing || 0) / 1e3 * fontSize;
|
|
11882
|
+
return ctx.measureText(line).width + Math.max(0, line.length - 1) * charSpacing;
|
|
11883
|
+
}
|
|
11884
|
+
function getFabricCanvasFromContainer(container) {
|
|
11885
|
+
const registry2 = window.__fabricCanvasRegistry;
|
|
11886
|
+
if (registry2 instanceof Map) {
|
|
11887
|
+
for (const entry of registry2.values()) {
|
|
11888
|
+
const canvas = (entry == null ? void 0 : entry.canvas) || entry;
|
|
11889
|
+
if (!canvas || typeof canvas.toSVG !== "function") continue;
|
|
11890
|
+
const el = canvas.lowerCanvasEl || canvas.upperCanvasEl;
|
|
11891
|
+
if (el && container.contains(el)) return canvas;
|
|
11892
|
+
}
|
|
11893
|
+
}
|
|
11894
|
+
return null;
|
|
11895
|
+
}
|
|
11896
|
+
function stabilizeFabricTextObjects(fabricInstance) {
|
|
11897
|
+
var _a, _b, _c;
|
|
11898
|
+
if (!(fabricInstance == null ? void 0 : fabricInstance.getObjects)) return;
|
|
11899
|
+
clearFabricCharCache();
|
|
11900
|
+
clearMeasurementCache();
|
|
11901
|
+
const walk = (obj) => {
|
|
11902
|
+
var _a2, _b2, _c2, _d;
|
|
11903
|
+
if (!obj) return;
|
|
11904
|
+
const children = Array.isArray(obj._objects) ? obj._objects : Array.isArray(obj.objects) ? obj.objects : [];
|
|
11905
|
+
if (children.length) children.forEach(walk);
|
|
11906
|
+
const isTextObject = typeof obj.text === "string" && typeof obj.initDimensions === "function" && (TEXT_TYPES.has(obj.type) || obj.isEditing !== void 0);
|
|
11907
|
+
if (!isTextObject) return;
|
|
11908
|
+
const saved = { width: obj.width, scaleX: obj.scaleX, scaleY: obj.scaleY };
|
|
11909
|
+
const reset = () => {
|
|
11910
|
+
var _a3;
|
|
11911
|
+
(_a3 = obj._clearCache) == null ? void 0 : _a3.call(obj);
|
|
11912
|
+
obj.__charBounds = [];
|
|
11913
|
+
obj.__lineWidths = [];
|
|
11914
|
+
obj.__lineHeights = [];
|
|
11915
|
+
obj.__graphemeLines = [];
|
|
11916
|
+
obj._textLines = [];
|
|
11917
|
+
obj.textLines = [];
|
|
11918
|
+
obj._styleMap = null;
|
|
11919
|
+
obj.styleMap = null;
|
|
11920
|
+
obj.dirty = true;
|
|
11921
|
+
};
|
|
11922
|
+
reset();
|
|
11923
|
+
obj.initDimensions();
|
|
11924
|
+
if (saved.width != null) {
|
|
11925
|
+
(_a2 = obj.set) == null ? void 0 : _a2.call(obj, { width: saved.width, scaleX: saved.scaleX, scaleY: saved.scaleY });
|
|
11926
|
+
reset();
|
|
11927
|
+
obj.initDimensions();
|
|
11928
|
+
(_b2 = obj.set) == null ? void 0 : _b2.call(obj, { width: saved.width, scaleX: saved.scaleX, scaleY: saved.scaleY });
|
|
11929
|
+
}
|
|
11930
|
+
if (obj.underline || obj.linethrough) {
|
|
11931
|
+
const lineWidths = Array.isArray(obj.__lineWidths) ? obj.__lineWidths : [];
|
|
11932
|
+
obj.__lineWidths = getTextLines(obj).map((line, index) => Math.max(lineWidths[index] || 0, measureLineWidth(obj, line)));
|
|
11933
|
+
}
|
|
11934
|
+
obj.dirty = true;
|
|
11935
|
+
(_c2 = obj._clearCache) == null ? void 0 : _c2.call(obj);
|
|
11936
|
+
(_d = obj.setCoords) == null ? void 0 : _d.call(obj);
|
|
11937
|
+
};
|
|
11938
|
+
fabricInstance.getObjects().forEach(walk);
|
|
11939
|
+
(_a = fabricInstance.calcOffset) == null ? void 0 : _a.call(fabricInstance);
|
|
11940
|
+
(_b = fabricInstance.renderAll) == null ? void 0 : _b.call(fabricInstance);
|
|
11941
|
+
(_c = fabricInstance.requestRenderAll) == null ? void 0 : _c.call(fabricInstance);
|
|
11942
|
+
}
|
|
11866
11943
|
function PixldocsPreview(props) {
|
|
11867
11944
|
const {
|
|
11868
11945
|
pageIndex = 0,
|
|
@@ -11959,6 +12036,13 @@ function PixldocsPreview(props) {
|
|
|
11959
12036
|
() => `${pageIndex}-${fontsReadyVersion}-${stabilizationPass}`,
|
|
11960
12037
|
[pageIndex, fontsReadyVersion, stabilizationPass]
|
|
11961
12038
|
);
|
|
12039
|
+
const previewWrapRef = react.useCallback((node) => {
|
|
12040
|
+
if (!node || !config) return;
|
|
12041
|
+
requestAnimationFrame(() => {
|
|
12042
|
+
const fabricCanvas = getFabricCanvasFromContainer(node);
|
|
12043
|
+
if (fabricCanvas) stabilizeFabricTextObjects(fabricCanvas);
|
|
12044
|
+
});
|
|
12045
|
+
}, [config, previewKey]);
|
|
11962
12046
|
react.useEffect(() => {
|
|
11963
12047
|
if (isResolveMode) return;
|
|
11964
12048
|
if (!config) {
|
|
@@ -11989,7 +12073,7 @@ function PixldocsPreview(props) {
|
|
|
11989
12073
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { ...style, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) });
|
|
11990
12074
|
}
|
|
11991
12075
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, style: { ...style, position: "relative" }, children: [
|
|
11992
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { visibility: canvasSettled ? "visible" : "hidden" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
12076
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: previewWrapRef, style: { visibility: canvasSettled ? "visible" : "hidden" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11993
12077
|
PreviewCanvas,
|
|
11994
12078
|
{
|
|
11995
12079
|
config,
|
|
@@ -12004,6 +12088,66 @@ function PixldocsPreview(props) {
|
|
|
12004
12088
|
!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..." }) })
|
|
12005
12089
|
] });
|
|
12006
12090
|
}
|
|
12091
|
+
const inlinedAssetCache = /* @__PURE__ */ new Map();
|
|
12092
|
+
function shouldInlineImageUrl(url) {
|
|
12093
|
+
if (!url || url.startsWith("data:")) return false;
|
|
12094
|
+
if (url.startsWith("blob:")) return true;
|
|
12095
|
+
if (url.startsWith("/") && !url.startsWith("//")) return true;
|
|
12096
|
+
try {
|
|
12097
|
+
const parsed = new URL(url, window.location.href);
|
|
12098
|
+
const current = new URL(window.location.href);
|
|
12099
|
+
const host = parsed.hostname.toLowerCase();
|
|
12100
|
+
return parsed.origin === current.origin || host === "localhost" || host === "127.0.0.1" || host === "0.0.0.0" || host.endsWith(".local") || /^(10\.|192\.168\.|169\.254\.)/.test(host);
|
|
12101
|
+
} catch {
|
|
12102
|
+
return false;
|
|
12103
|
+
}
|
|
12104
|
+
}
|
|
12105
|
+
async function imageUrlToDataUrl(url) {
|
|
12106
|
+
if (inlinedAssetCache.has(url)) return inlinedAssetCache.get(url) ?? null;
|
|
12107
|
+
try {
|
|
12108
|
+
const response = await fetch(url);
|
|
12109
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
12110
|
+
const blob = await response.blob();
|
|
12111
|
+
if (blob.type.includes("text/html")) throw new Error("Expected image but got text/html");
|
|
12112
|
+
const dataUrl = await new Promise((resolve, reject) => {
|
|
12113
|
+
const reader = new FileReader();
|
|
12114
|
+
reader.onloadend = () => resolve(String(reader.result || ""));
|
|
12115
|
+
reader.onerror = reject;
|
|
12116
|
+
reader.readAsDataURL(blob);
|
|
12117
|
+
});
|
|
12118
|
+
inlinedAssetCache.set(url, dataUrl);
|
|
12119
|
+
return dataUrl;
|
|
12120
|
+
} catch (error) {
|
|
12121
|
+
console.warn("[@pixldocs/canvas-renderer] Failed to inline image asset:", url, error);
|
|
12122
|
+
inlinedAssetCache.set(url, null);
|
|
12123
|
+
return null;
|
|
12124
|
+
}
|
|
12125
|
+
}
|
|
12126
|
+
async function inlineNodeAssets(node) {
|
|
12127
|
+
if (node.type === "image") {
|
|
12128
|
+
const url = typeof node.src === "string" && node.src.trim() ? node.src.trim() : typeof node.imageUrl === "string" ? node.imageUrl.trim() : "";
|
|
12129
|
+
if (shouldInlineImageUrl(url)) {
|
|
12130
|
+
const dataUrl = await imageUrlToDataUrl(url);
|
|
12131
|
+
if (dataUrl) {
|
|
12132
|
+
node.src = dataUrl;
|
|
12133
|
+
node.imageUrl = dataUrl;
|
|
12134
|
+
}
|
|
12135
|
+
}
|
|
12136
|
+
}
|
|
12137
|
+
if (Array.isArray(node.children)) {
|
|
12138
|
+
await Promise.all(node.children.map(inlineNodeAssets));
|
|
12139
|
+
}
|
|
12140
|
+
}
|
|
12141
|
+
async function inlineBrowserReachableImageAssets(config) {
|
|
12142
|
+
if (typeof window === "undefined" || typeof fetch === "undefined" || typeof FileReader === "undefined") {
|
|
12143
|
+
return config;
|
|
12144
|
+
}
|
|
12145
|
+
const cloned = JSON.parse(JSON.stringify(config));
|
|
12146
|
+
await Promise.all(
|
|
12147
|
+
(cloned.pages || []).flatMap((page) => (page.children || []).map(inlineNodeAssets))
|
|
12148
|
+
);
|
|
12149
|
+
return cloned;
|
|
12150
|
+
}
|
|
12007
12151
|
class PixldocsRenderer {
|
|
12008
12152
|
constructor(config) {
|
|
12009
12153
|
__publicField(this, "config");
|
|
@@ -12014,21 +12158,22 @@ class PixldocsRenderer {
|
|
|
12014
12158
|
* Mounts a hidden PreviewCanvas component and captures the Fabric canvas output.
|
|
12015
12159
|
*/
|
|
12016
12160
|
async render(templateConfig, options = {}) {
|
|
12161
|
+
const renderConfig = await inlineBrowserReachableImageAssets(templateConfig);
|
|
12017
12162
|
const pageIndex = options.pageIndex ?? 0;
|
|
12018
12163
|
const format = options.format ?? "png";
|
|
12019
12164
|
const quality = options.quality ?? 0.92;
|
|
12020
12165
|
const pixelRatio = options.pixelRatio ?? this.config.pixelRatio ?? 2;
|
|
12021
|
-
const canvasWidth =
|
|
12022
|
-
const canvasHeight =
|
|
12023
|
-
const page =
|
|
12166
|
+
const canvasWidth = renderConfig.canvas.width;
|
|
12167
|
+
const canvasHeight = renderConfig.canvas.height;
|
|
12168
|
+
const page = renderConfig.pages[pageIndex];
|
|
12024
12169
|
if (!page) {
|
|
12025
|
-
throw new Error(`Page index ${pageIndex} not found (template has ${
|
|
12170
|
+
throw new Error(`Page index ${pageIndex} not found (template has ${renderConfig.pages.length} pages)`);
|
|
12026
12171
|
}
|
|
12027
|
-
await ensureFontsForResolvedConfig(
|
|
12172
|
+
await ensureFontsForResolvedConfig(renderConfig);
|
|
12028
12173
|
const { setPackageApiUrl: setPackageApiUrl2 } = await Promise.resolve().then(() => appApi);
|
|
12029
12174
|
setPackageApiUrl2(this.config.imageProxyUrl);
|
|
12030
12175
|
const dataUrl = await this.renderPageViaPreviewCanvas(
|
|
12031
|
-
|
|
12176
|
+
renderConfig,
|
|
12032
12177
|
pageIndex,
|
|
12033
12178
|
pixelRatio,
|
|
12034
12179
|
format,
|
|
@@ -12080,16 +12225,17 @@ class PixldocsRenderer {
|
|
|
12080
12225
|
* This is the key building block for client-side vector PDF export.
|
|
12081
12226
|
*/
|
|
12082
12227
|
async renderPageSvg(templateConfig, pageIndex = 0) {
|
|
12083
|
-
const
|
|
12228
|
+
const renderConfig = await inlineBrowserReachableImageAssets(templateConfig);
|
|
12229
|
+
const page = renderConfig.pages[pageIndex];
|
|
12084
12230
|
if (!page) {
|
|
12085
|
-
throw new Error(`Page index ${pageIndex} not found (template has ${
|
|
12231
|
+
throw new Error(`Page index ${pageIndex} not found (template has ${renderConfig.pages.length} pages)`);
|
|
12086
12232
|
}
|
|
12087
|
-
await ensureFontsForResolvedConfig(
|
|
12233
|
+
await ensureFontsForResolvedConfig(renderConfig);
|
|
12088
12234
|
const { setPackageApiUrl: setPackageApiUrl2 } = await Promise.resolve().then(() => appApi);
|
|
12089
12235
|
setPackageApiUrl2(this.config.imageProxyUrl);
|
|
12090
|
-
const canvasWidth =
|
|
12091
|
-
const canvasHeight =
|
|
12092
|
-
return this.captureSvgViaPreviewCanvas(
|
|
12236
|
+
const canvasWidth = renderConfig.canvas.width;
|
|
12237
|
+
const canvasHeight = renderConfig.canvas.height;
|
|
12238
|
+
return this.captureSvgViaPreviewCanvas(renderConfig, pageIndex, canvasWidth, canvasHeight);
|
|
12093
12239
|
}
|
|
12094
12240
|
/**
|
|
12095
12241
|
* Render all pages and return SVG strings for each.
|
|
@@ -12437,7 +12583,7 @@ class PixldocsRenderer {
|
|
|
12437
12583
|
cleanup();
|
|
12438
12584
|
reject(new Error("Render timeout (30s)"));
|
|
12439
12585
|
}, 3e4);
|
|
12440
|
-
let
|
|
12586
|
+
let finished = false;
|
|
12441
12587
|
const cleanup = () => {
|
|
12442
12588
|
clearTimeout(timeout);
|
|
12443
12589
|
try {
|
|
@@ -12447,22 +12593,12 @@ class PixldocsRenderer {
|
|
|
12447
12593
|
container.remove();
|
|
12448
12594
|
};
|
|
12449
12595
|
const onReady = () => {
|
|
12450
|
-
if (
|
|
12451
|
-
|
|
12452
|
-
root.render(
|
|
12453
|
-
react.createElement(PreviewCanvas2, {
|
|
12454
|
-
config,
|
|
12455
|
-
pageIndex,
|
|
12456
|
-
zoom: pixelRatio,
|
|
12457
|
-
absoluteZoom: true,
|
|
12458
|
-
skipFontReadyWait: true,
|
|
12459
|
-
onReady
|
|
12460
|
-
})
|
|
12461
|
-
);
|
|
12462
|
-
return;
|
|
12463
|
-
}
|
|
12596
|
+
if (finished) return;
|
|
12597
|
+
finished = true;
|
|
12464
12598
|
this.waitForCanvasScene(container, config, pageIndex).then(async () => {
|
|
12465
12599
|
try {
|
|
12600
|
+
await this.waitForStableTextMetrics(container, config);
|
|
12601
|
+
await this.waitForCanvasScene(container, config, pageIndex, 2500, 50);
|
|
12466
12602
|
const fabricInstance = this.getFabricCanvasFromContainer(container);
|
|
12467
12603
|
const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
|
|
12468
12604
|
await this.waitForCanvasImages(container, expectedImageCount);
|
|
@@ -12533,7 +12669,7 @@ class PixldocsRenderer {
|
|
|
12533
12669
|
cleanup();
|
|
12534
12670
|
reject(new Error("SVG render timeout (30s)"));
|
|
12535
12671
|
}, 3e4);
|
|
12536
|
-
let
|
|
12672
|
+
let finished = false;
|
|
12537
12673
|
const cleanup = () => {
|
|
12538
12674
|
clearTimeout(timeout);
|
|
12539
12675
|
try {
|
|
@@ -12543,23 +12679,13 @@ class PixldocsRenderer {
|
|
|
12543
12679
|
container.remove();
|
|
12544
12680
|
};
|
|
12545
12681
|
const onReady = () => {
|
|
12546
|
-
if (
|
|
12547
|
-
|
|
12548
|
-
root.render(
|
|
12549
|
-
react.createElement(PreviewCanvas2, {
|
|
12550
|
-
config,
|
|
12551
|
-
pageIndex,
|
|
12552
|
-
zoom: 1,
|
|
12553
|
-
absoluteZoom: true,
|
|
12554
|
-
skipFontReadyWait: true,
|
|
12555
|
-
onReady
|
|
12556
|
-
})
|
|
12557
|
-
);
|
|
12558
|
-
return;
|
|
12559
|
-
}
|
|
12682
|
+
if (finished) return;
|
|
12683
|
+
finished = true;
|
|
12560
12684
|
this.waitForCanvasScene(container, config, pageIndex).then(async () => {
|
|
12561
12685
|
var _a, _b;
|
|
12562
12686
|
try {
|
|
12687
|
+
await this.waitForStableTextMetrics(container, config);
|
|
12688
|
+
await this.waitForCanvasScene(container, config, pageIndex, 2500, 50);
|
|
12563
12689
|
const fabricInstance = this.getFabricCanvasFromContainer(container);
|
|
12564
12690
|
if (!fabricInstance) {
|
|
12565
12691
|
cleanup();
|
|
@@ -12679,16 +12805,7 @@ class PixldocsRenderer {
|
|
|
12679
12805
|
* using the global __fabricCanvasRegistry (set by PageCanvas).
|
|
12680
12806
|
*/
|
|
12681
12807
|
getFabricCanvasFromContainer(container) {
|
|
12682
|
-
|
|
12683
|
-
if (registry2 instanceof Map) {
|
|
12684
|
-
for (const entry of registry2.values()) {
|
|
12685
|
-
const canvas = (entry == null ? void 0 : entry.canvas) || entry;
|
|
12686
|
-
if (!canvas || typeof canvas.toSVG !== "function") continue;
|
|
12687
|
-
const el = canvas.lowerCanvasEl || canvas.upperCanvasEl;
|
|
12688
|
-
if (el && container.contains(el)) return canvas;
|
|
12689
|
-
}
|
|
12690
|
-
}
|
|
12691
|
-
return null;
|
|
12808
|
+
return getFabricCanvasFromContainer(container);
|
|
12692
12809
|
}
|
|
12693
12810
|
async waitForStableTextMetrics(container, config) {
|
|
12694
12811
|
if (typeof document !== "undefined") {
|
|
@@ -12702,59 +12819,7 @@ class PixldocsRenderer {
|
|
|
12702
12819
|
clearFabricCharCache();
|
|
12703
12820
|
clearMeasurementCache();
|
|
12704
12821
|
};
|
|
12705
|
-
const reflowTextboxes = () =>
|
|
12706
|
-
var _a, _b, _c;
|
|
12707
|
-
const walk = (obj) => {
|
|
12708
|
-
var _a2, _b2, _c2, _d;
|
|
12709
|
-
if (!obj) return;
|
|
12710
|
-
const children = Array.isArray(obj._objects) ? obj._objects : Array.isArray(obj.objects) ? obj.objects : [];
|
|
12711
|
-
if (children.length) children.forEach(walk);
|
|
12712
|
-
const isTextObject = typeof obj.text === "string" && typeof obj.initDimensions === "function" && (obj.type === "textbox" || obj.type === "text" || obj.type === "i-text" || obj.isEditing !== void 0);
|
|
12713
|
-
if (isTextObject) {
|
|
12714
|
-
const saved = {
|
|
12715
|
-
width: obj.width,
|
|
12716
|
-
scaleX: obj.scaleX,
|
|
12717
|
-
scaleY: obj.scaleY
|
|
12718
|
-
};
|
|
12719
|
-
const resetTextboxLayoutInternals = () => {
|
|
12720
|
-
var _a3;
|
|
12721
|
-
(_a3 = obj._clearCache) == null ? void 0 : _a3.call(obj);
|
|
12722
|
-
obj.__charBounds = [];
|
|
12723
|
-
obj.__lineWidths = [];
|
|
12724
|
-
obj.__lineHeights = [];
|
|
12725
|
-
obj.__graphemeLines = [];
|
|
12726
|
-
obj._textLines = [];
|
|
12727
|
-
obj.textLines = [];
|
|
12728
|
-
obj._styleMap = null;
|
|
12729
|
-
obj.styleMap = null;
|
|
12730
|
-
obj.dirty = true;
|
|
12731
|
-
};
|
|
12732
|
-
resetTextboxLayoutInternals();
|
|
12733
|
-
obj.initDimensions();
|
|
12734
|
-
if (saved.width != null) {
|
|
12735
|
-
(_a2 = obj.set) == null ? void 0 : _a2.call(obj, {
|
|
12736
|
-
width: saved.width,
|
|
12737
|
-
scaleX: saved.scaleX,
|
|
12738
|
-
scaleY: saved.scaleY
|
|
12739
|
-
});
|
|
12740
|
-
resetTextboxLayoutInternals();
|
|
12741
|
-
obj.initDimensions();
|
|
12742
|
-
}
|
|
12743
|
-
(_b2 = obj.set) == null ? void 0 : _b2.call(obj, {
|
|
12744
|
-
width: saved.width,
|
|
12745
|
-
scaleX: saved.scaleX,
|
|
12746
|
-
scaleY: saved.scaleY,
|
|
12747
|
-
dirty: true
|
|
12748
|
-
});
|
|
12749
|
-
(_c2 = obj._clearCache) == null ? void 0 : _c2.call(obj);
|
|
12750
|
-
(_d = obj.setCoords) == null ? void 0 : _d.call(obj);
|
|
12751
|
-
}
|
|
12752
|
-
};
|
|
12753
|
-
fabricInstance.getObjects().forEach(walk);
|
|
12754
|
-
(_a = fabricInstance.calcOffset) == null ? void 0 : _a.call(fabricInstance);
|
|
12755
|
-
(_b = fabricInstance.renderAll) == null ? void 0 : _b.call(fabricInstance);
|
|
12756
|
-
(_c = fabricInstance.requestRenderAll) == null ? void 0 : _c.call(fabricInstance);
|
|
12757
|
-
};
|
|
12822
|
+
const reflowTextboxes = () => stabilizeFabricTextObjects(fabricInstance);
|
|
12758
12823
|
clearTextMetricCaches();
|
|
12759
12824
|
await waitForPaint();
|
|
12760
12825
|
reflowTextboxes();
|
|
@@ -14510,6 +14575,12 @@ function convertTextDecorationsToLines(svg) {
|
|
|
14510
14575
|
} else {
|
|
14511
14576
|
textWidth = content.length * fontSize * 0.6;
|
|
14512
14577
|
}
|
|
14578
|
+
if (typeof tspan.getComputedTextLength === "function") {
|
|
14579
|
+
try {
|
|
14580
|
+
textWidth = Math.max(textWidth, tspan.getComputedTextLength());
|
|
14581
|
+
} catch {
|
|
14582
|
+
}
|
|
14583
|
+
}
|
|
14513
14584
|
const underlineY = y + fontSize * 0.15;
|
|
14514
14585
|
const thickness = Math.max(0.5, fontSize * 0.066667);
|
|
14515
14586
|
const line = doc.createElementNS("http://www.w3.org/2000/svg", "line");
|