fix(core): fix horizontal positioning with kerning
What changed, and why it matters
This commit fixes a text-rendering bug in the Trezor hardware wallet's user interface. Previously, when laying out text on screen, the code measured each character's width individually but forgot to add the small spacing adjustments (called kerning) between certain pairs of letters. This could cause text lines to be slightly misaligned or overflow their intended boundaries. The fix tracks the previous character and adds the correct kerning amount to each character's width during layout.
No security action required. Treat as a normal UI bug fix. If desired, verify that text-heavy screens (passphrase entry, recovery seed display, transaction details) render correctly and do not truncate or overlap after the change.
Security signals we found
UI text layout correction only
No cryptographic, authentication, or secrets-handling code touched
No memory-unsafe operations introduced
No input validation or parsing changes
No privilege boundary or trust model changes
Evidence from the diff
In core/embed/rust/src/ui/component/text/layout.rs, the Span::layout logic now maintains a prev_char variable across the character iteration loop. For each character, it calls text_font.get_kerning(prev_char, ch) and adds the returned kerning value to char_width. This corrects the cumulative span_width calculation and any downstream line-breaking decisions that depend on accurate text metrics. The change is purely a UI layout correctness fix with no cryptographic, memory-safety, or input-validation changes visible in the diff.
Changed components
core/embed/rust/src/ui/component/text/layout.rsTrezor firmware UI text rendering / layout engineInspect captured patch +4 / −1
diff --git a/core/embed/rust/src/ui/component/text/layout.rs b/core/embed/rust/src/ui/component/text/layout.rs
index abd7db80..150d665e 100644
--- a/core/embed/rust/src/ui/component/text/layout.rs
+++ b/core/embed/rust/src/ui/component/text/layout.rs
@@ -728,13 +728,15 @@ impl Span {
};
let mut span_width = 0;
+ let mut prev_char: Option<char> = None;
let mut found_any_whitespace = false;
let mut char_indices_iter = text.char_indices().peekable();
// Iterating manually because we need a reference to the iterator inside the
// loop.
while let Some((i, ch)) = char_indices_iter.next() {
- let char_width = text_font.char_width(ch);
+ let kern = prev_char.map_or(0, |p| text_font.get_kerning(p, ch));
+ let char_width = text_font.char_width(ch) + kern;
// All chunkification logic goes here.
if let Some(chunkify_config) = chunks {
@@ -796,6 +798,7 @@ impl Span {
}
span_width += char_width;
+ prev_char = Some(ch);
}
// The whole text is fitting on the current line.
Why this scored 17/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.