From c950a1ab9479e53f8b91d457f44cea9246e24e4e Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Sun, 26 Feb 2023 17:55:04 +0200 Subject: [PATCH] [TextServer] Add mutex for FreeType face creation/deletion operations. --- modules/text_server_adv/text_server_adv.cpp | 77 ++++++++++++--------- modules/text_server_adv/text_server_adv.h | 2 + modules/text_server_fb/text_server_fb.cpp | 77 ++++++++++++--------- modules/text_server_fb/text_server_fb.h | 2 + 4 files changed, 92 insertions(+), 66 deletions(-) diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index b55188ce0c5..ecf466dd821 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -384,6 +384,8 @@ int64_t TextServerAdvanced::_get_features() const { void TextServerAdvanced::_free_rid(const RID &p_rid) { _THREAD_SAFE_METHOD_ if (font_owner.owns(p_rid)) { + MutexLock ftlock(ft_mutex); + FontAdvanced *fd = font_owner.get_or_null(p_rid); { MutexLock lock(fd->mutex); @@ -1319,45 +1321,48 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f // Init dynamic font. #ifdef MODULE_FREETYPE_ENABLED int error = 0; - if (!ft_library) { - error = FT_Init_FreeType(&ft_library); - if (error != 0) { - memdelete(fd); - ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'."); - } + { + MutexLock ftlock(ft_mutex); + if (!ft_library) { + error = FT_Init_FreeType(&ft_library); + if (error != 0) { + memdelete(fd); + ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'."); + } #ifdef MODULE_SVG_ENABLED - FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks()); + FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks()); #endif - } + } - memset(&fd->stream, 0, sizeof(FT_StreamRec)); - fd->stream.base = (unsigned char *)p_font_data->data_ptr; - fd->stream.size = p_font_data->data_size; - fd->stream.pos = 0; + memset(&fd->stream, 0, sizeof(FT_StreamRec)); + fd->stream.base = (unsigned char *)p_font_data->data_ptr; + fd->stream.size = p_font_data->data_size; + fd->stream.pos = 0; - FT_Open_Args fargs; - memset(&fargs, 0, sizeof(FT_Open_Args)); - fargs.memory_base = (unsigned char *)p_font_data->data_ptr; - fargs.memory_size = p_font_data->data_size; - fargs.flags = FT_OPEN_MEMORY; - fargs.stream = &fd->stream; + FT_Open_Args fargs; + memset(&fargs, 0, sizeof(FT_Open_Args)); + fargs.memory_base = (unsigned char *)p_font_data->data_ptr; + fargs.memory_size = p_font_data->data_size; + fargs.flags = FT_OPEN_MEMORY; + fargs.stream = &fd->stream; - int max_index = 0; - FT_Face tmp_face = nullptr; - error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); - if (tmp_face && error == 0) { - max_index = tmp_face->num_faces - 1; - } - if (tmp_face) { - FT_Done_Face(tmp_face); - } + int max_index = 0; + FT_Face tmp_face = nullptr; + error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); + if (tmp_face && error == 0) { + max_index = tmp_face->num_faces - 1; + } + 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) { - FT_Done_Face(fd->face); - fd->face = nullptr; - memdelete(fd); - ERR_FAIL_V_MSG(false, "FreeType: Error loading font: '" + String(FT_Error_String(error)) + "'."); + error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face); + if (error) { + FT_Done_Face(fd->face); + fd->face = nullptr; + memdelete(fd); + ERR_FAIL_V_MSG(false, "FreeType: Error loading font: '" + String(FT_Error_String(error)) + "'."); + } } if (p_font_data->msdf) { @@ -1784,6 +1789,8 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f } _FORCE_INLINE_ void TextServerAdvanced::_font_clear_cache(FontAdvanced *p_font_data) { + MutexLock ftlock(ft_mutex); + for (const KeyValue &E : p_font_data->cache) { memdelete(E.value); } @@ -1890,6 +1897,8 @@ int64_t TextServerAdvanced::_font_get_face_count(const RID &p_font_rid) const { fargs.flags = FT_OPEN_MEMORY; fargs.stream = &stream; + MutexLock ftlock(ft_mutex); + FT_Face tmp_face = nullptr; error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); if (error == 0) { @@ -2281,6 +2290,7 @@ void TextServerAdvanced::_font_clear_size_cache(const RID &p_font_rid) { ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); + MutexLock ftlock(ft_mutex); for (const KeyValue &E : fd->cache) { memdelete(E.value); } @@ -2292,6 +2302,7 @@ void TextServerAdvanced::_font_remove_size_cache(const RID &p_font_rid, const Ve ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); + MutexLock ftlock(ft_mutex); if (fd->cache.has(p_size)) { memdelete(fd->cache[p_size]); fd->cache.erase(p_size); diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 1acf5b21f07..1161f3224ed 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -616,6 +616,8 @@ class TextServerAdvanced : public TextServerExtension { _FORCE_INLINE_ void _add_featuers(const Dictionary &p_source, Vector &r_ftrs); + Mutex ft_mutex; + // HarfBuzz bitmap font interface. static hb_font_funcs_t *funcs; diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index b5d7d3a3cf5..01115ff5323 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -113,6 +113,8 @@ int64_t TextServerFallback::_get_features() const { void TextServerFallback::_free_rid(const RID &p_rid) { _THREAD_SAFE_METHOD_ if (font_owner.owns(p_rid)) { + MutexLock ftlock(ft_mutex); + FontFallback *fd = font_owner.get_or_null(p_rid); { MutexLock lock(fd->mutex); @@ -760,45 +762,48 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *p_f // Init dynamic font. #ifdef MODULE_FREETYPE_ENABLED int error = 0; - if (!ft_library) { - error = FT_Init_FreeType(&ft_library); - if (error != 0) { - memdelete(fd); - ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'."); - } + { + MutexLock ftlock(ft_mutex); + if (!ft_library) { + error = FT_Init_FreeType(&ft_library); + if (error != 0) { + memdelete(fd); + ERR_FAIL_V_MSG(false, "FreeType: Error initializing library: '" + String(FT_Error_String(error)) + "'."); + } #ifdef MODULE_SVG_ENABLED - FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks()); + FT_Property_Set(ft_library, "ot-svg", "svg-hooks", get_tvg_svg_in_ot_hooks()); #endif - } + } - memset(&fd->stream, 0, sizeof(FT_StreamRec)); - fd->stream.base = (unsigned char *)p_font_data->data_ptr; - fd->stream.size = p_font_data->data_size; - fd->stream.pos = 0; + memset(&fd->stream, 0, sizeof(FT_StreamRec)); + fd->stream.base = (unsigned char *)p_font_data->data_ptr; + fd->stream.size = p_font_data->data_size; + fd->stream.pos = 0; - FT_Open_Args fargs; - memset(&fargs, 0, sizeof(FT_Open_Args)); - fargs.memory_base = (unsigned char *)p_font_data->data_ptr; - fargs.memory_size = p_font_data->data_size; - fargs.flags = FT_OPEN_MEMORY; - fargs.stream = &fd->stream; + FT_Open_Args fargs; + memset(&fargs, 0, sizeof(FT_Open_Args)); + fargs.memory_base = (unsigned char *)p_font_data->data_ptr; + fargs.memory_size = p_font_data->data_size; + fargs.flags = FT_OPEN_MEMORY; + fargs.stream = &fd->stream; - int max_index = 0; - FT_Face tmp_face = nullptr; - error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); - if (tmp_face && error == 0) { - max_index = tmp_face->num_faces - 1; - } - if (tmp_face) { - FT_Done_Face(tmp_face); - } + int max_index = 0; + FT_Face tmp_face = nullptr; + error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); + if (tmp_face && error == 0) { + max_index = tmp_face->num_faces - 1; + } + 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) { - FT_Done_Face(fd->face); - fd->face = nullptr; - memdelete(fd); - ERR_FAIL_V_MSG(false, "FreeType: Error loading font: '" + String(FT_Error_String(error)) + "'."); + error = FT_Open_Face(ft_library, &fargs, CLAMP(p_font_data->face_index, 0, max_index), &fd->face); + if (error) { + FT_Done_Face(fd->face); + fd->face = nullptr; + memdelete(fd); + ERR_FAIL_V_MSG(false, "FreeType: Error loading font: '" + String(FT_Error_String(error)) + "'."); + } } if (p_font_data->msdf) { @@ -907,6 +912,8 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *p_f } _FORCE_INLINE_ void TextServerFallback::_font_clear_cache(FontFallback *p_font_data) { + MutexLock ftlock(ft_mutex); + for (const KeyValue &E : p_font_data->cache) { memdelete(E.value); } @@ -1010,6 +1017,8 @@ int64_t TextServerFallback::_font_get_face_count(const RID &p_font_rid) const { fargs.flags = FT_OPEN_MEMORY; fargs.stream = &stream; + MutexLock ftlock(ft_mutex); + FT_Face tmp_face = nullptr; error = FT_Open_Face(ft_library, &fargs, -1, &tmp_face); if (error == 0) { @@ -1391,6 +1400,7 @@ void TextServerFallback::_font_clear_size_cache(const RID &p_font_rid) { ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); + MutexLock ftlock(ft_mutex); for (const KeyValue &E : fd->cache) { memdelete(E.value); } @@ -1402,6 +1412,7 @@ void TextServerFallback::_font_remove_size_cache(const RID &p_font_rid, const Ve ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); + MutexLock ftlock(ft_mutex); if (fd->cache.has(p_size)) { memdelete(fd->cache[p_size]); fd->cache.erase(p_size); diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index 9fb048a5819..32c36b19f33 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -531,6 +531,8 @@ class TextServerFallback : public TextServerExtension { void _realign(ShapedTextDataFallback *p_sd) const; + Mutex ft_mutex; + protected: static void _bind_methods(){};