mirror of https://github.com/OpenRCT2/OpenRCT2.git
Fix crash with truetype fonts and multi threading (#9424)
This commit is contained in:
parent
6b7fee86bb
commit
7c0f04903e
|
@ -59,6 +59,7 @@
|
|||
- Fix: [#9324] Crash trying to remove invalid footpath scenery.
|
||||
- Fix: [#9402] Ad campaigns disappear when you save and load the game.
|
||||
- Fix: [#9411] Ad campaigns end too soon.
|
||||
- Fix: [#9424] Crash using multi threading with TrueType fonts.
|
||||
- Fix: Guests eating popcorn are drawn as if they're eating pizza.
|
||||
- Fix: The arbitrary ride type and vehicle dropdown lists are ordered case-sensitively.
|
||||
- Improved: [#6116] Expose colour scheme for track elements in the tile inspector.
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#ifndef NO_TTF
|
||||
|
||||
# include <atomic>
|
||||
# include <mutex>
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wdocumentation"
|
||||
# include <ft2build.h>
|
||||
|
@ -53,6 +55,8 @@ static int32_t _ttfGetWidthCacheCount = 0;
|
|||
static int32_t _ttfGetWidthCacheHitCount = 0;
|
||||
static int32_t _ttfGetWidthCacheMissCount = 0;
|
||||
|
||||
static std::mutex _mutex;
|
||||
|
||||
static TTF_Font* ttf_open_font(const utf8* fontPath, int32_t ptSize);
|
||||
static void ttf_close_font(TTF_Font* font);
|
||||
static uint32_t ttf_surface_cache_hash(TTF_Font* font, const utf8* text);
|
||||
|
@ -60,63 +64,111 @@ static void ttf_surface_cache_dispose(ttf_cache_entry* entry);
|
|||
static void ttf_surface_cache_dispose_all();
|
||||
static void ttf_getwidth_cache_dispose_all();
|
||||
static bool ttf_get_size(TTF_Font* font, const utf8* text, int32_t* width, int32_t* height);
|
||||
static void ttf_toggle_hinting(bool);
|
||||
static TTFSurface* ttf_render(TTF_Font* font, const utf8* text);
|
||||
|
||||
template<typename T> class FontLockHelper
|
||||
{
|
||||
T& _mutex;
|
||||
const bool _enabled;
|
||||
|
||||
public:
|
||||
FontLockHelper(T& mutex)
|
||||
: _mutex(mutex)
|
||||
, _enabled(gConfigGeneral.multithreading)
|
||||
{
|
||||
if (_enabled)
|
||||
_mutex.lock();
|
||||
}
|
||||
~FontLockHelper()
|
||||
{
|
||||
if (_enabled)
|
||||
_mutex.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
static void ttf_toggle_hinting(bool)
|
||||
{
|
||||
if (!LocalisationService_UseTrueTypeFont())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < FONT_SIZE_COUNT; i++)
|
||||
{
|
||||
TTFFontDescriptor* fontDesc = &(gCurrentTTFFontSet->size[i]);
|
||||
bool use_hinting = gConfigFonts.enable_hinting && fontDesc->hinting_threshold;
|
||||
TTF_SetFontHinting(fontDesc->font, use_hinting ? 1 : 0);
|
||||
}
|
||||
|
||||
if (_ttfSurfaceCacheCount)
|
||||
{
|
||||
ttf_surface_cache_dispose_all();
|
||||
}
|
||||
}
|
||||
|
||||
bool ttf_initialise()
|
||||
{
|
||||
if (!_ttfInitialised)
|
||||
FontLockHelper<std::mutex> lock(_mutex);
|
||||
|
||||
if (_ttfInitialised)
|
||||
return true;
|
||||
|
||||
if (TTF_Init() != 0)
|
||||
{
|
||||
if (TTF_Init() != 0)
|
||||
log_error("Couldn't initialise FreeType engine");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < FONT_SIZE_COUNT; i++)
|
||||
{
|
||||
TTFFontDescriptor* fontDesc = &(gCurrentTTFFontSet->size[i]);
|
||||
|
||||
utf8 fontPath[MAX_PATH];
|
||||
if (!platform_get_font_path(fontDesc, fontPath, sizeof(fontPath)))
|
||||
{
|
||||
log_error("Couldn't initialise FreeType engine");
|
||||
log_verbose("Unable to load font '%s'", fontDesc->font_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < FONT_SIZE_COUNT; i++)
|
||||
fontDesc->font = ttf_open_font(fontPath, fontDesc->ptSize);
|
||||
if (fontDesc->font == nullptr)
|
||||
{
|
||||
TTFFontDescriptor* fontDesc = &(gCurrentTTFFontSet->size[i]);
|
||||
|
||||
utf8 fontPath[MAX_PATH];
|
||||
if (!platform_get_font_path(fontDesc, fontPath, sizeof(fontPath)))
|
||||
{
|
||||
log_verbose("Unable to load font '%s'", fontDesc->font_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
fontDesc->font = ttf_open_font(fontPath, fontDesc->ptSize);
|
||||
if (fontDesc->font == nullptr)
|
||||
{
|
||||
log_verbose("Unable to load '%s'", fontPath);
|
||||
return false;
|
||||
}
|
||||
log_verbose("Unable to load '%s'", fontPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
ttf_toggle_hinting();
|
||||
_ttfInitialised = true;
|
||||
}
|
||||
|
||||
ttf_toggle_hinting(true);
|
||||
|
||||
_ttfInitialised = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ttf_dispose()
|
||||
{
|
||||
if (_ttfInitialised)
|
||||
FontLockHelper<std::mutex> lock(_mutex);
|
||||
|
||||
if (!_ttfInitialised)
|
||||
return;
|
||||
|
||||
ttf_surface_cache_dispose_all();
|
||||
ttf_getwidth_cache_dispose_all();
|
||||
|
||||
for (int32_t i = 0; i < FONT_SIZE_COUNT; i++)
|
||||
{
|
||||
ttf_surface_cache_dispose_all();
|
||||
ttf_getwidth_cache_dispose_all();
|
||||
|
||||
for (int32_t i = 0; i < FONT_SIZE_COUNT; i++)
|
||||
TTFFontDescriptor* fontDesc = &(gCurrentTTFFontSet->size[i]);
|
||||
if (fontDesc->font != nullptr)
|
||||
{
|
||||
TTFFontDescriptor* fontDesc = &(gCurrentTTFFontSet->size[i]);
|
||||
if (fontDesc->font != nullptr)
|
||||
{
|
||||
ttf_close_font(fontDesc->font);
|
||||
fontDesc->font = nullptr;
|
||||
}
|
||||
ttf_close_font(fontDesc->font);
|
||||
fontDesc->font = nullptr;
|
||||
}
|
||||
|
||||
TTF_Quit();
|
||||
_ttfInitialised = false;
|
||||
}
|
||||
|
||||
TTF_Quit();
|
||||
|
||||
_ttfInitialised = false;
|
||||
}
|
||||
|
||||
static TTF_Font* ttf_open_font(const utf8* fontPath, int32_t ptSize)
|
||||
|
@ -163,22 +215,8 @@ static void ttf_surface_cache_dispose_all()
|
|||
|
||||
void ttf_toggle_hinting()
|
||||
{
|
||||
if (!LocalisationService_UseTrueTypeFont())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < FONT_SIZE_COUNT; i++)
|
||||
{
|
||||
TTFFontDescriptor* fontDesc = &(gCurrentTTFFontSet->size[i]);
|
||||
bool use_hinting = gConfigFonts.enable_hinting && fontDesc->hinting_threshold;
|
||||
TTF_SetFontHinting(fontDesc->font, use_hinting ? 1 : 0);
|
||||
}
|
||||
|
||||
if (_ttfSurfaceCacheCount)
|
||||
{
|
||||
ttf_surface_cache_dispose_all();
|
||||
}
|
||||
FontLockHelper<std::mutex> lock(_mutex);
|
||||
ttf_toggle_hinting(true);
|
||||
}
|
||||
|
||||
TTFSurface* ttf_surface_cache_get_or_add(TTF_Font* font, const utf8* text)
|
||||
|
@ -187,6 +225,9 @@ TTFSurface* ttf_surface_cache_get_or_add(TTF_Font* font, const utf8* text)
|
|||
|
||||
uint32_t hash = ttf_surface_cache_hash(font, text);
|
||||
int32_t index = hash % TTF_SURFACE_CACHE_SIZE;
|
||||
|
||||
FontLockHelper<std::mutex> lock(_mutex);
|
||||
|
||||
for (int32_t i = 0; i < TTF_SURFACE_CACHE_SIZE; i++)
|
||||
{
|
||||
entry = &_ttfSurfaceCache[index];
|
||||
|
@ -260,6 +301,9 @@ uint32_t ttf_getwidth_cache_get_or_add(TTF_Font* font, const utf8* text)
|
|||
|
||||
uint32_t hash = ttf_surface_cache_hash(font, text);
|
||||
int32_t index = hash % TTF_GETWIDTH_CACHE_SIZE;
|
||||
|
||||
FontLockHelper<std::mutex> lock(_mutex);
|
||||
|
||||
for (int32_t i = 0; i < TTF_GETWIDTH_CACHE_SIZE; i++)
|
||||
{
|
||||
entry = &_ttfGetWidthCache[index];
|
||||
|
@ -304,6 +348,7 @@ uint32_t ttf_getwidth_cache_get_or_add(TTF_Font* font, const utf8* text)
|
|||
|
||||
TTFFontDescriptor* ttf_get_font_from_sprite_base(uint16_t spriteBase)
|
||||
{
|
||||
FontLockHelper<std::mutex> lock(_mutex);
|
||||
return &gCurrentTTFFontSet->size[font_get_size_from_sprite_base(spriteBase)];
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue