mirror of
https://github.com/OpenTTD/OpenTTD
synced 2025-12-10 06:52:05 +01:00
Add: Automatically load fonts for missing glyphs. (#14856)
This commit is contained in:
@@ -2326,7 +2326,7 @@ static bool ConContent(std::span<std::string_view> argv)
|
|||||||
*/
|
*/
|
||||||
static std::string_view FontLoadReasonToName(FontLoadReason load_reason)
|
static std::string_view FontLoadReasonToName(FontLoadReason load_reason)
|
||||||
{
|
{
|
||||||
static const std::string_view LOAD_REASON_TO_NAME[] = { "default", "configured", "language" };
|
static const std::string_view LOAD_REASON_TO_NAME[] = { "default", "configured", "language", "missing" };
|
||||||
static_assert(std::size(LOAD_REASON_TO_NAME) == to_underlying(FontLoadReason::End));
|
static_assert(std::size(LOAD_REASON_TO_NAME) == to_underlying(FontLoadReason::End));
|
||||||
return LOAD_REASON_TO_NAME[to_underlying(load_reason)];
|
return LOAD_REASON_TO_NAME[to_underlying(load_reason)];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ int FontCache::GetDefaultFontHeight(FontSize fs)
|
|||||||
|
|
||||||
for (const auto &fc : FontCache::caches) {
|
for (const auto &fc : FontCache::caches) {
|
||||||
if (fc == nullptr || fc->fs != fs) continue;
|
if (fc == nullptr || fc->fs != fs) continue;
|
||||||
|
if (fc->load_reason == FontLoadReason::MissingFallback) continue; // Avoid dynamically loaded fonts affecting widget sizes.
|
||||||
ascender = std::max(ascender, fc->ascender);
|
ascender = std::max(ascender, fc->ascender);
|
||||||
descender = std::min(descender, fc->descender);
|
descender = std::min(descender, fc->descender);
|
||||||
}
|
}
|
||||||
@@ -269,10 +270,11 @@ std::string GetFontCacheFontName(FontSize fs)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void FontCache::LoadFallbackFonts(FontSize fs)
|
/* static */ void FontCache::LoadFallbackFonts(FontSize fs, FontLoadReason load_reason)
|
||||||
{
|
{
|
||||||
const FontCacheSubSetting *setting = GetFontCacheSubSetting(fs);
|
const FontCacheSubSetting *setting = GetFontCacheSubSetting(fs);
|
||||||
for (auto it = setting->fallback_fonts.rbegin(); it != setting->fallback_fonts.rend(); ++it) {
|
for (auto it = setting->fallback_fonts.rbegin(); it != setting->fallback_fonts.rend(); ++it) {
|
||||||
|
if (it->load_reason != load_reason) continue;
|
||||||
FontCache::Register(FontProviderManager::LoadFont(fs, FontType::TrueType, false, it->name, it->os_handle), it->load_reason);
|
FontCache::Register(FontProviderManager::LoadFont(fs, FontType::TrueType, false, it->name, it->os_handle), it->load_reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -318,12 +320,15 @@ std::string GetFontCacheFontName(FontSize fs)
|
|||||||
if (std::ranges::find(fontnames, extra_font) == std::end(fontnames)) fontnames.push_back(extra_font);
|
if (std::ranges::find(fontnames, extra_font) == std::end(fontnames)) fontnames.push_back(extra_font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* First load fonts for missing glyphs discovered during string formatting. */
|
||||||
|
FontCache::LoadFallbackFonts(fs, FontLoadReason::MissingFallback);
|
||||||
|
|
||||||
/* Load configured fonts in reverse order so that the first entry has priority. */
|
/* Load configured fonts in reverse order so that the first entry has priority. */
|
||||||
for (auto it = fontnames.rbegin(); it != fontnames.rend(); ++it) {
|
for (auto it = fontnames.rbegin(); it != fontnames.rend(); ++it) {
|
||||||
if (*it == DEFAULT_FONT) {
|
if (*it == DEFAULT_FONT) {
|
||||||
FontCache::LoadDefaultFonts(fs);
|
FontCache::LoadDefaultFonts(fs);
|
||||||
} else if (*it == FALLBACK_FONT) {
|
} else if (*it == FALLBACK_FONT) {
|
||||||
FontCache::LoadFallbackFonts(fs);
|
FontCache::LoadFallbackFonts(fs, FontLoadReason::LanguageFallback);
|
||||||
} else {
|
} else {
|
||||||
FontCache::Register(FontProviderManager::LoadFont(fs, FontType::TrueType, true, std::string{*it}, {}), FontLoadReason::Configured);
|
FontCache::Register(FontProviderManager::LoadFont(fs, FontType::TrueType, true, std::string{*it}, {}), FontLoadReason::Configured);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ enum class FontLoadReason : uint8_t {
|
|||||||
Default,
|
Default,
|
||||||
Configured,
|
Configured,
|
||||||
LanguageFallback,
|
LanguageFallback,
|
||||||
|
MissingFallback,
|
||||||
End,
|
End,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ protected:
|
|||||||
FontCache(FontSize fs) : fs(fs) {}
|
FontCache(FontSize fs) : fs(fs) {}
|
||||||
static void Register(std::unique_ptr<FontCache> &&fc, FontLoadReason load_reason);
|
static void Register(std::unique_ptr<FontCache> &&fc, FontLoadReason load_reason);
|
||||||
static void LoadDefaultFonts(FontSize fs);
|
static void LoadDefaultFonts(FontSize fs);
|
||||||
static void LoadFallbackFonts(FontSize fs);
|
static void LoadFallbackFonts(FontSize fs, FontLoadReason load_reason);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~FontCache() = default;
|
virtual ~FontCache() = default;
|
||||||
|
|||||||
@@ -10,10 +10,15 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "core/math_func.hpp"
|
#include "core/math_func.hpp"
|
||||||
#include "gfx_layout.h"
|
#include "gfx_layout.h"
|
||||||
|
#include "gfx_func.h"
|
||||||
#include "string_func.h"
|
#include "string_func.h"
|
||||||
#include "strings_func.h"
|
#include "strings_func.h"
|
||||||
#include "core/utf8.hpp"
|
#include "core/utf8.hpp"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "timer/timer.h"
|
||||||
|
#include "timer/timer_window.h"
|
||||||
|
#include "viewport_func.h"
|
||||||
|
#include "window_func.h"
|
||||||
|
|
||||||
#include "table/control_codes.h"
|
#include "table/control_codes.h"
|
||||||
|
|
||||||
@@ -37,6 +42,50 @@
|
|||||||
/** Cache of ParagraphLayout lines. */
|
/** Cache of ParagraphLayout lines. */
|
||||||
std::unique_ptr<Layouter::LineCache> Layouter::linecache;
|
std::unique_ptr<Layouter::LineCache> Layouter::linecache;
|
||||||
|
|
||||||
|
class RuntimeMissingGlyphSearcher : public MissingGlyphSearcher {
|
||||||
|
std::array<std::set<char32_t>, FS_END> glyphs{};
|
||||||
|
public:
|
||||||
|
RuntimeMissingGlyphSearcher() : MissingGlyphSearcher(FONTSIZES_ALL) {}
|
||||||
|
|
||||||
|
FontLoadReason GetLoadReason() override { return FontLoadReason::MissingFallback; }
|
||||||
|
|
||||||
|
inline void Insert(FontSize fs, char32_t c)
|
||||||
|
{
|
||||||
|
this->glyphs[fs].insert(c);
|
||||||
|
this->search_timeout.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<char32_t> GetRequiredGlyphs(FontSizes fontsizes) override
|
||||||
|
{
|
||||||
|
std::set<char32_t> r;
|
||||||
|
for (FontSize fs : fontsizes) {
|
||||||
|
r.merge(this->glyphs[fs]);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeoutTimer<TimerWindow> search_timeout{std::chrono::milliseconds(250), [this]()
|
||||||
|
{
|
||||||
|
FontSizes changed_fontsizes{};
|
||||||
|
for (FontSize fs = FS_BEGIN; fs != FS_END; ++fs) {
|
||||||
|
auto &missing = this->glyphs[fs];
|
||||||
|
if (missing.empty()) continue;
|
||||||
|
|
||||||
|
if (FontProviderManager::FindFallbackFont({}, fs, this)) changed_fontsizes.Set(fs);
|
||||||
|
missing.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!changed_fontsizes.Any()) return;
|
||||||
|
|
||||||
|
FontCache::LoadFontCaches(changed_fontsizes);
|
||||||
|
LoadStringWidthTable(changed_fontsizes);
|
||||||
|
UpdateAllVirtCoords();
|
||||||
|
ReInitAllWindows(true);
|
||||||
|
}};
|
||||||
|
};
|
||||||
|
|
||||||
|
static RuntimeMissingGlyphSearcher _missing_glyphs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for getting a ParagraphLayouter of the given type.
|
* Helper for getting a ParagraphLayouter of the given type.
|
||||||
*
|
*
|
||||||
@@ -98,6 +147,7 @@ static inline void GetLayouter(Layouter::LineCacheItem &line, std::string_view s
|
|||||||
FontIndex font_index = FontCache::GetFontIndexForCharacter(state.fontsize, c);
|
FontIndex font_index = FontCache::GetFontIndexForCharacter(state.fontsize, c);
|
||||||
|
|
||||||
if (font_index == INVALID_FONT_INDEX) {
|
if (font_index == INVALID_FONT_INDEX) {
|
||||||
|
_missing_glyphs.Insert(state.fontsize, c);
|
||||||
font_index = FontCache::GetDefaultFontIndex(state.fontsize);
|
font_index = FontCache::GetDefaultFontIndex(state.fontsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user