pa_font 0.3.5 → 0.3.7

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/paFont.js CHANGED
@@ -272,6 +272,8 @@ function mod(value, divisor) {
272
272
  }
273
273
  //#endregion
274
274
  //#region src/paFont/core.js
275
+ var DEFAULT_TEXT_SIZE = 72;
276
+ var DEFAULT_TEXT_SIZE_BASIS = "bbox";
275
277
  function layoutGlyphs(font, value, opts) {
276
278
  const glyphs = [];
277
279
  const renderOptions = toRenderOptions(opts);
@@ -321,12 +323,14 @@ function measureText(font, value, opts) {
321
323
  const renderOptions = toRenderOptions(opts);
322
324
  const bbox = resolveMeasuredBBox(font.getPath(value, opts.x, opts.y, opts.size, renderOptions).getBoundingBox(), opts.x, opts.y);
323
325
  if (opts.anchor == null) return {
326
+ size: opts.size,
324
327
  width: measureAdvanceWidth(font, value, opts),
325
328
  bbox
326
329
  };
327
330
  const tx = opts.x - (bbox.x + bbox.w * opts.anchor.x);
328
331
  const ty = opts.y - (bbox.y + bbox.h * opts.anchor.y);
329
332
  return {
333
+ size: opts.size,
330
334
  width: measureAdvanceWidth(font, value, opts),
331
335
  bbox: translateRect(bbox, tx, ty)
332
336
  };
@@ -544,8 +548,30 @@ function translateGlyphGeometry(geometry, tx, ty, glyphPosition) {
544
548
  bbox: translateRect(geometry.bbox, tx, ty)
545
549
  };
546
550
  }
551
+ function resolveTextOptions(font, value, options = {}, config = {}) {
552
+ const sourceOptions = options ?? {};
553
+ return normalizeTextOptions({
554
+ ...sourceOptions,
555
+ size: resolveTextSize(font, value, sourceOptions, config)
556
+ });
557
+ }
558
+ function resolveTextSize(font, value, options = {}, config = {}) {
559
+ const sourceOptions = options ?? {};
560
+ const sizeOption = sourceOptions.size;
561
+ if (!isTextSizeConstraint(sizeOption)) return normalizePositive(sizeOption, DEFAULT_TEXT_SIZE);
562
+ const fit = normalizeTextSizeConstraint(sizeOption, config.methodName);
563
+ const referenceSize = DEFAULT_TEXT_SIZE;
564
+ const measurement = measureText(font, String(value ?? ""), normalizeTextOptions({
565
+ ...sourceOptions,
566
+ anchor: null,
567
+ size: referenceSize
568
+ }));
569
+ const measuredWidth = fit.basis === "advance" ? measurement.width : measurement.bbox.w;
570
+ if (!Number.isFinite(measuredWidth) || measuredWidth <= 0) return clampTextSize(referenceSize, fit.min, fit.max);
571
+ return clampTextSize(referenceSize * fit.width / measuredWidth, fit.min, fit.max);
572
+ }
547
573
  function normalizeTextOptions(options = {}) {
548
- const size = normalizePositive(options.size, 72);
574
+ const size = normalizePositive(options.size, DEFAULT_TEXT_SIZE);
549
575
  const anchor = normalizeAnchor(options.anchor);
550
576
  return {
551
577
  x: normalizeNumber(options.x, 0),
@@ -613,6 +639,28 @@ function resolveMeasuredBBox(box, fallbackX, fallbackY) {
613
639
  function defaultEdgeEpsilon(size) {
614
640
  return Math.min(1, Math.max(.01, size * .0025));
615
641
  }
642
+ function isTextSizeConstraint(value) {
643
+ return value != null && typeof value === "object" && !Array.isArray(value);
644
+ }
645
+ function normalizeTextSizeConstraint(value, methodName) {
646
+ const width = normalizeNonNegativeNumber(value.width, NaN);
647
+ if (!Number.isFinite(width)) throw new TypeError(`${methodName ?? "Text"} option "size.width" must be a non-negative number.`);
648
+ const min = normalizeNonNegativeNumber(value.min, 0);
649
+ const maxValue = value.max === Infinity ? Infinity : normalizeNonNegativeNumber(value.max, Number.POSITIVE_INFINITY);
650
+ const max = Number.isFinite(maxValue) ? Math.max(min, maxValue) : Infinity;
651
+ return {
652
+ width,
653
+ basis: value.basis === "advance" ? "advance" : DEFAULT_TEXT_SIZE_BASIS,
654
+ min,
655
+ max
656
+ };
657
+ }
658
+ function normalizeNonNegativeNumber(value, fallback) {
659
+ return Number.isFinite(value) && value >= 0 ? Number(value) : fallback;
660
+ }
661
+ function clampTextSize(value, min, max) {
662
+ return Math.min(max, Math.max(min, normalizeNonNegativeNumber(value, min)));
663
+ }
616
664
  function toRenderOptions(opts) {
617
665
  const renderOptions = { kerning: opts.kerning };
618
666
  if (opts.letterSpacing != null) renderOptions.letterSpacing = opts.letterSpacing;
@@ -4593,14 +4641,17 @@ var paFont = class paFont {
4593
4641
  return new paFont(await load(target, void 0, loadOptions));
4594
4642
  }
4595
4643
  text(value, options = {}) {
4596
- const opts = normalizeTextOptions(options);
4597
- assertValidAnchorOption("font.text()", options, opts.anchor);
4598
- return createTextShape(this._layoutText(String(value ?? ""), opts), opts, this);
4644
+ const text = String(value ?? "");
4645
+ const sourceOptions = options ?? {};
4646
+ const opts = resolveTextOptions(this.font, text, sourceOptions, { methodName: "font.text()" });
4647
+ assertValidAnchorOption("font.text()", sourceOptions, opts.anchor);
4648
+ return createTextShape(this._layoutText(text, opts), opts, this);
4599
4649
  }
4600
4650
  glyph(value, options = {}) {
4601
- const opts = normalizeTextOptions(options);
4602
- assertValidAnchorOption("font.glyph()", options, opts.anchor);
4603
4651
  const text = Array.from(String(value ?? ""))[0] ?? "";
4652
+ const sourceOptions = options ?? {};
4653
+ const opts = resolveTextOptions(this.font, text, sourceOptions, { methodName: "font.glyph()" });
4654
+ assertValidAnchorOption("font.glyph()", sourceOptions, opts.anchor);
4604
4655
  const glyph = this.font.charToGlyph(text);
4605
4656
  const layout = {
4606
4657
  text,
@@ -4621,9 +4672,11 @@ var paFont = class paFont {
4621
4672
  return createTextShape(anchorSingleGlyphLayout(this.font, text, layout, opts), opts, this);
4622
4673
  }
4623
4674
  metrics(value, options = {}) {
4624
- const opts = normalizeTextOptions(options);
4625
- assertValidAnchorOption("font.metrics()", options, opts.anchor);
4626
- return measureText(this.font, String(value ?? ""), opts);
4675
+ const text = String(value ?? "");
4676
+ const sourceOptions = options ?? {};
4677
+ const opts = resolveTextOptions(this.font, text, sourceOptions, { methodName: "font.metrics()" });
4678
+ assertValidAnchorOption("font.metrics()", sourceOptions, opts.anchor);
4679
+ return measureText(this.font, text, opts);
4627
4680
  }
4628
4681
  paragraph(value, options = {}) {
4629
4682
  return createParagraph(this, String(value ?? ""), options);