]> git.lizzy.rs Git - minetest.git/blobdiff - src/client/fontengine.cpp
Store stars in a single static mesh buffer
[minetest.git] / src / client / fontengine.cpp
index 93c3460d7ea1d4057e1984d8f87a60da807d8e75..a55420846a74c576150ba3f19d2d200009f63b18 100644 (file)
@@ -23,9 +23,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "config.h"
 #include "porting.h"
 #include "filesys.h"
+#include "gettext.h"
 
 #if USE_FREETYPE
-#include "gettext.h"
 #include "irrlicht_changes/CGUITTFont.h"
 #endif
 
@@ -59,7 +59,12 @@ FontEngine::FontEngine(Settings* main_settings, gui::IGUIEnvironment* env) :
 
        if (m_currentMode == FM_Standard) {
                m_settings->registerChangedCallback("font_size", font_setting_changed, NULL);
+               m_settings->registerChangedCallback("font_bold", font_setting_changed, NULL);
+               m_settings->registerChangedCallback("font_italic", font_setting_changed, NULL);
                m_settings->registerChangedCallback("font_path", font_setting_changed, NULL);
+               m_settings->registerChangedCallback("font_path_bold", font_setting_changed, NULL);
+               m_settings->registerChangedCallback("font_path_italic", font_setting_changed, NULL);
+               m_settings->registerChangedCallback("font_path_bolditalic", font_setting_changed, NULL);
                m_settings->registerChangedCallback("font_shadow", font_setting_changed, NULL);
                m_settings->registerChangedCallback("font_shadow_alpha", font_setting_changed, NULL);
        }
@@ -96,36 +101,45 @@ void FontEngine::cleanCache()
 }
 
 /******************************************************************************/
-irr::gui::IGUIFont* FontEngine::getFont(unsigned int font_size, FontMode mode)
+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];
+       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);
 
-       const auto &cache = m_font_cache[mode];
-       if (cache.find(font_size) == cache.end()) {
-               if (mode == FM_Simple || mode == FM_SimpleMono)
-                       initSimpleFont(font_size, mode);
-               else
-                       initFont(font_size, mode);
-       }
+       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)
+unsigned int FontEngine::getTextHeight(const FontSpec &spec)
 {
-       irr::gui::IGUIFont* font = getFont(font_size, mode);
+       irr::gui::IGUIFont *font = getFont(spec);
 
        // use current skin font as fallback
        if (font == NULL) {
@@ -137,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)
+unsigned int FontEngine::getTextWidth(const std::wstring &text, const FontSpec &spec)
 {
-       irr::gui::IGUIFont* font = getFont(font_size, mode);
+       irr::gui::IGUIFont *font = getFont(spec);
 
        // use current skin font as fallback
        if (font == NULL) {
@@ -153,9 +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)
+unsigned int FontEngine::getLineHeight(const FontSpec &spec)
 {
-       irr::gui::IGUIFont* font = getFont(font_size, mode);
+       irr::gui::IGUIFont *font = getFont(spec);
 
        // use current skin font as fallback
        if (font == NULL) {
@@ -173,6 +186,21 @@ unsigned int FontEngine::getDefaultFontSize()
        return m_default_size[m_currentMode];
 }
 
+unsigned int FontEngine::getFontSize(FontMode mode)
+{
+       if (m_currentMode == FM_Simple) {
+               if (mode == FM_Mono || mode == FM_SimpleMono)
+                       return m_default_size[FM_SimpleMono];
+               else
+                       return m_default_size[FM_Simple];
+       }
+
+       if (mode == FM_Unspecified)
+               return m_default_size[FM_Standard];
+
+       return m_default_size[mode];
+}
+
 /******************************************************************************/
 void FontEngine::readSettings()
 {
@@ -181,8 +209,20 @@ void FontEngine::readSettings()
                m_default_size[FM_Fallback] = m_settings->getU16("fallback_font_size");
                m_default_size[FM_Mono]     = m_settings->getU16("mono_font_size");
 
+               /*~ DO NOT TRANSLATE THIS LITERALLY!
+               This is a special string. Put either "no" or "yes"
+               into the translation field (literally).
+               Choose "yes" if the language requires use of the fallback
+               font, "no" otherwise.
+               The fallback font is (normally) required for languages with
+               non-Latin script, like Chinese.
+               When in doubt, test your translation. */
                m_currentMode = is_yes(gettext("needs_fallback_font")) ?
                                FM_Fallback : FM_Standard;
+
+               m_default_bold = m_settings->getBool("font_bold");
+               m_default_italic = m_settings->getBool("font_italic");
+
        } else {
                m_currentMode = FM_Simple;
        }
@@ -214,7 +254,7 @@ void FontEngine::updateSkin()
        FATAL_ERROR_IF(font == NULL, "Could not create/get font");
 
        u32 text_height = font->getDimension(L"Hello, world!").Height;
-       infostream << "text_height=" << text_height << std::endl;
+       infostream << "FontEngine: measured text_height=" << text_height << std::endl;
 }
 
 /******************************************************************************/
@@ -226,18 +266,14 @@ void FontEngine::updateFontCache()
 }
 
 /******************************************************************************/
-void FontEngine::initFont(unsigned int basesize, FontMode mode)
+gui::IGUIFont *FontEngine::initFont(const FontSpec &spec)
 {
-       assert(mode != FM_Unspecified);
-       assert(basesize != FONT_SIZE_UNSPECIFIED);
-
-       if (m_font_cache[mode].find(basesize) != m_font_cache[mode].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;
@@ -249,8 +285,15 @@ void FontEngine::initFont(unsigned int basesize, FontMode mode)
                        break;
        }
 
+       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;
                errorstream << "  display density: " << RenderingEngine::getDisplayDensity() << std::endl;
@@ -260,10 +303,14 @@ void FontEngine::initFont(unsigned int basesize, FontMode mode)
        u16 font_shadow       = 0;
        u16 font_shadow_alpha = 0;
        g_settings->getU16NoEx(setting_prefix + "font_shadow", font_shadow);
-       g_settings->getU16NoEx(setting_prefix + "font_shadow_alpha", font_shadow_alpha);
+       g_settings->getU16NoEx(setting_prefix + "font_shadow_alpha",
+                       font_shadow_alpha);
+
+       std::string wanted_font_path;
+       wanted_font_path = g_settings->get(setting_prefix + "font_path" + setting_suffix);
 
        std::string fallback_settings[] = {
-               m_settings->get(setting_prefix + "font_path"),
+               wanted_font_path,
                m_settings->get("fallback_font_path"),
                m_settings->getDefault(setting_prefix + "font_path")
        };
@@ -274,11 +321,8 @@ void FontEngine::initFont(unsigned int basesize, FontMode mode)
                                font_path.c_str(), size, true, true, font_shadow,
                                font_shadow_alpha);
 
-               if (font) {
-                       font->grab();
-                       m_font_cache[mode][basesize] = font;
-                       return;
-               }
+               if (font)
+                       return font;
 
                errorstream << "FontEngine: Cannot load '" << font_path <<
                                "'. Trying to fall back to another path." << std::endl;
@@ -297,12 +341,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;
@@ -311,19 +356,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" };
@@ -341,7 +383,7 @@ void FontEngine::initSimpleFont(unsigned int basesize, FontMode mode)
                        path.str(""); // Clear
                        path << basename << "_" << (size + offset * sign) << ext;
 
-                       if (!fs::PathExists(path.str())) 
+                       if (!fs::PathExists(path.str()))
                                continue;
 
                        font = m_env->getFont(path.str().c_str());
@@ -365,8 +407,5 @@ void FontEngine::initSimpleFont(unsigned int basesize, FontMode mode)
                }
        }
 
-       if (font) {
-               font->grab();
-               m_font_cache[mode][basesize] = font;
-       }
+       return font;
 }