Commit 10069877 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

dwrite: Create single shared factory.

parent 28e9b3f4
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(dwrite); WINE_DEFAULT_DEBUG_CHANNEL(dwrite);
static IDWriteFactory *shared_factory;
static void release_shared_factory(IDWriteFactory*);
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
{ {
switch (reason) switch (reason)
...@@ -44,6 +47,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved) ...@@ -44,6 +47,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:
if (reserved) break;
release_shared_factory(shared_factory);
} }
return TRUE; return TRUE;
} }
...@@ -387,7 +393,7 @@ HRESULT clone_localizedstring(IDWriteLocalizedStrings *iface, IDWriteLocalizedSt ...@@ -387,7 +393,7 @@ HRESULT clone_localizedstring(IDWriteLocalizedStrings *iface, IDWriteLocalizedSt
return S_OK; return S_OK;
} }
struct dwritefactory{ struct dwritefactory {
IDWriteFactory IDWriteFactory_iface; IDWriteFactory IDWriteFactory_iface;
LONG ref; LONG ref;
...@@ -405,6 +411,33 @@ static inline struct dwritefactory *impl_from_IDWriteFactory(IDWriteFactory *ifa ...@@ -405,6 +411,33 @@ static inline struct dwritefactory *impl_from_IDWriteFactory(IDWriteFactory *ifa
return CONTAINING_RECORD(iface, struct dwritefactory, IDWriteFactory_iface); 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) static HRESULT WINAPI dwritefactory_QueryInterface(IDWriteFactory *iface, REFIID riid, void **obj)
{ {
struct dwritefactory *This = impl_from_IDWriteFactory(iface); struct dwritefactory *This = impl_from_IDWriteFactory(iface);
...@@ -439,22 +472,8 @@ static ULONG WINAPI dwritefactory_Release(IDWriteFactory *iface) ...@@ -439,22 +472,8 @@ static ULONG WINAPI dwritefactory_Release(IDWriteFactory *iface)
TRACE("(%p)->(%d)\n", This, ref); TRACE("(%p)->(%d)\n", This, ref);
if (!ref) { if (!ref)
int i; release_dwritefactory(This);
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);
}
return ref; return ref;
} }
...@@ -796,27 +815,101 @@ static const struct IDWriteFactoryVtbl dwritefactoryvtbl = { ...@@ -796,27 +815,101 @@ static const struct IDWriteFactoryVtbl dwritefactoryvtbl = {
dwritefactory_CreateGlyphRunAnalysis dwritefactory_CreateGlyphRunAnalysis
}; };
HRESULT WINAPI DWriteCreateFactory(DWRITE_FACTORY_TYPE type, REFIID riid, IUnknown **factory) static ULONG WINAPI shareddwritefactory_AddRef(IDWriteFactory *iface)
{
struct dwritefactory *This = impl_from_IDWriteFactory(iface);
TRACE("(%p)\n", This);
return 2;
}
static ULONG WINAPI shareddwritefactory_Release(IDWriteFactory *iface)
{
struct dwritefactory *This = impl_from_IDWriteFactory(iface);
TRACE("(%p)\n", This);
return 1;
}
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
};
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;
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 *This; struct dwritefactory *factory;
HRESULT hr;
TRACE("(%d, %s, %p)\n", type, debugstr_guid(riid), factory); TRACE("(%d, %s, %p)\n", type, debugstr_guid(riid), ret);
*ret = NULL;
if (!IsEqualIID(riid, &IID_IDWriteFactory)) return E_FAIL; if (!IsEqualIID(riid, &IID_IDWriteFactory)) return E_FAIL;
This = heap_alloc(sizeof(struct dwritefactory)); if (type == DWRITE_FACTORY_TYPE_SHARED && shared_factory) {
if (!This) return E_OUTOFMEMORY; *ret = (IUnknown*)shared_factory;
IDWriteFactory_AddRef(shared_factory);
return S_OK;
}
This->IDWriteFactory_iface.lpVtbl = &dwritefactoryvtbl; factory = heap_alloc(sizeof(struct dwritefactory));
This->ref = 1; if (!factory) return E_OUTOFMEMORY;
This->localfontfileloader = NULL;
This->loader_count = 2; hr = init_dwritefactory(factory, type == DWRITE_FACTORY_TYPE_SHARED ? &shareddwritefactoryvtbl : &dwritefactoryvtbl);
This->loaders = heap_alloc_zero(sizeof(*This->loaders) * 2); if (FAILED(hr)) {
This->file_loader_count = 2; heap_free(factory);
This->file_loaders = heap_alloc_zero(sizeof(*This->file_loaders) * 2); return hr;
This->system_collection = NULL; }
*factory = (IUnknown*)&This->IDWriteFactory_iface; 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; return S_OK;
} }
...@@ -31,9 +31,10 @@ ...@@ -31,9 +31,10 @@
#define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__) #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
static void _expect_ref(IUnknown* obj, ULONG ref, int line) static void _expect_ref(IUnknown* obj, ULONG ref, int line)
{ {
ULONG rc = IUnknown_AddRef(obj); ULONG rc;
IUnknown_Release(obj); IUnknown_AddRef(obj);
ok_(__FILE__,line)(rc-1 == ref, "expected refcount %d, got %d\n", ref, rc-1); rc = IUnknown_Release(obj);
ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
} }
static IDWriteFactory *factory; static IDWriteFactory *factory;
...@@ -974,7 +975,7 @@ static void test_FontLoader(void) ...@@ -974,7 +975,7 @@ static void test_FontLoader(void)
hr = IDWriteFactory_CreateCustomFontFileReference(factory, &font, sizeof(HRSRC), &rloader, &ffile); hr = IDWriteFactory_CreateCustomFontFileReference(factory, &font, sizeof(HRSRC), &rloader, &ffile);
ok(hr == S_OK, "got 0x%08x\n", hr); 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(hr == S_OK, "got 0x%08x\n", hr);
ok(support == TRUE, "got %i\n", support); ok(support == TRUE, "got %i\n", support);
ok(type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", type); ok(type == DWRITE_FONT_FILE_TYPE_TRUETYPE, "got %i\n", type);
...@@ -1045,6 +1046,51 @@ static void test_CreateFontFileReference(void) ...@@ -1045,6 +1046,51 @@ static void test_CreateFontFileReference(void)
DeleteFileW(font_name); 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) START_TEST(font)
{ {
HRESULT hr; HRESULT hr;
...@@ -1068,6 +1114,7 @@ START_TEST(font) ...@@ -1068,6 +1114,7 @@ START_TEST(font)
test_CustomFontCollection(); test_CustomFontCollection();
test_FontLoader(); test_FontLoader();
test_CreateFontFileReference(); test_CreateFontFileReference();
test_shared_isolated();
IDWriteFactory_Release(factory); IDWriteFactory_Release(factory);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment