Skip to content

feat(text): expose trimmedHeight on text nodes#30

Merged
chiefcll merged 1 commit into
mainfrom
feat/text-trimmed-height
May 22, 2026
Merged

feat(text): expose trimmedHeight on text nodes#30
chiefcll merged 1 commit into
mainfrom
feat/text-trimmed-height

Conversation

@chiefcll
Copy link
Copy Markdown
Contributor

Summary

Adds a read-only node.trimmedHeight getter and trimmedHeight to the text loaded event payload. Represents the visible glyph extent — first line's cap-top to last line's descender bottom — independent of lineHeightPx's half-leading and ascender slack.

The intended use case is flex layouts:

text.once('loaded', (n, payload) => {
  text.h = payload.trimmedHeight;
});

After this, a flex parent with alignItems: 'center' will optically center the caps rather than the full lineHeightPx × N line-box. No more "the text looks a few pixels low" inside flex rows.

API

  • CoreTextNode#trimmedHeight: number — read-only getter (inherited automatically by ITextNode).
  • NodeTextLoadedPayload.trimmedHeight: number — new field alongside dimensions.
  • TextRenderInfo.trimmedHeight: number — new field (also on the cached TextLayout).

Formula

For N lines (descender is negative in NormalizedFontMetrics, so subtracting it adds the depth):

trimmedHeight = capHeight − descender + (N − 1) × lineHeightPx
  • 1 line: capHeight − descender (cap-top to descender bottom).
  • Empty text: 0.
  • Interior lines retain the full lineHeightPx between baselines — only the first cap-top and last descender are trimmed.

Matches CSS text-box-trim: trim-both; text-box-edge: cap text.

Decisions

Asked the user and locked:

  • Edges: cap-top → descender (rejected: cap-top → baseline; ascender → descender; per-node configurable).
  • API shape: read-only getter + loaded event payload (rejected: auto-apply trimToContent prop, both).

Files

Test plan

  • pnpm build clean.
  • vitest run — 182/182 pass.
  • VRT recert not expected (no rendering behavior change), but worth running once before merge.

🤖 Generated with Claude Code

Add a read-only `node.trimmedHeight` getter and include `trimmedHeight`
in the text `loaded` event payload. Represents the visible glyph
extent — cap-top of the first line to descender bottom of the last
line — useful for clients who want flex `alignItems: 'center'` (or any
layout that aligns by node `h`) to optically center the glyphs rather
than the full `lineHeightPx × N` line-box.

Typical usage:

    text.once('loaded', (n, p) => { text.h = p.trimmedHeight; });

Formula (descender is negative in font metrics):

    trimmedHeight = capHeight − descender + (lines − 1) × lineHeightPx

Computed once per layout in both the SDF and Canvas renderers, cached
in the SDF layout cache so cache hits don't recompute.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@chiefcll chiefcll merged commit 965999b into main May 22, 2026
1 check passed
@chiefcll chiefcll deleted the feat/text-trimmed-height branch May 22, 2026 21:57
chiefcll added a commit that referenced this pull request May 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant