diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2018-06-05 14:16:23 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2018-06-08 22:29:50 +0200 |
commit | c4c56de1b0e62ec866b519b2b24c5e805f0a86d3 (patch) | |
tree | a8a5b3c67b72804a27fd2f1aea39451691a3fa0c /vcl/source/font | |
parent | d865866ec5cf6966757c9f2abd24b18a39f2f924 (diff) |
hold LogicalFontInstance with rtl::Reference
instead of manual reference counting.
Also the releasing of not-currently-in-use LogicalFontInstance objects
from the cache is made less aggressive - we now only flush entries until
we have less than CACHE_SIZE instances, instead of flushing the whole
cache.
Change-Id: Ib235b132776b5f09ae8ae93a933c2eebe5fa9610
Reviewed-on: https://gerrit.libreoffice.org/55384
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'vcl/source/font')
-rw-r--r-- | vcl/source/font/PhysicalFontFace.cxx | 2 | ||||
-rw-r--r-- | vcl/source/font/fontcache.cxx | 148 | ||||
-rw-r--r-- | vcl/source/font/fontinstance.cxx | 22 | ||||
-rw-r--r-- | vcl/source/font/fontselect.cxx | 1 |
4 files changed, 36 insertions, 137 deletions
diff --git a/vcl/source/font/PhysicalFontFace.cxx b/vcl/source/font/PhysicalFontFace.cxx index 690fd1fdc401..d356438e43a1 100644 --- a/vcl/source/font/PhysicalFontFace.cxx +++ b/vcl/source/font/PhysicalFontFace.cxx @@ -45,7 +45,7 @@ PhysicalFontFace::PhysicalFontFace( const PhysicalFontFace& other ) { } -LogicalFontInstance* PhysicalFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const +rtl::Reference<LogicalFontInstance> PhysicalFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const { return new LogicalFontInstance(*this, rFSD); } diff --git a/vcl/source/font/fontcache.cxx b/vcl/source/font/fontcache.cxx index 205b49ada4e0..a58d9b6931f2 100644 --- a/vcl/source/font/fontcache.cxx +++ b/vcl/source/font/fontcache.cxx @@ -83,23 +83,14 @@ bool ImplFontCache::IFSD_Equal::operator()(const FontSelectPattern& rA, const Fo } ImplFontCache::ImplFontCache() -: mpLastHitCacheEntry( nullptr ), - mnRef0Count( 0 ) +: mpLastHitCacheEntry( nullptr ) {} ImplFontCache::~ImplFontCache() { - for (auto const& fontInstance : maFontInstanceList) - { - LogicalFontInstance* pFontInstance = fontInstance.second; - if (pFontInstance->mnRefCount) - pFontInstance->mpFontCache = nullptr; - else - delete pFontInstance; - } } -LogicalFontInstance* ImplFontCache::GetFontInstance( PhysicalFontCollection const * pFontList, +rtl::Reference<LogicalFontInstance> ImplFontCache::GetFontInstance( PhysicalFontCollection const * pFontList, const vcl::Font& rFont, const Size& rSize, float fExactHeight ) { // initialize internal font request object @@ -107,10 +98,10 @@ LogicalFontInstance* ImplFontCache::GetFontInstance( PhysicalFontCollection cons return GetFontInstance( pFontList, aFontSelData ); } -LogicalFontInstance* ImplFontCache::GetFontInstance( PhysicalFontCollection const * pFontList, +rtl::Reference<LogicalFontInstance> ImplFontCache::GetFontInstance( PhysicalFontCollection const * pFontList, FontSelectPattern& aFontSelData ) { - LogicalFontInstance *pFontInstance = nullptr; + rtl::Reference<LogicalFontInstance> pFontInstance; PhysicalFontFamily* pFontFamily = nullptr; // check if a directly matching logical font instance is already cached, @@ -140,12 +131,7 @@ LogicalFontInstance* ImplFontCache::GetFontInstance( PhysicalFontCollection cons } } - if( pFontInstance ) // cache hit => use existing font instance - { - // increase the font instance's reference count - pFontInstance->Acquire(); - } - else if (pFontFamily) // still no cache hit => create a new font instance + if( !pFontInstance && pFontFamily) // still no cache hit => create a new font instance { PhysicalFontFace* pFontData = pFontFamily->FindBestFontFace(aFontSelData); @@ -173,19 +159,38 @@ LogicalFontInstance* ImplFontCache::GetFontInstance( PhysicalFontCollection cons } #endif + static const size_t FONTCACHE_MAX = getenv("LO_TESTNAME") ? 1 : 50; + + 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() ) + { + LogicalFontInstance* pFontEntry = (*it_next).second.get(); + if( pFontEntry->m_nCount > 1 ) + { + ++it_next; + continue; + } + maFontInstanceList.erase(it_next); + if (mpLastHitCacheEntry == pFontEntry) + mpLastHitCacheEntry = nullptr; + // just remove one entry, which will bring us back under FONTCACHE_MAX size again + break; + } + } + + assert(pFontInstance); // add the new entry to the cache -#ifndef NDEBUG - auto aResult = -#endif - maFontInstanceList.insert({aFontSelData, pFontInstance}); - assert(aResult.second); + maFontInstanceList.insert({aFontSelData, pFontInstance.get()}); } - mpLastHitCacheEntry = pFontInstance; + mpLastHitCacheEntry = pFontInstance.get(); return pFontInstance; } -LogicalFontInstance* ImplFontCache::GetGlyphFallbackFont( PhysicalFontCollection const * pFontCollection, +rtl::Reference<LogicalFontInstance> ImplFontCache::GetGlyphFallbackFont( PhysicalFontCollection const * pFontCollection, FontSelectPattern& rFontSelData, int nFallbackLevel, OUString& rMissingCodes ) { // get a candidate font for glyph fallback @@ -216,102 +221,17 @@ LogicalFontInstance* ImplFontCache::GetGlyphFallbackFont( PhysicalFontCollection rFontSelData.maSearchName.clear(); } - LogicalFontInstance* pFallbackFont = GetFontInstance( pFontCollection, rFontSelData ); + rtl::Reference<LogicalFontInstance> pFallbackFont = GetFontInstance( pFontCollection, rFontSelData ); return pFallbackFont; } -void ImplFontCache::Acquire(LogicalFontInstance* pFontInstance) -{ - assert(pFontInstance->mpFontCache == this); - assert(IsFontInList(pFontInstance) && "ImplFontCache::Acquire() - font absent in the cache"); - - if (0 == pFontInstance->mnRefCount++) - --mnRef0Count; -} - -void ImplFontCache::Release(LogicalFontInstance* pFontInstance) -{ - static const int FONTCACHE_MAX = getenv("LO_TESTNAME") ? 1 : 50; - - assert(pFontInstance->mpFontCache == this); - assert(IsFontInList(pFontInstance) && "ImplFontCache::Release() - font absent in the cache"); - assert(pFontInstance->mnRefCount > 0 && "ImplFontCache::Release() - font refcount underflow"); - if( --pFontInstance->mnRefCount > 0 ) - return; - - if (++mnRef0Count < FONTCACHE_MAX) - return; - - assert(CountUnreferencedEntries() == mnRef0Count); - - // remove unused entries from font instance cache - FontInstanceList::iterator it_next = maFontInstanceList.begin(); - while( it_next != maFontInstanceList.end() ) - { - LogicalFontInstance* pFontEntry = (*it_next).second; - if( pFontEntry->mnRefCount > 0 ) - { - ++it_next; - continue; - } - - it_next = maFontInstanceList.erase(it_next); - delete pFontEntry; - --mnRef0Count; - assert(mnRef0Count>=0 && "ImplFontCache::Release() - refcount0 underflow"); - - if (mpLastHitCacheEntry == pFontEntry) - mpLastHitCacheEntry = nullptr; - } - - assert(mnRef0Count==0 && "ImplFontCache::Release() - refcount0 mismatch"); -} - -bool ImplFontCache::IsFontInList(const LogicalFontInstance* pFont) const -{ - auto Pred = [pFont](const FontInstanceList::value_type& el) -> bool { return el.second == pFont; }; - return std::find_if(maFontInstanceList.begin(), maFontInstanceList.end(), Pred) != maFontInstanceList.end(); -} - -int ImplFontCache::CountUnreferencedEntries() const -{ - size_t nCount = 0; - // count unreferenced entries - for (auto const& fontInstance : maFontInstanceList) - { - const LogicalFontInstance* pFontEntry = fontInstance.second; - if (pFontEntry->mnRefCount > 0) - continue; - ++nCount; - } - return nCount; -} - void ImplFontCache::Invalidate() { - assert(CountUnreferencedEntries() == mnRef0Count); - - // delete unreferenced entries - for (auto const& fontInstance : maFontInstanceList) - { - LogicalFontInstance* pFontEntry = fontInstance.second; - if( pFontEntry->mnRefCount > 0 ) - { - // These fonts will become orphans after clearing the list below; - // allow them to control their life from now on and wish good luck :) - pFontEntry->mpFontCache = nullptr; - continue; - } - - delete pFontEntry; - --mnRef0Count; - } - // #112304# make sure the font cache is really clean mpLastHitCacheEntry = nullptr; + for (auto const & pair : maFontInstanceList) + pair.second->mpFontCache = nullptr; maFontInstanceList.clear(); - - assert(mnRef0Count==0 && "ImplFontCache::Invalidate() - mnRef0Count non-zero"); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/font/fontinstance.cxx b/vcl/source/font/fontinstance.cxx index fca20fd03ca3..e5fac6c6a67b 100644 --- a/vcl/source/font/fontinstance.cxx +++ b/vcl/source/font/fontinstance.cxx @@ -48,7 +48,6 @@ LogicalFontInstance::LogicalFontInstance(const PhysicalFontFace& rFontFace, cons , mnOrientation( 0 ) , mbInit( false ) , mpFontCache( nullptr ) - , mnRefCount( 1 ) , m_aFontSelData(rFontSelData) , m_pHbFont(nullptr) , m_nAveWidthFactor(1.0f) @@ -115,27 +114,6 @@ void LogicalFontInstance::GetScale(double* nXScale, double* nYScale) *nXScale = nWidth / nUPEM; } -void LogicalFontInstance::Acquire() -{ - assert(mnRefCount < std::numeric_limits<decltype(mnRefCount)>::max() - && "LogicalFontInstance::Release() - refcount overflow"); - if (mpFontCache) - mpFontCache->Acquire(this); - else - ++mnRefCount; -} - -void LogicalFontInstance::Release() -{ - assert(mnRefCount > 0 && "LogicalFontInstance::Release() - refcount underflow"); - - if (mpFontCache) - mpFontCache->Release(this); - else - if (--mnRefCount == 0) - delete this; -} - void LogicalFontInstance::AddFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName ) { if( !mpUnicodeFallbackList ) diff --git a/vcl/source/font/fontselect.cxx b/vcl/source/font/fontselect.cxx index 80b9ba78ce6b..563c6ebcbc54 100644 --- a/vcl/source/font/fontselect.cxx +++ b/vcl/source/font/fontselect.cxx @@ -21,6 +21,7 @@ #include <o3tl/safeint.hxx> #include <fontselect.hxx> +#include <fontinstance.hxx> #include <PhysicalFontFace.hxx> #include <svdata.hxx> |