Add font configuration to skin
This commit is contained in:
parent
1d74efcd08
commit
25aca4328b
@ -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
|
||||
|
@ -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; }
|
||||
|
@ -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 */
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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(),
|
||||
|
Loading…
Reference in New Issue
Block a user