Repository: godotengine/godot (language: cpp)

Issue:
RichTextLabel `get_visible_line_count()` does not work with `visible_characters` anymore
### Godot version

4.0.2

### System information

Windows 10 x64

### Issue description

`get_visible_line_count()` used to take `visible_characters` into account, but now the value seems ignored. Visible line count returns the value as if all characters were visible (although it returns 0 for 0).

### Steps to reproduce

1. Add RichTextLabel
2. Put multiline text
3. Set `visible_characters` to 1
4. Attach this script
```GDScript
extends RichTextLabel

func _process(delta: float) -> void:
	print(get_visible_line_count())
```
5. Notice it doesn't print 1

### Minimal reproduction project

N/A
RichTextLabel `get_visible_line_count()` does not work with `visible_characters` anymore
### Godot version

4.0.2

### System information

Windows 10 x64

### Issue description

`get_visible_line_count()` used to take `visible_characters` into account, but now the value seems ignored. Visible line count returns the value as if all characters were visible (although it returns 0 for 0).

### Steps to reproduce

1. Add RichTextLabel
2. Put multiline text
3. Set `visible_characters` to 1
4. Attach this script
```GDScript
extends RichTextLabel

func _process(delta: float) -> void:
	print(get_visible_line_count())
```
5. Notice it doesn't print 1

### Minimal reproduction project

N/A


Discussion / hints:
I managed to fix the issue in my project by changing `visible_characters_behavior` to Characters Before Shaping (idk why I had it changed, probably to fix some other issue). However I can't reproduce the fix in a minimal project xd The above code still yields broken behavior. What's more, if you set `visible_characters` to 1, nothing will be displayed (it's as if visible characters begin with the set value - 1). It works if you set it in `_process()`, but visible line count is still wrong.
Still seems reproducible in 4.1 beta 3.
I tried to fix this but I can't figure it out. The culprit lies here, as the counter goes up regardless of how many lines are actually visible (they do need to be processed anyway, to get the right offsets):
https://github.com/godotengine/godot/blob/f28964805e44a5c068ce8fd9d1e00697fcd922dc/scene/gui/rich_text_label.cpp#L1974
https://github.com/godotengine/godot/blob/f28964805e44a5c068ce8fd9d1e00697fcd922dc/scene/gui/rich_text_label.cpp#L865

But yeah...
I managed to fix the issue in my project by changing `visible_characters_behavior` to Characters Before Shaping (idk why I had it changed, probably to fix some other issue). However I can't reproduce the fix in a minimal project xd The above code still yields broken behavior. What's more, if you set `visible_characters` to 1, nothing will be displayed (it's as if visible characters begin with the set value - 1). It works if you set it in `_process()`, but visible line count is still wrong.
Still seems reproducible in 4.1 beta 3.
I tried to fix this but I can't figure it out. The culprit lies here, as the counter goes up regardless of how many lines are actually visible (they do need to be processed anyway, to get the right offsets):
https://github.com/godotengine/godot/blob/f28964805e44a5c068ce8fd9d1e00697fcd922dc/scene/gui/rich_text_label.cpp#L1974
https://github.com/godotengine/godot/blob/f28964805e44a5c068ce8fd9d1e00697fcd922dc/scene/gui/rich_text_label.cpp#L865

But yeah...

Fix patch:
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index ad850b574c38..8f0add25eacd 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -820,6 +820,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
 	}
 
 	int line_count = 0;
+	bool has_visible_chars = false;
 	// Bottom margin for text clipping.
 	float v_limit = theme_cache.normal_style->get_margin(SIDE_BOTTOM);
 	Size2 ctrl_size = get_size();
@@ -843,8 +844,6 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
 		float length = l.text_buf->get_line_size(line).x;
 
 		// Draw line.
-		line_count++;
-
 		if (rtl) {
 			off.x = p_width - l.offset.x - width;
 			if (!lrtl && p_frame == main) { // Skip Scrollbar.
@@ -1290,6 +1289,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
 						bool skip = (trim_chars && l.char_offset + glyphs[i].end > visible_characters) || (trim_glyphs_ltr && (processed_glyphs_step >= visible_glyphs)) || (trim_glyphs_rtl && (processed_glyphs_step < total_glyphs - visible_glyphs));
 						if (!skip) {
 							if (txt_visible) {
+								has_visible_chars = true;
 								if (step == DRAW_STEP_TEXT) {
 									if (frid != RID()) {
 										TS->font_draw_glyph(frid, ci, glyphs[i].font_size, fx_offset + char_off, gl, font_color);
@@ -1410,6 +1410,10 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
 
 		r_processed_glyphs = processed_glyphs_step;
 		off.y += TS->shaped_text_get_descent(rid);
+		if (has_visible_chars) {
+			line_count++;
+			has_visible_chars = false;
+		}
 	}
 
 	return line_count;


Test patch: