From: Nikolay Sivov Subject: [PATCH 7/8] dwrite: Implement system font collection as any other font collection Message-Id: <544F45A4.9010105@codeweavers.com> Date: Tue, 28 Oct 2014 10:28:36 +0300 --- From 170e9742e2cc639b35593e7fdf4f7e7b19036ec3 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 28 Oct 2014 10:15:49 +0300 Subject: [PATCH 7/8] dwrite: Implement system font collection as any other font collection --- dlls/dwrite/dwrite_private.h | 2 +- dlls/dwrite/font.c | 631 +++++++++++++++---------------------------- dlls/dwrite/main.c | 2 +- dlls/dwrite/tests/font.c | 44 +-- 4 files changed, 230 insertions(+), 449 deletions(-) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index b2af03c..8386d92 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -101,7 +101,7 @@ extern void release_gdiinterop(IDWriteGdiInterop*) DECLSPEC_HIDDEN; extern HRESULT create_localizedstrings(IDWriteLocalizedStrings**) DECLSPEC_HIDDEN; extern HRESULT add_localizedstring(IDWriteLocalizedStrings*,const WCHAR*,const WCHAR*) DECLSPEC_HIDDEN; extern HRESULT clone_localizedstring(IDWriteLocalizedStrings *iface, IDWriteLocalizedStrings **strings) DECLSPEC_HIDDEN; -extern HRESULT get_system_fontcollection(IDWriteFontCollection**) DECLSPEC_HIDDEN; +extern HRESULT get_system_fontcollection(IDWriteFactory*,IDWriteFontCollection**) DECLSPEC_HIDDEN; 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; diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index f8bff51..622027c 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -65,10 +65,6 @@ struct dwrite_fontcollection { IDWriteFontCollection IDWriteFontCollection_iface; LONG ref; - WCHAR **families; - UINT32 count; - int alloc; - struct dwrite_fontfamily_data **family_data; UINT32 family_count; UINT32 family_alloc; @@ -87,7 +83,6 @@ struct dwrite_font { IDWriteFont2 IDWriteFont2_iface; LONG ref; - BOOL is_system; IDWriteFontFamily *family; DWRITE_FONT_SIMULATIONS simulations; @@ -120,9 +115,6 @@ struct dwrite_fontface { DWRITE_FONT_FACE_TYPE type; struct dwrite_fonttable cmap; - - BOOL is_system; - LOGFONTW logfont; }; struct dwrite_fontfile { @@ -135,9 +127,7 @@ struct dwrite_fontfile { IDWriteFontFileStream *stream; }; -static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family); static HRESULT create_fontfamily_from_data(struct dwrite_fontfamily_data *data, IDWriteFontCollection *collection, IDWriteFontFamily **family); -static HRESULT create_font_base(IDWriteFont **font); static HRESULT create_font_from_data(struct dwrite_font_data*,IDWriteFontFamily*,DWRITE_FONT_SIMULATIONS,IDWriteFont**); static HRESULT get_filestream_from_file(IDWriteFontFile*,IDWriteFontFileStream**); @@ -369,91 +359,53 @@ static HRESULT WINAPI dwritefontface_GetGlyphIndices(IDWriteFontFace2 *iface, UI { struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface); unsigned int i; + void *data; - if (This->is_system) - { - HFONT hfont; - WCHAR *str; - HDC hdc; - - TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices); - - str = heap_alloc(count*sizeof(WCHAR)); - if (!str) return E_OUTOFMEMORY; - - for (i = 0; i < count; i++) - str[i] = codepoints[i] < 0x10000 ? codepoints[i] : '?'; - - hdc = CreateCompatibleDC(0); - hfont = CreateFontIndirectW(&This->logfont); - SelectObject(hdc, hfont); - - GetGlyphIndicesW(hdc, str, count, glyph_indices, 0); - heap_free(str); - - DeleteDC(hdc); - DeleteObject(hfont); + TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices); - return S_OK; - } - else - { - void *data; - - TRACE("(%p)->(%p %u %p)\n", This, codepoints, count, glyph_indices); - - data = get_fontface_cmap(This); - if (!data) - return E_FAIL; + data = get_fontface_cmap(This); + if (!data) + return E_FAIL; - for (i = 0; i < count; i++) - opentype_cmap_get_glyphindex(data, codepoints[i], &glyph_indices[i]); + for (i = 0; i < count; i++) + opentype_cmap_get_glyphindex(data, codepoints[i], &glyph_indices[i]); - return S_OK; - } + return S_OK; } static HRESULT WINAPI dwritefontface_TryGetFontTable(IDWriteFontFace2 *iface, UINT32 table_tag, const void **table_data, UINT32 *table_size, void **context, BOOL *exists) { struct dwrite_fontface *This = impl_from_IDWriteFontFace2(iface); - if (This->is_system) - { - FIXME("(%p)->(%u %p %p %p %p): stub\n", This, table_tag, table_data, table_size, context, exists); - return E_NOTIMPL; - } - else - { - HRESULT hr = S_OK; - int i; - struct dwrite_fonttablecontext *tablecontext; + struct dwrite_fonttablecontext *tablecontext; + HRESULT hr = S_OK; + int i; - TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists); + TRACE("(%p)->(%u %p %p %p %p)\n", This, table_tag, table_data, table_size, context, exists); - tablecontext = heap_alloc(sizeof(struct dwrite_fonttablecontext)); - if (!tablecontext) - return E_OUTOFMEMORY; - tablecontext->magic = DWRITE_FONTTABLE_MAGIC; + tablecontext = heap_alloc(sizeof(struct dwrite_fonttablecontext)); + if (!tablecontext) + return E_OUTOFMEMORY; + tablecontext->magic = DWRITE_FONTTABLE_MAGIC; - *exists = FALSE; - for (i = 0; i < This->file_count && !(*exists); i++) - { - IDWriteFontFileStream *stream; - hr = _dwritefontfile_GetFontFileStream(This->files[i], &stream); - if (FAILED(hr)) - continue; - tablecontext->file_index = i; + *exists = FALSE; + for (i = 0; i < This->file_count && !(*exists); i++) { + IDWriteFontFileStream *stream; + hr = _dwritefontfile_GetFontFileStream(This->files[i], &stream); + if (FAILED(hr)) + continue; + tablecontext->file_index = i; - hr = opentype_get_font_table(stream, This->type, This->index, table_tag, table_data, &tablecontext->context, table_size, exists); + hr = opentype_get_font_table(stream, This->type, This->index, table_tag, table_data, &tablecontext->context, table_size, exists); - IDWriteFontFileStream_Release(stream); - } - if (FAILED(hr) && !*exists) - heap_free(tablecontext); - else - *context = (void*)tablecontext; - return hr; + IDWriteFontFileStream_Release(stream); } + if (FAILED(hr) && !*exists) + heap_free(tablecontext); + else + *context = (void*)tablecontext; + + return hr; } static void WINAPI dwritefontface_ReleaseFontTable(IDWriteFontFace2 *iface, void *table_context) @@ -692,38 +644,6 @@ static const IDWriteFontFace2Vtbl dwritefontfacevtbl = { dwritefontface2_GetRecommendedRenderingMode }; -static HRESULT create_system_fontface(struct dwrite_font *font, IDWriteFontFace **face) -{ - struct dwrite_fontface *This; - - *face = NULL; - - This = heap_alloc(sizeof(struct dwrite_fontface)); - if (!This) return E_OUTOFMEMORY; - - This->IDWriteFontFace2_iface.lpVtbl = &dwritefontfacevtbl; - This->ref = 1; - This->type = DWRITE_FONT_FACE_TYPE_UNKNOWN; - This->file_count = 0; - This->files = NULL; - This->index = 0; - This->simulations = DWRITE_FONT_SIMULATIONS_NONE; - This->cmap.data = NULL; - This->cmap.context = NULL; - This->cmap.size = 0; - - This->is_system = TRUE; - memset(&This->logfont, 0, sizeof(This->logfont)); - This->logfont.lfItalic = font->data->style == DWRITE_FONT_STYLE_ITALIC; - /* weight values from DWRITE_FONT_WEIGHT match values used for LOGFONT */ - This->logfont.lfWeight = font->data->weight; - strcpyW(This->logfont.lfFaceName, font->data->facename); - - *face = (IDWriteFontFace*)&This->IDWriteFontFace2_iface; - - return S_OK; -} - static void get_font_properties_from_stream(IDWriteFontFileStream *stream, DWRITE_FONT_FACE_TYPE face_type, UINT32 face_index, DWRITE_FONT_METRICS *metrics, DWRITE_FONT_STRETCH *stretch, DWRITE_FONT_WEIGHT *weight, DWRITE_FONT_STYLE *style) @@ -797,8 +717,7 @@ static HRESULT get_fontface_from_font(struct dwrite_font *font, IDWriteFontFace2 struct dwrite_font_data *data = font->data; IDWriteFontFace *face; - hr = font->is_system ? create_system_fontface(font, &face) : - IDWriteFactory_CreateFontFace(data->factory, data->face_type, 1, &data->file, + hr = IDWriteFactory_CreateFontFace(data->factory, data->face_type, 1, &data->file, data->face_index, font->simulations, &face); if (FAILED(hr)) return hr; @@ -811,126 +730,6 @@ static HRESULT get_fontface_from_font(struct dwrite_font *font, IDWriteFontFace2 return hr; } -static HRESULT create_font_base(IDWriteFont **font) -{ - struct dwrite_font_data *data; - HRESULT ret; - - *font = NULL; - data = heap_alloc_zero(sizeof(*data)); - if (!data) return E_OUTOFMEMORY; - - ret = create_font_from_data( data, NULL, DWRITE_FONT_SIMULATIONS_NONE, font ); - if (FAILED(ret)) heap_free( data ); - return ret; -} - -static HRESULT create_font_from_logfont(const LOGFONTW *logfont, IDWriteFont **font) -{ - const WCHAR* facename, *familyname; - IDWriteLocalizedStrings *name; - struct dwrite_font *This; - IDWriteFontFamily *family; - OUTLINETEXTMETRICW *otm; - HRESULT hr; - HFONT hfont; - HDC hdc; - int ret; - static const WCHAR enusW[] = {'e','n','-','u','s',0}; - LPVOID tt_os2 = NULL; - LPVOID tt_head = NULL; - LPVOID tt_post = NULL; - LONG size; - - hr = create_font_base(font); - if (FAILED(hr)) - return hr; - - This = impl_from_IDWriteFont2((IDWriteFont2*)*font); - - hfont = CreateFontIndirectW(logfont); - if (!hfont) - { - heap_free(This->data); - heap_free(This); - return DWRITE_E_NOFONT; - } - - hdc = CreateCompatibleDC(0); - SelectObject(hdc, hfont); - - ret = GetOutlineTextMetricsW(hdc, 0, NULL); - otm = heap_alloc(ret); - if (!otm) - { - heap_free(This->data); - heap_free(This); - DeleteDC(hdc); - DeleteObject(hfont); - return E_OUTOFMEMORY; - } - otm->otmSize = ret; - ret = GetOutlineTextMetricsW(hdc, otm->otmSize, otm); - - size = GetFontData(hdc, MS_OS2_TAG, 0, NULL, 0); - if (size != GDI_ERROR) - { - tt_os2 = heap_alloc(size); - GetFontData(hdc, MS_OS2_TAG, 0, tt_os2, size); - } - size = GetFontData(hdc, MS_HEAD_TAG, 0, NULL, 0); - if (size != GDI_ERROR) - { - tt_head = heap_alloc(size); - GetFontData(hdc, MS_HEAD_TAG, 0, tt_head, size); - } - size = GetFontData(hdc, MS_POST_TAG, 0, NULL, 0); - if (size != GDI_ERROR) - { - tt_post = heap_alloc(size); - GetFontData(hdc, MS_POST_TAG, 0, tt_post, size); - } - - get_font_properties(tt_os2, tt_head, tt_post, &This->data->metrics, &This->data->stretch, &This->data->weight, &This->data->style); - heap_free(tt_os2); - heap_free(tt_head); - heap_free(tt_post); - - if (logfont->lfItalic) - This->data->style = DWRITE_FONT_STYLE_ITALIC; - - DeleteDC(hdc); - DeleteObject(hfont); - - facename = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFaceName); - familyname = (WCHAR*)((char*)otm + (ptrdiff_t)otm->otmpFamilyName); - TRACE("facename=%s, familyname=%s\n", debugstr_w(facename), debugstr_w(familyname)); - - hr = create_localizedstrings(&name); - if (FAILED(hr)) - { - heap_free(This); - return hr; - } - add_localizedstring(name, enusW, familyname); - hr = create_fontfamily(name, &family); - - heap_free(otm); - if (hr != S_OK) - { - heap_free(This->data); - heap_free(This); - return hr; - } - - This->is_system = TRUE; - This->family = family; - This->simulations = DWRITE_FONT_SIMULATIONS_NONE; - This->data->facename = heap_strdupW(logfont->lfFaceName); - - return S_OK; -} - static HRESULT WINAPI dwritefont_QueryInterface(IDWriteFont2 *iface, REFIID riid, void **obj) { struct dwrite_font *This = impl_from_IDWriteFont2(iface); @@ -1231,14 +1030,10 @@ static HRESULT WINAPI dwritefontfamily_GetFontCollection(IDWriteFontFamily *ifac { struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface); TRACE("(%p)->(%p)\n", This, collection); - if (This->collection) - { - IDWriteFontCollection_AddRef(This->collection); - *collection = This->collection; - return S_OK; - } - else - return E_NOTIMPL; + + *collection = This->collection; + IDWriteFontCollection_AddRef(This->collection); + return S_OK; } static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface) @@ -1251,15 +1046,18 @@ static UINT32 WINAPI dwritefontfamily_GetFontCount(IDWriteFontFamily *iface) static HRESULT WINAPI dwritefontfamily_GetFont(IDWriteFontFamily *iface, UINT32 index, IDWriteFont **font) { struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface); + TRACE("(%p)->(%u %p)\n", This, index, font); - if (This->data->font_count > 0) - { - if (index >= This->data->font_count) - return E_INVALIDARG; - return create_font_from_data(This->data->fonts[index], iface, DWRITE_FONT_SIMULATIONS_NONE, font); - } - else - return E_NOTIMPL; + + *font = NULL; + + if (This->data->font_count == 0) + return S_FALSE; + + if (index >= This->data->font_count) + return E_INVALIDARG; + + return create_font_from_data(This->data->fonts[index], iface, DWRITE_FONT_SIMULATIONS_NONE, font); } static HRESULT WINAPI dwritefontfamily_GetFamilyNames(IDWriteFontFamily *iface, IDWriteLocalizedStrings **names) @@ -1283,49 +1081,34 @@ static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *i DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFont **font) { struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface); - LOGFONTW lf; + UINT32 min_weight_diff = ~0u; + int found = -1, i; TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, font); - /* fallback for system font collections */ - if (This->data->font_count == 0) - { - memset(&lf, 0, sizeof(lf)); - lf.lfWeight = weight; - lf.lfItalic = style == DWRITE_FONT_STYLE_ITALIC; - IDWriteLocalizedStrings_GetString(This->data->familyname, 0, lf.lfFaceName, LF_FACESIZE); - - return create_font_from_logfont(&lf, font); - } - else - { - UINT32 min_weight_diff = ~0u; - int found = -1, i; - - for (i = 0; i < This->data->font_count; i++) { - if (is_matching_font_style(style, This->data->fonts[i]->style) && stretch == This->data->fonts[i]->stretch) { - DWRITE_FONT_WEIGHT font_weight = This->data->fonts[i]->weight; - UINT32 weight_diff = abs(font_weight - weight); - if (weight_diff < min_weight_diff) { - min_weight_diff = weight_diff; - found = i; - } + for (i = 0; i < This->data->font_count; i++) { + if (is_matching_font_style(style, This->data->fonts[i]->style) && stretch == This->data->fonts[i]->stretch) { + DWRITE_FONT_WEIGHT font_weight = This->data->fonts[i]->weight; + UINT32 weight_diff = abs(font_weight - weight); + if (weight_diff < min_weight_diff) { + min_weight_diff = weight_diff; + found = i; } } + } - if (found != -1) { - DWRITE_FONT_SIMULATIONS simulations = DWRITE_FONT_SIMULATIONS_NONE; + if (found != -1) { + DWRITE_FONT_SIMULATIONS simulations = DWRITE_FONT_SIMULATIONS_NONE; - if (((style == DWRITE_FONT_STYLE_ITALIC) || (style == DWRITE_FONT_STYLE_OBLIQUE)) && - This->data->fonts[found]->style == DWRITE_FONT_STYLE_ITALIC) { - simulations = DWRITE_FONT_SIMULATIONS_OBLIQUE; - } - return create_font_from_data(This->data->fonts[found], iface, simulations, font); - } - else { - *font = NULL; - return DWRITE_E_NOFONT; + if (((style == DWRITE_FONT_STYLE_ITALIC) || (style == DWRITE_FONT_STYLE_OBLIQUE)) && + This->data->fonts[found]->style == DWRITE_FONT_STYLE_ITALIC) { + simulations = DWRITE_FONT_SIMULATIONS_OBLIQUE; } + return create_font_from_data(This->data->fonts[found], iface, simulations, font); + } + else { + *font = NULL; + return DWRITE_E_NOFONT; } } @@ -1381,11 +1164,7 @@ static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection *iface) ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p)->(%d)\n", This, ref); - if (!ref) - { - for (i = 0; i < This->count; i++) - heap_free(This->families[i]); - heap_free(This->families); + if (!ref) { for (i = 0; i < This->family_count; i++) _free_fontfamily_data(This->family_data[i]); heap_free(This->family_data); @@ -1399,45 +1178,21 @@ 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; + return This->family_count; } static HRESULT WINAPI dwritefontcollection_GetFontFamily(IDWriteFontCollection *iface, UINT32 index, IDWriteFontFamily **family) { struct dwrite_fontcollection *This = impl_from_IDWriteFontCollection(iface); - HRESULT hr; - IDWriteLocalizedStrings *familyname; - static const WCHAR enusW[] = {'e','n','-','u','s',0}; TRACE("(%p)->(%u %p)\n", This, index, family); - if (This->family_count) - { - if (index >= This->family_count) - { - *family = NULL; - return E_FAIL; - } - else - return create_fontfamily_from_data(This->family_data[index], iface, family); + if (index >= This->family_count) { + *family = NULL; + return E_FAIL; } - 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]); - return create_fontfamily(familyname, family); - } + return create_fontfamily_from_data(This->family_data[index], iface, family); } static HRESULT collection_find_family(struct dwrite_fontcollection *collection, const WCHAR *name, UINT32 *index, BOOL *exists) @@ -1465,17 +1220,6 @@ static HRESULT collection_find_family(struct dwrite_fontcollection *collection, *index = (UINT32)-1; *exists = FALSE; } - else { - for (i = 0; i < collection->count; i++) - if (!strcmpW(collection->families[i], name)) { - *index = i; - *exists = TRUE; - return S_OK; - } - - *index = (UINT32)-1; - *exists = FALSE; - } return S_OK; } @@ -1538,24 +1282,6 @@ static const IDWriteFontCollectionVtbl fontcollectionvtbl = { dwritefontcollection_GetFontFromFontFace }; -static HRESULT add_family_syscollection(struct dwrite_fontcollection *collection, const WCHAR *family) -{ - /* check for duplicate family name */ - if (collection->count && !strcmpW(collection->families[collection->count-1], family)) return S_OK; - - /* double array length */ - if (collection->count == collection->alloc) - { - collection->alloc *= 2; - collection->families = heap_realloc(collection->families, collection->alloc*sizeof(WCHAR*)); - } - - collection->families[collection->count++] = heap_strdupW(family); - TRACE("family name %s\n", debugstr_w(family)); - - return S_OK; -} - static HRESULT fontfamily_add_font(struct dwrite_fontfamily_data *family_data, struct dwrite_font_data *font_data) { if (family_data->font_count + 1 >= family_data->font_alloc) { @@ -1603,9 +1329,6 @@ static HRESULT init_font_collection(struct dwrite_fontcollection *collection) collection->ref = 1; collection->family_count = 0; collection->family_alloc = 2; - collection->count = 0; - collection->alloc = 0; - collection->families = NULL; collection->family_data = heap_alloc(sizeof(*collection->family_data)*2); if (!collection->family_data) @@ -1796,58 +1519,165 @@ HRESULT create_font_collection(IDWriteFactory* factory, IDWriteFontFileEnumerato return S_OK; } -static INT CALLBACK enum_font_families(const LOGFONTW *lf, const TEXTMETRICW *tm, DWORD type, LPARAM lParam) +struct system_fontfile_enumerator { - struct dwrite_fontcollection *collection = (struct dwrite_fontcollection*)lParam; - return add_family_syscollection(collection, lf->lfFaceName) == S_OK; + IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface; + LONG ref; + + IDWriteFactory *factory; + HKEY hkey; + int index; +}; + +static inline struct system_fontfile_enumerator *impl_from_IDWriteFontFileEnumerator(IDWriteFontFileEnumerator* iface) +{ + return CONTAINING_RECORD(iface, struct system_fontfile_enumerator, IDWriteFontFileEnumerator_iface); } -HRESULT get_system_fontcollection(IDWriteFontCollection **collection) +static HRESULT WINAPI systemfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator *iface, REFIID riid, void **obj) { - struct dwrite_fontcollection *This; - LOGFONTW lf; - HDC hdc; + *obj = NULL; - *collection = NULL; + if (IsEqualIID(riid, &IID_IDWriteFontFileEnumerator) || IsEqualIID(riid, &IID_IUnknown)) { + IDWriteFontFileEnumerator_AddRef(iface); + *obj = iface; + return S_OK; + } - This = heap_alloc(sizeof(struct dwrite_fontcollection)); - if (!This) return E_OUTOFMEMORY; + return E_NOINTERFACE; +} - This->IDWriteFontCollection_iface.lpVtbl = &fontcollectionvtbl; - This->ref = 1; - This->alloc = 50; - This->count = 0; - This->families = heap_alloc(This->alloc*sizeof(WCHAR*)); - if (!This->families) - { - heap_free(This); - return E_OUTOFMEMORY; +static ULONG WINAPI systemfontfileenumerator_AddRef(IDWriteFontFileEnumerator *iface) +{ + struct system_fontfile_enumerator *enumerator = impl_from_IDWriteFontFileEnumerator(iface); + return InterlockedIncrement(&enumerator->ref); +} + +static ULONG WINAPI systemfontfileenumerator_Release(IDWriteFontFileEnumerator *iface) +{ + struct system_fontfile_enumerator *enumerator = impl_from_IDWriteFontFileEnumerator(iface); + ULONG ref = InterlockedDecrement(&enumerator->ref); + + if (!ref) { + IDWriteFactory_Release(enumerator->factory); + RegCloseKey(enumerator->hkey); + heap_free(enumerator); } - This->family_count = 0; - This->family_alloc = 2; - This->family_data = heap_alloc(sizeof(*This->family_data)*2); - if (!This->family_data) - { - heap_free(This->families); - heap_free(This); + + return ref; +} + +static HRESULT WINAPI systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator *iface, IDWriteFontFile **file) +{ + struct system_fontfile_enumerator *enumerator = impl_from_IDWriteFontFileEnumerator(iface); + DWORD ret, type, count; + HRESULT hr; + BYTE *data; + + *file = NULL; + + if (enumerator->index < 0) + return E_FAIL; + + if (RegEnumValueW(enumerator->hkey, enumerator->index, NULL, NULL, NULL, &type, NULL, &count)) + return E_FAIL; + + if (!(data = heap_alloc(count))) return E_OUTOFMEMORY; + + ret = RegEnumValueW(enumerator->hkey, enumerator->index, NULL, NULL, NULL, &type, data, &count); + if (ret) { + heap_free(data); + return E_FAIL; } - TRACE("building system font collection:\n"); + hr = IDWriteFactory_CreateFontFileReference(enumerator->factory, (WCHAR*)data, NULL, file); + heap_free(data); + return hr; +} + +static HRESULT WINAPI systemfontfileenumerator_MoveNext(IDWriteFontFileEnumerator *iface, BOOL *current) +{ + struct system_fontfile_enumerator *enumerator = impl_from_IDWriteFontFileEnumerator(iface); + + *current = FALSE; + enumerator->index++; + + /* iterate until we find next string value */ + while (1) { + DWORD type = 0, count; + if (RegEnumValueW(enumerator->hkey, enumerator->index, NULL, NULL, NULL, &type, NULL, &count)) + break; + if (type == REG_SZ) { + *current = TRUE; + break; + } + enumerator->index++; + } + + TRACE("index = %d, current = %d\n", enumerator->index, *current); + return S_OK; +} + +static const struct IDWriteFontFileEnumeratorVtbl systemfontfileenumeratorvtbl = +{ + systemfontfileenumerator_QueryInterface, + systemfontfileenumerator_AddRef, + systemfontfileenumerator_Release, + systemfontfileenumerator_MoveNext, + systemfontfileenumerator_GetCurrentFontFile +}; + +static HRESULT create_system_fontfile_enumerator(IDWriteFactory *factory, IDWriteFontFileEnumerator **ret) +{ + struct system_fontfile_enumerator *enumerator; + static const WCHAR fontslistW[] = { + 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'F','o','n','t','s',0 + }; + + *ret = NULL; + + enumerator = heap_alloc(sizeof(*enumerator)); + if (!enumerator) + return E_OUTOFMEMORY; + + enumerator->IDWriteFontFileEnumerator_iface.lpVtbl = &systemfontfileenumeratorvtbl; + enumerator->ref = 1; + enumerator->factory = factory; + enumerator->index = -1; + IDWriteFactory_AddRef(factory); - hdc = CreateCompatibleDC(0); - memset(&lf, 0, sizeof(lf)); - lf.lfCharSet = DEFAULT_CHARSET; - lf.lfPitchAndFamily = DEFAULT_PITCH; - lf.lfFaceName[0] = 0; - EnumFontFamiliesExW(hdc, &lf, enum_font_families, (LPARAM)This, 0); - DeleteDC(hdc); + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, fontslistW, 0, GENERIC_READ, &enumerator->hkey)) { + ERR("failed to open fonts list key\n"); + IDWriteFactory_Release(factory); + heap_free(enumerator); + return E_FAIL; + } - *collection = &This->IDWriteFontCollection_iface; + *ret = &enumerator->IDWriteFontFileEnumerator_iface; return S_OK; } +HRESULT get_system_fontcollection(IDWriteFactory *factory, IDWriteFontCollection **collection) +{ + IDWriteFontFileEnumerator *enumerator; + HRESULT hr; + + *collection = NULL; + + hr = create_system_fontfile_enumerator(factory, &enumerator); + if (FAILED(hr)) + return hr; + + TRACE("building system font collection for factory %p\n", factory); + hr = create_font_collection(factory, enumerator, collection); + IDWriteFontFileEnumerator_Release(enumerator); + return hr; +} + static HRESULT create_fontfamily_from_data(struct dwrite_fontfamily_data *data, IDWriteFontCollection *collection, IDWriteFontFamily **family) { struct dwrite_fontfamily *This; @@ -1870,35 +1700,6 @@ static HRESULT create_fontfamily_from_data(struct dwrite_fontfamily_data *data, return S_OK; } -static HRESULT create_fontfamily(IDWriteLocalizedStrings *familyname, IDWriteFontFamily **family) -{ - struct dwrite_fontfamily_data *data; - HRESULT ret; - - data = heap_alloc(sizeof(struct dwrite_fontfamily_data)); - if (!data) return E_OUTOFMEMORY; - - data->ref = 0; - data->font_count = 0; - data->font_alloc = 2; - data->fonts = heap_alloc(sizeof(*data->fonts) * 2); - if (!data->fonts) - { - heap_free(data); - return E_OUTOFMEMORY; - } - data->familyname = familyname; - - ret = create_fontfamily_from_data(data, NULL, family); - if (FAILED(ret)) - { - heap_free(data->fonts); - heap_free(data); - } - - return ret; -} - static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFontFamily *family, DWRITE_FONT_SIMULATIONS simulations, IDWriteFont **font) { @@ -1913,7 +1714,6 @@ static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFontF This->family = family; if (family) IDWriteFontFamily_AddRef(family); - This->is_system = FALSE; This->simulations = simulations; This->data = data; InterlockedIncrement(&This->data->ref); @@ -2088,7 +1888,6 @@ HRESULT create_fontface(DWRITE_FONT_FACE_TYPE facetype, UINT32 files_number, IDW fontface->index = index; fontface->simulations = simulations; - fontface->is_system = FALSE; *ret = &fontface->IDWriteFontFace2_iface; return S_OK; diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index 05d853f..a523de0 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -563,7 +563,7 @@ static HRESULT WINAPI dwritefactory_GetSystemFontCollection(IDWriteFactory *ifac FIXME("checking for system font updates not implemented\n"); if (!This->system_collection) - hr = get_system_fontcollection(&This->system_collection); + hr = get_system_fontcollection(iface, &This->system_collection); if (SUCCEEDED(hr)) IDWriteFontCollection_AddRef(This->system_collection); diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 7debdda..3ddfb06 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -309,8 +309,14 @@ todo_wine { EXPECT_HR(hr, S_OK); weight = IDWriteFont_GetWeight(font); + if (weights[i][1] == DWRITE_FONT_WEIGHT_BOLD) + todo_wine ok(weight == weights[i][1], "%d: got %d, expected %d\n", i, weight, weights[i][1]); + else + ok(weight == weights[i][1], + "%d: got %d, expected %d\n", i, weight, weights[i][1]); + IDWriteFont_Release(font); } @@ -574,21 +580,16 @@ if (0) /* crashes on native */ collection = NULL; hr = IDWriteFontFamily_GetFontCollection(family, &collection); -todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); collection2 = NULL; hr = IDWriteFontFamily_GetFontCollection(family2, &collection2); -todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); ok(collection == collection2, "got %p, %p\n", collection, collection2); -todo_wine ok(collection == syscoll, "got %p, %p\n", collection, syscoll); IDWriteFontCollection_Release(syscoll); -if (collection2) IDWriteFontCollection_Release(collection2); -if (collection) IDWriteFontCollection_Release(collection); IDWriteFontFamily_Release(family2); IDWriteFontFamily_Release(family); @@ -745,7 +746,6 @@ if (0) /* crashes on native */ fontface2 = NULL; hr = IDWriteFont_CreateFontFace(font2, &fontface2); ok(hr == S_OK, "got 0x%08x\n", hr); -todo_wine ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface); IDWriteFontFace_Release(fontface2); @@ -783,7 +783,6 @@ todo_wine fontface2 = NULL; hr = IDWriteFont_CreateFontFace(font2, &fontface2); ok(hr == S_OK, "got 0x%08x\n", hr); -todo_wine ok(fontface == fontface2, "got %p, was %p\n", fontface2, fontface); IDWriteFontFace_Release(fontface); @@ -925,10 +924,8 @@ static void test_system_fontcollection(void) file = NULL; hr = IDWriteFontFace_GetFiles(fontface, &i, &file); ok(hr == S_OK, "got 0x%08x\n", hr); -todo_wine ok(file != NULL, "got %p\n", file); -if (file) { hr = IDWriteFontFile_GetLoader(file, &loader); ok(hr == S_OK, "got 0x%08x\n", hr); IDWriteFontFile_Release(file); @@ -956,7 +953,7 @@ if (file) { IDWriteFactory_Release(factory2); IDWriteFontFileLoader_Release(loader); -} + ret = TRUE; i = 0; hr = IDWriteFontCollection_FindFamilyName(collection, blahW, &i, &ret); @@ -1013,10 +1010,8 @@ if (0) /* crashes on native */ ok(hr == S_OK, "got 0x%08x\n", hr); ok(logfont.lfHeight == 0, "got %d\n", logfont.lfHeight); ok(logfont.lfWidth == 0, "got %d\n", logfont.lfWidth); -todo_wine ok(logfont.lfWeight == FW_NORMAL, "got %d\n", logfont.lfWeight); ok(logfont.lfEscapement == 0, "got %d\n", logfont.lfEscapement); -todo_wine ok(logfont.lfItalic == 1, "got %d\n", logfont.lfItalic); ok(logfont.lfUnderline == 0, "got %d\n", logfont.lfUnderline); ok(logfont.lfStrikeOut == 0, "got %d\n", logfont.lfStrikeOut); @@ -1439,36 +1434,26 @@ static void test_GetFontFromFontFace(void) font2 = NULL; hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font2); -todo_wine ok(hr == S_OK, "got 0x%08x\n", hr); ok(font2 != font, "got %p, %p\n", font2, font); font3 = NULL; hr = IDWriteFontCollection_GetFontFromFontFace(collection, fontface, &font3); -todo_wine { ok(hr == S_OK, "got 0x%08x\n", hr); ok(font3 != font && font3 != font2, "got %p, %p, %p\n", font3, font2, font); -} -if (font2) { hr = IDWriteFont_CreateFontFace(font2, &fontface2); ok(hr == S_OK, "got 0x%08x\n", hr); ok(fontface2 == fontface, "got %p, %p\n", fontface2, fontface); IDWriteFontFace_Release(fontface2); -} -if (font3) { hr = IDWriteFont_CreateFontFace(font3, &fontface2); ok(hr == S_OK, "got 0x%08x\n", hr); ok(fontface2 == fontface, "got %p, %p\n", fontface2, fontface); IDWriteFontFace_Release(fontface2); -} -if (font) IDWriteFont_Release(font); -if (font2) IDWriteFont_Release(font2); -if (font3) IDWriteFont_Release(font3); IDWriteFontFace_Release(fontface); IDWriteFontFamily_Release(family); @@ -1555,28 +1540,25 @@ static void test_GetInformationalStrings(void) ok(exists == FALSE, "got %d\n", exists); ok(strings == NULL, "got %p\n", strings); - exists = FALSE; - strings = NULL; - hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &exists); - ok(hr == S_OK, "got 0x%08x\n", hr); - ok(exists == TRUE, "got %d\n", exists); - exists = TRUE; strings = NULL; hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_NONE, &strings, &exists); ok(hr == S_OK, "got 0x%08x\n", hr); ok(exists == FALSE, "got %d\n", exists); + exists = FALSE; + strings = NULL; + hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings, &exists); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(exists == TRUE, "got %d\n", exists); + /* strings instance is not reused */ strings2 = NULL; hr = IDWriteFont_GetInformationalStrings(font, DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &strings2, &exists); ok(hr == S_OK, "got 0x%08x\n", hr); -todo_wine ok(strings2 != strings, "got %p, %p\n", strings2, strings); -if (strings) IDWriteLocalizedStrings_Release(strings); -if (strings2) IDWriteLocalizedStrings_Release(strings2); IDWriteFont_Release(font); IDWriteFontFamily_Release(family); -- 2.1.1