@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
|
@@ -4053,6 +4053,11 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
|
|
|
4053
4053
|
setObjectData(cropGroup, element.id);
|
|
4054
4054
|
cropGroup.__imageSrc = imageUrl;
|
|
4055
4055
|
cropGroup.__svgColorMap = nextSvgColorMap;
|
|
4056
|
+
cropGroup.set({
|
|
4057
|
+
flipX: element.flipX ?? false,
|
|
4058
|
+
flipY: element.flipY ?? false
|
|
4059
|
+
});
|
|
4060
|
+
cropGroup.setCoords();
|
|
4056
4061
|
finalObject = cropGroup;
|
|
4057
4062
|
} else {
|
|
4058
4063
|
setObjectData(img, element.id);
|
|
@@ -6879,8 +6884,10 @@ function buildTextShadow(element) {
|
|
|
6879
6884
|
if (!color || color === "transparent") return null;
|
|
6880
6885
|
const type = element.textShadowType;
|
|
6881
6886
|
if (type && type !== "drop") return null;
|
|
6887
|
+
const { perPassAlpha } = resolveShadowStrength(element);
|
|
6888
|
+
const finalColor = applyAlphaMultiplier(String(color), perPassAlpha);
|
|
6882
6889
|
return new fabric.Shadow({
|
|
6883
|
-
color:
|
|
6890
|
+
color: finalColor,
|
|
6884
6891
|
blur: blur || 0,
|
|
6885
6892
|
offsetX: ox || 0,
|
|
6886
6893
|
offsetY: oy || 0,
|
|
@@ -6888,6 +6895,65 @@ function buildTextShadow(element) {
|
|
|
6888
6895
|
nonScaling: false
|
|
6889
6896
|
});
|
|
6890
6897
|
}
|
|
6898
|
+
function resolveShadowStrength(element) {
|
|
6899
|
+
const raw = element.textShadowStrength;
|
|
6900
|
+
const s = typeof raw === "number" && Number.isFinite(raw) ? Math.max(0, Math.min(100, raw)) : 25;
|
|
6901
|
+
if (s <= 0) return { perPassAlpha: 0, passes: 0 };
|
|
6902
|
+
if (s <= 25) return { perPassAlpha: s / 25, passes: 1 };
|
|
6903
|
+
const passes = Math.min(4, Math.ceil(s / 25));
|
|
6904
|
+
return { perPassAlpha: 1, passes };
|
|
6905
|
+
}
|
|
6906
|
+
function applyTextShadow(textbox, element) {
|
|
6907
|
+
const shadow = buildTextShadow(element);
|
|
6908
|
+
const { passes } = resolveShadowStrength(element);
|
|
6909
|
+
const obj = textbox;
|
|
6910
|
+
if (!obj.__pdShadowOrigRender) {
|
|
6911
|
+
obj.__pdShadowOrigRender = obj.render.bind(obj);
|
|
6912
|
+
obj.render = function(ctx) {
|
|
6913
|
+
const n = Math.max(1, Number(obj.__pdShadowPasses || 1));
|
|
6914
|
+
for (let i = 0; i < n; i++) obj.__pdShadowOrigRender(ctx);
|
|
6915
|
+
};
|
|
6916
|
+
}
|
|
6917
|
+
obj.__pdShadowPasses = shadow ? Math.max(1, passes) : 1;
|
|
6918
|
+
textbox.set("shadow", shadow ?? null);
|
|
6919
|
+
}
|
|
6920
|
+
function applyAlphaMultiplier(c, mult) {
|
|
6921
|
+
const m = Math.max(0, Math.min(1, mult));
|
|
6922
|
+
const s = String(c).trim();
|
|
6923
|
+
const rgba = s.match(/^rgba?\s*\(([^)]+)\)$/i);
|
|
6924
|
+
if (rgba) {
|
|
6925
|
+
const parts = rgba[1].split(",").map((p) => p.trim());
|
|
6926
|
+
const [r, g, b] = parts;
|
|
6927
|
+
const baseA = parts.length >= 4 ? Math.max(0, Math.min(1, parseFloat(parts[3]) || 0)) : 1;
|
|
6928
|
+
return `rgba(${r}, ${g}, ${b}, ${Math.round(baseA * m * 1e3) / 1e3})`;
|
|
6929
|
+
}
|
|
6930
|
+
const hex8 = s.match(/^#([0-9a-f]{8})$/i);
|
|
6931
|
+
if (hex8) {
|
|
6932
|
+
const h = hex8[1];
|
|
6933
|
+
const r = parseInt(h.slice(0, 2), 16);
|
|
6934
|
+
const g = parseInt(h.slice(2, 4), 16);
|
|
6935
|
+
const b = parseInt(h.slice(4, 6), 16);
|
|
6936
|
+
const baseA = parseInt(h.slice(6, 8), 16) / 255;
|
|
6937
|
+
return `rgba(${r}, ${g}, ${b}, ${Math.round(baseA * m * 1e3) / 1e3})`;
|
|
6938
|
+
}
|
|
6939
|
+
const hex6 = s.match(/^#([0-9a-f]{6})$/i);
|
|
6940
|
+
if (hex6) {
|
|
6941
|
+
const h = hex6[1];
|
|
6942
|
+
const r = parseInt(h.slice(0, 2), 16);
|
|
6943
|
+
const g = parseInt(h.slice(2, 4), 16);
|
|
6944
|
+
const b = parseInt(h.slice(4, 6), 16);
|
|
6945
|
+
return `rgba(${r}, ${g}, ${b}, ${Math.round(m * 1e3) / 1e3})`;
|
|
6946
|
+
}
|
|
6947
|
+
const hex3 = s.match(/^#([0-9a-f]{3})$/i);
|
|
6948
|
+
if (hex3) {
|
|
6949
|
+
const h = hex3[1];
|
|
6950
|
+
const r = parseInt(h[0] + h[0], 16);
|
|
6951
|
+
const g = parseInt(h[1] + h[1], 16);
|
|
6952
|
+
const b = parseInt(h[2] + h[2], 16);
|
|
6953
|
+
return `rgba(${r}, ${g}, ${b}, ${Math.round(m * 1e3) / 1e3})`;
|
|
6954
|
+
}
|
|
6955
|
+
return `rgba(0, 0, 0, ${Math.round(m * 1e3) / 1e3})`;
|
|
6956
|
+
}
|
|
6891
6957
|
function buildRoundedRectPath2D(ctx, x, y, w, h, rTL, rTR, rBR, rBL) {
|
|
6892
6958
|
const maxR = Math.min(w, h) / 2;
|
|
6893
6959
|
const tl = Math.min(Math.max(0, rTL), maxR);
|
|
@@ -8452,8 +8518,7 @@ function createText(element) {
|
|
|
8452
8518
|
}));
|
|
8453
8519
|
}
|
|
8454
8520
|
applyTextBackground(textbox, extractTextBgConfig(element));
|
|
8455
|
-
|
|
8456
|
-
if (shadow) textbox.set("shadow", shadow);
|
|
8521
|
+
applyTextShadow(textbox, element);
|
|
8457
8522
|
return textbox;
|
|
8458
8523
|
}
|
|
8459
8524
|
function createLine(element) {
|
|
@@ -12260,8 +12325,7 @@ const PageCanvas = forwardRef(
|
|
|
12260
12325
|
obj.dirty = true;
|
|
12261
12326
|
try {
|
|
12262
12327
|
applyTextBackground(obj, extractTextBgConfig(element));
|
|
12263
|
-
|
|
12264
|
-
obj.set("shadow", shadow ?? null);
|
|
12328
|
+
applyTextShadow(obj, element);
|
|
12265
12329
|
try {
|
|
12266
12330
|
obj._cacheCanvas = null;
|
|
12267
12331
|
obj._cacheContext = null;
|
|
@@ -12289,7 +12353,8 @@ const PageCanvas = forwardRef(
|
|
|
12289
12353
|
sy: element.textShadowOffsetY ?? 0,
|
|
12290
12354
|
st: element.textShadowAffectsText !== false,
|
|
12291
12355
|
sa: element.textShadowAffectsBg !== false,
|
|
12292
|
-
sty: element.textShadowType ?? null
|
|
12356
|
+
sty: element.textShadowType ?? null,
|
|
12357
|
+
ss: element.textShadowStrength ?? null
|
|
12293
12358
|
});
|
|
12294
12359
|
obj.dirty = true;
|
|
12295
12360
|
} catch (err) {
|
|
@@ -18947,9 +19012,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
|
|
|
18947
19012
|
}
|
|
18948
19013
|
return svgString;
|
|
18949
19014
|
}
|
|
18950
|
-
const resolvedPackageVersion = "0.5.
|
|
19015
|
+
const resolvedPackageVersion = "0.5.212";
|
|
18951
19016
|
const PACKAGE_VERSION = resolvedPackageVersion;
|
|
18952
|
-
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.
|
|
19017
|
+
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.212";
|
|
18953
19018
|
const roundParityValue = (value) => {
|
|
18954
19019
|
if (typeof value !== "number") return value;
|
|
18955
19020
|
return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
|
|
@@ -19009,7 +19074,7 @@ function detectSafariOrIos() {
|
|
|
19009
19074
|
return false;
|
|
19010
19075
|
}
|
|
19011
19076
|
}
|
|
19012
|
-
async function downscaleConfigRasterImages(config, maxEdgePx, maxDataUrlBytes = 2e6) {
|
|
19077
|
+
async function downscaleConfigRasterImages(config, maxEdgePx, maxDataUrlBytes = 2e6, jpegQuality = 0.85) {
|
|
19013
19078
|
if (!maxEdgePx || maxEdgePx <= 0) return 0;
|
|
19014
19079
|
if (typeof document === "undefined") return 0;
|
|
19015
19080
|
const targets = [];
|
|
@@ -19073,7 +19138,7 @@ async function downscaleConfigRasterImages(config, maxEdgePx, maxDataUrlBytes =
|
|
|
19073
19138
|
return null;
|
|
19074
19139
|
}
|
|
19075
19140
|
let scale = tooLargeByEdge ? maxEdgePx / longest : 1;
|
|
19076
|
-
let quality = 0.
|
|
19141
|
+
let quality = Math.max(0.4, Math.min(1, jpegQuality));
|
|
19077
19142
|
let best = null;
|
|
19078
19143
|
for (let attempt = 0; attempt < 4; attempt++) {
|
|
19079
19144
|
const tw = Math.max(1, Math.round(w * scale));
|
|
@@ -19097,7 +19162,7 @@ async function downscaleConfigRasterImages(config, maxEdgePx, maxDataUrlBytes =
|
|
|
19097
19162
|
}
|
|
19098
19163
|
const byteScale = Math.sqrt(maxDataUrlBytes / Math.max(1, outBytes)) * 0.92;
|
|
19099
19164
|
scale = Math.max(0.1, scale * Math.min(0.95, byteScale));
|
|
19100
|
-
quality = Math.max(0.
|
|
19165
|
+
quality = Math.max(0.4, quality - 0.06);
|
|
19101
19166
|
}
|
|
19102
19167
|
if (blobUrl) URL.revokeObjectURL(blobUrl);
|
|
19103
19168
|
return best;
|
|
@@ -19472,7 +19537,9 @@ class PixldocsRenderer {
|
|
|
19472
19537
|
title: options == null ? void 0 : options.title,
|
|
19473
19538
|
textMode: options == null ? void 0 : options.textMode,
|
|
19474
19539
|
forcePerElementPdf: options == null ? void 0 : options.forcePerElementPdf,
|
|
19475
|
-
maxImageEdgePx: options == null ? void 0 : options.maxImageEdgePx
|
|
19540
|
+
maxImageEdgePx: options == null ? void 0 : options.maxImageEdgePx,
|
|
19541
|
+
compressImages: options == null ? void 0 : options.compressImages,
|
|
19542
|
+
compressionQuality: options == null ? void 0 : options.compressionQuality
|
|
19476
19543
|
});
|
|
19477
19544
|
}
|
|
19478
19545
|
/**
|
|
@@ -19480,7 +19547,7 @@ class PixldocsRenderer {
|
|
|
19480
19547
|
* This is the primary PDF export API — mirrors renderFromForm() but returns a PDF.
|
|
19481
19548
|
*/
|
|
19482
19549
|
async renderPdfFromForm(options) {
|
|
19483
|
-
const { templateId, formSchemaId, sectionState, themeId, watermark, watermarkOptions, prefetched, title, fontBaseUrl, textMode, forcePerElementPdf, maxImageEdgePx } = options;
|
|
19550
|
+
const { templateId, formSchemaId, sectionState, themeId, watermark, watermarkOptions, prefetched, title, fontBaseUrl, textMode, forcePerElementPdf, maxImageEdgePx, compressImages, compressionQuality } = options;
|
|
19484
19551
|
const resolved = await resolveFromForm({
|
|
19485
19552
|
templateId,
|
|
19486
19553
|
formSchemaId,
|
|
@@ -19503,7 +19570,9 @@ class PixldocsRenderer {
|
|
|
19503
19570
|
watermark: shouldWatermark,
|
|
19504
19571
|
textMode,
|
|
19505
19572
|
forcePerElementPdf,
|
|
19506
|
-
maxImageEdgePx
|
|
19573
|
+
maxImageEdgePx,
|
|
19574
|
+
compressImages,
|
|
19575
|
+
compressionQuality
|
|
19507
19576
|
});
|
|
19508
19577
|
}
|
|
19509
19578
|
async renderById(templateId, formData, options) {
|
|
@@ -19550,13 +19619,20 @@ class PixldocsRenderer {
|
|
|
19550
19619
|
const hasUserDataImage = configHasUserDataImage(cloned);
|
|
19551
19620
|
const isSafariLike = detectSafariOrIos();
|
|
19552
19621
|
const shouldForcePerElement = forceMode === true ? true : forceMode === false ? false : false;
|
|
19622
|
+
const compressImagesOpt = options.compressImages ?? true;
|
|
19553
19623
|
const maxEdgeOpt = options.maxImageEdgePx ?? this.config.maxImageEdgePx;
|
|
19554
|
-
const effectiveMaxEdge = typeof maxEdgeOpt === "number" ? Math.max(0, maxEdgeOpt | 0) : hasUserDataImage ? 2048 : 0;
|
|
19624
|
+
const effectiveMaxEdge = typeof maxEdgeOpt === "number" ? Math.max(0, maxEdgeOpt | 0) : compressImagesOpt ? hasUserDataImage ? 2048 : 0 : 0;
|
|
19625
|
+
const downscaleQuality = compressImagesOpt ? typeof options.compressionQuality === "number" ? Math.max(0.4, Math.min(1, options.compressionQuality)) : 0.85 : 0.95;
|
|
19555
19626
|
if (effectiveMaxEdge > 0) {
|
|
19556
19627
|
try {
|
|
19557
|
-
const downscaled = await downscaleConfigRasterImages(
|
|
19628
|
+
const downscaled = await downscaleConfigRasterImages(
|
|
19629
|
+
cloned,
|
|
19630
|
+
effectiveMaxEdge,
|
|
19631
|
+
void 0,
|
|
19632
|
+
downscaleQuality
|
|
19633
|
+
);
|
|
19558
19634
|
if (downscaled > 0) {
|
|
19559
|
-
console.log(`[canvas-renderer][pdf-unified] downscaled ${downscaled} raster image(s) to <=${effectiveMaxEdge}px edge`);
|
|
19635
|
+
console.log(`[canvas-renderer][pdf-unified] downscaled ${downscaled} raster image(s) to <=${effectiveMaxEdge}px edge @ q=${downscaleQuality}`);
|
|
19560
19636
|
}
|
|
19561
19637
|
} catch (e) {
|
|
19562
19638
|
console.warn("[canvas-renderer][pdf-unified] image downscale pass failed (continuing with originals):", e);
|
|
@@ -19567,7 +19643,9 @@ class PixldocsRenderer {
|
|
|
19567
19643
|
hasUserDataImage,
|
|
19568
19644
|
isSafariLike,
|
|
19569
19645
|
shouldForcePerElement,
|
|
19570
|
-
effectiveMaxEdge
|
|
19646
|
+
effectiveMaxEdge,
|
|
19647
|
+
compressImages: compressImagesOpt,
|
|
19648
|
+
downscaleQuality
|
|
19571
19649
|
});
|
|
19572
19650
|
const stampPrefix = `__pixldocs_pdf_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
19573
19651
|
const pageIds = cloned.pages.map((p, i) => {
|
|
@@ -19628,7 +19706,7 @@ class PixldocsRenderer {
|
|
|
19628
19706
|
await this.waitForCanvasScene(container, cloned, i);
|
|
19629
19707
|
}
|
|
19630
19708
|
console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
|
|
19631
|
-
const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-
|
|
19709
|
+
const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-CN-N0DE8.js");
|
|
19632
19710
|
const prepared = preparePagesForExport(
|
|
19633
19711
|
cloned.pages,
|
|
19634
19712
|
canvasWidth,
|
|
@@ -19645,7 +19723,9 @@ class PixldocsRenderer {
|
|
|
19645
19723
|
// path and use the live Fabric object PDF path instead, preserving live
|
|
19646
19724
|
// matrices/order so we do not regress into stale config-space layout.
|
|
19647
19725
|
skipLiveCanvasSvgFastPath: forceMode === true,
|
|
19648
|
-
useLiveCanvasObjectPdfPath: shouldForcePerElement && forceMode !== true
|
|
19726
|
+
useLiveCanvasObjectPdfPath: shouldForcePerElement && forceMode !== true,
|
|
19727
|
+
compressImages: options.compressImages ?? true,
|
|
19728
|
+
compressionQuality: options.compressionQuality
|
|
19649
19729
|
});
|
|
19650
19730
|
if (!result || typeof result === "undefined") {
|
|
19651
19731
|
throw new Error("exportMultiPagePdf returned no blob (returnBlob path failed)");
|
|
@@ -21812,7 +21892,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
|
|
|
21812
21892
|
if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
|
|
21813
21893
|
sanitizeSvgTreeForPdf(svgToDraw);
|
|
21814
21894
|
try {
|
|
21815
|
-
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-
|
|
21895
|
+
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-CN-N0DE8.js");
|
|
21816
21896
|
try {
|
|
21817
21897
|
await logTextMeasurementDiagnostic(svgToDraw);
|
|
21818
21898
|
} catch {
|
|
@@ -22212,4 +22292,4 @@ export {
|
|
|
22212
22292
|
buildTeaserBlurFlatKeys as y,
|
|
22213
22293
|
collectFontDescriptorsFromConfig as z
|
|
22214
22294
|
};
|
|
22215
|
-
//# sourceMappingURL=index-
|
|
22295
|
+
//# sourceMappingURL=index-B1QDVK5k.js.map
|