diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index fe3139c1736..9409ae23156 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -2781,6 +2781,44 @@ int RichTextLabel::get_progress_bar_delay() const { return progress_delay; } +_FORCE_INLINE_ float RichTextLabel::_update_scroll_exceeds(float p_total_height, float p_ctrl_height, float p_width, int p_idx, float p_old_scroll, float p_text_rect_height) { + updating_scroll = true; + + float total_height = p_total_height; + bool exceeds = p_total_height > p_ctrl_height && scroll_active; + if (exceeds != scroll_visible) { + if (exceeds) { + scroll_visible = true; + scroll_w = vscroll->get_combined_minimum_size().width; + vscroll->show(); + vscroll->set_anchor_and_offset(SIDE_LEFT, ANCHOR_END, -scroll_w); + } else { + scroll_visible = false; + scroll_w = 0; + vscroll->hide(); + } + + main->first_resized_line.store(0); + + total_height = 0; + for (int j = 0; j <= p_idx; j++) { + total_height = _resize_line(main, j, theme_cache.normal_font, theme_cache.normal_font_size, p_width, total_height); + + main->first_resized_line.store(j); + } + } + vscroll->set_max(total_height); + vscroll->set_page(p_text_rect_height); + if (scroll_follow && scroll_following) { + vscroll->set_value(total_height); + } else { + vscroll->set_value(p_old_scroll); + } + updating_scroll = false; + + return total_height; +} + bool RichTextLabel::_validate_line_caches() { if (updating.load()) { return false; @@ -2790,7 +2828,7 @@ bool RichTextLabel::_validate_line_caches() { MutexLock data_lock(data_mutex); Rect2 text_rect = _get_text_rect(); - int ctrl_height = get_size().height; + float ctrl_height = get_size().height; // Update fonts. float old_scroll = vscroll->get_value(); @@ -2814,40 +2852,7 @@ bool RichTextLabel::_validate_line_caches() { float total_height = (fi == 0) ? 0 : _calculate_line_vertical_offset(main->lines[fi - 1]); for (int i = fi; i < (int)main->lines.size(); i++) { total_height = _resize_line(main, i, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height); - - updating_scroll = true; - bool exceeds = total_height > ctrl_height && scroll_active; - if (exceeds != scroll_visible) { - if (exceeds) { - scroll_visible = true; - scroll_w = vscroll->get_combined_minimum_size().width; - vscroll->show(); - vscroll->set_anchor_and_offset(SIDE_LEFT, ANCHOR_END, -scroll_w); - } else { - scroll_visible = false; - scroll_w = 0; - vscroll->hide(); - } - - main->first_resized_line.store(0); - - total_height = 0; - for (int j = 0; j <= i; j++) { - total_height = _resize_line(main, j, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height); - - main->first_resized_line.store(j); - } - } - - vscroll->set_max(total_height); - vscroll->set_page(text_rect.size.height); - if (scroll_follow && scroll_following) { - vscroll->set_value(total_height); - } else { - vscroll->set_value(old_scroll); - } - updating_scroll = false; - + total_height = _update_scroll_exceeds(total_height, ctrl_height, text_rect.get_size().width - scroll_w, i, old_scroll, text_rect.size.height); main->first_resized_line.store(i); } @@ -2886,47 +2891,34 @@ void RichTextLabel::_process_line_caches() { MutexLock data_lock(data_mutex); Rect2 text_rect = _get_text_rect(); - int ctrl_height = get_size().height; + float ctrl_height = get_size().height; int fi = main->first_invalid_line.load(); int total_chars = main->lines[fi].char_offset; + float old_scroll = vscroll->get_value(); + + float total_height = 0; + if (fi != 0) { + // Update fonts. + + for (int i = main->first_invalid_font_line.load(); i < fi; i++) { + _update_line_font(main, i, theme_cache.normal_font, theme_cache.normal_font_size); + } + + // Resize lines without reshaping. + int sr = MIN(main->first_invalid_font_line.load(), main->first_resized_line.load()); + main->first_invalid_font_line.store(fi); + + for (int i = sr; i < fi; i++) { + total_height = _resize_line(main, i, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height); + total_height = _update_scroll_exceeds(total_height, ctrl_height, text_rect.get_size().width - scroll_w, i, old_scroll, text_rect.size.height); + + main->first_resized_line.store(i); + } + } - float total_height = (fi == 0) ? 0 : _calculate_line_vertical_offset(main->lines[fi - 1]); for (int i = fi; i < (int)main->lines.size(); i++) { total_height = _shape_line(main, i, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height, &total_chars); - updating_scroll = true; - bool exceeds = total_height > ctrl_height && scroll_active; - if (exceeds != scroll_visible) { - if (exceeds) { - scroll_visible = true; - scroll_w = vscroll->get_combined_minimum_size().width; - vscroll->show(); - vscroll->set_anchor_and_offset(SIDE_LEFT, ANCHOR_END, -scroll_w); - } else { - scroll_visible = false; - scroll_w = 0; - vscroll->hide(); - } - main->first_invalid_line.store(0); - main->first_resized_line.store(0); - main->first_invalid_font_line.store(0); - - // since scroll was added or removed we need to resize all lines - total_height = 0; - for (int j = 0; j <= i; j++) { - total_height = _resize_line(main, j, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height); - - main->first_invalid_line.store(j); - main->first_resized_line.store(j); - main->first_invalid_font_line.store(j); - } - } - - vscroll->set_max(total_height); - vscroll->set_page(text_rect.size.height); - if (scroll_follow && scroll_following) { - vscroll->set_value(total_height); - } - updating_scroll = false; + total_height = _update_scroll_exceeds(total_height, ctrl_height, text_rect.get_size().width - scroll_w, i, old_scroll, text_rect.size.height); main->first_invalid_line.store(i); main->first_resized_line.store(i); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index cbdad3e4d71..66891ab567d 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -421,6 +421,7 @@ private: void _stop_thread(); bool _validate_line_caches(); void _process_line_caches(); + _FORCE_INLINE_ float _update_scroll_exceeds(float p_total_height, float p_ctrl_height, float p_width, int p_idx, float p_old_scroll, float p_text_rect_height); void _add_item(Item *p_item, bool p_enter = false, bool p_ensure_newline = false); void _remove_item(Item *p_item, const int p_line, const int p_subitem_line);