mirror of
https://github.com/minetest/minetest.git
synced 2024-11-23 16:13:46 +01:00
Clean up font caching, fix bitmap fonts
This commit is contained in:
parent
72416a6a1f
commit
388ea737f5
@ -41,11 +41,6 @@ static void font_setting_changed(const std::string &name, void *userdata)
|
|||||||
g_fontengine->readSettings();
|
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) :
|
FontEngine::FontEngine(Settings* main_settings, gui::IGUIEnvironment* env) :
|
||||||
m_settings(main_settings),
|
m_settings(main_settings),
|
||||||
@ -106,45 +101,45 @@ void FontEngine::cleanCache()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
irr::gui::IGUIFont *FontEngine::getFont(unsigned int font_size, FontMode mode,
|
irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec)
|
||||||
bool bold, bool italic)
|
|
||||||
{
|
{
|
||||||
if (mode == FM_Unspecified) {
|
if (spec.mode == FM_Unspecified) {
|
||||||
mode = m_currentMode;
|
spec.mode = m_currentMode;
|
||||||
} else if (m_currentMode == FM_Simple) {
|
} else if (m_currentMode == FM_Simple) {
|
||||||
// Freetype disabled -> Force simple mode
|
// Freetype disabled -> Force simple mode
|
||||||
mode = (mode == FM_Mono || mode == FM_SimpleMono) ?
|
spec.mode = (spec.mode == FM_Mono ||
|
||||||
|
spec.mode == FM_SimpleMono) ?
|
||||||
FM_SimpleMono : FM_Simple;
|
FM_SimpleMono : FM_Simple;
|
||||||
|
// Support for those could be added, but who cares?
|
||||||
|
spec.bold = false;
|
||||||
|
spec.italic = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to default size
|
// Fallback to default size
|
||||||
if (font_size == FONT_SIZE_UNSPECIFIED)
|
if (spec.size == FONT_SIZE_UNSPECIFIED)
|
||||||
font_size = m_default_size[mode];
|
spec.size = m_default_size[spec.mode];
|
||||||
|
|
||||||
unsigned int cache_index = get_font_cache_index(mode, bold, italic);
|
const auto &cache = m_font_cache[spec.getHash()];
|
||||||
|
auto it = cache.find(spec.size);
|
||||||
|
if (it != cache.end())
|
||||||
|
return it->second;
|
||||||
|
|
||||||
const auto &cache = m_font_cache[cache_index];
|
// Font does not yet exist
|
||||||
|
gui::IGUIFont *font = nullptr;
|
||||||
if (cache.find(font_size) == cache.end()) {
|
if (spec.mode == FM_Simple || spec.mode == FM_SimpleMono)
|
||||||
if (mode == FM_Simple || mode == FM_SimpleMono)
|
font = initSimpleFont(spec);
|
||||||
initSimpleFont(font_size, mode);
|
|
||||||
else
|
else
|
||||||
initFont(font_size, mode, bold, italic);
|
font = initFont(spec);
|
||||||
}
|
|
||||||
|
|
||||||
if (m_font_cache[cache_index].find(font_size) ==
|
m_font_cache[spec.getHash()][spec.size] = font;
|
||||||
m_font_cache[cache_index].end())
|
|
||||||
initFont(font_size, mode, bold, italic);
|
|
||||||
|
|
||||||
const auto &font = cache.find(font_size);
|
return font;
|
||||||
return font != cache.end() ? font->second : nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
unsigned int FontEngine::getTextHeight(unsigned int font_size, FontMode mode,
|
unsigned int FontEngine::getTextHeight(const FontSpec &spec)
|
||||||
bool bold, bool italic)
|
|
||||||
{
|
{
|
||||||
irr::gui::IGUIFont *font = getFont(font_size, mode, bold, italic);
|
irr::gui::IGUIFont *font = getFont(spec);
|
||||||
|
|
||||||
// use current skin font as fallback
|
// use current skin font as fallback
|
||||||
if (font == NULL) {
|
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 FontEngine::getTextWidth(const std::wstring &text, const FontSpec &spec)
|
||||||
unsigned int font_size, FontMode mode, bool bold, bool italic)
|
|
||||||
{
|
{
|
||||||
irr::gui::IGUIFont *font = getFont(font_size, mode, bold, italic);
|
irr::gui::IGUIFont *font = getFont(spec);
|
||||||
|
|
||||||
// use current skin font as fallback
|
// use current skin font as fallback
|
||||||
if (font == NULL) {
|
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) */
|
/** 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)
|
||||||
bool bold, bool italic)
|
|
||||||
{
|
{
|
||||||
irr::gui::IGUIFont *font = getFont(font_size, mode, bold, italic);
|
irr::gui::IGUIFont *font = getFont(spec);
|
||||||
|
|
||||||
// use current skin font as fallback
|
// use current skin font as fallback
|
||||||
if (font == NULL) {
|
if (font == NULL) {
|
||||||
@ -250,21 +243,14 @@ void FontEngine::updateFontCache()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
void FontEngine::initFont(unsigned int basesize, FontMode mode,
|
gui::IGUIFont *FontEngine::initFont(const FontSpec &spec)
|
||||||
bool bold, bool italic)
|
|
||||||
{
|
{
|
||||||
assert(mode != FM_Unspecified);
|
assert(spec.mode != FM_Unspecified);
|
||||||
assert(basesize != FONT_SIZE_UNSPECIFIED);
|
assert(spec.size != 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;
|
|
||||||
|
|
||||||
std::string setting_prefix = "";
|
std::string setting_prefix = "";
|
||||||
|
|
||||||
switch (mode) {
|
switch (spec.mode) {
|
||||||
case FM_Fallback:
|
case FM_Fallback:
|
||||||
setting_prefix = "fallback_";
|
setting_prefix = "fallback_";
|
||||||
break;
|
break;
|
||||||
@ -276,12 +262,14 @@ void FontEngine::initFont(unsigned int basesize, FontMode mode,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string setting_suffix = (bold) ?
|
std::string setting_suffix = "";
|
||||||
((italic) ? "_bold_italic" : "_bold") :
|
if (spec.bold)
|
||||||
((italic) ? "_italic" : "");
|
setting_suffix.append("_bold");
|
||||||
|
if (spec.italic)
|
||||||
|
setting_suffix.append("_italic");
|
||||||
|
|
||||||
u32 size = std::floor(RenderingEngine::getDisplayDensity() *
|
u32 size = std::floor(RenderingEngine::getDisplayDensity() *
|
||||||
m_settings->getFloat("gui_scaling") * basesize);
|
m_settings->getFloat("gui_scaling") * spec.size);
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
errorstream << "FontEngine: attempt to use font size 0" << std::endl;
|
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_path.c_str(), size, true, true, font_shadow,
|
||||||
font_shadow_alpha);
|
font_shadow_alpha);
|
||||||
|
|
||||||
if (font) {
|
if (font)
|
||||||
m_font_cache[cache_index][basesize] = font;
|
return font;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
errorstream << "FontEngine: Cannot load '" << font_path <<
|
errorstream << "FontEngine: Cannot load '" << font_path <<
|
||||||
"'. Trying to fall back to another path." << std::endl;
|
"'. 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 */
|
/** 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(
|
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('.');
|
size_t pos_dot = font_path.find_last_of('.');
|
||||||
std::string basename = font_path;
|
std::string basename = font_path;
|
||||||
@ -346,19 +333,16 @@ void FontEngine::initSimpleFont(unsigned int basesize, FontMode mode)
|
|||||||
if (ending == ".ttf") {
|
if (ending == ".ttf") {
|
||||||
errorstream << "FontEngine: Found font \"" << font_path
|
errorstream << "FontEngine: Found font \"" << font_path
|
||||||
<< "\" but freetype is not available." << std::endl;
|
<< "\" but freetype is not available." << std::endl;
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ending == ".xml" || ending == ".png")
|
if (ending == ".xml" || ending == ".png")
|
||||||
basename = font_path.substr(0, pos_dot);
|
basename = font_path.substr(0, pos_dot);
|
||||||
|
|
||||||
if (basesize == FONT_SIZE_UNSPECIFIED)
|
|
||||||
basesize = DEFAULT_FONT_SIZE;
|
|
||||||
|
|
||||||
u32 size = std::floor(
|
u32 size = std::floor(
|
||||||
RenderingEngine::getDisplayDensity() *
|
RenderingEngine::getDisplayDensity() *
|
||||||
m_settings->getFloat("gui_scaling") *
|
m_settings->getFloat("gui_scaling") *
|
||||||
basesize);
|
spec.size);
|
||||||
|
|
||||||
irr::gui::IGUIFont *font = nullptr;
|
irr::gui::IGUIFont *font = nullptr;
|
||||||
std::string font_extensions[] = { ".png", ".xml" };
|
std::string font_extensions[] = { ".png", ".xml" };
|
||||||
@ -400,6 +384,5 @@ void FontEngine::initSimpleFont(unsigned int basesize, FontMode mode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font)
|
return font;
|
||||||
m_font_cache[get_font_cache_index(mode)][basesize] = font;
|
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#define FONT_SIZE_UNSPECIFIED 0xFFFFFFFF
|
#define FONT_SIZE_UNSPECIFIED 0xFFFFFFFF
|
||||||
|
|
||||||
enum FontMode {
|
enum FontMode : u8 {
|
||||||
FM_Standard = 0,
|
FM_Standard = 0,
|
||||||
FM_Mono,
|
FM_Mono,
|
||||||
FM_Fallback,
|
FM_Fallback,
|
||||||
@ -39,6 +39,24 @@ enum FontMode {
|
|||||||
FM_Unspecified
|
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
|
class FontEngine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -47,62 +65,60 @@ public:
|
|||||||
|
|
||||||
~FontEngine();
|
~FontEngine();
|
||||||
|
|
||||||
/** get Font */
|
// Get best possible font specified by FontSpec
|
||||||
irr::gui::IGUIFont *getFont(unsigned int font_size, FontMode mode,
|
irr::gui::IGUIFont *getFont(FontSpec spec);
|
||||||
bool bold, bool italic);
|
|
||||||
|
|
||||||
irr::gui::IGUIFont *getFont(unsigned int font_size=FONT_SIZE_UNSPECIFIED,
|
irr::gui::IGUIFont *getFont(unsigned int font_size=FONT_SIZE_UNSPECIFIED,
|
||||||
FontMode mode=FM_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 */
|
/** get text height for a specific font */
|
||||||
unsigned int getTextHeight(unsigned int font_size, FontMode mode,
|
unsigned int getTextHeight(const FontSpec &spec);
|
||||||
bool bold, bool italic);
|
|
||||||
|
|
||||||
/** get text width if a text for a specific font */
|
/** get text width if a text for a specific font */
|
||||||
unsigned int getTextHeight(
|
unsigned int getTextHeight(
|
||||||
unsigned int font_size=FONT_SIZE_UNSPECIFIED,
|
unsigned int font_size=FONT_SIZE_UNSPECIFIED,
|
||||||
FontMode mode=FM_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 getTextWidth(const std::wstring &text, const FontSpec &spec);
|
||||||
unsigned int font_size, FontMode mode, bool bold, bool italic);
|
|
||||||
|
|
||||||
/** get text width if a text for a specific font */
|
/** get text width if a text for a specific font */
|
||||||
unsigned int getTextWidth(const std::wstring& text,
|
unsigned int getTextWidth(const std::wstring& text,
|
||||||
unsigned int font_size=FONT_SIZE_UNSPECIFIED,
|
unsigned int font_size=FONT_SIZE_UNSPECIFIED,
|
||||||
FontMode mode=FM_Unspecified)
|
FontMode mode=FM_Unspecified)
|
||||||
{
|
{
|
||||||
return getTextWidth(text, font_size, mode, m_default_bold,
|
FontSpec spec(font_size, mode, m_default_bold, m_default_italic);
|
||||||
m_default_italic);
|
return getTextWidth(text, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int getTextWidth(const std::string& text,
|
unsigned int getTextWidth(const std::string &text, const FontSpec &spec)
|
||||||
unsigned int font_size, FontMode mode, bool bold, bool italic)
|
|
||||||
{
|
{
|
||||||
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 getTextWidth(const std::string& text,
|
||||||
unsigned int font_size=FONT_SIZE_UNSPECIFIED,
|
unsigned int font_size=FONT_SIZE_UNSPECIFIED,
|
||||||
FontMode mode=FM_Unspecified)
|
FontMode mode=FM_Unspecified)
|
||||||
{
|
{
|
||||||
return getTextWidth(utf8_to_wide(text), font_size, mode, m_default_bold,
|
FontSpec spec(font_size, mode, m_default_bold, m_default_italic);
|
||||||
m_default_italic);
|
return getTextWidth(utf8_to_wide(text), spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** get line height for a specific font (including empty room between lines) */
|
/** get line height for a specific font (including empty room between lines) */
|
||||||
unsigned int getLineHeight(unsigned int font_size, FontMode mode, bool bold,
|
unsigned int getLineHeight(const FontSpec &spec);
|
||||||
bool italic);
|
|
||||||
|
|
||||||
unsigned int getLineHeight(unsigned int font_size=FONT_SIZE_UNSPECIFIED,
|
unsigned int getLineHeight(unsigned int font_size=FONT_SIZE_UNSPECIFIED,
|
||||||
FontMode mode=FM_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 */
|
/** get default font size */
|
||||||
@ -119,14 +135,10 @@ private:
|
|||||||
void updateFontCache();
|
void updateFontCache();
|
||||||
|
|
||||||
/** initialize a new font */
|
/** initialize a new font */
|
||||||
void initFont(
|
gui::IGUIFont *initFont(const FontSpec &spec);
|
||||||
unsigned int basesize,
|
|
||||||
FontMode mode,
|
|
||||||
bool bold,
|
|
||||||
bool italic);
|
|
||||||
|
|
||||||
/** initialize a font without freetype */
|
/** 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 */
|
/** update current minetest skin with font changes */
|
||||||
void updateSkin();
|
void updateSkin();
|
||||||
@ -147,8 +159,8 @@ private:
|
|||||||
unsigned int m_default_size[FM_MaxMode];
|
unsigned int m_default_size[FM_MaxMode];
|
||||||
|
|
||||||
/** default bold and italic */
|
/** default bold and italic */
|
||||||
bool m_default_bold;
|
bool m_default_bold = false;
|
||||||
bool m_default_italic;
|
bool m_default_italic = false;
|
||||||
|
|
||||||
/** current font engine mode */
|
/** current font engine mode */
|
||||||
FontMode m_currentMode = FM_Standard;
|
FontMode m_currentMode = FM_Standard;
|
||||||
|
@ -71,14 +71,12 @@ void ParsedText::Element::setStyle(StyleList &style)
|
|||||||
if (style["fontstyle"] == "mono")
|
if (style["fontstyle"] == "mono")
|
||||||
font_mode = FM_Mono;
|
font_mode = FM_Mono;
|
||||||
|
|
||||||
|
FontSpec spec(font_size, font_mode,
|
||||||
|
is_yes(style["bold"]), is_yes(style["italic"]));
|
||||||
|
|
||||||
// TODO: find a way to check font validity
|
// TODO: find a way to check font validity
|
||||||
// Build a new fontengine ?
|
// Build a new fontengine ?
|
||||||
this->font =
|
this->font = g_fontengine->getFont(spec);
|
||||||
#if USE_FREETYPE
|
|
||||||
(gui::CGUITTFont *)
|
|
||||||
#endif
|
|
||||||
g_fontengine->getFont(font_size, font_mode,
|
|
||||||
is_yes(style["bold"]), is_yes(style["italic"]));
|
|
||||||
|
|
||||||
if (!this->font)
|
if (!this->font)
|
||||||
printf("No font found ! Size=%d, mode=%d, bold=%s, italic=%s\n",
|
printf("No font found ! Size=%d, mode=%d, bold=%s, italic=%s\n",
|
||||||
@ -606,7 +604,10 @@ TextDrawer::TextDrawer(const wchar_t *text, Client *client,
|
|||||||
e.dim.Width = e.font->getDimension(e.text.c_str()).Width;
|
e.dim.Width = e.font->getDimension(e.text.c_str()).Width;
|
||||||
e.dim.Height = e.font->getDimension(L"Yy").Height;
|
e.dim.Height = e.font->getDimension(L"Yy").Height;
|
||||||
#if USE_FREETYPE
|
#if USE_FREETYPE
|
||||||
e.baseline = e.dim.Height - 1 - e.font->getAscender()/64;
|
if (e.font->getType() == irr::gui::EGFT_CUSTOM) {
|
||||||
|
e.baseline = e.dim.Height - 1 -
|
||||||
|
((irr::gui::CGUITTFont *)e.font)->getAscender() / 64;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
e.dim = {0, 0};
|
e.dim = {0, 0};
|
||||||
|
@ -96,11 +96,7 @@ public:
|
|||||||
|
|
||||||
ValignType valign;
|
ValignType valign;
|
||||||
|
|
||||||
#if USE_FREETYPE
|
|
||||||
gui::CGUITTFont *font;
|
|
||||||
#else
|
|
||||||
gui::IGUIFont *font;
|
gui::IGUIFont *font;
|
||||||
#endif
|
|
||||||
|
|
||||||
irr::video::SColor color;
|
irr::video::SColor color;
|
||||||
irr::video::SColor hovercolor;
|
irr::video::SColor hovercolor;
|
||||||
|
Loading…
Reference in New Issue
Block a user