diff --git a/src/font.cpp b/src/font.cpp index a70d818a618..f754b39bf3a 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -139,6 +139,7 @@ namespace { GlyphRet vRenderShaped(char32_t glyph) const override; bool vCanShape() const override; std::vector vShape(U32StringView txt) const override; + void vApplyStyle(const Style& style) override; private: FT_Face face = nullptr; @@ -284,6 +285,7 @@ FTFont::FTFont(Filesystem_Stream::InputStream is, int size, bool bold, bool ital } if (FT_HAS_COLOR(face)) { + // FIXME: Find the best size FT_Select_Size(face, 0); } else { FT_Set_Pixel_Sizes(face, 0, size); @@ -313,6 +315,10 @@ FTFont::~FTFont() { if (hb_buffer) { hb_buffer_destroy(hb_buffer); } + + if (hb_font) { + hb_font_destroy(hb_font); + } #endif if (face) { @@ -489,6 +495,26 @@ std::vector FTFont::vShape(U32StringView txt) const { } #endif +void FTFont::vApplyStyle(const Style& style) { + if (current_style.size == style.size) { + return; + } + + if (FT_HAS_COLOR(face)) { + // FIXME: Find the best size + FT_Select_Size(face, 0); + } else { + FT_Set_Pixel_Sizes(face, 0, style.size); + } + +#ifdef HAVE_HARFBUZZ + // Without this the sizes become desynchronized + hb_font_destroy(hb_font); + hb_font = hb_ft_font_create_referenced(face); + hb_ft_font_set_funcs(hb_font); +#endif +} + #endif FontRef Font::Default() { @@ -583,16 +609,15 @@ void Font::Dispose() { // Constructor. Font::Font(StringView name, int size, bool bold, bool italic) : name(ToString(name)) - , size(size) - , bold(bold) - , italic(italic) { + original_style = {size, bold, italic, true}; + current_style = original_style; } Rect Font::GetSize(char32_t glyph) const { if (EP_UNLIKELY(Utils::IsControlCharacter(glyph))) { if (glyph == '\n') { - return {0, 0, 0, static_cast(size)}; + return {0, 0, 0, static_cast(current_style.size)}; } return {}; @@ -620,7 +645,7 @@ Point Font::Render(Bitmap& dest, int const x, int const y, const Bitmap& sys, in unsigned src_y; if (color != ColorShadow) { - if (!gret.has_color) { + if (!gret.has_color && current_style.draw_shadow) { auto shadow_rect = Rect(rect.x + 1, rect.y + 1, rect.width, rect.height); dest.MaskedBlit(shadow_rect, *gret.bitmap, 0, 0, sys, 16, 32); } @@ -667,7 +692,7 @@ Point Font::Render(Bitmap& dest, int const x, int const y, const Bitmap& sys, in unsigned src_y; if (color != ColorShadow) { - if (!gret.has_color) { + if (!gret.has_color && current_style.draw_shadow) { auto shadow_rect = Rect(rect.x + 1, rect.y + 1, rect.width, rect.height); dest.MaskedBlit(shadow_rect, *gret.bitmap, 0, 0, sys, 16, 32); } @@ -722,6 +747,20 @@ void Font::SetFallbackFont(FontRef fallback_font) { this->fallback_font = fallback_font; } +Font::Style Font::GetCurrentStyle() const { + return current_style; +} + +Font::StyleScopeGuard Font::ApplyStyle(Style new_style) { + vApplyStyle(new_style); + current_style = new_style; + + return lcf::ScopeGuard>([&]() { + vApplyStyle(original_style); + current_style = original_style; + }); +} + ExFont::ExFont() : Font("exfont", 12, false, false) { } diff --git a/src/font.h b/src/font.h index 2b17a83befd..95a5a98b86d 100644 --- a/src/font.h +++ b/src/font.h @@ -26,6 +26,7 @@ #include "rect.h" #include "string_view.h" #include +#include class Color; class Rect; @@ -69,6 +70,13 @@ class Font { bool not_found; }; + struct Style { + int size = -1; + bool bold = false; + bool italic = false; + bool draw_shadow = false; + }; + virtual ~Font() = default; /** @@ -149,6 +157,24 @@ class Font { */ void SetFallbackFont(FontRef fallback_font); + using StyleScopeGuard = lcf::ScopeGuard>; + + /** + * Returns the current font style used for rendering. + * + * @return current style + */ + Style GetCurrentStyle() const; + + /** + * Applies a new text style for rendering. + * The style is reverted to the original style afterwards through the returned scope guard. + * + * @param new_style new style to apply + * @return StyleScopeGuard When destroyed, reverts to the old style + */ + StyleScopeGuard ApplyStyle(Style new_style); + /** * Uses the FreeType library to load a font from the provided stream. * @@ -178,21 +204,19 @@ class Font { ColorHeal = 9 }; - size_t pixel_size() const { return size * 96 / 72; } - virtual Rect vGetSize(char32_t glyph) const = 0; virtual GlyphRet vRender(char32_t glyph) const = 0; virtual GlyphRet vRenderShaped(char32_t glyph) const { return vRender(glyph); }; virtual bool vCanShape() const { return false; } virtual std::vector vShape(U32StringView) const { return {}; } + virtual void vApplyStyle(const Style& style) { (void)style; }; protected: Font(StringView name, int size, bool bold, bool italic); std::string name; - unsigned size; - bool bold; - bool italic; + Style original_style; + Style current_style; FontRef fallback_font; }; diff --git a/src/game_windows.cpp b/src/game_windows.cpp index 9e941a9e17c..cad84c1b3d1 100644 --- a/src/game_windows.cpp +++ b/src/game_windows.cpp @@ -207,6 +207,10 @@ void Game_Windows::Window_User::Refresh() { const auto& pm = messages[i]; const auto& text = data.texts[i]; + auto style = font->GetCurrentStyle(); + style.size = text.font_size; + auto sg = font->ApplyStyle(style); + int x = text.position_x; int y = text.position_y; for (const auto& line: pm.GetLines()) { @@ -308,6 +312,11 @@ void Game_Windows::Window_User::Refresh() { const auto& pm = messages[i]; const auto& text = data.texts[i]; + auto style = font->GetCurrentStyle(); + style.size = text.font_size; + style.draw_shadow = text.flags.draw_shadow; + auto sg = font->ApplyStyle(style); + int x = text.position_x; int y = text.position_y; int text_color = 0; diff --git a/src/game_windows.h b/src/game_windows.h index 3cefa8a5c46..aab50e5e92a 100644 --- a/src/game_windows.h +++ b/src/game_windows.h @@ -33,7 +33,6 @@ Bold/Italic: Will only work when the font provides a bold/italic typeface TODO: Disable Text Gradient -Disable Text Shadow Async (System & Font) */