mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 10:40:01 +01:00
TextDrawer: Remove the current font and scale
Drawing now takes the style and scale too, like measuring, so the text drawers have no font state left. UIContext keeps its current style and passes it, and fills it in from the theme if nothing has set one yet. PPGe passes its one font. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
dc1e9e50fc
commit
4c7dd44351
16 files changed
+64
-108
No files matched your search
@@ -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<uint8_t> 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<uint8_t> &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<uint8_t> &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<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat srcFormat) const {
|
||||
@@ -311,7 +303,6 @@ void TextDrawer::ClearCache() {
|
||||
cache_.clear();
|
||||
sizeCache_.clear();
|
||||
wrapCache_.clear();
|
||||
fontStyle_ = {};
|
||||
}
|
||||
|
||||
void TextDrawer::OncePerFrame() {
|
||||
|
||||
@@ -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<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) = 0;
|
||||
bool DrawStringBitmapRect(std::vector<uint8_t> &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<uint8_t> &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<uint8_t> &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;
|
||||
|
||||
@@ -124,13 +124,13 @@ void TextDrawerAndroid::MeasureStringInternal(const FontStyle &style, std::strin
|
||||
*h = (float)(size & 0xFFFF);
|
||||
}
|
||||
|
||||
bool TextDrawerAndroid::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) {
|
||||
bool TextDrawerAndroid::DrawStringBitmap(const FontStyle &style, std::vector<uint8_t> &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;
|
||||
|
||||
@@ -20,11 +20,11 @@ public:
|
||||
~TextDrawerAndroid();
|
||||
|
||||
bool IsReady() const override;
|
||||
bool DrawStringBitmap(std::vector<uint8_t> &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<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
|
||||
bool SupportsColorEmoji() const override { return true; }
|
||||
|
||||
void ClearFonts() override;
|
||||
|
||||
@@ -16,11 +16,11 @@ public:
|
||||
TextDrawerCocoa(Draw::DrawContext *draw);
|
||||
~TextDrawerCocoa();
|
||||
|
||||
bool DrawStringBitmap(std::vector<uint8_t> &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<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
|
||||
bool SupportsColorEmoji() const override { return true; }
|
||||
|
||||
void ClearFonts() override;
|
||||
|
||||
@@ -223,13 +223,13 @@ void TextDrawerCocoa::MeasureStringInternal(const FontStyle &style, std::string_
|
||||
*h = ceilf(extH);
|
||||
}
|
||||
|
||||
bool TextDrawerCocoa::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) {
|
||||
bool TextDrawerCocoa::DrawStringBitmap(const FontStyle &style, std::vector<uint8_t> &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<uint8_t> &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);
|
||||
|
||||
@@ -436,7 +436,7 @@ void TextDrawerSDL::MeasureStringInternal(const FontStyle &style, std::string_vi
|
||||
*h = (float)extH;
|
||||
}
|
||||
|
||||
bool TextDrawerSDL::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) {
|
||||
bool TextDrawerSDL::DrawStringBitmap(const FontStyle &style, std::vector<uint8_t> &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<uint8_t> &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;
|
||||
|
||||
@@ -19,11 +19,11 @@ public:
|
||||
TextDrawerSDL(Draw::DrawContext *draw);
|
||||
~TextDrawerSDL();
|
||||
|
||||
bool DrawStringBitmap(std::vector<uint8_t> &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<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
|
||||
|
||||
bool SupportsColorEmoji() const override { return false; }
|
||||
void ClearFonts() override;
|
||||
|
||||
@@ -300,7 +300,7 @@ void TextDrawerUWP::MeasureStringInternal(const FontStyle &style, std::string_vi
|
||||
*h = (int)(metrics.height + 1.0f);
|
||||
}
|
||||
|
||||
bool TextDrawerUWP::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) {
|
||||
bool TextDrawerUWP::DrawStringBitmap(const FontStyle &style, std::vector<uint8_t> &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<uint8_t> &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;
|
||||
}
|
||||
|
||||
@@ -20,11 +20,11 @@ public:
|
||||
TextDrawerUWP(Draw::DrawContext *draw);
|
||||
~TextDrawerUWP();
|
||||
|
||||
bool DrawStringBitmap(std::vector<uint8_t> &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<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
|
||||
bool SupportsColorEmoji() const override { return true; }
|
||||
void ClearFonts() override;
|
||||
|
||||
|
||||
@@ -154,14 +154,14 @@ void TextDrawerWin32::MeasureStringInternal(const FontStyle &style, std::string_
|
||||
*h = extH;
|
||||
}
|
||||
|
||||
bool TextDrawerWin32::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) {
|
||||
bool TextDrawerWin32::DrawStringBitmap(const FontStyle &style, std::vector<uint8_t> &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);
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@ public:
|
||||
TextDrawerWin32(Draw::DrawContext *draw);
|
||||
~TextDrawerWin32();
|
||||
|
||||
bool DrawStringBitmap(std::vector<uint8_t> &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<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
|
||||
bool SupportsColorEmoji() const override { return false; }
|
||||
void ClearFonts() override;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
+6
-10
@@ -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<uint8_t> 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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
+14
-26
@@ -3744,18 +3744,16 @@ bool TestFatShortNames() {
|
||||
class FakeTextDrawer : public TextDrawer {
|
||||
public:
|
||||
FakeTextDrawer() : TextDrawer(nullptr) {}
|
||||
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override { return false; }
|
||||
|
||||
void TestDropShadow(std::vector<uint8_t> &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<uint8_t> &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<std::string_view> 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<uint8_t> bitmap;
|
||||
shadowTest(1.0f, entry1, bitmap);
|
||||
|
||||
Reference in new issue
Block a user