From 970592274d4aa91fbe41682faec7b7ec00bec6a2 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Mon, 26 Sep 2022 13:02:25 +0300 Subject: [PATCH] [RTL] Fix font variations / OpenType features of theme default font not updated when default font is changed. --- modules/text_server_adv/text_server_adv.cpp | 16 +-- scene/gui/rich_text_label.cpp | 140 ++++++++++++++++---- scene/gui/rich_text_label.h | 5 +- 3 files changed, 122 insertions(+), 39 deletions(-) diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 1a4831857f5..3565254ac78 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -3826,19 +3826,11 @@ void TextServerAdvanced::shaped_set_span_update_font(const RID &p_shaped, int64_ ERR_FAIL_INDEX(p_index, sd->spans.size()); ShapedTextDataAdvanced::Span &span = sd->spans.ptrw()[p_index]; - bool changed = (span.font_size != p_size) || (span.features != p_opentype_features) || (p_fonts.size() != span.fonts.size()); - if (!changed) { - for (int i = 0; i < p_fonts.size(); i++) { - changed = changed || (span.fonts[i] != p_fonts[i]); - } - } - if (changed) { - span.fonts = p_fonts; - span.font_size = p_size; - span.features = p_opentype_features; + span.fonts = p_fonts; + span.font_size = p_size; + span.features = p_opentype_features; - invalidate(sd, false); - } + invalidate(sd, false); } bool TextServerAdvanced::shaped_text_add_string(const RID &p_shaped, const String &p_text, const TypedArray &p_fonts, int64_t p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 3c45b906128..8bccf3ada1d 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -2196,24 +2196,69 @@ RichTextLabel::ItemFont *RichTextLabel::_find_font(Item *p_item) { ItemFont *fi = static_cast(fontitem); switch (fi->def_font) { case NORMAL_FONT: { - fi->font = theme_cache.normal_font; - fi->font_size = theme_cache.normal_font_size; + if (fi->variation) { + Ref fc = fi->font; + if (fc.is_valid()) { + fc->set_base_font(theme_cache.normal_font); + } + } else { + fi->font = theme_cache.normal_font; + } + if (fi->def_size) { + fi->font_size = theme_cache.normal_font_size; + } } break; case BOLD_FONT: { - fi->font = theme_cache.bold_font; - fi->font_size = theme_cache.bold_font_size; + if (fi->variation) { + Ref fc = fi->font; + if (fc.is_valid()) { + fc->set_base_font(theme_cache.bold_font); + } + } else { + fi->font = theme_cache.bold_font; + } + if (fi->def_size) { + fi->font_size = theme_cache.bold_font_size; + } } break; case ITALICS_FONT: { - fi->font = theme_cache.italics_font; - fi->font_size = theme_cache.italics_font_size; + if (fi->variation) { + Ref fc = fi->font; + if (fc.is_valid()) { + fc->set_base_font(theme_cache.italics_font); + } + } else { + fi->font = theme_cache.italics_font; + } + if (fi->def_size) { + fi->font_size = theme_cache.italics_font_size; + } } break; case BOLD_ITALICS_FONT: { - fi->font = theme_cache.bold_italics_font; - fi->font_size = theme_cache.bold_italics_font_size; + if (fi->variation) { + Ref fc = fi->font; + if (fc.is_valid()) { + fc->set_base_font(theme_cache.bold_italics_font); + } + } else { + fi->font = theme_cache.bold_italics_font; + } + if (fi->def_size) { + fi->font_size = theme_cache.bold_italics_font_size; + } } break; case MONO_FONT: { - fi->font = theme_cache.mono_font; - fi->font_size = theme_cache.mono_font_size; + if (fi->variation) { + Ref fc = fi->font; + if (fc.is_valid()) { + fc->set_base_font(theme_cache.mono_font); + } + } else { + fi->font = theme_cache.mono_font; + } + if (fi->def_size) { + fi->font_size = theme_cache.mono_font_size; + } } break; default: { } break; @@ -3034,14 +3079,30 @@ void RichTextLabel::push_dropcap(const String &p_string, const Ref &p_font _add_item(item, false); } -void RichTextLabel::_push_def_font(DefaultFont p_font) { +void RichTextLabel::_push_def_font_var(DefaultFont p_def_font, const Ref &p_font, int p_size) { _stop_thread(); MutexLock data_lock(data_mutex); ERR_FAIL_COND(current->type == ITEM_TABLE); ItemFont *item = memnew(ItemFont); - item->def_font = p_font; + item->def_font = p_def_font; + item->variation = true; + item->font = p_font; + item->font_size = p_size; + item->def_size = (p_size <= 0); + _add_item(item, true); +} + +void RichTextLabel::_push_def_font(DefaultFont p_def_font) { + _stop_thread(); + MutexLock data_lock(data_mutex); + + ERR_FAIL_COND(current->type == ITEM_TABLE); + ItemFont *item = memnew(ItemFont); + + item->def_font = p_def_font; + item->def_size = true; _add_item(item, true); } @@ -4122,24 +4183,21 @@ void RichTextLabel::append_text(const String &p_bbcode) { pos = brk_end + 1; tag_stack.push_front("font_size"); - } else if (tag.begins_with("opentype_features=")) { - String fnt_ftr = tag.substr(18, tag.length()); + } else if (tag.begins_with("opentype_features=") || tag.begins_with("otf=")) { + int value_pos = tag.find("="); + String fnt_ftr = tag.substr(value_pos + 1); Vector subtag = fnt_ftr.split(","); if (subtag.size() > 0) { Ref font = theme_cache.normal_font; - int font_size = 0; + DefaultFont def_font = NORMAL_FONT; + ItemFont *font_it = _find_font(current); if (font_it) { if (font_it->font.is_valid()) { font = font_it->font; - } - if (font_it->font_size > 0) { - font_size = font_it->font_size; + def_font = font_it->def_font; } } - Ref fc; - fc.instantiate(); - fc->set_base_font(font); Dictionary features; for (int i = 0; i < subtag.size(); i++) { Vector subtag_a = subtag[i].split("="); @@ -4149,11 +4207,21 @@ void RichTextLabel::append_text(const String &p_bbcode) { features[TS->name_to_tag(subtag_a[0])] = 1; } } + + Ref fc; + fc.instantiate(); + + fc->set_base_font(font); fc->set_opentype_features(features); - push_font(fc, font_size); + + if (def_font != CUSTOM_FONT) { + _push_def_font_var(def_font, fc); + } else { + push_font(fc); + } } pos = brk_end + 1; - tag_stack.push_front("opentype_features"); + tag_stack.push_front(tag.substr(0, value_pos)); } else if (tag.begins_with("font=")) { String fnt = tag.substr(5, tag.length()); @@ -4169,9 +4237,21 @@ void RichTextLabel::append_text(const String &p_bbcode) { } else if (tag.begins_with("font ")) { Vector subtag = tag.substr(2, tag.length()).split(" "); + Ref font = theme_cache.normal_font; + DefaultFont def_font = NORMAL_FONT; + + ItemFont *font_it = _find_font(current); + if (font_it) { + if (font_it->font.is_valid()) { + font = font_it->font; + def_font = font_it->def_font; + } + } + Ref fc; fc.instantiate(); - int fnt_size = 0; + + int fnt_size = -1; for (int i = 1; i < subtag.size(); i++) { Vector subtag_a = subtag[i].split("=", true, 2); if (subtag_a.size() == 2) { @@ -4179,7 +4259,8 @@ void RichTextLabel::append_text(const String &p_bbcode) { String fnt = subtag_a[1]; Ref font_data = ResourceLoader::load(fnt, "Font"); if (font_data.is_valid()) { - fc->set_base_font(font_data); + font = font_data; + def_font = CUSTOM_FONT; } } else if (subtag_a[0] == "size" || subtag_a[0] == "s") { fnt_size = subtag_a[1].to_int(); @@ -4233,7 +4314,14 @@ void RichTextLabel::append_text(const String &p_bbcode) { } } } - push_font(fc, fnt_size); + fc->set_base_font(font); + + if (def_font != CUSTOM_FONT) { + _push_def_font_var(def_font, fc, fnt_size); + } else { + push_font(fc, fnt_size); + } + pos = brk_end + 1; tag_stack.push_front("font"); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index e714cb4ced9..71123602ad6 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -189,6 +189,8 @@ private: struct ItemFont : public Item { DefaultFont def_font = CUSTOM_FONT; Ref font; + bool variation = false; + bool def_size = false; int font_size = 0; ItemFont() { type = ITEM_FONT; } }; @@ -571,7 +573,8 @@ public: void add_newline(); bool remove_line(const int p_line); void push_dropcap(const String &p_string, const Ref &p_font, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Color &p_color = Color(1, 1, 1), int p_ol_size = 0, const Color &p_ol_color = Color(0, 0, 0, 0)); - void _push_def_font(DefaultFont p_font); + void _push_def_font(DefaultFont p_def_font); + void _push_def_font_var(DefaultFont p_def_font, const Ref &p_font, int p_size = -1); void push_font(const Ref &p_font, int p_size = 0); void push_font_size(int p_font_size); void push_outline_size(int p_font_size);