2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "GUIFontTTF.h"
10 #include "windowing/GraphicContext.h"
15 using namespace std::chrono_literals
;
19 constexpr auto FONT_CACHE_TIME_LIMIT
= 1000ms
;
22 template<class Position
, class Value
>
23 class CGUIFontCacheImpl
27 using HashMap
= std::multimap
<size_t, std::unique_ptr
<CGUIFontCacheEntry
<Position
, Value
>>>;
28 using HashIter
= typename
HashMap::iterator
;
29 using AgeMap
= std::multimap
<std::chrono::steady_clock::time_point
, HashIter
>;
31 ~EntryList() { Flush(); }
33 HashIter
Insert(size_t hash
, std::unique_ptr
<CGUIFontCacheEntry
<Position
, Value
>> v
)
35 auto r(hashMap
.insert(typename
HashMap::value_type(hash
, std::move(v
))));
37 ageMap
.insert(typename
AgeMap::value_type(r
->second
->m_lastUsed
, r
));
46 typename
HashMap::iterator
FindKey(CGUIFontCacheKey
<Position
> key
)
48 CGUIFontCacheHash
<Position
> hashGen
;
49 CGUIFontCacheKeysMatch
<Position
> keyMatch
;
50 auto range
= hashMap
.equal_range(hashGen(key
));
51 for (auto ret
= range
.first
; ret
!= range
.second
; ++ret
)
53 if (keyMatch(ret
->second
->m_key
, key
))
61 void UpdateAge(HashIter it
, std::chrono::steady_clock::time_point now
)
63 auto range
= ageMap
.equal_range(it
->second
->m_lastUsed
);
64 for (auto ageit
= range
.first
; ageit
!= range
.second
; ++ageit
)
66 if (ageit
->second
== it
)
69 ageMap
.insert(typename
AgeMap::value_type(now
, it
));
70 it
->second
->m_lastUsed
= now
;
81 CGUIFontCache
<Position
, Value
>* m_parent
;
84 explicit CGUIFontCacheImpl(CGUIFontCache
<Position
, Value
>* parent
) : m_parent(parent
) {}
85 Value
& Lookup(const CGraphicContext
& context
,
87 const std::vector
<KODI::UTILS::COLOR::Color
>& colors
,
92 std::chrono::steady_clock::time_point now
,
97 template<class Position
, class Value
>
98 CGUIFontCacheEntry
<Position
, Value
>::~CGUIFontCacheEntry()
100 delete &m_key
.m_colors
;
101 delete &m_key
.m_text
;
105 template<class Position
, class Value
>
106 void CGUIFontCacheEntry
<Position
, Value
>::Assign(const CGUIFontCacheKey
<Position
>& key
,
107 std::chrono::steady_clock::time_point now
)
109 m_key
.m_pos
= key
.m_pos
;
110 m_key
.m_colors
.assign(key
.m_colors
.begin(), key
.m_colors
.end());
111 m_key
.m_text
.assign(key
.m_text
.begin(), key
.m_text
.end());
112 m_key
.m_alignment
= key
.m_alignment
;
113 m_key
.m_maxPixelWidth
= key
.m_maxPixelWidth
;
114 m_key
.m_scrolling
= key
.m_scrolling
;
115 m_matrix
= key
.m_matrix
;
116 m_key
.m_scaleX
= key
.m_scaleX
;
117 m_key
.m_scaleY
= key
.m_scaleY
;
122 template<class Position
, class Value
>
123 CGUIFontCache
<Position
, Value
>::CGUIFontCache(CGUIFontTTF
& font
)
124 : m_impl(std::make_unique
<CGUIFontCacheImpl
<Position
, Value
>>(this)), m_font(font
)
128 template<class Position
, class Value
>
129 CGUIFontCache
<Position
, Value
>::~CGUIFontCache() = default;
131 template<class Position
, class Value
>
132 Value
& CGUIFontCache
<Position
, Value
>::Lookup(const CGraphicContext
& context
,
134 const std::vector
<KODI::UTILS::COLOR::Color
>& colors
,
139 std::chrono::steady_clock::time_point now
,
143 m_impl
= std::make_unique
<CGUIFontCacheImpl
<Position
, Value
>>(this);
145 return m_impl
->Lookup(context
, pos
, colors
, text
, alignment
, maxPixelWidth
, scrolling
, now
,
149 template<class Position
, class Value
>
150 Value
& CGUIFontCacheImpl
<Position
, Value
>::Lookup(
151 const CGraphicContext
& context
,
153 const std::vector
<KODI::UTILS::COLOR::Color
>& colors
,
158 std::chrono::steady_clock::time_point now
,
161 const CGUIFontCacheKey
<Position
> key(
162 pos
, const_cast<std::vector
<KODI::UTILS::COLOR::Color
>&>(colors
), const_cast<vecText
&>(text
),
163 alignment
, maxPixelWidth
, scrolling
, context
.GetGUIMatrix(), context
.GetGUIScaleX(),
164 context
.GetGUIScaleY());
166 auto i
= m_list
.FindKey(key
);
167 if (i
== m_list
.hashMap
.end())
171 std::unique_ptr
<CGUIFontCacheEntry
<Position
, Value
>> entry
;
173 if (!m_list
.ageMap
.empty())
175 const auto duration
=
176 std::chrono::duration_cast
<std::chrono::milliseconds
>(now
- m_list
.ageMap
.begin()->first
);
177 if (duration
> FONT_CACHE_TIME_LIMIT
)
179 entry
= std::move(m_list
.ageMap
.begin()->second
->second
);
180 m_list
.hashMap
.erase(m_list
.ageMap
.begin()->second
);
181 m_list
.ageMap
.erase(m_list
.ageMap
.begin());
186 CGUIFontCacheHash
<Position
> hashgen
;
188 entry
= std::make_unique
<CGUIFontCacheEntry
<Position
, Value
>>(*m_parent
, key
, now
);
190 entry
->Assign(key
, now
);
191 return m_list
.Insert(hashgen(key
), std::move(entry
))->second
->m_value
;
196 // Update the translation arguments so that they hold the offset to apply
197 // to the cached values (but only in the dynamic case)
198 pos
.UpdateWithOffsets(i
->second
->m_key
.m_pos
, scrolling
);
200 // Update time in entry and move to the back of the list
201 m_list
.UpdateAge(i
, now
);
205 return i
->second
->m_value
;
209 template<class Position
, class Value
>
210 void CGUIFontCache
<Position
, Value
>::Flush()
215 template<class Position
, class Value
>
216 void CGUIFontCacheImpl
<Position
, Value
>::Flush()
221 template CGUIFontCache
<CGUIFontCacheStaticPosition
, CGUIFontCacheStaticValue
>::CGUIFontCache(
223 template CGUIFontCache
<CGUIFontCacheStaticPosition
, CGUIFontCacheStaticValue
>::~CGUIFontCache();
224 template CGUIFontCacheEntry
<CGUIFontCacheStaticPosition
,
225 CGUIFontCacheStaticValue
>::~CGUIFontCacheEntry();
226 template CGUIFontCacheStaticValue
& CGUIFontCache
<
227 CGUIFontCacheStaticPosition
,
228 CGUIFontCacheStaticValue
>::Lookup(const CGraphicContext
& context
,
229 CGUIFontCacheStaticPosition
&,
230 const std::vector
<KODI::UTILS::COLOR::Color
>&,
235 std::chrono::steady_clock::time_point
,
237 template void CGUIFontCache
<CGUIFontCacheStaticPosition
, CGUIFontCacheStaticValue
>::Flush();
239 template CGUIFontCache
<CGUIFontCacheDynamicPosition
, CGUIFontCacheDynamicValue
>::CGUIFontCache(
241 template CGUIFontCache
<CGUIFontCacheDynamicPosition
, CGUIFontCacheDynamicValue
>::~CGUIFontCache();
242 template CGUIFontCacheEntry
<CGUIFontCacheDynamicPosition
,
243 CGUIFontCacheDynamicValue
>::~CGUIFontCacheEntry();
244 template CGUIFontCacheDynamicValue
& CGUIFontCache
<
245 CGUIFontCacheDynamicPosition
,
246 CGUIFontCacheDynamicValue
>::Lookup(const CGraphicContext
& context
,
247 CGUIFontCacheDynamicPosition
&,
248 const std::vector
<KODI::UTILS::COLOR::Color
>&,
253 std::chrono::steady_clock::time_point
,
255 template void CGUIFontCache
<CGUIFontCacheDynamicPosition
, CGUIFontCacheDynamicValue
>::Flush();
257 void CVertexBuffer::clear()
260 m_font
->DestroyVertexBuffer(*this);