[PATCH 3/3] dwrite: Implement EUDC font collection

Nikolay Sivov nsivov at codeweavers.com
Sun Dec 27 22:35:12 CST 2015


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/dwrite/font.c | 198 +++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 148 insertions(+), 50 deletions(-)

diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 9244978..89d50b3 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -3234,6 +3234,27 @@ static ULONG WINAPI systemfontfileenumerator_Release(IDWriteFontFileEnumerator *
     return ref;
 }
 
+static HRESULT create_local_file_reference(IDWriteFactory2 *factory, const WCHAR *filename, IDWriteFontFile **file)
+{
+    HRESULT hr;
+
+    /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
+    if (!strchrW(filename, '\\')) {
+        static const WCHAR fontsW[] = {'\\','f','o','n','t','s','\\',0};
+        WCHAR fullpathW[MAX_PATH];
+
+        GetWindowsDirectoryW(fullpathW, sizeof(fullpathW)/sizeof(WCHAR));
+        strcatW(fullpathW, fontsW);
+        strcatW(fullpathW, filename);
+
+        hr = IDWriteFactory2_CreateFontFileReference(factory, fullpathW, NULL, file);
+    }
+    else
+        hr = IDWriteFactory2_CreateFontFileReference(factory, filename, NULL, file);
+
+    return hr;
+}
+
 static HRESULT WINAPI systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator *iface, IDWriteFontFile **file)
 {
     struct system_fontfile_enumerator *enumerator = impl_from_IDWriteFontFileEnumerator(iface);
@@ -3266,19 +3287,7 @@ static HRESULT WINAPI systemfontfileenumerator_GetCurrentFontFile(IDWriteFontFil
         return E_FAIL;
     }
 
-    /* Fonts installed in 'Fonts' system dir don't get full path in registry font files cache */
-    if (!strchrW(filename, '\\')) {
-        static const WCHAR fontsW[] = {'\\','f','o','n','t','s','\\',0};
-        WCHAR fullpathW[MAX_PATH];
-
-        GetWindowsDirectoryW(fullpathW, sizeof(fullpathW)/sizeof(WCHAR));
-        strcatW(fullpathW, fontsW);
-        strcatW(fullpathW, filename);
-
-        hr = IDWriteFactory2_CreateFontFileReference(enumerator->factory, fullpathW, NULL, file);
-    }
-    else
-        hr = IDWriteFactory2_CreateFontFileReference(enumerator->factory, filename, NULL, file);
+    hr = create_local_file_reference(enumerator->factory, filename, file);
 
     heap_free(value);
     heap_free(filename);
@@ -3379,56 +3388,145 @@ HRESULT get_system_fontcollection(IDWriteFactory2 *factory, IDWriteFontCollectio
     return hr;
 }
 
-static HRESULT WINAPI eudcfontfileenumerator_QueryInterface(IDWriteFontFileEnumerator *iface, REFIID riid, void **obj)
+static HRESULT eudc_collection_add_family(IDWriteFactory2 *factory, struct dwrite_fontcollection *collection,
+    const WCHAR *keynameW, const WCHAR *pathW)
 {
-    *obj = NULL;
+    static const WCHAR defaultfontW[] = {'S','y','s','t','e','m','D','e','f','a','u','l','t','E','U','D','C','F','o','n','t',0};
+    static const WCHAR emptyW[] = {0};
+    IDWriteLocalizedStrings *names;
+    DWRITE_FONT_FACE_TYPE face_type;
+    DWRITE_FONT_FILE_TYPE file_type;
+    BOOL supported;
+    UINT32 face_count, i;
+    IDWriteFontFile *file;
+    HRESULT hr;
+    struct dwrite_fontfamily_data *family_data;
 
-    if (IsEqualIID(riid, &IID_IDWriteFontFileEnumerator) || IsEqualIID(riid, &IID_IUnknown)) {
-        IDWriteFontFileEnumerator_AddRef(iface);
-        *obj = iface;
-        return S_OK;
+    /* create font file from this path */
+    hr = create_local_file_reference(factory, pathW, &file);
+    if (FAILED(hr))
+        return S_FALSE;
+
+    /* failed font files are skipped */
+    hr = IDWriteFontFile_Analyze(file, &supported, &file_type, &face_type, &face_count);
+    if (FAILED(hr) || !supported || face_count == 0) {
+        TRACE("unsupported font (%p, 0x%08x, %d, %u)\n", file, hr, supported, face_count);
+        IDWriteFontFile_Release(file);
+        return S_FALSE;
     }
 
-    return E_NOINTERFACE;
-}
+    /* create and init new family */
 
-static ULONG WINAPI eudcfontfileenumerator_AddRef(IDWriteFontFileEnumerator *iface)
-{
-    return 2;
-}
+    /* Family names are added for non-specific locale, represented with empty string.
+       Default family appears with empty family name. */
+    create_localizedstrings(&names);
+    if (!strcmpiW(keynameW, defaultfontW))
+        add_localizedstring(names, emptyW, emptyW);
+    else
+        add_localizedstring(names, emptyW, keynameW);
 
-static ULONG WINAPI eudcfontfileenumerator_Release(IDWriteFontFileEnumerator *iface)
-{
-    return 1;
-}
+    hr = init_fontfamily_data(names, &family_data);
+    IDWriteLocalizedStrings_Release(names);
+    if (hr != S_OK) {
+        IDWriteFontFile_Release(file);
+        return hr;
+    }
 
-static HRESULT WINAPI eudcfontfileenumerator_GetCurrentFontFile(IDWriteFontFileEnumerator *iface, IDWriteFontFile **file)
-{
-    *file = NULL;
-    return E_FAIL;
-}
+    /* fill with faces */
+    for (i = 0; i < face_count; i++) {
+        struct dwrite_font_data *font_data;
 
-static HRESULT WINAPI eudcfontfileenumerator_MoveNext(IDWriteFontFileEnumerator *iface, BOOL *current)
-{
-    *current = FALSE;
-    return S_OK;
+        /* alloc and init new font data structure */
+        hr = init_font_data(factory, file, face_type, i, &names, &font_data);
+        if (FAILED(hr))
+            continue;
+
+        IDWriteLocalizedStrings_Release(names);
+
+        /* add font to family */
+        hr = fontfamily_add_font(family_data, font_data);
+        if (hr != S_OK)
+            release_font_data(font_data);
+    }
+
+    /* add family to collection */
+    hr = fontcollection_add_family(collection, family_data);
+    if (FAILED(hr))
+        release_fontfamily_data(family_data);
+    IDWriteFontFile_Release(file);
+
+    return hr;
 }
 
-static const struct IDWriteFontFileEnumeratorVtbl eudcfontfileenumeratorvtbl =
+HRESULT get_eudc_fontcollection(IDWriteFactory2 *factory, IDWriteFontCollection **ret)
 {
-    eudcfontfileenumerator_QueryInterface,
-    eudcfontfileenumerator_AddRef,
-    eudcfontfileenumerator_Release,
-    eudcfontfileenumerator_MoveNext,
-    eudcfontfileenumerator_GetCurrentFontFile
-};
+    static const WCHAR eudckeyfmtW[] = {'E','U','D','C','\\','%','u',0};
+    struct dwrite_fontcollection *collection;
+    static const WCHAR emptyW[] = {0};
+    WCHAR eudckeypathW[16];
+    HKEY eudckey;
+    DWORD index;
+    BOOL exists;
+    LONG retval;
+    HRESULT hr;
+    UINT32 i;
 
-static IDWriteFontFileEnumerator eudc_fontfile_enumerator = { &eudcfontfileenumeratorvtbl };
+    TRACE("building EUDC font collection for factory %p, ACP %u\n", factory, GetACP());
 
-HRESULT get_eudc_fontcollection(IDWriteFactory2 *factory, IDWriteFontCollection **collection)
-{
-    TRACE("building EUDC font collection for factory %p\n", factory);
-    return create_font_collection(factory, &eudc_fontfile_enumerator, FALSE, collection);
+    *ret = NULL;
+
+    collection = heap_alloc(sizeof(struct dwrite_fontcollection));
+    if (!collection) return E_OUTOFMEMORY;
+
+    hr = init_font_collection(collection, FALSE);
+    if (FAILED(hr)) {
+        heap_free(collection);
+        return hr;
+    }
+
+    *ret = &collection->IDWriteFontCollection_iface;
+
+    /* return empty collection if EUDC fonts are not configured */
+    sprintfW(eudckeypathW, eudckeyfmtW, GetACP());
+    if (RegOpenKeyExW(HKEY_CURRENT_USER, eudckeypathW, 0, GENERIC_READ, &eudckey))
+        return S_OK;
+
+    retval = ERROR_SUCCESS;
+    index = 0;
+    while (retval != ERROR_NO_MORE_ITEMS) {
+        WCHAR keynameW[64], pathW[MAX_PATH];
+        DWORD type, path_len, name_len;
+
+        path_len = sizeof(pathW)/sizeof(*pathW);
+        name_len = sizeof(keynameW)/sizeof(*keynameW);
+        retval = RegEnumValueW(eudckey, index++, keynameW, &name_len, NULL, &type, (BYTE*)pathW, &path_len);
+        if (retval || type != REG_SZ)
+            continue;
+
+        hr = eudc_collection_add_family(factory, collection, keynameW, pathW);
+        if (hr != S_OK)
+            WARN("failed to add family %s, path %s\n", debugstr_w(keynameW), debugstr_w(pathW));
+    }
+    RegCloseKey(eudckey);
+
+    /* try to add global default if not defined for specific codepage */
+    exists = FALSE;
+    hr = IDWriteFontCollection_FindFamilyName(&collection->IDWriteFontCollection_iface, emptyW,
+        &index, &exists);
+    if (FAILED(hr) || !exists) {
+        const WCHAR globaldefaultW[] = {'E','U','D','C','.','T','T','E',0};
+        hr = eudc_collection_add_family(factory, collection, emptyW, globaldefaultW);
+        if (hr != S_OK)
+            WARN("failed to add global default EUDC font, 0x%08x\n", hr);
+    }
+
+    /* EUDC collection offers simulated faces too */
+    for (i = 0; i < collection->family_count; i++) {
+        fontfamily_add_bold_simulated_face(collection->family_data[i]);
+        fontfamily_add_oblique_simulated_face(collection->family_data[i]);
+    }
+
+    return S_OK;
 }
 
 static HRESULT WINAPI dwritefontfile_QueryInterface(IDWriteFontFile *iface, REFIID riid, void **obj)
-- 
2.6.4




More information about the wine-patches mailing list