@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.
@@ -4379,7 +4379,8 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
4379
4379
  } else if (imageFit2 === "contain") {
4380
4380
  const scaleX = elementWidth / imgNaturalWidth;
4381
4381
  const scaleY = elementHeight / imgNaturalHeight;
4382
- const scale = Math.min(scaleX, scaleY);
4382
+ const containScale = Math.max(1, Math.min(3, Number(element.containScale ?? 1)));
4383
+ const scale = Math.min(scaleX, scaleY) * containScale;
4383
4384
  baseScaleX = scale;
4384
4385
  baseScaleY = scale;
4385
4386
  } else {
@@ -4413,8 +4414,12 @@ async function loadImageAsync(element, placeholder, fc, fabricRef, syncLockedRef
4413
4414
  const elementHeight2 = Number(element.height) * (element.scaleY ?? 1);
4414
4415
  const scaledImageWidth = imgNaturalWidth * baseScaleX;
4415
4416
  const scaledImageHeight = imgNaturalHeight * baseScaleY;
4416
- const imageLeft = (elementWidth2 - scaledImageWidth) / 2;
4417
- const imageTop = (elementHeight2 - scaledImageHeight) / 2;
4417
+ const alignH = element.imageAlignH ?? "center";
4418
+ const alignV = element.imageAlignV ?? "middle";
4419
+ const slackX = elementWidth2 - scaledImageWidth;
4420
+ const slackY = elementHeight2 - scaledImageHeight;
4421
+ const imageLeft = imageFit2 === "contain" ? alignH === "left" ? 0 : alignH === "right" ? slackX : slackX / 2 : slackX / 2;
4422
+ const imageTop = imageFit2 === "contain" ? alignV === "top" ? 0 : alignV === "bottom" ? slackY : slackY / 2 : slackY / 2;
4418
4423
  img.set({
4419
4424
  originX: "left",
4420
4425
  originY: "top",
@@ -5193,7 +5198,7 @@ function updateCoverLayout(g) {
5193
5198
  const ih = img.height || 1;
5194
5199
  const fitContain = ct.fit === "contain";
5195
5200
  const baseScale = fitContain ? Math.min(frameW / iw, frameH / ih) : Math.max(frameW / iw, frameH / ih);
5196
- const zoom = fitContain ? 1 : Math.max(1, img._ct.zoom ?? 1);
5201
+ const zoom = fitContain ? Math.max(1, Math.min(3, ct.containScale ?? 1)) : Math.max(1, img._ct.zoom ?? 1);
5197
5202
  const finalScale = baseScale * zoom;
5198
5203
  img.set({
5199
5204
  scaleX: finalScale,
@@ -5213,8 +5218,19 @@ function updateCoverLayout(g) {
5213
5218
  const overflowY = Math.max(0, dispH - frameH);
5214
5219
  const panX = clamp$1(img._ct.panX ?? 0.5, 0, 1);
5215
5220
  const panY = clamp$1(img._ct.panY ?? 0.5, 0, 1);
5216
- const offsetX = fitContain ? 0 : overflowX > 0 ? -overflowX * (panX - 0.5) : 0;
5217
- const offsetY = fitContain ? 0 : overflowY > 0 ? -overflowY * (panY - 0.5) : 0;
5221
+ let offsetX = 0;
5222
+ let offsetY = 0;
5223
+ if (fitContain) {
5224
+ const alignH = ct.alignH ?? "center";
5225
+ const alignV = ct.alignV ?? "middle";
5226
+ const slackX = frameW - dispW;
5227
+ const slackY = frameH - dispH;
5228
+ offsetX = alignH === "left" ? -slackX / 2 : alignH === "right" ? slackX / 2 : 0;
5229
+ offsetY = alignV === "top" ? -slackY / 2 : alignV === "bottom" ? slackY / 2 : 0;
5230
+ } else {
5231
+ offsetX = overflowX > 0 ? -overflowX * (panX - 0.5) : 0;
5232
+ offsetY = overflowY > 0 ? -overflowY * (panY - 0.5) : 0;
5233
+ }
5218
5234
  img.set({ left: offsetX, top: offsetY });
5219
5235
  g.dirty = true;
5220
5236
  img.dirty = true;
@@ -5587,7 +5603,11 @@ async function createMaskedImageElement({
5587
5603
  visible = true,
5588
5604
  panX = 0.5,
5589
5605
  panY = 0.5,
5590
- zoom = 1
5606
+ zoom = 1,
5607
+ fit = "cover",
5608
+ alignH = "center",
5609
+ alignV = "middle",
5610
+ containScale = 1
5591
5611
  }) {
5592
5612
  const img = image || (url ? await fabric.FabricImage.fromURL(getProxiedImageUrl(url), { crossOrigin: "anonymous" }) : null);
5593
5613
  if (!img) {
@@ -5706,8 +5726,13 @@ async function createMaskedImageElement({
5706
5726
  rx,
5707
5727
  frameW,
5708
5728
  frameH,
5709
- fit: "cover",
5710
- // clip image to frame; use 'contain' only when simple-scale mode is set
5729
+ // Honor the element's authored imageFit. When 'contain', the image is
5730
+ // scaled to fit fully inside the frame (no clipping) and alignH/alignV
5731
+ // control where the letterboxed image sits.
5732
+ fit,
5733
+ alignH,
5734
+ alignV,
5735
+ containScale: Math.max(1, Math.min(3, containScale || 1)),
5711
5736
  _img: img,
5712
5737
  _border: border
5713
5738
  };
@@ -19616,7 +19641,14 @@ const PageCanvas = forwardRef(
19616
19641
  visible: !isHidden,
19617
19642
  panX,
19618
19643
  panY,
19619
- zoom: zoom2
19644
+ zoom: zoom2,
19645
+ // Honor authored Object Fit + alignment so contain logos render
19646
+ // fully inside the frame, with letterbox aligned to the chosen
19647
+ // edge (instead of being silently cover-cropped).
19648
+ fit: imageFitFinal === "contain" ? "contain" : "cover",
19649
+ alignH: element.imageAlignH ?? "center",
19650
+ alignV: element.imageAlignV ?? "middle",
19651
+ containScale: Math.max(1, Math.min(3, Number(element.containScale ?? 1)))
19620
19652
  });
19621
19653
  cropGroup.__maintainResolution = element.maintainResolution !== false;
19622
19654
  cropGroup.set({
@@ -26223,9 +26255,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
26223
26255
  }
26224
26256
  return svgString;
26225
26257
  }
26226
- const resolvedPackageVersion = "0.5.461";
26258
+ const resolvedPackageVersion = "0.5.463";
26227
26259
  const PACKAGE_VERSION = resolvedPackageVersion;
26228
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.461";
26260
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.463";
26229
26261
  const roundParityValue = (value) => {
26230
26262
  if (typeof value !== "number") return value;
26231
26263
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -27039,7 +27071,7 @@ class PixldocsRenderer {
27039
27071
  await this.waitForCanvasScene(container, cloned, i);
27040
27072
  }
27041
27073
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
27042
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-Bn1wgD8Q.js");
27074
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-BlCi6g1y.js");
27043
27075
  const prepared = preparePagesForExport(
27044
27076
  cloned.pages,
27045
27077
  canvasWidth,
@@ -29359,7 +29391,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
29359
29391
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
29360
29392
  sanitizeSvgTreeForPdf(svgToDraw);
29361
29393
  try {
29362
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-Bn1wgD8Q.js");
29394
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-BlCi6g1y.js");
29363
29395
  try {
29364
29396
  await logTextMeasurementDiagnostic(svgToDraw);
29365
29397
  } catch {
@@ -29676,4 +29708,4 @@ export {
29676
29708
  buildTeaserBlurFlatKeys as y,
29677
29709
  collectFontDescriptorsFromConfig as z
29678
29710
  };
29679
- //# sourceMappingURL=index-COG7WTYO.js.map
29711
+ //# sourceMappingURL=index-CJ3vY_6d.js.map