Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/rendering
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2024-04-24 07:44:53 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2024-04-24 07:44:53 +1000
commitd0f8aec244a0d71f67863f94cab4c5f84d93de22 (patch)
treea8e69fa28b7841d942e7e5f994518a69916c45c8 /source/rendering
parent6ac139321b2a03d71192f852ff958cf6176e1c2d (diff)
feat: unicode emoji support + other stuff
Diffstat (limited to 'source/rendering')
-rw-r--r--source/rendering/StarFontTextureGroup.cpp67
-rw-r--r--source/rendering/StarFontTextureGroup.hpp13
-rw-r--r--source/rendering/StarTextPainter.cpp19
-rw-r--r--source/rendering/StarTextPainter.hpp2
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;