diff options
Diffstat (limited to 'modules/text_server_adv')
| -rw-r--r-- | modules/text_server_adv/SCsub | 3 | ||||
| -rw-r--r-- | modules/text_server_adv/config.py | 10 | ||||
| -rw-r--r-- | modules/text_server_adv/doc_classes/TextServerAdvanced.xml | 10 | ||||
| -rw-r--r-- | modules/text_server_adv/register_types.cpp | 7 | ||||
| -rw-r--r-- | modules/text_server_adv/script_iterator.cpp | 20 | ||||
| -rw-r--r-- | modules/text_server_adv/script_iterator.h | 2 | ||||
| -rw-r--r-- | modules/text_server_adv/text_server_adv.cpp | 1590 | ||||
| -rw-r--r-- | modules/text_server_adv/text_server_adv.h | 136 |
8 files changed, 1014 insertions, 764 deletions
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index 6691f86e60..68d1af84df 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -7,7 +7,6 @@ env_text_server_adv = env_modules.Clone() def make_icu_data(target, source, env): - import os dst = target[0].srcnode().abspath @@ -24,7 +23,6 @@ def make_icu_data(target, source, env): f = open(source[0].srcnode().abspath, "rb") buf = f.read() - import os.path g.write('extern "C" U_EXPORT const size_t U_ICUDATA_SIZE = ' + str(len(buf)) + ";\n") g.write('extern "C" U_EXPORT const unsigned char U_ICUDATA_ENTRY_POINT[] = {\n') @@ -64,6 +62,7 @@ if env["builtin_harfbuzz"]: #'src/hb-gobject-structs.cc', "src/hb-icu.cc", "src/hb-map.cc", + "src/hb-ms-feature-ranges.cc", "src/hb-number.cc", "src/hb-ot-cff1-table.cc", "src/hb-ot-cff2-table.cc", diff --git a/modules/text_server_adv/config.py b/modules/text_server_adv/config.py index d22f9454ed..8c8df9b05e 100644 --- a/modules/text_server_adv/config.py +++ b/modules/text_server_adv/config.py @@ -4,3 +4,13 @@ def can_build(env, platform): def configure(env): pass + + +def get_doc_classes(): + return [ + "TextServerAdvanced", + ] + + +def get_doc_path(): + return "doc_classes" diff --git a/modules/text_server_adv/doc_classes/TextServerAdvanced.xml b/modules/text_server_adv/doc_classes/TextServerAdvanced.xml new file mode 100644 index 0000000000..eff4aa5fae --- /dev/null +++ b/modules/text_server_adv/doc_classes/TextServerAdvanced.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="TextServerAdvanced" inherits="TextServer" version="4.0"> + <brief_description> + Text Server using HarfBuzz, ICU and SIL Graphite to support BiDi, complex text layouts and contextual OpenType features. + </brief_description> + <description> + </description> + <tutorials> + </tutorials> +</class> diff --git a/modules/text_server_adv/register_types.cpp b/modules/text_server_adv/register_types.cpp index abefa83b9b..b711d1561f 100644 --- a/modules/text_server_adv/register_types.cpp +++ b/modules/text_server_adv/register_types.cpp @@ -33,7 +33,12 @@ #include "text_server_adv.h" void preregister_text_server_adv_types() { - TextServerAdvanced::register_server(); + GDREGISTER_CLASS(TextServerAdvanced); + if (TextServerManager::get_singleton()) { + Ref<TextServerAdvanced> ts; + ts.instantiate(); + TextServerManager::get_singleton()->add_interface(ts); + } } void register_text_server_adv_types() { diff --git a/modules/text_server_adv/script_iterator.cpp b/modules/text_server_adv/script_iterator.cpp index f9bbd25a5f..d1e849def8 100644 --- a/modules/text_server_adv/script_iterator.cpp +++ b/modules/text_server_adv/script_iterator.cpp @@ -30,6 +30,8 @@ #include "script_iterator.h" +// This implementation is derived from ICU: icu4c/source/extra/scrptrun/scrptrun.cpp + bool ScriptIterator::same_script(int32_t p_script_one, int32_t p_script_two) { return p_script_one <= USCRIPT_INHERITED || p_script_two <= USCRIPT_INHERITED || p_script_one == p_script_two; } @@ -48,7 +50,8 @@ ScriptIterator::ScriptIterator(const String &p_string, int p_start, int p_length p_start = 0; } - ParenStackEntry paren_stack[128]; + int paren_size = PAREN_STACK_DEPTH; + ParenStackEntry *paren_stack = (ParenStackEntry *)memalloc(paren_size * sizeof(ParenStackEntry)); int script_start; int script_end = p_start; @@ -64,13 +67,22 @@ ScriptIterator::ScriptIterator(const String &p_string, int p_start, int p_length UChar32 ch = str[script_end]; UScriptCode sc = uscript_getScript(ch, &err); if (U_FAILURE(err)) { + memfree(paren_stack); ERR_FAIL_MSG(u_errorName(err)); } if (u_getIntPropertyValue(ch, UCHAR_BIDI_PAIRED_BRACKET_TYPE) != U_BPT_NONE) { if (u_getIntPropertyValue(ch, UCHAR_BIDI_PAIRED_BRACKET_TYPE) == U_BPT_OPEN) { - paren_stack[++paren_sp].pair_index = ch; + // If it's an open character, push it onto the stack. + paren_sp++; + if (unlikely(paren_sp >= paren_size)) { + // If the stack is full, allocate more space to handle deeply nested parentheses. This is unlikely to happen with any real text. + paren_size += PAREN_STACK_DEPTH; + paren_stack = (ParenStackEntry *)memrealloc(paren_stack, paren_size * sizeof(ParenStackEntry)); + } + paren_stack[paren_sp].pair_index = ch; paren_stack[paren_sp].script_code = script_code; } else if (paren_sp >= 0) { + // If it's a close character, find the matching open on the stack, and use that script code. Any non-matching open characters above it on the stack will be poped. UChar32 paired_ch = u_getBidiPairedBracket(ch); while (paren_sp >= 0 && paren_stack[paren_sp].pair_index != paired_ch) { paren_sp -= 1; @@ -87,11 +99,13 @@ ScriptIterator::ScriptIterator(const String &p_string, int p_start, int p_length if (same_script(script_code, sc)) { if (script_code <= USCRIPT_INHERITED && sc > USCRIPT_INHERITED) { script_code = sc; + // Now that we have a final script code, fix any open characters we pushed before we knew the script code. while (start_sp < paren_sp) { paren_stack[++start_sp].script_code = script_code; } } if ((u_getIntPropertyValue(ch, UCHAR_BIDI_PAIRED_BRACKET_TYPE) == U_BPT_CLOSE) && paren_sp >= 0) { + // If this character is a close paired character pop the matching open character from the stack. paren_sp -= 1; if (start_sp >= 0) { start_sp -= 1; @@ -109,4 +123,6 @@ ScriptIterator::ScriptIterator(const String &p_string, int p_start, int p_length script_ranges.push_back(rng); } while (script_end < p_length); + + memfree(paren_stack); } diff --git a/modules/text_server_adv/script_iterator.h b/modules/text_server_adv/script_iterator.h index 896a0e5c15..5efd40f7c4 100644 --- a/modules/text_server_adv/script_iterator.h +++ b/modules/text_server_adv/script_iterator.h @@ -43,6 +43,8 @@ #include <hb.h> class ScriptIterator { + static const int PAREN_STACK_DEPTH = 128; + public: struct ScriptRange { int start = 0; diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 78a87be971..e95369ead7 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -30,6 +30,7 @@ #include "text_server_adv.h" +#include "core/error/error_macros.h" #include "core/string/print_string.h" #include "core/string/translation.h" @@ -45,13 +46,13 @@ #endif /*************************************************************************/ -/* hb_bmp_font_t HarfBuzz Bitmap font interface */ +/* bmp_font_t HarfBuzz Bitmap font interface */ /*************************************************************************/ hb_font_funcs_t *TextServerAdvanced::funcs = nullptr; -TextServerAdvanced::hb_bmp_font_t *TextServerAdvanced::_hb_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref) { - hb_bmp_font_t *bm_font = memnew(hb_bmp_font_t); +TextServerAdvanced::bmp_font_t *TextServerAdvanced::_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref) { + bmp_font_t *bm_font = memnew(bmp_font_t); if (!bm_font) { return nullptr; @@ -63,13 +64,13 @@ TextServerAdvanced::hb_bmp_font_t *TextServerAdvanced::_hb_bmp_font_create(TextS return bm_font; } -void TextServerAdvanced::_hb_bmp_font_destroy(void *p_data) { - hb_bmp_font_t *bm_font = reinterpret_cast<hb_bmp_font_t *>(p_data); +void TextServerAdvanced::_bmp_font_destroy(void *p_data) { + bmp_font_t *bm_font = reinterpret_cast<bmp_font_t *>(p_data); memdelete(bm_font); } -hb_bool_t TextServerAdvanced::hb_bmp_get_nominal_glyph(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_unicode, hb_codepoint_t *r_glyph, void *p_user_data) { - const hb_bmp_font_t *bm_font = reinterpret_cast<const hb_bmp_font_t *>(p_font_data); +hb_bool_t TextServerAdvanced::_bmp_get_nominal_glyph(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_unicode, hb_codepoint_t *r_glyph, void *p_user_data) { + const bmp_font_t *bm_font = reinterpret_cast<const bmp_font_t *>(p_font_data); if (!bm_font->face) { return false; @@ -88,8 +89,8 @@ hb_bool_t TextServerAdvanced::hb_bmp_get_nominal_glyph(hb_font_t *p_font, void * return true; } -hb_position_t TextServerAdvanced::hb_bmp_get_glyph_h_advance(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, void *p_user_data) { - const hb_bmp_font_t *bm_font = reinterpret_cast<const hb_bmp_font_t *>(p_font_data); +hb_position_t TextServerAdvanced::_bmp_get_glyph_h_advance(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, void *p_user_data) { + const bmp_font_t *bm_font = reinterpret_cast<const bmp_font_t *>(p_font_data); if (!bm_font->face) { return 0; @@ -102,8 +103,8 @@ hb_position_t TextServerAdvanced::hb_bmp_get_glyph_h_advance(hb_font_t *p_font, return bm_font->face->glyph_map[p_glyph].advance.x * 64; } -hb_position_t TextServerAdvanced::hb_bmp_get_glyph_v_advance(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, void *p_user_data) { - const hb_bmp_font_t *bm_font = reinterpret_cast<const hb_bmp_font_t *>(p_font_data); +hb_position_t TextServerAdvanced::_bmp_get_glyph_v_advance(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, void *p_user_data) { + const bmp_font_t *bm_font = reinterpret_cast<const bmp_font_t *>(p_font_data); if (!bm_font->face) { return 0; @@ -116,8 +117,8 @@ hb_position_t TextServerAdvanced::hb_bmp_get_glyph_v_advance(hb_font_t *p_font, return -bm_font->face->glyph_map[p_glyph].advance.y * 64; } -hb_position_t TextServerAdvanced::hb_bmp_get_glyph_h_kerning(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_left_glyph, hb_codepoint_t p_right_glyph, void *p_user_data) { - const hb_bmp_font_t *bm_font = reinterpret_cast<const hb_bmp_font_t *>(p_font_data); +hb_position_t TextServerAdvanced::_bmp_get_glyph_h_kerning(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_left_glyph, hb_codepoint_t p_right_glyph, void *p_user_data) { + const bmp_font_t *bm_font = reinterpret_cast<const bmp_font_t *>(p_font_data); if (!bm_font->face) { return 0; @@ -130,22 +131,8 @@ hb_position_t TextServerAdvanced::hb_bmp_get_glyph_h_kerning(hb_font_t *p_font, return bm_font->face->kerning_map[Vector2i(p_left_glyph, p_right_glyph)].x * 64; } -hb_position_t TextServerAdvanced::hb_bmp_get_glyph_v_kerning(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_left_glyph, hb_codepoint_t p_right_glyph, void *p_user_data) { - const hb_bmp_font_t *bm_font = reinterpret_cast<const hb_bmp_font_t *>(p_font_data); - - if (!bm_font->face) { - return 0; - } - - if (!bm_font->face->kerning_map.has(Vector2i(p_left_glyph, p_right_glyph))) { - return 0; - } - - return bm_font->face->kerning_map[Vector2i(p_left_glyph, p_right_glyph)].y * 64; -} - -hb_bool_t TextServerAdvanced::hb_bmp_get_glyph_v_origin(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, hb_position_t *r_x, hb_position_t *r_y, void *p_user_data) { - const hb_bmp_font_t *bm_font = reinterpret_cast<const hb_bmp_font_t *>(p_font_data); +hb_bool_t TextServerAdvanced::_bmp_get_glyph_v_origin(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, hb_position_t *r_x, hb_position_t *r_y, void *p_user_data) { + const bmp_font_t *bm_font = reinterpret_cast<const bmp_font_t *>(p_font_data); if (!bm_font->face) { return false; @@ -161,8 +148,8 @@ hb_bool_t TextServerAdvanced::hb_bmp_get_glyph_v_origin(hb_font_t *p_font, void return true; } -hb_bool_t TextServerAdvanced::hb_bmp_get_glyph_extents(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, hb_glyph_extents_t *r_extents, void *p_user_data) { - const hb_bmp_font_t *bm_font = reinterpret_cast<const hb_bmp_font_t *>(p_font_data); +hb_bool_t TextServerAdvanced::_bmp_get_glyph_extents(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, hb_glyph_extents_t *r_extents, void *p_user_data) { + const bmp_font_t *bm_font = reinterpret_cast<const bmp_font_t *>(p_font_data); if (!bm_font->face) { return false; @@ -180,8 +167,8 @@ hb_bool_t TextServerAdvanced::hb_bmp_get_glyph_extents(hb_font_t *p_font, void * return true; } -hb_bool_t TextServerAdvanced::hb_bmp_get_font_h_extents(hb_font_t *p_font, void *p_font_data, hb_font_extents_t *r_metrics, void *p_user_data) { - const hb_bmp_font_t *bm_font = reinterpret_cast<const hb_bmp_font_t *>(p_font_data); +hb_bool_t TextServerAdvanced::_bmp_get_font_h_extents(hb_font_t *p_font, void *p_font_data, hb_font_extents_t *r_metrics, void *p_user_data) { + const bmp_font_t *bm_font = reinterpret_cast<const bmp_font_t *>(p_font_data); if (!bm_font->face) { return false; @@ -194,41 +181,40 @@ hb_bool_t TextServerAdvanced::hb_bmp_get_font_h_extents(hb_font_t *p_font, void return true; } -void TextServerAdvanced::hb_bmp_create_font_funcs() { +void TextServerAdvanced::_bmp_create_font_funcs() { if (funcs == nullptr) { funcs = hb_font_funcs_create(); - hb_font_funcs_set_font_h_extents_func(funcs, hb_bmp_get_font_h_extents, nullptr, nullptr); - hb_font_funcs_set_nominal_glyph_func(funcs, hb_bmp_get_nominal_glyph, nullptr, nullptr); - hb_font_funcs_set_glyph_h_advance_func(funcs, hb_bmp_get_glyph_h_advance, nullptr, nullptr); - hb_font_funcs_set_glyph_v_advance_func(funcs, hb_bmp_get_glyph_v_advance, nullptr, nullptr); - hb_font_funcs_set_glyph_v_origin_func(funcs, hb_bmp_get_glyph_v_origin, nullptr, nullptr); - hb_font_funcs_set_glyph_h_kerning_func(funcs, hb_bmp_get_glyph_h_kerning, nullptr, nullptr); - hb_font_funcs_set_glyph_v_kerning_func(funcs, hb_bmp_get_glyph_v_kerning, nullptr, nullptr); - hb_font_funcs_set_glyph_extents_func(funcs, hb_bmp_get_glyph_extents, nullptr, nullptr); + hb_font_funcs_set_font_h_extents_func(funcs, _bmp_get_font_h_extents, nullptr, nullptr); + hb_font_funcs_set_nominal_glyph_func(funcs, _bmp_get_nominal_glyph, nullptr, nullptr); + hb_font_funcs_set_glyph_h_advance_func(funcs, _bmp_get_glyph_h_advance, nullptr, nullptr); + hb_font_funcs_set_glyph_v_advance_func(funcs, _bmp_get_glyph_v_advance, nullptr, nullptr); + hb_font_funcs_set_glyph_v_origin_func(funcs, _bmp_get_glyph_v_origin, nullptr, nullptr); + hb_font_funcs_set_glyph_h_kerning_func(funcs, _bmp_get_glyph_h_kerning, nullptr, nullptr); + hb_font_funcs_set_glyph_extents_func(funcs, _bmp_get_glyph_extents, nullptr, nullptr); hb_font_funcs_make_immutable(funcs); } } -void TextServerAdvanced::hb_bmp_free_font_funcs() { +void TextServerAdvanced::_bmp_free_font_funcs() { if (funcs != nullptr) { hb_font_funcs_destroy(funcs); funcs = nullptr; } } -void TextServerAdvanced::_hb_bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref) { - hb_font_set_funcs(p_font, funcs, _hb_bmp_font_create(p_face, p_unref), _hb_bmp_font_destroy); +void TextServerAdvanced::_bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref) { + hb_font_set_funcs(p_font, funcs, _bmp_font_create(p_face, p_unref), _bmp_font_destroy); } -hb_font_t *TextServerAdvanced::hb_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, hb_destroy_func_t p_destroy) { +hb_font_t *TextServerAdvanced::_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, hb_destroy_func_t p_destroy) { hb_font_t *font; hb_face_t *face = hb_face_create(nullptr, 0); font = hb_font_create(face); hb_face_destroy(face); - _hb_bmp_font_set_funcs(font, p_face, false); + _bmp_font_set_funcs(font, p_face, false); return font; } @@ -336,7 +322,7 @@ _FORCE_INLINE_ bool is_underscore(char32_t p_char) { String TextServerAdvanced::interface_name = "ICU / HarfBuzz / Graphite"; uint32_t TextServerAdvanced::interface_features = FEATURE_BIDI_LAYOUT | FEATURE_VERTICAL_LAYOUT | FEATURE_SHAPING | FEATURE_KASHIDA_JUSTIFICATION | FEATURE_BREAK_ITERATORS | FEATURE_USE_SUPPORT_DATA | FEATURE_FONT_VARIABLE; -bool TextServerAdvanced::has_feature(Feature p_feature) { +bool TextServerAdvanced::has_feature(Feature p_feature) const { return (interface_features & p_feature) == p_feature; } @@ -344,14 +330,18 @@ String TextServerAdvanced::get_name() const { return interface_name; } +uint32_t TextServerAdvanced::get_features() const { + return interface_features; +} + void TextServerAdvanced::free(RID p_rid) { _THREAD_SAFE_METHOD_ if (font_owner.owns(p_rid)) { - FontDataAdvanced *fd = font_owner.getornull(p_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_rid); font_owner.free(p_rid); memdelete(fd); } else if (shaped_owner.owns(p_rid)) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_rid); + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_rid); shaped_owner.free(p_rid); memdelete(sd); } @@ -408,9 +398,23 @@ bool TextServerAdvanced::load_support_data(const String &p_filename) { return true; } -#ifdef TOOLS_ENABLED +String TextServerAdvanced::get_support_data_filename() const { +#ifdef ICU_STATIC_DATA + return _MKSTR(ICU_DATA_NAME); +#else + return String(); +#endif +} -bool TextServerAdvanced::save_support_data(const String &p_filename) { +String TextServerAdvanced::get_support_data_info() const { +#ifdef ICU_STATIC_DATA + return String("ICU break iteration data (") + _MKSTR(ICU_DATA_NAME) + String(")."); +#else + return String(); +#endif +} + +bool TextServerAdvanced::save_support_data(const String &p_filename) const { _THREAD_SAFE_METHOD_ #ifdef ICU_STATIC_DATA @@ -429,9 +433,7 @@ bool TextServerAdvanced::save_support_data(const String &p_filename) { #endif } -#endif - -bool TextServerAdvanced::is_locale_right_to_left(const String &p_locale) { +bool TextServerAdvanced::is_locale_right_to_left(const String &p_locale) const { String l = p_locale.get_slicec('_', 0); if ((l == "ar") || (l == "dv") || (l == "he") || (l == "fa") || (l == "ff") || (l == "ku") || (l == "ur")) { return true; @@ -440,266 +442,258 @@ bool TextServerAdvanced::is_locale_right_to_left(const String &p_locale) { } } -struct FeatureInfo { - int32_t tag; - String name; -}; - -static FeatureInfo feature_set[] = { +void TextServerAdvanced::_insert_feature_sets() { // Registered OpenType feature tags. - { HB_TAG('a', 'a', 'l', 't'), "access_all_alternates" }, - { HB_TAG('a', 'b', 'v', 'f'), "above_base_forms" }, - { HB_TAG('a', 'b', 'v', 'm'), "above_base_mark_positioning" }, - { HB_TAG('a', 'b', 'v', 's'), "above_base_substitutions" }, - { HB_TAG('a', 'f', 'r', 'c'), "alternative_fractions" }, - { HB_TAG('a', 'k', 'h', 'n'), "akhands" }, - { HB_TAG('b', 'l', 'w', 'f'), "below_base_forms" }, - { HB_TAG('b', 'l', 'w', 'm'), "below_base_mark_positioning" }, - { HB_TAG('b', 'l', 'w', 's'), "below_base_substitutions" }, - { HB_TAG('c', 'a', 'l', 't'), "contextual_alternates" }, - { HB_TAG('c', 'a', 's', 'e'), "case_sensitive_forms" }, - { HB_TAG('c', 'c', 'm', 'p'), "glyph_composition" }, - { HB_TAG('c', 'f', 'a', 'r'), "conjunct_form_after_ro" }, - { HB_TAG('c', 'j', 'c', 't'), "conjunct_forms" }, - { HB_TAG('c', 'l', 'i', 'g'), "contextual_ligatures" }, - { HB_TAG('c', 'p', 'c', 't'), "centered_cjk_punctuation" }, - { HB_TAG('c', 'p', 's', 'p'), "capital_spacing" }, - { HB_TAG('c', 's', 'w', 'h'), "contextual_swash" }, - { HB_TAG('c', 'u', 'r', 's'), "cursive_positioning" }, - { HB_TAG('c', 'v', '0', '1'), "character_variant_01" }, - { HB_TAG('c', 'v', '0', '2'), "character_variant_02" }, - { HB_TAG('c', 'v', '0', '3'), "character_variant_03" }, - { HB_TAG('c', 'v', '0', '4'), "character_variant_04" }, - { HB_TAG('c', 'v', '0', '5'), "character_variant_05" }, - { HB_TAG('c', 'v', '0', '6'), "character_variant_06" }, - { HB_TAG('c', 'v', '0', '7'), "character_variant_07" }, - { HB_TAG('c', 'v', '0', '8'), "character_variant_08" }, - { HB_TAG('c', 'v', '0', '9'), "character_variant_09" }, - { HB_TAG('c', 'v', '1', '0'), "character_variant_10" }, - { HB_TAG('c', 'v', '1', '1'), "character_variant_11" }, - { HB_TAG('c', 'v', '1', '2'), "character_variant_12" }, - { HB_TAG('c', 'v', '1', '3'), "character_variant_13" }, - { HB_TAG('c', 'v', '1', '4'), "character_variant_14" }, - { HB_TAG('c', 'v', '1', '5'), "character_variant_15" }, - { HB_TAG('c', 'v', '1', '6'), "character_variant_16" }, - { HB_TAG('c', 'v', '1', '7'), "character_variant_17" }, - { HB_TAG('c', 'v', '1', '8'), "character_variant_18" }, - { HB_TAG('c', 'v', '1', '9'), "character_variant_19" }, - { HB_TAG('c', 'v', '2', '0'), "character_variant_20" }, - { HB_TAG('c', 'v', '2', '1'), "character_variant_21" }, - { HB_TAG('c', 'v', '2', '2'), "character_variant_22" }, - { HB_TAG('c', 'v', '2', '3'), "character_variant_23" }, - { HB_TAG('c', 'v', '2', '4'), "character_variant_24" }, - { HB_TAG('c', 'v', '2', '5'), "character_variant_25" }, - { HB_TAG('c', 'v', '2', '6'), "character_variant_26" }, - { HB_TAG('c', 'v', '2', '7'), "character_variant_27" }, - { HB_TAG('c', 'v', '2', '8'), "character_variant_28" }, - { HB_TAG('c', 'v', '2', '9'), "character_variant_29" }, - { HB_TAG('c', 'v', '3', '0'), "character_variant_30" }, - { HB_TAG('c', 'v', '3', '1'), "character_variant_31" }, - { HB_TAG('c', 'v', '3', '2'), "character_variant_32" }, - { HB_TAG('c', 'v', '3', '3'), "character_variant_33" }, - { HB_TAG('c', 'v', '3', '4'), "character_variant_34" }, - { HB_TAG('c', 'v', '3', '5'), "character_variant_35" }, - { HB_TAG('c', 'v', '3', '6'), "character_variant_36" }, - { HB_TAG('c', 'v', '3', '7'), "character_variant_37" }, - { HB_TAG('c', 'v', '3', '8'), "character_variant_38" }, - { HB_TAG('c', 'v', '3', '9'), "character_variant_39" }, - { HB_TAG('c', 'v', '4', '0'), "character_variant_40" }, - { HB_TAG('c', 'v', '4', '1'), "character_variant_41" }, - { HB_TAG('c', 'v', '4', '2'), "character_variant_42" }, - { HB_TAG('c', 'v', '4', '3'), "character_variant_43" }, - { HB_TAG('c', 'v', '4', '4'), "character_variant_44" }, - { HB_TAG('c', 'v', '4', '5'), "character_variant_45" }, - { HB_TAG('c', 'v', '4', '6'), "character_variant_46" }, - { HB_TAG('c', 'v', '4', '7'), "character_variant_47" }, - { HB_TAG('c', 'v', '4', '8'), "character_variant_48" }, - { HB_TAG('c', 'v', '4', '9'), "character_variant_49" }, - { HB_TAG('c', 'v', '5', '0'), "character_variant_50" }, - { HB_TAG('c', 'v', '5', '1'), "character_variant_51" }, - { HB_TAG('c', 'v', '5', '2'), "character_variant_52" }, - { HB_TAG('c', 'v', '5', '3'), "character_variant_53" }, - { HB_TAG('c', 'v', '5', '4'), "character_variant_54" }, - { HB_TAG('c', 'v', '5', '5'), "character_variant_55" }, - { HB_TAG('c', 'v', '5', '6'), "character_variant_56" }, - { HB_TAG('c', 'v', '5', '7'), "character_variant_57" }, - { HB_TAG('c', 'v', '5', '8'), "character_variant_58" }, - { HB_TAG('c', 'v', '5', '9'), "character_variant_59" }, - { HB_TAG('c', 'v', '6', '0'), "character_variant_60" }, - { HB_TAG('c', 'v', '6', '1'), "character_variant_61" }, - { HB_TAG('c', 'v', '6', '2'), "character_variant_62" }, - { HB_TAG('c', 'v', '6', '3'), "character_variant_63" }, - { HB_TAG('c', 'v', '6', '4'), "character_variant_64" }, - { HB_TAG('c', 'v', '6', '5'), "character_variant_65" }, - { HB_TAG('c', 'v', '6', '6'), "character_variant_66" }, - { HB_TAG('c', 'v', '6', '7'), "character_variant_67" }, - { HB_TAG('c', 'v', '6', '8'), "character_variant_68" }, - { HB_TAG('c', 'v', '6', '9'), "character_variant_69" }, - { HB_TAG('c', 'v', '7', '0'), "character_variant_70" }, - { HB_TAG('c', 'v', '7', '1'), "character_variant_71" }, - { HB_TAG('c', 'v', '7', '2'), "character_variant_72" }, - { HB_TAG('c', 'v', '7', '3'), "character_variant_73" }, - { HB_TAG('c', 'v', '7', '4'), "character_variant_74" }, - { HB_TAG('c', 'v', '7', '5'), "character_variant_75" }, - { HB_TAG('c', 'v', '7', '6'), "character_variant_76" }, - { HB_TAG('c', 'v', '7', '7'), "character_variant_77" }, - { HB_TAG('c', 'v', '7', '8'), "character_variant_78" }, - { HB_TAG('c', 'v', '7', '9'), "character_variant_79" }, - { HB_TAG('c', 'v', '8', '0'), "character_variant_80" }, - { HB_TAG('c', 'v', '8', '1'), "character_variant_81" }, - { HB_TAG('c', 'v', '8', '2'), "character_variant_82" }, - { HB_TAG('c', 'v', '8', '3'), "character_variant_83" }, - { HB_TAG('c', 'v', '8', '4'), "character_variant_84" }, - { HB_TAG('c', 'v', '8', '5'), "character_variant_85" }, - { HB_TAG('c', 'v', '8', '6'), "character_variant_86" }, - { HB_TAG('c', 'v', '8', '7'), "character_variant_87" }, - { HB_TAG('c', 'v', '8', '8'), "character_variant_88" }, - { HB_TAG('c', 'v', '8', '9'), "character_variant_89" }, - { HB_TAG('c', 'v', '9', '0'), "character_variant_90" }, - { HB_TAG('c', 'v', '9', '1'), "character_variant_91" }, - { HB_TAG('c', 'v', '9', '2'), "character_variant_92" }, - { HB_TAG('c', 'v', '9', '3'), "character_variant_93" }, - { HB_TAG('c', 'v', '9', '4'), "character_variant_94" }, - { HB_TAG('c', 'v', '9', '5'), "character_variant_95" }, - { HB_TAG('c', 'v', '9', '6'), "character_variant_96" }, - { HB_TAG('c', 'v', '9', '7'), "character_variant_97" }, - { HB_TAG('c', 'v', '9', '8'), "character_variant_98" }, - { HB_TAG('c', 'v', '9', '9'), "character_variant_99" }, - { HB_TAG('c', '2', 'p', 'c'), "petite_capitals_from_capitals" }, - { HB_TAG('c', '2', 's', 'c'), "small_capitals_from_capitals" }, - { HB_TAG('d', 'i', 's', 't'), "distances" }, - { HB_TAG('d', 'l', 'i', 'g'), "discretionary_ligatures" }, - { HB_TAG('d', 'n', 'o', 'm'), "denominators" }, - { HB_TAG('d', 't', 'l', 's'), "dotless_forms" }, - { HB_TAG('e', 'x', 'p', 't'), "expert_forms" }, - { HB_TAG('f', 'a', 'l', 't'), "final_glyph_on_line_alternates" }, - { HB_TAG('f', 'i', 'n', '2'), "terminal_forms_2" }, - { HB_TAG('f', 'i', 'n', '3'), "terminal_forms_3" }, - { HB_TAG('f', 'i', 'n', 'a'), "terminal_forms" }, - { HB_TAG('f', 'l', 'a', 'c'), "flattened_accent_forms" }, - { HB_TAG('f', 'r', 'a', 'c'), "fractions" }, - { HB_TAG('f', 'w', 'i', 'd'), "full_widths" }, - { HB_TAG('h', 'a', 'l', 'f'), "half_forms" }, - { HB_TAG('h', 'a', 'l', 'n'), "halant_forms" }, - { HB_TAG('h', 'a', 'l', 't'), "alternate_half_widths" }, - { HB_TAG('h', 'i', 's', 't'), "historical_forms" }, - { HB_TAG('h', 'k', 'n', 'a'), "horizontal_kana_alternates" }, - { HB_TAG('h', 'l', 'i', 'g'), "historical_ligatures" }, - { HB_TAG('h', 'n', 'g', 'l'), "hangul" }, - { HB_TAG('h', 'o', 'j', 'o'), "hojo_kanji_forms" }, - { HB_TAG('h', 'w', 'i', 'd'), "half_widths" }, - { HB_TAG('i', 'n', 'i', 't'), "initial_forms" }, - { HB_TAG('i', 's', 'o', 'l'), "isolated_forms" }, - { HB_TAG('i', 't', 'a', 'l'), "italics" }, - { HB_TAG('j', 'a', 'l', 't'), "justification_alternates" }, - { HB_TAG('j', 'p', '7', '8'), "jis78_forms" }, - { HB_TAG('j', 'p', '8', '3'), "jis83_forms" }, - { HB_TAG('j', 'p', '9', '0'), "jis90_forms" }, - { HB_TAG('j', 'p', '0', '4'), "jis2004_forms" }, - { HB_TAG('k', 'e', 'r', 'n'), "kerning" }, - { HB_TAG('l', 'f', 'b', 'd'), "left_bounds" }, - { HB_TAG('l', 'i', 'g', 'a'), "standard_ligatures" }, - { HB_TAG('l', 'j', 'm', 'o'), "leading_jamo_forms" }, - { HB_TAG('l', 'n', 'u', 'm'), "lining_figures" }, - { HB_TAG('l', 'o', 'c', 'l'), "localized_forms" }, - { HB_TAG('l', 't', 'r', 'a'), "left_to_right_alternates" }, - { HB_TAG('l', 't', 'r', 'm'), "left_to_right_mirrored_forms" }, - { HB_TAG('m', 'a', 'r', 'k'), "mark_positioning" }, - { HB_TAG('m', 'e', 'd', '2'), "medial_forms_2" }, - { HB_TAG('m', 'e', 'd', 'i'), "medial_forms" }, - { HB_TAG('m', 'g', 'r', 'k'), "mathematical_greek" }, - { HB_TAG('m', 'k', 'm', 'k'), "mark_to_mark_positioning" }, - { HB_TAG('m', 's', 'e', 't'), "mark_positioning_via_substitution" }, - { HB_TAG('n', 'a', 'l', 't'), "alternate_annotation_forms" }, - { HB_TAG('n', 'l', 'c', 'k'), "nlc_kanji_forms" }, - { HB_TAG('n', 'u', 'k', 't'), "nukta_forms" }, - { HB_TAG('n', 'u', 'm', 'r'), "numerators" }, - { HB_TAG('o', 'n', 'u', 'm'), "oldstyle_figures" }, - { HB_TAG('o', 'p', 'b', 'd'), "optical_bounds" }, - { HB_TAG('o', 'r', 'd', 'n'), "ordinals" }, - { HB_TAG('o', 'r', 'n', 'm'), "ornaments" }, - { HB_TAG('p', 'a', 'l', 't'), "proportional_alternate_widths" }, - { HB_TAG('p', 'c', 'a', 'p'), "petite_capitals" }, - { HB_TAG('p', 'k', 'n', 'a'), "proportional_kana" }, - { HB_TAG('p', 'n', 'u', 'm'), "proportional_figures" }, - { HB_TAG('p', 'r', 'e', 'f'), "pre_base_forms" }, - { HB_TAG('p', 'r', 'e', 's'), "pre_base_substitutions" }, - { HB_TAG('p', 's', 't', 'f'), "post_base_forms" }, - { HB_TAG('p', 's', 't', 's'), "post_base_substitutions" }, - { HB_TAG('p', 'w', 'i', 'd'), "proportional_widths" }, - { HB_TAG('q', 'w', 'i', 'd'), "quarter_widths" }, - { HB_TAG('r', 'a', 'n', 'd'), "randomize" }, - { HB_TAG('r', 'c', 'l', 't'), "required_contextual_alternates" }, - { HB_TAG('r', 'k', 'r', 'f'), "rakar_forms" }, - { HB_TAG('r', 'l', 'i', 'g'), "required_ligatures" }, - { HB_TAG('r', 'p', 'h', 'f'), "reph_forms" }, - { HB_TAG('r', 't', 'b', 'd'), "right_bounds" }, - { HB_TAG('r', 't', 'l', 'a'), "right_to_left_alternates" }, - { HB_TAG('r', 't', 'l', 'm'), "right_to_left_mirrored_forms" }, - { HB_TAG('r', 'u', 'b', 'y'), "ruby_notation_forms" }, - { HB_TAG('r', 'v', 'r', 'n'), "required_variation_alternates" }, - { HB_TAG('s', 'a', 'l', 't'), "stylistic_alternates" }, - { HB_TAG('s', 'i', 'n', 'f'), "scientific_inferiors" }, - { HB_TAG('s', 'i', 'z', 'e'), "optical_size" }, - { HB_TAG('s', 'm', 'c', 'p'), "small_capitals" }, - { HB_TAG('s', 'm', 'p', 'l'), "simplified_forms" }, - { HB_TAG('s', 's', '0', '1'), "stylistic_set_01" }, - { HB_TAG('s', 's', '0', '2'), "stylistic_set_02" }, - { HB_TAG('s', 's', '0', '3'), "stylistic_set_03" }, - { HB_TAG('s', 's', '0', '4'), "stylistic_set_04" }, - { HB_TAG('s', 's', '0', '5'), "stylistic_set_05" }, - { HB_TAG('s', 's', '0', '6'), "stylistic_set_06" }, - { HB_TAG('s', 's', '0', '7'), "stylistic_set_07" }, - { HB_TAG('s', 's', '0', '8'), "stylistic_set_08" }, - { HB_TAG('s', 's', '0', '9'), "stylistic_set_09" }, - { HB_TAG('s', 's', '1', '0'), "stylistic_set_10" }, - { HB_TAG('s', 's', '1', '1'), "stylistic_set_11" }, - { HB_TAG('s', 's', '1', '2'), "stylistic_set_12" }, - { HB_TAG('s', 's', '1', '3'), "stylistic_set_13" }, - { HB_TAG('s', 's', '1', '4'), "stylistic_set_14" }, - { HB_TAG('s', 's', '1', '5'), "stylistic_set_15" }, - { HB_TAG('s', 's', '1', '6'), "stylistic_set_16" }, - { HB_TAG('s', 's', '1', '7'), "stylistic_set_17" }, - { HB_TAG('s', 's', '1', '8'), "stylistic_set_18" }, - { HB_TAG('s', 's', '1', '9'), "stylistic_set_19" }, - { HB_TAG('s', 's', '2', '0'), "stylistic_set_20" }, - { HB_TAG('s', 's', 't', 'y'), "math_script_style_alternates" }, - { HB_TAG('s', 't', 'c', 'h'), "stretching_glyph_decomposition" }, - { HB_TAG('s', 'u', 'b', 's'), "subscript" }, - { HB_TAG('s', 'u', 'p', 's'), "superscript" }, - { HB_TAG('s', 'w', 's', 'h'), "swash" }, - { HB_TAG('t', 'i', 't', 'l'), "titling" }, - { HB_TAG('t', 'j', 'm', 'o'), "trailing_jamo_forms" }, - { HB_TAG('t', 'n', 'a', 'm'), "traditional_name_forms" }, - { HB_TAG('t', 'n', 'u', 'm'), "tabular_figures" }, - { HB_TAG('t', 'r', 'a', 'd'), "traditional_forms" }, - { HB_TAG('t', 'w', 'i', 'd'), "third_widths" }, - { HB_TAG('u', 'n', 'i', 'c'), "unicase" }, - { HB_TAG('v', 'a', 'l', 't'), "alternate_vertical_metrics" }, - { HB_TAG('v', 'a', 't', 'u'), "vattu_variants" }, - { HB_TAG('v', 'e', 'r', 't'), "vertical_writing" }, - { HB_TAG('v', 'h', 'a', 'l'), "alternate_vertical_half_metrics" }, - { HB_TAG('v', 'j', 'm', 'o'), "vowel_jamo_forms" }, - { HB_TAG('v', 'k', 'n', 'a'), "vertical_kana_alternates" }, - { HB_TAG('v', 'k', 'r', 'n'), "vertical_kerning" }, - { HB_TAG('v', 'p', 'a', 'l'), "proportional_alternate_vertical_metrics" }, - { HB_TAG('v', 'r', 't', '2'), "vertical_alternates_and_rotation" }, - { HB_TAG('v', 'r', 't', 'r'), "vertical_alternates_for_rotation" }, - { HB_TAG('z', 'e', 'r', 'o'), "slashed_zero" }, - // Registered OpenType variation tags. - { HB_TAG('i', 't', 'a', 'l'), "italic" }, - { HB_TAG('o', 'p', 's', 'z'), "optical_size" }, - { HB_TAG('s', 'l', 'n', 't'), "slant" }, - { HB_TAG('w', 'd', 't', 'h'), "width" }, - { HB_TAG('w', 'g', 'h', 't'), "weight" }, - { 0, String() }, -}; + feature_sets.insert("access_all_alternates", HB_TAG('a', 'a', 'l', 't')); + feature_sets.insert("above_base_forms", HB_TAG('a', 'b', 'v', 'f')); + feature_sets.insert("above_base_mark_positioning", HB_TAG('a', 'b', 'v', 'm')); + feature_sets.insert("above_base_substitutions", HB_TAG('a', 'b', 'v', 's')); + feature_sets.insert("alternative_fractions", HB_TAG('a', 'f', 'r', 'c')); + feature_sets.insert("akhands", HB_TAG('a', 'k', 'h', 'n')); + feature_sets.insert("below_base_forms", HB_TAG('b', 'l', 'w', 'f')); + feature_sets.insert("below_base_mark_positioning", HB_TAG('b', 'l', 'w', 'm')); + feature_sets.insert("below_base_substitutions", HB_TAG('b', 'l', 'w', 's')); + feature_sets.insert("contextual_alternates", HB_TAG('c', 'a', 'l', 't')); + feature_sets.insert("case_sensitive_forms", HB_TAG('c', 'a', 's', 'e')); + feature_sets.insert("glyph_composition", HB_TAG('c', 'c', 'm', 'p')); + feature_sets.insert("conjunct_form_after_ro", HB_TAG('c', 'f', 'a', 'r')); + feature_sets.insert("conjunct_forms", HB_TAG('c', 'j', 'c', 't')); + feature_sets.insert("contextual_ligatures", HB_TAG('c', 'l', 'i', 'g')); + feature_sets.insert("centered_cjk_punctuation", HB_TAG('c', 'p', 'c', 't')); + feature_sets.insert("capital_spacing", HB_TAG('c', 'p', 's', 'p')); + feature_sets.insert("contextual_swash", HB_TAG('c', 's', 'w', 'h')); + feature_sets.insert("cursive_positioning", HB_TAG('c', 'u', 'r', 's')); + feature_sets.insert("character_variant_01", HB_TAG('c', 'v', '0', '1')); + feature_sets.insert("character_variant_02", HB_TAG('c', 'v', '0', '2')); + feature_sets.insert("character_variant_03", HB_TAG('c', 'v', '0', '3')); + feature_sets.insert("character_variant_04", HB_TAG('c', 'v', '0', '4')); + feature_sets.insert("character_variant_05", HB_TAG('c', 'v', '0', '5')); + feature_sets.insert("character_variant_06", HB_TAG('c', 'v', '0', '6')); + feature_sets.insert("character_variant_07", HB_TAG('c', 'v', '0', '7')); + feature_sets.insert("character_variant_08", HB_TAG('c', 'v', '0', '8')); + feature_sets.insert("character_variant_09", HB_TAG('c', 'v', '0', '9')); + feature_sets.insert("character_variant_10", HB_TAG('c', 'v', '1', '0')); + feature_sets.insert("character_variant_11", HB_TAG('c', 'v', '1', '1')); + feature_sets.insert("character_variant_12", HB_TAG('c', 'v', '1', '2')); + feature_sets.insert("character_variant_13", HB_TAG('c', 'v', '1', '3')); + feature_sets.insert("character_variant_14", HB_TAG('c', 'v', '1', '4')); + feature_sets.insert("character_variant_15", HB_TAG('c', 'v', '1', '5')); + feature_sets.insert("character_variant_16", HB_TAG('c', 'v', '1', '6')); + feature_sets.insert("character_variant_17", HB_TAG('c', 'v', '1', '7')); + feature_sets.insert("character_variant_18", HB_TAG('c', 'v', '1', '8')); + feature_sets.insert("character_variant_19", HB_TAG('c', 'v', '1', '9')); + feature_sets.insert("character_variant_20", HB_TAG('c', 'v', '2', '0')); + feature_sets.insert("character_variant_21", HB_TAG('c', 'v', '2', '1')); + feature_sets.insert("character_variant_22", HB_TAG('c', 'v', '2', '2')); + feature_sets.insert("character_variant_23", HB_TAG('c', 'v', '2', '3')); + feature_sets.insert("character_variant_24", HB_TAG('c', 'v', '2', '4')); + feature_sets.insert("character_variant_25", HB_TAG('c', 'v', '2', '5')); + feature_sets.insert("character_variant_26", HB_TAG('c', 'v', '2', '6')); + feature_sets.insert("character_variant_27", HB_TAG('c', 'v', '2', '7')); + feature_sets.insert("character_variant_28", HB_TAG('c', 'v', '2', '8')); + feature_sets.insert("character_variant_29", HB_TAG('c', 'v', '2', '9')); + feature_sets.insert("character_variant_30", HB_TAG('c', 'v', '3', '0')); + feature_sets.insert("character_variant_31", HB_TAG('c', 'v', '3', '1')); + feature_sets.insert("character_variant_32", HB_TAG('c', 'v', '3', '2')); + feature_sets.insert("character_variant_33", HB_TAG('c', 'v', '3', '3')); + feature_sets.insert("character_variant_34", HB_TAG('c', 'v', '3', '4')); + feature_sets.insert("character_variant_35", HB_TAG('c', 'v', '3', '5')); + feature_sets.insert("character_variant_36", HB_TAG('c', 'v', '3', '6')); + feature_sets.insert("character_variant_37", HB_TAG('c', 'v', '3', '7')); + feature_sets.insert("character_variant_38", HB_TAG('c', 'v', '3', '8')); + feature_sets.insert("character_variant_39", HB_TAG('c', 'v', '3', '9')); + feature_sets.insert("character_variant_40", HB_TAG('c', 'v', '4', '0')); + feature_sets.insert("character_variant_41", HB_TAG('c', 'v', '4', '1')); + feature_sets.insert("character_variant_42", HB_TAG('c', 'v', '4', '2')); + feature_sets.insert("character_variant_43", HB_TAG('c', 'v', '4', '3')); + feature_sets.insert("character_variant_44", HB_TAG('c', 'v', '4', '4')); + feature_sets.insert("character_variant_45", HB_TAG('c', 'v', '4', '5')); + feature_sets.insert("character_variant_46", HB_TAG('c', 'v', '4', '6')); + feature_sets.insert("character_variant_47", HB_TAG('c', 'v', '4', '7')); + feature_sets.insert("character_variant_48", HB_TAG('c', 'v', '4', '8')); + feature_sets.insert("character_variant_49", HB_TAG('c', 'v', '4', '9')); + feature_sets.insert("character_variant_50", HB_TAG('c', 'v', '5', '0')); + feature_sets.insert("character_variant_51", HB_TAG('c', 'v', '5', '1')); + feature_sets.insert("character_variant_52", HB_TAG('c', 'v', '5', '2')); + feature_sets.insert("character_variant_53", HB_TAG('c', 'v', '5', '3')); + feature_sets.insert("character_variant_54", HB_TAG('c', 'v', '5', '4')); + feature_sets.insert("character_variant_55", HB_TAG('c', 'v', '5', '5')); + feature_sets.insert("character_variant_56", HB_TAG('c', 'v', '5', '6')); + feature_sets.insert("character_variant_57", HB_TAG('c', 'v', '5', '7')); + feature_sets.insert("character_variant_58", HB_TAG('c', 'v', '5', '8')); + feature_sets.insert("character_variant_59", HB_TAG('c', 'v', '5', '9')); + feature_sets.insert("character_variant_60", HB_TAG('c', 'v', '6', '0')); + feature_sets.insert("character_variant_61", HB_TAG('c', 'v', '6', '1')); + feature_sets.insert("character_variant_62", HB_TAG('c', 'v', '6', '2')); + feature_sets.insert("character_variant_63", HB_TAG('c', 'v', '6', '3')); + feature_sets.insert("character_variant_64", HB_TAG('c', 'v', '6', '4')); + feature_sets.insert("character_variant_65", HB_TAG('c', 'v', '6', '5')); + feature_sets.insert("character_variant_66", HB_TAG('c', 'v', '6', '6')); + feature_sets.insert("character_variant_67", HB_TAG('c', 'v', '6', '7')); + feature_sets.insert("character_variant_68", HB_TAG('c', 'v', '6', '8')); + feature_sets.insert("character_variant_69", HB_TAG('c', 'v', '6', '9')); + feature_sets.insert("character_variant_70", HB_TAG('c', 'v', '7', '0')); + feature_sets.insert("character_variant_71", HB_TAG('c', 'v', '7', '1')); + feature_sets.insert("character_variant_72", HB_TAG('c', 'v', '7', '2')); + feature_sets.insert("character_variant_73", HB_TAG('c', 'v', '7', '3')); + feature_sets.insert("character_variant_74", HB_TAG('c', 'v', '7', '4')); + feature_sets.insert("character_variant_75", HB_TAG('c', 'v', '7', '5')); + feature_sets.insert("character_variant_76", HB_TAG('c', 'v', '7', '6')); + feature_sets.insert("character_variant_77", HB_TAG('c', 'v', '7', '7')); + feature_sets.insert("character_variant_78", HB_TAG('c', 'v', '7', '8')); + feature_sets.insert("character_variant_79", HB_TAG('c', 'v', '7', '9')); + feature_sets.insert("character_variant_80", HB_TAG('c', 'v', '8', '0')); + feature_sets.insert("character_variant_81", HB_TAG('c', 'v', '8', '1')); + feature_sets.insert("character_variant_82", HB_TAG('c', 'v', '8', '2')); + feature_sets.insert("character_variant_83", HB_TAG('c', 'v', '8', '3')); + feature_sets.insert("character_variant_84", HB_TAG('c', 'v', '8', '4')); + feature_sets.insert("character_variant_85", HB_TAG('c', 'v', '8', '5')); + feature_sets.insert("character_variant_86", HB_TAG('c', 'v', '8', '6')); + feature_sets.insert("character_variant_87", HB_TAG('c', 'v', '8', '7')); + feature_sets.insert("character_variant_88", HB_TAG('c', 'v', '8', '8')); + feature_sets.insert("character_variant_89", HB_TAG('c', 'v', '8', '9')); + feature_sets.insert("character_variant_90", HB_TAG('c', 'v', '9', '0')); + feature_sets.insert("character_variant_91", HB_TAG('c', 'v', '9', '1')); + feature_sets.insert("character_variant_92", HB_TAG('c', 'v', '9', '2')); + feature_sets.insert("character_variant_93", HB_TAG('c', 'v', '9', '3')); + feature_sets.insert("character_variant_94", HB_TAG('c', 'v', '9', '4')); + feature_sets.insert("character_variant_95", HB_TAG('c', 'v', '9', '5')); + feature_sets.insert("character_variant_96", HB_TAG('c', 'v', '9', '6')); + feature_sets.insert("character_variant_97", HB_TAG('c', 'v', '9', '7')); + feature_sets.insert("character_variant_98", HB_TAG('c', 'v', '9', '8')); + feature_sets.insert("character_variant_99", HB_TAG('c', 'v', '9', '9')); + feature_sets.insert("petite_capitals_from_capitals", HB_TAG('c', '2', 'p', 'c')); + feature_sets.insert("small_capitals_from_capitals", HB_TAG('c', '2', 's', 'c')); + feature_sets.insert("distances", HB_TAG('d', 'i', 's', 't')); + feature_sets.insert("discretionary_ligatures", HB_TAG('d', 'l', 'i', 'g')); + feature_sets.insert("denominators", HB_TAG('d', 'n', 'o', 'm')); + feature_sets.insert("dotless_forms", HB_TAG('d', 't', 'l', 's')); + feature_sets.insert("expert_forms", HB_TAG('e', 'x', 'p', 't')); + feature_sets.insert("final_glyph_on_line_alternates", HB_TAG('f', 'a', 'l', 't')); + feature_sets.insert("terminal_forms_2", HB_TAG('f', 'i', 'n', '2')); + feature_sets.insert("terminal_forms_3", HB_TAG('f', 'i', 'n', '3')); + feature_sets.insert("terminal_forms", HB_TAG('f', 'i', 'n', 'a')); + feature_sets.insert("flattened_accent_forms", HB_TAG('f', 'l', 'a', 'c')); + feature_sets.insert("fractions", HB_TAG('f', 'r', 'a', 'c')); + feature_sets.insert("full_widths", HB_TAG('f', 'w', 'i', 'd')); + feature_sets.insert("half_forms", HB_TAG('h', 'a', 'l', 'f')); + feature_sets.insert("halant_forms", HB_TAG('h', 'a', 'l', 'n')); + feature_sets.insert("alternate_half_widths", HB_TAG('h', 'a', 'l', 't')); + feature_sets.insert("historical_forms", HB_TAG('h', 'i', 's', 't')); + feature_sets.insert("horizontal_kana_alternates", HB_TAG('h', 'k', 'n', 'a')); + feature_sets.insert("historical_ligatures", HB_TAG('h', 'l', 'i', 'g')); + feature_sets.insert("hangul", HB_TAG('h', 'n', 'g', 'l')); + feature_sets.insert("hojo_kanji_forms", HB_TAG('h', 'o', 'j', 'o')); + feature_sets.insert("half_widths", HB_TAG('h', 'w', 'i', 'd')); + feature_sets.insert("initial_forms", HB_TAG('i', 'n', 'i', 't')); + feature_sets.insert("isolated_forms", HB_TAG('i', 's', 'o', 'l')); + feature_sets.insert("italics", HB_TAG('i', 't', 'a', 'l')); + feature_sets.insert("justification_alternates", HB_TAG('j', 'a', 'l', 't')); + feature_sets.insert("jis78_forms", HB_TAG('j', 'p', '7', '8')); + feature_sets.insert("jis83_forms", HB_TAG('j', 'p', '8', '3')); + feature_sets.insert("jis90_forms", HB_TAG('j', 'p', '9', '0')); + feature_sets.insert("jis2004_forms", HB_TAG('j', 'p', '0', '4')); + feature_sets.insert("kerning", HB_TAG('k', 'e', 'r', 'n')); + feature_sets.insert("left_bounds", HB_TAG('l', 'f', 'b', 'd')); + feature_sets.insert("standard_ligatures", HB_TAG('l', 'i', 'g', 'a')); + feature_sets.insert("leading_jamo_forms", HB_TAG('l', 'j', 'm', 'o')); + feature_sets.insert("lining_figures", HB_TAG('l', 'n', 'u', 'm')); + feature_sets.insert("localized_forms", HB_TAG('l', 'o', 'c', 'l')); + feature_sets.insert("left_to_right_alternates", HB_TAG('l', 't', 'r', 'a')); + feature_sets.insert("left_to_right_mirrored_forms", HB_TAG('l', 't', 'r', 'm')); + feature_sets.insert("mark_positioning", HB_TAG('m', 'a', 'r', 'k')); + feature_sets.insert("medial_forms_2", HB_TAG('m', 'e', 'd', '2')); + feature_sets.insert("medial_forms", HB_TAG('m', 'e', 'd', 'i')); + feature_sets.insert("mathematical_greek", HB_TAG('m', 'g', 'r', 'k')); + feature_sets.insert("mark_to_mark_positioning", HB_TAG('m', 'k', 'm', 'k')); + feature_sets.insert("mark_positioning_via_substitution", HB_TAG('m', 's', 'e', 't')); + feature_sets.insert("alternate_annotation_forms", HB_TAG('n', 'a', 'l', 't')); + feature_sets.insert("nlc_kanji_forms", HB_TAG('n', 'l', 'c', 'k')); + feature_sets.insert("nukta_forms", HB_TAG('n', 'u', 'k', 't')); + feature_sets.insert("numerators", HB_TAG('n', 'u', 'm', 'r')); + feature_sets.insert("oldstyle_figures", HB_TAG('o', 'n', 'u', 'm')); + feature_sets.insert("optical_bounds", HB_TAG('o', 'p', 'b', 'd')); + feature_sets.insert("ordinals", HB_TAG('o', 'r', 'd', 'n')); + feature_sets.insert("ornaments", HB_TAG('o', 'r', 'n', 'm')); + feature_sets.insert("proportional_alternate_widths", HB_TAG('p', 'a', 'l', 't')); + feature_sets.insert("petite_capitals", HB_TAG('p', 'c', 'a', 'p')); + feature_sets.insert("proportional_kana", HB_TAG('p', 'k', 'n', 'a')); + feature_sets.insert("proportional_figures", HB_TAG('p', 'n', 'u', 'm')); + feature_sets.insert("pre_base_forms", HB_TAG('p', 'r', 'e', 'f')); + feature_sets.insert("pre_base_substitutions", HB_TAG('p', 'r', 'e', 's')); + feature_sets.insert("post_base_forms", HB_TAG('p', 's', 't', 'f')); + feature_sets.insert("post_base_substitutions", HB_TAG('p', 's', 't', 's')); + feature_sets.insert("proportional_widths", HB_TAG('p', 'w', 'i', 'd')); + feature_sets.insert("quarter_widths", HB_TAG('q', 'w', 'i', 'd')); + feature_sets.insert("randomize", HB_TAG('r', 'a', 'n', 'd')); + feature_sets.insert("required_contextual_alternates", HB_TAG('r', 'c', 'l', 't')); + feature_sets.insert("rakar_forms", HB_TAG('r', 'k', 'r', 'f')); + feature_sets.insert("required_ligatures", HB_TAG('r', 'l', 'i', 'g')); + feature_sets.insert("reph_forms", HB_TAG('r', 'p', 'h', 'f')); + feature_sets.insert("right_bounds", HB_TAG('r', 't', 'b', 'd')); + feature_sets.insert("right_to_left_alternates", HB_TAG('r', 't', 'l', 'a')); + feature_sets.insert("right_to_left_mirrored_forms", HB_TAG('r', 't', 'l', 'm')); + feature_sets.insert("ruby_notation_forms", HB_TAG('r', 'u', 'b', 'y')); + feature_sets.insert("required_variation_alternates", HB_TAG('r', 'v', 'r', 'n')); + feature_sets.insert("stylistic_alternates", HB_TAG('s', 'a', 'l', 't')); + feature_sets.insert("scientific_inferiors", HB_TAG('s', 'i', 'n', 'f')); + feature_sets.insert("optical_size", HB_TAG('s', 'i', 'z', 'e')); + feature_sets.insert("small_capitals", HB_TAG('s', 'm', 'c', 'p')); + feature_sets.insert("simplified_forms", HB_TAG('s', 'm', 'p', 'l')); + feature_sets.insert("stylistic_set_01", HB_TAG('s', 's', '0', '1')); + feature_sets.insert("stylistic_set_02", HB_TAG('s', 's', '0', '2')); + feature_sets.insert("stylistic_set_03", HB_TAG('s', 's', '0', '3')); + feature_sets.insert("stylistic_set_04", HB_TAG('s', 's', '0', '4')); + feature_sets.insert("stylistic_set_05", HB_TAG('s', 's', '0', '5')); + feature_sets.insert("stylistic_set_06", HB_TAG('s', 's', '0', '6')); + feature_sets.insert("stylistic_set_07", HB_TAG('s', 's', '0', '7')); + feature_sets.insert("stylistic_set_08", HB_TAG('s', 's', '0', '8')); + feature_sets.insert("stylistic_set_09", HB_TAG('s', 's', '0', '9')); + feature_sets.insert("stylistic_set_10", HB_TAG('s', 's', '1', '0')); + feature_sets.insert("stylistic_set_11", HB_TAG('s', 's', '1', '1')); + feature_sets.insert("stylistic_set_12", HB_TAG('s', 's', '1', '2')); + feature_sets.insert("stylistic_set_13", HB_TAG('s', 's', '1', '3')); + feature_sets.insert("stylistic_set_14", HB_TAG('s', 's', '1', '4')); + feature_sets.insert("stylistic_set_15", HB_TAG('s', 's', '1', '5')); + feature_sets.insert("stylistic_set_16", HB_TAG('s', 's', '1', '6')); + feature_sets.insert("stylistic_set_17", HB_TAG('s', 's', '1', '7')); + feature_sets.insert("stylistic_set_18", HB_TAG('s', 's', '1', '8')); + feature_sets.insert("stylistic_set_19", HB_TAG('s', 's', '1', '9')); + feature_sets.insert("stylistic_set_20", HB_TAG('s', 's', '2', '0')); + feature_sets.insert("math_script_style_alternates", HB_TAG('s', 's', 't', 'y')); + feature_sets.insert("stretching_glyph_decomposition", HB_TAG('s', 't', 'c', 'h')); + feature_sets.insert("subscript", HB_TAG('s', 'u', 'b', 's')); + feature_sets.insert("superscript", HB_TAG('s', 'u', 'p', 's')); + feature_sets.insert("swash", HB_TAG('s', 'w', 's', 'h')); + feature_sets.insert("titling", HB_TAG('t', 'i', 't', 'l')); + feature_sets.insert("trailing_jamo_forms", HB_TAG('t', 'j', 'm', 'o')); + feature_sets.insert("traditional_name_forms", HB_TAG('t', 'n', 'a', 'm')); + feature_sets.insert("tabular_figures", HB_TAG('t', 'n', 'u', 'm')); + feature_sets.insert("traditional_forms", HB_TAG('t', 'r', 'a', 'd')); + feature_sets.insert("third_widths", HB_TAG('t', 'w', 'i', 'd')); + feature_sets.insert("unicase", HB_TAG('u', 'n', 'i', 'c')); + feature_sets.insert("alternate_vertical_metrics", HB_TAG('v', 'a', 'l', 't')); + feature_sets.insert("vattu_variants", HB_TAG('v', 'a', 't', 'u')); + feature_sets.insert("vertical_writing", HB_TAG('v', 'e', 'r', 't')); + feature_sets.insert("alternate_vertical_half_metrics", HB_TAG('v', 'h', 'a', 'l')); + feature_sets.insert("vowel_jamo_forms", HB_TAG('v', 'j', 'm', 'o')); + feature_sets.insert("vertical_kana_alternates", HB_TAG('v', 'k', 'n', 'a')); + feature_sets.insert("vertical_kerning", HB_TAG('v', 'k', 'r', 'n')); + feature_sets.insert("proportional_alternate_vertical_metrics", HB_TAG('v', 'p', 'a', 'l')); + feature_sets.insert("vertical_alternates_and_rotation", HB_TAG('v', 'r', 't', '2')); + feature_sets.insert("vertical_alternates_for_rotation", HB_TAG('v', 'r', 't', 'r')); + feature_sets.insert("slashed_zero", HB_TAG('z', 'e', 'r', 'o')); + // Registered OpenType variation tag. + feature_sets.insert("italic", HB_TAG('i', 't', 'a', 'l')); + feature_sets.insert("optical_size", HB_TAG('o', 'p', 's', 'z')); + feature_sets.insert("slant", HB_TAG('s', 'l', 'n', 't')); + feature_sets.insert("width", HB_TAG('w', 'd', 't', 'h')); + feature_sets.insert("weight", HB_TAG('w', 'g', 'h', 't')); +} int32_t TextServerAdvanced::name_to_tag(const String &p_name) const { - for (int i = 0; feature_set[i].tag != 0; i++) { - if (feature_set[i].name == p_name) { - return feature_set[i].tag; - } + if (feature_sets.has(p_name)) { + return feature_sets[p_name]; } // No readable name, use tag string. @@ -707,9 +701,9 @@ int32_t TextServerAdvanced::name_to_tag(const String &p_name) const { } String TextServerAdvanced::tag_to_name(int32_t p_tag) const { - for (int i = 0; feature_set[i].tag != 0; i++) { - if (feature_set[i].tag == p_tag) { - return feature_set[i].name; + for (const KeyValue<StringName, int32_t> &E : feature_sets) { + if (E.value == p_tag) { + return E.key; } } @@ -744,6 +738,10 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_ continue; } + if (ct.offsets.size() < ct.texture_w) { + continue; + } + ret.y = 0x7FFFFFFF; ret.x = 0; @@ -960,7 +958,6 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf( edgeColoringSimple(shape, 3.0); // Max. angle. msdfgen::Bitmap<float, 4> image(w, h); // Texture size. - //msdfgen::generateMTSDF(image, shape, p_pixel_range, 1.0, msdfgen::Vector2(-bounds.l, -bounds.b)); // Range, scale, translation. DistancePixelConversion distancePixelConversion(p_pixel_range); msdfgen::Projection projection(msdfgen::Vector2(1.0, 1.0), msdfgen::Vector2(-bounds.l, -bounds.b)); @@ -990,10 +987,6 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf( wr[ofs + 1] = (uint8_t)(CLAMP(image(j, i)[1] * 256.f, 0.f, 255.f)); wr[ofs + 2] = (uint8_t)(CLAMP(image(j, i)[2] * 256.f, 0.f, 255.f)); wr[ofs + 3] = (uint8_t)(CLAMP(image(j, i)[3] * 256.f, 0.f, 255.f)); - //wr[ofs + 0] = 100; - //wr[ofs + 1] = 100; - //wr[ofs + 2] = 100; - //wr[ofs + 3] = 100; } } } @@ -1058,13 +1051,12 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma case FT_PIXEL_MODE_MONO: { int byte = i * bitmap.pitch + (j >> 3); int bit = 1 << (7 - (j % 8)); - wr[ofs + 0] = 255; //grayscale as 1 + wr[ofs + 0] = 255; // grayscale as 1 wr[ofs + 1] = (bitmap.buffer[byte] & bit) ? 255 : 0; } break; case FT_PIXEL_MODE_GRAY: - wr[ofs + 0] = 255; //grayscale as 1 + wr[ofs + 0] = 255; // grayscale as 1 wr[ofs + 1] = bitmap.buffer[i * bitmap.pitch + j]; - //wr[ofs + 1] = 100; break; case FT_PIXEL_MODE_BGRA: { int ofs_color = i * bitmap.pitch + (j << 2); @@ -1162,7 +1154,7 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontDataAdvanced *p_font_d int error = FT_Load_Glyph(fd->face, p_glyph, flags); if (error) { fd->glyph_map[p_glyph] = FontGlyph(); - ERR_FAIL_V_MSG(false, "FreeType: Failed to load glyph."); + return false; } if (!outline) { @@ -1225,13 +1217,13 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced FontDataForSizeAdvanced *fd = memnew(FontDataForSizeAdvanced); fd->size = p_size; - if (p_font_data->data_ptr) { + if (p_font_data->data_ptr && (p_font_data->data_size > 0)) { // Init dynamic font. #ifdef MODULE_FREETYPE_ENABLED int error = 0; if (!library) { error = FT_Init_FreeType(&library); - ERR_FAIL_COND_V_MSG(error != 0, false, TTR("FreeType: Error initializing library:") + " '" + String(FT_Error_String(error)) + "'."); + ERR_FAIL_COND_V_MSG(error != 0, false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'."); } memset(&fd->stream, 0, sizeof(FT_StreamRec)); @@ -1249,20 +1241,14 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced if (error) { FT_Done_Face(fd->face); fd->face = nullptr; - ERR_FAIL_V_MSG(false, TTR("FreeType: Error loading font:") + " '" + String(FT_Error_String(error)) + "'."); - } - fd->hb_handle = hb_ft_font_create(fd->face, nullptr); - if (fd->hb_handle == nullptr) { - FT_Done_Face(fd->face); - fd->face = nullptr; - ERR_FAIL_V_MSG(false, TTR("HarfBuzz: Error creating FreeType font object.")); + ERR_FAIL_V_MSG(false, "FreeType: Error loading font: '" + String(FT_Error_String(error)) + "'."); } if (p_font_data->msdf) { fd->oversampling = 1.0f; fd->size.x = p_font_data->msdf_source_size; } else if (p_font_data->oversampling <= 0.0f) { - fd->oversampling = TS->font_get_global_oversampling(); + fd->oversampling = font_get_global_oversampling(); } else { fd->oversampling = p_font_data->oversampling; } @@ -1270,13 +1256,13 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced if (FT_HAS_COLOR(fd->face) && fd->face->num_fixed_sizes > 0) { int best_match = 0; int diff = ABS(fd->size.x - ((int64_t)fd->face->available_sizes[0].width)); - fd->scale = real_t(fd->size.x * fd->oversampling) / fd->face->available_sizes[0].width; + fd->scale = float(fd->size.x * fd->oversampling) / fd->face->available_sizes[0].width; for (int i = 1; i < fd->face->num_fixed_sizes; i++) { int ndiff = ABS(fd->size.x - ((int64_t)fd->face->available_sizes[i].width)); if (ndiff < diff) { best_match = i; diff = ndiff; - fd->scale = real_t(fd->size.x * fd->oversampling) / fd->face->available_sizes[i].width; + fd->scale = float(fd->size.x * fd->oversampling) / fd->face->available_sizes[i].width; } } FT_Select_Size(fd->face, best_match); @@ -1284,6 +1270,8 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced FT_Set_Pixel_Sizes(fd->face, 0, fd->size.x * fd->oversampling); } + fd->hb_handle = hb_ft_font_create(fd->face, nullptr); + fd->ascent = (fd->face->size->metrics.ascender / 64.0) / fd->oversampling * fd->scale; fd->descent = (-fd->face->size->metrics.descender / 64.0) / fd->oversampling * fd->scale; fd->underline_position = (-FT_MulFix(fd->face->underline_position, fd->face->size->metrics.y_scale) / 64.0) / fd->oversampling * fd->scale; @@ -1598,22 +1586,19 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced FT_Done_MM_Var(library, amaster); } #else - ERR_FAIL_V_MSG(false, TTR("FreeType: Can't load dynamic font, engine is compiled without FreeType support!"); + ERR_FAIL_V_MSG(false, "FreeType: Can't load dynamic font, engine is compiled without FreeType support!"); #endif } else { // Init bitmap font. - fd->hb_handle = hb_bmp_font_create(fd, nullptr); - if (!fd->hb_handle) { - ERR_FAIL_V_MSG(false, TTR("HarfBuzz: Error creating bitmap font object.")); - } + fd->hb_handle = _bmp_font_create(fd, nullptr); } p_font_data->cache[p_size] = fd; return true; } _FORCE_INLINE_ void TextServerAdvanced::_font_clear_cache(FontDataAdvanced *p_font_data) { - for (const Map<Vector2i, FontDataForSizeAdvanced *>::Element *E = p_font_data->cache.front(); E; E = E->next()) { - memdelete(E->get()); + for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : p_font_data->cache) { + memdelete(E.value); } p_font_data->cache.clear(); p_font_data->face_init = false; @@ -1623,7 +1608,7 @@ _FORCE_INLINE_ void TextServerAdvanced::_font_clear_cache(FontDataAdvanced *p_fo } hb_font_t *TextServerAdvanced::_font_get_hb_handle(RID p_font_rid, int p_size) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, nullptr); MutexLock lock(fd->mutex); @@ -1641,7 +1626,7 @@ RID TextServerAdvanced::create_font() { } void TextServerAdvanced::font_set_data(RID p_font_rid, const PackedByteArray &p_data) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1652,7 +1637,7 @@ void TextServerAdvanced::font_set_data(RID p_font_rid, const PackedByteArray &p_ } void TextServerAdvanced::font_set_data_ptr(RID p_font_rid, const uint8_t *p_data_ptr, size_t p_data_size) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1663,7 +1648,7 @@ void TextServerAdvanced::font_set_data_ptr(RID p_font_rid, const uint8_t *p_data } void TextServerAdvanced::font_set_antialiased(RID p_font_rid, bool p_antialiased) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1674,7 +1659,7 @@ void TextServerAdvanced::font_set_antialiased(RID p_font_rid, bool p_antialiased } bool TextServerAdvanced::font_is_antialiased(RID p_font_rid) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1682,7 +1667,7 @@ bool TextServerAdvanced::font_is_antialiased(RID p_font_rid) const { } void TextServerAdvanced::font_set_multichannel_signed_distance_field(RID p_font_rid, bool p_msdf) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1693,7 +1678,7 @@ void TextServerAdvanced::font_set_multichannel_signed_distance_field(RID p_font_ } bool TextServerAdvanced::font_is_multichannel_signed_distance_field(RID p_font_rid) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1701,7 +1686,7 @@ bool TextServerAdvanced::font_is_multichannel_signed_distance_field(RID p_font_r } void TextServerAdvanced::font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pixel_range) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1712,7 +1697,7 @@ void TextServerAdvanced::font_set_msdf_pixel_range(RID p_font_rid, int p_msdf_pi } int TextServerAdvanced::font_get_msdf_pixel_range(RID p_font_rid) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1720,7 +1705,7 @@ int TextServerAdvanced::font_get_msdf_pixel_range(RID p_font_rid) const { } void TextServerAdvanced::font_set_msdf_size(RID p_font_rid, int p_msdf_size) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1731,7 +1716,7 @@ void TextServerAdvanced::font_set_msdf_size(RID p_font_rid, int p_msdf_size) { } int TextServerAdvanced::font_get_msdf_size(RID p_font_rid) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1739,7 +1724,7 @@ int TextServerAdvanced::font_get_msdf_size(RID p_font_rid) const { } void TextServerAdvanced::font_set_fixed_size(RID p_font_rid, int p_fixed_size) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1749,7 +1734,7 @@ void TextServerAdvanced::font_set_fixed_size(RID p_font_rid, int p_fixed_size) { } int TextServerAdvanced::font_get_fixed_size(RID p_font_rid) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1757,7 +1742,7 @@ int TextServerAdvanced::font_get_fixed_size(RID p_font_rid) const { } void TextServerAdvanced::font_set_force_autohinter(RID p_font_rid, bool p_force_autohinter) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1768,7 +1753,7 @@ void TextServerAdvanced::font_set_force_autohinter(RID p_font_rid, bool p_force_ } bool TextServerAdvanced::font_is_force_autohinter(RID p_font_rid) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1776,7 +1761,7 @@ bool TextServerAdvanced::font_is_force_autohinter(RID p_font_rid) const { } void TextServerAdvanced::font_set_hinting(RID p_font_rid, TextServer::Hinting p_hinting) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1787,7 +1772,7 @@ void TextServerAdvanced::font_set_hinting(RID p_font_rid, TextServer::Hinting p_ } TextServer::Hinting TextServerAdvanced::font_get_hinting(RID p_font_rid) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, HINTING_NONE); MutexLock lock(fd->mutex); @@ -1795,7 +1780,7 @@ TextServer::Hinting TextServerAdvanced::font_get_hinting(RID p_font_rid) const { } void TextServerAdvanced::font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1806,15 +1791,15 @@ void TextServerAdvanced::font_set_variation_coordinates(RID p_font_rid, const Di } Dictionary TextServerAdvanced::font_get_variation_coordinates(RID p_font_rid) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); MutexLock lock(fd->mutex); return fd->variation_coordinates; } -void TextServerAdvanced::font_set_oversampling(RID p_font_rid, real_t p_oversampling) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); +void TextServerAdvanced::font_set_oversampling(RID p_font_rid, float p_oversampling) { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1824,8 +1809,8 @@ void TextServerAdvanced::font_set_oversampling(RID p_font_rid, real_t p_oversamp } } -real_t TextServerAdvanced::font_get_oversampling(RID p_font_rid) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); +float TextServerAdvanced::font_get_oversampling(RID p_font_rid) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.f); MutexLock lock(fd->mutex); @@ -1833,7 +1818,7 @@ real_t TextServerAdvanced::font_get_oversampling(RID p_font_rid) const { } Array TextServerAdvanced::font_get_size_cache_list(RID p_font_rid) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Array()); MutexLock lock(fd->mutex); @@ -1845,18 +1830,18 @@ Array TextServerAdvanced::font_get_size_cache_list(RID p_font_rid) const { } void TextServerAdvanced::font_clear_size_cache(RID p_font_rid) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); - for (const Map<Vector2i, FontDataForSizeAdvanced *>::Element *E = fd->cache.front(); E; E = E->next()) { - memdelete(E->get()); + for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : fd->cache) { + memdelete(E.value); } fd->cache.clear(); } void TextServerAdvanced::font_remove_size_cache(RID p_font_rid, const Vector2i &p_size) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1866,8 +1851,8 @@ void TextServerAdvanced::font_remove_size_cache(RID p_font_rid, const Vector2i & } } -void TextServerAdvanced::font_set_ascent(RID p_font_rid, int p_size, real_t p_ascent) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); +void TextServerAdvanced::font_set_ascent(RID p_font_rid, int p_size, float p_ascent) { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1877,8 +1862,8 @@ void TextServerAdvanced::font_set_ascent(RID p_font_rid, int p_size, real_t p_as fd->cache[size]->ascent = p_ascent; } -real_t TextServerAdvanced::font_get_ascent(RID p_font_rid, int p_size) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); +float TextServerAdvanced::font_get_ascent(RID p_font_rid, int p_size) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.f); MutexLock lock(fd->mutex); @@ -1887,14 +1872,14 @@ real_t TextServerAdvanced::font_get_ascent(RID p_font_rid, int p_size) const { ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); if (fd->msdf) { - return fd->cache[size]->ascent * (real_t)p_size / (real_t)fd->msdf_source_size; + return fd->cache[size]->ascent * (float)p_size / (float)fd->msdf_source_size; } else { return fd->cache[size]->ascent; } } -void TextServerAdvanced::font_set_descent(RID p_font_rid, int p_size, real_t p_descent) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); +void TextServerAdvanced::font_set_descent(RID p_font_rid, int p_size, float p_descent) { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); Vector2i size = _get_size(fd, p_size); @@ -1903,8 +1888,8 @@ void TextServerAdvanced::font_set_descent(RID p_font_rid, int p_size, real_t p_d fd->cache[size]->descent = p_descent; } -real_t TextServerAdvanced::font_get_descent(RID p_font_rid, int p_size) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); +float TextServerAdvanced::font_get_descent(RID p_font_rid, int p_size) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.f); MutexLock lock(fd->mutex); @@ -1913,14 +1898,14 @@ real_t TextServerAdvanced::font_get_descent(RID p_font_rid, int p_size) const { ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); if (fd->msdf) { - return fd->cache[size]->descent * (real_t)p_size / (real_t)fd->msdf_source_size; + return fd->cache[size]->descent * (float)p_size / (float)fd->msdf_source_size; } else { return fd->cache[size]->descent; } } -void TextServerAdvanced::font_set_underline_position(RID p_font_rid, int p_size, real_t p_underline_position) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); +void TextServerAdvanced::font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1930,8 +1915,8 @@ void TextServerAdvanced::font_set_underline_position(RID p_font_rid, int p_size, fd->cache[size]->underline_position = p_underline_position; } -real_t TextServerAdvanced::font_get_underline_position(RID p_font_rid, int p_size) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); +float TextServerAdvanced::font_get_underline_position(RID p_font_rid, int p_size) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.f); MutexLock lock(fd->mutex); @@ -1940,14 +1925,14 @@ real_t TextServerAdvanced::font_get_underline_position(RID p_font_rid, int p_siz ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); if (fd->msdf) { - return fd->cache[size]->underline_position * (real_t)p_size / (real_t)fd->msdf_source_size; + return fd->cache[size]->underline_position * (float)p_size / (float)fd->msdf_source_size; } else { return fd->cache[size]->underline_position; } } -void TextServerAdvanced::font_set_underline_thickness(RID p_font_rid, int p_size, real_t p_underline_thickness) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); +void TextServerAdvanced::font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1957,8 +1942,8 @@ void TextServerAdvanced::font_set_underline_thickness(RID p_font_rid, int p_size fd->cache[size]->underline_thickness = p_underline_thickness; } -real_t TextServerAdvanced::font_get_underline_thickness(RID p_font_rid, int p_size) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); +float TextServerAdvanced::font_get_underline_thickness(RID p_font_rid, int p_size) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.f); MutexLock lock(fd->mutex); @@ -1967,14 +1952,14 @@ real_t TextServerAdvanced::font_get_underline_thickness(RID p_font_rid, int p_si ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); if (fd->msdf) { - return fd->cache[size]->underline_thickness * (real_t)p_size / (real_t)fd->msdf_source_size; + return fd->cache[size]->underline_thickness * (float)p_size / (float)fd->msdf_source_size; } else { return fd->cache[size]->underline_thickness; } } -void TextServerAdvanced::font_set_scale(RID p_font_rid, int p_size, real_t p_scale) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); +void TextServerAdvanced::font_set_scale(RID p_font_rid, int p_size, float p_scale) { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1984,8 +1969,8 @@ void TextServerAdvanced::font_set_scale(RID p_font_rid, int p_size, real_t p_sca fd->cache[size]->scale = p_scale; } -real_t TextServerAdvanced::font_get_scale(RID p_font_rid, int p_size) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); +float TextServerAdvanced::font_get_scale(RID p_font_rid, int p_size) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.f); MutexLock lock(fd->mutex); @@ -1994,14 +1979,14 @@ real_t TextServerAdvanced::font_get_scale(RID p_font_rid, int p_size) const { ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0.f); if (fd->msdf) { - return fd->cache[size]->scale * (real_t)p_size / (real_t)fd->msdf_source_size; + return fd->cache[size]->scale * (float)p_size / (float)fd->msdf_source_size; } else { return fd->cache[size]->scale / fd->cache[size]->oversampling; } } void TextServerAdvanced::font_set_spacing(RID p_font_rid, int p_size, TextServer::SpacingType p_spacing, int p_value) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2022,7 +2007,7 @@ void TextServerAdvanced::font_set_spacing(RID p_font_rid, int p_size, TextServer } int TextServerAdvanced::font_get_spacing(RID p_font_rid, int p_size, TextServer::SpacingType p_spacing) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); MutexLock lock(fd->mutex); @@ -2033,14 +2018,14 @@ int TextServerAdvanced::font_get_spacing(RID p_font_rid, int p_size, TextServer: switch (p_spacing) { case TextServer::SPACING_GLYPH: { if (fd->msdf) { - return fd->cache[size]->spacing_glyph * (real_t)p_size / (real_t)fd->msdf_source_size; + return fd->cache[size]->spacing_glyph * (float)p_size / (float)fd->msdf_source_size; } else { return fd->cache[size]->spacing_glyph; } } break; case TextServer::SPACING_SPACE: { if (fd->msdf) { - return fd->cache[size]->spacing_space * (real_t)p_size / (real_t)fd->msdf_source_size; + return fd->cache[size]->spacing_space * (float)p_size / (float)fd->msdf_source_size; } else { return fd->cache[size]->spacing_space; } @@ -2053,7 +2038,7 @@ int TextServerAdvanced::font_get_spacing(RID p_font_rid, int p_size, TextServer: } int TextServerAdvanced::font_get_texture_count(RID p_font_rid, const Vector2i &p_size) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); MutexLock lock(fd->mutex); @@ -2065,7 +2050,7 @@ int TextServerAdvanced::font_get_texture_count(RID p_font_rid, const Vector2i &p } void TextServerAdvanced::font_clear_textures(RID p_font_rid, const Vector2i &p_size) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); Vector2i size = _get_size_outline(fd, p_size); @@ -2075,7 +2060,7 @@ void TextServerAdvanced::font_clear_textures(RID p_font_rid, const Vector2i &p_s } void TextServerAdvanced::font_remove_texture(RID p_font_rid, const Vector2i &p_size, int p_texture_index) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2087,7 +2072,7 @@ void TextServerAdvanced::font_remove_texture(RID p_font_rid, const Vector2i &p_s } void TextServerAdvanced::font_set_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const Ref<Image> &p_image) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); ERR_FAIL_COND(p_image.is_null()); @@ -2113,7 +2098,7 @@ void TextServerAdvanced::font_set_texture_image(RID p_font_rid, const Vector2i & } Ref<Image> TextServerAdvanced::font_get_texture_image(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Ref<Image>()); MutexLock lock(fd->mutex); @@ -2128,12 +2113,13 @@ Ref<Image> TextServerAdvanced::font_get_texture_image(RID p_font_rid, const Vect } void TextServerAdvanced::font_set_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index, const PackedInt32Array &p_offset) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); + ERR_FAIL_COND(p_texture_index < 0); if (p_texture_index >= fd->cache[size]->textures.size()) { fd->cache[size]->textures.resize(p_texture_index + 1); } @@ -2143,7 +2129,7 @@ void TextServerAdvanced::font_set_texture_offsets(RID p_font_rid, const Vector2i } PackedInt32Array TextServerAdvanced::font_get_texture_offsets(RID p_font_rid, const Vector2i &p_size, int p_texture_index) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, PackedInt32Array()); MutexLock lock(fd->mutex); @@ -2156,7 +2142,7 @@ PackedInt32Array TextServerAdvanced::font_get_texture_offsets(RID p_font_rid, co } Array TextServerAdvanced::font_get_glyph_list(RID p_font_rid, const Vector2i &p_size) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Array()); MutexLock lock(fd->mutex); @@ -2173,7 +2159,7 @@ Array TextServerAdvanced::font_get_glyph_list(RID p_font_rid, const Vector2i &p_ } void TextServerAdvanced::font_clear_glyphs(RID p_font_rid, const Vector2i &p_size) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2184,7 +2170,7 @@ void TextServerAdvanced::font_clear_glyphs(RID p_font_rid, const Vector2i &p_siz } void TextServerAdvanced::font_remove_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2195,7 +2181,7 @@ void TextServerAdvanced::font_remove_glyph(RID p_font_rid, const Vector2i &p_siz } Vector2 TextServerAdvanced::font_get_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector2()); MutexLock lock(fd->mutex); @@ -2209,14 +2195,14 @@ Vector2 TextServerAdvanced::font_get_glyph_advance(RID p_font_rid, int p_size, i const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; if (fd->msdf) { - return gl[p_glyph].advance * (real_t)p_size / (real_t)fd->msdf_source_size; + return gl[p_glyph].advance * (float)p_size / (float)fd->msdf_source_size; } else { return gl[p_glyph].advance; } } void TextServerAdvanced::font_set_glyph_advance(RID p_font_rid, int p_size, int32_t p_glyph, const Vector2 &p_advance) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2231,7 +2217,7 @@ void TextServerAdvanced::font_set_glyph_advance(RID p_font_rid, int p_size, int3 } Vector2 TextServerAdvanced::font_get_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector2()); MutexLock lock(fd->mutex); @@ -2245,14 +2231,14 @@ Vector2 TextServerAdvanced::font_get_glyph_offset(RID p_font_rid, const Vector2i const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; if (fd->msdf) { - return gl[p_glyph].rect.position * (real_t)p_size.x / (real_t)fd->msdf_source_size; + return gl[p_glyph].rect.position * (float)p_size.x / (float)fd->msdf_source_size; } else { return gl[p_glyph].rect.position; } } void TextServerAdvanced::font_set_glyph_offset(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_offset) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2267,7 +2253,7 @@ void TextServerAdvanced::font_set_glyph_offset(RID p_font_rid, const Vector2i &p } Vector2 TextServerAdvanced::font_get_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector2()); MutexLock lock(fd->mutex); @@ -2281,14 +2267,14 @@ Vector2 TextServerAdvanced::font_get_glyph_size(RID p_font_rid, const Vector2i & const HashMap<int32_t, FontGlyph> &gl = fd->cache[size]->glyph_map; if (fd->msdf) { - return gl[p_glyph].rect.size * (real_t)p_size.x / (real_t)fd->msdf_source_size; + return gl[p_glyph].rect.size * (float)p_size.x / (float)fd->msdf_source_size; } else { return gl[p_glyph].rect.size; } } void TextServerAdvanced::font_set_glyph_size(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Vector2 &p_gl_size) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2303,7 +2289,7 @@ void TextServerAdvanced::font_set_glyph_size(RID p_font_rid, const Vector2i &p_s } Rect2 TextServerAdvanced::font_get_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Rect2()); MutexLock lock(fd->mutex); @@ -2319,7 +2305,7 @@ Rect2 TextServerAdvanced::font_get_glyph_uv_rect(RID p_font_rid, const Vector2i } void TextServerAdvanced::font_set_glyph_uv_rect(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, const Rect2 &p_uv_rect) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2334,7 +2320,7 @@ void TextServerAdvanced::font_set_glyph_uv_rect(RID p_font_rid, const Vector2i & } int TextServerAdvanced::font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, -1); MutexLock lock(fd->mutex); @@ -2350,7 +2336,7 @@ int TextServerAdvanced::font_get_glyph_texture_idx(RID p_font_rid, const Vector2 } void TextServerAdvanced::font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2364,42 +2350,50 @@ void TextServerAdvanced::font_set_glyph_texture_idx(RID p_font_rid, const Vector gl[p_glyph].found = true; } -bool TextServerAdvanced::font_get_glyph_contours(RID p_font_rid, int p_size, int32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); - ERR_FAIL_COND_V(!fd, false); +Dictionary TextServerAdvanced::font_get_glyph_contours(RID p_font_rid, int p_size, int32_t p_index) const { + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + ERR_FAIL_COND_V(!fd, Dictionary()); MutexLock lock(fd->mutex); Vector2i size = _get_size(fd, p_size); - ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), false); + ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Dictionary()); + Vector<Vector3> points; + Vector<int32_t> contours; + bool orientation; #ifdef MODULE_FREETYPE_ENABLED int error = FT_Load_Glyph(fd->cache[size]->face, p_index, FT_LOAD_NO_BITMAP | (fd->force_autohinter ? FT_LOAD_FORCE_AUTOHINT : 0)); - ERR_FAIL_COND_V(error, false); + ERR_FAIL_COND_V(error, Dictionary()); - r_points.clear(); - r_contours.clear(); + points.clear(); + contours.clear(); - real_t h = fd->cache[size]->ascent; - real_t scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale; + float h = fd->cache[size]->ascent; + float scale = (1.0 / 64.0) / fd->cache[size]->oversampling * fd->cache[size]->scale; if (fd->msdf) { - scale = scale * (real_t)p_size / (real_t)fd->msdf_source_size; + scale = scale * (float)p_size / (float)fd->msdf_source_size; } for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_points; i++) { - r_points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, h - fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i]))); + points.push_back(Vector3(fd->cache[size]->face->glyph->outline.points[i].x * scale, h - fd->cache[size]->face->glyph->outline.points[i].y * scale, FT_CURVE_TAG(fd->cache[size]->face->glyph->outline.tags[i]))); } for (short i = 0; i < fd->cache[size]->face->glyph->outline.n_contours; i++) { - r_contours.push_back(fd->cache[size]->face->glyph->outline.contours[i]); + contours.push_back(fd->cache[size]->face->glyph->outline.contours[i]); } - r_orientation = (FT_Outline_Get_Orientation(&fd->cache[size]->face->glyph->outline) == FT_ORIENTATION_FILL_RIGHT); + orientation = (FT_Outline_Get_Orientation(&fd->cache[size]->face->glyph->outline) == FT_ORIENTATION_FILL_RIGHT); #else - return false; + return Dictionary(); #endif - return true; + + Dictionary out; + out["points"] = points; + out["contours"] = contours; + out["orientation"] = orientation; + return out; } Array TextServerAdvanced::font_get_kerning_list(RID p_font_rid, int p_size) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Array()); MutexLock lock(fd->mutex); @@ -2415,7 +2409,7 @@ Array TextServerAdvanced::font_get_kerning_list(RID p_font_rid, int p_size) cons } void TextServerAdvanced::font_clear_kerning_map(RID p_font_rid, int p_size) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2426,7 +2420,7 @@ void TextServerAdvanced::font_clear_kerning_map(RID p_font_rid, int p_size) { } void TextServerAdvanced::font_remove_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2437,7 +2431,7 @@ void TextServerAdvanced::font_remove_kerning(RID p_font_rid, int p_size, const V } void TextServerAdvanced::font_set_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2448,7 +2442,7 @@ void TextServerAdvanced::font_set_kerning(RID p_font_rid, int p_size, const Vect } Vector2 TextServerAdvanced::font_get_kerning(RID p_font_rid, int p_size, const Vector2i &p_glyph_pair) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector2()); MutexLock lock(fd->mutex); @@ -2460,7 +2454,7 @@ Vector2 TextServerAdvanced::font_get_kerning(RID p_font_rid, int p_size, const V if (kern.has(p_glyph_pair)) { if (fd->msdf) { - return kern[p_glyph_pair] * (real_t)p_size / (real_t)fd->msdf_source_size; + return kern[p_glyph_pair] * (float)p_size / (float)fd->msdf_source_size; } else { return kern[p_glyph_pair]; } @@ -2470,7 +2464,7 @@ Vector2 TextServerAdvanced::font_get_kerning(RID p_font_rid, int p_size, const V FT_Vector delta; FT_Get_Kerning(fd->cache[size]->face, p_glyph_pair.x, p_glyph_pair.y, FT_KERNING_DEFAULT, &delta); if (fd->msdf) { - return Vector2(delta.x, delta.y) * (real_t)p_size / (real_t)fd->msdf_source_size; + return Vector2(delta.x, delta.y) * (float)p_size / (float)fd->msdf_source_size; } else { return Vector2(delta.x, delta.y); } @@ -2481,8 +2475,10 @@ Vector2 TextServerAdvanced::font_get_kerning(RID p_font_rid, int p_size, const V } int32_t TextServerAdvanced::font_get_glyph_index(RID p_font_rid, int p_size, char32_t p_char, char32_t p_variation_selector) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); + ERR_FAIL_COND_V_MSG((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff), 0, "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_char, 16) + "."); + ERR_FAIL_COND_V_MSG((p_variation_selector >= 0xd800 && p_variation_selector <= 0xdfff) || (p_variation_selector > 0x10ffff), 0, "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_variation_selector, 16) + "."); MutexLock lock(fd->mutex); Vector2i size = _get_size(fd, p_size); @@ -2504,8 +2500,9 @@ int32_t TextServerAdvanced::font_get_glyph_index(RID p_font_rid, int p_size, cha } bool TextServerAdvanced::font_has_char(RID p_font_rid, char32_t p_char) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); + ERR_FAIL_COND_V_MSG((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff), false, "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_char, 16) + "."); MutexLock lock(fd->mutex); if (fd->cache.is_empty()) { @@ -2522,7 +2519,7 @@ bool TextServerAdvanced::font_has_char(RID p_font_rid, char32_t p_char) const { } String TextServerAdvanced::font_get_supported_chars(RID p_font_rid) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, String()); MutexLock lock(fd->mutex); @@ -2556,8 +2553,10 @@ String TextServerAdvanced::font_get_supported_chars(RID p_font_rid) const { } void TextServerAdvanced::font_render_range(RID p_font_rid, const Vector2i &p_size, char32_t p_start, char32_t p_end) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); + ERR_FAIL_COND_MSG((p_start >= 0xd800 && p_start <= 0xdfff) || (p_start > 0x10ffff), "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_start, 16) + "."); + ERR_FAIL_COND_MSG((p_end >= 0xd800 && p_end <= 0xdfff) || (p_end > 0x10ffff), "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_end, 16) + "."); MutexLock lock(fd->mutex); Vector2i size = _get_size_outline(fd, p_size); @@ -2574,7 +2573,7 @@ void TextServerAdvanced::font_render_range(RID p_font_rid, const Vector2i &p_siz } void TextServerAdvanced::font_render_glyph(RID p_font_rid, const Vector2i &p_size, int32_t p_index) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2584,7 +2583,7 @@ void TextServerAdvanced::font_render_glyph(RID p_font_rid, const Vector2i &p_siz } void TextServerAdvanced::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2609,8 +2608,8 @@ void TextServerAdvanced::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid(); if (fd->msdf) { Point2 cpos = p_pos; - cpos += gl.rect.position * (real_t)p_size / (real_t)fd->msdf_source_size; - Size2 csize = gl.rect.size * (real_t)p_size / (real_t)fd->msdf_source_size; + cpos += gl.rect.position * (float)p_size / (float)fd->msdf_source_size; + Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size; RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, 0, fd->msdf_range); } else { Point2i cpos = p_pos; @@ -2624,7 +2623,7 @@ void TextServerAdvanced::font_draw_glyph(RID p_font_rid, RID p_canvas, int p_siz } void TextServerAdvanced::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, int p_size, int p_outline_size, const Vector2 &p_pos, int32_t p_index, const Color &p_color) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2649,8 +2648,8 @@ void TextServerAdvanced::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i RID texture = fd->cache[size]->textures[gl.texture_idx].texture->get_rid(); if (fd->msdf) { Point2 cpos = p_pos; - cpos += gl.rect.position * (real_t)p_size / (real_t)fd->msdf_source_size; - Size2 csize = gl.rect.size * (real_t)p_size / (real_t)fd->msdf_source_size; + cpos += gl.rect.position * (float)p_size / (float)fd->msdf_source_size; + Size2 csize = gl.rect.size * (float)p_size / (float)fd->msdf_source_size; RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, p_outline_size * 2, fd->msdf_range); } else { Point2i cpos = p_pos; @@ -2664,7 +2663,7 @@ void TextServerAdvanced::font_draw_glyph_outline(RID p_font_rid, RID p_canvas, i } bool TextServerAdvanced::font_is_language_supported(RID p_font_rid, const String &p_language) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -2676,7 +2675,7 @@ bool TextServerAdvanced::font_is_language_supported(RID p_font_rid, const String } void TextServerAdvanced::font_set_language_support_override(RID p_font_rid, const String &p_language, bool p_supported) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2684,7 +2683,7 @@ void TextServerAdvanced::font_set_language_support_override(RID p_font_rid, cons } bool TextServerAdvanced::font_get_language_support_override(RID p_font_rid, const String &p_language) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -2692,7 +2691,7 @@ bool TextServerAdvanced::font_get_language_support_override(RID p_font_rid, cons } void TextServerAdvanced::font_remove_language_support_override(RID p_font_rid, const String &p_language) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2700,19 +2699,19 @@ void TextServerAdvanced::font_remove_language_support_override(RID p_font_rid, c } Vector<String> TextServerAdvanced::font_get_language_support_overrides(RID p_font_rid) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector<String>()); MutexLock lock(fd->mutex); Vector<String> out; - for (const Map<String, bool>::Element *E = fd->language_support_overrides.front(); E; E = E->next()) { - out.push_back(E->key()); + for (const KeyValue<String, bool> &E : fd->language_support_overrides) { + out.push_back(E.key); } return out; } bool TextServerAdvanced::font_is_script_supported(RID p_font_rid, const String &p_script) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -2721,12 +2720,12 @@ bool TextServerAdvanced::font_is_script_supported(RID p_font_rid, const String & } else { Vector2i size = _get_size(fd, 16); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), false); - return fd->supported_scripts.has(TS->name_to_tag(p_script)); + return fd->supported_scripts.has(hb_tag_from_string(p_script.ascii().get_data(), -1)); } } void TextServerAdvanced::font_set_script_support_override(RID p_font_rid, const String &p_script, bool p_supported) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2734,7 +2733,7 @@ void TextServerAdvanced::font_set_script_support_override(RID p_font_rid, const } bool TextServerAdvanced::font_get_script_support_override(RID p_font_rid, const String &p_script) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -2742,7 +2741,7 @@ bool TextServerAdvanced::font_get_script_support_override(RID p_font_rid, const } void TextServerAdvanced::font_remove_script_support_override(RID p_font_rid, const String &p_script) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2750,7 +2749,7 @@ void TextServerAdvanced::font_remove_script_support_override(RID p_font_rid, con } Vector<String> TextServerAdvanced::font_get_script_support_overrides(RID p_font_rid) { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector<String>()); MutexLock lock(fd->mutex); @@ -2762,7 +2761,7 @@ Vector<String> TextServerAdvanced::font_get_script_support_overrides(RID p_font_ } Dictionary TextServerAdvanced::font_supported_feature_list(RID p_font_rid) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); MutexLock lock(fd->mutex); @@ -2772,7 +2771,7 @@ Dictionary TextServerAdvanced::font_supported_feature_list(RID p_font_rid) const } Dictionary TextServerAdvanced::font_supported_variation_list(RID p_font_rid) const { - FontDataAdvanced *fd = font_owner.getornull(p_font_rid); + FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); MutexLock lock(fd->mutex); @@ -2781,11 +2780,11 @@ Dictionary TextServerAdvanced::font_supported_variation_list(RID p_font_rid) con return fd->supported_varaitions; } -real_t TextServerAdvanced::font_get_global_oversampling() const { +float TextServerAdvanced::font_get_global_oversampling() const { return oversampling; } -void TextServerAdvanced::font_set_global_oversampling(real_t p_oversampling) { +void TextServerAdvanced::font_set_global_oversampling(float p_oversampling) { _THREAD_SAFE_METHOD_ if (oversampling != p_oversampling) { oversampling = p_oversampling; @@ -2803,7 +2802,7 @@ void TextServerAdvanced::font_set_global_oversampling(real_t p_oversampling) { List<RID> text_bufs; shaped_owner.get_owned_list(&text_bufs); for (const RID &E : text_bufs) { - invalidate(shaped_owner.getornull(E)); + invalidate(shaped_owner.get_or_null(E)); } } } @@ -2864,11 +2863,11 @@ void TextServerAdvanced::invalidate(TextServerAdvanced::ShapedTextDataAdvanced * } void TextServerAdvanced::full_copy(ShapedTextDataAdvanced *p_shaped) { - ShapedTextDataAdvanced *parent = shaped_owner.getornull(p_shaped->parent); + ShapedTextDataAdvanced *parent = shaped_owner.get_or_null(p_shaped->parent); - for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = parent->objects.front(); E; E = E->next()) { - if (E->get().pos >= p_shaped->start && E->get().pos < p_shaped->end) { - p_shaped->objects[E->key()] = E->get(); + for (const KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : parent->objects) { + if (E.value.pos >= p_shaped->start && E.value.pos < p_shaped->end) { + p_shaped->objects[E.key] = E.value; } } @@ -2895,7 +2894,7 @@ RID TextServerAdvanced::create_shaped_text(TextServer::Direction p_direction, Te } void TextServerAdvanced::shaped_text_clear(RID p_shaped) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND(!sd); MutexLock lock(sd->mutex); @@ -2910,7 +2909,7 @@ void TextServerAdvanced::shaped_text_clear(RID p_shaped) { } void TextServerAdvanced::shaped_text_set_direction(RID p_shaped, TextServer::Direction p_direction) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND(!sd); MutexLock lock(sd->mutex); @@ -2924,27 +2923,30 @@ void TextServerAdvanced::shaped_text_set_direction(RID p_shaped, TextServer::Dir } TextServer::Direction TextServerAdvanced::shaped_text_get_direction(RID p_shaped) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, TextServer::DIRECTION_LTR); MutexLock lock(sd->mutex); return sd->direction; } -void TextServerAdvanced::shaped_text_set_bidi_override(RID p_shaped, const Vector<Vector2i> &p_override) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); +void TextServerAdvanced::shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) { + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND(!sd); MutexLock lock(sd->mutex); if (sd->parent != RID()) { full_copy(sd); } - sd->bidi_override = p_override; + sd->bidi_override.clear(); + for (int i = 0; i < p_override.size(); i++) { + sd->bidi_override.push_back(p_override[i]); + } invalidate(sd); } void TextServerAdvanced::shaped_text_set_orientation(RID p_shaped, TextServer::Orientation p_orientation) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND(!sd); MutexLock lock(sd->mutex); @@ -2958,7 +2960,7 @@ void TextServerAdvanced::shaped_text_set_orientation(RID p_shaped, TextServer::O } void TextServerAdvanced::shaped_text_set_preserve_invalid(RID p_shaped, bool p_enabled) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND(!sd); MutexLock lock(sd->mutex); @@ -2970,7 +2972,7 @@ void TextServerAdvanced::shaped_text_set_preserve_invalid(RID p_shaped, bool p_e } bool TextServerAdvanced::shaped_text_get_preserve_invalid(RID p_shaped) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, false); MutexLock lock(sd->mutex); @@ -2978,7 +2980,7 @@ bool TextServerAdvanced::shaped_text_get_preserve_invalid(RID p_shaped) const { } void TextServerAdvanced::shaped_text_set_preserve_control(RID p_shaped, bool p_enabled) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND(!sd); MutexLock lock(sd->mutex); @@ -2992,7 +2994,7 @@ void TextServerAdvanced::shaped_text_set_preserve_control(RID p_shaped, bool p_e } bool TextServerAdvanced::shaped_text_get_preserve_control(RID p_shaped) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, false); MutexLock lock(sd->mutex); @@ -3000,7 +3002,7 @@ bool TextServerAdvanced::shaped_text_get_preserve_control(RID p_shaped) const { } TextServer::Orientation TextServerAdvanced::shaped_text_get_orientation(RID p_shaped) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, TextServer::ORIENTATION_HORIZONTAL); MutexLock lock(sd->mutex); @@ -3008,13 +3010,13 @@ TextServer::Orientation TextServerAdvanced::shaped_text_get_orientation(RID p_sh } bool TextServerAdvanced::shaped_text_add_string(RID p_shaped, const String &p_text, const Vector<RID> &p_fonts, int p_size, const Dictionary &p_opentype_features, const String &p_language) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, false); ERR_FAIL_COND_V(p_size <= 0, false); MutexLock lock(sd->mutex); for (int i = 0; i < p_fonts.size(); i++) { - ERR_FAIL_COND_V(!font_owner.getornull(p_fonts[i]), false); + ERR_FAIL_COND_V(!font_owner.get_or_null(p_fonts[i]), false); } if (p_text.is_empty()) { @@ -3043,7 +3045,7 @@ bool TextServerAdvanced::shaped_text_add_string(RID p_shaped, const String &p_te bool TextServerAdvanced::shaped_text_add_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align, int p_length) { _THREAD_SAFE_METHOD_ - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, false); ERR_FAIL_COND_V(p_key == Variant(), false); ERR_FAIL_COND_V(sd->objects.has(p_key), false); @@ -3072,7 +3074,7 @@ bool TextServerAdvanced::shaped_text_add_object(RID p_shaped, Variant p_key, con } bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, const Size2 &p_size, InlineAlign p_inline_align) { - ShapedTextData *sd = shaped_owner.getornull(p_shaped); + ShapedTextData *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, false); MutexLock lock(sd->mutex); @@ -3092,9 +3094,9 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, Glyph gl = sd->glyphs[i]; Variant key; if (gl.count == 1) { - for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) { - if (E->get().pos == gl.start) { - key = E->key(); + for (const KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) { + if (E.value.pos == gl.start) { + key = E.key; break; } } @@ -3123,8 +3125,7 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, } else if (sd->preserve_invalid || (sd->preserve_control && is_control(gl.index))) { // Glyph not found, replace with hex code box. if (sd->orientation == ORIENTATION_HORIZONTAL) { - sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f)); - sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f)); + sd->ascent = MAX(sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y); } else { sd->ascent = MAX(sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); sd->descent = MAX(sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); @@ -3135,66 +3136,66 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, } // Align embedded objects to baseline. - real_t full_ascent = sd->ascent; - real_t full_descent = sd->descent; - for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) { - if ((E->get().pos >= sd->start) && (E->get().pos < sd->end)) { + float full_ascent = sd->ascent; + float full_descent = sd->descent; + for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) { + if ((E.value.pos >= sd->start) && (E.value.pos < sd->end)) { if (sd->orientation == ORIENTATION_HORIZONTAL) { - switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) { + switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { case INLINE_ALIGN_TO_TOP: { - E->get().rect.position.y = -sd->ascent; + E.value.rect.position.y = -sd->ascent; } break; case INLINE_ALIGN_TO_CENTER: { - E->get().rect.position.y = (-sd->ascent + sd->descent) / 2; + E.value.rect.position.y = (-sd->ascent + sd->descent) / 2; } break; case INLINE_ALIGN_TO_BASELINE: { - E->get().rect.position.y = 0; + E.value.rect.position.y = 0; } break; case INLINE_ALIGN_TO_BOTTOM: { - E->get().rect.position.y = sd->descent; + E.value.rect.position.y = sd->descent; } break; } - switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) { + switch (E.value.inline_align & INLINE_ALIGN_IMAGE_MASK) { case INLINE_ALIGN_BOTTOM_TO: { - E->get().rect.position.y -= E->get().rect.size.y; + E.value.rect.position.y -= E.value.rect.size.y; } break; case INLINE_ALIGN_CENTER_TO: { - E->get().rect.position.y -= E->get().rect.size.y / 2; + E.value.rect.position.y -= E.value.rect.size.y / 2; } break; case INLINE_ALIGN_TOP_TO: { - //NOP + // NOP } break; } - full_ascent = MAX(full_ascent, -E->get().rect.position.y); - full_descent = MAX(full_descent, E->get().rect.position.y + E->get().rect.size.y); + full_ascent = MAX(full_ascent, -E.value.rect.position.y); + full_descent = MAX(full_descent, E.value.rect.position.y + E.value.rect.size.y); } else { - switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) { + switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { case INLINE_ALIGN_TO_TOP: { - E->get().rect.position.x = -sd->ascent; + E.value.rect.position.x = -sd->ascent; } break; case INLINE_ALIGN_TO_CENTER: { - E->get().rect.position.x = (-sd->ascent + sd->descent) / 2; + E.value.rect.position.x = (-sd->ascent + sd->descent) / 2; } break; case INLINE_ALIGN_TO_BASELINE: { - E->get().rect.position.x = 0; + E.value.rect.position.x = 0; } break; case INLINE_ALIGN_TO_BOTTOM: { - E->get().rect.position.x = sd->descent; + E.value.rect.position.x = sd->descent; } break; } - switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) { + switch (E.value.inline_align & INLINE_ALIGN_IMAGE_MASK) { case INLINE_ALIGN_BOTTOM_TO: { - E->get().rect.position.x -= E->get().rect.size.x; + E.value.rect.position.x -= E.value.rect.size.x; } break; case INLINE_ALIGN_CENTER_TO: { - E->get().rect.position.x -= E->get().rect.size.x / 2; + E.value.rect.position.x -= E.value.rect.size.x / 2; } break; case INLINE_ALIGN_TOP_TO: { - //NOP + // NOP } break; } - full_ascent = MAX(full_ascent, -E->get().rect.position.x); - full_descent = MAX(full_descent, E->get().rect.position.x + E->get().rect.size.x); + full_ascent = MAX(full_ascent, -E.value.rect.position.x); + full_descent = MAX(full_descent, E.value.rect.position.x + E.value.rect.size.x); } } } @@ -3205,7 +3206,7 @@ bool TextServerAdvanced::shaped_text_resize_object(RID p_shaped, Variant p_key, } RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_length) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, RID()); MutexLock lock(sd->mutex); @@ -3281,11 +3282,11 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng Variant key; bool find_embedded = false; if (gl.count == 1) { - for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) { - if (E->get().pos == gl.start) { + for (const KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) { + if (E.value.pos == gl.start) { find_embedded = true; - key = E->key(); - new_sd->objects[key] = E->get(); + key = E.key; + new_sd->objects[key] = E.value; break; } } @@ -3310,8 +3311,7 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng } else if (new_sd->preserve_invalid || (new_sd->preserve_control && is_control(gl.index))) { // Glyph not found, replace with hex code box. if (new_sd->orientation == ORIENTATION_HORIZONTAL) { - new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.75f)); - new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).y * 0.25f)); + new_sd->ascent = MAX(new_sd->ascent, get_hex_code_box_size(gl.font_size, gl.index).y); } else { new_sd->ascent = MAX(new_sd->ascent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); new_sd->descent = MAX(new_sd->descent, Math::round(get_hex_code_box_size(gl.font_size, gl.index).x * 0.5f)); @@ -3326,66 +3326,66 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng } // Align embedded objects to baseline. - real_t full_ascent = new_sd->ascent; - real_t full_descent = new_sd->descent; - for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = new_sd->objects.front(); E; E = E->next()) { - if ((E->get().pos >= new_sd->start) && (E->get().pos < new_sd->end)) { + float full_ascent = new_sd->ascent; + float full_descent = new_sd->descent; + for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : new_sd->objects) { + if ((E.value.pos >= new_sd->start) && (E.value.pos < new_sd->end)) { if (sd->orientation == ORIENTATION_HORIZONTAL) { - switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) { + switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { case INLINE_ALIGN_TO_TOP: { - E->get().rect.position.y = -new_sd->ascent; + E.value.rect.position.y = -new_sd->ascent; } break; case INLINE_ALIGN_TO_CENTER: { - E->get().rect.position.y = (-new_sd->ascent + new_sd->descent) / 2; + E.value.rect.position.y = (-new_sd->ascent + new_sd->descent) / 2; } break; case INLINE_ALIGN_TO_BASELINE: { - E->get().rect.position.y = 0; + E.value.rect.position.y = 0; } break; case INLINE_ALIGN_TO_BOTTOM: { - E->get().rect.position.y = new_sd->descent; + E.value.rect.position.y = new_sd->descent; } break; } - switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) { + switch (E.value.inline_align & INLINE_ALIGN_IMAGE_MASK) { case INLINE_ALIGN_BOTTOM_TO: { - E->get().rect.position.y -= E->get().rect.size.y; + E.value.rect.position.y -= E.value.rect.size.y; } break; case INLINE_ALIGN_CENTER_TO: { - E->get().rect.position.y -= E->get().rect.size.y / 2; + E.value.rect.position.y -= E.value.rect.size.y / 2; } break; case INLINE_ALIGN_TOP_TO: { - //NOP + // NOP } break; } - full_ascent = MAX(full_ascent, -E->get().rect.position.y); - full_descent = MAX(full_descent, E->get().rect.position.y + E->get().rect.size.y); + full_ascent = MAX(full_ascent, -E.value.rect.position.y); + full_descent = MAX(full_descent, E.value.rect.position.y + E.value.rect.size.y); } else { - switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) { + switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { case INLINE_ALIGN_TO_TOP: { - E->get().rect.position.x = -new_sd->ascent; + E.value.rect.position.x = -new_sd->ascent; } break; case INLINE_ALIGN_TO_CENTER: { - E->get().rect.position.x = (-new_sd->ascent + new_sd->descent) / 2; + E.value.rect.position.x = (-new_sd->ascent + new_sd->descent) / 2; } break; case INLINE_ALIGN_TO_BASELINE: { - E->get().rect.position.x = 0; + E.value.rect.position.x = 0; } break; case INLINE_ALIGN_TO_BOTTOM: { - E->get().rect.position.x = new_sd->descent; + E.value.rect.position.x = new_sd->descent; } break; } - switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) { + switch (E.value.inline_align & INLINE_ALIGN_IMAGE_MASK) { case INLINE_ALIGN_BOTTOM_TO: { - E->get().rect.position.x -= E->get().rect.size.x; + E.value.rect.position.x -= E.value.rect.size.x; } break; case INLINE_ALIGN_CENTER_TO: { - E->get().rect.position.x -= E->get().rect.size.x / 2; + E.value.rect.position.x -= E.value.rect.size.x / 2; } break; case INLINE_ALIGN_TOP_TO: { - //NOP + // NOP } break; } - full_ascent = MAX(full_ascent, -E->get().rect.position.x); - full_descent = MAX(full_descent, E->get().rect.position.x + E->get().rect.size.x); + full_ascent = MAX(full_ascent, -E.value.rect.position.x); + full_descent = MAX(full_descent, E.value.rect.position.x + E.value.rect.size.x); } } } @@ -3398,15 +3398,15 @@ RID TextServerAdvanced::shaped_text_substr(RID p_shaped, int p_start, int p_leng } RID TextServerAdvanced::shaped_text_get_parent(RID p_shaped) const { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, RID()); MutexLock lock(sd->mutex); return sd->parent; } -real_t TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, real_t p_width, uint8_t /*JustificationFlag*/ p_jst_flags) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); +float TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags) { + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, 0.f); MutexLock lock(sd->mutex); @@ -3446,7 +3446,7 @@ real_t TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, real_t p_width } } - real_t justification_width; + float justification_width; if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) == JUSTIFICATION_CONSTRAIN_ELLIPSIS) { if (sd->overrun_trim_data.trim_pos >= 0) { start_pos = sd->overrun_trim_data.trim_pos; @@ -3486,7 +3486,7 @@ real_t TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, real_t p_width } if ((elongation_count > 0) && ((p_jst_flags & JUSTIFICATION_KASHIDA) == JUSTIFICATION_KASHIDA)) { - real_t delta_width_per_kashida = (p_width - justification_width) / elongation_count; + float delta_width_per_kashida = (p_width - justification_width) / elongation_count; for (int i = start_pos; i <= end_pos; i++) { Glyph &gl = sd->glyphs.write[i]; if (gl.count > 0) { @@ -3501,15 +3501,15 @@ real_t TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, real_t p_width } } } - real_t adv_remain = 0; + float adv_remain = 0; if ((space_count > 0) && ((p_jst_flags & JUSTIFICATION_WORD_BOUND) == JUSTIFICATION_WORD_BOUND)) { - real_t delta_width_per_space = (p_width - justification_width) / space_count; + float delta_width_per_space = (p_width - justification_width) / space_count; for (int i = start_pos; i <= end_pos; i++) { Glyph &gl = sd->glyphs.write[i]; if (gl.count > 0) { if ((gl.flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE) { - real_t old_adv = gl.advance; - real_t new_advance; + float old_adv = gl.advance; + float new_advance; if ((gl.flags & GRAPHEME_IS_VIRTUAL) == GRAPHEME_IS_VIRTUAL) { new_advance = MAX(gl.advance + delta_width_per_space, 0.f); } else { @@ -3541,8 +3541,8 @@ real_t TextServerAdvanced::shaped_text_fit_to_width(RID p_shaped, real_t p_width return sd->width; } -real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<real_t> &p_tab_stops) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); +float TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) { + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, 0.f); MutexLock lock(sd->mutex); @@ -3554,7 +3554,7 @@ real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<real } int tab_index = 0; - real_t off = 0.f; + float off = 0.f; int start, end, delta; if (sd->para_direction == DIRECTION_LTR) { @@ -3571,7 +3571,7 @@ real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<real for (int i = start; i != end; i += delta) { if ((gl[i].flags & GRAPHEME_IS_TAB) == GRAPHEME_IS_TAB) { - real_t tab_off = 0.f; + float tab_off = 0.f; while (tab_off <= off) { tab_off += p_tab_stops[tab_index]; tab_index++; @@ -3579,7 +3579,7 @@ real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<real tab_index = 0; } } - real_t old_adv = gl[i].advance; + float old_adv = gl[i].advance; gl[i].advance = tab_off - off; sd->width += gl[i].advance - old_adv; off = 0; @@ -3591,8 +3591,8 @@ real_t TextServerAdvanced::shaped_text_tab_align(RID p_shaped, const Vector<real return 0.f; } -void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, real_t p_width, uint8_t p_trim_flags) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped_line); +void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, float p_width, uint16_t p_trim_flags) { + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped_line); ERR_FAIL_COND_MSG(!sd, "ShapedTextDataAdvanced invalid."); MutexLock lock(sd->mutex); @@ -3600,6 +3600,7 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, re shaped_text_shape(p_shaped_line); } + sd->text_trimmed = false; sd->overrun_trim_data.ellipsis_glyph_buf.clear(); bool add_ellipsis = (p_trim_flags & OVERRUN_ADD_ELLIPSIS) == OVERRUN_ADD_ELLIPSIS; @@ -3633,7 +3634,7 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, re } int ell_min_characters = 6; - real_t width = sd->width; + float width = sd->width; bool is_rtl = sd->direction == DIRECTION_RTL || (sd->direction == DIRECTION_AUTO && sd->para_direction == DIRECTION_RTL); @@ -3689,7 +3690,7 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, re if (add_ellipsis && (ellipsis_pos > 0 || enforce_ellipsis)) { // Insert an additional space when cutting word bound for aesthetics. if (cut_per_word && (ellipsis_pos > 0)) { - TextServer::Glyph gl; + Glyph gl; gl.count = 1; gl.advance = whitespace_adv.x; gl.index = whitespace_gl_idx; @@ -3700,7 +3701,7 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, re sd->overrun_trim_data.ellipsis_glyph_buf.append(gl); } // Add ellipsis dots. - TextServer::Glyph gl; + Glyph gl; gl.count = 1; gl.repeat = 3; gl.advance = dot_adv.x; @@ -3717,16 +3718,40 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(RID p_shaped_line, re } } -TextServer::TrimData TextServerAdvanced::shaped_text_get_trim_data(RID p_shaped) const { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); - ERR_FAIL_COND_V_MSG(!sd, TrimData(), "ShapedTextDataAdvanced invalid."); +int TextServerAdvanced::shaped_text_get_trim_pos(RID p_shaped) const { + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextDataAdvanced invalid."); + + MutexLock lock(sd->mutex); + return sd->overrun_trim_data.trim_pos; +} + +int TextServerAdvanced::shaped_text_get_ellipsis_pos(RID p_shaped) const { + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V_MSG(!sd, -1, "ShapedTextDataAdvanced invalid."); + + MutexLock lock(sd->mutex); + return sd->overrun_trim_data.ellipsis_pos; +} + +const Glyph *TextServerAdvanced::shaped_text_get_ellipsis_glyphs(RID p_shaped) const { + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V_MSG(!sd, nullptr, "ShapedTextDataAdvanced invalid."); MutexLock lock(sd->mutex); - return sd->overrun_trim_data; + return sd->overrun_trim_data.ellipsis_glyph_buf.ptr(); +} + +int TextServerAdvanced::shaped_text_get_ellipsis_glyph_count(RID p_shaped) const { + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V_MSG(!sd, 0, "ShapedTextDataAdvanced invalid."); + + MutexLock lock(sd->mutex); + return sd->overrun_trim_data.ellipsis_glyph_buf.size(); } bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, false); MutexLock lock(sd->mutex); @@ -3809,14 +3834,19 @@ bool TextServerAdvanced::shaped_text_update_breaks(RID p_shaped) { if (is_whitespace(c)) { sd_glyphs[i].flags |= GRAPHEME_IS_BREAK_SOFT; } else { - TextServer::Glyph gl; + Glyph gl; gl.start = sd_glyphs[i].start; gl.end = sd_glyphs[i].end; gl.count = 1; gl.font_rid = sd_glyphs[i].font_rid; gl.font_size = sd_glyphs[i].font_size; gl.flags = GRAPHEME_IS_BREAK_SOFT | GRAPHEME_IS_VIRTUAL; - sd->glyphs.insert(i + sd_glyphs[i].count, gl); // Insert after. + if (sd->glyphs[i].flags & GRAPHEME_IS_RTL) { + gl.flags |= GRAPHEME_IS_RTL; + sd->glyphs.insert(i, gl); // Insert before. + } else { + sd->glyphs.insert(i + sd_glyphs[i].count, gl); // Insert after. + } // Update write pointer and size. sd_size = sd->glyphs.size(); @@ -3913,7 +3943,7 @@ _FORCE_INLINE_ int _generate_kashida_justification_opportunies(const String &p_d } bool TextServerAdvanced::shaped_text_update_justification_ops(RID p_shaped) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, false); MutexLock lock(sd->mutex); @@ -3985,7 +4015,7 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(RID p_shaped) { sd->glyphs.write[i].flags |= GRAPHEME_IS_ELONGATION; } else { if (sd->glyphs[i].font_rid != RID()) { - TextServer::Glyph gl = _shape_single_glyph(sd, 0x0640, HB_SCRIPT_ARABIC, HB_DIRECTION_RTL, sd->glyphs[i].font_rid, sd->glyphs[i].font_size); + Glyph gl = _shape_single_glyph(sd, 0x0640, HB_SCRIPT_ARABIC, HB_DIRECTION_RTL, sd->glyphs[i].font_rid, sd->glyphs[i].font_size); if ((gl.flags & GRAPHEME_IS_VALID) == GRAPHEME_IS_VALID) { gl.start = sd->glyphs[i].start; gl.end = sd->glyphs[i].end; @@ -4003,14 +4033,19 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(RID p_shaped) { } } } else if (!is_whitespace(c)) { - TextServer::Glyph gl; + Glyph gl; gl.start = sd->glyphs[i].start; gl.end = sd->glyphs[i].end; gl.count = 1; gl.font_rid = sd->glyphs[i].font_rid; gl.font_size = sd->glyphs[i].font_size; gl.flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_VIRTUAL; - sd->glyphs.insert(i + sd->glyphs[i].count, gl); // Insert after. + if (sd->glyphs[i].flags & GRAPHEME_IS_RTL) { + gl.flags |= GRAPHEME_IS_RTL; + sd->glyphs.insert(i, gl); // Insert before. + } else { + sd->glyphs.insert(i + sd->glyphs[i].count, gl); // Insert after. + } i += sd->glyphs[i].count; continue; } @@ -4023,9 +4058,9 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(RID p_shaped) { return sd->justification_ops_valid; } -TextServer::Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, RID p_font, int p_font_size) { +Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, RID p_font, int p_font_size) { hb_font_t *hb_font = _font_get_hb_handle(p_font, p_font_size); - ERR_FAIL_COND_V(hb_font == nullptr, TextServer::Glyph()); + ERR_FAIL_COND_V(hb_font == nullptr, Glyph()); hb_buffer_clear_contents(p_sd->hb_buffer); hb_buffer_set_direction(p_sd->hb_buffer, p_direction); @@ -4040,7 +4075,7 @@ TextServer::Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(p_sd->hb_buffer, &glyph_count); // Process glyphs. - TextServer::Glyph gl; + Glyph gl; if (p_direction == HB_DIRECTION_RTL || p_direction == HB_DIRECTION_BTT) { gl.flags |= TextServer::GRAPHEME_IS_RTL; @@ -4050,7 +4085,7 @@ TextServer::Glyph TextServerAdvanced::_shape_single_glyph(ShapedTextDataAdvanced gl.font_size = p_font_size; if (glyph_count > 0) { - real_t scale = font_get_scale(p_font, p_font_size); + float scale = font_get_scale(p_font, p_font_size); if (p_sd->orientation == ORIENTATION_HORIZONTAL) { gl.advance = Math::round(glyph_pos[0].x_advance / (64.0 / scale)); } else { @@ -4075,7 +4110,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star // Add fallback glyphs. for (int i = p_start; i < p_end; i++) { if (p_sd->preserve_invalid || (p_sd->preserve_control && is_control(p_sd->text[i]))) { - TextServer::Glyph gl; + Glyph gl; gl.start = i; gl.end = i + 1; gl.count = 1; @@ -4087,8 +4122,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star } if (p_sd->orientation == ORIENTATION_HORIZONTAL) { gl.advance = get_hex_code_box_size(fs, gl.index).x; - p_sd->ascent = MAX(p_sd->ascent, Math::round(get_hex_code_box_size(fs, gl.index).y * 0.75f)); - p_sd->descent = MAX(p_sd->descent, Math::round(get_hex_code_box_size(fs, gl.index).y * 0.25f)); + p_sd->ascent = MAX(p_sd->ascent, get_hex_code_box_size(fs, gl.index).y); } else { gl.advance = get_hex_code_box_size(fs, gl.index).y; p_sd->ascent = MAX(p_sd->ascent, Math::round(get_hex_code_box_size(fs, gl.index).x * 0.5f)); @@ -4142,7 +4176,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star // Process glyphs. if (glyph_count > 0) { - TextServer::Glyph *w = (TextServer::Glyph *)memalloc(glyph_count * sizeof(TextServer::Glyph)); + Glyph *w = (Glyph *)memalloc(glyph_count * sizeof(Glyph)); int end = (p_direction == HB_DIRECTION_RTL || p_direction == HB_DIRECTION_BTT) ? p_end : 0; uint32_t last_cluster_id = UINT32_MAX; @@ -4159,7 +4193,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star } } if (p_direction == HB_DIRECTION_RTL || p_direction == HB_DIRECTION_BTT) { - w[last_cluster_index].flags |= TextServer::GRAPHEME_IS_RTL; + w[last_cluster_index].flags |= GRAPHEME_IS_RTL; } if (last_cluster_valid) { w[last_cluster_index].flags |= GRAPHEME_IS_VALID; @@ -4171,8 +4205,8 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star last_cluster_id = glyph_info[i].cluster; - TextServer::Glyph &gl = w[i]; - gl = TextServer::Glyph(); + Glyph &gl = w[i]; + gl = Glyph(); gl.start = glyph_info[i].cluster; gl.end = end; @@ -4181,9 +4215,13 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star gl.font_rid = p_fonts[p_fb_index]; gl.font_size = fs; + if (glyph_info[i].mask & HB_GLYPH_FLAG_DEFINED) { + gl.flags |= GRAPHEME_IS_CONNECTED; + } + gl.index = glyph_info[i].codepoint; if (gl.index != 0) { - real_t scale = font_get_scale(f, fs); + float scale = font_get_scale(f, fs); if (p_sd->orientation == ORIENTATION_HORIZONTAL) { gl.advance = Math::round(glyph_pos[i].x_advance / (64.0 / scale)); } else { @@ -4199,9 +4237,9 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star } if (p_sd->preserve_control) { - last_cluster_valid = last_cluster_valid && ((glyph_info[i].codepoint != 0) || is_whitespace(p_sd->text[glyph_info[i].cluster]) || is_linebreak(p_sd->text[glyph_info[i].cluster])); + last_cluster_valid = last_cluster_valid && ((glyph_info[i].codepoint != 0) || (p_sd->text[glyph_info[i].cluster] == 0x0009) || (u_isblank(p_sd->text[glyph_info[i].cluster]) && (gl.advance != 0)) || (!u_isblank(p_sd->text[glyph_info[i].cluster]) && is_linebreak(p_sd->text[glyph_info[i].cluster]))); } else { - last_cluster_valid = last_cluster_valid && ((glyph_info[i].codepoint != 0) || !u_isgraph(p_sd->text[glyph_info[i].cluster])); + last_cluster_valid = last_cluster_valid && ((glyph_info[i].codepoint != 0) || (p_sd->text[glyph_info[i].cluster] == 0x0009) || (u_isblank(p_sd->text[glyph_info[i].cluster]) && (gl.advance != 0)) || (!u_isblank(p_sd->text[glyph_info[i].cluster]) && !u_isgraph(p_sd->text[glyph_info[i].cluster]))); } } if (p_direction == HB_DIRECTION_LTR || p_direction == HB_DIRECTION_TTB) { @@ -4211,7 +4249,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star } w[last_cluster_index].count = glyph_count - last_cluster_index; if (p_direction == HB_DIRECTION_RTL || p_direction == HB_DIRECTION_BTT) { - w[last_cluster_index].flags |= TextServer::GRAPHEME_IS_RTL; + w[last_cluster_index].flags |= GRAPHEME_IS_RTL; } if (last_cluster_valid) { w[last_cluster_index].flags |= GRAPHEME_IS_VALID; @@ -4261,7 +4299,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_star } bool TextServerAdvanced::shaped_text_shape(RID p_shaped) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, false); MutexLock lock(sd->mutex); @@ -4423,65 +4461,65 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) { } // Align embedded objects to baseline. - real_t full_ascent = sd->ascent; - real_t full_descent = sd->descent; - for (Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) { + float full_ascent = sd->ascent; + float full_descent = sd->descent; + for (KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) { if (sd->orientation == ORIENTATION_HORIZONTAL) { - switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) { + switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { case INLINE_ALIGN_TO_TOP: { - E->get().rect.position.y = -sd->ascent; + E.value.rect.position.y = -sd->ascent; } break; case INLINE_ALIGN_TO_CENTER: { - E->get().rect.position.y = (-sd->ascent + sd->descent) / 2; + E.value.rect.position.y = (-sd->ascent + sd->descent) / 2; } break; case INLINE_ALIGN_TO_BASELINE: { - E->get().rect.position.y = 0; + E.value.rect.position.y = 0; } break; case INLINE_ALIGN_TO_BOTTOM: { - E->get().rect.position.y = sd->descent; + E.value.rect.position.y = sd->descent; } break; } - switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) { + switch (E.value.inline_align & INLINE_ALIGN_IMAGE_MASK) { case INLINE_ALIGN_BOTTOM_TO: { - E->get().rect.position.y -= E->get().rect.size.y; + E.value.rect.position.y -= E.value.rect.size.y; } break; case INLINE_ALIGN_CENTER_TO: { - E->get().rect.position.y -= E->get().rect.size.y / 2; + E.value.rect.position.y -= E.value.rect.size.y / 2; } break; case INLINE_ALIGN_TOP_TO: { - //NOP + // NOP } break; } - full_ascent = MAX(full_ascent, -E->get().rect.position.y); - full_descent = MAX(full_descent, E->get().rect.position.y + E->get().rect.size.y); + full_ascent = MAX(full_ascent, -E.value.rect.position.y); + full_descent = MAX(full_descent, E.value.rect.position.y + E.value.rect.size.y); } else { - switch (E->get().inline_align & INLINE_ALIGN_TEXT_MASK) { + switch (E.value.inline_align & INLINE_ALIGN_TEXT_MASK) { case INLINE_ALIGN_TO_TOP: { - E->get().rect.position.x = -sd->ascent; + E.value.rect.position.x = -sd->ascent; } break; case INLINE_ALIGN_TO_CENTER: { - E->get().rect.position.x = (-sd->ascent + sd->descent) / 2; + E.value.rect.position.x = (-sd->ascent + sd->descent) / 2; } break; case INLINE_ALIGN_TO_BASELINE: { - E->get().rect.position.x = 0; + E.value.rect.position.x = 0; } break; case INLINE_ALIGN_TO_BOTTOM: { - E->get().rect.position.x = sd->descent; + E.value.rect.position.x = sd->descent; } break; } - switch (E->get().inline_align & INLINE_ALIGN_IMAGE_MASK) { + switch (E.value.inline_align & INLINE_ALIGN_IMAGE_MASK) { case INLINE_ALIGN_BOTTOM_TO: { - E->get().rect.position.x -= E->get().rect.size.x; + E.value.rect.position.x -= E.value.rect.size.x; } break; case INLINE_ALIGN_CENTER_TO: { - E->get().rect.position.x -= E->get().rect.size.x / 2; + E.value.rect.position.x -= E.value.rect.size.x / 2; } break; case INLINE_ALIGN_TOP_TO: { - //NOP + // NOP } break; } - full_ascent = MAX(full_ascent, -E->get().rect.position.x); - full_descent = MAX(full_descent, E->get().rect.position.x + E->get().rect.size.x); + full_ascent = MAX(full_ascent, -E.value.rect.position.x); + full_descent = MAX(full_descent, E.value.rect.position.x + E.value.rect.size.x); } } sd->ascent = full_ascent; @@ -4491,35 +4529,38 @@ bool TextServerAdvanced::shaped_text_shape(RID p_shaped) { } bool TextServerAdvanced::shaped_text_is_ready(RID p_shaped) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, false); MutexLock lock(sd->mutex); return sd->valid; } -Vector<TextServer::Glyph> TextServerAdvanced::shaped_text_get_glyphs(RID p_shaped) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); - ERR_FAIL_COND_V(!sd, Vector<TextServer::Glyph>()); +const Glyph *TextServerAdvanced::shaped_text_get_glyphs(RID p_shaped) const { + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V(!sd, nullptr); MutexLock lock(sd->mutex); if (!sd->valid) { const_cast<TextServerAdvanced *>(this)->shaped_text_shape(p_shaped); } - return sd->glyphs; + return sd->glyphs.ptr(); } -Vector2i TextServerAdvanced::shaped_text_get_range(RID p_shaped) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); - ERR_FAIL_COND_V(!sd, Vector2i()); +int TextServerAdvanced::shaped_text_get_glyph_count(RID p_shaped) const { + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V(!sd, 0); MutexLock lock(sd->mutex); - return Vector2(sd->start, sd->end); + if (!sd->valid) { + const_cast<TextServerAdvanced *>(this)->shaped_text_shape(p_shaped); + } + return sd->glyphs.size(); } -Vector<TextServer::Glyph> TextServerAdvanced::shaped_text_sort_logical(RID p_shaped) { - ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); - ERR_FAIL_COND_V(!sd, Vector<TextServer::Glyph>()); +const Glyph *TextServerAdvanced::shaped_text_sort_logical(RID p_shaped) { + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V(!sd, nullptr); MutexLock lock(sd->mutex); if (!sd->valid) { @@ -4528,28 +4569,36 @@ Vector<TextServer::Glyph> TextServerAdvanced::shaped_text_sort_logical(RID p_sha if (!sd->sort_valid) { sd->glyphs_logical = sd->glyphs; - sd->glyphs_logical.sort_custom<TextServer::GlyphCompare>(); + sd->glyphs_logical.sort_custom<GlyphCompare>(); sd->sort_valid = true; } - return sd->glyphs_logical; + return sd->glyphs_logical.ptr(); +} + +Vector2i TextServerAdvanced::shaped_text_get_range(RID p_shaped) const { + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V(!sd, Vector2i()); + + MutexLock lock(sd->mutex); + return Vector2(sd->start, sd->end); } Array TextServerAdvanced::shaped_text_get_objects(RID p_shaped) const { Array ret; - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, ret); MutexLock lock(sd->mutex); - for (const Map<Variant, ShapedTextData::EmbeddedObject>::Element *E = sd->objects.front(); E; E = E->next()) { - ret.push_back(E->key()); + for (const KeyValue<Variant, ShapedTextData::EmbeddedObject> &E : sd->objects) { + ret.push_back(E.key); } return ret; } Rect2 TextServerAdvanced::shaped_text_get_object_rect(RID p_shaped, Variant p_key) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, Rect2()); MutexLock lock(sd->mutex); @@ -4561,7 +4610,7 @@ Rect2 TextServerAdvanced::shaped_text_get_object_rect(RID p_shaped, Variant p_ke } Size2 TextServerAdvanced::shaped_text_get_size(RID p_shaped) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, Size2()); MutexLock lock(sd->mutex); @@ -4575,8 +4624,8 @@ Size2 TextServerAdvanced::shaped_text_get_size(RID p_shaped) const { } } -real_t TextServerAdvanced::shaped_text_get_ascent(RID p_shaped) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); +float TextServerAdvanced::shaped_text_get_ascent(RID p_shaped) const { + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, 0.f); MutexLock lock(sd->mutex); @@ -4586,8 +4635,8 @@ real_t TextServerAdvanced::shaped_text_get_ascent(RID p_shaped) const { return sd->ascent; } -real_t TextServerAdvanced::shaped_text_get_descent(RID p_shaped) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); +float TextServerAdvanced::shaped_text_get_descent(RID p_shaped) const { + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, 0.f); MutexLock lock(sd->mutex); @@ -4597,8 +4646,8 @@ real_t TextServerAdvanced::shaped_text_get_descent(RID p_shaped) const { return sd->descent; } -real_t TextServerAdvanced::shaped_text_get_width(RID p_shaped) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); +float TextServerAdvanced::shaped_text_get_width(RID p_shaped) const { + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, 0.f); MutexLock lock(sd->mutex); @@ -4608,8 +4657,8 @@ real_t TextServerAdvanced::shaped_text_get_width(RID p_shaped) const { return (sd->text_trimmed ? sd->width_trimmed : sd->width); } -real_t TextServerAdvanced::shaped_text_get_underline_position(RID p_shaped) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); +float TextServerAdvanced::shaped_text_get_underline_position(RID p_shaped) const { + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, 0.f); MutexLock lock(sd->mutex); @@ -4620,8 +4669,8 @@ real_t TextServerAdvanced::shaped_text_get_underline_position(RID p_shaped) cons return sd->upos; } -real_t TextServerAdvanced::shaped_text_get_underline_thickness(RID p_shaped) const { - const ShapedTextDataAdvanced *sd = shaped_owner.getornull(p_shaped); +float TextServerAdvanced::shaped_text_get_underline_thickness(RID p_shaped) const { + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, 0.f); MutexLock lock(sd->mutex); @@ -4632,31 +4681,187 @@ real_t TextServerAdvanced::shaped_text_get_underline_thickness(RID p_shaped) con return sd->uthk; } -struct num_system_data { - String lang; - String digits; - String percent_sign; - String exp; -}; +void TextServerAdvanced::_insert_num_systems_lang() { + // Eastern Arabic numerals. + { + NumSystemData ar; + ar.lang.insert(StringName("ar")); // Arabic + ar.lang.insert(StringName("ar_AE")); + ar.lang.insert(StringName("ar_BH")); + ar.lang.insert(StringName("ar_DJ")); + ar.lang.insert(StringName("ar_EG")); + ar.lang.insert(StringName("ar_ER")); + ar.lang.insert(StringName("ar_IL")); + ar.lang.insert(StringName("ar_IQ")); + ar.lang.insert(StringName("ar_JO")); + ar.lang.insert(StringName("ar_KM")); + ar.lang.insert(StringName("ar_KW")); + ar.lang.insert(StringName("ar_LB")); + ar.lang.insert(StringName("ar_MR")); + ar.lang.insert(StringName("ar_OM")); + ar.lang.insert(StringName("ar_PS")); + ar.lang.insert(StringName("ar_QA")); + ar.lang.insert(StringName("ar_SA")); + ar.lang.insert(StringName("ar_SD")); + ar.lang.insert(StringName("ar_SO")); + ar.lang.insert(StringName("ar_SS")); + ar.lang.insert(StringName("ar_SY")); + ar.lang.insert(StringName("ar_TD")); + ar.lang.insert(StringName("ar_YE")); + ar.lang.insert(StringName("ckb")); // Central Kurdish + ar.lang.insert(StringName("ckb_IQ")); + ar.lang.insert(StringName("ckb_IR")); + ar.lang.insert(StringName("sd")); // Sindhi + ar.lang.insert(StringName("sd_PK")); + ar.lang.insert(StringName("sd_Arab")); + ar.lang.insert(StringName("sd_Arab_PK")); + ar.digits = U"٠١٢٣٤٥٦٧٨٩٫"; + ar.percent_sign = U"٪"; + ar.exp = U"اس"; + num_systems.push_back(ar); + } + + // Persian and Urdu numerals. + { + NumSystemData pr; + pr.lang.insert(StringName("fa")); // Persian + pr.lang.insert(StringName("fa_AF")); + pr.lang.insert(StringName("fa_IR")); + pr.lang.insert(StringName("ks")); // Kashmiri + pr.lang.insert(StringName("ks_IN")); + pr.lang.insert(StringName("ks_Arab")); + pr.lang.insert(StringName("ks_Arab_IN")); + pr.lang.insert(StringName("lrc")); // Northern Luri + pr.lang.insert(StringName("lrc_IQ")); + pr.lang.insert(StringName("lrc_IR")); + pr.lang.insert(StringName("mzn")); // Mazanderani + pr.lang.insert(StringName("mzn_IR")); + pr.lang.insert(StringName("pa_PK")); // Panjabi + pr.lang.insert(StringName("pa_Arab")); + pr.lang.insert(StringName("pa_Arab_PK")); + pr.lang.insert(StringName("ps")); // Pushto + pr.lang.insert(StringName("ps_AF")); + pr.lang.insert(StringName("ps_PK")); + pr.lang.insert(StringName("ur_IN")); // Urdu + pr.lang.insert(StringName("uz_AF")); // Uzbek + pr.lang.insert(StringName("uz_Arab")); + pr.lang.insert(StringName("uz_Arab_AF")); + pr.digits = U"۰۱۲۳۴۵۶۷۸۹٫"; + pr.percent_sign = U"٪"; + pr.exp = U"اس"; + num_systems.push_back(pr); + } + + // Bengali numerals. + { + NumSystemData bn; + bn.lang.insert(StringName("as")); // Assamese + bn.lang.insert(StringName("as_IN")); + bn.lang.insert(StringName("bn")); // Bengali + bn.lang.insert(StringName("bn_BD")); + bn.lang.insert(StringName("bn_IN")); + bn.lang.insert(StringName("mni")); // Manipuri + bn.lang.insert(StringName("mni_IN")); + bn.lang.insert(StringName("mni_Beng")); + bn.lang.insert(StringName("mni_Beng_IN")); + bn.digits = U"০১২৩৪৫৬৭৮৯."; + bn.percent_sign = U"%"; + bn.exp = U"e"; + num_systems.push_back(bn); + } + + // Devanagari numerals. + { + NumSystemData mr; + mr.lang.insert(StringName("mr")); // Marathi + mr.lang.insert(StringName("mr_IN")); + mr.lang.insert(StringName("ne")); // Nepali + mr.lang.insert(StringName("ne_IN")); + mr.lang.insert(StringName("ne_NP")); + mr.lang.insert(StringName("sa")); // Sanskrit + mr.lang.insert(StringName("sa_IN")); + mr.digits = U"०१२३४५६७८९."; + mr.percent_sign = U"%"; + mr.exp = U"e"; + num_systems.push_back(mr); + } + + // Dzongkha numerals. + { + NumSystemData dz; + dz.lang.insert(StringName("dz")); // Dzongkha + dz.lang.insert(StringName("dz_BT")); + dz.digits = U"༠༡༢༣༤༥༦༧༨༩."; + dz.percent_sign = U"%"; + dz.exp = U"e"; + num_systems.push_back(dz); + } -static num_system_data num_systems[]{ - { "ar,ar_AR,ar_BH,ar_DJ,ar_EG,ar_ER,ar_IL,ar_IQ,ar_JO,ar_KM,ar_KW,ar_LB,ar_MR,ar_OM,ar_PS,ar_QA,ar_SA,ar_SD,ar_SO,ar_SS,ar_SY,ar_TD,ar_YE", U"٠١٢٣٤٥٦٧٨٩٫", U"٪", U"اس" }, - { "fa,ks,pa_Arab,ps,ug,ur_IN,ur,uz_Arab", U"۰۱۲۳۴۵۶۷۸۹٫", U"٪", U"اس" }, - { "as,bn,mni", U"০১২৩৪৫৬৭৮৯.", U"%", U"e" }, - { "mr,ne", U"०१२३४५६७८९.", U"%", U"e" }, - { "dz", U"༠༡༢༣༤༥༦༧༨༩.", U"%", U"e" }, - { "sat", U"᱐᱑᱒᱓᱔᱕᱖᱗᱘᱙.", U"%", U"e" }, - { "my", U"၀၁၂၃၄၅၆၇၈၉.", U"%", U"e" }, - { String(), String(), String(), String() }, -}; + // Santali numerals. + { + NumSystemData sat; + sat.lang.insert(StringName("sat")); // Santali + sat.lang.insert(StringName("sat_IN")); + sat.lang.insert(StringName("sat_Olck")); + sat.lang.insert(StringName("sat_Olck_IN")); + sat.digits = U"᱐᱑᱒᱓᱔᱕᱖᱗᱘᱙."; + sat.percent_sign = U"%"; + sat.exp = U"e"; + num_systems.push_back(sat); + } + + // Burmese numerals. + { + NumSystemData my; + my.lang.insert(StringName("my")); // Burmese + my.lang.insert(StringName("my_MM")); + my.digits = U"၀၁၂၃၄၅၆၇၈၉."; + my.percent_sign = U"%"; + my.exp = U"e"; + num_systems.push_back(my); + } + + // Chakma numerals. + { + NumSystemData ccp; + ccp.lang.insert(StringName("ccp")); // Chakma + ccp.lang.insert(StringName("ccp_BD")); + ccp.lang.insert(StringName("ccp_IN")); + ccp.digits = U"𑄶𑄷𑄸𑄹𑄺𑄻𑄼𑄽𑄾𑄿."; + ccp.percent_sign = U"%"; + ccp.exp = U"e"; + num_systems.push_back(ccp); + } + + // Adlam numerals. + { + NumSystemData ff; + ff.lang.insert(StringName("ff")); // Fulah + ff.lang.insert(StringName("ff_Adlm_BF")); + ff.lang.insert(StringName("ff_Adlm_CM")); + ff.lang.insert(StringName("ff_Adlm_GH")); + ff.lang.insert(StringName("ff_Adlm_GM")); + ff.lang.insert(StringName("ff_Adlm_GN")); + ff.lang.insert(StringName("ff_Adlm_GW")); + ff.lang.insert(StringName("ff_Adlm_LR")); + ff.lang.insert(StringName("ff_Adlm_MR")); + ff.lang.insert(StringName("ff_Adlm_NE")); + ff.lang.insert(StringName("ff_Adlm_NG")); + ff.lang.insert(StringName("ff_Adlm_SL")); + ff.lang.insert(StringName("ff_Adlm_SN")); + ff.digits = U"𞥐𞥑𞥒𞥓𞥔𞥕𞥖𞥗𞥘𞥙."; + ff.percent_sign = U"%"; + ff.exp = U"e"; + num_systems.push_back(ff); + } +} String TextServerAdvanced::format_number(const String &p_string, const String &p_language) const { - String lang = (p_language == "") ? TranslationServer::get_singleton()->get_tool_locale() : p_language; + const StringName lang = (p_language == "") ? TranslationServer::get_singleton()->get_tool_locale() : p_language; String res = p_string; - for (int i = 0; num_systems[i].lang != String(); i++) { - Vector<String> langs = num_systems[i].lang.split(","); - if (langs.has(lang)) { + for (int i = 0; i < num_systems.size(); i++) { + if (num_systems[i].lang.has(lang)) { if (num_systems[i].digits == String()) { return p_string; } @@ -4677,12 +4882,11 @@ String TextServerAdvanced::format_number(const String &p_string, const String &p } String TextServerAdvanced::parse_number(const String &p_string, const String &p_language) const { - String lang = (p_language == "") ? TranslationServer::get_singleton()->get_tool_locale() : p_language; + const StringName lang = (p_language == "") ? TranslationServer::get_singleton()->get_tool_locale() : p_language; String res = p_string; - for (int i = 0; num_systems[i].lang != String(); i++) { - Vector<String> langs = num_systems[i].lang.split(","); - if (langs.has(lang)) { + for (int i = 0; i < num_systems.size(); i++) { + if (num_systems[i].lang.has(lang)) { if (num_systems[i].digits == String()) { return p_string; } @@ -4706,11 +4910,10 @@ String TextServerAdvanced::parse_number(const String &p_string, const String &p_ } String TextServerAdvanced::percent_sign(const String &p_language) const { - String lang = (p_language == "") ? TranslationServer::get_singleton()->get_tool_locale() : p_language; + const StringName lang = (p_language == "") ? TranslationServer::get_singleton()->get_tool_locale() : p_language; - for (int i = 0; num_systems[i].lang != String(); i++) { - Vector<String> langs = num_systems[i].lang.split(","); - if (langs.has(lang)) { + for (int i = 0; i < num_systems.size(); i++) { + if (num_systems[i].lang.has(lang)) { if (num_systems[i].percent_sign == String()) { return "%"; } @@ -4720,21 +4923,14 @@ String TextServerAdvanced::percent_sign(const String &p_language) const { return "%"; } -TextServer *TextServerAdvanced::create_func(Error &r_error, void *p_user_data) { - r_error = OK; - return memnew(TextServerAdvanced()); -} - -void TextServerAdvanced::register_server() { - TextServerManager::register_create_function(interface_name, interface_features, create_func, nullptr); -} - TextServerAdvanced::TextServerAdvanced() { - hb_bmp_create_font_funcs(); + _insert_num_systems_lang(); + _insert_feature_sets(); + _bmp_create_font_funcs(); } TextServerAdvanced::~TextServerAdvanced() { - hb_bmp_free_font_funcs(); + _bmp_free_font_funcs(); if (library != nullptr) { FT_Done_FreeType(library); } diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 5989035800..333b68e074 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -79,6 +79,19 @@ class TextServerAdvanced : public TextServer { static String interface_name; static uint32_t interface_features; + struct NumSystemData { + Set<StringName> lang; + String digits; + String percent_sign; + String exp; + }; + + Vector<NumSystemData> num_systems; + Map<StringName, int32_t> feature_sets; + + void _insert_num_systems_lang(); + void _insert_feature_sets(); + // ICU support data. uint8_t *icu_data = nullptr; @@ -115,12 +128,12 @@ class TextServerAdvanced : public TextServer { }; struct FontDataForSizeAdvanced { - real_t ascent = 0.f; - real_t descent = 0.f; - real_t underline_position = 0.f; - real_t underline_thickness = 0.f; - real_t scale = 1.f; - real_t oversampling = 1.f; + float ascent = 0.f; + float descent = 0.f; + float underline_position = 0.f; + float underline_thickness = 0.f; + float scale = 1.f; + float oversampling = 1.f; int spacing_glyph = 0; int spacing_space = 0; @@ -161,7 +174,7 @@ class TextServerAdvanced : public TextServer { bool force_autohinter = false; TextServer::Hinting hinting = TextServer::HINTING_LIGHT; Dictionary variation_coordinates; - real_t oversampling = 0.f; + float oversampling = 0.f; Map<Vector2i, FontDataForSizeAdvanced *> cache; @@ -245,38 +258,37 @@ class TextServerAdvanced : public TextServer { // Common data. - real_t oversampling = 1.f; + float oversampling = 1.f; mutable RID_PtrOwner<FontDataAdvanced> font_owner; mutable RID_PtrOwner<ShapedTextDataAdvanced> shaped_owner; int _convert_pos(const ShapedTextDataAdvanced *p_sd, int p_pos) const; int _convert_pos_inv(const ShapedTextDataAdvanced *p_sd, int p_pos) const; void _shape_run(ShapedTextDataAdvanced *p_sd, int32_t p_start, int32_t p_end, hb_script_t p_script, hb_direction_t p_direction, Vector<RID> p_fonts, int p_span, int p_fb_index); - TextServer::Glyph _shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, RID p_font, int p_font_size); + Glyph _shape_single_glyph(ShapedTextDataAdvanced *p_sd, char32_t p_char, hb_script_t p_script, hb_direction_t p_direction, RID p_font, int p_font_size); // HarfBuzz bitmap font interface. static hb_font_funcs_t *funcs; - struct hb_bmp_font_t { + struct bmp_font_t { TextServerAdvanced::FontDataForSizeAdvanced *face = nullptr; bool unref = false; /* Whether to destroy bm_face when done. */ }; - static hb_bmp_font_t *_hb_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref); - static void _hb_bmp_font_destroy(void *p_data); - static hb_bool_t hb_bmp_get_nominal_glyph(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_unicode, hb_codepoint_t *r_glyph, void *p_user_data); - static hb_position_t hb_bmp_get_glyph_h_advance(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, void *p_user_data); - static hb_position_t hb_bmp_get_glyph_v_advance(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, void *p_user_data); - static hb_position_t hb_bmp_get_glyph_h_kerning(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_left_glyph, hb_codepoint_t p_right_glyph, void *p_user_data); - static hb_position_t hb_bmp_get_glyph_v_kerning(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_left_glyph, hb_codepoint_t p_right_glyph, void *p_user_data); - static hb_bool_t hb_bmp_get_glyph_v_origin(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, hb_position_t *r_x, hb_position_t *r_y, void *p_user_data); - static hb_bool_t hb_bmp_get_glyph_extents(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, hb_glyph_extents_t *r_extents, void *p_user_data); - static hb_bool_t hb_bmp_get_font_h_extents(hb_font_t *p_font, void *p_font_data, hb_font_extents_t *r_metrics, void *p_user_data); - static void hb_bmp_create_font_funcs(); - static void hb_bmp_free_font_funcs(); - static void _hb_bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref); - static hb_font_t *hb_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, hb_destroy_func_t p_destroy); + static bmp_font_t *_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref); + static void _bmp_font_destroy(void *p_data); + static hb_bool_t _bmp_get_nominal_glyph(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_unicode, hb_codepoint_t *r_glyph, void *p_user_data); + static hb_position_t _bmp_get_glyph_h_advance(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, void *p_user_data); + static hb_position_t _bmp_get_glyph_v_advance(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, void *p_user_data); + static hb_position_t _bmp_get_glyph_h_kerning(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_left_glyph, hb_codepoint_t p_right_glyph, void *p_user_data); + static hb_bool_t _bmp_get_glyph_v_origin(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, hb_position_t *r_x, hb_position_t *r_y, void *p_user_data); + static hb_bool_t _bmp_get_glyph_extents(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, hb_glyph_extents_t *r_extents, void *p_user_data); + static hb_bool_t _bmp_get_font_h_extents(hb_font_t *p_font, void *p_font_data, hb_font_extents_t *r_metrics, void *p_user_data); + static void _bmp_create_font_funcs(); + static void _bmp_free_font_funcs(); + static void _bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref); + static hb_font_t *_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, hb_destroy_func_t p_destroy); protected: static void _bind_methods(){}; @@ -285,20 +297,19 @@ protected: void invalidate(ShapedTextDataAdvanced *p_shaped); public: - virtual bool has_feature(Feature p_feature) override; + virtual bool has_feature(Feature p_feature) const override; virtual String get_name() const override; + virtual uint32_t get_features() const override; virtual void free(RID p_rid) override; virtual bool has(RID p_rid) override; virtual bool load_support_data(const String &p_filename) override; -#ifdef TOOLS_ENABLED - virtual String get_support_data_filename() override { return _MKSTR(ICU_DATA_NAME); }; - virtual String get_support_data_info() override { return String("ICU break iteration data (") + _MKSTR(ICU_DATA_NAME) + String(")."); }; - virtual bool save_support_data(const String &p_filename) override; -#endif + virtual String get_support_data_filename() const override; + virtual String get_support_data_info() const override; + virtual bool save_support_data(const String &p_filename) const override; - virtual bool is_locale_right_to_left(const String &p_locale) override; + virtual bool is_locale_right_to_left(const String &p_locale) const override; virtual int32_t name_to_tag(const String &p_name) const override; virtual String tag_to_name(int32_t p_tag) const override; @@ -333,8 +344,8 @@ public: virtual void font_set_variation_coordinates(RID p_font_rid, const Dictionary &p_variation_coordinates) override; virtual Dictionary font_get_variation_coordinates(RID p_font_rid) const override; - virtual void font_set_oversampling(RID p_font_rid, real_t p_oversampling) override; - virtual real_t font_get_oversampling(RID p_font_rid) const override; + virtual void font_set_oversampling(RID p_font_rid, float p_oversampling) override; + virtual float font_get_oversampling(RID p_font_rid) const override; virtual Array font_get_size_cache_list(RID p_font_rid) const override; virtual void font_clear_size_cache(RID p_font_rid) override; @@ -342,20 +353,20 @@ public: hb_font_t *_font_get_hb_handle(RID p_font, int p_font_size) const; - virtual void font_set_ascent(RID p_font_rid, int p_size, real_t p_ascent) override; - virtual real_t font_get_ascent(RID p_font_rid, int p_size) const override; + virtual void font_set_ascent(RID p_font_rid, int p_size, float p_ascent) override; + virtual float font_get_ascent(RID p_font_rid, int p_size) const override; - virtual void font_set_descent(RID p_font_rid, int p_size, real_t p_descent) override; - virtual real_t font_get_descent(RID p_font_rid, int p_size) const override; + virtual void font_set_descent(RID p_font_rid, int p_size, float p_descent) override; + virtual float font_get_descent(RID p_font_rid, int p_size) const override; - virtual void font_set_underline_position(RID p_font_rid, int p_size, real_t p_underline_position) override; - virtual real_t font_get_underline_position(RID p_font_rid, int p_size) const override; + virtual void font_set_underline_position(RID p_font_rid, int p_size, float p_underline_position) override; + virtual float font_get_underline_position(RID p_font_rid, int p_size) const override; - virtual void font_set_underline_thickness(RID p_font_rid, int p_size, real_t p_underline_thickness) override; - virtual real_t font_get_underline_thickness(RID p_font_rid, int p_size) const override; + virtual void font_set_underline_thickness(RID p_font_rid, int p_size, float p_underline_thickness) override; + virtual float font_get_underline_thickness(RID p_font_rid, int p_size) const override; - virtual void font_set_scale(RID p_font_rid, int p_size, real_t p_scale) override; - virtual real_t font_get_scale(RID p_font_rid, int p_size) const override; + virtual void font_set_scale(RID p_font_rid, int p_size, float p_scale) override; + virtual float font_get_scale(RID p_font_rid, int p_size) const override; virtual void font_set_spacing(RID p_font_rid, int p_size, SpacingType p_spacing, int p_value) override; virtual int font_get_spacing(RID p_font_rid, int p_size, SpacingType p_spacing) const override; @@ -389,7 +400,7 @@ public: virtual int font_get_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph) const override; virtual void font_set_glyph_texture_idx(RID p_font_rid, const Vector2i &p_size, int32_t p_glyph, int p_texture_idx) override; - virtual bool font_get_glyph_contours(RID p_font, int p_size, int32_t p_index, Vector<Vector3> &r_points, Vector<int32_t> &r_contours, bool &r_orientation) const override; + virtual Dictionary font_get_glyph_contours(RID p_font, int p_size, int32_t p_index) const override; virtual Array font_get_kerning_list(RID p_font_rid, int p_size) const override; virtual void font_clear_kerning_map(RID p_font_rid, int p_size) override; @@ -424,8 +435,8 @@ public: virtual Dictionary font_supported_feature_list(RID p_font_rid) const override; virtual Dictionary font_supported_variation_list(RID p_font_rid) const override; - virtual real_t font_get_global_oversampling() const override; - virtual void font_set_global_oversampling(real_t p_oversampling) override; + virtual float font_get_global_oversampling() const override; + virtual void font_set_global_oversampling(float p_oversampling) override; /* Shaped text buffer interface */ @@ -436,7 +447,7 @@ public: virtual void shaped_text_set_direction(RID p_shaped, Direction p_direction = DIRECTION_AUTO) override; virtual Direction shaped_text_get_direction(RID p_shaped) const override; - virtual void shaped_text_set_bidi_override(RID p_shaped, const Vector<Vector2i> &p_override) override; + virtual void shaped_text_set_bidi_override(RID p_shaped, const Array &p_override) override; virtual void shaped_text_set_orientation(RID p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override; virtual Orientation shaped_text_get_orientation(RID p_shaped) const override; @@ -454,41 +465,42 @@ public: virtual RID shaped_text_substr(RID p_shaped, int p_start, int p_length) const override; virtual RID shaped_text_get_parent(RID p_shaped) const override; - virtual real_t shaped_text_fit_to_width(RID p_shaped, real_t p_width, uint8_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; - virtual real_t shaped_text_tab_align(RID p_shaped, const Vector<real_t> &p_tab_stops) override; + virtual float shaped_text_fit_to_width(RID p_shaped, float p_width, uint16_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; + virtual float shaped_text_tab_align(RID p_shaped, const PackedFloat32Array &p_tab_stops) override; virtual bool shaped_text_shape(RID p_shaped) override; virtual bool shaped_text_update_breaks(RID p_shaped) override; virtual bool shaped_text_update_justification_ops(RID p_shaped) override; - virtual void shaped_text_overrun_trim_to_width(RID p_shaped, real_t p_width, uint8_t p_trim_flags) override; - virtual TrimData shaped_text_get_trim_data(RID p_shaped) const override; + virtual int shaped_text_get_trim_pos(RID p_shaped) const override; + virtual int shaped_text_get_ellipsis_pos(RID p_shaped) const override; + virtual const Glyph *shaped_text_get_ellipsis_glyphs(RID p_shaped) const override; + virtual int shaped_text_get_ellipsis_glyph_count(RID p_shaped) const override; + + virtual void shaped_text_overrun_trim_to_width(RID p_shaped, float p_width, uint16_t p_trim_flags) override; virtual bool shaped_text_is_ready(RID p_shaped) const override; - virtual Vector<Glyph> shaped_text_get_glyphs(RID p_shaped) const override; + virtual const Glyph *shaped_text_get_glyphs(RID p_shaped) const override; + virtual const Glyph *shaped_text_sort_logical(RID p_shaped) override; + virtual int shaped_text_get_glyph_count(RID p_shaped) const override; virtual Vector2i shaped_text_get_range(RID p_shaped) const override; - virtual Vector<Glyph> shaped_text_sort_logical(RID p_shaped) override; - virtual Array shaped_text_get_objects(RID p_shaped) const override; virtual Rect2 shaped_text_get_object_rect(RID p_shaped, Variant p_key) const override; virtual Size2 shaped_text_get_size(RID p_shaped) const override; - virtual real_t shaped_text_get_ascent(RID p_shaped) const override; - virtual real_t shaped_text_get_descent(RID p_shaped) const override; - virtual real_t shaped_text_get_width(RID p_shaped) const override; - virtual real_t shaped_text_get_underline_position(RID p_shaped) const override; - virtual real_t shaped_text_get_underline_thickness(RID p_shaped) const override; + virtual float shaped_text_get_ascent(RID p_shaped) const override; + virtual float shaped_text_get_descent(RID p_shaped) const override; + virtual float shaped_text_get_width(RID p_shaped) const override; + virtual float shaped_text_get_underline_position(RID p_shaped) const override; + virtual float shaped_text_get_underline_thickness(RID p_shaped) const override; virtual String format_number(const String &p_string, const String &p_language = "") const override; virtual String parse_number(const String &p_string, const String &p_language = "") const override; virtual String percent_sign(const String &p_language = "") const override; - static TextServer *create_func(Error &r_error, void *p_user_data); - static void register_server(); - TextServerAdvanced(); ~TextServerAdvanced(); }; |