Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/editor/themes/editor_fonts.cpp
20936 views
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 "core/io/dir_access.h"
34
#include "core/os/os.h"
35
#include "core/string/translation_server.h"
36
#include "editor/editor_string_names.h"
37
#include "editor/settings/editor_settings.h"
38
#include "editor/themes/builtin_fonts.gen.h"
39
#include "editor/themes/editor_scale.h"
40
#include "scene/resources/font.h"
41
#include "scene/scene_string_names.h"
42
43
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_font_disable_embedded_bitmaps, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) {
44
Ref<FontFile> font;
45
font.instantiate();
46
47
Vector<uint8_t> data = FileAccess::get_file_as_bytes(p_path);
48
49
font->set_data(data);
50
font->set_multichannel_signed_distance_field(p_msdf);
51
font->set_antialiasing(p_aa);
52
font->set_hinting(p_hinting);
53
font->set_force_autohinter(p_autohint);
54
font->set_subpixel_positioning(p_font_subpixel_positioning);
55
font->set_disable_embedded_bitmaps(p_font_disable_embedded_bitmaps);
56
57
if (r_fallbacks != nullptr) {
58
r_fallbacks->push_back(font);
59
}
60
61
return font;
62
}
63
64
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_font_disable_embedded_bitmaps, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) {
65
Ref<SystemFont> font;
66
font.instantiate();
67
68
font->set_font_names(p_names);
69
font->set_multichannel_signed_distance_field(p_msdf);
70
font->set_antialiasing(p_aa);
71
font->set_hinting(p_hinting);
72
font->set_force_autohinter(p_autohint);
73
font->set_subpixel_positioning(p_font_subpixel_positioning);
74
font->set_disable_embedded_bitmaps(p_font_disable_embedded_bitmaps);
75
76
if (r_fallbacks != nullptr) {
77
r_fallbacks->push_back(font);
78
}
79
80
return font;
81
}
82
83
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_font_disable_embedded_bitmaps, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) {
84
Ref<FontFile> font;
85
font.instantiate();
86
87
font->set_data_ptr(p_data, p_size);
88
font->set_multichannel_signed_distance_field(p_msdf);
89
font->set_antialiasing(p_aa);
90
font->set_hinting(p_hinting);
91
font->set_force_autohinter(p_autohint);
92
font->set_subpixel_positioning(p_font_subpixel_positioning);
93
font->set_disable_embedded_bitmaps(p_font_disable_embedded_bitmaps);
94
95
if (r_fallbacks != nullptr) {
96
r_fallbacks->push_back(font);
97
}
98
99
return font;
100
}
101
102
Ref<FontVariation> make_bold_font(const Ref<Font> &p_font, double p_embolden, TypedArray<Font> *r_fallbacks = nullptr) {
103
Ref<FontVariation> font_var;
104
font_var.instantiate();
105
font_var->set_base_font(p_font);
106
font_var->set_variation_embolden(p_embolden);
107
108
if (r_fallbacks != nullptr) {
109
r_fallbacks->push_back(font_var);
110
}
111
112
return font_var;
113
}
114
115
void editor_register_fonts(const Ref<Theme> &p_theme) {
116
Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
117
118
TextServer::FontAntialiasing font_antialiasing = (TextServer::FontAntialiasing)(int)EDITOR_GET("interface/editor/font_antialiasing");
119
int font_hinting_setting = (int)EDITOR_GET("interface/editor/font_hinting");
120
TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)EDITOR_GET("interface/editor/font_subpixel_positioning");
121
bool font_disable_embedded_bitmaps = (bool)EDITOR_GET("interface/editor/font_disable_embedded_bitmaps");
122
bool font_allow_msdf = (bool)EDITOR_GET("interface/editor/font_allow_msdf");
123
124
TextServer::Hinting font_hinting;
125
TextServer::Hinting font_mono_hinting;
126
switch (font_hinting_setting) {
127
case 0:
128
// The "Auto" setting uses the setting that best matches the OS' font rendering:
129
// - macOS doesn't use font hinting.
130
// - Windows uses ClearType, which is in between "Light" and "Normal" hinting.
131
// - Linux has configurable font hinting, but most distributions including Ubuntu default to "Light".
132
#ifdef MACOS_ENABLED
133
font_hinting = TextServer::HINTING_NONE;
134
font_mono_hinting = TextServer::HINTING_NONE;
135
#else
136
font_hinting = TextServer::HINTING_LIGHT;
137
font_mono_hinting = TextServer::HINTING_LIGHT;
138
#endif
139
break;
140
case 1:
141
font_hinting = TextServer::HINTING_NONE;
142
font_mono_hinting = TextServer::HINTING_NONE;
143
break;
144
case 2:
145
font_hinting = TextServer::HINTING_LIGHT;
146
font_mono_hinting = TextServer::HINTING_LIGHT;
147
break;
148
default:
149
font_hinting = TextServer::HINTING_NORMAL;
150
font_mono_hinting = TextServer::HINTING_LIGHT;
151
break;
152
}
153
154
// Load built-in fonts.
155
const int default_font_size = int(EDITOR_GET("interface/editor/main_font_size")) * EDSCALE;
156
const float embolden_strength = 0.6;
157
158
Ref<Font> default_font = load_internal_font(_font_Inter_Regular, _font_Inter_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false);
159
Ref<Font> default_font_msdf = load_internal_font(_font_Inter_Regular, _font_Inter_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, font_allow_msdf);
160
161
Dictionary default_features;
162
default_features["calt"] = false; // Disable contextual alternates by default.
163
default_features["ss04"] = true; // Serifed I, tailed l for better distinction.
164
default_features["tnum"] = true; // Tabular numbers for better alignment.
165
166
String noto_cjk_path;
167
String noto_cjk_bold_path;
168
{
169
Vector<String> var_suffix;
170
171
// Note: Most Noto Sans CJK versions support all glyph variations, but select the best matching one in case it's not.
172
String locale = TranslationServer::get_singleton()->get_tool_locale();
173
if (!locale.begins_with("zh") && !locale.begins_with("ja") && !locale.begins_with("ko")) {
174
locale = OS::get_singleton()->get_locale();
175
}
176
if (locale.begins_with("zh") && (locale.contains("Hans") || locale.contains("CN") || locale.contains("SG"))) {
177
var_suffix = { "SC", "TC", "HK", "KR", "JP" };
178
} else if (locale.begins_with("zh") && locale.contains("HK")) {
179
var_suffix = { "HK", "TC", "SC", "KR", "JP" };
180
} else if (locale.begins_with("zh") && (locale.contains("Hant") || locale.contains("MO") || locale.contains("TW"))) {
181
var_suffix = { "TC", "HK", "SC", "KR", "JP" };
182
} else if (locale.begins_with("ko")) {
183
var_suffix = { "KR", "HK", "SC", "TC", "JP" };
184
} else if (locale.begins_with("ko")) {
185
var_suffix = { "JP", "HK", "KR", "SC", "TC" };
186
} else {
187
var_suffix = { "HK", "KR", "SC", "TC", "JP" };
188
}
189
for (int64_t i = 0; i < var_suffix.size(); i++) {
190
if (noto_cjk_path.is_empty()) {
191
noto_cjk_path = OS::get_singleton()->get_system_font_path("Noto Sans CJK " + var_suffix[i], 400, 100);
192
}
193
if (noto_cjk_bold_path.is_empty()) {
194
noto_cjk_bold_path = OS::get_singleton()->get_system_font_path("Noto Sans CJK " + var_suffix[i], 800, 100);
195
}
196
}
197
}
198
199
TypedArray<Font> fallbacks;
200
Ref<FontFile> arabic_font = load_internal_font(_font_Vazirmatn_Regular, _font_Vazirmatn_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
201
Ref<FontFile> bengali_font = load_internal_font(_font_NotoSansBengali_Regular, _font_NotoSansBengali_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
202
Ref<FontFile> devanagari_font = load_internal_font(_font_NotoSansDevanagari_Regular, _font_NotoSansDevanagari_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
203
Ref<FontFile> georgian_font = load_internal_font(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
204
Ref<FontFile> hebrew_font = load_internal_font(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
205
Ref<FontFile> malayalam_font = load_internal_font(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
206
Ref<FontFile> oriya_font = load_internal_font(_font_NotoSansOriya_Regular, _font_NotoSansOriya_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
207
Ref<FontFile> sinhala_font = load_internal_font(_font_NotoSansSinhala_Regular, _font_NotoSansSinhala_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
208
Ref<FontFile> tamil_font = load_internal_font(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
209
Ref<FontFile> telugu_font = load_internal_font(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
210
Ref<FontFile> thai_font = load_internal_font(_font_NotoSansThai_Regular, _font_NotoSansThai_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
211
if (!noto_cjk_path.is_empty()) {
212
load_external_font(noto_cjk_path, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
213
}
214
Ref<FontFile> fallback_font = load_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
215
fallback_font->set_language_support_override("ja", false);
216
fallback_font->set_language_support_override("zh", true);
217
fallback_font->set_language_support_override("ko", true);
218
fallback_font->set_language_support_override("*", false);
219
Ref<FontFile> japanese_font = load_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks);
220
japanese_font->set_language_support_override("ja", true);
221
japanese_font->set_language_support_override("zh", false);
222
japanese_font->set_language_support_override("ko", false);
223
japanese_font->set_language_support_override("*", false);
224
default_font->set_fallbacks(fallbacks);
225
default_font_msdf->set_fallbacks(fallbacks);
226
227
Ref<FontFile> default_font_bold = load_internal_font(_font_Inter_Bold, _font_Inter_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false);
228
Ref<FontFile> default_font_bold_msdf = load_internal_font(_font_Inter_Bold, _font_Inter_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, font_allow_msdf);
229
230
TypedArray<Font> fallbacks_bold;
231
Ref<FontFile> arabic_font_bold = load_internal_font(_font_Vazirmatn_Bold, _font_Vazirmatn_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks_bold);
232
Ref<FontFile> bengali_font_bold = load_internal_font(_font_NotoSansBengali_Bold, _font_NotoSansBengali_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks_bold);
233
Ref<FontFile> devanagari_font_bold = load_internal_font(_font_NotoSansDevanagari_Bold, _font_NotoSansDevanagari_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks_bold);
234
Ref<FontFile> georgian_font_bold = load_internal_font(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks_bold);
235
Ref<FontFile> hebrew_font_bold = load_internal_font(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks_bold);
236
Ref<FontFile> malayalam_font_bold = load_internal_font(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks_bold);
237
Ref<FontFile> oriya_font_bold = load_internal_font(_font_NotoSansOriya_Bold, _font_NotoSansOriya_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks_bold);
238
Ref<FontFile> sinhala_font_bold = load_internal_font(_font_NotoSansSinhala_Bold, _font_NotoSansSinhala_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks_bold);
239
Ref<FontFile> tamil_font_bold = load_internal_font(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks_bold);
240
Ref<FontFile> telugu_font_bold = load_internal_font(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks_bold);
241
Ref<FontFile> thai_font_bold = load_internal_font(_font_NotoSansThai_Bold, _font_NotoSansThai_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks_bold);
242
if (!noto_cjk_bold_path.is_empty()) {
243
load_external_font(noto_cjk_bold_path, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false, &fallbacks_bold);
244
}
245
Ref<FontVariation> fallback_font_bold = make_bold_font(fallback_font, embolden_strength, &fallbacks_bold);
246
Ref<FontVariation> japanese_font_bold = make_bold_font(japanese_font, embolden_strength, &fallbacks_bold);
247
248
if (OS::get_singleton()->has_feature("system_fonts")) {
249
PackedStringArray emoji_font_names = {
250
"Apple Color Emoji",
251
"Segoe UI Emoji",
252
"Noto Color Emoji",
253
"Twitter Color Emoji",
254
"OpenMoji",
255
"EmojiOne Color"
256
};
257
Ref<SystemFont> emoji_font = load_system_font(emoji_font_names, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, false);
258
fallbacks.push_back(emoji_font);
259
fallbacks_bold.push_back(emoji_font);
260
}
261
262
default_font_bold->set_fallbacks(fallbacks_bold);
263
default_font_bold_msdf->set_fallbacks(fallbacks_bold);
264
265
Ref<FontFile> default_font_mono = load_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_mono_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps);
266
default_font_mono->set_fallbacks(fallbacks);
267
268
// Init base font configs and load custom fonts.
269
String custom_font_path = EDITOR_GET("interface/editor/main_font");
270
String custom_font_path_bold = EDITOR_GET("interface/editor/main_font_bold");
271
String custom_font_path_source = EDITOR_GET("interface/editor/code_font");
272
273
Ref<FontVariation> default_fc;
274
default_fc.instantiate();
275
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
276
Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps);
277
{
278
TypedArray<Font> fallback_custom = { default_font };
279
custom_font->set_fallbacks(fallback_custom);
280
}
281
default_fc->set_base_font(custom_font);
282
} else {
283
EditorSettings::get_singleton()->set_manually("interface/editor/main_font", "");
284
default_fc->set_opentype_features(default_features);
285
default_fc->set_base_font(default_font);
286
}
287
default_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
288
default_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
289
Dictionary default_fc_opentype;
290
default_fc_opentype["weight"] = 400;
291
default_fc->set_variation_opentype(default_fc_opentype);
292
293
Ref<FontVariation> default_fc_msdf;
294
default_fc_msdf.instantiate();
295
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
296
Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, font_allow_msdf);
297
{
298
TypedArray<Font> fallback_custom = { default_font_msdf };
299
custom_font->set_fallbacks(fallback_custom);
300
}
301
default_fc_msdf->set_base_font(custom_font);
302
} else {
303
EditorSettings::get_singleton()->set_manually("interface/editor/main_font", "");
304
default_fc_msdf->set_opentype_features(default_features);
305
default_fc_msdf->set_base_font(default_font_msdf);
306
}
307
default_fc_msdf->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
308
default_fc_msdf->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
309
default_fc_msdf->set_variation_opentype(default_fc_opentype);
310
311
Ref<FontVariation> bold_fc;
312
bold_fc.instantiate();
313
if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) {
314
Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps);
315
{
316
TypedArray<Font> fallback_custom = { default_font_bold };
317
custom_font->set_fallbacks(fallback_custom);
318
}
319
bold_fc->set_base_font(custom_font);
320
} else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
321
Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps);
322
{
323
TypedArray<Font> fallback_custom = { default_font_bold };
324
custom_font->set_fallbacks(fallback_custom);
325
}
326
bold_fc->set_base_font(custom_font);
327
if (!custom_font->get_supported_variation_list().has(TS->name_to_tag("wght"))) {
328
bold_fc->set_variation_embolden(embolden_strength);
329
}
330
} else {
331
EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold", "");
332
bold_fc->set_opentype_features(default_features);
333
bold_fc->set_base_font(default_font_bold);
334
}
335
bold_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
336
bold_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
337
Dictionary bold_fc_opentype;
338
bold_fc_opentype["weight"] = 700;
339
bold_fc->set_variation_opentype(bold_fc_opentype);
340
341
Ref<FontVariation> bold_fc_msdf;
342
bold_fc_msdf.instantiate();
343
if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) {
344
Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, font_allow_msdf);
345
{
346
TypedArray<Font> fallback_custom = { default_font_bold_msdf };
347
custom_font->set_fallbacks(fallback_custom);
348
}
349
bold_fc_msdf->set_base_font(custom_font);
350
} else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
351
Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps, font_allow_msdf);
352
{
353
TypedArray<Font> fallback_custom = { default_font_bold_msdf };
354
custom_font->set_fallbacks(fallback_custom);
355
}
356
bold_fc_msdf->set_base_font(custom_font);
357
if (!custom_font->get_supported_variation_list().has(TS->name_to_tag("wght"))) {
358
bold_fc_msdf->set_variation_embolden(embolden_strength);
359
}
360
} else {
361
EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold", "");
362
bold_fc_msdf->set_opentype_features(default_features);
363
bold_fc_msdf->set_base_font(default_font_bold_msdf);
364
}
365
bold_fc_msdf->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
366
bold_fc_msdf->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
367
bold_fc_msdf->set_variation_opentype(bold_fc_opentype);
368
369
if (!String(EDITOR_GET("interface/editor/main_font_custom_opentype_features")).is_empty()) {
370
Vector<String> subtag = String(EDITOR_GET("interface/editor/main_font_custom_opentype_features")).split(",");
371
if (!subtag.is_empty()) {
372
Dictionary ftrs;
373
for (int i = 0; i < subtag.size(); i++) {
374
Vector<String> subtag_a = subtag[i].split("=");
375
if (subtag_a.size() == 2) {
376
ftrs[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int();
377
} else if (subtag_a.size() == 1) {
378
ftrs[TS->name_to_tag(subtag_a[0])] = 1;
379
}
380
}
381
default_fc->set_opentype_features(ftrs);
382
default_fc_msdf->set_opentype_features(ftrs);
383
bold_fc->set_opentype_features(ftrs);
384
bold_fc_msdf->set_opentype_features(ftrs);
385
}
386
}
387
388
Ref<FontVariation> mono_fc;
389
mono_fc.instantiate();
390
if (custom_font_path_source.length() > 0 && dir->file_exists(custom_font_path_source)) {
391
Ref<FontFile> custom_font = load_external_font(custom_font_path_source, font_mono_hinting, font_antialiasing, true, font_subpixel_positioning, font_disable_embedded_bitmaps);
392
{
393
TypedArray<Font> fallback_custom = { default_font_mono };
394
custom_font->set_fallbacks(fallback_custom);
395
}
396
mono_fc->set_base_font(custom_font);
397
} else {
398
EditorSettings::get_singleton()->set_manually("interface/editor/code_font", "");
399
mono_fc->set_base_font(default_font_mono);
400
}
401
mono_fc->set_spacing(TextServer::SPACING_TOP, -EDSCALE);
402
mono_fc->set_spacing(TextServer::SPACING_BOTTOM, -EDSCALE);
403
404
Ref<FontVariation> mono_other_fc = mono_fc->duplicate();
405
406
// Enable contextual alternates (coding ligatures) and custom features for the source editor font.
407
int ot_mode = EDITOR_GET("interface/editor/code_font_contextual_ligatures");
408
switch (ot_mode) {
409
case 1: { // Disable ligatures.
410
Dictionary ftrs;
411
ftrs[TS->name_to_tag("calt")] = 0;
412
mono_fc->set_opentype_features(ftrs);
413
} break;
414
case 2: { // Custom.
415
Vector<String> subtag = String(EDITOR_GET("interface/editor/code_font_custom_opentype_features")).split(",");
416
Dictionary ftrs;
417
for (int i = 0; i < subtag.size(); i++) {
418
Vector<String> subtag_a = subtag[i].split("=");
419
if (subtag_a.size() == 2) {
420
ftrs[TS->name_to_tag(subtag_a[0])] = subtag_a[1].to_int();
421
} else if (subtag_a.size() == 1) {
422
ftrs[TS->name_to_tag(subtag_a[0])] = 1;
423
}
424
}
425
mono_fc->set_opentype_features(ftrs);
426
} break;
427
default: { // Enabled.
428
Dictionary ftrs;
429
ftrs[TS->name_to_tag("calt")] = 1;
430
mono_fc->set_opentype_features(ftrs);
431
} break;
432
}
433
434
{
435
// Disable contextual alternates (coding ligatures).
436
Dictionary ftrs;
437
ftrs[TS->name_to_tag("calt")] = 0;
438
mono_other_fc->set_opentype_features(ftrs);
439
}
440
441
// Use fake bold/italics to style the editor log's `print_rich()` output.
442
// Use stronger embolden strength to make bold easier to distinguish from regular text.
443
Ref<FontVariation> mono_other_fc_bold = mono_other_fc->duplicate();
444
mono_other_fc_bold->set_variation_embolden(0.8);
445
446
Ref<FontVariation> mono_other_fc_italic = mono_other_fc->duplicate();
447
mono_other_fc_italic->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
448
449
Ref<FontVariation> mono_other_fc_bold_italic = mono_other_fc->duplicate();
450
mono_other_fc_bold_italic->set_variation_embolden(0.8);
451
mono_other_fc_bold_italic->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
452
453
Ref<FontVariation> mono_other_fc_mono = mono_other_fc->duplicate();
454
// Use a different font style to distinguish `[code]` in rich prints.
455
// This emulates the "faint" styling used in ANSI escape codes by using a slightly thinner font.
456
mono_other_fc_mono->set_variation_embolden(-0.25);
457
mono_other_fc_mono->set_variation_transform(Transform2D(1.0, 0.1, 0.0, 1.0, 0.0, 0.0));
458
459
Ref<FontVariation> italic_fc = default_fc->duplicate();
460
italic_fc->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
461
462
Ref<FontVariation> bold_italic_fc = bold_fc->duplicate();
463
bold_italic_fc->set_variation_transform(Transform2D(1.0, 0.2, 0.0, 1.0, 0.0, 0.0));
464
465
// Setup theme.
466
467
p_theme->set_default_font(default_fc); // Default theme font config.
468
p_theme->set_default_font_size(default_font_size);
469
470
// Main font.
471
472
p_theme->set_font("main", EditorStringName(EditorFonts), default_fc);
473
p_theme->set_font("main_msdf", EditorStringName(EditorFonts), default_fc_msdf);
474
p_theme->set_font_size("main_size", EditorStringName(EditorFonts), default_font_size);
475
476
p_theme->set_font("bold", EditorStringName(EditorFonts), bold_fc);
477
p_theme->set_font("main_bold_msdf", EditorStringName(EditorFonts), bold_fc_msdf);
478
p_theme->set_font_size("bold_size", EditorStringName(EditorFonts), default_font_size);
479
480
p_theme->set_font("italic", EditorStringName(EditorFonts), italic_fc);
481
p_theme->set_font_size("italic_size", EditorStringName(EditorFonts), default_font_size);
482
483
// Title font.
484
485
p_theme->set_font("title", EditorStringName(EditorFonts), bold_fc);
486
p_theme->set_font_size("title_size", EditorStringName(EditorFonts), default_font_size + 1 * EDSCALE);
487
488
p_theme->set_type_variation("MainScreenButton", "Button");
489
p_theme->set_font(SceneStringName(font), "MainScreenButton", bold_fc);
490
p_theme->set_font_size(SceneStringName(font_size), "MainScreenButton", default_font_size + 2 * EDSCALE);
491
492
// Labels.
493
494
p_theme->set_font(SceneStringName(font), "Label", default_fc);
495
496
p_theme->set_type_variation("HeaderSmall", "Label");
497
p_theme->set_font(SceneStringName(font), "HeaderSmall", bold_fc);
498
p_theme->set_font_size(SceneStringName(font_size), "HeaderSmall", default_font_size);
499
500
p_theme->set_type_variation("HeaderMedium", "Label");
501
p_theme->set_font(SceneStringName(font), "HeaderMedium", bold_fc);
502
p_theme->set_font_size(SceneStringName(font_size), "HeaderMedium", default_font_size + 1 * EDSCALE);
503
504
p_theme->set_type_variation("HeaderLarge", "Label");
505
p_theme->set_font(SceneStringName(font), "HeaderLarge", bold_fc);
506
p_theme->set_font_size(SceneStringName(font_size), "HeaderLarge", default_font_size + 3 * EDSCALE);
507
508
p_theme->set_font("normal_font", "RichTextLabel", default_fc);
509
p_theme->set_font("bold_font", "RichTextLabel", bold_fc);
510
p_theme->set_font("italics_font", "RichTextLabel", italic_fc);
511
p_theme->set_font("bold_italics_font", "RichTextLabel", bold_italic_fc);
512
513
// Documentation fonts
514
p_theme->set_font_size("doc_size", EditorStringName(EditorFonts), int(EDITOR_GET("text_editor/help/help_font_size")) * EDSCALE);
515
p_theme->set_font("doc", EditorStringName(EditorFonts), default_fc);
516
p_theme->set_font("doc_bold", EditorStringName(EditorFonts), bold_fc);
517
p_theme->set_font("doc_italic", EditorStringName(EditorFonts), italic_fc);
518
p_theme->set_font_size("doc_title_size", EditorStringName(EditorFonts), int(EDITOR_GET("text_editor/help/help_title_font_size")) * EDSCALE);
519
p_theme->set_font("doc_title", EditorStringName(EditorFonts), bold_fc);
520
p_theme->set_font_size("doc_source_size", EditorStringName(EditorFonts), int(EDITOR_GET("text_editor/help/help_source_font_size")) * EDSCALE);
521
p_theme->set_font("doc_source", EditorStringName(EditorFonts), mono_fc);
522
p_theme->set_font_size("doc_keyboard_size", EditorStringName(EditorFonts), (int(EDITOR_GET("text_editor/help/help_source_font_size")) - 1) * EDSCALE);
523
p_theme->set_font("doc_keyboard", EditorStringName(EditorFonts), mono_fc);
524
525
// Ruler font
526
p_theme->set_font_size("rulers_size", EditorStringName(EditorFonts), 8 * EDSCALE);
527
p_theme->set_font("rulers", EditorStringName(EditorFonts), default_fc);
528
529
// Rotation widget font
530
p_theme->set_font_size("rotation_control_size", EditorStringName(EditorFonts), 13 * EDSCALE);
531
p_theme->set_font("rotation_control", EditorStringName(EditorFonts), default_fc);
532
533
// Code font
534
p_theme->set_font_size("source_size", EditorStringName(EditorFonts), int(EDITOR_GET("interface/editor/code_font_size")) * EDSCALE);
535
p_theme->set_font("source", EditorStringName(EditorFonts), mono_fc);
536
537
p_theme->set_font_size("expression_size", EditorStringName(EditorFonts), (int(EDITOR_GET("interface/editor/code_font_size")) - 1) * EDSCALE);
538
p_theme->set_font("expression", EditorStringName(EditorFonts), mono_other_fc);
539
540
p_theme->set_font_size("output_source_size", EditorStringName(EditorFonts), int(EDITOR_GET("run/output/font_size")) * EDSCALE);
541
p_theme->set_font("output_source", EditorStringName(EditorFonts), mono_other_fc);
542
p_theme->set_font("output_source_bold", EditorStringName(EditorFonts), mono_other_fc_bold);
543
p_theme->set_font("output_source_italic", EditorStringName(EditorFonts), mono_other_fc_italic);
544
p_theme->set_font("output_source_bold_italic", EditorStringName(EditorFonts), mono_other_fc_bold_italic);
545
p_theme->set_font("output_source_mono", EditorStringName(EditorFonts), mono_other_fc_mono);
546
547
p_theme->set_font_size("status_source_size", EditorStringName(EditorFonts), default_font_size);
548
p_theme->set_font("status_source", EditorStringName(EditorFonts), mono_other_fc);
549
}
550
551