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@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
(cherry picked from commit a554079860)
Signed-off-by: Michael Stefaniuc <mstefani@winehq.org>
This commit is contained in:
Esme Povirk 2021-05-26 15:49:18 -05:00 committed by Michael Stefaniuc
parent bf92d6bedf
commit a0b7fb69e7
3 changed files with 30 additions and 7 deletions

View File

@ -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);

View File

@ -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 */

View File

@ -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);
}