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;
|
FONTOBJ *obj;
|
||||||
|
|
||||||
WineEngDestroyFontInstance( handle );
|
|
||||||
|
|
||||||
if (!(obj = free_gdi_handle( handle ))) return FALSE;
|
if (!(obj = free_gdi_handle( handle ))) return FALSE;
|
||||||
return HeapFree( GetProcessHeap(), 0, obj );
|
return HeapFree( GetProcessHeap(), 0, obj );
|
||||||
}
|
}
|
||||||
|
@ -304,11 +304,6 @@ typedef struct {
|
|||||||
BOOL can_use_bitmap;
|
BOOL can_use_bitmap;
|
||||||
} FONT_DESC;
|
} FONT_DESC;
|
||||||
|
|
||||||
typedef struct tagHFONTLIST {
|
|
||||||
struct list entry;
|
|
||||||
HFONT hfont;
|
|
||||||
} HFONTLIST;
|
|
||||||
|
|
||||||
typedef struct tagGdiFont GdiFont;
|
typedef struct tagGdiFont GdiFont;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -319,9 +314,10 @@ typedef struct {
|
|||||||
|
|
||||||
struct tagGdiFont {
|
struct tagGdiFont {
|
||||||
struct list entry;
|
struct list entry;
|
||||||
|
struct list unused_entry;
|
||||||
|
unsigned int refcount;
|
||||||
GM **gm;
|
GM **gm;
|
||||||
DWORD gmsize;
|
DWORD gmsize;
|
||||||
struct list hfontlist;
|
|
||||||
OUTLINETEXTMETRICW *potm;
|
OUTLINETEXTMETRICW *potm;
|
||||||
DWORD total_kern_pairs;
|
DWORD total_kern_pairs;
|
||||||
KERNINGPAIR *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)
|
static GdiFont *alloc_font(void)
|
||||||
{
|
{
|
||||||
GdiFont *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
|
GdiFont *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ret));
|
||||||
|
ret->refcount = 1;
|
||||||
ret->gmsize = 1;
|
ret->gmsize = 1;
|
||||||
ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM*));
|
ret->gm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM*));
|
||||||
ret->gm[0] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
|
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->font_desc.matrix.eM11 = ret->font_desc.matrix.eM22 = 1.0;
|
||||||
ret->total_kern_pairs = (DWORD)-1;
|
ret->total_kern_pairs = (DWORD)-1;
|
||||||
ret->kern_pairs = NULL;
|
ret->kern_pairs = NULL;
|
||||||
list_init(&ret->hfontlist);
|
|
||||||
list_init(&ret->child_fonts);
|
list_init(&ret->child_fonts);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -4040,7 +4036,6 @@ static GdiFont *alloc_font(void)
|
|||||||
static void free_font(GdiFont *font)
|
static void free_font(GdiFont *font)
|
||||||
{
|
{
|
||||||
CHILD_FONT *child, *child_next;
|
CHILD_FONT *child, *child_next;
|
||||||
HFONTLIST *hfontlist, *hfnext;
|
|
||||||
DWORD i;
|
DWORD i;
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY_SAFE( child, child_next, &font->child_fonts, CHILD_FONT, entry )
|
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);
|
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->ft_face) pFT_Done_Face(font->ft_face);
|
||||||
if (font->mapping) unmap_font_file( font->mapping );
|
if (font->mapping) unmap_font_file( font->mapping );
|
||||||
HeapFree(GetProcessHeap(), 0, font->kern_pairs);
|
HeapFree(GetProcessHeap(), 0, font->kern_pairs);
|
||||||
@ -4236,6 +4225,48 @@ static LONG load_VDMX(GdiFont *font, LONG height)
|
|||||||
return ppem;
|
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)
|
static BOOL fontcmp(const GdiFont *font, FONT_DESC *fd)
|
||||||
{
|
{
|
||||||
if(font->font_desc.hash != fd->hash) return TRUE;
|
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)
|
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;
|
FONT_DESC fd;
|
||||||
HFONTLIST *hflist;
|
|
||||||
|
|
||||||
fd.lf = *plf;
|
fd.lf = *plf;
|
||||||
fd.matrix = *pmat;
|
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(fontcmp(ret, &fd)) continue;
|
||||||
if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
|
if(!can_use_bitmap && !FT_IS_SCALABLE(ret->ft_face)) continue;
|
||||||
LIST_FOR_EACH_ENTRY( hflist, &ret->hfontlist, struct tagHFONTLIST, entry )
|
list_remove( &ret->entry );
|
||||||
if(hflist->hfont == hfont) return ret;
|
list_add_head( &gdi_font_list, &ret->entry );
|
||||||
|
grab_font( 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--;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -4320,6 +4330,7 @@ static void add_to_cache(GdiFont *font)
|
|||||||
|
|
||||||
font->cache_num = cache_num++;
|
font->cache_num = cache_num++;
|
||||||
list_add_head(&gdi_font_list, &font->entry);
|
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 )
|
static BOOL freetype_DeleteDC( PHYSDEV dev )
|
||||||
{
|
{
|
||||||
struct freetype_physdev *physdev = get_freetype_dev( dev );
|
struct freetype_physdev *physdev = get_freetype_dev( dev );
|
||||||
|
release_font( physdev->font );
|
||||||
HeapFree( GetProcessHeap(), 0, physdev );
|
HeapFree( GetProcessHeap(), 0, physdev );
|
||||||
return TRUE;
|
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;
|
BOOL bd, it, can_use_bitmap, want_vertical;
|
||||||
LOGFONTW lf;
|
LOGFONTW lf;
|
||||||
CHARSETINFO csi;
|
CHARSETINFO csi;
|
||||||
HFONTLIST *hflist;
|
|
||||||
FMAT2 dcmat;
|
FMAT2 dcmat;
|
||||||
FontSubst *psub = NULL;
|
FontSubst *psub = NULL;
|
||||||
DC *dc = get_dc_ptr( dev->hdc );
|
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 */
|
if (!hfont) /* notification that the font has been changed by another driver */
|
||||||
{
|
{
|
||||||
|
release_font( physdev->font );
|
||||||
physdev->font = NULL;
|
physdev->font = NULL;
|
||||||
release_dc_ptr( dc );
|
release_dc_ptr( dc );
|
||||||
return 0;
|
return 0;
|
||||||
@ -4596,12 +4608,6 @@ static HFONT freetype_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags )
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(list_empty(&font_list)) /* No fonts installed */
|
|
||||||
{
|
|
||||||
TRACE("No fonts installed\n");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE("not in cache\n");
|
TRACE("not in cache\n");
|
||||||
ret = alloc_font();
|
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.lf = lf;
|
||||||
ret->font_desc.can_use_bitmap = can_use_bitmap;
|
ret->font_desc.can_use_bitmap = can_use_bitmap;
|
||||||
calc_hash(&ret->font_desc);
|
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
|
/* If lfFaceName is "Symbol" then Windows fixes up lfCharSet to
|
||||||
SYMBOL_CHARSET so that Symbol gets picked irrespective of the
|
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 );
|
TRACE( "%p %s %d aa %x\n", hfont, debugstr_w(lf.lfFaceName), lf.lfHeight, *aa_flags );
|
||||||
|
release_font( physdev->font );
|
||||||
physdev->font = ret;
|
physdev->font = ret;
|
||||||
}
|
}
|
||||||
LeaveCriticalSection( &freetype_cs );
|
LeaveCriticalSection( &freetype_cs );
|
||||||
@ -4997,68 +5001,6 @@ done:
|
|||||||
return ret ? hfont : 0;
|
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] )
|
static INT load_script_name( UINT id, WCHAR buffer[LF_FACESIZE] )
|
||||||
{
|
{
|
||||||
HRSRC rsrc;
|
HRSRC rsrc;
|
||||||
@ -7882,10 +7824,6 @@ BOOL WineEngInit(void)
|
|||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
BOOL WineEngDestroyFontInstance(HFONT hfont)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
|
INT WineEngAddFontResourceEx(LPCWSTR file, DWORD flags, PVOID pdv)
|
||||||
{
|
{
|
||||||
|
@ -290,7 +290,6 @@ typedef struct
|
|||||||
extern INT WineEngAddFontResourceEx(LPCWSTR, DWORD, PVOID) DECLSPEC_HIDDEN;
|
extern INT WineEngAddFontResourceEx(LPCWSTR, DWORD, PVOID) DECLSPEC_HIDDEN;
|
||||||
extern HANDLE WineEngAddFontMemResourceEx(PVOID, DWORD, PVOID, LPDWORD) DECLSPEC_HIDDEN;
|
extern HANDLE WineEngAddFontMemResourceEx(PVOID, DWORD, PVOID, LPDWORD) DECLSPEC_HIDDEN;
|
||||||
extern BOOL WineEngCreateScalableFontResource(DWORD, LPCWSTR, LPCWSTR, LPCWSTR) 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 WineEngInit(void) DECLSPEC_HIDDEN;
|
||||||
extern BOOL WineEngRemoveFontResourceEx(LPCWSTR, DWORD, PVOID) DECLSPEC_HIDDEN;
|
extern BOOL WineEngRemoveFontResourceEx(LPCWSTR, DWORD, PVOID) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user