@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
|
@@ -4071,6 +4071,11 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
|
|
|
4071
4071
|
setObjectData(cropGroup, element.id);
|
|
4072
4072
|
cropGroup.__imageSrc = imageUrl;
|
|
4073
4073
|
cropGroup.__svgColorMap = nextSvgColorMap;
|
|
4074
|
+
cropGroup.set({
|
|
4075
|
+
flipX: element.flipX ?? false,
|
|
4076
|
+
flipY: element.flipY ?? false
|
|
4077
|
+
});
|
|
4078
|
+
cropGroup.setCoords();
|
|
4074
4079
|
finalObject = cropGroup;
|
|
4075
4080
|
} else {
|
|
4076
4081
|
setObjectData(img, element.id);
|
|
@@ -6897,8 +6902,10 @@ function buildTextShadow(element) {
|
|
|
6897
6902
|
if (!color || color === "transparent") return null;
|
|
6898
6903
|
const type = element.textShadowType;
|
|
6899
6904
|
if (type && type !== "drop") return null;
|
|
6905
|
+
const { perPassAlpha } = resolveShadowStrength(element);
|
|
6906
|
+
const finalColor = applyAlphaMultiplier(String(color), perPassAlpha);
|
|
6900
6907
|
return new fabric__namespace.Shadow({
|
|
6901
|
-
color:
|
|
6908
|
+
color: finalColor,
|
|
6902
6909
|
blur: blur || 0,
|
|
6903
6910
|
offsetX: ox || 0,
|
|
6904
6911
|
offsetY: oy || 0,
|
|
@@ -6906,6 +6913,65 @@ function buildTextShadow(element) {
|
|
|
6906
6913
|
nonScaling: false
|
|
6907
6914
|
});
|
|
6908
6915
|
}
|
|
6916
|
+
function resolveShadowStrength(element) {
|
|
6917
|
+
const raw = element.textShadowStrength;
|
|
6918
|
+
const s = typeof raw === "number" && Number.isFinite(raw) ? Math.max(0, Math.min(100, raw)) : 25;
|
|
6919
|
+
if (s <= 0) return { perPassAlpha: 0, passes: 0 };
|
|
6920
|
+
if (s <= 25) return { perPassAlpha: s / 25, passes: 1 };
|
|
6921
|
+
const passes = Math.min(4, Math.ceil(s / 25));
|
|
6922
|
+
return { perPassAlpha: 1, passes };
|
|
6923
|
+
}
|
|
6924
|
+
function applyTextShadow(textbox, element) {
|
|
6925
|
+
const shadow = buildTextShadow(element);
|
|
6926
|
+
const { passes } = resolveShadowStrength(element);
|
|
6927
|
+
const obj = textbox;
|
|
6928
|
+
if (!obj.__pdShadowOrigRender) {
|
|
6929
|
+
obj.__pdShadowOrigRender = obj.render.bind(obj);
|
|
6930
|
+
obj.render = function(ctx) {
|
|
6931
|
+
const n = Math.max(1, Number(obj.__pdShadowPasses || 1));
|
|
6932
|
+
for (let i = 0; i < n; i++) obj.__pdShadowOrigRender(ctx);
|
|
6933
|
+
};
|
|
6934
|
+
}
|
|
6935
|
+
obj.__pdShadowPasses = shadow ? Math.max(1, passes) : 1;
|
|
6936
|
+
textbox.set("shadow", shadow ?? null);
|
|
6937
|
+
}
|
|
6938
|
+
function applyAlphaMultiplier(c, mult) {
|
|
6939
|
+
const m = Math.max(0, Math.min(1, mult));
|
|
6940
|
+
const s = String(c).trim();
|
|
6941
|
+
const rgba = s.match(/^rgba?\s*\(([^)]+)\)$/i);
|
|
6942
|
+
if (rgba) {
|
|
6943
|
+
const parts = rgba[1].split(",").map((p) => p.trim());
|
|
6944
|
+
const [r, g, b] = parts;
|
|
6945
|
+
const baseA = parts.length >= 4 ? Math.max(0, Math.min(1, parseFloat(parts[3]) || 0)) : 1;
|
|
6946
|
+
return `rgba(${r}, ${g}, ${b}, ${Math.round(baseA * m * 1e3) / 1e3})`;
|
|
6947
|
+
}
|
|
6948
|
+
const hex8 = s.match(/^#([0-9a-f]{8})$/i);
|
|
6949
|
+
if (hex8) {
|
|
6950
|
+
const h = hex8[1];
|
|
6951
|
+
const r = parseInt(h.slice(0, 2), 16);
|
|
6952
|
+
const g = parseInt(h.slice(2, 4), 16);
|
|
6953
|
+
const b = parseInt(h.slice(4, 6), 16);
|
|
6954
|
+
const baseA = parseInt(h.slice(6, 8), 16) / 255;
|
|
6955
|
+
return `rgba(${r}, ${g}, ${b}, ${Math.round(baseA * m * 1e3) / 1e3})`;
|
|
6956
|
+
}
|
|
6957
|
+
const hex6 = s.match(/^#([0-9a-f]{6})$/i);
|
|
6958
|
+
if (hex6) {
|
|
6959
|
+
const h = hex6[1];
|
|
6960
|
+
const r = parseInt(h.slice(0, 2), 16);
|
|
6961
|
+
const g = parseInt(h.slice(2, 4), 16);
|
|
6962
|
+
const b = parseInt(h.slice(4, 6), 16);
|
|
6963
|
+
return `rgba(${r}, ${g}, ${b}, ${Math.round(m * 1e3) / 1e3})`;
|
|
6964
|
+
}
|
|
6965
|
+
const hex3 = s.match(/^#([0-9a-f]{3})$/i);
|
|
6966
|
+
if (hex3) {
|
|
6967
|
+
const h = hex3[1];
|
|
6968
|
+
const r = parseInt(h[0] + h[0], 16);
|
|
6969
|
+
const g = parseInt(h[1] + h[1], 16);
|
|
6970
|
+
const b = parseInt(h[2] + h[2], 16);
|
|
6971
|
+
return `rgba(${r}, ${g}, ${b}, ${Math.round(m * 1e3) / 1e3})`;
|
|
6972
|
+
}
|
|
6973
|
+
return `rgba(0, 0, 0, ${Math.round(m * 1e3) / 1e3})`;
|
|
6974
|
+
}
|
|
6909
6975
|
function buildRoundedRectPath2D(ctx, x, y, w, h, rTL, rTR, rBR, rBL) {
|
|
6910
6976
|
const maxR = Math.min(w, h) / 2;
|
|
6911
6977
|
const tl = Math.min(Math.max(0, rTL), maxR);
|
|
@@ -8470,8 +8536,7 @@ function createText(element) {
|
|
|
8470
8536
|
}));
|
|
8471
8537
|
}
|
|
8472
8538
|
applyTextBackground(textbox, extractTextBgConfig(element));
|
|
8473
|
-
|
|
8474
|
-
if (shadow) textbox.set("shadow", shadow);
|
|
8539
|
+
applyTextShadow(textbox, element);
|
|
8475
8540
|
return textbox;
|
|
8476
8541
|
}
|
|
8477
8542
|
function createLine(element) {
|
|
@@ -12278,8 +12343,7 @@ const PageCanvas = react.forwardRef(
|
|
|
12278
12343
|
obj.dirty = true;
|
|
12279
12344
|
try {
|
|
12280
12345
|
applyTextBackground(obj, extractTextBgConfig(element));
|
|
12281
|
-
|
|
12282
|
-
obj.set("shadow", shadow ?? null);
|
|
12346
|
+
applyTextShadow(obj, element);
|
|
12283
12347
|
try {
|
|
12284
12348
|
obj._cacheCanvas = null;
|
|
12285
12349
|
obj._cacheContext = null;
|
|
@@ -12307,7 +12371,8 @@ const PageCanvas = react.forwardRef(
|
|
|
12307
12371
|
sy: element.textShadowOffsetY ?? 0,
|
|
12308
12372
|
st: element.textShadowAffectsText !== false,
|
|
12309
12373
|
sa: element.textShadowAffectsBg !== false,
|
|
12310
|
-
sty: element.textShadowType ?? null
|
|
12374
|
+
sty: element.textShadowType ?? null,
|
|
12375
|
+
ss: element.textShadowStrength ?? null
|
|
12311
12376
|
});
|
|
12312
12377
|
obj.dirty = true;
|
|
12313
12378
|
} catch (err) {
|
|
@@ -18965,9 +19030,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
|
|
|
18965
19030
|
}
|
|
18966
19031
|
return svgString;
|
|
18967
19032
|
}
|
|
18968
|
-
const resolvedPackageVersion = "0.5.
|
|
19033
|
+
const resolvedPackageVersion = "0.5.212";
|
|
18969
19034
|
const PACKAGE_VERSION = resolvedPackageVersion;
|
|
18970
|
-
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.
|
|
19035
|
+
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.212";
|
|
18971
19036
|
const roundParityValue = (value) => {
|
|
18972
19037
|
if (typeof value !== "number") return value;
|
|
18973
19038
|
return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
|
|
@@ -19027,7 +19092,7 @@ function detectSafariOrIos() {
|
|
|
19027
19092
|
return false;
|
|
19028
19093
|
}
|
|
19029
19094
|
}
|
|
19030
|
-
async function downscaleConfigRasterImages(config, maxEdgePx, maxDataUrlBytes = 2e6) {
|
|
19095
|
+
async function downscaleConfigRasterImages(config, maxEdgePx, maxDataUrlBytes = 2e6, jpegQuality = 0.85) {
|
|
19031
19096
|
if (!maxEdgePx || maxEdgePx <= 0) return 0;
|
|
19032
19097
|
if (typeof document === "undefined") return 0;
|
|
19033
19098
|
const targets = [];
|
|
@@ -19091,7 +19156,7 @@ async function downscaleConfigRasterImages(config, maxEdgePx, maxDataUrlBytes =
|
|
|
19091
19156
|
return null;
|
|
19092
19157
|
}
|
|
19093
19158
|
let scale = tooLargeByEdge ? maxEdgePx / longest : 1;
|
|
19094
|
-
let quality = 0.
|
|
19159
|
+
let quality = Math.max(0.4, Math.min(1, jpegQuality));
|
|
19095
19160
|
let best = null;
|
|
19096
19161
|
for (let attempt = 0; attempt < 4; attempt++) {
|
|
19097
19162
|
const tw = Math.max(1, Math.round(w * scale));
|
|
@@ -19115,7 +19180,7 @@ async function downscaleConfigRasterImages(config, maxEdgePx, maxDataUrlBytes =
|
|
|
19115
19180
|
}
|
|
19116
19181
|
const byteScale = Math.sqrt(maxDataUrlBytes / Math.max(1, outBytes)) * 0.92;
|
|
19117
19182
|
scale = Math.max(0.1, scale * Math.min(0.95, byteScale));
|
|
19118
|
-
quality = Math.max(0.
|
|
19183
|
+
quality = Math.max(0.4, quality - 0.06);
|
|
19119
19184
|
}
|
|
19120
19185
|
if (blobUrl) URL.revokeObjectURL(blobUrl);
|
|
19121
19186
|
return best;
|
|
@@ -19490,7 +19555,9 @@ class PixldocsRenderer {
|
|
|
19490
19555
|
title: options == null ? void 0 : options.title,
|
|
19491
19556
|
textMode: options == null ? void 0 : options.textMode,
|
|
19492
19557
|
forcePerElementPdf: options == null ? void 0 : options.forcePerElementPdf,
|
|
19493
|
-
maxImageEdgePx: options == null ? void 0 : options.maxImageEdgePx
|
|
19558
|
+
maxImageEdgePx: options == null ? void 0 : options.maxImageEdgePx,
|
|
19559
|
+
compressImages: options == null ? void 0 : options.compressImages,
|
|
19560
|
+
compressionQuality: options == null ? void 0 : options.compressionQuality
|
|
19494
19561
|
});
|
|
19495
19562
|
}
|
|
19496
19563
|
/**
|
|
@@ -19498,7 +19565,7 @@ class PixldocsRenderer {
|
|
|
19498
19565
|
* This is the primary PDF export API — mirrors renderFromForm() but returns a PDF.
|
|
19499
19566
|
*/
|
|
19500
19567
|
async renderPdfFromForm(options) {
|
|
19501
|
-
const { templateId, formSchemaId, sectionState, themeId, watermark, watermarkOptions, prefetched, title, fontBaseUrl, textMode, forcePerElementPdf, maxImageEdgePx } = options;
|
|
19568
|
+
const { templateId, formSchemaId, sectionState, themeId, watermark, watermarkOptions, prefetched, title, fontBaseUrl, textMode, forcePerElementPdf, maxImageEdgePx, compressImages, compressionQuality } = options;
|
|
19502
19569
|
const resolved = await resolveFromForm({
|
|
19503
19570
|
templateId,
|
|
19504
19571
|
formSchemaId,
|
|
@@ -19521,7 +19588,9 @@ class PixldocsRenderer {
|
|
|
19521
19588
|
watermark: shouldWatermark,
|
|
19522
19589
|
textMode,
|
|
19523
19590
|
forcePerElementPdf,
|
|
19524
|
-
maxImageEdgePx
|
|
19591
|
+
maxImageEdgePx,
|
|
19592
|
+
compressImages,
|
|
19593
|
+
compressionQuality
|
|
19525
19594
|
});
|
|
19526
19595
|
}
|
|
19527
19596
|
async renderById(templateId, formData, options) {
|
|
@@ -19568,13 +19637,20 @@ class PixldocsRenderer {
|
|
|
19568
19637
|
const hasUserDataImage = configHasUserDataImage(cloned);
|
|
19569
19638
|
const isSafariLike = detectSafariOrIos();
|
|
19570
19639
|
const shouldForcePerElement = forceMode === true ? true : forceMode === false ? false : false;
|
|
19640
|
+
const compressImagesOpt = options.compressImages ?? true;
|
|
19571
19641
|
const maxEdgeOpt = options.maxImageEdgePx ?? this.config.maxImageEdgePx;
|
|
19572
|
-
const effectiveMaxEdge = typeof maxEdgeOpt === "number" ? Math.max(0, maxEdgeOpt | 0) : hasUserDataImage ? 2048 : 0;
|
|
19642
|
+
const effectiveMaxEdge = typeof maxEdgeOpt === "number" ? Math.max(0, maxEdgeOpt | 0) : compressImagesOpt ? hasUserDataImage ? 2048 : 0 : 0;
|
|
19643
|
+
const downscaleQuality = compressImagesOpt ? typeof options.compressionQuality === "number" ? Math.max(0.4, Math.min(1, options.compressionQuality)) : 0.85 : 0.95;
|
|
19573
19644
|
if (effectiveMaxEdge > 0) {
|
|
19574
19645
|
try {
|
|
19575
|
-
const downscaled = await downscaleConfigRasterImages(
|
|
19646
|
+
const downscaled = await downscaleConfigRasterImages(
|
|
19647
|
+
cloned,
|
|
19648
|
+
effectiveMaxEdge,
|
|
19649
|
+
void 0,
|
|
19650
|
+
downscaleQuality
|
|
19651
|
+
);
|
|
19576
19652
|
if (downscaled > 0) {
|
|
19577
|
-
console.log(`[canvas-renderer][pdf-unified] downscaled ${downscaled} raster image(s) to <=${effectiveMaxEdge}px edge`);
|
|
19653
|
+
console.log(`[canvas-renderer][pdf-unified] downscaled ${downscaled} raster image(s) to <=${effectiveMaxEdge}px edge @ q=${downscaleQuality}`);
|
|
19578
19654
|
}
|
|
19579
19655
|
} catch (e) {
|
|
19580
19656
|
console.warn("[canvas-renderer][pdf-unified] image downscale pass failed (continuing with originals):", e);
|
|
@@ -19585,7 +19661,9 @@ class PixldocsRenderer {
|
|
|
19585
19661
|
hasUserDataImage,
|
|
19586
19662
|
isSafariLike,
|
|
19587
19663
|
shouldForcePerElement,
|
|
19588
|
-
effectiveMaxEdge
|
|
19664
|
+
effectiveMaxEdge,
|
|
19665
|
+
compressImages: compressImagesOpt,
|
|
19666
|
+
downscaleQuality
|
|
19589
19667
|
});
|
|
19590
19668
|
const stampPrefix = `__pixldocs_pdf_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
19591
19669
|
const pageIds = cloned.pages.map((p, i) => {
|
|
@@ -19646,7 +19724,7 @@ class PixldocsRenderer {
|
|
|
19646
19724
|
await this.waitForCanvasScene(container, cloned, i);
|
|
19647
19725
|
}
|
|
19648
19726
|
console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
|
|
19649
|
-
const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-
|
|
19727
|
+
const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-zGrrm-iT.cjs"));
|
|
19650
19728
|
const prepared = preparePagesForExport(
|
|
19651
19729
|
cloned.pages,
|
|
19652
19730
|
canvasWidth,
|
|
@@ -19663,7 +19741,9 @@ class PixldocsRenderer {
|
|
|
19663
19741
|
// path and use the live Fabric object PDF path instead, preserving live
|
|
19664
19742
|
// matrices/order so we do not regress into stale config-space layout.
|
|
19665
19743
|
skipLiveCanvasSvgFastPath: forceMode === true,
|
|
19666
|
-
useLiveCanvasObjectPdfPath: shouldForcePerElement && forceMode !== true
|
|
19744
|
+
useLiveCanvasObjectPdfPath: shouldForcePerElement && forceMode !== true,
|
|
19745
|
+
compressImages: options.compressImages ?? true,
|
|
19746
|
+
compressionQuality: options.compressionQuality
|
|
19667
19747
|
});
|
|
19668
19748
|
if (!result || typeof result === "undefined") {
|
|
19669
19749
|
throw new Error("exportMultiPagePdf returned no blob (returnBlob path failed)");
|
|
@@ -21830,7 +21910,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
|
|
|
21830
21910
|
if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
|
|
21831
21911
|
sanitizeSvgTreeForPdf(svgToDraw);
|
|
21832
21912
|
try {
|
|
21833
|
-
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-
|
|
21913
|
+
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-zGrrm-iT.cjs"));
|
|
21834
21914
|
try {
|
|
21835
21915
|
await logTextMeasurementDiagnostic(svgToDraw);
|
|
21836
21916
|
} catch {
|
|
@@ -22227,4 +22307,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
|
|
|
22227
22307
|
exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
|
|
22228
22308
|
exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
|
|
22229
22309
|
exports.warmTemplateFromForm = warmTemplateFromForm;
|
|
22230
|
-
//# sourceMappingURL=index-
|
|
22310
|
+
//# sourceMappingURL=index-DB8j0PV0.cjs.map
|