From 58978d154a57cb5f4d68867c8e966af42fc7770c Mon Sep 17 00:00:00 2001 From: Devran Cosmo Uenal Date: Thu, 8 Oct 2026 18:03:13 +0200 Subject: [PATCH] font: rasterize glyphs larger than 128 pixels (#1214) Glyph images were rendered into a fixed 128x128 buffer and their width and height were clamped to 128. Since glyphs are rasterized at the requested scale (f96a14a0), large text such as title cards lost every row and column past 128 pixels, so letters were drawn cut into bands. The glyph buffers now grow to the glyph's bitmap box and width_byte is the glyph's width. The VGA fallback font keeps its 128-pixel limit; scalable glyphs are limited to 4096 pixels only to reject absurd scales. --- src/libs/libFont.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/libs/libFont.cpp b/src/libs/libFont.cpp index 8d834e3db..2d1365e02 100644 --- a/src/libs/libFont.cpp +++ b/src/libs/libFont.cpp @@ -78,6 +78,8 @@ constexpr int SCE_FONT_TEXT_PARSER_RESULT_TERMINATE = 0; constexpr int SCE_FONT_TEXT_PARSER_RESULT_ERROR = -1; constexpr int SCE_FONT_WRITING_FORM_HORIZONTAL = 0x10; constexpr int FONT_BITMAP_MAX_DIM = 128; +// TrueType glyphs are rasterized at the requested size; the limit only rejects absurd scales. +constexpr int FONT_GLYPH_MAX_DIM = 4096; constexpr int FONT_ERROR_INVALID_PARAMETER = static_cast(0x80460002u); constexpr int FONT_ERROR_INVALID_FONT_HANDLE = static_cast(0x80460005u); constexpr int FONT_ERROR_NO_SUPPORT_CODE = static_cast(0x80460041u); @@ -206,7 +208,7 @@ struct FontState { const uint8_t* ttf_data; uint32_t ttf_size; bool has_ttf; - std::array fallback_image; + std::vector fallback_image; FontTransImage trans_image; }; @@ -227,7 +229,7 @@ struct GlyphState { uint32_t code; int attribute; FontGlyphMetrics metrics; - std::array image; + std::vector image; FontTransImage trans_image; }; @@ -851,8 +853,8 @@ static bool get_stb_metrics(FontState* font, uint32_t code, FontGlyphMetrics* me return true; } -static bool init_stb_image(std::array* image, - FontTransImage* trans_image, uint32_t code, FontState* font) { +static bool init_stb_image(std::vector* image, FontTransImage* trans_image, uint32_t code, + FontState* font) { if (image == nullptr || trans_image == nullptr || !ensure_stb_font(font)) { return false; } @@ -868,12 +870,12 @@ static bool init_stb_image(std::arrayfont_info, static_cast(code), scale_x, scale_y, &x0, &y0, &x1, &y1); - image->fill(0); - - const auto width = static_cast(std::clamp(x1 - x0, 0, FONT_BITMAP_MAX_DIM)); - const auto height = static_cast(std::clamp(y1 - y0, 0, FONT_BITMAP_MAX_DIM)); + const auto width = static_cast(std::clamp(x1 - x0, 0, FONT_GLYPH_MAX_DIM)); + const auto height = static_cast(std::clamp(y1 - y0, 0, FONT_GLYPH_MAX_DIM)); + // Keep at least one byte so that blank glyphs still get a valid address. + image->assign(std::max(static_cast(width) * height, 1), 0); trans_image->address = image->data(); - trans_image->width_byte = FONT_BITMAP_MAX_DIM; + trans_image->width_byte = width; trans_image->image_width = width; trans_image->image_height = height; @@ -882,7 +884,7 @@ static bool init_stb_image(std::arrayfont_info, image->data(), static_cast(width), - static_cast(height), FONT_BITMAP_MAX_DIM, scale_x, scale_y, + static_cast(height), static_cast(width), scale_x, scale_y, static_cast(code)); return true; @@ -939,8 +941,8 @@ static uint32_t normalize_bitmap_font_code(uint32_t code) { return static_cast('?'); } -static void init_image(std::array* image, - FontTransImage* trans_image, uint32_t code, const FontState* font) { +static void init_image(std::vector* image, FontTransImage* trans_image, uint32_t code, + const FontState* font) { EXIT_NOT_IMPLEMENTED(image == nullptr); EXIT_NOT_IMPLEMENTED(trans_image == nullptr); @@ -948,11 +950,11 @@ static void init_image(std::arrayfill(0); code = normalize_bitmap_font_code(code); const auto width = static_cast(scaled_font_width(font)); const auto height = static_cast(scaled_font_height(font)); + image->assign(static_cast(width) * height, 0); #if LIBAVUTIL_VERSION_MAJOR < 61 const auto* vga_font = avpriv_vga16_font; #else @@ -965,13 +967,13 @@ static void init_image(std::array((x * 8u) / width, 7u); if ((row & (0x80u >> src_x)) != 0) { - (*image)[y * FONT_BITMAP_MAX_DIM + x] = 0xff; + (*image)[y * width + x] = 0xff; } } } trans_image->address = image->data(); - trans_image->width_byte = FONT_BITMAP_MAX_DIM; + trans_image->width_byte = width; trans_image->image_width = width; trans_image->image_height = height; }