From 8016c5399f4bd7179b0866d3b1ec15a3dfaaca44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Sun, 23 Feb 2025 17:59:14 +0200 Subject: [PATCH] [Label] Fix rounding errors with fractional scale. --- scene/gui/label.cpp | 71 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 4c8bca487bd..9a9d09cac2d 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -91,7 +91,15 @@ int Label::get_line_height(int p_line) const { int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size; int font_h = font->get_height(font_size); if (p_line >= 0 && p_line < total_line_count) { - return MAX(font_h, TS->shaped_text_get_size(get_line_rid(p_line)).y); + RID rid = get_line_rid(p_line); + double asc = TS->shaped_text_get_ascent(rid); + double dsc = TS->shaped_text_get_descent(rid); + if (asc + dsc < font_h) { + double diff = font_h - (asc + dsc); + asc += diff / 2; + dsc += diff - (diff / 2); + } + return asc + dsc; } else if (total_line_count > 0) { int h = font_h; for (const Paragraph ¶ : paragraphs) { @@ -357,7 +365,14 @@ void Label::_update_visible() const { break; } for (int i = start; i < end; i++) { - minsize.height += MAX(font_h, TS->shaped_text_get_size(para.lines_rid[i]).y) + line_spacing; + double asc = TS->shaped_text_get_ascent(para.lines_rid[i]); + double dsc = TS->shaped_text_get_descent(para.lines_rid[i]); + if (asc + dsc < font_h) { + double diff = font_h - (asc + dsc); + asc += diff / 2; + dsc += diff - (diff / 2); + } + minsize.height += asc + dsc + line_spacing; } minsize.height += paragraph_spacing; line_index += para.lines_rid.size(); @@ -454,8 +469,16 @@ Rect2 Label::_get_line_rect(int p_para, int p_line) const { int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size; int font_h = font->get_height(font_size); Size2 size = get_size(); - Size2 line_size = TS->shaped_text_get_size(paragraphs[p_para].lines_rid[p_line]); - line_size.y = MAX(font_h, line_size.y); + RID rid = paragraphs[p_para].lines_rid[p_line]; + Size2 line_size = TS->shaped_text_get_size(rid); + double asc = TS->shaped_text_get_ascent(rid); + double dsc = TS->shaped_text_get_descent(rid); + if (asc + dsc < font_h) { + double diff = font_h - (asc + dsc); + asc += diff / 2; + dsc += diff - (diff / 2); + } + line_size.y = asc + dsc; Vector2 offset; switch (horizontal_alignment) { case HORIZONTAL_ALIGNMENT_FILL: @@ -508,8 +531,15 @@ int Label::get_layout_data(Vector2 &r_offset, int &r_last_line, int &r_line_spac } else { int start = (line_index < lines_skipped) ? lines_skipped - line_index : 0; for (int i = start; i < para.lines_rid.size(); i++) { - total_h += MAX(font_h, TS->shaped_text_get_size(para.lines_rid[i]).y) + line_spacing; - if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) { + double asc = TS->shaped_text_get_ascent(para.lines_rid[i]); + double dsc = TS->shaped_text_get_descent(para.lines_rid[i]); + if (asc + dsc < font_h) { + double diff = font_h - (asc + dsc); + asc += diff / 2; + dsc += diff - (diff / 2); + } + total_h += asc + dsc + line_spacing; + if (total_h > Math::ceil(get_size().height - style->get_minimum_size().height + line_spacing)) { break; } lines_visible++; @@ -539,7 +569,14 @@ int Label::get_layout_data(Vector2 &r_offset, int &r_last_line, int &r_line_spac break; } for (int i = start; i < end; i++) { - total_h += MAX(font_h, TS->shaped_text_get_size(para.lines_rid[i]).y) + line_spacing; + double asc = TS->shaped_text_get_ascent(para.lines_rid[i]); + double dsc = TS->shaped_text_get_descent(para.lines_rid[i]); + if (asc + dsc < font_h) { + double diff = font_h - (asc + dsc); + asc += diff / 2; + dsc += diff - (diff / 2); + } + total_h += asc + dsc + line_spacing; total_glyphs += TS->shaped_text_get_glyph_count(para.lines_rid[i]) + TS->shaped_text_get_ellipsis_glyph_count(para.lines_rid[i]); } total_h += paragraph_spacing; @@ -879,7 +916,14 @@ Rect2 Label::get_character_bounds(int p_pos) const { } gl_off += glyphs[j].advance * glyphs[j].repeat; } - ofs.y += MAX(font_h, TS->shaped_text_get_ascent(line_rid) + TS->shaped_text_get_descent(line_rid)) + line_spacing; + double asc = TS->shaped_text_get_ascent(line_rid); + double dsc = TS->shaped_text_get_descent(line_rid); + if (asc + dsc < font_h) { + double diff = font_h - (asc + dsc); + asc += diff / 2; + dsc += diff - (diff / 2); + } + ofs.y += asc + dsc + line_spacing; } ofs.y += paragraph_spacing; line_index += para.lines_rid.size(); @@ -948,8 +992,15 @@ int Label::get_visible_line_count() const { } else { int start = (line_index < lines_skipped) ? lines_skipped - line_index : 0; for (int i = start; i < para.lines_rid.size(); i++) { - total_h += MAX(font_h, TS->shaped_text_get_size(para.lines_rid[i]).y) + line_spacing; - if (total_h > (get_size().height - style->get_minimum_size().height + line_spacing)) { + double asc = TS->shaped_text_get_ascent(para.lines_rid[i]); + double dsc = TS->shaped_text_get_descent(para.lines_rid[i]); + if (asc + dsc < font_h) { + double diff = font_h - (asc + dsc); + asc += diff / 2; + dsc += diff - (diff / 2); + } + total_h += asc + dsc + line_spacing; + if (total_h > Math::ceil(get_size().height - style->get_minimum_size().height + line_spacing)) { break; } lines_visible++;