From: Aric Stewart Subject: [2/3]dwrite: build non-system font collections as a list of font families Message-Id: <540E4590.3050504@codeweavers.com> Date: Mon, 08 Sep 2014 19:10:56 -0500 --- dlls/dwrite/font.c | 134 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 112 insertions(+), 22 deletions(-) diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index efa305e..d6dbf6d 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -59,6 +59,8 @@ struct dwrite_font_data { }; struct dwrite_fontfamily_data { + LONG ref; + IDWriteLocalizedStrings *familyname; struct dwrite_font_data **fonts; @@ -73,6 +75,10 @@ struct dwrite_fontcollection { WCHAR **families; UINT32 count; int alloc; + + struct dwrite_fontfamily_data **font_families; + DWORD family_count; + int family_alloc; }; struct dwrite_fontfamily { @@ -130,6 +136,7 @@ struct dwrite_fontfile { static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family); static HRESULT create_font_base(IDWriteFont **font); static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFont **font); +static HRESULT create_fontfamily_from_data(struct dwrite_fontfamily_data *data, IDWriteFontCollection *collection, IDWriteFontFamily **family); static inline struct dwrite_fontface *impl_from_IDWriteFontFace(IDWriteFontFace *iface) { @@ -202,6 +209,21 @@ static VOID _free_font_data(struct dwrite_font_data *data) heap_free(data); } +static VOID _free_fontfamily_data(struct dwrite_fontfamily_data *data) +{ + int i; + if (!data) + return; + i = InterlockedDecrement(&data->ref); + if (i > 0) + return; + for (i = 0; i < data->font_count; i++) + _free_font_data(data->fonts[i]); + heap_free(data->fonts); + IDWriteLocalizedStrings_Release(data->familyname); + heap_free(data); +} + static HRESULT WINAPI dwritefontface_QueryInterface(IDWriteFontFace *iface, REFIID riid, void **obj) { struct dwrite_fontface *This = impl_from_IDWriteFontFace(iface); @@ -747,15 +769,9 @@ static ULONG WINAPI dwritefontfamily_Release(IDWriteFontFamily *iface) if (!ref) { - int i; - IDWriteLocalizedStrings_Release(This->data->familyname); - if (This->collection) IDWriteFontCollection_Release(This->collection); - for (i = 0; i < This->data->font_count; i++) - _free_font_data(This->data->fonts[i]); - heap_free(This->data->fonts); - heap_free(This->data); + _free_fontfamily_data(This->data); heap_free(This); } @@ -910,6 +926,9 @@ static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface) for (i = 0; i < This->count; i++) heap_free(This->families[i]); heap_free(This->families); + for (i = 0; i < This->family_count; i++) + _free_fontfamily_data(This->font_families[i]); + heap_free(This->font_families); heap_free(This); } @@ -920,6 +939,8 @@ static UINT32 WINAPI dwritefontcollection_GetFontFamilyCount(IDWriteFontCollecti { struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface); TRACE("(%p)\n", This); + if (This->family_count) + return This->family_count; return This->count; } @@ -932,18 +953,31 @@ static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection * TRACE("(%p)->(%u %p)\n", This, index, family); - if (index >= This->count) + if (This->family_count) { - *family = NULL; - return E_FAIL; + if (index >= This->family_count) + { + *family = NULL; + return E_FAIL; + } + else + return create_fontfamily_from_data(This->font_families[index], iface, family); } + else + { + if (index >= This->count) + { + *family = NULL; + return E_FAIL; + } - hr = create_localizedstrings(&familyname); - if (FAILED(hr)) - return hr; - add_localizedstring(familyname, enusW, This->families[index]); + hr = create_localizedstrings(&familyname); + if (FAILED(hr)) + return hr; + add_localizedstring(familyname, enusW, This->families[index]); - return create_fontfamily(familyname, family); + return create_fontfamily(familyname, family); + } } static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection *iface, const WCHAR *name, UINT32 *index, BOOL *exists) @@ -953,16 +987,44 @@ static HRESULT WINAPI dwritefontcollection_FindFamilyName(IDWriteFontCollection TRACE("(%p)->(%s %p %p)\n", This, debugstr_w(name), index, exists); - for (i = 0; i < This->count; i++) - if (!strcmpW(This->families[i], name)) + if (This->family_count) + { + for (i = 0; i < This->family_count; i++) { - *index = i; - *exists = TRUE; - return S_OK; + HRESULT hr; + IDWriteLocalizedStrings *family_name = This->font_families[i]->familyname; + int j; + for (j = 0; j < IDWriteLocalizedStrings_GetCount(family_name); j ++) + { + WCHAR buffer[255]; + hr = IDWriteLocalizedStrings_GetString(family_name, j, buffer, 255); + if (SUCCEEDED(hr)) + { + if (!strcmpW(buffer, name)) + { + *index = i; + *exists = TRUE; + return S_OK; + } + } + } } + *index = (UINT32)-1; + *exists = FALSE; + } + else + { + for (i = 0; i < This->count; i++) + if (!strcmpW(This->families[i], name)) + { + *index = i; + *exists = TRUE; + return S_OK; + } - *index = (UINT32)-1; - *exists = FALSE; + *index = (UINT32)-1; + *exists = FALSE; + } return S_OK; } @@ -1024,6 +1086,9 @@ HRESULT get_system_fontcollection(IDWriteFontCollection **collection) This->alloc = 50; This->count = 0; This->families = heap_alloc(This->alloc*sizeof(WCHAR*)); + This->family_count = 0; + This->family_alloc = 2; + This->font_families = heap_alloc(sizeof(*This->font_families)*2); TRACE("building system font collection:\n"); @@ -1040,6 +1105,30 @@ HRESULT get_system_fontcollection(IDWriteFontCollection **collection) return S_OK; } +static HRESULT create_fontfamily_from_data(struct dwrite_fontfamily_data *data, IDWriteFontCollection *collection, IDWriteFontFamily **family) +{ + HRESULT hr; + struct dwrite_fontfamily *This; + + hr = create_fontfamily(NULL, family); + if (FAILED(hr)) + return hr; + + This = impl_from_IDWriteFontFamily(*family); + + heap_free(This->data->fonts); + heap_free(This->data); + + This->data = data; + InterlockedIncrement(&This->data->ref); + + This->collection = collection; + if (collection) + IDWriteFontCollection_AddRef(collection); + + return S_OK; +} + static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family) { struct dwrite_fontfamily *This; @@ -1057,6 +1146,7 @@ static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFon This->IDWriteFontFamily_iface.lpVtbl = &fontfamilyvtbl; This->ref = 1; + This->data->ref = 1; This->data->font_count = 0; This->data->alloc = 2; This->data->fonts = heap_alloc(sizeof(*This->data->fonts) * 2);