@pixldocs/canvas-renderer 0.5.461 → 0.5.463

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.
@@ -4397,7 +4397,8 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
4397
4397
  } else if (imageFit2 === "contain") {
4398
4398
  const scaleX = elementWidth / imgNaturalWidth;
4399
4399
  const scaleY = elementHeight / imgNaturalHeight;
4400
- const scale = Math.min(scaleX, scaleY);
4400
+ const containScale = Math.max(1, Math.min(3, Number(element.containScale ?? 1)));
4401
+ const scale = Math.min(scaleX, scaleY) * containScale;
4401
4402
  baseScaleX = scale;
4402
4403
  baseScaleY = scale;
4403
4404
  } else {
@@ -4431,8 +4432,12 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
4431
4432
  const elementHeight2 = Number(element.height) * (element.scaleY ?? 1);
4432
4433
  const scaledImageWidth = imgNaturalWidth * baseScaleX;
4433
4434
  const scaledImageHeight = imgNaturalHeight * baseScaleY;
4434
- const imageLeft = (elementWidth2 - scaledImageWidth) / 2;
4435
- const imageTop = (elementHeight2 - scaledImageHeight) / 2;
4435
+ const alignH = element.imageAlignH ?? "center";
4436
+ const alignV = element.imageAlignV ?? "middle";
4437
+ const slackX = elementWidth2 - scaledImageWidth;
4438
+ const slackY = elementHeight2 - scaledImageHeight;
4439
+ const imageLeft = imageFit2 === "contain" ? alignH === "left" ? 0 : alignH === "right" ? slackX : slackX / 2 : slackX / 2;
4440
+ const imageTop = imageFit2 === "contain" ? alignV === "top" ? 0 : alignV === "bottom" ? slackY : slackY / 2 : slackY / 2;
4436
4441
  img.set({
4437
4442
  originX: "left",
4438
4443
  originY: "top",
@@ -5211,7 +5216,7 @@ function updateCoverLayout(g) {
5211
5216
  const ih = img.height || 1;
5212
5217
  const fitContain = ct.fit === "contain";
5213
5218
  const baseScale = fitContain ? Math.min(frameW / iw, frameH / ih) : Math.max(frameW / iw, frameH / ih);
5214
- const zoom = fitContain ? 1 : Math.max(1, img._ct.zoom ?? 1);
5219
+ const zoom = fitContain ? Math.max(1, Math.min(3, ct.containScale ?? 1)) : Math.max(1, img._ct.zoom ?? 1);
5215
5220
  const finalScale = baseScale * zoom;
5216
5221
  img.set({
5217
5222
  scaleX: finalScale,
@@ -5231,8 +5236,19 @@ function updateCoverLayout(g) {
5231
5236
  const overflowY = Math.max(0, dispH - frameH);
5232
5237
  const panX = clamp$1(img._ct.panX ?? 0.5, 0, 1);
5233
5238
  const panY = clamp$1(img._ct.panY ?? 0.5, 0, 1);
5234
- const offsetX = fitContain ? 0 : overflowX > 0 ? -overflowX * (panX - 0.5) : 0;
5235
- const offsetY = fitContain ? 0 : overflowY > 0 ? -overflowY * (panY - 0.5) : 0;
5239
+ let offsetX = 0;
5240
+ let offsetY = 0;
5241
+ if (fitContain) {
5242
+ const alignH = ct.alignH ?? "center";
5243
+ const alignV = ct.alignV ?? "middle";
5244
+ const slackX = frameW - dispW;
5245
+ const slackY = frameH - dispH;
5246
+ offsetX = alignH === "left" ? -slackX / 2 : alignH === "right" ? slackX / 2 : 0;
5247
+ offsetY = alignV === "top" ? -slackY / 2 : alignV === "bottom" ? slackY / 2 : 0;
5248
+ } else {
5249
+ offsetX = overflowX > 0 ? -overflowX * (panX - 0.5) : 0;
5250
+ offsetY = overflowY > 0 ? -overflowY * (panY - 0.5) : 0;
5251
+ }
5236
5252
  img.set({ left: offsetX, top: offsetY });
5237
5253
  g.dirty = true;
5238
5254
  img.dirty = true;
@@ -5605,7 +5621,11 @@ async function createMaskedImageElement({
5605
5621
  visible = true,
5606
5622
  panX = 0.5,
5607
5623
  panY = 0.5,
5608
- zoom = 1
5624
+ zoom = 1,
5625
+ fit = "cover",
5626
+ alignH = "center",
5627
+ alignV = "middle",
5628
+ containScale = 1
5609
5629
  }) {
5610
5630
  const img = image || (url ? await fabric__namespace.FabricImage.fromURL(getProxiedImageUrl(url), { crossOrigin: "anonymous" }) : null);
5611
5631
  if (!img) {
@@ -5724,8 +5744,13 @@ async function createMaskedImageElement({
5724
5744
  rx,
5725
5745
  frameW,
5726
5746
  frameH,
5727
- fit: "cover",
5728
- // clip image to frame; use 'contain' only when simple-scale mode is set
5747
+ // Honor the element's authored imageFit. When 'contain', the image is
5748
+ // scaled to fit fully inside the frame (no clipping) and alignH/alignV
5749
+ // control where the letterboxed image sits.
5750
+ fit,
5751
+ alignH,
5752
+ alignV,
5753
+ containScale: Math.max(1, Math.min(3, containScale || 1)),
5729
5754
  _img: img,
5730
5755
  _border: border
5731
5756
  };
@@ -19634,7 +19659,14 @@ const PageCanvas = react.forwardRef(
19634
19659
  visible: !isHidden,
19635
19660
  panX,
19636
19661
  panY,
19637
- zoom: zoom2
19662
+ zoom: zoom2,
19663
+ // Honor authored Object Fit + alignment so contain logos render
19664
+ // fully inside the frame, with letterbox aligned to the chosen
19665
+ // edge (instead of being silently cover-cropped).
19666
+ fit: imageFitFinal === "contain" ? "contain" : "cover",
19667
+ alignH: element.imageAlignH ?? "center",
19668
+ alignV: element.imageAlignV ?? "middle",
19669
+ containScale: Math.max(1, Math.min(3, Number(element.containScale ?? 1)))
19638
19670
  });
19639
19671
  cropGroup.__maintainResolution = element.maintainResolution !== false;
19640
19672
  cropGroup.set({
@@ -26241,9 +26273,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
26241
26273
  }
26242
26274
  return svgString;
26243
26275
  }
26244
- const resolvedPackageVersion = "0.5.461";
26276
+ const resolvedPackageVersion = "0.5.463";
26245
26277
  const PACKAGE_VERSION = resolvedPackageVersion;
26246
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.461";
26278
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.463";
26247
26279
  const roundParityValue = (value) => {
26248
26280
  if (typeof value !== "number") return value;
26249
26281
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -27057,7 +27089,7 @@ class PixldocsRenderer {
27057
27089
  await this.waitForCanvasScene(container, cloned, i);
27058
27090
  }
27059
27091
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
27060
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-C7mmAR68.cjs"));
27092
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-DFhh1h5p.cjs"));
27061
27093
  const prepared = preparePagesForExport(
27062
27094
  cloned.pages,
27063
27095
  canvasWidth,
@@ -29377,7 +29409,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
29377
29409
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
29378
29410
  sanitizeSvgTreeForPdf(svgToDraw);
29379
29411
  try {
29380
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-C7mmAR68.cjs"));
29412
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-DFhh1h5p.cjs"));
29381
29413
  try {
29382
29414
  await logTextMeasurementDiagnostic(svgToDraw);
29383
29415
  } catch {
@@ -29691,4 +29723,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
29691
29723
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
29692
29724
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
29693
29725
  exports.warmTemplateFromForm = warmTemplateFromForm;
29694
- //# sourceMappingURL=index-D1sMo2it.cjs.map
29726
+ //# sourceMappingURL=index-kf9OkhGi.cjs.map