UI: Cache measured text sizes.

This can be a bit slow to ask the font renderer every frame, might as well
cache like we do the drawn version.
This commit is contained in:
Unknown W. Brackets committed 2016-09-04 09:10:50 -07:00
1 parent 995e056598
commit 57e68be754
2 files changed
+80 -21

No files matched your search

+73 -21
View File
@@ -73,13 +73,18 @@ TextDrawer::TextDrawer(Thin3DContext *thin3d) : thin3d_(thin3d), ctx_(NULL) {
}
TextDrawer::~TextDrawer() {
for (auto iter = cache_.begin(); iter != cache_.end(); ++iter) {
if (iter->second->texture)
iter->second->texture->Release();
delete iter->second;
for (auto iter : cache_) {
if (iter.second->texture)
iter.second->texture->Release();
delete iter.second;
}
cache_.clear();
for (auto iter : sizeCache_) {
delete iter.second;
}
sizeCache_.clear();
for (auto iter = fontMap_.begin(); iter != fontMap_.end(); ++iter) {
DeleteObject(iter->second->hFont);
delete iter->second;
@@ -136,16 +141,32 @@ void TextDrawer::MeasureString(const char *str, float *w, float *h) {
}
void TextDrawer::MeasureString(const char *str, size_t len, float *w, float *h) {
auto iter = fontMap_.find(fontHash_);
if (iter != fontMap_.end()) {
SelectObject(ctx_->hDC, iter->second->hFont);
uint32_t stringHash = hash::Fletcher((const uint8_t *)str, len);
uint32_t entryHash = stringHash ^ fontHash_;
TextMeasureEntry *entry;
auto iter = sizeCache_.find(entryHash);
if (iter != sizeCache_.end()) {
entry = iter->second;
} else {
auto iter = fontMap_.find(fontHash_);
if (iter != fontMap_.end()) {
SelectObject(ctx_->hDC, iter->second->hFont);
}
SIZE size;
std::wstring wstr = ConvertUTF8ToWString(ReplaceAll(std::string(str, len), "\n", "\r\n"));
GetTextExtentPoint32(ctx_->hDC, wstr.c_str(), (int)wstr.size(), &size);
entry = new TextMeasureEntry();
entry->width = size.cx;
entry->height = size.cy;
sizeCache_[entryHash] = entry;
}
SIZE size;
std::wstring wstr = ConvertUTF8ToWString(ReplaceAll(std::string(str, len), "\n", "\r\n"));
GetTextExtentPoint32(ctx_->hDC, wstr.c_str(), (int)wstr.size(), &size);
*w = size.cx * fontScaleX_;
*h = size.cy * fontScaleY_;
entry->lastUsedFrame = frameCount_;
*w = entry->width * fontScaleX_;
*h = entry->height * fontScaleY_;
}
void TextDrawer::MeasureStringRect(const char *str, size_t len, const Bounds &bounds, float *w, float *h, int align) {
@@ -165,13 +186,29 @@ void TextDrawer::MeasureStringRect(const char *str, size_t len, const Bounds &bo
float total_w = 0.0f;
float total_h = 0.0f;
for (size_t i = 0; i < lines.size(); i++) {
SIZE size;
std::wstring wstr = ConvertUTF8ToWString(lines[i].length() == 0 ? " " : lines[i]);
GetTextExtentPoint32(ctx_->hDC, wstr.c_str(), (int)wstr.size(), &size);
if (total_w < size.cx * fontScaleX_) {
total_w = size.cx * fontScaleX_;
uint32_t stringHash = hash::Fletcher((const uint8_t *)&lines[i][0], lines[i].length());
uint32_t entryHash = stringHash ^ fontHash_;
TextMeasureEntry *entry;
auto iter = sizeCache_.find(entryHash);
if (iter != sizeCache_.end()) {
entry = iter->second;
} else {
SIZE size;
std::wstring wstr = ConvertUTF8ToWString(lines[i].length() == 0 ? " " : lines[i]);
GetTextExtentPoint32(ctx_->hDC, wstr.c_str(), (int)wstr.size(), &size);
entry = new TextMeasureEntry();
entry->width = size.cx;
entry->height = size.cy;
sizeCache_[entryHash] = entry;
}
total_h += size.cy * fontScaleY_;
entry->lastUsedFrame = frameCount_;
if (total_w < entry->width * fontScaleX_) {
total_w = entry->width * fontScaleX_;
}
total_h += entry->height * fontScaleY_;
}
*w = total_w;
*h = total_h;
@@ -268,11 +305,17 @@ TextDrawer::TextDrawer(Thin3DContext *thin3d) : thin3d_(thin3d), ctx_(NULL) {
}
TextDrawer::~TextDrawer() {
for (auto iter = cache_.begin(); iter != cache_.end(); ++iter) {
iter->second->texture->Release();
delete iter->second;
for (auto iter : cache_) {
if (iter.second->texture)
iter.second->texture->Release();
delete iter.second;
}
cache_.clear();
for (auto iter : sizeCache_) {
delete iter.second;
}
sizeCache_.clear();
}
uint32_t TextDrawer::SetFont(const char *fontName, int size, int flags) {
@@ -450,5 +493,14 @@ void TextDrawer::OncePerFrame() {
iter++;
}
}
for (auto iter = sizeCache_.begin(); iter != sizeCache_.end(); ) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
delete iter->second;
sizeCache_.erase(iter++);
} else {
iter++;
}
}
}
}
+7
View File
@@ -29,6 +29,12 @@ struct TextStringEntry {
int lastUsedFrame;
};
struct TextMeasureEntry {
int width;
int height;
int lastUsedFrame;
};
// Not yet functional
enum {
FONTSTYLE_BOLD = 1,
@@ -75,4 +81,5 @@ private:
uint32_t fontHash_;
// The key is the CityHash of the string xor the fontHash_.
std::map<uint32_t, TextStringEntry *> cache_;
std::map<uint32_t, TextMeasureEntry *> sizeCache_;
};