Przeglądaj źródła

Merge pull request #103224 from bruvzg/lbl_rounding_errors

[Label] Fix rounding errors with fractional scale.
Thaddeus Crews 5 miesięcy temu
rodzic
commit
c80eb95741
1 zmienionych plików z 61 dodań i 10 usunięć
  1. 61 10
      scene/gui/label.cpp

+ 61 - 10
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 &para : 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++;