custom fonts!!

This commit is contained in:
Kae 2023-06-21 19:46:23 +10:00
parent f2e64e1752
commit 8dce334931
6 changed files with 61 additions and 13 deletions

View File

@ -4,17 +4,31 @@
namespace Star { namespace Star {
FontTextureGroup::FontTextureGroup(FontPtr font, TextureGroupPtr textureGroup) FontTextureGroup::FontTextureGroup(TextureGroupPtr textureGroup)
: m_font(move(font)), m_textureGroup(move(textureGroup)) {} : m_textureGroup(move(textureGroup)) {}
void FontTextureGroup::cleanup(int64_t timeout) { void FontTextureGroup::cleanup(int64_t timeout) {
int64_t currentTime = Time::monotonicMilliseconds(); int64_t currentTime = Time::monotonicMilliseconds();
eraseWhere(m_glyphs, [&](auto const& p) { return currentTime - p.second.time > timeout; }); 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) 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) { if (res.second) {
m_font->setPixelSize(size); m_font->setPixelSize(size);

View File

@ -11,7 +11,8 @@ STAR_CLASS(FontTextureGroup);
class FontTextureGroup { class FontTextureGroup {
public: public:
typedef tuple<String::Char, unsigned, String> GlyphDescriptor; // Font* is only included for key uniqueness and should not be dereferenced
typedef tuple<String::Char, unsigned, String, Font*> GlyphDescriptor;
struct GlyphTexture { struct GlyphTexture {
TexturePtr texture; TexturePtr texture;
@ -19,7 +20,7 @@ public:
Vec2F processingOffset; Vec2F processingOffset;
}; };
FontTextureGroup(FontPtr font, TextureGroupPtr textureGroup); FontTextureGroup(TextureGroupPtr textureGroup);
const GlyphTexture& glyphTexture(String::Char, unsigned fontSize, String const& processingDirectives); 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 // Removes glyphs that haven't been used in more than the given time in
// milliseconds // milliseconds
void cleanup(int64_t timeout); 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: private:
StringMap<FontPtr> m_fonts;
String m_fontName;
FontPtr m_font; FontPtr m_font;
FontPtr m_defaultFont;
TextureGroupPtr m_textureGroup; TextureGroupPtr m_textureGroup;
HashMap<GlyphDescriptor, GlyphTexture> m_glyphs; HashMap<GlyphDescriptor, GlyphTexture> m_glyphs;
}; };

View File

@ -83,15 +83,27 @@ TextPositioning TextPositioning::translated(Vec2F translation) const {
return {pos + translation, hAnchor, vAnchor, wrapWidth, charLimit}; 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_renderer(renderer),
m_fontTextureGroup(move(font), textureGroup), m_fontTextureGroup(textureGroup),
m_fontSize(8), m_fontSize(8),
m_lineSpacing(1.30f), m_lineSpacing(1.30f),
m_renderSettings({FontMode::Normal, Vec4B::filled(255)}), m_renderSettings({FontMode::Normal, Vec4B::filled(255), "hobo"}),
m_splitIgnore(" \t"), m_splitIgnore(" \t"),
m_splitForce("\n\v"), 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) { RectF TextPainter::renderText(String const& s, TextPositioning const& position) {
if (position.charLimit) { if (position.charLimit) {
@ -259,6 +271,14 @@ void TextPainter::setProcessingDirectives(String directives) {
m_processingDirectives = move(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) { void TextPainter::cleanup(int64_t timeout) {
m_fontTextureGroup.cleanup(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); m_renderSettings.mode = (FontMode)((int)m_renderSettings.mode | (int)FontMode::Shadow);
} else if (command == "noshadow") { } else if (command == "noshadow") {
m_renderSettings.mode = (FontMode)((int)m_renderSettings.mode & (-1 ^ (int)FontMode::Shadow)); m_renderSettings.mode = (FontMode)((int)m_renderSettings.mode & (-1 ^ (int)FontMode::Shadow));
} else if (command.beginsWith("font=")) {
m_renderSettings.font = command.substr(5);
} else { } else {
// expects both #... sequences and plain old color names. // expects both #... sequences and plain old color names.
Color c = jsonToColor(command); Color c = jsonToColor(command);
@ -377,6 +399,7 @@ RectF TextPainter::doRenderGlyph(String::Char c, TextPositioning const& position
vOffset = -(float)m_fontSize; vOffset = -(float)m_fontSize;
if (reallyRender) { if (reallyRender) {
setFont(m_renderSettings.font);
if ((int)m_renderSettings.mode & (int)FontMode::Shadow) { if ((int)m_renderSettings.mode & (int)FontMode::Shadow) {
Color shadow = Color::Black; Color shadow = Color::Black;
uint8_t alphaU = m_renderSettings.color[3]; uint8_t alphaU = m_renderSettings.color[3];

View File

@ -3,6 +3,7 @@
#include "StarFontTextureGroup.hpp" #include "StarFontTextureGroup.hpp"
#include "StarAnchorTypes.hpp" #include "StarAnchorTypes.hpp"
#include "StarRoot.hpp"
namespace Star { namespace Star {
@ -51,7 +52,7 @@ struct TextPositioning {
// kerning*. // kerning*.
class TextPainter { class TextPainter {
public: public:
TextPainter(FontPtr font, RendererPtr renderer, TextureGroupPtr textureGroup); TextPainter(RendererPtr renderer, TextureGroupPtr textureGroup);
RectF renderText(String const& s, TextPositioning const& position); RectF renderText(String const& s, TextPositioning const& position);
RectF renderLine(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 setSplitIgnore(String const& splitIgnore);
void setFontColor(Vec4B color); void setFontColor(Vec4B color);
void setProcessingDirectives(String directives); void setProcessingDirectives(String directives);
void setFont(String const& font);
void addFont(FontPtr const& font, String const& name);
void cleanup(int64_t textureTimeout); void cleanup(int64_t textureTimeout);
@ -80,6 +83,7 @@ private:
struct RenderSettings { struct RenderSettings {
FontMode mode; FontMode mode;
Vec4B color; Vec4B color;
String font;
}; };
RectF doRenderText(String const& s, TextPositioning const& position, bool reallyRender, unsigned* charLimit); RectF doRenderText(String const& s, TextPositioning const& position, bool reallyRender, unsigned* charLimit);

View File

@ -30,7 +30,7 @@ void WorldPainter::renderInit(RendererPtr renderer) {
m_renderer = move(renderer); m_renderer = move(renderer);
auto textureGroup = m_renderer->createTextureGroup(TextureGroupSize::Large); auto textureGroup = m_renderer->createTextureGroup(TextureGroupSize::Large);
m_textPainter = make_shared<TextPainter>(m_assets->font("/hobo.ttf")->clone(), m_renderer, textureGroup); m_textPainter = make_shared<TextPainter>(m_renderer, textureGroup);
m_tilePainter = make_shared<TilePainter>(m_renderer); m_tilePainter = make_shared<TilePainter>(m_renderer);
m_drawablePainter = make_shared<DrawablePainter>(m_renderer, make_shared<AssetTextureGroup>(textureGroup)); m_drawablePainter = make_shared<DrawablePainter>(m_renderer, make_shared<AssetTextureGroup>(textureGroup));
m_environmentPainter = make_shared<EnvironmentPainter>(m_renderer); m_environmentPainter = make_shared<EnvironmentPainter>(m_renderer);

View File

@ -45,7 +45,7 @@ void GuiContext::renderInit(RendererPtr renderer) {
auto textureGroup = m_renderer->createTextureGroup(); auto textureGroup = m_renderer->createTextureGroup();
m_textureCollection = make_shared<AssetTextureGroup>(textureGroup); m_textureCollection = make_shared<AssetTextureGroup>(textureGroup);
m_drawablePainter = make_shared<DrawablePainter>(m_renderer, m_textureCollection); m_drawablePainter = make_shared<DrawablePainter>(m_renderer, m_textureCollection);
m_textPainter = make_shared<TextPainter>(Root::singleton().assets()->font("/hobo.ttf")->clone(), m_renderer, textureGroup); m_textPainter = make_shared<TextPainter>(m_renderer, textureGroup);
} }
MixerPtr const& GuiContext::mixer() const { MixerPtr const& GuiContext::mixer() const {