Get font family of private GDI+ font from the cache
When font family of a private font is retrieved with call to Gdiplus::Font::GetFamily() then later on there is thrown access violation exception when array of cached private font families (filled in by Gdiplus::PrivateFontCollection::GetFamilies()) is deleted in wxGDIPlusRenderer::Unload(). Call to Font::GetFamily() is done in wxGDIPlusContext::GetTextExtent() so this issue can be seen once text extent is retrieved for a private font. Because it looks that calling to Font::GetFamily() for a private font is messing up something in the array of cached private font families so we should avoid calling this method and directly fetch corresponding font family from the cache instead. Reference to the cached font family would be stored in the wxGDIPlusDataFont and it could be fetched from there directly instead of making a call to Font::GetFamily(). Closes #18704.
This commit is contained in:
@@ -361,6 +361,14 @@ public:
|
|||||||
|
|
||||||
virtual Brush* GetGDIPlusBrush() { return m_textBrush; }
|
virtual Brush* GetGDIPlusBrush() { return m_textBrush; }
|
||||||
virtual Font* GetGDIPlusFont() { return m_font; }
|
virtual Font* GetGDIPlusFont() { return m_font; }
|
||||||
|
virtual FontFamily * GetGDIPlusPrivateFontFamily() const
|
||||||
|
{
|
||||||
|
#if wxUSE_PRIVATE_FONTS
|
||||||
|
return m_privateFontFamily;
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif // wxUSE_PRIVATE_FONTS
|
||||||
|
}
|
||||||
|
|
||||||
private :
|
private :
|
||||||
// Common part of all ctors, flags here is a combination of values of
|
// Common part of all ctors, flags here is a combination of values of
|
||||||
@@ -381,6 +389,9 @@ private :
|
|||||||
|
|
||||||
Brush* m_textBrush;
|
Brush* m_textBrush;
|
||||||
Font* m_font;
|
Font* m_font;
|
||||||
|
#if wxUSE_PRIVATE_FONTS
|
||||||
|
FontFamily* m_privateFontFamily;
|
||||||
|
#endif // wxUSE_PRIVATE_FONTS
|
||||||
};
|
};
|
||||||
|
|
||||||
class wxGDIPlusContext : public wxGraphicsContext
|
class wxGDIPlusContext : public wxGraphicsContext
|
||||||
@@ -1086,6 +1097,7 @@ wxGDIPlusFontData::Init(const wxString& name,
|
|||||||
// If the user has registered any private fonts, they should be used in
|
// If the user has registered any private fonts, they should be used in
|
||||||
// preference to any system-wide ones.
|
// preference to any system-wide ones.
|
||||||
m_font = NULL;
|
m_font = NULL;
|
||||||
|
m_privateFontFamily = NULL;
|
||||||
if ( gs_privateFonts )
|
if ( gs_privateFonts )
|
||||||
{
|
{
|
||||||
const int count = gs_privateFonts->GetFamilyCount();
|
const int count = gs_privateFonts->GetFamilyCount();
|
||||||
@@ -1100,7 +1112,12 @@ wxGDIPlusFontData::Init(const wxString& name,
|
|||||||
int rc = gs_pFontFamily[j].GetFamilyName(familyName);
|
int rc = gs_pFontFamily[j].GetFamilyName(familyName);
|
||||||
if ( rc == 0 && name == familyName )
|
if ( rc == 0 && name == familyName )
|
||||||
{
|
{
|
||||||
m_font = new Font(&gs_pFontFamily[j], sizeInPixels, style, UnitPixel);
|
// Store reference to the cached FontFamily to avoid calling Font::GetFamily()
|
||||||
|
// for private font because calling this method apparently is messing up something
|
||||||
|
// in the array of font families (m_privateFontFamily).
|
||||||
|
m_privateFontFamily = &gs_pFontFamily[j];
|
||||||
|
m_font = new Font(m_privateFontFamily, sizeInPixels, style, UnitPixel);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2228,17 +2245,33 @@ void wxGDIPlusContext::GetTextExtent( const wxString &str, wxDouble *width, wxDo
|
|||||||
// Get the font metrics if we actually need them.
|
// Get the font metrics if we actually need them.
|
||||||
if ( descent || externalLeading || (height && str.empty()) )
|
if ( descent || externalLeading || (height && str.empty()) )
|
||||||
{
|
{
|
||||||
FontFamily ffamily ;
|
// Because it looks that calling to Font::GetFamily() for a private font is
|
||||||
f->GetFamily(&ffamily) ;
|
// messing up something in the array of cached private font families so
|
||||||
|
// we should avoid calling this method fetch corresponding font family
|
||||||
|
// from the cache instead.
|
||||||
|
FontFamily* pPrivFontFamily = ((wxGDIPlusFontData*)m_font.GetRefData())->GetGDIPlusPrivateFontFamily();
|
||||||
|
FontFamily* pffamily;
|
||||||
|
if ( pPrivFontFamily )
|
||||||
|
{
|
||||||
|
pffamily = pPrivFontFamily;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pffamily = new FontFamily;
|
||||||
|
f->GetFamily(pffamily);
|
||||||
|
}
|
||||||
|
|
||||||
// Notice that we must use the real font style or the results would be
|
// Notice that we must use the real font style or the results would be
|
||||||
// incorrect for italic/bold fonts.
|
// incorrect for italic/bold fonts.
|
||||||
const INT style = f->GetStyle();
|
const INT style = f->GetStyle();
|
||||||
const REAL size = f->GetSize();
|
const REAL size = f->GetSize();
|
||||||
const REAL emHeight = ffamily.GetEmHeight(style);
|
const REAL emHeight = pffamily->GetEmHeight(style);
|
||||||
REAL rDescent = ffamily.GetCellDescent(style) * size / emHeight;
|
REAL rDescent = pffamily->GetCellDescent(style) * size / emHeight;
|
||||||
REAL rAscent = ffamily.GetCellAscent(style) * size / emHeight;
|
REAL rAscent = pffamily->GetCellAscent(style) * size / emHeight;
|
||||||
REAL rHeight = ffamily.GetLineSpacing(style) * size / emHeight;
|
REAL rHeight = pffamily->GetLineSpacing(style) * size / emHeight;
|
||||||
|
|
||||||
|
if ( !pPrivFontFamily )
|
||||||
|
delete pffamily;
|
||||||
|
|
||||||
if ( height && str.empty() )
|
if ( height && str.empty() )
|
||||||
*height = rHeight;
|
*height = rHeight;
|
||||||
|
Reference in New Issue
Block a user