Merge pull request #19223 from hrydgard/more-text-cleanup

More text rendering code cleanup
This commit is contained in:
Henrik Rydgård 2024-06-01 10:35:33 +02:00 committed by GitHub
commit e1b760f628
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 75 additions and 282 deletions

View File

@ -164,6 +164,49 @@ bool TextDrawer::DrawStringBitmapRect(std::vector<uint8_t> &bitmapData, TextStri
return DrawStringBitmap(bitmapData, entry, texFormat, toDraw.c_str(), align, fullColor);
}
void TextDrawer::ClearCache() {
for (auto &iter : cache_) {
if (iter.second->texture)
iter.second->texture->Release();
}
cache_.clear();
sizeCache_.clear();
fontHash_ = 0;
}
void TextDrawer::OncePerFrame() {
frameCount_++;
// If DPI changed (small-mode, future proper monitor DPI support), drop everything.
float newDpiScale = CalculateDPIScale();
if (newDpiScale != dpiScale_) {
INFO_LOG(G3D, "DPI Scale changed (%f to %f) - wiping font cache (%d items)", dpiScale_, newDpiScale, (int)cache_.size());
dpiScale_ = newDpiScale;
ClearCache();
ClearFonts();
}
// Drop old strings. Use a prime number to reduce clashing with other rhythms
if (frameCount_ % 23 == 0) {
for (auto iter = cache_.begin(); iter != cache_.end();) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
if (iter->second->texture)
iter->second->texture->Release();
cache_.erase(iter++);
} else {
iter++;
}
}
for (auto iter = sizeCache_.begin(); iter != sizeCache_.end(); ) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
sizeCache_.erase(iter++);
} else {
iter++;
}
}
}
}
TextDrawer *TextDrawer::Create(Draw::DrawContext *draw) {
TextDrawer *drawer = nullptr;
#if defined(__LIBRETRO__)

View File

@ -56,7 +56,7 @@ public:
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);
// Use for housekeeping like throwing out old strings.
virtual void OncePerFrame() = 0;
void OncePerFrame();
float CalculateDPIScale();
void SetForcedDPIScale(float dpi) {
@ -69,9 +69,10 @@ public:
protected:
TextDrawer(Draw::DrawContext *draw);
void ClearCache();
virtual bool SupportsColorEmoji() const = 0;
virtual void ClearCache() = 0;
virtual void ClearFonts() = 0;
void WrapString(std::string &out, std::string_view str, float maxWidth, int flags);

View File

@ -37,6 +37,7 @@ TextDrawerAndroid::~TextDrawerAndroid() {
// At worst we leak one ref...
// env_->DeleteGlobalRef(cls_textRenderer);
ClearCache();
ClearFonts();
}
bool TextDrawerAndroid::IsReady() const {
@ -184,47 +185,8 @@ bool TextDrawerAndroid::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextS
return true;
}
void TextDrawerAndroid::ClearCache() {
for (auto &iter : cache_) {
if (iter.second->texture)
iter.second->texture->Release();
}
cache_.clear();
sizeCache_.clear();
}
void TextDrawerAndroid::OncePerFrame() {
frameCount_++;
// If DPI changed (small-mode, future proper monitor DPI support), drop everything.
float newDpiScale = CalculateDPIScale();
if (newDpiScale != dpiScale_) {
// TODO: Don't bother if it's a no-op (cache already empty)
INFO_LOG(G3D, "DPI Scale changed (%f to %f) - wiping font cache (%d items, %d fonts)", dpiScale_, newDpiScale, (int)cache_.size(), (int)fontMap_.size());
dpiScale_ = newDpiScale;
ClearCache();
fontMap_.clear(); // size is precomputed using dpiScale_.
}
// Drop old strings. Use a prime number to reduce clashing with other rhythms
if (frameCount_ % 23 == 0) {
for (auto iter = cache_.begin(); iter != cache_.end();) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
if (iter->second->texture)
iter->second->texture->Release();
cache_.erase(iter++);
} else {
iter++;
}
}
for (auto iter = sizeCache_.begin(); iter != sizeCache_.end(); ) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
sizeCache_.erase(iter++);
} else {
iter++;
}
}
}
void TextDrawerAndroid::ClearFonts() {
fontMap_.clear(); // size is precomputed using dpiScale_.
}
#endif

View File

@ -23,13 +23,11 @@ public:
void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once.
void MeasureString(std::string_view str, float *w, float *h) override;
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
// Use for housekeeping like throwing out old strings.
void OncePerFrame() override;
protected:
bool SupportsColorEmoji() const override { return true; }
void ClearCache() override;
void ClearFonts() override;
private:
// JNI functions

View File

@ -20,14 +20,11 @@ public:
void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once.
void MeasureString(std::string_view str, float *w, float *h) override;
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
// Use for housekeeping like throwing out old strings.
void OncePerFrame() override;
protected:
bool SupportsColorEmoji() const override { return true; }
void ClearCache() override;
void RecreateFonts(); // On DPI change
void ClearFonts() override;
TextDrawerContext *ctx_;
std::map<uint32_t, std::unique_ptr<TextDrawerFontContext>> fontMap_;

View File

@ -69,8 +69,7 @@ TextDrawerCocoa::TextDrawerCocoa(Draw::DrawContext *draw) : TextDrawer(draw) {
TextDrawerCocoa::~TextDrawerCocoa() {
ClearCache();
fontMap_.clear();
ClearFonts();
}
// TODO: Share with other backends.
@ -110,20 +109,12 @@ void TextDrawerCocoa::SetFont(uint32_t fontHandle) {
}
}
void TextDrawerCocoa::ClearCache() {
for (auto &iter : cache_) {
if (iter.second->texture)
iter.second->texture->Release();
}
cache_.clear();
sizeCache_.clear();
}
void TextDrawerCocoa::RecreateFonts() {
void TextDrawerCocoa::ClearFonts() {
for (auto &iter : fontMap_) {
iter.second->dpiScale = dpiScale_;
iter.second->Create();
iter.second->Destroy();
}
fontMap_.clear();
}
void TextDrawerCocoa::MeasureString(std::string_view str, float *w, float *h) {
@ -299,37 +290,4 @@ bool TextDrawerCocoa::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStr
return true;
}
void TextDrawerCocoa::OncePerFrame() {
frameCount_++;
// If DPI changed (small-mode, future proper monitor DPI support), drop everything.
float newDpiScale = CalculateDPIScale();
if (newDpiScale != dpiScale_) {
INFO_LOG(G3D, "TextDrawerCocoa: DPI scale: %0.1f", newDpiScale);
dpiScale_ = newDpiScale;
ClearCache();
RecreateFonts();
}
// Drop old strings. Use a prime number to reduce clashing with other rhythms
if (frameCount_ % 23 == 0) {
for (auto iter = cache_.begin(); iter != cache_.end();) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
if (iter->second->texture)
iter->second->texture->Release();
cache_.erase(iter++);
} else {
iter++;
}
}
for (auto iter = sizeCache_.begin(); iter != sizeCache_.end(); ) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
sizeCache_.erase(iter++);
} else {
iter++;
}
}
}
}
#endif

View File

@ -20,6 +20,7 @@ TextDrawerQt::TextDrawerQt(Draw::DrawContext *draw) : TextDrawer(draw) {}
TextDrawerQt::~TextDrawerQt() {
ClearCache();
ClearFonts();
}
uint32_t TextDrawerQt::SetFont(const char *fontName, int size, int flags) {
@ -125,13 +126,7 @@ bool TextDrawerQt::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextString
return true;
}
void TextDrawerQt::ClearCache() {
for (auto &iter : cache_) {
if (iter.second->texture)
iter.second->texture->Release();
}
cache_.clear();
sizeCache_.clear();
void TextDrawerQt::ClearFonts() {
// Also wipe the font map.
for (auto iter : fontMap_) {
delete iter.second;
@ -140,35 +135,4 @@ void TextDrawerQt::ClearCache() {
fontHash_ = 0;
}
void TextDrawerQt::OncePerFrame() {
frameCount_++;
// If DPI changed (small-mode, future proper monitor DPI support), drop everything.
float newDpiScale = CalculateDPIScale();
if (newDpiScale != dpiScale_) {
dpiScale_ = newDpiScale;
ClearCache();
}
// Drop old strings. Use a prime number to reduce clashing with other rhythms
if (frameCount_ % 23 == 0) {
for (auto iter = cache_.begin(); iter != cache_.end();) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
if (iter->second->texture)
iter->second->texture->Release();
cache_.erase(iter++);
} else {
iter++;
}
}
for (auto iter = sizeCache_.begin(); iter != sizeCache_.end(); ) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
sizeCache_.erase(iter++);
} else {
iter++;
}
}
}
}
#endif

View File

@ -18,13 +18,11 @@ public:
void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once.
void MeasureString(std::string_view str, float *w, float *h) override;
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
// Use for housekeeping like throwing out old strings.
void OncePerFrame() override;
protected:
bool SupportsColorEmoji() const override { return false; }
void ClearCache() override;
void ClearFonts() override;
std::map<uint32_t, QFont *> fontMap_;
};

View File

@ -46,6 +46,8 @@ TextDrawerSDL::TextDrawerSDL(Draw::DrawContext *draw): TextDrawer(draw) {
TextDrawerSDL::~TextDrawerSDL() {
ClearCache();
ClearFonts();
TTF_Quit();
#if defined(USE_SDL2_TTF_FONTCONFIG)
@ -392,44 +394,7 @@ bool TextDrawerSDL::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStrin
return true;
}
void TextDrawerSDL::OncePerFrame() {
// Reset everything if DPI changes
float newDpiScale = CalculateDPIScale();
if (newDpiScale != dpiScale_) {
dpiScale_ = newDpiScale;
ClearCache();
}
// Drop old strings. Use a prime number to reduce clashing with other rhythms
if (frameCount_ % 23 == 0) {
for (auto iter = cache_.begin(); iter != cache_.end();) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
if (iter->second->texture)
iter->second->texture->Release();
cache_.erase(iter++);
} else {
iter++;
}
}
for (auto iter = sizeCache_.begin(); iter != sizeCache_.end(); ) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
sizeCache_.erase(iter++);
} else {
iter++;
}
}
}
}
void TextDrawerSDL::ClearCache() {
for (auto &iter : cache_) {
if (iter.second->texture)
iter.second->texture->Release();
}
cache_.clear();
sizeCache_.clear();
void TextDrawerSDL::ClearFonts() {
for (auto iter : fontMap_) {
TTF_CloseFont(iter.second);
}
@ -438,7 +403,6 @@ void TextDrawerSDL::ClearCache() {
}
fontMap_.clear();
fallbackFonts_.clear();
fontHash_ = 0;
}
#endif

View File

@ -21,13 +21,12 @@ public:
void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once.
void MeasureString(std::string_view str, float *w, float *h) override;
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
// Use for housekeeping like throwing out old strings.
void OncePerFrame() override;
protected:
bool SupportsColorEmoji() const override { return false; }
void ClearFonts() override;
void ClearCache() override;
private:
void PrepareFallbackFonts(std::string_view locale);
uint32_t CheckMissingGlyph(const std::string& text);
int FindFallbackFonts(uint32_t missingGlyph, int ptSize);

View File

@ -141,8 +141,7 @@ TextDrawerUWP::TextDrawerUWP(Draw::DrawContext *draw) : TextDrawer(draw), ctx_(n
TextDrawerUWP::~TextDrawerUWP() {
ClearCache();
fontMap_.clear();
ClearFonts();
ctx_->bitmap->Release();
ctx_->mirror_bmp->Release();
@ -377,52 +376,12 @@ bool TextDrawerUWP::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStrin
return true;
}
void TextDrawerUWP::RecreateFonts() {
void TextDrawerUWP::ClearFonts() {
for (auto &iter : fontMap_) {
iter.second->dpiScale = dpiScale_;
iter.second->Create();
}
}
void TextDrawerUWP::ClearCache() {
for (auto &iter : cache_) {
if (iter.second->texture)
iter.second->texture->Release();
}
cache_.clear();
sizeCache_.clear();
}
void TextDrawerUWP::OncePerFrame() {
frameCount_++;
// If DPI changed (small-mode, future proper monitor DPI support), drop everything.
float newDpiScale = CalculateDPIScale();
if (newDpiScale != dpiScale_) {
dpiScale_ = newDpiScale;
ClearCache();
RecreateFonts();
}
// Drop old strings. Use a prime number to reduce clashing with other rhythms
if (frameCount_ % 23 == 0) {
for (auto iter = cache_.begin(); iter != cache_.end();) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
if (iter->second->texture)
iter->second->texture->Release();
cache_.erase(iter++);
} else {
iter++;
}
}
for (auto iter = sizeCache_.begin(); iter != sizeCache_.end(); ) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
sizeCache_.erase(iter++);
} else {
iter++;
}
}
iter.second->Destroy();
}
fontMap_.clear();
}
#endif

View File

@ -23,14 +23,10 @@ public:
void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once.
void MeasureString(std::string_view str, float *w, float *h) override;
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
// Use for housekeeping like throwing out old strings.
void OncePerFrame() override;
protected:
bool SupportsColorEmoji() const override { return true; }
void ClearCache() override;
void RecreateFonts(); // On DPI change
void ClearFonts() override;
TextDrawerContext *ctx_;
std::map<uint32_t, std::unique_ptr<TextDrawerFontContext>> fontMap_;

View File

@ -77,8 +77,7 @@ TextDrawerWin32::TextDrawerWin32(Draw::DrawContext *draw) : TextDrawer(draw), ct
TextDrawerWin32::~TextDrawerWin32() {
ClearCache();
fontMap_.clear();
ClearFonts();
DeleteObject(ctx_->hbmBitmap);
DeleteDC(ctx_->hDC);
@ -255,52 +254,11 @@ bool TextDrawerWin32::DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStr
return true;
}
void TextDrawerWin32::RecreateFonts() {
void TextDrawerWin32::ClearFonts() {
for (auto &iter : fontMap_) {
iter.second->dpiScale = dpiScale_;
iter.second->Create();
}
}
void TextDrawerWin32::ClearCache() {
for (auto &iter : cache_) {
if (iter.second->texture)
iter.second->texture->Release();
}
cache_.clear();
sizeCache_.clear();
}
void TextDrawerWin32::OncePerFrame() {
frameCount_++;
// If DPI changed (small-mode, future proper monitor DPI support), drop everything.
float newDpiScale = CalculateDPIScale();
if (newDpiScale != dpiScale_) {
dpiScale_ = newDpiScale;
ClearCache();
RecreateFonts();
}
// Drop old strings. Use a prime number to reduce clashing with other rhythms
if (frameCount_ % 23 == 0) {
for (auto iter = cache_.begin(); iter != cache_.end();) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
if (iter->second->texture)
iter->second->texture->Release();
cache_.erase(iter++);
} else {
iter++;
}
}
for (auto iter = sizeCache_.begin(); iter != sizeCache_.end(); ) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
sizeCache_.erase(iter++);
} else {
iter++;
}
}
iter.second->Destroy();
}
fontMap_.clear();
}
#endif

View File

@ -23,14 +23,10 @@ public:
void SetFont(uint32_t fontHandle) override; // Shortcut once you've set the font once.
void MeasureString(std::string_view str, float *w, float *h) override;
bool DrawStringBitmap(std::vector<uint8_t> &bitmapData, TextStringEntry &entry, Draw::DataFormat texFormat, std::string_view str, int align, bool fullColor) override;
// Use for housekeeping like throwing out old strings.
void OncePerFrame() override;
protected:
bool SupportsColorEmoji() const override { return false; }
void ClearCache() override;
void RecreateFonts(); // On DPI change
void ClearFonts() override;
TextDrawerContext *ctx_;
std::map<uint32_t, std::unique_ptr<TextDrawerFontContext>> fontMap_;

View File

@ -71,9 +71,9 @@ Enable Sound = Ljud
Global volume = Global volym
Microphone = Mikrofon
Microphone Device = Mikrofon-enhet
Mix audio with other apps = Mix audio with other apps
Mix audio with other apps = Mixa ljud med andra appar
Mute = Tysta
Respect silent mode = Respect silent mode
Respect silent mode = Respektera tyst läge
Reverb volume = Volym på reverb-effekt
Use new audio devices automatically = Byt automatiskt till senast inkopplad ljudenhet
Use global volume = Använd global volym