Browse Source

[TextServer] Fix caret hit test rounding.

Pāvels Nadtočajevs 1 week ago
parent
commit
d13b5361b4
4 changed files with 18 additions and 6 deletions
  1. 3 0
      scene/gui/line_edit.cpp
  2. 5 3
      scene/gui/rich_text_label.cpp
  3. 6 0
      scene/gui/text_edit.cpp
  4. 4 3
      servers/text_server.cpp

+ 3 - 0
scene/gui/line_edit.cpp

@@ -1825,6 +1825,9 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) {
 	}
 
 	int ofs = std::ceil(TS->shaped_text_hit_test_position(text_rid, p_x - x_ofs - scroll_offset));
+	if (ofs == -1) {
+		return;
+	}
 	if (!caret_mid_grapheme_enabled) {
 		ofs = TS->shaped_text_closest_character_pos(text_rid, ofs);
 	}

+ 5 - 3
scene/gui/rich_text_label.cpp

@@ -1770,9 +1770,11 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
 						}
 					}
 				} else {
-					char_pos = TS->shaped_text_hit_test_position(rid, p_click.x - rect.position.x);
-					char_pos = TS->shaped_text_closest_character_pos(rid, char_pos);
-					char_clicked = true;
+					int click_char_pos = TS->shaped_text_hit_test_position(rid, p_click.x - rect.position.x);
+					if (click_char_pos != -1) {
+						char_pos = TS->shaped_text_closest_character_pos(rid, click_char_pos);
+						char_clicked = true;
+					}
 				}
 			}
 			line_clicked = true;

+ 6 - 0
scene/gui/text_edit.cpp

@@ -5034,6 +5034,9 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_clamp_line
 	}
 
 	int col = TS->shaped_text_hit_test_position(text_rid, colx);
+	if (col == -1) {
+		return Point2i(-1, -1);
+	}
 	if (!caret_mid_grapheme_enabled) {
 		col = TS->shaped_text_closest_character_pos(text_rid, col);
 	}
@@ -8197,6 +8200,9 @@ int TextEdit::_get_char_pos_for_line(int p_px, int p_line, int p_wrap_index) con
 		p_px -= wrap_indent;
 	}
 	int ofs = TS->shaped_text_hit_test_position(text_rid, p_px);
+	if (ofs == -1) {
+		return 0;
+	}
 	if (!caret_mid_grapheme_enabled) {
 		ofs = TS->shaped_text_closest_character_pos(text_rid, ofs);
 	}

+ 4 - 3
servers/text_server.cpp

@@ -1539,7 +1539,7 @@ int64_t TextServer::shaped_text_hit_test_position(const RID &p_shaped, double p_
 	// Cursor placement hit test.
 
 	// Place caret to the left of the leftmost grapheme, or to position 0 if string is empty.
-	if (p_coords <= 0) {
+	if (Math::floor(p_coords) <= 0) {
 		if (v_size > 0) {
 			if ((glyphs[0].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
 				return glyphs[0].end;
@@ -1552,7 +1552,7 @@ int64_t TextServer::shaped_text_hit_test_position(const RID &p_shaped, double p_
 	}
 
 	// Place caret to the right of the rightmost grapheme, or to position 0 if string is empty.
-	if (p_coords >= shaped_text_get_width(p_shaped)) {
+	if (Math::ceil(p_coords) >= shaped_text_get_width(p_shaped)) {
 		if (v_size > 0) {
 			if ((glyphs[v_size - 1].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
 				return glyphs[v_size - 1].start;
@@ -1622,7 +1622,8 @@ int64_t TextServer::shaped_text_hit_test_position(const RID &p_shaped, double p_
 		}
 		off += glyphs[i].advance * glyphs[i].repeat;
 	}
-	return 0;
+
+	return -1;
 }
 
 Vector2 TextServer::shaped_text_get_grapheme_bounds(const RID &p_shaped, int64_t p_pos) const {