summaryrefslogtreecommitdiff
path: root/vcl/source/font
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2018-06-05 14:16:23 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2018-06-08 22:29:50 +0200
commitc4c56de1b0e62ec866b519b2b24c5e805f0a86d3 (patch)
treea8a5b3c67b72804a27fd2f1aea39451691a3fa0c /vcl/source/font
parentd865866ec5cf6966757c9f2abd24b18a39f2f924 (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.cxx2
-rw-r--r--vcl/source/font/fontcache.cxx148
-rw-r--r--vcl/source/font/fontinstance.cxx22
-rw-r--r--vcl/source/font/fontselect.cxx1
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>