From f930b7a73128adb127945540b0fb8f472a71af0c Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Wed, 26 Feb 2025 21:25:13 +0100 Subject: [PATCH] Fix #135097: Wrap Text Lines Without Control Chars in Glyph Cache Our text wrapping code is written in a way that requires the Line Feed character to be in our glyph cache. This is problematic as none of the control characters will ever be there if not using fallback. With fallback these glyphs could be a zero-width character from a symbol font, or something with width if using a last resort font. So we'd have to ignore the advance in the latter case. This came to a head recently because we are turning off fallback in some circumstances. 12b1f8bd7a removed the rendering of control characters so they are never in the cache. That change requires this one, which does wrapping based on the string's codepoint, not that of its glyph. Pull Request: https://projects.blender.org/blender/blender/pulls/135196 --- source/blender/blenfont/intern/blf_font.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/source/blender/blenfont/intern/blf_font.cc b/source/blender/blenfont/intern/blf_font.cc index 50339eed8b3..7e4d0f9bcac 100644 --- a/source/blender/blenfont/intern/blf_font.cc +++ b/source/blender/blenfont/intern/blf_font.cc @@ -1286,9 +1286,8 @@ static void blf_font_wrap_apply(FontBLF *font, g = blf_glyph_from_utf8_and_step(font, gc, g_prev, str, str_len, &i, &pen_x); - if (UNLIKELY(g == nullptr)) { - continue; - } + const ft_pix advance_x = g ? g->advance_x : 0; + const uint codepoint = g ? g->c : BLI_str_utf8_as_unicode_safe(&str[i_curr]); /** * Implementation Detail (utf8). @@ -1298,22 +1297,22 @@ static void blf_font_wrap_apply(FontBLF *font, * * This is _only_ done when we know for sure the character is ascii (newline or a space). */ - pen_x_next = pen_x + g->advance_x; + pen_x_next = pen_x + advance_x; if (UNLIKELY((pen_x_next >= wrap.wrap_width) && (wrap.start != wrap.last[0]))) { do_draw = true; } else if (UNLIKELY(((i < str_len) && str[i]) == 0)) { /* Need check here for trailing newline, else we draw it. */ - wrap.last[0] = i + ((g->c != '\n') ? 1 : 0); + wrap.last[0] = i + ((codepoint != '\n') ? 1 : 0); wrap.last[1] = i; do_draw = true; } - else if (UNLIKELY(g->c == '\n')) { + else if (UNLIKELY(codepoint == '\n')) { wrap.last[0] = i_curr + 1; wrap.last[1] = i; do_draw = true; } - else if (UNLIKELY(g->c != ' ' && (g_prev ? g_prev->c == ' ' : false))) { + else if (UNLIKELY(codepoint != ' ' && (g_prev ? g_prev->c == ' ' : false))) { wrap.last[0] = i_curr; wrap.last[1] = i_curr; }