diff --git a/src/fontcache.cpp b/src/fontcache.cpp index b51cecaf6c..9e0fd1e166 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -17,6 +17,7 @@ #include "core/smallmap_type.hpp" #include "strings_func.h" #include "zoom_type.h" +#include "gfx_layout.h" #include "table/sprites.h" #include "table/control_codes.h" @@ -39,6 +40,7 @@ FontCache::FontCache(FontSize fs) : parent(FontCache::Get(fs)), fs(fs), height(_ { assert(parent == NULL || this->fs == parent->fs); FontCache::caches[this->fs] = this; + Layouter::ResetFontCache(this->fs); } /** Clean everything up. */ @@ -46,6 +48,7 @@ FontCache::~FontCache() { assert(this->fs == parent->fs); FontCache::caches[this->fs] = this->parent; + Layouter::ResetFontCache(this->fs); } diff --git a/src/gfx_layout.cpp b/src/gfx_layout.cpp index f3b1ac1d3a..cba5a7ddd9 100644 --- a/src/gfx_layout.cpp +++ b/src/gfx_layout.cpp @@ -20,6 +20,11 @@ #include #endif /* WITH_ICU */ + +/** Cache of Font instances. */ +Layouter::FontColourMap Layouter::fonts[FS_END]; + + /** * Construct a new font. * @param size The font size to use for this font. @@ -414,7 +419,7 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi WChar c = 0; do { - Font *f = new Font(state.fontsize, state.cur_colour); + Font *f = GetFont(state.fontsize, state.cur_colour); CharType *buff_begin = buff; FontMap fontMapping; @@ -442,11 +447,8 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi if (!fontMapping.Contains(buff - buff_begin)) { fontMapping.Insert(buff - buff_begin, f); - *this->fonts.Append() = f; - } else { - delete f; } - f = new Font(state.fontsize, state.cur_colour); + f = GetFont(state.fontsize, state.cur_colour); } /* Better safe than sorry. */ @@ -454,7 +456,6 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi if (!fontMapping.Contains(buff - buff_begin)) { fontMapping.Insert(buff - buff_begin, f); - *this->fonts.Append() = f; } ParagraphLayout *p = GetParagraphLayout(buff_begin, buff, fontMapping); @@ -469,14 +470,6 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi } while (c != '\0' && buff < buffer_last); } -/** Free everything we allocated. */ -Layouter::~Layouter() -{ - for (Font **iter = this->fonts.Begin(); iter != this->fonts.End(); iter++) { - delete *iter; - } -} - /** * Get the boundaries of this paragraph. * @return The boundaries. @@ -490,3 +483,28 @@ Dimension Layouter::GetBounds() } return d; } + +/** + * Get a static font instance. + */ +Font *Layouter::GetFont(FontSize size, TextColour colour) +{ + FontColourMap::iterator it = fonts[size].Find(colour); + if (it != fonts[size].End()) return it->second; + + Font *f = new Font(size, colour); + *fonts[size].Append() = FontColourMap::Pair(colour, f); + return f; +} + +/** + * Reset cached font information. + * @param size Font size to reset. + */ +void Layouter::ResetFontCache(FontSize size) +{ + for (FontColourMap::iterator it = fonts[size].Begin(); it != fonts[size].End(); ++it) { + delete it->second; + } + fonts[size].Clear(); +} diff --git a/src/gfx_layout.h b/src/gfx_layout.h index 6dbf3f872f..ea9c34aae3 100644 --- a/src/gfx_layout.h +++ b/src/gfx_layout.h @@ -167,12 +167,16 @@ class Layouter : public AutoDeleteSmallVector { ParagraphLayout *GetParagraphLayout(CharType *buff, CharType *buff_end, FontMap &fontMapping); CharType buffer[DRAW_STRING_BUFFER]; ///< Buffer for the text that is going to be drawn. - SmallVector fonts; ///< The fonts needed for drawing. + + typedef SmallMap FontColourMap; + static FontColourMap fonts[FS_END]; + static Font *GetFont(FontSize size, TextColour colour); public: Layouter(const char *str, int maxw = INT32_MAX, TextColour colour = TC_FROMSTRING, FontSize fontsize = FS_NORMAL); - ~Layouter(); Dimension GetBounds(); + + static void ResetFontCache(FontSize size); }; #endif /* GFX_LAYOUT_H */