mirror of
https://github.com/minetest/minetest.git
synced 2024-11-30 03:23:45 +01:00
Replace fallback font nonsense with automatic per-glyph fallback (#11084)
This commit is contained in:
parent
5f4c78a77d
commit
8d89f5f0cc
@ -859,7 +859,7 @@ font_path (Regular font path) filepath fonts/Arimo-Regular.ttf
|
|||||||
|
|
||||||
font_path_bold (Bold font path) filepath fonts/Arimo-Bold.ttf
|
font_path_bold (Bold font path) filepath fonts/Arimo-Bold.ttf
|
||||||
font_path_italic (Italic font path) filepath fonts/Arimo-Italic.ttf
|
font_path_italic (Italic font path) filepath fonts/Arimo-Italic.ttf
|
||||||
font_path_bolditalic (Bold and italic font path) filepath fonts/Arimo-BoldItalic.ttf
|
font_path_bold_italic (Bold and italic font path) filepath fonts/Arimo-BoldItalic.ttf
|
||||||
|
|
||||||
# Font size of the monospace font in point (pt).
|
# Font size of the monospace font in point (pt).
|
||||||
mono_font_size (Monospace font size) int 15 1
|
mono_font_size (Monospace font size) int 15 1
|
||||||
@ -872,16 +872,7 @@ mono_font_path (Monospace font path) filepath fonts/Cousine-Regular.ttf
|
|||||||
|
|
||||||
mono_font_path_bold (Bold monospace font path) filepath fonts/Cousine-Bold.ttf
|
mono_font_path_bold (Bold monospace font path) filepath fonts/Cousine-Bold.ttf
|
||||||
mono_font_path_italic (Italic monospace font path) filepath fonts/Cousine-Italic.ttf
|
mono_font_path_italic (Italic monospace font path) filepath fonts/Cousine-Italic.ttf
|
||||||
mono_font_path_bolditalic (Bold and italic monospace font path) filepath fonts/Cousine-BoldItalic.ttf
|
mono_font_path_bold_italic (Bold and italic monospace font path) filepath fonts/Cousine-BoldItalic.ttf
|
||||||
|
|
||||||
# Font size of the fallback font in point (pt).
|
|
||||||
fallback_font_size (Fallback font size) int 15 1
|
|
||||||
|
|
||||||
# Shadow offset (in pixels) of the fallback font. If 0, then shadow will not be drawn.
|
|
||||||
fallback_font_shadow (Fallback font shadow) int 1
|
|
||||||
|
|
||||||
# Opaqueness (alpha) of the shadow behind the fallback font, between 0 and 255.
|
|
||||||
fallback_font_shadow_alpha (Fallback font shadow alpha) int 128 0 255
|
|
||||||
|
|
||||||
# Path of the fallback font.
|
# Path of the fallback font.
|
||||||
# If “freetype” setting is enabled: Must be a TrueType font.
|
# If “freetype” setting is enabled: Must be a TrueType font.
|
||||||
|
@ -1085,18 +1085,6 @@ msgstr ""
|
|||||||
msgid "Invalid gamespec."
|
msgid "Invalid gamespec."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. ~ 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.
|
|
||||||
#: src/client/fontengine.cpp
|
|
||||||
msgid "needs_fallback_font"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/client/game.cpp
|
#: src/client/game.cpp
|
||||||
msgid "Shutting down..."
|
msgid "Shutting down..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -668,7 +668,10 @@ endif(BUILD_SERVER)
|
|||||||
# see issue #4638
|
# see issue #4638
|
||||||
set(GETTEXT_BLACKLISTED_LOCALES
|
set(GETTEXT_BLACKLISTED_LOCALES
|
||||||
ar
|
ar
|
||||||
|
dv
|
||||||
he
|
he
|
||||||
|
hi
|
||||||
|
kn
|
||||||
ky
|
ky
|
||||||
ms_Arab
|
ms_Arab
|
||||||
th
|
th
|
||||||
|
@ -56,7 +56,7 @@ FontEngine::FontEngine(gui::IGUIEnvironment* env) :
|
|||||||
|
|
||||||
readSettings();
|
readSettings();
|
||||||
|
|
||||||
if (m_currentMode == FM_Standard) {
|
if (m_currentMode != FM_Simple) {
|
||||||
g_settings->registerChangedCallback("font_size", font_setting_changed, NULL);
|
g_settings->registerChangedCallback("font_size", font_setting_changed, NULL);
|
||||||
g_settings->registerChangedCallback("font_bold", font_setting_changed, NULL);
|
g_settings->registerChangedCallback("font_bold", font_setting_changed, NULL);
|
||||||
g_settings->registerChangedCallback("font_italic", font_setting_changed, NULL);
|
g_settings->registerChangedCallback("font_italic", font_setting_changed, NULL);
|
||||||
@ -66,12 +66,7 @@ FontEngine::FontEngine(gui::IGUIEnvironment* env) :
|
|||||||
g_settings->registerChangedCallback("font_path_bolditalic", font_setting_changed, NULL);
|
g_settings->registerChangedCallback("font_path_bolditalic", font_setting_changed, NULL);
|
||||||
g_settings->registerChangedCallback("font_shadow", font_setting_changed, NULL);
|
g_settings->registerChangedCallback("font_shadow", font_setting_changed, NULL);
|
||||||
g_settings->registerChangedCallback("font_shadow_alpha", font_setting_changed, NULL);
|
g_settings->registerChangedCallback("font_shadow_alpha", font_setting_changed, NULL);
|
||||||
}
|
|
||||||
else if (m_currentMode == FM_Fallback) {
|
|
||||||
g_settings->registerChangedCallback("fallback_font_size", font_setting_changed, NULL);
|
|
||||||
g_settings->registerChangedCallback("fallback_font_path", font_setting_changed, NULL);
|
g_settings->registerChangedCallback("fallback_font_path", font_setting_changed, NULL);
|
||||||
g_settings->registerChangedCallback("fallback_font_shadow", font_setting_changed, NULL);
|
|
||||||
g_settings->registerChangedCallback("fallback_font_shadow_alpha", font_setting_changed, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_settings->registerChangedCallback("mono_font_path", font_setting_changed, NULL);
|
g_settings->registerChangedCallback("mono_font_path", font_setting_changed, NULL);
|
||||||
@ -101,6 +96,11 @@ void FontEngine::cleanCache()
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec)
|
irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec)
|
||||||
|
{
|
||||||
|
return getFont(spec, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec, bool may_fail)
|
||||||
{
|
{
|
||||||
if (spec.mode == FM_Unspecified) {
|
if (spec.mode == FM_Unspecified) {
|
||||||
spec.mode = m_currentMode;
|
spec.mode = m_currentMode;
|
||||||
@ -112,6 +112,10 @@ irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec)
|
|||||||
// Support for those could be added, but who cares?
|
// Support for those could be added, but who cares?
|
||||||
spec.bold = false;
|
spec.bold = false;
|
||||||
spec.italic = false;
|
spec.italic = false;
|
||||||
|
} else if (spec.mode == _FM_Fallback) {
|
||||||
|
// Fallback font doesn't support these either
|
||||||
|
spec.bold = false;
|
||||||
|
spec.italic = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to default size
|
// Fallback to default size
|
||||||
@ -130,6 +134,13 @@ irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec)
|
|||||||
else
|
else
|
||||||
font = initFont(spec);
|
font = initFont(spec);
|
||||||
|
|
||||||
|
if (!font && !may_fail) {
|
||||||
|
errorstream << "Minetest cannot continue without a valid font. "
|
||||||
|
"Please correct the 'font_path' setting or install the font "
|
||||||
|
"file in the proper location." << std::endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
m_font_cache[spec.getHash()][spec.size] = font;
|
m_font_cache[spec.getHash()][spec.size] = font;
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
@ -205,20 +216,9 @@ void FontEngine::readSettings()
|
|||||||
{
|
{
|
||||||
if (USE_FREETYPE && g_settings->getBool("freetype")) {
|
if (USE_FREETYPE && g_settings->getBool("freetype")) {
|
||||||
m_default_size[FM_Standard] = g_settings->getU16("font_size");
|
m_default_size[FM_Standard] = g_settings->getU16("font_size");
|
||||||
m_default_size[FM_Fallback] = g_settings->getU16("fallback_font_size");
|
m_default_size[_FM_Fallback] = g_settings->getU16("font_size");
|
||||||
m_default_size[FM_Mono] = g_settings->getU16("mono_font_size");
|
m_default_size[FM_Mono] = g_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 = g_settings->getBool("font_bold");
|
m_default_bold = g_settings->getBool("font_bold");
|
||||||
m_default_italic = g_settings->getBool("font_italic");
|
m_default_italic = g_settings->getBool("font_italic");
|
||||||
|
|
||||||
@ -271,18 +271,8 @@ gui::IGUIFont *FontEngine::initFont(const FontSpec &spec)
|
|||||||
assert(spec.size != FONT_SIZE_UNSPECIFIED);
|
assert(spec.size != FONT_SIZE_UNSPECIFIED);
|
||||||
|
|
||||||
std::string setting_prefix = "";
|
std::string setting_prefix = "";
|
||||||
|
if (spec.mode == FM_Mono)
|
||||||
switch (spec.mode) {
|
|
||||||
case FM_Fallback:
|
|
||||||
setting_prefix = "fallback_";
|
|
||||||
break;
|
|
||||||
case FM_Mono:
|
|
||||||
case FM_SimpleMono:
|
|
||||||
setting_prefix = "mono_";
|
setting_prefix = "mono_";
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string setting_suffix = "";
|
std::string setting_suffix = "";
|
||||||
if (spec.bold)
|
if (spec.bold)
|
||||||
@ -305,38 +295,41 @@ gui::IGUIFont *FontEngine::initFont(const FontSpec &spec)
|
|||||||
g_settings->getU16NoEx(setting_prefix + "font_shadow_alpha",
|
g_settings->getU16NoEx(setting_prefix + "font_shadow_alpha",
|
||||||
font_shadow_alpha);
|
font_shadow_alpha);
|
||||||
|
|
||||||
std::string wanted_font_path;
|
std::string path_setting;
|
||||||
wanted_font_path = g_settings->get(setting_prefix + "font_path" + setting_suffix);
|
if (spec.mode == _FM_Fallback)
|
||||||
|
path_setting = "fallback_font_path";
|
||||||
|
else
|
||||||
|
path_setting = setting_prefix + "font_path" + setting_suffix;
|
||||||
|
|
||||||
std::string fallback_settings[] = {
|
std::string fallback_settings[] = {
|
||||||
wanted_font_path,
|
g_settings->get(path_setting),
|
||||||
g_settings->get("fallback_font_path"),
|
Settings::getLayer(SL_DEFAULTS)->get(path_setting)
|
||||||
Settings::getLayer(SL_DEFAULTS)->get(setting_prefix + "font_path")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#if USE_FREETYPE
|
#if USE_FREETYPE
|
||||||
for (const std::string &font_path : fallback_settings) {
|
for (const std::string &font_path : fallback_settings) {
|
||||||
irr::gui::IGUIFont *font = gui::CGUITTFont::createTTFont(m_env,
|
gui::CGUITTFont *font = gui::CGUITTFont::createTTFont(m_env,
|
||||||
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) {
|
||||||
return font;
|
|
||||||
|
|
||||||
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;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (spec.mode != _FM_Fallback) {
|
||||||
// give up
|
FontSpec spec2(spec);
|
||||||
errorstream << "minetest can not continue without a valid font. "
|
spec2.mode = _FM_Fallback;
|
||||||
"Please correct the 'font_path' setting or install the font "
|
font->setFallback(getFont(spec2, true));
|
||||||
"file in the proper location" << std::endl;
|
}
|
||||||
|
return font;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
errorstream << "FontEngine: Tried to load freetype fonts but Minetest was"
|
errorstream << "FontEngine: Tried to load TTF font but Minetest was"
|
||||||
" not compiled with that library." << std::endl;
|
" compiled without Freetype." << std::endl;
|
||||||
#endif
|
#endif
|
||||||
abort();
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** initialize a font without freetype */
|
/** initialize a font without freetype */
|
||||||
|
@ -33,7 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
enum FontMode : u8 {
|
enum FontMode : u8 {
|
||||||
FM_Standard = 0,
|
FM_Standard = 0,
|
||||||
FM_Mono,
|
FM_Mono,
|
||||||
FM_Fallback,
|
_FM_Fallback, // do not use directly
|
||||||
FM_Simple,
|
FM_Simple,
|
||||||
FM_SimpleMono,
|
FM_SimpleMono,
|
||||||
FM_MaxMode,
|
FM_MaxMode,
|
||||||
@ -47,7 +47,7 @@ struct FontSpec {
|
|||||||
bold(bold),
|
bold(bold),
|
||||||
italic(italic) {}
|
italic(italic) {}
|
||||||
|
|
||||||
u16 getHash()
|
u16 getHash() const
|
||||||
{
|
{
|
||||||
return (mode << 2) | (static_cast<u8>(bold) << 1) | static_cast<u8>(italic);
|
return (mode << 2) | (static_cast<u8>(bold) << 1) | static_cast<u8>(italic);
|
||||||
}
|
}
|
||||||
@ -132,10 +132,12 @@ public:
|
|||||||
void readSettings();
|
void readSettings();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
irr::gui::IGUIFont *getFont(FontSpec spec, bool may_fail);
|
||||||
|
|
||||||
/** update content of font cache in case of a setting change made it invalid */
|
/** update content of font cache in case of a setting change made it invalid */
|
||||||
void updateFontCache();
|
void updateFontCache();
|
||||||
|
|
||||||
/** initialize a new font */
|
/** initialize a new TTF font */
|
||||||
gui::IGUIFont *initFont(const FontSpec &spec);
|
gui::IGUIFont *initFont(const FontSpec &spec);
|
||||||
|
|
||||||
/** initialize a font without freetype */
|
/** initialize a font without freetype */
|
||||||
|
@ -304,12 +304,7 @@ void set_default_settings()
|
|||||||
settings->setDefault("mono_font_path_bold_italic", porting::getDataPath("fonts" DIR_DELIM "Cousine-BoldItalic.ttf"));
|
settings->setDefault("mono_font_path_bold_italic", porting::getDataPath("fonts" DIR_DELIM "Cousine-BoldItalic.ttf"));
|
||||||
settings->setDefault("fallback_font_path", porting::getDataPath("fonts" DIR_DELIM "DroidSansFallbackFull.ttf"));
|
settings->setDefault("fallback_font_path", porting::getDataPath("fonts" DIR_DELIM "DroidSansFallbackFull.ttf"));
|
||||||
|
|
||||||
settings->setDefault("fallback_font_shadow", "1");
|
|
||||||
settings->setDefault("fallback_font_shadow_alpha", "128");
|
|
||||||
|
|
||||||
std::string font_size_str = std::to_string(TTF_DEFAULT_FONT_SIZE);
|
std::string font_size_str = std::to_string(TTF_DEFAULT_FONT_SIZE);
|
||||||
|
|
||||||
settings->setDefault("fallback_font_size", font_size_str);
|
|
||||||
#else
|
#else
|
||||||
settings->setDefault("freetype", "false");
|
settings->setDefault("freetype", "false");
|
||||||
settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "mono_dejavu_sans"));
|
settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "mono_dejavu_sans"));
|
||||||
|
@ -275,7 +275,8 @@ CGUITTFont* CGUITTFont::create(IrrlichtDevice *device, const io::path& filename,
|
|||||||
//! Constructor.
|
//! Constructor.
|
||||||
CGUITTFont::CGUITTFont(IGUIEnvironment *env)
|
CGUITTFont::CGUITTFont(IGUIEnvironment *env)
|
||||||
: use_monochrome(false), use_transparency(true), use_hinting(true), use_auto_hinting(true),
|
: use_monochrome(false), use_transparency(true), use_hinting(true), use_auto_hinting(true),
|
||||||
batch_load_size(1), Device(0), Environment(env), Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
|
batch_load_size(1), Device(0), Environment(env), Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0),
|
||||||
|
shadow_offset(0), shadow_alpha(0), fallback(0)
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
setDebugName("CGUITTFont");
|
setDebugName("CGUITTFont");
|
||||||
@ -640,7 +641,30 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32>& positio
|
|||||||
if (current_color < colors.size())
|
if (current_color < colors.size())
|
||||||
applied_colors.push_back(colors[current_color]);
|
applied_colors.push_back(colors[current_color]);
|
||||||
}
|
}
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
offset.X += getWidthFromCharacter(currentChar);
|
offset.X += getWidthFromCharacter(currentChar);
|
||||||
|
}
|
||||||
|
else if (fallback != 0)
|
||||||
|
{
|
||||||
|
// Let the fallback font draw it, this isn't super efficient but hopefully that doesn't matter
|
||||||
|
wchar_t l1[] = { (wchar_t) currentChar, 0 }, l2 = (wchar_t) previousChar;
|
||||||
|
|
||||||
|
if (visible)
|
||||||
|
{
|
||||||
|
// Apply kerning.
|
||||||
|
offset.X += fallback->getKerningWidth(l1, &l2);
|
||||||
|
offset.Y += fallback->getKerningHeight();
|
||||||
|
|
||||||
|
u32 current_color = iter.getPos();
|
||||||
|
fallback->draw(core::stringw(l1),
|
||||||
|
core::rect<s32>({offset.X-1, offset.Y-1}, position.LowerRightCorner), // ???
|
||||||
|
current_color < colors.size() ? colors[current_color] : video::SColor(255, 255, 255, 255),
|
||||||
|
false, false, clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
offset.X += fallback->getDimension(l1).Width;
|
||||||
|
}
|
||||||
|
|
||||||
previousChar = currentChar;
|
previousChar = currentChar;
|
||||||
++iter;
|
++iter;
|
||||||
@ -766,6 +790,12 @@ inline u32 CGUITTFont::getWidthFromCharacter(uchar32_t c) const
|
|||||||
int w = Glyphs[n-1].advance.x / 64;
|
int w = Glyphs[n-1].advance.x / 64;
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
if (fallback != 0)
|
||||||
|
{
|
||||||
|
wchar_t s[] = { (wchar_t) c, 0 };
|
||||||
|
return fallback->getDimension(s).Width;
|
||||||
|
}
|
||||||
|
|
||||||
if (c >= 0x2000)
|
if (c >= 0x2000)
|
||||||
return (font_metrics.ascender / 64);
|
return (font_metrics.ascender / 64);
|
||||||
else return (font_metrics.ascender / 64) / 2;
|
else return (font_metrics.ascender / 64) / 2;
|
||||||
@ -789,6 +819,12 @@ inline u32 CGUITTFont::getHeightFromCharacter(uchar32_t c) const
|
|||||||
s32 height = (font_metrics.ascender / 64) - Glyphs[n-1].offset.Y + Glyphs[n-1].source_rect.getHeight();
|
s32 height = (font_metrics.ascender / 64) - Glyphs[n-1].offset.Y + Glyphs[n-1].source_rect.getHeight();
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
if (fallback != 0)
|
||||||
|
{
|
||||||
|
wchar_t s[] = { (wchar_t) c, 0 };
|
||||||
|
return fallback->getDimension(s).Height;
|
||||||
|
}
|
||||||
|
|
||||||
if (c >= 0x2000)
|
if (c >= 0x2000)
|
||||||
return (font_metrics.ascender / 64);
|
return (font_metrics.ascender / 64);
|
||||||
else return (font_metrics.ascender / 64) / 2;
|
else return (font_metrics.ascender / 64) / 2;
|
||||||
@ -804,9 +840,9 @@ u32 CGUITTFont::getGlyphIndexByChar(uchar32_t c) const
|
|||||||
// Get the glyph.
|
// Get the glyph.
|
||||||
u32 glyph = FT_Get_Char_Index(tt_face, c);
|
u32 glyph = FT_Get_Char_Index(tt_face, c);
|
||||||
|
|
||||||
// Check for a valid glyph. If it is invalid, attempt to use the replacement character.
|
// Check for a valid glyph.
|
||||||
if (glyph == 0)
|
if (glyph == 0)
|
||||||
glyph = FT_Get_Char_Index(tt_face, core::unicode::UTF_REPLACEMENT_CHARACTER);
|
return 0;
|
||||||
|
|
||||||
// If our glyph is already loaded, don't bother doing any batch loading code.
|
// If our glyph is already loaded, don't bother doing any batch loading code.
|
||||||
if (glyph != 0 && Glyphs[glyph - 1].isLoaded)
|
if (glyph != 0 && Glyphs[glyph - 1].isLoaded)
|
||||||
@ -922,13 +958,26 @@ core::vector2di CGUITTFont::getKerning(const uchar32_t thisLetter, const uchar32
|
|||||||
|
|
||||||
core::vector2di ret(GlobalKerningWidth, GlobalKerningHeight);
|
core::vector2di ret(GlobalKerningWidth, GlobalKerningHeight);
|
||||||
|
|
||||||
|
u32 n = getGlyphIndexByChar(thisLetter);
|
||||||
|
|
||||||
|
// If we don't have this glyph, ask fallback font
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
if (fallback != 0) {
|
||||||
|
wchar_t l1 = (wchar_t) thisLetter, l2 = (wchar_t) previousLetter;
|
||||||
|
ret.X = fallback->getKerningWidth(&l1, &l2);
|
||||||
|
ret.Y = fallback->getKerningHeight();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// If we don't have kerning, no point in continuing.
|
// If we don't have kerning, no point in continuing.
|
||||||
if (!FT_HAS_KERNING(tt_face))
|
if (!FT_HAS_KERNING(tt_face))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
// Get the kerning information.
|
// Get the kerning information.
|
||||||
FT_Vector v;
|
FT_Vector v;
|
||||||
FT_Get_Kerning(tt_face, getGlyphIndexByChar(previousLetter), getGlyphIndexByChar(thisLetter), FT_KERNING_DEFAULT, &v);
|
FT_Get_Kerning(tt_face, getGlyphIndexByChar(previousLetter), n, FT_KERNING_DEFAULT, &v);
|
||||||
|
|
||||||
// If we have a scalable font, the return value will be in font points.
|
// If we have a scalable font, the return value will be in font points.
|
||||||
if (FT_IS_SCALABLE(tt_face))
|
if (FT_IS_SCALABLE(tt_face))
|
||||||
@ -960,6 +1009,9 @@ void CGUITTFont::setInvisibleCharacters(const core::ustring& s)
|
|||||||
video::IImage* CGUITTFont::createTextureFromChar(const uchar32_t& ch)
|
video::IImage* CGUITTFont::createTextureFromChar(const uchar32_t& ch)
|
||||||
{
|
{
|
||||||
u32 n = getGlyphIndexByChar(ch);
|
u32 n = getGlyphIndexByChar(ch);
|
||||||
|
if (n == 0)
|
||||||
|
n = getGlyphIndexByChar((uchar32_t) core::unicode::UTF_REPLACEMENT_CHARACTER);
|
||||||
|
|
||||||
const SGUITTGlyph& glyph = Glyphs[n-1];
|
const SGUITTGlyph& glyph = Glyphs[n-1];
|
||||||
CGUITTGlyphPage* page = Glyph_Pages[glyph.glyph_page];
|
CGUITTGlyphPage* page = Glyph_Pages[glyph.glyph_page];
|
||||||
|
|
||||||
@ -1147,6 +1199,8 @@ core::array<scene::ISceneNode*> CGUITTFont::addTextSceneNode(const wchar_t* text
|
|||||||
container.push_back(current_node);
|
container.push_back(current_node);
|
||||||
}
|
}
|
||||||
offset.X += getWidthFromCharacter(current_char);
|
offset.X += getWidthFromCharacter(current_char);
|
||||||
|
// Note that fallback font handling is missing here (Minetest never uses this)
|
||||||
|
|
||||||
previous_char = current_char;
|
previous_char = current_char;
|
||||||
++text;
|
++text;
|
||||||
}
|
}
|
||||||
|
@ -269,7 +269,7 @@ namespace gui
|
|||||||
video::SColor color, bool hcenter=false, bool vcenter=false,
|
video::SColor color, bool hcenter=false, bool vcenter=false,
|
||||||
const core::rect<s32>* clip=0);
|
const core::rect<s32>* clip=0);
|
||||||
|
|
||||||
virtual void draw(const EnrichedString& text, const core::rect<s32>& position,
|
void draw(const EnrichedString& text, const core::rect<s32>& position,
|
||||||
video::SColor color, bool hcenter=false, bool vcenter=false,
|
video::SColor color, bool hcenter=false, bool vcenter=false,
|
||||||
const core::rect<s32>* clip=0);
|
const core::rect<s32>* clip=0);
|
||||||
|
|
||||||
@ -313,6 +313,9 @@ namespace gui
|
|||||||
//! Get the last glyph page's index.
|
//! Get the last glyph page's index.
|
||||||
u32 getLastGlyphPageIndex() const { return Glyph_Pages.size() - 1; }
|
u32 getLastGlyphPageIndex() const { return Glyph_Pages.size() - 1; }
|
||||||
|
|
||||||
|
//! Set font that should be used for glyphs not present in ours
|
||||||
|
void setFallback(gui::IGUIFont* font) { fallback = font; }
|
||||||
|
|
||||||
//! Create corresponding character's software image copy from the font,
|
//! Create corresponding character's software image copy from the font,
|
||||||
//! so you can use this data just like any ordinary video::IImage.
|
//! so you can use this data just like any ordinary video::IImage.
|
||||||
//! \param ch The character you need
|
//! \param ch The character you need
|
||||||
@ -387,6 +390,8 @@ namespace gui
|
|||||||
core::ustring Invisible;
|
core::ustring Invisible;
|
||||||
u32 shadow_offset;
|
u32 shadow_offset;
|
||||||
u32 shadow_alpha;
|
u32 shadow_alpha;
|
||||||
|
|
||||||
|
gui::IGUIFont* fallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace gui
|
} // end namespace gui
|
||||||
|
Loading…
Reference in New Issue
Block a user