Esme Povirk : gdiplus: Implement reference counting for private font families.

Alexandre Julliard julliard at winehq.org
Tue Oct 26 09:40:28 CDT 2021


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

Author: Esme Povirk <esme at codeweavers.com>
Date:   Wed May 26 15:49:18 2021 -0500

gdiplus: Implement reference counting for private font families.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50896
Signed-off-by: Esme Povirk <esme at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit a5540798605b3ef9abcf654bc28d9dd8d8736e53)
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>

---

 dlls/gdiplus/font.c            | 22 ++++++++++++++++------
 dlls/gdiplus/gdiplus_private.h |  2 ++
 dlls/gdiplus/tests/font.c      | 13 ++++++++++++-
 3 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/dlls/gdiplus/font.c b/dlls/gdiplus/font.c
index 05663b71aad..c18e5702ca2 100644
--- a/dlls/gdiplus/font.c
+++ b/dlls/gdiplus/font.c
@@ -190,7 +190,7 @@ GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
     (*font)->unit = unit;
     (*font)->emSize = emSize;
     (*font)->otm = otm;
-    (*font)->family = (GpFontFamily *)fontFamily;
+    GdipCloneFontFamily((GpFontFamily*)fontFamily, &(*font)->family);
 
     TRACE("<-- %p\n", *font);
 
@@ -323,8 +323,7 @@ GpStatus WINGDIPAPI GdipGetFamily(GpFont *font, GpFontFamily **family)
     if (!(font && family))
         return InvalidParameter;
 
-    *family = font->family;
-    return Ok;
+    return GdipCloneFontFamily(font->family, family);
 }
 
 static REAL get_font_size(const GpFont *font)
@@ -746,9 +745,8 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
         {
             if (!wcsicmp(lf.lfFaceName, collection->FontFamilies[i]->FamilyName))
             {
-                *family = collection->FontFamilies[i];
+                status = GdipCloneFontFamily(collection->FontFamilies[i], family);
                 TRACE("<-- %p\n", *family);
-                status = Ok;
                 break;
             }
         }
@@ -778,6 +776,10 @@ GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily *family, GpFontFamily **clo
     TRACE("%p (%s), %p\n", family, debugstr_w(family->FamilyName), clone);
 
     *clone = family;
+
+    if (!family->installed)
+        InterlockedIncrement(&family->ref);
+
     return Ok;
 }
 
@@ -835,6 +837,11 @@ GpStatus WINGDIPAPI GdipDeleteFontFamily(GpFontFamily *FontFamily)
     if (!FontFamily)
         return InvalidParameter;
 
+    if (!FontFamily->installed && !InterlockedDecrement(&FontFamily->ref))
+    {
+        heap_free(FontFamily);
+    }
+
     return Ok;
 }
 
@@ -1079,7 +1086,7 @@ GpStatus WINGDIPAPI GdipDeletePrivateFontCollection(GpFontCollection **fontColle
     if (!fontCollection)
         return InvalidParameter;
 
-    for (i = 0; i < (*fontCollection)->count; i++) heap_free((*fontCollection)->FontFamilies[i]);
+    for (i = 0; i < (*fontCollection)->count; i++) GdipDeleteFontFamily((*fontCollection)->FontFamilies[i]);
     heap_free((*fontCollection)->FontFamilies);
     heap_free(*fontCollection);
 
@@ -1541,6 +1548,7 @@ GpStatus WINGDIPAPI GdipGetFontCollectionFamilyList(
 
     for (i = 0; i < numSought && i < fontCollection->count; i++)
     {
+        /* caller is responsible for cloning these if it keeps references */
         gpfamilies[i] = fontCollection->FontFamilies[i];
     }
 
@@ -1641,6 +1649,8 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm,
     family->descent = fm.descent;
     family->line_spacing = fm.line_spacing;
     family->dpi = fm.dpi;
+    family->installed = param->is_system;
+    family->ref = 1;
 
     lstrcpyW(family->FamilyName, lfw->lfFaceName);
 
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h
index aac5509afa7..07716690d47 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -528,6 +528,8 @@ struct GpFontFamily{
     WCHAR FamilyName[LF_FACESIZE];
     UINT16 em_height, ascent, descent, line_spacing; /* in font units */
     int dpi;
+    BOOL installed;
+    LONG ref;
 };
 
 /* internal use */
diff --git a/dlls/gdiplus/tests/font.c b/dlls/gdiplus/tests/font.c
index 32cd1ff2c4f..b208989c054 100644
--- a/dlls/gdiplus/tests/font.c
+++ b/dlls/gdiplus/tests/font.c
@@ -72,7 +72,7 @@ static void test_long_name(void)
     GpStatus stat;
     GpFontCollection *fonts;
     INT num_families;
-    GpFontFamily *family;
+    GpFontFamily *family, *cloned_family;
     WCHAR family_name[LF_FACESIZE];
     GpFont *font;
 
@@ -98,6 +98,10 @@ static void test_long_name(void)
     stat = GdipCreateFont(family, 256.0, FontStyleRegular, UnitPixel, &font);
     ok(stat == Ok, "GdipCreateFont failed: %d\n", stat);
 
+    stat = GdipCloneFontFamily(family, &cloned_family);
+    ok(stat == Ok, "GdipCloneFontFamily failed: %d\n", stat);
+    ok(family == cloned_family, "GdipCloneFontFamily returned new object\n");
+
     /* Cleanup */
 
     stat = GdipDeleteFont(font);
@@ -106,6 +110,13 @@ static void test_long_name(void)
     stat = GdipDeletePrivateFontCollection(&fonts);
     ok(stat == Ok, "GdipDeletePrivateFontCollection failed: %d\n", stat);
 
+    /* Cloned family survives after collection is deleted */
+    stat = GdipGetFamilyName(cloned_family, family_name, LANG_NEUTRAL);
+    ok(stat == Ok, "GdipGetFamilyName failed: %d\n", stat);
+
+    stat = GdipDeleteFontFamily(cloned_family);
+    ok(stat == Ok, "GdipDeleteFontFamily failed: %d\n", stat);
+
     DELETE_FONTFILE(path);
 }
 




More information about the wine-cvs mailing list