summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorHerbert Duerr <hdu@openoffice.org>2000-11-16 12:44:43 +0000
committerHerbert Duerr <hdu@openoffice.org>2000-11-16 12:44:43 +0000
commitecd7d21bf716aeccf02cea392000889c391bdd09 (patch)
treedc8b06b4b044de15a7bb3b10f943b940e78b9968 /vcl
parenta949f50ce969b1f8d018d2913c0d86cfcec4e72a (diff)
improved GC scalability and implemented SetFontPath/GetFontPath
Diffstat (limited to 'vcl')
-rw-r--r--vcl/source/glyphs/glyphcache.cxx170
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
// =======================================================================