diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/gui.cpp | 10 | ||||
-rw-r--r-- | src/gui/gui.h | 4 | ||||
-rw-r--r-- | src/gui/truetypefont.cpp | 154 | ||||
-rw-r--r-- | src/gui/truetypefont.h | 8 |
4 files changed, 105 insertions, 71 deletions
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 68f43cc3..ae74cab2 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -106,6 +106,9 @@ Gui::Gui(Graphics *graphics) std::string fontFile = branding.getValue("font", "fonts/dejavusans.ttf"); std::string path = resman->getPath(fontFile); + // Initialize the font scale before creating the fonts + TrueTypeFont::updateFontScale(graphics->getScale()); + try { mGuiFont = new TrueTypeFont(path, fontSize); @@ -222,17 +225,20 @@ void Gui::draw() mGraphics->_endDraw(); } -void Gui::videoResized(int width, int height) +bool Gui::videoResized(int width, int height) { + TrueTypeFont::updateFontScale(static_cast<Graphics*>(mGraphics)->getScale()); + auto *top = static_cast<WindowContainer*>(getTop()); int oldWidth = top->getWidth(); int oldHeight = top->getHeight(); if (oldWidth == width && oldHeight == height) - return; + return false; top->setSize(width, height); top->adjustAfterResize(oldWidth, oldHeight); + return true; } void Gui::setUseCustomCursor(bool customCursor) diff --git a/src/gui/gui.h b/src/gui/gui.h index b731514f..29dcdef2 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -86,8 +86,10 @@ class Gui : public gcn::Gui /** * Called when the application window has been resized. + * + * Returns whether the top widget changed size. */ - void videoResized(int width, int height); + bool videoResized(int width, int height); gcn::FocusHandler *getFocusHandler() const { return mFocusHandler; } diff --git a/src/gui/truetypefont.cpp b/src/gui/truetypefont.cpp index adb49780..30037f84 100644 --- a/src/gui/truetypefont.cpp +++ b/src/gui/truetypefont.cpp @@ -29,6 +29,9 @@ #include <guichan/color.hpp> #include <guichan/exception.hpp> +#include <cmath> +#include <memory> + const unsigned int CACHE_SIZE = 256; static const char *getSafeUtf8String(const std::string &text) @@ -42,64 +45,55 @@ static const char *getSafeUtf8String(const std::string &text) return buf; } -class TextChunk +bool operator==(SDL_Color lhs, SDL_Color rhs) { - public: - TextChunk(const std::string &text, const gcn::Color &color) : - text(text), color(color) - { - } - - ~TextChunk() - { - delete img; - } - - bool operator==(const TextChunk &chunk) const - { - return (chunk.text == text && chunk.color == color); - } + return (lhs.r == rhs.r && + lhs.g == rhs.g && + lhs.b == rhs.b && + lhs.a == rhs.a); +} - void generate(TTF_Font *font) - { - SDL_Color sdlCol; - sdlCol.r = color.r; - sdlCol.g = color.g; - sdlCol.b = color.b; - sdlCol.a = color.a; +class TextChunk +{ +public: + TextChunk(const std::string &text, SDL_Color color) + : text(text) + , color(color) + {} - const char *str = getSafeUtf8String(text); - SDL_Surface *surface = TTF_RenderUTF8_Blended( - font, str, sdlCol); + void generate(TTF_Font *font) + { + SDL_Surface *surface = TTF_RenderUTF8_Blended(font, + getSafeUtf8String(text), + color); - if (!surface) - { - img = nullptr; - return; - } + if (!surface) + return; - img = Image::load(surface); + img.reset(Image::load(surface)); - SDL_FreeSurface(surface); - } + SDL_FreeSurface(surface); + } - Image *img = nullptr; - std::string text; - gcn::Color color; + std::unique_ptr<Image> img; + const std::string text; + const SDL_Color color; }; -static int fontCounter; +std::list<TrueTypeFont*> TrueTypeFont::mFonts; +float TrueTypeFont::mScale = 1.0f; TrueTypeFont::TrueTypeFont(const std::string &filename, int size, int style) + : mFilename(filename) + , mPointSize(size) { - if (fontCounter == 0 && TTF_Init() == -1) + if (TTF_Init() == -1) { throw GCN_EXCEPTION("Unable to initialize SDL_ttf: " + std::string(TTF_GetError())); } - ++fontCounter; - mFont = TTF_OpenFont(filename.c_str(), size); + mFont = TTF_OpenFont(filename.c_str(), size * mScale); if (!mFont) { @@ -108,15 +102,18 @@ TrueTypeFont::TrueTypeFont(const std::string &filename, int size, int style) } TTF_SetFontStyle(mFont, style); + + mFonts.push_back(this); } TrueTypeFont::~TrueTypeFont() { - TTF_CloseFont(mFont); - --fontCounter; + mFonts.remove(this); + + if (mFont) + TTF_CloseFont(mFont); - if (fontCounter == 0) - TTF_Quit(); + TTF_Quit(); } void TrueTypeFont::drawString(gcn::Graphics *graphics, @@ -126,26 +123,25 @@ void TrueTypeFont::drawString(gcn::Graphics *graphics, if (text.empty()) return; - auto *g = dynamic_cast<Graphics *>(graphics); + auto *g = static_cast<Graphics *>(graphics); + const gcn::Color col = g->getColor(); - if (!g) - throw "Not a valid graphics object!"; - - gcn::Color col = g->getColor(); - const float alpha = col.a / 255.0f; - - /* The alpha value is ignored at string generation so avoid caching the + /* The alpha value is ignored at image generation to avoid caching the * same text with different alpha values. */ - col.a = 255; - - TextChunk chunk(text, col); + const SDL_Color color = { + static_cast<Uint8>(col.r), + static_cast<Uint8>(col.g), + static_cast<Uint8>(col.b), + 255 + }; bool found = false; for (auto i = mCache.begin(); i != mCache.end(); ++i) { - if (chunk == (*i)) + auto &chunk = *i; + if (chunk.text == text && chunk.color == color) { // Raise priority: move it to front mCache.splice(mCache.begin(), mCache, i); @@ -154,19 +150,42 @@ void TrueTypeFont::drawString(gcn::Graphics *graphics, } } - // Surface not found if (!found) { if (mCache.size() >= CACHE_SIZE) mCache.pop_back(); - mCache.push_front(chunk); + mCache.emplace_front(text, color); mCache.front().generate(mFont); } - if (mCache.front().img) + if (auto img = mCache.front().img.get()) + { + img->setAlpha(col.a / 255.0f); + g->drawRescaledImageF(img, 0, 0, x, y, + img->getWidth(), + img->getHeight(), + img->getWidth() / mScale, + img->getHeight() / mScale); + } +} + +void TrueTypeFont::updateFontScale(float scale) +{ + if (mScale == scale) + return; + + mScale = scale; + + for (auto font : mFonts) { - mCache.front().img->setAlpha(alpha); - g->drawImage(mCache.front().img, x, y); +#if SDL_TTF_VERSION_ATLEAST(2, 0, 18) + TTF_SetFontSize(font->mFont, font->mPointSize * mScale); +#else + TTF_CloseFont(font->mFont); + font->mFont = TTF_OpenFont(font->mFilename.c_str(), font->mPointSize * mScale); +#endif + + font->mCache.clear(); } } @@ -180,23 +199,22 @@ int TrueTypeFont::getWidth(const std::string &text) const // Assumption is that TTF::draw will be called next mCache.splice(mCache.begin(), mCache, i); if (i->img) - return i->img->getWidth(); + return std::ceil(i->img->getWidth() / mScale); return 0; } } int w, h; - const char *str = getSafeUtf8String(text); - TTF_SizeUTF8(mFont, str, &w, &h); - return w; + TTF_SizeUTF8(mFont, getSafeUtf8String(text), &w, &h); + return std::ceil(w / mScale); } int TrueTypeFont::getHeight() const { - return TTF_FontHeight(mFont); + return std::ceil(TTF_FontHeight(mFont) / mScale); } int TrueTypeFont::getLineHeight() const { - return TTF_FontLineSkip(mFont); + return std::ceil(TTF_FontLineSkip(mFont) / mScale); } diff --git a/src/gui/truetypefont.h b/src/gui/truetypefont.h index d42400d8..b3ebcc73 100644 --- a/src/gui/truetypefont.h +++ b/src/gui/truetypefont.h @@ -72,11 +72,19 @@ class TrueTypeFont : public gcn::Font const std::string &text, int x, int y) override; + static void updateFontScale(float scale); + private: + const std::string mFilename; TTF_Font *mFont; + const int mPointSize; + // Word surfaces cache mutable std::list<TextChunk> mCache; + + static std::list<TrueTypeFont*> mFonts; + static float mScale; }; #endif |