Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/resources/font.cpp
20816 views
1
/**************************************************************************/
2
/* font.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 "font.h"
32
#include "font.compat.inc"
33
34
#include "core/io/image_loader.h"
35
#include "core/templates/hash_map.h"
36
#include "core/templates/hashfuncs.h"
37
#include "scene/resources/image_texture.h"
38
#include "scene/resources/text_line.h"
39
#include "scene/resources/text_paragraph.h"
40
#include "scene/resources/theme.h"
41
#include "scene/theme/theme_db.h"
42
#include "servers/rendering/rendering_server.h"
43
44
/*************************************************************************/
45
/* Font */
46
/*************************************************************************/
47
48
void Font::_bind_methods() {
49
ClassDB::bind_method(D_METHOD("set_fallbacks", "fallbacks"), &Font::set_fallbacks);
50
ClassDB::bind_method(D_METHOD("get_fallbacks"), &Font::get_fallbacks);
51
52
// Output.
53
ClassDB::bind_method(D_METHOD("find_variation", "variation_coordinates", "face_index", "strength", "transform", "spacing_top", "spacing_bottom", "spacing_space", "spacing_glyph", "baseline_offset"), &Font::find_variation, DEFVAL(0), DEFVAL(0.0), DEFVAL(Transform2D()), DEFVAL(0), DEFVAL(0), DEFVAL(0), DEFVAL(0), DEFVAL(0.0));
54
ClassDB::bind_method(D_METHOD("get_rids"), &Font::get_rids);
55
56
// Font metrics.
57
ClassDB::bind_method(D_METHOD("get_height", "font_size"), &Font::get_height, DEFVAL(DEFAULT_FONT_SIZE));
58
ClassDB::bind_method(D_METHOD("get_ascent", "font_size"), &Font::get_ascent, DEFVAL(DEFAULT_FONT_SIZE));
59
ClassDB::bind_method(D_METHOD("get_descent", "font_size"), &Font::get_descent, DEFVAL(DEFAULT_FONT_SIZE));
60
ClassDB::bind_method(D_METHOD("get_underline_position", "font_size"), &Font::get_underline_position, DEFVAL(DEFAULT_FONT_SIZE));
61
ClassDB::bind_method(D_METHOD("get_underline_thickness", "font_size"), &Font::get_underline_thickness, DEFVAL(DEFAULT_FONT_SIZE));
62
63
ClassDB::bind_method(D_METHOD("get_font_name"), &Font::get_font_name);
64
ClassDB::bind_method(D_METHOD("get_font_style_name"), &Font::get_font_style_name);
65
ClassDB::bind_method(D_METHOD("get_ot_name_strings"), &Font::get_ot_name_strings);
66
ClassDB::bind_method(D_METHOD("get_font_style"), &Font::get_font_style);
67
ClassDB::bind_method(D_METHOD("get_font_weight"), &Font::get_font_weight);
68
ClassDB::bind_method(D_METHOD("get_font_stretch"), &Font::get_font_stretch);
69
70
ClassDB::bind_method(D_METHOD("get_spacing", "spacing"), &Font::get_spacing);
71
ClassDB::bind_method(D_METHOD("get_opentype_features"), &Font::get_opentype_features);
72
73
// Drawing string.
74
ClassDB::bind_method(D_METHOD("set_cache_capacity", "single_line", "multi_line"), &Font::set_cache_capacity);
75
76
ClassDB::bind_method(D_METHOD("get_string_size", "text", "alignment", "width", "font_size", "justification_flags", "direction", "orientation"), &Font::get_string_size, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
77
ClassDB::bind_method(D_METHOD("get_multiline_string_size", "text", "alignment", "width", "font_size", "max_lines", "brk_flags", "justification_flags", "direction", "orientation"), &Font::get_multiline_string_size, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
78
79
ClassDB::bind_method(D_METHOD("draw_string", "canvas_item", "pos", "text", "alignment", "width", "font_size", "modulate", "justification_flags", "direction", "orientation", "oversampling"), &Font::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL), DEFVAL(0.0));
80
ClassDB::bind_method(D_METHOD("draw_multiline_string", "canvas_item", "pos", "text", "alignment", "width", "font_size", "max_lines", "modulate", "brk_flags", "justification_flags", "direction", "orientation", "oversampling"), &Font::draw_multiline_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL), DEFVAL(0.0));
81
82
ClassDB::bind_method(D_METHOD("draw_string_outline", "canvas_item", "pos", "text", "alignment", "width", "font_size", "size", "modulate", "justification_flags", "direction", "orientation", "oversampling"), &Font::draw_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL), DEFVAL(0.0));
83
ClassDB::bind_method(D_METHOD("draw_multiline_string_outline", "canvas_item", "pos", "text", "alignment", "width", "font_size", "max_lines", "size", "modulate", "brk_flags", "justification_flags", "direction", "orientation", "oversampling"), &Font::draw_multiline_string_outline, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(DEFAULT_FONT_SIZE), DEFVAL(-1), DEFVAL(1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL), DEFVAL(0.0));
84
85
// Drawing char.
86
ClassDB::bind_method(D_METHOD("get_char_size", "char", "font_size"), &Font::get_char_size);
87
ClassDB::bind_method(D_METHOD("draw_char", "canvas_item", "pos", "char", "font_size", "modulate", "oversampling"), &Font::draw_char, DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(0.0));
88
ClassDB::bind_method(D_METHOD("draw_char_outline", "canvas_item", "pos", "char", "font_size", "size", "modulate", "oversampling"), &Font::draw_char_outline, DEFVAL(-1), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(0.0));
89
90
// Helper functions.
91
ClassDB::bind_method(D_METHOD("has_char", "char"), &Font::has_char);
92
ClassDB::bind_method(D_METHOD("get_supported_chars"), &Font::get_supported_chars);
93
94
ClassDB::bind_method(D_METHOD("is_language_supported", "language"), &Font::is_language_supported);
95
ClassDB::bind_method(D_METHOD("is_script_supported", "script"), &Font::is_script_supported);
96
97
ClassDB::bind_method(D_METHOD("get_supported_feature_list"), &Font::get_supported_feature_list);
98
ClassDB::bind_method(D_METHOD("get_supported_variation_list"), &Font::get_supported_variation_list);
99
ClassDB::bind_method(D_METHOD("get_face_count"), &Font::get_face_count);
100
101
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font")), "set_fallbacks", "get_fallbacks");
102
}
103
104
void Font::_update_rids_fb(const Font *p_f, int p_depth) const {
105
ERR_FAIL_COND(p_depth > MAX_FALLBACK_DEPTH);
106
if (p_f != nullptr) {
107
RID rid = p_f->_get_rid();
108
if (rid.is_valid()) {
109
rids.push_back(rid);
110
}
111
const TypedArray<Font> &_fallbacks = p_f->get_fallbacks();
112
for (int i = 0; i < _fallbacks.size(); i++) {
113
Ref<Font> fb_font = _fallbacks[i];
114
_update_rids_fb(fb_font.ptr(), p_depth + 1);
115
}
116
}
117
}
118
119
void Font::_update_rids() const {
120
rids.clear();
121
_update_rids_fb(this, 0);
122
dirty_rids = false;
123
}
124
125
void Font::_invalidate_rids() {
126
rids.clear();
127
dirty_rids = true;
128
129
cache.clear();
130
cache_wrap.clear();
131
132
emit_changed();
133
}
134
135
bool Font::_is_cyclic(const Ref<Font> &p_f, int p_depth) const {
136
ERR_FAIL_COND_V(p_depth > MAX_FALLBACK_DEPTH, true);
137
if (p_f.is_null()) {
138
return false;
139
}
140
if (p_f == this) {
141
return true;
142
}
143
for (int i = 0; i < p_f->fallbacks.size(); i++) {
144
const Ref<Font> &f = p_f->fallbacks[i];
145
if (_is_cyclic(f, p_depth + 1)) {
146
return true;
147
}
148
}
149
return false;
150
}
151
152
bool Font::_is_base_cyclic(const Ref<Font> &p_f, int p_depth) const {
153
ERR_FAIL_COND_V(p_depth > MAX_FALLBACK_DEPTH, true);
154
if (p_f.is_null()) {
155
return false;
156
}
157
if (p_f == this) {
158
return true;
159
}
160
Ref<FontVariation> fv = p_f;
161
if (fv.is_valid()) {
162
return _is_base_cyclic(fv->get_base_font(), p_depth + 1);
163
}
164
Ref<SystemFont> fs = p_f;
165
if (fs.is_valid()) {
166
return _is_base_cyclic(fs->get_base_font(), p_depth + 1);
167
}
168
return false;
169
}
170
171
void Font::reset_state() {
172
_invalidate_rids();
173
}
174
175
// Fallbacks.
176
void Font::set_fallbacks(const TypedArray<Font> &p_fallbacks) {
177
for (int i = 0; i < p_fallbacks.size(); i++) {
178
const Ref<Font> &f = p_fallbacks[i];
179
ERR_FAIL_COND_MSG(_is_cyclic(f, 0), "Cyclic font fallback.");
180
}
181
for (int i = 0; i < fallbacks.size(); i++) {
182
Ref<Font> f = fallbacks[i];
183
if (f.is_valid()) {
184
f->disconnect_changed(callable_mp(this, &Font::_invalidate_rids));
185
}
186
}
187
fallbacks = p_fallbacks;
188
for (int i = 0; i < fallbacks.size(); i++) {
189
Ref<Font> f = fallbacks[i];
190
if (f.is_valid()) {
191
f->connect_changed(callable_mp(this, &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
192
}
193
}
194
_invalidate_rids();
195
}
196
197
TypedArray<Font> Font::get_fallbacks() const {
198
return fallbacks;
199
}
200
201
// Output.
202
TypedArray<RID> Font::get_rids() const {
203
if (dirty_rids) {
204
_update_rids();
205
}
206
return rids;
207
}
208
209
// Drawing string.
210
real_t Font::get_height(int p_font_size) const {
211
if (dirty_rids) {
212
_update_rids();
213
}
214
215
real_t ret = 0.f;
216
for (int i = 0; i < rids.size(); i++) {
217
ret = MAX(ret, TS->font_get_ascent(rids.get(i), p_font_size) + TS->font_get_descent(rids.get(i), p_font_size));
218
}
219
return ret + get_spacing(TextServer::SPACING_BOTTOM) + get_spacing(TextServer::SPACING_TOP);
220
}
221
222
real_t Font::get_ascent(int p_font_size) const {
223
if (dirty_rids) {
224
_update_rids();
225
}
226
real_t ret = 0.f;
227
for (int i = 0; i < rids.size(); i++) {
228
ret = MAX(ret, TS->font_get_ascent(rids.get(i), p_font_size));
229
}
230
return ret + get_spacing(TextServer::SPACING_TOP);
231
}
232
233
real_t Font::get_descent(int p_font_size) const {
234
if (dirty_rids) {
235
_update_rids();
236
}
237
real_t ret = 0.f;
238
for (int i = 0; i < rids.size(); i++) {
239
ret = MAX(ret, TS->font_get_descent(rids.get(i), p_font_size));
240
}
241
return ret + get_spacing(TextServer::SPACING_BOTTOM);
242
}
243
244
real_t Font::get_underline_position(int p_font_size) const {
245
if (dirty_rids) {
246
_update_rids();
247
}
248
real_t ret = 0.f;
249
for (int i = 0; i < rids.size(); i++) {
250
ret = MAX(ret, TS->font_get_underline_position(rids.get(i), p_font_size));
251
}
252
return ret + get_spacing(TextServer::SPACING_TOP);
253
}
254
255
real_t Font::get_underline_thickness(int p_font_size) const {
256
if (dirty_rids) {
257
_update_rids();
258
}
259
real_t ret = 0.f;
260
for (int i = 0; i < rids.size(); i++) {
261
ret = MAX(ret, TS->font_get_underline_thickness(rids.get(i), p_font_size));
262
}
263
return ret;
264
}
265
266
String Font::get_font_name() const {
267
return TS->font_get_name(_get_rid());
268
}
269
270
Dictionary Font::get_ot_name_strings() const {
271
return TS->font_get_ot_name_strings(_get_rid());
272
}
273
274
String Font::get_font_style_name() const {
275
return TS->font_get_style_name(_get_rid());
276
}
277
278
BitField<TextServer::FontStyle> Font::get_font_style() const {
279
return TS->font_get_style(_get_rid());
280
}
281
282
int Font::get_font_weight() const {
283
return TS->font_get_weight(_get_rid());
284
}
285
286
int Font::get_font_stretch() const {
287
return TS->font_get_stretch(_get_rid());
288
}
289
290
Dictionary Font::get_opentype_features() const {
291
return Dictionary();
292
}
293
294
// Drawing string.
295
void Font::set_cache_capacity(int p_single_line, int p_multi_line) {
296
cache.set_capacity(p_single_line);
297
cache_wrap.set_capacity(p_multi_line);
298
}
299
300
Size2 Font::get_string_size(const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
301
bool fill = (p_alignment == HORIZONTAL_ALIGNMENT_FILL);
302
ShapedTextKey key = ShapedTextKey(p_text, p_font_size, fill ? p_width : 0.0, fill ? p_jst_flags : BitField(TextServer::JUSTIFICATION_NONE), TextServer::BREAK_NONE, p_direction, p_orientation);
303
304
Ref<TextLine> buffer;
305
if (cache.has(key)) {
306
buffer = cache.get(key);
307
} else {
308
buffer.instantiate();
309
buffer->set_direction(p_direction);
310
buffer->set_orientation(p_orientation);
311
buffer->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_CHAR);
312
buffer->add_string(p_text, Ref<Font>(this), p_font_size);
313
cache.insert(key, buffer);
314
}
315
316
buffer->set_width(p_width);
317
buffer->set_horizontal_alignment(p_alignment);
318
if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
319
buffer->set_flags(p_jst_flags);
320
}
321
322
return buffer->get_size();
323
}
324
325
Size2 Font::get_multiline_string_size(const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const {
326
ShapedTextKey key = ShapedTextKey(p_text, p_font_size, p_width, p_jst_flags, p_brk_flags, p_direction, p_orientation);
327
328
Ref<TextParagraph> lines_buffer;
329
if (cache_wrap.has(key)) {
330
lines_buffer = cache_wrap.get(key);
331
} else {
332
lines_buffer.instantiate();
333
lines_buffer->set_direction(p_direction);
334
lines_buffer->set_orientation(p_orientation);
335
lines_buffer->add_string(p_text, Ref<Font>(this), p_font_size);
336
lines_buffer->set_width(p_width);
337
lines_buffer->set_break_flags(p_brk_flags);
338
lines_buffer->set_justification_flags(p_jst_flags);
339
lines_buffer->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_CHAR);
340
cache_wrap.insert(key, lines_buffer);
341
}
342
343
lines_buffer->set_alignment(p_alignment);
344
lines_buffer->set_max_lines_visible(p_max_lines);
345
346
return lines_buffer->get_size();
347
}
348
349
void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, const Color &p_modulate, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation, float p_oversampling) const {
350
bool fill = (p_alignment == HORIZONTAL_ALIGNMENT_FILL);
351
ShapedTextKey key = ShapedTextKey(p_text, p_font_size, fill ? p_width : 0.0, fill ? p_jst_flags : BitField(TextServer::JUSTIFICATION_NONE), TextServer::BREAK_NONE, p_direction, p_orientation);
352
353
Ref<TextLine> buffer;
354
if (cache.has(key)) {
355
buffer = cache.get(key);
356
} else {
357
buffer.instantiate();
358
buffer->set_direction(p_direction);
359
buffer->set_orientation(p_orientation);
360
buffer->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_CHAR);
361
buffer->add_string(p_text, Ref<Font>(this), p_font_size);
362
cache.insert(key, buffer);
363
}
364
365
Vector2 ofs = p_pos;
366
if (p_orientation == TextServer::ORIENTATION_HORIZONTAL) {
367
ofs.y -= buffer->get_line_ascent();
368
} else {
369
ofs.x -= buffer->get_line_ascent();
370
}
371
372
buffer->set_width(p_width);
373
buffer->set_horizontal_alignment(p_alignment);
374
if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
375
buffer->set_flags(p_jst_flags);
376
}
377
378
buffer->draw(p_canvas_item, ofs, p_modulate, p_oversampling);
379
}
380
381
void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, const Color &p_modulate, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation, float p_oversampling) const {
382
ShapedTextKey key = ShapedTextKey(p_text, p_font_size, p_width, p_jst_flags, p_brk_flags, p_direction, p_orientation);
383
384
Ref<TextParagraph> lines_buffer;
385
if (cache_wrap.has(key)) {
386
lines_buffer = cache_wrap.get(key);
387
} else {
388
lines_buffer.instantiate();
389
lines_buffer->set_direction(p_direction);
390
lines_buffer->set_orientation(p_orientation);
391
lines_buffer->add_string(p_text, Ref<Font>(this), p_font_size);
392
lines_buffer->set_width(p_width);
393
lines_buffer->set_break_flags(p_brk_flags);
394
lines_buffer->set_justification_flags(p_jst_flags);
395
lines_buffer->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_CHAR);
396
cache_wrap.insert(key, lines_buffer);
397
}
398
399
Vector2 ofs = p_pos;
400
if (p_orientation == TextServer::ORIENTATION_HORIZONTAL) {
401
ofs.y -= lines_buffer->get_line_ascent(0);
402
} else {
403
ofs.x -= lines_buffer->get_line_ascent(0);
404
}
405
406
lines_buffer->set_alignment(p_alignment);
407
lines_buffer->set_max_lines_visible(p_max_lines);
408
409
lines_buffer->draw(p_canvas_item, ofs, p_modulate, p_modulate, p_oversampling);
410
}
411
412
void Font::draw_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_size, const Color &p_modulate, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation, float p_oversampling) const {
413
bool fill = (p_alignment == HORIZONTAL_ALIGNMENT_FILL);
414
ShapedTextKey key = ShapedTextKey(p_text, p_font_size, fill ? p_width : 0.0, fill ? p_jst_flags : BitField(TextServer::JUSTIFICATION_NONE), TextServer::BREAK_NONE, p_direction, p_orientation);
415
416
Ref<TextLine> buffer;
417
if (cache.has(key)) {
418
buffer = cache.get(key);
419
} else {
420
buffer.instantiate();
421
buffer->set_direction(p_direction);
422
buffer->set_orientation(p_orientation);
423
buffer->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_CHAR);
424
buffer->add_string(p_text, Ref<Font>(this), p_font_size);
425
cache.insert(key, buffer);
426
}
427
428
Vector2 ofs = p_pos;
429
if (p_orientation == TextServer::ORIENTATION_HORIZONTAL) {
430
ofs.y -= buffer->get_line_ascent();
431
} else {
432
ofs.x -= buffer->get_line_ascent();
433
}
434
435
buffer->set_width(p_width);
436
buffer->set_horizontal_alignment(p_alignment);
437
if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) {
438
buffer->set_flags(p_jst_flags);
439
}
440
441
buffer->draw_outline(p_canvas_item, ofs, p_size, p_modulate, p_oversampling);
442
}
443
444
void Font::draw_multiline_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, int p_size, const Color &p_modulate, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation, float p_oversampling) const {
445
ShapedTextKey key = ShapedTextKey(p_text, p_font_size, p_width, p_jst_flags, p_brk_flags, p_direction, p_orientation);
446
447
Ref<TextParagraph> lines_buffer;
448
if (cache_wrap.has(key)) {
449
lines_buffer = cache_wrap.get(key);
450
} else {
451
lines_buffer.instantiate();
452
lines_buffer->set_direction(p_direction);
453
lines_buffer->set_orientation(p_orientation);
454
lines_buffer->add_string(p_text, Ref<Font>(this), p_font_size);
455
lines_buffer->set_width(p_width);
456
lines_buffer->set_break_flags(p_brk_flags);
457
lines_buffer->set_justification_flags(p_jst_flags);
458
lines_buffer->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_CHAR);
459
cache_wrap.insert(key, lines_buffer);
460
}
461
462
Vector2 ofs = p_pos;
463
if (p_orientation == TextServer::ORIENTATION_HORIZONTAL) {
464
ofs.y -= lines_buffer->get_line_ascent(0);
465
} else {
466
ofs.x -= lines_buffer->get_line_ascent(0);
467
}
468
469
lines_buffer->set_alignment(p_alignment);
470
lines_buffer->set_max_lines_visible(p_max_lines);
471
472
lines_buffer->draw_outline(p_canvas_item, ofs, p_size, p_modulate, p_modulate, p_oversampling);
473
}
474
475
// Drawing char.
476
Size2 Font::get_char_size(char32_t p_char, int p_font_size) const {
477
if (dirty_rids) {
478
_update_rids();
479
}
480
for (int i = 0; i < rids.size(); i++) {
481
if (TS->font_has_char(rids.get(i), p_char)) {
482
int32_t glyph = TS->font_get_glyph_index(rids.get(i), p_font_size, p_char, 0);
483
return Size2(TS->font_get_glyph_advance(rids.get(i), p_font_size, glyph).x, get_height(p_font_size));
484
}
485
}
486
return Size2();
487
}
488
489
real_t Font::draw_char(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, int p_font_size, const Color &p_modulate, float p_oversampling) const {
490
if (dirty_rids) {
491
_update_rids();
492
}
493
for (int i = 0; i < rids.size(); i++) {
494
if (TS->font_has_char(rids.get(i), p_char)) {
495
int32_t glyph = TS->font_get_glyph_index(rids.get(i), p_font_size, p_char, 0);
496
TS->font_draw_glyph(rids.get(i), p_canvas_item, p_font_size, p_pos, glyph, p_modulate, p_oversampling);
497
return TS->font_get_glyph_advance(rids.get(i), p_font_size, glyph).x;
498
}
499
}
500
return 0.f;
501
}
502
503
real_t Font::draw_char_outline(RID p_canvas_item, const Point2 &p_pos, char32_t p_char, int p_font_size, int p_size, const Color &p_modulate, float p_oversampling) const {
504
if (dirty_rids) {
505
_update_rids();
506
}
507
for (int i = 0; i < rids.size(); i++) {
508
if (TS->font_has_char(rids.get(i), p_char)) {
509
int32_t glyph = TS->font_get_glyph_index(rids.get(i), p_font_size, p_char, 0);
510
TS->font_draw_glyph_outline(rids.get(i), p_canvas_item, p_font_size, p_size, p_pos, glyph, p_modulate, p_oversampling);
511
return TS->font_get_glyph_advance(rids.get(i), p_font_size, glyph).x;
512
}
513
}
514
return 0.f;
515
}
516
517
// Helper functions.
518
bool Font::has_char(char32_t p_char) const {
519
if (dirty_rids) {
520
_update_rids();
521
}
522
for (int i = 0; i < rids.size(); i++) {
523
if (TS->font_has_char(rids.get(i), p_char)) {
524
return true;
525
}
526
}
527
return false;
528
}
529
530
String Font::get_supported_chars() const {
531
if (dirty_rids) {
532
_update_rids();
533
}
534
String chars;
535
for (int i = 0; i < rids.size(); i++) {
536
String data_chars = TS->font_get_supported_chars(rids.get(i));
537
for (int j = 0; j < data_chars.length(); j++) {
538
if (chars.find_char(data_chars[j]) == -1) {
539
chars += data_chars[j];
540
}
541
}
542
}
543
return chars;
544
}
545
546
bool Font::is_language_supported(const String &p_language) const {
547
return TS->font_is_language_supported(_get_rid(), p_language);
548
}
549
550
bool Font::is_script_supported(const String &p_script) const {
551
return TS->font_is_script_supported(_get_rid(), p_script);
552
}
553
554
Dictionary Font::get_supported_feature_list() const {
555
return TS->font_supported_feature_list(_get_rid());
556
}
557
558
Dictionary Font::get_supported_variation_list() const {
559
return TS->font_supported_variation_list(_get_rid());
560
}
561
562
int64_t Font::get_face_count() const {
563
return TS->font_get_face_count(_get_rid());
564
}
565
566
Font::Font() {
567
cache.set_capacity(64);
568
cache_wrap.set_capacity(16);
569
}
570
571
Font::~Font() {
572
}
573
574
/*************************************************************************/
575
/* FontFile */
576
/*************************************************************************/
577
578
_FORCE_INLINE_ void FontFile::_clear_cache() {
579
for (int i = 0; i < cache.size(); i++) {
580
if (cache[i].is_valid()) {
581
TS->free_rid(cache[i]);
582
cache.write[i] = RID();
583
}
584
}
585
}
586
587
_FORCE_INLINE_ void FontFile::_ensure_rid(int p_cache_index, int p_make_linked_from) const {
588
if (unlikely(p_cache_index >= cache.size())) {
589
cache.resize(p_cache_index + 1);
590
}
591
if (unlikely(!cache[p_cache_index].is_valid())) {
592
if (p_make_linked_from >= 0 && p_make_linked_from != p_cache_index && p_make_linked_from < cache.size()) {
593
cache.write[p_cache_index] = TS->create_font_linked_variation(cache[p_make_linked_from]);
594
} else {
595
cache.write[p_cache_index] = TS->create_font();
596
TS->font_set_data_ptr(cache[p_cache_index], data_ptr, data_size);
597
TS->font_set_antialiasing(cache[p_cache_index], antialiasing);
598
TS->font_set_generate_mipmaps(cache[p_cache_index], mipmaps);
599
TS->font_set_disable_embedded_bitmaps(cache[p_cache_index], disable_embedded_bitmaps);
600
TS->font_set_multichannel_signed_distance_field(cache[p_cache_index], msdf);
601
TS->font_set_msdf_pixel_range(cache[p_cache_index], msdf_pixel_range);
602
TS->font_set_msdf_size(cache[p_cache_index], msdf_size);
603
TS->font_set_fixed_size(cache[p_cache_index], fixed_size);
604
TS->font_set_fixed_size_scale_mode(cache[p_cache_index], fixed_size_scale_mode);
605
TS->font_set_force_autohinter(cache[p_cache_index], force_autohinter);
606
TS->font_set_modulate_color_glyphs(cache[p_cache_index], modulate_color_glyphs);
607
TS->font_set_allow_system_fallback(cache[p_cache_index], allow_system_fallback);
608
TS->font_set_hinting(cache[p_cache_index], hinting);
609
TS->font_set_subpixel_positioning(cache[p_cache_index], subpixel_positioning);
610
TS->font_set_keep_rounding_remainders(cache[p_cache_index], keep_rounding_remainders);
611
TS->font_set_oversampling(cache[p_cache_index], oversampling_override);
612
for (const KeyValue<String, bool> &E : script_support_overrides) {
613
TS->font_set_script_support_override(cache[p_cache_index], E.key, E.value);
614
}
615
for (const KeyValue<String, bool> &E : language_support_overrides) {
616
TS->font_set_language_support_override(cache[p_cache_index], E.key, E.value);
617
}
618
TS->font_set_opentype_feature_overrides(cache[p_cache_index], feature_overrides);
619
}
620
}
621
}
622
623
void FontFile::_convert_packed_8bit(Ref<Image> &p_source, int p_page, int p_sz) {
624
int w = p_source->get_width();
625
int h = p_source->get_height();
626
627
PackedByteArray imgdata = p_source->get_data();
628
const uint8_t *r = imgdata.ptr();
629
630
PackedByteArray imgdata_r;
631
imgdata_r.resize(w * h * 2);
632
uint8_t *wr = imgdata_r.ptrw();
633
634
PackedByteArray imgdata_g;
635
imgdata_g.resize(w * h * 2);
636
uint8_t *wg = imgdata_g.ptrw();
637
638
PackedByteArray imgdata_b;
639
imgdata_b.resize(w * h * 2);
640
uint8_t *wb = imgdata_b.ptrw();
641
642
PackedByteArray imgdata_a;
643
imgdata_a.resize(w * h * 2);
644
uint8_t *wa = imgdata_a.ptrw();
645
646
for (int i = 0; i < h; i++) {
647
for (int j = 0; j < w; j++) {
648
int ofs_src = (i * w + j) * 4;
649
int ofs_dst = (i * w + j) * 2;
650
wr[ofs_dst + 0] = 255;
651
wr[ofs_dst + 1] = r[ofs_src + 0];
652
wg[ofs_dst + 0] = 255;
653
wg[ofs_dst + 1] = r[ofs_src + 1];
654
wb[ofs_dst + 0] = 255;
655
wb[ofs_dst + 1] = r[ofs_src + 2];
656
wa[ofs_dst + 0] = 255;
657
wa[ofs_dst + 1] = r[ofs_src + 3];
658
}
659
}
660
Ref<Image> img_r = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_r));
661
set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 0, img_r);
662
Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_g));
663
set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 1, img_g);
664
Ref<Image> img_b = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_b));
665
set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 2, img_b);
666
Ref<Image> img_a = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_a));
667
set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 3, img_a);
668
}
669
670
void FontFile::_convert_packed_4bit(Ref<Image> &p_source, int p_page, int p_sz) {
671
int w = p_source->get_width();
672
int h = p_source->get_height();
673
674
PackedByteArray imgdata = p_source->get_data();
675
const uint8_t *r = imgdata.ptr();
676
677
PackedByteArray imgdata_r;
678
imgdata_r.resize(w * h * 2);
679
uint8_t *wr = imgdata_r.ptrw();
680
681
PackedByteArray imgdata_g;
682
imgdata_g.resize(w * h * 2);
683
uint8_t *wg = imgdata_g.ptrw();
684
685
PackedByteArray imgdata_b;
686
imgdata_b.resize(w * h * 2);
687
uint8_t *wb = imgdata_b.ptrw();
688
689
PackedByteArray imgdata_a;
690
imgdata_a.resize(w * h * 2);
691
uint8_t *wa = imgdata_a.ptrw();
692
693
PackedByteArray imgdata_ro;
694
imgdata_ro.resize(w * h * 2);
695
uint8_t *wro = imgdata_ro.ptrw();
696
697
PackedByteArray imgdata_go;
698
imgdata_go.resize(w * h * 2);
699
uint8_t *wgo = imgdata_go.ptrw();
700
701
PackedByteArray imgdata_bo;
702
imgdata_bo.resize(w * h * 2);
703
uint8_t *wbo = imgdata_bo.ptrw();
704
705
PackedByteArray imgdata_ao;
706
imgdata_ao.resize(w * h * 2);
707
uint8_t *wao = imgdata_ao.ptrw();
708
709
for (int i = 0; i < h; i++) {
710
for (int j = 0; j < w; j++) {
711
int ofs_src = (i * w + j) * 4;
712
int ofs_dst = (i * w + j) * 2;
713
wr[ofs_dst + 0] = 255;
714
wro[ofs_dst + 0] = 255;
715
if (r[ofs_src + 0] > 0x0F) {
716
wr[ofs_dst + 1] = (r[ofs_src + 0] - 0x0F) * 2;
717
wro[ofs_dst + 1] = 0;
718
} else {
719
wr[ofs_dst + 1] = 0;
720
wro[ofs_dst + 1] = r[ofs_src + 0] * 2;
721
}
722
wg[ofs_dst + 0] = 255;
723
wgo[ofs_dst + 0] = 255;
724
if (r[ofs_src + 1] > 0x0F) {
725
wg[ofs_dst + 1] = (r[ofs_src + 1] - 0x0F) * 2;
726
wgo[ofs_dst + 1] = 0;
727
} else {
728
wg[ofs_dst + 1] = 0;
729
wgo[ofs_dst + 1] = r[ofs_src + 1] * 2;
730
}
731
wb[ofs_dst + 0] = 255;
732
wbo[ofs_dst + 0] = 255;
733
if (r[ofs_src + 2] > 0x0F) {
734
wb[ofs_dst + 1] = (r[ofs_src + 2] - 0x0F) * 2;
735
wbo[ofs_dst + 1] = 0;
736
} else {
737
wb[ofs_dst + 1] = 0;
738
wbo[ofs_dst + 1] = r[ofs_src + 2] * 2;
739
}
740
wa[ofs_dst + 0] = 255;
741
wao[ofs_dst + 0] = 255;
742
if (r[ofs_src + 3] > 0x0F) {
743
wa[ofs_dst + 1] = (r[ofs_src + 3] - 0x0F) * 2;
744
wao[ofs_dst + 1] = 0;
745
} else {
746
wa[ofs_dst + 1] = 0;
747
wao[ofs_dst + 1] = r[ofs_src + 3] * 2;
748
}
749
}
750
}
751
Ref<Image> img_r = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_r));
752
set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 0, img_r);
753
Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_g));
754
set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 1, img_g);
755
Ref<Image> img_b = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_b));
756
set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 2, img_b);
757
Ref<Image> img_a = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_a));
758
set_texture_image(0, Vector2i(p_sz, 0), p_page * 4 + 3, img_a);
759
760
Ref<Image> img_ro = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_ro));
761
set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 0, img_ro);
762
Ref<Image> img_go = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_go));
763
set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 1, img_go);
764
Ref<Image> img_bo = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_bo));
765
set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 2, img_bo);
766
Ref<Image> img_ao = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_ao));
767
set_texture_image(0, Vector2i(p_sz, 1), p_page * 4 + 3, img_ao);
768
}
769
770
void FontFile::_convert_rgba_4bit(Ref<Image> &p_source, int p_page, int p_sz) {
771
int w = p_source->get_width();
772
int h = p_source->get_height();
773
774
PackedByteArray imgdata = p_source->get_data();
775
const uint8_t *r = imgdata.ptr();
776
777
PackedByteArray imgdata_g;
778
imgdata_g.resize(w * h * 4);
779
uint8_t *wg = imgdata_g.ptrw();
780
781
PackedByteArray imgdata_o;
782
imgdata_o.resize(w * h * 4);
783
uint8_t *wo = imgdata_o.ptrw();
784
785
for (int i = 0; i < h; i++) {
786
for (int j = 0; j < w; j++) {
787
int ofs = (i * w + j) * 4;
788
789
if (r[ofs + 0] > 0x7F) {
790
wg[ofs + 0] = r[ofs + 0];
791
wo[ofs + 0] = 0;
792
} else {
793
wg[ofs + 0] = 0;
794
wo[ofs + 0] = r[ofs + 0] * 2;
795
}
796
if (r[ofs + 1] > 0x7F) {
797
wg[ofs + 1] = r[ofs + 1];
798
wo[ofs + 1] = 0;
799
} else {
800
wg[ofs + 1] = 0;
801
wo[ofs + 1] = r[ofs + 1] * 2;
802
}
803
if (r[ofs + 2] > 0x7F) {
804
wg[ofs + 2] = r[ofs + 2];
805
wo[ofs + 2] = 0;
806
} else {
807
wg[ofs + 2] = 0;
808
wo[ofs + 2] = r[ofs + 2] * 2;
809
}
810
if (r[ofs + 3] > 0x7F) {
811
wg[ofs + 3] = r[ofs + 3];
812
wo[ofs + 3] = 0;
813
} else {
814
wg[ofs + 3] = 0;
815
wo[ofs + 3] = r[ofs + 3] * 2;
816
}
817
}
818
}
819
Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_RGBA8, imgdata_g));
820
set_texture_image(0, Vector2i(p_sz, 0), p_page, img_g);
821
822
Ref<Image> img_o = memnew(Image(w, h, false, Image::FORMAT_RGBA8, imgdata_o));
823
set_texture_image(0, Vector2i(p_sz, 1), p_page, img_o);
824
}
825
826
void FontFile::_convert_mono_8bit(Ref<Image> &p_source, int p_page, int p_ch, int p_sz, int p_ol) {
827
int w = p_source->get_width();
828
int h = p_source->get_height();
829
830
PackedByteArray imgdata = p_source->get_data();
831
const uint8_t *r = imgdata.ptr();
832
833
int size = 4;
834
if (p_source->get_format() == Image::FORMAT_L8) {
835
size = 1;
836
p_ch = 0;
837
}
838
839
PackedByteArray imgdata_g;
840
imgdata_g.resize(w * h * 2);
841
uint8_t *wg = imgdata_g.ptrw();
842
843
for (int i = 0; i < h; i++) {
844
for (int j = 0; j < w; j++) {
845
int ofs_src = (i * w + j) * size;
846
int ofs_dst = (i * w + j) * 2;
847
wg[ofs_dst + 0] = 255;
848
wg[ofs_dst + 1] = r[ofs_src + p_ch];
849
}
850
}
851
Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_g));
852
set_texture_image(0, Vector2i(p_sz, p_ol), p_page, img_g);
853
}
854
855
void FontFile::_convert_mono_4bit(Ref<Image> &p_source, int p_page, int p_ch, int p_sz, int p_ol) {
856
int w = p_source->get_width();
857
int h = p_source->get_height();
858
859
PackedByteArray imgdata = p_source->get_data();
860
const uint8_t *r = imgdata.ptr();
861
862
int size = 4;
863
if (p_source->get_format() == Image::FORMAT_L8) {
864
size = 1;
865
p_ch = 0;
866
}
867
868
PackedByteArray imgdata_g;
869
imgdata_g.resize(w * h * 2);
870
uint8_t *wg = imgdata_g.ptrw();
871
872
PackedByteArray imgdata_o;
873
imgdata_o.resize(w * h * 2);
874
uint8_t *wo = imgdata_o.ptrw();
875
876
for (int i = 0; i < h; i++) {
877
for (int j = 0; j < w; j++) {
878
int ofs_src = (i * w + j) * size;
879
int ofs_dst = (i * w + j) * 2;
880
wg[ofs_dst + 0] = 255;
881
wo[ofs_dst + 0] = 255;
882
if (r[ofs_src + p_ch] > 0x7F) {
883
wg[ofs_dst + 1] = r[ofs_src + p_ch];
884
wo[ofs_dst + 1] = 0;
885
} else {
886
wg[ofs_dst + 1] = 0;
887
wo[ofs_dst + 1] = r[ofs_src + p_ch] * 2;
888
}
889
}
890
}
891
Ref<Image> img_g = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_g));
892
set_texture_image(0, Vector2i(p_sz, 0), p_page, img_g);
893
894
Ref<Image> img_o = memnew(Image(w, h, false, Image::FORMAT_LA8, imgdata_o));
895
set_texture_image(0, Vector2i(p_sz, p_ol), p_page, img_o);
896
}
897
898
void FontFile::_bind_methods() {
899
ClassDB::bind_method(D_METHOD("load_bitmap_font", "path"), &FontFile::load_bitmap_font);
900
ClassDB::bind_method(D_METHOD("load_dynamic_font", "path"), &FontFile::load_dynamic_font);
901
902
ClassDB::bind_method(D_METHOD("set_data", "data"), &FontFile::set_data);
903
ClassDB::bind_method(D_METHOD("get_data"), &FontFile::get_data);
904
905
ClassDB::bind_method(D_METHOD("set_font_name", "name"), &FontFile::set_font_name);
906
ClassDB::bind_method(D_METHOD("set_font_style_name", "name"), &FontFile::set_font_style_name);
907
ClassDB::bind_method(D_METHOD("set_font_style", "style"), &FontFile::set_font_style);
908
ClassDB::bind_method(D_METHOD("set_font_weight", "weight"), &FontFile::set_font_weight);
909
ClassDB::bind_method(D_METHOD("set_font_stretch", "stretch"), &FontFile::set_font_stretch);
910
911
ClassDB::bind_method(D_METHOD("set_antialiasing", "antialiasing"), &FontFile::set_antialiasing);
912
ClassDB::bind_method(D_METHOD("get_antialiasing"), &FontFile::get_antialiasing);
913
914
ClassDB::bind_method(D_METHOD("set_disable_embedded_bitmaps", "disable_embedded_bitmaps"), &FontFile::set_disable_embedded_bitmaps);
915
ClassDB::bind_method(D_METHOD("get_disable_embedded_bitmaps"), &FontFile::get_disable_embedded_bitmaps);
916
917
ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &FontFile::set_generate_mipmaps);
918
ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &FontFile::get_generate_mipmaps);
919
920
ClassDB::bind_method(D_METHOD("set_multichannel_signed_distance_field", "msdf"), &FontFile::set_multichannel_signed_distance_field);
921
ClassDB::bind_method(D_METHOD("is_multichannel_signed_distance_field"), &FontFile::is_multichannel_signed_distance_field);
922
923
ClassDB::bind_method(D_METHOD("set_msdf_pixel_range", "msdf_pixel_range"), &FontFile::set_msdf_pixel_range);
924
ClassDB::bind_method(D_METHOD("get_msdf_pixel_range"), &FontFile::get_msdf_pixel_range);
925
926
ClassDB::bind_method(D_METHOD("set_msdf_size", "msdf_size"), &FontFile::set_msdf_size);
927
ClassDB::bind_method(D_METHOD("get_msdf_size"), &FontFile::get_msdf_size);
928
929
ClassDB::bind_method(D_METHOD("set_fixed_size", "fixed_size"), &FontFile::set_fixed_size);
930
ClassDB::bind_method(D_METHOD("get_fixed_size"), &FontFile::get_fixed_size);
931
932
ClassDB::bind_method(D_METHOD("set_fixed_size_scale_mode", "fixed_size_scale_mode"), &FontFile::set_fixed_size_scale_mode);
933
ClassDB::bind_method(D_METHOD("get_fixed_size_scale_mode"), &FontFile::get_fixed_size_scale_mode);
934
935
ClassDB::bind_method(D_METHOD("set_allow_system_fallback", "allow_system_fallback"), &FontFile::set_allow_system_fallback);
936
ClassDB::bind_method(D_METHOD("is_allow_system_fallback"), &FontFile::is_allow_system_fallback);
937
938
ClassDB::bind_method(D_METHOD("set_force_autohinter", "force_autohinter"), &FontFile::set_force_autohinter);
939
ClassDB::bind_method(D_METHOD("is_force_autohinter"), &FontFile::is_force_autohinter);
940
941
ClassDB::bind_method(D_METHOD("set_modulate_color_glyphs", "modulate"), &FontFile::set_modulate_color_glyphs);
942
ClassDB::bind_method(D_METHOD("is_modulate_color_glyphs"), &FontFile::is_modulate_color_glyphs);
943
944
ClassDB::bind_method(D_METHOD("set_hinting", "hinting"), &FontFile::set_hinting);
945
ClassDB::bind_method(D_METHOD("get_hinting"), &FontFile::get_hinting);
946
947
ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &FontFile::set_subpixel_positioning);
948
ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &FontFile::get_subpixel_positioning);
949
950
ClassDB::bind_method(D_METHOD("set_keep_rounding_remainders", "keep_rounding_remainders"), &FontFile::set_keep_rounding_remainders);
951
ClassDB::bind_method(D_METHOD("get_keep_rounding_remainders"), &FontFile::get_keep_rounding_remainders);
952
953
ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &FontFile::set_oversampling);
954
ClassDB::bind_method(D_METHOD("get_oversampling"), &FontFile::get_oversampling);
955
956
ClassDB::bind_method(D_METHOD("get_cache_count"), &FontFile::get_cache_count);
957
ClassDB::bind_method(D_METHOD("clear_cache"), &FontFile::clear_cache);
958
ClassDB::bind_method(D_METHOD("remove_cache", "cache_index"), &FontFile::remove_cache);
959
960
ClassDB::bind_method(D_METHOD("get_size_cache_list", "cache_index"), &FontFile::get_size_cache_list);
961
ClassDB::bind_method(D_METHOD("clear_size_cache", "cache_index"), &FontFile::clear_size_cache);
962
ClassDB::bind_method(D_METHOD("remove_size_cache", "cache_index", "size"), &FontFile::remove_size_cache);
963
964
ClassDB::bind_method(D_METHOD("set_variation_coordinates", "cache_index", "variation_coordinates"), &FontFile::set_variation_coordinates);
965
ClassDB::bind_method(D_METHOD("get_variation_coordinates", "cache_index"), &FontFile::get_variation_coordinates);
966
967
ClassDB::bind_method(D_METHOD("set_embolden", "cache_index", "strength"), &FontFile::set_embolden);
968
ClassDB::bind_method(D_METHOD("get_embolden", "cache_index"), &FontFile::get_embolden);
969
970
ClassDB::bind_method(D_METHOD("set_transform", "cache_index", "transform"), &FontFile::set_transform);
971
ClassDB::bind_method(D_METHOD("get_transform", "cache_index"), &FontFile::get_transform);
972
973
ClassDB::bind_method(D_METHOD("set_extra_spacing", "cache_index", "spacing", "value"), &FontFile::set_extra_spacing);
974
ClassDB::bind_method(D_METHOD("get_extra_spacing", "cache_index", "spacing"), &FontFile::get_extra_spacing);
975
976
ClassDB::bind_method(D_METHOD("set_extra_baseline_offset", "cache_index", "baseline_offset"), &FontFile::set_extra_baseline_offset);
977
ClassDB::bind_method(D_METHOD("get_extra_baseline_offset", "cache_index"), &FontFile::get_extra_baseline_offset);
978
979
ClassDB::bind_method(D_METHOD("set_face_index", "cache_index", "face_index"), &FontFile::set_face_index);
980
ClassDB::bind_method(D_METHOD("get_face_index", "cache_index"), &FontFile::get_face_index);
981
982
ClassDB::bind_method(D_METHOD("set_cache_ascent", "cache_index", "size", "ascent"), &FontFile::set_cache_ascent);
983
ClassDB::bind_method(D_METHOD("get_cache_ascent", "cache_index", "size"), &FontFile::get_cache_ascent);
984
985
ClassDB::bind_method(D_METHOD("set_cache_descent", "cache_index", "size", "descent"), &FontFile::set_cache_descent);
986
ClassDB::bind_method(D_METHOD("get_cache_descent", "cache_index", "size"), &FontFile::get_cache_descent);
987
988
ClassDB::bind_method(D_METHOD("set_cache_underline_position", "cache_index", "size", "underline_position"), &FontFile::set_cache_underline_position);
989
ClassDB::bind_method(D_METHOD("get_cache_underline_position", "cache_index", "size"), &FontFile::get_cache_underline_position);
990
991
ClassDB::bind_method(D_METHOD("set_cache_underline_thickness", "cache_index", "size", "underline_thickness"), &FontFile::set_cache_underline_thickness);
992
ClassDB::bind_method(D_METHOD("get_cache_underline_thickness", "cache_index", "size"), &FontFile::get_cache_underline_thickness);
993
994
ClassDB::bind_method(D_METHOD("set_cache_scale", "cache_index", "size", "scale"), &FontFile::set_cache_scale);
995
ClassDB::bind_method(D_METHOD("get_cache_scale", "cache_index", "size"), &FontFile::get_cache_scale);
996
997
ClassDB::bind_method(D_METHOD("get_texture_count", "cache_index", "size"), &FontFile::get_texture_count);
998
ClassDB::bind_method(D_METHOD("clear_textures", "cache_index", "size"), &FontFile::clear_textures);
999
ClassDB::bind_method(D_METHOD("remove_texture", "cache_index", "size", "texture_index"), &FontFile::remove_texture);
1000
1001
ClassDB::bind_method(D_METHOD("set_texture_image", "cache_index", "size", "texture_index", "image"), &FontFile::set_texture_image);
1002
ClassDB::bind_method(D_METHOD("get_texture_image", "cache_index", "size", "texture_index"), &FontFile::get_texture_image);
1003
1004
ClassDB::bind_method(D_METHOD("set_texture_offsets", "cache_index", "size", "texture_index", "offset"), &FontFile::set_texture_offsets);
1005
ClassDB::bind_method(D_METHOD("get_texture_offsets", "cache_index", "size", "texture_index"), &FontFile::get_texture_offsets);
1006
1007
ClassDB::bind_method(D_METHOD("get_glyph_list", "cache_index", "size"), &FontFile::get_glyph_list);
1008
ClassDB::bind_method(D_METHOD("clear_glyphs", "cache_index", "size"), &FontFile::clear_glyphs);
1009
ClassDB::bind_method(D_METHOD("remove_glyph", "cache_index", "size", "glyph"), &FontFile::remove_glyph);
1010
1011
ClassDB::bind_method(D_METHOD("set_glyph_advance", "cache_index", "size", "glyph", "advance"), &FontFile::set_glyph_advance);
1012
ClassDB::bind_method(D_METHOD("get_glyph_advance", "cache_index", "size", "glyph"), &FontFile::get_glyph_advance);
1013
1014
ClassDB::bind_method(D_METHOD("set_glyph_offset", "cache_index", "size", "glyph", "offset"), &FontFile::set_glyph_offset);
1015
ClassDB::bind_method(D_METHOD("get_glyph_offset", "cache_index", "size", "glyph"), &FontFile::get_glyph_offset);
1016
1017
ClassDB::bind_method(D_METHOD("set_glyph_size", "cache_index", "size", "glyph", "gl_size"), &FontFile::set_glyph_size);
1018
ClassDB::bind_method(D_METHOD("get_glyph_size", "cache_index", "size", "glyph"), &FontFile::get_glyph_size);
1019
1020
ClassDB::bind_method(D_METHOD("set_glyph_uv_rect", "cache_index", "size", "glyph", "uv_rect"), &FontFile::set_glyph_uv_rect);
1021
ClassDB::bind_method(D_METHOD("get_glyph_uv_rect", "cache_index", "size", "glyph"), &FontFile::get_glyph_uv_rect);
1022
1023
ClassDB::bind_method(D_METHOD("set_glyph_texture_idx", "cache_index", "size", "glyph", "texture_idx"), &FontFile::set_glyph_texture_idx);
1024
ClassDB::bind_method(D_METHOD("get_glyph_texture_idx", "cache_index", "size", "glyph"), &FontFile::get_glyph_texture_idx);
1025
1026
ClassDB::bind_method(D_METHOD("get_kerning_list", "cache_index", "size"), &FontFile::get_kerning_list);
1027
ClassDB::bind_method(D_METHOD("clear_kerning_map", "cache_index", "size"), &FontFile::clear_kerning_map);
1028
ClassDB::bind_method(D_METHOD("remove_kerning", "cache_index", "size", "glyph_pair"), &FontFile::remove_kerning);
1029
1030
ClassDB::bind_method(D_METHOD("set_kerning", "cache_index", "size", "glyph_pair", "kerning"), &FontFile::set_kerning);
1031
ClassDB::bind_method(D_METHOD("get_kerning", "cache_index", "size", "glyph_pair"), &FontFile::get_kerning);
1032
1033
ClassDB::bind_method(D_METHOD("render_range", "cache_index", "size", "start", "end"), &FontFile::render_range);
1034
ClassDB::bind_method(D_METHOD("render_glyph", "cache_index", "size", "index"), &FontFile::render_glyph);
1035
1036
ClassDB::bind_method(D_METHOD("set_language_support_override", "language", "supported"), &FontFile::set_language_support_override);
1037
ClassDB::bind_method(D_METHOD("get_language_support_override", "language"), &FontFile::get_language_support_override);
1038
ClassDB::bind_method(D_METHOD("remove_language_support_override", "language"), &FontFile::remove_language_support_override);
1039
ClassDB::bind_method(D_METHOD("get_language_support_overrides"), &FontFile::get_language_support_overrides);
1040
1041
ClassDB::bind_method(D_METHOD("set_script_support_override", "script", "supported"), &FontFile::set_script_support_override);
1042
ClassDB::bind_method(D_METHOD("get_script_support_override", "script"), &FontFile::get_script_support_override);
1043
ClassDB::bind_method(D_METHOD("remove_script_support_override", "script"), &FontFile::remove_script_support_override);
1044
ClassDB::bind_method(D_METHOD("get_script_support_overrides"), &FontFile::get_script_support_overrides);
1045
1046
ClassDB::bind_method(D_METHOD("set_opentype_feature_overrides", "overrides"), &FontFile::set_opentype_feature_overrides);
1047
ClassDB::bind_method(D_METHOD("get_opentype_feature_overrides"), &FontFile::get_opentype_feature_overrides);
1048
1049
ClassDB::bind_method(D_METHOD("get_glyph_index", "size", "char", "variation_selector"), &FontFile::get_glyph_index);
1050
ClassDB::bind_method(D_METHOD("get_char_from_glyph_index", "size", "glyph_index"), &FontFile::get_char_from_glyph_index);
1051
1052
ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_data", "get_data");
1053
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_generate_mipmaps", "get_generate_mipmaps");
1054
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_embedded_bitmaps", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_disable_embedded_bitmaps", "get_disable_embedded_bitmaps");
1055
ADD_PROPERTY(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD Subpixel", PROPERTY_USAGE_STORAGE), "set_antialiasing", "get_antialiasing");
1056
ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_name", "get_font_name");
1057
ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name");
1058
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_FLAGS, "Bold,Italic,Fixed Size", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style");
1059
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_weight", PROPERTY_HINT_RANGE, "100,999,25", PROPERTY_USAGE_STORAGE), "set_font_weight", "get_font_weight");
1060
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_stretch", PROPERTY_HINT_RANGE, "50,200,25", PROPERTY_USAGE_STORAGE), "set_font_stretch", "get_font_stretch");
1061
1062
ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One Half of a Pixel,One Quarter of a Pixel", PROPERTY_USAGE_STORAGE), "set_subpixel_positioning", "get_subpixel_positioning");
1063
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_rounding_remainders", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_keep_rounding_remainders", "get_keep_rounding_remainders");
1064
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field");
1065
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_pixel_range", "get_msdf_pixel_range");
1066
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_size", "get_msdf_size");
1067
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_system_fallback", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_allow_system_fallback", "is_allow_system_fallback");
1068
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_autohinter", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_force_autohinter", "is_force_autohinter");
1069
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "modulate_color_glyphs", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_modulate_color_glyphs", "is_modulate_color_glyphs");
1070
ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_STORAGE), "set_hinting", "get_hinting");
1071
ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_fixed_size", "get_fixed_size");
1072
ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_size_scale_mode", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_fixed_size_scale_mode", "get_fixed_size_scale_mode");
1073
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "opentype_feature_overrides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_opentype_feature_overrides", "get_opentype_feature_overrides");
1074
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_oversampling", "get_oversampling");
1075
}
1076
1077
void FontFile::_validate_property(PropertyInfo &p_property) const {
1078
if (!Engine::get_singleton()->is_editor_hint()) {
1079
return;
1080
}
1081
if (p_property.name == "fallbacks") {
1082
p_property.usage &= ~PROPERTY_USAGE_EDITOR;
1083
}
1084
}
1085
1086
bool FontFile::_set(const StringName &p_name, const Variant &p_value) {
1087
Vector<String> tokens = p_name.operator String().split("/");
1088
1089
#ifndef DISABLE_DEPRECATED
1090
if (tokens.size() == 1 && tokens[0] == "font_path") {
1091
// Compatibility, DynamicFontData.
1092
load_dynamic_font(p_value);
1093
}
1094
if (tokens.size() == 1 && tokens[0] == "font_data") {
1095
// Compatibility, DynamicFont.
1096
Ref<Font> f = p_value;
1097
if (f.is_valid()) {
1098
fallbacks.push_back(f);
1099
return true;
1100
}
1101
return false;
1102
} else if (tokens.size() == 2 && tokens[0] == "fallback") {
1103
// Compatibility, DynamicFont.
1104
Ref<FontFile> f = p_value;
1105
if (f.is_valid()) {
1106
fallbacks.push_back(f);
1107
return true;
1108
}
1109
return false;
1110
} else if (tokens.size() == 1 && tokens[0] == "textures") {
1111
// Compatibility, BitmapFont.
1112
set_fixed_size(16);
1113
Array textures = p_value;
1114
for (int i = 0; i < textures.size(); i++) {
1115
Ref<ImageTexture> tex = textures[i];
1116
ERR_CONTINUE(tex.is_null());
1117
set_texture_image(0, Vector2i(16, 0), i, tex->get_image());
1118
}
1119
} else if (tokens.size() == 1 && tokens[0] == "chars") {
1120
// Compatibility, BitmapFont.
1121
set_fixed_size(16);
1122
PackedInt32Array arr = p_value;
1123
int len = arr.size();
1124
ERR_FAIL_COND_V(len % 9, false);
1125
if (!len) {
1126
return false;
1127
}
1128
int chars = len / 9;
1129
for (int i = 0; i < chars; i++) {
1130
const int32_t *char_data = &arr[i * 9];
1131
char32_t c = char_data[0];
1132
set_glyph_texture_idx(0, Vector2i(16, 0), c, char_data[1]);
1133
set_glyph_uv_rect(0, Vector2i(16, 0), c, Rect2(char_data[2], char_data[3], char_data[4], char_data[5]));
1134
set_glyph_offset(0, Vector2i(16, 0), c, Size2(char_data[6], char_data[7]));
1135
set_glyph_advance(0, 16, c, Vector2(char_data[8], 0));
1136
}
1137
} else if (tokens.size() == 1 && tokens[0] == "kernings") {
1138
// Compatibility, BitmapFont.
1139
set_fixed_size(16);
1140
PackedInt32Array arr = p_value;
1141
int len = arr.size();
1142
ERR_FAIL_COND_V(len % 3, false);
1143
if (!len) {
1144
return false;
1145
}
1146
for (int i = 0; i < len / 3; i++) {
1147
const int32_t *kern_data = &arr[i * 3];
1148
set_kerning(0, 16, Vector2i(kern_data[0], kern_data[1]), Vector2(kern_data[2], 0));
1149
}
1150
} else if (tokens.size() == 1 && tokens[0] == "height") {
1151
// Compatibility, BitmapFont.
1152
bmp_height = p_value;
1153
set_fixed_size(16);
1154
set_cache_descent(0, 16, bmp_height - bmp_ascent);
1155
} else if (tokens.size() == 1 && tokens[0] == "ascent") {
1156
// Compatibility, BitmapFont.
1157
bmp_ascent = p_value;
1158
set_fixed_size(16);
1159
set_cache_ascent(0, 16, bmp_ascent);
1160
set_cache_descent(0, 16, bmp_height - bmp_ascent);
1161
} else if (tokens.size() == 1 && tokens[0] == "fallback") {
1162
// Compatibility, BitmapFont.
1163
Ref<Font> f = p_value;
1164
if (f.is_valid()) {
1165
fallbacks.push_back(f);
1166
return true;
1167
}
1168
return false;
1169
}
1170
#endif // DISABLE_DEPRECATED
1171
1172
if (tokens.size() == 2 && tokens[0] == "language_support_override") {
1173
const String &lang_code = tokens[1];
1174
set_language_support_override(lang_code, p_value);
1175
return true;
1176
} else if (tokens.size() == 2 && tokens[0] == "script_support_override") {
1177
const String &script_code = tokens[1];
1178
set_script_support_override(script_code, p_value);
1179
return true;
1180
} else if (tokens.size() >= 3 && tokens[0] == "cache") {
1181
int cache_index = tokens[1].to_int();
1182
if (tokens.size() == 3 && tokens[2] == "variation_coordinates") {
1183
set_variation_coordinates(cache_index, p_value);
1184
return true;
1185
} else if (tokens.size() == 3 && tokens[2] == "embolden") {
1186
set_embolden(cache_index, p_value);
1187
return true;
1188
} else if (tokens.size() == 3 && tokens[2] == "face_index") {
1189
set_face_index(cache_index, p_value);
1190
return true;
1191
} else if (tokens.size() == 3 && tokens[2] == "transform") {
1192
set_transform(cache_index, p_value);
1193
return true;
1194
} else if (tokens.size() == 3 && tokens[2] == "spacing_top") {
1195
set_extra_spacing(cache_index, TextServer::SPACING_TOP, p_value);
1196
return true;
1197
} else if (tokens.size() == 3 && tokens[2] == "spacing_bottom") {
1198
set_extra_spacing(cache_index, TextServer::SPACING_BOTTOM, p_value);
1199
return true;
1200
} else if (tokens.size() == 3 && tokens[2] == "spacing_space") {
1201
set_extra_spacing(cache_index, TextServer::SPACING_SPACE, p_value);
1202
return true;
1203
} else if (tokens.size() == 3 && tokens[2] == "spacing_glyph") {
1204
set_extra_spacing(cache_index, TextServer::SPACING_GLYPH, p_value);
1205
return true;
1206
} else if (tokens.size() == 3 && tokens[2] == "baseline_offset") {
1207
set_extra_baseline_offset(cache_index, p_value);
1208
return true;
1209
}
1210
if (tokens.size() >= 5) {
1211
Vector2i sz = Vector2i(tokens[2].to_int(), tokens[3].to_int());
1212
if (tokens[4] == "ascent") {
1213
set_cache_ascent(cache_index, sz.x, p_value);
1214
return true;
1215
} else if (tokens[4] == "descent") {
1216
set_cache_descent(cache_index, sz.x, p_value);
1217
return true;
1218
} else if (tokens[4] == "underline_position") {
1219
set_cache_underline_position(cache_index, sz.x, p_value);
1220
return true;
1221
} else if (tokens[4] == "underline_thickness") {
1222
set_cache_underline_thickness(cache_index, sz.x, p_value);
1223
return true;
1224
} else if (tokens[4] == "scale") {
1225
set_cache_scale(cache_index, sz.x, p_value);
1226
return true;
1227
} else if (tokens.size() == 7 && tokens[4] == "textures") {
1228
int texture_index = tokens[5].to_int();
1229
if (tokens[6] == "image") {
1230
set_texture_image(cache_index, sz, texture_index, p_value);
1231
return true;
1232
} else if (tokens[6] == "offsets") {
1233
set_texture_offsets(cache_index, sz, texture_index, p_value);
1234
return true;
1235
}
1236
} else if (tokens.size() == 7 && tokens[4] == "glyphs") {
1237
int32_t glyph_index = tokens[5].to_int();
1238
if (tokens[6] == "advance") {
1239
set_glyph_advance(cache_index, sz.x, glyph_index, p_value);
1240
return true;
1241
} else if (tokens[6] == "offset") {
1242
set_glyph_offset(cache_index, sz, glyph_index, p_value);
1243
return true;
1244
} else if (tokens[6] == "size") {
1245
set_glyph_size(cache_index, sz, glyph_index, p_value);
1246
return true;
1247
} else if (tokens[6] == "uv_rect") {
1248
set_glyph_uv_rect(cache_index, sz, glyph_index, p_value);
1249
return true;
1250
} else if (tokens[6] == "texture_idx") {
1251
set_glyph_texture_idx(cache_index, sz, glyph_index, p_value);
1252
return true;
1253
}
1254
} else if (tokens.size() == 7 && tokens[4] == "kerning_overrides") {
1255
Vector2i gp = Vector2i(tokens[5].to_int(), tokens[6].to_int());
1256
set_kerning(cache_index, sz.x, gp, p_value);
1257
return true;
1258
}
1259
}
1260
}
1261
return false;
1262
}
1263
1264
bool FontFile::_get(const StringName &p_name, Variant &r_ret) const {
1265
Vector<String> tokens = p_name.operator String().split("/");
1266
if (tokens.size() == 2 && tokens[0] == "language_support_override") {
1267
const String &lang_code = tokens[1];
1268
r_ret = get_language_support_override(lang_code);
1269
return true;
1270
} else if (tokens.size() == 2 && tokens[0] == "script_support_override") {
1271
const String &script_code = tokens[1];
1272
r_ret = get_script_support_override(script_code);
1273
return true;
1274
} else if (tokens.size() >= 3 && tokens[0] == "cache") {
1275
int cache_index = tokens[1].to_int();
1276
if (tokens.size() == 3 && tokens[2] == "variation_coordinates") {
1277
r_ret = get_variation_coordinates(cache_index);
1278
return true;
1279
} else if (tokens.size() == 3 && tokens[2] == "embolden") {
1280
r_ret = get_embolden(cache_index);
1281
return true;
1282
} else if (tokens.size() == 3 && tokens[2] == "face_index") {
1283
r_ret = get_face_index(cache_index);
1284
return true;
1285
} else if (tokens.size() == 3 && tokens[2] == "transform") {
1286
r_ret = get_transform(cache_index);
1287
return true;
1288
} else if (tokens.size() == 3 && tokens[2] == "spacing_top") {
1289
r_ret = get_extra_spacing(cache_index, TextServer::SPACING_TOP);
1290
return true;
1291
} else if (tokens.size() == 3 && tokens[2] == "spacing_bottom") {
1292
r_ret = get_extra_spacing(cache_index, TextServer::SPACING_BOTTOM);
1293
return true;
1294
} else if (tokens.size() == 3 && tokens[2] == "spacing_space") {
1295
r_ret = get_extra_spacing(cache_index, TextServer::SPACING_SPACE);
1296
return true;
1297
} else if (tokens.size() == 3 && tokens[2] == "spacing_glyph") {
1298
r_ret = get_extra_spacing(cache_index, TextServer::SPACING_GLYPH);
1299
return true;
1300
} else if (tokens.size() == 3 && tokens[2] == "baseline_offset") {
1301
r_ret = get_extra_baseline_offset(cache_index);
1302
return true;
1303
}
1304
if (tokens.size() >= 5) {
1305
Vector2i sz = Vector2i(tokens[2].to_int(), tokens[3].to_int());
1306
if (tokens[4] == "ascent") {
1307
r_ret = get_cache_ascent(cache_index, sz.x);
1308
return true;
1309
} else if (tokens[4] == "descent") {
1310
r_ret = get_cache_descent(cache_index, sz.x);
1311
return true;
1312
} else if (tokens[4] == "underline_position") {
1313
r_ret = get_cache_underline_position(cache_index, sz.x);
1314
return true;
1315
} else if (tokens[4] == "underline_thickness") {
1316
r_ret = get_cache_underline_thickness(cache_index, sz.x);
1317
return true;
1318
} else if (tokens[4] == "scale") {
1319
r_ret = get_cache_scale(cache_index, sz.x);
1320
return true;
1321
} else if (tokens.size() == 7 && tokens[4] == "textures") {
1322
int texture_index = tokens[5].to_int();
1323
if (tokens[6] == "image") {
1324
r_ret = get_texture_image(cache_index, sz, texture_index);
1325
return true;
1326
} else if (tokens[6] == "offsets") {
1327
r_ret = get_texture_offsets(cache_index, sz, texture_index);
1328
return true;
1329
}
1330
} else if (tokens.size() == 7 && tokens[4] == "glyphs") {
1331
int32_t glyph_index = tokens[5].to_int();
1332
if (tokens[6] == "advance") {
1333
r_ret = get_glyph_advance(cache_index, sz.x, glyph_index);
1334
return true;
1335
} else if (tokens[6] == "offset") {
1336
r_ret = get_glyph_offset(cache_index, sz, glyph_index);
1337
return true;
1338
} else if (tokens[6] == "size") {
1339
r_ret = get_glyph_size(cache_index, sz, glyph_index);
1340
return true;
1341
} else if (tokens[6] == "uv_rect") {
1342
r_ret = get_glyph_uv_rect(cache_index, sz, glyph_index);
1343
return true;
1344
} else if (tokens[6] == "texture_idx") {
1345
r_ret = get_glyph_texture_idx(cache_index, sz, glyph_index);
1346
return true;
1347
}
1348
} else if (tokens.size() == 7 && tokens[4] == "kerning_overrides") {
1349
Vector2i gp = Vector2i(tokens[5].to_int(), tokens[6].to_int());
1350
r_ret = get_kerning(cache_index, sz.x, gp);
1351
return true;
1352
}
1353
}
1354
}
1355
return false;
1356
}
1357
1358
void FontFile::_get_property_list(List<PropertyInfo> *p_list) const {
1359
Vector<String> lang_over = get_language_support_overrides();
1360
for (int i = 0; i < lang_over.size(); i++) {
1361
p_list->push_back(PropertyInfo(Variant::BOOL, "language_support_override/" + lang_over[i], PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1362
}
1363
Vector<String> scr_over = get_script_support_overrides();
1364
for (int i = 0; i < scr_over.size(); i++) {
1365
p_list->push_back(PropertyInfo(Variant::BOOL, "script_support_override/" + scr_over[i], PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1366
}
1367
for (int i = 0; i < cache.size(); i++) {
1368
String prefix = "cache/" + itos(i) + "/";
1369
TypedArray<Vector2i> sizes = get_size_cache_list(i);
1370
p_list->push_back(PropertyInfo(Variant::DICTIONARY, prefix + "variation_coordinates", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1371
p_list->push_back(PropertyInfo(Variant::INT, prefix + "face_index", PROPERTY_HINT_RANGE, "0,32767,1", PROPERTY_USAGE_STORAGE));
1372
p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + "embolden", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1373
p_list->push_back(PropertyInfo(Variant::TRANSFORM2D, prefix + "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1374
p_list->push_back(PropertyInfo(Variant::INT, prefix + "spacing_top", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1375
p_list->push_back(PropertyInfo(Variant::INT, prefix + "spacing_bottom", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1376
p_list->push_back(PropertyInfo(Variant::INT, prefix + "spacing_space", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1377
p_list->push_back(PropertyInfo(Variant::INT, prefix + "spacing_glyph", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1378
p_list->push_back(PropertyInfo(Variant::FLOAT, prefix + "baseline_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1379
1380
for (int j = 0; j < sizes.size(); j++) {
1381
Vector2i sz = sizes[j];
1382
String prefix_sz = prefix + itos(sz.x) + "/" + itos(sz.y) + "/";
1383
if (sz.y == 0) {
1384
p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "ascent", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1385
p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "descent", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1386
p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "underline_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1387
p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "underline_thickness", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1388
p_list->push_back(PropertyInfo(Variant::FLOAT, prefix_sz + "scale", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1389
}
1390
1391
int tx_cnt = get_texture_count(i, sz);
1392
for (int k = 0; k < tx_cnt; k++) {
1393
p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, prefix_sz + "textures/" + itos(k) + "/offsets", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1394
p_list->push_back(PropertyInfo(Variant::OBJECT, prefix_sz + "textures/" + itos(k) + "/image", PROPERTY_HINT_RESOURCE_TYPE, Image::get_class_static(), PROPERTY_USAGE_STORAGE));
1395
}
1396
PackedInt32Array glyphs = get_glyph_list(i, sz);
1397
for (int k = 0; k < glyphs.size(); k++) {
1398
const int32_t &gl = glyphs[k];
1399
if (sz.y == 0) {
1400
p_list->push_back(PropertyInfo(Variant::VECTOR2, prefix_sz + "glyphs/" + itos(gl) + "/advance", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1401
}
1402
p_list->push_back(PropertyInfo(Variant::VECTOR2, prefix_sz + "glyphs/" + itos(gl) + "/offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1403
p_list->push_back(PropertyInfo(Variant::VECTOR2, prefix_sz + "glyphs/" + itos(gl) + "/size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1404
p_list->push_back(PropertyInfo(Variant::RECT2, prefix_sz + "glyphs/" + itos(gl) + "/uv_rect", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1405
p_list->push_back(PropertyInfo(Variant::INT, prefix_sz + "glyphs/" + itos(gl) + "/texture_idx", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1406
}
1407
if (sz.y == 0) {
1408
TypedArray<Vector2i> kerning_map = get_kerning_list(i, sz.x);
1409
for (int k = 0; k < kerning_map.size(); k++) {
1410
const Vector2i &gl_pair = kerning_map[k];
1411
p_list->push_back(PropertyInfo(Variant::VECTOR2, prefix_sz + "kerning_overrides/" + itos(gl_pair.x) + "/" + itos(gl_pair.y), PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE));
1412
}
1413
}
1414
}
1415
}
1416
}
1417
1418
void FontFile::reset_state() {
1419
_clear_cache();
1420
data.clear();
1421
data_ptr = nullptr;
1422
data_size = 0;
1423
cache.clear();
1424
1425
antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
1426
mipmaps = false;
1427
disable_embedded_bitmaps = true;
1428
msdf = false;
1429
force_autohinter = false;
1430
modulate_color_glyphs = false;
1431
allow_system_fallback = true;
1432
hinting = TextServer::HINTING_LIGHT;
1433
subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_DISABLED;
1434
keep_rounding_remainders = true;
1435
oversampling_override = 0.0;
1436
msdf_pixel_range = 14;
1437
msdf_size = 128;
1438
fixed_size = 0;
1439
fixed_size_scale_mode = TextServer::FIXED_SIZE_SCALE_DISABLE;
1440
1441
Font::reset_state();
1442
}
1443
1444
/*************************************************************************/
1445
1446
// OEM encoding mapping for 0x80..0xFF range.
1447
static const char32_t _oem_to_unicode[][129] = {
1448
U"\u20ac\ufffe\u201a\ufffe\u201e\u2026\u2020\u2021\ufffe\u2030\u0160\u2039\u015a\u0164\u017d\u0179\ufffe\u2018\u2019\u201c\u201d\u2022\u2013\u2014\ufffe\u2122\u0161\u203a\u015b\u0165\u017e\u017a\xa0\u02c7\u02d8\u0141\xa4\u0104\xa6\xa7\xa8\xa9\u015e\xab\xac\xad\xae\u017b\xb0\xb1\u02db\u0142\xb4\xb5\xb6\xb7\xb8\u0105\u015f\xbb\u013d\u02dd\u013e\u017c\u0154\xc1\xc2\u0102\xc4\u0139\u0106\xc7\u010c\xc9\u0118\xcb\u011a\xcd\xce\u010e\u0110\u0143\u0147\xd3\xd4\u0150\xd6\xd7\u0158\u016e\xda\u0170\xdc\xdd\u0162\xdf\u0155\xe1\xe2\u0103\xe4\u013a\u0107\xe7\u010d\xe9\u0119\xeb\u011b\xed\xee\u010f\u0111\u0144\u0148\xf3\xf4\u0151\xf6\xf7\u0159\u016f\xfa\u0171\xfc\xfd\u0163\u02d9", // 1250 - Latin 2
1449
U"\u0402\u0403\u201a\u0453\u201e\u2026\u2020\u2021\u20ac\u2030\u0409\u2039\u040a\u040c\u040b\u040f\u0452\u2018\u2019\u201c\u201d\u2022\u2013\u2014\ufffe\u2122\u0459\u203a\u045a\u045c\u045b\u045f\xa0\u040e\u045e\u0408\xa4\u0490\xa6\xa7\u0401\xa9\u0404\xab\xac\xad\xae\u0407\xb0\xb1\u0406\u0456\u0491\xb5\xb6\xb7\u0451\u2116\u0454\xbb\u0458\u0405\u0455\u0457\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042a\u042b\u042c\u042d\u042e\u042f\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f", // 1251 - Cyrillic
1450
U"\u20ac\ufffe\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u0160\u2039\u0152\ufffe\u017d\ufffe\ufffe\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\u0161\u203a\u0153\ufffe\u017e\u0178\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", // 1252 - Latin 1
1451
U"\u20ac\ufffe\u201a\u0192\u201e\u2026\u2020\u2021\ufffe\u2030\ufffe\u2039\ufffe\ufffe\ufffe\ufffe\ufffe\u2018\u2019\u201c\u201d\u2022\u2013\u2014\ufffe\u2122\ufffe\u203a\ufffe\ufffe\ufffe\ufffe\xa0\u0385\u0386\xa3\xa4\xa5\xa6\xa7\xa8\xa9\ufffe\xab\xac\xad\xae\u2015\xb0\xb1\xb2\xb3\u0384\xb5\xb6\xb7\u0388\u0389\u038a\xbb\u038c\xbd\u038e\u038f\u0390\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\ufffe\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9\u03aa\u03ab\u03ac\u03ad\u03ae\u03af\u03b0\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9\u03ca\u03cb\u03cc\u03cd\u03ce\ufffe", // 1253 - Greek
1452
U"\u20ac\ufffe\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u0160\u2039\u0152\ufffe\ufffe\ufffe\ufffe\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\u0161\u203a\u0153\ufffe\ufffe\u0178\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\u011e\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\u0130\u015e\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\u011f\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\u0131\u015f\xff", // 1254 - Turkish
1453
U"\u20ac\ufffe\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\ufffe\u2039\ufffe\ufffe\ufffe\ufffe\ufffe\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\ufffe\u203a\ufffe\ufffe\ufffe\ufffe\xa0\xa1\xa2\xa3\u20aa\xa5\xa6\xa7\xa8\xa9\xd7\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xf7\xbb\xbc\xbd\xbe\xbf\u05b0\u05b1\u05b2\u05b3\u05b4\u05b5\u05b6\u05b7\u05b8\u05b9\ufffe\u05bb\u05bc\u05bd\u05be\u05bf\u05c0\u05c1\u05c2\u05c3\u05f0\u05f1\u05f2\u05f3\u05f4\ufffe\ufffe\ufffe\ufffe\ufffe\ufffe\ufffe\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\u05e3\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea\ufffe\ufffe\u200e\u200f\ufffe", // 1255 - Hebrew
1454
U"\u20ac\u067e\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\u0679\u2039\u0152\u0686\u0698\u0688\u06af\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u06a9\u2122\u0691\u203a\u0153\u200c\u200d\u06ba\xa0\u060c\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\u06be\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\u061b\xbb\xbc\xbd\xbe\u061f\u06c1\u0621\u0622\u0623\u0624\u0625\u0626\u0627\u0628\u0629\u062a\u062b\u062c\u062d\u062e\u062f\u0630\u0631\u0632\u0633\u0634\u0635\u0636\xd7\u0637\u0638\u0639\u063a\u0640\u0641\u0642\u0643\xe0\u0644\xe2\u0645\u0646\u0647\u0648\xe7\xe8\xe9\xea\xeb\u0649\u064a\xee\xef\u064b\u064c\u064d\u064e\xf4\u064f\u0650\xf7\u0651\xf9\u0652\xfb\xfc\u200e\u200f\u06d2", // 1256 - Arabic
1455
U"\u20ac\ufffe\u201a\ufffe\u201e\u2026\u2020\u2021\ufffe\u2030\ufffe\u2039\ufffe\xa8\u02c7\xb8\ufffe\u2018\u2019\u201c\u201d\u2022\u2013\u2014\ufffe\u2122\ufffe\u203a\ufffe\xaf\u02db\ufffe\xa0\ufffe\xa2\xa3\xa4\ufffe\xa6\xa7\xd8\xa9\u0156\xab\xac\xad\xae\xc6\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xf8\xb9\u0157\xbb\xbc\xbd\xbe\xe6\u0104\u012e\u0100\u0106\xc4\xc5\u0118\u0112\u010c\xc9\u0179\u0116\u0122\u0136\u012a\u013b\u0160\u0143\u0145\xd3\u014c\xd5\xd6\xd7\u0172\u0141\u015a\u016a\xdc\u017b\u017d\xdf\u0105\u012f\u0101\u0107\xe4\xe5\u0119\u0113\u010d\xe9\u017a\u0117\u0123\u0137\u012b\u013c\u0161\u0144\u0146\xf3\u014d\xf5\xf6\xf7\u0173\u0142\u015b\u016b\xfc\u017c\u017e\u02d9", // 1257 - Baltic
1456
U"\u20ac\ufffe\u201a\u0192\u201e\u2026\u2020\u2021\u02c6\u2030\ufffe\u2039\u0152\ufffe\ufffe\ufffe\ufffe\u2018\u2019\u201c\u201d\u2022\u2013\u2014\u02dc\u2122\ufffe\u203a\u0153\ufffe\ufffe\u0178\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\u0102\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\u0300\xcd\xce\xcf\u0110\xd1\u0309\xd3\xd4\u01a0\xd6\xd7\xd8\xd9\xda\xdb\xdc\u01af\u0303\xdf\xe0\xe1\xe2\u0103\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\u0301\xed\xee\xef\u0111\xf1\u0323\xf3\xf4\u01a1\xf6\xf7\xf8\xf9\xfa\xfb\xfc\u01b0\u20ab\xff", // 1258 - Vietnamese
1457
};
1458
1459
Error FontFile::load_bitmap_font(const String &p_path) {
1460
return _load_bitmap_font(p_path, nullptr);
1461
}
1462
1463
Error FontFile::_load_bitmap_font(const String &p_path, List<String> *r_image_files) {
1464
reset_state();
1465
1466
antialiasing = TextServer::FONT_ANTIALIASING_NONE;
1467
mipmaps = false;
1468
disable_embedded_bitmaps = true;
1469
msdf = false;
1470
force_autohinter = false;
1471
modulate_color_glyphs = false;
1472
allow_system_fallback = true;
1473
hinting = TextServer::HINTING_NONE;
1474
1475
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
1476
ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_CREATE, vformat("Cannot open font from file: %s.", p_path));
1477
1478
int base_size = 16;
1479
int height = 0;
1480
int ascent = 0;
1481
int outline = 0;
1482
BitField<TextServer::FontStyle> st_flags = 0;
1483
String font_name;
1484
1485
bool packed = false;
1486
uint8_t ch[4] = { 0, 0, 0, 0 }; // RGBA
1487
int first_gl_ch = -1;
1488
int first_ol_ch = -1;
1489
int first_cm_ch = -1;
1490
1491
unsigned char magic[4];
1492
f->get_buffer((unsigned char *)&magic, 4);
1493
if (magic[0] == 'B' && magic[1] == 'M' && magic[2] == 'F') {
1494
// Binary BMFont file.
1495
ERR_FAIL_COND_V_MSG(magic[3] != 3, ERR_CANT_CREATE, vformat("Version %d of BMFont is not supported (should be 3).", (int)magic[3]));
1496
1497
uint8_t block_type = f->get_8();
1498
uint32_t block_size = f->get_32();
1499
bool unicode = false;
1500
uint8_t encoding = 9;
1501
while (!f->eof_reached()) {
1502
uint64_t off = f->get_position();
1503
switch (block_type) {
1504
case 1: /* info */ {
1505
ERR_FAIL_COND_V_MSG(block_size < 15, ERR_CANT_CREATE, "Invalid BMFont info block size.");
1506
base_size = Math::abs(static_cast<int16_t>(f->get_16()));
1507
if (base_size == 0) {
1508
base_size = 16;
1509
}
1510
uint8_t flags = f->get_8();
1511
//fixed_height = flags & (1 << 3);
1512
if (flags & (1 << 4)) {
1513
st_flags.set_flag(TextServer::FONT_BOLD);
1514
}
1515
if (flags & (1 << 5)) {
1516
st_flags.set_flag(TextServer::FONT_ITALIC);
1517
}
1518
unicode = flags & (1 << 6);
1519
//smooth = flags & (1 << 7);
1520
uint8_t encoding_id = f->get_8(); // non-unicode charset
1521
if (!unicode) {
1522
switch (encoding_id) {
1523
case 0x00: {
1524
encoding = 2;
1525
} break;
1526
case 0xB2: {
1527
encoding = 6;
1528
} break;
1529
case 0xBA: {
1530
encoding = 7;
1531
} break;
1532
case 0xEE: {
1533
encoding = 0;
1534
} break;
1535
case 0xA1: {
1536
encoding = 3;
1537
} break;
1538
case 0xB1: {
1539
encoding = 5;
1540
} break;
1541
case 0xCC: {
1542
encoding = 1;
1543
} break;
1544
case 0xA2: {
1545
encoding = 4;
1546
} break;
1547
case 0xA3: {
1548
encoding = 8;
1549
} break;
1550
default: {
1551
WARN_PRINT(vformat("Unknown BMFont OEM encoding %x, parsing as Unicode (should be 0x00 - Latin 1, 0xB2 - Arabic, 0xBA - Baltic, 0xEE - Latin 2, 0xA1 - Greek, 0xB1 - Hebrew, 0xCC - Cyrillic, 0xA2 - Turkish, 0xA3 - Vietnamese).", encoding_id));
1552
} break;
1553
};
1554
}
1555
f->get_16(); // stretch_h, skip
1556
f->get_8(); // aa, skip
1557
f->get_32(); // padding, skip
1558
f->get_16(); // spacing, skip
1559
outline = f->get_8();
1560
// font name
1561
PackedByteArray name_data;
1562
name_data.resize(block_size - 14);
1563
f->get_buffer(name_data.ptrw(), block_size - 14);
1564
font_name = String::utf8((const char *)name_data.ptr(), block_size - 14);
1565
set_fixed_size(base_size);
1566
} break;
1567
case 2: /* common */ {
1568
ERR_FAIL_COND_V_MSG(block_size != 15, ERR_CANT_CREATE, "Invalid BMFont common block size.");
1569
height = f->get_16();
1570
ascent = f->get_16();
1571
f->get_32(); // scale, skip
1572
f->get_16(); // pages, skip
1573
uint8_t flags = f->get_8();
1574
packed = (flags & 0x01);
1575
ch[3] = f->get_8();
1576
ch[0] = f->get_8();
1577
ch[1] = f->get_8();
1578
ch[2] = f->get_8();
1579
for (int i = 0; i < 4; i++) {
1580
if (ch[i] == 0 && first_gl_ch == -1) {
1581
first_gl_ch = i;
1582
}
1583
if (ch[i] == 1 && first_ol_ch == -1) {
1584
first_ol_ch = i;
1585
if (outline == 0) {
1586
outline = 1;
1587
}
1588
}
1589
if (ch[i] == 2 && first_cm_ch == -1) {
1590
first_cm_ch = i;
1591
}
1592
}
1593
} break;
1594
case 3: /* pages */ {
1595
int page = 0;
1596
CharString cs;
1597
char32_t c = f->get_8();
1598
while (!f->eof_reached() && f->get_position() <= off + block_size) {
1599
if (c == '\0') {
1600
String base_dir = p_path.get_base_dir();
1601
String file = base_dir.path_join(String::utf8(cs.ptr(), cs.length()));
1602
if (RenderingServer::get_singleton() != nullptr) {
1603
Ref<Image> img;
1604
img.instantiate();
1605
Error err = ImageLoader::load_image(file, img);
1606
ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_READ, vformat("Can't load font texture: %s.", file));
1607
if (r_image_files) {
1608
r_image_files->push_back(file);
1609
}
1610
1611
if (packed) {
1612
if (ch[3] == 0) { // 4 x 8 bit monochrome, no outline
1613
outline = 0;
1614
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1615
_convert_packed_8bit(img, page, base_size);
1616
} else if ((ch[3] == 2) && (outline > 0)) { // 4 x 4 bit monochrome, gl + outline
1617
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1618
_convert_packed_4bit(img, page, base_size);
1619
} else {
1620
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Unsupported BMFont texture format.");
1621
}
1622
} else {
1623
if ((ch[0] == 0) && (ch[1] == 0) && (ch[2] == 0) && (ch[3] == 0)) { // RGBA8 color, no outline
1624
outline = 0;
1625
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1626
set_texture_image(0, Vector2i(base_size, 0), page, img);
1627
} else if ((ch[0] == 2) && (ch[1] == 2) && (ch[2] == 2) && (ch[3] == 2) && (outline > 0)) { // RGBA4 color, gl + outline
1628
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1629
_convert_rgba_4bit(img, page, base_size);
1630
} else if ((first_gl_ch >= 0) && (first_ol_ch >= 0) && (outline > 0)) { // 1 x 8 bit monochrome, gl + outline
1631
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8 && img->get_format() != Image::FORMAT_L8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1632
_convert_mono_8bit(img, page, first_gl_ch, base_size, 0);
1633
_convert_mono_8bit(img, page, first_ol_ch, base_size, 1);
1634
} else if ((first_cm_ch >= 0) && (outline > 0)) { // 1 x 4 bit monochrome, gl + outline
1635
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8 && img->get_format() != Image::FORMAT_L8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1636
_convert_mono_4bit(img, page, first_cm_ch, base_size, 1);
1637
} else if (first_gl_ch >= 0) { // 1 x 8 bit monochrome, no outline
1638
outline = 0;
1639
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8 && img->get_format() != Image::FORMAT_L8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1640
_convert_mono_8bit(img, page, first_gl_ch, base_size, 0);
1641
} else {
1642
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Unsupported BMFont texture format.");
1643
}
1644
}
1645
}
1646
page++;
1647
cs = "";
1648
} else {
1649
cs += c;
1650
}
1651
c = f->get_8();
1652
}
1653
} break;
1654
case 4: /* chars */ {
1655
int char_count = block_size / 20;
1656
for (int i = 0; i < char_count; i++) {
1657
Vector2 advance;
1658
Vector2 size;
1659
Vector2 offset;
1660
Rect2 uv_rect;
1661
1662
char32_t idx = f->get_32();
1663
if (!unicode && encoding < 9) {
1664
if (idx >= 0x80 && idx <= 0xFF) {
1665
idx = _oem_to_unicode[encoding][idx - 0x80];
1666
} else if (idx > 0xFF) {
1667
WARN_PRINT(vformat("Invalid BMFont OEM character %x (should be 0x00-0xFF).", idx));
1668
idx = 0x00;
1669
}
1670
}
1671
uv_rect.position.x = (int16_t)f->get_16();
1672
uv_rect.position.y = (int16_t)f->get_16();
1673
uv_rect.size.width = (int16_t)f->get_16();
1674
size.width = uv_rect.size.width;
1675
uv_rect.size.height = (int16_t)f->get_16();
1676
size.height = uv_rect.size.height;
1677
offset.x = (int16_t)f->get_16();
1678
offset.y = (int16_t)f->get_16() - ascent;
1679
advance.x = (int16_t)f->get_16();
1680
if (advance.x < 0) {
1681
advance.x = size.width + 1;
1682
}
1683
1684
int texture_idx = f->get_8();
1685
uint8_t channel = f->get_8();
1686
1687
int ch_off = 0;
1688
if (packed) {
1689
switch (channel) {
1690
case 1:
1691
ch_off = 2;
1692
break; // B
1693
case 2:
1694
ch_off = 1;
1695
break; // G
1696
case 4:
1697
ch_off = 0;
1698
break; // R
1699
case 8:
1700
ch_off = 3;
1701
break; // A
1702
default:
1703
ch_off = 0;
1704
break;
1705
}
1706
}
1707
set_glyph_advance(0, base_size, idx, advance);
1708
set_glyph_offset(0, Vector2i(base_size, 0), idx, offset);
1709
set_glyph_size(0, Vector2i(base_size, 0), idx, size);
1710
set_glyph_uv_rect(0, Vector2i(base_size, 0), idx, uv_rect);
1711
set_glyph_texture_idx(0, Vector2i(base_size, 0), idx, texture_idx * (packed ? 4 : 1) + ch_off);
1712
if (outline > 0) {
1713
set_glyph_offset(0, Vector2i(base_size, 1), idx, offset);
1714
set_glyph_size(0, Vector2i(base_size, 1), idx, size);
1715
set_glyph_uv_rect(0, Vector2i(base_size, 1), idx, uv_rect);
1716
set_glyph_texture_idx(0, Vector2i(base_size, 1), idx, texture_idx * (packed ? 4 : 1) + ch_off);
1717
}
1718
}
1719
} break;
1720
case 5: /* kerning */ {
1721
int pair_count = block_size / 10;
1722
for (int i = 0; i < pair_count; i++) {
1723
Vector2i kpk;
1724
kpk.x = f->get_32();
1725
kpk.y = f->get_32();
1726
if (!unicode && encoding < 9) {
1727
if (kpk.x >= 0x80 && kpk.x <= 0xFF) {
1728
kpk.x = _oem_to_unicode[encoding][kpk.x - 0x80];
1729
} else if (kpk.x > 0xFF) {
1730
WARN_PRINT(vformat("Invalid BMFont OEM character %x (should be 0x00-0xFF).", kpk.x));
1731
kpk.x = 0x00;
1732
}
1733
if (kpk.y >= 0x80 && kpk.y <= 0xFF) {
1734
kpk.y = _oem_to_unicode[encoding][kpk.y - 0x80];
1735
} else if (kpk.y > 0xFF) {
1736
WARN_PRINT(vformat("Invalid BMFont OEM character %x (should be 0x00-0xFF).", kpk.y));
1737
kpk.y = 0x00;
1738
}
1739
}
1740
set_kerning(0, base_size, kpk, Vector2((int16_t)f->get_16(), 0));
1741
}
1742
} break;
1743
default: {
1744
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Invalid BMFont block type.");
1745
} break;
1746
}
1747
f->seek(off + block_size);
1748
block_type = f->get_8();
1749
block_size = f->get_32();
1750
}
1751
1752
} else {
1753
// Text BMFont file.
1754
f->seek(0);
1755
bool unicode = false;
1756
uint8_t encoding = 9;
1757
while (true) {
1758
String line = f->get_line();
1759
1760
int delimiter = line.find_char(' ');
1761
String type = line.substr(0, delimiter);
1762
int pos = delimiter + 1;
1763
HashMap<String, String> keys;
1764
1765
while (pos < line.size() && line[pos] == ' ') {
1766
pos++;
1767
}
1768
1769
while (pos < line.size()) {
1770
int eq = line.find_char('=', pos);
1771
if (eq == -1) {
1772
break;
1773
}
1774
String key = line.substr(pos, eq - pos);
1775
int end = -1;
1776
String value;
1777
if (line[eq + 1] == '"') {
1778
end = line.find_char('"', eq + 2);
1779
if (end == -1) {
1780
break;
1781
}
1782
value = line.substr(eq + 2, end - 1 - eq - 1);
1783
pos = end + 1;
1784
} else {
1785
end = line.find_char(' ', eq + 1);
1786
if (end == -1) {
1787
end = line.size();
1788
}
1789
value = line.substr(eq + 1, end - eq);
1790
pos = end;
1791
}
1792
1793
while (pos < line.size() && line[pos] == ' ') {
1794
pos++;
1795
}
1796
1797
keys[key] = value;
1798
}
1799
1800
if (type == "info") {
1801
if (keys.has("size")) {
1802
base_size = Math::abs(keys["size"].to_int());
1803
if (base_size == 0) {
1804
base_size = 16;
1805
}
1806
}
1807
if (keys.has("outline")) {
1808
outline = keys["outline"].to_int();
1809
}
1810
if (keys.has("bold")) {
1811
if (keys["bold"].to_int()) {
1812
st_flags.set_flag(TextServer::FONT_BOLD);
1813
}
1814
}
1815
if (keys.has("italic")) {
1816
if (keys["italic"].to_int()) {
1817
st_flags.set_flag(TextServer::FONT_ITALIC);
1818
}
1819
}
1820
if (keys.has("face")) {
1821
font_name = keys["face"];
1822
}
1823
if (keys.has("unicode")) {
1824
unicode = keys["unicode"].to_int();
1825
}
1826
if (!unicode) {
1827
if (keys.has("charset")) {
1828
String encoding_name = keys["charset"].to_upper();
1829
if (encoding_name == "" || encoding_name == "ASCII" || encoding_name == "ANSI") {
1830
encoding = 2;
1831
} else if (encoding_name == "ARABIC") {
1832
encoding = 6;
1833
} else if (encoding_name == "BALTIC") {
1834
encoding = 7;
1835
} else if (encoding_name == "EASTEUROPE") {
1836
encoding = 0;
1837
} else if (encoding_name == "GREEK") {
1838
encoding = 3;
1839
} else if (encoding_name == "HEBREW") {
1840
encoding = 5;
1841
} else if (encoding_name == "RUSSIAN") {
1842
encoding = 1;
1843
} else if (encoding_name == "TURKISH") {
1844
encoding = 4;
1845
} else if (encoding_name == "VIETNAMESE") {
1846
encoding = 8;
1847
} else {
1848
WARN_PRINT(vformat("Unknown BMFont OEM encoding %s, parsing as Unicode (should be ANSI, ASCII, ARABIC, BALTIC, EASTEUROPE, GREEK, HEBREW, RUSSIAN, TURKISH or VIETNAMESE).", encoding_name));
1849
}
1850
} else {
1851
encoding = 2;
1852
}
1853
}
1854
set_fixed_size(base_size);
1855
} else if (type == "common") {
1856
if (keys.has("lineHeight")) {
1857
height = keys["lineHeight"].to_int();
1858
}
1859
if (keys.has("base")) {
1860
ascent = keys["base"].to_int();
1861
}
1862
if (keys.has("packed")) {
1863
packed = (keys["packed"].to_int() == 1);
1864
}
1865
if (keys.has("alphaChnl")) {
1866
ch[3] = keys["alphaChnl"].to_int();
1867
}
1868
if (keys.has("redChnl")) {
1869
ch[0] = keys["redChnl"].to_int();
1870
}
1871
if (keys.has("greenChnl")) {
1872
ch[1] = keys["greenChnl"].to_int();
1873
}
1874
if (keys.has("blueChnl")) {
1875
ch[2] = keys["blueChnl"].to_int();
1876
}
1877
for (int i = 0; i < 4; i++) {
1878
if (ch[i] == 0 && first_gl_ch == -1) {
1879
first_gl_ch = i;
1880
}
1881
if (ch[i] == 1 && first_ol_ch == -1) {
1882
first_ol_ch = i;
1883
if (outline == 0) {
1884
outline = 1;
1885
}
1886
}
1887
if (ch[i] == 2 && first_cm_ch == -1) {
1888
first_cm_ch = i;
1889
}
1890
}
1891
} else if (type == "page") {
1892
int page = 0;
1893
if (keys.has("id")) {
1894
page = keys["id"].to_int();
1895
}
1896
if (keys.has("file")) {
1897
String base_dir = p_path.get_base_dir();
1898
String file = base_dir.path_join(keys["file"]);
1899
if (RenderingServer::get_singleton() != nullptr) {
1900
Ref<Image> img;
1901
img.instantiate();
1902
Error err = ImageLoader::load_image(file, img);
1903
ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CANT_READ, vformat("Can't load font texture: %s.", file));
1904
if (r_image_files) {
1905
r_image_files->push_back(file);
1906
}
1907
1908
if (packed) {
1909
if (ch[3] == 0) { // 4 x 8 bit monochrome, no outline
1910
outline = 0;
1911
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1912
_convert_packed_8bit(img, page, base_size);
1913
} else if ((ch[3] == 2) && (outline > 0)) { // 4 x 4 bit monochrome, gl + outline
1914
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1915
_convert_packed_4bit(img, page, base_size);
1916
} else {
1917
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Unsupported BMFont texture format.");
1918
}
1919
} else {
1920
if ((ch[3] == 0) && (ch[0] == 4) && (ch[1] == 4) && (ch[2] == 4) && img->get_format() == Image::FORMAT_RGBA8) { // might be RGBA8 color, no outline (color part of the image should be sold white, but some apps designed for Godot 3 generate color fonts with this config)
1921
outline = 0;
1922
set_texture_image(0, Vector2i(base_size, 0), page, img);
1923
} else if ((ch[0] == 0) && (ch[1] == 0) && (ch[2] == 0) && (ch[3] == 0)) { // RGBA8 color, no outline
1924
outline = 0;
1925
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1926
set_texture_image(0, Vector2i(base_size, 0), page, img);
1927
} else if ((ch[0] == 2) && (ch[1] == 2) && (ch[2] == 2) && (ch[3] == 2) && (outline > 0)) { // RGBA4 color, gl + outline
1928
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1929
_convert_rgba_4bit(img, page, base_size);
1930
} else if ((first_gl_ch >= 0) && (first_ol_ch >= 0) && (outline > 0)) { // 1 x 8 bit monochrome, gl + outline
1931
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8 && img->get_format() != Image::FORMAT_L8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1932
_convert_mono_8bit(img, page, first_gl_ch, base_size, 0);
1933
_convert_mono_8bit(img, page, first_ol_ch, base_size, 1);
1934
} else if ((first_cm_ch >= 0) && (outline > 0)) { // 1 x 4 bit monochrome, gl + outline
1935
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8 && img->get_format() != Image::FORMAT_L8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1936
_convert_mono_4bit(img, page, first_cm_ch, base_size, 1);
1937
} else if (first_gl_ch >= 0) { // 1 x 8 bit monochrome, no outline
1938
outline = 0;
1939
ERR_FAIL_COND_V_MSG(img->get_format() != Image::FORMAT_RGBA8 && img->get_format() != Image::FORMAT_L8, ERR_FILE_CANT_READ, "Unsupported BMFont texture format.");
1940
_convert_mono_8bit(img, page, first_gl_ch, base_size, 0);
1941
} else {
1942
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "Unsupported BMFont texture format.");
1943
}
1944
}
1945
}
1946
}
1947
} else if (type == "char") {
1948
char32_t idx = 0;
1949
Vector2 advance;
1950
Vector2 size;
1951
Vector2 offset;
1952
Rect2 uv_rect;
1953
int texture_idx = -1;
1954
uint8_t channel = 15;
1955
1956
if (keys.has("id")) {
1957
idx = keys["id"].to_int();
1958
if (!unicode && encoding < 9) {
1959
if (idx >= 0x80 && idx <= 0xFF) {
1960
idx = _oem_to_unicode[encoding][idx - 0x80];
1961
} else if (idx > 0xFF) {
1962
WARN_PRINT(vformat("Invalid BMFont OEM character %x (should be 0x00-0xFF).", idx));
1963
idx = 0x00;
1964
}
1965
}
1966
}
1967
if (keys.has("x")) {
1968
uv_rect.position.x = keys["x"].to_int();
1969
}
1970
if (keys.has("y")) {
1971
uv_rect.position.y = keys["y"].to_int();
1972
}
1973
if (keys.has("width")) {
1974
uv_rect.size.width = keys["width"].to_int();
1975
size.width = keys["width"].to_int();
1976
}
1977
if (keys.has("height")) {
1978
uv_rect.size.height = keys["height"].to_int();
1979
size.height = keys["height"].to_int();
1980
}
1981
if (keys.has("xoffset")) {
1982
offset.x = keys["xoffset"].to_int();
1983
}
1984
if (keys.has("yoffset")) {
1985
offset.y = keys["yoffset"].to_int() - ascent;
1986
}
1987
if (keys.has("page")) {
1988
texture_idx = keys["page"].to_int();
1989
}
1990
if (keys.has("xadvance")) {
1991
advance.x = keys["xadvance"].to_int();
1992
}
1993
if (advance.x < 0) {
1994
advance.x = size.width + 1;
1995
}
1996
if (keys.has("chnl")) {
1997
channel = keys["chnl"].to_int();
1998
}
1999
2000
int ch_off = 0;
2001
if (packed) {
2002
switch (channel) {
2003
case 1:
2004
ch_off = 2;
2005
break; // B
2006
case 2:
2007
ch_off = 1;
2008
break; // G
2009
case 4:
2010
ch_off = 0;
2011
break; // R
2012
case 8:
2013
ch_off = 3;
2014
break; // A
2015
default:
2016
ch_off = 0;
2017
break;
2018
}
2019
}
2020
set_glyph_advance(0, base_size, idx, advance);
2021
set_glyph_offset(0, Vector2i(base_size, 0), idx, offset);
2022
set_glyph_size(0, Vector2i(base_size, 0), idx, size);
2023
set_glyph_uv_rect(0, Vector2i(base_size, 0), idx, uv_rect);
2024
set_glyph_texture_idx(0, Vector2i(base_size, 0), idx, texture_idx * (packed ? 4 : 1) + ch_off);
2025
if (outline > 0) {
2026
set_glyph_offset(0, Vector2i(base_size, 1), idx, offset);
2027
set_glyph_size(0, Vector2i(base_size, 1), idx, size);
2028
set_glyph_uv_rect(0, Vector2i(base_size, 1), idx, uv_rect);
2029
set_glyph_texture_idx(0, Vector2i(base_size, 1), idx, texture_idx * (packed ? 4 : 1) + ch_off);
2030
}
2031
} else if (type == "kerning") {
2032
Vector2i kpk;
2033
if (keys.has("first")) {
2034
kpk.x = keys["first"].to_int();
2035
}
2036
if (keys.has("second")) {
2037
kpk.y = keys["second"].to_int();
2038
}
2039
if (!unicode && encoding < 9) {
2040
if (kpk.x >= 0x80 && kpk.x <= 0xFF) {
2041
kpk.x = _oem_to_unicode[encoding][kpk.x - 0x80];
2042
} else if (kpk.x > 0xFF) {
2043
WARN_PRINT(vformat("Invalid BMFont OEM character %x (should be 0x00-0xFF).", kpk.x));
2044
kpk.x = 0x00;
2045
}
2046
if (kpk.y >= 0x80 && kpk.y <= 0xFF) {
2047
kpk.y = _oem_to_unicode[encoding][kpk.y - 0x80];
2048
} else if (kpk.y > 0xFF) {
2049
WARN_PRINT(vformat("Invalid BMFont OEM character %x (should be 0x00-0xFF).", kpk.x));
2050
kpk.y = 0x00;
2051
}
2052
}
2053
if (keys.has("amount")) {
2054
set_kerning(0, base_size, kpk, Vector2(keys["amount"].to_int(), 0));
2055
}
2056
}
2057
2058
if (f->eof_reached()) {
2059
break;
2060
}
2061
}
2062
}
2063
2064
set_font_name(font_name);
2065
set_font_style(st_flags);
2066
if (st_flags & TextServer::FONT_BOLD) {
2067
set_font_weight(700);
2068
}
2069
set_cache_ascent(0, base_size, ascent);
2070
set_cache_descent(0, base_size, height - ascent);
2071
2072
return OK;
2073
}
2074
2075
Error FontFile::load_dynamic_font(const String &p_path) {
2076
reset_state();
2077
2078
Vector<uint8_t> font_data = FileAccess::get_file_as_bytes(p_path);
2079
set_data(font_data);
2080
2081
return OK;
2082
}
2083
2084
void FontFile::set_data_ptr(const uint8_t *p_data, size_t p_size) {
2085
data.clear();
2086
data_ptr = p_data;
2087
data_size = p_size;
2088
2089
for (int i = 0; i < cache.size(); i++) {
2090
if (cache[i].is_valid()) {
2091
TS->font_set_data_ptr(cache[i], data_ptr, data_size);
2092
}
2093
}
2094
}
2095
2096
void FontFile::set_data(const PackedByteArray &p_data) {
2097
data = p_data;
2098
data_ptr = data.ptr();
2099
data_size = data.size();
2100
2101
for (int i = 0; i < cache.size(); i++) {
2102
if (cache[i].is_valid()) {
2103
TS->font_set_data_ptr(cache[i], data_ptr, data_size);
2104
}
2105
}
2106
}
2107
2108
PackedByteArray FontFile::get_data() const {
2109
if (unlikely((size_t)data.size() != data_size)) {
2110
data.resize(data_size);
2111
memcpy(data.ptrw(), data_ptr, data_size);
2112
}
2113
return data;
2114
}
2115
2116
void FontFile::set_font_name(const String &p_name) {
2117
_ensure_rid(0);
2118
TS->font_set_name(cache[0], p_name);
2119
}
2120
2121
void FontFile::set_font_style_name(const String &p_name) {
2122
_ensure_rid(0);
2123
TS->font_set_style_name(cache[0], p_name);
2124
}
2125
2126
void FontFile::set_font_style(BitField<TextServer::FontStyle> p_style) {
2127
_ensure_rid(0);
2128
TS->font_set_style(cache[0], p_style);
2129
}
2130
2131
void FontFile::set_font_weight(int p_weight) {
2132
_ensure_rid(0);
2133
TS->font_set_weight(cache[0], p_weight);
2134
}
2135
2136
void FontFile::set_font_stretch(int p_stretch) {
2137
_ensure_rid(0);
2138
TS->font_set_stretch(cache[0], p_stretch);
2139
}
2140
2141
void FontFile::set_antialiasing(TextServer::FontAntialiasing p_antialiasing) {
2142
if (antialiasing != p_antialiasing) {
2143
antialiasing = p_antialiasing;
2144
for (int i = 0; i < cache.size(); i++) {
2145
_ensure_rid(i);
2146
TS->font_set_antialiasing(cache[i], antialiasing);
2147
}
2148
emit_changed();
2149
}
2150
}
2151
2152
TextServer::FontAntialiasing FontFile::get_antialiasing() const {
2153
return antialiasing;
2154
}
2155
2156
void FontFile::set_disable_embedded_bitmaps(bool p_disable_embedded_bitmaps) {
2157
if (disable_embedded_bitmaps != p_disable_embedded_bitmaps) {
2158
disable_embedded_bitmaps = p_disable_embedded_bitmaps;
2159
for (int i = 0; i < cache.size(); i++) {
2160
_ensure_rid(i);
2161
TS->font_set_disable_embedded_bitmaps(cache[i], disable_embedded_bitmaps);
2162
}
2163
emit_changed();
2164
}
2165
}
2166
2167
bool FontFile::get_disable_embedded_bitmaps() const {
2168
return disable_embedded_bitmaps;
2169
}
2170
2171
void FontFile::set_generate_mipmaps(bool p_generate_mipmaps) {
2172
if (mipmaps != p_generate_mipmaps) {
2173
mipmaps = p_generate_mipmaps;
2174
for (int i = 0; i < cache.size(); i++) {
2175
_ensure_rid(i);
2176
TS->font_set_generate_mipmaps(cache[i], mipmaps);
2177
}
2178
emit_changed();
2179
}
2180
}
2181
2182
bool FontFile::get_generate_mipmaps() const {
2183
return mipmaps;
2184
}
2185
2186
void FontFile::set_multichannel_signed_distance_field(bool p_msdf) {
2187
if (msdf != p_msdf) {
2188
msdf = p_msdf;
2189
for (int i = 0; i < cache.size(); i++) {
2190
_ensure_rid(i);
2191
TS->font_set_multichannel_signed_distance_field(cache[i], msdf);
2192
}
2193
emit_changed();
2194
}
2195
}
2196
2197
bool FontFile::is_multichannel_signed_distance_field() const {
2198
return msdf;
2199
}
2200
2201
void FontFile::set_msdf_pixel_range(int p_msdf_pixel_range) {
2202
if (msdf_pixel_range != p_msdf_pixel_range) {
2203
msdf_pixel_range = p_msdf_pixel_range;
2204
for (int i = 0; i < cache.size(); i++) {
2205
_ensure_rid(i);
2206
TS->font_set_msdf_pixel_range(cache[i], msdf_pixel_range);
2207
}
2208
emit_changed();
2209
}
2210
}
2211
2212
int FontFile::get_msdf_pixel_range() const {
2213
return msdf_pixel_range;
2214
}
2215
2216
void FontFile::set_msdf_size(int p_msdf_size) {
2217
if (msdf_size != p_msdf_size) {
2218
msdf_size = p_msdf_size;
2219
for (int i = 0; i < cache.size(); i++) {
2220
_ensure_rid(i);
2221
TS->font_set_msdf_size(cache[i], msdf_size);
2222
}
2223
emit_changed();
2224
}
2225
}
2226
2227
int FontFile::get_msdf_size() const {
2228
return msdf_size;
2229
}
2230
2231
void FontFile::set_fixed_size(int p_fixed_size) {
2232
if (fixed_size != p_fixed_size) {
2233
fixed_size = p_fixed_size;
2234
for (int i = 0; i < cache.size(); i++) {
2235
_ensure_rid(i);
2236
TS->font_set_fixed_size(cache[i], fixed_size);
2237
}
2238
emit_changed();
2239
}
2240
}
2241
2242
int FontFile::get_fixed_size() const {
2243
return fixed_size;
2244
}
2245
2246
void FontFile::set_fixed_size_scale_mode(TextServer::FixedSizeScaleMode p_fixed_size_scale_mode) {
2247
if (fixed_size_scale_mode != p_fixed_size_scale_mode) {
2248
fixed_size_scale_mode = p_fixed_size_scale_mode;
2249
for (int i = 0; i < cache.size(); i++) {
2250
_ensure_rid(i);
2251
TS->font_set_fixed_size_scale_mode(cache[i], fixed_size_scale_mode);
2252
}
2253
emit_changed();
2254
}
2255
}
2256
2257
TextServer::FixedSizeScaleMode FontFile::get_fixed_size_scale_mode() const {
2258
return fixed_size_scale_mode;
2259
}
2260
2261
void FontFile::set_allow_system_fallback(bool p_allow_system_fallback) {
2262
if (allow_system_fallback != p_allow_system_fallback) {
2263
allow_system_fallback = p_allow_system_fallback;
2264
for (int i = 0; i < cache.size(); i++) {
2265
_ensure_rid(i);
2266
TS->font_set_allow_system_fallback(cache[i], allow_system_fallback);
2267
}
2268
emit_changed();
2269
}
2270
}
2271
2272
bool FontFile::is_allow_system_fallback() const {
2273
return allow_system_fallback;
2274
}
2275
2276
void FontFile::set_force_autohinter(bool p_force_autohinter) {
2277
if (force_autohinter != p_force_autohinter) {
2278
force_autohinter = p_force_autohinter;
2279
for (int i = 0; i < cache.size(); i++) {
2280
_ensure_rid(i);
2281
TS->font_set_force_autohinter(cache[i], force_autohinter);
2282
}
2283
emit_changed();
2284
}
2285
}
2286
2287
bool FontFile::is_force_autohinter() const {
2288
return force_autohinter;
2289
}
2290
2291
void FontFile::set_modulate_color_glyphs(bool p_modulate) {
2292
if (modulate_color_glyphs != p_modulate) {
2293
modulate_color_glyphs = p_modulate;
2294
for (int i = 0; i < cache.size(); i++) {
2295
_ensure_rid(i);
2296
TS->font_set_modulate_color_glyphs(cache[i], modulate_color_glyphs);
2297
}
2298
emit_changed();
2299
}
2300
}
2301
2302
bool FontFile::is_modulate_color_glyphs() const {
2303
return modulate_color_glyphs;
2304
}
2305
2306
void FontFile::set_hinting(TextServer::Hinting p_hinting) {
2307
if (hinting != p_hinting) {
2308
hinting = p_hinting;
2309
for (int i = 0; i < cache.size(); i++) {
2310
_ensure_rid(i);
2311
TS->font_set_hinting(cache[i], hinting);
2312
}
2313
emit_changed();
2314
}
2315
}
2316
2317
TextServer::Hinting FontFile::get_hinting() const {
2318
return hinting;
2319
}
2320
2321
void FontFile::set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel) {
2322
if (subpixel_positioning != p_subpixel) {
2323
subpixel_positioning = p_subpixel;
2324
for (int i = 0; i < cache.size(); i++) {
2325
_ensure_rid(i);
2326
TS->font_set_subpixel_positioning(cache[i], subpixel_positioning);
2327
}
2328
emit_changed();
2329
}
2330
}
2331
2332
TextServer::SubpixelPositioning FontFile::get_subpixel_positioning() const {
2333
return subpixel_positioning;
2334
}
2335
2336
void FontFile::set_keep_rounding_remainders(bool p_keep_rounding_remainders) {
2337
if (keep_rounding_remainders != p_keep_rounding_remainders) {
2338
keep_rounding_remainders = p_keep_rounding_remainders;
2339
for (int i = 0; i < cache.size(); i++) {
2340
_ensure_rid(i);
2341
TS->font_set_keep_rounding_remainders(cache[i], keep_rounding_remainders);
2342
}
2343
emit_changed();
2344
}
2345
}
2346
2347
bool FontFile::get_keep_rounding_remainders() const {
2348
return keep_rounding_remainders;
2349
}
2350
2351
void FontFile::set_oversampling(real_t p_oversampling) {
2352
if (oversampling_override != p_oversampling) {
2353
oversampling_override = p_oversampling;
2354
for (int i = 0; i < cache.size(); i++) {
2355
_ensure_rid(i);
2356
TS->font_set_oversampling(cache[i], oversampling_override);
2357
}
2358
emit_changed();
2359
}
2360
}
2361
2362
real_t FontFile::get_oversampling() const {
2363
return oversampling_override;
2364
}
2365
2366
RID FontFile::find_variation(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform, int p_spacing_top, int p_spacing_bottom, int p_spacing_space, int p_spacing_glyph, float p_baseline_offset) const {
2367
// Find existing variation cache.
2368
const Dictionary &supported_coords = get_supported_variation_list();
2369
int make_linked_from = -1;
2370
for (int i = 0; i < cache.size(); i++) {
2371
if (cache[i].is_valid()) {
2372
const Dictionary &cache_var = TS->font_get_variation_coordinates(cache[i]);
2373
bool match = true;
2374
bool match_linked = true;
2375
match = match && (TS->font_get_face_index(cache[i]) == p_face_index);
2376
match = match && (TS->font_get_embolden(cache[i]) == p_strength);
2377
match = match && (TS->font_get_transform(cache[i]) == p_transform);
2378
match_linked = match_linked && (TS->font_get_spacing(cache[i], TextServer::SPACING_TOP) == p_spacing_top);
2379
match_linked = match_linked && (TS->font_get_spacing(cache[i], TextServer::SPACING_BOTTOM) == p_spacing_bottom);
2380
match_linked = match_linked && (TS->font_get_spacing(cache[i], TextServer::SPACING_SPACE) == p_spacing_space);
2381
match_linked = match_linked && (TS->font_get_spacing(cache[i], TextServer::SPACING_GLYPH) == p_spacing_glyph);
2382
match_linked = match_linked && (TS->font_get_baseline_offset(cache[i]) == p_baseline_offset);
2383
for (const Variant *V = supported_coords.next(nullptr); V && match; V = supported_coords.next(V)) {
2384
const Vector3 &def = supported_coords[*V];
2385
2386
real_t c_v = def.z;
2387
if (cache_var.has(*V)) {
2388
real_t val = cache_var[*V];
2389
c_v = CLAMP(val, def.x, def.y);
2390
}
2391
if (cache_var.has(TS->tag_to_name(*V))) {
2392
real_t val = cache_var[TS->tag_to_name(*V)];
2393
c_v = CLAMP(val, def.x, def.y);
2394
}
2395
2396
real_t s_v = def.z;
2397
if (p_variation_coordinates.has(*V)) {
2398
real_t val = p_variation_coordinates[*V];
2399
s_v = CLAMP(val, def.x, def.y);
2400
}
2401
if (p_variation_coordinates.has(TS->tag_to_name(*V))) {
2402
real_t val = p_variation_coordinates[TS->tag_to_name(*V)];
2403
s_v = CLAMP(val, def.x, def.y);
2404
}
2405
2406
match = match && (c_v == s_v);
2407
}
2408
if (match) {
2409
if (match_linked) {
2410
return cache[i];
2411
} else {
2412
make_linked_from = i;
2413
}
2414
}
2415
}
2416
}
2417
2418
// Create new variation cache.
2419
int idx = cache.size();
2420
if (make_linked_from >= 0) {
2421
_ensure_rid(idx, make_linked_from);
2422
TS->font_set_spacing(cache[idx], TextServer::SPACING_TOP, p_spacing_top);
2423
TS->font_set_spacing(cache[idx], TextServer::SPACING_BOTTOM, p_spacing_bottom);
2424
TS->font_set_spacing(cache[idx], TextServer::SPACING_SPACE, p_spacing_space);
2425
TS->font_set_spacing(cache[idx], TextServer::SPACING_GLYPH, p_spacing_glyph);
2426
TS->font_set_baseline_offset(cache[idx], p_baseline_offset);
2427
} else {
2428
_ensure_rid(idx);
2429
TS->font_set_variation_coordinates(cache[idx], p_variation_coordinates);
2430
TS->font_set_face_index(cache[idx], p_face_index);
2431
TS->font_set_embolden(cache[idx], p_strength);
2432
TS->font_set_transform(cache[idx], p_transform);
2433
TS->font_set_spacing(cache[idx], TextServer::SPACING_TOP, p_spacing_top);
2434
TS->font_set_spacing(cache[idx], TextServer::SPACING_BOTTOM, p_spacing_bottom);
2435
TS->font_set_spacing(cache[idx], TextServer::SPACING_SPACE, p_spacing_space);
2436
TS->font_set_spacing(cache[idx], TextServer::SPACING_GLYPH, p_spacing_glyph);
2437
TS->font_set_baseline_offset(cache[idx], p_baseline_offset);
2438
}
2439
return cache[idx];
2440
}
2441
2442
RID FontFile::_get_rid() const {
2443
_ensure_rid(0);
2444
return cache[0];
2445
}
2446
2447
int FontFile::get_cache_count() const {
2448
return cache.size();
2449
}
2450
2451
void FontFile::clear_cache() {
2452
_clear_cache();
2453
cache.clear();
2454
emit_changed();
2455
}
2456
2457
void FontFile::remove_cache(int p_cache_index) {
2458
ERR_FAIL_INDEX(p_cache_index, cache.size());
2459
if (cache[p_cache_index].is_valid()) {
2460
TS->free_rid(cache.write[p_cache_index]);
2461
}
2462
cache.remove_at(p_cache_index);
2463
emit_changed();
2464
}
2465
2466
TypedArray<Vector2i> FontFile::get_size_cache_list(int p_cache_index) const {
2467
ERR_FAIL_COND_V(p_cache_index < 0, Array());
2468
_ensure_rid(p_cache_index);
2469
return TS->font_get_size_cache_list(cache[p_cache_index]);
2470
}
2471
2472
void FontFile::clear_size_cache(int p_cache_index) {
2473
ERR_FAIL_COND(p_cache_index < 0);
2474
_ensure_rid(p_cache_index);
2475
TS->font_clear_size_cache(cache[p_cache_index]);
2476
}
2477
2478
void FontFile::remove_size_cache(int p_cache_index, const Vector2i &p_size) {
2479
ERR_FAIL_COND(p_cache_index < 0);
2480
_ensure_rid(p_cache_index);
2481
TS->font_remove_size_cache(cache[p_cache_index], p_size);
2482
}
2483
2484
void FontFile::set_variation_coordinates(int p_cache_index, const Dictionary &p_variation_coordinates) {
2485
ERR_FAIL_COND(p_cache_index < 0);
2486
_ensure_rid(p_cache_index);
2487
TS->font_set_variation_coordinates(cache[p_cache_index], p_variation_coordinates);
2488
}
2489
2490
Dictionary FontFile::get_variation_coordinates(int p_cache_index) const {
2491
ERR_FAIL_COND_V(p_cache_index < 0, Dictionary());
2492
_ensure_rid(p_cache_index);
2493
return TS->font_get_variation_coordinates(cache[p_cache_index]);
2494
}
2495
2496
void FontFile::set_embolden(int p_cache_index, float p_strength) {
2497
ERR_FAIL_COND(p_cache_index < 0);
2498
_ensure_rid(p_cache_index);
2499
TS->font_set_embolden(cache[p_cache_index], p_strength);
2500
}
2501
2502
float FontFile::get_embolden(int p_cache_index) const {
2503
ERR_FAIL_COND_V(p_cache_index < 0, 0.f);
2504
_ensure_rid(p_cache_index);
2505
return TS->font_get_embolden(cache[p_cache_index]);
2506
}
2507
2508
void FontFile::set_transform(int p_cache_index, Transform2D p_transform) {
2509
ERR_FAIL_COND(p_cache_index < 0);
2510
_ensure_rid(p_cache_index);
2511
TS->font_set_transform(cache[p_cache_index], p_transform);
2512
}
2513
2514
Transform2D FontFile::get_transform(int p_cache_index) const {
2515
ERR_FAIL_COND_V(p_cache_index < 0, Transform2D());
2516
_ensure_rid(p_cache_index);
2517
return TS->font_get_transform(cache[p_cache_index]);
2518
}
2519
2520
void FontFile::set_extra_spacing(int p_cache_index, TextServer::SpacingType p_spacing, int64_t p_value) {
2521
ERR_FAIL_COND(p_cache_index < 0);
2522
_ensure_rid(p_cache_index);
2523
TS->font_set_spacing(cache[p_cache_index], p_spacing, p_value);
2524
}
2525
2526
int64_t FontFile::get_extra_spacing(int p_cache_index, TextServer::SpacingType p_spacing) const {
2527
ERR_FAIL_COND_V(p_cache_index < 0, 0);
2528
_ensure_rid(p_cache_index);
2529
return TS->font_get_spacing(cache[p_cache_index], p_spacing);
2530
}
2531
2532
float FontFile::get_extra_baseline_offset(int p_cache_index) const {
2533
ERR_FAIL_COND_V(p_cache_index < 0, 0);
2534
_ensure_rid(p_cache_index);
2535
return TS->font_get_baseline_offset(cache[p_cache_index]);
2536
}
2537
2538
void FontFile::set_extra_baseline_offset(int p_cache_index, float p_baseline_offset) {
2539
ERR_FAIL_COND(p_cache_index < 0);
2540
_ensure_rid(p_cache_index);
2541
TS->font_set_baseline_offset(cache[p_cache_index], p_baseline_offset);
2542
}
2543
2544
void FontFile::set_face_index(int p_cache_index, int64_t p_index) {
2545
ERR_FAIL_COND(p_cache_index < 0);
2546
ERR_FAIL_COND(p_index < 0);
2547
ERR_FAIL_COND(p_index >= 0x7FFF);
2548
2549
_ensure_rid(p_cache_index);
2550
TS->font_set_face_index(cache[p_cache_index], p_index);
2551
}
2552
2553
int64_t FontFile::get_face_index(int p_cache_index) const {
2554
ERR_FAIL_COND_V(p_cache_index < 0, 0);
2555
_ensure_rid(p_cache_index);
2556
return TS->font_get_face_index(cache[p_cache_index]);
2557
}
2558
2559
void FontFile::set_cache_ascent(int p_cache_index, int p_size, real_t p_ascent) {
2560
ERR_FAIL_COND(p_cache_index < 0);
2561
_ensure_rid(p_cache_index);
2562
TS->font_set_ascent(cache[p_cache_index], p_size, p_ascent);
2563
}
2564
2565
real_t FontFile::get_cache_ascent(int p_cache_index, int p_size) const {
2566
ERR_FAIL_COND_V(p_cache_index < 0, 0.f);
2567
_ensure_rid(p_cache_index);
2568
return TS->font_get_ascent(cache[p_cache_index], p_size);
2569
}
2570
2571
void FontFile::set_cache_descent(int p_cache_index, int p_size, real_t p_descent) {
2572
ERR_FAIL_COND(p_cache_index < 0);
2573
_ensure_rid(p_cache_index);
2574
TS->font_set_descent(cache[p_cache_index], p_size, p_descent);
2575
}
2576
2577
real_t FontFile::get_cache_descent(int p_cache_index, int p_size) const {
2578
ERR_FAIL_COND_V(p_cache_index < 0, 0.f);
2579
_ensure_rid(p_cache_index);
2580
return TS->font_get_descent(cache[p_cache_index], p_size);
2581
}
2582
2583
void FontFile::set_cache_underline_position(int p_cache_index, int p_size, real_t p_underline_position) {
2584
ERR_FAIL_COND(p_cache_index < 0);
2585
_ensure_rid(p_cache_index);
2586
TS->font_set_underline_position(cache[p_cache_index], p_size, p_underline_position);
2587
}
2588
2589
real_t FontFile::get_cache_underline_position(int p_cache_index, int p_size) const {
2590
ERR_FAIL_COND_V(p_cache_index < 0, 0.f);
2591
_ensure_rid(p_cache_index);
2592
return TS->font_get_underline_position(cache[p_cache_index], p_size);
2593
}
2594
2595
void FontFile::set_cache_underline_thickness(int p_cache_index, int p_size, real_t p_underline_thickness) {
2596
ERR_FAIL_COND(p_cache_index < 0);
2597
_ensure_rid(p_cache_index);
2598
TS->font_set_underline_thickness(cache[p_cache_index], p_size, p_underline_thickness);
2599
}
2600
2601
real_t FontFile::get_cache_underline_thickness(int p_cache_index, int p_size) const {
2602
ERR_FAIL_COND_V(p_cache_index < 0, 0.f);
2603
_ensure_rid(p_cache_index);
2604
return TS->font_get_underline_thickness(cache[p_cache_index], p_size);
2605
}
2606
2607
void FontFile::set_cache_scale(int p_cache_index, int p_size, real_t p_scale) {
2608
ERR_FAIL_COND(p_cache_index < 0);
2609
_ensure_rid(p_cache_index);
2610
TS->font_set_scale(cache[p_cache_index], p_size, p_scale);
2611
}
2612
2613
real_t FontFile::get_cache_scale(int p_cache_index, int p_size) const {
2614
ERR_FAIL_COND_V(p_cache_index < 0, 0.f);
2615
_ensure_rid(p_cache_index);
2616
return TS->font_get_scale(cache[p_cache_index], p_size);
2617
}
2618
2619
int FontFile::get_texture_count(int p_cache_index, const Vector2i &p_size) const {
2620
ERR_FAIL_COND_V(p_cache_index < 0, 0);
2621
_ensure_rid(p_cache_index);
2622
return TS->font_get_texture_count(cache[p_cache_index], p_size);
2623
}
2624
2625
void FontFile::clear_textures(int p_cache_index, const Vector2i &p_size) {
2626
ERR_FAIL_COND(p_cache_index < 0);
2627
_ensure_rid(p_cache_index);
2628
TS->font_clear_textures(cache[p_cache_index], p_size);
2629
}
2630
2631
void FontFile::remove_texture(int p_cache_index, const Vector2i &p_size, int p_texture_index) {
2632
ERR_FAIL_COND(p_cache_index < 0);
2633
_ensure_rid(p_cache_index);
2634
TS->font_remove_texture(cache[p_cache_index], p_size, p_texture_index);
2635
}
2636
2637
void FontFile::set_texture_image(int p_cache_index, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) {
2638
ERR_FAIL_COND(p_cache_index < 0);
2639
_ensure_rid(p_cache_index);
2640
TS->font_set_texture_image(cache[p_cache_index], p_size, p_texture_index, p_image);
2641
}
2642
2643
Ref<Image> FontFile::get_texture_image(int p_cache_index, const Vector2i &p_size, int p_texture_index) const {
2644
ERR_FAIL_COND_V(p_cache_index < 0, Ref<Image>());
2645
_ensure_rid(p_cache_index);
2646
return TS->font_get_texture_image(cache[p_cache_index], p_size, p_texture_index);
2647
}
2648
2649
void FontFile::set_texture_offsets(int p_cache_index, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) {
2650
ERR_FAIL_COND(p_cache_index < 0);
2651
_ensure_rid(p_cache_index);
2652
TS->font_set_texture_offsets(cache[p_cache_index], p_size, p_texture_index, p_offset);
2653
}
2654
2655
PackedInt32Array FontFile::get_texture_offsets(int p_cache_index, const Vector2i &p_size, int p_texture_index) const {
2656
ERR_FAIL_COND_V(p_cache_index < 0, PackedInt32Array());
2657
_ensure_rid(p_cache_index);
2658
return TS->font_get_texture_offsets(cache[p_cache_index], p_size, p_texture_index);
2659
}
2660
2661
PackedInt32Array FontFile::get_glyph_list(int p_cache_index, const Vector2i &p_size) const {
2662
ERR_FAIL_COND_V(p_cache_index < 0, PackedInt32Array());
2663
_ensure_rid(p_cache_index);
2664
return TS->font_get_glyph_list(cache[p_cache_index], p_size);
2665
}
2666
2667
void FontFile::clear_glyphs(int p_cache_index, const Vector2i &p_size) {
2668
ERR_FAIL_COND(p_cache_index < 0);
2669
_ensure_rid(p_cache_index);
2670
TS->font_clear_glyphs(cache[p_cache_index], p_size);
2671
}
2672
2673
void FontFile::remove_glyph(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) {
2674
ERR_FAIL_COND(p_cache_index < 0);
2675
_ensure_rid(p_cache_index);
2676
TS->font_remove_glyph(cache[p_cache_index], p_size, p_glyph);
2677
}
2678
2679
void FontFile::set_glyph_advance(int p_cache_index, int p_size, int32_t p_glyph, const Vector2 &p_advance) {
2680
ERR_FAIL_COND(p_cache_index < 0);
2681
_ensure_rid(p_cache_index);
2682
TS->font_set_glyph_advance(cache[p_cache_index], p_size, p_glyph, p_advance);
2683
}
2684
2685
Vector2 FontFile::get_glyph_advance(int p_cache_index, int p_size, int32_t p_glyph) const {
2686
ERR_FAIL_COND_V(p_cache_index < 0, Vector2());
2687
_ensure_rid(p_cache_index);
2688
return TS->font_get_glyph_advance(cache[p_cache_index], p_size, p_glyph);
2689
}
2690
2691
void FontFile::set_glyph_offset(int p_cache_index, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) {
2692
ERR_FAIL_COND(p_cache_index < 0);
2693
_ensure_rid(p_cache_index);
2694
TS->font_set_glyph_offset(cache[p_cache_index], p_size, p_glyph, p_offset);
2695
}
2696
2697
Vector2 FontFile::get_glyph_offset(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) const {
2698
ERR_FAIL_COND_V(p_cache_index < 0, Vector2());
2699
_ensure_rid(p_cache_index);
2700
return TS->font_get_glyph_offset(cache[p_cache_index], p_size, p_glyph);
2701
}
2702
2703
void FontFile::set_glyph_size(int p_cache_index, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) {
2704
ERR_FAIL_COND(p_cache_index < 0);
2705
_ensure_rid(p_cache_index);
2706
TS->font_set_glyph_size(cache[p_cache_index], p_size, p_glyph, p_gl_size);
2707
}
2708
2709
Vector2 FontFile::get_glyph_size(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) const {
2710
ERR_FAIL_COND_V(p_cache_index < 0, Vector2());
2711
_ensure_rid(p_cache_index);
2712
return TS->font_get_glyph_size(cache[p_cache_index], p_size, p_glyph);
2713
}
2714
2715
void FontFile::set_glyph_uv_rect(int p_cache_index, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) {
2716
ERR_FAIL_COND(p_cache_index < 0);
2717
_ensure_rid(p_cache_index);
2718
TS->font_set_glyph_uv_rect(cache[p_cache_index], p_size, p_glyph, p_uv_rect);
2719
}
2720
2721
Rect2 FontFile::get_glyph_uv_rect(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) const {
2722
ERR_FAIL_COND_V(p_cache_index < 0, Rect2());
2723
_ensure_rid(p_cache_index);
2724
return TS->font_get_glyph_uv_rect(cache[p_cache_index], p_size, p_glyph);
2725
}
2726
2727
void FontFile::set_glyph_texture_idx(int p_cache_index, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) {
2728
ERR_FAIL_COND(p_cache_index < 0);
2729
_ensure_rid(p_cache_index);
2730
TS->font_set_glyph_texture_idx(cache[p_cache_index], p_size, p_glyph, p_texture_idx);
2731
}
2732
2733
int FontFile::get_glyph_texture_idx(int p_cache_index, const Vector2i &p_size, int32_t p_glyph) const {
2734
ERR_FAIL_COND_V(p_cache_index < 0, 0);
2735
_ensure_rid(p_cache_index);
2736
return TS->font_get_glyph_texture_idx(cache[p_cache_index], p_size, p_glyph);
2737
}
2738
2739
TypedArray<Vector2i> FontFile::get_kerning_list(int p_cache_index, int p_size) const {
2740
ERR_FAIL_COND_V(p_cache_index < 0, Array());
2741
_ensure_rid(p_cache_index);
2742
return TS->font_get_kerning_list(cache[p_cache_index], p_size);
2743
}
2744
2745
void FontFile::clear_kerning_map(int p_cache_index, int p_size) {
2746
ERR_FAIL_COND(p_cache_index < 0);
2747
_ensure_rid(p_cache_index);
2748
TS->font_clear_kerning_map(cache[p_cache_index], p_size);
2749
}
2750
2751
void FontFile::remove_kerning(int p_cache_index, int p_size, const Vector2i &p_glyph_pair) {
2752
ERR_FAIL_COND(p_cache_index < 0);
2753
_ensure_rid(p_cache_index);
2754
TS->font_remove_kerning(cache[p_cache_index], p_size, p_glyph_pair);
2755
}
2756
2757
void FontFile::set_kerning(int p_cache_index, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) {
2758
ERR_FAIL_COND(p_cache_index < 0);
2759
_ensure_rid(p_cache_index);
2760
TS->font_set_kerning(cache[p_cache_index], p_size, p_glyph_pair, p_kerning);
2761
}
2762
2763
Vector2 FontFile::get_kerning(int p_cache_index, int p_size, const Vector2i &p_glyph_pair) const {
2764
ERR_FAIL_COND_V(p_cache_index < 0, Vector2());
2765
_ensure_rid(p_cache_index);
2766
return TS->font_get_kerning(cache[p_cache_index], p_size, p_glyph_pair);
2767
}
2768
2769
void FontFile::render_range(int p_cache_index, const Vector2i &p_size, char32_t p_start, char32_t p_end) {
2770
ERR_FAIL_COND(p_cache_index < 0);
2771
_ensure_rid(p_cache_index);
2772
TS->font_render_range(cache[p_cache_index], p_size, p_start, p_end);
2773
}
2774
2775
void FontFile::render_glyph(int p_cache_index, const Vector2i &p_size, int32_t p_index) {
2776
ERR_FAIL_COND(p_cache_index < 0);
2777
_ensure_rid(p_cache_index);
2778
TS->font_render_glyph(cache[p_cache_index], p_size, p_index);
2779
}
2780
2781
void FontFile::set_language_support_override(const String &p_language, bool p_supported) {
2782
language_support_overrides[p_language] = p_supported;
2783
for (int i = 0; i < cache.size(); i++) {
2784
_ensure_rid(i);
2785
TS->font_set_language_support_override(cache[i], p_language, p_supported);
2786
}
2787
}
2788
2789
bool FontFile::get_language_support_override(const String &p_language) const {
2790
if (language_support_overrides.has(p_language)) {
2791
return language_support_overrides[p_language];
2792
} else {
2793
return false;
2794
}
2795
}
2796
2797
void FontFile::remove_language_support_override(const String &p_language) {
2798
if (language_support_overrides.has(p_language)) {
2799
language_support_overrides.erase(p_language);
2800
for (int i = 0; i < cache.size(); i++) {
2801
_ensure_rid(i);
2802
TS->font_remove_language_support_override(cache[i], p_language);
2803
}
2804
}
2805
}
2806
2807
Vector<String> FontFile::get_language_support_overrides() const {
2808
PackedStringArray out;
2809
for (const KeyValue<String, bool> &E : language_support_overrides) {
2810
out.push_back(E.key);
2811
}
2812
return out;
2813
}
2814
2815
void FontFile::set_script_support_override(const String &p_script, bool p_supported) {
2816
script_support_overrides[p_script] = p_supported;
2817
for (int i = 0; i < cache.size(); i++) {
2818
_ensure_rid(i);
2819
TS->font_set_script_support_override(cache[i], p_script, p_supported);
2820
}
2821
}
2822
2823
bool FontFile::get_script_support_override(const String &p_script) const {
2824
if (script_support_overrides.has(p_script)) {
2825
return script_support_overrides[p_script];
2826
} else {
2827
return false;
2828
}
2829
}
2830
2831
void FontFile::remove_script_support_override(const String &p_script) {
2832
if (script_support_overrides.has(p_script)) {
2833
script_support_overrides.erase(p_script);
2834
for (int i = 0; i < cache.size(); i++) {
2835
_ensure_rid(i);
2836
TS->font_remove_script_support_override(cache[i], p_script);
2837
}
2838
}
2839
}
2840
2841
Vector<String> FontFile::get_script_support_overrides() const {
2842
PackedStringArray out;
2843
for (const KeyValue<String, bool> &E : script_support_overrides) {
2844
out.push_back(E.key);
2845
}
2846
return out;
2847
}
2848
2849
void FontFile::set_opentype_feature_overrides(const Dictionary &p_overrides) {
2850
feature_overrides = p_overrides;
2851
for (int i = 0; i < cache.size(); i++) {
2852
_ensure_rid(i);
2853
TS->font_set_opentype_feature_overrides(cache[i], p_overrides);
2854
}
2855
}
2856
2857
Dictionary FontFile::get_opentype_feature_overrides() const {
2858
return feature_overrides;
2859
}
2860
2861
int32_t FontFile::get_glyph_index(int p_size, char32_t p_char, char32_t p_variation_selector) const {
2862
_ensure_rid(0);
2863
return TS->font_get_glyph_index(cache[0], p_size, p_char, p_variation_selector);
2864
}
2865
2866
char32_t FontFile::get_char_from_glyph_index(int p_size, int32_t p_glyph_index) const {
2867
_ensure_rid(0);
2868
return TS->font_get_char_from_glyph_index(cache[0], p_size, p_glyph_index);
2869
}
2870
2871
FontFile::FontFile() {
2872
}
2873
2874
FontFile::~FontFile() {
2875
_clear_cache();
2876
}
2877
2878
/*************************************************************************/
2879
/* FontVariation */
2880
/*************************************************************************/
2881
2882
void FontVariation::_bind_methods() {
2883
ClassDB::bind_method(D_METHOD("set_base_font", "font"), &FontVariation::set_base_font);
2884
ClassDB::bind_method(D_METHOD("get_base_font"), &FontVariation::get_base_font);
2885
2886
ClassDB::bind_method(D_METHOD("set_variation_opentype", "coords"), &FontVariation::set_variation_opentype);
2887
ClassDB::bind_method(D_METHOD("get_variation_opentype"), &FontVariation::get_variation_opentype);
2888
2889
ClassDB::bind_method(D_METHOD("set_variation_embolden", "strength"), &FontVariation::set_variation_embolden);
2890
ClassDB::bind_method(D_METHOD("get_variation_embolden"), &FontVariation::get_variation_embolden);
2891
2892
ClassDB::bind_method(D_METHOD("set_variation_face_index", "face_index"), &FontVariation::set_variation_face_index);
2893
ClassDB::bind_method(D_METHOD("get_variation_face_index"), &FontVariation::get_variation_face_index);
2894
2895
ClassDB::bind_method(D_METHOD("set_variation_transform", "transform"), &FontVariation::set_variation_transform);
2896
ClassDB::bind_method(D_METHOD("get_variation_transform"), &FontVariation::get_variation_transform);
2897
2898
ClassDB::bind_method(D_METHOD("set_opentype_features", "features"), &FontVariation::set_opentype_features);
2899
2900
ClassDB::bind_method(D_METHOD("set_spacing", "spacing", "value"), &FontVariation::set_spacing);
2901
2902
ClassDB::bind_method(D_METHOD("set_baseline_offset", "baseline_offset"), &FontVariation::set_baseline_offset);
2903
ClassDB::bind_method(D_METHOD("get_baseline_offset"), &FontVariation::get_baseline_offset);
2904
2905
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "base_font", PROPERTY_HINT_RESOURCE_TYPE, Font::get_class_static()), "set_base_font", "get_base_font");
2906
2907
ADD_GROUP("Variation", "variation_");
2908
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "variation_opentype"), "set_variation_opentype", "get_variation_opentype");
2909
ADD_PROPERTY(PropertyInfo(Variant::INT, "variation_face_index", PROPERTY_HINT_RANGE, "0,32767,1"), "set_variation_face_index", "get_variation_face_index");
2910
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "variation_embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), "set_variation_embolden", "get_variation_embolden");
2911
ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "variation_transform", PROPERTY_HINT_NONE, "suffix:px"), "set_variation_transform", "get_variation_transform");
2912
2913
ADD_GROUP("OpenType Features", "opentype_");
2914
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "opentype_features"), "set_opentype_features", "get_opentype_features");
2915
2916
ADD_GROUP("Extra Spacing", "spacing_");
2917
ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_glyph", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_GLYPH);
2918
ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_space", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_SPACE);
2919
ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_top", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_TOP);
2920
ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_bottom", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_BOTTOM);
2921
2922
ADD_GROUP("Baseline", "baseline_");
2923
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "baseline_offset", PROPERTY_HINT_RANGE, "-2,2,0.005"), "set_baseline_offset", "get_baseline_offset");
2924
}
2925
2926
void FontVariation::_update_rids() const {
2927
Ref<Font> f = _get_base_font_or_default();
2928
2929
rids.clear();
2930
if (fallbacks.is_empty() && f.is_valid()) {
2931
RID rid = _get_rid();
2932
if (rid.is_valid()) {
2933
rids.push_back(rid);
2934
}
2935
2936
const TypedArray<Font> &base_fallbacks = f->get_fallbacks();
2937
for (int i = 0; i < base_fallbacks.size(); i++) {
2938
Ref<Font> fb_font = base_fallbacks[i];
2939
_update_rids_fb(fb_font.ptr(), 0);
2940
}
2941
} else {
2942
_update_rids_fb(this, 0);
2943
}
2944
dirty_rids = false;
2945
}
2946
2947
void FontVariation::reset_state() {
2948
if (base_font.is_valid()) {
2949
base_font->disconnect_changed(callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
2950
base_font.unref();
2951
}
2952
2953
if (theme_font.is_valid()) {
2954
theme_font->disconnect_changed(callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
2955
theme_font.unref();
2956
}
2957
2958
variation = Variation();
2959
opentype_features = Dictionary();
2960
2961
for (int i = 0; i < TextServer::SPACING_MAX; i++) {
2962
extra_spacing[i] = 0;
2963
}
2964
baseline_offset = 0.0;
2965
2966
Font::reset_state();
2967
}
2968
2969
void FontVariation::set_base_font(const Ref<Font> &p_font) {
2970
if (base_font != p_font) {
2971
if (base_font.is_valid()) {
2972
base_font->disconnect_changed(callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
2973
}
2974
base_font = p_font;
2975
if (base_font.is_valid()) {
2976
base_font->connect_changed(callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
2977
}
2978
_invalidate_rids();
2979
notify_property_list_changed();
2980
}
2981
}
2982
2983
Ref<Font> FontVariation::get_base_font() const {
2984
return base_font;
2985
}
2986
2987
Ref<Font> FontVariation::_get_base_font_or_default() const {
2988
if (theme_font.is_valid()) {
2989
theme_font->disconnect_changed(callable_mp(static_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids));
2990
theme_font.unref();
2991
}
2992
2993
if (base_font.is_valid()) {
2994
return base_font;
2995
}
2996
2997
StringName theme_name = "font";
2998
Vector<StringName> theme_types;
2999
ThemeDB::get_singleton()->get_native_type_dependencies(get_class_name(), theme_types);
3000
3001
ThemeContext *global_context = ThemeDB::get_singleton()->get_default_theme_context();
3002
Vector<Ref<Theme>> themes = global_context->get_themes();
3003
if (Engine::get_singleton()->is_editor_hint()) {
3004
themes.insert(0, ThemeDB::get_singleton()->get_project_theme());
3005
}
3006
3007
for (const Ref<Theme> &theme : themes) {
3008
if (theme.is_null()) {
3009
continue;
3010
}
3011
3012
for (const StringName &E : theme_types) {
3013
if (!theme->has_font(theme_name, E)) {
3014
continue;
3015
}
3016
3017
Ref<Font> f = theme->get_font(theme_name, E);
3018
if (_is_base_cyclic(f, 0)) {
3019
continue;
3020
}
3021
if (f.is_valid()) {
3022
theme_font = f;
3023
theme_font->connect_changed(callable_mp(static_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
3024
}
3025
return f;
3026
}
3027
}
3028
3029
Ref<Font> f = global_context->get_fallback_theme()->get_font(theme_name, StringName());
3030
if (!_is_base_cyclic(f, 0)) {
3031
if (f.is_valid()) {
3032
theme_font = f;
3033
theme_font->connect_changed(callable_mp(static_cast<Font *>(const_cast<FontVariation *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
3034
}
3035
return f;
3036
}
3037
3038
return Ref<Font>();
3039
}
3040
3041
void FontVariation::set_variation_opentype(const Dictionary &p_coords) {
3042
if (!variation.opentype.recursive_equal(p_coords, 1)) {
3043
variation.opentype = p_coords.duplicate();
3044
_invalidate_rids();
3045
}
3046
}
3047
3048
Dictionary FontVariation::get_variation_opentype() const {
3049
return variation.opentype.duplicate();
3050
}
3051
3052
void FontVariation::set_variation_embolden(float p_strength) {
3053
if (variation.embolden != p_strength) {
3054
variation.embolden = p_strength;
3055
_invalidate_rids();
3056
}
3057
}
3058
3059
float FontVariation::get_variation_embolden() const {
3060
return variation.embolden;
3061
}
3062
3063
void FontVariation::set_variation_transform(Transform2D p_transform) {
3064
if (variation.transform != p_transform) {
3065
variation.transform = p_transform;
3066
_invalidate_rids();
3067
}
3068
}
3069
3070
Transform2D FontVariation::get_variation_transform() const {
3071
return variation.transform;
3072
}
3073
3074
void FontVariation::set_variation_face_index(int p_face_index) {
3075
if (variation.face_index != p_face_index) {
3076
variation.face_index = p_face_index;
3077
_invalidate_rids();
3078
}
3079
}
3080
3081
int FontVariation::get_variation_face_index() const {
3082
return variation.face_index;
3083
}
3084
3085
void FontVariation::set_opentype_features(const Dictionary &p_features) {
3086
if (!opentype_features.recursive_equal(p_features, 1)) {
3087
opentype_features = p_features.duplicate();
3088
_invalidate_rids();
3089
}
3090
}
3091
3092
Dictionary FontVariation::get_opentype_features() const {
3093
return opentype_features.duplicate();
3094
}
3095
3096
void FontVariation::set_spacing(TextServer::SpacingType p_spacing, int p_value) {
3097
ERR_FAIL_INDEX((int)p_spacing, TextServer::SPACING_MAX);
3098
if (extra_spacing[p_spacing] != p_value) {
3099
extra_spacing[p_spacing] = p_value;
3100
_invalidate_rids();
3101
}
3102
}
3103
3104
int FontVariation::get_spacing(TextServer::SpacingType p_spacing) const {
3105
ERR_FAIL_INDEX_V((int)p_spacing, TextServer::SPACING_MAX, 0);
3106
return extra_spacing[p_spacing];
3107
}
3108
3109
void FontVariation::set_baseline_offset(float p_baseline_offset) {
3110
if (baseline_offset != p_baseline_offset) {
3111
baseline_offset = p_baseline_offset;
3112
_invalidate_rids();
3113
}
3114
}
3115
3116
float FontVariation::get_baseline_offset() const {
3117
return baseline_offset;
3118
}
3119
3120
RID FontVariation::find_variation(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform, int p_spacing_top, int p_spacing_bottom, int p_spacing_space, int p_spacing_glyph, float p_baseline_offset) const {
3121
Ref<Font> f = _get_base_font_or_default();
3122
if (f.is_valid()) {
3123
return f->find_variation(p_variation_coordinates, p_face_index, p_strength, p_transform, p_spacing_top, p_spacing_bottom, p_spacing_space, p_spacing_glyph, p_baseline_offset);
3124
}
3125
return RID();
3126
}
3127
3128
RID FontVariation::_get_rid() const {
3129
Ref<Font> f = _get_base_font_or_default();
3130
if (f.is_valid()) {
3131
return f->find_variation(variation.opentype, variation.face_index, variation.embolden, variation.transform, extra_spacing[TextServer::SPACING_TOP], extra_spacing[TextServer::SPACING_BOTTOM], extra_spacing[TextServer::SPACING_SPACE], extra_spacing[TextServer::SPACING_GLYPH], baseline_offset);
3132
}
3133
return RID();
3134
}
3135
3136
FontVariation::FontVariation() {
3137
for (int i = 0; i < TextServer::SPACING_MAX; i++) {
3138
extra_spacing[i] = 0;
3139
}
3140
}
3141
3142
FontVariation::~FontVariation() {
3143
}
3144
3145
/*************************************************************************/
3146
/* SystemFont */
3147
/*************************************************************************/
3148
3149
void SystemFont::_bind_methods() {
3150
ClassDB::bind_method(D_METHOD("set_antialiasing", "antialiasing"), &SystemFont::set_antialiasing);
3151
ClassDB::bind_method(D_METHOD("get_antialiasing"), &SystemFont::get_antialiasing);
3152
3153
ClassDB::bind_method(D_METHOD("set_disable_embedded_bitmaps", "disable_embedded_bitmaps"), &SystemFont::set_disable_embedded_bitmaps);
3154
ClassDB::bind_method(D_METHOD("get_disable_embedded_bitmaps"), &SystemFont::get_disable_embedded_bitmaps);
3155
3156
ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &SystemFont::set_generate_mipmaps);
3157
ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &SystemFont::get_generate_mipmaps);
3158
3159
ClassDB::bind_method(D_METHOD("set_allow_system_fallback", "allow_system_fallback"), &SystemFont::set_allow_system_fallback);
3160
ClassDB::bind_method(D_METHOD("is_allow_system_fallback"), &SystemFont::is_allow_system_fallback);
3161
3162
ClassDB::bind_method(D_METHOD("set_force_autohinter", "force_autohinter"), &SystemFont::set_force_autohinter);
3163
ClassDB::bind_method(D_METHOD("is_force_autohinter"), &SystemFont::is_force_autohinter);
3164
3165
ClassDB::bind_method(D_METHOD("set_modulate_color_glyphs", "modulate"), &SystemFont::set_modulate_color_glyphs);
3166
ClassDB::bind_method(D_METHOD("is_modulate_color_glyphs"), &SystemFont::is_modulate_color_glyphs);
3167
3168
ClassDB::bind_method(D_METHOD("set_hinting", "hinting"), &SystemFont::set_hinting);
3169
ClassDB::bind_method(D_METHOD("get_hinting"), &SystemFont::get_hinting);
3170
3171
ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &SystemFont::set_subpixel_positioning);
3172
ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &SystemFont::get_subpixel_positioning);
3173
3174
ClassDB::bind_method(D_METHOD("set_keep_rounding_remainders", "keep_rounding_remainders"), &SystemFont::set_keep_rounding_remainders);
3175
ClassDB::bind_method(D_METHOD("get_keep_rounding_remainders"), &SystemFont::get_keep_rounding_remainders);
3176
3177
ClassDB::bind_method(D_METHOD("set_multichannel_signed_distance_field", "msdf"), &SystemFont::set_multichannel_signed_distance_field);
3178
ClassDB::bind_method(D_METHOD("is_multichannel_signed_distance_field"), &SystemFont::is_multichannel_signed_distance_field);
3179
3180
ClassDB::bind_method(D_METHOD("set_msdf_pixel_range", "msdf_pixel_range"), &SystemFont::set_msdf_pixel_range);
3181
ClassDB::bind_method(D_METHOD("get_msdf_pixel_range"), &SystemFont::get_msdf_pixel_range);
3182
3183
ClassDB::bind_method(D_METHOD("set_msdf_size", "msdf_size"), &SystemFont::set_msdf_size);
3184
ClassDB::bind_method(D_METHOD("get_msdf_size"), &SystemFont::get_msdf_size);
3185
3186
ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &SystemFont::set_oversampling);
3187
ClassDB::bind_method(D_METHOD("get_oversampling"), &SystemFont::get_oversampling);
3188
3189
ClassDB::bind_method(D_METHOD("get_font_names"), &SystemFont::get_font_names);
3190
ClassDB::bind_method(D_METHOD("set_font_names", "names"), &SystemFont::set_font_names);
3191
3192
ClassDB::bind_method(D_METHOD("get_font_italic"), &SystemFont::get_font_italic);
3193
ClassDB::bind_method(D_METHOD("set_font_italic", "italic"), &SystemFont::set_font_italic);
3194
ClassDB::bind_method(D_METHOD("set_font_weight", "weight"), &SystemFont::set_font_weight);
3195
ClassDB::bind_method(D_METHOD("set_font_stretch", "stretch"), &SystemFont::set_font_stretch);
3196
3197
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "font_names"), "set_font_names", "get_font_names");
3198
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "font_italic"), "set_font_italic", "get_font_italic");
3199
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_weight", PROPERTY_HINT_RANGE, "100,999,25"), "set_font_weight", "get_font_weight");
3200
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_stretch", PROPERTY_HINT_RANGE, "50,200,25"), "set_font_stretch", "get_font_stretch");
3201
ADD_PROPERTY(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD Subpixel", PROPERTY_USAGE_STORAGE), "set_antialiasing", "get_antialiasing");
3202
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps"), "set_generate_mipmaps", "get_generate_mipmaps");
3203
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_embedded_bitmaps"), "set_disable_embedded_bitmaps", "get_disable_embedded_bitmaps");
3204
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_system_fallback"), "set_allow_system_fallback", "is_allow_system_fallback");
3205
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_autohinter"), "set_force_autohinter", "is_force_autohinter");
3206
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "modulate_color_glyphs"), "set_modulate_color_glyphs", "is_modulate_color_glyphs");
3207
ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting");
3208
ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One Half of a Pixel,One Quarter of a Pixel"), "set_subpixel_positioning", "get_subpixel_positioning");
3209
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_rounding_remainders"), "set_keep_rounding_remainders", "get_keep_rounding_remainders");
3210
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field"), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field");
3211
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_pixel_range"), "set_msdf_pixel_range", "get_msdf_pixel_range");
3212
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_size"), "set_msdf_size", "get_msdf_size");
3213
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "oversampling"), "set_oversampling", "get_oversampling");
3214
}
3215
3216
void SystemFont::_update_rids() const {
3217
Ref<Font> f = _get_base_font_or_default();
3218
3219
rids.clear();
3220
if (fallbacks.is_empty() && f.is_valid()) {
3221
RID rid = _get_rid();
3222
if (rid.is_valid()) {
3223
rids.push_back(rid);
3224
}
3225
3226
const TypedArray<Font> &base_fallbacks = f->get_fallbacks();
3227
for (int i = 0; i < base_fallbacks.size(); i++) {
3228
Ref<Font> fb_font = base_fallbacks[i];
3229
_update_rids_fb(fb_font.ptr(), 0);
3230
}
3231
} else {
3232
_update_rids_fb(this, 0);
3233
}
3234
dirty_rids = false;
3235
}
3236
3237
void SystemFont::_update_base_font() {
3238
if (base_font.is_valid()) {
3239
base_font->disconnect_changed(callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
3240
base_font.unref();
3241
}
3242
3243
face_indices.clear();
3244
ftr_weight = 0;
3245
ftr_stretch = 0;
3246
ftr_italic = 0;
3247
for (const String &E : names) {
3248
if (E.is_empty()) {
3249
continue;
3250
}
3251
3252
String path = OS::get_singleton()->get_system_font_path(E, weight, stretch, italic);
3253
if (path.is_empty()) {
3254
continue;
3255
}
3256
Ref<FontFile> file;
3257
file.instantiate();
3258
Error err = file->load_dynamic_font(path);
3259
if (err != OK) {
3260
continue;
3261
}
3262
3263
// If it's a font collection check all faces to match requested style and name.
3264
int best_score = 0;
3265
for (int i = 0; i < file->get_face_count(); i++) {
3266
int score = 0;
3267
file->set_face_index(0, i);
3268
const String n = file->get_font_name();
3269
if (n.to_upper() == E.to_upper()) {
3270
score += 80;
3271
}
3272
BitField<TextServer::FontStyle> style = file->get_font_style();
3273
int font_weight = file->get_font_weight();
3274
int font_stretch = file->get_font_stretch();
3275
score += (20 - Math::abs(font_weight - weight) / 50);
3276
score += (20 - Math::abs(font_stretch - stretch) / 10);
3277
if (bool(style & TextServer::FONT_ITALIC) == italic) {
3278
score += 30;
3279
}
3280
if (score > best_score) {
3281
face_indices.clear();
3282
}
3283
if (score >= best_score) {
3284
best_score = score;
3285
face_indices.push_back(i);
3286
}
3287
}
3288
if (face_indices.is_empty()) {
3289
face_indices.push_back(0);
3290
}
3291
file->set_face_index(0, face_indices[0]);
3292
3293
// If it's a variable font, apply weight, stretch and italic coordinates to match requested style.
3294
if (best_score != 150) {
3295
Dictionary ftr = file->get_supported_variation_list();
3296
if (ftr.has(TS->name_to_tag("width"))) {
3297
ftr_stretch = stretch;
3298
}
3299
if (ftr.has(TS->name_to_tag("weight"))) {
3300
ftr_weight = weight;
3301
}
3302
if (italic && ftr.has(TS->name_to_tag("italic"))) {
3303
ftr_italic = 1;
3304
}
3305
}
3306
3307
// Apply font rendering settings.
3308
file->set_antialiasing(antialiasing);
3309
file->set_generate_mipmaps(mipmaps);
3310
file->set_disable_embedded_bitmaps(disable_embedded_bitmaps);
3311
file->set_force_autohinter(force_autohinter);
3312
file->set_modulate_color_glyphs(modulate_color_glyphs);
3313
file->set_allow_system_fallback(allow_system_fallback);
3314
file->set_hinting(hinting);
3315
file->set_subpixel_positioning(subpixel_positioning);
3316
file->set_keep_rounding_remainders(keep_rounding_remainders);
3317
file->set_oversampling(oversampling_override);
3318
file->set_multichannel_signed_distance_field(msdf);
3319
file->set_msdf_pixel_range(msdf_pixel_range);
3320
file->set_msdf_size(msdf_size);
3321
3322
base_font = file;
3323
3324
break;
3325
}
3326
3327
if (base_font.is_valid()) {
3328
base_font->connect_changed(callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
3329
}
3330
3331
_invalidate_rids();
3332
}
3333
3334
void SystemFont::reset_state() {
3335
if (base_font.is_valid()) {
3336
base_font->disconnect_changed(callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
3337
base_font.unref();
3338
}
3339
3340
if (theme_font.is_valid()) {
3341
theme_font->disconnect_changed(callable_mp(reinterpret_cast<Font *>(this), &Font::_invalidate_rids));
3342
theme_font.unref();
3343
}
3344
3345
names.clear();
3346
face_indices.clear();
3347
ftr_weight = 0;
3348
ftr_stretch = 0;
3349
ftr_italic = 0;
3350
italic = false;
3351
weight = 400;
3352
stretch = 100;
3353
antialiasing = TextServer::FONT_ANTIALIASING_GRAY;
3354
mipmaps = false;
3355
disable_embedded_bitmaps = true;
3356
force_autohinter = false;
3357
modulate_color_glyphs = false;
3358
allow_system_fallback = true;
3359
hinting = TextServer::HINTING_LIGHT;
3360
subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_DISABLED;
3361
keep_rounding_remainders = true;
3362
oversampling_override = 0.0;
3363
msdf = false;
3364
3365
Font::reset_state();
3366
}
3367
3368
Ref<Font> SystemFont::_get_base_font_or_default() const {
3369
if (theme_font.is_valid()) {
3370
theme_font->disconnect_changed(callable_mp(static_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids));
3371
theme_font.unref();
3372
}
3373
3374
if (base_font.is_valid()) {
3375
return base_font;
3376
}
3377
3378
StringName theme_name = "font";
3379
Vector<StringName> theme_types;
3380
ThemeDB::get_singleton()->get_native_type_dependencies(get_class_name(), theme_types);
3381
3382
ThemeContext *global_context = ThemeDB::get_singleton()->get_default_theme_context();
3383
for (const Ref<Theme> &theme : global_context->get_themes()) {
3384
if (theme.is_null()) {
3385
continue;
3386
}
3387
3388
for (const StringName &E : theme_types) {
3389
if (!theme->has_font(theme_name, E)) {
3390
continue;
3391
}
3392
3393
Ref<Font> f = theme->get_font(theme_name, E);
3394
if (_is_base_cyclic(f, 0)) {
3395
continue;
3396
}
3397
if (f.is_valid()) {
3398
theme_font = f;
3399
theme_font->connect_changed(callable_mp(static_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
3400
}
3401
return f;
3402
}
3403
}
3404
3405
Ref<Font> f = global_context->get_fallback_theme()->get_font(theme_name, StringName());
3406
if (!_is_base_cyclic(f, 0)) {
3407
if (f.is_valid()) {
3408
theme_font = f;
3409
theme_font->connect_changed(callable_mp(static_cast<Font *>(const_cast<SystemFont *>(this)), &Font::_invalidate_rids), CONNECT_REFERENCE_COUNTED);
3410
}
3411
return f;
3412
}
3413
3414
return Ref<Font>();
3415
}
3416
3417
void SystemFont::set_antialiasing(TextServer::FontAntialiasing p_antialiasing) {
3418
if (antialiasing != p_antialiasing) {
3419
antialiasing = p_antialiasing;
3420
if (base_font.is_valid()) {
3421
base_font->set_antialiasing(antialiasing);
3422
}
3423
emit_changed();
3424
}
3425
}
3426
3427
TextServer::FontAntialiasing SystemFont::get_antialiasing() const {
3428
return antialiasing;
3429
}
3430
3431
void SystemFont::set_disable_embedded_bitmaps(bool p_disable_embedded_bitmaps) {
3432
if (disable_embedded_bitmaps != p_disable_embedded_bitmaps) {
3433
disable_embedded_bitmaps = p_disable_embedded_bitmaps;
3434
if (base_font.is_valid()) {
3435
base_font->set_disable_embedded_bitmaps(disable_embedded_bitmaps);
3436
}
3437
emit_changed();
3438
}
3439
}
3440
3441
bool SystemFont::get_disable_embedded_bitmaps() const {
3442
return disable_embedded_bitmaps;
3443
}
3444
3445
void SystemFont::set_generate_mipmaps(bool p_generate_mipmaps) {
3446
if (mipmaps != p_generate_mipmaps) {
3447
mipmaps = p_generate_mipmaps;
3448
if (base_font.is_valid()) {
3449
base_font->set_generate_mipmaps(mipmaps);
3450
}
3451
emit_changed();
3452
}
3453
}
3454
3455
bool SystemFont::get_generate_mipmaps() const {
3456
return mipmaps;
3457
}
3458
3459
void SystemFont::set_allow_system_fallback(bool p_allow_system_fallback) {
3460
if (allow_system_fallback != p_allow_system_fallback) {
3461
allow_system_fallback = p_allow_system_fallback;
3462
if (base_font.is_valid()) {
3463
base_font->set_allow_system_fallback(allow_system_fallback);
3464
}
3465
emit_changed();
3466
}
3467
}
3468
3469
bool SystemFont::is_allow_system_fallback() const {
3470
return allow_system_fallback;
3471
}
3472
3473
void SystemFont::set_force_autohinter(bool p_force_autohinter) {
3474
if (force_autohinter != p_force_autohinter) {
3475
force_autohinter = p_force_autohinter;
3476
if (base_font.is_valid()) {
3477
base_font->set_force_autohinter(force_autohinter);
3478
}
3479
emit_changed();
3480
}
3481
}
3482
3483
bool SystemFont::is_force_autohinter() const {
3484
return force_autohinter;
3485
}
3486
3487
void SystemFont::set_modulate_color_glyphs(bool p_modulate) {
3488
if (modulate_color_glyphs != p_modulate) {
3489
modulate_color_glyphs = p_modulate;
3490
if (base_font.is_valid()) {
3491
base_font->set_modulate_color_glyphs(modulate_color_glyphs);
3492
}
3493
emit_changed();
3494
}
3495
}
3496
3497
bool SystemFont::is_modulate_color_glyphs() const {
3498
return modulate_color_glyphs;
3499
}
3500
3501
void SystemFont::set_hinting(TextServer::Hinting p_hinting) {
3502
if (hinting != p_hinting) {
3503
hinting = p_hinting;
3504
if (base_font.is_valid()) {
3505
base_font->set_hinting(hinting);
3506
}
3507
emit_changed();
3508
}
3509
}
3510
3511
TextServer::Hinting SystemFont::get_hinting() const {
3512
return hinting;
3513
}
3514
3515
void SystemFont::set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel) {
3516
if (subpixel_positioning != p_subpixel) {
3517
subpixel_positioning = p_subpixel;
3518
if (base_font.is_valid()) {
3519
base_font->set_subpixel_positioning(subpixel_positioning);
3520
}
3521
emit_changed();
3522
}
3523
}
3524
3525
TextServer::SubpixelPositioning SystemFont::get_subpixel_positioning() const {
3526
return subpixel_positioning;
3527
}
3528
3529
void SystemFont::set_keep_rounding_remainders(bool p_keep_rounding_remainders) {
3530
if (keep_rounding_remainders != p_keep_rounding_remainders) {
3531
keep_rounding_remainders = p_keep_rounding_remainders;
3532
if (base_font.is_valid()) {
3533
base_font->set_keep_rounding_remainders(keep_rounding_remainders);
3534
}
3535
emit_changed();
3536
}
3537
}
3538
3539
bool SystemFont::get_keep_rounding_remainders() const {
3540
return keep_rounding_remainders;
3541
}
3542
3543
void SystemFont::set_oversampling(real_t p_oversampling) {
3544
if (oversampling_override != p_oversampling) {
3545
oversampling_override = p_oversampling;
3546
if (base_font.is_valid()) {
3547
base_font->set_oversampling(oversampling_override);
3548
}
3549
emit_changed();
3550
}
3551
}
3552
3553
real_t SystemFont::get_oversampling() const {
3554
return oversampling_override;
3555
}
3556
3557
void SystemFont::set_multichannel_signed_distance_field(bool p_msdf) {
3558
if (msdf != p_msdf) {
3559
msdf = p_msdf;
3560
if (base_font.is_valid()) {
3561
base_font->set_multichannel_signed_distance_field(msdf);
3562
}
3563
emit_changed();
3564
}
3565
}
3566
3567
bool SystemFont::is_multichannel_signed_distance_field() const {
3568
return msdf;
3569
}
3570
3571
void SystemFont::set_msdf_pixel_range(int p_msdf_pixel_range) {
3572
if (msdf_pixel_range != p_msdf_pixel_range) {
3573
msdf_pixel_range = p_msdf_pixel_range;
3574
if (base_font.is_valid()) {
3575
base_font->set_msdf_pixel_range(msdf_pixel_range);
3576
}
3577
emit_changed();
3578
}
3579
}
3580
3581
int SystemFont::get_msdf_pixel_range() const {
3582
return msdf_pixel_range;
3583
}
3584
3585
void SystemFont::set_msdf_size(int p_msdf_size) {
3586
if (msdf_size != p_msdf_size) {
3587
msdf_size = p_msdf_size;
3588
if (base_font.is_valid()) {
3589
base_font->set_msdf_size(msdf_size);
3590
}
3591
emit_changed();
3592
}
3593
}
3594
3595
int SystemFont::get_msdf_size() const {
3596
return msdf_size;
3597
}
3598
3599
void SystemFont::set_font_names(const PackedStringArray &p_names) {
3600
if (names != p_names) {
3601
names = p_names;
3602
_update_base_font();
3603
}
3604
}
3605
3606
PackedStringArray SystemFont::get_font_names() const {
3607
return names;
3608
}
3609
3610
void SystemFont::set_font_italic(bool p_italic) {
3611
if (italic != p_italic) {
3612
italic = p_italic;
3613
_update_base_font();
3614
}
3615
}
3616
3617
bool SystemFont::get_font_italic() const {
3618
return italic;
3619
}
3620
3621
void SystemFont::set_font_weight(int p_weight) {
3622
if (weight != p_weight) {
3623
weight = CLAMP(p_weight, 100, 999);
3624
_update_base_font();
3625
}
3626
}
3627
3628
int SystemFont::get_font_weight() const {
3629
return weight;
3630
}
3631
3632
void SystemFont::set_font_stretch(int p_stretch) {
3633
if (stretch != p_stretch) {
3634
stretch = CLAMP(p_stretch, 50, 200);
3635
_update_base_font();
3636
}
3637
}
3638
3639
int SystemFont::get_font_stretch() const {
3640
return stretch;
3641
}
3642
3643
int SystemFont::get_spacing(TextServer::SpacingType p_spacing) const {
3644
if (base_font.is_valid()) {
3645
return base_font->get_spacing(p_spacing);
3646
} else {
3647
return 0;
3648
}
3649
}
3650
3651
RID SystemFont::find_variation(const Dictionary &p_variation_coordinates, int p_face_index, float p_strength, Transform2D p_transform, int p_spacing_top, int p_spacing_bottom, int p_spacing_space, int p_spacing_glyph, float p_baseline_offset) const {
3652
Ref<Font> f = _get_base_font_or_default();
3653
if (f.is_valid()) {
3654
Dictionary var = p_variation_coordinates;
3655
if (ftr_weight > 0 && !var.has(TS->name_to_tag("weight"))) {
3656
var[TS->name_to_tag("weight")] = ftr_weight;
3657
}
3658
if (ftr_stretch > 0 && !var.has(TS->name_to_tag("width"))) {
3659
var[TS->name_to_tag("width")] = ftr_stretch;
3660
}
3661
if (ftr_italic > 0 && !var.has(TS->name_to_tag("italic"))) {
3662
var[TS->name_to_tag("italic")] = ftr_italic;
3663
}
3664
3665
if (!face_indices.is_empty()) {
3666
int face_index = CLAMP(p_face_index, 0, face_indices.size() - 1);
3667
return f->find_variation(var, face_indices[face_index], p_strength, p_transform, p_spacing_top, p_spacing_bottom, p_spacing_space, p_spacing_glyph, p_baseline_offset);
3668
} else {
3669
return f->find_variation(var, 0, p_strength, p_transform, p_spacing_top, p_spacing_bottom, p_spacing_space, p_spacing_glyph, p_baseline_offset);
3670
}
3671
}
3672
return RID();
3673
}
3674
3675
RID SystemFont::_get_rid() const {
3676
Ref<Font> f = _get_base_font_or_default();
3677
if (f.is_valid()) {
3678
if (!face_indices.is_empty()) {
3679
Dictionary var;
3680
if (ftr_weight > 0) {
3681
var[TS->name_to_tag("weight")] = ftr_weight;
3682
}
3683
if (ftr_stretch > 0) {
3684
var[TS->name_to_tag("width")] = ftr_stretch;
3685
}
3686
if (ftr_italic > 0) {
3687
var[TS->name_to_tag("italic")] = ftr_italic;
3688
}
3689
return f->find_variation(var, face_indices[0]);
3690
} else {
3691
return f->_get_rid();
3692
}
3693
}
3694
return RID();
3695
}
3696
3697
int64_t SystemFont::get_face_count() const {
3698
return face_indices.size();
3699
}
3700
3701
SystemFont::SystemFont() {
3702
/* NOP */
3703
}
3704
3705
SystemFont::~SystemFont() {
3706
}
3707
3708