diff --git a/doc/classes/Button.xml b/doc/classes/Button.xml index 68fb918904f..c774667a7db 100644 --- a/doc/classes/Button.xml +++ b/doc/classes/Button.xml @@ -127,6 +127,9 @@ The maximum allowed width of the [Button]'s icon. This limit is applied on top of the default size of the icon, or its expanded size if [member expand_icon] is [code]true[/code]. The height is adjusted according to the icon's ratio. If the button has additional icons (e.g. [CheckBox]), they will also be limited. + + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. + The size of the text outline. [b]Note:[/b] If using a font with [member FontFile.multichannel_signed_distance_field] enabled, its [member FontFile.msdf_pixel_range] must be set to at least [i]twice[/i] the value of [theme_item outline_size] for outline rendering to look correct. Otherwise, the outline may appear to be cut off earlier than intended. diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml index f91006f69a0..ae5a62753f1 100644 --- a/doc/classes/Label.xml +++ b/doc/classes/Label.xml @@ -122,7 +122,7 @@ [Color] of the text's shadow effect. - Vertical space between lines in multiline [Label]. + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. Text outline size. diff --git a/doc/classes/Label3D.xml b/doc/classes/Label3D.xml index ff26c5490dd..7584a1d526b 100644 --- a/doc/classes/Label3D.xml +++ b/doc/classes/Label3D.xml @@ -79,7 +79,7 @@ Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead. - Vertical space between lines in multiline [Label3D]. + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. Text [Color] of the [Label3D]. diff --git a/doc/classes/LabelSettings.xml b/doc/classes/LabelSettings.xml index 8cdb30c3036..ff7b8e7b0e4 100644 --- a/doc/classes/LabelSettings.xml +++ b/doc/classes/LabelSettings.xml @@ -19,7 +19,7 @@ Size of the text. - Vertical space between lines when the text is multiline. + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. The color of the outline. diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 4a2cbbc3d8e..2ac346b5c2f 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -810,7 +810,7 @@ The default background color for odd rows. - The vertical space between lines. + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. The size of the text outline. diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index 42558bf9929..7a4bef57479 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -1624,7 +1624,7 @@ The caret's width in pixels. Greater values can be used to improve accessibility by ensuring the caret is easily visible, or to ensure consistency with a large font size. If set to [code]0[/code] or lower, the caret width is automatically set to 1 pixel and multiplied by the display scaling factor. - Sets the spacing between the lines. + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. The size of the text outline. diff --git a/doc/classes/TextMesh.xml b/doc/classes/TextMesh.xml index 898d19aed39..b6b1052af5f 100644 --- a/doc/classes/TextMesh.xml +++ b/doc/classes/TextMesh.xml @@ -37,7 +37,7 @@ Language code used for text shaping algorithms, if left empty current locale is used instead. - Vertical space between lines in multiline [TextMesh]. + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. The text drawing offset (in pixels). diff --git a/doc/classes/TextParagraph.xml b/doc/classes/TextParagraph.xml index 46197f19b88..c9ac660b8c4 100644 --- a/doc/classes/TextParagraph.xml +++ b/doc/classes/TextParagraph.xml @@ -280,6 +280,9 @@ Line fill alignment rules. See [enum TextServer.JustificationFlag] for more information. + + Additional vertical spacing between lines (in pixels), spacing is added to line descent. This value can be negative. + Limits the lines of text shown. diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index 4bd85cbde99..3e593a83720 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -561,6 +561,7 @@ void Button::_shape(Ref p_paragraph, String p_text) { } autowrap_flags = autowrap_flags | TextServer::BREAK_TRIM_EDGE_SPACES; p_paragraph->set_break_flags(autowrap_flags); + p_paragraph->set_line_spacing(theme_cache.line_spacing); if (text_direction == Control::TEXT_DIRECTION_INHERITED) { p_paragraph->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR); @@ -833,6 +834,7 @@ void Button::_bind_methods() { BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, icon_max_width); BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, align_to_largest_stylebox); + BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Button, line_spacing); } Button::Button(const String &p_text) { diff --git a/scene/gui/button.h b/scene/gui/button.h index b86d6a6c1fa..686d4806dbc 100644 --- a/scene/gui/button.h +++ b/scene/gui/button.h @@ -100,6 +100,7 @@ private: int h_separation = 0; int icon_max_width = 0; + int line_spacing = 0; } theme_cache; void _shape(Ref p_paragraph = Ref(), String p_text = ""); diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp index f8fd51e26a3..65c6e40241c 100644 --- a/scene/resources/text_paragraph.cpp +++ b/scene/resources/text_paragraph.cpp @@ -112,6 +112,11 @@ void TextParagraph::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "max_lines_visible"), "set_max_lines_visible", "get_max_lines_visible"); + ClassDB::bind_method(D_METHOD("set_line_spacing", "line_spacing"), &TextParagraph::set_line_spacing); + ClassDB::bind_method(D_METHOD("get_line_spacing"), &TextParagraph::get_line_spacing); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing"), "set_line_spacing", "get_line_spacing"); + ClassDB::bind_method(D_METHOD("get_line_objects", "line"), &TextParagraph::get_line_objects); ClassDB::bind_method(D_METHOD("get_line_object_rect", "line", "key"), &TextParagraph::get_line_object_rect); ClassDB::bind_method(D_METHOD("get_line_size", "line"), &TextParagraph::get_line_size); @@ -180,6 +185,7 @@ void TextParagraph::_shape_lines() { for (int i = 0; i < line_breaks.size(); i = i + 2) { RID line = TS->shaped_text_substr(rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]); float h = (TS->shaped_text_get_orientation(line) == TextServer::ORIENTATION_HORIZONTAL) ? TS->shaped_text_get_size(line).y : TS->shaped_text_get_size(line).x; + h += line_spacing; if (!tab_stops.is_empty()) { TS->shaped_text_tab_align(line, tab_stops); } @@ -574,12 +580,18 @@ Size2 TextParagraph::get_size() const { } size.x = MAX(size.x, lsize.x); size.y += lsize.y; + if (i != visible_lines - 1) { + size.y += line_spacing; + } } else { if (h_offset > 0 && i <= dropcap_lines) { lsize.y += h_offset; } size.x += lsize.x; size.y = MAX(size.y, lsize.y); + if (i != visible_lines - 1) { + size.x += line_spacing; + } } } if (h_offset > 0) { @@ -612,6 +624,19 @@ int TextParagraph::get_max_lines_visible() const { return max_lines_visible; } +void TextParagraph::set_line_spacing(float p_spacing) { + _THREAD_SAFE_METHOD_ + + if (line_spacing != p_spacing) { + line_spacing = p_spacing; + lines_dirty = true; + } +} + +float TextParagraph::get_line_spacing() const { + return line_spacing; +} + Array TextParagraph::get_line_objects(int p_line) const { _THREAD_SAFE_METHOD_ @@ -697,10 +722,10 @@ Rect2 TextParagraph::get_line_object_rect(int p_line, Variant p_key) const { if (i != p_line) { if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) { ofs.x = 0.f; - ofs.y += TS->shaped_text_get_descent(lines_rid[i]); + ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } else { ofs.y = 0.f; - ofs.x += TS->shaped_text_get_descent(lines_rid[i]); + ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } } } @@ -872,10 +897,10 @@ void TextParagraph::draw(RID p_canvas, const Vector2 &p_pos, const Color &p_colo TS->shaped_text_draw(lines_rid[i], p_canvas, ofs, clip_l, clip_l + l_width, p_color); if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) { ofs.x = p_pos.x; - ofs.y += TS->shaped_text_get_descent(lines_rid[i]); + ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } else { ofs.y = p_pos.y; - ofs.x += TS->shaped_text_get_descent(lines_rid[i]); + ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } } } @@ -974,10 +999,10 @@ void TextParagraph::draw_outline(RID p_canvas, const Vector2 &p_pos, int p_outli TS->shaped_text_draw_outline(lines_rid[i], p_canvas, ofs, clip_l, clip_l + l_width, p_outline_size, p_color); if (TS->shaped_text_get_orientation(lines_rid[i]) == TextServer::ORIENTATION_HORIZONTAL) { ofs.x = p_pos.x; - ofs.y += TS->shaped_text_get_descent(lines_rid[i]); + ofs.y += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } else { ofs.y = p_pos.y; - ofs.x += TS->shaped_text_get_descent(lines_rid[i]); + ofs.x += TS->shaped_text_get_descent(lines_rid[i]) + line_spacing; } } } @@ -1001,12 +1026,12 @@ int TextParagraph::hit_test(const Point2 &p_coords) const { if ((p_coords.y >= ofs.y) && (p_coords.y <= ofs.y + TS->shaped_text_get_size(line_rid).y)) { return TS->shaped_text_hit_test_position(line_rid, p_coords.x); } - ofs.y += TS->shaped_text_get_size(line_rid).y; + ofs.y += TS->shaped_text_get_size(line_rid).y + line_spacing; } else { if ((p_coords.x >= ofs.x) && (p_coords.x <= ofs.x + TS->shaped_text_get_size(line_rid).x)) { return TS->shaped_text_hit_test_position(line_rid, p_coords.y); } - ofs.y += TS->shaped_text_get_size(line_rid).x; + ofs.y += TS->shaped_text_get_size(line_rid).x + line_spacing; } } return TS->shaped_text_get_range(rid).y; diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h index b083c8fe68c..966ce556d54 100644 --- a/scene/resources/text_paragraph.h +++ b/scene/resources/text_paragraph.h @@ -51,6 +51,7 @@ private: bool lines_dirty = true; + float line_spacing = 0.0; float width = -1.0; int max_lines_visible = -1; @@ -122,6 +123,9 @@ public: void set_max_lines_visible(int p_lines); int get_max_lines_visible() const; + void set_line_spacing(float p_spacing); + float get_line_spacing() const; + Size2 get_non_wrapped_size() const; Size2 get_size() const;