Kaydet (Commit) dd36db16 authored tarafından Jan-Marek Glogowski's avatar Jan-Marek Glogowski

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: 's avatarJan-Marek Glogowski <glogow@fbihome.de>
üst 2f182faa
......@@ -41,7 +41,6 @@
class FreetypeFont;
class FreetypeFontInstance;
class FreetypeFontInfo;
class GlyphData;
class FontConfigFontOptions;
class PhysicalFontCollection;
class FreetypeFont;
......@@ -70,13 +69,6 @@ public:
void ClearFontCache();
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();
......@@ -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
......
......@@ -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 )
{
......
......@@ -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
......
......@@ -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)
......
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment