@fieldnotes/core 0.40.2 → 0.40.4

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
@@ -670,7 +670,7 @@ function getBendFromPoint(from, to, dragPoint) {
670
670
  if (len === 0) return 0;
671
671
  const perpX = -dy / len;
672
672
  const perpY = dx / len;
673
- return (dragPoint.x - midX) * perpX + (dragPoint.y - midY) * perpY;
673
+ return 2 * ((dragPoint.x - midX) * perpX + (dragPoint.y - midY) * perpY);
674
674
  }
675
675
  function getArrowTangentAngle(from, to, bend, t) {
676
676
  const cp = getArrowControlPoint(from, to, bend);
@@ -4721,29 +4721,42 @@ function buildFontString(run) {
4721
4721
  const weight = run.bold ? "bold" : "normal";
4722
4722
  return `${style} ${weight} ${run.fontSize}px system-ui, sans-serif`;
4723
4723
  }
4724
- function renderStyledRuns(ctx, runs, startX, startY, maxWidth) {
4724
+ function renderStyledRuns(ctx, runs, startX, startY, maxWidth, opts = {}) {
4725
+ const align = opts.align ?? "left";
4726
+ const lhMul = opts.lineHeight ?? 1.3;
4725
4727
  ctx.textBaseline = "top";
4728
+ const lines = [];
4726
4729
  let cursorX = startX;
4727
- let cursorY = startY;
4730
+ let lineY = startY;
4728
4731
  let lineHeight = 0;
4732
+ let fragments = [];
4733
+ const finalizeLine = () => {
4734
+ const last = fragments[fragments.length - 1];
4735
+ const width = last ? last.x + last.width : 0;
4736
+ lines.push({ y: lineY, width, fragments });
4737
+ };
4738
+ const breakLine = (runLineHeight) => {
4739
+ finalizeLine();
4740
+ lineY += lineHeight;
4741
+ lineHeight = runLineHeight;
4742
+ fragments = [];
4743
+ cursorX = startX;
4744
+ };
4729
4745
  for (const run of runs) {
4730
- ctx.font = buildFontString(run);
4731
- const runLineHeight = run.fontSize * 1.3;
4746
+ const font = buildFontString(run);
4747
+ ctx.font = font;
4748
+ const runLineHeight = run.fontSize * lhMul;
4732
4749
  lineHeight = Math.max(lineHeight, runLineHeight);
4733
4750
  const words = run.text.split(/(\n| )/);
4734
4751
  for (const word of words) {
4735
4752
  if (word === "\n") {
4736
- cursorX = startX;
4737
- cursorY += lineHeight;
4738
- lineHeight = runLineHeight;
4753
+ breakLine(runLineHeight);
4739
4754
  continue;
4740
4755
  }
4741
4756
  if (word === " ") {
4742
4757
  const spaceWidth = ctx.measureText(" ").width;
4743
4758
  if (cursorX + spaceWidth > startX + maxWidth && cursorX > startX) {
4744
- cursorX = startX;
4745
- cursorY += lineHeight;
4746
- lineHeight = runLineHeight;
4759
+ breakLine(runLineHeight);
4747
4760
  } else {
4748
4761
  cursorX += spaceWidth;
4749
4762
  }
@@ -4752,20 +4765,33 @@ function renderStyledRuns(ctx, runs, startX, startY, maxWidth) {
4752
4765
  if (!word) continue;
4753
4766
  const metrics = ctx.measureText(word);
4754
4767
  if (cursorX + metrics.width > startX + maxWidth && cursorX > startX) {
4755
- cursorX = startX;
4756
- cursorY += lineHeight;
4757
- lineHeight = runLineHeight;
4768
+ breakLine(runLineHeight);
4758
4769
  }
4759
- ctx.fillText(word, cursorX, cursorY);
4760
- if (run.underline) {
4761
- const underY = cursorY + run.fontSize + 1;
4762
- ctx.fillRect(cursorX, underY, metrics.width, 1);
4770
+ fragments.push({
4771
+ text: word,
4772
+ font,
4773
+ x: cursorX - startX,
4774
+ width: metrics.width,
4775
+ fontSize: run.fontSize,
4776
+ underline: run.underline,
4777
+ strikethrough: run.strikethrough
4778
+ });
4779
+ cursorX += metrics.width;
4780
+ }
4781
+ }
4782
+ finalizeLine();
4783
+ for (const line of lines) {
4784
+ const offset = align === "center" ? (maxWidth - line.width) / 2 : align === "right" ? maxWidth - line.width : 0;
4785
+ for (const fragment of line.fragments) {
4786
+ ctx.font = fragment.font;
4787
+ const fx = startX + offset + fragment.x;
4788
+ ctx.fillText(fragment.text, fx, line.y);
4789
+ if (fragment.underline) {
4790
+ ctx.fillRect(fx, line.y + fragment.fontSize + 1, fragment.width, 1);
4763
4791
  }
4764
- if (run.strikethrough) {
4765
- const strikeY = cursorY + run.fontSize * 0.55;
4766
- ctx.fillRect(cursorX, strikeY, metrics.width, 1);
4792
+ if (fragment.strikethrough) {
4793
+ ctx.fillRect(fx, line.y + fragment.fontSize * 0.55, fragment.width, 1);
4767
4794
  }
4768
- cursorX += metrics.width;
4769
4795
  }
4770
4796
  }
4771
4797
  }
@@ -4776,7 +4802,10 @@ function renderTextOnCanvas(ctx, text) {
4776
4802
  ctx.save();
4777
4803
  ctx.fillStyle = text.color;
4778
4804
  const runs = parseStyledRuns(text.text ?? "", text.fontSize);
4779
- renderStyledRuns(ctx, runs, text.position.x + pad, text.position.y + pad, text.size.w - pad * 2);
4805
+ renderStyledRuns(ctx, runs, text.position.x + pad, text.position.y + pad, text.size.w - pad * 2, {
4806
+ align: text.textAlign,
4807
+ lineHeight: 1.4
4808
+ });
4780
4809
  ctx.restore();
4781
4810
  }
4782
4811
 
@@ -9747,7 +9776,7 @@ var LaserTool = class {
9747
9776
  };
9748
9777
 
9749
9778
  // src/index.ts
9750
- var VERSION = "0.40.2";
9779
+ var VERSION = "0.40.4";
9751
9780
  // Annotate the CommonJS export names for ESM import in node:
9752
9781
  0 && (module.exports = {
9753
9782
  ArrowTool,