Nikolay Sivov : dwrite: Make font set entries refcounted.

Alexandre Julliard julliard at winehq.org
Wed Mar 10 14:58:45 CST 2021


Module: wine
Branch: master
Commit: dc37782f663497413f27309e10cf7a1584bac33c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=dc37782f663497413f27309e10cf7a1584bac33c

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed Mar 10 12:30:27 2021 +0300

dwrite: Make font set entries refcounted.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dwrite/font.c | 105 ++++++++++++++++++++++++++++++++---------------------
 1 file changed, 64 insertions(+), 41 deletions(-)

diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index 1afc72e22c5..07d96dfe107 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -252,6 +252,7 @@ struct dwrite_fontresource
 
 struct dwrite_fontset_entry
 {
+    LONG refcount;
     IDWriteFontFile *file;
     unsigned int face_index;
     unsigned int simulations;
@@ -263,7 +264,7 @@ struct dwrite_fontset
     LONG refcount;
     IDWriteFactory7 *factory;
 
-    struct dwrite_fontset_entry *entries;
+    struct dwrite_fontset_entry **entries;
     unsigned int count;
 };
 
@@ -273,7 +274,7 @@ struct dwrite_fontset_builder
     LONG refcount;
     IDWriteFactory7 *factory;
 
-    struct dwrite_fontset_entry *entries;
+    struct dwrite_fontset_entry **entries;
     size_t count;
     size_t capacity;
 };
@@ -7103,25 +7104,27 @@ static ULONG WINAPI dwritefontset_AddRef(IDWriteFontSet3 *iface)
     return refcount;
 }
 
-static void fontset_release_entries(struct dwrite_fontset_entry *entries, unsigned int count)
+static void release_fontset_entry(struct dwrite_fontset_entry *entry)
 {
-    unsigned int i;
-
-    for (i = 0; i < count; ++i)
-        IDWriteFontFile_Release(entries[i].file);
+    if (InterlockedDecrement(&entry->refcount) > 0)
+        return;
+    IDWriteFontFile_Release(entry->file);
+    heap_free(entry);
 }
 
 static ULONG WINAPI dwritefontset_Release(IDWriteFontSet3 *iface)
 {
     struct dwrite_fontset *set = impl_from_IDWriteFontSet3(iface);
     ULONG refcount = InterlockedDecrement(&set->refcount);
+    unsigned int i;
 
     TRACE("%p, refcount %u.\n", iface, refcount);
 
     if (!refcount)
     {
         IDWriteFactory7_Release(set->factory);
-        fontset_release_entries(set->entries, set->count);
+        for (i = 0; i < set->count; ++i)
+            release_fontset_entry(set->entries[i]);
         heap_free(set->entries);
         heap_free(set);
     }
@@ -7142,7 +7145,6 @@ static HRESULT WINAPI dwritefontset_GetFontFaceReference(IDWriteFontSet3 *iface,
         IDWriteFontFaceReference **reference)
 {
     struct dwrite_fontset *set = impl_from_IDWriteFontSet3(iface);
-    struct dwrite_fontset_entry *entry;
 
     TRACE("%p, %u, %p.\n", iface, index, reference);
 
@@ -7151,9 +7153,8 @@ static HRESULT WINAPI dwritefontset_GetFontFaceReference(IDWriteFontSet3 *iface,
     if (index >= set->count)
         return E_INVALIDARG;
 
-    entry = &set->entries[index];
-    return IDWriteFactory7_CreateFontFaceReference_(set->factory, entry->file, entry->face_index,
-            entry->simulations, reference);
+    return IDWriteFactory7_CreateFontFaceReference_(set->factory, set->entries[index]->file,
+            set->entries[index]->face_index, set->entries[index]->simulations, reference);
 }
 
 static HRESULT WINAPI dwritefontset_FindFontFaceReference(IDWriteFontSet3 *iface,
@@ -7386,65 +7387,85 @@ static const IDWriteFontSet3Vtbl fontsetvtbl =
     dwritefontset3_GetFontSourceName,
 };
 
-static HRESULT fontset_create_from_font_data(IDWriteFactory7 *factory, struct dwrite_font_data **fonts,
-        unsigned int count, IDWriteFontSet1 **ret)
+static HRESULT fontset_create_entry(IDWriteFontFile *file, unsigned int face_index,
+        unsigned int simulations, struct dwrite_fontset_entry **ret)
 {
-    struct dwrite_fontset *object;
-    unsigned int i;
+    struct dwrite_fontset_entry *entry;
 
-    if (!(object = heap_alloc_zero(sizeof(*object))))
+    if (!(entry = heap_alloc_zero(sizeof(*entry))))
         return E_OUTOFMEMORY;
 
+    entry->refcount = 1;
+    entry->file = file;
+    IDWriteFontFile_AddRef(entry->file);
+    entry->face_index = face_index;
+    entry->simulations = simulations;
+
+    *ret = entry;
+
+    return S_OK;
+}
+
+static void init_fontset(struct dwrite_fontset *object, IDWriteFactory7 *factory,
+        struct dwrite_fontset_entry **entries, unsigned int count)
+{
     object->IDWriteFontSet3_iface.lpVtbl = &fontsetvtbl;
     object->refcount = 1;
     object->factory = factory;
     IDWriteFactory7_AddRef(object->factory);
+    object->entries = entries;
+    object->count = count;
+}
+
+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;
+    unsigned int i;
+
+    if (!(object = heap_alloc_zero(sizeof(*object))))
+        return E_OUTOFMEMORY;
 
     if (count)
     {
-        object->entries = heap_calloc(count, sizeof(*object->entries));
-        object->count = count;
+        entries = heap_calloc(count, sizeof(*entries));
 
         /* FIXME: set available properties too */
-        for (i = 0; i < object->count; ++i)
+
+        for (i = 0; i < count; ++i)
         {
-            object->entries[i].file = fonts[i]->file;
-            object->entries[i].face_index = fonts[i]->face_index;
-            object->entries[i].simulations = fonts[i]->simulations;
-            IDWriteFontFile_AddRef(object->entries[i].file);
+            fontset_create_entry(fonts[i]->file, fonts[i]->face_index, fonts[i]->simulations, &entries[i]);
         }
     }
+    init_fontset(object, factory, entries, count);
 
     *ret = (IDWriteFontSet1 *)&object->IDWriteFontSet3_iface;
 
     return S_OK;
 }
 
-static HRESULT fontset_builder_create_fontset(IDWriteFactory7 *factory, struct dwrite_fontset_entry *entries,
+static HRESULT fontset_builder_create_fontset(IDWriteFactory7 *factory, struct dwrite_fontset_entry **src_entries,
         unsigned int count, IDWriteFontSet **ret)
 {
+    struct dwrite_fontset_entry **entries = NULL;
     struct dwrite_fontset *object;
     unsigned int i;
 
     if (!(object = heap_alloc_zero(sizeof(*object))))
         return E_OUTOFMEMORY;
 
-    object->IDWriteFontSet3_iface.lpVtbl = &fontsetvtbl;
-    object->refcount = 1;
-    object->factory = factory;
-    IDWriteFactory7_AddRef(object->factory);
-
     if (count)
     {
-        object->entries = heap_calloc(count, sizeof(*object->entries));
-        object->count = count;
+        entries = heap_calloc(count, sizeof(*entries));
 
-        for (i = 0; i < object->count; ++i)
+        for (i = 0; i < count; ++i)
         {
-            object->entries[i] = entries[i];
-            IDWriteFontFile_AddRef(object->entries[i].file);
+            entries[i] = src_entries[i];
+            InterlockedIncrement(&entries[i]->refcount);
         }
     }
+    init_fontset(object, factory, entries, count);
 
     *ret = (IDWriteFontSet *)&object->IDWriteFontSet3_iface;
 
@@ -7485,13 +7506,15 @@ static ULONG WINAPI dwritefontsetbuilder_Release(IDWriteFontSetBuilder2 *iface)
 {
     struct dwrite_fontset_builder *builder = impl_from_IDWriteFontSetBuilder2(iface);
     ULONG refcount = InterlockedDecrement(&builder->refcount);
+    unsigned int i;
 
     TRACE("%p, refcount %u.\n", iface, refcount);
 
     if (!refcount)
     {
         IDWriteFactory7_Release(builder->factory);
-        fontset_release_entries(builder->entries, builder->count);
+        for (i = 0; i < builder->count; ++i)
+            release_fontset_entry(builder->entries[i]);
         heap_free(builder->entries);
         heap_free(builder);
     }
@@ -7503,6 +7526,7 @@ static HRESULT fontset_builder_add_entry(struct dwrite_fontset_builder *builder,
         unsigned int face_index, unsigned int simulations)
 {
     struct dwrite_fontset_entry *entry;
+    HRESULT hr;
 
     if (!dwrite_array_reserve((void **)&builder->entries, &builder->capacity, builder->count + 1,
             sizeof(*builder->entries)))
@@ -7510,11 +7534,10 @@ static HRESULT fontset_builder_add_entry(struct dwrite_fontset_builder *builder,
         return E_OUTOFMEMORY;
     }
 
-    entry = &builder->entries[builder->count++];
-    entry->file = file;
-    IDWriteFontFile_AddRef(entry->file);
-    entry->face_index = face_index;
-    entry->simulations = simulations;
+    if (FAILED(hr = fontset_create_entry(file, face_index, simulations, &entry)))
+        return hr;
+
+    builder->entries[builder->count++] = entry;
 
     return S_OK;
 }




More information about the wine-cvs mailing list