dwrite: Create single shared factory.

This commit is contained in:
Nikolay Sivov 2014-10-09 09:05:27 +04:00 committed by Alexandre Julliard
parent 28e9b3f421
commit 1006987712
2 changed files with 177 additions and 37 deletions

View file

@ -35,6 +35,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
static IDWriteFactory *shared_factory;
static void release_shared_factory(IDWriteFactory*);
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
{
switch (reason)
@ -44,6 +47,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls( hinstDLL );
break;
case DLL_PROCESS_DETACH:
if (reserved) break;
release_shared_factory(shared_factory);
}
return TRUE;
}
@ -387,7 +393,7 @@ HRESULT clone_localizedstring(IDWriteLocalizedStrings *iface, IDWriteLocalizedSt
return S_OK;
}
struct dwritefactory{
struct dwritefactory {
IDWriteFactory IDWriteFactory_iface;
LONG ref;
@ -405,6 +411,33 @@ static inline struct dwritefactory *impl_from_IDWriteFactory(IDWriteFactory *ifa
return CONTAINING_RECORD(iface, struct dwritefactory, IDWriteFactory_iface);
}
static void release_dwritefactory(struct dwritefactory *factory)
{
int i;
if (factory->localfontfileloader)
IDWriteLocalFontFileLoader_Release(factory->localfontfileloader);
for (i = 0; i < factory->loader_count; i++)
if (factory->loaders[i])
IDWriteFontCollectionLoader_Release(factory->loaders[i]);
heap_free(factory->loaders);
for (i = 0; i < factory->file_loader_count; i++)
if (factory->file_loaders[i])
IDWriteFontFileLoader_Release(factory->file_loaders[i]);
heap_free(factory->file_loaders);
if (factory->system_collection)
IDWriteFontCollection_Release(factory->system_collection);
heap_free(factory);
}
static void release_shared_factory(IDWriteFactory *iface)
{
struct dwritefactory *factory;
if (!iface) return;
factory = impl_from_IDWriteFactory(iface);
release_dwritefactory(factory);
}
static HRESULT WINAPI dwritefactory_QueryInterface(IDWriteFactory *iface, REFIID riid, void **obj)
{
struct dwritefactory *This = impl_from_IDWriteFactory(iface);
@ -439,22 +472,8 @@ static ULONG WINAPI dwritefactory_Release(IDWriteFactory *iface)
TRACE("(%p)->(%d)\n", This, ref);
if (!ref) {
int i;
if (This->localfontfileloader)
IDWriteLocalFontFileLoader_Release(This->localfontfileloader);
for (i = 0; i < This->loader_count; i++)
if (This->loaders[i])
IDWriteFontCollectionLoader_Release(This->loaders[i]);
heap_free(This->loaders);
for (i = 0; i < This->file_loader_count; i++)
if (This->file_loaders[i])
IDWriteFontFileLoader_Release(This->file_loaders[i]);
heap_free(This->file_loaders);
if (This->system_collection)
IDWriteFontCollection_Release(This->system_collection);
heap_free(This);
}
if (!ref)
release_dwritefactory(This);
return ref;
}
@ -796,27 +815,101 @@ static const struct IDWriteFactoryVtbl dwritefactoryvtbl = {
dwritefactory_CreateGlyphRunAnalysis
};
HRESULT WINAPI DWriteCreateFactory(DWRITE_FACTORY_TYPE type, REFIID riid, IUnknown **factory)
static ULONG WINAPI shareddwritefactory_AddRef(IDWriteFactory *iface)
{
struct dwritefactory *This;
struct dwritefactory *This = impl_from_IDWriteFactory(iface);
TRACE("(%p)\n", This);
return 2;
}
TRACE("(%d, %s, %p)\n", type, debugstr_guid(riid), factory);
static ULONG WINAPI shareddwritefactory_Release(IDWriteFactory *iface)
{
struct dwritefactory *This = impl_from_IDWriteFactory(iface);
TRACE("(%p)\n", This);
return 1;
}
if (!IsEqualIID(riid, &IID_IDWriteFactory)) return E_FAIL;
static const struct IDWriteFactoryVtbl shareddwritefactoryvtbl = {
dwritefactory_QueryInterface,
shareddwritefactory_AddRef,
shareddwritefactory_Release,
dwritefactory_GetSystemFontCollection,
dwritefactory_CreateCustomFontCollection,
dwritefactory_RegisterFontCollectionLoader,
dwritefactory_UnregisterFontCollectionLoader,
dwritefactory_CreateFontFileReference,
dwritefactory_CreateCustomFontFileReference,
dwritefactory_CreateFontFace,
dwritefactory_CreateRenderingParams,
dwritefactory_CreateMonitorRenderingParams,
dwritefactory_CreateCustomRenderingParams,
dwritefactory_RegisterFontFileLoader,
dwritefactory_UnregisterFontFileLoader,
dwritefactory_CreateTextFormat,
dwritefactory_CreateTypography,
dwritefactory_GetGdiInterop,
dwritefactory_CreateTextLayout,
dwritefactory_CreateGdiCompatibleTextLayout,
dwritefactory_CreateEllipsisTrimmingSign,
dwritefactory_CreateTextAnalyzer,
dwritefactory_CreateNumberSubstitution,
dwritefactory_CreateGlyphRunAnalysis
};
This = heap_alloc(sizeof(struct dwritefactory));
if (!This) return E_OUTOFMEMORY;
static HRESULT init_dwritefactory(struct dwritefactory *factory, const struct IDWriteFactoryVtbl *vtbl)
{
factory->IDWriteFactory_iface.lpVtbl = vtbl;
factory->ref = 1;
factory->localfontfileloader = NULL;
factory->loader_count = 2;
factory->loaders = heap_alloc_zero(sizeof(*factory->loaders) * 2);
factory->file_loader_count = 2;
factory->file_loaders = heap_alloc_zero(sizeof(*factory->file_loaders) * 2);
factory->system_collection = NULL;
This->IDWriteFactory_iface.lpVtbl = &dwritefactoryvtbl;
This->ref = 1;
This->localfontfileloader = NULL;
This->loader_count = 2;
This->loaders = heap_alloc_zero(sizeof(*This->loaders) * 2);
This->file_loader_count = 2;
This->file_loaders = heap_alloc_zero(sizeof(*This->file_loaders) * 2);
This->system_collection = NULL;
*factory = (IUnknown*)&This->IDWriteFactory_iface;
if (!factory->loaders || !factory->file_loaders) {
heap_free(factory->loaders);
heap_free(factory->file_loaders);
return E_OUTOFMEMORY;
}
return S_OK;
}
HRESULT WINAPI DWriteCreateFactory(DWRITE_FACTORY_TYPE type, REFIID riid, IUnknown **ret)
{
struct dwritefactory *factory;
HRESULT hr;
TRACE("(%d, %s, %p)\n", type, debugstr_guid(riid), ret);
*ret = NULL;
if (!IsEqualIID(riid, &IID_IDWriteFactory)) return E_FAIL;
if (type == DWRITE_FACTORY_TYPE_SHARED && shared_factory) {
*ret = (IUnknown*)shared_factory;
IDWriteFactory_AddRef(shared_factory);
return S_OK;
}
factory = heap_alloc(sizeof(struct dwritefactory));
if (!factory) return E_OUTOFMEMORY;
hr = init_dwritefactory(factory, type == DWRITE_FACTORY_TYPE_SHARED ? &shareddwritefactoryvtbl : &dwritefactoryvtbl);
if (FAILED(hr)) {
heap_free(factory);
return hr;
}
if (type == DWRITE_FACTORY_TYPE_SHARED)
if (InterlockedCompareExchangePointer((void**)&shared_factory, factory, NULL)) {
release_shared_factory(&factory->IDWriteFactory_iface);
*ret = (IUnknown*)shared_factory;
IDWriteFactory_AddRef(shared_factory);
return S_OK;
}
*ret = (IUnknown*)&factory->IDWriteFactory_iface;
return S_OK;
}

View file

@ -31,9 +31,10 @@
#define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
static void _expect_ref(IUnknown* obj, ULONG ref, int line)
{
ULONG rc = IUnknown_AddRef(obj);
IUnknown_Release(obj);
ok_(__FILE__,line)(rc-1 == ref, "expected refcount %d, got %d\n", ref, rc-1);
ULONG rc;
IUnknown_AddRef(obj);
rc = IUnknown_Release(obj);
ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
}
static IDWriteFactory *factory;
@ -974,7 +975,7 @@ static void test_FontLoader(void)
hr = IDWriteFactory_CreateCustomFontFileReference(factory, &font, sizeof(HRSRC), &rloader, &ffile);
ok(hr == S_OK, "got 0x%08x\n", hr);
IDWriteFontFile_Analyze(ffile, &support, &type, &face, &count);
hr = IDWriteFontFile_Analyze(ffile, &support, &type, &face, &count);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(support == TRUE, "got %i\n", support);
ok(type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", type);
@ -1045,6 +1046,51 @@ static void test_CreateFontFileReference(void)
DeleteFileW(font_name);
}
static void test_shared_isolated(void)
{
IDWriteFactory *isolated, *isolated2;
IDWriteFactory *shared, *shared2;
HRESULT hr;
/* invalid type */
shared = NULL;
hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED+1, &IID_IDWriteFactory, (IUnknown**)&shared);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(shared != NULL, "got %p\n", shared);
IDWriteFactory_Release(shared);
hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared2);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(shared == shared2, "got %p, and %p\n", shared, shared2);
IDWriteFactory_Release(shared);
IDWriteFactory_Release(shared2);
/* we got 2 references, released 2 - still same pointer is returned */
hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, &IID_IDWriteFactory, (IUnknown**)&shared2);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(shared == shared2, "got %p, and %p\n", shared, shared2);
IDWriteFactory_Release(shared2);
hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&isolated);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&isolated2);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(isolated != isolated2, "got %p, and %p\n", isolated, isolated2);
IDWriteFactory_Release(isolated2);
hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED+1, &IID_IDWriteFactory, (IUnknown**)&isolated2);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(shared != isolated2, "got %p, and %p\n", shared, isolated2);
IDWriteFactory_Release(isolated);
IDWriteFactory_Release(isolated2);
}
START_TEST(font)
{
HRESULT hr;
@ -1068,6 +1114,7 @@ START_TEST(font)
test_CustomFontCollection();
test_FontLoader();
test_CreateFontFileReference();
test_shared_isolated();
IDWriteFactory_Release(factory);
}