Cache system fonts in wxOSX
Call CTFontCreateUIFontForLanguage() only once for every CTFontUIFontType value and cache the results, as it is expensive to do it every time wxSystemSettings::GetFont() is called. Closes #19191. This commit is best viewed ignoring whitespace-only changes.
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
#include "wx/gdicmn.h"
|
#include "wx/gdicmn.h"
|
||||||
#include "wx/log.h"
|
#include "wx/log.h"
|
||||||
#include "wx/math.h"
|
#include "wx/math.h"
|
||||||
|
#include "wx/module.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "wx/fontutil.h"
|
#include "wx/fontutil.h"
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
#include "wx/osx/private.h"
|
#include "wx/osx/private.h"
|
||||||
#include "wx/osx/private/available.h"
|
#include "wx/osx/private/available.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -440,44 +442,115 @@ bool wxFont::Create(const wxNativeFontInfo& info)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Module maintaining and, most importantly, cleaning up, a cache wxFontRefData
|
||||||
|
// objects corresponding to the system fonts, as recreating them every time is
|
||||||
|
// too expensive.
|
||||||
|
class wxOSXSystemFontsCacheModule : public wxModule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxOSXSystemFontsCacheModule() { }
|
||||||
|
|
||||||
|
bool OnInit() wxOVERRIDE
|
||||||
|
{
|
||||||
|
for ( auto& p: ms_systemFontsCache )
|
||||||
|
p = nullptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnExit() wxOVERRIDE
|
||||||
|
{
|
||||||
|
for ( auto& p: ms_systemFontsCache )
|
||||||
|
{
|
||||||
|
if ( p )
|
||||||
|
{
|
||||||
|
p->DecRef();
|
||||||
|
p = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The returned pointer must be DecRef()'d by caller if non-null.
|
||||||
|
static wxFontRefData* Get(wxOSXSystemFont font)
|
||||||
|
{
|
||||||
|
wxCHECK(font != wxOSX_SYSTEM_FONT_NONE, nullptr);
|
||||||
|
|
||||||
|
wxFontRefData*& cached = ms_systemFontsCache[font - 1];
|
||||||
|
if ( !cached )
|
||||||
|
{
|
||||||
|
CTFontUIFontType uifont;
|
||||||
|
switch (font)
|
||||||
|
{
|
||||||
|
// This case is unreachable because of the precondition check
|
||||||
|
// above and is only present to avoid -Wswitch warnings.
|
||||||
|
case wxOSX_SYSTEM_FONT_NONE:
|
||||||
|
wxFALLTHROUGH;
|
||||||
|
|
||||||
|
case wxOSX_SYSTEM_FONT_NORMAL:
|
||||||
|
uifont = kCTFontSystemFontType;
|
||||||
|
break;
|
||||||
|
case wxOSX_SYSTEM_FONT_BOLD:
|
||||||
|
uifont = kCTFontEmphasizedSystemFontType;
|
||||||
|
break;
|
||||||
|
case wxOSX_SYSTEM_FONT_SMALL:
|
||||||
|
uifont = kCTFontSmallSystemFontType;
|
||||||
|
break;
|
||||||
|
case wxOSX_SYSTEM_FONT_SMALL_BOLD:
|
||||||
|
uifont = kCTFontSmallEmphasizedSystemFontType;
|
||||||
|
break;
|
||||||
|
case wxOSX_SYSTEM_FONT_MINI:
|
||||||
|
uifont = kCTFontMiniSystemFontType;
|
||||||
|
break;
|
||||||
|
case wxOSX_SYSTEM_FONT_MINI_BOLD:
|
||||||
|
uifont = kCTFontMiniEmphasizedSystemFontType;
|
||||||
|
break;
|
||||||
|
case wxOSX_SYSTEM_FONT_LABELS:
|
||||||
|
uifont = kCTFontLabelFontType;
|
||||||
|
break;
|
||||||
|
case wxOSX_SYSTEM_FONT_VIEWS:
|
||||||
|
uifont = kCTFontViewsFontType;
|
||||||
|
break;
|
||||||
|
case wxOSX_SYSTEM_FONT_FIXED:
|
||||||
|
uifont = kCTFontUIFontUserFixedPitch;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Remember to update Cache array size when adding new cases to
|
||||||
|
// this switch statement!
|
||||||
|
}
|
||||||
|
wxCFRef<CTFontRef> ctfont(CTFontCreateUIFontForLanguage(uifont, 0.0, NULL));
|
||||||
|
cached = new wxFontRefData(ctfont);
|
||||||
|
}
|
||||||
|
|
||||||
|
cached->IncRef();
|
||||||
|
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// This relies on wxOSX_SYSTEM_FONT_FIXED being the last element of enum,
|
||||||
|
// which should rename true until a new enum element is added, at which
|
||||||
|
// stage we should get a warning about the missing case in the switch above
|
||||||
|
// and the size of this array will need to be modified when adding the new
|
||||||
|
// case.
|
||||||
|
//
|
||||||
|
// Notice that we don't need "+ 1" here because we never cache the font for
|
||||||
|
// wxOSX_SYSTEM_FONT_NONE which should be never used, so we use the index
|
||||||
|
// of "enum value - 1" in the cache.
|
||||||
|
using Cache = std::array<wxFontRefData*, wxOSX_SYSTEM_FONT_FIXED>;
|
||||||
|
|
||||||
|
// Cache owns the pointers, i.e. calls DecRef() on them when it's destroyed.
|
||||||
|
static Cache ms_systemFontsCache;
|
||||||
|
|
||||||
|
wxDECLARE_DYNAMIC_CLASS(wxOSXSystemFontsCacheModule);
|
||||||
|
};
|
||||||
|
|
||||||
|
wxIMPLEMENT_DYNAMIC_CLASS(wxOSXSystemFontsCacheModule, wxModule);
|
||||||
|
|
||||||
|
wxOSXSystemFontsCacheModule::Cache wxOSXSystemFontsCacheModule::ms_systemFontsCache;
|
||||||
|
|
||||||
wxFont::wxFont(wxOSXSystemFont font)
|
wxFont::wxFont(wxOSXSystemFont font)
|
||||||
{
|
{
|
||||||
wxASSERT(font != wxOSX_SYSTEM_FONT_NONE);
|
m_refData = wxOSXSystemFontsCacheModule::Get(font);
|
||||||
CTFontUIFontType uifont = kCTFontSystemFontType;
|
|
||||||
switch (font)
|
|
||||||
{
|
|
||||||
case wxOSX_SYSTEM_FONT_NORMAL:
|
|
||||||
uifont = kCTFontSystemFontType;
|
|
||||||
break;
|
|
||||||
case wxOSX_SYSTEM_FONT_BOLD:
|
|
||||||
uifont = kCTFontEmphasizedSystemFontType;
|
|
||||||
break;
|
|
||||||
case wxOSX_SYSTEM_FONT_SMALL:
|
|
||||||
uifont = kCTFontSmallSystemFontType;
|
|
||||||
break;
|
|
||||||
case wxOSX_SYSTEM_FONT_SMALL_BOLD:
|
|
||||||
uifont = kCTFontSmallEmphasizedSystemFontType;
|
|
||||||
break;
|
|
||||||
case wxOSX_SYSTEM_FONT_MINI:
|
|
||||||
uifont = kCTFontMiniSystemFontType;
|
|
||||||
break;
|
|
||||||
case wxOSX_SYSTEM_FONT_MINI_BOLD:
|
|
||||||
uifont = kCTFontMiniEmphasizedSystemFontType;
|
|
||||||
break;
|
|
||||||
case wxOSX_SYSTEM_FONT_LABELS:
|
|
||||||
uifont = kCTFontLabelFontType;
|
|
||||||
break;
|
|
||||||
case wxOSX_SYSTEM_FONT_VIEWS:
|
|
||||||
uifont = kCTFontViewsFontType;
|
|
||||||
break;
|
|
||||||
case wxOSX_SYSTEM_FONT_FIXED:
|
|
||||||
uifont = kCTFontUIFontUserFixedPitch;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
wxCFRef<CTFontRef> ctfont(CTFontCreateUIFontForLanguage(uifont, 0.0, NULL));
|
|
||||||
m_refData = new wxFontRefData(ctfont);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if wxOSX_USE_COCOA
|
#if wxOSX_USE_COCOA
|
||||||
|
Reference in New Issue
Block a user