1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 11:03:00 +01:00
Files
OpenRCT2/src/openrct2/interface/Fonts.cpp
Michał Janiszewski dfcb527ada Ensure TTF system is torn down in correct order (#21707)
`TTFDispose` uses `gCurrentTTFFontSet` to deallocate internal resources.
Having the function called after global variable got changed meant it
tried to deallocate incorrect font and would subsequently call
`FT_Done_Face` on a struct having internal data set to nullptr.

Reproduction is fairly easy:
1. launch the game in Korean (I made sure to have all the indexes primed
   for this language beforehand - i.e. launch it twice),
2. switch to Japanese,
3. switch back to Korean

Fixes #21664
2024-04-02 00:52:40 +02:00

198 lines
8.2 KiB
C++

/*****************************************************************************
* Copyright (c) 2014-2024 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "Fonts.h"
#include "../config/Config.h"
#include "../core/String.hpp"
#include "../drawing/TTF.h"
#include "../localisation/Language.h"
#include "../localisation/LocalisationService.h"
#include "../util/Util.h"
#include "FontFamilies.h"
using namespace OpenRCT2::Localisation;
#ifndef NO_TTF
uint8_t const HINTING_DISABLED = 0;
uint8_t const HINTING_THRESHOLD_LOW = 40;
uint8_t const HINTING_THRESHOLD_MEDIUM = 60;
// clang-format off
TTFFontSetDescriptor TTFFontMSGothic = { {
{ "msgothic.ttc", "MS PGothic", 12, 1, 0, 14, HINTING_THRESHOLD_MEDIUM, nullptr },
{ "msgothic.ttc", "MS PGothic", 12, 1, 0, 14, HINTING_THRESHOLD_MEDIUM, nullptr },
{ "msgothic.ttc", "MS PGothic", 9, 1, 1, 9, HINTING_THRESHOLD_MEDIUM, nullptr },
} };
TTFFontSetDescriptor TTFFontNotoSansMono = { {
{ "NotoSansCJK-Regular.ttc", "Noto Sans Mono CJK JP", 12, 1, -3, 14, HINTING_THRESHOLD_MEDIUM, nullptr },
{ "NotoSansCJK-Regular.ttc", "Noto Sans Mono CJK JP", 12, 1, -3, 14, HINTING_THRESHOLD_MEDIUM, nullptr },
{ "NotoSansCJK-Regular.ttc", "Noto Sans Mono CJK JP", 9, 1, -2, 9, HINTING_THRESHOLD_MEDIUM, nullptr },
} };
TTFFontSetDescriptor TTFFontHiragano = { {
{ u8"ヒラギノ丸ゴ ProN W4.ttc", "Hiragino Maru Gothic ProN", 11, 1, 0, 13, HINTING_THRESHOLD_MEDIUM, nullptr },
{ u8"ヒラギノ丸ゴ ProN W4.ttc", "Hiragino Maru Gothic ProN", 11, 1, 0, 13, HINTING_THRESHOLD_MEDIUM, nullptr },
{ u8"ヒラギノ丸ゴ ProN W4.ttc", "Hiragino Maru Gothic ProN", 9, 1, 1, 9, HINTING_THRESHOLD_MEDIUM, nullptr },
} };
TTFFontSetDescriptor TTFFontMingLiu = { {
{ "mingliu.ttc", "MingLiU", 11, 1, 1, 14, HINTING_THRESHOLD_MEDIUM, nullptr },
{ "mingliu.ttc", "MingLiU", 12, 1, 0, 15, HINTING_THRESHOLD_MEDIUM, nullptr },
{ "msjh.ttc", "JhengHei", 9, -1, -1, 9, HINTING_THRESHOLD_MEDIUM, nullptr },
} };
TTFFontSetDescriptor TTFFontHeiti = { {
{ u8"华文黑体.ttf", "STHeiti", 11, 1, 1, 14, HINTING_THRESHOLD_MEDIUM, nullptr },
{ u8"华文黑体.ttf", "STHeiti", 12, 1, 0, 15, HINTING_THRESHOLD_MEDIUM, nullptr },
{ u8"华文黑体.ttf", "STHeiti", 9, -1, -1, 9, HINTING_THRESHOLD_MEDIUM, nullptr },
} };
TTFFontSetDescriptor TTFFontSimSun = { {
{ "simsun.ttc", "SimSun", 11, 1, -1, 14, HINTING_THRESHOLD_MEDIUM, nullptr },
{ "simsun.ttc", "SimSun", 12, 1, -2, 15, HINTING_THRESHOLD_MEDIUM, nullptr },
{ "msyh.ttc", "Microsoft YaHei", 9, -1, -1, 9, HINTING_THRESHOLD_MEDIUM, nullptr },
} };
TTFFontSetDescriptor TTFFontLiHeiPro = { {
{ u8"儷黑 Pro.ttf", "LiHei Pro", 11, 1, 0, 14, HINTING_THRESHOLD_MEDIUM, nullptr },
{ u8"儷黑 Pro.ttf", "LiHei Pro", 12, 1, 0, 15, HINTING_THRESHOLD_MEDIUM, nullptr },
{ u8"儷黑 Pro.ttf", "LiHei Pro", 9, 1, -1, 9, HINTING_THRESHOLD_MEDIUM, nullptr },
} };
TTFFontSetDescriptor TTFFontGulim = { {
{ "gulim.ttc", "Gulim", 12, 1, 0, 15, HINTING_THRESHOLD_MEDIUM, nullptr },
{ "gulim.ttc", "Gulim", 12, 1, 0, 15, HINTING_THRESHOLD_MEDIUM, nullptr },
{ "gulim.ttc", "Gulim", 10, 1, 0, 10, HINTING_DISABLED, nullptr },
} };
TTFFontSetDescriptor TTFFontMalgun = { {
{ "malgun.ttf", "Malgun Gothic", 12, 1, -3, 15, HINTING_THRESHOLD_LOW, nullptr },
{ "malgun.ttf", "Malgun Gothic", 12, 1, -3, 15, HINTING_THRESHOLD_LOW, nullptr },
{ "malgun.ttf", "Malgun Gothic", 10, 1, -3, 10, HINTING_THRESHOLD_LOW, nullptr },
} };
TTFFontSetDescriptor TTFFontNanum = { {
{ "NanumGothic.ttf", "Nanum Gothic", 12, 1, -2, 15, HINTING_THRESHOLD_LOW, nullptr },
{ "NanumGothic.ttf", "Nanum Gothic", 12, 1, -2, 15, HINTING_THRESHOLD_LOW, nullptr },
{ "NanumGothic.ttf", "Nanum Gothic", 10, 1, -2, 10, HINTING_DISABLED, nullptr },
} };
TTFFontSetDescriptor TTFFontArial = { {
{ "arial.ttf", "Arial", 12, 0, -1, 12, HINTING_THRESHOLD_LOW, nullptr },
{ "arial.ttf", "Arial", 12, 0, -1, 12, HINTING_THRESHOLD_LOW, nullptr },
{ "arial.ttf", "Arial", 10, 0, -1, 9, HINTING_THRESHOLD_LOW, nullptr },
} };
TTFFontSetDescriptor TTFFontArialUnicode = { {
{ "arialuni.ttf", "Arial Unicode MS", 12, 0, -1, 12, HINTING_THRESHOLD_LOW, nullptr },
{ "arialuni.ttf", "Arial Unicode MS", 12, 0, -1, 12, HINTING_THRESHOLD_LOW, nullptr },
{ "arialuni.ttf", "Arial Unicode MS", 10, 0, -1, 9, HINTING_THRESHOLD_LOW, nullptr },
} };
TTFFontSetDescriptor TTFFontMicroHei = { {
{ "wqy-microhei.ttc", "WenQuanYi Micro Hei", 11, 1, -1, 14, HINTING_THRESHOLD_MEDIUM, nullptr },
{ "wqy-microhei.ttc", "WenQuanYi Micro Hei", 11, 1, -2, 14, HINTING_THRESHOLD_MEDIUM, nullptr },
{ "wqy-microhei.ttc", "WenQuanYi Micro Hei", 10, -1, -1, 10, HINTING_THRESHOLD_MEDIUM, nullptr },
} };
// clang-format on
#endif // NO_TTF
static void LoadSpriteFont(LocalisationService& localisationService)
{
TTFDispose();
localisationService.UseTrueTypeFont(false);
#ifndef NO_TTF
gCurrentTTFFontSet = nullptr;
#endif // NO_TTF
}
#ifndef NO_TTF
static bool LoadFont(LocalisationService& localisationService, TTFFontSetDescriptor* font)
{
TTFDispose();
localisationService.UseTrueTypeFont(true);
gCurrentTTFFontSet = font;
bool fontInitialised = TTFInitialise();
return fontInitialised;
}
static bool LoadCustomConfigFont(LocalisationService& localisationService)
{
static TTFFontSetDescriptor TTFFontCustom = { {
{ gConfigFonts.FileName.c_str(), gConfigFonts.FontName.c_str(), gConfigFonts.SizeTiny, gConfigFonts.OffsetX,
gConfigFonts.OffsetY, gConfigFonts.HeightTiny, gConfigFonts.HintingThreshold, nullptr },
{ gConfigFonts.FileName.c_str(), gConfigFonts.FontName.c_str(), gConfigFonts.SizeSmall, gConfigFonts.OffsetX,
gConfigFonts.OffsetY, gConfigFonts.HeightSmall, gConfigFonts.HintingThreshold, nullptr },
{ gConfigFonts.FileName.c_str(), gConfigFonts.FontName.c_str(), gConfigFonts.SizeMedium, gConfigFonts.OffsetX,
gConfigFonts.OffsetY, gConfigFonts.HeightMedium, gConfigFonts.HintingThreshold, nullptr },
} };
TTFDispose();
localisationService.UseTrueTypeFont(true);
gCurrentTTFFontSet = &TTFFontCustom;
bool fontInitialised = TTFInitialise();
return fontInitialised;
}
#endif // NO_TTF
void TryLoadFonts(LocalisationService& localisationService)
{
#ifndef NO_TTF
auto currentLanguage = localisationService.GetCurrentLanguage();
TTFontFamily const* fontFamily = LanguagesDescriptors[currentLanguage].font_family;
if (fontFamily != FAMILY_OPENRCT2_SPRITE)
{
if (!gConfigFonts.FileName.empty())
{
if (LoadCustomConfigFont(localisationService))
{
return;
}
LOG_VERBOSE("Unable to initialise configured TrueType font -- falling back to the language's default.");
}
for (auto& font : *fontFamily)
{
if (LoadFont(localisationService, font))
{
return;
}
TTFFontDescriptor smallFont = font->size[EnumValue(FontStyle::Small)];
LOG_VERBOSE("Unable to load TrueType font '%s' -- trying the next font in the family.", smallFont.font_name);
}
if (fontFamily != &TTFFamilySansSerif)
{
LOG_VERBOSE("Unable to initialise any of the preferred TrueType fonts -- falling back to sans serif fonts.");
for (auto& font : TTFFamilySansSerif)
{
if (LoadFont(localisationService, font))
{
return;
}
TTFFontDescriptor smallFont = font->size[EnumValue(FontStyle::Small)];
LOG_VERBOSE("Unable to load TrueType font '%s' -- trying the next font in the family.", smallFont.font_name);
}
LOG_VERBOSE("Unable to initialise any of the preferred TrueType fonts -- falling back to sprite font.");
}
}
#endif // NO_TTF
LoadSpriteFont(localisationService);
}