summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gui/fonts/font.cpp72
-rw-r--r--src/gui/fonts/font.h4
-rw-r--r--src/gui/fonts/font_unittest.cc73
-rw-r--r--src/gui/fonts/textchunk.cpp31
-rw-r--r--src/gui/fonts/textchunk.h8
-rw-r--r--src/gui/fonts/textchunklist.cpp22
-rw-r--r--src/gui/fonts/textchunklist.h2
-rw-r--r--src/gui/widgets/label.cpp38
-rw-r--r--src/gui/widgets/label.h9
-rw-r--r--src/gui/widgets/tabs/tab.cpp57
-rw-r--r--src/gui/widgets/tabs/tab.h1
11 files changed, 288 insertions, 29 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);
diff --git a/src/gui/widgets/label.cpp b/src/gui/widgets/label.cpp
index 8b074a0b1..65e7f86d0 100644
--- a/src/gui/widgets/label.cpp
+++ b/src/gui/widgets/label.cpp
@@ -78,8 +78,10 @@ Label::Label(const Widget2 *const widget) :
Widget(widget),
ToolTipListener(),
mCaption(),
+ mTextChunk(),
mAlignment(Graphics::LEFT),
- mPadding(0)
+ mPadding(0),
+ mTextChanged(true)
{
init();
}
@@ -89,8 +91,10 @@ Label::Label(const Widget2 *const widget,
Widget(widget),
ToolTipListener(),
mCaption(caption),
+ mTextChunk(),
mAlignment(Graphics::LEFT),
- mPadding(0)
+ mPadding(0),
+ mTextChanged(true)
{
const Font *const font = getFont();
if (font)
@@ -113,6 +117,7 @@ Label::~Label()
theme->unload(mSkin);
}
removeMouseListener(this);
+ mTextChunk.deleteImage();
}
void Label::init()
@@ -160,7 +165,21 @@ void Label::draw(Graphics* graphics)
}
graphics->setColorAll(mForegroundColor, mForegroundColor2);
- font->drawString(graphics, mCaption, textX, textY);
+ if (mTextChanged)
+ {
+ mTextChunk.textFont = font;
+ mTextChunk.deleteImage();
+ mTextChunk.text = mCaption;
+ mTextChunk.color = mForegroundColor;
+ mTextChunk.color2 = mForegroundColor2;
+ font->generate(mTextChunk);
+ mTextChanged = false;
+ }
+
+ const Image *const image = mTextChunk.img;
+ if (image)
+ graphics->drawImage(image, textX, textY);
+// font->drawString(graphics, mCaption, textX, textY);
BLOCK_END("Label::draw")
}
@@ -174,6 +193,9 @@ void Label::adjustSize()
void Label::setForegroundColor(const Color &color)
{
+ if (mForegroundColor != color || mForegroundColor2 != color)
+ mTextChanged = true;
+// logger->log("Label::setForegroundColor: " + mCaption);
mForegroundColor = color;
mForegroundColor2 = color;
}
@@ -181,6 +203,9 @@ void Label::setForegroundColor(const Color &color)
void Label::setForegroundColorAll(const Color &color1,
const Color &color2)
{
+ if (mForegroundColor != color1 || mForegroundColor2 != color2)
+ mTextChanged = true;
+// logger->log("Label::setForegroundColorAll: " + mCaption);
mForegroundColor = color1;
mForegroundColor2 = color2;
}
@@ -221,3 +246,10 @@ void Label::resizeTo(const int maxSize, const int minSize)
setWidth(sz);
}
}
+
+void Label::setCaption(const std::string& caption)
+{
+ if (caption != mCaption)
+ mTextChanged = true;
+ mCaption = caption;
+}
diff --git a/src/gui/widgets/label.h b/src/gui/widgets/label.h
index 681908b71..9e82f0a5d 100644
--- a/src/gui/widgets/label.h
+++ b/src/gui/widgets/label.h
@@ -65,6 +65,8 @@
#ifndef GUI_WIDGETS_LABEL_H
#define GUI_WIDGETS_LABEL_H
+#include "gui/fonts/textchunk.h"
+
#include "gui/widgets/widget.h"
#include "listeners/tooltiplistener.h"
@@ -132,8 +134,7 @@ class Label final : public Widget,
* @param caption The caption of the label.
* @see getCaption, adjustSize
*/
- void setCaption(const std::string& caption)
- { mCaption = caption; }
+ void setCaption(const std::string& caption);
/**
* Sets the alignment of the caption. The alignment is relative
@@ -165,12 +166,16 @@ class Label final : public Widget,
*/
std::string mCaption;
+ TextChunk mTextChunk;
+
/**
* Holds the alignment of the caption.
*/
Graphics::Alignment mAlignment;
int mPadding;
+
+ bool mTextChanged;
};
#endif // GUI_WIDGETS_LABEL_H
diff --git a/src/gui/widgets/tabs/tab.cpp b/src/gui/widgets/tabs/tab.cpp
index 2f300fb5f..e361c78ff 100644
--- a/src/gui/widgets/tabs/tab.cpp
+++ b/src/gui/widgets/tabs/tab.cpp
@@ -120,6 +120,7 @@ Tab::Tab(const Widget2 *const widget) :
mVertexes(new ImageCollection),
mImage(nullptr),
mMode(0),
+ mLabelMode(-1),
mHasMouse(false)
{
init();
@@ -211,37 +212,55 @@ void Tab::draw(Graphics *graphics)
// check which type of tab to draw
if (mTabbedArea)
{
+ int labelMode = mFlash;
+
if (mTabbedArea->isTabSelected(this))
{
- mLabel->setForegroundColorAll(*mTabSelectedColor,
- *mTabSelectedOutlineColor);
+ labelMode = 3;
mode = TAB_SELECTED;
// if tab is selected, it doesnt need to highlight activity
mFlash = 0;
}
- else if (mHasMouse)
+ else if (!labelMode)
{
- mLabel->setForegroundColorAll(*mTabHighlightedColor,
- *mTabHighlightedOutlineColor);
- mode = TAB_HIGHLIGHTED;
+ if (mHasMouse)
+ {
+ labelMode = 4;
+ mode = TAB_HIGHLIGHTED;
+ }
}
- else
+ else if (mHasMouse)
{
- mLabel->setForegroundColorAll(*mTabColor, *mTabOutlineColor);
+ mode = TAB_HIGHLIGHTED;
}
- switch (mFlash)
+ if (labelMode != mLabelMode)
{
- case 1:
- mLabel->setForegroundColorAll(*mFlashColor,
- *mFlashOutlineColor);
- break;
- case 2:
- mLabel->setForegroundColorAll(*mPlayerFlashColor,
- *mPlayerFlashOutlineColor);
- break;
- default:
- break;
+ mLabelMode = labelMode;
+ switch (labelMode)
+ {
+ case 0: // default state
+ default:
+ mLabel->setForegroundColorAll(*mTabColor,
+ *mTabOutlineColor);
+ break;
+ case 1: // mFlash == 1
+ mLabel->setForegroundColorAll(*mFlashColor,
+ *mFlashOutlineColor);
+ break;
+ case 2: // mFlash == 2
+ mLabel->setForegroundColorAll(*mPlayerFlashColor,
+ *mPlayerFlashOutlineColor);
+ break;
+ case 3: //mTabbedArea->isTabSelected(this)
+ mLabel->setForegroundColorAll(*mTabSelectedColor,
+ *mTabSelectedOutlineColor);
+ break;
+ case 4: // mHasMouse
+ mLabel->setForegroundColorAll(*mTabHighlightedColor,
+ *mTabHighlightedOutlineColor);
+ break;
+ }
}
}
diff --git a/src/gui/widgets/tabs/tab.h b/src/gui/widgets/tabs/tab.h
index 06b5a3d18..8b26ee3d4 100644
--- a/src/gui/widgets/tabs/tab.h
+++ b/src/gui/widgets/tabs/tab.h
@@ -228,6 +228,7 @@ class Tab notfinal : public BasicContainer,
ImageCollection *mVertexes;
Image *mImage;
int mMode;
+ int mLabelMode;
protected:
bool mHasMouse;