Skip to content

Commit d26146e

Browse files
committed
Merge pull request #107394 from bruvzg/char_before_pref
Improve performance of `visible_characters`updates in `VC_CHARS_BEFORE_SHAPING` mode.
2 parents b54197a + c11c449 commit d26146e

File tree

1 file changed

+78
-8
lines changed

1 file changed

+78
-8
lines changed

scene/gui/rich_text_label.cpp

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7058,6 +7058,7 @@ void RichTextLabel::set_visible_ratio(float p_ratio) {
70587058
if (visible_ratio != p_ratio) {
70597059
_stop_thread();
70607060

7061+
int prev_vc = visible_characters;
70617062
if (p_ratio >= 1.0) {
70627063
visible_characters = -1;
70637064
visible_ratio = 1.0;
@@ -7069,10 +7070,44 @@ void RichTextLabel::set_visible_ratio(float p_ratio) {
70697070
visible_ratio = p_ratio;
70707071
}
70717072

7072-
if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
7073-
main->first_invalid_line.store(0); // Invalidate all lines..
7074-
_invalidate_accessibility();
7075-
_validate_line_caches();
7073+
if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING && visible_characters != prev_vc) {
7074+
int new_vc = (visible_characters < 0) ? get_total_character_count() : visible_characters;
7075+
int old_vc = (prev_vc < 0) ? get_total_character_count() : prev_vc;
7076+
int to_line = main->first_invalid_line.load();
7077+
int old_from_l = to_line;
7078+
int new_from_l = to_line;
7079+
for (int i = 0; i < to_line; i++) {
7080+
const Line &l = main->lines[i];
7081+
if (l.char_offset <= old_vc && l.char_offset + l.char_count > old_vc) {
7082+
old_from_l = i;
7083+
}
7084+
if (l.char_offset <= new_vc && l.char_offset + l.char_count > new_vc) {
7085+
new_from_l = i;
7086+
}
7087+
}
7088+
Rect2 text_rect = _get_text_rect();
7089+
int first_invalid = MIN(new_from_l, old_from_l);
7090+
int second_invalid = MAX(new_from_l, old_from_l);
7091+
7092+
float total_height = (first_invalid == 0) ? 0 : _calculate_line_vertical_offset(main->lines[first_invalid - 1]);
7093+
if (first_invalid < to_line) {
7094+
int total_chars = main->lines[first_invalid].char_offset;
7095+
total_height = _shape_line(main, first_invalid, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height, &total_chars);
7096+
}
7097+
if (first_invalid != second_invalid) {
7098+
for (int i = first_invalid + 1; i < second_invalid; i++) {
7099+
main->lines[i].offset.y = total_height;
7100+
total_height = _calculate_line_vertical_offset(main->lines[i]);
7101+
}
7102+
if (second_invalid < to_line) {
7103+
int total_chars = main->lines[second_invalid].char_offset;
7104+
total_height = _shape_line(main, second_invalid, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height, &total_chars);
7105+
}
7106+
}
7107+
for (int i = second_invalid + 1; i < to_line; i++) {
7108+
main->lines[i].offset.y = total_height;
7109+
total_height = _calculate_line_vertical_offset(main->lines[i]);
7110+
}
70767111
}
70777112
queue_redraw();
70787113
}
@@ -7497,6 +7532,7 @@ void RichTextLabel::set_visible_characters(int p_visible) {
74977532
if (visible_characters != p_visible) {
74987533
_stop_thread();
74997534

7535+
int prev_vc = visible_characters;
75007536
visible_characters = p_visible;
75017537
if (p_visible == -1) {
75027538
visible_ratio = 1;
@@ -7506,10 +7542,44 @@ void RichTextLabel::set_visible_characters(int p_visible) {
75067542
visible_ratio = (float)p_visible / (float)total_char_count;
75077543
}
75087544
}
7509-
if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) {
7510-
main->first_invalid_line.store(0); // Invalidate all lines.
7511-
_invalidate_accessibility();
7512-
_validate_line_caches();
7545+
if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING && visible_characters != prev_vc) {
7546+
int new_vc = (visible_characters < 0) ? get_total_character_count() : visible_characters;
7547+
int old_vc = (prev_vc < 0) ? get_total_character_count() : prev_vc;
7548+
int to_line = main->first_invalid_line.load();
7549+
int old_from_l = to_line;
7550+
int new_from_l = to_line;
7551+
for (int i = 0; i < to_line; i++) {
7552+
const Line &l = main->lines[i];
7553+
if (l.char_offset <= old_vc && l.char_offset + l.char_count > old_vc) {
7554+
old_from_l = i;
7555+
}
7556+
if (l.char_offset <= new_vc && l.char_offset + l.char_count > new_vc) {
7557+
new_from_l = i;
7558+
}
7559+
}
7560+
Rect2 text_rect = _get_text_rect();
7561+
int first_invalid = MIN(new_from_l, old_from_l);
7562+
int second_invalid = MAX(new_from_l, old_from_l);
7563+
7564+
float total_height = (first_invalid == 0) ? 0 : _calculate_line_vertical_offset(main->lines[first_invalid - 1]);
7565+
if (first_invalid < to_line) {
7566+
int total_chars = main->lines[first_invalid].char_offset;
7567+
total_height = _shape_line(main, first_invalid, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height, &total_chars);
7568+
}
7569+
if (first_invalid != second_invalid) {
7570+
for (int i = first_invalid + 1; i < second_invalid; i++) {
7571+
main->lines[i].offset.y = total_height;
7572+
total_height = _calculate_line_vertical_offset(main->lines[i]);
7573+
}
7574+
if (second_invalid < to_line) {
7575+
int total_chars = main->lines[second_invalid].char_offset;
7576+
total_height = _shape_line(main, second_invalid, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height, &total_chars);
7577+
}
7578+
}
7579+
for (int i = second_invalid + 1; i < to_line; i++) {
7580+
main->lines[i].offset.y = total_height;
7581+
total_height = _calculate_line_vertical_offset(main->lines[i]);
7582+
}
75137583
}
75147584
queue_redraw();
75157585
}

0 commit comments

Comments
 (0)