* Check whether the currently loaded language pack * uses characters that the currently loaded font * does not support. If this is the case an error * message will be shown in English. The error * message will not be localized because that would * mean it might use characters that are not in the * font, which is the whole reason this check has * been added. * @param searcher The methods t
| 2388 | * If nullptr the loaded language pack searcher is used. |
| 2389 | */ |
| 2390 | void CheckForMissingGlyphs(MissingGlyphSearcher *searcher) |
| 2391 | { |
| 2392 | static LanguagePackGlyphSearcher pack_searcher; |
| 2393 | if (searcher == nullptr) searcher = &pack_searcher; |
| 2394 | bool bad_font = searcher->FindMissingGlyphs(); |
| 2395 | #if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) |
| 2396 | if (bad_font) { |
| 2397 | /* We found an unprintable character... lets try whether we can find |
| 2398 | * a fallback font that can print the characters in the current language. */ |
| 2399 | bool any_font_configured = !_fcsettings.medium.font.empty(); |
| 2400 | FontCacheSettings backup = _fcsettings; |
| 2401 | |
| 2402 | _fcsettings.mono.os_handle = nullptr; |
| 2403 | _fcsettings.medium.os_handle = nullptr; |
| 2404 | |
| 2405 | bad_font = !FontProviderManager::FindFallbackFont(&_fcsettings, _langpack.langpack->isocode, searcher); |
| 2406 | |
| 2407 | _fcsettings = std::move(backup); |
| 2408 | |
| 2409 | if (!bad_font && any_font_configured) { |
| 2410 | /* If the user configured a bad font, and we found a better one, |
| 2411 | * show that we loaded the better font instead of the configured one. |
| 2412 | */ |
| 2413 | std::string err_str; |
| 2414 | StringBuilder builder(err_str); |
| 2415 | builder.PutUtf8(SCC_YELLOW); |
| 2416 | builder.Put("The current font is missing some of the characters used in the texts for this language. Using system fallback font instead."); |
| 2417 | ShowErrorMessage(GetEncodedString(STR_JUST_RAW_STRING, std::move(err_str)), {}, WL_WARNING); |
| 2418 | } |
| 2419 | |
| 2420 | if (bad_font) { |
| 2421 | /* Our fallback font does miss characters too, so keep the |
| 2422 | * user chosen font as that is more likely to be any good than |
| 2423 | * the wild guess we made */ |
| 2424 | FontCache::LoadFontCaches(searcher->Monospace() ? FontSizes{FS_MONO} : FONTSIZES_REQUIRED); |
| 2425 | } |
| 2426 | } |
| 2427 | #endif |
| 2428 | |
| 2429 | if (bad_font) { |
| 2430 | /* All attempts have failed. Display an error. As we do not want the string to be translated by |
| 2431 | * the translators, we 'force' it into the binary and 'load' it via a BindCString. To do this |
| 2432 | * properly we have to set the colour of the string, otherwise we end up with a lot of artifacts. |
| 2433 | */ |
| 2434 | std::string err_str; |
| 2435 | StringBuilder builder(err_str); |
| 2436 | builder.PutUtf8(SCC_YELLOW); |
| 2437 | builder.Put("The current font is missing some of the characters used in the texts for this language. Go to Help & Manuals > Fonts, or read the file docs/fonts.md in your OpenTTD directory, to see how to solve this."); |
| 2438 | ShowErrorMessage(GetEncodedString(STR_JUST_RAW_STRING, std::move(err_str)), {}, WL_WARNING); |
| 2439 | |
| 2440 | /* Reset the font width */ |
| 2441 | LoadStringWidthTable(searcher->Monospace() ? FontSizes{FS_MONO} : FONTSIZES_REQUIRED); |
| 2442 | return; |
| 2443 | } |
| 2444 | |
| 2445 | /* Update the font with cache */ |
| 2446 | LoadStringWidthTable(searcher->Monospace() ? FontSizes{FS_MONO} : FONTSIZES_REQUIRED); |
| 2447 |
no test coverage detected