Add font configuration to skin

This commit is contained in:
Benau 2019-09-21 11:48:22 +08:00
parent 1d74efcd08
commit 25aca4328b
7 changed files with 152 additions and 24 deletions

View File

@ -18,12 +18,13 @@
#include "font/font_manager.hpp"
#include "config/stk_config.hpp"
#include "io/file_manager.hpp"
#include "font/bold_face.hpp"
#include "font/digit_face.hpp"
#include "font/face_ttf.hpp"
#include "font/regular_face.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/skin.hpp"
#include "modes/profile_world.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/string_utils.hpp"
@ -89,10 +90,8 @@ std::vector<FT_Face>
for (const std::string& font : ttf_list)
{
FT_Face face = NULL;
const std::string loc = file_manager
->getAssetChecked(FileManager::TTF, font.c_str(), true);
font_manager->checkFTError(FT_New_Face(
m_ft_library, loc.c_str(), 0, &face), loc + " is loaded");
m_ft_library, font.c_str(), 0, &face), font + " is loaded");
ret.push_back(face);
}
return ret;
@ -563,12 +562,11 @@ void FontManager::initGlyphLayouts(const core::stringw& text,
// ----------------------------------------------------------------------------
FT_Face FontManager::loadColorEmoji()
{
if (stk_config->m_color_emoji_ttf.empty())
if (GUIEngine::getSkin()->getColorEmojiTTF().empty())
return NULL;
FT_Face face = NULL;
const std::string loc = file_manager->getAssetChecked(FileManager::TTF,
stk_config->m_color_emoji_ttf.c_str(), true);
FT_Error err = FT_New_Face(m_ft_library, loc.c_str(), 0, &face);
FT_Error err = FT_New_Face(m_ft_library,
GUIEngine::getSkin()->getColorEmojiTTF().c_str(), 0, &face);
if (err > 0)
{
Log::error("FontManager", "Something wrong when loading color emoji! "
@ -579,7 +577,7 @@ FT_Face FontManager::loadColorEmoji()
if (!FT_HAS_COLOR(face) || face->num_fixed_sizes == 0)
{
Log::error("FontManager", "Bad %s color emoji, ignored.",
stk_config->m_color_emoji_ttf.c_str());
GUIEngine::getSkin()->getColorEmojiTTF().c_str());
checkFTError(FT_Done_Face(face), "removing faces for emoji");
return NULL;
}
@ -601,7 +599,8 @@ void FontManager::loadFonts()
{
#ifndef SERVER_ONLY
// First load the TTF files required by each font
std::vector<FT_Face> normal_ttf = loadTTF(stk_config->m_normal_ttf);
std::vector<FT_Face> normal_ttf = loadTTF(
GUIEngine::getSkin()->getNormalTTF());
std::vector<FT_Face> bold_ttf = normal_ttf;
if (!ProfileWorld::isNoGraphics())
{
@ -622,7 +621,8 @@ void FontManager::loadFonts()
m_ft_faces_to_index[normal_ttf[i]] = i;
}
std::vector<FT_Face> digit_ttf = loadTTF(stk_config->m_digit_ttf);
std::vector<FT_Face> digit_ttf =
loadTTF(GUIEngine::getSkin()->getDigitTTF());
if (!digit_ttf.empty())
m_digit_face = digit_ttf.front();
#endif

View File

@ -75,6 +75,9 @@ private:
std::vector<irr::gui::GlyphLayout> > m_cached_gls;
bool m_has_color_emoji;
// ------------------------------------------------------------------------
std::vector<FT_Face> loadTTF(const std::vector<std::string>& ttf_list);
#endif
/** Map type for each \ref FontWithFace with a index, save getting time in
@ -120,8 +123,6 @@ public:
/** Return the \ref m_ft_library. */
FT_Library getFTLibrary() const { return m_ft_library; }
// ------------------------------------------------------------------------
std::vector<FT_Face> loadTTF(const std::vector<std::string>& ttf_list);
// ------------------------------------------------------------------------
FT_Face loadColorEmoji();
// ------------------------------------------------------------------------
unsigned getShapingDPI() const { return m_shaping_dpi; }

View File

@ -177,6 +177,7 @@ namespace GUIEngine
*/
inline Skin* getSkin() { return Private::g_skin; }
inline void setSkin(Skin* skin) { Private::g_skin = skin; }
Screen* getScreenNamed(const char* name);
/** \return the height of the title font in pixels */

View File

@ -54,7 +54,11 @@ namespace SkinConfig
static std::map<std::string, BoxRenderParams> m_render_params;
static std::map<std::string, SColor> m_colors;
static std::string m_data_path;
static std::vector<std::string> m_normal_ttf;
static std::vector<std::string> m_digit_ttf;
static std::string m_color_emoji_ttf;
static bool m_icon_theme;
static bool m_font;
static void parseElement(const XMLNode* node)
{
@ -156,13 +160,26 @@ namespace SkinConfig
* \brief loads skin information from a STK skin file
* \throw std::runtime_error if file cannot be read
*/
static void loadFromFile(std::string file)
static void loadFromFile(std::string file, bool load_advanced_only)
{
// Clear global variables for android
m_render_params.clear();
m_colors.clear();
m_data_path.clear();
m_normal_ttf.clear();
for (auto& p : stk_config->m_normal_ttf)
m_normal_ttf.push_back(file_manager->getAssetChecked(FileManager::TTF, p, true));
m_digit_ttf.clear();
for (auto& p : stk_config->m_digit_ttf)
m_digit_ttf.push_back(file_manager->getAssetChecked(FileManager::TTF, p, true));
m_color_emoji_ttf.clear();
if (!stk_config->m_color_emoji_ttf.empty())
{
m_color_emoji_ttf = file_manager->getAssetChecked(FileManager::TTF,
stk_config->m_color_emoji_ttf, true);
}
m_icon_theme = false;
m_font = false;
XMLNode* root = file_manager->createXMLTree(file);
if(!root)
@ -179,11 +196,11 @@ namespace SkinConfig
{
const XMLNode* node = root->getNode(i);
if (node->getName() == "element")
if (node->getName() == "element" && !load_advanced_only)
{
parseElement(node);
}
else if (node->getName() == "color")
else if (node->getName() == "color" && !load_advanced_only)
{
parseColor(node);
}
@ -195,8 +212,54 @@ namespace SkinConfig
if (file_manager->fileExists(m_data_path + "data/gui/icons/"))
m_icon_theme = true;
}
std::string color_ttf;
if (node->get("color_emoji_ttf", &color_ttf))
{
std::string test_path = m_data_path + "data/ttf/" + color_ttf;
if (file_manager->fileExists(test_path))
{
m_color_emoji_ttf = test_path;
m_font = true;
}
}
std::vector<std::string> list_ttf;
std::vector<std::string> list_ttf_path;
if (node->get("normal_ttf", &list_ttf))
{
for (auto& t : list_ttf)
{
std::string test_path = m_data_path + "data/ttf/" + t;
if (file_manager->fileExists(test_path))
{
list_ttf_path.push_back(test_path);
m_font = true;
}
}
// We append at the begining of default ttf, so if some
// character missing from skin font we will fallback to
// bundled font later
m_normal_ttf.insert(m_normal_ttf.begin(),
list_ttf_path.begin(), list_ttf_path.end());
}
list_ttf.clear();
list_ttf_path.clear();
if (node->get("digit_ttf", &list_ttf))
{
m_digit_ttf.clear();
for (auto& t : list_ttf)
{
std::string test_path = m_data_path + "data/ttf/" + t;
if (file_manager->fileExists(test_path))
{
list_ttf_path.push_back(test_path);
m_font = true;
}
}
m_digit_ttf.insert(m_digit_ttf.begin(),
list_ttf_path.begin(), list_ttf_path.end());
}
}
else
else if (!load_advanced_only)
{
Log::error("skin", "Unknown node in XML file '%s'.",
node->getName().c_str());
@ -321,6 +384,7 @@ X##_yflip.LowerRightCorner.Y = y1;}
Skin::Skin(IGUISkin* fallback_skin)
{
// fallback_skin will be null if load only basic theming data
std::string skin_id = UserConfigParams::m_skin_file;
std::string skin_name = skin_id.find("addon_") != std::string::npos ?
file_manager->getAddonsFile(
@ -329,7 +393,7 @@ Skin::Skin(IGUISkin* fallback_skin)
try
{
SkinConfig::loadFromFile( skin_name );
SkinConfig::loadFromFile(skin_name, /*load_advanced_only*/fallback_skin == NULL);
}
catch (std::runtime_error& e)
{
@ -339,14 +403,18 @@ Skin::Skin(IGUISkin* fallback_skin)
std::string default_skin_id = UserConfigParams::m_skin_file;
skin_name = file_manager->getAsset(FileManager::SKIN,
default_skin_id + "/stkskin.xml");
SkinConfig::loadFromFile( skin_name );
SkinConfig::loadFromFile(skin_name, /*load_advanced_only*/fallback_skin == NULL);
}
m_bg_image = NULL;
m_fallback_skin = fallback_skin;
m_fallback_skin->grab();
assert(fallback_skin != NULL);
m_fallback_skin = NULL;
if (fallback_skin)
{
m_fallback_skin = fallback_skin;
m_fallback_skin->grab();
assert(fallback_skin != NULL);
}
m_dialog = false;
m_dialog_size = 0.0f;
@ -355,7 +423,8 @@ Skin::Skin(IGUISkin* fallback_skin)
// ----------------------------------------------------------------------------
Skin::~Skin()
{
m_fallback_skin->drop();
if (m_fallback_skin)
m_fallback_skin->drop();
} // ~Skin
// ----------------------------------------------------------------------------
@ -2642,12 +2711,37 @@ const std::string& Skin::getDataPath() const
return SkinConfig::m_data_path;
} // getDataPath
// -----------------------------------------------------------------------------
/* All TTF list here are in absolute path. */
const std::vector<std::string>& Skin::getNormalTTF() const
{
return SkinConfig::m_normal_ttf;
} // getNormalTTF
// -----------------------------------------------------------------------------
const std::vector<std::string>& Skin::getDigitTTF() const
{
return SkinConfig::m_digit_ttf;
} // getDigitTTF
// -----------------------------------------------------------------------------
const std::string& Skin::getColorEmojiTTF() const
{
return SkinConfig::m_color_emoji_ttf;
} // getColorEmojiTTF
// -----------------------------------------------------------------------------
bool Skin::hasIconTheme() const
{
return SkinConfig::m_icon_theme;
} // hasIconTheme
// -----------------------------------------------------------------------------
bool Skin::hasFont() const
{
return SkinConfig::m_font;
} // hasFont
// -----------------------------------------------------------------------------
/* Return a themed icon from its relative path, if not found return the bundled
* icon. */

View File

@ -424,6 +424,14 @@ namespace GUIEngine
bool hasIconTheme() const;
bool hasFont() const;
const std::vector<std::string>& getNormalTTF() const;
const std::vector<std::string>& getDigitTTF() const;
const std::string& getColorEmojiTTF() const;
std::string getThemedIcon(const std::string& relative_path) const;
}; // Skin
} // guiengine

View File

@ -1729,8 +1729,14 @@ void initRest()
exit(0);
}
// We need a temporary skin to load the font list from skin (if any)
GUIEngine::Skin* tmp_skin = new GUIEngine::Skin(NULL);
GUIEngine::setSkin(tmp_skin);
font_manager = new FontManager();
font_manager->loadFonts();
delete tmp_skin;
GUIEngine::setSkin(NULL);
GUIEngine::init(device, driver, StateManager::get());
input_manager = new InputManager();
// Get into menu mode initially.

View File

@ -306,10 +306,28 @@ void OptionsScreenUI::eventCallback(Widget* widget, const std::string& name, con
UserConfigParams::m_skin_file = m_skins[selectedSkin];
irr_driver->unsetMaxTextureSize();
bool prev_icon_theme = GUIEngine::getSkin()->hasIconTheme();
bool prev_font = GUIEngine::getSkin()->hasFont();
GUIEngine::reloadSkin();
if (GUIEngine::getSkin()->hasIconTheme() != prev_icon_theme)
if (GUIEngine::getSkin()->hasIconTheme() != prev_icon_theme ||
prev_font != GUIEngine::getSkin()->hasFont())
{
if (prev_font != GUIEngine::getSkin()->hasFont())
{
GUIEngine::clear();
GUIEngine::cleanUp();
}
GUIEngine::clearScreenCache();
if (prev_font != GUIEngine::getSkin()->hasFont())
{
delete font_manager;
font_manager = new FontManager();
font_manager->loadFonts();
GUIEngine::init(irr_driver->getDevice(), irr_driver->getVideoDriver(),
StateManager::get(), false/*loading*/);
}
Screen* screen_list[] =
{
MainMenuScreen::getInstance(),