Skip to content

Fix scrolling text smearing at text sizes above 1 - #69

Merged
leonardocavagnis merged 1 commit into
masterfrom
fix-scroll-text-size
Sep 7, 2026
Merged

leonardocavagnis merged 1 commit into
masterfrom
fix-scroll-text-size

Conversation

@sebromero

Copy link
Copy Markdown
Contributor

The problem

endText() scrolls by one pixel per frame and, rather than repainting the screen, erases only the single line the text just vacated. That erase has to land exactly on the trailing edge, because nothing else will cover it.

It doesn't. The travel distance is computed from textFontWidth() / textFontHeight(), which scale with textSize(), while the erase is positioned from _font->width / _font->height, which don't:

int scrollLength = _textBuffer.length() * textFontWidth() + _textX + 1;  // scaled
...
const int clearX = text_x + _textBuffer.length() * _font->width;         // unscaled
line(clearX, _textY, clearX, _textY + _font->height - 1);                // unscaled

The two agree only at textSize(1). Above that the erase falls short of the trailing edge and leaves a line of pixels behind on every frame, so glyphs smear in the scroll direction.

The fix

Use the scaled accessors for the erase as well. Six lines across the four scroll branches.

The two bitmap() calls in SCROLL_RIGHT and SCROLL_DOWN are deliberately left alone: bitmap() takes unscaled source dimensions plus separate scale factors, so passing _font->width / _font->height there is already correct.

Why horizontal scrolling looked fine

SCROLL_RIGHT was the least affected because the space-glyph bitmap() drawn just after the erase already covers the full scaled height. SCROLL_LEFT leaves a 1px-wide column behind, which is invisible whenever the trailing column of the last glyph happens to be blank. The vertical directions have no such cover, which is why they were the visible ones.

Verification

Modelling the painted and erased regions frame by frame, counting pixels from frame N that frame N+1 neither repaints nor erases (Font_5x7):

textSize LEFT RIGHT UP DOWN LEFT RIGHT UP DOWN
1 x 1 0 0 0 0 → 0 0 0 0
2 x 2 14 0 20 20 → 0 0 0 0
3 x 1 7 0 20 40 → 0 0 0 0
1 x 3 14 0 10 0 → 0 0 0 0

Zero stale pixels in every direction at every size, including the non-uniform ones from textSize(sx, sy).

Originally found on a 128x64 I2C OLED driven through a Print-based ArduinoGraphics backend: SCROLL_UP at textSize(2) tore the glyphs and left the previous word's pixels on screen. Confirmed fixed there.

🤖 Generated with Claude Code

endText() moves the text one pixel per frame and, rather than repainting
the screen, erases only the single line the text just vacated. That erase
has to land exactly on the trailing edge, because nothing else will cover
it.

It did not. The travel distance came from textFontWidth() and
textFontHeight(), which scale with textSize(), but the erase was
positioned from _font->width and _font->height, which do not. The two
agree only at textSize(1). Above that the erase fell short of the
trailing edge and left a line of pixels behind on every frame, so glyphs
smeared in the scroll direction.

Use the scaled accessors for the erase as well.

SCROLL_RIGHT was the least affected because the space-glyph bitmap drawn
just after the erase already covers the full scaled height, which is why
horizontal scrolling could look correct while vertical scrolling did not.

Modelling the painted and erased regions frame by frame, stale pixels per
frame before and after, for Font_5x7:

  size   LEFT  RIGHT  UP  DOWN        LEFT  RIGHT  UP  DOWN
  1x1       0      0   0     0           0      0   0     0
  2x2      14      0  20    20    ->     0      0   0     0
  3x1       7      0  20    40           0      0   0     0
  1x3      14      0  10     0           0      0   0     0

The two bitmap() calls are left alone: they take unscaled source
dimensions plus separate scale factors, so passing _font->width and
_font->height there is correct.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@leonardocavagnis
leonardocavagnis self-requested a review September 7, 2026 14:58

@leonardocavagnis leonardocavagnis left a comment

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.

LGTM :)

Tested on 128x64 I2C OLED (Chip controller: ST7315)

@leonardocavagnis
leonardocavagnis merged commit f997bbc into master Sep 7, 2026
11 checks passed
@per1234 per1234 added type: imperfection Perceived defect in any part of project topic: code Related to content of the project itself labels Sep 10, 2026
@per1234
per1234 deleted the fix-scroll-text-size branch September 27, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants