From 8e57960703babd1c4310146e2baa97341f064a66 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
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;
}
}