mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-12 00:59:41 +01:00
Merge pull request #10176 from hrydgard/android-text-fixes
Android text fixes
This commit is contained in:
9 files changed
+44
-40
No files matched your search
@@ -26,10 +26,8 @@ public class TextRenderer {
|
||||
}
|
||||
}
|
||||
private static Point measure(String string, double textSize) {
|
||||
Rect bound = new Rect();
|
||||
p.setTextSize((float)textSize);
|
||||
p.getTextBounds(string, 0, string.length(), bound);
|
||||
int w = bound.width();
|
||||
int w = (int)p.measureText(string);
|
||||
int h = (int)(p.descent() - p.ascent() + 2.0f);
|
||||
// Round width up to even already here to avoid annoyances from odd-width 16-bit textures which
|
||||
// OpenGL does not like - each line must be 4-byte aligned
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user