Merge pull request #2617 from Jupeyy/pr_font_fallback

Font fallback
This commit is contained in:
Dennis Felsing 2020-08-20 20:34:48 +02:00 committed by GitHub
commit dbb9c662ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 81 additions and 23 deletions

View file

@ -1009,8 +1009,9 @@ set(EXPECTED_DATA
editor/winter_main.rules
emoticons.png
file_icons.png
fonts/DejavuWenQuanYiMicroHei.ttf
fonts/DejaVuSans.ttf
fonts/Icons.ttf
fonts/SourceHanSansSC-Regular.otf
game.png
gui_buttons.png
gui_cursor.png
@ -1254,7 +1255,7 @@ set(EXPECTED_DATA
wordlist.txt
)
set_glob(DATA GLOB_RECURSE "frag;json;map;pem;png;rules;ttf;txt;vert;wv" data ${EXPECTED_DATA})
set_glob(DATA GLOB_RECURSE "frag;json;map;otf;png;rules;ttf;txt;vert;wv" data ${EXPECTED_DATA})
########################################################################
# COPY DATA AND DLLS

BIN
data/fonts/DejaVuSans.ttf Normal file

Binary file not shown.

Binary file not shown.

View file

@ -3837,8 +3837,10 @@ void CClient::ToggleWindowVSync()
void CClient::LoadFont()
{
static CFont *pDefaultFont = 0;
static bool LoadedFallbackFont = false;
char aFilename[512];
const char *pFontFile = "fonts/DejavuWenQuanYiMicroHei.ttf";
const char *pFontFile = "fonts/DejaVuSans.ttf";
const char *pFallbackFontFile = "fonts/SourceHanSansSC-Regular.otf";
IOHANDLE File = Storage()->OpenFile(pFontFile, IOFLAG_READ, IStorage::TYPE_ALL, aFilename, sizeof(aFilename));
if(File)
{
@ -3847,10 +3849,22 @@ void CClient::LoadFont()
pDefaultFont = pTextRender->GetFont(aFilename);
if(pDefaultFont == NULL)
pDefaultFont = pTextRender->LoadFont(aFilename);
File = Storage()->OpenFile(pFallbackFontFile, IOFLAG_READ, IStorage::TYPE_ALL, aFilename, sizeof(aFilename));
if(File)
{
io_close(File);
IEngineTextRender *pTextRender = Kernel()->RequestInterface<IEngineTextRender>();
LoadedFallbackFont = pTextRender->LoadFallbackFont(pDefaultFont, aFilename);
}
Kernel()->RequestInterface<IEngineTextRender>()->SetDefaultFont(pDefaultFont);
}
if(!pDefaultFont)
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gameclient", "failed to load font. filename='%s'", pFontFile);
if(!LoadedFallbackFont)
m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "gameclient", "failed to load the fallback font. filename='%s'", pFallbackFontFile);
}
void CClient::Notify(const char *pTitle, const char *pMessage)

View file

@ -100,6 +100,15 @@ public:
char m_aFilename[512];
FT_Face m_FtFace;
struct SFontFallBack
{
char m_aFilename[512];
FT_Face m_FtFace;
};
std::vector<SFontFallBack> m_FtFallbackFonts;
CFontSizeData m_aFontSizes[NUM_FONT_SIZES];
IGraphics::CTextureHandle m_aTextures[2];
@ -433,31 +442,49 @@ class CTextRender : public IEngineTextRender
int y = 1;
unsigned int px, py;
FT_Set_Pixel_Sizes(pFont->m_FtFace, 0, pSizeData->m_FontSize);
FT_Face FtFace = pFont->m_FtFace;
FT_Set_Pixel_Sizes(FtFace, 0, pSizeData->m_FontSize);
FT_UInt GlyphIndex = 0;
if(pFont->m_FtFace->charmap)
GlyphIndex = FT_Get_Char_Index(pFont->m_FtFace, (FT_ULong)Chr);
if(FtFace->charmap)
GlyphIndex = FT_Get_Char_Index(FtFace, (FT_ULong)Chr);
if(GlyphIndex == 0)
{
const int ReplacementChr = 0x25a1; // White square to indicate missing glyph
GlyphIndex = FT_Get_Char_Index(pFont->m_FtFace, (FT_ULong)ReplacementChr);
for(CFont::SFontFallBack& FallbackFont : pFont->m_FtFallbackFonts)
{
FtFace = FallbackFont.m_FtFace;
FT_Set_Pixel_Sizes(FtFace, 0, pSizeData->m_FontSize);
if(FtFace->charmap)
GlyphIndex = FT_Get_Char_Index(FtFace, (FT_ULong)Chr);
if(GlyphIndex != 0)
break;
}
if(GlyphIndex == 0)
{
dbg_msg("pFont", "font has no glyph for either %d or replacement char %d", Chr, ReplacementChr);
return;
const int ReplacementChr = 0x25a1; // White square to indicate missing glyph
FtFace = pFont->m_FtFace;
GlyphIndex = FT_Get_Char_Index(FtFace, (FT_ULong)ReplacementChr);
if(GlyphIndex == 0)
{
dbg_msg("pFont", "font has no glyph for either %d or replacement char %d", Chr, ReplacementChr);
return;
}
}
}
if(FT_Load_Glyph(pFont->m_FtFace, GlyphIndex, FT_LOAD_RENDER|FT_LOAD_NO_BITMAP))
if(FT_Load_Glyph(FtFace, GlyphIndex, FT_LOAD_RENDER|FT_LOAD_NO_BITMAP))
{
dbg_msg("pFont", "error loading glyph %d", Chr);
return;
}
pBitmap = &pFont->m_FtFace->glyph->bitmap; // ignore_convention
pBitmap = &FtFace->glyph->bitmap; // ignore_convention
// adjust spacing
int OutlineThickness = AdjustOutlineThicknessToFontSize(1, pSizeData->m_FontSize);
@ -515,9 +542,9 @@ class CTextRender : public IEngineTextRender
pFontchr->m_ID = Chr;
pFontchr->m_Height = Height;
pFontchr->m_Width = Width;
pFontchr->m_OffsetX = (pFont->m_FtFace->glyph->metrics.horiBearingX >> 6); // ignore_convention
pFontchr->m_OffsetY = -((pFont->m_FtFace->glyph->metrics.height >> 6) - (pFont->m_FtFace->glyph->metrics.horiBearingY >> 6));
pFontchr->m_AdvanceX = (pFont->m_FtFace->glyph->advance.x>>6); // ignore_convention
pFontchr->m_OffsetX = (FtFace->glyph->metrics.horiBearingX >> 6); // ignore_convention
pFontchr->m_OffsetY = -((FtFace->glyph->metrics.height >> 6) - (FtFace->glyph->metrics.horiBearingY >> 6));
pFontchr->m_AdvanceX = (FtFace->glyph->advance.x>>6); // ignore_convention
pFontchr->m_aUVs[0] = X;
pFontchr->m_aUVs[1] = Y;
@ -545,12 +572,6 @@ class CTextRender : public IEngineTextRender
}
}
// must only be called from the rendering function as the pFont must be set to the correct size
void RenderSetup(CFont *pFont, int size)
{
FT_Set_Pixel_Sizes(pFont->m_FtFace, 0, size);
}
float Kerning(CFont *pFont, FT_UInt GlyphIndexLeft, FT_UInt GlyphIndexRight)
{
FT_Vector Kerning = {0,0};
@ -672,7 +693,23 @@ public:
m_Fonts.push_back(pFont);
return pFont;
};
}
virtual bool LoadFallbackFont(CFont* pFont, const char *pFilename)
{
CFont::SFontFallBack FallbackFont;
str_copy(FallbackFont.m_aFilename, pFilename, sizeof(FallbackFont.m_aFilename));
if(FT_New_Face(m_FTLibrary, pFilename, 0, &FallbackFont.m_FtFace) == 0)
{
dbg_msg("textrender", "loaded fallback font from '%s'", pFilename);
pFont->m_FtFallbackFonts.emplace_back(std::move(FallbackFont));
return true;
}
return false;
}
virtual CFont *GetFont(int FontIndex)
{
@ -703,6 +740,12 @@ public:
m_Fonts.pop_back();
FT_Done_Face(pFont->m_FtFace);
for(CFont::SFontFallBack& FallbackFont : pFont->m_FtFallbackFonts)
{
FT_Done_Face(FallbackFont.m_FtFace);
}
delete pFont;
}
}

View file

@ -77,6 +77,7 @@ public:
virtual void SetCursor(CTextCursor *pCursor, float x, float y, float FontSize, int Flags) = 0;
virtual CFont *LoadFont(const char *pFilename) = 0;
virtual bool LoadFallbackFont(CFont* pFont, const char *pFilename) = 0;
virtual CFont *GetFont(int FontIndex) = 0;
virtual CFont *GetFont(const char *pFilename) = 0;
virtual void DestroyFont(CFont *pFont) = 0;

View file

@ -1329,7 +1329,6 @@ void CMenus::RenderLanguageSelection(CUIRect MainView)
{
str_copy(g_Config.m_ClLanguagefile, s_Languages[s_SelectedLanguage].m_FileName, sizeof(g_Config.m_ClLanguagefile));
g_Localization.Load(s_Languages[s_SelectedLanguage].m_FileName, Storage(), Console());
Client()->LoadFont();
}
}