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

Fix Label and RichTextLabel visible_characters and percent_visible methods.

This commit is contained in:
bruvzg
2021-09-20 09:35:24 +03:00
parent 0e5b0c025c
commit 9d0e3cff09
2 changed files with 69 additions and 73 deletions

View File

@@ -92,8 +92,12 @@ void Label::_shape() {
const Ref<Font> &font = get_theme_font(SNAME("font")); const Ref<Font> &font = get_theme_font(SNAME("font"));
int font_size = get_theme_font_size(SNAME("font_size")); int font_size = get_theme_font_size(SNAME("font_size"));
ERR_FAIL_COND(font.is_null()); ERR_FAIL_COND(font.is_null());
TS->shaped_text_add_string(text_rid, (uppercase) ? xl_text.to_upper() : xl_text, font->get_rids(), font_size, opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale()); String text = (uppercase) ? xl_text.to_upper() : xl_text;
TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, xl_text)); if (visible_chars >= 0) {
text = text.substr(0, visible_chars);
}
TS->shaped_text_add_string(text_rid, text, font->get_rids(), font_size, opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale());
TS->shaped_text_set_bidi_override(text_rid, structured_text_parser(st_parser, st_args, text));
dirty = false; dirty = false;
lines_dirty = true; lines_dirty = true;
} }
@@ -258,6 +262,9 @@ void Label::_notification(int p_what) {
return; // Nothing new. return; // Nothing new.
} }
xl_text = new_text; xl_text = new_text;
if (percent_visible < 1) {
visible_chars = get_total_character_count() * percent_visible;
}
dirty = true; dirty = true;
update(); update();
@@ -342,24 +349,6 @@ void Label::_notification(int p_what) {
} }
} }
int visible_glyphs = -1;
int glyhps_drawn = 0;
if (percent_visible < 1) {
int total_glyphs = 0;
for (int i = lines_skipped; i < last_line; i++) {
const Vector<TextServer::Glyph> visual = TS->shaped_text_get_glyphs(lines_rid[i]);
const TextServer::Glyph *glyphs = visual.ptr();
int gl_size = visual.size();
for (int j = 0; j < gl_size; j++) {
if ((glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
total_glyphs++;
}
}
}
visible_glyphs = MIN(total_glyphs, visible_chars);
}
Vector2 ofs; Vector2 ofs;
ofs.y = style->get_offset().y + vbegin; ofs.y = style->get_offset().y + vbegin;
for (int i = lines_skipped; i < last_line; i++) { for (int i = lines_skipped; i < last_line; i++) {
@@ -407,14 +396,6 @@ void Label::_notification(int p_what) {
// Draw main text. // Draw main text.
for (int j = 0; j < gl_size; j++) { for (int j = 0; j < gl_size; j++) {
for (int k = 0; k < glyphs[j].repeat; k++) { for (int k = 0; k < glyphs[j].repeat; k++) {
if (visible_glyphs != -1) {
if ((glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
if (glyhps_drawn >= visible_glyphs) {
return;
}
}
}
// Trim when necessary. // Trim when necessary.
if (trim_data.trim_pos >= 0) { if (trim_data.trim_pos >= 0) {
if (rtl) { if (rtl) {
@@ -431,7 +412,6 @@ void Label::_notification(int p_what) {
// Draw glyph outlines and shadow. // Draw glyph outlines and shadow.
draw_glyph_outline(glyphs[j], ci, font_color, font_shadow_color, font_outline_color, shadow_outline_size, outline_size, offset, shadow_ofs); draw_glyph_outline(glyphs[j], ci, font_color, font_shadow_color, font_outline_color, shadow_outline_size, outline_size, offset, shadow_ofs);
offset.x += glyphs[j].advance; offset.x += glyphs[j].advance;
glyhps_drawn++;
} }
} }
// Draw LTR ellipsis string when necessary. // Draw LTR ellipsis string when necessary.
@@ -462,14 +442,6 @@ void Label::_notification(int p_what) {
// Draw main text. // Draw main text.
for (int j = 0; j < gl_size; j++) { for (int j = 0; j < gl_size; j++) {
for (int k = 0; k < glyphs[j].repeat; k++) { for (int k = 0; k < glyphs[j].repeat; k++) {
if (visible_glyphs != -1) {
if ((glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) != TextServer::GRAPHEME_IS_VIRTUAL) {
if (glyhps_drawn >= visible_glyphs) {
return;
}
}
}
// Trim when necessary. // Trim when necessary.
if (trim_data.trim_pos >= 0) { if (trim_data.trim_pos >= 0) {
if (rtl) { if (rtl) {
@@ -486,7 +458,6 @@ void Label::_notification(int p_what) {
// Draw glyph outlines and shadow. // Draw glyph outlines and shadow.
draw_glyph(glyphs[j], ci, font_color, ofs); draw_glyph(glyphs[j], ci, font_color, ofs);
ofs.x += glyphs[j].advance; ofs.x += glyphs[j].advance;
glyhps_drawn++;
} }
} }
// Draw LTR ellipsis string when necessary. // Draw LTR ellipsis string when necessary.
@@ -709,33 +680,35 @@ String Label::get_text() const {
} }
void Label::set_visible_characters(int p_amount) { void Label::set_visible_characters(int p_amount) {
if (visible_chars != p_amount) {
visible_chars = p_amount; visible_chars = p_amount;
if (get_total_character_count() > 0) { if (get_total_character_count() > 0) {
percent_visible = (float)p_amount / (float)get_total_character_count(); percent_visible = (float)p_amount / (float)get_total_character_count();
} else { } else {
percent_visible = 1.0; percent_visible = 1.0;
} }
if (p_amount == -1) { dirty = true;
lines_dirty = true;
}
update(); update();
} }
}
int Label::get_visible_characters() const { int Label::get_visible_characters() const {
return visible_chars; return visible_chars;
} }
void Label::set_percent_visible(float p_percent) { void Label::set_percent_visible(float p_percent) {
if (percent_visible != p_percent) {
if (p_percent < 0 || p_percent >= 1) { if (p_percent < 0 || p_percent >= 1) {
visible_chars = -1; visible_chars = -1;
percent_visible = 1; percent_visible = 1;
lines_dirty = true;
} else { } else {
visible_chars = get_total_character_count() * p_percent; visible_chars = get_total_character_count() * p_percent;
percent_visible = p_percent; percent_visible = p_percent;
} }
dirty = true;
update(); update();
} }
}
float Label::get_percent_visible() const { float Label::get_percent_visible() const {
return percent_visible; return percent_visible;
@@ -889,7 +862,7 @@ void Label::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "is_clipping_text"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "is_clipping_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_overrun_behavior", PROPERTY_HINT_ENUM, "Trim Nothing,Trim Characters,Trim Words,Ellipsis,Word Ellipsis"), "set_text_overrun_behavior", "get_text_overrun_behavior");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase");
ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1", PROPERTY_USAGE_EDITOR), "set_visible_characters", "get_visible_characters"); ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible");
ADD_PROPERTY(PropertyInfo(Variant::INT, "lines_skipped", PROPERTY_HINT_RANGE, "0,999,1"), "set_lines_skipped", "get_lines_skipped"); ADD_PROPERTY(PropertyInfo(Variant::INT, "lines_skipped", PROPERTY_HINT_RANGE, "0,999,1"), "set_lines_skipped", "get_lines_skipped");
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_lines_visible", PROPERTY_HINT_RANGE, "-1,999,1"), "set_max_lines_visible", "get_max_lines_visible"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_lines_visible", PROPERTY_HINT_RANGE, "-1,999,1"), "set_max_lines_visible", "get_max_lines_visible");

View File

@@ -399,8 +399,9 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
// Shape current paragraph. // Shape current paragraph.
String text; String text;
Item *it_to = (p_line + 1 < p_frame->lines.size()) ? p_frame->lines[p_line + 1].from : nullptr; Item *it_to = (p_line + 1 < p_frame->lines.size()) ? p_frame->lines[p_line + 1].from : nullptr;
int remaining_characters = visible_characters - l.char_offset;
for (Item *it = l.from; it && it != it_to; it = _get_next_item(it)) { for (Item *it = l.from; it && it != it_to; it = _get_next_item(it)) {
if (visible_characters >= 0 && l.char_offset + l.char_count > visible_characters) { if (visible_characters >= 0 && remaining_characters <= 0) {
break; break;
} }
switch (it->type) { switch (it->type) {
@@ -427,7 +428,8 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
} }
l.text_buf->add_string("\n", font, font_size, Dictionary(), ""); l.text_buf->add_string("\n", font, font_size, Dictionary(), "");
text += "\n"; text += "\n";
l.char_count += 1; l.char_count++;
remaining_characters--;
} break; } break;
case ITEM_TEXT: { case ITEM_TEXT: {
ItemText *t = (ItemText *)it; ItemText *t = (ItemText *)it;
@@ -442,9 +444,10 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
Dictionary font_ftr = _find_font_features(it); Dictionary font_ftr = _find_font_features(it);
String lang = _find_language(it); String lang = _find_language(it);
String tx = t->text; String tx = t->text;
if (visible_characters >= 0 && l.char_offset + l.char_count + tx.length() > visible_characters) { if (visible_characters >= 0 && remaining_characters >= 0) {
tx = tx.substr(0, l.char_offset + l.char_count + tx.length() - visible_characters); tx = tx.substr(0, remaining_characters);
} }
remaining_characters -= tx.length();
l.text_buf->add_string(tx, font, font_size, font_ftr, lang); l.text_buf->add_string(tx, font, font_size, font_ftr, lang);
text += tx; text += tx;
@@ -454,7 +457,8 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
ItemImage *img = (ItemImage *)it; ItemImage *img = (ItemImage *)it;
l.text_buf->add_object((uint64_t)it, img->image->get_size(), img->inline_align, 1); l.text_buf->add_object((uint64_t)it, img->image->get_size(), img->inline_align, 1);
text += String::chr(0xfffc); text += String::chr(0xfffc);
l.char_count += 1; l.char_count++;
remaining_characters--;
} break; } break;
case ITEM_TABLE: { case ITEM_TABLE: {
ItemTable *table = static_cast<ItemTable *>(it); ItemTable *table = static_cast<ItemTable *>(it);
@@ -483,6 +487,7 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
int cell_ch = (char_offset - (l.char_offset + l.char_count)); int cell_ch = (char_offset - (l.char_offset + l.char_count));
l.char_count += cell_ch; l.char_count += cell_ch;
t_char_count += cell_ch; t_char_count += cell_ch;
remaining_characters -= cell_ch;
table->columns.write[column].min_width = MAX(table->columns[column].min_width, ceil(frame->lines[i].text_buf->get_size().x)); table->columns.write[column].min_width = MAX(table->columns[column].min_width, ceil(frame->lines[i].text_buf->get_size().x));
table->columns.write[column].max_width = MAX(table->columns[column].max_width, ceil(frame->lines[i].text_buf->get_non_wraped_size().x)); table->columns.write[column].max_width = MAX(table->columns[column].max_width, ceil(frame->lines[i].text_buf->get_non_wraped_size().x));
@@ -3855,7 +3860,12 @@ String RichTextLabel::get_parsed_text() const {
String text = ""; String text = "";
Item *it = main; Item *it = main;
while (it) { while (it) {
if (it->type == ITEM_TEXT) { if (it->type == ITEM_DROPCAP) {
const ItemDropcap *dc = (ItemDropcap *)it;
if (dc != nullptr) {
text += dc->text;
}
} else if (it->type == ITEM_TEXT) {
ItemText *t = static_cast<ItemText *>(it); ItemText *t = static_cast<ItemText *>(it);
text += t->text; text += t->text;
} else if (it->type == ITEM_NEWLINE) { } else if (it->type == ITEM_NEWLINE) {
@@ -3926,7 +3936,6 @@ void RichTextLabel::set_percent_visible(float p_percent) {
if (p_percent < 0 || p_percent >= 1) { if (p_percent < 0 || p_percent >= 1) {
visible_characters = -1; visible_characters = -1;
percent_visible = 1; percent_visible = 1;
} else { } else {
visible_characters = get_total_character_count() * p_percent; visible_characters = get_total_character_count() * p_percent;
percent_visible = p_percent; percent_visible = p_percent;
@@ -4160,6 +4169,7 @@ void RichTextLabel::_bind_methods() {
} }
void RichTextLabel::set_visible_characters(int p_visible) { void RichTextLabel::set_visible_characters(int p_visible) {
if (visible_characters != p_visible) {
visible_characters = p_visible; visible_characters = p_visible;
if (p_visible == -1) { if (p_visible == -1) {
percent_visible = 1; percent_visible = 1;
@@ -4169,17 +4179,30 @@ void RichTextLabel::set_visible_characters(int p_visible) {
percent_visible = (float)p_visible / (float)total_char_count; percent_visible = (float)p_visible / (float)total_char_count;
} }
} }
main->first_invalid_line = 0; //invalidate ALL
_validate_line_caches(main);
update(); update();
} }
}
int RichTextLabel::get_visible_characters() const { int RichTextLabel::get_visible_characters() const {
return visible_characters; return visible_characters;
} }
int RichTextLabel::get_total_character_count() const { int RichTextLabel::get_total_character_count() const {
// Note: Do not use line buffer "char_count", it includes only visible characters.
int tc = 0; int tc = 0;
for (int i = 0; i < current_frame->lines.size(); i++) { Item *it = main;
tc += current_frame->lines[i].char_count; while (it) {
if (it->type == ITEM_TEXT) {
ItemText *t = static_cast<ItemText *>(it);
tc += t->text.length();
} else if (it->type == ITEM_NEWLINE) {
tc++;
} else if (it->type == ITEM_IMAGE) {
tc++;
}
it = _get_next_item(it, true);
} }
return tc; return tc;