Skip to content

fix(text): avoid spurious measuring in _measureChar when only kerning-irrelevant entries are missing#11028

Open
jiayihu wants to merge 2 commits into
fabricjs:masterfrom
jiayihu:fix/measure-char-cache-miss
Open

fix(text): avoid spurious measuring in _measureChar when only kerning-irrelevant entries are missing#11028
jiayihu wants to merge 2 commits into
fabricjs:masterfrom
jiayihu:fix/measure-char-cache-miss

Conversation

@jiayihu

@jiayihu jiayihu commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Disclosure: I found out the issue during work but I fully asked GLM 5.2 to port the fix back to fabric, add tests and open the PR using the repo skill.

Summary

_measureChar was treating missing previousWidth or coupleWidth as a cache miss even when kerning was irrelevant (no usable previous char, or previous char with a different style). On a pure single-character cache hit this forced an unnecessary fetch of the measuring context and extra _setTextStyles/measureText bookkeeping. The fix only builds and reads the kerning pair when a same-style previous char exists, and only enters the measuring path when the single-character width is missing or a same-style kerning pair actually needs measuring.

Changes

  • src/shapes/Text/Text.ts: rewrote the _measureChar cache/measure logic so the couple key and previousWidth are only built/read when previousChar exists, and the measuring path is gated on width === undefined || (stylesAreEqual && coupleWidth === undefined).
  • src/shapes/Text/Text.spec.ts: added two tests covering the regression — one asserting _setTextStyles is not called when only kerning-irrelevant entries are missing, and one asserting measureText is invoked for previousWidth and coupleWidth (and not for an already-cached single char) when both are undefined.

@codesandbox

codesandbox Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Build Stats

file / KB (diff) bundled minified
fabric 774.150 (+0.022) 293.403 (+0.003)

Comment thread src/shapes/Text/Text.ts Outdated
if (previousChar && fontCache.has(previousChar)) {
previousWidth = fontCache.get(previousChar);
if (hasPrevChar && fontCache.has(previousChar!)) {
previousWidth = fontCache.get(previousChar!);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is incredible that TS still can't catch this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad (or GLM's so ultimately mine eheh). It was using Boolean, which defeats the TS control flow analysis. Using raw !! preserves it. Still needed for Maps though as there is no control flow analysis for Map.has

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.

2 participants