[PATCH 3/4] dwrite: Implement GetFont() for matching list

Nikolay Sivov nsivov at codeweavers.com
Tue Sep 8 03:41:28 CDT 2015


---

-------------- next part --------------
From c44114e4d8d0cc8c988f0c63164d0c6e2491c074 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Tue, 8 Sep 2015 11:30:18 +0300
Subject: [PATCH 3/4] 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 2129094..aea35c9 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.1.4



More information about the wine-patches mailing list