Commit a5540798 authored by Esme Povirk's avatar Esme Povirk Committed by Alexandre Julliard

gdiplus: Implement reference counting for private font families.

parent 7763efa3
...@@ -190,7 +190,7 @@ GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily, ...@@ -190,7 +190,7 @@ GpStatus WINGDIPAPI GdipCreateFont(GDIPCONST GpFontFamily *fontFamily,
(*font)->unit = unit; (*font)->unit = unit;
(*font)->emSize = emSize; (*font)->emSize = emSize;
(*font)->otm = otm; (*font)->otm = otm;
(*font)->family = (GpFontFamily *)fontFamily; GdipCloneFontFamily((GpFontFamily*)fontFamily, &(*font)->family);
TRACE("<-- %p\n", *font); TRACE("<-- %p\n", *font);
...@@ -323,8 +323,7 @@ GpStatus WINGDIPAPI GdipGetFamily(GpFont *font, GpFontFamily **family) ...@@ -323,8 +323,7 @@ GpStatus WINGDIPAPI GdipGetFamily(GpFont *font, GpFontFamily **family)
if (!(font && family)) if (!(font && family))
return InvalidParameter; return InvalidParameter;
*family = font->family; return GdipCloneFontFamily(font->family, family);
return Ok;
} }
static REAL get_font_size(const GpFont *font) static REAL get_font_size(const GpFont *font)
...@@ -746,9 +745,8 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name, ...@@ -746,9 +745,8 @@ GpStatus WINGDIPAPI GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name,
{ {
if (!wcsicmp(lf.lfFaceName, collection->FontFamilies[i]->FamilyName)) if (!wcsicmp(lf.lfFaceName, collection->FontFamilies[i]->FamilyName))
{ {
*family = collection->FontFamilies[i]; status = GdipCloneFontFamily(collection->FontFamilies[i], family);
TRACE("<-- %p\n", *family); TRACE("<-- %p\n", *family);
status = Ok;
break; break;
} }
} }
...@@ -778,6 +776,10 @@ GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily *family, GpFontFamily **clo ...@@ -778,6 +776,10 @@ GpStatus WINGDIPAPI GdipCloneFontFamily(GpFontFamily *family, GpFontFamily **clo
TRACE("%p (%s), %p\n", family, debugstr_w(family->FamilyName), clone); TRACE("%p (%s), %p\n", family, debugstr_w(family->FamilyName), clone);
*clone = family; *clone = family;
if (!family->installed)
InterlockedIncrement(&family->ref);
return Ok; return Ok;
} }
...@@ -835,6 +837,11 @@ GpStatus WINGDIPAPI GdipDeleteFontFamily(GpFontFamily *FontFamily) ...@@ -835,6 +837,11 @@ GpStatus WINGDIPAPI GdipDeleteFontFamily(GpFontFamily *FontFamily)
if (!FontFamily) if (!FontFamily)
return InvalidParameter; return InvalidParameter;
if (!FontFamily->installed && !InterlockedDecrement(&FontFamily->ref))
{
heap_free(FontFamily);
}
return Ok; return Ok;
} }
...@@ -1079,7 +1086,7 @@ GpStatus WINGDIPAPI GdipDeletePrivateFontCollection(GpFontCollection **fontColle ...@@ -1079,7 +1086,7 @@ GpStatus WINGDIPAPI GdipDeletePrivateFontCollection(GpFontCollection **fontColle
if (!fontCollection) if (!fontCollection)
return InvalidParameter; 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)->FontFamilies);
heap_free(*fontCollection); heap_free(*fontCollection);
...@@ -1541,6 +1548,7 @@ GpStatus WINGDIPAPI GdipGetFontCollectionFamilyList( ...@@ -1541,6 +1548,7 @@ GpStatus WINGDIPAPI GdipGetFontCollectionFamilyList(
for (i = 0; i < numSought && i < fontCollection->count; i++) for (i = 0; i < numSought && i < fontCollection->count; i++)
{ {
/* caller is responsible for cloning these if it keeps references */
gpfamilies[i] = fontCollection->FontFamilies[i]; gpfamilies[i] = fontCollection->FontFamilies[i];
} }
...@@ -1641,6 +1649,8 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm, ...@@ -1641,6 +1649,8 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm,
family->descent = fm.descent; family->descent = fm.descent;
family->line_spacing = fm.line_spacing; family->line_spacing = fm.line_spacing;
family->dpi = fm.dpi; family->dpi = fm.dpi;
family->installed = param->is_system;
family->ref = 1;
lstrcpyW(family->FamilyName, lfw->lfFaceName); lstrcpyW(family->FamilyName, lfw->lfFaceName);
......
...@@ -543,6 +543,8 @@ struct GpFontFamily{ ...@@ -543,6 +543,8 @@ struct GpFontFamily{
WCHAR FamilyName[LF_FACESIZE]; WCHAR FamilyName[LF_FACESIZE];
UINT16 em_height, ascent, descent, line_spacing; /* in font units */ UINT16 em_height, ascent, descent, line_spacing; /* in font units */
int dpi; int dpi;
BOOL installed;
LONG ref;
}; };
/* internal use */ /* internal use */
......
...@@ -72,7 +72,7 @@ static void test_long_name(void) ...@@ -72,7 +72,7 @@ static void test_long_name(void)
GpStatus stat; GpStatus stat;
GpFontCollection *fonts; GpFontCollection *fonts;
INT num_families; INT num_families;
GpFontFamily *family; GpFontFamily *family, *cloned_family;
WCHAR family_name[LF_FACESIZE]; WCHAR family_name[LF_FACESIZE];
GpFont *font; GpFont *font;
...@@ -98,6 +98,10 @@ static void test_long_name(void) ...@@ -98,6 +98,10 @@ static void test_long_name(void)
stat = GdipCreateFont(family, 256.0, FontStyleRegular, UnitPixel, &font); stat = GdipCreateFont(family, 256.0, FontStyleRegular, UnitPixel, &font);
ok(stat == Ok, "GdipCreateFont failed: %d\n", stat); 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 */ /* Cleanup */
stat = GdipDeleteFont(font); stat = GdipDeleteFont(font);
...@@ -106,6 +110,13 @@ static void test_long_name(void) ...@@ -106,6 +110,13 @@ static void test_long_name(void)
stat = GdipDeletePrivateFontCollection(&fonts); stat = GdipDeletePrivateFontCollection(&fonts);
ok(stat == Ok, "GdipDeletePrivateFontCollection failed: %d\n", stat); 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); DELETE_FONTFILE(path);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment