@pixldocs/canvas-renderer 0.5.210 → 0.5.212
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-DwYUddYW.js → index-B1QDVK5k.js} +102 -22
- package/dist/index-B1QDVK5k.js.map +1 -0
- package/dist/{index-54CXM_hR.cjs → index-DB8j0PV0.cjs} +102 -22
- package/dist/index-DB8j0PV0.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-Ch6GbQqO.js → vectorPdfExport-CN-N0DE8.js} +213 -39
- package/dist/vectorPdfExport-CN-N0DE8.js.map +1 -0
- package/dist/{vectorPdfExport-BSK-Z1p4.cjs → vectorPdfExport-zGrrm-iT.cjs} +213 -39
- package/dist/vectorPdfExport-zGrrm-iT.cjs.map +1 -0
- package/package.json +1 -1
- package/dist/index-54CXM_hR.cjs.map +0 -1
- package/dist/index-DwYUddYW.js.map +0 -1
- package/dist/vectorPdfExport-BSK-Z1p4.cjs.map +0 -1
- package/dist/vectorPdfExport-Ch6GbQqO.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const index = require("./index-
|
|
3
|
+
const index = require("./index-DB8j0PV0.cjs");
|
|
4
4
|
exports.DEPLOYMENT_VERSION_MARKER = index.DEPLOYMENT_VERSION_MARKER;
|
|
5
5
|
exports.FONT_FALLBACK_DEVANAGARI = index.FONT_FALLBACK_DEVANAGARI;
|
|
6
6
|
exports.FONT_FALLBACK_MATH = index.FONT_FALLBACK_MATH;
|
package/dist/index.d.ts
CHANGED
|
@@ -373,6 +373,10 @@ export declare interface PdfFromFormOptions {
|
|
|
373
373
|
* Per-call override of `RendererConfig.maxImageEdgePx`. See that field.
|
|
374
374
|
*/
|
|
375
375
|
maxImageEdgePx?: number;
|
|
376
|
+
/** Preserve original raster bytes when false; use bounded JPEG/PNG optimization when true. */
|
|
377
|
+
compressImages?: boolean;
|
|
378
|
+
/** JPEG quality (0..1) used only when compressImages is true. */
|
|
379
|
+
compressionQuality?: number;
|
|
376
380
|
}
|
|
377
381
|
|
|
378
382
|
export declare interface PdfRenderResult {
|
|
@@ -540,6 +544,8 @@ export declare class PixldocsRenderer {
|
|
|
540
544
|
textMode?: 'auto' | 'selectable' | 'pixel-perfect';
|
|
541
545
|
forcePerElementPdf?: boolean | 'auto';
|
|
542
546
|
maxImageEdgePx?: number;
|
|
547
|
+
compressImages?: boolean;
|
|
548
|
+
compressionQuality?: number;
|
|
543
549
|
}): Promise<PdfRenderResult>;
|
|
544
550
|
/**
|
|
545
551
|
* Resolve from V2 sectionState and render a vector PDF.
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { D, F, o, q, s, P, t, u, v, w, x, y, z, B, C, E, G, H, I, J, K, L, M, b, N, O, Q, R, S, U, V, W, X, Y, Z, _, $, a0, a1, a2, a3, a4, a5 } from "./index-
|
|
1
|
+
import { D, F, o, q, s, P, t, u, v, w, x, y, z, B, C, E, G, H, I, J, K, L, M, b, N, O, Q, R, S, U, V, W, X, Y, Z, _, $, a0, a1, a2, a3, a4, a5 } from "./index-B1QDVK5k.js";
|
|
2
2
|
export {
|
|
3
3
|
D as DEPLOYMENT_VERSION_MARKER,
|
|
4
4
|
F as FONT_FALLBACK_DEVANAGARI,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsPDF, ShadingPattern } from "jspdf";
|
|
2
2
|
import { svg2pdf } from "svg2pdf.js";
|
|
3
3
|
import * as fabric from "fabric";
|
|
4
|
-
import { p as parseTextMarkdown, r as renderSmartElementToSvg, g as getCanvasForPage, c as captureFabricCanvasSvgForPdf, f as findNodeById, a as getAbsoluteBounds, b as getProxiedImageUrl, d as getImageProxyFetchOptions, A as API_URL, n as normalizeShapeType, i as isElement, e as isGroup, h as buildRoundedTrianglePath, j as hasEdgeFade, k as bakeEdgeFade, l as getRoundedRectRadii, T as TRIANGLE_STROKE_MITER_LIMIT, m as getTrianglePoints } from "./index-
|
|
4
|
+
import { p as parseTextMarkdown, r as renderSmartElementToSvg, g as getCanvasForPage, c as captureFabricCanvasSvgForPdf, f as findNodeById, a as getAbsoluteBounds, b as getProxiedImageUrl, d as getImageProxyFetchOptions, A as API_URL, n as normalizeShapeType, i as isElement, e as isGroup, h as buildRoundedTrianglePath, j as hasEdgeFade, k as bakeEdgeFade, l as getRoundedRectRadii, T as TRIANGLE_STROKE_MITER_LIMIT, m as getTrianglePoints } from "./index-B1QDVK5k.js";
|
|
5
5
|
import { resetPdfFontRegistry, FONT_FALLBACK_SYMBOLS, FONT_FALLBACK_MATH, FONT_FALLBACK_DEVANAGARI, embedFontWithGoogleFallback, getEmbeddedVariantsList, isFontAvailable, isFamilyEmbedded, resolveBestRegisteredVariant, getEmbeddedJsPDFFontName, resolveFontWeight, doesVariantSupportChar } from "./pdfFonts-DhEaMTZl.js";
|
|
6
6
|
async function embedFontsForSvg(pdf, svgStr) {
|
|
7
7
|
var _a;
|
|
@@ -124,6 +124,32 @@ function elementHasFade(element) {
|
|
|
124
124
|
const yieldToUI = () => new Promise((resolve) => {
|
|
125
125
|
requestAnimationFrame(() => setTimeout(resolve, 0));
|
|
126
126
|
});
|
|
127
|
+
const IS_SAFARI = typeof navigator !== "undefined" && /^((?!chrome|android|crios|fxios).)*safari/i.test(navigator.userAgent || "");
|
|
128
|
+
const IS_IOS = typeof navigator !== "undefined" && /iPad|iPhone|iPod/.test(navigator.userAgent || "");
|
|
129
|
+
const SAFARI_MAX_SIDE = IS_IOS ? 4096 : 16384;
|
|
130
|
+
const SAFARI_MAX_AREA = IS_IOS ? 16777216 : 268435456;
|
|
131
|
+
function getSafeCanvasDims(w, h) {
|
|
132
|
+
const width = Math.max(1, Math.round(w));
|
|
133
|
+
const height = Math.max(1, Math.round(h));
|
|
134
|
+
if (!IS_SAFARI) return { width, height, scale: 1 };
|
|
135
|
+
const sideScale = Math.min(1, SAFARI_MAX_SIDE / Math.max(width, height));
|
|
136
|
+
const areaScale = Math.min(1, Math.sqrt(SAFARI_MAX_AREA / (width * height)));
|
|
137
|
+
const scale = Math.min(sideScale, areaScale);
|
|
138
|
+
if (scale >= 1) return { width, height, scale: 1 };
|
|
139
|
+
return {
|
|
140
|
+
width: Math.max(1, Math.floor(width * scale)),
|
|
141
|
+
height: Math.max(1, Math.floor(height * scale)),
|
|
142
|
+
scale
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
async function ensureImageDecoded(img) {
|
|
146
|
+
try {
|
|
147
|
+
if (typeof img.decode === "function") {
|
|
148
|
+
await img.decode();
|
|
149
|
+
}
|
|
150
|
+
} catch {
|
|
151
|
+
}
|
|
152
|
+
}
|
|
127
153
|
const SHADOW_RASTER_ALPHA_COMPENSATION = 0.84;
|
|
128
154
|
function collectFontSpecsFromShadowMarkup(markup) {
|
|
129
155
|
const specs = /* @__PURE__ */ new Set();
|
|
@@ -314,6 +340,7 @@ async function rasterizeStoredCropImageToPng(options) {
|
|
|
314
340
|
}
|
|
315
341
|
});
|
|
316
342
|
if (!img) return null;
|
|
343
|
+
await ensureImageDecoded(img);
|
|
317
344
|
const natW = Math.max(1, naturalWidth || img.naturalWidth || frameW);
|
|
318
345
|
const natH = Math.max(1, naturalHeight || img.naturalHeight || frameH);
|
|
319
346
|
const baseScale = Math.max(frameW / natW, frameH / natH);
|
|
@@ -328,8 +355,11 @@ async function rasterizeStoredCropImageToPng(options) {
|
|
|
328
355
|
const offsetY = overflowY > 0 ? -overflowY * (clampedPanY - 0.5) : 0;
|
|
329
356
|
const imgX = frameW / 2 + offsetX - drawW / 2;
|
|
330
357
|
const imgY = frameH / 2 + offsetY - drawH / 2;
|
|
331
|
-
const
|
|
332
|
-
const
|
|
358
|
+
const requestedW = maintainResolution && natW > frameW ? Math.max(1, Math.round(natW)) : Math.max(1, Math.round(frameW * 2));
|
|
359
|
+
const requestedH = maintainResolution && natH > frameH ? Math.max(1, Math.round(natH)) : Math.max(1, Math.round(frameH * 2));
|
|
360
|
+
const safe = getSafeCanvasDims(requestedW, requestedH);
|
|
361
|
+
const outW = safe.width;
|
|
362
|
+
const outH = safe.height;
|
|
333
363
|
const canvas = document.createElement("canvas");
|
|
334
364
|
canvas.width = outW;
|
|
335
365
|
canvas.height = outH;
|
|
@@ -491,6 +521,51 @@ function parseSvgNumber(value) {
|
|
|
491
521
|
const n = Number(match[0]);
|
|
492
522
|
return Number.isFinite(n) && n > 0 ? n : null;
|
|
493
523
|
}
|
|
524
|
+
function getPdfJpegQuality() {
|
|
525
|
+
return Math.max(0.5, Math.min(0.95, Number(__pdfJpegQuality) || 0.82));
|
|
526
|
+
}
|
|
527
|
+
function getCompressedRasterSizing(quality) {
|
|
528
|
+
if (quality >= 0.9) return { density: 2.25, maxEdge: 2600 };
|
|
529
|
+
if (quality >= 0.8) return { density: 1.9, maxEdge: 2200 };
|
|
530
|
+
if (quality >= 0.65) return { density: 1.45, maxEdge: 1700 };
|
|
531
|
+
return { density: 1.15, maxEdge: 1300 };
|
|
532
|
+
}
|
|
533
|
+
async function decodeImageForPdf(src) {
|
|
534
|
+
return new Promise((resolve) => {
|
|
535
|
+
try {
|
|
536
|
+
const img = new Image();
|
|
537
|
+
if (!src.startsWith("data:") && !src.startsWith("blob:")) img.crossOrigin = "anonymous";
|
|
538
|
+
img.onload = async () => {
|
|
539
|
+
try {
|
|
540
|
+
if (typeof img.decode === "function") await img.decode();
|
|
541
|
+
} catch {
|
|
542
|
+
}
|
|
543
|
+
resolve((img.naturalWidth || img.width) && (img.naturalHeight || img.height) ? img : null);
|
|
544
|
+
};
|
|
545
|
+
img.onerror = () => resolve(null);
|
|
546
|
+
img.src = src;
|
|
547
|
+
} catch {
|
|
548
|
+
resolve(null);
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
function decodedImageHasAlpha(img, width, height) {
|
|
553
|
+
try {
|
|
554
|
+
const sample = document.createElement("canvas");
|
|
555
|
+
sample.width = Math.min(32, Math.max(1, width));
|
|
556
|
+
sample.height = Math.min(32, Math.max(1, height));
|
|
557
|
+
const ctx = sample.getContext("2d");
|
|
558
|
+
if (!ctx) return false;
|
|
559
|
+
ctx.clearRect(0, 0, sample.width, sample.height);
|
|
560
|
+
ctx.drawImage(img, 0, 0, sample.width, sample.height);
|
|
561
|
+
const pixels = ctx.getImageData(0, 0, sample.width, sample.height).data;
|
|
562
|
+
for (let i = 3; i < pixels.length; i += 4) {
|
|
563
|
+
if (pixels[i] < 255) return true;
|
|
564
|
+
}
|
|
565
|
+
} catch {
|
|
566
|
+
}
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
494
569
|
function getApproxSvgTransformScale(image) {
|
|
495
570
|
let sx = 1;
|
|
496
571
|
let sy = 1;
|
|
@@ -517,6 +592,61 @@ function getApproxSvgTransformScale(image) {
|
|
|
517
592
|
}
|
|
518
593
|
return { x: Math.max(0.01, Math.abs(sx)), y: Math.max(0.01, Math.abs(sy)) };
|
|
519
594
|
}
|
|
595
|
+
async function rewriteCompressedLiveSvgRasterImages(svg) {
|
|
596
|
+
if (!__pdfCompressImages || typeof document === "undefined") return;
|
|
597
|
+
const images = Array.from(svg.querySelectorAll("image")).filter((image) => {
|
|
598
|
+
const href = getSvgImageHref(image).trim();
|
|
599
|
+
return /^data:image\/(?:png|jpe?g|webp|avif)[;,]/i.test(href);
|
|
600
|
+
});
|
|
601
|
+
if (images.length === 0) return;
|
|
602
|
+
const jpegQuality = getPdfJpegQuality();
|
|
603
|
+
const sizing = getCompressedRasterSizing(jpegQuality);
|
|
604
|
+
let rewritten = 0;
|
|
605
|
+
for (const image of images) {
|
|
606
|
+
const href = getSvgImageHref(image).trim();
|
|
607
|
+
const loaded = await decodeImageForPdf(href);
|
|
608
|
+
if (!loaded) continue;
|
|
609
|
+
const naturalW = Math.max(1, Math.round(loaded.naturalWidth || loaded.width || 1));
|
|
610
|
+
const naturalH = Math.max(1, Math.round(loaded.naturalHeight || loaded.height || 1));
|
|
611
|
+
const attrW = parseSvgNumber(image.getAttribute("width")) || naturalW;
|
|
612
|
+
const attrH = parseSvgNumber(image.getAttribute("height")) || naturalH;
|
|
613
|
+
const transformScale = getApproxSvgTransformScale(image);
|
|
614
|
+
let targetW = Math.max(1, Math.round(Math.min(naturalW, Math.max(attrW, attrW * transformScale.x * sizing.density))));
|
|
615
|
+
let targetH = Math.max(1, Math.round(Math.min(naturalH, Math.max(attrH, attrH * transformScale.y * sizing.density))));
|
|
616
|
+
const longest = Math.max(targetW, targetH);
|
|
617
|
+
if (longest > sizing.maxEdge) {
|
|
618
|
+
const scale = sizing.maxEdge / longest;
|
|
619
|
+
targetW = Math.max(1, Math.round(targetW * scale));
|
|
620
|
+
targetH = Math.max(1, Math.round(targetH * scale));
|
|
621
|
+
}
|
|
622
|
+
const hasAlpha = !/^data:image\/jpe?g[;,]/i.test(href) && decodedImageHasAlpha(loaded, naturalW, naturalH);
|
|
623
|
+
const canvas = document.createElement("canvas");
|
|
624
|
+
canvas.width = targetW;
|
|
625
|
+
canvas.height = targetH;
|
|
626
|
+
const ctx = canvas.getContext("2d");
|
|
627
|
+
if (!ctx) continue;
|
|
628
|
+
if (hasAlpha) {
|
|
629
|
+
ctx.clearRect(0, 0, targetW, targetH);
|
|
630
|
+
} else {
|
|
631
|
+
ctx.fillStyle = "#ffffff";
|
|
632
|
+
ctx.fillRect(0, 0, targetW, targetH);
|
|
633
|
+
}
|
|
634
|
+
ctx.imageSmoothingEnabled = true;
|
|
635
|
+
try {
|
|
636
|
+
ctx.imageSmoothingQuality = "high";
|
|
637
|
+
} catch {
|
|
638
|
+
}
|
|
639
|
+
ctx.drawImage(loaded, 0, 0, targetW, targetH);
|
|
640
|
+
const next = hasAlpha ? canvas.toDataURL("image/png") : canvas.toDataURL("image/jpeg", jpegQuality);
|
|
641
|
+
image.setAttribute("href", next);
|
|
642
|
+
if (image.hasAttribute("xlink:href")) image.setAttribute("xlink:href", next);
|
|
643
|
+
image.setAttribute("data-pixldocs-compressed-pdf-asset", hasAlpha ? "PNG" : "JPEG");
|
|
644
|
+
rewritten++;
|
|
645
|
+
}
|
|
646
|
+
if (rewritten > 0) {
|
|
647
|
+
console.log(`[client-pdf-export] compressed ${rewritten} live SVG raster image(s) @ q=${jpegQuality}`);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
520
650
|
async function rewriteSafariInlineJpegImagesToPng(svg) {
|
|
521
651
|
if (!isSafariLikeForInlineJpegSvgPdf() || typeof document === "undefined") return;
|
|
522
652
|
const jpegImages = Array.from(svg.querySelectorAll("image")).filter((image) => /^data:image\/jpe?g[;,]/i.test(getSvgImageHref(image)));
|
|
@@ -562,8 +692,7 @@ async function rewriteSafariInlineJpegImagesToPng(svg) {
|
|
|
562
692
|
const transformScale = getApproxSvgTransformScale(image);
|
|
563
693
|
const renderedW = attrW * transformScale.x;
|
|
564
694
|
const renderedH = attrH * transformScale.y;
|
|
565
|
-
const density =
|
|
566
|
-
const maxEdge = 1800;
|
|
695
|
+
const { density, maxEdge } = getCompressedRasterSizing(getPdfJpegQuality());
|
|
567
696
|
targetW = Math.max(1, Math.round(Math.min(attrW, renderedW * density || attrW)));
|
|
568
697
|
targetH = Math.max(1, Math.round(Math.min(attrH, renderedH * density || attrH)));
|
|
569
698
|
const longest = Math.max(targetW, targetH);
|
|
@@ -573,7 +702,6 @@ async function rewriteSafariInlineJpegImagesToPng(svg) {
|
|
|
573
702
|
targetH = Math.max(1, Math.round(targetH * scale));
|
|
574
703
|
}
|
|
575
704
|
}
|
|
576
|
-
const outputAsPng = __pdfCompressImages;
|
|
577
705
|
let pngDataUrl = null;
|
|
578
706
|
for (const shrink of __pdfCompressImages ? [1, 0.82, 0.68, 0.55] : [1]) {
|
|
579
707
|
const canvas = document.createElement("canvas");
|
|
@@ -584,7 +712,7 @@ async function rewriteSafariInlineJpegImagesToPng(svg) {
|
|
|
584
712
|
ctx.fillStyle = "#ffffff";
|
|
585
713
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
586
714
|
ctx.drawImage(loaded, 0, 0, canvas.width, canvas.height);
|
|
587
|
-
pngDataUrl =
|
|
715
|
+
pngDataUrl = canvas.toDataURL("image/jpeg", __pdfCompressImages ? getPdfJpegQuality() : 1);
|
|
588
716
|
if (!__pdfCompressImages || estimateDataUrlBytesForPdf(pngDataUrl) <= 4e6 || shrink === 0.55) break;
|
|
589
717
|
}
|
|
590
718
|
if (blobUrl) URL.revokeObjectURL(blobUrl);
|
|
@@ -629,8 +757,7 @@ async function rewriteUnsupportedRasterImagesForSvgPdf(svg) {
|
|
|
629
757
|
const transformScale = getApproxSvgTransformScale(image);
|
|
630
758
|
const renderedW = attrW * transformScale.x;
|
|
631
759
|
const renderedH = attrH * transformScale.y;
|
|
632
|
-
const density =
|
|
633
|
-
const maxEdge = 2200;
|
|
760
|
+
const { density, maxEdge } = getCompressedRasterSizing(getPdfJpegQuality());
|
|
634
761
|
targetW = Math.max(1, Math.round(Math.min(bitmap.width || attrW, renderedW * density || attrW)));
|
|
635
762
|
targetH = Math.max(1, Math.round(Math.min(bitmap.height || attrH, renderedH * density || attrH)));
|
|
636
763
|
const longest = Math.max(targetW, targetH);
|
|
@@ -673,7 +800,7 @@ async function rewriteUnsupportedRasterImagesForSvgPdf(svg) {
|
|
|
673
800
|
} catch {
|
|
674
801
|
}
|
|
675
802
|
ctx.drawImage(bitmap, 0, 0, targetW, targetH);
|
|
676
|
-
const jpegQuality = __pdfCompressImages ?
|
|
803
|
+
const jpegQuality = __pdfCompressImages ? getPdfJpegQuality() : 1;
|
|
677
804
|
const safeDataUrl = hasAlpha ? canvas.toDataURL("image/png") : canvas.toDataURL("image/jpeg", jpegQuality);
|
|
678
805
|
image.setAttribute("href", safeDataUrl);
|
|
679
806
|
if (image.hasAttribute("xlink:href")) image.setAttribute("xlink:href", safeDataUrl);
|
|
@@ -825,6 +952,28 @@ function isInSvgDefinitionSubtree(el) {
|
|
|
825
952
|
}
|
|
826
953
|
return false;
|
|
827
954
|
}
|
|
955
|
+
async function encodePdfRasterDataUrl(dataUrl, options) {
|
|
956
|
+
if (!__pdfCompressImages || !(options == null ? void 0 : options.allowJpeg)) return { data: dataUrl, format: "PNG" };
|
|
957
|
+
const loaded = await decodeImageForPdf(dataUrl);
|
|
958
|
+
if (!loaded) return { data: dataUrl, format: "PNG" };
|
|
959
|
+
const w = Math.max(1, Math.round(loaded.naturalWidth || loaded.width || 1));
|
|
960
|
+
const h = Math.max(1, Math.round(loaded.naturalHeight || loaded.height || 1));
|
|
961
|
+
if (decodedImageHasAlpha(loaded, w, h)) return { data: dataUrl, format: "PNG" };
|
|
962
|
+
const canvas = document.createElement("canvas");
|
|
963
|
+
canvas.width = w;
|
|
964
|
+
canvas.height = h;
|
|
965
|
+
const ctx = canvas.getContext("2d");
|
|
966
|
+
if (!ctx) return { data: dataUrl, format: "PNG" };
|
|
967
|
+
ctx.fillStyle = "#ffffff";
|
|
968
|
+
ctx.fillRect(0, 0, w, h);
|
|
969
|
+
ctx.imageSmoothingEnabled = true;
|
|
970
|
+
try {
|
|
971
|
+
ctx.imageSmoothingQuality = "high";
|
|
972
|
+
} catch {
|
|
973
|
+
}
|
|
974
|
+
ctx.drawImage(loaded, 0, 0, w, h);
|
|
975
|
+
return { data: canvas.toDataURL("image/jpeg", getPdfJpegQuality()), format: "JPEG" };
|
|
976
|
+
}
|
|
828
977
|
function parseInlineSvgStyleDeclarations(styleText) {
|
|
829
978
|
return styleText.split(";").map((part) => part.trim()).filter(Boolean).map((part) => {
|
|
830
979
|
const idx = part.indexOf(":");
|
|
@@ -2176,6 +2325,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
|
|
|
2176
2325
|
}
|
|
2177
2326
|
sanitizeSvgTreeForPdf(svgToDraw);
|
|
2178
2327
|
await replaceLiveSvgRasterImagesWithOriginalAssets(svgToDraw, options == null ? void 0 : options.originalRasterImagesById);
|
|
2328
|
+
await rewriteCompressedLiveSvgRasterImages(svgToDraw);
|
|
2179
2329
|
await rewriteUnsupportedRasterImagesForSvgPdf(svgToDraw);
|
|
2180
2330
|
await rewriteSafariInlineJpegImagesToPng(svgToDraw);
|
|
2181
2331
|
try {
|
|
@@ -2801,7 +2951,7 @@ async function fetchSvgAsElement(imageUrl, colorMap) {
|
|
|
2801
2951
|
async function getRecoloredSvgDataUrl(imageUrl, colorMap) {
|
|
2802
2952
|
if (!colorMap || Object.keys(colorMap).length === 0) return null;
|
|
2803
2953
|
try {
|
|
2804
|
-
const { getNormalizedSvgUrl } = await import("./index-
|
|
2954
|
+
const { getNormalizedSvgUrl } = await import("./index-B1QDVK5k.js").then((n) => n.a6);
|
|
2805
2955
|
return await getNormalizedSvgUrl(imageUrl, colorMap);
|
|
2806
2956
|
} catch {
|
|
2807
2957
|
return null;
|
|
@@ -3497,7 +3647,7 @@ function __setPdfJpegQuality(v) {
|
|
|
3497
3647
|
if (typeof v === "number" && isFinite(v) && v > 0 && v <= 1) __pdfJpegQuality = v;
|
|
3498
3648
|
}
|
|
3499
3649
|
function pdfRasterCompression() {
|
|
3500
|
-
return __pdfCompressImages ? "SLOW" : "
|
|
3650
|
+
return __pdfCompressImages ? "SLOW" : "FAST";
|
|
3501
3651
|
}
|
|
3502
3652
|
function normalizeBgColor(bg) {
|
|
3503
3653
|
if (!bg || bg === "transparent" || bg === "none") return "#ffffff";
|
|
@@ -3547,9 +3697,11 @@ function getTargetPixelSize(bitmap, opts) {
|
|
|
3547
3697
|
if (!__pdfCompressImages && !(opts.resolutionMultiplier && opts.resolutionMultiplier > 1)) {
|
|
3548
3698
|
return { w: bitmap.width, h: bitmap.height };
|
|
3549
3699
|
}
|
|
3550
|
-
const
|
|
3700
|
+
const quality = getPdfJpegQuality();
|
|
3701
|
+
const compressedSizing = getCompressedRasterSizing(quality);
|
|
3702
|
+
const dpiScale = (__pdfCompressImages ? compressedSizing.density : 1.5) * (opts.resolutionMultiplier ?? 1);
|
|
3551
3703
|
const hasMultiplier = !!(opts.resolutionMultiplier && opts.resolutionMultiplier > 1);
|
|
3552
|
-
const maxPx = !__pdfCompressImages ? 1e4 : hasMultiplier ?
|
|
3704
|
+
const maxPx = !__pdfCompressImages ? 1e4 : hasMultiplier ? Math.max(3200, compressedSizing.maxEdge * 1.7) : compressedSizing.maxEdge;
|
|
3553
3705
|
const capByBitmap = !(opts.resolutionMultiplier && opts.resolutionMultiplier > 1);
|
|
3554
3706
|
const desiredW = Math.max(1, Math.round((opts.targetWidthPt ?? bitmap.width) * dpiScale));
|
|
3555
3707
|
const desiredH = Math.max(1, Math.round((opts.targetHeightPt ?? bitmap.height) * dpiScale));
|
|
@@ -3579,7 +3731,7 @@ async function rasterizeToDataUrl(blob, opts, out, flattenBackground) {
|
|
|
3579
3731
|
}
|
|
3580
3732
|
ctx.drawImage(bitmap, 0, 0, w, h);
|
|
3581
3733
|
if (out === "JPEG") {
|
|
3582
|
-
const quality = __pdfCompressImages ?
|
|
3734
|
+
const quality = __pdfCompressImages ? getPdfJpegQuality() : 1;
|
|
3583
3735
|
return canvas.toDataURL("image/jpeg", quality);
|
|
3584
3736
|
}
|
|
3585
3737
|
return canvas.toDataURL("image/png");
|
|
@@ -3608,7 +3760,7 @@ async function fetchImageAsBase64(imageUrl, opts = {}) {
|
|
|
3608
3760
|
}
|
|
3609
3761
|
let fetchUrl = imageUrl;
|
|
3610
3762
|
if (imageUrl.startsWith("http://") || imageUrl.startsWith("https://")) {
|
|
3611
|
-
const { isPrivateUrl } = await import("./index-
|
|
3763
|
+
const { isPrivateUrl } = await import("./index-B1QDVK5k.js").then((n) => n.a6);
|
|
3612
3764
|
if (isPrivateUrl(imageUrl)) return null;
|
|
3613
3765
|
const proxyUrl = new URL(`${API_URL}/image-proxy`);
|
|
3614
3766
|
proxyUrl.searchParams.set("url", imageUrl);
|
|
@@ -3837,6 +3989,7 @@ async function rasterizeCropGroupToPng(liveGroup, frameW, frameH, multiplier = 2
|
|
|
3837
3989
|
}
|
|
3838
3990
|
}
|
|
3839
3991
|
if (htmlImg) {
|
|
3992
|
+
await ensureImageDecoded(htmlImg);
|
|
3840
3993
|
const iw = htmlImg.naturalWidth || useNatW;
|
|
3841
3994
|
const ih = htmlImg.naturalHeight || useNatH;
|
|
3842
3995
|
const baseScale = Math.max(frameW / iw, frameH / ih);
|
|
@@ -3854,39 +4007,42 @@ async function rasterizeCropGroupToPng(liveGroup, frameW, frameH, multiplier = 2
|
|
|
3854
4007
|
const srcW = Math.min(Math.ceil(frameW / finalScale), iw - srcX);
|
|
3855
4008
|
const srcH = Math.min(Math.ceil(frameH / finalScale), ih - srcY);
|
|
3856
4009
|
if (srcW >= 1 && srcH >= 1) {
|
|
4010
|
+
const safeCrop = getSafeCanvasDims(srcW, srcH);
|
|
3857
4011
|
const cropCanvas = document.createElement("canvas");
|
|
3858
|
-
cropCanvas.width =
|
|
3859
|
-
cropCanvas.height =
|
|
4012
|
+
cropCanvas.width = safeCrop.width;
|
|
4013
|
+
cropCanvas.height = safeCrop.height;
|
|
3860
4014
|
const ctx = cropCanvas.getContext("2d");
|
|
3861
4015
|
if (ctx) {
|
|
4016
|
+
const dstW = safeCrop.width;
|
|
4017
|
+
const dstH = safeCrop.height;
|
|
3862
4018
|
if (bgFill) {
|
|
3863
4019
|
ctx.fillStyle = bgFill;
|
|
3864
|
-
ctx.fillRect(0, 0,
|
|
4020
|
+
ctx.fillRect(0, 0, dstW, dstH);
|
|
3865
4021
|
} else {
|
|
3866
|
-
ctx.clearRect(0, 0,
|
|
4022
|
+
ctx.clearRect(0, 0, dstW, dstH);
|
|
3867
4023
|
}
|
|
3868
|
-
ctx.drawImage(htmlImg, srcX, srcY, srcW, srcH, 0, 0,
|
|
4024
|
+
ctx.drawImage(htmlImg, srcX, srcY, srcW, srcH, 0, 0, dstW, dstH);
|
|
3869
4025
|
if (shape === "circle" || shape === "roundRect" || shape === "rect") {
|
|
3870
4026
|
ctx.globalCompositeOperation = "destination-in";
|
|
3871
4027
|
if (shape === "circle") {
|
|
3872
4028
|
ctx.beginPath();
|
|
3873
|
-
ctx.ellipse(
|
|
4029
|
+
ctx.ellipse(dstW / 2, dstH / 2, dstW / 2, dstH / 2, 0, 0, 2 * Math.PI);
|
|
3874
4030
|
ctx.fill();
|
|
3875
4031
|
} else {
|
|
3876
4032
|
const rx2 = Math.min(
|
|
3877
|
-
(rxRatio > 0.5 ? rxRatio : rxRatio * minFrameDim) * (
|
|
3878
|
-
|
|
3879
|
-
|
|
4033
|
+
(rxRatio > 0.5 ? rxRatio : rxRatio * minFrameDim) * (dstW / frameW),
|
|
4034
|
+
dstW / 2,
|
|
4035
|
+
dstH / 2
|
|
3880
4036
|
);
|
|
3881
4037
|
const r = Math.max(0, rx2);
|
|
3882
4038
|
ctx.beginPath();
|
|
3883
4039
|
ctx.moveTo(r, 0);
|
|
3884
|
-
ctx.lineTo(
|
|
3885
|
-
if (r > 0) ctx.quadraticCurveTo(
|
|
3886
|
-
ctx.lineTo(
|
|
3887
|
-
if (r > 0) ctx.quadraticCurveTo(
|
|
3888
|
-
ctx.lineTo(r,
|
|
3889
|
-
if (r > 0) ctx.quadraticCurveTo(0,
|
|
4040
|
+
ctx.lineTo(dstW - r, 0);
|
|
4041
|
+
if (r > 0) ctx.quadraticCurveTo(dstW, 0, dstW, r);
|
|
4042
|
+
ctx.lineTo(dstW, dstH - r);
|
|
4043
|
+
if (r > 0) ctx.quadraticCurveTo(dstW, dstH, dstW - r, dstH);
|
|
4044
|
+
ctx.lineTo(r, dstH);
|
|
4045
|
+
if (r > 0) ctx.quadraticCurveTo(0, dstH, 0, dstH - r);
|
|
3890
4046
|
ctx.lineTo(0, r);
|
|
3891
4047
|
if (r > 0) ctx.quadraticCurveTo(0, 0, r, 0);
|
|
3892
4048
|
ctx.closePath();
|
|
@@ -3905,8 +4061,11 @@ async function rasterizeCropGroupToPng(liveGroup, frameW, frameH, multiplier = 2
|
|
|
3905
4061
|
const natH = (dims == null ? void 0 : dims.height) ?? (stored == null ? void 0 : stored.naturalHeight) ?? frameH;
|
|
3906
4062
|
const useNatW = natW > 0 && natH > 0 ? natW : frameW;
|
|
3907
4063
|
const useNatH = natW > 0 && natH > 0 ? natH : frameH;
|
|
3908
|
-
const
|
|
3909
|
-
const
|
|
4064
|
+
const reqOutW = maintainResolution && useNatW > frameW ? Math.max(1, Math.round(useNatW)) : Math.max(1, Math.round(frameW * multiplier));
|
|
4065
|
+
const reqOutH = maintainResolution && useNatH > frameH ? Math.max(1, Math.round(useNatH)) : Math.max(1, Math.round(frameH * multiplier));
|
|
4066
|
+
const safeOut = getSafeCanvasDims(reqOutW, reqOutH);
|
|
4067
|
+
const outW2 = safeOut.width;
|
|
4068
|
+
const outH2 = safeOut.height;
|
|
3910
4069
|
const proxied = getProxiedImageUrl(imageUrl);
|
|
3911
4070
|
const res = await fetch(proxied);
|
|
3912
4071
|
if (!res.ok) throw new Error(`Export blob fetch failed: ${res.status}`);
|
|
@@ -4498,6 +4657,7 @@ async function drawElement(pdf, element, embeddedFonts, canvasWidth, canvasHeigh
|
|
|
4498
4657
|
if (fadedMasked) {
|
|
4499
4658
|
png = fadedMasked;
|
|
4500
4659
|
}
|
|
4660
|
+
const encodedMasked = await encodePdfRasterDataUrl(png, { allowJpeg: !fadedMasked });
|
|
4501
4661
|
if (canUseAdvancedTransforms2 && fabricMatrix && fabricMatrix.length === 6) {
|
|
4502
4662
|
const mPdf = fabricMatrixToJsPdfAdvancedMatrix(fabricMatrix);
|
|
4503
4663
|
const localX = -frameW / 2;
|
|
@@ -4505,13 +4665,13 @@ async function drawElement(pdf, element, embeddedFonts, canvasWidth, canvasHeigh
|
|
|
4505
4665
|
anyPdf2.advancedAPI(() => {
|
|
4506
4666
|
pdf.saveGraphicsState();
|
|
4507
4667
|
anyPdf2.setCurrentTransformationMatrix(anyPdf2.Matrix(...mPdf));
|
|
4508
|
-
pdf.addImage(
|
|
4668
|
+
pdf.addImage(encodedMasked.data, encodedMasked.format, localX, localY, frameW, frameH, void 0, pdfRasterCompression());
|
|
4509
4669
|
pdf.restoreGraphicsState();
|
|
4510
4670
|
});
|
|
4511
4671
|
pdf.setGState(pdf.GState({ opacity: 1, "stroke-opacity": 1 }));
|
|
4512
4672
|
return;
|
|
4513
4673
|
}
|
|
4514
|
-
pdf.addImage(
|
|
4674
|
+
pdf.addImage(encodedMasked.data, encodedMasked.format, norm.x, norm.y, frameW, frameH, void 0, pdfRasterCompression());
|
|
4515
4675
|
pdf.setGState(pdf.GState({ opacity: 1, "stroke-opacity": 1 }));
|
|
4516
4676
|
return;
|
|
4517
4677
|
}
|
|
@@ -5018,8 +5178,8 @@ async function drawElementContentCore(pdf, element, norm, x, y, w, h, embeddedFo
|
|
|
5018
5178
|
if (croppedPng) {
|
|
5019
5179
|
try {
|
|
5020
5180
|
const fadedCrop = await bakeEdgeFadeIntoDataUrl(croppedPng, element);
|
|
5021
|
-
const
|
|
5022
|
-
pdf.addImage(
|
|
5181
|
+
const encodedCrop = await encodePdfRasterDataUrl(fadedCrop || croppedPng, { allowJpeg: !fadedCrop });
|
|
5182
|
+
pdf.addImage(encodedCrop.data, encodedCrop.format, x, y, w, h, void 0, pdfRasterCompression());
|
|
5023
5183
|
break;
|
|
5024
5184
|
} catch {
|
|
5025
5185
|
}
|
|
@@ -5227,10 +5387,21 @@ function getExpectedRasterImageIdsForPdfPage(page) {
|
|
|
5227
5387
|
function getOriginalRasterImageUrlMapForPdfPage(page) {
|
|
5228
5388
|
const byId = /* @__PURE__ */ new Map();
|
|
5229
5389
|
const isSvgUrl = (url) => /\.svg(?:\?|#|$)/i.test(url) || /^data:image\/svg/i.test(url);
|
|
5390
|
+
const hasVisualImageEffect = (item) => {
|
|
5391
|
+
const hasCrop = item.cropPanX != null || item.cropPanY != null || item.cropZoom != null;
|
|
5392
|
+
const hasMask = item.maskSvgUrl || item.clipShape && item.clipShape !== "none" && item.clipShape !== "rectangle";
|
|
5393
|
+
const hasFade = ["Top", "Right", "Bottom", "Left"].some(
|
|
5394
|
+
(side) => item[`fade${side}Amount`] != null || item[`fade${side}Size`] != null || item[`fade${side}Hardness`] != null
|
|
5395
|
+
);
|
|
5396
|
+
const hasFrame = (item.strokeWidth ?? 0) > 0 || !!item.stroke || (item.rx ?? 0) > 0 || (item.ry ?? 0) > 0;
|
|
5397
|
+
const hasShadowOrFilter = item.shadow || item.shadowColor || item.shadowBlur || item.shadowOffsetX || item.shadowOffsetY || item.filter || item.filters;
|
|
5398
|
+
return Boolean(hasCrop || hasMask || hasFade || hasFrame || hasShadowOrFilter);
|
|
5399
|
+
};
|
|
5230
5400
|
for (const item of page.elements) {
|
|
5231
5401
|
if (isGroupBackgroundDrawable(item) || item.type !== "image" || item.visible === false) continue;
|
|
5232
5402
|
const src = String(item.src || item.imageUrl || "").trim();
|
|
5233
5403
|
if (!src || item.sourceFormat === "svg" || isSvgUrl(src)) continue;
|
|
5404
|
+
if (hasVisualImageEffect(item)) continue;
|
|
5234
5405
|
byId.set(item.id, src);
|
|
5235
5406
|
}
|
|
5236
5407
|
return byId;
|
|
@@ -5276,7 +5447,10 @@ async function __exportMultiPagePdfInner(pages, options) {
|
|
|
5276
5447
|
unit: "px",
|
|
5277
5448
|
format: [firstPage.width, firstPage.height],
|
|
5278
5449
|
hotfixes: ["px_scaling"],
|
|
5279
|
-
|
|
5450
|
+
// Always keep PDF object/stream compression on. The UI's image-compression
|
|
5451
|
+
// switch controls raster resampling/JPEG quality, not lossless PDF packing;
|
|
5452
|
+
// disabling this made "uncompressed image" PDFs balloon with no quality gain.
|
|
5453
|
+
compress: true
|
|
5280
5454
|
});
|
|
5281
5455
|
if (title) {
|
|
5282
5456
|
pdf.setProperties({ title, creator: "DocuForge" });
|
|
@@ -5687,4 +5861,4 @@ export {
|
|
|
5687
5861
|
preparePagesForExport,
|
|
5688
5862
|
rewriteSvgFontsForJsPDFWithSourceMeta
|
|
5689
5863
|
};
|
|
5690
|
-
//# sourceMappingURL=vectorPdfExport-
|
|
5864
|
+
//# sourceMappingURL=vectorPdfExport-CN-N0DE8.js.map
|