From 3caa3d57dbcdcbd47e15201fc6fb18fc0b9e5cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Mon, 15 Dec 2025 09:07:11 +0200 Subject: [PATCH] [TextServer] Do not skip non-color font if system fallback is disabled. --- modules/text_server_adv/text_server_adv.cpp | 25 ++++++++++++++++----- modules/text_server_adv/text_server_adv.h | 8 ++++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 41cc7a71720..2fdf5b9ab87 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -2014,6 +2014,22 @@ _FORCE_INLINE_ void TextServerAdvanced::_font_clear_cache(FontAdvanced *p_font_d p_font_data->supported_scripts.clear(); } +bool TextServerAdvanced::_font_is_color(const RID &p_font_rid) const { + FontAdvanced *fd = _get_font_data(p_font_rid); + ERR_FAIL_NULL_V(fd, false); + + MutexLock lock(fd->mutex); + Vector2i size = _get_size(fd, 16); + + FontForSizeAdvanced *ffsd = nullptr; + ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size, ffsd), false); +#ifdef MODULE_FREETYPE_ENABLED + return ffsd->face && FT_HAS_COLOR(ffsd->face); +#else + return false; +#endif +} + hb_font_t *TextServerAdvanced::_font_get_hb_handle(const RID &p_font_rid, int64_t p_size, bool &r_is_color) const { FontAdvanced *fd = _get_font_data(p_font_rid); ERR_FAIL_NULL_V(fd, nullptr); @@ -6742,8 +6758,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star f = p_fonts[p_fb_index]; } else if (OS::get_singleton()->has_feature("system_fonts") && p_fonts.size() > 0 && ((p_fb_index == p_fonts.size()) || (p_fb_index > p_fonts.size() && p_start != p_prev_start))) { // Try system fallback. - RID fdef = p_fonts[0]; - if (_font_is_allow_system_fallback(fdef)) { + if (_font_is_allow_system_fallback(p_fonts[0])) { _update_chars(p_sd); int64_t next = p_end; @@ -6758,7 +6773,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star String script_code = String(scr_buffer); String text = p_sd->text.substr(p_start, next - p_start); - f = _find_sys_font_for_text(fdef, script_code, p_sd->spans[p_span].language, text); + f = _find_sys_font_for_text(p_fonts[0], script_code, p_sd->spans[p_span].language, text); } } @@ -6851,7 +6866,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star Vector2i fss = _get_size(fd, fs); hb_font_t *hb_font = _font_get_hb_handle(f, fs, color); - if (p_script == HB_TAG('Z', 's', 'y', 'e') && !color) { + if (p_script == HB_TAG('Z', 's', 'y', 'e') && !color && _font_is_allow_system_fallback(p_fonts[0])) { // Color emoji is requested, skip non-color font. _shape_run(p_sd, p_start, p_end, p_script, p_direction, p_fonts, p_span, p_fb_index + 1, p_start, p_end, f); return; @@ -7318,7 +7333,7 @@ bool TextServerAdvanced::_shaped_text_shape(const RID &p_shaped) { } sd->glyphs.push_back(gl); } else { - FontPriorityList fonts(this, span.fonts, span.language, script_code); + FontPriorityList fonts(this, span.fonts, span.language, script_code, sd->script_iter->script_ranges[j].script == HB_TAG('Z', 's', 'y', 'e')); _shape_run(sd, MAX(span.start - sd->start, script_run_start), MIN(span.end - sd->start, script_run_end), sd->script_iter->script_ranges[j].script, bidi_run_direction, fonts, k, 0, 0, 0, RID()); } } diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 57a2028c5f5..448a365fdfd 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -705,15 +705,17 @@ class TextServerAdvanced : public TextServerExtension { uint32_t font_count = 0; const String *language; const String *script_code; + bool color = false; LocalVector> unprocessed_fonts; LocalVector fonts; const TextServerAdvanced *text_server; - FontPriorityList(const TextServerAdvanced *p_text_server, const Array &p_fonts, const String &p_language, const String &p_script_code) { + FontPriorityList(const TextServerAdvanced *p_text_server, const Array &p_fonts, const String &p_language, const String &p_script_code, bool p_color) { text_server = p_text_server; language = &p_language; script_code = &p_script_code; font_count = p_fonts.size(); + color = p_color; unprocessed_fonts.reserve(font_count); for (uint32_t i = 0; i < font_count; i++) { @@ -733,6 +735,9 @@ class TextServerAdvanced : public TextServerExtension { } _FORCE_INLINE_ int _get_priority(const RID &p_font) { + if (color && text_server->_font_is_color(p_font)) { + return 0; + } return text_server->_font_is_script_supported(p_font, *script_code) ? (text_server->_font_is_language_supported(p_font, *language) ? 0 : 1) : 2; } @@ -794,6 +799,7 @@ class TextServerAdvanced : public TextServerExtension { static hb_font_t *_bmp_font_create(TextServerAdvanced::FontForSizeAdvanced *p_face, hb_destroy_func_t p_destroy); hb_font_t *_font_get_hb_handle(const RID &p_font, int64_t p_font_size, bool &r_is_color) const; + bool _font_is_color(const RID &p_font) const; struct GlyphCompare { // For line breaking reordering. _FORCE_INLINE_ bool operator()(const Glyph &l, const Glyph &r) const {