summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan-Marek Glogowski <glogow@fbihome.de>2018-10-04 13:25:06 +0000
committerJan-Marek Glogowski <glogow@fbihome.de>2018-10-06 20:13:28 +0200
commitdd36db168c658ebe588396255ad61363cc4ea7af (patch)
treeeb69c3c23b1ff05474ba075514d037ffe96f4bd4
parent2f182faaf08542e381a1aee4544b47c4cd7c0b92 (diff)
UNX use font cache based glyph rect cache
Drop the special / duplicate glyph rect bound cache implementation for Freetype fonts. The GlyphCache class now looks a lot like the ImplFontCache class. The lru handling for Freetype fonts is based on the byte / memory size, including the glyth bound-rect caching. Using the new common cache is effectivly removing the bound-rects from this accounting, so the garbage collection won't free them anymore. Change-Id: Ie53226596ee2287e1059a74885f52c3d64bbccaa Reviewed-on: https://gerrit.libreoffice.org/61377 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
-rw-r--r--vcl/inc/unx/glyphcache.hxx35
-rw-r--r--vcl/unx/generic/gdi/cairotextrender.cxx4
-rw-r--r--vcl/unx/generic/glyphs/freetype_glyphcache.cxx19
-rw-r--r--vcl/unx/generic/glyphs/glyphcache.cxx79
-rw-r--r--vcl/unx/generic/print/genpspgraphics.cxx3
5 files changed, 20 insertions, 120 deletions
diff --git a/vcl/inc/unx/glyphcache.hxx b/vcl/inc/unx/glyphcache.hxx
index 446acc2944af..9fe3bd3dc7cf 100644
--- a/vcl/inc/unx/glyphcache.hxx
+++ b/vcl/inc/unx/glyphcache.hxx
@@ -41,7 +41,6 @@
class FreetypeFont;
class FreetypeFontInstance;
class FreetypeFontInfo;
-class GlyphData;
class FontConfigFontOptions;
class PhysicalFontCollection;
class FreetypeFont;
@@ -71,13 +70,6 @@ public:
void ClearFontOptions();
private:
- friend class FreetypeFont;
- // used by FreetypeFont class only
- void AddedGlyph( GlyphData& );
- void RemovingGlyph();
- void UsingGlyph( GlyphData const & );
-
-private:
void InitFreetype();
void GarbageCollect();
FreetypeFont* CreateFont(LogicalFontInstance* pLogicalFont);
@@ -92,32 +84,12 @@ private:
FontList maFontList;
static constexpr sal_uLong gnMaxSize = 1500000; // max overall cache size in bytes
mutable sal_uLong mnBytesUsed;
- mutable long mnLruIndex;
- mutable int mnGlyphCount;
FreetypeFont* mpCurrentGCFont;
FontInfoList m_aFontInfoList;
sal_IntPtr m_nMaxFontId;
};
-class GlyphData
-{
-public:
- GlyphData() : mnLruValue(0) {}
-
- const tools::Rectangle& GetBoundRect() const { return maBoundRect; }
- void SetBoundRect(tools::Rectangle r) { maBoundRect = r; }
-
- void SetLruValue( int n ) const { mnLruValue = n; }
- long GetLruValue() const { return mnLruValue;}
-
-private:
- tools::Rectangle maBoundRect;
-
- // used by GlyphCache for cache LRU algorithm
- mutable long mnLruValue;
-};
-
class VCL_DLLPUBLIC FreetypeFont final
{
public:
@@ -139,7 +111,7 @@ public:
const FontCharMapRef GetFontCharMap() const;
bool GetFontCapabilities(vcl::FontCapabilities &) const;
- const tools::Rectangle& GetGlyphBoundRect(const GlyphItem& rGlyph);
+ bool GetGlyphBoundRect(const GlyphItem&, tools::Rectangle&);
bool GetGlyphOutline(const GlyphItem& rGlyph, basegfx::B2DPolyPolygon&) const;
bool GetAntialiasAdvice() const;
@@ -156,15 +128,10 @@ private:
long Release() const;
sal_uLong GetByteCount() const { return mnBytesUsed; }
- void InitGlyphData(const GlyphItem&, GlyphData&) const;
- void GarbageCollect( long );
void ReleaseFromGarbageCollect();
void ApplyGlyphTransform(bool bVertical, FT_Glyph) const;
- typedef std::unordered_map<sal_GlyphId, GlyphData> GlyphList;
- mutable GlyphList maGlyphList;
-
rtl::Reference<FreetypeFontInstance> mpFontInstance;
// used by GlyphCache for cache LRU algorithm
diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx
index 11d4e94592c4..40e1c5a8db3b 100644
--- a/vcl/unx/generic/gdi/cairotextrender.cxx
+++ b/vcl/unx/generic/gdi/cairotextrender.cxx
@@ -451,7 +451,9 @@ bool CairoTextRender::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangl
if( !pSF )
return false;
- tools::Rectangle aRect = pSF->GetGlyphBoundRect(rGlyph);
+ tools::Rectangle aRect;
+ if (!pSF->GetGlyphBoundRect(rGlyph, aRect))
+ return false;
if ( pSF->mnCos != 0x10000 && pSF->mnSin != 0 )
{
diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
index cfc91deb07e0..8a5314ff697b 100644
--- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
+++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
@@ -347,8 +347,7 @@ rtl::Reference<LogicalFontInstance> FreetypeFontFace::CreateFontInstance(const F
// FreetypeFont
FreetypeFont::FreetypeFont(LogicalFontInstance* pFontInstance, FreetypeFontInfo* pFI )
-: maGlyphList( 0),
- mpFontInstance(static_cast<FreetypeFontInstance*>(pFontInstance)),
+: mpFontInstance(static_cast<FreetypeFontInstance*>(pFontInstance)),
mnRefCount(1),
mnBytesUsed( sizeof(FreetypeFont) ),
mpPrevGCFont( nullptr ),
@@ -589,14 +588,18 @@ void FreetypeFont::ApplyGlyphTransform(bool bVertical, FT_Glyph pGlyphFT ) const
}
}
-void FreetypeFont::InitGlyphData(const GlyphItem& rGlyph, GlyphData& rGD ) const
+bool FreetypeFont::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle& rRect)
{
+ assert(mpFontInstance.is());
+ if (mpFontInstance.is() && mpFontInstance->GetCachedGlyphBoundRect(rGlyph.maGlyphId, rRect))
+ return true;
+
FT_Activate_Size( maSizeFT );
FT_Error rc = FT_Load_Glyph(maFaceFT, rGlyph.maGlyphId, mnLoadFlags);
if (rc != FT_Err_Ok)
- return;
+ return false;
if (mbArtBold)
FT_GlyphSlot_Embolden(maFaceFT->glyph);
@@ -604,16 +607,20 @@ void FreetypeFont::InitGlyphData(const GlyphItem& rGlyph, GlyphData& rGD ) const
FT_Glyph pGlyphFT;
rc = FT_Get_Glyph(maFaceFT->glyph, &pGlyphFT);
if (rc != FT_Err_Ok)
- return;
+ return false;
ApplyGlyphTransform(rGlyph.IsVertical(), pGlyphFT);
FT_BBox aBbox;
FT_Glyph_Get_CBox( pGlyphFT, FT_GLYPH_BBOX_PIXELS, &aBbox );
- rGD.SetBoundRect(tools::Rectangle(aBbox.xMin, -aBbox.yMax, aBbox.xMax, -aBbox.yMin));
+ rRect = tools::Rectangle(aBbox.xMin, -aBbox.yMax, aBbox.xMax, -aBbox.yMin);
+ if (mpFontInstance.is())
+ mpFontInstance->CacheGlyphBoundRect(rGlyph.maGlyphId, rRect);
FT_Done_Glyph( pGlyphFT );
+
+ return true;
}
bool FreetypeFont::GetAntialiasAdvice() const
diff --git a/vcl/unx/generic/glyphs/glyphcache.cxx b/vcl/unx/generic/glyphs/glyphcache.cxx
index 5bdcf9ac7491..c4bf10ac76c0 100644
--- a/vcl/unx/generic/glyphs/glyphcache.cxx
+++ b/vcl/unx/generic/glyphs/glyphcache.cxx
@@ -33,8 +33,6 @@
GlyphCache::GlyphCache()
: mnBytesUsed(sizeof(GlyphCache)),
- mnLruIndex(0),
- mnGlyphCount(0),
mpCurrentGCFont(nullptr)
, m_nMaxFontId(0)
{
@@ -48,14 +46,6 @@ GlyphCache::~GlyphCache()
void GlyphCache::ClearFontCache()
{
- for (auto& font : maFontList)
- {
- FreetypeFont* pFreetypeFont = font.second.get();
- // free all pFreetypeFont related data
- pFreetypeFont->GarbageCollect( mnLruIndex+0x10000000 );
- font.second.reset();
- }
-
maFontList.clear();
mpCurrentGCFont = nullptr;
m_aFontInfoList.clear();
@@ -206,10 +196,7 @@ FreetypeFont* GlyphCache::CacheFont(LogicalFontInstance* pFontInstance)
void GlyphCache::UncacheFont( FreetypeFont& rFreetypeFont )
{
if( (rFreetypeFont.Release() <= 0) && (gnMaxSize <= mnBytesUsed) )
- {
mpCurrentGCFont = &rFreetypeFont;
- GarbageCollect();
- }
}
void GlyphCache::GarbageCollect()
@@ -230,19 +217,13 @@ void GlyphCache::GarbageCollect()
FreetypeFont* const pFreetypeFont = mpCurrentGCFont;
mpCurrentGCFont = pFreetypeFont->mpNextGCFont;
- if( (pFreetypeFont == mpCurrentGCFont) // no other fonts
- || (pFreetypeFont->GetRefCount() > 0) ) // font still used
- {
- // try to garbage collect at least a few bytes
- pFreetypeFont->GarbageCollect( mnLruIndex - mnGlyphCount/2 );
- }
- else // current GC font is unreferenced
+ if( (pFreetypeFont != mpCurrentGCFont) // no other fonts
+ && (pFreetypeFont->GetRefCount() <= 0) ) // font still used
{
SAL_WARN_IF( (pFreetypeFont->GetRefCount() != 0), "vcl",
"GlyphCache::GC detected RefCount underflow" );
// free all pFreetypeFont related data
- pFreetypeFont->GarbageCollect( mnLruIndex+0x10000000 );
if( pFreetypeFont == mpCurrentGCFont )
mpCurrentGCFont = nullptr;
mnBytesUsed -= pFreetypeFont->GetByteCount();
@@ -259,26 +240,6 @@ void GlyphCache::GarbageCollect()
}
}
-inline void GlyphCache::UsingGlyph( GlyphData const & rGlyphData )
-{
- rGlyphData.SetLruValue( mnLruIndex++ );
-}
-
-inline void GlyphCache::AddedGlyph( GlyphData& rGlyphData )
-{
- ++mnGlyphCount;
- mnBytesUsed += sizeof( rGlyphData );
- UsingGlyph( rGlyphData );
- if( mnBytesUsed > gnMaxSize )
- GarbageCollect();
-}
-
-inline void GlyphCache::RemovingGlyph()
-{
- mnBytesUsed -= sizeof( GlyphData );
- --mnGlyphCount;
-}
-
void FreetypeFont::ReleaseFromGarbageCollect()
{
// remove from GC list
@@ -296,42 +257,6 @@ long FreetypeFont::Release() const
return --mnRefCount;
}
-const tools::Rectangle& FreetypeFont::GetGlyphBoundRect(const GlyphItem& rGlyph)
-{
- // usually the GlyphData is cached
- GlyphList::iterator it = maGlyphList.find(rGlyph.maGlyphId);
- if( it != maGlyphList.end() ) {
- GlyphData& rGlyphData = it->second;
- GlyphCache::GetInstance().UsingGlyph( rGlyphData );
- return rGlyphData.GetBoundRect();
- }
-
- // sometimes not => we need to create and initialize it ourselves
- GlyphData& rGlyphData = maGlyphList[rGlyph.maGlyphId];
- mnBytesUsed += sizeof( GlyphData );
- InitGlyphData(rGlyph, rGlyphData);
- GlyphCache::GetInstance().AddedGlyph( rGlyphData );
- return rGlyphData.GetBoundRect();
-}
-
-void FreetypeFont::GarbageCollect( long nMinLruIndex )
-{
- GlyphList::iterator it = maGlyphList.begin();
- while( it != maGlyphList.end() )
- {
- GlyphData& rGD = it->second;
- if( (nMinLruIndex - rGD.GetLruValue()) > 0 )
- {
- OSL_ASSERT( mnBytesUsed >= sizeof(GlyphData) );
- mnBytesUsed -= sizeof( GlyphData );
- GlyphCache::GetInstance().RemovingGlyph();
- it = maGlyphList.erase( it );
- }
- else
- ++it;
- }
-}
-
FreetypeFontInstance::FreetypeFontInstance(const PhysicalFontFace& rPFF, const FontSelectPattern& rFSP)
: LogicalFontInstance(rPFF, rFSP)
, mpFreetypeFont(nullptr)
diff --git a/vcl/unx/generic/print/genpspgraphics.cxx b/vcl/unx/generic/print/genpspgraphics.cxx
index 88e7fcdf901a..ae30cfad6286 100644
--- a/vcl/unx/generic/print/genpspgraphics.cxx
+++ b/vcl/unx/generic/print/genpspgraphics.cxx
@@ -742,8 +742,7 @@ bool GenPspGraphics::GetGlyphBoundRect(const GlyphItem& rGlyph, tools::Rectangle
if( !pSF )
return false;
- rRect = pSF->GetGlyphBoundRect(rGlyph);
- return true;
+ return pSF->GetGlyphBoundRect(rGlyph, rRect);
}
bool GenPspGraphics::GetGlyphOutline(const GlyphItem& rGlyph,