Repository: godotengine/godot (language: cpp)

Issue:
RichTextLabel table with padding and BBCode enabled cause misalignment
### Tested versions

v4.5.dev.custom_build.6b4fda04c

### System information

Godot v4.5.dev (6b4fda04c) - Ubuntu 22.04.5 LTS 22.04 - X11 display driver, Multi-window, 1 monitor - OpenGL 3 (Compatibility) - D3D12 (AMD Radeon(TM) Graphics) - AMD Ryzen 5 5600H with Radeon Graphics (12 threads)

### Issue description

When using a RichTextLabel with BBCode enabled, tables with padding display incorrect horizontal and vertical alignment. This issue only occurs when BBCode is enabled.
I would like to fix this bug as my first contribution to Godot. I'm already investigating the offset calculation in the relevant functions and would appreciate any guidance from the maintainers on the correct approach.

https://github.com/user-attachments/assets/b1a6895c-f446-4fa2-b885-6757e4ca36d9

### Steps to reproduce

1.Create a RichTextLabel node
2.Enable BBCode (set bbcode_enabled = true)
3.Set text content with a table that includes padding, for example:
```
[table=1]
[cell bg=black padding=20,20,20,20]Lorem ipsum dolor sit amet, consectetur adipiscing elit.[/cell]
[/table]
```


### Minimal reproduction project (MRP)

[padding-misalignment.zip](https://github.com/user-attachments/files/19135134/padding-misalignment.zip)


Discussion / hints:

Fix patch:
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 19d59e53c99f..d3648c9faf02 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -685,6 +685,7 @@ void RichTextLabel::_set_table_size(ItemTable *p_table, int p_available_width) {
 		} else {
 			p_table->total_width += p_table->columns[i].width;
 		}
+		p_table->columns[i].width_with_padding = p_table->columns[i].width;
 	}
 
 	// Resize to max_width if needed and distribute the remaining space.
@@ -702,6 +703,7 @@ void RichTextLabel::_set_table_size(ItemTable *p_table, int p_available_width) {
 				p_table->columns[i].width = p_table->columns[i].max_width;
 				p_table->total_width -= dif;
 				total_ratio -= p_table->columns[i].expand_ratio;
+				p_table->columns[i].width_with_padding = p_table->columns[i].width;
 			}
 		}
 		// Grow.
@@ -715,6 +717,7 @@ void RichTextLabel::_set_table_size(ItemTable *p_table, int p_available_width) {
 						int incr = MIN(dif, slice);
 						p_table->columns[i].width += incr;
 						p_table->total_width += incr;
+						p_table->columns[i].width_with_padding = p_table->columns[i].width;
 					}
 				}
 			}
@@ -745,6 +748,7 @@ void RichTextLabel::_set_table_size(ItemTable *p_table, int p_available_width) {
 
 			frame->lines[i].text_buf->set_width(p_table->columns[column].width);
 			p_table->columns[column].width = MAX(p_table->columns[column].width, ceil(frame->lines[i].text_buf->get_size().x));
+			p_table->columns[column].width_with_padding = MAX(p_table->columns[column].width_with_padding, ceil(frame->lines[i].text_buf->get_size().x + frame->padding.position.x + frame->padding.size.x));
 
 			frame->lines[i].offset.y = prev_h;
 
@@ -780,6 +784,12 @@ void RichTextLabel::_set_table_size(ItemTable *p_table, int p_available_width) {
 		}
 		idx++;
 	}
+
+	// Recalculate total width.
+	p_table->total_width = 0;
+	for (int i = 0; i < col_count; i++) {
+		p_table->total_width += p_table->columns[i].width_with_padding + theme_cache.table_h_separation;
+	}
 }
 
 int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_ofs, int p_width, float p_vsep, const Color &p_base_color, int p_outline_size, const Color &p_outline_color, const Color &p_font_shadow_color, int p_shadow_outline_size, const Point2 &p_shadow_ofs, int &r_processed_glyphs) {
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 013ee15c03fe..dd1cedcd8bb5 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -347,6 +347,7 @@ class RichTextLabel : public Control {
 			int min_width = 0;
 			int max_width = 0;
 			int width = 0;
+			int width_with_padding = 0;
 		};
 
 		LocalVector<Column> columns;


Test patch: