Fix: UI: Text shortening function off by one character

Noticed while working on #134814 that `BLF_width_to_rstrlen()` would
give one character too much to put into the available space, resulting
in a visual overflow or clipped text when BLF clipping is enabled.

I think the issue was hidden by the code from 9c09998530, which would
remove further characters until the string actually fits. I'm proposing
to disable that code for now, hoping that this properly fixes the issue.

`BLF_width_to_rstrlen()`/`blf_font_width_to_rstrlen()` are supposed to
find the largest part from the end of a string that fits into a given
width. It would iterate the string from the back until a character
doesn't fit into the width anymore. However, it would return the
index of that character, the one that doesn't fit anymore, instead of
the last character known to fit.

Pull Request: https://projects.blender.org/blender/blender/pulls/135239
This commit is contained in:
Julian Eisel
2025-02-28 11:58:52 +01:00
committed by Julian Eisel
parent d853d994ae
commit 80d6ad3e9d
2 changed files with 7 additions and 2 deletions

View File

@@ -849,6 +849,7 @@ size_t blf_font_width_to_rstrlen(
GlyphBLF *g, *g_prev;
ft_pix pen_x, width_new;
size_t i, i_prev, i_tmp;
std::optional<size_t> i_next = {};
const char *s, *s_prev;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
@@ -862,7 +863,7 @@ size_t blf_font_width_to_rstrlen(
i_tmp = i;
g = blf_glyph_from_utf8_and_step(font, gc, nullptr, str, str_len, &i_tmp, nullptr);
for (width_new = pen_x = 0; (s != nullptr && i > 0);
i = i_prev, s = s_prev, g = g_prev, g_prev = nullptr, width_new = pen_x)
i_next = i, i = i_prev, s = s_prev, g = g_prev, g_prev = nullptr, width_new = pen_x)
{
s_prev = BLI_str_find_prev_char_utf8(s, str);
i_prev = size_t(s_prev - str);
@@ -881,7 +882,7 @@ size_t blf_font_width_to_rstrlen(
}
blf_glyph_cache_release(font);
return i;
return i_next ? *i_next : i;
}
/** \} */

View File

@@ -1566,6 +1566,9 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle,
/* -1 to remove trailing '\0'! */
final_lpart_len = size_t(l_end + sep_len + r_len - 1);
/* Seems like this was only needed because of an error in #BLF_width_to_rstrlen(), not because of
* integer imprecision. See PR #135239. */
#if 0
while (BLF_width(fstyle->uifont_id, str, max_len) > okwidth) {
/* This will happen because a lot of string width processing is done in integer pixels,
* which can introduce a rather high error in the end (about 2 pixels or so).
@@ -1575,6 +1578,7 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle,
char *c = str + l_end + sep_len;
memmove(c, c + 1, r_len);
}
#endif
}
}