@pixldocs/canvas-renderer 0.5.209 → 0.5.211
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-DOIdbh-Q.js → index-C0tTvSFQ.js} +41 -20
- package/dist/index-C0tTvSFQ.js.map +1 -0
- package/dist/{index-DQF_on2h.cjs → index-d8U2oDzI.cjs} +41 -20
- package/dist/index-d8U2oDzI.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1 -1
- package/dist/{vectorPdfExport-C0GsER0C.js → vectorPdfExport-BEGl71uB.js} +213 -39
- package/dist/vectorPdfExport-BEGl71uB.js.map +1 -0
- package/dist/{vectorPdfExport-B04JIcJr.cjs → vectorPdfExport-QzySzFJJ.cjs} +213 -39
- package/dist/vectorPdfExport-QzySzFJJ.cjs.map +1 -0
- package/package.json +1 -1
- package/dist/index-DOIdbh-Q.js.map +0 -1
- package/dist/index-DQF_on2h.cjs.map +0 -1
- package/dist/vectorPdfExport-B04JIcJr.cjs.map +0 -1
- package/dist/vectorPdfExport-C0GsER0C.js.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-d8U2oDzI.cjs");
|
|
7
7
|
const pdfFonts = require("./pdfFonts-BTj2f465.cjs");
|
|
8
8
|
function _interopNamespaceDefault(e) {
|
|
9
9
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
@@ -143,6 +143,32 @@ function elementHasFade(element) {
|
|
|
143
143
|
const yieldToUI = () => new Promise((resolve) => {
|
|
144
144
|
requestAnimationFrame(() => setTimeout(resolve, 0));
|
|
145
145
|
});
|
|
146
|
+
const IS_SAFARI = typeof navigator !== "undefined" && /^((?!chrome|android|crios|fxios).)*safari/i.test(navigator.userAgent || "");
|
|
147
|
+
const IS_IOS = typeof navigator !== "undefined" && /iPad|iPhone|iPod/.test(navigator.userAgent || "");
|
|
148
|
+
const SAFARI_MAX_SIDE = IS_IOS ? 4096 : 16384;
|
|
149
|
+
const SAFARI_MAX_AREA = IS_IOS ? 16777216 : 268435456;
|
|
150
|
+
function getSafeCanvasDims(w, h) {
|
|
151
|
+
const width = Math.max(1, Math.round(w));
|
|
152
|
+
const height = Math.max(1, Math.round(h));
|
|
153
|
+
if (!IS_SAFARI) return { width, height, scale: 1 };
|
|
154
|
+
const sideScale = Math.min(1, SAFARI_MAX_SIDE / Math.max(width, height));
|
|
155
|
+
const areaScale = Math.min(1, Math.sqrt(SAFARI_MAX_AREA / (width * height)));
|
|
156
|
+
const scale = Math.min(sideScale, areaScale);
|
|
157
|
+
if (scale >= 1) return { width, height, scale: 1 };
|
|
158
|
+
return {
|
|
159
|
+
width: Math.max(1, Math.floor(width * scale)),
|
|
160
|
+
height: Math.max(1, Math.floor(height * scale)),
|
|
161
|
+
scale
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
async function ensureImageDecoded(img) {
|
|
165
|
+
try {
|
|
166
|
+
if (typeof img.decode === "function") {
|
|
167
|
+
await img.decode();
|
|
168
|
+
}
|
|
169
|
+
} catch {
|
|
170
|
+
}
|
|
171
|
+
}
|
|
146
172
|
const SHADOW_RASTER_ALPHA_COMPENSATION = 0.84;
|
|
147
173
|
function collectFontSpecsFromShadowMarkup(markup) {
|
|
148
174
|
const specs = /* @__PURE__ */ new Set();
|
|
@@ -333,6 +359,7 @@ async function rasterizeStoredCropImageToPng(options) {
|
|
|
333
359
|
}
|
|
334
360
|
});
|
|
335
361
|
if (!img) return null;
|
|
362
|
+
await ensureImageDecoded(img);
|
|
336
363
|
const natW = Math.max(1, naturalWidth || img.naturalWidth || frameW);
|
|
337
364
|
const natH = Math.max(1, naturalHeight || img.naturalHeight || frameH);
|
|
338
365
|
const baseScale = Math.max(frameW / natW, frameH / natH);
|
|
@@ -347,8 +374,11 @@ async function rasterizeStoredCropImageToPng(options) {
|
|
|
347
374
|
const offsetY = overflowY > 0 ? -overflowY * (clampedPanY - 0.5) : 0;
|
|
348
375
|
const imgX = frameW / 2 + offsetX - drawW / 2;
|
|
349
376
|
const imgY = frameH / 2 + offsetY - drawH / 2;
|
|
350
|
-
const
|
|
351
|
-
const
|
|
377
|
+
const requestedW = maintainResolution && natW > frameW ? Math.max(1, Math.round(natW)) : Math.max(1, Math.round(frameW * 2));
|
|
378
|
+
const requestedH = maintainResolution && natH > frameH ? Math.max(1, Math.round(natH)) : Math.max(1, Math.round(frameH * 2));
|
|
379
|
+
const safe = getSafeCanvasDims(requestedW, requestedH);
|
|
380
|
+
const outW = safe.width;
|
|
381
|
+
const outH = safe.height;
|
|
352
382
|
const canvas = document.createElement("canvas");
|
|
353
383
|
canvas.width = outW;
|
|
354
384
|
canvas.height = outH;
|
|
@@ -510,6 +540,51 @@ function parseSvgNumber(value) {
|
|
|
510
540
|
const n = Number(match[0]);
|
|
511
541
|
return Number.isFinite(n) && n > 0 ? n : null;
|
|
512
542
|
}
|
|
543
|
+
function getPdfJpegQuality() {
|
|
544
|
+
return Math.max(0.5, Math.min(0.95, Number(__pdfJpegQuality) || 0.82));
|
|
545
|
+
}
|
|
546
|
+
function getCompressedRasterSizing(quality) {
|
|
547
|
+
if (quality >= 0.9) return { density: 2.25, maxEdge: 2600 };
|
|
548
|
+
if (quality >= 0.8) return { density: 1.9, maxEdge: 2200 };
|
|
549
|
+
if (quality >= 0.65) return { density: 1.45, maxEdge: 1700 };
|
|
550
|
+
return { density: 1.15, maxEdge: 1300 };
|
|
551
|
+
}
|
|
552
|
+
async function decodeImageForPdf(src) {
|
|
553
|
+
return new Promise((resolve) => {
|
|
554
|
+
try {
|
|
555
|
+
const img = new Image();
|
|
556
|
+
if (!src.startsWith("data:") && !src.startsWith("blob:")) img.crossOrigin = "anonymous";
|
|
557
|
+
img.onload = async () => {
|
|
558
|
+
try {
|
|
559
|
+
if (typeof img.decode === "function") await img.decode();
|
|
560
|
+
} catch {
|
|
561
|
+
}
|
|
562
|
+
resolve((img.naturalWidth || img.width) && (img.naturalHeight || img.height) ? img : null);
|
|
563
|
+
};
|
|
564
|
+
img.onerror = () => resolve(null);
|
|
565
|
+
img.src = src;
|
|
566
|
+
} catch {
|
|
567
|
+
resolve(null);
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
function decodedImageHasAlpha(img, width, height) {
|
|
572
|
+
try {
|
|
573
|
+
const sample = document.createElement("canvas");
|
|
574
|
+
sample.width = Math.min(32, Math.max(1, width));
|
|
575
|
+
sample.height = Math.min(32, Math.max(1, height));
|
|
576
|
+
const ctx = sample.getContext("2d");
|
|
577
|
+
if (!ctx) return false;
|
|
578
|
+
ctx.clearRect(0, 0, sample.width, sample.height);
|
|
579
|
+
ctx.drawImage(img, 0, 0, sample.width, sample.height);
|
|
580
|
+
const pixels = ctx.getImageData(0, 0, sample.width, sample.height).data;
|
|
581
|
+
for (let i = 3; i < pixels.length; i += 4) {
|
|
582
|
+
if (pixels[i] < 255) return true;
|
|
583
|
+
}
|
|
584
|
+
} catch {
|
|
585
|
+
}
|
|
586
|
+
return false;
|
|
587
|
+
}
|
|
513
588
|
function getApproxSvgTransformScale(image) {
|
|
514
589
|
let sx = 1;
|
|
515
590
|
let sy = 1;
|
|
@@ -536,6 +611,61 @@ function getApproxSvgTransformScale(image) {
|
|
|
536
611
|
}
|
|
537
612
|
return { x: Math.max(0.01, Math.abs(sx)), y: Math.max(0.01, Math.abs(sy)) };
|
|
538
613
|
}
|
|
614
|
+
async function rewriteCompressedLiveSvgRasterImages(svg) {
|
|
615
|
+
if (!__pdfCompressImages || typeof document === "undefined") return;
|
|
616
|
+
const images = Array.from(svg.querySelectorAll("image")).filter((image) => {
|
|
617
|
+
const href = getSvgImageHref(image).trim();
|
|
618
|
+
return /^data:image\/(?:png|jpe?g|webp|avif)[;,]/i.test(href);
|
|
619
|
+
});
|
|
620
|
+
if (images.length === 0) return;
|
|
621
|
+
const jpegQuality = getPdfJpegQuality();
|
|
622
|
+
const sizing = getCompressedRasterSizing(jpegQuality);
|
|
623
|
+
let rewritten = 0;
|
|
624
|
+
for (const image of images) {
|
|
625
|
+
const href = getSvgImageHref(image).trim();
|
|
626
|
+
const loaded = await decodeImageForPdf(href);
|
|
627
|
+
if (!loaded) continue;
|
|
628
|
+
const naturalW = Math.max(1, Math.round(loaded.naturalWidth || loaded.width || 1));
|
|
629
|
+
const naturalH = Math.max(1, Math.round(loaded.naturalHeight || loaded.height || 1));
|
|
630
|
+
const attrW = parseSvgNumber(image.getAttribute("width")) || naturalW;
|
|
631
|
+
const attrH = parseSvgNumber(image.getAttribute("height")) || naturalH;
|
|
632
|
+
const transformScale = getApproxSvgTransformScale(image);
|
|
633
|
+
let targetW = Math.max(1, Math.round(Math.min(naturalW, Math.max(attrW, attrW * transformScale.x * sizing.density))));
|
|
634
|
+
let targetH = Math.max(1, Math.round(Math.min(naturalH, Math.max(attrH, attrH * transformScale.y * sizing.density))));
|
|
635
|
+
const longest = Math.max(targetW, targetH);
|
|
636
|
+
if (longest > sizing.maxEdge) {
|
|
637
|
+
const scale = sizing.maxEdge / longest;
|
|
638
|
+
targetW = Math.max(1, Math.round(targetW * scale));
|
|
639
|
+
targetH = Math.max(1, Math.round(targetH * scale));
|
|
640
|
+
}
|
|
641
|
+
const hasAlpha = !/^data:image\/jpe?g[;,]/i.test(href) && decodedImageHasAlpha(loaded, naturalW, naturalH);
|
|
642
|
+
const canvas = document.createElement("canvas");
|
|
643
|
+
canvas.width = targetW;
|
|
644
|
+
canvas.height = targetH;
|
|
645
|
+
const ctx = canvas.getContext("2d");
|
|
646
|
+
if (!ctx) continue;
|
|
647
|
+
if (hasAlpha) {
|
|
648
|
+
ctx.clearRect(0, 0, targetW, targetH);
|
|
649
|
+
} else {
|
|
650
|
+
ctx.fillStyle = "#ffffff";
|
|
651
|
+
ctx.fillRect(0, 0, targetW, targetH);
|
|
652
|
+
}
|
|
653
|
+
ctx.imageSmoothingEnabled = true;
|
|
654
|
+
try {
|
|
655
|
+
ctx.imageSmoothingQuality = "high";
|
|
656
|
+
} catch {
|
|
657
|
+
}
|
|
658
|
+
ctx.drawImage(loaded, 0, 0, targetW, targetH);
|
|
659
|
+
const next = hasAlpha ? canvas.toDataURL("image/png") : canvas.toDataURL("image/jpeg", jpegQuality);
|
|
660
|
+
image.setAttribute("href", next);
|
|
661
|
+
if (image.hasAttribute("xlink:href")) image.setAttribute("xlink:href", next);
|
|
662
|
+
image.setAttribute("data-pixldocs-compressed-pdf-asset", hasAlpha ? "PNG" : "JPEG");
|
|
663
|
+
rewritten++;
|
|
664
|
+
}
|
|
665
|
+
if (rewritten > 0) {
|
|
666
|
+
console.log(`[client-pdf-export] compressed ${rewritten} live SVG raster image(s) @ q=${jpegQuality}`);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
539
669
|
async function rewriteSafariInlineJpegImagesToPng(svg) {
|
|
540
670
|
if (!isSafariLikeForInlineJpegSvgPdf() || typeof document === "undefined") return;
|
|
541
671
|
const jpegImages = Array.from(svg.querySelectorAll("image")).filter((image) => /^data:image\/jpe?g[;,]/i.test(getSvgImageHref(image)));
|
|
@@ -581,8 +711,7 @@ async function rewriteSafariInlineJpegImagesToPng(svg) {
|
|
|
581
711
|
const transformScale = getApproxSvgTransformScale(image);
|
|
582
712
|
const renderedW = attrW * transformScale.x;
|
|
583
713
|
const renderedH = attrH * transformScale.y;
|
|
584
|
-
const density =
|
|
585
|
-
const maxEdge = 1800;
|
|
714
|
+
const { density, maxEdge } = getCompressedRasterSizing(getPdfJpegQuality());
|
|
586
715
|
targetW = Math.max(1, Math.round(Math.min(attrW, renderedW * density || attrW)));
|
|
587
716
|
targetH = Math.max(1, Math.round(Math.min(attrH, renderedH * density || attrH)));
|
|
588
717
|
const longest = Math.max(targetW, targetH);
|
|
@@ -592,7 +721,6 @@ async function rewriteSafariInlineJpegImagesToPng(svg) {
|
|
|
592
721
|
targetH = Math.max(1, Math.round(targetH * scale));
|
|
593
722
|
}
|
|
594
723
|
}
|
|
595
|
-
const outputAsPng = __pdfCompressImages;
|
|
596
724
|
let pngDataUrl = null;
|
|
597
725
|
for (const shrink of __pdfCompressImages ? [1, 0.82, 0.68, 0.55] : [1]) {
|
|
598
726
|
const canvas = document.createElement("canvas");
|
|
@@ -603,7 +731,7 @@ async function rewriteSafariInlineJpegImagesToPng(svg) {
|
|
|
603
731
|
ctx.fillStyle = "#ffffff";
|
|
604
732
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
605
733
|
ctx.drawImage(loaded, 0, 0, canvas.width, canvas.height);
|
|
606
|
-
pngDataUrl =
|
|
734
|
+
pngDataUrl = canvas.toDataURL("image/jpeg", __pdfCompressImages ? getPdfJpegQuality() : 1);
|
|
607
735
|
if (!__pdfCompressImages || estimateDataUrlBytesForPdf(pngDataUrl) <= 4e6 || shrink === 0.55) break;
|
|
608
736
|
}
|
|
609
737
|
if (blobUrl) URL.revokeObjectURL(blobUrl);
|
|
@@ -648,8 +776,7 @@ async function rewriteUnsupportedRasterImagesForSvgPdf(svg) {
|
|
|
648
776
|
const transformScale = getApproxSvgTransformScale(image);
|
|
649
777
|
const renderedW = attrW * transformScale.x;
|
|
650
778
|
const renderedH = attrH * transformScale.y;
|
|
651
|
-
const density =
|
|
652
|
-
const maxEdge = 2200;
|
|
779
|
+
const { density, maxEdge } = getCompressedRasterSizing(getPdfJpegQuality());
|
|
653
780
|
targetW = Math.max(1, Math.round(Math.min(bitmap.width || attrW, renderedW * density || attrW)));
|
|
654
781
|
targetH = Math.max(1, Math.round(Math.min(bitmap.height || attrH, renderedH * density || attrH)));
|
|
655
782
|
const longest = Math.max(targetW, targetH);
|
|
@@ -692,7 +819,7 @@ async function rewriteUnsupportedRasterImagesForSvgPdf(svg) {
|
|
|
692
819
|
} catch {
|
|
693
820
|
}
|
|
694
821
|
ctx.drawImage(bitmap, 0, 0, targetW, targetH);
|
|
695
|
-
const jpegQuality = __pdfCompressImages ?
|
|
822
|
+
const jpegQuality = __pdfCompressImages ? getPdfJpegQuality() : 1;
|
|
696
823
|
const safeDataUrl = hasAlpha ? canvas.toDataURL("image/png") : canvas.toDataURL("image/jpeg", jpegQuality);
|
|
697
824
|
image.setAttribute("href", safeDataUrl);
|
|
698
825
|
if (image.hasAttribute("xlink:href")) image.setAttribute("xlink:href", safeDataUrl);
|
|
@@ -844,6 +971,28 @@ function isInSvgDefinitionSubtree(el) {
|
|
|
844
971
|
}
|
|
845
972
|
return false;
|
|
846
973
|
}
|
|
974
|
+
async function encodePdfRasterDataUrl(dataUrl, options) {
|
|
975
|
+
if (!__pdfCompressImages || !(options == null ? void 0 : options.allowJpeg)) return { data: dataUrl, format: "PNG" };
|
|
976
|
+
const loaded = await decodeImageForPdf(dataUrl);
|
|
977
|
+
if (!loaded) return { data: dataUrl, format: "PNG" };
|
|
978
|
+
const w = Math.max(1, Math.round(loaded.naturalWidth || loaded.width || 1));
|
|
979
|
+
const h = Math.max(1, Math.round(loaded.naturalHeight || loaded.height || 1));
|
|
980
|
+
if (decodedImageHasAlpha(loaded, w, h)) return { data: dataUrl, format: "PNG" };
|
|
981
|
+
const canvas = document.createElement("canvas");
|
|
982
|
+
canvas.width = w;
|
|
983
|
+
canvas.height = h;
|
|
984
|
+
const ctx = canvas.getContext("2d");
|
|
985
|
+
if (!ctx) return { data: dataUrl, format: "PNG" };
|
|
986
|
+
ctx.fillStyle = "#ffffff";
|
|
987
|
+
ctx.fillRect(0, 0, w, h);
|
|
988
|
+
ctx.imageSmoothingEnabled = true;
|
|
989
|
+
try {
|
|
990
|
+
ctx.imageSmoothingQuality = "high";
|
|
991
|
+
} catch {
|
|
992
|
+
}
|
|
993
|
+
ctx.drawImage(loaded, 0, 0, w, h);
|
|
994
|
+
return { data: canvas.toDataURL("image/jpeg", getPdfJpegQuality()), format: "JPEG" };
|
|
995
|
+
}
|
|
847
996
|
function parseInlineSvgStyleDeclarations(styleText) {
|
|
848
997
|
return styleText.split(";").map((part) => part.trim()).filter(Boolean).map((part) => {
|
|
849
998
|
const idx = part.indexOf(":");
|
|
@@ -2195,6 +2344,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
|
|
|
2195
2344
|
}
|
|
2196
2345
|
sanitizeSvgTreeForPdf(svgToDraw);
|
|
2197
2346
|
await replaceLiveSvgRasterImagesWithOriginalAssets(svgToDraw, options == null ? void 0 : options.originalRasterImagesById);
|
|
2347
|
+
await rewriteCompressedLiveSvgRasterImages(svgToDraw);
|
|
2198
2348
|
await rewriteUnsupportedRasterImagesForSvgPdf(svgToDraw);
|
|
2199
2349
|
await rewriteSafariInlineJpegImagesToPng(svgToDraw);
|
|
2200
2350
|
try {
|
|
@@ -2820,7 +2970,7 @@ async function fetchSvgAsElement(imageUrl, colorMap) {
|
|
|
2820
2970
|
async function getRecoloredSvgDataUrl(imageUrl, colorMap) {
|
|
2821
2971
|
if (!colorMap || Object.keys(colorMap).length === 0) return null;
|
|
2822
2972
|
try {
|
|
2823
|
-
const { getNormalizedSvgUrl } = await Promise.resolve().then(() => require("./index-
|
|
2973
|
+
const { getNormalizedSvgUrl } = await Promise.resolve().then(() => require("./index-d8U2oDzI.cjs")).then((n) => n.canvasImageLoader);
|
|
2824
2974
|
return await getNormalizedSvgUrl(imageUrl, colorMap);
|
|
2825
2975
|
} catch {
|
|
2826
2976
|
return null;
|
|
@@ -3516,7 +3666,7 @@ function __setPdfJpegQuality(v) {
|
|
|
3516
3666
|
if (typeof v === "number" && isFinite(v) && v > 0 && v <= 1) __pdfJpegQuality = v;
|
|
3517
3667
|
}
|
|
3518
3668
|
function pdfRasterCompression() {
|
|
3519
|
-
return __pdfCompressImages ? "SLOW" : "
|
|
3669
|
+
return __pdfCompressImages ? "SLOW" : "FAST";
|
|
3520
3670
|
}
|
|
3521
3671
|
function normalizeBgColor(bg) {
|
|
3522
3672
|
if (!bg || bg === "transparent" || bg === "none") return "#ffffff";
|
|
@@ -3566,9 +3716,11 @@ function getTargetPixelSize(bitmap, opts) {
|
|
|
3566
3716
|
if (!__pdfCompressImages && !(opts.resolutionMultiplier && opts.resolutionMultiplier > 1)) {
|
|
3567
3717
|
return { w: bitmap.width, h: bitmap.height };
|
|
3568
3718
|
}
|
|
3569
|
-
const
|
|
3719
|
+
const quality = getPdfJpegQuality();
|
|
3720
|
+
const compressedSizing = getCompressedRasterSizing(quality);
|
|
3721
|
+
const dpiScale = (__pdfCompressImages ? compressedSizing.density : 1.5) * (opts.resolutionMultiplier ?? 1);
|
|
3570
3722
|
const hasMultiplier = !!(opts.resolutionMultiplier && opts.resolutionMultiplier > 1);
|
|
3571
|
-
const maxPx = !__pdfCompressImages ? 1e4 : hasMultiplier ?
|
|
3723
|
+
const maxPx = !__pdfCompressImages ? 1e4 : hasMultiplier ? Math.max(3200, compressedSizing.maxEdge * 1.7) : compressedSizing.maxEdge;
|
|
3572
3724
|
const capByBitmap = !(opts.resolutionMultiplier && opts.resolutionMultiplier > 1);
|
|
3573
3725
|
const desiredW = Math.max(1, Math.round((opts.targetWidthPt ?? bitmap.width) * dpiScale));
|
|
3574
3726
|
const desiredH = Math.max(1, Math.round((opts.targetHeightPt ?? bitmap.height) * dpiScale));
|
|
@@ -3598,7 +3750,7 @@ async function rasterizeToDataUrl(blob, opts, out, flattenBackground) {
|
|
|
3598
3750
|
}
|
|
3599
3751
|
ctx.drawImage(bitmap, 0, 0, w, h);
|
|
3600
3752
|
if (out === "JPEG") {
|
|
3601
|
-
const quality = __pdfCompressImages ?
|
|
3753
|
+
const quality = __pdfCompressImages ? getPdfJpegQuality() : 1;
|
|
3602
3754
|
return canvas.toDataURL("image/jpeg", quality);
|
|
3603
3755
|
}
|
|
3604
3756
|
return canvas.toDataURL("image/png");
|
|
@@ -3627,7 +3779,7 @@ async function fetchImageAsBase64(imageUrl, opts = {}) {
|
|
|
3627
3779
|
}
|
|
3628
3780
|
let fetchUrl = imageUrl;
|
|
3629
3781
|
if (imageUrl.startsWith("http://") || imageUrl.startsWith("https://")) {
|
|
3630
|
-
const { isPrivateUrl } = await Promise.resolve().then(() => require("./index-
|
|
3782
|
+
const { isPrivateUrl } = await Promise.resolve().then(() => require("./index-d8U2oDzI.cjs")).then((n) => n.canvasImageLoader);
|
|
3631
3783
|
if (isPrivateUrl(imageUrl)) return null;
|
|
3632
3784
|
const proxyUrl = new URL(`${index.API_URL}/image-proxy`);
|
|
3633
3785
|
proxyUrl.searchParams.set("url", imageUrl);
|
|
@@ -3856,6 +4008,7 @@ async function rasterizeCropGroupToPng(liveGroup, frameW, frameH, multiplier = 2
|
|
|
3856
4008
|
}
|
|
3857
4009
|
}
|
|
3858
4010
|
if (htmlImg) {
|
|
4011
|
+
await ensureImageDecoded(htmlImg);
|
|
3859
4012
|
const iw = htmlImg.naturalWidth || useNatW;
|
|
3860
4013
|
const ih = htmlImg.naturalHeight || useNatH;
|
|
3861
4014
|
const baseScale = Math.max(frameW / iw, frameH / ih);
|
|
@@ -3873,39 +4026,42 @@ async function rasterizeCropGroupToPng(liveGroup, frameW, frameH, multiplier = 2
|
|
|
3873
4026
|
const srcW = Math.min(Math.ceil(frameW / finalScale), iw - srcX);
|
|
3874
4027
|
const srcH = Math.min(Math.ceil(frameH / finalScale), ih - srcY);
|
|
3875
4028
|
if (srcW >= 1 && srcH >= 1) {
|
|
4029
|
+
const safeCrop = getSafeCanvasDims(srcW, srcH);
|
|
3876
4030
|
const cropCanvas = document.createElement("canvas");
|
|
3877
|
-
cropCanvas.width =
|
|
3878
|
-
cropCanvas.height =
|
|
4031
|
+
cropCanvas.width = safeCrop.width;
|
|
4032
|
+
cropCanvas.height = safeCrop.height;
|
|
3879
4033
|
const ctx = cropCanvas.getContext("2d");
|
|
3880
4034
|
if (ctx) {
|
|
4035
|
+
const dstW = safeCrop.width;
|
|
4036
|
+
const dstH = safeCrop.height;
|
|
3881
4037
|
if (bgFill) {
|
|
3882
4038
|
ctx.fillStyle = bgFill;
|
|
3883
|
-
ctx.fillRect(0, 0,
|
|
4039
|
+
ctx.fillRect(0, 0, dstW, dstH);
|
|
3884
4040
|
} else {
|
|
3885
|
-
ctx.clearRect(0, 0,
|
|
4041
|
+
ctx.clearRect(0, 0, dstW, dstH);
|
|
3886
4042
|
}
|
|
3887
|
-
ctx.drawImage(htmlImg, srcX, srcY, srcW, srcH, 0, 0,
|
|
4043
|
+
ctx.drawImage(htmlImg, srcX, srcY, srcW, srcH, 0, 0, dstW, dstH);
|
|
3888
4044
|
if (shape === "circle" || shape === "roundRect" || shape === "rect") {
|
|
3889
4045
|
ctx.globalCompositeOperation = "destination-in";
|
|
3890
4046
|
if (shape === "circle") {
|
|
3891
4047
|
ctx.beginPath();
|
|
3892
|
-
ctx.ellipse(
|
|
4048
|
+
ctx.ellipse(dstW / 2, dstH / 2, dstW / 2, dstH / 2, 0, 0, 2 * Math.PI);
|
|
3893
4049
|
ctx.fill();
|
|
3894
4050
|
} else {
|
|
3895
4051
|
const rx2 = Math.min(
|
|
3896
|
-
(rxRatio > 0.5 ? rxRatio : rxRatio * minFrameDim) * (
|
|
3897
|
-
|
|
3898
|
-
|
|
4052
|
+
(rxRatio > 0.5 ? rxRatio : rxRatio * minFrameDim) * (dstW / frameW),
|
|
4053
|
+
dstW / 2,
|
|
4054
|
+
dstH / 2
|
|
3899
4055
|
);
|
|
3900
4056
|
const r = Math.max(0, rx2);
|
|
3901
4057
|
ctx.beginPath();
|
|
3902
4058
|
ctx.moveTo(r, 0);
|
|
3903
|
-
ctx.lineTo(
|
|
3904
|
-
if (r > 0) ctx.quadraticCurveTo(
|
|
3905
|
-
ctx.lineTo(
|
|
3906
|
-
if (r > 0) ctx.quadraticCurveTo(
|
|
3907
|
-
ctx.lineTo(r,
|
|
3908
|
-
if (r > 0) ctx.quadraticCurveTo(0,
|
|
4059
|
+
ctx.lineTo(dstW - r, 0);
|
|
4060
|
+
if (r > 0) ctx.quadraticCurveTo(dstW, 0, dstW, r);
|
|
4061
|
+
ctx.lineTo(dstW, dstH - r);
|
|
4062
|
+
if (r > 0) ctx.quadraticCurveTo(dstW, dstH, dstW - r, dstH);
|
|
4063
|
+
ctx.lineTo(r, dstH);
|
|
4064
|
+
if (r > 0) ctx.quadraticCurveTo(0, dstH, 0, dstH - r);
|
|
3909
4065
|
ctx.lineTo(0, r);
|
|
3910
4066
|
if (r > 0) ctx.quadraticCurveTo(0, 0, r, 0);
|
|
3911
4067
|
ctx.closePath();
|
|
@@ -3924,8 +4080,11 @@ async function rasterizeCropGroupToPng(liveGroup, frameW, frameH, multiplier = 2
|
|
|
3924
4080
|
const natH = (dims == null ? void 0 : dims.height) ?? (stored == null ? void 0 : stored.naturalHeight) ?? frameH;
|
|
3925
4081
|
const useNatW = natW > 0 && natH > 0 ? natW : frameW;
|
|
3926
4082
|
const useNatH = natW > 0 && natH > 0 ? natH : frameH;
|
|
3927
|
-
const
|
|
3928
|
-
const
|
|
4083
|
+
const reqOutW = maintainResolution && useNatW > frameW ? Math.max(1, Math.round(useNatW)) : Math.max(1, Math.round(frameW * multiplier));
|
|
4084
|
+
const reqOutH = maintainResolution && useNatH > frameH ? Math.max(1, Math.round(useNatH)) : Math.max(1, Math.round(frameH * multiplier));
|
|
4085
|
+
const safeOut = getSafeCanvasDims(reqOutW, reqOutH);
|
|
4086
|
+
const outW2 = safeOut.width;
|
|
4087
|
+
const outH2 = safeOut.height;
|
|
3929
4088
|
const proxied = index.getProxiedImageUrl(imageUrl);
|
|
3930
4089
|
const res = await fetch(proxied);
|
|
3931
4090
|
if (!res.ok) throw new Error(`Export blob fetch failed: ${res.status}`);
|
|
@@ -4517,6 +4676,7 @@ async function drawElement(pdf, element, embeddedFonts, canvasWidth, canvasHeigh
|
|
|
4517
4676
|
if (fadedMasked) {
|
|
4518
4677
|
png = fadedMasked;
|
|
4519
4678
|
}
|
|
4679
|
+
const encodedMasked = await encodePdfRasterDataUrl(png, { allowJpeg: !fadedMasked });
|
|
4520
4680
|
if (canUseAdvancedTransforms2 && fabricMatrix && fabricMatrix.length === 6) {
|
|
4521
4681
|
const mPdf = fabricMatrixToJsPdfAdvancedMatrix(fabricMatrix);
|
|
4522
4682
|
const localX = -frameW / 2;
|
|
@@ -4524,13 +4684,13 @@ async function drawElement(pdf, element, embeddedFonts, canvasWidth, canvasHeigh
|
|
|
4524
4684
|
anyPdf2.advancedAPI(() => {
|
|
4525
4685
|
pdf.saveGraphicsState();
|
|
4526
4686
|
anyPdf2.setCurrentTransformationMatrix(anyPdf2.Matrix(...mPdf));
|
|
4527
|
-
pdf.addImage(
|
|
4687
|
+
pdf.addImage(encodedMasked.data, encodedMasked.format, localX, localY, frameW, frameH, void 0, pdfRasterCompression());
|
|
4528
4688
|
pdf.restoreGraphicsState();
|
|
4529
4689
|
});
|
|
4530
4690
|
pdf.setGState(pdf.GState({ opacity: 1, "stroke-opacity": 1 }));
|
|
4531
4691
|
return;
|
|
4532
4692
|
}
|
|
4533
|
-
pdf.addImage(
|
|
4693
|
+
pdf.addImage(encodedMasked.data, encodedMasked.format, norm.x, norm.y, frameW, frameH, void 0, pdfRasterCompression());
|
|
4534
4694
|
pdf.setGState(pdf.GState({ opacity: 1, "stroke-opacity": 1 }));
|
|
4535
4695
|
return;
|
|
4536
4696
|
}
|
|
@@ -5037,8 +5197,8 @@ async function drawElementContentCore(pdf, element, norm, x, y, w, h, embeddedFo
|
|
|
5037
5197
|
if (croppedPng) {
|
|
5038
5198
|
try {
|
|
5039
5199
|
const fadedCrop = await bakeEdgeFadeIntoDataUrl(croppedPng, element);
|
|
5040
|
-
const
|
|
5041
|
-
pdf.addImage(
|
|
5200
|
+
const encodedCrop = await encodePdfRasterDataUrl(fadedCrop || croppedPng, { allowJpeg: !fadedCrop });
|
|
5201
|
+
pdf.addImage(encodedCrop.data, encodedCrop.format, x, y, w, h, void 0, pdfRasterCompression());
|
|
5042
5202
|
break;
|
|
5043
5203
|
} catch {
|
|
5044
5204
|
}
|
|
@@ -5246,10 +5406,21 @@ function getExpectedRasterImageIdsForPdfPage(page) {
|
|
|
5246
5406
|
function getOriginalRasterImageUrlMapForPdfPage(page) {
|
|
5247
5407
|
const byId = /* @__PURE__ */ new Map();
|
|
5248
5408
|
const isSvgUrl = (url) => /\.svg(?:\?|#|$)/i.test(url) || /^data:image\/svg/i.test(url);
|
|
5409
|
+
const hasVisualImageEffect = (item) => {
|
|
5410
|
+
const hasCrop = item.cropPanX != null || item.cropPanY != null || item.cropZoom != null;
|
|
5411
|
+
const hasMask = item.maskSvgUrl || item.clipShape && item.clipShape !== "none" && item.clipShape !== "rectangle";
|
|
5412
|
+
const hasFade = ["Top", "Right", "Bottom", "Left"].some(
|
|
5413
|
+
(side) => item[`fade${side}Amount`] != null || item[`fade${side}Size`] != null || item[`fade${side}Hardness`] != null
|
|
5414
|
+
);
|
|
5415
|
+
const hasFrame = (item.strokeWidth ?? 0) > 0 || !!item.stroke || (item.rx ?? 0) > 0 || (item.ry ?? 0) > 0;
|
|
5416
|
+
const hasShadowOrFilter = item.shadow || item.shadowColor || item.shadowBlur || item.shadowOffsetX || item.shadowOffsetY || item.filter || item.filters;
|
|
5417
|
+
return Boolean(hasCrop || hasMask || hasFade || hasFrame || hasShadowOrFilter);
|
|
5418
|
+
};
|
|
5249
5419
|
for (const item of page.elements) {
|
|
5250
5420
|
if (isGroupBackgroundDrawable(item) || item.type !== "image" || item.visible === false) continue;
|
|
5251
5421
|
const src = String(item.src || item.imageUrl || "").trim();
|
|
5252
5422
|
if (!src || item.sourceFormat === "svg" || isSvgUrl(src)) continue;
|
|
5423
|
+
if (hasVisualImageEffect(item)) continue;
|
|
5253
5424
|
byId.set(item.id, src);
|
|
5254
5425
|
}
|
|
5255
5426
|
return byId;
|
|
@@ -5295,7 +5466,10 @@ async function __exportMultiPagePdfInner(pages, options) {
|
|
|
5295
5466
|
unit: "px",
|
|
5296
5467
|
format: [firstPage.width, firstPage.height],
|
|
5297
5468
|
hotfixes: ["px_scaling"],
|
|
5298
|
-
|
|
5469
|
+
// Always keep PDF object/stream compression on. The UI's image-compression
|
|
5470
|
+
// switch controls raster resampling/JPEG quality, not lossless PDF packing;
|
|
5471
|
+
// disabling this made "uncompressed image" PDFs balloon with no quality gain.
|
|
5472
|
+
compress: true
|
|
5299
5473
|
});
|
|
5300
5474
|
if (title) {
|
|
5301
5475
|
pdf.setProperties({ title, creator: "DocuForge" });
|
|
@@ -5704,4 +5878,4 @@ exports.exportMultiPagePdf = exportMultiPagePdf;
|
|
|
5704
5878
|
exports.logTextMeasurementDiagnostic = logTextMeasurementDiagnostic;
|
|
5705
5879
|
exports.preparePagesForExport = preparePagesForExport;
|
|
5706
5880
|
exports.rewriteSvgFontsForJsPDFWithSourceMeta = rewriteSvgFontsForJsPDFWithSourceMeta;
|
|
5707
|
-
//# sourceMappingURL=vectorPdfExport-
|
|
5881
|
+
//# sourceMappingURL=vectorPdfExport-QzySzFJJ.cjs.map
|