Nikolay Sivov : dwrite: Fix excessive refcount increment when setting interface pointers as range attributes.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Mar 12 10:48:18 CDT 2015


Module: wine
Branch: master
Commit: 985bff76be11799a1317e8195318ef31a6162e2e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=985bff76be11799a1317e8195318ef31a6162e2e

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed Mar 11 22:20:34 2015 +0300

dwrite: Fix excessive refcount increment when setting interface pointers as range attributes.

---

 dlls/dwrite/layout.c       | 34 ++++++++++++++++------------------
 dlls/dwrite/tests/layout.c | 26 ++++++++++++++++++++++++++
 2 files changed, 42 insertions(+), 18 deletions(-)

diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index b4833c2..2665664 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -775,6 +775,19 @@ static struct layout_range *get_layout_range_by_pos(struct dwrite_textlayout *la
     return NULL;
 }
 
+static inline BOOL set_layout_range_iface_attr(IUnknown **dest, IUnknown *value)
+{
+    if (*dest == value) return FALSE;
+
+    if (*dest)
+        IUnknown_Release(*dest);
+    *dest = value;
+    if (*dest)
+        IUnknown_AddRef(*dest);
+
+    return TRUE;
+}
+
 static BOOL set_layout_range_attrval(struct layout_range *dest, enum layout_range_attr_kind attr, struct layout_range_attr_value *value)
 {
     BOOL changed = FALSE;
@@ -797,20 +810,10 @@ static BOOL set_layout_range_attrval(struct layout_range *dest, enum layout_rang
         dest->fontsize = value->u.fontsize;
         break;
     case LAYOUT_RANGE_ATTR_INLINE:
-        changed = dest->object != value->u.object;
-        if (changed && dest->object)
-            IDWriteInlineObject_Release(dest->object);
-        dest->object = value->u.object;
-        if (dest->object)
-            IDWriteInlineObject_AddRef(dest->object);
+        changed = set_layout_range_iface_attr((IUnknown**)&dest->object, (IUnknown*)value->u.object);
         break;
     case LAYOUT_RANGE_ATTR_EFFECT:
-        changed = dest->effect != value->u.effect;
-        if (changed && dest->effect)
-            IUnknown_Release(dest->effect);
-        dest->effect = value->u.effect;
-        if (dest->effect)
-            IUnknown_AddRef(dest->effect);
+        changed = set_layout_range_iface_attr((IUnknown**)&dest->effect, (IUnknown*)value->u.effect);
         break;
     case LAYOUT_RANGE_ATTR_UNDERLINE:
         changed = dest->underline != value->u.underline;
@@ -821,12 +824,7 @@ static BOOL set_layout_range_attrval(struct layout_range *dest, enum layout_rang
         dest->strikethrough = value->u.strikethrough;
         break;
     case LAYOUT_RANGE_ATTR_FONTCOLL:
-        changed = dest->collection != value->u.collection;
-        if (changed && dest->collection)
-            IDWriteFontCollection_Release(dest->collection);
-        dest->collection = value->u.collection;
-        if (dest->collection)
-            IDWriteFontCollection_AddRef(dest->collection);
+        changed = set_layout_range_iface_attr((IUnknown**)&dest->collection, (IUnknown*)value->u.collection);
         break;
     case LAYOUT_RANGE_ATTR_LOCALE:
         changed = strcmpW(dest->locale, value->u.locale) != 0;
diff --git a/dlls/dwrite/tests/layout.c b/dlls/dwrite/tests/layout.c
index 98358a4..89c96e4 100644
--- a/dlls/dwrite/tests/layout.c
+++ b/dlls/dwrite/tests/layout.c
@@ -691,6 +691,9 @@ static void test_SetInlineObject(void)
     hr = IDWriteFactory_CreateEllipsisTrimmingSign(factory, format, &inlineobj2);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
+    EXPECT_REF(inlineobj, 1);
+    EXPECT_REF(inlineobj2, 1);
+
     inlinetest = (void*)0x1;
     hr = IDWriteTextLayout_GetInlineObject(layout, 0, &inlinetest, NULL);
     ok(hr == S_OK, "got 0x%08x\n", hr);
@@ -701,6 +704,8 @@ static void test_SetInlineObject(void)
     hr = IDWriteTextLayout_SetInlineObject(layout, inlineobj, range);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
+    EXPECT_REF(inlineobj, 2);
+
     inlinetest = (void*)0x1;
     hr = IDWriteTextLayout_GetInlineObject(layout, 2, &inlinetest, NULL);
     ok(hr == S_OK, "got 0x%08x\n", hr);
@@ -714,6 +719,8 @@ static void test_SetInlineObject(void)
     ok(r2.startPosition == 0 && r2.length == 2, "got %d, %d\n", r2.startPosition, r2.length);
     IDWriteInlineObject_Release(inlinetest);
 
+    EXPECT_REF(inlineobj, 2);
+
     /* get from somewhere inside a range */
     inlinetest = NULL;
     r2.startPosition = r2.length = 100;
@@ -723,6 +730,8 @@ static void test_SetInlineObject(void)
     ok(r2.startPosition == 0 && r2.length == 2, "got %d, %d\n", r2.startPosition, r2.length);
     IDWriteInlineObject_Release(inlinetest);
 
+    EXPECT_REF(inlineobj, 2);
+
     range.startPosition = 1;
     range.length = 1;
     hr = IDWriteTextLayout_SetInlineObject(layout, inlineobj2, range);
@@ -736,6 +745,9 @@ static void test_SetInlineObject(void)
     ok(r2.startPosition == 1 && r2.length == 1, "got %d, %d\n", r2.startPosition, r2.length);
     IDWriteInlineObject_Release(inlinetest);
 
+    EXPECT_REF(inlineobj, 2);
+    EXPECT_REF(inlineobj2, 2);
+
     inlinetest = NULL;
     r2.startPosition = r2.length = 100;
     hr = IDWriteTextLayout_GetInlineObject(layout, 0, &inlinetest, &r2);
@@ -744,6 +756,8 @@ static void test_SetInlineObject(void)
     ok(r2.startPosition == 0 && r2.length == 1, "got %d, %d\n", r2.startPosition, r2.length);
     IDWriteInlineObject_Release(inlinetest);
 
+    EXPECT_REF(inlineobj, 2);
+
     range.startPosition = 1;
     range.length = 1;
     hr = IDWriteTextLayout_SetInlineObject(layout, inlineobj, range);
@@ -756,11 +770,15 @@ static void test_SetInlineObject(void)
     ok(r2.startPosition == 0 && r2.length == 2, "got %d, %d\n", r2.startPosition, r2.length);
     IDWriteInlineObject_Release(inlinetest);
 
+    EXPECT_REF(inlineobj, 2);
+
     range.startPosition = 1;
     range.length = 2;
     hr = IDWriteTextLayout_SetInlineObject(layout, inlineobj, range);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
+    EXPECT_REF(inlineobj, 2);
+
     r2.startPosition = r2.length = 100;
     hr = IDWriteTextLayout_GetInlineObject(layout, 0, &inlinetest, &r2);
     ok(hr == S_OK, "got 0x%08x\n", hr);
@@ -768,7 +786,15 @@ static void test_SetInlineObject(void)
     ok(r2.startPosition == 0 && r2.length == 3, "got %d, %d\n", r2.startPosition, r2.length);
     IDWriteInlineObject_Release(inlinetest);
 
+    EXPECT_REF(inlineobj, 2);
+    EXPECT_REF(inlineobj2, 1);
+
     IDWriteTextLayout_Release(layout);
+
+    EXPECT_REF(inlineobj, 1);
+
+    IDWriteInlineObject_Release(inlineobj);
+    IDWriteInlineObject_Release(inlineobj2);
     IDWriteTextFormat_Release(format);
 }
 




More information about the wine-cvs mailing list