| 1 | /**************************************************************************/ |
| 2 | /* editor_fonts.cpp */ |
| 3 | /**************************************************************************/ |
| 4 | /* This file is part of: */ |
| 5 | /* GODOT ENGINE */ |
| 6 | /* https://godotengine.org */ |
| 7 | /**************************************************************************/ |
| 8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
| 9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
| 10 | /* */ |
| 11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
| 12 | /* a copy of this software and associated documentation files (the */ |
| 13 | /* "Software"), to deal in the Software without restriction, including */ |
| 14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
| 15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
| 16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
| 17 | /* the following conditions: */ |
| 18 | /* */ |
| 19 | /* The above copyright notice and this permission notice shall be */ |
| 20 | /* included in all copies or substantial portions of the Software. */ |
| 21 | /* */ |
| 22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
| 23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
| 24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
| 25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
| 26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
| 27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
| 28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
| 29 | /**************************************************************************/ |
| 30 | |
| 31 | #include "editor_fonts.h" |
| 32 | |
| 33 | #include "builtin_fonts.gen.h" |
| 34 | #include "core/io/dir_access.h" |
| 35 | #include "editor/editor_scale.h" |
| 36 | #include "editor/editor_settings.h" |
| 37 | #include "editor/editor_string_names.h" |
| 38 | #include "scene/resources/font.h" |
| 39 | |
| 40 | Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hinting, TextServer::FontAntialiasing p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { |
| 41 | Ref<FontFile> font; |
| 42 | font.instantiate(); |
| 43 | |
| 44 | Vector<uint8_t> data = FileAccess::get_file_as_bytes(p_path); |
| 45 | |
| 46 | font->set_data(data); |
| 47 | font->set_multichannel_signed_distance_field(p_msdf); |
| 48 | font->set_antialiasing(p_aa); |
| 49 | font->set_hinting(p_hinting); |
| 50 | font->set_force_autohinter(p_autohint); |
| 51 | font->set_subpixel_positioning(p_font_subpixel_positioning); |
| 52 | |
| 53 | if (r_fallbacks != nullptr) { |
| 54 | r_fallbacks->push_back(font); |
| 55 | } |
| 56 | |
| 57 | return font; |
| 58 | } |
| 59 | |
| 60 | Ref<SystemFont> load_system_font(const PackedStringArray &p_names, TextServer::Hinting p_hinting, TextServer::FontAntialiasing p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { |
| 61 | Ref<SystemFont> font; |
| 62 | font.instantiate(); |
| 63 | |
| 64 | font->set_font_names(p_names); |
| 65 | font->set_multichannel_signed_distance_field(p_msdf); |
| 66 | font->set_antialiasing(p_aa); |
| 67 | font->set_hinting(p_hinting); |
| 68 | font->set_force_autohinter(p_autohint); |
| 69 | font->set_subpixel_positioning(p_font_subpixel_positioning); |
| 70 | |
| 71 | if (r_fallbacks != nullptr) { |
| 72 | r_fallbacks->push_back(font); |
| 73 | } |
| 74 | |
| 75 | return font; |
| 76 | } |
| 77 | |
| 78 | Ref<FontFile> load_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, TextServer::FontAntialiasing p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { |
| 79 | Ref<FontFile> font; |
| 80 | font.instantiate(); |
| 81 | |
| 82 | font->set_data_ptr(p_data, p_size); |
| 83 | font->set_multichannel_signed_distance_field(p_msdf); |
| 84 | font->set_antialiasing(p_aa); |
| 85 | font->set_hinting(p_hinting); |
| 86 | font->set_force_autohinter(p_autohint); |
| 87 | font->set_subpixel_positioning(p_font_subpixel_positioning); |
| 88 | |
| 89 | if (r_fallbacks != nullptr) { |
| 90 | r_fallbacks->push_back(font); |
| 91 | } |
| 92 | |
| 93 | return font; |
| 94 | } |
| 95 | |
| 96 | Ref<FontVariation> make_bold_font(const Ref<Font> &p_font, double p_embolden, TypedArray<Font> *r_fallbacks = nullptr) { |
| 97 | Ref<FontVariation> font_var; |
| 98 | font_var.instantiate(); |
| 99 | font_var->set_base_font(p_font); |
| 100 | font_var->set_variation_embolden(p_embolden); |
| 101 | |
| 102 | if (r_fallbacks != nullptr) { |
| 103 | r_fallbacks->push_back(font_var); |
| 104 | } |
| 105 | |
| 106 | return font_var; |
| 107 | } |
| 108 | |
| 109 | void editor_register_fonts(Ref<Theme> p_theme) { |
| 110 | OS::get_singleton()->benchmark_begin_measure("editor_register_fonts" ); |
| 111 | Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); |
| 112 | |
| 113 | TextServer::FontAntialiasing font_antialiasing = (TextServer::FontAntialiasing)(int)EDITOR_GET("interface/editor/font_antialiasing" ); |
| 114 | int font_hinting_setting = (int)EDITOR_GET("interface/editor/font_hinting" ); |
| 115 | TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)EDITOR_GET("interface/editor/font_subpixel_positioning" ); |
| 116 | |
| 117 | TextServer::Hinting font_hinting; |
| 118 | TextServer::Hinting font_mono_hinting; |
| 119 | switch (font_hinting_setting) { |
| 120 | case 0: |
| 121 | // The "Auto" setting uses the setting that best matches the OS' font rendering: |
| 122 | // - macOS doesn't use font hinting. |
| 123 | // - Windows uses ClearType, which is in between "Light" and "Normal" hinting. |
| 124 | // - Linux has configurable font hinting, but most distributions including Ubuntu default to "Light". |
| 125 | #ifdef MACOS_ENABLED |
| 126 | font_hinting = TextServer::HINTING_NONE; |
| 127 | font_mono_hinting = TextServer::HINTING_NONE; |
| 128 | #else |
| 129 | font_hinting = TextServer::HINTING_LIGHT; |
| 130 | font_mono_hinting = TextServer::HINTING_LIGHT; |
| 131 | #endif |
| 132 | break; |
| 133 | case 1: |
| 134 | font_hinting = TextServer::HINTING_NONE; |
| 135 | font_mono_hinting = TextServer::HINTING_NONE; |
| 136 | break; |
| 137 | case 2: |
| 138 | font_hinting = TextServer::HINTING_LIGHT; |
| 139 | font_mono_hinting = TextServer::HINTING_LIGHT; |
| 140 | break; |
| 141 | default: |
| 142 | font_hinting = TextServer::HINTING_NORMAL; |
| 143 | font_mono_hinting = TextServer::HINTING_LIGHT; |
| 144 | break; |
| 145 | } |
| 146 | |
| 147 | // Load built-in fonts. |
| 148 | const int default_font_size = int(EDITOR_GET("interface/editor/main_font_size" )) * EDSCALE; |
| 149 | const float embolden_strength = 0.6; |
| 150 | |
| 151 | Ref<Font> default_font = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false); |
| 152 | Ref<Font> default_font_msdf = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, true); |
| 153 | |
| 154 | TypedArray<Font> fallbacks; |
| 155 | Ref<FontFile> arabic_font = load_internal_font(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); |
| 156 | Ref<FontFile> bengali_font = load_internal_font(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); |
| 157 | Ref<FontFile> devanagari_font = load_internal_font(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); |
| 158 | Ref<FontFile> georgian_font = load_internal_font(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); |
| 159 | Ref<FontFile> hebrew_font = load_internal_font(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); |
| 160 | Ref<FontFile> malayalam_font = load_internal_font(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); |
| 161 | Ref<FontFile> oriya_font = load_internal_font(_font_NotoSansOriya_Regular, _font_NotoSansOriya_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); |
| 162 | Ref<FontFile> sinhala_font = load_internal_font(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); |
| 163 | Ref<FontFile> tamil_font = load_internal_font(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); |
| 164 | Ref<FontFile> telugu_font = load_internal_font(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); |
| 165 | Ref<FontFile> thai_font = load_internal_font(_font_NotoSansThai_Regular, _font_NotoSansThai_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); |
| 166 | Ref<FontFile> fallback_font = load_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); |
| 167 | Ref<FontFile> japanese_font = load_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); |
| 168 | default_font->set_fallbacks(fallbacks); |
| 169 | default_font_msdf->set_fallbacks(fallbacks); |
| 170 | |
| 171 | Ref<FontFile> default_font_bold = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false); |
| 172 | Ref<FontFile> default_font_bold_msdf = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, true); |
| 173 | |
| 174 | TypedArray<Font> fallbacks_bold; |
| 175 | Ref<FontFile> arabic_font_bold = load_internal_font(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); |
| 176 | Ref<FontFile> bengali_font_bold = load_internal_font(_font_NotoSansBengaliUI_Bold, _font_NotoSansBengaliUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); |
| 177 | Ref<FontFile> devanagari_font_bold = load_internal_font(_font_NotoSansDevanagariUI_Bold, _font_NotoSansDevanagariUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); |
| 178 | Ref<FontFile> georgian_font_bold = load_internal_font(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); |
| 179 | Ref<FontFile> hebrew_font_bold = load_internal_font(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); |
| 180 | Ref<FontFile> malayalam_font_bold = load_internal_font(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); |
| 181 | Ref<FontFile> oriya_font_bold = load_internal_font(_font_NotoSansOriya_Bold, _font_NotoSansOriya_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); |
| 182 | Ref<FontFile> sinhala_font_bold = load_internal_font(_font_NotoSansSinhalaUI_Bold, _font_NotoSansSinhalaUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); |
| 183 | Ref<FontFile> tamil_font_bold = load_internal_font(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); |
| 184 | Ref<FontFile> telugu_font_bold = load_internal_font(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); |
| 185 | Ref<FontFile> thai_font_bold = load_internal_font(_font_NotoSansThai_Bold, _font_NotoSansThai_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); |
| 186 | Ref<FontVariation> fallback_font_bold = make_bold_font(fallback_font, embolden_strength, &fallbacks_bold); |
| 187 | Ref<FontVariation> japanese_font_bold = make_bold_font(japanese_font, embolden_strength, &fallbacks_bold); |
| 188 | |
| 189 | if (OS::get_singleton()->has_feature("system_fonts" )) { |
| 190 | PackedStringArray emoji_font_names; |
| 191 | emoji_font_names.push_back("Apple Color Emoji" ); |
| 192 | emoji_font_names.push_back("Segoe UI Emoji" ); |
| 193 | emoji_font_names.push_back("Noto Color Emoji" ); |
| 194 | emoji_font_names.push_back("Twitter Color Emoji" ); |
| 195 | emoji_font_names.push_back("OpenMoji" ); |
| 196 | emoji_font_names.push_back("EmojiOne Color" ); |
| 197 | Ref<SystemFont> emoji_font = load_system_font(emoji_font_names, font_hinting, font_antialiasing, true, font_subpixel_positioning, false); |
| 198 | fallbacks.push_back(emoji_font); |
| 199 | fallbacks_bold.push_back(emoji_font); |
| 200 | } |
| 201 | |
| 202 | default_font_bold->set_fallbacks(fallbacks_bold); |
| 203 | default_font_bold_msdf->set_fallbacks(fallbacks_bold); |
| 204 | |
| 205 | Ref<FontFile> default_font_mono = load_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_mono_hinting, font_antialiasing, true, font_subpixel_positioning); |
| 206 | default_font_mono->set_fallbacks(fallbacks); |
| 207 | |
| 208 | // Init base font configs and load custom fonts. |
| 209 | String custom_font_path = EDITOR_GET("interface/editor/main_font" ); |
| 210 | String custom_font_path_bold = EDITOR_GET("interface/editor/main_font_bold" ); |
| 211 | String custom_font_path_source = EDITOR_GET("interface/editor/code_font" ); |
| 212 | |
| 213 | Ref<FontVariation> default_fc; |
| 214 | default_fc.instantiate(); |
| 215 | if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { |
| 216 | Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning); |
| 217 | { |
| 218 | TypedArray<Font> fallback_custom; |
| 219 | fallback_custom.push_back(default_font); |
| 220 | custom_font->set_fallbacks(fallback_custom); |
| 221 | } |
| 222 | default_fc->set_base_font(custom_font); |
| 223 | } else { |
| 224 | EditorSettings::get_singleton()->set_manually("interface/editor/main_font" , "" ); |
| 225 | default_fc->set_base_font(default_font); |
| 226 | } |
| 227 | default_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE); |
| 228 | default_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); |
| 229 | |
| 230 | Ref<FontVariation> default_fc_msdf; |
| 231 | default_fc_msdf.instantiate(); |
| 232 | if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { |
| 233 | Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning); |
| 234 | { |
| 235 | TypedArray<Font> fallback_custom; |
| 236 | fallback_custom.push_back(default_font_msdf); |
| 237 | custom_font->set_fallbacks(fallback_custom); |
| 238 | } |
| 239 | default_fc_msdf->set_base_font(custom_font); |
| 240 | } else { |
| 241 | EditorSettings::get_singleton()->set_manually("interface/editor/main_font" , "" ); |
| 242 | default_fc_msdf->set_base_font(default_font_msdf); |
| 243 | } |
| 244 | default_fc_msdf->set_spacing(TextServer::SPACING_TOP, -EDSCALE); |
| 245 | default_fc_msdf->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); |
| 246 | |
| 247 | Ref<FontVariation> bold_fc; |
| 248 | bold_fc.instantiate(); |
| 249 | if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) { |
| 250 | Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiasing, true, font_subpixel_positioning); |
| 251 | { |
| 252 | TypedArray<Font> fallback_custom; |
| 253 | fallback_custom.push_back(default_font_bold); |
| 254 | custom_font->set_fallbacks(fallback_custom); |
| 255 | } |
| 256 | bold_fc->set_base_font(custom_font); |
| 257 | } else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { |
| 258 | Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning); |
| 259 | { |
| 260 | TypedArray<Font> fallback_custom; |
| 261 | fallback_custom.push_back(default_font_bold); |
| 262 | custom_font->set_fallbacks(fallback_custom); |
| 263 | } |
| 264 | bold_fc->set_base_font(custom_font); |
| 265 | bold_fc->set_variation_embolden(embolden_strength); |
| 266 | } else { |
| 267 | EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold" , "" ); |
| 268 | bold_fc->set_base_font(default_font_bold); |
| 269 | } |
| 270 | bold_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE); |
| 271 | bold_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); |
| 272 | |
| 273 | Ref<FontVariation> bold_fc_msdf; |
| 274 | bold_fc_msdf.instantiate(); |
| 275 | if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) { |
| 276 | Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiasing, true, font_subpixel_positioning); |
| 277 | { |
| 278 | TypedArray<Font> fallback_custom; |
| 279 | fallback_custom.push_back(default_font_bold_msdf); |
| 280 | custom_font->set_fallbacks(fallback_custom); |
| 281 | } |
| 282 | bold_fc_msdf->set_base_font(custom_font); |
| 283 | } else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { |
| 284 | Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning); |
| 285 | { |
| 286 | TypedArray<Font> fallback_custom; |
| 287 | fallback_custom.push_back(default_font_bold_msdf); |
| 288 | custom_font->set_fallbacks(fallback_custom); |
| 289 | } |
| 290 | bold_fc_msdf->set_base_font(custom_font); |
| 291 | bold_fc_msdf->set_variation_embolden(embolden_strength); |
| 292 | } else { |
| 293 | EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold" , "" ); |
| 294 | bold_fc_msdf->set_base_font(default_font_bold_msdf); |
| 295 | } |
| 296 | bold_fc_msdf->set_spacing(TextServer::SPACING_TOP, -EDSCALE); |
| 297 | bold_fc_msdf->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); |
| 298 | |
| 299 | Ref<FontVariation> mono_fc; |
| 300 | mono_fc.instantiate(); |
| 301 | if (custom_font_path_source.length() > 0 && dir->file_exists(custom_font_path_source)) { |
| 302 | Ref<FontFile> custom_font = load_external_font(custom_font_path_source, font_mono_hinting, font_antialiasing, true, font_subpixel_positioning); |
| 303 | { |
| 304 | TypedArray<Font> fallback_custom; |
| 305 | fallback_custom.push_back(default_font_mono); |
| 306 | custom_font->set_fallbacks(fallback_custom); |
| 307 | } |
| 308 | mono_fc->set_base_font(custom_font); |
| 309 | } else { |
| 310 | EditorSettings::get_singleton()->set_manually("interface/editor/code_font" , "" ); |
| 311 | mono_fc->set_base_font(default_font_mono); |
| 312 | } |
| 313 | mono_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE); |
| 314 | mono_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE); |
| 315 | |
| 316 | Ref<FontVariation> mono_other_fc = mono_fc->duplicate(); |
| 317 | |
| 318 | // Enable contextual alternates (coding ligatures) and custom features for the source editor font. |
| 319 | int ot_mode = EDITOR_GET("interface/editor/code_font_contextual_ligatures" ); |
| 320 | switch (ot_mode) { |
| 321 | case 1: { // Disable ligatures. |
| 322 | Dictionary ftrs; |
| 323 | ftrs[TS->name_to_tag("calt" )] = 0; |
| 324 | mono_fc->set_opentype_features(ftrs); |
| 325 | } break; |
| 326 | case 2: { // Custom. |
| 327 | Vector<String> subtag = String(EDITOR_GET("interface/editor/code_font_custom_opentype_features" )).split("," ); |
| 328 | Dictionary ftrs; |
| 329 | for (int i = 0; i < subtag.size(); i++) { |
| 330 | Vector<String> subtag_a = subtag[i].split("=" ); |
| 331 | if (subtag_a.size() == 2) { |
| 332 | ftrs[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int(); |
| 333 | } else if (subtag_a.size() == 1) { |
| 334 | ftrs[TS->name_to_tag(subtag_a[0])] = 1; |
| 335 | } |
| 336 | } |
| 337 | mono_fc->set_opentype_features(ftrs); |
| 338 | } break; |
| 339 | default: { // Enabled. |
| 340 | Dictionary ftrs; |
| 341 | ftrs[TS->name_to_tag("calt" )] = 1; |
| 342 | mono_fc->set_opentype_features(ftrs); |
| 343 | } break; |
| 344 | } |
| 345 | |
| 346 | { |
| 347 | // Disable contextual alternates (coding ligatures). |
| 348 | Dictionary ftrs; |
| 349 | ftrs[TS->name_to_tag("calt" )] = 0; |
| 350 | mono_other_fc->set_opentype_features(ftrs); |
| 351 | } |
| 352 | |
| 353 | // Use fake bold/italics to style the editor log's `print_rich()` output. |
| 354 | // Use stronger embolden strength to make bold easier to distinguish from regular text. |
| 355 | Ref<FontVariation> mono_other_fc_bold = mono_other_fc->duplicate(); |
| 356 | mono_other_fc_bold->set_variation_embolden(0.8); |
| 357 | |
| 358 | Ref<FontVariation> mono_other_fc_italic = mono_other_fc->duplicate(); |
| 359 | mono_other_fc_italic->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0)); |
| 360 | |
| 361 | Ref<FontVariation> mono_other_fc_bold_italic = mono_other_fc->duplicate(); |
| 362 | mono_other_fc_bold_italic->set_variation_embolden(0.8); |
| 363 | mono_other_fc_bold_italic->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0)); |
| 364 | |
| 365 | Ref<FontVariation> mono_other_fc_mono = mono_other_fc->duplicate(); |
| 366 | // Use a different font style to distinguish `[code]` in rich prints. |
| 367 | // This emulates the "faint" styling used in ANSI escape codes by using a slightly thinner font. |
| 368 | mono_other_fc_mono->set_variation_embolden(-0.25); |
| 369 | mono_other_fc_mono->set_variation_transform(Transform2D(1.0, 0.1, 0.0, 1.0, 0.0, 0.0)); |
| 370 | |
| 371 | Ref<FontVariation> italic_fc = default_fc->duplicate(); |
| 372 | italic_fc->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0)); |
| 373 | |
| 374 | // Setup theme. |
| 375 | |
| 376 | p_theme->set_default_font(default_fc); // Default theme font config. |
| 377 | p_theme->set_default_font_size(default_font_size); |
| 378 | |
| 379 | // Main font. |
| 380 | |
| 381 | p_theme->set_font("main" , EditorStringName(EditorFonts), default_fc); |
| 382 | p_theme->set_font("main_msdf" , EditorStringName(EditorFonts), default_fc_msdf); |
| 383 | p_theme->set_font_size("main_size" , EditorStringName(EditorFonts), default_font_size); |
| 384 | |
| 385 | p_theme->set_font("bold" , EditorStringName(EditorFonts), bold_fc); |
| 386 | p_theme->set_font("main_bold_msdf" , EditorStringName(EditorFonts), bold_fc_msdf); |
| 387 | p_theme->set_font_size("bold_size" , EditorStringName(EditorFonts), default_font_size); |
| 388 | |
| 389 | // Title font. |
| 390 | |
| 391 | p_theme->set_font("title" , EditorStringName(EditorFonts), bold_fc); |
| 392 | p_theme->set_font_size("title_size" , EditorStringName(EditorFonts), default_font_size + 1 * EDSCALE); |
| 393 | |
| 394 | p_theme->set_font("main_button_font" , EditorStringName(EditorFonts), bold_fc); |
| 395 | p_theme->set_font_size("main_button_font_size" , EditorStringName(EditorFonts), default_font_size + 1 * EDSCALE); |
| 396 | |
| 397 | p_theme->set_font("font" , "Label" , default_fc); |
| 398 | |
| 399 | p_theme->set_type_variation("HeaderSmall" , "Label" ); |
| 400 | p_theme->set_font("font" , "HeaderSmall" , bold_fc); |
| 401 | p_theme->set_font_size("font_size" , "HeaderSmall" , default_font_size); |
| 402 | |
| 403 | p_theme->set_type_variation("HeaderMedium" , "Label" ); |
| 404 | p_theme->set_font("font" , "HeaderMedium" , bold_fc); |
| 405 | p_theme->set_font_size("font_size" , "HeaderMedium" , default_font_size + 1 * EDSCALE); |
| 406 | |
| 407 | p_theme->set_type_variation("HeaderLarge" , "Label" ); |
| 408 | p_theme->set_font("font" , "HeaderLarge" , bold_fc); |
| 409 | p_theme->set_font_size("font_size" , "HeaderLarge" , default_font_size + 3 * EDSCALE); |
| 410 | |
| 411 | // Documentation fonts |
| 412 | p_theme->set_font_size("doc_size" , EditorStringName(EditorFonts), int(EDITOR_GET("text_editor/help/help_font_size" )) * EDSCALE); |
| 413 | p_theme->set_font("doc" , EditorStringName(EditorFonts), default_fc); |
| 414 | p_theme->set_font("doc_bold" , EditorStringName(EditorFonts), bold_fc); |
| 415 | p_theme->set_font("doc_italic" , EditorStringName(EditorFonts), italic_fc); |
| 416 | p_theme->set_font_size("doc_title_size" , EditorStringName(EditorFonts), int(EDITOR_GET("text_editor/help/help_title_font_size" )) * EDSCALE); |
| 417 | p_theme->set_font("doc_title" , EditorStringName(EditorFonts), bold_fc); |
| 418 | p_theme->set_font_size("doc_source_size" , EditorStringName(EditorFonts), int(EDITOR_GET("text_editor/help/help_source_font_size" )) * EDSCALE); |
| 419 | p_theme->set_font("doc_source" , EditorStringName(EditorFonts), mono_fc); |
| 420 | p_theme->set_font_size("doc_keyboard_size" , EditorStringName(EditorFonts), (int(EDITOR_GET("text_editor/help/help_source_font_size" )) - 1) * EDSCALE); |
| 421 | p_theme->set_font("doc_keyboard" , EditorStringName(EditorFonts), mono_fc); |
| 422 | |
| 423 | // Ruler font |
| 424 | p_theme->set_font_size("rulers_size" , EditorStringName(EditorFonts), 8 * EDSCALE); |
| 425 | p_theme->set_font("rulers" , EditorStringName(EditorFonts), default_fc); |
| 426 | |
| 427 | // Rotation widget font |
| 428 | p_theme->set_font_size("rotation_control_size" , EditorStringName(EditorFonts), 14 * EDSCALE); |
| 429 | p_theme->set_font("rotation_control" , EditorStringName(EditorFonts), default_fc); |
| 430 | |
| 431 | // Code font |
| 432 | p_theme->set_font_size("source_size" , EditorStringName(EditorFonts), int(EDITOR_GET("interface/editor/code_font_size" )) * EDSCALE); |
| 433 | p_theme->set_font("source" , EditorStringName(EditorFonts), mono_fc); |
| 434 | |
| 435 | p_theme->set_font_size("expression_size" , EditorStringName(EditorFonts), (int(EDITOR_GET("interface/editor/code_font_size" )) - 1) * EDSCALE); |
| 436 | p_theme->set_font("expression" , EditorStringName(EditorFonts), mono_other_fc); |
| 437 | |
| 438 | p_theme->set_font_size("output_source_size" , EditorStringName(EditorFonts), int(EDITOR_GET("run/output/font_size" )) * EDSCALE); |
| 439 | p_theme->set_font("output_source" , EditorStringName(EditorFonts), mono_other_fc); |
| 440 | p_theme->set_font("output_source_bold" , EditorStringName(EditorFonts), mono_other_fc_bold); |
| 441 | p_theme->set_font("output_source_italic" , EditorStringName(EditorFonts), mono_other_fc_italic); |
| 442 | p_theme->set_font("output_source_bold_italic" , EditorStringName(EditorFonts), mono_other_fc_bold_italic); |
| 443 | p_theme->set_font("output_source_mono" , EditorStringName(EditorFonts), mono_other_fc_mono); |
| 444 | |
| 445 | p_theme->set_font_size("status_source_size" , EditorStringName(EditorFonts), default_font_size); |
| 446 | p_theme->set_font("status_source" , EditorStringName(EditorFonts), mono_other_fc); |
| 447 | |
| 448 | OS::get_singleton()->benchmark_end_measure("editor_register_fonts" ); |
| 449 | } |
| 450 | |