diff options
author | Andrei Karas <akaras@inbox.ru> | 2015-05-19 14:49:19 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2015-05-20 00:02:36 +0300 |
commit | e224a077737739a895fe533c9cce93783621d8e9 (patch) | |
tree | 28194260919ffcc8aa77f52caf45cbf3a1747334 /src/gui/fonts | |
parent | fd85f62f2e3003a79e90611e95b09e23710be479 (diff) | |
download | mv-e224a077737739a895fe533c9cce93783621d8e9.tar.gz mv-e224a077737739a895fe533c9cce93783621d8e9.tar.bz2 mv-e224a077737739a895fe533c9cce93783621d8e9.tar.xz mv-e224a077737739a895fe533c9cce93783621d8e9.zip |
Add fast way for draw not changed text strings.
TextChunk with colors and image stored inside draw object.
If string or color changed old string image moved to cache.
New string image generated or moved from cache.
Use new way in drawing string in label.
Diffstat (limited to 'src/gui/fonts')
-rw-r--r-- | src/gui/fonts/font.cpp | 72 | ||||
-rw-r--r-- | src/gui/fonts/font.h | 4 | ||||
-rw-r--r-- | src/gui/fonts/font_unittest.cc | 73 | ||||
-rw-r--r-- | src/gui/fonts/textchunk.cpp | 31 | ||||
-rw-r--r-- | src/gui/fonts/textchunk.h | 8 | ||||
-rw-r--r-- | src/gui/fonts/textchunklist.cpp | 22 | ||||
-rw-r--r-- | src/gui/fonts/textchunklist.h | 2 |
7 files changed, 207 insertions, 5 deletions
diff --git a/src/gui/fonts/font.cpp b/src/gui/fonts/font.cpp index 27628aec5..58528f383 100644 --- a/src/gui/fonts/font.cpp +++ b/src/gui/fonts/font.cpp @@ -73,6 +73,7 @@ #include "resources/image.h" #include "resources/imagehelper.h" +#include "utils/delete2.h" #include "utils/files.h" #include "utils/paths.h" #include "utils/sdlcheckutils.h" @@ -316,7 +317,7 @@ void Font::doClean() TextChunkList *const cache = &mCache[f]; const size_t size = static_cast<size_t>(cache->size); #ifdef DEBUG_FONT_COUNTERS - logger->log("ptr: %d, size: %d", f, size); + logger->log("ptr: %u, size: %ld", f, size); #endif if (size > CACHE_SIZE_SMALL3) { @@ -367,3 +368,72 @@ const TextChunkList *Font::getCache() const { return mCache; } + +void Font::generate(TextChunk &chunk) +{ + const std::string &text = chunk.text; + if (text.empty()) + return; + + const unsigned char chr = text[0]; + TextChunkList *const cache = &mCache[chr]; + Color &col = chunk.color; + Color &col2 = chunk.color2; + const int oldAlpha = col.a; + col.a = 255; + + TextChunkSmall key(text, col, col2); + std::map<TextChunkSmall, TextChunk*> &search = cache->search; + std::map<TextChunkSmall, TextChunk*>::iterator i = search.find(key); + if (i != search.end()) + { + TextChunk *const chunk2 = (*i).second; + cache->moveToFirst(chunk2); + //search.erase(key); + cache->remove(chunk2); + chunk.img = chunk2->img; +// logger->log("cached image: " + chunk.text); + } + else + { + if (cache->size >= CACHE_SIZE) + { +#ifdef DEBUG_FONT_COUNTERS + mDeleteCounter ++; +#endif + cache->removeBack(); + } +#ifdef DEBUG_FONT_COUNTERS + mCreateCounter ++; +#endif + const float alpha = static_cast<float>(chunk.color.a) / 255.0F; + chunk.generate(mFont, alpha); +// logger->log("generate image: " + chunk.text); + } + col.a = oldAlpha; +} + +void Font::insertChunk(TextChunk *const chunk) +{ + if (!chunk || chunk->text.empty() || !chunk->img) + return; +// logger->log("insert chunk: text=%s, color: %d,%d,%d", +// chunk->text.c_str(), chunk->color.r, chunk->color.g, chunk->color.b); + const unsigned char chr = chunk->text[0]; + TextChunkList *const cache = &mCache[chr]; + + std::map<TextChunkSmall, TextChunk*> &search = cache->search; + std::map<TextChunkSmall, TextChunk*>::iterator i + = search.find(TextChunkSmall(chunk->text, + chunk->color, chunk->color2)); + if (i != search.end()) + { + delete2(chunk->img); + return; + } + + TextChunk *const chunk2 = new TextChunk(chunk->text, + chunk->color, chunk->color2, chunk->textFont); + chunk2->img = chunk->img; + cache->insertFirst(chunk2); +} diff --git a/src/gui/fonts/font.h b/src/gui/fonts/font.h index 2e0dfad7f..a112673a1 100644 --- a/src/gui/fonts/font.h +++ b/src/gui/fonts/font.h @@ -125,6 +125,10 @@ class Font final int getStringIndexAt(const std::string& text, const int x) const A_WARN_UNUSED; + void generate(TextChunk &chunk); + + void insertChunk(TextChunk *const chunk); + static bool mSoftMode; private: diff --git a/src/gui/fonts/font_unittest.cc b/src/gui/fonts/font_unittest.cc index 8b8d027c5..f41249f96 100644 --- a/src/gui/fonts/font_unittest.cc +++ b/src/gui/fonts/font_unittest.cc @@ -369,7 +369,6 @@ TEST(TextChunkList, clear5) TextChunk *chunk3 = new TextChunk("test3", Color(1, 2, 3), Color(2, 0, 2), nullptr); - chunk1->refCount = 1; list.insertFirst(chunk1); list.insertFirst(chunk2); list.insertFirst(chunk3); @@ -389,6 +388,78 @@ TEST(TextChunkList, clear5) EXPECT_EQ(0, list.searchWidth.size()); } +TEST(TextChunkList, remove1) +{ + TextChunkList list; + int chunksLeft = textChunkCnt; + + TextChunk *chunk = new TextChunk("test", + Color(), Color(), nullptr); + + list.insertFirst(chunk); + list.remove(chunk); + delete chunk; + + EXPECT_EQ(0, list.size); + EXPECT_EQ(nullptr, list.start); + EXPECT_EQ(nullptr, list.end); + EXPECT_EQ(chunksLeft, textChunkCnt); + EXPECT_EQ(0, list.search.size()); + EXPECT_EQ(0, list.searchWidth.size()); +} + +TEST(TextChunkList, remove2) +{ + TextChunkList list; + int chunksLeft = textChunkCnt; + + TextChunk *chunk1 = new TextChunk("test1", + Color(1, 2, 3), Color(2, 0, 0), nullptr); + TextChunk *chunk2 = new TextChunk("test2", + Color(1, 2, 3), Color(2, 0, 1), nullptr); + TextChunk *chunk3 = new TextChunk("test3", + Color(1, 2, 3), Color(2, 0, 2), nullptr); + + list.insertFirst(chunk1); + list.insertFirst(chunk2); + list.insertFirst(chunk3); + list.remove(chunk1); + delete chunk1; + + EXPECT_EQ(2, list.size); + EXPECT_EQ(chunk3, list.start); + EXPECT_EQ(chunk2, list.end); + EXPECT_EQ(chunksLeft + 2, textChunkCnt); + EXPECT_EQ(2, list.search.size()); + EXPECT_EQ(2, list.searchWidth.size()); +} + +TEST(TextChunkList, remove3) +{ + TextChunkList list; + int chunksLeft = textChunkCnt; + + TextChunk *chunk1 = new TextChunk("test1", + Color(1, 2, 3), Color(2, 0, 0), nullptr); + TextChunk *chunk2 = new TextChunk("test2", + Color(1, 2, 3), Color(2, 0, 1), nullptr); + TextChunk *chunk3 = new TextChunk("test3", + Color(1, 2, 3), Color(2, 0, 2), nullptr); + + list.insertFirst(chunk1); + list.insertFirst(chunk2); + list.insertFirst(chunk3); + list.remove(chunk2); + delete chunk2; + + EXPECT_EQ(2, list.size); + EXPECT_EQ(chunk3, list.start); + EXPECT_EQ(chunk1, list.end); + EXPECT_EQ(chunksLeft + 2, textChunkCnt); + EXPECT_EQ(2, list.search.size()); + EXPECT_EQ(2, list.searchWidth.size()); +} + TEST(TextChunkList, sort1) { TextChunkSmall item1("test line1", diff --git a/src/gui/fonts/textchunk.cpp b/src/gui/fonts/textchunk.cpp index b0933a3e0..a0c8a39dc 100644 --- a/src/gui/fonts/textchunk.cpp +++ b/src/gui/fonts/textchunk.cpp @@ -25,6 +25,8 @@ #include "sdlshared.h" +#include "gui/fonts/font.h" + #include "resources/image.h" #include "resources/surfaceimagehelper.h" @@ -45,10 +47,24 @@ char *strBuf = nullptr; int textChunkCnt = 0; #endif +TextChunk::TextChunk() : + img(nullptr), + textFont(nullptr), + text(), + color(), + color2(), + prev(nullptr), + next(nullptr) +{ +#ifdef UNITTESTS + textChunkCnt ++; +#endif +} + TextChunk::TextChunk(const std::string &text0, const Color &color0, const Color &color1, - const Font *const font) : + Font *const font) : img(nullptr), textFont(font), text(text0), @@ -167,3 +183,16 @@ void TextChunk::generate(TTF_Font *const font, const float alpha) BLOCK_END("TextChunk::generate") } + +void TextChunk::deleteImage() +{ + if (textFont) + { + textFont->insertChunk(this); + img = nullptr; + } + else + { + delete2(img); + } +} diff --git a/src/gui/fonts/textchunk.h b/src/gui/fonts/textchunk.h index 13187473d..6b8beec35 100644 --- a/src/gui/fonts/textchunk.h +++ b/src/gui/fonts/textchunk.h @@ -38,10 +38,12 @@ class Image; class TextChunk final { public: + TextChunk(); + TextChunk(const std::string &text0, const Color &color0, const Color &color1, - const Font *const font); + Font *const font); A_DELETE_COPY(TextChunk) @@ -51,8 +53,10 @@ class TextChunk final void generate(TTF_Font *const font, const float alpha); + void deleteImage(); + Image *img; - const Font *textFont; + Font *textFont; std::string text; Color color; Color color2; diff --git a/src/gui/fonts/textchunklist.cpp b/src/gui/fonts/textchunklist.cpp index bb5cc646f..023727282 100644 --- a/src/gui/fonts/textchunklist.cpp +++ b/src/gui/fonts/textchunklist.cpp @@ -70,6 +70,28 @@ void TextChunkList::moveToFirst(TextChunk *const item) start = item; } +void TextChunkList::remove(TextChunk *const item) +{ + if (!item) + return; + + TextChunk *const oldPrev = item->prev; + TextChunk *const oldNext = item->next; + if (oldPrev) + oldPrev->next = item->next; + else + start = oldNext; + if (oldNext) + oldNext->prev = item->prev; + else + end = oldPrev; + + search.erase(TextChunkSmall(item->text, + item->color, item->color2)); + searchWidth.erase(item->text); + size --; +} + void TextChunkList::removeBack() { TextChunk *oldEnd = end; diff --git a/src/gui/fonts/textchunklist.h b/src/gui/fonts/textchunklist.h index d89a8ab3b..1f5eff0ea 100644 --- a/src/gui/fonts/textchunklist.h +++ b/src/gui/fonts/textchunklist.h @@ -40,6 +40,8 @@ class TextChunkList final void moveToFirst(TextChunk *const item); + void remove(TextChunk *const item); + void removeBack(); void removeBack(int n); |