gfx: fix printBuffer wrap, UB glyph access order, and text_size.y

Three bugs fixed in gfx_printBuffer:

1. Word-wrap was remeasuring line size from the start of the buffer
   instead of from the current position, causing incorrect alignment on
   wrapped lines.  Pass &buf[i] to get_line_size and pass reset_x (not
   start.x) to get_reset_x so the left margin is preserved across wraps.

2. The glyph array was indexed unconditionally before the '\n'/'\r'
   check.  For fonts whose first glyph is 0x20 (space), a newline
   character (0x0A) produces a negative index, which is undefined
   behaviour.  Move the control-character check before the glyph lookup.

3. text_size.y was computed as (saved_start_y - start.y) + line_h.
   Because start.y grows downward as lines are added, the subtraction
   underflows for any multi-line string.  Correct to
   (start.y - saved_start_y) + line_h.  Also change saved_start_y to
   int16_t to match point_t.y.

Co-authored-by: GitHub Copilot <copilot@github.com>
Signed-off-by: Ryan Turner <ryan@turnrye.com>
This commit is contained in:
Ryan Turner 2026-05-19 19:49:09 -05:00 committed by Silvano Seva
parent 578c48a39c
commit 20cde4e473

View file

@ -451,27 +451,18 @@ point_t gfx_printBuffer(point_t start, fontSize_t size, textAlign_t alignment,
uint16_t reset_x = get_reset_x(alignment, line_size, start.x);
start.x = reset_x;
// Save initial start.y value to calculate vertical size
uint16_t saved_start_y = start.y;
int16_t saved_start_y = start.y;
uint16_t line_h = 0;
/* For each char in the string */
for(unsigned i = 0; i < len; i++)
{
char c = buf[i];
GFXglyph glyph = f.glyph[c - f.first];
uint8_t *bitmap = f.bitmap;
uint16_t bo = glyph.bitmapOffset;
uint8_t w = glyph.width, h = glyph.height;
int8_t xo = glyph.xOffset,
yo = glyph.yOffset;
uint8_t xx, yy, bits = 0, bit = 0;
line_h = h;
// Handle newline and carriage return
// Handle newline and carriage return before accessing glyph table
if (c == '\n')
{
if(alignment!=TEXT_ALIGN_CENTER)
if(alignment != TEXT_ALIGN_CENTER)
{
start.x = reset_x;
}
@ -489,12 +480,23 @@ point_t gfx_printBuffer(point_t start, fontSize_t size, textAlign_t alignment,
continue;
}
GFXglyph glyph = f.glyph[c - f.first];
uint8_t *bitmap = f.bitmap;
uint16_t bo = glyph.bitmapOffset;
uint8_t w = glyph.width, h = glyph.height;
int8_t xo = glyph.xOffset,
yo = glyph.yOffset;
uint8_t xx, yy, bits = 0, bit = 0;
line_h = h;
// Handle wrap around
if (start.x + glyph.xAdvance > CONFIG_SCREEN_WIDTH)
{
// Compute size of the first row in pixels
line_size = get_line_size(f, buf, len);
start.x = reset_x = get_reset_x(alignment, line_size, start.x);
// Compute size of the remaining text for this new line
line_size = get_line_size(f, &buf[i], len - i);
// Pass reset_x (the original start x) not start.x (current pos)
start.x = reset_x = get_reset_x(alignment, line_size, reset_x);
start.y += f.yAdvance;
}
@ -532,7 +534,7 @@ point_t gfx_printBuffer(point_t start, fontSize_t size, textAlign_t alignment,
// Calculate text size
point_t text_size = {0, 0};
text_size.x = line_size;
text_size.y = (saved_start_y - start.y) + line_h;
text_size.y = (start.y - saved_start_y) + line_h;
return text_size;
}