From f917fffe346560b6604c012b2e4d43c188ad8b97 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Mon, 10 Jan 2022 13:41:12 +0100 Subject: [PATCH] Upgrade platform_get_font_path() --- src/openrct2/drawing/TTF.cpp | 9 ++-- src/openrct2/platform/Android.cpp | 8 --- src/openrct2/platform/Linux.cpp | 63 ---------------------- src/openrct2/platform/Platform.Android.cpp | 8 +++ src/openrct2/platform/Platform.Linux.cpp | 61 +++++++++++++++++++++ src/openrct2/platform/Platform.Win32.cpp | 20 +++++++ src/openrct2/platform/Platform.macOS.mm | 20 +++++++ src/openrct2/platform/Platform2.h | 3 ++ src/openrct2/platform/Windows.cpp | 31 ----------- src/openrct2/platform/macos.mm | 22 -------- src/openrct2/platform/platform.h | 4 -- 11 files changed, 117 insertions(+), 132 deletions(-) diff --git a/src/openrct2/drawing/TTF.cpp b/src/openrct2/drawing/TTF.cpp index 2c430f3672..005cb0746c 100644 --- a/src/openrct2/drawing/TTF.cpp +++ b/src/openrct2/drawing/TTF.cpp @@ -23,6 +23,7 @@ # include "../core/String.hpp" # include "../localisation/Localisation.h" # include "../localisation/LocalisationService.h" +# include "../platform/Platform2.h" # include "../platform/platform.h" # include "TTF.h" @@ -125,17 +126,17 @@ bool ttf_initialise() { TTFFontDescriptor* fontDesc = &(gCurrentTTFFontSet->size[i]); - utf8 fontPath[MAX_PATH]; - if (!platform_get_font_path(fontDesc, fontPath, sizeof(fontPath))) + auto fontPath = Platform::GetFontPath(*fontDesc); + if (fontPath.empty()) { log_verbose("Unable to load font '%s'", fontDesc->font_name); return false; } - fontDesc->font = ttf_open_font(fontPath, fontDesc->ptSize); + fontDesc->font = ttf_open_font(fontPath.c_str(), fontDesc->ptSize); if (fontDesc->font == nullptr) { - log_verbose("Unable to load '%s'", fontPath); + log_verbose("Unable to load '%s'", fontPath.c_str()); return false; } } diff --git a/src/openrct2/platform/Android.cpp b/src/openrct2/platform/Android.cpp index 9380edd844..979ab3dc81 100644 --- a/src/openrct2/platform/Android.cpp +++ b/src/openrct2/platform/Android.cpp @@ -18,14 +18,6 @@ # include # include -# ifndef NO_TTF -bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size) -{ - STUB(); - return false; -} -# endif - float platform_get_default_scale() { JNIEnv* env = static_cast(SDL_AndroidGetJNIEnv()); diff --git a/src/openrct2/platform/Linux.cpp b/src/openrct2/platform/Linux.cpp index 3720d779cb..001a14e325 100644 --- a/src/openrct2/platform/Linux.cpp +++ b/src/openrct2/platform/Linux.cpp @@ -34,67 +34,4 @@ # include -# ifndef NO_TTF -bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size) -{ - assert(buffer != nullptr); - assert(font != nullptr); - - log_verbose("Looking for font %s with FontConfig.", font->font_name); - FcConfig* config = FcInitLoadConfigAndFonts(); - if (!config) - { - log_error("Failed to initialize FontConfig library"); - FcFini(); - return false; - } - - FcPattern* pat = FcNameParse(reinterpret_cast(font->font_name)); - - FcConfigSubstitute(config, pat, FcMatchPattern); - FcDefaultSubstitute(pat); - - bool found = false; - FcResult result = FcResultNoMatch; - FcPattern* match = FcFontMatch(config, pat, &result); - - if (match) - { - bool is_substitute = false; - - // FontConfig implicitly falls back to any default font it is configured to handle. - // In our implementation, this cannot account for supported character sets, leading - // to unrendered characters (tofu) when trying to render e.g. CJK characters using a - // Western (sans-)serif font. We therefore ignore substitutions FontConfig provides, - // and instead rely on exact matches on the fonts predefined for each font family. - FcChar8* matched_font_face = nullptr; - if (FcPatternGetString(match, FC_FULLNAME, 0, &matched_font_face) == FcResultMatch - && strcmp(font->font_name, reinterpret_cast(matched_font_face)) != 0) - { - log_verbose("FontConfig provided substitute font %s -- disregarding.", matched_font_face); - is_substitute = true; - } - - FcChar8* filename = nullptr; - if (!is_substitute && FcPatternGetString(match, FC_FILE, 0, &filename) == FcResultMatch) - { - found = true; - safe_strcpy(buffer, reinterpret_cast(filename), size); - log_verbose("FontConfig provided font %s", filename); - } - - FcPatternDestroy(match); - } - else - { - log_warning("Failed to find required font."); - } - - FcPatternDestroy(pat); - FcConfigDestroy(config); - FcFini(); - return found; -} -# endif // NO_TTF - #endif diff --git a/src/openrct2/platform/Platform.Android.cpp b/src/openrct2/platform/Platform.Android.cpp index 8fa0a80f26..0062d89a29 100644 --- a/src/openrct2/platform/Platform.Android.cpp +++ b/src/openrct2/platform/Platform.Android.cpp @@ -75,6 +75,14 @@ namespace Platform { return ""; } + +# ifndef NO_TTF + std::string GetFontPath(const TTFFontDescriptor& font) + { + STUB(); + return ""; + } +# endif } // namespace Platform #endif diff --git a/src/openrct2/platform/Platform.Linux.cpp b/src/openrct2/platform/Platform.Linux.cpp index d4ae5b7daa..4f69f37462 100644 --- a/src/openrct2/platform/Platform.Linux.cpp +++ b/src/openrct2/platform/Platform.Linux.cpp @@ -24,6 +24,10 @@ // for PATH_MAX # include # endif // __linux__ +# ifndef NO_TTF +# include +# endif // NO_TTF + # include "../OpenRCT2.h" # include "../core/Path.hpp" # include "../localisation/Language.h" @@ -310,6 +314,63 @@ namespace Platform return ""; } + + std::string GetFontPath(const TTFFontDescriptor& font) + { + log_verbose("Looking for font %s with FontConfig.", font.font_name); + FcConfig* config = FcInitLoadConfigAndFonts(); + if (!config) + { + log_error("Failed to initialize FontConfig library"); + FcFini(); + return ""; + } + + FcPattern* pat = FcNameParse(reinterpret_cast(font.font_name)); + + FcConfigSubstitute(config, pat, FcMatchPattern); + FcDefaultSubstitute(pat); + + std::string path = ""; + FcResult result = FcResultNoMatch; + FcPattern* match = FcFontMatch(config, pat, &result); + + if (match) + { + bool is_substitute = false; + + // FontConfig implicitly falls back to any default font it is configured to handle. + // In our implementation, this cannot account for supported character sets, leading + // to unrendered characters (tofu) when trying to render e.g. CJK characters using a + // Western (sans-)serif font. We therefore ignore substitutions FontConfig provides, + // and instead rely on exact matches on the fonts predefined for each font family. + FcChar8* matched_font_face = nullptr; + if (FcPatternGetString(match, FC_FULLNAME, 0, &matched_font_face) == FcResultMatch + && strcmp(font.font_name, reinterpret_cast(matched_font_face)) != 0) + { + log_verbose("FontConfig provided substitute font %s -- disregarding.", matched_font_face); + is_substitute = true; + } + + FcChar8* filename = nullptr; + if (!is_substitute && FcPatternGetString(match, FC_FILE, 0, &filename) == FcResultMatch) + { + path = reinterpret_cast(filename); + log_verbose("FontConfig provided font %s", filename); + } + + FcPatternDestroy(match); + } + else + { + log_warning("Failed to find required font."); + } + + FcPatternDestroy(pat); + FcConfigDestroy(config); + FcFini(); + return path; + } } // namespace Platform #endif diff --git a/src/openrct2/platform/Platform.Win32.cpp b/src/openrct2/platform/Platform.Win32.cpp index 5959c71afd..4cae076866 100644 --- a/src/openrct2/platform/Platform.Win32.cpp +++ b/src/openrct2/platform/Platform.Win32.cpp @@ -852,6 +852,26 @@ namespace Platform RegCloseKey(hKey); return outPath; } + + std::string GetFontPath(const TTFFontDescriptor& font) + { +# if !defined(__MINGW32__) && ((NTDDI_VERSION >= NTDDI_VISTA) && !defined(_USING_V110_SDK71_) && !defined(_ATL_XP_TARGETING)) + wchar_t* fontFolder; + if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Fonts, 0, nullptr, &fontFolder))) + { + // Convert wchar to utf8, then copy the font folder path to the buffer. + auto outPathTemp = String::ToUtf8(fontFolder); + CoTaskMemFree(fontFolder); + + return Path::Combine(outPathTemp, font.filename); + } + + return ""; +# else + log_warning("Compatibility hack: falling back to C:\\Windows\\Fonts"); + return Path::Combine("C:\\Windows\\Fonts\\", font.filename); +# endif + } } // namespace Platform #endif diff --git a/src/openrct2/platform/Platform.macOS.mm b/src/openrct2/platform/Platform.macOS.mm index 2b23da6135..ec31c5a99c 100644 --- a/src/openrct2/platform/Platform.macOS.mm +++ b/src/openrct2/platform/Platform.macOS.mm @@ -19,6 +19,7 @@ # undef interface # undef abstract +# include # include # include # include @@ -250,6 +251,25 @@ namespace Platform return ""; } + + std::string GetFontPath(const TTFFontDescriptor& font) + { + @autoreleasepool + { + CTFontDescriptorRef fontRef = CTFontDescriptorCreateWithNameAndSize( + static_cast([NSString stringWithUTF8String:font.font_name]), 0.0); + CFURLRef url = static_cast(CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute)); + if (url) + { + NSString* fontPath = [NSString stringWithString:[static_cast(CFBridgingRelease(url)) path]]; + return fontPath.UTF8String; + } + else + { + return ""; + } + } + } } #endif diff --git a/src/openrct2/platform/Platform2.h b/src/openrct2/platform/Platform2.h index b7d2c6e2e5..f324da3af4 100644 --- a/src/openrct2/platform/Platform2.h +++ b/src/openrct2/platform/Platform2.h @@ -64,6 +64,9 @@ namespace Platform std::string GetEnvironmentPath(const char* name); std::string GetHomePath(); #endif +#ifndef NO_TTF + std::string GetFontPath(const TTFFontDescriptor& font); +#endif // NO_TTF std::string FormatShortDate(std::time_t timestamp); std::string FormatTime(std::time_t timestamp); diff --git a/src/openrct2/platform/Windows.cpp b/src/openrct2/platform/Windows.cpp index 779952c5bf..cd68f1312a 100644 --- a/src/openrct2/platform/Windows.cpp +++ b/src/openrct2/platform/Windows.cpp @@ -96,8 +96,6 @@ int32_t platform_get_drives() return GetLogicalDrives(); } - - std::string platform_get_rct1_steam_dir() { return "Rollercoaster Tycoon Deluxe"; @@ -128,35 +126,6 @@ time_t platform_file_get_modified_time(const utf8* path) return 0; } -# ifndef NO_TTF -bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size) -{ -# if !defined(__MINGW32__) \ - && ((NTDDI_VERSION >= NTDDI_VISTA) && !defined(_USING_V110_SDK71_) && !defined(_ATL_XP_TARGETING)) - wchar_t* fontFolder; - if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Fonts, 0, nullptr, &fontFolder))) - { - // Convert wchar to utf8, then copy the font folder path to the buffer. - auto outPathTemp = String::ToUtf8(fontFolder); - safe_strcpy(buffer, outPathTemp.c_str(), size); - - CoTaskMemFree(fontFolder); - - // Append the requested font's file name. - safe_strcat_path(buffer, font->filename, size); - return true; - } - - return false; -# else - log_warning("Compatibility hack: falling back to C:\\Windows\\Fonts"); - safe_strcpy(buffer, "C:\\Windows\\Fonts\\", size); - safe_strcat_path(buffer, font->filename, size); - return true; -# endif -} -# endif // NO_TTF - std::string platform_get_absolute_path(const utf8* relativePath, const utf8* basePath) { std::string result; diff --git a/src/openrct2/platform/macos.mm b/src/openrct2/platform/macos.mm index 7a3e49e995..fca8723d52 100644 --- a/src/openrct2/platform/macos.mm +++ b/src/openrct2/platform/macos.mm @@ -24,26 +24,4 @@ # include # include -# ifndef NO_TTF -bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size) -{ - @autoreleasepool - { - CTFontDescriptorRef fontRef = CTFontDescriptorCreateWithNameAndSize( - static_cast([NSString stringWithUTF8String:font->font_name]), 0.0); - CFURLRef url = static_cast(CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute)); - if (url) - { - NSString* fontPath = [NSString stringWithString:[static_cast(CFBridgingRelease(url)) path]]; - safe_strcpy(buffer, fontPath.UTF8String, size); - return true; - } - else - { - return false; - } - } -} -# endif // NO_TTF - #endif diff --git a/src/openrct2/platform/platform.h b/src/openrct2/platform/platform.h index 1b0358e1c7..e20392b576 100644 --- a/src/openrct2/platform/platform.h +++ b/src/openrct2/platform/platform.h @@ -101,10 +101,6 @@ utf8* platform_open_directory_browser(const utf8* title); std::string platform_get_rct1_steam_dir(); std::string platform_get_rct2_steam_dir(); -#ifndef NO_TTF -bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size); -#endif // NO_TTF - datetime64 platform_get_datetime_now_utc(); float platform_get_default_scale();