Skip to content

fix(text): preserve kerning across animation transitions - #396

Open
TupiC wants to merge 1 commit into
walterlow:mainfrom
TupiC:fix/text-animation-kerning
Open

TupiC wants to merge 1 commit into
walterlow:mainfrom
TupiC:fix/text-animation-kerning

Conversation

@TupiC

@TupiC TupiC commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Needed to prevent letters from shifting closer together when an animation ends.

@vercel

vercel Bot commented Nov 3, 2026

Copy link
Copy Markdown

@TupiC is attempting to deploy a commit to the walterlow's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Tip

🎯 Customize your risk assessments

Guide how CodeRabbit assesses merge risk and security architecture risk. Highlight sensitive changes and explain your security boundaries using Merge Risk Instructions and Security Risk Instructions in your review settings. Security architecture risk assessments require the Advanced plan or above.

✅ Automatic approvals, with your rules

Let CodeRabbit approve pull requests once required threads are resolved, pre-merge checks pass, and your risk limits are met. Enable Automatic approvals in review settings, with overrides for teams or file paths.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@greptile-apps

greptile-apps Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The change affects animated text rendering in both Canvas and GPU paths.

Fix the inline-span handoff before merging; styled letters can still jump when motion ends.

Findings

  1. P1 Styled letters jump after animation ▶
  2. P2 Animated lines repeat text measurements ▶
Fix with agent prompt
### Issue 1
src/runtime/renderer/canvas-item-renderer/text.ts:318-323
With `spanLayout: 'inline'` and differently colored `A` and `V` spans, the new formula places `V` at the kerned width of `AV` minus its own width. Settled text draws each run separately and places `V` at the width of `A`, without that pair’s kerning. These two single-character runs matched before this change, but now `V` shifts when motion ends.

Use the same run boundaries and offsets in both paths, and add a split-span handoff test.

### Issue 2
src/runtime/renderer/canvas-item-renderer/text.ts:315-321
The new loop measures every growing prefix again on each animated frame. A line with `N` characters now sends roughly `N² / 2` characters through text measurement instead of advancing through the line once. The GPU loop repeats the same work, even though the text and font usually stay unchanged throughout the animation.

Cache these positions by text and style to avoid repeating this work during playback and export of longer lines.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

Preserves kerning by measuring whole strings for GPU layout and growing prefixes for letter positions.

  • Animated letters keep their spacing when they meet settled text.

Reviews (1) · Last reviewed commit: "fix(text): preserve kerning across anima..." · Reviewed by Greptile

Comment on lines +318 to +323
const currentX =
originX +
line.startX +
ctx.measureText(prefix).width -
advance +
charIndex * line.letterSpacing

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Styled letters jump after animation

With spanLayout: 'inline' and differently colored A and V spans, the new formula places V at the kerned width of AV minus its own width. Settled text draws each run separately and places V at the width of A, without that pair’s kerning. These two single-character runs matched before this change, but now V shifts when motion ends.

Use the same run boundaries and offsets in both paths, and add a split-span handoff test.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/runtime/renderer/canvas-item-renderer/text.ts
Line: 318-323

Comment:
**Styled letters jump after animation**

With `spanLayout: 'inline'` and differently colored `A` and `V` spans, the new formula places `V` at the kerned width of `AV` minus its own width. Settled text draws each run separately and places `V` at the width of `A`, without that pair’s kerning. These two single-character runs matched before this change, but now `V` shifts when motion ends.

Use the same run boundaries and offsets in both paths, and add a split-span handoff test.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines 315 to +321
const advance = ctx.measureText(char).width
prefix += char
// Include the preceding pair's kerning, as the settled whole-line draw does.
const currentX =
originX +
line.startX +
ctx.measureText(prefix).width -

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Animated lines repeat text measurements

The new loop measures every growing prefix again on each animated frame. A line with N characters now sends roughly N² / 2 characters through text measurement instead of advancing through the line once. The GPU loop repeats the same work, even though the text and font usually stay unchanged throughout the animation.

Cache these positions by text and style to avoid repeating this work during playback and export of longer lines.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/runtime/renderer/canvas-item-renderer/text.ts
Line: 315-321

Comment:
**Animated lines repeat text measurements**

The new loop measures every growing prefix again on each animated frame. A line with `N` characters now sends roughly `N² / 2` characters through text measurement instead of advancing through the line once. The GPU loop repeats the same work, even though the text and font usually stay unchanged throughout the animation.

Cache these positions by text and style to avoid repeating this work during playback and export of longer lines.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

This branch has not been deployed

No deployments
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