@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.
@@ -6884,8 +6884,11 @@ 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 { passAlphas } = resolveShadowStrength(element);
6888
+ const firstAlpha = passAlphas.length > 0 ? passAlphas[0] : 0;
6889
+ const finalColor = applyAlphaMultiplier(String(color), firstAlpha);
6887
6890
  return new fabric.Shadow({
6888
- color: String(color),
6891
+ color: finalColor,
6889
6892
  blur: blur || 0,
6890
6893
  offsetX: ox || 0,
6891
6894
  offsetY: oy || 0,
@@ -6893,6 +6896,106 @@ function buildTextShadow(element) {
6893
6896
  nonScaling: false
6894
6897
  });
6895
6898
  }
6899
+ function resolveShadowStrength(element) {
6900
+ const raw = element.textShadowStrength;
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 };
6910
+ }
6911
+ function applyTextShadow(textbox, 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;
6919
+ const obj = textbox;
6920
+ if (!obj.__pdShadowOrigRender) {
6921
+ obj.__pdShadowOrigRender = obj.render.bind(obj);
6922
+ obj.render = function(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;
6945
+ };
6946
+ }
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);
6961
+ }
6962
+ function applyAlphaMultiplier(c, mult) {
6963
+ const m = Math.max(0, Math.min(1, mult));
6964
+ const s = String(c).trim();
6965
+ const rgba = s.match(/^rgba?\s*\(([^)]+)\)$/i);
6966
+ if (rgba) {
6967
+ const parts = rgba[1].split(",").map((p) => p.trim());
6968
+ const [r, g, b] = parts;
6969
+ const baseA = parts.length >= 4 ? Math.max(0, Math.min(1, parseFloat(parts[3]) || 0)) : 1;
6970
+ return `rgba(${r}, ${g}, ${b}, ${Math.round(baseA * m * 1e3) / 1e3})`;
6971
+ }
6972
+ const hex8 = s.match(/^#([0-9a-f]{8})$/i);
6973
+ if (hex8) {
6974
+ const h = hex8[1];
6975
+ const r = parseInt(h.slice(0, 2), 16);
6976
+ const g = parseInt(h.slice(2, 4), 16);
6977
+ const b = parseInt(h.slice(4, 6), 16);
6978
+ const baseA = parseInt(h.slice(6, 8), 16) / 255;
6979
+ return `rgba(${r}, ${g}, ${b}, ${Math.round(baseA * m * 1e3) / 1e3})`;
6980
+ }
6981
+ const hex6 = s.match(/^#([0-9a-f]{6})$/i);
6982
+ if (hex6) {
6983
+ const h = hex6[1];
6984
+ const r = parseInt(h.slice(0, 2), 16);
6985
+ const g = parseInt(h.slice(2, 4), 16);
6986
+ const b = parseInt(h.slice(4, 6), 16);
6987
+ return `rgba(${r}, ${g}, ${b}, ${Math.round(m * 1e3) / 1e3})`;
6988
+ }
6989
+ const hex3 = s.match(/^#([0-9a-f]{3})$/i);
6990
+ if (hex3) {
6991
+ const h = hex3[1];
6992
+ const r = parseInt(h[0] + h[0], 16);
6993
+ const g = parseInt(h[1] + h[1], 16);
6994
+ const b = parseInt(h[2] + h[2], 16);
6995
+ return `rgba(${r}, ${g}, ${b}, ${Math.round(m * 1e3) / 1e3})`;
6996
+ }
6997
+ return `rgba(0, 0, 0, ${Math.round(m * 1e3) / 1e3})`;
6998
+ }
6896
6999
  function buildRoundedRectPath2D(ctx, x, y, w, h, rTL, rTR, rBR, rBL) {
6897
7000
  const maxR = Math.min(w, h) / 2;
6898
7001
  const tl = Math.min(Math.max(0, rTL), maxR);
@@ -7235,7 +7338,10 @@ function applyTextBackground(obj, cfg) {
7235
7338
  const by = shadowBounds.y - pad;
7236
7339
  const bw = shadowBounds.w + pad * 2;
7237
7340
  const bh = shadowBounds.h + pad * 2;
7238
- 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)}"`;
7239
7345
  const wrapShadow = (markup) => blur <= 0 ? `<g transform="translate(${ox.toFixed(3)} ${oy.toFixed(3)})">${markup}</g>` : `<g class="__pdShadowRaster" ${dataAttrs}>${markup}</g>`;
7240
7346
  if (hasBg && (bg == null ? void 0 : bg.shadowAffectsBg) !== false) {
7241
7347
  const shadowOpacityAttr = bgOpacity < 1 ? ` fill-opacity="${bgOpacity}"` : "";
@@ -8457,8 +8563,7 @@ function createText(element) {
8457
8563
  }));
8458
8564
  }
8459
8565
  applyTextBackground(textbox, extractTextBgConfig(element));
8460
- const shadow = buildTextShadow(element);
8461
- if (shadow) textbox.set("shadow", shadow);
8566
+ applyTextShadow(textbox, element);
8462
8567
  return textbox;
8463
8568
  }
8464
8569
  function createLine(element) {
@@ -12265,8 +12370,7 @@ const PageCanvas = forwardRef(
12265
12370
  obj.dirty = true;
12266
12371
  try {
12267
12372
  applyTextBackground(obj, extractTextBgConfig(element));
12268
- const shadow = buildTextShadow(element);
12269
- obj.set("shadow", shadow ?? null);
12373
+ applyTextShadow(obj, element);
12270
12374
  try {
12271
12375
  obj._cacheCanvas = null;
12272
12376
  obj._cacheContext = null;
@@ -12294,7 +12398,8 @@ const PageCanvas = forwardRef(
12294
12398
  sy: element.textShadowOffsetY ?? 0,
12295
12399
  st: element.textShadowAffectsText !== false,
12296
12400
  sa: element.textShadowAffectsBg !== false,
12297
- sty: element.textShadowType ?? null
12401
+ sty: element.textShadowType ?? null,
12402
+ ss: element.textShadowStrength ?? null
12298
12403
  });
12299
12404
  obj.dirty = true;
12300
12405
  } catch (err) {
@@ -18952,9 +19057,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
18952
19057
  }
18953
19058
  return svgString;
18954
19059
  }
18955
- const resolvedPackageVersion = "0.5.211";
19060
+ const resolvedPackageVersion = "0.5.213";
18956
19061
  const PACKAGE_VERSION = resolvedPackageVersion;
18957
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.211";
19062
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.213";
18958
19063
  const roundParityValue = (value) => {
18959
19064
  if (typeof value !== "number") return value;
18960
19065
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -19646,7 +19751,7 @@ class PixldocsRenderer {
19646
19751
  await this.waitForCanvasScene(container, cloned, i);
19647
19752
  }
19648
19753
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
19649
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-BEGl71uB.js");
19754
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-ox1nl4G9.js");
19650
19755
  const prepared = preparePagesForExport(
19651
19756
  cloned.pages,
19652
19757
  canvasWidth,
@@ -21568,7 +21673,7 @@ async function convertSvgTextDecorationsToLinesString(svgStr) {
21568
21673
  }
21569
21674
  }
21570
21675
  async function rasterizeShadowMarkers(svg) {
21571
- var _a, _b, _c, _d, _e, _f;
21676
+ var _a, _b, _c, _d, _e, _f, _g;
21572
21677
  if (typeof window === "undefined" || typeof document === "undefined") return;
21573
21678
  const markers = Array.from(svg.querySelectorAll("g.__pdShadowRaster"));
21574
21679
  if (markers.length === 0) return;
@@ -21627,11 +21732,25 @@ async function rasterizeShadowMarkers(svg) {
21627
21732
  img.setAttribute("preserveAspectRatio", "none");
21628
21733
  img.setAttributeNS(XLINK_NS, "xlink:href", dataUrl);
21629
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;
21630
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
+ }
21631
21750
  } catch (e) {
21632
21751
  console.warn("[pdf-export] rasterizeShadowMarkers failed for one marker:", e);
21633
21752
  try {
21634
- (_f = marker.parentNode) == null ? void 0 : _f.removeChild(marker);
21753
+ (_g = marker.parentNode) == null ? void 0 : _g.removeChild(marker);
21635
21754
  } catch {
21636
21755
  }
21637
21756
  }
@@ -21832,7 +21951,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
21832
21951
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
21833
21952
  sanitizeSvgTreeForPdf(svgToDraw);
21834
21953
  try {
21835
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-BEGl71uB.js");
21954
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-ox1nl4G9.js");
21836
21955
  try {
21837
21956
  await logTextMeasurementDiagnostic(svgToDraw);
21838
21957
  } catch {
@@ -22232,4 +22351,4 @@ export {
22232
22351
  buildTeaserBlurFlatKeys as y,
22233
22352
  collectFontDescriptorsFromConfig as z
22234
22353
  };
22235
- //# sourceMappingURL=index-C0tTvSFQ.js.map
22354
+ //# sourceMappingURL=index-XZf4TDQ-.js.map