From bf1cc6326a3d9422a880e470a1a3c2950ec1a419 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Tue, 9 Aug 2022 14:19:03 +0300 Subject: Allow MSDF rendering for system fonts, fix crash on loading damaged / unsupported font files. --- doc/classes/SystemFont.xml | 3 +++ modules/text_server_adv/text_server_adv.cpp | 8 +++++--- modules/text_server_fb/text_server_fb.cpp | 8 +++++--- scene/resources/font.cpp | 20 ++++++++++++++++++++ scene/resources/font.h | 4 ++++ 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/doc/classes/SystemFont.xml b/doc/classes/SystemFont.xml index b1b78f1705..b7454cc7d2 100644 --- a/doc/classes/SystemFont.xml +++ b/doc/classes/SystemFont.xml @@ -34,6 +34,9 @@ Font hinting mode. + + If set to [code]true[/code], glyphs of all sizes are rendered using single multichannel signed distance field generated from the dynamic font vector data. + Font oversampling factor, if set to [code]0.0[/code] global oversampling factor is used instead. diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index 73dbf2f443..c0cff08f13 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -1313,12 +1313,14 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f fargs.stream = &fd->stream; int max_index = 0; - FT_Face tmp_face; + FT_Face tmp_face = nullptr; error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); - if (error == 0) { + if (tmp_face && error == 0) { max_index = tmp_face->num_faces - 1; } - FT_Done_Face(tmp_face); + if (tmp_face) { + FT_Done_Face(tmp_face); + } error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face); if (error) { diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index 55d912a10a..3b91c6981e 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -733,12 +733,14 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *p_f fargs.stream = &fd->stream; int max_index = 0; - FT_Face tmp_face; + FT_Face tmp_face = nullptr; error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); - if (error == 0) { + if (tmp_face && error == 0) { max_index = tmp_face->num_faces - 1; } - FT_Done_Face(tmp_face); + if (tmp_face) { + FT_Done_Face(tmp_face); + } error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face); if (error) { diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 619036d296..84097f95ad 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -2714,6 +2714,9 @@ void SystemFont::_bind_methods() { ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &SystemFont::set_subpixel_positioning); ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &SystemFont::get_subpixel_positioning); + ClassDB::bind_method(D_METHOD("set_multichannel_signed_distance_field", "msdf"), &SystemFont::set_multichannel_signed_distance_field); + ClassDB::bind_method(D_METHOD("is_multichannel_signed_distance_field"), &SystemFont::is_multichannel_signed_distance_field); + ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &SystemFont::set_oversampling); ClassDB::bind_method(D_METHOD("get_oversampling"), &SystemFont::get_oversampling); @@ -2729,6 +2732,7 @@ void SystemFont::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_autohinter"), "set_force_autohinter", "is_force_autohinter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting"); ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel"), "set_subpixel_positioning", "get_subpixel_positioning"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field"), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), "set_oversampling", "get_oversampling"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), "set_fallbacks", "get_fallbacks"); } @@ -2805,6 +2809,7 @@ void SystemFont::_update_base_font() { file->set_force_autohinter(force_autohinter); file->set_hinting(hinting); file->set_subpixel_positioning(subpixel_positioning); + file->set_multichannel_signed_distance_field(msdf); file->set_oversampling(oversampling); base_font = file; @@ -2840,6 +2845,7 @@ void SystemFont::reset_state() { hinting = TextServer::HINTING_LIGHT; subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_DISABLED; oversampling = 0.f; + msdf = false; Font::reset_state(); } @@ -2969,6 +2975,20 @@ TextServer::SubpixelPositioning SystemFont::get_subpixel_positioning() const { return subpixel_positioning; } +void SystemFont::set_multichannel_signed_distance_field(bool p_msdf) { + if (msdf != p_msdf) { + msdf = p_msdf; + if (base_font.is_valid()) { + base_font->set_multichannel_signed_distance_field(msdf); + } + emit_changed(); + } +} + +bool SystemFont::is_multichannel_signed_distance_field() const { + return msdf; +} + void SystemFont::set_oversampling(real_t p_oversampling) { if (oversampling != p_oversampling) { oversampling = p_oversampling; diff --git a/scene/resources/font.h b/scene/resources/font.h index 260b4e521f..696152a23b 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -404,6 +404,7 @@ class SystemFont : public Font { TextServer::Hinting hinting = TextServer::HINTING_LIGHT; TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO; real_t oversampling = 0.f; + bool msdf = false; protected: static void _bind_methods(); @@ -434,6 +435,9 @@ public: virtual void set_oversampling(real_t p_oversampling); virtual real_t get_oversampling() const; + virtual void set_multichannel_signed_distance_field(bool p_msdf); + virtual bool is_multichannel_signed_distance_field() const; + virtual void set_font_names(const PackedStringArray &p_names); virtual PackedStringArray get_font_names() const; -- cgit v1.2.3