From 9c198982174d30e7fc933aeb526d8e508ba39940 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 8 Sep 2015 11:41:28 +0300 Subject: [PATCH] dwrite: Implement GetFont() for matching list. --- dlls/dwrite/font.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 4 deletions(-) diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 212909467e9..aea35c93811 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -97,6 +97,10 @@ struct dwrite_font_data { struct dwrite_fontlist { IDWriteFontList IDWriteFontList_iface; LONG ref; + + IDWriteFontFamily *family; + struct dwrite_font_data **fonts; + UINT32 font_count; }; struct dwrite_fontfamily_data { @@ -1495,6 +1499,11 @@ static ULONG WINAPI dwritefontlist_Release(IDWriteFontList *iface) TRACE("(%p)->(%d)\n", This, ref); if (!ref) { + UINT32 i; + + for (i = 0; i < This->font_count; i++) + release_font_data(This->fonts[i]); + IDWriteFontFamily_Release(This->family); heap_free(This); } @@ -1513,19 +1522,25 @@ static HRESULT WINAPI dwritefontlist_GetFontCollection(IDWriteFontList *iface, I static UINT32 WINAPI dwritefontlist_GetFontCount(IDWriteFontList *iface) { struct dwrite_fontlist *This = impl_from_IDWriteFontList(iface); - FIXME("(%p): stub\n", This); - return 0; + TRACE("(%p)\n", This); + return This->font_count; } static HRESULT WINAPI dwritefontlist_GetFont(IDWriteFontList *iface, UINT32 index, IDWriteFont **font) { struct dwrite_fontlist *This = impl_from_IDWriteFontList(iface); - FIXME("(%p)->(%u %p): stub\n", This, index, font); + TRACE("(%p)->(%u %p)\n", This, index, font); *font = NULL; - return E_NOTIMPL; + if (This->font_count == 0) + return S_FALSE; + + if (index >= This->font_count) + return E_INVALIDARG; + + return create_font(This->fonts[index], This->family, font); } static const IDWriteFontListVtbl dwritefontlistvtbl = { @@ -1687,11 +1702,48 @@ static HRESULT WINAPI dwritefontfamily_GetFirstMatchingFont(IDWriteFontFamily *i return create_font(match, iface, font); } +typedef BOOL (*matching_filter_func)(const struct dwrite_font_data*); + +static BOOL is_font_acceptable_for_normal(const struct dwrite_font_data *font) +{ + return font->style == DWRITE_FONT_STYLE_NORMAL || font->style == DWRITE_FONT_STYLE_ITALIC; +} + +static BOOL is_font_acceptable_for_oblique_italic(const struct dwrite_font_data *font) +{ + return font->style == DWRITE_FONT_STYLE_OBLIQUE || font->style == DWRITE_FONT_STYLE_ITALIC; +} + +static void matchingfonts_sort(struct dwrite_fontlist *fonts, const struct dwrite_font_propvec *req) +{ + UINT32 b = fonts->font_count - 1, j, t; + + while (1) { + t = b; + + for (j = 0; j < b; j++) { + if (is_better_font_match(&fonts->fonts[j+1]->propvec, &fonts->fonts[j]->propvec, req)) { + struct dwrite_font_data *s = fonts->fonts[j]; + fonts->fonts[j] = fonts->fonts[j+1]; + fonts->fonts[j+1] = s; + t = j; + } + } + + if (t == b) + break; + b = t; + }; +} + static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface, DWRITE_FONT_WEIGHT weight, DWRITE_FONT_STRETCH stretch, DWRITE_FONT_STYLE style, IDWriteFontList **ret) { struct dwrite_fontfamily *This = impl_from_IDWriteFontFamily(iface); + matching_filter_func func = NULL; + struct dwrite_font_propvec req; struct dwrite_fontlist *fonts; + UINT32 i; TRACE("(%p)->(%d %d %d %p)\n", This, weight, stretch, style, ret); @@ -1700,8 +1752,41 @@ static HRESULT WINAPI dwritefontfamily_GetMatchingFonts(IDWriteFontFamily *iface fonts = heap_alloc(sizeof(*fonts)); if (!fonts) return E_OUTOFMEMORY; + + /* Allocate as many as family has, not all of them will be necessary used. */ + fonts->fonts = heap_alloc(sizeof(*fonts->fonts) * This->data->font_count); + if (!fonts->fonts) { + heap_free(fonts); + return E_OUTOFMEMORY; + } + fonts->IDWriteFontList_iface.lpVtbl = &dwritefontlistvtbl; fonts->ref = 1; + fonts->family = iface; + IDWriteFontFamily_AddRef(fonts->family); + fonts->font_count = 0; + + /* Normal style accepts Normal or Italic, Oblique and Italic - both Oblique and Italic styles */ + if (style == DWRITE_FONT_STYLE_NORMAL) { + if (This->data->has_normal_face || This->data->has_italic_face) + func = is_font_acceptable_for_normal; + } + else /* requested oblique or italic */ { + if (This->data->has_oblique_face || This->data->has_italic_face) + func = is_font_acceptable_for_oblique_italic; + } + + for (i = 0; i < This->data->font_count; i++) { + if (!func || func(This->data->fonts[i])) { + fonts->fonts[fonts->font_count] = This->data->fonts[i]; + InterlockedIncrement(&This->data->fonts[i]->ref); + fonts->font_count++; + } + } + + /* now potential matches are sorted using same criteria GetFirstMatchingFont uses */ + init_font_prop_vec(weight, stretch, style, &req); + matchingfonts_sort(fonts, &req); *ret = &fonts->IDWriteFontList_iface; return S_OK; -- 2.11.4.GIT