diff --git a/src/os/unix/font_unix.cpp b/src/os/unix/font_unix.cpp index 98543c1bdc..0855fdb498 100644 --- a/src/os/unix/font_unix.cpp +++ b/src/os/unix/font_unix.cpp @@ -109,7 +109,8 @@ bool SetFallbackFont(FontCacheSettings *settings, const char *language_isocode, if (split != nullptr) *split = '\0'; /* First create a pattern to match the wanted language. */ - FcPattern *pat = FcNameParse((FcChar8 *)lang); + //FcPattern *pat = FcNameParse((FcChar8*)lang); + FcPattern *pat = FcPatternCreate(); /* We only want to know the filename. */ FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_SPACING, FC_SLANT, FC_WEIGHT, nullptr); /* Get the list of filenames matching the wanted language. */ @@ -122,6 +123,7 @@ bool SetFallbackFont(FontCacheSettings *settings, const char *language_isocode, if (fs != nullptr) { int best_weight = -1; const char *best_font = nullptr; + int best_missing_glypths = 65536; for (int i = 0; i < fs->nfont; i++) { FcPattern *font = fs->fonts[i]; @@ -131,28 +133,31 @@ bool SetFallbackFont(FontCacheSettings *settings, const char *language_isocode, if (res != FcResultMatch || file == nullptr) { continue; } + int missing = 0; /* Get a font with the right spacing .*/ int value = 0; FcPatternGetInteger(font, FC_SPACING, 0, &value); - if (callback->Monospace() != (value == FC_MONO) && value != FC_DUAL) continue; + if (callback->Monospace() != (value == FC_MONO) && value != FC_DUAL) missing += 1; /* Do not use those that explicitly say they're slanted. */ FcPatternGetInteger(font, FC_SLANT, 0, &value); - if (value != 0) continue; + if (value != 0) missing += 1; /* We want the fatter font as they look better at small sizes. */ FcPatternGetInteger(font, FC_WEIGHT, 0, &value); - if (value <= best_weight) continue; + if (value <= best_weight) missing += 1; callback->SetFontNames(settings, (const char *)file); - bool missing = callback->FindMissingGlyphs(); - Debug(fontcache, 1, "Font \"{}\" misses{} glyphs", file, missing ? "" : " no"); + missing += callback->FindMissingGlyphs(); + Debug(fontcache, 1, "Font \"{}\" misses {} glyphs for lang {}", file, missing, lang); - if (!missing) { + if (missing < best_missing_glypths) { best_weight = value; best_font = (const char *)file; + best_missing_glypths = missing; + if (missing == 0) break; } } @@ -160,6 +165,7 @@ bool SetFallbackFont(FontCacheSettings *settings, const char *language_isocode, ret = true; callback->SetFontNames(settings, best_font); InitFontCache(callback->Monospace()); + Debug(fontcache, 1, "Selected font {} for lang {}", best_font, lang); } /* Clean up the list of filenames. */ diff --git a/src/strings.cpp b/src/strings.cpp index 4c78e0fe7b..5c27585409 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -2035,7 +2035,7 @@ const char *GetCurrentLanguageIsoCode() * Check whether there are glyphs missing in the current language. * @return If glyphs are missing, return \c true, else return \c false. */ -bool MissingGlyphSearcher::FindMissingGlyphs() +int MissingGlyphSearcher::FindMissingGlyphs() { InitFontCache(this->Monospace()); const Sprite *question_mark[FS_END]; @@ -2045,6 +2045,7 @@ bool MissingGlyphSearcher::FindMissingGlyphs() } this->Reset(); + int missing = 0; for (const char *text = this->NextString(); text != nullptr; text = this->NextString()) { FontSize size = this->DefaultSize(); for (WChar c = Utf8Consume(&text); c != '\0'; c = Utf8Consume(&text)) { @@ -2063,11 +2064,11 @@ bool MissingGlyphSearcher::FindMissingGlyphs() } Debug(fontcache, 0, "Font is missing glyphs to display char 0x{:X} in {} font size", (int)c, size_name); - return true; + missing++; } } } - return false; + return missing; } /** Helper for searching through the language pack. */ @@ -2142,7 +2143,7 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher) if (bad_font) { /* We found an unprintable character... lets try whether we can find * a fallback font that can print the characters in the current language. */ - bool any_font_configured = !_fcsettings.medium.font.empty(); + //bool any_font_configured = !_fcsettings.medium.font.empty(); FontCacheSettings backup = _fcsettings; _fcsettings.mono.os_handle = nullptr; @@ -2152,17 +2153,19 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher) _fcsettings = backup; - if (!bad_font && any_font_configured) { - /* If the user configured a bad font, and we found a better one, - * show that we loaded the better font instead of the configured one. - * The colour 'character' might change in the + if (!bad_font) { + /* Show that we loaded fallback font. To do this properly we have + * to set the colour of the string, otherwise we end up with a lot + * of artifacts.* The colour 'character' might change in the * future, so for safety we just Utf8 Encode it into the string, * which takes exactly three characters, so it replaces the "XXX" * with the colour marker. */ +#if !defined(__ANDROID__) && !defined(__EMSCRIPTEN__) static char *err_str = stredup("XXXThe current font is missing some of the characters used in the texts for this language. Using system fallback font instead."); Utf8Encode(err_str, SCC_YELLOW); SetDParamStr(0, err_str); ShowErrorMessage(STR_JUST_RAW_STRING, INVALID_STRING_ID, WL_WARNING); +#endif } if (bad_font && base_font) { diff --git a/src/strings_func.h b/src/strings_func.h index bdb4fc6cd6..6ae35945a9 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -276,7 +276,7 @@ public: */ virtual void SetFontNames(struct FontCacheSettings *settings, const char *font_name, const void *os_data = nullptr) = 0; - bool FindMissingGlyphs(); + int FindMissingGlyphs(); }; void CheckForMissingGlyphs(bool base_font = true, MissingGlyphSearcher *search = nullptr);