[PATCH 8/9] dwrite: Initial implementation of CreateFontCollectionFromFontSet().

Nikolay Sivov nsivov at codeweavers.com
Mon Apr 25 05:31:48 CDT 2022


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/dwrite_private.h |   2 +
 dlls/dwrite/font.c           | 117 +++++++++++++++++++++++++++++++++++
 dlls/dwrite/main.c           |  11 ++--
 dlls/dwrite/tests/font.c     |  28 +++------
 4 files changed, 134 insertions(+), 24 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 35cf5add34b..60e8b87f499 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -347,6 +347,8 @@ extern HRESULT create_font_resource(IDWriteFactory7 *factory, IDWriteFontFile *f
 extern HRESULT create_fontset_builder(IDWriteFactory7 *factory, IDWriteFontSetBuilder2 **ret) DECLSPEC_HIDDEN;
 extern HRESULT compute_glyph_origins(DWRITE_GLYPH_RUN const *run, DWRITE_MEASURING_MODE measuring_mode,
         D2D1_POINT_2F baseline_origin, DWRITE_MATRIX const *transform, D2D1_POINT_2F *origins) DECLSPEC_HIDDEN;
+extern HRESULT create_font_collection_from_set(IDWriteFactory7 *factory, IDWriteFontSet *set,
+        DWRITE_FONT_FAMILY_MODEL family_model, REFGUID riid, void **ret) DECLSPEC_HIDDEN;
 
 struct dwrite_fontface;
 
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index e32b2d0f4cb..23dad8970b8 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -624,6 +624,8 @@ static struct dwrite_fontset *impl_from_IDWriteFontSet3(IDWriteFontSet3 *iface)
     return CONTAINING_RECORD(iface, struct dwrite_fontset, IDWriteFontSet3_iface);
 }
 
+static struct dwrite_fontset *unsafe_impl_from_IDWriteFontSet(IDWriteFontSet *iface);
+
 static HRESULT get_cached_glyph_metrics(struct dwrite_fontface *fontface, UINT16 glyph, DWRITE_GLYPH_METRICS *metrics)
 {
     static const DWRITE_GLYPH_METRICS nil;
@@ -4791,6 +4793,113 @@ HRESULT create_font_collection(IDWriteFactory7 *factory, IDWriteFontFileEnumerat
     return hr;
 }
 
+static HRESULT collection_add_font_entry(struct dwrite_fontcollection *collection, const struct fontface_desc *desc)
+{
+    struct dwrite_font_data *font_data;
+    WCHAR familyW[255];
+    UINT32 index;
+    HRESULT hr;
+
+    if (FAILED(hr = init_font_data(desc, collection->family_model, &font_data)))
+        return hr;
+
+    fontstrings_get_en_string(font_data->family_names, familyW, ARRAY_SIZE(familyW));
+
+    /* ignore dot named faces */
+    if (familyW[0] == '.')
+    {
+        WARN("Ignoring face %s\n", debugstr_w(familyW));
+        release_font_data(font_data);
+        return S_OK;
+    }
+
+    index = collection_find_family(collection, familyW);
+    if (index != ~0u)
+        hr = fontfamily_add_font(collection->family_data[index], font_data);
+    else
+    {
+        struct dwrite_fontfamily_data *family_data;
+
+        /* Create and initialize new family */
+        hr = init_fontfamily_data(font_data->family_names, &family_data);
+        if (hr == S_OK)
+        {
+            /* add font to family, family - to collection */
+            hr = fontfamily_add_font(family_data, font_data);
+            if (hr == S_OK)
+                hr = fontcollection_add_family(collection, family_data);
+
+            if (FAILED(hr))
+                release_fontfamily_data(family_data);
+        }
+    }
+
+    if (FAILED(hr))
+        release_font_data(font_data);
+
+    return hr;
+}
+
+HRESULT create_font_collection_from_set(IDWriteFactory7 *factory, IDWriteFontSet *fontset,
+        DWRITE_FONT_FAMILY_MODEL family_model, REFGUID riid, void **ret)
+{
+    struct dwrite_fontset *set = unsafe_impl_from_IDWriteFontSet(fontset);
+    struct dwrite_fontcollection *collection;
+    HRESULT hr = S_OK;
+    size_t i;
+
+    *ret = NULL;
+
+    if (!(collection = calloc(1, sizeof(*collection))))
+        return E_OUTOFMEMORY;
+
+    if (FAILED(hr = init_font_collection(collection, factory, family_model, FALSE)))
+    {
+        free(collection);
+        return hr;
+    }
+
+    for (i = 0; i < set->count; ++i)
+    {
+        const struct dwrite_fontset_entry *entry = set->entries[i];
+        IDWriteFontFileStream *stream;
+        struct fontface_desc desc;
+
+        if (FAILED(get_filestream_from_file(entry->desc.file, &stream)))
+        {
+            WARN("Failed to get file stream.\n");
+            continue;
+        }
+
+        desc.factory = factory;
+        desc.face_type = entry->desc.face_type;
+        desc.file = entry->desc.file;
+        desc.stream = stream;
+        desc.index = entry->desc.face_index;
+        desc.simulations = entry->desc.simulations;
+        desc.font_data = NULL;
+
+        if (FAILED(hr = collection_add_font_entry(collection, &desc)))
+            WARN("Failed to add font collection element, hr %#lx.\n", hr);
+
+        IDWriteFontFileStream_Release(stream);
+    }
+
+    if (family_model == DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE)
+    {
+        for (i = 0; i < collection->count; ++i)
+        {
+            fontfamily_add_bold_simulated_face(collection->family_data[i]);
+            fontfamily_add_oblique_simulated_face(collection->family_data[i]);
+        }
+    }
+
+    hr = IDWriteFontCollection3_QueryInterface(&collection->IDWriteFontCollection3_iface, riid, ret);
+    IDWriteFontCollection3_Release(&collection->IDWriteFontCollection3_iface);
+
+    return hr;
+}
+
 struct system_fontfile_enumerator
 {
     IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface;
@@ -7908,6 +8017,14 @@ static const IDWriteFontSet3Vtbl fontsetvtbl =
     dwritefontset3_GetFontSourceName,
 };
 
+static struct dwrite_fontset *unsafe_impl_from_IDWriteFontSet(IDWriteFontSet *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == (IDWriteFontSetVtbl *)&fontsetvtbl);
+    return CONTAINING_RECORD(iface, struct dwrite_fontset, IDWriteFontSet3_iface);
+}
+
 static HRESULT fontset_create_entry(IDWriteFontFile *file, DWRITE_FONT_FACE_TYPE face_type,
         unsigned int face_index, unsigned int simulations, struct dwrite_fontset_entry **ret)
 {
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 82dc34a0cdc..4d7d6a7eab0 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -1670,11 +1670,12 @@ static HRESULT WINAPI dwritefactory3_CreateFontSetBuilder(IDWriteFactory7 *iface
 }
 
 static HRESULT WINAPI dwritefactory3_CreateFontCollectionFromFontSet(IDWriteFactory7 *iface, IDWriteFontSet *fontset,
-    IDWriteFontCollection1 **collection)
+        IDWriteFontCollection1 **collection)
 {
-    FIXME("%p, %p, %p: stub\n", iface, fontset, collection);
+    TRACE("%p, %p, %p.\n", iface, fontset, collection);
 
-    return E_NOTIMPL;
+    return create_font_collection_from_set(iface, fontset, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE,
+            &IID_IDWriteFontCollection1, (void **)collection);
 }
 
 static HRESULT WINAPI dwritefactory3_GetSystemFontCollection(IDWriteFactory7 *iface, BOOL include_downloadable,
@@ -1856,9 +1857,9 @@ static HRESULT WINAPI dwritefactory6_GetSystemFontCollection(IDWriteFactory7 *if
 static HRESULT WINAPI dwritefactory6_CreateFontCollectionFromFontSet(IDWriteFactory7 *iface, IDWriteFontSet *fontset,
         DWRITE_FONT_FAMILY_MODEL family_model, IDWriteFontCollection2 **collection)
 {
-    FIXME("%p, %p, %d, %p.\n", iface, fontset, family_model, collection);
+    TRACE("%p, %p, %d, %p.\n", iface, fontset, family_model, collection);
 
-    return E_NOTIMPL;
+    return create_font_collection_from_set(iface, fontset, family_model, &IID_IDWriteFontCollection2, (void **)collection);
 }
 
 static HRESULT WINAPI dwritefactory6_CreateFontSetBuilder(IDWriteFactory7 *iface, IDWriteFontSetBuilder2 **builder)
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 3d4c4caad98..2ca1a5f9c81 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -9656,14 +9656,10 @@ static void test_fontsetbuilder(void)
         hr = IDWriteFontSetBuilder1_CreateFontSet(builder1, &fontset);
         ok(hr == S_OK, "Unexpected hr %#lx.\n",hr);
         hr = IDWriteFactory3_CreateFontCollectionFromFontSet(factory, fontset, &collection);
-        todo_wine
         ok(hr == S_OK, "Unexpected hr %#lx.\n",hr);
-        if (SUCCEEDED(hr))
-        {
-            count = IDWriteFontCollection1_GetFontFamilyCount(collection);
-            ok(count == 1, "Unexpected family count %u.\n", count);
-            IDWriteFontCollection1_Release(collection);
-        }
+        count = IDWriteFontCollection1_GetFontFamilyCount(collection);
+        ok(count == 1, "Unexpected family count %u.\n", count);
+        IDWriteFontCollection1_Release(collection);
         IDWriteFontSet_Release(fontset);
 
         hr = IDWriteFontSetBuilder1_AddFontFile(builder1, file);
@@ -9673,15 +9669,11 @@ static void test_fontsetbuilder(void)
         ok(hr == S_OK, "Unexpected hr %#lx.\n",hr);
 
         hr = IDWriteFactory3_CreateFontCollectionFromFontSet(factory, fontset, &collection);
-        todo_wine
         ok(hr == S_OK, "Unexpected hr %#lx.\n",hr);
-        if (SUCCEEDED(hr))
-        {
-            check_familymodel(collection, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE);
-            count = IDWriteFontCollection1_GetFontFamilyCount(collection);
-            ok(count == 1, "Unexpected family count %u.\n", count);
-            IDWriteFontCollection1_Release(collection);
-        }
+        check_familymodel(collection, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE);
+        count = IDWriteFontCollection1_GetFontFamilyCount(collection);
+        ok(count == 1, "Unexpected family count %u.\n", count);
+        IDWriteFontCollection1_Release(collection);
 
         /* No attempt to eliminate duplicates. */
         count = IDWriteFontSet_GetFontCount(fontset);
@@ -10405,22 +10397,20 @@ static void test_CreateFontCollectionFromFontSet(void)
     ok(hr == S_OK, "Unexpected hr %#lx.\n",hr);
 
     hr = IDWriteFactory5_CreateFontCollectionFromFontSet(factory, fontset, &collection);
-    todo_wine
     ok(hr == S_OK, "Unexpected hr %#lx.\n",hr);
 
-if (SUCCEEDED(hr))
-{
     count = IDWriteFontCollection1_GetFontFamilyCount(collection);
+    todo_wine
     ok(count == 2, "Unexpected family count %u.\n", count);
 
     /* Explicit fontset properties are prioritized and not replaced by actual properties from a file. */
     exists = FALSE;
     hr = IDWriteFontCollection1_FindFamilyName(collection, L"Another Font", &index, &exists);
     ok(hr == S_OK, "Unexpected hr %#lx.\n",hr);
+    todo_wine
     ok(!!exists, "Unexpected return value %d.\n", exists);
 
     IDWriteFontCollection1_Release(collection);
-}
     IDWriteFontSet_Release(fontset);
 
     IDWriteFontSetBuilder1_Release(builder);
-- 
2.35.1




More information about the wine-devel mailing list