Commit 82c140f1 authored by Alexandre Julliard's avatar Alexandre Julliard

gdi32: Move the font cache list out of freetype.c.

parent d7a54394
...@@ -402,6 +402,9 @@ struct gdi_font *alloc_gdi_font(void) ...@@ -402,6 +402,9 @@ struct gdi_font *alloc_gdi_font(void)
{ {
struct gdi_font *font = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*font) ); struct gdi_font *font = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*font) );
font->refcount = 1;
font->matrix.eM11 = font->matrix.eM22 = 1.0;
if (!(font->handle = alloc_font_handle( font ))) if (!(font->handle = alloc_font_handle( font )))
{ {
HeapFree( GetProcessHeap(), 0, font ); HeapFree( GetProcessHeap(), 0, font );
...@@ -422,6 +425,100 @@ void free_gdi_font( struct gdi_font *font ) ...@@ -422,6 +425,100 @@ void free_gdi_font( struct gdi_font *font )
HeapFree( GetProcessHeap(), 0, font ); HeapFree( GetProcessHeap(), 0, font );
} }
/* font cache */
static struct list gdi_font_list = LIST_INIT( gdi_font_list );
static struct list unused_gdi_font_list = LIST_INIT( unused_gdi_font_list );
static unsigned int unused_font_count;
#define UNUSED_CACHE_SIZE 10
static BOOL fontcmp( const struct gdi_font *font, DWORD hash, const LOGFONTW *lf,
const FMAT2 *matrix, BOOL can_use_bitmap )
{
if (font->hash != hash) return TRUE;
if (memcmp( &font->matrix, matrix, sizeof(*matrix))) return TRUE;
if (memcmp( &font->lf, lf, offsetof(LOGFONTW, lfFaceName))) return TRUE;
if (!font->can_use_bitmap != !can_use_bitmap) return TRUE;
return strcmpiW( font->lf.lfFaceName, lf->lfFaceName);
}
static DWORD hash_font( const LOGFONTW *lf, const FMAT2 *matrix, BOOL can_use_bitmap )
{
DWORD hash = 0, *ptr, two_chars;
WORD *pwc;
unsigned int i;
for (i = 0, ptr = (DWORD *)matrix; i < sizeof(*matrix) / sizeof(DWORD); i++, ptr++)
hash ^= *ptr;
for(i = 0, ptr = (DWORD *)lf; i < 7; i++, ptr++)
hash ^= *ptr;
for(i = 0, ptr = (DWORD *)lf->lfFaceName; i < LF_FACESIZE/2; i++, ptr++)
{
two_chars = *ptr;
pwc = (WCHAR *)&two_chars;
if(!*pwc) break;
*pwc = toupperW(*pwc);
pwc++;
*pwc = toupperW(*pwc);
hash ^= two_chars;
if(!*pwc) break;
}
hash ^= !can_use_bitmap;
return hash;
}
void cache_gdi_font( struct gdi_font *font )
{
static DWORD cache_num = 1;
font->cache_num = cache_num++;
font->hash = hash_font( &font->lf, &font->matrix, font->can_use_bitmap );
list_add_head( &gdi_font_list, &font->entry );
TRACE( "font %p\n", font );
}
struct gdi_font *find_cached_gdi_font( const LOGFONTW *lf, const FMAT2 *matrix, BOOL can_use_bitmap )
{
struct gdi_font *font;
DWORD hash = hash_font( lf, matrix, can_use_bitmap );
/* try the in-use list */
LIST_FOR_EACH_ENTRY( font, &gdi_font_list, struct gdi_font, entry )
{
if (fontcmp( font, hash, lf, matrix, can_use_bitmap )) continue;
list_remove( &font->entry );
list_add_head( &gdi_font_list, &font->entry );
if (!font->refcount++)
{
list_remove( &font->unused_entry );
unused_font_count--;
}
return font;
}
return NULL;
}
static void release_gdi_font( struct gdi_font *font )
{
if (!font) return;
if (--font->refcount) return;
TRACE( "font %p\n", font );
/* add it to the unused list */
list_add_head( &unused_gdi_font_list, &font->unused_entry );
if (unused_font_count > UNUSED_CACHE_SIZE)
{
font = LIST_ENTRY( list_tail( &unused_gdi_font_list ), struct gdi_font, unused_entry );
TRACE( "freeing %p\n", font );
list_remove( &font->entry );
list_remove( &font->unused_entry );
free_gdi_font( font );
return;
}
unused_font_count++;
}
static void add_font_list(HKEY hkey, const struct nls_update_font_list *fl, int dpi) static void add_font_list(HKEY hkey, const struct nls_update_font_list *fl, int dpi)
{ {
const char *sserif = (dpi <= 108) ? fl->sserif_96 : fl->sserif_120; const char *sserif = (dpi <= 108) ? fl->sserif_96 : fl->sserif_120;
...@@ -687,7 +784,7 @@ static BOOL CDECL font_DeleteDC( PHYSDEV dev ) ...@@ -687,7 +784,7 @@ static BOOL CDECL font_DeleteDC( PHYSDEV dev )
{ {
struct font_physdev *physdev = get_font_dev( dev ); struct font_physdev *physdev = get_font_dev( dev );
font_funcs->pSelectFont( physdev->font, NULL, 0, NULL, 0 ); release_gdi_font( physdev->font );
HeapFree( GetProcessHeap(), 0, physdev ); HeapFree( GetProcessHeap(), 0, physdev );
return TRUE; return TRUE;
} }
...@@ -982,6 +1079,7 @@ static HFONT CDECL font_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags ) ...@@ -982,6 +1079,7 @@ static HFONT CDECL font_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags )
{ {
UINT default_aa_flags = *aa_flags; UINT default_aa_flags = *aa_flags;
struct font_physdev *physdev = get_font_dev( dev ); struct font_physdev *physdev = get_font_dev( dev );
struct gdi_font *prev = physdev->font;
DC *dc = get_physdev_dc( dev ); DC *dc = get_physdev_dc( dev );
if (!default_aa_flags) if (!default_aa_flags)
...@@ -989,7 +1087,12 @@ static HFONT CDECL font_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags ) ...@@ -989,7 +1087,12 @@ static HFONT CDECL font_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags )
PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectFont ); PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectFont );
next->funcs->pSelectFont( next, hfont, &default_aa_flags ); next->funcs->pSelectFont( next, hfont, &default_aa_flags );
} }
physdev->font = font_funcs->pSelectFont( physdev->font, dc, hfont, aa_flags, default_aa_flags ); if (!hfont) /* notification that the font has been changed by another driver */
physdev->font = NULL;
else
physdev->font = font_funcs->pSelectFont( dc, hfont, aa_flags, default_aa_flags );
if (prev) release_gdi_font( prev );
return physdev->font ? hfont : 0; return physdev->font ? hfont : 0;
} }
......
...@@ -309,10 +309,21 @@ struct font_fileinfo ...@@ -309,10 +309,21 @@ struct font_fileinfo
WCHAR path[1]; WCHAR path[1];
}; };
typedef struct { FLOAT eM11, eM12, eM21, eM22; } FMAT2;
struct gdi_font struct gdi_font
{ {
struct list entry;
struct list unused_entry;
DWORD refcount;
/* the following members can be accessed without locking, they are never modified after creation */
void *private; /* font backend private data */ void *private; /* font backend private data */
DWORD handle; DWORD handle;
DWORD cache_num;
DWORD hash;
LOGFONTW lf;
FMAT2 matrix;
BOOL can_use_bitmap;
}; };
struct font_backend_funcs struct font_backend_funcs
...@@ -336,8 +347,8 @@ struct font_backend_funcs ...@@ -336,8 +347,8 @@ struct font_backend_funcs
BOOL (CDECL *pGetTextExtentExPointI)( struct gdi_font *font, const WORD *indices, INT count, INT *dxs ); BOOL (CDECL *pGetTextExtentExPointI)( struct gdi_font *font, const WORD *indices, INT count, INT *dxs );
INT (CDECL *pGetTextFace)( struct gdi_font *font, INT count, WCHAR *str ); INT (CDECL *pGetTextFace)( struct gdi_font *font, INT count, WCHAR *str );
BOOL (CDECL *pGetTextMetrics)( struct gdi_font *font, TEXTMETRICW *metrics ); BOOL (CDECL *pGetTextMetrics)( struct gdi_font *font, TEXTMETRICW *metrics );
struct gdi_font * (CDECL *pSelectFont)( struct gdi_font *prev, DC *dc, HFONT hfont, struct gdi_font * (CDECL *pSelectFont)( DC *dc, HFONT hfont, UINT *aa_flags, UINT default_aa_flags );
UINT *aa_flags, UINT default_aa_flags );
INT (CDECL *pAddFontResourceEx)( LPCWSTR file, DWORD flags, PVOID pdv ); INT (CDECL *pAddFontResourceEx)( LPCWSTR file, DWORD flags, PVOID pdv );
INT (CDECL *pRemoveFontResourceEx)( LPCWSTR file, DWORD flags, PVOID pdv ); INT (CDECL *pRemoveFontResourceEx)( LPCWSTR file, DWORD flags, PVOID pdv );
HANDLE (CDECL *pAddFontMemResourceEx)( void *font, DWORD size, PVOID pdv, DWORD *count ); HANDLE (CDECL *pAddFontMemResourceEx)( void *font, DWORD size, PVOID pdv, DWORD *count );
...@@ -354,6 +365,9 @@ struct font_backend_funcs ...@@ -354,6 +365,9 @@ struct font_backend_funcs
extern struct gdi_font *alloc_gdi_font(void) DECLSPEC_HIDDEN; extern struct gdi_font *alloc_gdi_font(void) DECLSPEC_HIDDEN;
extern void free_gdi_font( struct gdi_font *font ) DECLSPEC_HIDDEN; extern void free_gdi_font( struct gdi_font *font ) DECLSPEC_HIDDEN;
extern void cache_gdi_font( struct gdi_font *font ) DECLSPEC_HIDDEN;
extern struct gdi_font *find_cached_gdi_font( const LOGFONTW *lf, const FMAT2 *matrix,
BOOL can_use_bitmap ) DECLSPEC_HIDDEN;
extern void font_init(void) DECLSPEC_HIDDEN; extern void font_init(void) DECLSPEC_HIDDEN;
/* freetype.c */ /* freetype.c */
......
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