@pixldocs/canvas-renderer 0.5.212 → 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.
@@ -6884,8 +6884,9 @@ function buildTextShadow(element) {
6884
6884
  if (!color || color === "transparent") return null;
6885
6885
  const type = element.textShadowType;
6886
6886
  if (type && type !== "drop") return null;
6887
- const { perPassAlpha } = resolveShadowStrength(element);
6888
- const finalColor = applyAlphaMultiplier(String(color), perPassAlpha);
6887
+ const { passAlphas } = resolveShadowStrength(element);
6888
+ const firstAlpha = passAlphas.length > 0 ? passAlphas[0] : 0;
6889
+ const finalColor = applyAlphaMultiplier(String(color), firstAlpha);
6889
6890
  return new fabric.Shadow({
6890
6891
  color: finalColor,
6891
6892
  blur: blur || 0,
@@ -6897,25 +6898,66 @@ function buildTextShadow(element) {
6897
6898
  }
6898
6899
  function resolveShadowStrength(element) {
6899
6900
  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 };
6901
+ const s = typeof raw === "number" && Number.isFinite(raw) ? Math.max(0, Math.min(100, raw)) : 33.34;
6902
+ if (s <= 0) return { passAlphas: [] };
6903
+ const intensity = Math.min(3, s / 33.34);
6904
+ if (intensity <= 1) return { passAlphas: [intensity] };
6905
+ const full = Math.floor(intensity);
6906
+ const frac = intensity - full;
6907
+ const arr = new Array(full).fill(1);
6908
+ if (frac > 0.01) arr.push(frac);
6909
+ return { passAlphas: arr };
6905
6910
  }
6906
6911
  function applyTextShadow(textbox, element) {
6907
- const shadow = buildTextShadow(element);
6908
- const { passes } = resolveShadowStrength(element);
6912
+ const canonicalShadow = buildTextShadow(element);
6913
+ const { passAlphas } = resolveShadowStrength(element);
6914
+ const baseColor = element.textShadowColor;
6915
+ const blur = Number(element.textShadowBlur ?? 0) || 0;
6916
+ const ox = Number(element.textShadowOffsetX ?? 0) || 0;
6917
+ const oy = Number(element.textShadowOffsetY ?? 0) || 0;
6918
+ const hasShadow = !!canonicalShadow && passAlphas.length > 0;
6909
6919
  const obj = textbox;
6910
6920
  if (!obj.__pdShadowOrigRender) {
6911
6921
  obj.__pdShadowOrigRender = obj.render.bind(obj);
6912
6922
  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);
6923
+ const alphas = obj.__pdShadowPassAlphas;
6924
+ if (!alphas || alphas.length <= 1) {
6925
+ obj.__pdShadowOrigRender(ctx);
6926
+ return;
6927
+ }
6928
+ const orig = obj.shadow;
6929
+ const baseC = obj.__pdShadowBaseColor || "#000";
6930
+ const b = obj.__pdShadowBlur || 0;
6931
+ const x = obj.__pdShadowOX || 0;
6932
+ const y = obj.__pdShadowOY || 0;
6933
+ for (let i = 0; i < alphas.length; i++) {
6934
+ obj.shadow = new fabric.Shadow({
6935
+ color: applyAlphaMultiplier(String(baseC), alphas[i]),
6936
+ blur: b,
6937
+ offsetX: x,
6938
+ offsetY: y,
6939
+ affectStroke: false,
6940
+ nonScaling: false
6941
+ });
6942
+ obj.__pdShadowOrigRender(ctx);
6943
+ }
6944
+ obj.shadow = orig;
6915
6945
  };
6916
6946
  }
6917
- obj.__pdShadowPasses = shadow ? Math.max(1, passes) : 1;
6918
- textbox.set("shadow", shadow ?? null);
6947
+ if (hasShadow) {
6948
+ obj.__pdShadowPassAlphas = passAlphas;
6949
+ obj.__pdShadowBaseColor = baseColor;
6950
+ obj.__pdShadowBlur = blur;
6951
+ obj.__pdShadowOX = ox;
6952
+ obj.__pdShadowOY = oy;
6953
+ obj.__pdShadowPasses = passAlphas.length;
6954
+ obj.__pdShadowLastAlpha = passAlphas[passAlphas.length - 1];
6955
+ } else {
6956
+ obj.__pdShadowPassAlphas = void 0;
6957
+ obj.__pdShadowPasses = 0;
6958
+ obj.__pdShadowLastAlpha = 1;
6959
+ }
6960
+ textbox.set("shadow", canonicalShadow ?? null);
6919
6961
  }
6920
6962
  function applyAlphaMultiplier(c, mult) {
6921
6963
  const m = Math.max(0, Math.min(1, mult));
@@ -7296,7 +7338,10 @@ function applyTextBackground(obj, cfg) {
7296
7338
  const by = shadowBounds.y - pad;
7297
7339
  const bw = shadowBounds.w + pad * 2;
7298
7340
  const bh = shadowBounds.h + pad * 2;
7299
- 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)}"`;
7341
+ const passes = Math.max(1, Math.min(8, Number(this.__pdShadowPasses) || 1));
7342
+ const lastAlphaRaw = Number(this.__pdShadowLastAlpha);
7343
+ const lastAlpha = Number.isFinite(lastAlphaRaw) ? Math.max(0, Math.min(1, lastAlphaRaw)) : 1;
7344
+ 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)}"`;
7300
7345
  const wrapShadow = (markup) => blur <= 0 ? `<g transform="translate(${ox.toFixed(3)} ${oy.toFixed(3)})">${markup}</g>` : `<g class="__pdShadowRaster" ${dataAttrs}>${markup}</g>`;
7301
7346
  if (hasBg && (bg == null ? void 0 : bg.shadowAffectsBg) !== false) {
7302
7347
  const shadowOpacityAttr = bgOpacity < 1 ? ` fill-opacity="${bgOpacity}"` : "";
@@ -19012,9 +19057,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
19012
19057
  }
19013
19058
  return svgString;
19014
19059
  }
19015
- const resolvedPackageVersion = "0.5.212";
19060
+ const resolvedPackageVersion = "0.5.213";
19016
19061
  const PACKAGE_VERSION = resolvedPackageVersion;
19017
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.212";
19062
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.213";
19018
19063
  const roundParityValue = (value) => {
19019
19064
  if (typeof value !== "number") return value;
19020
19065
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -19706,7 +19751,7 @@ class PixldocsRenderer {
19706
19751
  await this.waitForCanvasScene(container, cloned, i);
19707
19752
  }
19708
19753
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
19709
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-CN-N0DE8.js");
19754
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-ox1nl4G9.js");
19710
19755
  const prepared = preparePagesForExport(
19711
19756
  cloned.pages,
19712
19757
  canvasWidth,
@@ -21628,7 +21673,7 @@ async function convertSvgTextDecorationsToLinesString(svgStr) {
21628
21673
  }
21629
21674
  }
21630
21675
  async function rasterizeShadowMarkers(svg) {
21631
- var _a, _b, _c, _d, _e, _f;
21676
+ var _a, _b, _c, _d, _e, _f, _g;
21632
21677
  if (typeof window === "undefined" || typeof document === "undefined") return;
21633
21678
  const markers = Array.from(svg.querySelectorAll("g.__pdShadowRaster"));
21634
21679
  if (markers.length === 0) return;
@@ -21687,11 +21732,25 @@ async function rasterizeShadowMarkers(svg) {
21687
21732
  img.setAttribute("preserveAspectRatio", "none");
21688
21733
  img.setAttributeNS(XLINK_NS, "xlink:href", dataUrl);
21689
21734
  img.setAttribute("href", dataUrl);
21735
+ const passes = Math.max(1, Math.min(8, parseInt(marker.getAttribute("data-passes") || "1", 10) || 1));
21736
+ const lastAlphaRaw = parseFloat(marker.getAttribute("data-last-alpha") || "1");
21737
+ const lastAlpha = Number.isFinite(lastAlphaRaw) ? Math.max(0, Math.min(1, lastAlphaRaw)) : 1;
21738
+ const baseOpacity = Number(img.getAttribute("opacity") || "1") || 1;
21690
21739
  (_e = marker.parentNode) == null ? void 0 : _e.replaceChild(img, marker);
21740
+ for (let i = 1; i < passes; i++) {
21741
+ const extra = img.cloneNode(true);
21742
+ if (i === passes - 1 && lastAlpha < 1) {
21743
+ extra.setAttribute("opacity", String(baseOpacity * lastAlpha));
21744
+ }
21745
+ (_f = img.parentNode) == null ? void 0 : _f.insertBefore(extra, img.nextSibling);
21746
+ }
21747
+ if (passes === 1 && lastAlpha < 1) {
21748
+ img.setAttribute("opacity", String(baseOpacity * lastAlpha));
21749
+ }
21691
21750
  } catch (e) {
21692
21751
  console.warn("[pdf-export] rasterizeShadowMarkers failed for one marker:", e);
21693
21752
  try {
21694
- (_f = marker.parentNode) == null ? void 0 : _f.removeChild(marker);
21753
+ (_g = marker.parentNode) == null ? void 0 : _g.removeChild(marker);
21695
21754
  } catch {
21696
21755
  }
21697
21756
  }
@@ -21892,7 +21951,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
21892
21951
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
21893
21952
  sanitizeSvgTreeForPdf(svgToDraw);
21894
21953
  try {
21895
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-CN-N0DE8.js");
21954
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-ox1nl4G9.js");
21896
21955
  try {
21897
21956
  await logTextMeasurementDiagnostic(svgToDraw);
21898
21957
  } catch {
@@ -22292,4 +22351,4 @@ export {
22292
22351
  buildTeaserBlurFlatKeys as y,
22293
22352
  collectFontDescriptorsFromConfig as z
22294
22353
  };
22295
- //# sourceMappingURL=index-B1QDVK5k.js.map
22354
+ //# sourceMappingURL=index-XZf4TDQ-.js.map