dwrite: Implement GetFont() for matching list.

This commit is contained in:
Nikolay Sivov 2015-09-08 11:41:28 +03:00 committed by Alexandre Julliard
parent 42a99a8de5
commit 9c19898217
1 changed files with 89 additions and 4 deletions

View File

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