diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2024-04-24 07:44:53 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2024-04-24 07:44:53 +1000 |
commit | d0f8aec244a0d71f67863f94cab4c5f84d93de22 (patch) | |
tree | a8e69fa28b7841d942e7e5f994518a69916c45c8 /source/rendering | |
parent | 6ac139321b2a03d71192f852ff958cf6176e1c2d (diff) |
feat: unicode emoji support + other stuff
Diffstat (limited to 'source/rendering')
-rw-r--r-- | source/rendering/StarFontTextureGroup.cpp | 67 | ||||
-rw-r--r-- | source/rendering/StarFontTextureGroup.hpp | 13 | ||||
-rw-r--r-- | source/rendering/StarTextPainter.cpp | 19 | ||||
-rw-r--r-- | source/rendering/StarTextPainter.hpp | 2 |
4 files changed, 64 insertions, 37 deletions
diff --git a/source/rendering/StarFontTextureGroup.cpp b/source/rendering/StarFontTextureGroup.cpp index d5e6ef9..5f0cdbc 100644 --- a/source/rendering/StarFontTextureGroup.cpp +++ b/source/rendering/StarFontTextureGroup.cpp @@ -14,13 +14,13 @@ void FontTextureGroup::cleanup(int64_t timeout) { void FontTextureGroup::switchFont(String const& font) { if (font.empty()) { - m_font = m_defaultFont; + m_activeFont = m_defaultFont; m_fontName.clear(); } else if (m_fontName != font) { m_fontName = font; auto find = m_fonts.find(font); - m_font = find != m_fonts.end() ? find->second : m_defaultFont; + m_activeFont = find != m_fonts.end() ? find->second : m_defaultFont; } } @@ -28,31 +28,35 @@ String const& FontTextureGroup::activeFont() { return m_fontName; } -void FontTextureGroup::addFont(FontPtr const& font, String const& name, bool isDefault) { +void FontTextureGroup::addFont(FontPtr const& font, String const& name) { m_fonts[name] = font; - if (isDefault) - m_defaultFont = m_font = font; } void FontTextureGroup::clearFonts() { m_fonts.clear(); - m_font = m_defaultFont; + m_activeFont = m_defaultFont; } -void FontTextureGroup::setFallbackFont(String const& fontName) { - if (auto font = m_fonts.ptr(fontName)) - m_fallbackFont = *font; +void FontTextureGroup::setFixedFonts(String const& defaultFontName, String const& fallbackFontName, String const& emojiFontName) { + if (auto defaultFont = m_fonts.ptr(defaultFontName)) + m_defaultFont = m_activeFont = *defaultFont; + if (auto fallbackFont = m_fonts.ptr(fallbackFontName)) + m_fallbackFont = *fallbackFont; + if (auto emojiFont = m_fonts.ptr(emojiFontName)) + m_emojiFont = *emojiFont; } const FontTextureGroup::GlyphTexture& FontTextureGroup::glyphTexture(String::Char c, unsigned size, Directives const* processingDirectives) { - Font* font = (m_font->exists(c) || !m_fallbackFont) ? m_font.get() : m_fallbackFont.get(); + Font* font = getFontForCharacter(c); + if (font == m_emojiFont.get()) + processingDirectives = nullptr; auto res = m_glyphs.insert(GlyphDescriptor{c, size, processingDirectives ? processingDirectives->hash() : 0, font}, GlyphTexture()); - + auto& glyphTexture = res.first->second; if (res.second) { font->setPixelSize(size); - auto pair = font->render(c); - Image& image = pair.first; + auto renderResult = font->render(c); + Image& image = get<0>(renderResult); if (processingDirectives) { try { Directives const& directives = *processingDirectives; @@ -61,7 +65,7 @@ const FontTextureGroup::GlyphTexture& FontTextureGroup::glyphTexture(String::Cha for (auto& entry : directives->entries) processImageOperation(entry.operation, image); - res.first->second.offset = (preSize - Vec2F(image.size())) / 2; + glyphTexture.offset = (preSize - Vec2F(image.size())) / 2; } catch (StarException const&) { image.forEachPixel([](unsigned x, unsigned y, Vec4B& pixel) { @@ -69,15 +73,14 @@ const FontTextureGroup::GlyphTexture& FontTextureGroup::glyphTexture(String::Cha }); } } - else - res.first->second.offset = Vec2F(); - res.first->second.offset += Vec2F(pair.second); - res.first->second.texture = m_textureGroup->create(image); + glyphTexture.colored = get<2>(renderResult); + glyphTexture.offset += Vec2F(get<1>(renderResult)); + glyphTexture.texture = m_textureGroup->create(image); } - res.first->second.time = Time::monotonicMilliseconds(); - return res.first->second; + glyphTexture.time = Time::monotonicMilliseconds(); + return glyphTexture; } TexturePtr FontTextureGroup::glyphTexturePtr(String::Char c, unsigned size) { @@ -89,9 +92,31 @@ TexturePtr FontTextureGroup::glyphTexturePtr(String::Char c, unsigned size, Dire } unsigned FontTextureGroup::glyphWidth(String::Char c, unsigned fontSize) { - Font* font = (m_font->exists(c) || !m_fallbackFont) ? m_font.get() : m_fallbackFont.get(); + Font* font = getFontForCharacter(c); font->setPixelSize(fontSize); return font->width(c); } +Font* FontTextureGroup::getFontForCharacter(String::Char c) { + if (((c >= 0x1F600 && c <= 0x1F64F) || // Emoticons + (c >= 0x1F300 && c <= 0x1F5FF) || // Misc Symbols and Pictographs + (c >= 0x1F680 && c <= 0x1F6FF) || // Transport and Map + (c >= 0x1F1E6 && c <= 0x1F1FF) || // Regional country flags + (c >= 0x2600 && c <= 0x26FF ) || // Misc symbols 9728 - 9983 + (c >= 0x2700 && c <= 0x27BF ) || // Dingbats + (c >= 0xFE00 && c <= 0xFE0F ) || // Variation Selectors + (c >= 0x1F900 && c <= 0x1F9FF) || // Supplemental Symbols and Pictographs + (c >= 0x1F018 && c <= 0x1F270) || // Various asian characters + (c >= 65024 && c <= 65039 ) || // Variation selector + (c >= 9100 && c <= 9300 ) || // Misc items + (c >= 8400 && c <= 8447 ))&& // Combining Diacritical Marks for Symbols + m_emojiFont->exists(c) + ) + return m_emojiFont.get(); + else if (m_activeFont->exists(c) || !m_fallbackFont) + return m_activeFont.get(); + else + return m_fallbackFont.get(); +} + } diff --git a/source/rendering/StarFontTextureGroup.hpp b/source/rendering/StarFontTextureGroup.hpp index 864b44f..b2fa572 100644 --- a/source/rendering/StarFontTextureGroup.hpp +++ b/source/rendering/StarFontTextureGroup.hpp @@ -16,7 +16,8 @@ public: struct GlyphTexture { TexturePtr texture; - int64_t time; + bool colored = false; + int64_t time = 0; Vec2F offset; }; @@ -35,16 +36,18 @@ public: // Switches the current font void switchFont(String const& font); String const& activeFont(); - void addFont(FontPtr const& font, String const& name, bool isDefault = false); + void addFont(FontPtr const& font, String const& name); void clearFonts(); - void setFallbackFont(String const& fontName); - + void setFixedFonts(String const& defaultFontName, String const& fallbackFontName, String const& emojiFontName); private: + Font* getFontForCharacter(String::Char); + CaseInsensitiveStringMap<FontPtr> m_fonts; String m_fontName; - FontPtr m_font; + FontPtr m_activeFont; FontPtr m_defaultFont; FontPtr m_fallbackFont; + FontPtr m_emojiFont; TextureGroupPtr m_textureGroup; HashMap<GlyphDescriptor, GlyphTexture> m_glyphs; diff --git a/source/rendering/StarTextPainter.cpp b/source/rendering/StarTextPainter.cpp index fa90208..7fc02bc 100644 --- a/source/rendering/StarTextPainter.cpp +++ b/source/rendering/StarTextPainter.cpp @@ -320,14 +320,9 @@ void TextPainter::reloadFonts() { m_fontTextureGroup.clearFonts(); m_fontTextureGroup.cleanup(0); auto assets = Root::singleton().assets(); - String defaultName = "hobo"; - auto defaultFont = loadFont("/hobo.ttf", defaultName); auto loadFontsByExtension = [&](String const& ext) { for (auto& fontPath : assets->scanExtension(ext)) { auto font = assets->font(fontPath); - if (font == defaultFont) - continue; - auto name = AssetPath::filename(fontPath); name = name.substr(0, name.findLast(".")); addFont(loadFont(fontPath, name), name); @@ -335,8 +330,10 @@ void TextPainter::reloadFonts() { }; loadFontsByExtension("ttf"); loadFontsByExtension("woff2"); - m_fontTextureGroup.addFont(defaultFont, defaultName, true); - m_fontTextureGroup.setFallbackFont("unifont"); + m_fontTextureGroup.setFixedFonts( + assets->json("/interface.config:font.defaultFont").toString(), + assets->json("/interface.config:font.fallbackFont").toString(), + assets->json("/interface.config:font.emojiFont").toString()); } void TextPainter::cleanup(int64_t timeout) { @@ -518,13 +515,15 @@ void TextPainter::renderPrimitives() { } void TextPainter::renderGlyph(String::Char c, Vec2F const& screenPos, List<RenderPrimitive>& out, unsigned fontSize, - float scale, Vec4B const& color, Directives const* processingDirectives) { + float scale, Vec4B color, Directives const* processingDirectives) { if (!fontSize) return; const FontTextureGroup::GlyphTexture& glyphTexture = m_fontTextureGroup.glyphTexture(c, fontSize, processingDirectives); - Vec2F offset = glyphTexture.offset * scale; - out.emplace_back(std::in_place_type_t<RenderQuad>(), glyphTexture.texture, Vec2F::round(screenPos + offset), scale, color, 0.0f); + if (glyphTexture.colored) + color[0] = color[1] = color[2] = 255; + out.emplace_back(std::in_place_type_t<RenderQuad>(), + glyphTexture.texture, Vec2F::round(screenPos + glyphTexture.offset * scale), scale, color, 0.0f); } FontPtr TextPainter::loadFont(String const& fontPath, Maybe<String> fontName) { diff --git a/source/rendering/StarTextPainter.hpp b/source/rendering/StarTextPainter.hpp index bff3a64..05f16f2 100644 --- a/source/rendering/StarTextPainter.hpp +++ b/source/rendering/StarTextPainter.hpp @@ -86,7 +86,7 @@ private: RectF doRenderGlyph(String::Char c, TextPositioning const& position, bool reallyRender); void renderPrimitives(); - void renderGlyph(String::Char c, Vec2F const& screenPos, List<RenderPrimitive>& out, unsigned fontSize, float scale, Vec4B const& color, Directives const* processingDirectives = nullptr); + void renderGlyph(String::Char c, Vec2F const& screenPos, List<RenderPrimitive>& out, unsigned fontSize, float scale, Vec4B color, Directives const* processingDirectives = nullptr); static FontPtr loadFont(String const& fontPath, Maybe<String> fontName = {}); RendererPtr m_renderer; |