dwrite: Keep a single instance of system font collection.

This commit is contained in:
Nikolay Sivov 2012-10-21 23:20:42 -04:00 committed by Alexandre Julliard
parent 7978a38f24
commit a291a7adf8
4 changed files with 67 additions and 50 deletions

View File

@ -74,4 +74,5 @@ extern HRESULT create_textlayout(const WCHAR*,UINT32,IDWriteTextLayout**) DECLSP
extern HRESULT create_gdiinterop(IDWriteGdiInterop**) DECLSPEC_HIDDEN; extern HRESULT create_gdiinterop(IDWriteGdiInterop**) DECLSPEC_HIDDEN;
extern HRESULT create_localizedstrings(IDWriteLocalizedStrings**) DECLSPEC_HIDDEN; extern HRESULT create_localizedstrings(IDWriteLocalizedStrings**) DECLSPEC_HIDDEN;
extern HRESULT add_localizedstring(IDWriteLocalizedStrings*,const WCHAR*,const WCHAR*) DECLSPEC_HIDDEN; extern HRESULT add_localizedstring(IDWriteLocalizedStrings*,const WCHAR*,const WCHAR*) DECLSPEC_HIDDEN;
extern HRESULT create_system_fontcollection(IDWriteFontCollection**) DECLSPEC_HIDDEN; extern HRESULT get_system_fontcollection(IDWriteFontCollection**) DECLSPEC_HIDDEN;
extern void release_system_fontcollection(void) DECLSPEC_HIDDEN;

View File

@ -129,13 +129,14 @@ typedef struct
struct dwrite_fontcollection { struct dwrite_fontcollection {
IDWriteFontCollection IDWriteFontCollection_iface; IDWriteFontCollection IDWriteFontCollection_iface;
LONG ref;
WCHAR **families; WCHAR **families;
UINT32 count; UINT32 count;
int alloc; int alloc;
}; };
static IDWriteFontCollection *system_collection;
struct dwrite_fontfamily { struct dwrite_fontfamily {
IDWriteFontFamily IDWriteFontFamily_iface; IDWriteFontFamily IDWriteFontFamily_iface;
LONG ref; LONG ref;
@ -645,32 +646,14 @@ static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection
return E_NOINTERFACE; return E_NOINTERFACE;
} }
static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection *iface) static ULONG WINAPI dwritesysfontcollection_AddRef(IDWriteFontCollection *iface)
{ {
struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface); return 2;
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p)->(%d)\n", This, ref);
return ref;
} }
static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface) static ULONG WINAPI dwritesysfontcollection_Release(IDWriteFontCollection *iface)
{ {
struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface); return 1;
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p)->(%d)\n", This, ref);
if (!ref)
{
int i;
for (i = 0; i < This->count; i++)
heap_free(This->families[i]);
heap_free(This->families);
heap_free(This);
}
return ref;
} }
static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface) static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
@ -715,10 +698,10 @@ static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollec
return E_NOTIMPL; return E_NOTIMPL;
} }
static const IDWriteFontCollectionVtbl fontcollectionvtbl = { static const IDWriteFontCollectionVtbl systemfontcollectionvtbl = {
dwritefontcollection_QueryInterface, dwritefontcollection_QueryInterface,
dwritefontcollection_AddRef, dwritesysfontcollection_AddRef,
dwritefontcollection_Release, dwritesysfontcollection_Release,
dwritefontcollection_GetFontFamilyCount, dwritefontcollection_GetFontFamilyCount,
dwritefontcollection_GetFontFamily, dwritefontcollection_GetFontFamily,
dwritefontcollection_FindFamilyName, dwritefontcollection_FindFamilyName,
@ -749,35 +732,55 @@ static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm
return add_family_syscollection(collection, lf->lfFaceName) == S_OK; return add_family_syscollection(collection, lf->lfFaceName) == S_OK;
} }
HRESULT create_system_fontcollection(IDWriteFontCollection **collection) static void release_font_collection(IDWriteFontCollection *iface)
{ {
struct dwrite_fontcollection *This; struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
LOGFONTW lf; int i;
HDC hdc;
*collection = NULL; for (i = 0; i < This->count; i++)
heap_free(This->families[i]);
heap_free(This->families);
heap_free(This);
}
This = heap_alloc(sizeof(struct dwrite_fontcollection)); void release_system_fontcollection(void)
if (!This) return E_OUTOFMEMORY; {
release_font_collection(system_collection);
}
This->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl; HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
This->ref = 1; {
if (!system_collection)
{
struct dwrite_fontcollection *This;
LOGFONTW lf;
HDC hdc;
This->alloc = 50; *collection = NULL;
This->count = 0;
This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
TRACE("building system font collection:\n"); This = heap_alloc(sizeof(struct dwrite_fontcollection));
if (!This) return E_OUTOFMEMORY;
hdc = CreateCompatibleDC(0); This->IDWriteFontCollection_iface.lpVtbl = &systemfontcollectionvtbl;
memset(&lf, 0, sizeof(lf)); This->alloc = 50;
lf.lfCharSet = DEFAULT_CHARSET; This->count = 0;
lf.lfPitchAndFamily = DEFAULT_PITCH; This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
lf.lfFaceName[0] = 0;
EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
DeleteDC(hdc);
*collection = &This->IDWriteFontCollection_iface; TRACE("building system font collection:\n");
hdc = CreateCompatibleDC(0);
memset(&lf, 0, sizeof(lf));
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfPitchAndFamily = DEFAULT_PITCH;
lf.lfFaceName[0] = 0;
EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0);
DeleteDC(hdc);
if (InterlockedCompareExchangePointer((void**)&system_collection, &This->IDWriteFontCollection_iface, NULL))
release_font_collection(&This->IDWriteFontCollection_iface);
}
*collection = system_collection;
return S_OK; return S_OK;
} }

View File

@ -43,6 +43,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls( hinstDLL ); DisableThreadLibraryCalls( hinstDLL );
break; break;
case DLL_PROCESS_DETACH:
release_system_fontcollection();
break;
} }
return TRUE; return TRUE;
} }
@ -389,7 +392,7 @@ static HRESULT WINAPI dwritefactory_GetSystemFontCollection(IDWriteFactory *ifac
if (check_for_updates) if (check_for_updates)
FIXME("checking for system font updates not implemented\n"); FIXME("checking for system font updates not implemented\n");
return create_system_fontcollection(collection); return get_system_fontcollection(collection);
} }
static HRESULT WINAPI dwritefactory_CreateCustomFontCollection(IDWriteFactory *iface, static HRESULT WINAPI dwritefactory_CreateCustomFontCollection(IDWriteFactory *iface,

View File

@ -525,7 +525,7 @@ todo_wine
static void test_system_fontcollection(void) static void test_system_fontcollection(void)
{ {
IDWriteFontCollection *collection; IDWriteFontCollection *collection, *coll2;
HRESULT hr; HRESULT hr;
UINT32 i; UINT32 i;
BOOL ret; BOOL ret;
@ -533,6 +533,16 @@ static void test_system_fontcollection(void)
hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE); hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, FALSE);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
IDWriteFontCollection_Release(coll2);
hr = IDWriteFactory_GetSystemFontCollection(factory, &coll2, TRUE);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(coll2 == collection, "got %p, was %p\n", coll2, collection);
IDWriteFontCollection_Release(coll2);
i = IDWriteFontCollection_GetFontFamilyCount(collection); i = IDWriteFontCollection_GetFontFamilyCount(collection);
ok(i, "got %u\n", i); ok(i, "got %u\n", i);