1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-18 20:43:04 +01:00

Upgrade platform_get_font_path()

This commit is contained in:
Gymnasiast
2022-01-10 13:41:12 +01:00
parent 310ad1e400
commit f917fffe34
11 changed files with 117 additions and 132 deletions

View File

@@ -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;
}
}

View File

@@ -18,14 +18,6 @@
# include <jni.h>
# include <wchar.h>
# 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<JNIEnv*>(SDL_AndroidGetJNIEnv());

View File

@@ -34,67 +34,4 @@
# include <pwd.h>
# 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<const FcChar8*>(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<const char*>(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<utf8*>(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

View File

@@ -75,6 +75,14 @@ namespace Platform
{
return "";
}
# ifndef NO_TTF
std::string GetFontPath(const TTFFontDescriptor& font)
{
STUB();
return "";
}
# endif
} // namespace Platform
#endif

View File

@@ -24,6 +24,10 @@
// for PATH_MAX
# include <linux/limits.h>
# endif // __linux__
# ifndef NO_TTF
# include <fontconfig/fontconfig.h>
# 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<const FcChar8*>(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<const char*>(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<utf8*>(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

View File

@@ -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

View File

@@ -19,6 +19,7 @@
# undef interface
# undef abstract
# include <CoreText/CoreText.h>
# include <Foundation/Foundation.h>
# include <mach-o/dyld.h>
# include <pwd.h>
@@ -250,6 +251,25 @@ namespace Platform
return "";
}
std::string GetFontPath(const TTFFontDescriptor& font)
{
@autoreleasepool
{
CTFontDescriptorRef fontRef = CTFontDescriptorCreateWithNameAndSize(
static_cast<CFStringRef>([NSString stringWithUTF8String:font.font_name]), 0.0);
CFURLRef url = static_cast<CFURLRef>(CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute));
if (url)
{
NSString* fontPath = [NSString stringWithString:[static_cast<NSURL*>(CFBridgingRelease(url)) path]];
return fontPath.UTF8String;
}
else
{
return "";
}
}
}
}
#endif

View File

@@ -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);

View File

@@ -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;

View File

@@ -24,26 +24,4 @@
# include <mach-o/dyld.h>
# include <pwd.h>
# ifndef NO_TTF
bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size)
{
@autoreleasepool
{
CTFontDescriptorRef fontRef = CTFontDescriptorCreateWithNameAndSize(
static_cast<CFStringRef>([NSString stringWithUTF8String:font->font_name]), 0.0);
CFURLRef url = static_cast<CFURLRef>(CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute));
if (url)
{
NSString* fontPath = [NSString stringWithString:[static_cast<NSURL*>(CFBridgingRelease(url)) path]];
safe_strcpy(buffer, fontPath.UTF8String, size);
return true;
}
else
{
return false;
}
}
}
# endif // NO_TTF
#endif

View File

@@ -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();