dwrite: Implement GetSystemFontSet().

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2021-03-11 12:41:23 +03:00 committed by Alexandre Julliard
parent 1f8d7489b7
commit 318ebc89dc
2 changed files with 178 additions and 6 deletions

View file

@ -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,

View file

@ -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);
}