diff --git a/assets/opensb/font/unifont.woff2 b/assets/opensb/font/unifont.woff2 new file mode 100644 index 0000000..5da6c98 Binary files /dev/null and b/assets/opensb/font/unifont.woff2 differ diff --git a/source/core/StarFont.cpp b/source/core/StarFont.cpp index 63356ad..b21b85a 100644 --- a/source/core/StarFont.cpp +++ b/source/core/StarFont.cpp @@ -133,4 +133,8 @@ std::pair Font::render(String::Char c) { return { std::move(image), {slot->bitmap_left - 1, (slot->bitmap_top - height) + (m_pixelSize / 4) - 1} }; } +bool Font::exists(String::Char c) { + return FT_Get_Char_Index(m_fontImpl->face, c); +} + } diff --git a/source/core/StarFont.hpp b/source/core/StarFont.hpp index ec10533..dee50f7 100644 --- a/source/core/StarFont.hpp +++ b/source/core/StarFont.hpp @@ -35,6 +35,7 @@ public: // render a box, but if there is an internal freetype error this may return // an empty image). std::pair render(String::Char c); + bool exists(String::Char c); private: FontImplPtr m_fontImpl; diff --git a/source/rendering/StarFontTextureGroup.cpp b/source/rendering/StarFontTextureGroup.cpp index fb3a107..d5e6ef9 100644 --- a/source/rendering/StarFontTextureGroup.cpp +++ b/source/rendering/StarFontTextureGroup.cpp @@ -39,13 +39,19 @@ void FontTextureGroup::clearFonts() { m_font = m_defaultFont; } +void FontTextureGroup::setFallbackFont(String const& fontName) { + if (auto font = m_fonts.ptr(fontName)) + m_fallbackFont = *font; +} + const FontTextureGroup::GlyphTexture& FontTextureGroup::glyphTexture(String::Char c, unsigned size, Directives const* processingDirectives) { - auto res = m_glyphs.insert(GlyphDescriptor{c, size, processingDirectives ? processingDirectives->hash() : 0, m_font.get()}, GlyphTexture()); + Font* font = (m_font->exists(c) || !m_fallbackFont) ? m_font.get() : m_fallbackFont.get(); + auto res = m_glyphs.insert(GlyphDescriptor{c, size, processingDirectives ? processingDirectives->hash() : 0, font}, GlyphTexture()); if (res.second) { - m_font->setPixelSize(size); - auto pair = m_font->render(c); + font->setPixelSize(size); + auto pair = font->render(c); Image& image = pair.first; if (processingDirectives) { try { @@ -83,8 +89,9 @@ TexturePtr FontTextureGroup::glyphTexturePtr(String::Char c, unsigned size, Dire } unsigned FontTextureGroup::glyphWidth(String::Char c, unsigned fontSize) { - m_font->setPixelSize(fontSize); - return m_font->width(c); + Font* font = (m_font->exists(c) || !m_fallbackFont) ? m_font.get() : m_fallbackFont.get(); + font->setPixelSize(fontSize); + return font->width(c); } } diff --git a/source/rendering/StarFontTextureGroup.hpp b/source/rendering/StarFontTextureGroup.hpp index 9a32daf..864b44f 100644 --- a/source/rendering/StarFontTextureGroup.hpp +++ b/source/rendering/StarFontTextureGroup.hpp @@ -37,11 +37,14 @@ public: String const& activeFont(); void addFont(FontPtr const& font, String const& name, bool isDefault = false); void clearFonts(); + void setFallbackFont(String const& fontName); + private: CaseInsensitiveStringMap m_fonts; String m_fontName; FontPtr m_font; FontPtr m_defaultFont; + FontPtr m_fallbackFont; TextureGroupPtr m_textureGroup; HashMap m_glyphs; diff --git a/source/rendering/StarTextPainter.cpp b/source/rendering/StarTextPainter.cpp index 8198969..19e48f1 100644 --- a/source/rendering/StarTextPainter.cpp +++ b/source/rendering/StarTextPainter.cpp @@ -331,6 +331,7 @@ void TextPainter::reloadFonts() { loadFontsByExtension("ttf"); loadFontsByExtension("woff2"); m_fontTextureGroup.addFont(defaultFont, defaultName, true); + m_fontTextureGroup.setFallbackFont("unifont"); } void TextPainter::cleanup(int64_t timeout) {