Repository: godotengine/godot (language: cpp)

Issue:
Font color is applied to coloured emoji
### Tested versions

- Reproducible in: v4.4.1.stable.official [49a5bc7b6]
- Not reproducible in: v4.4.stable.official [4c311cbee]

### System information

Godot v4.4.1.stable - Debian GNU/Linux trixie/sid trixie on Wayland - X11 display driver, Multi-window, 2 monitors - Vulkan (Forward+) - dedicated AMD Radeon RX 7600 (RADV NAVI33) - AMD Ryzen 5 7600 6-Core Processor (12 threads)

### Issue description

Under 4.4.1, (Noto Color) emojis are affected by a control's font color, even when that emoji already has its own colours:

![Image](https://github.com/user-attachments/assets/4284981c-8af2-4936-9ff1-6da0bfc234a3)

This was not the case in 4.4:

![Image](https://github.com/user-attachments/assets/afdfdaa1-fdf8-4e36-831e-fa4fb2e11449)


### Steps to reproduce

1. Create a `Label`, `LineEdit`, or `Button`
2. Assign Noto Color Emoji as the font (via `LabelSettings` or theme override)
3. Set the visible text to include a coloured emoji
4. Change the font color (via `LabelSettings` or theme override) to something other than white
5. ⚠️👀

### Minimal reproduction project (MRP)

[recoloured-emoji.zip](https://github.com/user-attachments/files/19548540/recoloured-emoji.zip)


Discussion / hints:
Confirmed, also occurs in 4.5.dev1, ~will bisect~
This seems to be intentional change from https://github.com/godotengine/godot/pull/102880
For the reference, reverting it to not color emojis is simple (and won't affect the rest of the changes from aforementioned PR), but I guess it depend on what kind of SVG font are you using and for what purpose. Maybe it's better to add a font import flag to make in configurable.

```diff
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 9715785575..62d0efb70e 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -3800,7 +3800,7 @@ void TextServerAdvanced::_font_draw_glyph(const RID &p_font_rid, const RID &p_ca
                if (fgl.texture_idx != -1) {
                        Color modulate = p_color;
 #ifdef MODULE_FREETYPE_ENABLED
-                       if (!fgl.from_svg && ffsd->face && ffsd->textures[fgl.texture_idx].image.is_valid() && (ffsd->textures[fgl.texture_idx].image->get_format() == Image::FORMAT_RGBA8) && !lcd_aa && !fd->msdf) {
+                       if (ffsd->face && ffsd->textures[fgl.texture_idx].image.is_valid() && (ffsd->textures[fgl.texture_idx].image->get_format() == Image::FORMAT_RGBA8) && !lcd_aa && !fd->msdf) {
                                modulate.r = modulate.g = modulate.b = 1.0;
                        }
 #endif
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index c010a1242f..f4d150e064 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -2741,7 +2741,7 @@ void TextServerFallback::_font_draw_glyph(const RID &p_font_rid, const RID &p_ca
                if (fgl.texture_idx != -1) {
                        Color modulate = p_color;
 #ifdef MODULE_FREETYPE_ENABLED
-                       if (!fgl.from_svg && ffsd->face && ffsd->textures[fgl.texture_idx].image.is_valid() && (ffsd->textures[fgl.texture_idx].image->get_format() == Image::FORMAT_RGBA8) && !lcd_aa && !fd->msdf) {
+                       if (ffsd->face && ffsd->textures[fgl.texture_idx].image.is_valid() && (ffsd->textures[fgl.texture_idx].image->get_format() == Image::FORMAT_RGBA8) && !lcd_aa && !fd->msdf) {
                                modulate.r = modulate.g = modulate.b = 1.0;
                        }
```
Yeah, I can see an argument for either way being the intended functionality.
I do notice that the screenshots in https://github.com/godotengine/godot/pull/102880 seem to show that the previous behaviour also coloured emoji in certain cases (the last of the 4 lines in the before/after screenshots)?  But it's unclear to me what context each line of the example images represents 😕 

Rather than an import option, could it make sense for a toggle for this to be available as a `FontVariation` option?  Then the same font could be used in either manner, depending on the context (eg. a simulated green-screen terminal in one place, and regular text elsewhere).

Either way, if a toggle isn't a trivial addition for the next point release, my preference would be to revert to the previous behaviour, at least for the 4.4 branch.

For labels at least, replicating the new behaviour can be done using `modulate`; whereas replicating the old behaviour introduces significant complexity, especially if the text is user-supplied or otherwise not known beforehand.
> For the reference, reverting it to not color emojis is simple (and won't affect the rest of the changes from aforementioned PR), but I guess it depend on what kind of SVG font are you using and for what purpose. Maybe it's better to add a font import flag to make in configurable.

For 4.4.2, I'd suggest committing the above diff to remove the behavior change, while keeping the rest of the bug fix. WDYT?
Indeed, for 4.4.2 it's probably better to just disable it.

Fix patch:
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 71bded1ff1d5..ba3af46eb5c1 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -3808,7 +3808,7 @@ void TextServerAdvanced::_font_draw_glyph(const RID &p_font_rid, const RID &p_ca
 		if (fgl.texture_idx != -1) {
 			Color modulate = p_color;
 #ifdef MODULE_FREETYPE_ENABLED
-			if (!fgl.from_svg && ffsd->face && ffsd->textures[fgl.texture_idx].image.is_valid() && (ffsd->textures[fgl.texture_idx].image->get_format() == Image::FORMAT_RGBA8) && !lcd_aa && !fd->msdf) {
+			if (ffsd->face && ffsd->textures[fgl.texture_idx].image.is_valid() && (ffsd->textures[fgl.texture_idx].image->get_format() == Image::FORMAT_RGBA8) && !lcd_aa && !fd->msdf) {
 				modulate.r = modulate.g = modulate.b = 1.0;
 			}
 #endif
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index c70f5e00d113..012bd999d7d9 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -2739,7 +2739,7 @@ void TextServerFallback::_font_draw_glyph(const RID &p_font_rid, const RID &p_ca
 		if (fgl.texture_idx != -1) {
 			Color modulate = p_color;
 #ifdef MODULE_FREETYPE_ENABLED
-			if (!fgl.from_svg && ffsd->face && ffsd->textures[fgl.texture_idx].image.is_valid() && (ffsd->textures[fgl.texture_idx].image->get_format() == Image::FORMAT_RGBA8) && !lcd_aa && !fd->msdf) {
+			if (ffsd->face && ffsd->textures[fgl.texture_idx].image.is_valid() && (ffsd->textures[fgl.texture_idx].image->get_format() == Image::FORMAT_RGBA8) && !lcd_aa && !fd->msdf) {
 				modulate.r = modulate.g = modulate.b = 1.0;
 			}
 #endif


Test patch: