diff --git a/ext/native/gfx_es2/draw_text.h b/ext/native/gfx_es2/draw_text.h index 482e3912b7..a36db98ad2 100644 --- a/ext/native/gfx_es2/draw_text.h +++ b/ext/native/gfx_es2/draw_text.h @@ -74,6 +74,18 @@ protected: virtual void ClearCache() = 0; void WrapString(std::string &out, const char *str, float maxWidth); + struct CacheKey { + bool operator < (const CacheKey &other) const { + if (fontHash < other.fontHash) + return true; + if (fontHash > other.fontHash) + return false; + return text < other.text; + } + std::string text; + uint32_t fontHash; + }; + int frameCount_; float fontScaleX_; float fontScaleY_; diff --git a/ext/native/gfx_es2/draw_text_android.cpp b/ext/native/gfx_es2/draw_text_android.cpp index c8e7ed1925..922e578a6e 100644 --- a/ext/native/gfx_es2/draw_text_android.cpp +++ b/ext/native/gfx_es2/draw_text_android.cpp @@ -80,11 +80,9 @@ std::string TextDrawerAndroid::NormalizeString(std::string str) { } void TextDrawerAndroid::MeasureString(const char *str, size_t len, float *w, float *h) { - uint32_t stringHash = hash::Adler32((const uint8_t *)str, len); - uint32_t entryHash = stringHash ^ fontHash_; - + CacheKey key{ std::string(str, len), fontHash_ }; TextMeasureEntry *entry; - auto iter = sizeCache_.find(entryHash); + auto iter = sizeCache_.find(key); if (iter != sizeCache_.end()) { entry = iter->second.get(); } else { @@ -103,7 +101,7 @@ void TextDrawerAndroid::MeasureString(const char *str, size_t len, float *w, flo entry = new TextMeasureEntry(); entry->width = (size >> 16); entry->height = (size & 0xFFFF); - sizeCache_[entryHash] = std::unique_ptr(entry); + sizeCache_[key] = std::unique_ptr(entry); } entry->lastUsedFrame = frameCount_; *w = entry->width * fontScaleX_ * dpiScale_; @@ -130,11 +128,10 @@ void TextDrawerAndroid::MeasureStringRect(const char *str, size_t len, const Bou float total_w = 0.0f; float total_h = 0.0f; for (size_t i = 0; i < lines.size(); i++) { - uint32_t stringHash = hash::Adler32((const uint8_t *)&lines[i][0], lines[i].length()); - uint32_t entryHash = stringHash ^ fontHash_; + CacheKey key{ lines[i], fontHash_ }; TextMeasureEntry *entry; - auto iter = sizeCache_.find(entryHash); + auto iter = sizeCache_.find(key); if (iter != sizeCache_.end()) { entry = iter->second.get(); } else { @@ -147,7 +144,7 @@ void TextDrawerAndroid::MeasureStringRect(const char *str, size_t len, const Bou entry = new TextMeasureEntry(); entry->width = sizecx; entry->height = sizecy; - sizeCache_[entryHash] = std::unique_ptr(entry); + sizeCache_[key] = std::unique_ptr(entry); } entry->lastUsedFrame = frameCount_; @@ -166,14 +163,12 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, if (text.empty()) return; - uint32_t stringHash = hash::Adler32((const uint8_t *)text.data(), text.size()); - uint32_t entryHash = stringHash ^ fontHash_ ^ (align << 24); - + CacheKey key{ std::string(str), fontHash_ }; target.Flush(true); TextStringEntry *entry; - auto iter = cache_.find(entryHash); + auto iter = cache_.find(key); if (iter != cache_.end()) { entry = iter->second.get(); entry->lastUsedFrame = frameCount_; @@ -223,7 +218,7 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, desc.initData.push_back((uint8_t *)bitmapData); entry->texture = draw_->CreateTexture(desc); delete[] bitmapData; - cache_[entryHash] = std::unique_ptr(entry); + cache_[key] = std::unique_ptr(entry); draw_->BindTexture(0, entry->texture); } float w = entry->bmWidth * fontScaleX_ * dpiScale_; diff --git a/ext/native/gfx_es2/draw_text_android.h b/ext/native/gfx_es2/draw_text_android.h index 010cb8c8b5..9ed3fdbd22 100644 --- a/ext/native/gfx_es2/draw_text_android.h +++ b/ext/native/gfx_es2/draw_text_android.h @@ -44,9 +44,8 @@ private: std::map fontMap_; - // The key is the CityHash of the string xor the fontHash_. - std::map> cache_; - std::map> sizeCache_; + std::map> cache_; + std::map> sizeCache_; }; #endif diff --git a/ext/native/gfx_es2/draw_text_win.cpp b/ext/native/gfx_es2/draw_text_win.cpp index 4f0dd44e19..0b500af293 100644 --- a/ext/native/gfx_es2/draw_text_win.cpp +++ b/ext/native/gfx_es2/draw_text_win.cpp @@ -119,11 +119,10 @@ void TextDrawerWin32::SetFont(uint32_t fontHandle) { } void TextDrawerWin32::MeasureString(const char *str, size_t len, float *w, float *h) { - uint32_t stringHash = hash::Adler32((const uint8_t *)str, len); - uint32_t entryHash = stringHash ^ fontHash_; - + CacheKey key{ std::string(str, len), fontHash_ }; + TextMeasureEntry *entry; - auto iter = sizeCache_.find(entryHash); + auto iter = sizeCache_.find(key); if (iter != sizeCache_.end()) { entry = iter->second.get(); } else { @@ -139,7 +138,7 @@ void TextDrawerWin32::MeasureString(const char *str, size_t len, float *w, float entry = new TextMeasureEntry(); entry->width = size.cx; entry->height = size.cy; - sizeCache_[entryHash] = std::unique_ptr(entry); + sizeCache_[key] = std::unique_ptr(entry); } entry->lastUsedFrame = frameCount_; @@ -164,11 +163,10 @@ void TextDrawerWin32::MeasureStringRect(const char *str, size_t len, const Bound float total_w = 0.0f; float total_h = 0.0f; for (size_t i = 0; i < lines.size(); i++) { - uint32_t stringHash = hash::Adler32((const uint8_t *)&lines[i][0], lines[i].length()); - uint32_t entryHash = stringHash ^ fontHash_; + CacheKey key{ lines[i], fontHash_ }; TextMeasureEntry *entry; - auto iter = sizeCache_.find(entryHash); + auto iter = sizeCache_.find(key); if (iter != sizeCache_.end()) { entry = iter->second.get(); } else { @@ -179,7 +177,7 @@ void TextDrawerWin32::MeasureStringRect(const char *str, size_t len, const Bound entry = new TextMeasureEntry(); entry->width = size.cx; entry->height = size.cy; - sizeCache_[entryHash] = std::unique_ptr(entry); + sizeCache_[key] = std::unique_ptr(entry); } entry->lastUsedFrame = frameCount_; @@ -197,14 +195,13 @@ void TextDrawerWin32::DrawString(DrawBuffer &target, const char *str, float x, f if (!strlen(str)) return; - uint32_t stringHash = hash::Adler32((const uint8_t *)str, strlen(str)); - uint32_t entryHash = stringHash ^ fontHash_ ^ (align << 24); + CacheKey key{ std::string(str), fontHash_ }; target.Flush(true); TextStringEntry *entry; - auto iter = cache_.find(entryHash); + auto iter = cache_.find(key); if (iter != cache_.end()) { entry = iter->second.get(); entry->lastUsedFrame = frameCount_; @@ -304,7 +301,7 @@ void TextDrawerWin32::DrawString(DrawBuffer &target, const char *str, float x, f delete[] bitmapData16; if (bitmapData32) delete[] bitmapData32; - cache_[entryHash] = std::unique_ptr(entry); + cache_[key] = std::unique_ptr(entry); } draw_->BindTexture(0, entry->texture); diff --git a/ext/native/gfx_es2/draw_text_win.h b/ext/native/gfx_es2/draw_text_win.h index a8d35744b5..ec76d3ef2b 100644 --- a/ext/native/gfx_es2/draw_text_win.h +++ b/ext/native/gfx_es2/draw_text_win.h @@ -36,9 +36,8 @@ protected: std::map> fontMap_; uint32_t fontHash_; - // The key is the CityHash of the string xor the fontHash_. - std::map> cache_; - std::map> sizeCache_; + std::map> cache_; + std::map> sizeCache_; }; #endif \ No newline at end of file diff --git a/ext/native/ui/ui_screen.cpp b/ext/native/ui/ui_screen.cpp index a8bb3147bc..a661f6208b 100644 --- a/ext/native/ui/ui_screen.cpp +++ b/ext/native/ui/ui_screen.cpp @@ -638,6 +638,7 @@ void SliderPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { edit_ = new TextEdit(temp, "", new LinearLayoutParams(10.0f)); edit_->SetMaxLen(16); edit_->SetTextColor(dc.theme->popupStyle.fgColor); + edit_->SetTextAlign(FLAG_DYNAMIC_ASCII); edit_->OnTextChange.Handle(this, &SliderPopupScreen::OnTextChange); changing_ = false; lin->Add(edit_); @@ -668,6 +669,7 @@ void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { edit_ = new TextEdit(temp, "", new LinearLayoutParams(10.0f)); edit_->SetMaxLen(16); edit_->SetTextColor(dc.theme->popupStyle.fgColor); + edit_->SetTextAlign(FLAG_DYNAMIC_ASCII); edit_->OnTextChange.Handle(this, &SliderFloatPopupScreen::OnTextChange); changing_ = false; lin->Add(edit_); diff --git a/ext/native/ui/view.cpp b/ext/native/ui/view.cpp index 65f1aab6fe..ad977e12da 100644 --- a/ext/native/ui/view.cpp +++ b/ext/native/ui/view.cpp @@ -791,12 +791,12 @@ void TextEdit::Draw(UIContext &dc) { dc.DrawTextRect(placeholderText_.c_str(), bounds_, c, ALIGN_CENTER); } } else { - dc.DrawTextRect(text_.c_str(), textBounds, textColor, ALIGN_VCENTER | ALIGN_LEFT); + dc.DrawTextRect(text_.c_str(), textBounds, textColor, ALIGN_VCENTER | ALIGN_LEFT | align_); } if (HasFocus()) { // Hack to find the caret position. Might want to find a better way... - dc.MeasureTextCount(dc.theme->uiFont, 1.0f, 1.0f, text_.c_str(), caret_, &w, &h, ALIGN_VCENTER | ALIGN_LEFT); + dc.MeasureTextCount(dc.theme->uiFont, 1.0f, 1.0f, text_.c_str(), caret_, &w, &h, ALIGN_VCENTER | ALIGN_LEFT | align_); float caretX = w - scrollPos_; if (caretX > bounds_.w) { scrollPos_ += caretX - bounds_.w; @@ -811,7 +811,7 @@ void TextEdit::Draw(UIContext &dc) { } void TextEdit::GetContentDimensions(const UIContext &dc, float &w, float &h) const { - dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, text_.size() ? text_.c_str() : "Wj", &w, &h); + dc.MeasureText(dc.theme->uiFont, 1.0f, 1.0f, text_.size() ? text_.c_str() : "Wj", &w, &h, align_); w += 2; h += 2; } @@ -1115,7 +1115,7 @@ void Slider::Draw(UIContext &dc) { else sprintf(temp, "%i", *value_); dc.SetFontStyle(dc.theme->uiFont); - dc.DrawText(temp, bounds_.x2() - 22, bounds_.centerY(), dc.theme->popupStyle.fgColor, ALIGN_CENTER); + dc.DrawText(temp, bounds_.x2() - 22, bounds_.centerY(), dc.theme->popupStyle.fgColor, ALIGN_CENTER | FLAG_DYNAMIC_ASCII); } void Slider::Update() { diff --git a/ext/native/ui/view.h b/ext/native/ui/view.h index 93afab7c18..a5a0cbac4c 100644 --- a/ext/native/ui/view.h +++ b/ext/native/ui/view.h @@ -784,6 +784,7 @@ public: void SetTextColor(uint32_t color) { textColor_ = color; hasTextColor_ = true; } const std::string &GetText() const { return text_; } void SetMaxLen(size_t maxLen) { maxLen_ = maxLen; } + void SetTextAlign(int align) { align_ = align; } // Only really useful for setting FLAG_DYNAMIC_ASCII void GetContentDimensions(const UIContext &dc, float &w, float &h) const override; void Draw(UIContext &dc) override; @@ -805,6 +806,7 @@ private: int scrollPos_ = 0; size_t maxLen_; bool ctrlDown_ = false; // TODO: Make some global mechanism for this. + int align_ = 0; // TODO: Selections };