From 8e57960703babd1c4310146e2baa97341f064a66 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 3 Oct 2024 18:32:45 -0700 Subject: [PATCH] Fixed display of newlines in wrapped text We keep the newlines in the buffer and replace them with ZERO WIDTH SPACE for rendering purposes. --- src/SDL_ttf.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/SDL_ttf.c b/src/SDL_ttf.c index a0d7f4ac..b2817711 100644 --- a/src/SDL_ttf.c +++ b/src/SDL_ttf.c @@ -3001,7 +3001,13 @@ static bool TTF_Size_Internal(TTF_Font *font, const char *text, size_t length, i hb_buffer_guess_segment_properties(hb_buffer); // Layout the text - hb_buffer_add_utf8(hb_buffer, text, (int)length, 0, -1); + if (length > 0 && text[length - 1] == '\n') { + // Replace newline with ZERO WIDTH SPACE + hb_buffer_add_utf8(hb_buffer, text, (int)(length - 1), 0, -1); + hb_buffer_add_utf8(hb_buffer, "\xE2\x80\x8B", 3, 0, -1); + } else { + hb_buffer_add_utf8(hb_buffer, text, (int)length, 0, -1); + } hb_feature_t userfeatures[1]; userfeatures[0].tag = HB_TAG('k','e','r','n'); @@ -3017,8 +3023,7 @@ static bool TTF_Size_Internal(TTF_Font *font, const char *text, size_t length, i // Load and render each character int offset = 0; - for (g = 0; g < glyph_count; g++) - { + for (g = 0; g < glyph_count; g++) { FT_UInt idx = hb_glyph_info[g].codepoint; int x_advance = hb_glyph_position[g].x_advance; int y_advance = hb_glyph_position[g].y_advance; @@ -3039,6 +3044,9 @@ static bool TTF_Size_Internal(TTF_Font *font, const char *text, size_t length, i if (c == UNICODE_BOM_NATIVE || c == UNICODE_BOM_SWAPPED) { continue; } + if (c == '\n') { + c = 0x200B; // ZERO WIDTH SPACE + } #endif if (!Find_GlyphByIndex(font, idx, 0, 0, 0, 0, 0, &glyph, NULL)) { goto failure; @@ -3462,7 +3470,9 @@ static bool GetWrappedLines(TTF_Font *font, const char *text, size_t length, int // Trim whitespace from the wrapped lines for (i = 0; i < (numLines - 1); ++i) { TTF_Line *line = &strLines[i]; - while (line->length > 0 && CharacterIsDelimiter(line->text[line->length - 1])) { + while (line->length > 0 && + CharacterIsDelimiter(line->text[line->length - 1]) && + line->text[line->length - 1] != '\n') { --line->length; } }