[PATCH 9/9] dwrite: Implement newer GetSystemFontCollection() variants.

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


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/dwrite_private.h |   4 +-
 dlls/dwrite/font.c           |  28 +++++++---
 dlls/dwrite/main.c           | 100 +++++++++++++++++++++++------------
 dlls/dwrite/tests/font.c     |   5 +-
 4 files changed, 90 insertions(+), 47 deletions(-)

diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h
index 60e8b87f499..fdc916adc40 100644
--- a/dlls/dwrite/dwrite_private.h
+++ b/dlls/dwrite/dwrite_private.h
@@ -299,7 +299,8 @@ extern void    set_en_localizedstring(IDWriteLocalizedStrings*,const WCHAR*) DEC
 extern void    sort_localizedstrings(IDWriteLocalizedStrings*) DECLSPEC_HIDDEN;
 extern unsigned int get_localizedstrings_count(IDWriteLocalizedStrings *strings) DECLSPEC_HIDDEN;
 extern BOOL localizedstrings_contains(IDWriteLocalizedStrings *strings, const WCHAR *str) DECLSPEC_HIDDEN;
-extern HRESULT get_system_fontcollection(IDWriteFactory7 *factory, IDWriteFontCollection1 **collection) DECLSPEC_HIDDEN;
+extern HRESULT get_system_fontcollection(IDWriteFactory7 *factory, DWRITE_FONT_FAMILY_MODEL family_model,
+        IDWriteFontCollection **collection) DECLSPEC_HIDDEN;
 extern HRESULT get_eudc_fontcollection(IDWriteFactory7 *factory, IDWriteFontCollection3 **collection) DECLSPEC_HIDDEN;
 extern IDWriteTextAnalyzer2 *get_text_analyzer(void) DECLSPEC_HIDDEN;
 extern HRESULT create_font_file(IDWriteFontFileLoader *loader, const void *reference_key, UINT32 key_size, IDWriteFontFile **font_file) DECLSPEC_HIDDEN;
@@ -349,6 +350,7 @@ extern HRESULT compute_glyph_origins(DWRITE_GLYPH_RUN const *run, DWRITE_MEASURI
         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;
+extern HRESULT create_system_fontset(IDWriteFactory7 *factory, REFIID riid, void **obj) DECLSPEC_HIDDEN;
 
 struct dwrite_fontface;
 
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 23dad8970b8..385c7fdeb03 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -5092,20 +5092,34 @@ static HRESULT create_system_fontfile_enumerator(IDWriteFactory7 *factory, IDWri
     return S_OK;
 }
 
-HRESULT get_system_fontcollection(IDWriteFactory7 *factory, IDWriteFontCollection1 **collection)
+HRESULT get_system_fontcollection(IDWriteFactory7 *factory, DWRITE_FONT_FAMILY_MODEL family_model,
+        IDWriteFontCollection **collection)
 {
     IDWriteFontFileEnumerator *enumerator;
+    IDWriteFontSet *fontset;
     HRESULT hr;
 
     *collection = NULL;
 
-    hr = create_system_fontfile_enumerator(factory, &enumerator);
-    if (FAILED(hr))
-        return hr;
+    if (family_model == DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC)
+    {
+        if (SUCCEEDED(hr = create_system_fontset(factory, &IID_IDWriteFontSet, (void **)&fontset)))
+        {
+            hr = create_font_collection_from_set(factory, fontset, family_model,
+                    &IID_IDWriteFontCollection, (void **)collection);
+            IDWriteFontSet_Release(fontset);
+        }
+    }
+    else
+    {
+        if (SUCCEEDED(hr = create_system_fontfile_enumerator(factory, &enumerator)))
+        {
+            TRACE("Building system font collection for factory %p.\n", factory);
+            hr = create_font_collection(factory, enumerator, TRUE, (IDWriteFontCollection3 **)collection);
+            IDWriteFontFileEnumerator_Release(enumerator);
+        }
+    }
 
-    TRACE("building system font collection for factory %p\n", factory);
-    hr = create_font_collection(factory, enumerator, TRUE, (IDWriteFontCollection3 **)collection);
-    IDWriteFontFileEnumerator_Release(enumerator);
     return hr;
 }
 
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index 4d7d6a7eab0..01b47e673bb 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -598,7 +598,7 @@ struct dwritefactory
     IDWriteFactory7 IDWriteFactory7_iface;
     LONG refcount;
 
-    IDWriteFontCollection1 *system_collection;
+    IDWriteFontCollection *system_collections[DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE + 1];
     IDWriteFontCollection1 *eudc_collection;
     IDWriteGdiInterop1 *gdiinterop;
     IDWriteFontFallback1 *fallback;
@@ -640,6 +640,7 @@ static void release_dwritefactory(struct dwritefactory *factory)
 {
     struct fileloader *fileloader, *fileloader2;
     struct collectionloader *loader, *loader2;
+    unsigned int i;
 
     EnterCriticalSection(&factory->cs);
     release_fontface_cache(&factory->localfontfaces);
@@ -654,8 +655,11 @@ static void release_dwritefactory(struct dwritefactory *factory)
     LIST_FOR_EACH_ENTRY_SAFE(fileloader, fileloader2, &factory->file_loaders, struct fileloader, entry)
         release_fileloader(fileloader);
 
-    if (factory->system_collection)
-        IDWriteFontCollection1_Release(factory->system_collection);
+    for (i = 0; i < ARRAY_SIZE(factory->system_collections); ++i)
+    {
+        if (factory->system_collections[i])
+            IDWriteFontCollection_Release(factory->system_collections[i]);
+    }
     if (factory->eudc_collection)
         IDWriteFontCollection1_Release(factory->eudc_collection);
     if (factory->fallback)
@@ -703,26 +707,35 @@ static struct collectionloader *factory_get_collection_loader(struct dwritefacto
     return found;
 }
 
-static IDWriteFontCollection1 *factory_get_system_collection(struct dwritefactory *factory)
+static HRESULT factory_get_system_collection(struct dwritefactory *factory,
+        DWRITE_FONT_FAMILY_MODEL family_model, REFIID riid, void **out)
 {
-    IDWriteFontCollection1 *collection;
+    IDWriteFontCollection *collection;
     HRESULT hr;
 
-    if (factory->system_collection) {
-        IDWriteFontCollection1_AddRef(factory->system_collection);
-        return factory->system_collection;
+    *out = NULL;
+
+    if (family_model != DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC &&
+            family_model != DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE)
+    {
+        return E_INVALIDARG;
     }
 
-    if (FAILED(hr = get_system_fontcollection(&factory->IDWriteFactory7_iface, &collection)))
+    if (factory->system_collections[family_model])
+        return IDWriteFontCollection_QueryInterface(factory->system_collections[family_model], riid, out);
+
+    if (FAILED(hr = get_system_fontcollection(&factory->IDWriteFactory7_iface, family_model, &collection)))
     {
         WARN("Failed to create system font collection, hr %#lx.\n", hr);
-        return NULL;
+        return hr;
     }
 
-    if (InterlockedCompareExchangePointer((void **)&factory->system_collection, collection, NULL))
-        IDWriteFontCollection1_Release(collection);
+    if (InterlockedCompareExchangePointer((void **)&factory->system_collections[family_model], collection, NULL))
+        IDWriteFontCollection_Release(collection);
 
-    return factory->system_collection;
+    hr = IDWriteFontCollection_QueryInterface(factory->system_collections[family_model], riid, out);
+    IDWriteFontCollection_Release(factory->system_collections[family_model]);
+    return hr;
 }
 
 static HRESULT WINAPI dwritefactory_QueryInterface(IDWriteFactory7 *iface, REFIID riid, void **obj)
@@ -773,10 +786,17 @@ static ULONG WINAPI dwritefactory_Release(IDWriteFactory7 *iface)
 }
 
 static HRESULT WINAPI dwritefactory_GetSystemFontCollection(IDWriteFactory7 *iface,
-    IDWriteFontCollection **collection, BOOL check_for_updates)
+        IDWriteFontCollection **collection, BOOL check_for_updates)
 {
-    return IDWriteFactory5_GetSystemFontCollection((IDWriteFactory5 *)iface, FALSE, (IDWriteFontCollection1 **)collection,
-            check_for_updates);
+    struct dwritefactory *factory = impl_from_IDWriteFactory7(iface);
+
+    TRACE("%p, %p, %d.\n", iface, collection, check_for_updates);
+
+    if (check_for_updates)
+        FIXME("checking for system font updates not implemented\n");
+
+    return factory_get_system_collection(factory, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE,
+            &IID_IDWriteFontCollection, (void **)collection);
 }
 
 static HRESULT WINAPI dwritefactory_CreateCustomFontCollection(IDWriteFactory7 *iface,
@@ -1167,14 +1187,16 @@ static HRESULT WINAPI dwritefactory_CreateTextFormat(IDWriteFactory7 *iface, WCH
     TRACE("%p, %s, %p, %d, %d, %d, %.8e, %s, %p.\n", iface, debugstr_w(family_name), collection, weight, style, stretch,
         size, debugstr_w(locale), format);
 
+    *format = NULL;
+
     if (collection)
+    {
         IDWriteFontCollection_AddRef(collection);
-    else {
-        collection = (IDWriteFontCollection *)factory_get_system_collection(factory);
-        if (!collection) {
-            *format = NULL;
-            return E_FAIL;
-        }
+    }
+    else if (FAILED(hr = factory_get_system_collection(factory, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE,
+                &IID_IDWriteFontCollection, (void **)&collection)))
+    {
+        return hr;
     }
 
     hr = create_textformat(family_name, collection, weight, style, stretch, size, locale, format);
@@ -1611,7 +1633,7 @@ static int __cdecl create_system_fontset_compare(const void *left, const void *r
     return wcsicmp(_l, _r);
 };
 
-static HRESULT create_system_fontset(IDWriteFactory7 *factory, REFIID riid, void **obj)
+HRESULT create_system_fontset(IDWriteFactory7 *factory, REFIID riid, void **obj)
 {
     IDWriteFontSetBuilder2 *builder;
     IDWriteFontSet *fontset;
@@ -1691,9 +1713,8 @@ static HRESULT WINAPI dwritefactory3_GetSystemFontCollection(IDWriteFactory7 *if
     if (check_for_updates)
         FIXME("checking for system font updates not implemented\n");
 
-    *collection = factory_get_system_collection(factory);
-
-    return *collection ? S_OK : E_FAIL;
+    return factory_get_system_collection(factory, DWRITE_FONT_FAMILY_MODEL_WEIGHT_STRETCH_STYLE,
+            &IID_IDWriteFontCollection1, (void **)collection);
 }
 
 static HRESULT WINAPI dwritefactory3_GetFontDownloadQueue(IDWriteFactory7 *iface, IDWriteFontDownloadQueue **queue)
@@ -1849,9 +1870,14 @@ static HRESULT WINAPI dwritefactory6_GetSystemFontSet(IDWriteFactory7 *iface, BO
 static HRESULT WINAPI dwritefactory6_GetSystemFontCollection(IDWriteFactory7 *iface, BOOL include_downloadable,
         DWRITE_FONT_FAMILY_MODEL family_model, IDWriteFontCollection2 **collection)
 {
-    FIXME("%p, %d, %d, %p.\n", iface, include_downloadable, family_model, collection);
+    struct dwritefactory *factory = impl_from_IDWriteFactory7(iface);
 
-    return E_NOTIMPL;
+    TRACE("%p, %d, %d, %p.\n", iface, include_downloadable, family_model, collection);
+
+    if (include_downloadable)
+        FIXME("remote fonts are not supported\n");
+
+    return factory_get_system_collection(factory, family_model, &IID_IDWriteFontCollection2, (void **)collection);
 }
 
 static HRESULT WINAPI dwritefactory6_CreateFontCollectionFromFontSet(IDWriteFactory7 *iface, IDWriteFontSet *fontset,
@@ -1893,9 +1919,14 @@ static HRESULT WINAPI dwritefactory7_GetSystemFontSet(IDWriteFactory7 *iface, BO
 static HRESULT WINAPI dwritefactory7_GetSystemFontCollection(IDWriteFactory7 *iface, BOOL include_downloadable,
         DWRITE_FONT_FAMILY_MODEL family_model, IDWriteFontCollection3 **collection)
 {
-    FIXME("%p, %d, %d, %p.\n", iface, include_downloadable, family_model, collection);
+    struct dwritefactory *factory = impl_from_IDWriteFactory7(iface);
 
-    return E_NOTIMPL;
+    TRACE("%p, %d, %d, %p.\n", iface, include_downloadable, family_model, collection);
+
+    if (include_downloadable)
+        FIXME("remote fonts are not supported\n");
+
+    return factory_get_system_collection(factory, family_model, &IID_IDWriteFontCollection3, (void **)collection);
 }
 
 static const IDWriteFactory7Vtbl dwritefactoryvtbl =
@@ -2040,10 +2071,6 @@ static void init_dwritefactory(struct dwritefactory *factory, DWRITE_FACTORY_TYP
             &shareddwritefactoryvtbl : &dwritefactoryvtbl;
     factory->refcount = 1;
     factory->localfontfileloader = get_local_fontfile_loader();
-    factory->system_collection = NULL;
-    factory->eudc_collection = NULL;
-    factory->gdiinterop = NULL;
-    factory->fallback = NULL;
 
     list_init(&factory->collection_loaders);
     list_init(&factory->file_loaders);
@@ -2056,7 +2083,10 @@ static void init_dwritefactory(struct dwritefactory *factory, DWRITE_FACTORY_TYP
 void factory_detach_fontcollection(IDWriteFactory7 *iface, IDWriteFontCollection3 *collection)
 {
     struct dwritefactory *factory = impl_from_IDWriteFactory7(iface);
-    InterlockedCompareExchangePointer((void **)&factory->system_collection, NULL, collection);
+    unsigned int i;
+
+    for (i = 0; i < ARRAY_SIZE(factory->system_collections); ++i)
+        InterlockedCompareExchangePointer((void **)&factory->system_collections[i], NULL, collection);
     InterlockedCompareExchangePointer((void **)&factory->eudc_collection, NULL, collection);
     IDWriteFactory7_Release(iface);
 }
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index 2ca1a5f9c81..81008db6f23 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -2654,10 +2654,8 @@ static void test_system_fontcollection(void)
 
         hr = IDWriteFactory6_GetSystemFontCollection(factory6, FALSE, DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC,
                 &collection2);
-    todo_wine
         ok(hr == S_OK, "Failed to get collection, hr %#lx.\n", hr);
-    if (SUCCEEDED(hr))
-    {
+
         hr = IDWriteFactory6_GetSystemFontCollection(factory6, FALSE, DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC, &c2);
         ok(hr == S_OK, "Failed to get collection, hr %#lx.\n", hr);
         ok(c2 == collection2 && collection != (IDWriteFontCollection *)c2, "Unexpected collection instance.\n");
@@ -2668,7 +2666,6 @@ static void test_system_fontcollection(void)
                 &collection2);
         ok(hr == S_OK, "Failed to get collection, hr %#lx.\n", hr);
         IDWriteFontCollection2_Release(collection2);
-    }
         IDWriteFactory6_Release(factory6);
     }
     else
-- 
2.35.1




More information about the wine-devel mailing list