Module: wine Branch: master Commit: 318ebc89dcb590c6afa71e5b1504669037979a60 URL: https://source.winehq.org/git/wine.git/?a=commit;h=318ebc89dcb590c6afa71e5b1...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Thu Mar 11 12:41:23 2021 +0300
dwrite: Implement GetSystemFontSet().
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/dwrite/main.c | 159 +++++++++++++++++++++++++++++++++++++++++++++-- dlls/dwrite/tests/font.c | 25 ++++++++ 2 files changed, 178 insertions(+), 6 deletions(-)
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index 51020d6f586..3326b1550ce 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -1509,11 +1509,152 @@ static HRESULT WINAPI dwritefactory3_CreateFontFaceReference(IDWriteFactory7 *if return hr; }
+static HRESULT create_system_path_list(WCHAR ***ret, unsigned int *ret_count) +{ + unsigned int index = 0, value_size, name_count, max_name_count, type, data_size; + WCHAR **paths = NULL, *name, *value = NULL; + size_t capacity = 0, count = 0; + HKEY hkey; + LONG r; + + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\Microsoft\Windows NT\CurrentVersion\Fonts", + 0, GENERIC_READ, &hkey)) + { + return E_UNEXPECTED; + } + + value_size = MAX_PATH * sizeof(*value); + value = heap_alloc(value_size); + + max_name_count = MAX_PATH; + name = heap_alloc(max_name_count * sizeof(*name)); + + for (;;) + { + if (!value) + { + value_size = MAX_PATH * sizeof(*value); + value = heap_alloc(value_size); + } + + do + { + name_count = max_name_count; + data_size = value_size - sizeof(*value); + + r = RegEnumValueW(hkey, index, name, &name_count, NULL, &type, (BYTE *)value, &data_size); + if (r == ERROR_MORE_DATA) + { + if (name_count >= max_name_count) + { + max_name_count *= 2; + heap_free(name); + name = heap_alloc(max_name_count * sizeof(*name)); + } + + if (data_size > value_size - sizeof(*value)) + { + heap_free(value); + value_size = max(data_size + sizeof(*value), value_size * 2); + value = heap_alloc(value_size); + } + } + } while (r == ERROR_MORE_DATA); + + if (r != ERROR_SUCCESS) + break; + + value[data_size / sizeof(*value)] = 0; + if (type == REG_SZ && *name != '@') + { + if (dwrite_array_reserve((void **)&paths, &capacity, count + 1, sizeof(*paths))) + { + if (!strchrW(value, '\')) + { + static const WCHAR fontsW[] = {'\','f','o','n','t','s','\',0}; + WCHAR *ptrW; + + ptrW = heap_alloc((MAX_PATH + lstrlenW(value)) * sizeof(WCHAR)); + GetWindowsDirectoryW(ptrW, MAX_PATH); + lstrcatW(ptrW, fontsW); + lstrcatW(ptrW, value); + + heap_free(value); + value = ptrW; + } + + paths[count++] = value; + value = NULL; + } + } + index++; + } + + heap_free(name); + + *ret = paths; + *ret_count = count; + + RegCloseKey(hkey); + + return S_OK; +} + +static int create_system_fontset_compare(const void *left, const void *right) +{ + const WCHAR *_l = *(WCHAR **)left, *_r = *(WCHAR **)right; + return lstrcmpiW(_l, _r); +}; + +static HRESULT create_system_fontset(IDWriteFactory7 *factory, REFIID riid, void **obj) +{ + IDWriteFontSetBuilder2 *builder; + IDWriteFontSet *fontset; + unsigned int i, j, count; + WCHAR **paths; + HRESULT hr; + + *obj = NULL; + + if (FAILED(hr = create_fontset_builder(factory, &builder))) return hr; + + if (SUCCEEDED(hr = create_system_path_list(&paths, &count))) + { + /* Sort, skip duplicates. */ + + qsort(paths, count, sizeof(*paths), create_system_fontset_compare); + + for (i = 0, j = 0; i < count; ++i) + { + if (i != j && !lstrcmpiW(paths[i], paths[j])) continue; + + if (FAILED(hr = IDWriteFontSetBuilder2_AddFontFile(builder, paths[i])) && hr != DWRITE_E_FILEFORMAT) + WARN("Failed to add font file, hr %#x, path %s.\n", hr, debugstr_w(paths[i])); + + j = i; + } + + for (i = 0; i < count; ++i) + heap_free(paths[i]); + heap_free(paths); + } + + if (SUCCEEDED(hr = IDWriteFontSetBuilder2_CreateFontSet(builder, &fontset))) + { + hr = IDWriteFontSet_QueryInterface(fontset, riid, obj); + IDWriteFontSet_Release(fontset); + } + + IDWriteFontSetBuilder2_Release(builder); + + return hr; +} + static HRESULT WINAPI dwritefactory3_GetSystemFontSet(IDWriteFactory7 *iface, IDWriteFontSet **fontset) { - FIXME("%p, %p: stub\n", iface, fontset); + TRACE("%p, %p.\n", iface, fontset);
- return E_NOTIMPL; + return create_system_fontset(iface, &IID_IDWriteFontSet, (void **)fontset); }
static HRESULT WINAPI dwritefactory3_CreateFontSetBuilder(IDWriteFactory7 *iface, IDWriteFontSetBuilder **builder) @@ -1691,9 +1832,12 @@ static HRESULT WINAPI dwritefactory6_CreateFontResource(IDWriteFactory7 *iface, static HRESULT WINAPI dwritefactory6_GetSystemFontSet(IDWriteFactory7 *iface, BOOL include_downloadable, IDWriteFontSet1 **fontset) { - FIXME("%p, %d, %p.\n", iface, include_downloadable, fontset); + TRACE("%p, %d, %p.\n", iface, include_downloadable, fontset);
- return E_NOTIMPL; + if (include_downloadable) + FIXME("Downloadable fonts are not supported.\n"); + + return create_system_fontset(iface, &IID_IDWriteFontSet1, (void **)fontset); }
static HRESULT WINAPI dwritefactory6_GetSystemFontCollection(IDWriteFactory7 *iface, BOOL include_downloadable, @@ -1732,9 +1876,12 @@ static HRESULT WINAPI dwritefactory6_CreateTextFormat(IDWriteFactory7 *iface, co static HRESULT WINAPI dwritefactory7_GetSystemFontSet(IDWriteFactory7 *iface, BOOL include_downloadable, IDWriteFontSet2 **fontset) { - FIXME("%p, %d, %p.\n", iface, include_downloadable, fontset); + TRACE("%p, %d, %p.\n", iface, include_downloadable, fontset);
- return E_NOTIMPL; + if (include_downloadable) + FIXME("Downloadable fonts are not supported.\n"); + + return create_system_fontset(iface, &IID_IDWriteFontSet2, (void **)fontset); }
static HRESULT WINAPI dwritefactory7_GetSystemFontCollection(IDWriteFactory7 *iface, BOOL include_downloadable, diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c index 4367f1d95c8..bded40a53c7 100644 --- a/dlls/dwrite/tests/font.c +++ b/dlls/dwrite/tests/font.c @@ -10009,6 +10009,30 @@ static void test_family_font_set(void) ok(!refcount, "Unexpected factory refcount %u.\n", refcount); }
+static void test_system_font_set(void) +{ + IDWriteFactory3 *factory; + IDWriteFontSet *fontset; + unsigned int count; + HRESULT hr; + + if (!(factory = create_factory_iid(&IID_IDWriteFactory3))) + { + win_skip("System font set is not supported.\n"); + return; + } + + hr = IDWriteFactory3_GetSystemFontSet(factory, &fontset); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + count = IDWriteFontSet_GetFontCount(fontset); + ok(!!count, "Unexpected font count %u.\n", count); + + IDWriteFontSet_Release(fontset); + + IDWriteFactory3_Release(factory); +} + START_TEST(font) { IDWriteFactory *factory; @@ -10081,6 +10105,7 @@ START_TEST(font) test_GetVerticalGlyphVariants(); test_expiration_event(); test_family_font_set(); + test_system_font_set();
IDWriteFactory_Release(factory); }