@pixldocs/canvas-renderer 0.5.143 → 0.5.146
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-r5VzSOHa.cjs → index-DoPXmxDJ.cjs} +10 -6
- package/dist/index-DoPXmxDJ.cjs.map +1 -0
- package/dist/{index-CUpy7HO9.js → index-oR6VOGAL.js} +10 -6
- package/dist/index-oR6VOGAL.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/{vectorPdfExport-GvaizFte.js → vectorPdfExport-DI7k8pt7.js} +147 -8
- package/dist/vectorPdfExport-DI7k8pt7.js.map +1 -0
- package/dist/{vectorPdfExport-JVEe_tSQ.cjs → vectorPdfExport-SMvSP0el.cjs} +147 -8
- package/dist/vectorPdfExport-SMvSP0el.cjs.map +1 -0
- package/package.json +1 -1
- package/dist/index-CUpy7HO9.js.map +0 -1
- package/dist/index-r5VzSOHa.cjs.map +0 -1
- package/dist/vectorPdfExport-GvaizFte.js.map +0 -1
- package/dist/vectorPdfExport-JVEe_tSQ.cjs.map +0 -1
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const jspdf = require("jspdf");
|
|
4
4
|
const svg2pdf_js = require("svg2pdf.js");
|
|
5
5
|
const fabric = require("fabric");
|
|
6
|
-
const index = require("./index-
|
|
6
|
+
const index = require("./index-DoPXmxDJ.cjs");
|
|
7
7
|
const pdfFonts = require("./pdfFonts-BTEVnYX8.cjs");
|
|
8
8
|
function _interopNamespaceDefault(e) {
|
|
9
9
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
@@ -142,6 +142,33 @@ const yieldToUI = () => new Promise((resolve) => {
|
|
|
142
142
|
requestAnimationFrame(() => setTimeout(resolve, 0));
|
|
143
143
|
});
|
|
144
144
|
const SHADOW_RASTER_ALPHA_COMPENSATION = 0.84;
|
|
145
|
+
function collectFontSpecsFromShadowMarkup(markup) {
|
|
146
|
+
const specs = /* @__PURE__ */ new Set();
|
|
147
|
+
const re = /<(?:text|tspan)\b[^>]*>/gi;
|
|
148
|
+
let match;
|
|
149
|
+
while ((match = re.exec(markup)) !== null) {
|
|
150
|
+
const tag = match[0];
|
|
151
|
+
const get = (attr) => {
|
|
152
|
+
const m = tag.match(new RegExp(`\\s${attr}\\s*=\\s*"([^"]*)"`, "i"));
|
|
153
|
+
if (m) return m[1];
|
|
154
|
+
const styleM = tag.match(/\sstyle\s*=\s*"([^"]*)"/i);
|
|
155
|
+
if (styleM) {
|
|
156
|
+
const sm = styleM[1].match(new RegExp(`${attr}\\s*:\\s*([^;]+)`, "i"));
|
|
157
|
+
if (sm) return sm[1].trim();
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
};
|
|
161
|
+
const family = (get("font-family") || "").split(",")[0].replace(/['"]/g, "").trim();
|
|
162
|
+
if (!family) continue;
|
|
163
|
+
const weight = get("font-weight") || "400";
|
|
164
|
+
const style = get("font-style") || "normal";
|
|
165
|
+
const size = get("font-size") || "16px";
|
|
166
|
+
const sizePx = /[a-z%]/i.test(size) ? size : `${size}px`;
|
|
167
|
+
const famSpec = /\s/.test(family) ? `"${family}"` : family;
|
|
168
|
+
specs.add(`${style} ${weight} ${sizePx} ${famSpec}`);
|
|
169
|
+
}
|
|
170
|
+
return Array.from(specs);
|
|
171
|
+
}
|
|
145
172
|
let debugSvgDrawSequence = 0;
|
|
146
173
|
function debugLog(...args) {
|
|
147
174
|
}
|
|
@@ -1227,6 +1254,105 @@ async function bakeTextAnchorPositionsFromLiveSvg(svg) {
|
|
|
1227
1254
|
}
|
|
1228
1255
|
}
|
|
1229
1256
|
}
|
|
1257
|
+
async function logTextMeasurementDiagnostic(svg) {
|
|
1258
|
+
var _a, _b, _c, _d, _e;
|
|
1259
|
+
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
1260
|
+
try {
|
|
1261
|
+
const params = new URLSearchParams(((_a = window.location) == null ? void 0 : _a.search) || "");
|
|
1262
|
+
if (params.get("pdfdiag") !== "1") return;
|
|
1263
|
+
} catch {
|
|
1264
|
+
return;
|
|
1265
|
+
}
|
|
1266
|
+
if (!svg) return;
|
|
1267
|
+
const tempContainer = document.createElement("div");
|
|
1268
|
+
tempContainer.style.cssText = "position:fixed;left:-9999px;top:-9999px;visibility:hidden;pointer-events:none;";
|
|
1269
|
+
const clone = svg.cloneNode(true);
|
|
1270
|
+
for (const tn of clone.querySelectorAll("text, tspan, textPath")) {
|
|
1271
|
+
const sf = tn.getAttribute("data-source-font-family");
|
|
1272
|
+
const sw = tn.getAttribute("data-source-font-weight");
|
|
1273
|
+
const ss = tn.getAttribute("data-source-font-style");
|
|
1274
|
+
if (sf) tn.setAttribute("font-family", sf);
|
|
1275
|
+
if (sw) tn.setAttribute("font-weight", sw);
|
|
1276
|
+
if (ss) tn.setAttribute("font-style", ss);
|
|
1277
|
+
}
|
|
1278
|
+
tempContainer.appendChild(clone);
|
|
1279
|
+
document.body.appendChild(tempContainer);
|
|
1280
|
+
const measureCanvas = document.createElement("canvas");
|
|
1281
|
+
const mctx = measureCanvas.getContext("2d");
|
|
1282
|
+
try {
|
|
1283
|
+
const liveTexts = Array.from(clone.querySelectorAll("text"));
|
|
1284
|
+
const srcTexts = Array.from(svg.querySelectorAll("text"));
|
|
1285
|
+
const rows = [];
|
|
1286
|
+
for (let i = 0; i < liveTexts.length; i++) {
|
|
1287
|
+
const live = liveTexts[i];
|
|
1288
|
+
const src = srcTexts[i];
|
|
1289
|
+
if (!live || !src) continue;
|
|
1290
|
+
const liveTspans = Array.from(live.querySelectorAll("tspan"));
|
|
1291
|
+
const srcTspans = Array.from(src.querySelectorAll("tspan"));
|
|
1292
|
+
const tspans = liveTspans.length ? liveTspans : [live];
|
|
1293
|
+
const srcs = srcTspans.length ? srcTspans : [src];
|
|
1294
|
+
for (let j = 0; j < tspans.length; j++) {
|
|
1295
|
+
const ln = tspans[j];
|
|
1296
|
+
const sn = srcs[j];
|
|
1297
|
+
const text = ln.textContent || "";
|
|
1298
|
+
const fam = (ln.getAttribute("font-family") || "").replace(/['"]/g, "").trim();
|
|
1299
|
+
const wt = ln.getAttribute("font-weight") || "400";
|
|
1300
|
+
const sty = ln.getAttribute("font-style") || "normal";
|
|
1301
|
+
const sz = parseFloat(ln.getAttribute("font-size") || src.getAttribute("font-size") || "16") || 16;
|
|
1302
|
+
let domX = null;
|
|
1303
|
+
let bboxW = null;
|
|
1304
|
+
try {
|
|
1305
|
+
if (ln.getNumberOfChars && ln.getNumberOfChars() > 0) {
|
|
1306
|
+
domX = ln.getStartPositionOfChar(0).x;
|
|
1307
|
+
}
|
|
1308
|
+
} catch {
|
|
1309
|
+
}
|
|
1310
|
+
try {
|
|
1311
|
+
bboxW = ((_b = ln.getBBox) == null ? void 0 : _b.call(ln).width) ?? null;
|
|
1312
|
+
} catch {
|
|
1313
|
+
}
|
|
1314
|
+
let canvasW = null;
|
|
1315
|
+
if (mctx) {
|
|
1316
|
+
mctx.font = `${sty} ${wt} ${sz}px "${fam}"`;
|
|
1317
|
+
try {
|
|
1318
|
+
canvasW = mctx.measureText(text).width;
|
|
1319
|
+
} catch {
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
rows.push({
|
|
1323
|
+
line: text.length > 40 ? text.slice(0, 37) + "..." : text,
|
|
1324
|
+
font: `${fam} ${wt} ${sty}`,
|
|
1325
|
+
size: sz,
|
|
1326
|
+
srcAnchor: sn.getAttribute("text-anchor") || ((_c = sn.parentElement) == null ? void 0 : _c.getAttribute("text-anchor")) || "",
|
|
1327
|
+
srcX: sn.getAttribute("x") || ((_d = sn.parentElement) == null ? void 0 : _d.getAttribute("x")) || "",
|
|
1328
|
+
domX: domX !== null ? +domX.toFixed(2) : null,
|
|
1329
|
+
bboxW: bboxW !== null ? +bboxW.toFixed(2) : null,
|
|
1330
|
+
measureCtxW: canvasW !== null ? +canvasW.toFixed(2) : null
|
|
1331
|
+
});
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
if (rows.length > 0) {
|
|
1335
|
+
console.log("[PDF-DIAG] ===== text measurement diagnostic =====");
|
|
1336
|
+
console.log(
|
|
1337
|
+
"[PDF-DIAG] env=",
|
|
1338
|
+
typeof navigator !== "undefined" ? navigator.userAgent.slice(0, 80) : "n/a",
|
|
1339
|
+
"dpr=",
|
|
1340
|
+
window.devicePixelRatio,
|
|
1341
|
+
"fontsReady=",
|
|
1342
|
+
!!((_e = document.fonts) == null ? void 0 : _e.ready)
|
|
1343
|
+
);
|
|
1344
|
+
for (const r of rows) {
|
|
1345
|
+
console.log("[PDF-DIAG]", JSON.stringify(r));
|
|
1346
|
+
}
|
|
1347
|
+
console.log("[PDF-DIAG] ===== end =====");
|
|
1348
|
+
}
|
|
1349
|
+
} finally {
|
|
1350
|
+
try {
|
|
1351
|
+
document.body.removeChild(tempContainer);
|
|
1352
|
+
} catch {
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1230
1356
|
async function _convertTextDecorationsToLines_impl(svg) {
|
|
1231
1357
|
const doc = svg.ownerDocument;
|
|
1232
1358
|
if (!doc) return;
|
|
@@ -1423,7 +1549,7 @@ async function convertSvgTextDecorationsToLinesString(svgStr) {
|
|
|
1423
1549
|
}
|
|
1424
1550
|
}
|
|
1425
1551
|
async function rasterizeShadowMarkers(svg) {
|
|
1426
|
-
var _a, _b, _c, _d, _e;
|
|
1552
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1427
1553
|
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
1428
1554
|
const markers = Array.from(svg.querySelectorAll("g.__pdShadowRaster"));
|
|
1429
1555
|
if (markers.length === 0) return;
|
|
@@ -1450,6 +1576,17 @@ async function rasterizeShadowMarkers(svg) {
|
|
|
1450
1576
|
const innerXml = restoreSourceFontsForShadowRaster(
|
|
1451
1577
|
Array.from(marker.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("")
|
|
1452
1578
|
);
|
|
1579
|
+
try {
|
|
1580
|
+
const fontSpecs = collectFontSpecsFromShadowMarkup(innerXml);
|
|
1581
|
+
if (fontSpecs.length > 0 && ((_c = document.fonts) == null ? void 0 : _c.load)) {
|
|
1582
|
+
await Promise.all(
|
|
1583
|
+
fontSpecs.map(
|
|
1584
|
+
(spec) => document.fonts.load(spec).catch(() => void 0)
|
|
1585
|
+
)
|
|
1586
|
+
);
|
|
1587
|
+
}
|
|
1588
|
+
} catch {
|
|
1589
|
+
}
|
|
1453
1590
|
const scale = 2;
|
|
1454
1591
|
const pxW = Math.min(4096, Math.max(8, Math.ceil(bw * scale)));
|
|
1455
1592
|
const pxH = Math.min(4096, Math.max(8, Math.ceil(bh * scale)));
|
|
@@ -1459,7 +1596,7 @@ async function rasterizeShadowMarkers(svg) {
|
|
|
1459
1596
|
const miniSvg = `<svg xmlns="${SVG_NS}" xmlns:xlink="${XLINK_NS}" width="${pxW}" height="${pxH}" viewBox="${bx} ${by} ${bw} ${bh}">${styleBlock}<defs><filter id="${filterId}" filterUnits="userSpaceOnUse" x="${bx}" y="${by}" width="${bw}" height="${bh}" color-interpolation-filters="sRGB"><feOffset dx="${ox}" dy="${oy}" result="offsetShadow" /><feGaussianBlur in="offsetShadow" stdDeviation="${stdDev}" /></filter></defs><g filter="url(#${filterId})">${innerXml}</g></svg>`;
|
|
1460
1597
|
const dataUrl = await rasterSvgToPngDataUrl(miniSvg, pxW, pxH);
|
|
1461
1598
|
if (!dataUrl) {
|
|
1462
|
-
(
|
|
1599
|
+
(_d = marker.parentNode) == null ? void 0 : _d.removeChild(marker);
|
|
1463
1600
|
continue;
|
|
1464
1601
|
}
|
|
1465
1602
|
const img = svg.ownerDocument.createElementNS(SVG_NS, "image");
|
|
@@ -1471,11 +1608,11 @@ async function rasterizeShadowMarkers(svg) {
|
|
|
1471
1608
|
img.setAttribute("preserveAspectRatio", "none");
|
|
1472
1609
|
img.setAttributeNS(XLINK_NS, "xlink:href", dataUrl);
|
|
1473
1610
|
img.setAttribute("href", dataUrl);
|
|
1474
|
-
(
|
|
1611
|
+
(_e = marker.parentNode) == null ? void 0 : _e.replaceChild(img, marker);
|
|
1475
1612
|
} catch (error) {
|
|
1476
1613
|
console.warn("[Vector PDF] text shadow rasterization failed for one marker:", error);
|
|
1477
1614
|
try {
|
|
1478
|
-
(
|
|
1615
|
+
(_f = marker.parentNode) == null ? void 0 : _f.removeChild(marker);
|
|
1479
1616
|
} catch {
|
|
1480
1617
|
}
|
|
1481
1618
|
}
|
|
@@ -1677,6 +1814,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
|
|
|
1677
1814
|
}
|
|
1678
1815
|
sanitizeSvgTreeForPdf(svgToDraw);
|
|
1679
1816
|
try {
|
|
1817
|
+
await logTextMeasurementDiagnostic(svgToDraw);
|
|
1680
1818
|
await bakeTextAnchorPositionsFromLiveSvg(svgToDraw);
|
|
1681
1819
|
} catch (e) {
|
|
1682
1820
|
console.warn("[Vector PDF] anchor-bake pass failed (continuing):", e);
|
|
@@ -2267,7 +2405,7 @@ async function fetchSvgAsElement(imageUrl, colorMap) {
|
|
|
2267
2405
|
async function getRecoloredSvgDataUrl(imageUrl, colorMap) {
|
|
2268
2406
|
if (!colorMap || Object.keys(colorMap).length === 0) return null;
|
|
2269
2407
|
try {
|
|
2270
|
-
const { getNormalizedSvgUrl } = await Promise.resolve().then(() => require("./index-
|
|
2408
|
+
const { getNormalizedSvgUrl } = await Promise.resolve().then(() => require("./index-DoPXmxDJ.cjs")).then((n) => n.canvasImageLoader);
|
|
2271
2409
|
return await getNormalizedSvgUrl(imageUrl, colorMap);
|
|
2272
2410
|
} catch {
|
|
2273
2411
|
return null;
|
|
@@ -3048,7 +3186,7 @@ async function fetchImageAsBase64(imageUrl, opts = {}) {
|
|
|
3048
3186
|
}
|
|
3049
3187
|
let fetchUrl = imageUrl;
|
|
3050
3188
|
if (imageUrl.startsWith("http://") || imageUrl.startsWith("https://")) {
|
|
3051
|
-
const { isPrivateUrl } = await Promise.resolve().then(() => require("./index-
|
|
3189
|
+
const { isPrivateUrl } = await Promise.resolve().then(() => require("./index-DoPXmxDJ.cjs")).then((n) => n.canvasImageLoader);
|
|
3052
3190
|
if (isPrivateUrl(imageUrl)) return null;
|
|
3053
3191
|
const proxyUrl = new URL(`${index.API_URL}/image-proxy`);
|
|
3054
3192
|
proxyUrl.searchParams.set("url", imageUrl);
|
|
@@ -5027,6 +5165,7 @@ exports.drawPreparedLiveCanvasSvgPageToPdf = drawPreparedLiveCanvasSvgPageToPdf;
|
|
|
5027
5165
|
exports.embedFontsForSvg = embedFontsForSvg;
|
|
5028
5166
|
exports.exportFabricCanvasToVectorPdf = exportFabricCanvasToVectorPdf;
|
|
5029
5167
|
exports.exportMultiPagePdf = exportMultiPagePdf;
|
|
5168
|
+
exports.logTextMeasurementDiagnostic = logTextMeasurementDiagnostic;
|
|
5030
5169
|
exports.preparePagesForExport = preparePagesForExport;
|
|
5031
5170
|
exports.rewriteSvgFontsForJsPDFWithSourceMeta = rewriteSvgFontsForJsPDFWithSourceMeta;
|
|
5032
|
-
//# sourceMappingURL=vectorPdfExport-
|
|
5171
|
+
//# sourceMappingURL=vectorPdfExport-SMvSP0el.cjs.map
|