From 5fdcb805d4dfd75f69b5349cc07cb82ee2f75dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Thu, 11 Sep 2025 13:05:31 +0300 Subject: [PATCH] [TextServer] Use a separate flag to disable min. string length for adding ellipsis. --- doc/classes/TextServer.xml | 3 +++ modules/text_server_adv/text_server_adv.cpp | 23 +++++++++++---------- modules/text_server_fb/text_server_fb.cpp | 23 +++++++++++---------- servers/text/text_server.cpp | 5 +++-- servers/text/text_server.h | 1 + 5 files changed, 31 insertions(+), 24 deletions(-) diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml index 6ec7bf77ffc..0fb8af1e146 100644 --- a/doc/classes/TextServer.xml +++ b/doc/classes/TextServer.xml @@ -2143,6 +2143,9 @@ Accounts for the text being justified before attempting to trim it (see [enum JustificationFlag]). + + Determines whether the ellipsis should be added regardless of the string length, otherwise it is added only if the string is 6 characters or longer. + Grapheme is supported by the font, and can be drawn. diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 8d49120a0aa..41cc7a71720 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -5882,6 +5882,7 @@ void TextServerAdvanced::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ bool add_ellipsis = p_trim_flags.has_flag(OVERRUN_ADD_ELLIPSIS); bool cut_per_word = p_trim_flags.has_flag(OVERRUN_TRIM_WORD_ONLY); bool enforce_ellipsis = p_trim_flags.has_flag(OVERRUN_ENFORCE_ELLIPSIS); + bool short_string_ellipsis = p_trim_flags.has_flag(OVERRUN_SHORT_STRING_ELLIPSIS); bool justification_aware = p_trim_flags.has_flag(OVERRUN_JUSTIFICATION_AWARE); Glyph *sd_glyphs = sd->glyphs.ptr(); @@ -5914,7 +5915,7 @@ void TextServerAdvanced::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ // Find usable fonts, if fonts from the last glyph do not have required chars. RID dot_gl_font_rid = sd_glyphs[sd_size - 1].font_rid; - if (add_ellipsis || enforce_ellipsis) { + if (add_ellipsis || enforce_ellipsis || short_string_ellipsis) { if (!_font_has_char(dot_gl_font_rid, sd->el_char)) { const Array &fonts = spans[span_size - 1].fonts; for (int i = 0; i < fonts.size(); i++) { @@ -5967,8 +5968,8 @@ void TextServerAdvanced::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ } } - int32_t dot_gl_idx = ((add_ellipsis || enforce_ellipsis) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_index(dot_gl_font_rid, last_gl_font_size, (found_el_char ? sd->el_char : '.'), 0) : -1; - Vector2 dot_adv = ((add_ellipsis || enforce_ellipsis) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_advance(dot_gl_font_rid, last_gl_font_size, dot_gl_idx) : Vector2(); + int32_t dot_gl_idx = ((add_ellipsis || enforce_ellipsis || short_string_ellipsis) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_index(dot_gl_font_rid, last_gl_font_size, (found_el_char ? sd->el_char : '.'), 0) : -1; + Vector2 dot_adv = ((add_ellipsis || enforce_ellipsis || short_string_ellipsis) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_advance(dot_gl_font_rid, last_gl_font_size, dot_gl_idx) : Vector2(); int32_t whitespace_gl_idx = whitespace_gl_font_rid.is_valid() ? _font_get_glyph_index(whitespace_gl_font_rid, last_gl_font_size, ' ', 0) : -1; Vector2 whitespace_adv = whitespace_gl_font_rid.is_valid() ? _font_get_glyph_advance(whitespace_gl_font_rid, last_gl_font_size, whitespace_gl_idx) : Vector2(); @@ -5984,7 +5985,7 @@ void TextServerAdvanced::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ bool is_rtl = sd->para_direction == DIRECTION_RTL; int trim_pos = (is_rtl) ? sd_size : 0; - int ellipsis_pos = (enforce_ellipsis) ? 0 : -1; + int ellipsis_pos = (enforce_ellipsis || short_string_ellipsis) ? 0 : -1; int last_valid_cut = -1; int last_valid_cut_witout_el = -1; @@ -5993,7 +5994,7 @@ void TextServerAdvanced::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ int glyphs_to = (is_rtl) ? sd_size - 1 : -1; int glyphs_delta = (is_rtl) ? +1 : -1; - if (enforce_ellipsis && (width + ellipsis_width <= p_width)) { + if ((enforce_ellipsis || short_string_ellipsis) && (width + ellipsis_width <= p_width)) { trim_pos = -1; ellipsis_pos = (is_rtl) ? 0 : sd_size; } else { @@ -6009,7 +6010,7 @@ void TextServerAdvanced::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ width = width_without_el; break; } - if (!enforce_ellipsis && width <= p_width && last_valid_cut_witout_el == -1) { + if (!(enforce_ellipsis || short_string_ellipsis) && width <= p_width && last_valid_cut_witout_el == -1) { if (cut_per_word && above_min_char_threshold) { if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) { last_valid_cut_witout_el = i; @@ -6020,7 +6021,7 @@ void TextServerAdvanced::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ width_without_el = width; } } - if (width + (((above_min_char_threshold && add_ellipsis) || enforce_ellipsis) ? ellipsis_width : 0) <= p_width) { + if (width + (((above_min_char_threshold && add_ellipsis) || enforce_ellipsis || short_string_ellipsis) ? ellipsis_width : 0) <= p_width) { if (cut_per_word && above_min_char_threshold) { if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) { last_valid_cut = i; @@ -6031,7 +6032,7 @@ void TextServerAdvanced::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ if (last_valid_cut != -1) { trim_pos = last_valid_cut; - if (add_ellipsis && (above_min_char_threshold || enforce_ellipsis) && width - ellipsis_width <= p_width) { + if (add_ellipsis && (above_min_char_threshold || enforce_ellipsis || short_string_ellipsis) && width - ellipsis_width <= p_width) { ellipsis_pos = trim_pos; } break; @@ -6046,12 +6047,12 @@ void TextServerAdvanced::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ sd->overrun_trim_data.trim_pos = trim_pos; sd->overrun_trim_data.ellipsis_pos = ellipsis_pos; - if (trim_pos == 0 && enforce_ellipsis && add_ellipsis) { + if (trim_pos == 0 && (enforce_ellipsis || short_string_ellipsis) && add_ellipsis) { sd->overrun_trim_data.ellipsis_pos = 0; } - if ((trim_pos >= 0 && sd->width > p_width) || enforce_ellipsis) { - if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis)) { + if ((trim_pos >= 0 && sd->width > p_width) || enforce_ellipsis || short_string_ellipsis) { + if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis || short_string_ellipsis)) { // Insert an additional space when cutting word bound for aesthetics. if (cut_per_word && (ellipsis_pos > 0)) { Glyph gl; diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index ac39da6f152..76d8530813b 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -4586,6 +4586,7 @@ void TextServerFallback::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ bool add_ellipsis = p_trim_flags.has_flag(OVERRUN_ADD_ELLIPSIS); bool cut_per_word = p_trim_flags.has_flag(OVERRUN_TRIM_WORD_ONLY); bool enforce_ellipsis = p_trim_flags.has_flag(OVERRUN_ENFORCE_ELLIPSIS); + bool short_string_ellipsis = p_trim_flags.has_flag(OVERRUN_SHORT_STRING_ELLIPSIS); bool justification_aware = p_trim_flags.has_flag(OVERRUN_JUSTIFICATION_AWARE); Glyph *sd_glyphs = sd->glyphs.ptrw(); @@ -4618,7 +4619,7 @@ void TextServerFallback::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ // Find usable fonts, if fonts from the last glyph do not have required chars. RID dot_gl_font_rid = sd_glyphs[sd_size - 1].font_rid; - if (add_ellipsis || enforce_ellipsis) { + if (add_ellipsis || enforce_ellipsis || short_string_ellipsis) { if (!_font_has_char(dot_gl_font_rid, sd->el_char)) { const Array &fonts = spans[span_size - 1].fonts; for (int i = 0; i < fonts.size(); i++) { @@ -4671,8 +4672,8 @@ void TextServerFallback::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ } } - int32_t dot_gl_idx = ((add_ellipsis || enforce_ellipsis) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_index(dot_gl_font_rid, last_gl_font_size, (found_el_char ? sd->el_char : '.'), 0) : -1; - Vector2 dot_adv = ((add_ellipsis || enforce_ellipsis) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_advance(dot_gl_font_rid, last_gl_font_size, dot_gl_idx) : Vector2(); + int32_t dot_gl_idx = ((add_ellipsis || enforce_ellipsis || short_string_ellipsis) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_index(dot_gl_font_rid, last_gl_font_size, (found_el_char ? sd->el_char : '.'), 0) : -1; + Vector2 dot_adv = ((add_ellipsis || enforce_ellipsis || short_string_ellipsis) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_advance(dot_gl_font_rid, last_gl_font_size, dot_gl_idx) : Vector2(); int32_t whitespace_gl_idx = whitespace_gl_font_rid.is_valid() ? _font_get_glyph_index(whitespace_gl_font_rid, last_gl_font_size, ' ', 0) : -1; Vector2 whitespace_adv = whitespace_gl_font_rid.is_valid() ? _font_get_glyph_advance(whitespace_gl_font_rid, last_gl_font_size, whitespace_gl_idx) : Vector2(); @@ -4686,12 +4687,12 @@ void TextServerFallback::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ double width_without_el = width; int trim_pos = 0; - int ellipsis_pos = (enforce_ellipsis) ? 0 : -1; + int ellipsis_pos = (enforce_ellipsis || short_string_ellipsis) ? 0 : -1; int last_valid_cut = -1; int last_valid_cut_witout_el = -1; - if (enforce_ellipsis && (width + ellipsis_width <= p_width)) { + if ((enforce_ellipsis || short_string_ellipsis) && (width + ellipsis_width <= p_width)) { trim_pos = -1; ellipsis_pos = sd_size; } else { @@ -4706,7 +4707,7 @@ void TextServerFallback::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ width = width_without_el; break; } - if (!enforce_ellipsis && width <= p_width && last_valid_cut_witout_el == -1) { + if (!(enforce_ellipsis || short_string_ellipsis) && width <= p_width && last_valid_cut_witout_el == -1) { if (cut_per_word && above_min_char_threshold) { if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) { last_valid_cut_witout_el = i; @@ -4717,7 +4718,7 @@ void TextServerFallback::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ width_without_el = width; } } - if (width + (((above_min_char_threshold && add_ellipsis) || enforce_ellipsis) ? ellipsis_width : 0) <= p_width) { + if (width + (((above_min_char_threshold && add_ellipsis) || enforce_ellipsis || short_string_ellipsis) ? ellipsis_width : 0) <= p_width) { if (cut_per_word && above_min_char_threshold) { if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) { last_valid_cut = i; @@ -4728,7 +4729,7 @@ void TextServerFallback::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ if (last_valid_cut != -1) { trim_pos = last_valid_cut; - if (add_ellipsis && (above_min_char_threshold || enforce_ellipsis) && width - ellipsis_width <= p_width) { + if (add_ellipsis && (above_min_char_threshold || enforce_ellipsis || short_string_ellipsis) && width - ellipsis_width <= p_width) { ellipsis_pos = trim_pos; } break; @@ -4740,12 +4741,12 @@ void TextServerFallback::_shaped_text_overrun_trim_to_width(const RID &p_shaped_ sd->overrun_trim_data.trim_pos = trim_pos; sd->overrun_trim_data.ellipsis_pos = ellipsis_pos; - if (trim_pos == 0 && enforce_ellipsis && add_ellipsis) { + if (trim_pos == 0 && (enforce_ellipsis || short_string_ellipsis) && add_ellipsis) { sd->overrun_trim_data.ellipsis_pos = 0; } - if ((trim_pos >= 0 && sd->width > p_width) || enforce_ellipsis) { - if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis)) { + if ((trim_pos >= 0 && sd->width > p_width) || enforce_ellipsis || short_string_ellipsis) { + if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis || short_string_ellipsis)) { // Insert an additional space when cutting word bound for aesthetics. if (cut_per_word && (ellipsis_pos > 0)) { Glyph gl; diff --git a/servers/text/text_server.cpp b/servers/text/text_server.cpp index 117dc5073fe..436eb2400a6 100644 --- a/servers/text/text_server.cpp +++ b/servers/text/text_server.cpp @@ -608,6 +608,7 @@ void TextServer::_bind_methods() { BIND_BITFIELD_FLAG(OVERRUN_ADD_ELLIPSIS); BIND_BITFIELD_FLAG(OVERRUN_ENFORCE_ELLIPSIS); BIND_BITFIELD_FLAG(OVERRUN_JUSTIFICATION_AWARE); + BIND_BITFIELD_FLAG(OVERRUN_SHORT_STRING_ELLIPSIS); /* GraphemeFlag */ BIND_BITFIELD_FLAG(GRAPHEME_IS_VALID); @@ -2398,12 +2399,12 @@ BitField TextServer::get_overrun_flags_from_behavio overrun_flags.set_flag(OVERRUN_TRIM); overrun_flags.set_flag(OVERRUN_TRIM_WORD_ONLY); overrun_flags.set_flag(OVERRUN_ADD_ELLIPSIS); - overrun_flags.set_flag(OVERRUN_ENFORCE_ELLIPSIS); + overrun_flags.set_flag(OVERRUN_SHORT_STRING_ELLIPSIS); } break; case OVERRUN_TRIM_ELLIPSIS_FORCE: { overrun_flags.set_flag(OVERRUN_TRIM); overrun_flags.set_flag(OVERRUN_ADD_ELLIPSIS); - overrun_flags.set_flag(OVERRUN_ENFORCE_ELLIPSIS); + overrun_flags.set_flag(OVERRUN_SHORT_STRING_ELLIPSIS); } break; case OVERRUN_TRIM_WORD_ELLIPSIS: overrun_flags.set_flag(OVERRUN_TRIM); diff --git a/servers/text/text_server.h b/servers/text/text_server.h index 64e8a6bc80f..90c4df51afd 100644 --- a/servers/text/text_server.h +++ b/servers/text/text_server.h @@ -137,6 +137,7 @@ public: OVERRUN_ADD_ELLIPSIS = 1 << 2, OVERRUN_ENFORCE_ELLIPSIS = 1 << 3, OVERRUN_JUSTIFICATION_AWARE = 1 << 4, + OVERRUN_SHORT_STRING_ELLIPSIS = 1 << 5, }; enum GraphemeFlag {