mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Get rid of collision-prone font cache keys. Stress the font cache a little less on slider dialogs.
This commit is contained in:
parent
543bb34dbc
commit
3ecd7b4c02
8 changed files with 43 additions and 37 deletions
|
@ -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_;
|
||||
|
|
|
@ -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<TextMeasureEntry>(entry);
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(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<TextMeasureEntry>(entry);
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(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<TextStringEntry>(entry);
|
||||
cache_[key] = std::unique_ptr<TextStringEntry>(entry);
|
||||
draw_->BindTexture(0, entry->texture);
|
||||
}
|
||||
float w = entry->bmWidth * fontScaleX_ * dpiScale_;
|
||||
|
|
|
@ -44,9 +44,8 @@ private:
|
|||
|
||||
std::map<uint32_t, AndroidFontEntry> fontMap_;
|
||||
|
||||
// The key is the CityHash of the string xor the fontHash_.
|
||||
std::map<uint32_t, std::unique_ptr<TextStringEntry>> cache_;
|
||||
std::map<uint32_t, std::unique_ptr<TextMeasureEntry>> sizeCache_;
|
||||
std::map<CacheKey, std::unique_ptr<TextStringEntry>> cache_;
|
||||
std::map<CacheKey, std::unique_ptr<TextMeasureEntry>> sizeCache_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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<TextMeasureEntry>(entry);
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(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<TextMeasureEntry>(entry);
|
||||
sizeCache_[key] = std::unique_ptr<TextMeasureEntry>(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<TextStringEntry>(entry);
|
||||
cache_[key] = std::unique_ptr<TextStringEntry>(entry);
|
||||
}
|
||||
|
||||
draw_->BindTexture(0, entry->texture);
|
||||
|
|
|
@ -36,9 +36,8 @@ protected:
|
|||
std::map<uint32_t, std::unique_ptr<TextDrawerFontContext>> fontMap_;
|
||||
|
||||
uint32_t fontHash_;
|
||||
// The key is the CityHash of the string xor the fontHash_.
|
||||
std::map<uint32_t, std::unique_ptr<TextStringEntry>> cache_;
|
||||
std::map<uint32_t, std::unique_ptr<TextMeasureEntry>> sizeCache_;
|
||||
std::map<CacheKey, std::unique_ptr<TextStringEntry>> cache_;
|
||||
std::map<CacheKey, std::unique_ptr<TextMeasureEntry>> sizeCache_;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -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_);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue