From: Tim Clem tclem@codeweavers.com
--- dlls/dwrite/font.c | 68 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 3 deletions(-)
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c index 65bf7021938..040502a07ed 100644 --- a/dlls/dwrite/font.c +++ b/dlls/dwrite/font.c @@ -346,6 +346,11 @@ struct dwrite_fontcollection struct dwrite_fontfamily_data **family_data; size_t size; size_t count; + + /* Populated if GetFontSet is called on this collection. The + collection owns a reference to each of these entries. */ + struct dwrite_fontset_entry **fontset_entries; + unsigned int entry_count; };
struct dwrite_fontfamily @@ -3263,6 +3268,8 @@ static ULONG WINAPI dwritefontcollection_AddRef(IDWriteFontCollection3 *iface) return refcount; }
+static void release_fontset_entry(struct dwrite_fontset_entry *entry); + static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection3 *iface) { struct dwrite_fontcollection *collection = impl_from_IDWriteFontCollection3(iface); @@ -3277,6 +3284,9 @@ static ULONG WINAPI dwritefontcollection_Release(IDWriteFontCollection3 *iface) for (i = 0; i < collection->count; ++i) release_fontfamily_data(collection->family_data[i]); free(collection->family_data); + for (i = 0; i < collection->entry_count; ++i) + release_fontset_entry(collection->fontset_entries[i]); + free(collection->fontset_entries); free(collection); }
@@ -3402,6 +3412,26 @@ static HRESULT WINAPI dwritefontcollection_GetFontFromFontFace(IDWriteFontCollec return hr; }
+static void init_fontset(struct dwrite_fontset *object, IDWriteFactory7 *factory, + struct dwrite_fontset_entry **entries, unsigned int count); + +static struct dwrite_fontset_entry * addref_fontset_entry(struct dwrite_fontset_entry *entry); + +/* Shallow copies an array of font set entries, adding a reference to each. */ +static HRESULT duplicate_fontset_entries(struct dwrite_fontset_entry **entries, unsigned int count, + struct dwrite_fontset_entry ***copy) +{ + unsigned int i; + + if (!(*copy = malloc(count * sizeof(*entries)))) + return E_OUTOFMEMORY; + + for (i = 0; i < count; i++) + (*copy)[i] = addref_fontset_entry(entries[i]); + + return S_OK; +} + static HRESULT fontset_create_from_font_collection(struct dwrite_fontcollection *collection, IDWriteFontSet1 **fontset) { struct dwrite_font_data **fonts; @@ -3410,6 +3440,28 @@ static HRESULT fontset_create_from_font_collection(struct dwrite_fontcollection
*fontset = NULL;
+ /* Reuse cached entries if we've already made a set from this collection. */ + if (collection->fontset_entries) + { + struct dwrite_fontset_entry **entries; + struct dwrite_fontset *object; + if (!(object = calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + + hr = duplicate_fontset_entries(collection->fontset_entries, collection->entry_count, &entries); + if (FAILED(hr)) + { + free(object); + return hr; + } + + init_fontset(object, collection->factory, entries, collection->entry_count); + + *fontset = (IDWriteFontSet1 *)&object->IDWriteFontSet3_iface; + + return S_OK; + } + for (i = 0; i < collection->count; ++i) count += collection->family_data[i]->count;
@@ -3422,6 +3474,19 @@ static HRESULT fontset_create_from_font_collection(struct dwrite_fontcollection
hr = fontset_create_from_font_data(collection->factory, fonts, count, fontset);
+ /* Cache the entries from the font set. */ + if (SUCCEEDED(hr)) + { + HRESULT copy_hr; + struct dwrite_fontset *object = impl_from_IDWriteFontSet3((IDWriteFontSet3 *)*fontset); + + copy_hr = duplicate_fontset_entries(object->entries, object->count, &collection->fontset_entries); + if (SUCCEEDED(copy_hr)) + collection->entry_count = object->count; + else + ERR("failed to cache font set entries on collection %p, 0x%08lx\n", collection, copy_hr); + } + free(fonts);
return hr; @@ -7753,9 +7818,6 @@ static IDWriteLocalizedStrings * fontset_entry_get_property(struct dwrite_fontse return value; }
-static void init_fontset(struct dwrite_fontset *object, IDWriteFactory7 *factory, - struct dwrite_fontset_entry **entries, unsigned int count); - static ULONG WINAPI dwritefontset_Release(IDWriteFontSet3 *iface) { struct dwrite_fontset *set = impl_from_IDWriteFontSet3(iface);