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

summaryrefslogtreecommitdiff
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
parent6ac139321b2a03d71192f852ff958cf6176e1c2d (diff)
feat: unicode emoji support + other stuff
-rw-r--r--assets/opensb/font/twemoji.woff2bin0 -> 476456 bytes
-rw-r--r--assets/opensb/interface.config.patch13
-rw-r--r--assets/opensb/interface/chat/chat.config.patch3
-rw-r--r--source/core/StarFont.cpp75
-rw-r--r--source/core/StarFont.hpp4
-rw-r--r--source/frontend/StarBaseScriptPane.cpp3
-rw-r--r--source/frontend/StarChat.cpp13
-rw-r--r--source/frontend/StarChat.hpp2
-rw-r--r--source/frontend/StarInterfaceLuaBindings.cpp9
-rw-r--r--source/frontend/StarMainInterface.cpp8
-rw-r--r--source/frontend/StarMainInterface.hpp5
-rw-r--r--source/game/StarPlayerStorage.cpp2
-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
16 files changed, 163 insertions, 75 deletions
diff --git a/assets/opensb/font/twemoji.woff2 b/assets/opensb/font/twemoji.woff2
new file mode 100644
index 0000000..6cc58b6
--- /dev/null
+++ b/assets/opensb/font/twemoji.woff2
Binary files differ
diff --git a/assets/opensb/interface.config.patch b/assets/opensb/interface.config.patch
index d798609..47076b2 100644
--- a/assets/opensb/interface.config.patch
+++ b/assets/opensb/interface.config.patch
@@ -1,9 +1,14 @@
{
+ "font" : {
+ "defaultFont" : "hobo",
+ "fallbackFont" : "unifont",
+ "emojiFont" : "twemoji"
+ },
"nametag" : {
"showMasterNames" : true,
// border is double here as it otherwise fades out near the end
// (could just the end to opaque too, but then diagonals are more jaggy)
- "textStyle" : { "backDirectives" : "?border=1;222;2224?border=1;222;2224" },
+ "textStyle" : { "backDirectives" : "border=1;222;2224?border=1;222;2224" },
"inspectOpacityRate" : 0.15,
"movementThreshold" : 0.5,
"offset" : [0, 13]
@@ -19,7 +24,7 @@
"paneTextStyle" : {},
"textBoxTextStyle" : {},
"itemSlotTextStyle" : {
- "backDirectives" : "?border=1;444;4444"
+ "backDirectives" : "border=1;444;4444"
},
"teamBarNameStyle" : {},
"cursorTooltip" : { "textStyle" : {} },
@@ -27,7 +32,7 @@
"debugTextStyle" : {
"font" : "iosevka-semibold",
"fontSize" : 7,
- "backDirectives" : "?border=2;111a;1114"
+ "backDirectives" : "border=1;333a;3334"
},
"debugSpatialClearTime" : 0.0,
"debugOffset" : [80, 130],
@@ -35,7 +40,7 @@
// Change planet name to support the new internal string formatting.
"planetNameFormatString" : "- {} -",
"planetTextStyle" : {
- "backDirectives" : "?border=6;000;000",
+ "backDirectives" : "border=6;000;000",
"fontSize" : 24
},
diff --git a/assets/opensb/interface/chat/chat.config.patch b/assets/opensb/interface/chat/chat.config.patch
index d71b88d..afdc3f8 100644
--- a/assets/opensb/interface/chat/chat.config.patch
+++ b/assets/opensb/interface/chat/chat.config.patch
@@ -2,7 +2,8 @@
"config" : {
"lineHeight" : 1,
"padding" : [1, 1],
- "textStyle" : { "backDirectives" : "?border=1;111a;1114" },
+ "textStyle" : { "backDirectives" : "border=1;111a;1117" },
+ "chatFormatString" : "^backdirectives=border=1=333=3337;<^backdirectives=border=1=333=3330?border=1=333=3337,white;{}^reset,backdirectives=border=1=333=3337;>^reset,#eee; {}",
"colors" : {
"local" : "^white;",
"party" : "^blue;",
diff --git a/source/core/StarFont.cpp b/source/core/StarFont.cpp
index b21b85a..86262f5 100644
--- a/source/core/StarFont.cpp
+++ b/source/core/StarFont.cpp
@@ -7,7 +7,7 @@
namespace Star {
-constexpr int FontLoadFlags = FT_LOAD_FORCE_AUTOHINT;
+constexpr int FontLoadFlags = FT_LOAD_NO_SVG | FT_LOAD_COLOR;
struct FTContext {
FT_Library library;
@@ -90,47 +90,70 @@ unsigned Font::width(String::Char c) {
}
-std::pair<Image, Vec2I> Font::render(String::Char c) {
+tuple<Image, Vec2I, bool> Font::render(String::Char c) {
if (!m_fontImpl)
throw FontException("Font::render called on uninitialized font.");
FT_Face face = m_fontImpl->face;
- FT_UInt glyph_index = FT_Get_Char_Index(face, c);
- if (FT_Load_Glyph(face, glyph_index, FontLoadFlags) != 0)
- return {};
+ if (m_loadedPixelSize != m_pixelSize || m_loadedChar != c) {
+ FT_UInt glyph_index = FT_Get_Char_Index(face, c);
+ if (FT_Load_Glyph(face, glyph_index, FontLoadFlags) != 0)
+ return {};
+
+ /* convert to an anti-aliased bitmap */
+ if (FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL) != 0)
+ return {};
+ }
- /* convert to an anti-aliased bitmap */
- if (FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL) != 0)
- return {};
+ m_loadedPixelSize = m_pixelSize;
+ m_loadedChar = m_loadedChar;
FT_GlyphSlot slot = face->glyph;
unsigned width = slot->bitmap.width;
unsigned height = slot->bitmap.rows;
-
- Image image(width + 2, height + 2, PixelFormat::RGBA32);
- Vec4B white(255, 255, 255, 0);
- image.fill(white);
-
- for (unsigned y = 0; y != height; ++y) {
- uint8_t* p = slot->bitmap.buffer + y * slot->bitmap.pitch;
- for (unsigned x = 0; x != width; ++x) {
- if (x < width && y < height) {
- uint8_t value = *(p + x);
- if (m_alphaThreshold) {
- if (value >= m_alphaThreshold) {
- white[3] = 255;
- image.set(x + 1, height - y, white);
- }
- } else if (value) {
- white[3] = value;
+ bool colored = false;
+
+ Image image(width + 2, height + 2, PixelFormat::BGRA32);
+ if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
+ Vec4B white(255, 255, 255, 0);
+ image.fill(white);
+ for (unsigned y = 0; y != height; ++y) {
+ uint8_t* p = slot->bitmap.buffer + y * slot->bitmap.pitch;
+ for (unsigned x = 0; x != width; ++x) {
+ if (x < width && y < height) {
+ white[3] = m_alphaThreshold
+ ? (*(p + x) >= m_alphaThreshold ? 255 : 0)
+ : *(p + x);
image.set(x + 1, height - y, white);
}
}
}
+ } else if (colored = slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
+ unsigned bpp = image.bytesPerPixel();
+ uint8_t* data = image.data() + bpp + ((image.width() * (image.height() - 2)) * bpp); // offset by 1 pixel as it's padded
+ for (size_t y = 0; y != height; ++y) {
+ memcpy(data - (y * image.width() * bpp),
+ slot->bitmap.buffer + y * slot->bitmap.pitch,
+ slot->bitmap.pitch);
+ }
+ // unfortunately FreeType pre-multiplied the color channels :(
+ image.forEachPixel([](unsigned, unsigned, Vec4B& pixel) {
+ if (pixel[3] != 0 && pixel[3] != 255) {
+ float a = byteToFloat(pixel[3]);
+ pixel[0] /= a;
+ pixel[1] /= a;
+ pixel[2] /= a;
+ }
+ });
+ } else {
+ return {};
}
- return { std::move(image), {slot->bitmap_left - 1, (slot->bitmap_top - height) + (m_pixelSize / 4) - 1} };
+ return make_tuple(
+ std::move(image),
+ Vec2I(slot->bitmap_left - 1, (slot->bitmap_top - height) + (m_pixelSize / 4) - 1),
+ colored);
}
bool Font::exists(String::Char c) {
diff --git a/source/core/StarFont.hpp b/source/core/StarFont.hpp
index dee50f7..6686dbc 100644
--- a/source/core/StarFont.hpp
+++ b/source/core/StarFont.hpp
@@ -34,13 +34,15 @@ public:
// May return empty image on unrenderable character (Normally, this will
// render a box, but if there is an internal freetype error this may return
// an empty image).
- std::pair<Image, Vec2I> render(String::Char c);
+ tuple<Image, Vec2I, bool> render(String::Char c);
bool exists(String::Char c);
private:
FontImplPtr m_fontImpl;
ByteArrayConstPtr m_fontBuffer;
unsigned m_pixelSize;
+ unsigned m_loadedPixelSize;
+ String::Char m_loadedChar;
uint8_t m_alphaThreshold;
HashMap<pair<String::Char, unsigned>, unsigned> m_widthCache;
diff --git a/source/frontend/StarBaseScriptPane.cpp b/source/frontend/StarBaseScriptPane.cpp
index 6db092d..7facc1c 100644
--- a/source/frontend/StarBaseScriptPane.cpp
+++ b/source/frontend/StarBaseScriptPane.cpp
@@ -90,7 +90,8 @@ void BaseScriptPane::tick(float dt) {
bool BaseScriptPane::sendEvent(InputEvent const& event) {
// Intercept GuiClose before the canvas child so GuiClose always closes
// BaseScriptPanes without having to support it in the script.
- if (context()->actions(event).contains(InterfaceAction::GuiClose)) {
+ if (context()->actions(event).contains(InterfaceAction::GuiClose)
+ && m_config.getBool("dismissable", true)) {
dismiss();
return true;
}
diff --git a/source/frontend/StarChat.cpp b/source/frontend/StarChat.cpp
index d780d23..bbb28c1 100644
--- a/source/frontend/StarChat.cpp
+++ b/source/frontend/StarChat.cpp
@@ -27,6 +27,7 @@ Chat::Chat(UniverseClientPtr client) : m_client(client) {
m_chatVisTime = config.get("visTime").toFloat();
m_fadeRate = config.get("fadeRate").toDouble();
m_chatHistoryLimit = config.get("chatHistoryLimit").toInt();
+ m_chatFormatString = config.getString("chatFormatString");
m_portraitTextOffset = jsonToVec2I(config.get("portraitTextOffset"));
m_portraitImageOffset = jsonToVec2I(config.get("portraitImageOffset"));
@@ -180,7 +181,7 @@ void Chat::addMessages(List<ChatReceivedMessage> const& messages, bool showPane)
guiContext.setTextStyle(m_chatTextStyle);
StringList lines;
if (message.fromNick != "" && message.portrait == "")
- lines = guiContext.wrapInterfaceText(strf("<{}> {}", message.fromNick, message.text), wrapWidth);
+ lines = guiContext.wrapInterfaceText(strf(m_chatFormatString.utf8Ptr(), message.fromNick, message.text), wrapWidth);
else
lines = guiContext.wrapInterfaceText(message.text, wrapWidth);
@@ -203,7 +204,8 @@ void Chat::addMessages(List<ChatReceivedMessage> const& messages, bool showPane)
show();
}
- m_receivedMessages.resize(std::min((unsigned)m_receivedMessages.size(), m_chatHistoryLimit));
+ if ((unsigned)m_receivedMessages.size() > m_chatHistoryLimit)
+ m_receivedMessages.resize(m_chatHistoryLimit);
}
void Chat::addHistory(String const& chat) {
@@ -216,6 +218,13 @@ void Chat::addHistory(String const& chat) {
m_client->playerStorage()->setMetadata("chatHistory", JsonArray::from(m_chatHistory));
}
+void Chat::clear(size_t count) {
+ if (count > m_receivedMessages.size())
+ m_receivedMessages.clear();
+ else
+ m_receivedMessages.erase(m_receivedMessages.begin(), m_receivedMessages.begin() + count);
+}
+
void Chat::renderImpl() {
Pane::renderImpl();
if (m_textBox->hasFocus())
diff --git a/source/frontend/StarChat.hpp b/source/frontend/StarChat.hpp
index 80cf683..df2d63c 100644
--- a/source/frontend/StarChat.hpp
+++ b/source/frontend/StarChat.hpp
@@ -30,6 +30,7 @@ public:
void addLine(String const& text, bool showPane = true);
void addMessages(List<ChatReceivedMessage> const& messages, bool showPane = true);
void addHistory(String const& chat);
+ void clear(size_t count = std::numeric_limits<size_t>::max());
String currentChat() const;
bool setCurrentChat(String const& chat, bool moveCursor = false);
@@ -69,6 +70,7 @@ private:
TextStyle m_chatTextStyle;
unsigned m_chatHistoryLimit;
int m_historyOffset;
+ String m_chatFormatString;
CanvasWidgetPtr m_chatLog;
Vec2I m_chatLogPadding;
diff --git a/source/frontend/StarInterfaceLuaBindings.cpp b/source/frontend/StarInterfaceLuaBindings.cpp
index 9e0bb2e..9523036 100644
--- a/source/frontend/StarInterfaceLuaBindings.cpp
+++ b/source/frontend/StarInterfaceLuaBindings.cpp
@@ -13,6 +13,11 @@ namespace Star {
LuaCallbacks LuaBindings::makeInterfaceCallbacks(MainInterface* mainInterface) {
LuaCallbacks callbacks;
+ callbacks.registerCallbackWithSignature<bool>(
+ "hudVisible", bind(mem_fn(&MainInterface::hudVisible), mainInterface));
+ callbacks.registerCallbackWithSignature<void, bool>(
+ "setHudVisible", bind(mem_fn(&MainInterface::setHudVisible), mainInterface, _1));
+
callbacks.registerCallback("bindCanvas", [mainInterface](String const& canvasName, Maybe<bool> ignoreInterfaceScale) -> Maybe<CanvasWidgetPtr> {
if (auto canvas = mainInterface->fetchCanvas(canvasName, ignoreInterfaceScale.value(false)))
return canvas;
@@ -87,6 +92,10 @@ LuaCallbacks LuaBindings::makeChatCallbacks(MainInterface* mainInterface, Univer
return chat->setCurrentChat(text, moveCursor.value(false));
});
+ callbacks.registerCallback("clear", [chat](Maybe<size_t> count) {
+ chat->clear(count.value(std::numeric_limits<size_t>::max()));
+ });
+
return callbacks;
}
diff --git a/source/frontend/StarMainInterface.cpp b/source/frontend/StarMainInterface.cpp
index 533aa58..5163eeb 100644
--- a/source/frontend/StarMainInterface.cpp
+++ b/source/frontend/StarMainInterface.cpp
@@ -893,6 +893,14 @@ bool MainInterface::fixedCamera() const {
return m_clientCommandProcessor->fixedCameraEnabled();
}
+bool MainInterface::hudVisible() const {
+ return !m_disableHud;
+}
+
+void MainInterface::setHudVisible(bool visible) {
+ m_disableHud = !visible;
+}
+
void MainInterface::warpToOrbitedWorld(bool deploy) {
if (m_client->canBeamDown(deploy)) {
if (deploy)
diff --git a/source/frontend/StarMainInterface.hpp b/source/frontend/StarMainInterface.hpp
index ec79f68..667a2fe 100644
--- a/source/frontend/StarMainInterface.hpp
+++ b/source/frontend/StarMainInterface.hpp
@@ -100,7 +100,6 @@ public:
Vec2F cursorWorldPosition() const;
- void toggleDebugDisplay();
bool isDebugDisplayed();
void doChat(String const& chat, bool addToHistory);
@@ -112,6 +111,8 @@ public:
void queueJoinRequest(pair<String, RpcPromiseKeeper<P2PJoinRequestReply>> request);
bool fixedCamera() const;
+ bool hudVisible() const;
+ void setHudVisible(bool visible = true);
void warpToOrbitedWorld(bool deploy = false);
void warpToOwnShip();
@@ -209,7 +210,7 @@ private:
QuestIndicatorPainterPtr m_questIndicatorPainter;
ChatBubbleManagerPtr m_chatBubbleManager;
- bool m_disableHud{false};
+ bool m_disableHud = false;
String m_lastCommand;
diff --git a/source/game/StarPlayerStorage.cpp b/source/game/StarPlayerStorage.cpp
index 1946ce2..7857f8d 100644
--- a/source/game/StarPlayerStorage.cpp
+++ b/source/game/StarPlayerStorage.cpp
@@ -115,7 +115,7 @@ Maybe<Uuid> PlayerStorage::playerUuidByName(String const& name, Maybe<Uuid> exce
RecursiveMutexLocker locker(m_mutex);
- size_t longest = SIZE_MAX;
+ size_t longest = std::numeric_limits<size_t>::max();
for (auto& cache : m_savedPlayersCache) {
if (except && *except == cache.first)
continue;
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;