gdi32: Add ref counting to the font objects and simplify the cache management.
This commit is contained in:
parent
fa664b548e
commit
75fff47f94
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue