dwrite: Implement GetFont() for matching list.
This commit is contained in:
parent
42a99a8de5
commit
9c19898217
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue