Convert ImplFontCache to use o3tl::lru_map
We still do our own cleanup of the LRU map, as we can't drop any fonts in use. Change-Id: I8ec5c6ce8f80893635621357e9085950e7010f5b Reviewed-on: https://gerrit.libreoffice.org/61455 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
This commit is contained in:
parent
01a782d2ce
commit
16a338e173
4 changed files with 46 additions and 24 deletions
|
@ -31,7 +31,7 @@ namespace o3tl
|
|||
* for most of the operations with a combination unordered map and linked list.
|
||||
*
|
||||
**/
|
||||
template<typename Key, typename Value, class KeyHash = std::hash<Key>>
|
||||
template<typename Key, typename Value, class KeyHash = std::hash<Key>, class KeyEqual = std::equal_to<Key>>
|
||||
class lru_map final
|
||||
{
|
||||
public:
|
||||
|
@ -42,7 +42,7 @@ private:
|
|||
typedef typename list_t::iterator list_iterator_t;
|
||||
typedef typename list_t::const_iterator list_const_iterator_t;
|
||||
|
||||
typedef std::unordered_map<Key, list_iterator_t, KeyHash> map_t;
|
||||
typedef std::unordered_map<Key, list_iterator_t, KeyHash, KeyEqual> map_t;
|
||||
typedef typename map_t::iterator map_iterator_t;
|
||||
typedef typename map_t::const_iterator map_const_iterator_t;
|
||||
|
||||
|
@ -65,8 +65,9 @@ public:
|
|||
typedef list_iterator_t iterator;
|
||||
typedef list_const_iterator_t const_iterator;
|
||||
|
||||
// a size of 0 effectively disables the LRU cleanup code
|
||||
lru_map(size_t nMaxSize)
|
||||
: mMaxSize(nMaxSize)
|
||||
: mMaxSize(nMaxSize ? nMaxSize : std::min(mLruMap.max_size(), mLruList.max_size()))
|
||||
{}
|
||||
|
||||
void insert(key_value_pair_t& rPair)
|
||||
|
|
|
@ -28,6 +28,7 @@ public:
|
|||
void testLruRemoval();
|
||||
void testCustomHash();
|
||||
void testRemoveIf();
|
||||
void testNoAutoCleanup();
|
||||
|
||||
CPPUNIT_TEST_SUITE(lru_map_test);
|
||||
CPPUNIT_TEST(testBaseUsage);
|
||||
|
@ -36,6 +37,7 @@ public:
|
|||
CPPUNIT_TEST(testLruRemoval);
|
||||
CPPUNIT_TEST(testCustomHash);
|
||||
CPPUNIT_TEST(testRemoveIf);
|
||||
CPPUNIT_TEST(testNoAutoCleanup);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
};
|
||||
|
||||
|
@ -289,6 +291,24 @@ void lru_map_test::testRemoveIf()
|
|||
CPPUNIT_ASSERT_EQUAL(size_t(0), lru.size());
|
||||
}
|
||||
|
||||
void lru_map_test::testNoAutoCleanup()
|
||||
{
|
||||
o3tl::lru_map<int, int> lru(0);
|
||||
CPPUNIT_ASSERT_EQUAL(size_t(0), lru.size());
|
||||
lru.insert({0,0});
|
||||
lru.insert({1,1});
|
||||
CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
|
||||
lru.insert({0,0});
|
||||
CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
|
||||
|
||||
int i = 0;
|
||||
for (auto &rPair : lru)
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL(i, rPair.first);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(lru_map_test);
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
||||
|
|
|
@ -69,7 +69,8 @@ private:
|
|||
// cache of recently used font instances
|
||||
struct IFSD_Equal { bool operator()( const FontSelectPattern&, const FontSelectPattern& ) const; };
|
||||
struct IFSD_Hash { size_t operator()( const FontSelectPattern& ) const; };
|
||||
typedef std::unordered_map<FontSelectPattern, rtl::Reference<LogicalFontInstance>, IFSD_Hash, IFSD_Equal> FontInstanceList;
|
||||
typedef o3tl::lru_map<FontSelectPattern, rtl::Reference<LogicalFontInstance>, IFSD_Hash, IFSD_Equal> FontInstanceList;
|
||||
typedef FontInstanceList::key_value_pair_t FontInstanceListPair;
|
||||
|
||||
LogicalFontInstance* mpLastHitCacheEntry; ///< keeps the last hit cache entry
|
||||
FontInstanceList maFontInstanceList;
|
||||
|
|
|
@ -85,13 +85,14 @@ bool ImplFontCache::IFSD_Equal::operator()(const FontSelectPattern& rA, const Fo
|
|||
|
||||
ImplFontCache::ImplFontCache()
|
||||
: mpLastHitCacheEntry( nullptr )
|
||||
, maFontInstanceList(0)
|
||||
// The cache limit is set by the rough number of characters needed to read your average Asian newspaper.
|
||||
, m_aBoundRectCache(3000)
|
||||
{}
|
||||
|
||||
ImplFontCache::~ImplFontCache()
|
||||
{
|
||||
for (auto & rLFI : maFontInstanceList)
|
||||
for (const auto & rLFI : maFontInstanceList)
|
||||
rLFI.second->mpFontCache = nullptr;
|
||||
}
|
||||
|
||||
|
@ -115,7 +116,7 @@ rtl::Reference<LogicalFontInstance> ImplFontCache::GetFontInstance( PhysicalFont
|
|||
pFontInstance = mpLastHitCacheEntry;
|
||||
else
|
||||
{
|
||||
FontInstanceList::iterator it = maFontInstanceList.find( aFontSelData );
|
||||
FontInstanceList::const_iterator it = maFontInstanceList.find( aFontSelData );
|
||||
if( it != maFontInstanceList.end() )
|
||||
pFontInstance = (*it).second;
|
||||
}
|
||||
|
@ -130,7 +131,7 @@ rtl::Reference<LogicalFontInstance> ImplFontCache::GetFontInstance( PhysicalFont
|
|||
aFontSelData.maSearchName = pFontFamily->GetSearchName();
|
||||
|
||||
// check if an indirectly matching logical font instance is already cached
|
||||
FontInstanceList::iterator it = maFontInstanceList.find( aFontSelData );
|
||||
FontInstanceList::const_iterator it = maFontInstanceList.find( aFontSelData );
|
||||
if( it != maFontInstanceList.end() )
|
||||
pFontInstance = (*it).second;
|
||||
}
|
||||
|
@ -168,25 +169,24 @@ rtl::Reference<LogicalFontInstance> ImplFontCache::GetFontInstance( PhysicalFont
|
|||
|
||||
if (maFontInstanceList.size() >= FONTCACHE_MAX)
|
||||
{
|
||||
// remove entries from font instance cache that are only referenced by the cache
|
||||
FontInstanceList::iterator it_next = maFontInstanceList.begin();
|
||||
while( it_next != maFontInstanceList.end() )
|
||||
struct limit_exception : public std::exception {};
|
||||
try
|
||||
{
|
||||
LogicalFontInstance* pFontEntry = (*it_next).second.get();
|
||||
if( pFontEntry->m_nCount > 1 )
|
||||
{
|
||||
++it_next;
|
||||
continue;
|
||||
}
|
||||
m_aBoundRectCache.remove_if([&pFontEntry] (GlpyhBoundRectCachePair const& rPair)
|
||||
{ return rPair.first.m_pFont == pFontEntry; } );
|
||||
|
||||
maFontInstanceList.erase(it_next);
|
||||
if (mpLastHitCacheEntry == pFontEntry)
|
||||
mpLastHitCacheEntry = nullptr;
|
||||
// just remove one entry, which will bring us back under FONTCACHE_MAX size again
|
||||
break;
|
||||
maFontInstanceList.remove_if([this] (FontInstanceListPair const& rFontPair)
|
||||
{
|
||||
if (maFontInstanceList.size() < FONTCACHE_MAX)
|
||||
throw limit_exception();
|
||||
LogicalFontInstance* pFontEntry = rFontPair.second.get();
|
||||
if (pFontEntry->m_nCount > 1)
|
||||
return false;
|
||||
m_aBoundRectCache.remove_if([&pFontEntry] (GlpyhBoundRectCachePair const& rGlyphPair)
|
||||
{ return rGlyphPair.first.m_pFont == pFontEntry; });
|
||||
if (mpLastHitCacheEntry == pFontEntry)
|
||||
mpLastHitCacheEntry = nullptr;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
catch (limit_exception) {}
|
||||
}
|
||||
|
||||
assert(pFontInstance);
|
||||
|
|
Loading…
Reference in a new issue