Esme Povirk : gdiplus: Implement reference counting for private font families.
Alexandre Julliard
julliard at winehq.org
Thu May 27 16:02:08 CDT 2021
Module: wine
Branch: master
Commit: a5540798605b3ef9abcf654bc28d9dd8d8736e53
URL: https://source.winehq.org/git/wine.git/?a=commit;h=a5540798605b3ef9abcf654bc28d9dd8d8736e53
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>
---
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 cf43985d02a..64604367da3 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 2b0f920473d..22213e9f278 100644
--- a/dlls/gdiplus/gdiplus_private.h
+++ b/dlls/gdiplus/gdiplus_private.h
@@ -543,6 +543,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