[PATCH 1/3] dwrite: Improve font objects refcounting
Nikolay Sivov
nsivov at codeweavers.com
Tue Apr 11 06:21:32 CDT 2017
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
This fixes virtual memory exhaustion when running tests,
especially important on macos that's shipped with more fonts by default
than average clean Linux installation.
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 4eed73c1f0..886beb7c57 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 096c7f3fa7..aeebb0d749 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 67fc4a0f68..cf3b3fa10c 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 067bc8a3ce..c17bb5a3a7 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;
+}
+
+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 **font_face)
+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 79aebe3ebe..8b16d0e442 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();
--
2.11.0
More information about the wine-patches
mailing list