From 4115b813fe61b4993faa45a812a77ff0e46f4d8e Mon Sep 17 00:00:00 2001 From: ExEago Date: Thu, 17 Apr 2025 20:04:43 +0200 Subject: [PATCH] Add two methods to compute the height and width of an individual line in a RichTextLabel --- doc/classes/RichTextLabel.xml | 16 +++++++++++++++ scene/gui/rich_text_label.cpp | 38 +++++++++++++++++++++++++++++++++++ scene/gui/rich_text_label.h | 3 +++ 3 files changed, 57 insertions(+) diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 2786879d352..0665c9e62ca 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -106,6 +106,14 @@ [b]Note:[/b] If [member threaded] is enabled, this method returns a value for the loaded part of the document. Use [method is_finished] or [signal finished] to determine whether document is fully loaded. + + + + + Returns the height of the line found at the provided index. + [b]Note:[/b] If [member threaded] is enabled, this method returns a value for the loaded part of the document. Use [method is_finished] or [signal finished] to determine whether the document is fully loaded. + + @@ -123,6 +131,14 @@ [b]Note:[/b] If [member threaded] is enabled, this method returns a value for the loaded part of the document. Use [method is_finished] or [signal finished] to determine whether document is fully loaded. + + + + + Returns the width of the line found at the provided index. + [b]Note:[/b] If [member threaded] is enabled, this method returns a value for the loaded part of the document. Use [method is_finished] or [signal finished] to determine whether the document is fully loaded. + + diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index a195435d827..f832bc9564f 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -7085,6 +7085,41 @@ int RichTextLabel::get_content_width() const { return total_width; } +int RichTextLabel::get_line_height(int p_line) const { + const_cast(this)->_validate_line_caches(); + + int line_count = 0; + int to_line = main->first_invalid_line.load(); + for (int i = 0; i < to_line; i++) { + MutexLock lock(main->lines[i].text_buf->get_mutex()); + int lc = main->lines[i].text_buf->get_line_count(); + + if (p_line < line_count + lc) { + const Ref text_buf = main->lines[i].text_buf; + return text_buf->get_line_ascent(p_line - line_count) + text_buf->get_line_descent(p_line - line_count) + theme_cache.line_separation; + } + line_count += lc; + } + return 0; +} + +int RichTextLabel::get_line_width(int p_line) const { + const_cast(this)->_validate_line_caches(); + + int line_count = 0; + int to_line = main->first_invalid_line.load(); + for (int i = 0; i < to_line; i++) { + MutexLock lock(main->lines[i].text_buf->get_mutex()); + int lc = main->lines[i].text_buf->get_line_count(); + + if (p_line < line_count + lc) { + return main->lines[i].text_buf->get_line_width(p_line - line_count); + } + line_count += lc; + } + return 0; +} + #ifndef DISABLE_DEPRECATED // People will be very angry, if their texts get erased, because of #39148. (3.x -> 4.0) // Although some people may not used bbcode_text, so we only overwrite, if bbcode_text is not empty. @@ -7256,6 +7291,9 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("get_content_height"), &RichTextLabel::get_content_height); ClassDB::bind_method(D_METHOD("get_content_width"), &RichTextLabel::get_content_width); + ClassDB::bind_method(D_METHOD("get_line_height", "line"), &RichTextLabel::get_line_height); + ClassDB::bind_method(D_METHOD("get_line_width", "line"), &RichTextLabel::get_line_width); + ClassDB::bind_method(D_METHOD("get_line_offset", "line"), &RichTextLabel::get_line_offset); ClassDB::bind_method(D_METHOD("get_paragraph_offset", "paragraph"), &RichTextLabel::get_paragraph_offset); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 6dc6916c15c..b66767c6de4 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -849,6 +849,9 @@ public: int get_content_height() const; int get_content_width() const; + int get_line_height(int p_line) const; + int get_line_width(int p_line) const; + void scroll_to_selection(); VScrollBar *get_v_scroll_bar() { return vscroll; }