1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-23 15:16:17 +00:00

[TextServer] Use a separate flag to disable min. string length for adding ellipsis.

This commit is contained in:
Pāvels Nadtočajevs
2025-09-11 13:05:31 +03:00
parent b79fe2e020
commit 5fdcb805d4
5 changed files with 31 additions and 24 deletions

View File

@@ -2143,6 +2143,9 @@
<constant name="OVERRUN_JUSTIFICATION_AWARE" value="16" enum="TextOverrunFlag" is_bitfield="true"> <constant name="OVERRUN_JUSTIFICATION_AWARE" value="16" enum="TextOverrunFlag" is_bitfield="true">
Accounts for the text being justified before attempting to trim it (see [enum JustificationFlag]). Accounts for the text being justified before attempting to trim it (see [enum JustificationFlag]).
</constant> </constant>
<constant name="OVERRUN_SHORT_STRING_ELLIPSIS" value="32" enum="TextOverrunFlag" is_bitfield="true">
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.
</constant>
<constant name="GRAPHEME_IS_VALID" value="1" enum="GraphemeFlag" is_bitfield="true"> <constant name="GRAPHEME_IS_VALID" value="1" enum="GraphemeFlag" is_bitfield="true">
Grapheme is supported by the font, and can be drawn. Grapheme is supported by the font, and can be drawn.
</constant> </constant>

View File

@@ -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 add_ellipsis = p_trim_flags.has_flag(OVERRUN_ADD_ELLIPSIS);
bool cut_per_word = p_trim_flags.has_flag(OVERRUN_TRIM_WORD_ONLY); 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 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); bool justification_aware = p_trim_flags.has_flag(OVERRUN_JUSTIFICATION_AWARE);
Glyph *sd_glyphs = sd->glyphs.ptr(); 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. // 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; 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)) { if (!_font_has_char(dot_gl_font_rid, sd->el_char)) {
const Array &fonts = spans[span_size - 1].fonts; const Array &fonts = spans[span_size - 1].fonts;
for (int i = 0; i < fonts.size(); i++) { 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; 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) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_advance(dot_gl_font_rid, last_gl_font_size, dot_gl_idx) : Vector2(); 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; 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(); 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; bool is_rtl = sd->para_direction == DIRECTION_RTL;
int trim_pos = (is_rtl) ? sd_size : 0; 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 = -1;
int last_valid_cut_witout_el = -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_to = (is_rtl) ? sd_size - 1 : -1;
int glyphs_delta = (is_rtl) ? +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; trim_pos = -1;
ellipsis_pos = (is_rtl) ? 0 : sd_size; ellipsis_pos = (is_rtl) ? 0 : sd_size;
} else { } else {
@@ -6009,7 +6010,7 @@ void TextServerAdvanced::_shaped_text_overrun_trim_to_width(const RID &p_shaped_
width = width_without_el; width = width_without_el;
break; 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 (cut_per_word && above_min_char_threshold) {
if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) { if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) {
last_valid_cut_witout_el = i; 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; 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 (cut_per_word && above_min_char_threshold) {
if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) { if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) {
last_valid_cut = i; 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) { if (last_valid_cut != -1) {
trim_pos = last_valid_cut; 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; ellipsis_pos = trim_pos;
} }
break; 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.trim_pos = trim_pos;
sd->overrun_trim_data.ellipsis_pos = ellipsis_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; sd->overrun_trim_data.ellipsis_pos = 0;
} }
if ((trim_pos >= 0 && sd->width > p_width) || enforce_ellipsis) { if ((trim_pos >= 0 && sd->width > p_width) || enforce_ellipsis || short_string_ellipsis) {
if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis)) { if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis || short_string_ellipsis)) {
// Insert an additional space when cutting word bound for aesthetics. // Insert an additional space when cutting word bound for aesthetics.
if (cut_per_word && (ellipsis_pos > 0)) { if (cut_per_word && (ellipsis_pos > 0)) {
Glyph gl; Glyph gl;

View File

@@ -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 add_ellipsis = p_trim_flags.has_flag(OVERRUN_ADD_ELLIPSIS);
bool cut_per_word = p_trim_flags.has_flag(OVERRUN_TRIM_WORD_ONLY); 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 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); bool justification_aware = p_trim_flags.has_flag(OVERRUN_JUSTIFICATION_AWARE);
Glyph *sd_glyphs = sd->glyphs.ptrw(); 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. // 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; 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)) { if (!_font_has_char(dot_gl_font_rid, sd->el_char)) {
const Array &fonts = spans[span_size - 1].fonts; const Array &fonts = spans[span_size - 1].fonts;
for (int i = 0; i < fonts.size(); i++) { 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; 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) && dot_gl_font_rid.is_valid()) ? _font_get_glyph_advance(dot_gl_font_rid, last_gl_font_size, dot_gl_idx) : Vector2(); 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; 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(); 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; double width_without_el = width;
int trim_pos = 0; 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 = -1;
int last_valid_cut_witout_el = -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; trim_pos = -1;
ellipsis_pos = sd_size; ellipsis_pos = sd_size;
} else { } else {
@@ -4706,7 +4707,7 @@ void TextServerFallback::_shaped_text_overrun_trim_to_width(const RID &p_shaped_
width = width_without_el; width = width_without_el;
break; 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 (cut_per_word && above_min_char_threshold) {
if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) { if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) {
last_valid_cut_witout_el = i; 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; 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 (cut_per_word && above_min_char_threshold) {
if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) { if ((sd_glyphs[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) {
last_valid_cut = i; 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) { if (last_valid_cut != -1) {
trim_pos = last_valid_cut; 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; ellipsis_pos = trim_pos;
} }
break; 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.trim_pos = trim_pos;
sd->overrun_trim_data.ellipsis_pos = ellipsis_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; sd->overrun_trim_data.ellipsis_pos = 0;
} }
if ((trim_pos >= 0 && sd->width > p_width) || enforce_ellipsis) { if ((trim_pos >= 0 && sd->width > p_width) || enforce_ellipsis || short_string_ellipsis) {
if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis)) { if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis || short_string_ellipsis)) {
// Insert an additional space when cutting word bound for aesthetics. // Insert an additional space when cutting word bound for aesthetics.
if (cut_per_word && (ellipsis_pos > 0)) { if (cut_per_word && (ellipsis_pos > 0)) {
Glyph gl; Glyph gl;

View File

@@ -608,6 +608,7 @@ void TextServer::_bind_methods() {
BIND_BITFIELD_FLAG(OVERRUN_ADD_ELLIPSIS); BIND_BITFIELD_FLAG(OVERRUN_ADD_ELLIPSIS);
BIND_BITFIELD_FLAG(OVERRUN_ENFORCE_ELLIPSIS); BIND_BITFIELD_FLAG(OVERRUN_ENFORCE_ELLIPSIS);
BIND_BITFIELD_FLAG(OVERRUN_JUSTIFICATION_AWARE); BIND_BITFIELD_FLAG(OVERRUN_JUSTIFICATION_AWARE);
BIND_BITFIELD_FLAG(OVERRUN_SHORT_STRING_ELLIPSIS);
/* GraphemeFlag */ /* GraphemeFlag */
BIND_BITFIELD_FLAG(GRAPHEME_IS_VALID); BIND_BITFIELD_FLAG(GRAPHEME_IS_VALID);
@@ -2398,12 +2399,12 @@ BitField<TextServer::TextOverrunFlag> TextServer::get_overrun_flags_from_behavio
overrun_flags.set_flag(OVERRUN_TRIM); overrun_flags.set_flag(OVERRUN_TRIM);
overrun_flags.set_flag(OVERRUN_TRIM_WORD_ONLY); overrun_flags.set_flag(OVERRUN_TRIM_WORD_ONLY);
overrun_flags.set_flag(OVERRUN_ADD_ELLIPSIS); overrun_flags.set_flag(OVERRUN_ADD_ELLIPSIS);
overrun_flags.set_flag(OVERRUN_ENFORCE_ELLIPSIS); overrun_flags.set_flag(OVERRUN_SHORT_STRING_ELLIPSIS);
} break; } break;
case OVERRUN_TRIM_ELLIPSIS_FORCE: { case OVERRUN_TRIM_ELLIPSIS_FORCE: {
overrun_flags.set_flag(OVERRUN_TRIM); overrun_flags.set_flag(OVERRUN_TRIM);
overrun_flags.set_flag(OVERRUN_ADD_ELLIPSIS); overrun_flags.set_flag(OVERRUN_ADD_ELLIPSIS);
overrun_flags.set_flag(OVERRUN_ENFORCE_ELLIPSIS); overrun_flags.set_flag(OVERRUN_SHORT_STRING_ELLIPSIS);
} break; } break;
case OVERRUN_TRIM_WORD_ELLIPSIS: case OVERRUN_TRIM_WORD_ELLIPSIS:
overrun_flags.set_flag(OVERRUN_TRIM); overrun_flags.set_flag(OVERRUN_TRIM);

View File

@@ -137,6 +137,7 @@ public:
OVERRUN_ADD_ELLIPSIS = 1 << 2, OVERRUN_ADD_ELLIPSIS = 1 << 2,
OVERRUN_ENFORCE_ELLIPSIS = 1 << 3, OVERRUN_ENFORCE_ELLIPSIS = 1 << 3,
OVERRUN_JUSTIFICATION_AWARE = 1 << 4, OVERRUN_JUSTIFICATION_AWARE = 1 << 4,
OVERRUN_SHORT_STRING_ELLIPSIS = 1 << 5,
}; };
enum GraphemeFlag { enum GraphemeFlag {