From be5a4656bd299f0b2d42623a8112bdb7eba61f63 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 11 Apr 2017 14:21:32 +0300 Subject: [PATCH] dwrite: Improve font objects refcounting. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/dwrite/dwrite_private.h | 15 +- dlls/dwrite/font.c | 186 +++++++------ dlls/dwrite/gdiinterop.c | 40 ++- dlls/dwrite/main.c | 79 ++++-- dlls/dwrite/tests/font.c | 512 +++++++++++++++++++++++++++++------ 5 files changed, 617 insertions(+), 215 deletions(-) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 4eed73c1f0e..886beb7c579 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -118,12 +118,6 @@ static inline BOOL is_simulation_valid(DWRITE_FONT_SIMULATIONS simulations) DWRITE_FONT_SIMULATIONS_OBLIQUE)) == 0; } -struct gdiinterop -{ - IDWriteGdiInterop1 IDWriteGdiInterop1_iface; - IDWriteFactory4 *factory; -}; - struct textlayout_desc { IDWriteFactory4 *factory; @@ -169,7 +163,6 @@ extern HRESULT create_textformat(const WCHAR*,IDWriteFontCollection*,DWRITE_FONT extern HRESULT create_textlayout(const struct textlayout_desc*,IDWriteTextLayout**) DECLSPEC_HIDDEN; extern HRESULT create_trimmingsign(IDWriteFactory4*,IDWriteTextFormat*,IDWriteInlineObject**) DECLSPEC_HIDDEN; extern HRESULT create_typography(IDWriteTypography**) DECLSPEC_HIDDEN; -extern void gdiinterop_init(struct gdiinterop*,IDWriteFactory4*) 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; @@ -179,7 +172,7 @@ extern HRESULT get_eudc_fontcollection(IDWriteFactory4*,IDWriteFontCollection**) extern HRESULT get_textanalyzer(IDWriteTextAnalyzer**) DECLSPEC_HIDDEN; extern HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file) DECLSPEC_HIDDEN; extern HRESULT create_localfontfileloader(IDWriteLocalFontFileLoader** iface) DECLSPEC_HIDDEN; -extern HRESULT create_fontface(const struct fontface_desc*,IDWriteFontFace4**) DECLSPEC_HIDDEN; +extern HRESULT create_fontface(const struct fontface_desc*,struct list*,IDWriteFontFace4**) DECLSPEC_HIDDEN; extern HRESULT create_font_collection(IDWriteFactory4*,IDWriteFontFileEnumerator*,BOOL,IDWriteFontCollection1**) DECLSPEC_HIDDEN; extern HRESULT create_glyphrunanalysis(const struct glyphrunanalysis_desc*,IDWriteGlyphRunAnalysis**) DECLSPEC_HIDDEN; extern BOOL is_system_collection(IDWriteFontCollection*) DECLSPEC_HIDDEN; @@ -198,9 +191,13 @@ extern HRESULT create_fontfacereference(IDWriteFactory4*,IDWriteFontFile*,UINT32 IDWriteFontFaceReference**) DECLSPEC_HIDDEN; extern HRESULT factory_get_cached_fontface(IDWriteFactory4*,IDWriteFontFile*const*,UINT32,DWRITE_FONT_SIMULATIONS,IDWriteFontFace**, struct list**) DECLSPEC_HIDDEN; -extern void factory_cache_fontface(struct list*,IDWriteFontFace4*) DECLSPEC_HIDDEN; +extern void factory_detach_fontcollection(IDWriteFactory4*,IDWriteFontCollection1*) DECLSPEC_HIDDEN; +extern void factory_detach_gdiinterop(IDWriteFactory4*,IDWriteGdiInterop1*) DECLSPEC_HIDDEN; +extern struct fontfacecached *factory_cache_fontface(struct list*,IDWriteFontFace4*) DECLSPEC_HIDDEN; +extern void factory_release_cached_fontface(struct fontfacecached*) DECLSPEC_HIDDEN; extern void get_logfont_from_font(IDWriteFont*,LOGFONTW*) DECLSPEC_HIDDEN; extern void get_logfont_from_fontface(IDWriteFontFace*,LOGFONTW*) DECLSPEC_HIDDEN; +extern HRESULT create_gdiinterop(IDWriteFactory4*,IDWriteGdiInterop1**) DECLSPEC_HIDDEN; /* Opentype font table functions */ struct dwrite_font_props { diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 096c7f3fa73..aeebb0d7493 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -83,7 +83,6 @@ struct dwrite_font_data { IDWriteLocalizedStrings *names; /* data needed to create fontface instance */ - IDWriteFactory4 *factory; DWRITE_FONT_FACE_TYPE face_type; IDWriteFontFile *file; UINT32 face_index; @@ -99,15 +98,6 @@ struct dwrite_font_data { BOOL oblique_sim_tested : 1; }; -struct dwrite_fontlist { - IDWriteFontList1 IDWriteFontList1_iface; - LONG ref; - - IDWriteFontFamily1 *family; - struct dwrite_font_data **fonts; - UINT32 font_count; -}; - struct dwrite_fontfamily_data { LONG ref; @@ -125,6 +115,7 @@ struct dwrite_fontcollection { IDWriteFontCollection1 IDWriteFontCollection1_iface; LONG ref; + IDWriteFactory4 *factory; struct dwrite_fontfamily_data **family_data; UINT32 family_count; UINT32 family_alloc; @@ -135,18 +126,25 @@ struct dwrite_fontfamily { LONG ref; struct dwrite_fontfamily_data *data; + struct dwrite_fontcollection *collection; +}; - IDWriteFontCollection1 *collection; +struct dwrite_fontlist { + IDWriteFontList1 IDWriteFontList1_iface; + LONG ref; + + struct dwrite_font_data **fonts; + UINT32 font_count; + struct dwrite_fontfamily *family; }; struct dwrite_font { IDWriteFont3 IDWriteFont3_iface; LONG ref; - IDWriteFontFamily1 *family; - DWRITE_FONT_STYLE style; struct dwrite_font_data *data; + struct dwrite_fontfamily *family; }; struct dwrite_fonttable { @@ -223,6 +221,9 @@ struct dwrite_fontface { UINT32 file_count; UINT32 index; + IDWriteFactory4 *factory; + struct fontfacecached *cached; + USHORT simulations; DWRITE_FONT_FACE_TYPE type; DWRITE_FONT_METRICS1 metrics; @@ -418,7 +419,6 @@ static void release_font_data(struct dwrite_font_data *data) IDWriteLocalizedStrings_Release(data->names); IDWriteFontFile_Release(data->file); - IDWriteFactory4_Release(data->factory); heap_free(data->facename); heap_free(data); } @@ -500,6 +500,8 @@ static ULONG WINAPI dwritefontface_Release(IDWriteFontFace4 *iface) heap_free(This->glyphs[i]); freetype_notify_cacheremove(iface); + factory_release_cached_fontface(This->cached); + IDWriteFactory4_Release(This->factory); heap_free(This); } @@ -1355,25 +1357,21 @@ static HRESULT get_fontface_from_font(struct dwrite_font *font, IDWriteFontFace4 *fontface = NULL; - hr = factory_get_cached_fontface(data->factory, &data->file, data->face_index, - font->data->simulations, (IDWriteFontFace**)fontface, &cached_list); - if (hr != S_FALSE) + hr = factory_get_cached_fontface(font->family->collection->factory, &data->file, data->face_index, + font->data->simulations, (IDWriteFontFace **)fontface, &cached_list); + if (hr == S_OK) { + IDWriteFontFace4_AddRef(*fontface); return hr; + } - desc.factory = data->factory; + desc.factory = font->family->collection->factory; desc.face_type = data->face_type; desc.files = &data->file; desc.files_number = 1; desc.index = data->face_index; desc.simulations = data->simulations; desc.font_data = data; - hr = create_fontface(&desc, fontface); - if (FAILED(hr)) - return hr; - - factory_cache_fontface(cached_list, *fontface); - - return S_OK; + return create_fontface(&desc, cached_list, fontface); } static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont3 *iface, REFIID riid, void **obj) @@ -1413,7 +1411,7 @@ static ULONG WINAPI dwritefont_Release(IDWriteFont3 *iface) TRACE("(%p)->(%d)\n", This, ref); if (!ref) { - IDWriteFontFamily1_Release(This->family); + IDWriteFontFamily1_Release(&This->family->IDWriteFontFamily1_iface); release_font_data(This->data); heap_free(This); } @@ -1457,6 +1455,7 @@ static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont3 *iface) struct dwrite_font *This = impl_from_IDWriteFont3(iface); IDWriteFontFace4 *fontface; HRESULT hr; + BOOL ret; TRACE("(%p)\n", This); @@ -1464,7 +1463,9 @@ static BOOL WINAPI dwritefont_IsSymbolFont(IDWriteFont3 *iface) if (FAILED(hr)) return FALSE; - return IDWriteFontFace4_IsSymbolFont(fontface); + ret = IDWriteFontFace4_IsSymbolFont(fontface); + IDWriteFontFace4_Release(fontface); + return ret; } static HRESULT WINAPI dwritefont_GetFaceNames(IDWriteFont3 *iface, IDWriteLocalizedStrings **names) @@ -1507,10 +1508,11 @@ static HRESULT WINAPI dwritefont_GetInformationalStrings(IDWriteFont3 *iface, if (table_exists) { hr = opentype_get_font_info_strings(table_data, stringid, &data->info_strings[stringid]); + IDWriteFontFace4_ReleaseFontTable(fontface, context); if (FAILED(hr) || !data->info_strings[stringid]) return hr; - IDWriteFontFace4_ReleaseFontTable(fontface, context); } + IDWriteFontFace4_Release(fontface); } hr = clone_localizedstring(data->info_strings[stringid], strings); @@ -1555,6 +1557,7 @@ static HRESULT WINAPI dwritefont_HasCharacter(IDWriteFont3 *iface, UINT32 value, hr = IDWriteFontFace4_GetGlyphIndices(fontface, &value, 1, &index); if (FAILED(hr)) return hr; + IDWriteFontFace4_Release(fontface); *exists = index != 0; return S_OK; @@ -1593,7 +1596,9 @@ static HRESULT WINAPI dwritefont1_GetUnicodeRanges(IDWriteFont3 *iface, UINT32 m if (FAILED(hr)) return hr; - return IDWriteFontFace4_GetUnicodeRanges(fontface, max_count, ranges, count); + hr = IDWriteFontFace4_GetUnicodeRanges(fontface, max_count, ranges, count); + IDWriteFontFace4_Release(fontface); + return hr; } static BOOL WINAPI dwritefont1_IsMonospacedFont(IDWriteFont3 *iface) @@ -1601,6 +1606,7 @@ static BOOL WINAPI dwritefont1_IsMonospacedFont(IDWriteFont3 *iface) struct dwrite_font *This = impl_from_IDWriteFont3(iface); IDWriteFontFace4 *fontface; HRESULT hr; + BOOL ret; TRACE("(%p)\n", This); @@ -1608,7 +1614,9 @@ static BOOL WINAPI dwritefont1_IsMonospacedFont(IDWriteFont3 *iface) if (FAILED(hr)) return FALSE; - return IDWriteFontFace4_IsMonospacedFont(fontface); + ret = IDWriteFontFace4_IsMonospacedFont(fontface); + IDWriteFontFace4_Release(fontface); + return ret; } static BOOL WINAPI dwritefont2_IsColorFont(IDWriteFont3 *iface) @@ -1616,6 +1624,7 @@ static BOOL WINAPI dwritefont2_IsColorFont(IDWriteFont3 *iface) struct dwrite_font *This = impl_from_IDWriteFont3(iface); IDWriteFontFace4 *fontface; HRESULT hr; + BOOL ret; TRACE("(%p)\n", This); @@ -1623,21 +1632,18 @@ static BOOL WINAPI dwritefont2_IsColorFont(IDWriteFont3 *iface) if (FAILED(hr)) return FALSE; - return IDWriteFontFace4_IsColorFont(fontface); + ret = IDWriteFontFace4_IsColorFont(fontface); + IDWriteFontFace4_Release(fontface); + return ret; } static HRESULT WINAPI dwritefont3_CreateFontFace(IDWriteFont3 *iface, IDWriteFontFace3 **fontface) { struct dwrite_font *This = impl_from_IDWriteFont3(iface); - HRESULT hr; TRACE("(%p)->(%p)\n", This, fontface); - hr = get_fontface_from_font(This, (IDWriteFontFace4**)fontface); - if (hr == S_OK) - IDWriteFontFace3_AddRef(*fontface); - - return hr; + return get_fontface_from_font(This, (IDWriteFontFace4 **)fontface); } static BOOL WINAPI dwritefont3_Equals(IDWriteFont3 *iface, IDWriteFont *font) @@ -1653,8 +1659,8 @@ static HRESULT WINAPI dwritefont3_GetFontFaceReference(IDWriteFont3 *iface, IDWr TRACE("(%p)->(%p)\n", This, reference); - return IDWriteFactory4_CreateFontFaceReference_(This->data->factory, This->data->file, This->data->face_index, - This->data->simulations, reference); + return IDWriteFactory4_CreateFontFaceReference_(This->family->collection->factory, This->data->file, + This->data->face_index, This->data->simulations, reference); } static BOOL WINAPI dwritefont3_HasCharacter(IDWriteFont3 *iface, UINT32 ch) @@ -1731,18 +1737,20 @@ void get_logfont_from_fontface(IDWriteFontFace *iface, LOGFONTW *lf) *lf = fontface->lf; } -static HRESULT create_font(struct dwrite_font_data *data, IDWriteFontFamily1 *family, IDWriteFont3 **font) +static HRESULT create_font(struct dwrite_font_data *data, struct dwrite_fontfamily *family, IDWriteFont3 **font) { struct dwrite_font *This; + *font = NULL; - This = heap_alloc(sizeof(struct dwrite_font)); - if (!This) return E_OUTOFMEMORY; + This = heap_alloc(sizeof(*This)); + if (!This) + return E_OUTOFMEMORY; This->IDWriteFont3_iface.lpVtbl = &dwritefontvtbl; This->ref = 1; This->family = family; - IDWriteFontFamily1_AddRef(family); + IDWriteFontFamily1_AddRef(&family->IDWriteFontFamily1_iface); This->style = data->style; This->data = data; InterlockedIncrement(&This->data->ref); @@ -1792,7 +1800,7 @@ static ULONG WINAPI dwritefontlist_Release(IDWriteFontList1 *iface) for (i = 0; i < This->font_count; i++) release_font_data(This->fonts[i]); - IDWriteFontFamily1_Release(This->family); + IDWriteFontFamily1_Release(&This->family->IDWriteFontFamily1_iface); heap_free(This->fonts); heap_free(This); } @@ -1803,7 +1811,7 @@ static ULONG WINAPI dwritefontlist_Release(IDWriteFontList1 *iface) static HRESULT WINAPI dwritefontlist_GetFontCollection(IDWriteFontList1 *iface, IDWriteFontCollection **collection) { struct dwrite_fontlist *This = impl_from_IDWriteFontList1(iface); - return IDWriteFontFamily1_GetFontCollection(This->family, collection); + return IDWriteFontFamily1_GetFontCollection(&This->family->IDWriteFontFamily1_iface, collection); } static UINT32 WINAPI dwritefontlist_GetFontCount(IDWriteFontList1 *iface) @@ -1827,7 +1835,7 @@ static HRESULT WINAPI dwritefontlist_GetFont(IDWriteFontList1 *iface, UINT32 ind if (index >= This->font_count) return E_INVALIDARG; - return create_font(This->fonts[index], This->family, (IDWriteFont3**)font); + return create_font(This->fonts[index], This->family, (IDWriteFont3 **)font); } static DWRITE_LOCALITY WINAPI dwritefontlist1_GetFontLocality(IDWriteFontList1 *iface, UINT32 index) @@ -1926,7 +1934,7 @@ static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily1 *iface) if (!ref) { - IDWriteFontCollection1_Release(This->collection); + IDWriteFontCollection1_Release(&This->collection->IDWriteFontCollection1_iface); release_fontfamily_data(This->data); heap_free(This); } @@ -1966,7 +1974,7 @@ static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily1 *iface, UINT32 if (index >= This->data->font_count) return E_INVALIDARG; - return create_font(This->data->fonts[index], iface, (IDWriteFont3**)font); + return create_font(This->data->fonts[index], This, (IDWriteFont3 **)font); } static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily1 *iface, IDWriteLocalizedStrings **names) @@ -2039,7 +2047,7 @@ static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily1 * match = This->data->fonts[i]; } - return create_font(match, iface, (IDWriteFont3**)font); + return create_font(match, This, (IDWriteFont3 **)font); } typedef BOOL (*matching_filter_func)(const struct dwrite_font_data*); @@ -2102,8 +2110,8 @@ static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily1 *ifac fonts->IDWriteFontList1_iface.lpVtbl = &dwritefontlistvtbl; fonts->ref = 1; - fonts->family = iface; - IDWriteFontFamily1_AddRef(fonts->family); + fonts->family = This; + IDWriteFontFamily1_AddRef(&fonts->family->IDWriteFontFamily1_iface); fonts->font_count = 0; /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */ @@ -2155,7 +2163,7 @@ static HRESULT WINAPI dwritefontfamily1_GetFont(IDWriteFontFamily1 *iface, UINT3 if (index >= This->data->font_count) return E_FAIL; - return create_font(This->data->fonts[index], iface, font); + return create_font(This->data->fonts[index], This, font); } static HRESULT WINAPI dwritefontfamily1_GetFontFaceReference(IDWriteFontFamily1 *iface, UINT32 index, @@ -2194,7 +2202,8 @@ static const IDWriteFontFamily1Vtbl fontfamilyvtbl = { dwritefontfamily1_GetFontFaceReference }; -static HRESULT create_fontfamily(struct dwrite_fontfamily_data *data, IDWriteFontCollection1 *collection, IDWriteFontFamily1 **family) +static HRESULT create_fontfamily(struct dwrite_fontfamily_data *data, struct dwrite_fontcollection *collection, + IDWriteFontFamily1 **family) { struct dwrite_fontfamily *This; @@ -2206,7 +2215,7 @@ static HRESULT create_fontfamily(struct dwrite_fontfamily_data *data, IDWriteFon This->IDWriteFontFamily1_iface.lpVtbl = &fontfamilyvtbl; This->ref = 1; This->collection = collection; - IDWriteFontCollection1_AddRef(collection); + IDWriteFontCollection1_AddRef(&collection->IDWriteFontCollection1_iface); This->data = data; InterlockedIncrement(&This->data->ref); @@ -2272,12 +2281,15 @@ static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection1 *iface) static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection1 *iface) { - unsigned int i; struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection1(iface); ULONG ref = InterlockedDecrement(&This->ref); + TRACE("(%p)->(%d)\n", This, ref); if (!ref) { + int i; + + factory_detach_fontcollection(This->factory, iface); for (i = 0; i < This->family_count; i++) release_fontfamily_data(This->family_data[i]); heap_free(This->family_data); @@ -2305,7 +2317,7 @@ static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection1 return E_FAIL; } - return create_fontfamily(This->family_data[index], iface, (IDWriteFontFamily1**)family); + return create_fontfamily(This->family_data[index], This, (IDWriteFontFamily1 **)family); } static UINT32 collection_find_family(struct dwrite_fontcollection *collection, const WCHAR *name) @@ -2399,11 +2411,11 @@ static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollec if (!found_font) return DWRITE_E_NOFONT; - hr = create_fontfamily(found_family, iface, &family); + hr = create_fontfamily(found_family, This, &family); if (FAILED(hr)) return hr; - hr = create_font(found_font, family, (IDWriteFont3**)font); + hr = create_font(found_font, impl_from_IDWriteFontFamily1(family), (IDWriteFont3 **)font); IDWriteFontFamily1_Release(family); return hr; } @@ -2428,7 +2440,7 @@ static HRESULT WINAPI dwritefontcollection1_GetFontFamily(IDWriteFontCollection1 return E_FAIL; } - return create_fontfamily(This->family_data[index], iface, family); + return create_fontfamily(This->family_data[index], This, family); } static const IDWriteFontCollection1Vtbl fontcollectionvtbl = { @@ -2495,9 +2507,7 @@ static HRESULT fontcollection_add_family(struct dwrite_fontcollection *collectio collection->family_data = new_list; } - collection->family_data[collection->family_count] = family; - collection->family_count++; - + collection->family_data[collection->family_count++] = family; return S_OK; } @@ -3272,7 +3282,6 @@ static HRESULT init_font_data(const struct fontface_desc *desc, IDWriteLocalized } data->ref = 1; - data->factory = desc->factory; data->file = desc->files[0]; data->face_index = desc->index; data->face_type = desc->face_type; @@ -3280,7 +3289,6 @@ static HRESULT init_font_data(const struct fontface_desc *desc, IDWriteLocalized data->bold_sim_tested = 0; data->oblique_sim_tested = 0; IDWriteFontFile_AddRef(data->file); - IDWriteFactory4_AddRef(data->factory); stream_desc.stream = stream; stream_desc.face_type = desc->face_type; @@ -3317,12 +3325,13 @@ static HRESULT init_font_data(const struct fontface_desc *desc, IDWriteLocalized return S_OK; } -static HRESULT init_font_data_from_font(const struct dwrite_font_data *src, DWRITE_FONT_SIMULATIONS sim, const WCHAR *facenameW, - struct dwrite_font_data **ret) +static HRESULT init_font_data_from_font(const struct dwrite_font_data *src, DWRITE_FONT_SIMULATIONS sim, + const WCHAR *facenameW, struct dwrite_font_data **ret) { struct dwrite_font_data *data; *ret = NULL; + data = heap_alloc_zero(sizeof(*data)); if (!data) return E_OUTOFMEMORY; @@ -3336,7 +3345,6 @@ static HRESULT init_font_data_from_font(const struct dwrite_font_data *src, DWRI data->style = DWRITE_FONT_STYLE_OBLIQUE; memset(data->info_strings, 0, sizeof(data->info_strings)); data->names = NULL; - IDWriteFactory4_AddRef(data->factory); IDWriteFontFile_AddRef(data->file); create_localizedstrings(&data->names); @@ -3738,6 +3746,9 @@ HRESULT create_font_collection(IDWriteFactory4 *factory, IDWriteFontFileEnumerat if (is_system) fontcollection_add_replacements(collection); + collection->factory = factory; + IDWriteFactory4_AddRef(factory); + return hr; } @@ -3749,6 +3760,9 @@ struct system_fontfile_enumerator IDWriteFactory4 *factory; HKEY hkey; int index; + + WCHAR *value; + DWORD max_val_count; }; static inline struct system_fontfile_enumerator *impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator* iface) @@ -3783,6 +3797,7 @@ static ULONG WINAPI systemfontfileenumerator_Release(IDWriteFontFileEnumerator * if (!ref) { IDWriteFactory4_Release(enumerator->factory); RegCloseKey(enumerator->hkey); + heap_free(enumerator->value); heap_free(enumerator); } @@ -3852,29 +3867,30 @@ static HRESULT WINAPI systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFil static HRESULT WINAPI systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator *iface, BOOL *current) { struct system_fontfile_enumerator *enumerator = impl_from_IDWriteFontFileEnumerator(iface); - DWORD ret, max_val_count; - WCHAR *value; *current = FALSE; enumerator->index++; - ret = RegQueryInfoKeyW(enumerator->hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &max_val_count, NULL, NULL, NULL); - if (ret != ERROR_SUCCESS) - return E_FAIL; + if (!enumerator->value) { + if (RegQueryInfoKeyW(enumerator->hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + &enumerator->max_val_count, NULL, NULL, NULL)) + return E_FAIL; - max_val_count++; - if (!(value = heap_alloc( max_val_count * sizeof(value[0]) ))) - return E_OUTOFMEMORY; + enumerator->max_val_count++; + if (!(enumerator->value = heap_alloc(enumerator->max_val_count * sizeof(*enumerator->value)))) + return E_OUTOFMEMORY; + } /* iterate until we find next string value */ - while (1) { + for (;;) { DWORD type = 0, count, val_count; - val_count = max_val_count; - value[0] = 0; - if (RegEnumValueW(enumerator->hkey, enumerator->index, value, &val_count, NULL, &type, NULL, &count)) + val_count = enumerator->max_val_count; + *enumerator->value = 0; + if (RegEnumValueW(enumerator->hkey, enumerator->index, enumerator->value, &val_count, + NULL, &type, NULL, &count)) break; - if (type == REG_SZ && *value && *value != '@') { + if (type == REG_SZ && *enumerator->value && *enumerator->value != '@') { *current = TRUE; break; } @@ -3882,7 +3898,6 @@ static HRESULT WINAPI systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerato } TRACE("index = %d, current = %d\n", enumerator->index, *current); - heap_free(value); return S_OK; } @@ -3914,6 +3929,8 @@ static HRESULT create_system_fontfile_enumerator(IDWriteFactory4 *factory, IDWri enumerator->ref = 1; enumerator->factory = factory; enumerator->index = -1; + enumerator->value = NULL; + enumerator->max_val_count = 0; IDWriteFactory4_AddRef(factory); if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, fontslistW, 0, GENERIC_READ, &enumerator->hkey)) { @@ -4238,7 +4255,7 @@ static HRESULT get_stream_from_file(IDWriteFontFile *file, IDWriteFontFileStream return hr; } -HRESULT create_fontface(const struct fontface_desc *desc, IDWriteFontFace4 **ret) +HRESULT create_fontface(const struct fontface_desc *desc, struct list *cached_list, IDWriteFontFace4 **ret) { struct file_stream_desc stream_desc; struct dwrite_fontface *fontface; @@ -4346,6 +4363,9 @@ HRESULT create_fontface(const struct fontface_desc *desc, IDWriteFontFace4 **ret release_font_data(data); } + fontface->cached = factory_cache_fontface(cached_list, &fontface->IDWriteFontFace4_iface); + IDWriteFactory4_AddRef(fontface->factory = desc->factory); + *ret = &fontface->IDWriteFontFace4_iface; return S_OK; } @@ -5627,7 +5647,7 @@ static HRESULT WINAPI fontfacereference_CreateFontFaceWithSimulations(IDWriteFon hr = IDWriteFactory4_CreateFontFace(This->factory, face_type, 1, &This->file, This->index, simulations, &fontface); if (SUCCEEDED(hr)) { - hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace4, (void**)ret); + hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace3, (void **)ret); IDWriteFontFace_Release(fontface); } diff --git a/dlls/dwrite/gdiinterop.c b/dlls/dwrite/gdiinterop.c index 67fc4a0f68d..cf3b3fa10c6 100644 --- a/dlls/dwrite/gdiinterop.c +++ b/dlls/dwrite/gdiinterop.c @@ -52,6 +52,12 @@ struct rendertarget { struct dib_data dib; }; +struct gdiinterop { + IDWriteGdiInterop1 IDWriteGdiInterop1_iface; + LONG ref; + IDWriteFactory4 *factory; +}; + static inline int get_dib_stride(int width, int bpp) { return ((width * bpp + 31) >> 3) & ~3; @@ -598,15 +604,24 @@ static HRESULT WINAPI gdiinterop_QueryInterface(IDWriteGdiInterop1 *iface, REFII static ULONG WINAPI gdiinterop_AddRef(IDWriteGdiInterop1 *iface) { struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface); - TRACE("(%p)\n", This); - return IDWriteFactory4_AddRef(This->factory); + LONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p)->(%d)\n", This, ref); + return ref; } static ULONG WINAPI gdiinterop_Release(IDWriteGdiInterop1 *iface) { struct gdiinterop *This = impl_from_IDWriteGdiInterop1(iface); - TRACE("(%p)\n", This); - return IDWriteFactory4_Release(This->factory); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(%d)\n", This, ref); + + if (!ref) { + factory_detach_gdiinterop(This->factory, iface); + heap_free(This); + } + + return ref; } static HRESULT WINAPI gdiinterop_CreateFontFromLOGFONT(IDWriteGdiInterop1 *iface, @@ -890,10 +905,19 @@ static const struct IDWriteGdiInterop1Vtbl gdiinteropvtbl = { gdiinterop1_GetMatchingFontsByLOGFONT }; -void gdiinterop_init(struct gdiinterop *interop, IDWriteFactory4 *factory) +HRESULT create_gdiinterop(IDWriteFactory4 *factory, IDWriteGdiInterop1 **ret) { + struct gdiinterop *interop; + + *ret = NULL; + + if (!(interop = heap_alloc(sizeof(*interop)))) + return E_OUTOFMEMORY; + interop->IDWriteGdiInterop1_iface.lpVtbl = &gdiinteropvtbl; - /* Interop is a part of a factory, sharing its refcount. - GetGdiInterop() will AddRef() on every call. */ - interop->factory = factory; + interop->ref = 1; + IDWriteFactory4_AddRef(interop->factory = factory); + + *ret = &interop->IDWriteGdiInterop1_iface; + return S_OK; } diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index 067bc8a3ce0..c17bb5a3a7a 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -538,7 +538,7 @@ struct dwritefactory { IDWriteFontCollection1 *system_collection; IDWriteFontCollection *eudc_collection; - struct gdiinterop interop; + IDWriteGdiInterop1 *gdiinterop; IDWriteFontFallback *fallback; IDWriteLocalFontFileLoader* localfontfileloader; @@ -556,9 +556,9 @@ static inline struct dwritefactory *impl_from_IDWriteFactory4(IDWriteFactory4 *i static void release_fontface_cache(struct list *fontfaces) { struct fontfacecached *fontface, *fontface2; + LIST_FOR_EACH_ENTRY_SAFE(fontface, fontface2, fontfaces, struct fontfacecached, entry) { list_remove(&fontface->entry); - IDWriteFontFace4_Release(fontface->fontface); heap_free(fontface); } } @@ -875,36 +875,44 @@ HRESULT factory_get_cached_fontface(IDWriteFactory4 *iface, IDWriteFontFile * co return S_FALSE; } -void factory_cache_fontface(struct list *fontfaces, IDWriteFontFace4 *fontface) +struct fontfacecached *factory_cache_fontface(struct list *fontfaces, IDWriteFontFace4 *fontface) { struct fontfacecached *cached; /* new cache entry */ cached = heap_alloc(sizeof(*cached)); if (!cached) - return; + return NULL; cached->fontface = fontface; list_add_tail(fontfaces, &cached->entry); + + return cached; } -static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory4 *iface, - DWRITE_FONT_FACE_TYPE req_facetype, UINT32 files_number, IDWriteFontFile* const* font_files, - UINT32 index, DWRITE_FONT_SIMULATIONS simulations, IDWriteFontFace **font_face) +void factory_release_cached_fontface(struct fontfacecached *cached) +{ + list_remove(&cached->entry); + heap_free(cached); +} + +static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory4 *iface, DWRITE_FONT_FACE_TYPE req_facetype, + UINT32 files_number, IDWriteFontFile* const* font_files, UINT32 index, DWRITE_FONT_SIMULATIONS simulations, + IDWriteFontFace **fontface) { struct dwritefactory *This = impl_from_IDWriteFactory4(iface); DWRITE_FONT_FILE_TYPE file_type; DWRITE_FONT_FACE_TYPE face_type; struct fontface_desc desc; struct list *fontfaces; - IDWriteFontFace4 *face; BOOL is_supported; UINT32 count; HRESULT hr; - TRACE("(%p)->(%d %u %p %u 0x%x %p)\n", This, req_facetype, files_number, font_files, index, simulations, font_face); + TRACE("(%p)->(%d %u %p %u 0x%x %p)\n", This, req_facetype, files_number, font_files, index, + simulations, fontface); - *font_face = NULL; + *fontface = NULL; if (!is_face_type_supported(req_facetype)) return E_INVALIDARG; @@ -928,9 +936,9 @@ static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory4 *iface, if (face_type != req_facetype) return DWRITE_E_FILEFORMAT; - hr = factory_get_cached_fontface(iface, font_files, index, simulations, font_face, &fontfaces); + hr = factory_get_cached_fontface(iface, font_files, index, simulations, fontface, &fontfaces); if (hr == S_OK) - IDWriteFontFace_AddRef(*font_face); + IDWriteFontFace_AddRef(*fontface); if (hr != S_FALSE) return hr; @@ -942,16 +950,7 @@ static HRESULT WINAPI dwritefactory_CreateFontFace(IDWriteFactory4 *iface, desc.index = index; desc.simulations = simulations; desc.font_data = NULL; - hr = create_fontface(&desc, &face); - if (FAILED(hr)) - return hr; - - factory_cache_fontface(fontfaces, face); - - *font_face = (IDWriteFontFace*)face; - IDWriteFontFace_AddRef(*font_face); - - return S_OK; + return create_fontface(&desc, fontfaces, (IDWriteFontFace4 **)fontface); } static HRESULT WINAPI dwritefactory_CreateRenderingParams(IDWriteFactory4 *iface, IDWriteRenderingParams **params) @@ -1083,12 +1082,18 @@ static HRESULT WINAPI dwritefactory_CreateTypography(IDWriteFactory4 *iface, IDW static HRESULT WINAPI dwritefactory_GetGdiInterop(IDWriteFactory4 *iface, IDWriteGdiInterop **gdi_interop) { struct dwritefactory *This = impl_from_IDWriteFactory4(iface); + HRESULT hr = S_OK; TRACE("(%p)->(%p)\n", This, gdi_interop); - *gdi_interop = (IDWriteGdiInterop*)&This->interop.IDWriteGdiInterop1_iface; - IDWriteGdiInterop_AddRef(*gdi_interop); - return S_OK; + if (This->gdiinterop) + IDWriteGdiInterop1_AddRef(This->gdiinterop); + else + hr = create_gdiinterop(iface, &This->gdiinterop); + + *gdi_interop = (IDWriteGdiInterop *)This->gdiinterop; + + return hr; } static HRESULT WINAPI dwritefactory_CreateTextLayout(IDWriteFactory4 *iface, WCHAR const* string, @@ -1407,11 +1412,10 @@ static HRESULT WINAPI dwritefactory3_GetSystemFontCollection(IDWriteFactory4 *if if (check_for_updates) FIXME("checking for system font updates not implemented\n"); - if (!This->system_collection) - hr = get_system_fontcollection(iface, &This->system_collection); - - if (SUCCEEDED(hr)) + if (This->system_collection) IDWriteFontCollection1_AddRef(This->system_collection); + else + hr = get_system_fontcollection(iface, &This->system_collection); *collection = This->system_collection; @@ -1646,7 +1650,7 @@ static void init_dwritefactory(struct dwritefactory *factory, DWRITE_FACTORY_TYP factory->localfontfileloader = NULL; factory->system_collection = NULL; factory->eudc_collection = NULL; - gdiinterop_init(&factory->interop, &factory->IDWriteFactory4_iface); + factory->gdiinterop = NULL; factory->fallback = NULL; list_init(&factory->collection_loaders); @@ -1654,6 +1658,21 @@ static void init_dwritefactory(struct dwritefactory *factory, DWRITE_FACTORY_TYP list_init(&factory->localfontfaces); } +void factory_detach_fontcollection(IDWriteFactory4 *iface, IDWriteFontCollection1 *collection) +{ + struct dwritefactory *factory = impl_from_IDWriteFactory4(iface); + if (factory->system_collection == collection) + factory->system_collection = NULL; + IDWriteFactory4_Release(iface); +} + +void factory_detach_gdiinterop(IDWriteFactory4 *iface, IDWriteGdiInterop1 *interop) +{ + struct dwritefactory *factory = impl_from_IDWriteFactory4(iface); + factory->gdiinterop = NULL; + IDWriteFactory4_Release(iface); +} + HRESULT WINAPI DWriteCreateFactory(DWRITE_FACTORY_TYPE type, REFIID riid, IUnknown **ret) { struct dwritefactory *factory; diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 79aebe3ebe8..8b16d0e4423 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -92,6 +92,15 @@ static void _expect_ref(IUnknown* obj, ULONG ref, int line) ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc); } +#define EXPECT_REF_BROKEN(obj,ref,brokenref) _expect_ref_broken((IUnknown*)obj, ref, brokenref, __LINE__) +static void _expect_ref_broken(IUnknown* obj, ULONG ref, ULONG brokenref, int line) +{ + ULONG rc; + IUnknown_AddRef(obj); + rc = IUnknown_Release(obj); + ok_(__FILE__,line)(rc == ref || broken(rc == brokenref), "expected refcount %d, got %d\n", ref, rc); +} + static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t size) { return HeapAlloc(GetProcessHeap(), 0, size); @@ -847,13 +856,14 @@ static void test_CreateFontFromLOGFONT(void) HDC hdc; HFONT hfont; BOOL exists; + ULONG ref; int i; UINT r; factory = create_factory(); hr = IDWriteFactory_GetGdiInterop(factory, &interop); - EXPECT_HR(hr, S_OK); + ok(hr == S_OK, "got %#x\n", hr); if (0) /* null out parameter crashes this call */ @@ -940,6 +950,7 @@ static void test_CreateFontFromLOGFONT(void) weight = IDWriteFont_GetWeight(font); ok(weight == DWRITE_FONT_WEIGHT_NORMAL || weight == DWRITE_FONT_WEIGHT_BOLD, "got %d\n", weight); + IDWriteFont_Release(font); /* empty or nonexistent face name */ @@ -996,8 +1007,10 @@ static void test_CreateFontFromLOGFONT(void) else win_skip("IDWriteGdiInterop1 is not supported, skipping CreateFontFromLOGFONT() tests.\n"); - IDWriteGdiInterop_Release(interop); - IDWriteFactory_Release(factory); + ref = IDWriteGdiInterop_Release(interop); + ok(ref == 0, "interop is not released, %u\n", ref); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory is not released, %u\n", ref); } static void test_CreateBitmapRenderTarget(void) @@ -1014,6 +1027,7 @@ static void test_CreateBitmapRenderTarget(void) HRESULT hr; FLOAT pdip; SIZE size; + ULONG ref; HDC hdc; int ret; @@ -1257,9 +1271,12 @@ static void test_CreateBitmapRenderTarget(void) else win_skip("IDWriteBitmapRenderTarget1 is not supported.\n"); - IDWriteBitmapRenderTarget_Release(target); - IDWriteGdiInterop_Release(interop); - IDWriteFactory_Release(factory); + ref = IDWriteBitmapRenderTarget_Release(target); + ok(ref == 0, "render target not released, %u\n", ref); + ref = IDWriteGdiInterop_Release(interop); + ok(ref == 0, "interop not released, %u\n", ref); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_GetFontFamily(void) @@ -1273,6 +1290,7 @@ static void test_GetFontFamily(void) IDWriteFactory *factory; LOGFONTW logfont; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -1386,7 +1404,8 @@ if (0) /* crashes on native */ IDWriteFontFamily_Release(family2); IDWriteFontFamily_Release(family); IDWriteGdiInterop_Release(interop); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_GetFamilyNames(void) @@ -1400,6 +1419,7 @@ static void test_GetFamilyNames(void) WCHAR buffer[100]; HRESULT hr; UINT32 len; + ULONG ref; factory = create_factory(); @@ -1482,7 +1502,8 @@ static void test_GetFamilyNames(void) IDWriteFontFamily_Release(family); IDWriteFont_Release(font); IDWriteGdiInterop_Release(interop); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_CreateFontFace(void) @@ -1826,6 +1847,7 @@ static void test_GetMetrics(void) HRESULT hr; HDC hdc; HFONT hfont; + ULONG ref; int ret; factory = create_factory(); @@ -1991,6 +2013,7 @@ static void test_GetMetrics(void) metrics.strikethroughThickness); IDWriteFontFile_Release(file); + IDWriteFontFace_Release(fontface); IDWriteFont_Release(font); /* test metrics for whole system collection */ @@ -2043,7 +2066,8 @@ static void test_GetMetrics(void) IDWriteFontFamily_Release(family); } IDWriteFontCollection_Release(syscollection); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_system_fontcollection(void) @@ -2058,6 +2082,7 @@ static void test_system_fontcollection(void) IDWriteFontFile *file; IDWriteFont *font; HRESULT hr; + ULONG ref; UINT32 i; BOOL ret; @@ -2131,6 +2156,7 @@ static void test_system_fontcollection(void) hr = IDWriteFontFace_GetFiles(fontface, &i, &file); ok(hr == S_OK, "got 0x%08x\n", hr); ok(file != NULL, "got %p\n", file); + IDWriteFontFace_Release(fontface); hr = IDWriteFontFile_GetLoader(file, &loader); ok(hr == S_OK, "got 0x%08x\n", hr); @@ -2189,8 +2215,10 @@ static void test_system_fontcollection(void) else win_skip("IDWriteFontCollection1 is not supported.\n"); - IDWriteFontCollection_Release(collection); - IDWriteFactory_Release(factory); + ref = IDWriteFontCollection_Release(collection); + ok(ref == 0, "collection not released, %u\n", ref); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void get_logfont_from_font(IDWriteFont *font, LOGFONTW *logfont) @@ -2303,13 +2331,14 @@ static void get_logfont_from_font(IDWriteFont *font, LOGFONTW *logfont) static void test_ConvertFontFaceToLOGFONT(void) { + IDWriteFontCollection *collection; IDWriteGdiInterop *interop; IDWriteFontFace *fontface; IDWriteFactory *factory; LOGFONTW logfont; UINT32 count, i; HRESULT hr; - IDWriteFontCollection *collection; + ULONG ref; factory = create_factory(); @@ -2375,8 +2404,8 @@ if (0) /* crashes on native */ ok(hr == S_OK, "got 0x%08x\n", hr); sim = IDWriteFontFace_GetSimulations(fontface); - get_logfont_from_font(font, &lf); + ok(logfont.lfWeight == lf.lfWeight, "%s: unexpected lfWeight %d, expected lfWeight %d, font weight %d, " "bold simulation %s\n", wine_dbgstr_w(nameW), logfont.lfWeight, lf.lfWeight, IDWriteFont_GetWeight(font), sim & DWRITE_FONT_SIMULATIONS_BOLD ? "yes" : "no"); @@ -2402,7 +2431,8 @@ if (0) /* crashes on native */ IDWriteFontCollection_Release(collection); IDWriteGdiInterop_Release(interop); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static HRESULT WINAPI fontfileenumerator_QueryInterface(IDWriteFontFileEnumerator *iface, REFIID riid, void **obj) @@ -2447,20 +2477,48 @@ static const struct IDWriteFontFileEnumeratorVtbl dwritefontfileenumeratorvtbl = fontfileenumerator_GetCurrentFontFile, }; +struct collection_loader +{ + IDWriteFontCollectionLoader IDWriteFontCollectionLoader_iface; + LONG ref; +}; + +static inline struct collection_loader *impl_from_IDWriteFontCollectionLoader(IDWriteFontCollectionLoader *iface) +{ + return CONTAINING_RECORD(iface, struct collection_loader, IDWriteFontCollectionLoader_iface); +} + static HRESULT WINAPI fontcollectionloader_QueryInterface(IDWriteFontCollectionLoader *iface, REFIID riid, void **obj) { - *obj = iface; - return S_OK; + struct collection_loader *loader = impl_from_IDWriteFontCollectionLoader(iface); + + if (IsEqualIID(&IID_IDWriteFontCollectionLoader, riid) || + IsEqualIID(&IID_IUnknown, riid)) + { + *obj = &loader->IDWriteFontCollectionLoader_iface; + IDWriteFontCollectionLoader_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; } static ULONG WINAPI fontcollectionloader_AddRef(IDWriteFontCollectionLoader *iface) { - return 2; + struct collection_loader *loader = impl_from_IDWriteFontCollectionLoader(iface); + return InterlockedIncrement(&loader->ref); } static ULONG WINAPI fontcollectionloader_Release(IDWriteFontCollectionLoader *iface) { - return 1; + struct collection_loader *loader = impl_from_IDWriteFontCollectionLoader(iface); + ULONG ref = InterlockedDecrement(&loader->ref); + + if (!ref) + heap_free(loader); + + return ref; } static HRESULT WINAPI fontcollectionloader_CreateEnumeratorFromKey(IDWriteFontCollectionLoader *iface, IDWriteFactory *factory, const void *key, @@ -2478,12 +2536,20 @@ static const struct IDWriteFontCollectionLoaderVtbl dwritefontcollectionloadervt fontcollectionloader_CreateEnumeratorFromKey }; +static IDWriteFontCollectionLoader *create_collection_loader(void) +{ + struct collection_loader *loader = heap_alloc(sizeof(*loader)); + + loader->IDWriteFontCollectionLoader_iface.lpVtbl = &dwritefontcollectionloadervtbl; + loader->ref = 1; + + return &loader->IDWriteFontCollectionLoader_iface; +} + static void test_CustomFontCollection(void) { static const WCHAR fontnameW[] = {'w','i','n','e','_','t','e','s','t',0}; - IDWriteFontCollectionLoader collection = { &dwritefontcollectionloadervtbl }; - IDWriteFontCollectionLoader collection2 = { &dwritefontcollectionloadervtbl }; - IDWriteFontCollectionLoader collection3 = { &dwritefontcollectionloadervtbl }; + IDWriteFontCollectionLoader *loader, *loader2, *loader3; IDWriteFontCollection *font_collection = NULL; static IDWriteFontFileLoader rloader = { &resourcefontfileloadervtbl }; struct test_fontcollectionloader resource_collection = { { &resourcecollectionloadervtbl }, &rloader }; @@ -2497,37 +2563,53 @@ static void test_CustomFontCollection(void) BOOL exists; HRESULT hr; HRSRC font; + ULONG ref; factory = create_factory(); + loader = create_collection_loader(); + loader2 = create_collection_loader(); + loader3 = create_collection_loader(); + hr = IDWriteFactory_RegisterFontCollectionLoader(factory, NULL); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, NULL); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); - hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection); + EXPECT_REF(loader, 1); + EXPECT_REF(loader2, 1); + + hr = IDWriteFactory_RegisterFontCollectionLoader(factory, loader); ok(hr == S_OK, "got 0x%08x\n", hr); - hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection2); + hr = IDWriteFactory_RegisterFontCollectionLoader(factory, loader2); ok(hr == S_OK, "got 0x%08x\n", hr); - hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &collection); + hr = IDWriteFactory_RegisterFontCollectionLoader(factory, loader); ok(hr == DWRITE_E_ALREADYREGISTERED, "got 0x%08x\n", hr); + EXPECT_REF(loader, 2); + EXPECT_REF(loader2, 2); + hr = IDWriteFactory_RegisterFontFileLoader(factory, &rloader); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IDWriteFactory_RegisterFontCollectionLoader(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface); ok(hr == S_OK, "got 0x%08x\n", hr); + /* Loader wasn't registered. */ font_collection = (void*)0xdeadbeef; - hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection3, "Billy", 6, &font_collection); + hr = IDWriteFactory_CreateCustomFontCollection(factory, loader3, "Billy", 6, &font_collection); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); ok(font_collection == NULL, "got %p\n", font_collection); - hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection, "Billy", 6, &font_collection); + EXPECT_REF(factory, 1); + hr = IDWriteFactory_CreateCustomFontCollection(factory, loader, "Billy", 6, &font_collection); ok(hr == S_OK, "got 0x%08x\n", hr); +todo_wine + EXPECT_REF(factory, 1); + EXPECT_REF(loader, 2); IDWriteFontCollection_Release(font_collection); - hr = IDWriteFactory_CreateCustomFontCollection(factory, &collection2, "Billy", 6, &font_collection); + hr = IDWriteFactory_CreateCustomFontCollection(factory, loader2, "Billy", 6, &font_collection); ok(hr == S_OK, "got 0x%08x\n", hr); IDWriteFontCollection_Release(font_collection); @@ -2542,6 +2624,7 @@ static void test_CustomFontCollection(void) hr = IDWriteFactory_CreateCustomFontCollection(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface, &font, sizeof(HRSRC), &font_collection); ok(hr == S_OK, "got 0x%08x\n",hr); + EXPECT_REF(font_collection, 1); index = 1; exists = FALSE; @@ -2626,18 +2709,23 @@ static void test_CustomFontCollection(void) IDWriteFontFamily_Release(family); IDWriteFontCollection_Release(font_collection); - hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection); + hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, loader); ok(hr == S_OK, "got 0x%08x\n", hr); - hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection); + hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, loader); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); - hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &collection2); + hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, loader2); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IDWriteFactory_UnregisterFontCollectionLoader(factory, &resource_collection.IDWriteFontFileCollectionLoader_iface); ok(hr == S_OK, "got 0x%08x\n", hr); hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader); ok(hr == S_OK, "got 0x%08x\n", hr); - IDWriteFactory_Release(factory); + IDWriteFontCollectionLoader_Release(loader); + IDWriteFontCollectionLoader_Release(loader2); + IDWriteFontCollectionLoader_Release(loader3); + + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static HRESULT WINAPI fontfileloader_QueryInterface(IDWriteFontFileLoader *iface, REFIID riid, void **obj) @@ -2696,6 +2784,7 @@ static void test_CreateCustomFontFileReference(void) const void *key; UINT32 key_size; WCHAR *path; + ULONG ref; path = create_testfontfile(test_fontfile); @@ -2854,8 +2943,10 @@ if (face2) { hr = IDWriteFactory_UnregisterFontFileLoader(factory, &rloader); ok(hr == S_OK, "got 0x%08x\n", hr); - IDWriteFactory_Release(factory2); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory2); + ok(ref == 0, "factory not released, %u\n", ref); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); DELETE_FONTFILE(path); } @@ -2870,6 +2961,7 @@ static void test_CreateFontFileReference(void) IDWriteFontFace *fface = NULL; IDWriteFactory *factory; WCHAR *path; + ULONG ref; path = create_testfontfile(test_fontfile); factory = create_factory(); @@ -2898,7 +2990,8 @@ static void test_CreateFontFileReference(void) IDWriteFontFace_Release(fface); IDWriteFontFile_Release(ffile); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); DELETE_FONTFILE(path); } @@ -2908,6 +3001,7 @@ static void test_shared_isolated(void) IDWriteFactory *isolated, *isolated2; IDWriteFactory *shared, *shared2; HRESULT hr; + ULONG ref; /* invalid type */ shared = NULL; @@ -2953,8 +3047,10 @@ static void test_shared_isolated(void) 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); + ref = IDWriteFactory_Release(isolated); + ok(ref == 0, "factory not released, %u\n", ref); + ref = IDWriteFactory_Release(isolated2); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_GetUnicodeRanges(void) @@ -2967,6 +3063,7 @@ static void test_GetUnicodeRanges(void) UINT32 count; HRESULT hr; HRSRC font; + ULONG ref; factory = create_factory(); @@ -3021,7 +3118,8 @@ static void test_GetUnicodeRanges(void) ok(hr == S_OK, "got 0x%08x\n", hr); IDWriteFontFace1_Release(fontface1); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_GetFontFromFontFace(void) @@ -3034,6 +3132,7 @@ static void test_GetFontFromFontFace(void) IDWriteFontFile *file; WCHAR *path; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -3093,7 +3192,8 @@ static void test_GetFontFromFontFace(void) IDWriteFont_Release(font2); IDWriteFontFamily_Release(family); IDWriteFontCollection_Release(collection); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); DELETE_FONTFILE(path); } @@ -3105,6 +3205,7 @@ static void test_GetFirstMatchingFont(void) IDWriteFont *font, *font2; IDWriteFactory *factory; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -3147,7 +3248,8 @@ static void test_GetFirstMatchingFont(void) IDWriteFont_Release(font); IDWriteFontCollection_Release(collection); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_GetMatchingFonts(void) @@ -3158,6 +3260,7 @@ static void test_GetMatchingFonts(void) IDWriteFontList *fontlist, *fontlist2; IDWriteFontList1 *fontlist1; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -3234,7 +3337,8 @@ static void test_GetMatchingFonts(void) IDWriteFontFamily_Release(family); IDWriteFontCollection_Release(collection); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_GetInformationalStrings(void) @@ -3246,6 +3350,7 @@ static void test_GetInformationalStrings(void) IDWriteFont *font; BOOL exists; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -3289,7 +3394,8 @@ static void test_GetInformationalStrings(void) IDWriteFont_Release(font); IDWriteFontFamily_Release(family); IDWriteFontCollection_Release(collection); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_GetGdiInterop(void) @@ -3299,6 +3405,7 @@ static void test_GetGdiInterop(void) IDWriteFont *font; LOGFONTW logfont; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -3337,7 +3444,8 @@ static void test_GetGdiInterop(void) IDWriteGdiInterop_Release(interop2); IDWriteGdiInterop_Release(interop); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_CreateFontFaceFromHdc(void) @@ -3348,6 +3456,7 @@ static void test_CreateFontFaceFromHdc(void) HFONT hfont, oldhfont; LOGFONTW logfont; HRESULT hr; + ULONG ref; HDC hdc; factory = create_factory(); @@ -3380,7 +3489,8 @@ static void test_CreateFontFaceFromHdc(void) DeleteDC(hdc); IDWriteGdiInterop_Release(interop); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_GetSimulations(void) @@ -3392,6 +3502,7 @@ static void test_GetSimulations(void) IDWriteFont *font; LOGFONTW logfont; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -3437,7 +3548,8 @@ static void test_GetSimulations(void) IDWriteFont_Release(font); IDWriteGdiInterop_Release(interop); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_GetFaceNames(void) @@ -3454,6 +3566,7 @@ static void test_GetFaceNames(void) WCHAR buffW[255]; BOOL exists; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -3506,7 +3619,8 @@ static void test_GetFaceNames(void) IDWriteFont_Release(font); IDWriteGdiInterop_Release(interop); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } struct local_refkey @@ -3531,6 +3645,7 @@ static void test_TryGetFontTable(void) UINT32 size, len; WCHAR *path; HRESULT hr; + ULONG ref; path = create_testfontfile(test_fontfile); @@ -3596,7 +3711,8 @@ static void test_TryGetFontTable(void) IDWriteFontFace_Release(fontface); IDWriteFontFile_Release(file); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); DELETE_FONTFILE(path); } @@ -3611,6 +3727,7 @@ static void test_ConvertFontToLOGFONT(void) UINT32 i, count; BOOL system; HRESULT hr; + ULONG ref; factory = create_factory(); factory2 = create_factory(); @@ -3716,7 +3833,8 @@ if (0) { /* crashes on native */ IDWriteFontFamily_Release(family); IDWriteFont_Release(font); IDWriteGdiInterop_Release(interop); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_CreateStreamFromKey(void) @@ -3731,6 +3849,7 @@ static void test_CreateStreamFromKey(void) void *key; UINT32 size; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -3775,7 +3894,8 @@ static void test_CreateStreamFromKey(void) IDWriteFontFile_Release(file); IDWriteLocalFontFileLoader_Release(localloader); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); DELETE_FONTFILE(path); } @@ -3792,6 +3912,7 @@ static void test_ReadFileFragment(void) UINT32 size; WCHAR *path; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -3854,7 +3975,8 @@ static void test_ReadFileFragment(void) IDWriteFontFile_Release(file); IDWriteFontFileStream_Release(stream); IDWriteLocalFontFileLoader_Release(localloader); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); DELETE_FONTFILE(path); } @@ -3868,6 +3990,7 @@ static void test_GetDesignGlyphMetrics(void) UINT32 codepoint; WCHAR *path; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -3905,7 +4028,8 @@ static void test_GetDesignGlyphMetrics(void) ok(metrics[1].advanceWidth == 0, "got %d\n", metrics[1].advanceWidth); IDWriteFontFace_Release(fontface); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); DELETE_FONTFILE(path); } @@ -3917,6 +4041,7 @@ static void test_IsMonospacedFont(void) UINT32 index; BOOL exists; HRESULT hr; + ULONG ref; factory = create_factory(); hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE); @@ -3960,11 +4085,14 @@ static void test_IsMonospacedFont(void) } else win_skip("IsMonospacedFont() is not supported.\n"); + + IDWriteFont_Release(font); } else skip("Courier New font not found.\n"); - IDWriteFontCollection_Release(collection); + ref = IDWriteFontCollection_Release(collection); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_GetDesignGlyphAdvances(void) @@ -3975,6 +4103,7 @@ static void test_GetDesignGlyphAdvances(void) IDWriteFontFile *file; WCHAR *path; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -4017,7 +4146,8 @@ static void test_GetDesignGlyphAdvances(void) win_skip("GetDesignGlyphAdvances() is not supported.\n"); IDWriteFontFace_Release(fontface); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); DELETE_FONTFILE(path); } @@ -4032,6 +4162,7 @@ static void test_GetGlyphRunOutline(void) UINT16 glyphs[2]; WCHAR *path; HRESULT hr; + ULONG ref; path = create_testfontfile(test_fontfile); factory = create_factory(); @@ -4155,8 +4286,9 @@ static void test_GetGlyphRunOutline(void) ok(hr == S_OK, "got 0x%08x\n", hr); CHECK_CALLED(setfillmode); - IDWriteFactory_Release(factory); IDWriteFontFace_Release(face); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_GetEudcFontCollection(void) @@ -4165,6 +4297,7 @@ static void test_GetEudcFontCollection(void) IDWriteFactory1 *factory1; IDWriteFactory *factory; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -4183,7 +4316,8 @@ static void test_GetEudcFontCollection(void) IDWriteFontCollection_Release(coll); IDWriteFontCollection_Release(coll2); - IDWriteFactory1_Release(factory1); + ref = IDWriteFactory1_Release(factory1); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_GetCaretMetrics(void) @@ -4197,6 +4331,7 @@ static void test_GetCaretMetrics(void) IDWriteFont *font; WCHAR *path; HRESULT hr; + ULONG ref; path = create_testfontfile(test_fontfile); factory = create_factory(); @@ -4212,7 +4347,8 @@ static void test_GetCaretMetrics(void) IDWriteFontFace_Release(fontface); if (hr != S_OK) { win_skip("GetCaretMetrics() is not supported.\n"); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); DELETE_FONTFILE(path); return; } @@ -4260,7 +4396,8 @@ static void test_GetCaretMetrics(void) ok(caret.offset == 0, "got %d\n", caret.offset); IDWriteFontFace1_Release(fontface1); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); DELETE_FONTFILE(path); } @@ -4272,6 +4409,7 @@ static void test_GetGlyphCount(void) UINT16 count; WCHAR *path; HRESULT hr; + ULONG ref; path = create_testfontfile(test_fontfile); factory = create_factory(); @@ -4287,7 +4425,8 @@ static void test_GetGlyphCount(void) ok(count == 7, "got %u\n", count); IDWriteFontFace_Release(fontface); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); DELETE_FONTFILE(path); } @@ -4299,6 +4438,7 @@ static void test_GetKerningPairAdjustments(void) IDWriteFontFile *file; WCHAR *path; HRESULT hr; + ULONG ref; path = create_testfontfile(test_fontfile); factory = create_factory(); @@ -4331,7 +4471,8 @@ static void test_GetKerningPairAdjustments(void) win_skip("GetKerningPairAdjustments() is not supported.\n"); IDWriteFontFace_Release(fontface); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); DELETE_FONTFILE(path); } @@ -4344,6 +4485,7 @@ static void test_CreateRenderingParams(void) IDWriteFactory3 *factory3; IDWriteFactory *factory; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -4406,7 +4548,8 @@ static void test_CreateRenderingParams(void) else win_skip("IDWriteRenderingParams3 not supported.\n"); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_CreateGlyphRunAnalysis(void) @@ -4432,6 +4575,7 @@ static void test_CreateGlyphRunAnalysis(void) DWRITE_GLYPH_METRICS metrics; DWRITE_FONT_METRICS fm; DWRITE_MATRIX m; + ULONG ref; int i; factory = create_factory(); @@ -4717,7 +4861,8 @@ static void test_CreateGlyphRunAnalysis(void) IDWriteGlyphRunAnalysis_Release(analysis); IDWriteFontFace_Release(face); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } #define round(x) ((int)floor((x) + 0.5)) @@ -4912,7 +5057,7 @@ static void get_expected_metrics(IDWriteFontFace *fontface, struct compatmetrics ok(hr == S_OK, "got %08x\n", hr); } -static void test_GetGdiCompatibleMetrics_face(IDWriteFontFace *face) +static void test_gdicompat_metrics(IDWriteFontFace *face) { IDWriteFontFace1 *fontface1 = NULL; HRESULT hr; @@ -5049,6 +5194,7 @@ static void test_GetGdiCompatibleMetrics(void) IDWriteFont *font; IDWriteFontFace *fontface; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -5056,7 +5202,7 @@ static void test_GetGdiCompatibleMetrics(void) hr = IDWriteFont_CreateFontFace(font, &fontface); ok(hr == S_OK, "got 0x%08x\n", hr); IDWriteFont_Release(font); - test_GetGdiCompatibleMetrics_face(fontface); + test_gdicompat_metrics(fontface); IDWriteFontFace_Release(fontface); font = get_font(factory, arialW, DWRITE_FONT_STYLE_NORMAL); @@ -5068,11 +5214,12 @@ static void test_GetGdiCompatibleMetrics(void) ok(hr == S_OK, "got 0x%08x\n", hr); IDWriteFont_Release(font); - test_GetGdiCompatibleMetrics_face(fontface); + test_gdicompat_metrics(fontface); IDWriteFontFace_Release(fontface); } - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void get_expected_panose(IDWriteFont1 *font, DWRITE_PANOSE *panose) @@ -5108,18 +5255,21 @@ static void test_GetPanose(void) IDWriteFont *font; UINT count, i; HRESULT hr; + ULONG ref; factory = create_factory(); font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL); - hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFont1, (void**)&font1); + hr = IDWriteFont_QueryInterface(font, &IID_IDWriteFont1, (void **)&font1); IDWriteFont_Release(font); if (FAILED(hr)) { - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); win_skip("GetPanose() is not supported.\n"); return; } + IDWriteFont1_Release(font1); hr = IDWriteFactory_GetSystemFontCollection(factory, &syscollection, FALSE); ok(hr == S_OK, "got 0x%08x\n", hr); @@ -5191,7 +5341,8 @@ static void test_GetPanose(void) } IDWriteFontCollection_Release(syscollection); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static INT32 get_gdi_font_advance(HDC hdc, FLOAT emsize) @@ -5231,6 +5382,7 @@ static void test_GetGdiCompatibleGlyphAdvances(void) FLOAT emsize; DWRITE_FONT_METRICS1 fm; INT32 advance; + ULONG ref; factory = create_factory(); font = get_tahoma_instance(factory, DWRITE_FONT_STYLE_NORMAL); @@ -5239,11 +5391,12 @@ static void test_GetGdiCompatibleGlyphAdvances(void) ok(hr == S_OK, "got 0x%08x\n", hr); IDWriteFont_Release(font); - hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1); + hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void **)&fontface1); IDWriteFontFace_Release(fontface); if (hr != S_OK) { - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); win_skip("GetGdiCompatibleGlyphAdvances() is not supported\n"); return; } @@ -5301,7 +5454,9 @@ static void test_GetGdiCompatibleGlyphAdvances(void) DeleteObject(hdc); - IDWriteFactory_Release(factory); + IDWriteFontFace1_Release(fontface1); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static WORD get_gasp_flags(IDWriteFontFace *fontface, FLOAT emsize, FLOAT ppdip) @@ -5434,6 +5589,7 @@ static void test_GetRecommendedRenderingMode(void) IDWriteFactory *factory; FLOAT emsize; HRESULT hr; + ULONG ref; factory = create_factory(); fontface = create_fontface(factory); @@ -5746,7 +5902,8 @@ static void test_GetRecommendedRenderingMode(void) if (fontface1) IDWriteFontFace1_Release(fontface1); IDWriteFontFace_Release(fontface); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static inline BOOL float_eq(FLOAT left, FLOAT right) @@ -5785,6 +5942,7 @@ static void test_GetAlphaBlendParams(void) UINT16 glyph; UINT32 ch, i; HRESULT hr; + ULONG ref; BOOL ret; factory = create_factory(); @@ -5854,7 +6012,8 @@ static void test_GetAlphaBlendParams(void) IDWriteRenderingParams_Release(params); IDWriteFontFace_Release(fontface); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_CreateAlphaTexture(void) @@ -5871,6 +6030,7 @@ static void test_CreateAlphaTexture(void) FLOAT advance; UINT16 glyph; HRESULT hr; + ULONG ref; factory = create_factory(); fontface = create_fontface(factory); @@ -5995,7 +6155,8 @@ static void test_CreateAlphaTexture(void) IDWriteGlyphRunAnalysis_Release(analysis); IDWriteFontFace_Release(fontface); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_IsSymbolFont(void) @@ -6006,6 +6167,7 @@ static void test_IsSymbolFont(void) IDWriteFactory *factory; IDWriteFont *font; HRESULT hr; + ULONG ref; BOOL ret; factory = create_factory(); @@ -6037,9 +6199,11 @@ static void test_IsSymbolFont(void) ok(hr == S_OK, "got 0x%08x\n", hr); ret = IDWriteFontFace_IsSymbolFont(fontface); ok(ret, "got %d\n", ret); + IDWriteFontFace_Release(fontface); IDWriteFont_Release(font); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } struct CPAL_Header_0 @@ -6064,6 +6228,7 @@ static void test_GetPaletteEntries(void) const struct CPAL_Header_0 *cpal_header; HRESULT hr; BOOL exists; + ULONG ref; factory = create_factory(); @@ -6072,7 +6237,8 @@ static void test_GetPaletteEntries(void) hr = IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace2, (void**)&fontface2); IDWriteFontFace_Release(fontface); if (hr != S_OK) { - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); win_skip("GetPaletteEntries() is not supported.\n"); return; } @@ -6084,7 +6250,8 @@ static void test_GetPaletteEntries(void) /* Segoe UI Emoji, with color support */ font = get_font(factory, emojiW, DWRITE_FONT_STYLE_NORMAL); if (!font) { - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); skip("Segoe UI Emoji font not found.\n"); return; } @@ -6138,7 +6305,8 @@ static void test_GetPaletteEntries(void) "got wrong color %.2fx%.2fx%.2fx%.2f\n", color.r, color.g, color.b, color.a); IDWriteFontFace2_Release(fontface2); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_TranslateColorGlyphRun(void) @@ -6155,6 +6323,7 @@ static void test_TranslateColorGlyphRun(void) UINT16 glyphs[2]; BOOL hasrun; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -6282,7 +6451,8 @@ static void test_TranslateColorGlyphRun(void) IDWriteFontFace2_Release(fontface2); IDWriteFontFace_Release(fontface); - IDWriteFactory2_Release(factory2); + ref = IDWriteFactory2_Release(factory2); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_HasCharacter(void) @@ -6292,6 +6462,7 @@ static void test_HasCharacter(void) IDWriteFont3 *font3; IDWriteFont *font; HRESULT hr; + ULONG ref; BOOL ret; factory = create_factory(); @@ -6315,7 +6486,8 @@ static void test_HasCharacter(void) win_skip("IDWriteFont3 is not supported.\n"); IDWriteFont_Release(font); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_CreateFontFaceReference(void) @@ -6328,6 +6500,7 @@ static void test_CreateFontFaceReference(void) IDWriteFactory *factory; IDWriteFont3 *font3; IDWriteFont *font; + ULONG refcount; UINT32 index; WCHAR *path; HRESULT hr; @@ -6482,7 +6655,8 @@ if (hr == S_OK) { IDWriteFontFace3_Release(fontface); IDWriteFont3_Release(font3); - IDWriteFactory3_Release(factory3); + refcount = IDWriteFactory3_Release(factory3); + ok(refcount == 0, "factory not released, %u\n", refcount); DELETE_FONTFILE(path); } @@ -6533,6 +6707,7 @@ static void test_GetFontSignature(void) FONTSIGNATURE fontsig; UINT count, i; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -6602,7 +6777,8 @@ static void test_GetFontSignature(void) IDWriteGdiInterop1_Release(interop1); IDWriteFontCollection_Release(syscollection); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_font_properties(void) @@ -6613,6 +6789,7 @@ static void test_font_properties(void) DWRITE_FONT_STYLE style; IDWriteFont *font; HRESULT hr; + ULONG ref; factory = create_factory(); @@ -6635,7 +6812,8 @@ static void test_font_properties(void) } IDWriteFont_Release(font); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static BOOL has_vertical_glyph_variants(IDWriteFontFace1 *fontface) @@ -6724,6 +6902,7 @@ static void test_HasVerticalGlyphVariants(void) IDWriteFactory *factory; UINT32 count, i; HRESULT hr; + ULONG ref; factory = create_factory(); fontface = create_fontface(factory); @@ -6781,7 +6960,8 @@ static void test_HasVerticalGlyphVariants(void) } IDWriteFontCollection_Release(syscollection); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_HasKerningPairs(void) @@ -6792,6 +6972,7 @@ static void test_HasKerningPairs(void) IDWriteFactory *factory; UINT32 count, i; HRESULT hr; + ULONG ref; factory = create_factory(); fontface = create_fontface(factory); @@ -6855,7 +7036,8 @@ static void test_HasKerningPairs(void) } IDWriteFontCollection_Release(syscollection); - IDWriteFactory_Release(factory); + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } static void test_ComputeGlyphOrigins(void) @@ -6869,6 +7051,7 @@ static void test_ComputeGlyphOrigins(void) UINT16 glyphs[2]; FLOAT advances[2]; DWRITE_MATRIX m; + ULONG ref; factory = create_factory(); hr = IDWriteFactory_QueryInterface(factory, &IID_IDWriteFactory4, (void **)&factory4); @@ -6919,7 +7102,165 @@ static void test_ComputeGlyphOrigins(void) ok(origins[0].x == 123.0f && origins[0].y == 321.0f, "origins[0] %f,%f\n", origins[0].x, origins[0].y); ok(origins[1].x == 133.0f && origins[1].y == 321.0f, "origins[1] %f,%f\n", origins[1].x, origins[1].y); - IDWriteFactory4_Release(factory4); + ref = IDWriteFactory4_Release(factory4); + ok(ref == 0, "factory not released, %u\n", ref); +} + +static void test_object_lifetime(void) +{ + IDWriteFontCollection *collection, *collection2; + IDWriteFontList *fontlist, *fontlist2; + IDWriteGdiInterop *interop, *interop2; + IDWriteFontFamily *family, *family2; + IDWriteFontFace *fontface; + IDWriteFont *font, *font2; + IDWriteFactory *factory; + HRESULT hr; + ULONG ref; + + factory = create_factory(); + EXPECT_REF(factory, 1); + + /* system collection takes factory reference */ + hr = IDWriteFactory_GetSystemFontCollection(factory, &collection, FALSE); + ok(hr == S_OK, "got %#x\n", hr); + + EXPECT_REF(collection, 1); + EXPECT_REF(factory, 2); + + hr = IDWriteFactory_GetSystemFontCollection(factory, &collection2, FALSE); + ok(hr == S_OK, "got %#x\n", hr); + ok(collection2 == collection, "expected same collection\n"); + + EXPECT_REF(collection, 2); + EXPECT_REF(factory, 2); + + IDWriteFontCollection_Release(collection2); + + IDWriteFontCollection_AddRef(collection); + EXPECT_REF(collection, 2); + EXPECT_REF(factory, 2); + IDWriteFontCollection_Release(collection); + + EXPECT_REF(collection, 1); + + /* family takes collection reference */ + hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family); + ok(hr == S_OK, "got %#x\n", hr); + + EXPECT_REF(family, 1); + EXPECT_REF(collection, 2); + EXPECT_REF(factory, 2); + + hr = IDWriteFontCollection_GetFontFamily(collection, 0, &family2); + ok(hr == S_OK, "got %#x\n", hr); + + EXPECT_REF(family2, 1); + EXPECT_REF(collection, 3); + EXPECT_REF(factory, 2); + + IDWriteFontFamily_Release(family2); + + EXPECT_REF(family, 1); + EXPECT_REF(collection, 2); + EXPECT_REF(factory, 2); + + /* font takes family reference */ + hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &font); + ok(hr == S_OK, "got %#x\n", hr); + + EXPECT_REF(family, 2); + EXPECT_REF(collection, 2); + EXPECT_REF(factory, 2); + + hr = IDWriteFont_GetFontFamily(font, &family2); + ok(hr == S_OK, "got %#x\n", hr); + ok(family2 == family, "unexpected family pointer\n"); + IDWriteFontFamily_Release(family2); + + EXPECT_REF(font, 1); + EXPECT_REF(factory, 2); + + /* Fontface takes factory reference and nothing else. */ + hr = IDWriteFont_CreateFontFace(font, &fontface); + ok(hr == S_OK, "got %#x\n", hr); + + EXPECT_REF(font, 1); + EXPECT_REF_BROKEN(fontface, 1, 2); + EXPECT_REF(family, 2); + EXPECT_REF(collection, 2); + EXPECT_REF_BROKEN(factory, 3, 2); + + /* get font from fontface */ + hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font2); + ok(hr == S_OK, "got %#x\n", hr); + + EXPECT_REF(font, 1); + EXPECT_REF(font2, 1); + EXPECT_REF_BROKEN(fontface, 1, 2); + EXPECT_REF(family, 2); + EXPECT_REF(collection, 3); + EXPECT_REF_BROKEN(factory, 3, 2); + + IDWriteFont_Release(font2); + IDWriteFontFace_Release(fontface); + + EXPECT_REF(font, 1); + EXPECT_REF(family, 2); + EXPECT_REF(collection, 2); + EXPECT_REF(factory, 2); + + IDWriteFont_Release(font); + + EXPECT_REF(family, 1); + EXPECT_REF(collection, 2); + EXPECT_REF(factory, 2); + + /* Matching fonts list takes family reference. */ + hr = IDWriteFontFamily_GetMatchingFonts(family, DWRITE_FONT_WEIGHT_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &fontlist); + ok(hr == S_OK, "got %#x\n", hr); + + EXPECT_REF(family, 2); + EXPECT_REF(collection, 2); + EXPECT_REF(factory, 2); + + hr = IDWriteFontFamily_GetMatchingFonts(family, DWRITE_FONT_WEIGHT_NORMAL, + DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &fontlist2); + ok(hr == S_OK, "got %#x\n", hr); + ok(fontlist2 != fontlist, "unexpected font list\n"); + IDWriteFontList_Release(fontlist2); + + IDWriteFontList_Release(fontlist); + + IDWriteFontFamily_Release(family); + EXPECT_REF(collection, 1); + + EXPECT_REF(factory, 2); + ref = IDWriteFontCollection_Release(collection); + ok(ref == 0, "collection not released, %u\n", ref); + EXPECT_REF(factory, 1); + + /* GDI interop object takes factory reference */ + hr = IDWriteFactory_GetGdiInterop(factory, &interop); + ok(hr == S_OK, "got %#x\n", hr); + EXPECT_REF(interop, 1); + EXPECT_REF(factory, 2); + + hr = IDWriteFactory_GetGdiInterop(factory, &interop2); + ok(hr == S_OK, "got %#x\n", hr); + ok(interop == interop2, "got unexpected interop pointer\n"); + + EXPECT_REF(interop, 2); + EXPECT_REF(factory, 2); + + IDWriteGdiInterop_Release(interop2); + ref = IDWriteGdiInterop_Release(interop); + ok(ref == 0, "interop not released, %u\n", ref); + + ref = IDWriteFactory_Release(factory); + ok(ref == 0, "factory not released, %u\n", ref); } START_TEST(font) @@ -6931,6 +7272,7 @@ START_TEST(font) return; } + test_object_lifetime(); test_CreateFontFromLOGFONT(); test_CreateBitmapRenderTarget(); test_GetFontFamily();