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_localizedstrings(IDWriteLocalizedStrings**) 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 {
IDWriteFontCollection IDWriteFontCollection_iface;
LONG ref;
WCHAR **families;
UINT32 count;
int alloc;
};
static IDWriteFontCollection *system_collection;
struct dwrite_fontfamily {
IDWriteFontFamily IDWriteFontFamily_iface;
LONG ref;
@ -645,32 +646,14 @@ static HRESULT WINAPI dwritefontcollection_QueryInterface(IDWriteFontCollection
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);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p)->(%d)\n", This, ref);
return ref;
return 2;
}
static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface)
static ULONG WINAPI dwritesysfontcollection_Release(IDWriteFontCollection *iface)
{
struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
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;
return 1;
}
static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollection *iface)
@ -715,10 +698,10 @@ static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollec
return E_NOTIMPL;
}
static const IDWriteFontCollectionVtbl fontcollectionvtbl = {
static const IDWriteFontCollectionVtbl systemfontcollectionvtbl = {
dwritefontcollection_QueryInterface,
dwritefontcollection_AddRef,
dwritefontcollection_Release,
dwritesysfontcollection_AddRef,
dwritesysfontcollection_Release,
dwritefontcollection_GetFontFamilyCount,
dwritefontcollection_GetFontFamily,
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;
}
HRESULT create_system_fontcollection(IDWriteFontCollection **collection)
static void release_font_collection(IDWriteFontCollection *iface)
{
struct dwrite_fontcollection *This;
LOGFONTW lf;
HDC hdc;
struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface);
int i;
*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));
if (!This) return E_OUTOFMEMORY;
void release_system_fontcollection(void)
{
release_font_collection(system_collection);
}
This->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl;
This->ref = 1;
HRESULT get_system_fontcollection(IDWriteFontCollection **collection)
{
if (!system_collection)
{
struct dwrite_fontcollection *This;
LOGFONTW lf;
HDC hdc;
This->alloc = 50;
This->count = 0;
This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
*collection = NULL;
TRACE("building system font collection:\n");
This = heap_alloc(sizeof(struct dwrite_fontcollection));
if (!This) return E_OUTOFMEMORY;
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);
This->IDWriteFontCollection_iface.lpVtbl = &systemfontcollectionvtbl;
This->alloc = 50;
This->count = 0;
This->families = heap_alloc(This->alloc*sizeof(WCHAR*));
*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;
}

View File

@ -43,6 +43,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls( hinstDLL );
break;
case DLL_PROCESS_DETACH:
release_system_fontcollection();
break;
}
return TRUE;
}
@ -389,7 +392,7 @@ static HRESULT WINAPI dwritefactory_GetSystemFontCollection(IDWriteFactory *ifac
if (check_for_updates)
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,

View File

@ -525,7 +525,7 @@ todo_wine
static void test_system_fontcollection(void)
{
IDWriteFontCollection *collection;
IDWriteFontCollection *collection, *coll2;
HRESULT hr;
UINT32 i;
BOOL ret;
@ -533,6 +533,16 @@ static void test_system_fontcollection(void)
hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE);
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);
ok(i, "got %u\n", i);