@pixldocs/canvas-renderer 0.5.151 → 0.5.153

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.
@@ -5762,20 +5762,56 @@ function recolorSvgFills(svg, color) {
5762
5762
  return _recolorSvgFills(svg, color);
5763
5763
  }
5764
5764
  function bakeTextSvgToFabricLineStarts(svg, obj, w) {
5765
- var _a;
5765
+ var _a, _b, _c, _d;
5766
5766
  try {
5767
5767
  const lines = (obj == null ? void 0 : obj._textLines) ?? [];
5768
5768
  if (!Array.isArray(lines) || lines.length === 0) return svg;
5769
+ const rawAlign = String((obj == null ? void 0 : obj.textAlign) || "left").toLowerCase();
5770
+ const alignmentAnchor = /right|end/.test(rawAlign) ? "end" : /center/.test(rawAlign) ? "middle" : "start";
5771
+ const hasStyledChars = (() => {
5772
+ const styles = obj == null ? void 0 : obj.styles;
5773
+ if (!styles || typeof styles !== "object") return false;
5774
+ return Object.values(styles).some((line) => line && typeof line === "object" && Object.keys(line).length > 0);
5775
+ })();
5776
+ const canUseAlignmentAnchor = alignmentAnchor !== "start" && !hasStyledChars && !(obj == null ? void 0 : obj.path) && !Number((obj == null ? void 0 : obj.charSpacing) ?? 0);
5769
5777
  const halfW = w / 2;
5770
- const lineXs = [];
5778
+ const lineAnchors = [];
5771
5779
  for (let i = 0; i < lines.length; i++) {
5772
5780
  let lineLeft = 0;
5781
+ let lineW = 0;
5782
+ let firstGlyphAdjust = 0;
5773
5783
  try {
5774
5784
  lineLeft = ((_a = obj._getLineLeftOffset) == null ? void 0 : _a.call(obj, i)) ?? 0;
5775
5785
  } catch {
5776
5786
  lineLeft = 0;
5777
5787
  }
5778
- lineXs.push(-halfW + (Number.isFinite(lineLeft) ? lineLeft : 0));
5788
+ try {
5789
+ lineW = ((_b = obj.getLineWidth) == null ? void 0 : _b.call(obj, i)) ?? 0;
5790
+ } catch {
5791
+ lineW = 0;
5792
+ }
5793
+ try {
5794
+ const firstBox = (_d = (_c = obj.__charBounds) == null ? void 0 : _c[i]) == null ? void 0 : _d[0];
5795
+ const kerned = Number(firstBox == null ? void 0 : firstBox.kernedWidth);
5796
+ const glyphW = Number(firstBox == null ? void 0 : firstBox.width);
5797
+ if (Number.isFinite(kerned) && Number.isFinite(glyphW)) {
5798
+ firstGlyphAdjust = kerned - glyphW;
5799
+ }
5800
+ } catch {
5801
+ firstGlyphAdjust = 0;
5802
+ }
5803
+ const baseStart = -halfW + (Number.isFinite(lineLeft) ? lineLeft : 0);
5804
+ if (canUseAlignmentAnchor && Number.isFinite(lineW) && lineW > 0) {
5805
+ lineAnchors.push({
5806
+ x: alignmentAnchor === "end" ? baseStart + lineW : baseStart + lineW / 2,
5807
+ anchor: alignmentAnchor
5808
+ });
5809
+ } else {
5810
+ lineAnchors.push({
5811
+ x: baseStart + (Number.isFinite(firstGlyphAdjust) ? firstGlyphAdjust : 0),
5812
+ anchor: "start"
5813
+ });
5814
+ }
5779
5815
  }
5780
5816
  const textOpenRe = /<text\b([^>]*)>/i;
5781
5817
  const textOpenMatch = svg.match(textOpenRe);
@@ -5791,14 +5827,27 @@ function bakeTextSvgToFabricLineStarts(svg, obj, w) {
5791
5827
  (_m, pre, val, post) => pre + val.replace(/text-align\s*:\s*[^;"']+;?/gi, "").trim() + post
5792
5828
  );
5793
5829
  const newTextOpen = `<text${textAttrs}>`;
5830
+ const stripAnchorAttrs = (attrs) => attrs.replace(/\s+text-anchor\s*=\s*"[^"]*"/gi, "").replace(
5831
+ /(\sstyle=")([^"]*)(")/i,
5832
+ (_m, pre, val, post) => pre + val.replace(/text-anchor\s*:\s*[^;"']+;?/gi, "").trim() + post
5833
+ );
5794
5834
  let lineIdx = 0;
5835
+ let lastY = "";
5795
5836
  const newSvg = svg.replace(textOpenMatch[0], newTextOpen).replace(
5796
5837
  /<tspan\b([^>]*?)\sx="([^"]*)"([^>]*)>/gi,
5797
5838
  (_m, pre, _oldX, post) => {
5798
- const x = lineXs[lineIdx];
5839
+ const attrs = `${pre} ${post}`;
5840
+ const yMatch = attrs.match(/\sy\s*=\s*"([^"]*)"/i);
5841
+ const y = (yMatch == null ? void 0 : yMatch[1]) ?? "";
5842
+ const isLineStart = y !== "" ? y !== lastY : lineIdx < lineAnchors.length;
5843
+ if (!isLineStart) return _m;
5844
+ if (y !== "") lastY = y;
5845
+ const lineAnchor = lineAnchors[lineIdx];
5799
5846
  lineIdx += 1;
5800
- if (typeof x !== "number" || !Number.isFinite(x)) return _m;
5801
- return `<tspan${pre} x="${x.toFixed(3)}"${post}>`;
5847
+ if (!lineAnchor || typeof lineAnchor.x !== "number" || !Number.isFinite(lineAnchor.x)) return _m;
5848
+ const cleanPre = stripAnchorAttrs(pre);
5849
+ const cleanPost = stripAnchorAttrs(post);
5850
+ return `<tspan${cleanPre} x="${lineAnchor.x.toFixed(3)}" text-anchor="${lineAnchor.anchor}" data-pd-line-anchor="1"${cleanPost}>`;
5802
5851
  }
5803
5852
  );
5804
5853
  return newSvg;
@@ -16027,9 +16076,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
16027
16076
  }
16028
16077
  return svgString;
16029
16078
  }
16030
- const resolvedPackageVersion = "0.5.151";
16079
+ const resolvedPackageVersion = "0.5.153";
16031
16080
  const PACKAGE_VERSION = resolvedPackageVersion;
16032
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.151";
16081
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.153";
16033
16082
  const roundParityValue = (value) => {
16034
16083
  if (typeof value !== "number") return value;
16035
16084
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -16464,7 +16513,7 @@ class PixldocsRenderer {
16464
16513
  await this.waitForCanvasScene(container, cloned, i);
16465
16514
  }
16466
16515
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
16467
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-BEohav7Y.cjs"));
16516
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-YSo453Ul.cjs"));
16468
16517
  const prepared = preparePagesForExport(
16469
16518
  cloned.pages,
16470
16519
  canvasWidth,
@@ -18566,7 +18615,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
18566
18615
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
18567
18616
  sanitizeSvgTreeForPdf(svgToDraw);
18568
18617
  try {
18569
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-BEohav7Y.cjs"));
18618
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-YSo453Ul.cjs"));
18570
18619
  try {
18571
18620
  await logTextMeasurementDiagnostic(svgToDraw);
18572
18621
  } catch {
@@ -18701,7 +18750,7 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
18701
18750
  }
18702
18751
  if (shouldOutlineText) {
18703
18752
  try {
18704
- const { convertAllTextToPath } = await Promise.resolve().then(() => require("./svgTextToPath-qhinMiiS.cjs"));
18753
+ const { convertAllTextToPath } = await Promise.resolve().then(() => require("./svgTextToPath-IM1f6F-f.cjs"));
18705
18754
  pageSvg = await convertAllTextToPath(pageSvg, fontBaseUrl, { mode: outlineSubMode });
18706
18755
  try {
18707
18756
  dumpSvgTextDiagnostics(pageSvg, i, PARITY_TAG, "STAGE-1b-after-text-to-path-raw");
@@ -18913,4 +18962,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
18913
18962
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
18914
18963
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
18915
18964
  exports.warmTemplateFromForm = warmTemplateFromForm;
18916
- //# sourceMappingURL=index-Clvky1Ne.cjs.map
18965
+ //# sourceMappingURL=index-Bp0cz5Mq.cjs.map