From: Nikolay Sivov Subject: [PATCH 2/3] dwrite: Implement CreateFontFromLOGFONT() on top of system font collection Message-Id: <544496B9.70400@codeweavers.com> Date: Mon, 20 Oct 2014 08:59:37 +0400 --- From b12ca540af0b5f1e0eec2bf2407e185dee77b5a4 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Mon, 20 Oct 2014 00:25:26 +0400 Subject: [PATCH 2/3] dwrite: Implement CreateFontFromLOGFONT() on top of system font collection --- dlls/dwrite/dwrite_private.h | 1 - dlls/dwrite/font.c | 246 +++++++++++++++++++++---------------------- dlls/dwrite/gdiinterop.c | 38 ++++++- dlls/dwrite/tests/font.c | 20 ++-- 4 files changed, 167 insertions(+), 138 deletions(-) diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index 64c2be1..dad9ec8 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -89,7 +89,6 @@ static inline unsigned short get_table_entry(const unsigned short *table, WCHAR return table[table[table[ch >> 8] + ((ch >> 4) & 0x0f)] + (ch & 0xf)]; } -extern HRESULT create_font_from_logfont(const LOGFONTW*, IDWriteFont**) DECLSPEC_HIDDEN; extern HRESULT convert_fontface_to_logfont(IDWriteFontFace*, LOGFONTW*) DECLSPEC_HIDDEN; extern HRESULT create_numbersubstitution(DWRITE_NUMBER_SUBSTITUTION_METHOD,const WCHAR *locale,BOOL,IDWriteNumberSubstitution**) DECLSPEC_HIDDEN; extern HRESULT create_textformat(const WCHAR*,IDWriteFontCollection*,DWRITE_FONT_WEIGHT,DWRITE_FONT_STYLE,DWRITE_FONT_STRETCH, diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index fc13941..e3b4f3c 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -749,6 +749,129 @@ static HRESULT get_fontface_from_font(struct dwrite_font *font, IDWriteFontFace2 return S_OK; } +static HRESULT create_font_base(IDWriteFont **font) +{ + struct dwrite_font_data *data; + HRESULT ret; + + *font = NULL; + data = heap_alloc(sizeof(*data)); + if (!data) return E_OUTOFMEMORY; + + data->ref = 0; + data->face_data = NULL; + + ret = create_font_from_data( data, NULL, 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->data->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); @@ -1404,129 +1527,6 @@ static HRESULT create_font_from_data(struct dwrite_font_data *data, IDWriteFontF return S_OK; } -static HRESULT create_font_base(IDWriteFont **font) -{ - struct dwrite_font_data *data; - HRESULT ret; - - *font = NULL; - data = heap_alloc(sizeof(*data)); - if (!data) return E_OUTOFMEMORY; - - data->ref = 0; - data->face_data = NULL; - - ret = create_font_from_data( data, NULL, font ); - if (FAILED(ret)) heap_free( data ); - return ret; -} - -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->data->simulations = DWRITE_FONT_SIMULATIONS_NONE; - This->data->facename = heap_strdupW(logfont->lfFaceName); - - return S_OK; -} - static HRESULT WINAPI dwritefontfile_QueryInterface(IDWriteFontFile *iface, REFIID riid, void **obj) { struct dwrite_fontfile *This = impl_from_IDWriteFontFile(iface); diff --git a/dlls/dwrite/gdiinterop.c b/dlls/dwrite/gdiinterop.c index 9c3d61e..43ab60f 100644 --- a/dlls/dwrite/gdiinterop.c +++ b/dlls/dwrite/gdiinterop.c @@ -271,11 +271,47 @@ static HRESULT WINAPI gdiinterop_CreateFontFromLOGFONT(IDWriteGdiInterop *iface, LOGFONTW const *logfont, IDWriteFont **font) { struct gdiinterop *This = impl_from_IDWriteGdiInterop(iface); + IDWriteFontCollection *collection; + IDWriteFontFamily *family; + DWRITE_FONT_STYLE style; + BOOL exists = FALSE; + UINT32 index; + HRESULT hr; + TRACE("(%p)->(%p %p)\n", This, logfont, font); + *font = NULL; + if (!logfont) return E_INVALIDARG; - return create_font_from_logfont(logfont, font); + hr = IDWriteFactory_GetSystemFontCollection(This->factory, &collection, FALSE); + if (FAILED(hr)) { + ERR("failed to get system font collection: 0x%08x.\n", hr); + return hr; + } + + hr = IDWriteFontCollection_FindFamilyName(collection, logfont->lfFaceName, &index, &exists); + if (FAILED(hr)) { + IDWriteFontCollection_Release(collection); + goto done; + } + + if (!exists) { + hr = DWRITE_E_NOFONT; + goto done; + } + + hr = IDWriteFontCollection_GetFontFamily(collection, index, &family); + if (FAILED(hr)) + goto done; + + style = logfont->lfItalic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; + hr = IDWriteFontFamily_GetFirstMatchingFont(family, logfont->lfWeight, DWRITE_FONT_STRETCH_NORMAL, style, font); + IDWriteFontFamily_Release(family); + +done: + IDWriteFontCollection_Release(collection); + return hr; } static HRESULT WINAPI gdiinterop_ConvertFontToLOGFONT(IDWriteGdiInterop *iface, diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index e27740a..1e46b52 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -312,8 +312,9 @@ todo_wine { logfont.lfWeight = 550; lstrcpyW(logfont.lfFaceName, tahomaW); + font = NULL; hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font); - EXPECT_HR(hr, S_OK); + ok(hr == S_OK, "got 0x%08x\n", hr); weight = IDWriteFont_GetWeight(font); ok(weight == DWRITE_FONT_WEIGHT_NORMAL || broken(weight == DWRITE_FONT_WEIGHT_BOLD) /* win7 w/o SP */, @@ -329,12 +330,10 @@ todo_wine { font = (void*)0xdeadbeef; hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font); -todo_wine { - EXPECT_HR(hr, DWRITE_E_NOFONT); + ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr); ok(font == NULL, "got %p\n", font); - if(font) IDWriteFont_Release(font); -} + /* Try with name 'Tahoma ' */ memset(&logfont, 0, sizeof(logfont)); logfont.lfHeight = 12; logfont.lfWidth = 12; @@ -343,12 +342,10 @@ todo_wine { font = (void*)0xdeadbeef; hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font); -todo_wine { - EXPECT_HR(hr, DWRITE_E_NOFONT); + ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr); ok(font == NULL, "got %p\n", font); - if(font) IDWriteFont_Release(font); -} + /* empty string as a facename */ memset(&logfont, 0, sizeof(logfont)); logfont.lfHeight = 12; logfont.lfWidth = 12; @@ -356,11 +353,8 @@ todo_wine { font = (void*)0xdeadbeef; hr = IDWriteGdiInterop_CreateFontFromLOGFONT(interop, &logfont, &font); -todo_wine { - EXPECT_HR(hr, DWRITE_E_NOFONT); + ok(hr == DWRITE_E_NOFONT, "got 0x%08x\n", hr); ok(font == NULL, "got %p\n", font); - if(font) IDWriteFont_Release(font); -} IDWriteGdiInterop_Release(interop); } -- 2.1.1