From 388ea737f5d37d637556bf40890948bfc36734ce Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Thu, 17 Oct 2019 20:40:50 +0200 Subject: Clean up font caching, fix bitmap fonts --- src/client/fontengine.cpp | 117 ++++++++++++++++++++-------------------------- src/client/fontengine.h | 68 ++++++++++++++++----------- 2 files changed, 90 insertions(+), 95 deletions(-) (limited to 'src/client') diff --git a/src/client/fontengine.cpp b/src/client/fontengine.cpp index 8120f82df..26ceda4c5 100644 --- a/src/client/fontengine.cpp +++ b/src/client/fontengine.cpp @@ -41,11 +41,6 @@ static void font_setting_changed(const std::string &name, void *userdata) g_fontengine->readSettings(); } -unsigned int get_font_cache_index(FontMode mode, bool bold = false, bool italic = false) -{ - return (mode << 2) | (bold << 1) | italic; -} - /******************************************************************************/ FontEngine::FontEngine(Settings* main_settings, gui::IGUIEnvironment* env) : m_settings(main_settings), @@ -106,45 +101,45 @@ void FontEngine::cleanCache() } /******************************************************************************/ -irr::gui::IGUIFont *FontEngine::getFont(unsigned int font_size, FontMode mode, - bool bold, bool italic) +irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec) { - if (mode == FM_Unspecified) { - mode = m_currentMode; + if (spec.mode == FM_Unspecified) { + spec.mode = m_currentMode; } else if (m_currentMode == FM_Simple) { // Freetype disabled -> Force simple mode - mode = (mode == FM_Mono || mode == FM_SimpleMono) ? - FM_SimpleMono : FM_Simple; + spec.mode = (spec.mode == FM_Mono || + spec.mode == FM_SimpleMono) ? + FM_SimpleMono : FM_Simple; + // Support for those could be added, but who cares? + spec.bold = false; + spec.italic = false; } // Fallback to default size - if (font_size == FONT_SIZE_UNSPECIFIED) - font_size = m_default_size[mode]; - - unsigned int cache_index = get_font_cache_index(mode, bold, italic); - - const auto &cache = m_font_cache[cache_index]; - - if (cache.find(font_size) == cache.end()) { - if (mode == FM_Simple || mode == FM_SimpleMono) - initSimpleFont(font_size, mode); - else - initFont(font_size, mode, bold, italic); - } + if (spec.size == FONT_SIZE_UNSPECIFIED) + spec.size = m_default_size[spec.mode]; + + const auto &cache = m_font_cache[spec.getHash()]; + auto it = cache.find(spec.size); + if (it != cache.end()) + return it->second; + + // Font does not yet exist + gui::IGUIFont *font = nullptr; + if (spec.mode == FM_Simple || spec.mode == FM_SimpleMono) + font = initSimpleFont(spec); + else + font = initFont(spec); - if (m_font_cache[cache_index].find(font_size) == - m_font_cache[cache_index].end()) - initFont(font_size, mode, bold, italic); + m_font_cache[spec.getHash()][spec.size] = font; - const auto &font = cache.find(font_size); - return font != cache.end() ? font->second : nullptr; + return font; } /******************************************************************************/ -unsigned int FontEngine::getTextHeight(unsigned int font_size, FontMode mode, - bool bold, bool italic) +unsigned int FontEngine::getTextHeight(const FontSpec &spec) { - irr::gui::IGUIFont *font = getFont(font_size, mode, bold, italic); + irr::gui::IGUIFont *font = getFont(spec); // use current skin font as fallback if (font == NULL) { @@ -156,10 +151,9 @@ unsigned int FontEngine::getTextHeight(unsigned int font_size, FontMode mode, } /******************************************************************************/ -unsigned int FontEngine::getTextWidth(const std::wstring& text, - unsigned int font_size, FontMode mode, bool bold, bool italic) +unsigned int FontEngine::getTextWidth(const std::wstring &text, const FontSpec &spec) { - irr::gui::IGUIFont *font = getFont(font_size, mode, bold, italic); + irr::gui::IGUIFont *font = getFont(spec); // use current skin font as fallback if (font == NULL) { @@ -172,10 +166,9 @@ unsigned int FontEngine::getTextWidth(const std::wstring& text, /** get line height for a specific font (including empty room between lines) */ -unsigned int FontEngine::getLineHeight(unsigned int font_size, FontMode mode, - bool bold, bool italic) +unsigned int FontEngine::getLineHeight(const FontSpec &spec) { - irr::gui::IGUIFont *font = getFont(font_size, mode, bold, italic); + irr::gui::IGUIFont *font = getFont(spec); // use current skin font as fallback if (font == NULL) { @@ -250,21 +243,14 @@ void FontEngine::updateFontCache() } /******************************************************************************/ -void FontEngine::initFont(unsigned int basesize, FontMode mode, - bool bold, bool italic) +gui::IGUIFont *FontEngine::initFont(const FontSpec &spec) { - assert(mode != FM_Unspecified); - assert(basesize != FONT_SIZE_UNSPECIFIED); - - int cache_index = get_font_cache_index(mode, bold, italic); - - if (m_font_cache[cache_index].find(basesize) != - m_font_cache[cache_index].end()) - return; + assert(spec.mode != FM_Unspecified); + assert(spec.size != FONT_SIZE_UNSPECIFIED); std::string setting_prefix = ""; - switch (mode) { + switch (spec.mode) { case FM_Fallback: setting_prefix = "fallback_"; break; @@ -276,12 +262,14 @@ void FontEngine::initFont(unsigned int basesize, FontMode mode, break; } - std::string setting_suffix = (bold) ? - ((italic) ? "_bold_italic" : "_bold") : - ((italic) ? "_italic" : ""); + std::string setting_suffix = ""; + if (spec.bold) + setting_suffix.append("_bold"); + if (spec.italic) + setting_suffix.append("_italic"); u32 size = std::floor(RenderingEngine::getDisplayDensity() * - m_settings->getFloat("gui_scaling") * basesize); + m_settings->getFloat("gui_scaling") * spec.size); if (size == 0) { errorstream << "FontEngine: attempt to use font size 0" << std::endl; @@ -310,10 +298,8 @@ void FontEngine::initFont(unsigned int basesize, FontMode mode, font_path.c_str(), size, true, true, font_shadow, font_shadow_alpha); - if (font) { - m_font_cache[cache_index][basesize] = font; - return; - } + if (font) + return font; errorstream << "FontEngine: Cannot load '" << font_path << "'. Trying to fall back to another path." << std::endl; @@ -332,12 +318,13 @@ void FontEngine::initFont(unsigned int basesize, FontMode mode, } /** initialize a font without freetype */ -void FontEngine::initSimpleFont(unsigned int basesize, FontMode mode) +gui::IGUIFont *FontEngine::initSimpleFont(const FontSpec &spec) { - assert(mode == FM_Simple || mode == FM_SimpleMono); + assert(spec.mode == FM_Simple || spec.mode == FM_SimpleMono); + assert(spec.size != FONT_SIZE_UNSPECIFIED); const std::string &font_path = m_settings->get( - (mode == FM_SimpleMono) ? "mono_font_path" : "font_path"); + (spec.mode == FM_SimpleMono) ? "mono_font_path" : "font_path"); size_t pos_dot = font_path.find_last_of('.'); std::string basename = font_path; @@ -346,19 +333,16 @@ void FontEngine::initSimpleFont(unsigned int basesize, FontMode mode) if (ending == ".ttf") { errorstream << "FontEngine: Found font \"" << font_path << "\" but freetype is not available." << std::endl; - return; + return nullptr; } if (ending == ".xml" || ending == ".png") basename = font_path.substr(0, pos_dot); - if (basesize == FONT_SIZE_UNSPECIFIED) - basesize = DEFAULT_FONT_SIZE; - u32 size = std::floor( RenderingEngine::getDisplayDensity() * m_settings->getFloat("gui_scaling") * - basesize); + spec.size); irr::gui::IGUIFont *font = nullptr; std::string font_extensions[] = { ".png", ".xml" }; @@ -400,6 +384,5 @@ void FontEngine::initSimpleFont(unsigned int basesize, FontMode mode) } } - if (font) - m_font_cache[get_font_cache_index(mode)][basesize] = font; + return font; } diff --git a/src/client/fontengine.h b/src/client/fontengine.h index ecffc7660..53f14c45f 100644 --- a/src/client/fontengine.h +++ b/src/client/fontengine.h @@ -29,7 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define FONT_SIZE_UNSPECIFIED 0xFFFFFFFF -enum FontMode { +enum FontMode : u8 { FM_Standard = 0, FM_Mono, FM_Fallback, @@ -39,6 +39,24 @@ enum FontMode { FM_Unspecified }; +struct FontSpec { + FontSpec(unsigned int font_size, FontMode mode, bool bold, bool italic) : + size(font_size), + mode(mode), + bold(bold), + italic(italic) {} + + u16 getHash() + { + return (mode << 2) | (bold << 1) | italic; + } + + unsigned int size; + FontMode mode; + bool bold; + bool italic; +}; + class FontEngine { public: @@ -47,62 +65,60 @@ public: ~FontEngine(); - /** get Font */ - irr::gui::IGUIFont *getFont(unsigned int font_size, FontMode mode, - bool bold, bool italic); + // Get best possible font specified by FontSpec + irr::gui::IGUIFont *getFont(FontSpec spec); irr::gui::IGUIFont *getFont(unsigned int font_size=FONT_SIZE_UNSPECIFIED, FontMode mode=FM_Unspecified) { - return getFont(font_size, mode, m_default_bold, m_default_italic); + FontSpec spec(font_size, mode, m_default_bold, m_default_italic); + return getFont(spec); } /** get text height for a specific font */ - unsigned int getTextHeight(unsigned int font_size, FontMode mode, - bool bold, bool italic); + unsigned int getTextHeight(const FontSpec &spec); /** get text width if a text for a specific font */ unsigned int getTextHeight( unsigned int font_size=FONT_SIZE_UNSPECIFIED, FontMode mode=FM_Unspecified) { - return getTextHeight(font_size, mode, m_default_bold, m_default_italic); + FontSpec spec(font_size, mode, m_default_bold, m_default_italic); + return getTextHeight(spec); } - unsigned int getTextWidth(const std::wstring& text, - unsigned int font_size, FontMode mode, bool bold, bool italic); + unsigned int getTextWidth(const std::wstring &text, const FontSpec &spec); /** get text width if a text for a specific font */ unsigned int getTextWidth(const std::wstring& text, unsigned int font_size=FONT_SIZE_UNSPECIFIED, FontMode mode=FM_Unspecified) { - return getTextWidth(text, font_size, mode, m_default_bold, - m_default_italic); + FontSpec spec(font_size, mode, m_default_bold, m_default_italic); + return getTextWidth(text, spec); } - unsigned int getTextWidth(const std::string& text, - unsigned int font_size, FontMode mode, bool bold, bool italic) + unsigned int getTextWidth(const std::string &text, const FontSpec &spec) { - return getTextWidth(utf8_to_wide(text), font_size, mode, bold, italic); + return getTextWidth(utf8_to_wide(text), spec); } unsigned int getTextWidth(const std::string& text, unsigned int font_size=FONT_SIZE_UNSPECIFIED, FontMode mode=FM_Unspecified) { - return getTextWidth(utf8_to_wide(text), font_size, mode, m_default_bold, - m_default_italic); + FontSpec spec(font_size, mode, m_default_bold, m_default_italic); + return getTextWidth(utf8_to_wide(text), spec); } /** get line height for a specific font (including empty room between lines) */ - unsigned int getLineHeight(unsigned int font_size, FontMode mode, bool bold, - bool italic); + unsigned int getLineHeight(const FontSpec &spec); unsigned int getLineHeight(unsigned int font_size=FONT_SIZE_UNSPECIFIED, FontMode mode=FM_Unspecified) { - return getLineHeight(font_size, mode, m_default_bold, m_default_italic); + FontSpec spec(font_size, mode, m_default_bold, m_default_italic); + return getLineHeight(spec); } /** get default font size */ @@ -119,14 +135,10 @@ private: void updateFontCache(); /** initialize a new font */ - void initFont( - unsigned int basesize, - FontMode mode, - bool bold, - bool italic); + gui::IGUIFont *initFont(const FontSpec &spec); /** initialize a font without freetype */ - void initSimpleFont(unsigned int basesize, FontMode mode); + gui::IGUIFont *initSimpleFont(const FontSpec &spec); /** update current minetest skin with font changes */ void updateSkin(); @@ -147,8 +159,8 @@ private: unsigned int m_default_size[FM_MaxMode]; /** default bold and italic */ - bool m_default_bold; - bool m_default_italic; + bool m_default_bold = false; + bool m_default_italic = false; /** current font engine mode */ FontMode m_currentMode = FM_Standard; -- cgit v1.2.3