From 8dce3349312927653b2ca7a33dcee0d2e6b69137 Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Wed, 21 Jun 2023 19:46:23 +1000 Subject: [PATCH] custom fonts!! --- source/rendering/StarFontTextureGroup.cpp | 20 ++++++++++++--- source/rendering/StarFontTextureGroup.hpp | 13 +++++++--- source/rendering/StarTextPainter.cpp | 31 ++++++++++++++++++++--- source/rendering/StarTextPainter.hpp | 6 ++++- source/rendering/StarWorldPainter.cpp | 2 +- source/windowing/StarGuiContext.cpp | 2 +- 6 files changed, 61 insertions(+), 13 deletions(-) diff --git a/source/rendering/StarFontTextureGroup.cpp b/source/rendering/StarFontTextureGroup.cpp index 340a389..21f6d6a 100644 --- a/source/rendering/StarFontTextureGroup.cpp +++ b/source/rendering/StarFontTextureGroup.cpp @@ -4,17 +4,31 @@ namespace Star { -FontTextureGroup::FontTextureGroup(FontPtr font, TextureGroupPtr textureGroup) - : m_font(move(font)), m_textureGroup(move(textureGroup)) {} +FontTextureGroup::FontTextureGroup(TextureGroupPtr textureGroup) + : m_textureGroup(move(textureGroup)) {} void FontTextureGroup::cleanup(int64_t timeout) { int64_t currentTime = Time::monotonicMilliseconds(); eraseWhere(m_glyphs, [&](auto const& p) { return currentTime - p.second.time > timeout; }); } +void FontTextureGroup::switchFont(String const& font) { + if (m_fontName != font) { + m_fontName = font; + auto find = m_fonts.find(font); + m_font = find != m_fonts.end() ? find->second : m_defaultFont; + } +} + +void FontTextureGroup::addFont(FontPtr const& font, String const& name, bool default) { + m_fonts[name] = font; + if (default) + m_defaultFont = m_font = font; +} + const FontTextureGroup::GlyphTexture& FontTextureGroup::glyphTexture(String::Char c, unsigned size, String const& processingDirectives) { - auto res = m_glyphs.insert(GlyphDescriptor{c, size, processingDirectives}, GlyphTexture()); + auto res = m_glyphs.insert(GlyphDescriptor{c, size, processingDirectives, m_font.get() }, GlyphTexture()); if (res.second) { m_font->setPixelSize(size); diff --git a/source/rendering/StarFontTextureGroup.hpp b/source/rendering/StarFontTextureGroup.hpp index 17c6467..9beb5d6 100644 --- a/source/rendering/StarFontTextureGroup.hpp +++ b/source/rendering/StarFontTextureGroup.hpp @@ -11,7 +11,8 @@ STAR_CLASS(FontTextureGroup); class FontTextureGroup { public: - typedef tuple GlyphDescriptor; + // Font* is only included for key uniqueness and should not be dereferenced + typedef tuple GlyphDescriptor; struct GlyphTexture { TexturePtr texture; @@ -19,7 +20,7 @@ public: Vec2F processingOffset; }; - FontTextureGroup(FontPtr font, TextureGroupPtr textureGroup); + FontTextureGroup(TextureGroupPtr textureGroup); const GlyphTexture& glyphTexture(String::Char, unsigned fontSize, String const& processingDirectives); @@ -31,9 +32,15 @@ public: // Removes glyphs that haven't been used in more than the given time in // milliseconds void cleanup(int64_t timeout); + // Switches the current font + void switchFont(String const& font); + void addFont(FontPtr const& font, String const& name, bool default = false); private: - + StringMap m_fonts; + String m_fontName; FontPtr m_font; + FontPtr m_defaultFont; + TextureGroupPtr m_textureGroup; HashMap m_glyphs; }; diff --git a/source/rendering/StarTextPainter.cpp b/source/rendering/StarTextPainter.cpp index 205aefe..abdd4b8 100644 --- a/source/rendering/StarTextPainter.cpp +++ b/source/rendering/StarTextPainter.cpp @@ -83,15 +83,27 @@ TextPositioning TextPositioning::translated(Vec2F translation) const { return {pos + translation, hAnchor, vAnchor, wrapWidth, charLimit}; } -TextPainter::TextPainter(FontPtr font, RendererPtr renderer, TextureGroupPtr textureGroup) +TextPainter::TextPainter(RendererPtr renderer, TextureGroupPtr textureGroup) : m_renderer(renderer), - m_fontTextureGroup(move(font), textureGroup), + m_fontTextureGroup(textureGroup), m_fontSize(8), m_lineSpacing(1.30f), - m_renderSettings({FontMode::Normal, Vec4B::filled(255)}), + m_renderSettings({FontMode::Normal, Vec4B::filled(255), "hobo"}), m_splitIgnore(" \t"), m_splitForce("\n\v"), - m_nonRenderedCharacters("\n\v\r") {} + m_nonRenderedCharacters("\n\v\r") { + auto assets = Root::singleton().assets(); + auto defaultFont = assets->font("/hobo.ttf"); + for (auto& fontPath : assets->scanExtension("ttf")) { + auto font = assets->font(fontPath); + if (font == defaultFont) + continue; + + auto fileName = AssetPath::filename(fontPath); + addFont(font->clone(), fileName.substr(0, fileName.findLast("."))); + } + m_fontTextureGroup.addFont(defaultFont->clone(), "hobo", true); +} RectF TextPainter::renderText(String const& s, TextPositioning const& position) { if (position.charLimit) { @@ -259,6 +271,14 @@ void TextPainter::setProcessingDirectives(String directives) { m_processingDirectives = move(directives); } +void TextPainter::setFont(String const& font) { + m_fontTextureGroup.switchFont(font); +} + +void TextPainter::addFont(FontPtr const& font, String const& name) { + m_fontTextureGroup.addFont(font, name); +} + void TextPainter::cleanup(int64_t timeout) { m_fontTextureGroup.cleanup(timeout); } @@ -339,6 +359,8 @@ RectF TextPainter::doRenderLine(String const& s, TextPositioning const& position m_renderSettings.mode = (FontMode)((int)m_renderSettings.mode | (int)FontMode::Shadow); } else if (command == "noshadow") { m_renderSettings.mode = (FontMode)((int)m_renderSettings.mode & (-1 ^ (int)FontMode::Shadow)); + } else if (command.beginsWith("font=")) { + m_renderSettings.font = command.substr(5); } else { // expects both #... sequences and plain old color names. Color c = jsonToColor(command); @@ -377,6 +399,7 @@ RectF TextPainter::doRenderGlyph(String::Char c, TextPositioning const& position vOffset = -(float)m_fontSize; if (reallyRender) { + setFont(m_renderSettings.font); if ((int)m_renderSettings.mode & (int)FontMode::Shadow) { Color shadow = Color::Black; uint8_t alphaU = m_renderSettings.color[3]; diff --git a/source/rendering/StarTextPainter.hpp b/source/rendering/StarTextPainter.hpp index 64b2748..fb201cf 100644 --- a/source/rendering/StarTextPainter.hpp +++ b/source/rendering/StarTextPainter.hpp @@ -3,6 +3,7 @@ #include "StarFontTextureGroup.hpp" #include "StarAnchorTypes.hpp" +#include "StarRoot.hpp" namespace Star { @@ -51,7 +52,7 @@ struct TextPositioning { // kerning*. class TextPainter { public: - TextPainter(FontPtr font, RendererPtr renderer, TextureGroupPtr textureGroup); + TextPainter(RendererPtr renderer, TextureGroupPtr textureGroup); RectF renderText(String const& s, TextPositioning const& position); RectF renderLine(String const& s, TextPositioning const& position); @@ -73,6 +74,8 @@ public: void setSplitIgnore(String const& splitIgnore); void setFontColor(Vec4B color); void setProcessingDirectives(String directives); + void setFont(String const& font); + void addFont(FontPtr const& font, String const& name); void cleanup(int64_t textureTimeout); @@ -80,6 +83,7 @@ private: struct RenderSettings { FontMode mode; Vec4B color; + String font; }; RectF doRenderText(String const& s, TextPositioning const& position, bool reallyRender, unsigned* charLimit); diff --git a/source/rendering/StarWorldPainter.cpp b/source/rendering/StarWorldPainter.cpp index a063f36..74812b9 100644 --- a/source/rendering/StarWorldPainter.cpp +++ b/source/rendering/StarWorldPainter.cpp @@ -30,7 +30,7 @@ void WorldPainter::renderInit(RendererPtr renderer) { m_renderer = move(renderer); auto textureGroup = m_renderer->createTextureGroup(TextureGroupSize::Large); - m_textPainter = make_shared(m_assets->font("/hobo.ttf")->clone(), m_renderer, textureGroup); + m_textPainter = make_shared(m_renderer, textureGroup); m_tilePainter = make_shared(m_renderer); m_drawablePainter = make_shared(m_renderer, make_shared(textureGroup)); m_environmentPainter = make_shared(m_renderer); diff --git a/source/windowing/StarGuiContext.cpp b/source/windowing/StarGuiContext.cpp index 45d0806..21f44f9 100644 --- a/source/windowing/StarGuiContext.cpp +++ b/source/windowing/StarGuiContext.cpp @@ -45,7 +45,7 @@ void GuiContext::renderInit(RendererPtr renderer) { auto textureGroup = m_renderer->createTextureGroup(); m_textureCollection = make_shared(textureGroup); m_drawablePainter = make_shared(m_renderer, m_textureCollection); - m_textPainter = make_shared(Root::singleton().assets()->font("/hobo.ttf")->clone(), m_renderer, textureGroup); + m_textPainter = make_shared(m_renderer, textureGroup); } MixerPtr const& GuiContext::mixer() const {