Skip to content

Commit

Permalink
Font: Add a ApplyStyle function that allows to temporarely change how…
Browse files Browse the repository at this point in the history
… the font is rendered

The returned value is a ScopeGuard to ensure it is always reverted because fonts are shared.

Mostly useful for FreeType to allow reusing the same font for different sizes.
  • Loading branch information
Ghabry committed Dec 7, 2022
1 parent fedffff commit 1d26553
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 12 deletions.
51 changes: 45 additions & 6 deletions src/font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ namespace {
GlyphRet vRenderShaped(char32_t glyph) const override;
bool vCanShape() const override;
std::vector<ShapeRet> vShape(U32StringView txt) const override;
void vApplyStyle(const Style& style) override;

private:
FT_Face face = nullptr;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -489,6 +495,26 @@ std::vector<Font::ShapeRet> 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() {
Expand Down Expand Up @@ -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<int>(size)};
return {0, 0, 0, static_cast<int>(current_style.size)};
}

return {};
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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<std::function<void()>>([&]() {
vApplyStyle(original_style);
current_style = original_style;
});
}

ExFont::ExFont() : Font("exfont", 12, false, false) {
}

Expand Down
34 changes: 29 additions & 5 deletions src/font.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "rect.h"
#include "string_view.h"
#include <string>
#include <lcf/scope_guard.h>

class Color;
class Rect;
Expand Down Expand Up @@ -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;

/**
Expand Down Expand Up @@ -149,6 +157,24 @@ class Font {
*/
void SetFallbackFont(FontRef fallback_font);

using StyleScopeGuard = lcf::ScopeGuard<std::function<void()>>;

/**
* 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.
*
Expand Down Expand Up @@ -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<ShapeRet> 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;
};

Expand Down
9 changes: 9 additions & 0 deletions src/game_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion src/game_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
*/
Expand Down

0 comments on commit 1d26553

Please sign in to comment.