From: Nikolay Sivov nsivov@codeweavers.com
--- dlls/dwrite/dwrite_private.h | 7 +++ dlls/dwrite/font.c | 66 +++++++++++++++++++-------- dlls/dwrite/main.c | 88 +++++++++++++++++++++++++++++++----- 3 files changed, 130 insertions(+), 31 deletions(-)
diff --git a/dlls/dwrite/dwrite_private.h b/dlls/dwrite/dwrite_private.h index dc25ce351c6..0ce0984b23b 100644 --- a/dlls/dwrite/dwrite_private.h +++ b/dlls/dwrite/dwrite_private.h @@ -383,6 +383,13 @@ extern HRESULT create_font_collection_from_set(IDWriteFactory7 *factory, IDWrite DWRITE_FONT_FAMILY_MODEL family_model, REFGUID riid, void **ret); extern HRESULT create_system_fontset(IDWriteFactory7 *factory, REFIID riid, void **obj);
+struct dwrite_fontset_entry; +extern void release_fontset_entry(struct dwrite_fontset_entry *); +extern HRESULT fontset_builder_get_entries(IDWriteFontSetBuilder2 *iface, struct dwrite_fontset_entry ***ret, + unsigned int *count); +extern HRESULT fontset_create_from_set(IDWriteFactory7 *factory, struct dwrite_fontset_entry **src_entries, + unsigned int count, BOOL is_system, IDWriteFontSet **ret); + struct dwrite_fontface;
extern float fontface_get_scaled_design_advance(struct dwrite_fontface *fontface, DWRITE_MEASURING_MODE measuring_mode, diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 8750511bbc3..63a5f4e8dc7 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -7370,7 +7370,7 @@ static ULONG WINAPI dwritefontset_AddRef(IDWriteFontSet3 *iface)
#define MISSING_SET_PROP ((void *)0x1)
-static void release_fontset_entry(struct dwrite_fontset_entry *entry) +void release_fontset_entry(struct dwrite_fontset_entry *entry) { unsigned int i;
@@ -7391,6 +7391,25 @@ static struct dwrite_fontset_entry * addref_fontset_entry(struct dwrite_fontset_ return entry; }
+HRESULT fontset_builder_get_entries(IDWriteFontSetBuilder2 *iface, struct dwrite_fontset_entry ***ret, + unsigned int *count) +{ + struct dwrite_fontset_builder *builder = impl_from_IDWriteFontSetBuilder2(iface); + struct dwrite_fontset_entry **entries; + unsigned int i; + + if (!(entries = calloc(builder->count, sizeof(*entries)))) + return E_OUTOFMEMORY; + + for (i = 0; i < builder->count; ++i) + entries[i] = addref_fontset_entry(builder->entries[i]); + + *ret = entries; + *count = builder->count; + + return S_OK; +} + static IDWriteLocalizedStrings * fontset_entry_get_property(struct dwrite_fontset_entry *entry, DWRITE_FONT_PROPERTY_ID property) { @@ -7851,36 +7870,38 @@ static void init_fontset(struct dwrite_fontset *object, IDWriteFactory7 *factory object->is_system = is_system; }
-static HRESULT fontset_create_from_font_data(IDWriteFactory7 *factory, struct dwrite_font_data **fonts, - unsigned int count, IDWriteFontSet1 **ret) +HRESULT fontset_create_from_set(IDWriteFactory7 *factory, struct dwrite_fontset_entry **src_entries, + unsigned int count, BOOL is_system, IDWriteFontSet **ret) { struct dwrite_fontset_entry **entries = NULL; struct dwrite_fontset *object; unsigned int i;
+ *ret = NULL; + if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY;
if (count) { - entries = calloc(count, sizeof(*entries)); - - /* FIXME: set available properties too */ - - for (i = 0; i < count; ++i) + if (!(entries = calloc(count, sizeof(*entries)))) { - fontset_create_entry(fonts[i]->file, fonts[i]->face_type, fonts[i]->face_index, - fonts[i]->simulations, &entries[i]); + free(object); + return E_OUTOFMEMORY; } + + for (i = 0; i < count; ++i) + entries[i] = addref_fontset_entry(src_entries[i]); } - init_fontset(object, factory, entries, count, FALSE); + init_fontset(object, factory, entries, count, is_system);
- *ret = (IDWriteFontSet1 *)&object->IDWriteFontSet3_iface; + *ret = (IDWriteFontSet *)&object->IDWriteFontSet3_iface;
return S_OK; }
-static HRESULT fontset_builder_create_fontset(struct dwrite_fontset_builder *builder, IDWriteFontSet **ret) +static HRESULT fontset_create_from_font_data(IDWriteFactory7 *factory, struct dwrite_font_data **fonts, + unsigned int count, IDWriteFontSet1 **ret) { struct dwrite_fontset_entry **entries = NULL; struct dwrite_fontset *object; @@ -7889,16 +7910,21 @@ static HRESULT fontset_builder_create_fontset(struct dwrite_fontset_builder *bui if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY;
- if (builder->count) + if (count) { - entries = calloc(builder->count, sizeof(*entries)); + entries = calloc(count, sizeof(*entries));
- for (i = 0; i < builder->count; ++i) - entries[i] = addref_fontset_entry(builder->entries[i]); + /* FIXME: set available properties too */ + + for (i = 0; i < count; ++i) + { + fontset_create_entry(fonts[i]->file, fonts[i]->face_type, fonts[i]->face_index, + fonts[i]->simulations, &entries[i]); + } } - init_fontset(object, builder->factory, entries, builder->count, builder->is_system); + init_fontset(object, factory, entries, count, FALSE);
- *ret = (IDWriteFontSet *)&object->IDWriteFontSet3_iface; + *ret = (IDWriteFontSet1 *)&object->IDWriteFontSet3_iface;
return S_OK; } @@ -8050,7 +8076,7 @@ static HRESULT WINAPI dwritefontsetbuilder_CreateFontSet(IDWriteFontSetBuilder2
TRACE("%p, %p.\n", iface, fontset);
- return fontset_builder_create_fontset(builder, fontset); + return fontset_create_from_set(builder->factory, builder->entries, builder->count, builder->is_system, fontset); }
static HRESULT WINAPI dwritefontsetbuilder1_AddFontFile(IDWriteFontSetBuilder2 *iface, IDWriteFontFile *file) diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c index 9c6afa5de98..b343d65631c 100644 --- a/dlls/dwrite/main.c +++ b/dlls/dwrite/main.c @@ -603,6 +603,13 @@ struct dwritefactory IDWriteGdiInterop1 *gdiinterop; IDWriteFontFallback1 *fallback;
+ struct + { + FILETIME timestamp; + struct dwrite_fontset_entry **entries; + unsigned int count; + } system_set; + IDWriteFontFileLoader *localfontfileloader; struct list localfontfaces;
@@ -636,6 +643,15 @@ static void release_fileloader(struct fileloader *fileloader) free(fileloader); }
+static void factory_cleanup_fontset(struct dwritefactory *factory) +{ + unsigned int i; + + for (i = 0; i < factory->system_set.count; ++i) + release_fontset_entry(factory->system_set.entries[i]); + memset(&factory->system_set, 0, sizeof(factory->system_set)); +} + static void release_dwritefactory(struct dwritefactory *factory) { struct fileloader *fileloader, *fileloader2; @@ -660,6 +676,7 @@ static void release_dwritefactory(struct dwritefactory *factory) if (factory->system_collections[i]) IDWriteFontCollection_Release(factory->system_collections[i]); } + factory_cleanup_fontset(factory); if (factory->eudc_collection) IDWriteFontCollection1_Release(factory->eudc_collection); if (factory->fallback) @@ -1524,6 +1541,16 @@ static HRESULT WINAPI dwritefactory3_CreateFontFaceReference(IDWriteFactory7 *if return hr; }
+static HKEY open_fonts_key(void) +{ + HKEY hkey = NULL; + + RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\Microsoft\Windows NT\CurrentVersion\Fonts", + 0, GENERIC_READ | KEY_QUERY_VALUE, &hkey); + + return hkey; +} + static HRESULT create_system_path_list(WCHAR ***ret, unsigned int *ret_count) { unsigned int index = 0, value_size, max_name_count; @@ -1533,11 +1560,8 @@ static HRESULT create_system_path_list(WCHAR ***ret, unsigned int *ret_count) HKEY hkey; LONG r;
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\Microsoft\Windows NT\CurrentVersion\Fonts", - 0, GENERIC_READ, &hkey)) - { + if (!(hkey = open_fonts_key())) return E_UNEXPECTED; - }
value_size = MAX_PATH * sizeof(*value); value = malloc(value_size); @@ -1616,23 +1640,37 @@ static HRESULT create_system_path_list(WCHAR ***ret, unsigned int *ret_count) return S_OK; }
+static void get_system_fonts_mtime(FILETIME *mtime) +{ + HKEY hkey; + + memset(mtime, 0, sizeof(*mtime)); + + if ((hkey = open_fonts_key())) + { + RegQueryInfoKeyW(hkey, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, mtime); + RegCloseKey(hkey); + } +} + static int __cdecl create_system_fontset_compare(const void *left, const void *right) { const WCHAR *_l = *(WCHAR **)left, *_r = *(WCHAR **)right; return wcsicmp(_l, _r); };
-HRESULT create_system_fontset(IDWriteFactory7 *factory, REFIID riid, void **obj) +static HRESULT factory_create_system_fontset(struct dwritefactory *factory, const FILETIME *timestamp) { IDWriteFontSetBuilder2 *builder; - IDWriteFontSet *fontset; unsigned int i, j, count; WCHAR **paths; HRESULT hr;
- *obj = NULL; + factory_cleanup_fontset(factory); + factory->system_set.timestamp = *timestamp;
- if (FAILED(hr = create_fontset_builder(factory, TRUE, &builder))) return hr; + if (FAILED(hr = create_fontset_builder(&factory->IDWriteFactory7_iface, TRUE, &builder))) return hr;
if (SUCCEEDED(hr = create_system_path_list(&paths, &count))) { @@ -1655,14 +1693,42 @@ HRESULT create_system_fontset(IDWriteFactory7 *factory, REFIID riid, void **obj) free(paths); }
- if (SUCCEEDED(hr = IDWriteFontSetBuilder2_CreateFontSet(builder, &fontset))) + hr = fontset_builder_get_entries(builder, &factory->system_set.entries, &factory->system_set.count); + IDWriteFontSetBuilder2_Release(builder); + + return hr; +} + +HRESULT create_system_fontset(IDWriteFactory7 *factory_iface, REFIID riid, void **obj) +{ + struct dwritefactory *factory = impl_from_IDWriteFactory7(factory_iface); + IDWriteFontSet *fontset; + FILETIME timestamp; + HRESULT hr = S_OK; + + *obj = NULL; + + get_system_fonts_mtime(×tamp); + + EnterCriticalSection(&factory->cs); + + if (CompareFileTime(×tamp, &factory->system_set.timestamp) > 0) + hr = factory_create_system_fontset(factory, ×tamp); + + if (SUCCEEDED(hr)) + { + hr = fontset_create_from_set(factory_iface, factory->system_set.entries, + factory->system_set.count, TRUE, &fontset); + } + + LeaveCriticalSection(&factory->cs); + + if (SUCCEEDED(hr)) { hr = IDWriteFontSet_QueryInterface(fontset, riid, obj); IDWriteFontSet_Release(fontset); }
- IDWriteFontSetBuilder2_Release(builder); - return hr; }