From 75fff47f945dd2b5855c863383c82ff6ba4221ab Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 10 Dec 2012 12:32:17 +0100 Subject: [PATCH] gdi32: Add ref counting to the font objects and simplify the cache management. --- dlls/gdi32/font.c | 2 - dlls/gdi32/freetype.c | 168 ++++++++++++--------------------------- dlls/gdi32/gdi_private.h | 1 - 3 files changed, 53 insertions(+), 118 deletions(-) diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index f84e7074fd5..3d67c6405cc 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -644,8 +644,6 @@ static BOOL FONT_DeleteObject( HGDIOBJ handle ) { FONTOBJ *obj; - WineEngDestroyFontInstance( handle ); - if (!(obj = free_gdi_handle( handle ))) return FALSE; return HeapFree( GetProcessHeap(), 0, obj ); } diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index ce8bbd998da..521e6658aed 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -304,11 +304,6 @@ typedef struct { BOOL can_use_bitmap; } FONT_DESC; -typedef struct tagHFONTLIST { - struct list entry; - HFONT hfont; -} HFONTLIST; - typedef struct tagGdiFont GdiFont; typedef struct { @@ -319,9 +314,10 @@ typedef struct { struct tagGdiFont { struct list entry; + struct list unused_entry; + unsigned int refcount; GM **gm; DWORD gmsize; - struct list hfontlist; OUTLINETEXTMETRICW *potm; DWORD total_kern_pairs; KERNINGPAIR *kern_pairs; @@ -4025,6 +4021,7 @@ static int get_nearest_charset(const WCHAR *family_name, Face *face, int *cp) static GdiFont *alloc_font(void) { GdiFont *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret)); + ret->refcount = 1; ret->gmsize = 1; ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM*)); ret->gm[0] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE); @@ -4032,7 +4029,6 @@ static GdiFont *alloc_font(void) ret->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0; ret->total_kern_pairs = (DWORD)-1; ret->kern_pairs = NULL; - list_init(&ret->hfontlist); list_init(&ret->child_fonts); return ret; } @@ -4040,7 +4036,6 @@ static GdiFont *alloc_font(void) static void free_font(GdiFont *font) { CHILD_FONT *child, *child_next; - HFONTLIST *hfontlist, *hfnext; DWORD i; LIST_FOR_EACH_ENTRY_SAFE( child, child_next, &font->child_fonts, CHILD_FONT, entry ) @@ -4051,12 +4046,6 @@ static void free_font(GdiFont *font) HeapFree(GetProcessHeap(), 0, child); } - LIST_FOR_EACH_ENTRY_SAFE( hfontlist, hfnext, &font->hfontlist, HFONTLIST, entry ) - { - list_remove(&hfontlist->entry); - HeapFree(GetProcessHeap(), 0, hfontlist); - } - if (font->ft_face) pFT_Done_Face(font->ft_face); if (font->mapping) unmap_font_file( font->mapping ); HeapFree(GetProcessHeap(), 0, font->kern_pairs); @@ -4236,6 +4225,48 @@ static LONG load_VDMX(GdiFont *font, LONG height) return ppem; } +static void dump_gdi_font_list(void) +{ + GdiFont *font; + + TRACE("---------- Font Cache ----------\n"); + LIST_FOR_EACH_ENTRY( font, &gdi_font_list, struct tagGdiFont, entry ) + TRACE("font=%p ref=%u %s %d\n", font, font->refcount, + debugstr_w(font->font_desc.lf.lfFaceName), font->font_desc.lf.lfHeight); +} + +static void grab_font( GdiFont *font ) +{ + if (!font->refcount++) + { + list_remove( &font->unused_entry ); + unused_font_count--; + } +} + +static void release_font( GdiFont *font ) +{ + if (!font) return; + if (!--font->refcount) + { + 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 tagGdiFont, unused_entry ); + TRACE( "freeing %p\n", font ); + list_remove( &font->entry ); + list_remove( &font->unused_entry ); + free_font( font ); + } + else unused_font_count++; + + if (TRACE_ON(font)) dump_gdi_font_list(); + } +} + static BOOL fontcmp(const GdiFont *font, FONT_DESC *fd) { if(font->font_desc.hash != fd->hash) return TRUE; @@ -4272,9 +4303,8 @@ static void calc_hash(FONT_DESC *pfd) static GdiFont *find_in_cache(HFONT hfont, const LOGFONTW *plf, const FMAT2 *pmat, BOOL can_use_bitmap) { - GdiFont *ret, *next; + GdiFont *ret; FONT_DESC fd; - HFONTLIST *hflist; fd.lf = *plf; fd.matrix = *pmat; @@ -4286,29 +4316,9 @@ static GdiFont *find_in_cache(HFONT hfont, const LOGFONTW *plf, const FMAT2 *pma { if(fontcmp(ret, &fd)) continue; if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue; - LIST_FOR_EACH_ENTRY( hflist, &ret->hfontlist, struct tagHFONTLIST, entry ) - if(hflist->hfont == hfont) return ret; - - hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist)); - hflist->hfont = hfont; - list_add_head(&ret->hfontlist, &hflist->entry); - return ret; - } - - /* then the unused list */ - LIST_FOR_EACH_ENTRY_SAFE( ret, next, &unused_gdi_font_list, struct tagGdiFont, entry ) - { - if(fontcmp(ret, &fd)) continue; - if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue; - - assert(list_empty(&ret->hfontlist)); - TRACE("Found %p in unused list\n", ret); - list_remove(&ret->entry); - list_add_head(&gdi_font_list, &ret->entry); - hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist)); - hflist->hfont = hfont; - list_add_head(&ret->hfontlist, &hflist->entry); - unused_font_count--; + list_remove( &ret->entry ); + list_add_head( &gdi_font_list, &ret->entry ); + grab_font( ret ); return ret; } return NULL; @@ -4320,6 +4330,7 @@ static void add_to_cache(GdiFont *font) font->cache_num = cache_num++; list_add_head(&gdi_font_list, &font->entry); + TRACE( "font %p\n", font ); } /************************************************************* @@ -4452,6 +4463,7 @@ static BOOL freetype_CreateDC( PHYSDEV *dev, LPCWSTR driver, LPCWSTR device, static BOOL freetype_DeleteDC( PHYSDEV dev ) { struct freetype_physdev *physdev = get_freetype_dev( dev ); + release_font( physdev->font ); HeapFree( GetProcessHeap(), 0, physdev ); return TRUE; } @@ -4535,7 +4547,6 @@ static HFONT freetype_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags ) BOOL bd, it, can_use_bitmap, want_vertical; LOGFONTW lf; CHARSETINFO csi; - HFONTLIST *hflist; FMAT2 dcmat; FontSubst *psub = NULL; DC *dc = get_dc_ptr( dev->hdc ); @@ -4543,6 +4554,7 @@ static HFONT freetype_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags ) if (!hfont) /* notification that the font has been changed by another driver */ { + release_font( physdev->font ); physdev->font = NULL; release_dc_ptr( dc ); return 0; @@ -4596,12 +4608,6 @@ static HFONT freetype_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags ) goto done; } - if(list_empty(&font_list)) /* No fonts installed */ - { - TRACE("No fonts installed\n"); - goto done; - } - TRACE("not in cache\n"); ret = alloc_font(); @@ -4609,9 +4615,6 @@ static HFONT freetype_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags ) ret->font_desc.lf = lf; ret->font_desc.can_use_bitmap = can_use_bitmap; calc_hash(&ret->font_desc); - hflist = HeapAlloc(GetProcessHeap(), 0, sizeof(*hflist)); - hflist->hfont = hfont; - list_add_head(&ret->hfontlist, &hflist->entry); /* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to SYMBOL_CHARSET so that Symbol gets picked irrespective of the @@ -4990,6 +4993,7 @@ done: } } TRACE( "%p %s %d aa %x\n", hfont, debugstr_w(lf.lfFaceName), lf.lfHeight, *aa_flags ); + release_font( physdev->font ); physdev->font = ret; } LeaveCriticalSection( &freetype_cs ); @@ -4997,68 +5001,6 @@ done: return ret ? hfont : 0; } -static void dump_gdi_font_list(void) -{ - GdiFont *gdiFont; - - TRACE("---------- gdiFont Cache ----------\n"); - LIST_FOR_EACH_ENTRY( gdiFont, &gdi_font_list, struct tagGdiFont, entry ) - TRACE("gdiFont=%p %s %d\n", - gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight); - - TRACE("---------- Unused gdiFont Cache ----------\n"); - LIST_FOR_EACH_ENTRY( gdiFont, &unused_gdi_font_list, struct tagGdiFont, entry ) - TRACE("gdiFont=%p %s %d\n", - gdiFont, debugstr_w(gdiFont->font_desc.lf.lfFaceName), gdiFont->font_desc.lf.lfHeight); -} - -/************************************************************* - * WineEngDestroyFontInstance - * - * free the gdiFont associated with this handle - * - */ -BOOL WineEngDestroyFontInstance(HFONT handle) -{ - GdiFont *gdiFont, *next; - HFONTLIST *hflist, *hfnext; - BOOL ret = FALSE; - - GDI_CheckNotLock(); - EnterCriticalSection( &freetype_cs ); - - TRACE("destroying hfont=%p\n", handle); - if(TRACE_ON(font)) - dump_gdi_font_list(); - - LIST_FOR_EACH_ENTRY_SAFE( gdiFont, next, &gdi_font_list, struct tagGdiFont, entry ) - { - LIST_FOR_EACH_ENTRY_SAFE( hflist, hfnext, &gdiFont->hfontlist, struct tagHFONTLIST, entry ) - { - if(hflist->hfont == handle) { - list_remove(&hflist->entry); - HeapFree(GetProcessHeap(), 0, hflist); - ret = TRUE; - } - } - if(list_empty(&gdiFont->hfontlist)) { - TRACE("Moving to Unused list\n"); - list_remove(&gdiFont->entry); - list_add_head(&unused_gdi_font_list, &gdiFont->entry); - if (unused_font_count > UNUSED_CACHE_SIZE) - { - gdiFont = LIST_ENTRY( list_tail( &unused_gdi_font_list ), struct tagGdiFont, entry ); - TRACE("freeing %p\n", gdiFont); - list_remove(&gdiFont->entry); - free_font(gdiFont); - } - else unused_font_count++; - } - } - LeaveCriticalSection( &freetype_cs ); - return ret; -} - static INT load_script_name( UINT id, WCHAR buffer[LF_FACESIZE] ) { HRSRC rsrc; @@ -7882,10 +7824,6 @@ BOOL WineEngInit(void) { return FALSE; } -BOOL WineEngDestroyFontInstance(HFONT hfont) -{ - return FALSE; -} INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv) { diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 8288e35ea63..84febeb1ffd 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -290,7 +290,6 @@ typedef struct extern INT WineEngAddFontResourceEx(LPCWSTR, DWORD, PVOID) DECLSPEC_HIDDEN; extern HANDLE WineEngAddFontMemResourceEx(PVOID, DWORD, PVOID, LPDWORD) DECLSPEC_HIDDEN; extern BOOL WineEngCreateScalableFontResource(DWORD, LPCWSTR, LPCWSTR, LPCWSTR) DECLSPEC_HIDDEN; -extern BOOL WineEngDestroyFontInstance(HFONT handle) DECLSPEC_HIDDEN; extern BOOL WineEngInit(void) DECLSPEC_HIDDEN; extern BOOL WineEngRemoveFontResourceEx(LPCWSTR, DWORD, PVOID) DECLSPEC_HIDDEN;