diff --git a/Common/Render/Text/draw_text_sdl.cpp b/Common/Render/Text/draw_text_sdl.cpp index 7f71b3a2b8..2a9cd045fb 100644 --- a/Common/Render/Text/draw_text_sdl.cpp +++ b/Common/Render/Text/draw_text_sdl.cpp @@ -187,12 +187,15 @@ void TextDrawerSDL::PrepareFallbackFonts(std::string_view locale) { } uint32_t TextDrawerSDL::CheckMissingGlyph(std::string_view text) { - auto iter = fontMap_.find(fontHash_); + auto iter = fontMap_.find(fontStyle_); if (iter == fontMap_.end()) { return 0; } TTF_Font *font = iter->second; + if (!font) { + return 0; + } UTF8 utf8Decoded(text); uint32_t missingGlyph = 0; @@ -245,48 +248,42 @@ int TextDrawerSDL::FindFallbackFonts(uint32_t missingGlyph, int ptSize) { return -1; } -uint32_t TextDrawerSDL::SetOrCreateFont(const FontStyle &style) { - const uint32_t fontHash = style.Hash(); - - auto iter = fontMap_.find(fontHash); +void TextDrawerSDL::SetOrCreateFont(const FontStyle &style) { + auto iter = fontMap_.find(style); if (iter != fontMap_.end()) { - fontHash_ = fontHash; - return fontHash; + fontStyle_ = style; + return; } - std::string useFont = !style.fontName.empty() ? style.fontName : std::string("Roboto-Condensed.ttf"); - const int ptSize = (int)((style.sizePts + 6) / dpiScale_); + std::string useFont = "assets/" + GetFilenameForFontStyle(style) + ".ttf"; - TTF_Font *font = TTF_OpenFont(useFont.c_str(), ptSize); - - if (!font) { - File::FileInfo fileInfo; - g_VFS.GetFileInfo("Roboto-Condensed.ttf", &fileInfo); - font = TTF_OpenFont(fileInfo.fullName.c_str(), ptSize); + if (loadedFonts_.find(useFont) == loadedFonts_.end()) { + int ptSize = static_cast(style.sizePts / dpiScale_ * 1.25f); + TTF_Font *font = TTF_OpenFont(useFont.c_str(), ptSize); + if (!font) { + ERROR_LOG(Log::G3D, "Failed to load font file %s", useFont.c_str()); + } + // Still, mark it with a nullptr to avoid retrying. + loadedFonts_[useFont] = font; } - fontMap_[fontHash] = font; - fontHash_ = fontHash; - return fontHash; -} - -void TextDrawerSDL::SetFont(uint32_t fontHandle) { - uint32_t fontHash = fontHandle; - auto iter = fontMap_.find(fontHash); - if (iter != fontMap_.end()) { - fontHash_ = fontHandle; - } else { - ERROR_LOG(Log::G3D, "Invalid font handle %08x", fontHandle); - } + fontMap_[style] = loadedFonts_[useFont]; + fontStyle_ = style; } void TextDrawerSDL::MeasureStringInternal(std::string_view str, float *w, float *h) { - TTF_Font *font = fontMap_.find(fontHash_)->second; - int ptSize = TTF_FontHeight(font) / 1.35; + TTF_Font *font = fontMap_.find(fontStyle_)->second; + + if (!font) { + *w = 1.0f; + *h = 1.0f; + return; + } uint32_t missingGlyph = CheckMissingGlyph(str); if (missingGlyph) { + int ptSize = static_cast(fontStyle_.sizePts / dpiScale_ * 1.25f); int fallbackFont = FindFallbackFonts(missingGlyph, ptSize); if (fallbackFont >= 0 && fallbackFont < (int)fallbackFonts_.size()) { font = fallbackFonts_[fallbackFont]; @@ -300,8 +297,8 @@ void TextDrawerSDL::MeasureStringInternal(std::string_view str, float *w, float std::string text(str); TTF_SizeUTF8(font, text.c_str(), &width, &height); - *w = width; - *h = height; + *w = (float)width; + *h = (float)height; } bool TextDrawerSDL::DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) { @@ -322,14 +319,17 @@ bool TextDrawerSDL::DrawStringBitmap(std::vector &bitmapData, TextStrin processedStr.push_back(' '); } - auto fontIter = fontMap_.find(fontHash_); + auto fontIter = fontMap_.find(fontStyle_); if (fontIter == fontMap_.end()) { - ERROR_LOG(Log::G3D, "Font hash not in map: %08x", fontHash_); + ERROR_LOG(Log::G3D, "Font style not in map"); return false; } TTF_Font *font = fontIter->second; - int ptSize = TTF_FontHeight(font) / 1.35; + if (!font) { + return false; + } + int ptSize = TTF_FontHeight(font) / 1.25; uint32_t missingGlyph = CheckMissingGlyph(processedStr); @@ -392,12 +392,19 @@ bool TextDrawerSDL::DrawStringBitmap(std::vector &bitmapData, TextStrin } void TextDrawerSDL::ClearFonts() { - for (auto iter : fontMap_) { - TTF_CloseFont(iter.second); + for (auto iter : loadedFonts_) { + if (iter.second) { + TTF_CloseFont(iter.second); + } } for (auto iter : fallbackFonts_) { - TTF_CloseFont(iter); + if (iter) { + TTF_CloseFont(iter); + } } + + // We wipe all the maps, including fontMap_. Everything it contains is also in loadedFonts_ which is cleared above. + loadedFonts_.clear(); fontMap_.clear(); fallbackFonts_.clear(); } diff --git a/Common/Render/Text/draw_text_sdl.h b/Common/Render/Text/draw_text_sdl.h index 31bf7908b0..cef8c9e733 100644 --- a/Common/Render/Text/draw_text_sdl.h +++ b/Common/Render/Text/draw_text_sdl.h @@ -19,8 +19,7 @@ public: TextDrawerSDL(Draw::DrawContext *draw); ~TextDrawerSDL(); - uint32_t SetOrCreateFont(const FontStyle &style) override; - void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once. + void SetOrCreateFont(const FontStyle &style) override; bool DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override; protected: @@ -34,7 +33,11 @@ private: uint32_t CheckMissingGlyph(std::string_view text); int FindFallbackFonts(uint32_t missingGlyph, int ptSize); - std::map fontMap_; + // NOTE: This can contain dupes. The below doesn't. + std::map fontMap_; + + // These are the ones we free. fontMap points into this map. + std::map loadedFonts_; std::vector fallbackFonts_; std::vector> fallbackFontPaths_; // path and font face index diff --git a/Common/UI/ViewGroup.cpp b/Common/UI/ViewGroup.cpp index fee4e12138..f3c0326d1c 100644 --- a/Common/UI/ViewGroup.cpp +++ b/Common/UI/ViewGroup.cpp @@ -32,12 +32,14 @@ void ApplyGravity(const Bounds &outer, const Margins &margins, float w, float h, case Gravity::G_LEFT: inner.x = outer.x + margins.left; break; case Gravity::G_RIGHT: inner.x = outer.x + outer.w - w - margins.right; break; case Gravity::G_HCENTER: inner.x = outer.x + (outer.w - w) * 0.5f; break; + default: break; } switch ((Gravity)((int)gravity & (int)Gravity::G_VERTMASK)) { case Gravity::G_TOP: inner.y = outer.y + margins.top; break; case Gravity::G_BOTTOM: inner.y = outer.y + outer.h - h - margins.bottom; break; case Gravity::G_VCENTER: inner.y = outer.y + (outer.h - h) * 0.5f; break; + default: break; } }