From: Nikolay Sivov Subject: [PATCH 1/3] dwrite: Store factory pointer gdiinterop was created from Message-Id: <544496AC.3040603@codeweavers.com> Date: Mon, 20 Oct 2014 08:59:24 +0400 --- From 729cf74093ca56b340caa5606a8c2d0a8bcd8812 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Sun, 19 Oct 2014 23:57:53 +0400 Subject: [PATCH 1/3] dwrite: Store factory pointer gdiinterop was created from --- dlls/dwrite/dwrite_private.h | 3 +- dlls/dwrite/gdiinterop.c | 31 +++++----- dlls/dwrite/main.c | 19 +++++- dlls/dwrite/tests/font.c | 143 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 176 insertions(+), 20 deletions(-) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 88ca127..64c2be1 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -97,7 +97,8 @@ extern HRESULT create_textformat(const WCHAR*,IDWriteFontCollection*,DWRITE_FONT extern HRESULT create_textlayout(const WCHAR*,UINT32,IDWriteTextFormat*,FLOAT,FLOAT,IDWriteTextLayout**) DECLSPEC_HIDDEN; extern HRESULT create_trimmingsign(IDWriteInlineObject**) DECLSPEC_HIDDEN; extern HRESULT create_typography(IDWriteTypography**) DECLSPEC_HIDDEN; -extern HRESULT get_gdiinterop(IDWriteGdiInterop**) DECLSPEC_HIDDEN; +extern HRESULT create_gdiinterop(IDWriteFactory*,IDWriteGdiInterop**) DECLSPEC_HIDDEN; +extern void release_gdiinterop(IDWriteGdiInterop*) DECLSPEC_HIDDEN; extern HRESULT create_localizedstrings(IDWriteLocalizedStrings**) DECLSPEC_HIDDEN; extern HRESULT add_localizedstring(IDWriteLocalizedStrings*,const WCHAR*,const WCHAR*) DECLSPEC_HIDDEN; extern HRESULT clone_localizedstring(IDWriteLocalizedStrings *iface, IDWriteLocalizedStrings **strings) DECLSPEC_HIDDEN; diff --git a/dlls/dwrite/gdiinterop.c b/dlls/dwrite/gdiinterop.c index c3c2b11..9c3d61e 100644 --- a/dlls/dwrite/gdiinterop.c +++ b/dlls/dwrite/gdiinterop.c @@ -33,7 +33,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dwrite); struct gdiinterop { IDWriteGdiInterop IDWriteGdiInterop_iface; - LONG ref; + IDWriteFactory *factory; }; struct rendertarget { @@ -241,7 +241,8 @@ static HRESULT WINAPI gdiinterop_QueryInterface(IDWriteGdiInterop *iface, REFIID TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); - if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDWriteGdiInterop)) + if (IsEqualIID(riid, &IID_IDWriteGdiInterop) || + IsEqualIID(riid, &IID_IUnknown)) { *obj = iface; IDWriteGdiInterop_AddRef(iface); @@ -255,23 +256,15 @@ static HRESULT WINAPI gdiinterop_QueryInterface(IDWriteGdiInterop *iface, REFIID static ULONG WINAPI gdiinterop_AddRef(IDWriteGdiInterop *iface) { struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface); - ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p)->(%d)\n", This, ref); - return ref; + TRACE("(%p)\n", This); + return IDWriteFactory_AddRef(This->factory); } static ULONG WINAPI gdiinterop_Release(IDWriteGdiInterop *iface) { struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface); - ULONG ref = InterlockedDecrement(&This->ref); - - TRACE("(%p)->(%d)\n", This, ref); - - if (!ref) - { - heap_free(This); - } - return ref; + TRACE("(%p)\n", This); + return IDWriteFactory_Release(This->factory); } static HRESULT WINAPI gdiinterop_CreateFontFromLOGFONT(IDWriteGdiInterop *iface, @@ -328,7 +321,7 @@ static const struct IDWriteGdiInteropVtbl gdiinteropvtbl = { gdiinterop_CreateBitmapRenderTarget }; -HRESULT get_gdiinterop(IDWriteGdiInterop **ret) +HRESULT create_gdiinterop(IDWriteFactory *factory, IDWriteGdiInterop **ret) { struct gdiinterop *This; @@ -338,8 +331,14 @@ HRESULT get_gdiinterop(IDWriteGdiInterop **ret) if (!This) return E_OUTOFMEMORY; This->IDWriteGdiInterop_iface.lpVtbl = &gdiinteropvtbl; - This->ref = 1; + This->factory = factory; *ret= &This->IDWriteGdiInterop_iface; return S_OK; } + +void release_gdiinterop(IDWriteGdiInterop *iface) +{ + struct gdiinterop *interop = impl_from_IDWriteGdiInterop(iface); + heap_free(interop); +} diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index 50ad539..6ac3852 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -397,6 +397,7 @@ struct dwritefactory { IDWriteLocalFontFileLoader* localfontfileloader; IDWriteFontCollection *system_collection; + IDWriteGdiInterop *gdiinterop; IDWriteFontCollectionLoader **loaders; LONG loader_count; @@ -425,6 +426,8 @@ static void release_dwritefactory(struct dwritefactory *factory) heap_free(factory->file_loaders); if (factory->system_collection) IDWriteFontCollection_Release(factory->system_collection); + if (factory->gdiinterop) + release_gdiinterop(factory->gdiinterop); heap_free(factory); } @@ -727,8 +730,21 @@ static HRESULT WINAPI dwritefactory_CreateTypography(IDWriteFactory *iface, IDWr static HRESULT WINAPI dwritefactory_GetGdiInterop(IDWriteFactory *iface, IDWriteGdiInterop **gdi_interop) { struct dwritefactory *This = impl_from_IDWriteFactory(iface); + TRACE("(%p)->(%p)\n", This, gdi_interop); - return get_gdiinterop(gdi_interop); + + *gdi_interop = NULL; + + if (!This->gdiinterop) { + HRESULT hr = create_gdiinterop(iface, &This->gdiinterop); + if (FAILED(hr)) + return hr; + } + + *gdi_interop = This->gdiinterop; + IDWriteGdiInterop_AddRef(*gdi_interop); + + return S_OK; } static HRESULT WINAPI dwritefactory_CreateTextLayout(IDWriteFactory *iface, WCHAR const* string, @@ -864,6 +880,7 @@ static HRESULT init_dwritefactory(struct dwritefactory *factory, const struct ID factory->file_loader_count = 2; factory->file_loaders = heap_alloc_zero(sizeof(*factory->file_loaders) * 2); factory->system_collection = NULL; + factory->gdiinterop = NULL; if (!factory->loaders || !factory->file_loaders) { heap_free(factory->loaders); diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 3305cdb..e27740a 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -509,15 +509,20 @@ if (0) /* crashes on native */ static void test_GetFontFamily(void) { + IDWriteFontCollection *collection, *collection2; + IDWriteFontCollection *syscoll; IDWriteFontFamily *family, *family2; IDWriteGdiInterop *interop; - IDWriteFont *font; + IDWriteFont *font, *font2; LOGFONTW logfont; HRESULT hr; hr = IDWriteFactory_GetGdiInterop(factory, &interop); EXPECT_HR(hr, S_OK); + hr = IDWriteFactory_GetSystemFontCollection(factory, &syscoll, FALSE); + ok(hr == S_OK, "got 0x%08x\n", hr); + memset(&logfont, 0, sizeof(logfont)); logfont.lfHeight = 12; logfont.lfWidth = 12; @@ -526,7 +531,11 @@ static void test_GetFontFamily(void) lstrcpyW(logfont.lfFaceName, tahomaW); hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font); - EXPECT_HR(hr, S_OK); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font2); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(font2 != font, "got %p, %p\n", font2, font); if (0) /* crashes on native */ hr = IDWriteFont_GetFontFamily(font, NULL); @@ -548,8 +557,32 @@ if (0) /* crashes on native */ EXPECT_HR(hr, E_NOINTERFACE); ok(family2 == NULL, "got %p\n", family2); + hr = IDWriteFont_GetFontFamily(font2, &family2); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(family2 != family, "got %p, %p\n", family2, family); + + collection = NULL; + hr = IDWriteFontFamily_GetFontCollection(family, &collection); +todo_wine + ok(hr == S_OK, "got 0x%08x\n", hr); + + collection2 = NULL; + hr = IDWriteFontFamily_GetFontCollection(family2, &collection2); +todo_wine + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(collection == collection2, "got %p, %p\n", collection, collection2); +todo_wine + ok(collection == syscoll, "got %p, %p\n", collection, syscoll); + + IDWriteFontCollection_Release(syscoll); +if (collection2) + IDWriteFontCollection_Release(collection2); +if (collection) + IDWriteFontCollection_Release(collection); + IDWriteFontFamily_Release(family2); IDWriteFontFamily_Release(family); IDWriteFont_Release(font); + IDWriteFont_Release(font2); IDWriteGdiInterop_Release(interop); } @@ -1276,6 +1309,110 @@ static void test_GetFirstMatchingFont(void) IDWriteFontCollection_Release(collection); } +static void test_GetInformationalStrings(void) +{ + IDWriteLocalizedStrings *strings, *strings2; + IDWriteFontCollection *collection; + IDWriteFontFamily *family; + IDWriteFont *font; + BOOL exists; + HRESULT hr; + + hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font); + ok(hr == S_OK, "got 0x%08x\n", hr); + + exists = TRUE; + strings = (void*)0xdeadbeef; + hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_CID_NAME+1, &strings, &exists); +todo_wine { + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(exists == FALSE, "got %d\n", exists); + ok(strings == NULL, "got %p\n", strings); +} + exists = FALSE; + strings = NULL; + hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &exists); +todo_wine { + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(exists == TRUE, "got %d\n", exists); +} + + exists = TRUE; + strings = NULL; + hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_NONE, &strings, &exists); +todo_wine { + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(exists == FALSE, "got %d\n", exists); +} + + /* strings instance is not reused */ + strings2 = NULL; + hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings2, &exists); +todo_wine { + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(strings2 != strings, "got %p, %p\n", strings2, strings); +} + +if (strings) + IDWriteLocalizedStrings_Release(strings); +if (strings2) + IDWriteLocalizedStrings_Release(strings2); + IDWriteFont_Release(font); + IDWriteFontFamily_Release(family); + IDWriteFontCollection_Release(collection); +} + +static void test_GetGdiInterop(void) +{ + IDWriteGdiInterop *interop, *interop2; + IDWriteFactory *factory2; + IDWriteFont *font; + LOGFONTW logfont; + HRESULT hr; + + interop = NULL; + hr = IDWriteFactory_GetGdiInterop(factory, &interop); + ok(hr == S_OK, "got 0x%08x\n", hr); + + interop2 = NULL; + hr = IDWriteFactory_GetGdiInterop(factory, &interop2); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(interop == interop2, "got %p, %p\n", interop, interop2); + IDWriteGdiInterop_Release(interop2); + + hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory2); + ok(hr == S_OK, "got 0x%08x\n", hr); + + /* each factory gets its own interop */ + interop2 = NULL; + hr = IDWriteFactory_GetGdiInterop(factory2, &interop2); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(interop != interop2, "got %p, %p\n", interop, interop2); + + /* release factory - interop still works */ + IDWriteFactory_Release(factory2); + + memset(&logfont, 0, sizeof(logfont)); + logfont.lfHeight = 12; + logfont.lfWidth = 12; + logfont.lfWeight = FW_NORMAL; + logfont.lfItalic = 1; + lstrcpyW(logfont.lfFaceName, tahomaW); + + hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop2, &logfont, &font); + ok(hr == S_OK, "got 0x%08x\n", hr); + + IDWriteGdiInterop_Release(interop2); + IDWriteGdiInterop_Release(interop); +} + START_TEST(font) { HRESULT hr; @@ -1303,6 +1440,8 @@ START_TEST(font) test_GetUnicodeRanges(); test_GetFontFromFontFace(); test_GetFirstMatchingFont(); + test_GetInformationalStrings(); + test_GetGdiInterop(); IDWriteFactory_Release(factory); } -- 2.1.1