From b9458ff2bc7175ea7778328268a66ff95fa8f4a0 Mon Sep 17 00:00:00 2001 From: Subrata Banik Date: Thu, 12 Feb 2026 18:37:37 +0530 Subject: [PATCH] lib: Implement resolution-based text scaling Add support for dynamic text scaling based on the display resolution to ensure bootsplash text remains legible on high-density panels. Key changes: - Implement get_resolution_scale() to determine a scaling factor (1x, 2x, or 3x) based on the panel's major dimension (HD, QHD, or 4K). - Update draw_char() to render glyphs as scaled blocks, repeating each font pixel across a square of the calculated scale factor. - Apply the scaling factor to all text layout calculations, including kerning, character advance, and total string dimensions. - Ensure anti-aliasing (alpha blending) is correctly applied to each individual pixel within the scaled blocks. Change-Id: I8b22019ddaa46f1a24f38d565d946bb28a213791 Signed-off-by: Subrata Banik Reviewed-on: https://review.coreboot.org/c/coreboot/+/91182 Tested-by: build bot (Jenkins) Reviewed-by: Kapil Porwal --- src/lib/render_text.c | 73 ++++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/src/lib/render_text.c b/src/lib/render_text.c index d20281b6e1..a87489a616 100644 --- a/src/lib/render_text.c +++ b/src/lib/render_text.c @@ -3,10 +3,30 @@ #include #include #include +#include #include "fonts/fonts.h" #include "render_bmp.h" +/* Major dimension for panel */ +#define PANEL_4K 3840 +#define PANEL_2K_QHD 2560 + +/* Determine scaling factor based on display resolution */ +static uint32_t get_resolution_scale(struct logo_config *config) +{ + uint32_t width = config->horizontal_resolution; + uint32_t height = config->vertical_resolution; + uint32_t major_dim = (width > height) ? width : height; + + if (major_dim >= PANEL_4K) + return 3; + else if (major_dim >= PANEL_2K_QHD) + return 2; + else /* HD / FHD Panels */ + return 1; +} + /* Maps an unsigned character to the 8-bit alpha map (smoothing data) */ static const uint8_t *get_glyph_data(unsigned char c) { @@ -61,7 +81,7 @@ static inline void get_rotated_text_coords(struct logo_config *config, * @color: Primary text color. */ static void draw_char(struct logo_config *config, unsigned char c, uint32_t x, uint32_t y, - struct blt_pixel color) + struct blt_pixel color, uint32_t scale) { size_t pixel_size = sizeof(struct blt_pixel); uint8_t *fb = (uint8_t *)config->framebuffer_base; @@ -77,23 +97,31 @@ static void draw_char(struct logo_config *config, unsigned char c, uint32_t x, u if (alpha == 0) continue; - uint32_t fb_x, fb_y; - get_rotated_text_coords(config, x, y, row, col, &fb_x, &fb_y); + /* Fill a scale x scale block for each font pixel */ + for (uint32_t sy = 0; sy < scale; sy++) { + for (uint32_t sx = 0; sx < scale; sx++) { + uint32_t fb_x, fb_y; + get_rotated_text_coords(config, x, y, + (row * scale) + sy, + (col * scale) + sx, + &fb_x, &fb_y); - if (fb_x < config->horizontal_resolution && - fb_y < config->vertical_resolution) { + if (fb_x < config->horizontal_resolution && + fb_y < config->vertical_resolution) { + struct blt_pixel *bg = (struct blt_pixel *) + (fb + (fb_y * config->bytes_per_scanline) + (fb_x * pixel_size)); - struct blt_pixel *bg = (struct blt_pixel *) - (fb + (fb_y * config->bytes_per_scanline) + (fb_x * pixel_size)); - - if (alpha == 255) { - /* Fully opaque: just overwrite */ - *bg = color; - } else { - /* Perform Alpha Blending */ - bg->Red = (uint8_t)((color.Red * alpha + bg->Red * (255 - alpha)) / 255); - bg->Green = (uint8_t)((color.Green * alpha + bg->Green * (255 - alpha)) / 255); - bg->Blue = (uint8_t)((color.Blue * alpha + bg->Blue * (255 - alpha)) / 255); + if (alpha == 255) { + *bg = color; + } else { + bg->Red = (uint8_t)((color.Red * alpha + bg->Red * + (255 - alpha)) / 255); + bg->Green = (uint8_t)((color.Green * alpha + bg->Green * + (255 - alpha)) / 255); + bg->Blue = (uint8_t)((color.Blue * alpha + bg->Blue * + (255 - alpha)) / 255); + } + } } } } @@ -157,11 +185,12 @@ void render_text_to_framebuffer(struct logo_config *config, const char *str, if (len == 0) return; - const uint32_t kerning = 1; + uint32_t scale = get_resolution_scale(config); + const uint32_t kerning = 1 * scale; uint32_t total_width = 0; for (size_t i = 0; i < len; i++) - total_width += get_glyph_width((unsigned char)str[i]) + kerning; + total_width += (get_glyph_width((unsigned char)str[i]) * scale) + kerning; uint32_t text_w, text_h; enum fw_splash_horizontal_alignment halign; @@ -173,11 +202,11 @@ void render_text_to_framebuffer(struct logo_config *config, const char *str, if (config->panel_orientation == LB_FB_ORIENTATION_LEFT_UP || config->panel_orientation == LB_FB_ORIENTATION_RIGHT_UP) { - text_w = CONFIG_FONT_HEIGHT; + text_w = CONFIG_FONT_HEIGHT * scale; text_h = total_width; } else { text_w = total_width; - text_h = CONFIG_FONT_HEIGHT; + text_h = CONFIG_FONT_HEIGHT * scale; } struct logo_coordinates coords = calculate_logo_coordinates(config->horizontal_resolution, @@ -207,9 +236,9 @@ void render_text_to_framebuffer(struct logo_config *config, const char *str, /* Loop through characters and draw them */ for (size_t i = 0; i < len; i++) { unsigned char c = (unsigned char)str[i]; - draw_char(config, c, cur_x, cur_y, text_color); + draw_char(config, c, cur_x, cur_y, text_color, scale); - uint32_t advance = get_glyph_width(c) + kerning; + uint32_t advance = (get_glyph_width(c) * scale) + kerning; if (config->panel_orientation == LB_FB_ORIENTATION_RIGHT_UP) cur_y += advance; else if (config->panel_orientation == LB_FB_ORIENTATION_LEFT_UP)