diff options
author | Herbert Duerr <hdu@openoffice.org> | 2000-11-16 12:44:43 +0000 |
---|---|---|
committer | Herbert Duerr <hdu@openoffice.org> | 2000-11-16 12:44:43 +0000 |
commit | ecd7d21bf716aeccf02cea392000889c391bdd09 (patch) | |
tree | dc8b06b4b044de15a7bb3b10f943b940e78b9968 /vcl | |
parent | a949f50ce969b1f8d018d2913c0d86cfcec4e72a (diff) |
improved GC scalability and implemented SetFontPath/GetFontPath
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/source/glyphs/glyphcache.cxx | 170 |
1 files changed, 123 insertions, 47 deletions
diff --git a/vcl/source/glyphs/glyphcache.cxx b/vcl/source/glyphs/glyphcache.cxx index 0b97ef46736b..c81e0855236c 100644 --- a/vcl/source/glyphs/glyphcache.cxx +++ b/vcl/source/glyphs/glyphcache.cxx @@ -2,9 +2,9 @@ * * $RCSfile: glyphcache.cxx,v $ * - * $Revision: 1.1 $ + * $Revision: 1.2 $ * - * last change: $Author: hdu $ $Date: 2000-11-10 17:21:28 $ + * last change: $Author: hdu $ $Date: 2000-11-16 13:44:43 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -71,29 +71,25 @@ #include <tools/debug.hxx> #include <stdlib.h> +#include <math.h> // ======================================================================= // GlyphCache // ======================================================================= -GlyphCache GlyphCache::aSingleton( 250000 ); -static class FreetypeManager* pFtManager = NULL; +GlyphCache* GlyphCache::pSingleton = 0; // ----------------------------------------------------------------------- GlyphCache::GlyphCache( ULONG _nMaxSize ) -: mnMaxSize(_nMaxSize), mnBytesUsed(sizeof(GlyphCache)), - mnLruIndex(0), mnLastGC(0), mnMinGCInterval(200) +: mnMaxSize(_nMaxSize), + mnBytesUsed(sizeof(GlyphCache)), + mnLruIndex(0), + pFtManager(NULL), + pCurrentGCFont(NULL) { #ifndef NO_FREETYPE_FONTS - if( const char* pFontPath = getenv( "SAL_FONTPATH_PRIVATE" ) ) - { - String aEnv = String::CreateFromAscii( pFontPath ); - ::rtl::OUString aNormalizedName; - osl::FileBase::normalizePath( aEnv, aNormalizedName ); - pFtManager = new FreetypeManager; - pFtManager->AddFontDir( aNormalizedName ); - } + pFtManager = new FreetypeManager; #endif // NO_FREETYPE_FONTS } @@ -112,7 +108,7 @@ GlyphCache::~GlyphCache() // ----------------------------------------------------------------------- -size_t std::hash<const ImplFontSelectData>::operator()( const ImplFontSelectData& rFontSelData ) const +inline size_t std::hash<const ImplFontSelectData>::operator()( const ImplFontSelectData& rFontSelData ) const { // TODO: does it pay much to improve this hash function? size_t nHash = ::rtl::OUString( rFontSelData.maName ).hashCode(); @@ -124,22 +120,66 @@ size_t std::hash<const ImplFontSelectData>::operator()( const ImplFontSelectData // ----------------------------------------------------------------------- -bool std::equal_to<const ImplFontSelectData>::operator()( - const ImplFontSelectData& rA, const ImplFontSelectData& rB ) const +bool operator==( const ImplFontSelectData& rA, const ImplFontSelectData& rB ) { if( (rA.maName == rB.maName) && (rA.maStyleName == rB.maStyleName) && (rA.mnHeight == rB.mnHeight) && (rA.mnWidth == rB.mnWidth) && (rA.mnOrientation == rB.mnOrientation) - && (rA.mbVertical == rB.mbVertical) ) + && (rA.mbVertical == rB.mbVertical) + && (rA.meWeight == rB.meWeight) + && (rA.meItalic == rB.meItalic) + && (rA.mePitch == rB.mePitch) + && (rA.meCharSet == rB.meCharSet) + && (rA.meFamily == rB.meFamily) + && (rA.meWidthType == rB.meWidthType) ) return true; return false; } // ----------------------------------------------------------------------- -long GlyphCache::FetchFontList( ImplDevFontList* pList ) +void GlyphCache::EnsureInstance() +{ + static GlyphCache aGlyphCache( 250000 ); + pSingleton = &aGlyphCache; +} + +// ----------------------------------------------------------------------- + +void GlyphCache::ClearFontPath() +{ +#ifndef NO_FREETYPE_FONTS + if( pFtManager ) + pFtManager->ClearFontList(); +#endif // NO_FREETYPE_FONTS +} + +// ----------------------------------------------------------------------- + +void GlyphCache::AddFontPath( const String& rFontPath ) +{ + if( !pFtManager ) + return; + +#ifndef NO_FREETYPE_FONTS + for( xub_StrLen nComma1 = 0, nComma2 = 0; nComma2 != STRING_LEN; nComma1 = nComma2 + 1 ) + { + nComma2 = rFontPath.Search( ',', nComma1 ); + if( nComma2 == STRING_NOTFOUND ) + nComma2 = STRING_LEN; + + ::rtl::OUString aNormalizedName; + osl::FileBase::normalizePath( rFontPath.Copy( nComma1, nComma2 ), aNormalizedName ); + pFtManager->AddFontDir( aNormalizedName ); + } +#endif // NO_FREETYPE_FONTS +} + +// ----------------------------------------------------------------------- + +long GlyphCache::FetchFontList( ImplDevFontList* pList ) const { long nCount = VirtDevServerFont::FetchFontList( pList ); #ifndef NO_FREETYPE_FONTS @@ -161,9 +201,8 @@ const ServerFont* GlyphCache::CacheFont( const ImplFontSelectData& rFontSelData } // font not cached yet => create new font item - const ServerFont* pNew = NULL; - // TODO: - // pNew = VirtDevServerFont::CreateFont( rFontSelData ); + ServerFont* pNew = NULL; + // TODO: pNew = VirtDevServerFont::CreateFont( rFontSelData ); #ifndef NO_FREETYPE_FONTS if( !pNew && pFtManager) pNew = pFtManager->CreateFont( rFontSelData ); @@ -173,6 +212,17 @@ const ServerFont* GlyphCache::CacheFont( const ImplFontSelectData& rFontSelData { aFontList[ rFontSelData ] = pNew; mnBytesUsed += pNew->GetByteCount(); + + // schedule it for garbage collection some time later + if( !pCurrentGCFont ) + { + pCurrentGCFont = pNew; + pNew->pPrevGCFont = pNew; + } + pNew->pNextGCFont = pCurrentGCFont; + pNew->pPrevGCFont = pCurrentGCFont->pPrevGCFont; + pCurrentGCFont->pPrevGCFont->pNextGCFont = pNew; + pCurrentGCFont->pPrevGCFont = pNew; } return pNew; @@ -184,7 +234,7 @@ void GlyphCache::UncacheFont( const ServerFont& rServerFont ) { // the interface for rServerFont must be const because a // user who wants to release it only got const ServerFonts. - // The caching algorithm needs a non-const object though + // The caching algorithm needs a non-const object ServerFont* pFont = const_cast<ServerFont*>( &rServerFont ); if( pFont->Release() <= 0) // lazy release @@ -205,28 +255,29 @@ ULONG GlyphCache::CalcByteCount() const ULONG GlyphCache::GarbageCollect() { - if( mnLruIndex - mnLastGC < mnMinGCInterval ) - return 0; - - mnLastGC = mnLruIndex; - - // TODO: improve garbage collection scalability - ULONG nBytesCollected = 0; - for( FontList::iterator it = aFontList.begin(); it != aFontList.end(); ) + // prepare advance to next font for garbage collection + ServerFont* pServerFont = pCurrentGCFont; + pCurrentGCFont = pCurrentGCFont->pNextGCFont; + if( pCurrentGCFont == pServerFont ) + pCurrentGCFont = NULL; + + ULONG nBytesCollected; + if( pServerFont->GetRefCount() == 0 ) { - ServerFont& rServerFont = const_cast<ServerFont&>( *(it->second) ); - if( rServerFont.GetRefCount() > 0) - { - nBytesCollected += rServerFont.GarbageCollect( mnLruIndex ); - ++it; - } - else - { - // this is a good time to remove unreferenced fonts - nBytesCollected += rServerFont.GetByteCount(); - delete &rServerFont; - aFontList.erase( it++ ); - } + // now its time to remove the unreferenced font + ServerFont* pPrev = pServerFont->pPrevGCFont; + ServerFont* pNext = pServerFont->pNextGCFont; + pPrev->pNextGCFont = pNext; + pNext->pPrevGCFont = pPrev; + + nBytesCollected = pServerFont->GetByteCount(); + aFontList.erase( pServerFont->GetFontSelData() ); + delete pServerFont; + } + else + { + // try to save at least a few bytes + nBytesCollected = pServerFont->GarbageCollect( mnLruIndex ); } return nBytesCollected; @@ -244,7 +295,7 @@ const GlyphMetric& GlyphCache::GetGlyphMetric( const ServerFont& rServerFont, sa if( mnBytesUsed > mnMaxSize ) mnBytesUsed -= const_cast<GlyphCache*>(this) -> GarbageCollect(); - ULONG nOldSize = rServerFont.GetByteCount(); + const ULONG nOldSize = rServerFont.GetByteCount(); pGD = rServerFont.CacheGlyphData( nGlyphIndex, false ); mnBytesUsed += rServerFont.GetByteCount() - nOldSize; } @@ -287,8 +338,19 @@ bool GlyphCache::GetGlyphOutline( const ServerFont& rServerFont, sal_Unicode aCh // ======================================================================= ServerFont::ServerFont( const ImplFontSelectData& rFSD ) -: maFontSelData(rFSD), mnRefCount(1), mnBytesUsed( sizeof(ServerFont) ) -{} +: maFontSelData(rFSD), + mnRefCount(1), + mnBytesUsed( sizeof(ServerFont) ), + nCos( 0x10000), + nSin( 0) +{ + if( rFSD.mnOrientation != 0 ) + { + const double dRad = rFSD.mnOrientation * ( F_2PI / 3600.0 ); + nCos = (long)( 0x10000 * cos( dRad ) + 0.5 ); + nSin = (long)( 0x10000 * sin( dRad ) + 0.5 ); + } +} // ----------------------------------------------------------------------- @@ -345,6 +407,20 @@ ULONG ServerFont::GarbageCollect( long nLruIndex ) return (nOldByteCount - mnBytesUsed); } +// ----------------------------------------------------------------------- + +Point ServerFont::TransformPoint( const Point& rPoint ) const +{ + if( !nSin) + return rPoint; + // TODO: use 32x32=>64bit intermediate + const double dCos = nCos * 1.0 / 0x10000; + const double dSin = nSin * 1.0 / 0x10000; + long nX = (long)(rPoint.X() * dCos + rPoint.Y() * dSin); + long nY = (long)(rPoint.Y() * dCos - rPoint.X() * dSin); + return Point( nX, nY ); +} + // ======================================================================= // GlyphData // ======================================================================= |