### Godot version

v4.2.rc1.official [ad72de508]

### System information

Godot v4.2.rc1 - Windows 10.0.22621 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1660 Ti (NVIDIA; 31.0.15.3742) - Intel(R) Core(TM) i7-10700F CPU @ 2.90GHz (16 Threads)

### Issue description

While trying to use a custom effect script as a workaround for the [rainbow bbcode effect](https://github.com/godotengine/godot/issues/85031) at the RichTextLabel I found a bug regarding the `CharFXTransform.relative_index`.
The variable is explained as follows in the [documentation](https://docs.godotengine.org/en/4.0/classes/class_charfxtransform.html#class-charfxtransform-property-relative-index): 
```
The character offset of the glyph, relative to the current RichTextEffect custom block.
```
However, when using the script below, the character index shifts one to the left each time instead of being at the same position for each new effect block.
![grafik](https://github.com/godotengine/godot/assets/71942164/7b1b0557-d515-4d56-a25e-d2a2810b2966)


### Steps to reproduce

Add this script as Custom Effect to the RichTextLabel (or see the MRP):
```@tool
extends RichTextEffect
class_name test

var bbcode = "test"

func _process_custom_fx(char_fx):
	if char_fx.relative_index == 5:
		char_fx.color = Color.BLACK
	pass
```
Add this Text to a Rich TextLabel:
```
[test]0123456789[/test]
[test]0123456789[/test]
[test]0123456789[/test]
[test]0123456789[/test]
[test]0123456789[/test]
[test]0123456789[/test]
``` 

### Minimal reproduction project

[relative_index_issue.zip](https://github.com/godotengine/godot/files/13462368/relative_index_issue.zip)

off.y += TS->shaped_text_get_ascent(rid);
		
		Array objects = TS->shaped_text_get_objects(rid);
		for (int i = 0; i < objects.size(); i++) {
			Item *it = reinterpret_cast<Item *>((uint64_t)objects[i]);
			if (it != nullptr) {
				Rect2 rect = TS->shaped_text_get_object_rect(rid, objects[i]);
				
				switch (it->type) {
					case ITEM_IMAGE: {
						ItemImage *img = static_cast<ItemImage *>(it);
						if (img->pad) {
							Size2 pad_size = Size2(MIN(rect.size.x, img->image->get_width()), MIN(rect.size.y, img->image->get_height()));
							Vector2 pad_off = (rect.size - pad_size) / 2;
							img->image->draw_rect(ci, Rect2(p_ofs + rect.position + off + pad_off, pad_size), false, img->color);
						} else {
							img->image->draw_rect(ci, Rect2(p_ofs + rect.position + off, rect.size), false, img->color);
						}
					} break;
					case ITEM_TABLE: {
						ItemTable *table = static_cast<ItemTable *>(it);
						Color odd_row_bg = theme_cache.table_odd_row_bg;
						Color even_row_bg = theme_cache.table_even_row_bg;
						Color border = theme_cache.table_border;
						int h_separation = theme_cache.table_h_separation;
						int col_count = table->columns.size();
						int row_count = table->rows.size();
						int idx = 0;
						for (Item *E : table->subitems) {