1// SuperTux
2// Copyright (C) 2016 Ingo Ruhnke <grumbel@gmail.com>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17#include "video/ttf_surface_manager.hpp"
18
19#include <SDL_ttf.h>
20#include <sstream>
21#include <iostream>
22
23#include "supertux/globals.hpp"
24#include "video/sdl_surface_ptr.hpp"
25#include "video/surface.hpp"
26#include "video/ttf_font.hpp"
27#include "video/ttf_surface.hpp"
28#include "video/video_system.hpp"
29
30TTFSurfaceManager::CacheEntry::CacheEntry(const TTFSurfacePtr& s) :
31 ttf_surface(s),
32 last_access(g_game_time)
33{
34}
35
36TTFSurfaceManager::TTFSurfaceManager() :
37 m_cache(),
38 m_cache_iter(m_cache.end())
39{
40}
41
42TTFSurfacePtr
43TTFSurfaceManager::create_surface(const TTFFont& font, const std::string& text)
44{
45 auto key = Key(font.get_ttf_font(), text);
46 auto it = m_cache.find(key);
47 if (it != m_cache.end())
48 {
49 auto& entry = m_cache[key];
50 entry.last_access = g_game_time;
51 return entry.ttf_surface;
52 }
53 else
54 {
55 if ((false))
56 {
57 // Font debug output should go to 'std::cerr', not any of the
58 // log_* functions, as those are mirrored on the console which
59 // in turn will lead to the creation of more TTFSurface's and
60 // screw up the results.
61 print_debug_info(std::cerr);
62 }
63
64 cache_cleanup_step();
65
66 TTFSurfacePtr ttf_surface = TTFSurface::create(font, text);
67 m_cache[key] = ttf_surface;
68 return ttf_surface;
69 }
70}
71
72void
73TTFSurfaceManager::cache_cleanup_step()
74{
75 if (m_cache.empty())
76 return;
77
78 if (m_cache_iter == m_cache.end())
79 {
80 m_cache_iter = m_cache.begin();
81 }
82
83 while (g_game_time - m_cache_iter->second.last_access > 10.0f)
84 {
85 m_cache_iter = m_cache.erase(m_cache_iter);
86 if (m_cache_iter == m_cache.end())
87 {
88 return;
89 }
90 }
91
92 ++m_cache_iter;
93}
94
95void
96TTFSurfaceManager::print_debug_info(std::ostream& out)
97{
98 int cache_bytes = 0;
99 for (const auto& entry : m_cache)
100 {
101 cache_bytes += entry.second.ttf_surface->get_width() * entry.second.ttf_surface->get_height() * 4;
102 }
103 out << "TTFSurfaceManager.cache_size: " << m_cache.size() << " " << cache_bytes / 1000 << "KB" << std::endl;
104}
105
106/* EOF */
107