diff --git a/Common/Render/Text/draw_text.cpp b/Common/Render/Text/draw_text.cpp index f2a88343f6..e4c210b17d 100644 --- a/Common/Render/Text/draw_text.cpp +++ b/Common/Render/Text/draw_text.cpp @@ -90,23 +90,13 @@ const std::string &TextDrawer::WrapString(const FontStyle &style, float scale, s return entry.wrapped; } -void TextDrawer::SetOrCreateFont(const FontStyle &style) { - EnsureFont(style); - fontStyle_ = style; -} - -void TextDrawer::SetFontScale(float xscale, float yscale) { - fontScaleX_ = xscale; - fontScaleY_ = yscale; -} - float TextDrawer::CalculateDPIScale() const { if (ignoreGlobalDpi_) return dpiScale_; return g_display.dpi_scale_y; } -void TextDrawer::DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align) { +void TextDrawer::DrawString(DrawBuffer &target, const FontStyle &style, float scaleX, float scaleY, std::string_view str, float x, float y, uint32_t color, int align) { using namespace Draw; if (str.empty()) { return; @@ -117,7 +107,7 @@ void TextDrawer::DrawString(DrawBuffer &target, std::string_view str, float x, f TextStringEntry *entry; - auto [iter, inserted] = cache_.try_emplace(LookupKey(fontStyle_, str, align & FLAG_DROP_SHADOW)); + auto [iter, inserted] = cache_.try_emplace(LookupKey(style, str, align & FLAG_DROP_SHADOW)); if (!inserted) { entry = iter->second.get(); entry->lastUsedFrame = frameCount_; @@ -152,7 +142,8 @@ void TextDrawer::DrawString(DrawBuffer &target, std::string_view str, float x, f // because we need white. Well, we could using swizzle, but not all our backends support that. TextureDesc desc{}; std::vector bitmapData; - if (!DrawStringBitmap(bitmapData, *entry, bitmapFormat, str, align, emoji)) { + EnsureFont(style); + if (!DrawStringBitmap(style, bitmapData, *entry, bitmapFormat, str, align, emoji)) { // Nothing drawn. The entry without a texture records that fact. return; } @@ -178,15 +169,15 @@ void TextDrawer::DrawString(DrawBuffer &target, std::string_view str, float x, f draw_->BindTexture(0, entry->texture); // Okay, the texture is bound, let's draw. - float w = (float)entry->width * (fontScaleX_ * dpiScale_); - float h = (float)entry->height * (fontScaleY_ * dpiScale_); + float w = (float)entry->width * (scaleX * dpiScale_); + float h = (float)entry->height * (scaleY * dpiScale_); float u = (float)(entry->width + entry->shadowPad * 2) / (float)entry->bmWidth; float v = (float)(entry->height + entry->shadowPad * 2) / (float)entry->bmHeight; DrawBuffer::DoAlign(align, &x, &y, &w, &h); // Align by the text, then grow the quad to include the shadow padding. - const float padX = entry->shadowPad * (fontScaleX_ * dpiScale_); - const float padY = entry->shadowPad * (fontScaleY_ * dpiScale_); + const float padX = entry->shadowPad * (scaleX * dpiScale_); + const float padY = entry->shadowPad * (scaleY * dpiScale_); target.DrawTexRect(x - padX, y - padY, x + w + padX, y + h + padY, 0.0f, 0.0f, u, v, color); target.Flush(true); } @@ -239,7 +230,7 @@ void TextDrawer::MeasureStringRect(const FontStyle &style, float scaleX, float s } } -void TextDrawer::DrawStringRect(DrawBuffer &target, std::string_view str, const Bounds &bounds, uint32_t color, int align) { +void TextDrawer::DrawStringRect(DrawBuffer &target, const FontStyle &style, float scaleX, float scaleY, std::string_view str, const Bounds &bounds, uint32_t color, int align) { if (bounds.w < 0.0f || bounds.h < 0.0f) { return; } @@ -262,17 +253,18 @@ void TextDrawer::DrawStringRect(DrawBuffer &target, std::string_view str, const } const int wrap = align & (FLAG_WRAP_TEXT | FLAG_ELLIPSIZE_TEXT); - DrawString(target, wrap ? std::string_view(WrapString(fontStyle_, fontScaleX_, str, bounds.w, wrap)) : str, x, y, color, align); + DrawString(target, style, scaleX, scaleY, wrap ? std::string_view(WrapString(style, scaleX, str, bounds.w, wrap)) : str, x, y, color, align); } -bool TextDrawer::DrawStringBitmapRect(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, const Bounds &bounds, int align, bool fullColor) { +bool TextDrawer::DrawStringBitmapRect(const FontStyle &style, float scale, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, const Bounds &bounds, int align, bool fullColor) { // Clamp the size to something sane. if (str.size() > MAX_TEXT_LENGTH) { str = str.substr(0, MAX_TEXT_LENGTH); } const int wrap = align & (FLAG_WRAP_TEXT | FLAG_ELLIPSIZE_TEXT); - return DrawStringBitmap(bitmapData, entry, texFormat, wrap ? std::string_view(WrapString(fontStyle_, fontScaleX_, str, bounds.w, wrap)) : str, align, fullColor); + EnsureFont(style); + return DrawStringBitmap(style, bitmapData, entry, texFormat, wrap ? std::string_view(WrapString(style, scale, str, bounds.w, wrap)) : str, align, fullColor); } void TextDrawer::AddDropShadow(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat srcFormat) const { @@ -311,7 +303,6 @@ void TextDrawer::ClearCache() { cache_.clear(); sizeCache_.clear(); wrapCache_.clear(); - fontStyle_ = {}; } void TextDrawer::OncePerFrame() { diff --git a/Common/Render/Text/draw_text.h b/Common/Render/Text/draw_text.h index d5033aee12..e337c5b8a6 100644 --- a/Common/Render/Text/draw_text.h +++ b/Common/Render/Text/draw_text.h @@ -71,25 +71,14 @@ public: virtual ~TextDrawer() = default; virtual bool IsReady() const { return true; } - // Sets the font and scale that drawing uses. - void SetOrCreateFont(const FontStyle &style); - void SetFontScale(float xscale, float yscale); - // Measuring doesn't depend on the current font and scale. + // The font and scale are passed to each call. The fonts are created as they're first used. void MeasureString(const FontStyle &style, float scaleX, float scaleY, std::string_view str, float *w, float *h); void MeasureStringRect(const FontStyle &style, float scaleX, float scaleY, std::string_view str, float maxWidth, float *w, float *h, int align = ALIGN_TOPLEFT); - // In the current font and scale. - void MeasureString(std::string_view str, float *w, float *h) { - MeasureString(fontStyle_, fontScaleX_, fontScaleY_, str, w, h); - } - void MeasureStringRect(std::string_view str, float maxWidth, float *w, float *h, int align = ALIGN_TOPLEFT) { - MeasureStringRect(fontStyle_, fontScaleX_, fontScaleY_, str, maxWidth, w, h, align); - } - - void DrawString(DrawBuffer &target, std::string_view str, float x, float y, uint32_t color, int align = ALIGN_TOPLEFT); - void DrawStringRect(DrawBuffer &target, std::string_view str, const Bounds &bounds, uint32_t color, int align); - virtual bool DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) = 0; - bool DrawStringBitmapRect(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, const Bounds &bounds, int align, bool fullColor); + void DrawString(DrawBuffer &target, const FontStyle &style, float scaleX, float scaleY, std::string_view str, float x, float y, uint32_t color, int align = ALIGN_TOPLEFT); + void DrawStringRect(DrawBuffer &target, const FontStyle &style, float scaleX, float scaleY, std::string_view str, const Bounds &bounds, uint32_t color, int align); + // Rasterizes at scale 1, wrapping to bounds as if drawn at scale. + bool DrawStringBitmapRect(const FontStyle &style, float scale, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, const Bounds &bounds, int align, bool fullColor); // Use for housekeeping like throwing out old strings. void OncePerFrame(); @@ -113,8 +102,9 @@ protected: // Creates the font for style, if it isn't already. virtual void EnsureFont(const FontStyle &style) = 0; - // Implementations of this must handle multi-line strings. EnsureFont has been called for style. + // Implementations of these must handle multi-line strings. EnsureFont has been called for style. virtual void MeasureStringInternal(const FontStyle &style, std::string_view str, float *w, float *h) = 0; + virtual bool DrawStringBitmap(const FontStyle &style, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) = 0; void ClearCache(); @@ -154,11 +144,8 @@ protected: Draw::DrawContext *draw_; int frameCount_ = 0; - float fontScaleX_ = 1.0f; - float fontScaleY_ = 1.0f; float dpiScale_ = 1.0f; bool ignoreGlobalDpi_ = false; - FontStyle fontStyle_{}; // We will clamp strings to this length to avoid various degenenerate behaviors.k static constexpr size_t MAX_TEXT_LENGTH = 16384; diff --git a/Common/Render/Text/draw_text_android.cpp b/Common/Render/Text/draw_text_android.cpp index b95b81cccf..38a43ab57e 100644 --- a/Common/Render/Text/draw_text_android.cpp +++ b/Common/Render/Text/draw_text_android.cpp @@ -124,13 +124,13 @@ void TextDrawerAndroid::MeasureStringInternal(const FontStyle &style, std::strin *h = (float)(size & 0xFFFF); } -bool TextDrawerAndroid::DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) { +bool TextDrawerAndroid::DrawStringBitmap(const FontStyle &style, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) { if (str.empty()) { bitmapData.clear(); return false; } - auto iter = fontMap_.find(fontStyle_); + auto iter = fontMap_.find(style); if (iter == fontMap_.end()) { ERROR_LOG(Log::G3D, "Missing font"); return false; diff --git a/Common/Render/Text/draw_text_android.h b/Common/Render/Text/draw_text_android.h index 1156619929..4a0bb9a9e0 100644 --- a/Common/Render/Text/draw_text_android.h +++ b/Common/Render/Text/draw_text_android.h @@ -20,11 +20,11 @@ public: ~TextDrawerAndroid(); bool IsReady() const override; - bool DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override; protected: void EnsureFont(const FontStyle &style) override; void MeasureStringInternal(const FontStyle &style, std::string_view str, float *w, float *h) override; + bool DrawStringBitmap(const FontStyle &style, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override; bool SupportsColorEmoji() const override { return true; } void ClearFonts() override; diff --git a/Common/Render/Text/draw_text_cocoa.h b/Common/Render/Text/draw_text_cocoa.h index c61eec39ba..ebc5f5ac42 100644 --- a/Common/Render/Text/draw_text_cocoa.h +++ b/Common/Render/Text/draw_text_cocoa.h @@ -16,11 +16,11 @@ public: TextDrawerCocoa(Draw::DrawContext *draw); ~TextDrawerCocoa(); - bool DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override; protected: void EnsureFont(const FontStyle &style) override; void MeasureStringInternal(const FontStyle &style, std::string_view str, float *w, float *h) override; + bool DrawStringBitmap(const FontStyle &style, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override; bool SupportsColorEmoji() const override { return true; } void ClearFonts() override; diff --git a/Common/Render/Text/draw_text_cocoa.mm b/Common/Render/Text/draw_text_cocoa.mm index 3dfa3fff3e..c109a20cc3 100644 --- a/Common/Render/Text/draw_text_cocoa.mm +++ b/Common/Render/Text/draw_text_cocoa.mm @@ -223,13 +223,13 @@ void TextDrawerCocoa::MeasureStringInternal(const FontStyle &style, std::string_ *h = ceilf(extH); } -bool TextDrawerCocoa::DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) { +bool TextDrawerCocoa::DrawStringBitmap(const FontStyle &style, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) { if (str.empty()) { bitmapData.clear(); return false; } - auto iter = fontMap_.find(fontStyle_); + auto iter = fontMap_.find(style); if (iter == fontMap_.end()) { return false; } @@ -258,10 +258,10 @@ bool TextDrawerCocoa::DrawStringBitmap(std::vector &bitmapData, TextStr // Figure out how big an image we need. // We re-use MeasureString here. float w, h; - MeasureString(str, &w, &h); + MeasureString(style, 1.0f, 1.0f, str, &w, &h); // Reverse the DPI scale that MeasureString baked in. - w /= (dpiScale_ * fontScaleX_); - h /= (dpiScale_ * fontScaleY_); + w /= dpiScale_; + h /= dpiScale_; int width = (int)ceilf(w); int height = (int)ceilf(h); diff --git a/Common/Render/Text/draw_text_sdl.cpp b/Common/Render/Text/draw_text_sdl.cpp index 2cde9fae30..ab93190da6 100644 --- a/Common/Render/Text/draw_text_sdl.cpp +++ b/Common/Render/Text/draw_text_sdl.cpp @@ -436,7 +436,7 @@ void TextDrawerSDL::MeasureStringInternal(const FontStyle &style, std::string_vi *h = (float)extH; } -bool TextDrawerSDL::DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) { +bool TextDrawerSDL::DrawStringBitmap(const FontStyle &style, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) { _dbg_assert_(!fullColor) if (str.empty()) { @@ -444,7 +444,7 @@ bool TextDrawerSDL::DrawStringBitmap(std::vector &bitmapData, TextStrin return false; } - auto fontIter = fontMap_.find(fontStyle_); + auto fontIter = fontMap_.find(style); if (fontIter == fontMap_.end()) { ERROR_LOG(Log::G3D, "Font style not in map"); return false; diff --git a/Common/Render/Text/draw_text_sdl.h b/Common/Render/Text/draw_text_sdl.h index 9744002689..2abca5aab3 100644 --- a/Common/Render/Text/draw_text_sdl.h +++ b/Common/Render/Text/draw_text_sdl.h @@ -19,11 +19,11 @@ public: TextDrawerSDL(Draw::DrawContext *draw); ~TextDrawerSDL(); - bool DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override; protected: void EnsureFont(const FontStyle &style) override; void MeasureStringInternal(const FontStyle &style, std::string_view str, float *w, float *h) override; + bool DrawStringBitmap(const FontStyle &style, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override; bool SupportsColorEmoji() const override { return false; } void ClearFonts() override; diff --git a/Common/Render/Text/draw_text_uwp.cpp b/Common/Render/Text/draw_text_uwp.cpp index 9242fdbb7f..5b69551fa5 100644 --- a/Common/Render/Text/draw_text_uwp.cpp +++ b/Common/Render/Text/draw_text_uwp.cpp @@ -300,7 +300,7 @@ void TextDrawerUWP::MeasureStringInternal(const FontStyle &style, std::string_vi *h = (int)(metrics.height + 1.0f); } -bool TextDrawerUWP::DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) { +bool TextDrawerUWP::DrawStringBitmap(const FontStyle &style, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) { if (str.empty()) { bitmapData.clear(); return false; @@ -310,7 +310,7 @@ bool TextDrawerUWP::DrawStringBitmap(std::vector &bitmapData, TextStrin SIZE size; IDWriteTextFormat *format = nullptr; - auto iter = fontMap_.find(fontStyle_); + auto iter = fontMap_.find(style); if (iter != fontMap_.end()) { format = iter->second->textFmt; } diff --git a/Common/Render/Text/draw_text_uwp.h b/Common/Render/Text/draw_text_uwp.h index 95b7300078..c6c89898ee 100644 --- a/Common/Render/Text/draw_text_uwp.h +++ b/Common/Render/Text/draw_text_uwp.h @@ -20,11 +20,11 @@ public: TextDrawerUWP(Draw::DrawContext *draw); ~TextDrawerUWP(); - bool DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override; protected: void EnsureFont(const FontStyle &style) override; void MeasureStringInternal(const FontStyle &style, std::string_view str, float *w, float *h) override; + bool DrawStringBitmap(const FontStyle &style, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override; bool SupportsColorEmoji() const override { return true; } void ClearFonts() override; diff --git a/Common/Render/Text/draw_text_win.cpp b/Common/Render/Text/draw_text_win.cpp index 9caf064660..889b2e1a6e 100644 --- a/Common/Render/Text/draw_text_win.cpp +++ b/Common/Render/Text/draw_text_win.cpp @@ -154,14 +154,14 @@ void TextDrawerWin32::MeasureStringInternal(const FontStyle &style, std::string_ *h = extH; } -bool TextDrawerWin32::DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) { +bool TextDrawerWin32::DrawStringBitmap(const FontStyle &style, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) { if (str.empty()) { bitmapData.clear(); return false; } std::wstring wstr = ConvertUTF8ToWString(ReplaceAll(str, "\n", "\r\n")); - auto iter = fontMap_.find(fontStyle_); + auto iter = fontMap_.find(style); if (iter != fontMap_.end()) { SelectObject(ctx_->hDC, iter->second->hFont); } diff --git a/Common/Render/Text/draw_text_win.h b/Common/Render/Text/draw_text_win.h index 26ebc6c1ce..6388fd208f 100644 --- a/Common/Render/Text/draw_text_win.h +++ b/Common/Render/Text/draw_text_win.h @@ -16,11 +16,11 @@ public: TextDrawerWin32(Draw::DrawContext *draw); ~TextDrawerWin32(); - bool DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override; protected: void EnsureFont(const FontStyle &style) override; void MeasureStringInternal(const FontStyle &style, std::string_view str, float *w, float *h) override; + bool DrawStringBitmap(const FontStyle &style, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override; bool SupportsColorEmoji() const override { return false; } void ClearFonts() override; diff --git a/Common/UI/Context.cpp b/Common/UI/Context.cpp index 26928a5a03..b4deb5af30 100644 --- a/Common/UI/Context.cpp +++ b/Common/UI/Context.cpp @@ -42,6 +42,10 @@ void UIContext::Init(Draw::DrawContext *thin3d, Draw::Pipeline *uipipe, Draw::Pi void UIContext::BeginFrame() { frameStartTime_ = time_now_d(); + // Text drawn before anything set a style uses the theme's. + if (fontStyle_->sizePts <= 0 && theme) { + *fontStyle_ = theme->uiFont; + } if (atlasInvalid_ || !uitexture_) { if (uitexture_) { uitexture_->Release(); @@ -266,10 +270,6 @@ void UIContext::SetFontScale(float scaleX, float scaleY) { void UIContext::SetFontStyle(const FontStyle &fontStyle) { *fontStyle_ = fontStyle; - if (textDrawer_) { - textDrawer_->SetFontScale(fontScaleX_, fontScaleY_); - textDrawer_->SetOrCreateFont(fontStyle); - } } static FontID AtlasFontFromStyle(const FontStyle &style) { @@ -314,8 +314,7 @@ void UIContext::DrawText(std::string_view str, float x, float y, uint32_t color, if (useFontTexture) Flush(); } else { - textDrawer_->SetFontScale(fontScaleX_, fontScaleY_); - textDrawer_->DrawString(*Draw(), str, x, y, color, align); + textDrawer_->DrawString(*Draw(), *fontStyle_, fontScaleX_, fontScaleY_, str, x, y, color, align); } RebindTexture(); } @@ -340,11 +339,10 @@ void UIContext::DrawTextRect(std::string_view str, const Bounds &bounds, uint32_ if (useFontTexture) Flush(); } else { - textDrawer_->SetFontScale(fontScaleX_, fontScaleY_); Bounds rounded = bounds; rounded.x = floorf(rounded.x); rounded.y = floorf(rounded.y); - textDrawer_->DrawStringRect(*Draw(), str, rounded, color, align); + textDrawer_->DrawStringRect(*Draw(), *fontStyle_, fontScaleX_, fontScaleY_, str, rounded, color, align); } RebindTexture(); } diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index bdac917e2d..98d8ee7030 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -115,6 +115,7 @@ static AtlasTextMetrics char_lines_metrics; static bool textDrawerInited = false; static TextDrawer *textDrawer = nullptr; +static const FontStyle textDrawerFont(FontFamily::SansSerif, 18, FontStyleFlags::Default); struct PPGeTextDrawerCacheKey { bool operator < (const PPGeTextDrawerCacheKey &other) const { if (align != other.align) @@ -769,9 +770,7 @@ static bool HasTextDrawer() { // Should we pass a draw_? Yes! UWP requires it. textDrawer = TextDrawer::Create(g_draw); if (textDrawer) { - textDrawer->SetFontScale(1.0f, 1.0f); textDrawer->SetForcedDPIScale(1.0f); - textDrawer->SetOrCreateFont(FontStyle(FontFamily::SansSerif, 18, FontStyleFlags::Default)); } textDrawerInited = true; return textDrawer != nullptr; @@ -786,11 +785,10 @@ void PPGeMeasureText(float *w, float *h, std::string_view text, float scale, int if (HasTextDrawer()) { float mw, mh; - textDrawer->SetFontScale(scale, scale); int dtalign = (WrapType & PPGE_LINE_WRAP_WORD) ? FLAG_WRAP_TEXT : 0; if (WrapType & PPGE_LINE_USE_ELLIPSIS) dtalign |= FLAG_ELLIPSIZE_TEXT; - textDrawer->MeasureStringRect(s, wrapWidth <= 0 ? 480.0f : wrapWidth, &mw, &mh, dtalign); + textDrawer->MeasureStringRect(textDrawerFont, scale, scale, s, wrapWidth <= 0 ? 480.0f : wrapWidth, &mw, &mh, dtalign); if (w) *w = mw; @@ -920,10 +918,9 @@ static PPGeTextDrawerImage PPGeGetTextImage(std::string_view text, const PPGeSty cacheItem->second.entry.lastUsedFrame = gpuStats.totals.numFlips; } else { std::vector bitmapData; - textDrawer->SetFontScale(style.scale, style.scale); Bounds b(0, 0, maxWidth, 272.0f); std::string cleaned = ReplaceAll(text, "\r", ""); - textDrawer->DrawStringBitmapRect(bitmapData, im.entry, Draw::DataFormat::R8_UNORM, cleaned.c_str(), b, tdalign, false); + textDrawer->DrawStringBitmapRect(textDrawerFont, style.scale, bitmapData, im.entry, Draw::DataFormat::R8_UNORM, cleaned.c_str(), b, tdalign, false); int bufwBytes = ((im.entry.bmWidth + 31) / 32) * 16; u32 sz = bufwBytes * (im.entry.bmHeight + 1); @@ -1125,16 +1122,15 @@ void PPGeDrawTextWrapped(std::string_view text, float x, float y, float wrapWidt float actualWidth, actualHeight; Bounds b(0, 0, wrapWidth <= 0 ? 480.0f - x : wrapWidth, wrapHeight); int tdalign = 0; - textDrawer->SetFontScale(style.scale, style.scale); - textDrawer->MeasureStringRect(s, b.w, &actualWidth, &actualHeight, tdalign | FLAG_WRAP_TEXT); + textDrawer->MeasureStringRect(textDrawerFont, style.scale, style.scale, s, b.w, &actualWidth, &actualHeight, tdalign | FLAG_WRAP_TEXT); // Check if we need to scale the text down to fit better. PPGeStyle adjustedStyle = style; if (wrapHeight != 0.0f && actualHeight > wrapHeight) { // Cheap way to get the line height. float oneLine, twoLines; - textDrawer->MeasureString("|", &actualWidth, &oneLine); - textDrawer->MeasureStringRect("|\n|", 480, &actualWidth, &twoLines); + textDrawer->MeasureString(textDrawerFont, style.scale, style.scale, "|", &actualWidth, &oneLine); + textDrawer->MeasureStringRect(textDrawerFont, style.scale, style.scale, "|\n|", 480, &actualWidth, &twoLines); float lineHeight = twoLines - oneLine; if (actualHeight > wrapHeight * maxScaleDown) { diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index aa04513b1c..40f037a2dd 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1005,10 +1005,6 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) { ui_draw2d.Init(g_draw, texColorPipeline); uiContext->Init(g_draw, texColorPipeline, colorPipeline, &ui_draw2d); - if (uiContext->Text()) { - // This seems unnecessary. - // uiContext->Text()->SetOrCreateFont(FontStyle(FontID::invalid(), FontFamily::SansSerif, 20, FontStyleFlags::Default)); - } g_screenManager->setUIContext(uiContext); // Live before the queue is processed: a removal that comes in while the outputs' swapchains are being diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 35fa45989a..06f47a1aa4 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -3744,18 +3744,16 @@ bool TestFatShortNames() { class FakeTextDrawer : public TextDrawer { public: FakeTextDrawer() : TextDrawer(nullptr) {} - bool DrawStringBitmap(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override { return false; } void TestDropShadow(std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat srcFormat) { AddDropShadow(bitmapData, entry, srcFormat); } - const FontStyle &CurrentStyle() const { return fontStyle_; } - int measureCalls = 0; protected: void EnsureFont(const FontStyle &style) override {} + bool DrawStringBitmap(const FontStyle &style, std::vector &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override { return false; } void MeasureStringInternal(const FontStyle &style, std::string_view str, float *w, float *h) override { measureCalls++; std::vector lines; @@ -3774,49 +3772,40 @@ protected: bool TestTextDrawerCache() { FakeTextDrawer drawer; drawer.SetForcedDPIScale(1.0f); - drawer.SetOrCreateFont(FontStyle(FontFamily::SansSerif, 20, FontStyleFlags::Default)); + const FontStyle font20(FontFamily::SansSerif, 20, FontStyleFlags::Default); + const FontStyle font30(FontFamily::SansSerif, 30, FontStyleFlags::Default); float w, h; - drawer.MeasureString("hello", &w, &h); + drawer.MeasureString(font20, 1.0f, 1.0f, "hello", &w, &h); EXPECT_EQ_FLOAT(w, 50.0f); EXPECT_EQ_FLOAT(h, 20.0f); - drawer.MeasureString("hello", &w, &h); + drawer.MeasureString(font20, 1.0f, 1.0f, "hello", &w, &h); EXPECT_EQ_INT(drawer.measureCalls, 1); - // A different style is a different cache entry. - drawer.SetOrCreateFont(FontStyle(FontFamily::SansSerif, 30, FontStyleFlags::Default)); - drawer.MeasureString("hello", &w, &h); + // A different style is a different cache entry, but a different scale isn't. + drawer.MeasureString(font30, 1.0f, 1.0f, "hello", &w, &h); + EXPECT_EQ_INT(drawer.measureCalls, 2); + drawer.MeasureString(font30, 2.0f, 2.0f, "hello", &w, &h); + EXPECT_EQ_FLOAT(w, 100.0f); EXPECT_EQ_INT(drawer.measureCalls, 2); - // Measuring in another style and scale leaves the current ones alone. - const FontStyle small(FontFamily::SansSerif, 10, FontStyleFlags::Default); - drawer.MeasureString(small, 2.0f, 2.0f, "hello", &w, &h); - EXPECT_EQ_FLOAT(w, 100.0f); - EXPECT_EQ_INT(drawer.measureCalls, 3); - EXPECT_TRUE(drawer.CurrentStyle() == FontStyle(FontFamily::SansSerif, 30, FontStyleFlags::Default)); - drawer.MeasureString("hello", &w, &h); - EXPECT_EQ_FLOAT(w, 50.0f); - EXPECT_EQ_INT(drawer.measureCalls, 3); - const std::string_view para = "The quick brown fox jumps over the lazy dog, and then it does it again, and again, until the dog finally gets up and leaves."; - drawer.MeasureStringRect(para, 200.0f, &w, &h, FLAG_WRAP_TEXT); + drawer.MeasureStringRect(font30, 1.0f, 1.0f, para, 200.0f, &w, &h, FLAG_WRAP_TEXT); // The trailing space of a wrapped line is measured too. EXPECT_TRUE(w <= 210.0f); EXPECT_TRUE(h > 20.0f); float w2, h2; int callsBefore = drawer.measureCalls; - drawer.MeasureStringRect(para, 200.0f, &w2, &h2, FLAG_WRAP_TEXT); + drawer.MeasureStringRect(font30, 1.0f, 1.0f, para, 200.0f, &w2, &h2, FLAG_WRAP_TEXT); EXPECT_EQ_FLOAT(w, w2); EXPECT_EQ_FLOAT(h, h2); EXPECT_EQ_INT(drawer.measureCalls, callsBefore); // Scaling the font changes where the text wraps. - drawer.SetFontScale(0.5f, 0.5f); - drawer.MeasureStringRect(para, 200.0f, &w2, &h2, FLAG_WRAP_TEXT); + drawer.MeasureStringRect(font30, 0.5f, 0.5f, para, 200.0f, &w2, &h2, FLAG_WRAP_TEXT); EXPECT_TRUE(h2 < h * 0.5f); - drawer.SetFontScale(1.0f, 1.0f); - drawer.MeasureStringRect(para, 200.0f, &w, &h, FLAG_ELLIPSIZE_TEXT); + drawer.MeasureStringRect(font30, 1.0f, 1.0f, para, 200.0f, &w, &h, FLAG_ELLIPSIZE_TEXT); EXPECT_EQ_FLOAT(h, 20.0f); EXPECT_TRUE(w <= 200.0f); @@ -3830,7 +3819,6 @@ bool TestTextDrawerCache() { } drawer.TestDropShadow(bitmap, entry, Draw::DataFormat::R8_UNORM); }; - drawer.SetOrCreateFont(FontStyle(FontFamily::SansSerif, 24, FontStyleFlags::Default)); TextStringEntry entry1(0), entry2(0); std::vector bitmap; shadowTest(1.0f, entry1, bitmap);