1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-09 12:50:35 +00:00

[RTL] Add paragraph separation theme property.

This commit is contained in:
Pāvels Nadtočajevs
2025-06-09 18:58:48 +03:00
parent fc523ec5f6
commit 1e2fc9bcad
5 changed files with 23 additions and 12 deletions

View File

@@ -882,6 +882,9 @@
The size of the text outline. 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. [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.
</theme_item> </theme_item>
<theme_item name="paragraph_separation" data_type="constant" type="int" default="0">
Additional vertical spacing between paragraphs (in pixels). Spacing is added after the last line. This value can be negative.
</theme_item>
<theme_item name="shadow_offset_x" data_type="constant" type="int" default="1"> <theme_item name="shadow_offset_x" data_type="constant" type="int" default="1">
The horizontal offset of the font's shadow. The horizontal offset of the font's shadow.
</theme_item> </theme_item>

View File

@@ -762,7 +762,7 @@ void RichTextLabel::_set_table_size(ItemTable *p_table, int p_available_width) {
float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * theme_cache.line_separation; float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * theme_cache.line_separation;
if (i > 0) { if (i > 0) {
h += theme_cache.line_separation; h += theme_cache.paragraph_separation;
} }
if (frame->min_size_over.y > 0) { if (frame->min_size_over.y > 0) {
h = MAX(h, frame->min_size_over.y); h = MAX(h, frame->min_size_over.y);
@@ -771,7 +771,7 @@ void RichTextLabel::_set_table_size(ItemTable *p_table, int p_available_width) {
h = MIN(h, frame->max_size_over.y); h = MIN(h, frame->max_size_over.y);
} }
yofs += h; yofs += h;
prev_h = frame->lines[i].offset.y + frame->lines[i].text_buf->get_size().y + frame->lines[i].text_buf->get_line_count() * theme_cache.line_separation; prev_h = frame->lines[i].offset.y + frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * theme_cache.line_separation + theme_cache.paragraph_separation;
frame->lines[i].offset += offset; frame->lines[i].offset += offset;
row_baseline = MAX(row_baseline, frame->lines[i].text_buf->get_line_ascent(frame->lines[i].text_buf->get_line_count() - 1)); row_baseline = MAX(row_baseline, frame->lines[i].text_buf->get_line_ascent(frame->lines[i].text_buf->get_line_count() - 1));
@@ -1513,7 +1513,7 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
// Do not apply to the last line to avoid cutting text. // Do not apply to the last line to avoid cutting text.
total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + (main->lines[to_line - 1].text_buf->get_line_count() - 1) * theme_cache.line_separation; total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + (main->lines[to_line - 1].text_buf->get_line_count() - 1) * theme_cache.line_separation;
} else { } else {
total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + main->lines[to_line - 1].text_buf->get_line_count() * theme_cache.line_separation; total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + (main->lines[to_line - 1].text_buf->get_line_count() - 1) * theme_cache.line_separation + theme_cache.paragraph_separation;
} }
} }
float vbegin = 0, vsep = 0; float vbegin = 0, vsep = 0;
@@ -1545,7 +1545,7 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
while (ofs.y < size.height && from_line < to_line) { while (ofs.y < size.height && from_line < to_line) {
MutexLock lock(main->lines[from_line].text_buf->get_mutex()); MutexLock lock(main->lines[from_line].text_buf->get_mutex());
_find_click_in_line(p_frame, from_line, ofs, text_rect.size.x, vsep, p_click, r_click_frame, r_click_line, r_click_item, r_click_char, false, p_meta); _find_click_in_line(p_frame, from_line, ofs, text_rect.size.x, vsep, p_click, r_click_frame, r_click_line, r_click_item, r_click_char, false, p_meta);
ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * (theme_cache.line_separation + vsep); ofs.y += main->lines[from_line].text_buf->get_size().y + (main->lines[from_line].text_buf->get_line_count() - 1) * (theme_cache.line_separation + vsep) + (theme_cache.paragraph_separation + vsep);
if (((r_click_item != nullptr) && ((*r_click_item) != nullptr)) || ((r_click_frame != nullptr) && ((*r_click_frame) != nullptr))) { if (((r_click_item != nullptr) && ((*r_click_item) != nullptr)) || ((r_click_frame != nullptr) && ((*r_click_frame) != nullptr))) {
if (r_outside != nullptr) { if (r_outside != nullptr) {
*r_outside = false; *r_outside = false;
@@ -1762,7 +1762,11 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
return table_offy; return table_offy;
} }
off.y += TS->shaped_text_get_descent(rid) + theme_cache.line_separation + p_vsep; if (line == l.text_buf->get_line_count() - 1) {
off.y += TS->shaped_text_get_descent(rid) + theme_cache.paragraph_separation + p_vsep;
} else {
off.y += TS->shaped_text_get_descent(rid) + theme_cache.line_separation + p_vsep;
}
} }
// Text line hit. // Text line hit.
@@ -1891,7 +1895,7 @@ int RichTextLabel::_find_first_line(int p_from, int p_to, int p_vofs) const {
} }
_FORCE_INLINE_ float RichTextLabel::_calculate_line_vertical_offset(const RichTextLabel::Line &line) const { _FORCE_INLINE_ float RichTextLabel::_calculate_line_vertical_offset(const RichTextLabel::Line &line) const {
return line.get_height(theme_cache.line_separation); return line.get_height(theme_cache.line_separation, theme_cache.paragraph_separation);
} }
void RichTextLabel::_update_theme_item_cache() { void RichTextLabel::_update_theme_item_cache() {
@@ -2287,7 +2291,7 @@ void RichTextLabel::_notification(int p_what) {
// Do not apply to the last line to avoid cutting text. // Do not apply to the last line to avoid cutting text.
total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + (main->lines[to_line - 1].text_buf->get_line_count() - 1) * theme_cache.line_separation; total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + (main->lines[to_line - 1].text_buf->get_line_count() - 1) * theme_cache.line_separation;
} else { } else {
total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + main->lines[to_line - 1].text_buf->get_line_count() * theme_cache.line_separation; total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + (main->lines[to_line - 1].text_buf->get_line_count() - 1) * theme_cache.line_separation + theme_cache.paragraph_separation;
} }
} }
float vbegin = 0, vsep = 0; float vbegin = 0, vsep = 0;
@@ -2450,7 +2454,7 @@ void RichTextLabel::_notification(int p_what) {
// Do not apply to the last line to avoid cutting text. // Do not apply to the last line to avoid cutting text.
total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + (main->lines[to_line - 1].text_buf->get_line_count() - 1) * theme_cache.line_separation; total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + (main->lines[to_line - 1].text_buf->get_line_count() - 1) * theme_cache.line_separation;
} else { } else {
total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + main->lines[to_line - 1].text_buf->get_line_count() * theme_cache.line_separation; total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + (main->lines[to_line - 1].text_buf->get_line_count() - 1) * theme_cache.line_separation + theme_cache.paragraph_separation;
} }
} }
float vbegin = 0, vsep = 0; float vbegin = 0, vsep = 0;
@@ -2494,7 +2498,7 @@ void RichTextLabel::_notification(int p_what) {
if (drawn_lines > 0) { if (drawn_lines > 0) {
visible_paragraph_count++; visible_paragraph_count++;
} }
ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * (theme_cache.line_separation + vsep); ofs.y += main->lines[from_line].text_buf->get_size().y + (main->lines[from_line].text_buf->get_line_count() - 1) * (theme_cache.line_separation + vsep) + (theme_cache.paragraph_separation + vsep);
from_line++; from_line++;
} }
if (has_focus() && get_tree()->is_accessibility_enabled()) { if (has_focus() && get_tree()->is_accessibility_enabled()) {
@@ -7129,7 +7133,7 @@ int RichTextLabel::get_content_height() const {
// Do not apply to the last line to avoid cutting text. // Do not apply to the last line to avoid cutting text.
total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + (main->lines[to_line - 1].text_buf->get_line_count() - 1) * theme_cache.line_separation; total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + (main->lines[to_line - 1].text_buf->get_line_count() - 1) * theme_cache.line_separation;
} else { } else {
total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + main->lines[to_line - 1].text_buf->get_line_count() * theme_cache.line_separation; total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + (main->lines[to_line - 1].text_buf->get_line_count() - 1) * theme_cache.line_separation + theme_cache.paragraph_separation;
} }
} }
return total_height; return total_height;
@@ -7448,6 +7452,7 @@ void RichTextLabel::_bind_methods() {
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, RichTextLabel, progress_fg_style, "fill", "ProgressBar"); BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, RichTextLabel, progress_fg_style, "fill", "ProgressBar");
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, line_separation); BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, line_separation);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, paragraph_separation);
BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, RichTextLabel, normal_font); BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, RichTextLabel, normal_font);
BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, RichTextLabel, normal_font_size); BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, RichTextLabel, normal_font_size);

View File

@@ -181,8 +181,8 @@ private:
} }
} }
_FORCE_INLINE_ float get_height(float line_separation) const { _FORCE_INLINE_ float get_height(float p_line_separation, float p_paragraph_separation) const {
return offset.y + text_buf->get_size().y + text_buf->get_line_count() * line_separation; return offset.y + text_buf->get_size().y + (text_buf->get_line_count() - 1) * p_line_separation + p_paragraph_separation;
} }
}; };
@@ -717,6 +717,7 @@ private:
Ref<StyleBox> progress_fg_style; Ref<StyleBox> progress_fg_style;
int line_separation; int line_separation;
int paragraph_separation;
Ref<Font> normal_font; Ref<Font> normal_font;
int normal_font_size; int normal_font_size;

View File

@@ -69,6 +69,7 @@ public:
const StringName updated = "updated"; const StringName updated = "updated";
const StringName line_separation = "line_separation"; const StringName line_separation = "line_separation";
const StringName paragraph_separation = "paragraph_separation";
const StringName font = "font"; const StringName font = "font";
const StringName font_size = "font_size"; const StringName font_size = "font_size";
const StringName font_color = "font_color"; const StringName font_color = "font_color";

View File

@@ -1178,6 +1178,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_constant("shadow_outline_size", "RichTextLabel", Math::round(1 * scale)); theme->set_constant("shadow_outline_size", "RichTextLabel", Math::round(1 * scale));
theme->set_constant(SceneStringName(line_separation), "RichTextLabel", 0); theme->set_constant(SceneStringName(line_separation), "RichTextLabel", 0);
theme->set_constant(SceneStringName(paragraph_separation), "RichTextLabel", 0);
theme->set_constant("table_h_separation", "RichTextLabel", Math::round(3 * scale)); theme->set_constant("table_h_separation", "RichTextLabel", Math::round(3 * scale));
theme->set_constant("table_v_separation", "RichTextLabel", Math::round(3 * scale)); theme->set_constant("table_v_separation", "RichTextLabel", Math::round(3 * scale));