dwrite: Improve font objects refcounting.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2017-04-11 14:21:32 +03:00 committed by Alexandre Julliard
parent 6a307598b1
commit be5a4656bd
5 changed files with 617 additions and 215 deletions

View file

@ -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 {

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;

File diff suppressed because it is too large Load diff