From 1747253c42eae88159bfcd05011986d919975188 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 30 Oct 2017 15:39:16 +0100 Subject: [PATCH] Do not accept implicit font substitutions from FontConfig. 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. --- src/openrct2/platform/linux.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/openrct2/platform/linux.c b/src/openrct2/platform/linux.c index fc41f5a6fa..a221346833 100644 --- a/src/openrct2/platform/linux.c +++ b/src/openrct2/platform/linux.c @@ -314,6 +314,7 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size) FcFini(); return false; } + FcPattern* pat = FcNameParse((const FcChar8*) font->font_name); FcConfigSubstitute(config, pat, FcMatchPattern); @@ -325,15 +326,33 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer, size_t size) 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 = NULL; + if (FcPatternGetString(match, FC_FULLNAME, 0, &matched_font_face) == FcResultMatch && + strcmp(font->font_name, (const char *) matched_font_face) != 0) + { + log_verbose("FontConfig provided substitute font %s -- disregarding.", matched_font_face); + is_substitute = true; + } + FcChar8* filename = NULL; - if (FcPatternGetString(match, FC_FILE, 0, &filename) == FcResultMatch) + if (!is_substitute && FcPatternGetString(match, FC_FILE, 0, &filename) == FcResultMatch) { found = true; safe_strcpy(buffer, (utf8*) filename, size); log_verbose("FontConfig provided font %s", filename); } + FcPatternDestroy(match); - } else { + } + else + { log_warning("Failed to find required font."); }