@pixldocs/canvas-renderer 0.5.76 → 0.5.77

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.
package/dist/index.cjs CHANGED
@@ -5213,6 +5213,17 @@ function buildRoundedTrianglePath(w, h, rTop, rBR, rBL) {
5213
5213
  ];
5214
5214
  return parts.join(" ");
5215
5215
  }
5216
+ const roundDiag = (value) => {
5217
+ if (typeof value !== "number") return value;
5218
+ return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
5219
+ };
5220
+ const stringifyDiag = (payload) => {
5221
+ try {
5222
+ return JSON.stringify(payload, (_key, value) => roundDiag(value));
5223
+ } catch {
5224
+ return String(payload);
5225
+ }
5226
+ };
5216
5227
  function buildRoundedRectPath(w, h, tl, tr, br, bl) {
5217
5228
  return buildRoundedRectPath$1(w, h, getRoundedRectRadii(w, h, { rxTL: tl, rxTR: tr, rxBR: br, rxBL: bl }));
5218
5229
  }
@@ -5323,11 +5334,11 @@ function createShape(element) {
5323
5334
  }
5324
5335
  }
5325
5336
  function createText(element) {
5326
- var _a;
5337
+ var _a, _b;
5327
5338
  const overflowPolicy = element.overflowPolicy || "grow-and-push";
5328
5339
  let text = element.text || "Text";
5329
5340
  let fontSize = element.fontSize || 16;
5330
- element.minFontSize || 8;
5341
+ const minFontSize = element.minFontSize || 8;
5331
5342
  const maxLines = element.maxLines || 3;
5332
5343
  const baseWidth = element.width && element.width > 0 ? element.width : 200;
5333
5344
  const baseHeight = element.height;
@@ -5339,6 +5350,7 @@ function createText(element) {
5339
5350
  const startFontSize = fontSize;
5340
5351
  let breakReason = "min-font-size-reached";
5341
5352
  let lastIter = null;
5353
+ const iterationSamples = [];
5342
5354
  while (fontSize > 1) {
5343
5355
  const testTextbox = new fabric__namespace.Textbox(text, {
5344
5356
  width: fixedWidth,
@@ -5356,7 +5368,7 @@ function createText(element) {
5356
5368
  const hasNoImplicitWrap = renderedLineCount <= explicitLineCount;
5357
5369
  const fitsHeight = !baseHeight || textHeight <= baseHeight;
5358
5370
  const widthMetrics = getTextboxWidthFitMetrics(testTextbox, fixedWidth);
5359
- const { fitsWidth } = widthMetrics;
5371
+ const { maxLineWidth, widthDidGrow, fitsWidth } = widthMetrics;
5360
5372
  if (debugAutoShrink) {
5361
5373
  lastIter = {
5362
5374
  fontSize,
@@ -5367,8 +5379,12 @@ function createText(element) {
5367
5379
  fixedWidth,
5368
5380
  hasNoImplicitWrap,
5369
5381
  fitsHeight,
5370
- fitsWidth
5382
+ fitsWidth,
5383
+ textLines: (testTextbox.textLines || []).map((line) => Array.isArray(line) ? line.join("") : String(line ?? ""))
5371
5384
  };
5385
+ if (iterationSamples.length < 6 || fontSize <= minFontSize + 2) {
5386
+ iterationSamples.push(lastIter);
5387
+ }
5372
5388
  }
5373
5389
  if (hasNoImplicitWrap && fitsHeight && fitsWidth) {
5374
5390
  breakReason = "fits";
@@ -5377,10 +5393,11 @@ function createText(element) {
5377
5393
  fontSize--;
5378
5394
  }
5379
5395
  if (debugAutoShrink) {
5380
- console.log("[auto-shrink][diag]", {
5396
+ console.log("[auto-shrink][diag] " + stringifyDiag({
5381
5397
  id: element.id,
5382
5398
  name: element.name,
5383
- text,
5399
+ text: text.slice(0, 180),
5400
+ textLength: text.length,
5384
5401
  fontFamily: element.fontFamily,
5385
5402
  fontWeight: element.fontWeight,
5386
5403
  elementWidth: element.width,
@@ -5392,10 +5409,11 @@ function createText(element) {
5392
5409
  startFontSize,
5393
5410
  finalFontSize: fontSize,
5394
5411
  breakReason,
5412
+ iterations: iterationSamples,
5395
5413
  lastIter,
5396
5414
  fontCheckRegular: typeof document !== "undefined" && document.fonts ? document.fonts.check(`16px "${element.fontFamily || "Open Sans"}"`) : null,
5397
5415
  fontCheckBold: typeof document !== "undefined" && document.fonts ? document.fonts.check(`bold 16px "${element.fontFamily || "Open Sans"}"`) : null
5398
- });
5416
+ }));
5399
5417
  }
5400
5418
  }
5401
5419
  if (overflowPolicy === "max-lines-ellipsis") {
@@ -5470,6 +5488,22 @@ function createText(element) {
5470
5488
  textbox.setCoords();
5471
5489
  }
5472
5490
  textbox.dirty = true;
5491
+ if (overflowPolicy === "auto-shrink" && typeof window !== "undefined" && window.__pixldocsDebugAutoShrink === true) {
5492
+ console.log("[auto-shrink][final-textbox] " + stringifyDiag({
5493
+ id: element.id,
5494
+ name: element.name,
5495
+ text: text.slice(0, 180),
5496
+ targetWidth,
5497
+ targetScaleX,
5498
+ targetScaleY,
5499
+ finalFontSize: fontSize,
5500
+ textboxWidth: textbox.width,
5501
+ textboxHeight: textbox.height,
5502
+ lineCount: ((_b = textbox.textLines) == null ? void 0 : _b.length) || 0,
5503
+ lines: (textbox.textLines || []).map((line) => Array.isArray(line) ? line.join("") : String(line ?? "")),
5504
+ widthMetrics: getTextboxWidthFitMetrics(textbox, targetWidth)
5505
+ }));
5506
+ }
5473
5507
  applyTextBackground(textbox, extractTextBgConfig(element));
5474
5508
  const shadow = buildTextShadow(element);
5475
5509
  if (shadow) textbox.set("shadow", shadow);
@@ -12553,7 +12587,18 @@ function PixldocsPreview(props) {
12553
12587
  !canvasSettled && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) })
12554
12588
  ] });
12555
12589
  }
12556
- const PACKAGE_VERSION = "0.5.76";
12590
+ const PACKAGE_VERSION = "0.5.77";
12591
+ const roundParityValue = (value) => {
12592
+ if (typeof value !== "number") return value;
12593
+ return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
12594
+ };
12595
+ function logJsonLine(tag, payload) {
12596
+ try {
12597
+ console.log(`${tag} ${JSON.stringify(payload, (_key, value) => roundParityValue(value))}`);
12598
+ } catch {
12599
+ console.log(tag, payload);
12600
+ }
12601
+ }
12557
12602
  let __underlineFixInstalled = false;
12558
12603
  function installUnderlineFix(fab) {
12559
12604
  var _a;
@@ -13429,6 +13474,42 @@ class PixldocsRenderer {
13429
13474
  }
13430
13475
  return null;
13431
13476
  }
13477
+ logFabricTextParitySnapshot(stage, fabricInstance) {
13478
+ var _a;
13479
+ if (typeof window === "undefined" || window.__pixldocsDebugAutoShrink !== true) return;
13480
+ const sample = [];
13481
+ const visit = (obj, groupPath = "") => {
13482
+ var _a2;
13483
+ if (!obj) return;
13484
+ if (obj instanceof fabric__namespace.Textbox) {
13485
+ const lineWidths = getCanvasMeasuredTextboxLineWidths(obj);
13486
+ sample.push({
13487
+ id: getObjectId(obj),
13488
+ groupPath,
13489
+ text: String(obj.text ?? "").slice(0, 180),
13490
+ left: obj.left,
13491
+ top: obj.top,
13492
+ width: obj.width,
13493
+ height: obj.height,
13494
+ scaleX: obj.scaleX,
13495
+ scaleY: obj.scaleY,
13496
+ fontSize: obj.fontSize,
13497
+ fontFamily: obj.fontFamily,
13498
+ fontWeight: obj.fontWeight,
13499
+ lineCount: ((_a2 = obj.textLines) == null ? void 0 : _a2.length) || 0,
13500
+ lines: (obj.textLines || []).map((line) => Array.isArray(line) ? line.join("") : String(line ?? "")),
13501
+ lineWidths,
13502
+ maxLineWidth: lineWidths.length ? Math.max(...lineWidths) : 0
13503
+ });
13504
+ }
13505
+ if (obj instanceof fabric__namespace.Group && typeof obj.getObjects === "function") {
13506
+ const nextPath = [groupPath, getObjectId(obj) || obj.type || "group"].filter(Boolean).join("/");
13507
+ obj.getObjects().forEach((child) => visit(child, nextPath));
13508
+ }
13509
+ };
13510
+ (_a = fabricInstance == null ? void 0 : fabricInstance.getObjects) == null ? void 0 : _a.call(fabricInstance).forEach((obj) => visit(obj));
13511
+ logJsonLine("[canvas-renderer][fabric-text-parity]", { stage, textboxes: sample.length, sample });
13512
+ }
13432
13513
  async waitForStableTextMetrics(container, config) {
13433
13514
  var _a, _b, _c;
13434
13515
  if (typeof document !== "undefined") {
@@ -13437,6 +13518,7 @@ class PixldocsRenderer {
13437
13518
  }
13438
13519
  const fabricInstance = this.getFabricCanvasFromContainer(container);
13439
13520
  if (!(fabricInstance == null ? void 0 : fabricInstance.getObjects)) return;
13521
+ this.logFabricTextParitySnapshot("before-stable-text-metrics", fabricInstance);
13440
13522
  const waitForPaint = () => new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(() => r())));
13441
13523
  const primeCharBounds = (obj) => {
13442
13524
  if (obj instanceof fabric__namespace.Textbox) {
@@ -13463,6 +13545,7 @@ class PixldocsRenderer {
13463
13545
  await waitForPaint();
13464
13546
  (_c = fabricInstance.renderAll) == null ? void 0 : _c.call(fabricInstance);
13465
13547
  await waitForPaint();
13548
+ this.logFabricTextParitySnapshot("after-stable-text-metrics", fabricInstance);
13466
13549
  }
13467
13550
  }
13468
13551
  const FONT_WEIGHT_LABELS = {
@@ -14284,6 +14367,16 @@ const pdfFonts = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProp
14284
14367
  resolveFontWeight,
14285
14368
  rewriteSvgFontsForJsPDF
14286
14369
  }, Symbol.toStringTag, { value: "Module" }));
14370
+ function logParityJson(tag, stage, payload) {
14371
+ try {
14372
+ console.log(`${tag} ${stage} ${JSON.stringify(payload, (_key, value) => {
14373
+ if (typeof value !== "number") return value;
14374
+ return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
14375
+ })}`);
14376
+ } catch {
14377
+ console.log(`${tag} ${stage}`, payload);
14378
+ }
14379
+ }
14287
14380
  function dumpSvgTextDiagnostics(svgStr, pageIndex, tag, stage, maxItems = 30) {
14288
14381
  try {
14289
14382
  if (typeof DOMParser === "undefined") return;
@@ -14306,7 +14399,7 @@ function dumpSvgTextDiagnostics(svgStr, pageIndex, tag, stage, maxItems = 30) {
14306
14399
  svgViewBox,
14307
14400
  textCount: texts.length
14308
14401
  };
14309
- console.log(`${tag} ${stage} page=${pageIndex} summary`, summary);
14402
+ logParityJson(tag, stage, { kind: "summary", ...summary });
14310
14403
  const sample = texts.slice(0, maxItems).map((t, idx) => {
14311
14404
  var _a, _b;
14312
14405
  const tspans = Array.from(t.querySelectorAll("tspan"));
@@ -14338,7 +14431,7 @@ function dumpSvgTextDiagnostics(svgStr, pageIndex, tag, stage, maxItems = 30) {
14338
14431
  tspanSample: tspanInfo
14339
14432
  };
14340
14433
  });
14341
- console.log(`${tag} ${stage} page=${pageIndex} text-sample (first ${sample.length}/${texts.length})`, sample);
14434
+ logParityJson(tag, stage, { kind: "text-sample", page: pageIndex, count: sample.length, total: texts.length, sample });
14342
14435
  } catch (err) {
14343
14436
  console.warn(`${tag} ${stage} page=${pageIndex} dump threw`, err);
14344
14437
  }