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