@pixldocs/canvas-renderer 0.5.211 → 0.5.213

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.
@@ -6902,8 +6902,11 @@ function buildTextShadow(element) {
6902
6902
  if (!color || color === "transparent") return null;
6903
6903
  const type = element.textShadowType;
6904
6904
  if (type && type !== "drop") return null;
6905
+ const { passAlphas } = resolveShadowStrength(element);
6906
+ const firstAlpha = passAlphas.length > 0 ? passAlphas[0] : 0;
6907
+ const finalColor = applyAlphaMultiplier(String(color), firstAlpha);
6905
6908
  return new fabric__namespace.Shadow({
6906
- color: String(color),
6909
+ color: finalColor,
6907
6910
  blur: blur || 0,
6908
6911
  offsetX: ox || 0,
6909
6912
  offsetY: oy || 0,
@@ -6911,6 +6914,106 @@ function buildTextShadow(element) {
6911
6914
  nonScaling: false
6912
6915
  });
6913
6916
  }
6917
+ function resolveShadowStrength(element) {
6918
+ const raw = element.textShadowStrength;
6919
+ const s = typeof raw === "number" && Number.isFinite(raw) ? Math.max(0, Math.min(100, raw)) : 33.34;
6920
+ if (s <= 0) return { passAlphas: [] };
6921
+ const intensity = Math.min(3, s / 33.34);
6922
+ if (intensity <= 1) return { passAlphas: [intensity] };
6923
+ const full = Math.floor(intensity);
6924
+ const frac = intensity - full;
6925
+ const arr = new Array(full).fill(1);
6926
+ if (frac > 0.01) arr.push(frac);
6927
+ return { passAlphas: arr };
6928
+ }
6929
+ function applyTextShadow(textbox, element) {
6930
+ const canonicalShadow = buildTextShadow(element);
6931
+ const { passAlphas } = resolveShadowStrength(element);
6932
+ const baseColor = element.textShadowColor;
6933
+ const blur = Number(element.textShadowBlur ?? 0) || 0;
6934
+ const ox = Number(element.textShadowOffsetX ?? 0) || 0;
6935
+ const oy = Number(element.textShadowOffsetY ?? 0) || 0;
6936
+ const hasShadow = !!canonicalShadow && passAlphas.length > 0;
6937
+ const obj = textbox;
6938
+ if (!obj.__pdShadowOrigRender) {
6939
+ obj.__pdShadowOrigRender = obj.render.bind(obj);
6940
+ obj.render = function(ctx) {
6941
+ const alphas = obj.__pdShadowPassAlphas;
6942
+ if (!alphas || alphas.length <= 1) {
6943
+ obj.__pdShadowOrigRender(ctx);
6944
+ return;
6945
+ }
6946
+ const orig = obj.shadow;
6947
+ const baseC = obj.__pdShadowBaseColor || "#000";
6948
+ const b = obj.__pdShadowBlur || 0;
6949
+ const x = obj.__pdShadowOX || 0;
6950
+ const y = obj.__pdShadowOY || 0;
6951
+ for (let i = 0; i < alphas.length; i++) {
6952
+ obj.shadow = new fabric__namespace.Shadow({
6953
+ color: applyAlphaMultiplier(String(baseC), alphas[i]),
6954
+ blur: b,
6955
+ offsetX: x,
6956
+ offsetY: y,
6957
+ affectStroke: false,
6958
+ nonScaling: false
6959
+ });
6960
+ obj.__pdShadowOrigRender(ctx);
6961
+ }
6962
+ obj.shadow = orig;
6963
+ };
6964
+ }
6965
+ if (hasShadow) {
6966
+ obj.__pdShadowPassAlphas = passAlphas;
6967
+ obj.__pdShadowBaseColor = baseColor;
6968
+ obj.__pdShadowBlur = blur;
6969
+ obj.__pdShadowOX = ox;
6970
+ obj.__pdShadowOY = oy;
6971
+ obj.__pdShadowPasses = passAlphas.length;
6972
+ obj.__pdShadowLastAlpha = passAlphas[passAlphas.length - 1];
6973
+ } else {
6974
+ obj.__pdShadowPassAlphas = void 0;
6975
+ obj.__pdShadowPasses = 0;
6976
+ obj.__pdShadowLastAlpha = 1;
6977
+ }
6978
+ textbox.set("shadow", canonicalShadow ?? null);
6979
+ }
6980
+ function applyAlphaMultiplier(c, mult) {
6981
+ const m = Math.max(0, Math.min(1, mult));
6982
+ const s = String(c).trim();
6983
+ const rgba = s.match(/^rgba?\s*\(([^)]+)\)$/i);
6984
+ if (rgba) {
6985
+ const parts = rgba[1].split(",").map((p) => p.trim());
6986
+ const [r, g, b] = parts;
6987
+ const baseA = parts.length >= 4 ? Math.max(0, Math.min(1, parseFloat(parts[3]) || 0)) : 1;
6988
+ return `rgba(${r}, ${g}, ${b}, ${Math.round(baseA * m * 1e3) / 1e3})`;
6989
+ }
6990
+ const hex8 = s.match(/^#([0-9a-f]{8})$/i);
6991
+ if (hex8) {
6992
+ const h = hex8[1];
6993
+ const r = parseInt(h.slice(0, 2), 16);
6994
+ const g = parseInt(h.slice(2, 4), 16);
6995
+ const b = parseInt(h.slice(4, 6), 16);
6996
+ const baseA = parseInt(h.slice(6, 8), 16) / 255;
6997
+ return `rgba(${r}, ${g}, ${b}, ${Math.round(baseA * m * 1e3) / 1e3})`;
6998
+ }
6999
+ const hex6 = s.match(/^#([0-9a-f]{6})$/i);
7000
+ if (hex6) {
7001
+ const h = hex6[1];
7002
+ const r = parseInt(h.slice(0, 2), 16);
7003
+ const g = parseInt(h.slice(2, 4), 16);
7004
+ const b = parseInt(h.slice(4, 6), 16);
7005
+ return `rgba(${r}, ${g}, ${b}, ${Math.round(m * 1e3) / 1e3})`;
7006
+ }
7007
+ const hex3 = s.match(/^#([0-9a-f]{3})$/i);
7008
+ if (hex3) {
7009
+ const h = hex3[1];
7010
+ const r = parseInt(h[0] + h[0], 16);
7011
+ const g = parseInt(h[1] + h[1], 16);
7012
+ const b = parseInt(h[2] + h[2], 16);
7013
+ return `rgba(${r}, ${g}, ${b}, ${Math.round(m * 1e3) / 1e3})`;
7014
+ }
7015
+ return `rgba(0, 0, 0, ${Math.round(m * 1e3) / 1e3})`;
7016
+ }
6914
7017
  function buildRoundedRectPath2D(ctx, x, y, w, h, rTL, rTR, rBR, rBL) {
6915
7018
  const maxR = Math.min(w, h) / 2;
6916
7019
  const tl = Math.min(Math.max(0, rTL), maxR);
@@ -7253,7 +7356,10 @@ function applyTextBackground(obj, cfg) {
7253
7356
  const by = shadowBounds.y - pad;
7254
7357
  const bw = shadowBounds.w + pad * 2;
7255
7358
  const bh = shadowBounds.h + pad * 2;
7256
- const dataAttrs = `data-blur="${blur.toFixed(3)}" data-ox="${ox.toFixed(3)}" data-oy="${oy.toFixed(3)}" data-bx="${bx.toFixed(3)}" data-by="${by.toFixed(3)}" data-bw="${bw.toFixed(3)}" data-bh="${bh.toFixed(3)}" data-color="${escapeXmlAttr(shadowColor)}"`;
7359
+ const passes = Math.max(1, Math.min(8, Number(this.__pdShadowPasses) || 1));
7360
+ const lastAlphaRaw = Number(this.__pdShadowLastAlpha);
7361
+ const lastAlpha = Number.isFinite(lastAlphaRaw) ? Math.max(0, Math.min(1, lastAlphaRaw)) : 1;
7362
+ const dataAttrs = `data-blur="${blur.toFixed(3)}" data-ox="${ox.toFixed(3)}" data-oy="${oy.toFixed(3)}" data-bx="${bx.toFixed(3)}" data-by="${by.toFixed(3)}" data-bw="${bw.toFixed(3)}" data-bh="${bh.toFixed(3)}" data-color="${escapeXmlAttr(shadowColor)}" data-passes="${passes}" data-last-alpha="${lastAlpha.toFixed(3)}"`;
7257
7363
  const wrapShadow = (markup) => blur <= 0 ? `<g transform="translate(${ox.toFixed(3)} ${oy.toFixed(3)})">${markup}</g>` : `<g class="__pdShadowRaster" ${dataAttrs}>${markup}</g>`;
7258
7364
  if (hasBg && (bg == null ? void 0 : bg.shadowAffectsBg) !== false) {
7259
7365
  const shadowOpacityAttr = bgOpacity < 1 ? ` fill-opacity="${bgOpacity}"` : "";
@@ -8475,8 +8581,7 @@ function createText(element) {
8475
8581
  }));
8476
8582
  }
8477
8583
  applyTextBackground(textbox, extractTextBgConfig(element));
8478
- const shadow = buildTextShadow(element);
8479
- if (shadow) textbox.set("shadow", shadow);
8584
+ applyTextShadow(textbox, element);
8480
8585
  return textbox;
8481
8586
  }
8482
8587
  function createLine(element) {
@@ -12283,8 +12388,7 @@ const PageCanvas = react.forwardRef(
12283
12388
  obj.dirty = true;
12284
12389
  try {
12285
12390
  applyTextBackground(obj, extractTextBgConfig(element));
12286
- const shadow = buildTextShadow(element);
12287
- obj.set("shadow", shadow ?? null);
12391
+ applyTextShadow(obj, element);
12288
12392
  try {
12289
12393
  obj._cacheCanvas = null;
12290
12394
  obj._cacheContext = null;
@@ -12312,7 +12416,8 @@ const PageCanvas = react.forwardRef(
12312
12416
  sy: element.textShadowOffsetY ?? 0,
12313
12417
  st: element.textShadowAffectsText !== false,
12314
12418
  sa: element.textShadowAffectsBg !== false,
12315
- sty: element.textShadowType ?? null
12419
+ sty: element.textShadowType ?? null,
12420
+ ss: element.textShadowStrength ?? null
12316
12421
  });
12317
12422
  obj.dirty = true;
12318
12423
  } catch (err) {
@@ -18970,9 +19075,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
18970
19075
  }
18971
19076
  return svgString;
18972
19077
  }
18973
- const resolvedPackageVersion = "0.5.211";
19078
+ const resolvedPackageVersion = "0.5.213";
18974
19079
  const PACKAGE_VERSION = resolvedPackageVersion;
18975
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.211";
19080
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.213";
18976
19081
  const roundParityValue = (value) => {
18977
19082
  if (typeof value !== "number") return value;
18978
19083
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -19664,7 +19769,7 @@ class PixldocsRenderer {
19664
19769
  await this.waitForCanvasScene(container, cloned, i);
19665
19770
  }
19666
19771
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
19667
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-QzySzFJJ.cjs"));
19772
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-krI8SwbX.cjs"));
19668
19773
  const prepared = preparePagesForExport(
19669
19774
  cloned.pages,
19670
19775
  canvasWidth,
@@ -21586,7 +21691,7 @@ async function convertSvgTextDecorationsToLinesString(svgStr) {
21586
21691
  }
21587
21692
  }
21588
21693
  async function rasterizeShadowMarkers(svg) {
21589
- var _a, _b, _c, _d, _e, _f;
21694
+ var _a, _b, _c, _d, _e, _f, _g;
21590
21695
  if (typeof window === "undefined" || typeof document === "undefined") return;
21591
21696
  const markers = Array.from(svg.querySelectorAll("g.__pdShadowRaster"));
21592
21697
  if (markers.length === 0) return;
@@ -21645,11 +21750,25 @@ async function rasterizeShadowMarkers(svg) {
21645
21750
  img.setAttribute("preserveAspectRatio", "none");
21646
21751
  img.setAttributeNS(XLINK_NS, "xlink:href", dataUrl);
21647
21752
  img.setAttribute("href", dataUrl);
21753
+ const passes = Math.max(1, Math.min(8, parseInt(marker.getAttribute("data-passes") || "1", 10) || 1));
21754
+ const lastAlphaRaw = parseFloat(marker.getAttribute("data-last-alpha") || "1");
21755
+ const lastAlpha = Number.isFinite(lastAlphaRaw) ? Math.max(0, Math.min(1, lastAlphaRaw)) : 1;
21756
+ const baseOpacity = Number(img.getAttribute("opacity") || "1") || 1;
21648
21757
  (_e = marker.parentNode) == null ? void 0 : _e.replaceChild(img, marker);
21758
+ for (let i = 1; i < passes; i++) {
21759
+ const extra = img.cloneNode(true);
21760
+ if (i === passes - 1 && lastAlpha < 1) {
21761
+ extra.setAttribute("opacity", String(baseOpacity * lastAlpha));
21762
+ }
21763
+ (_f = img.parentNode) == null ? void 0 : _f.insertBefore(extra, img.nextSibling);
21764
+ }
21765
+ if (passes === 1 && lastAlpha < 1) {
21766
+ img.setAttribute("opacity", String(baseOpacity * lastAlpha));
21767
+ }
21649
21768
  } catch (e) {
21650
21769
  console.warn("[pdf-export] rasterizeShadowMarkers failed for one marker:", e);
21651
21770
  try {
21652
- (_f = marker.parentNode) == null ? void 0 : _f.removeChild(marker);
21771
+ (_g = marker.parentNode) == null ? void 0 : _g.removeChild(marker);
21653
21772
  } catch {
21654
21773
  }
21655
21774
  }
@@ -21850,7 +21969,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
21850
21969
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
21851
21970
  sanitizeSvgTreeForPdf(svgToDraw);
21852
21971
  try {
21853
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-QzySzFJJ.cjs"));
21972
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-krI8SwbX.cjs"));
21854
21973
  try {
21855
21974
  await logTextMeasurementDiagnostic(svgToDraw);
21856
21975
  } catch {
@@ -22247,4 +22366,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
22247
22366
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
22248
22367
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
22249
22368
  exports.warmTemplateFromForm = warmTemplateFromForm;
22250
- //# sourceMappingURL=index-d8U2oDzI.cjs.map
22369
+ //# sourceMappingURL=index-zkVpb-YL.cjs.map