Fix system UI font handling on macOS 11

PostScript name for the system SF font, starting with a dot, was always
considered private, but it was possible to round-trip it. Starting with
macOS 11, font descriptors can't be created from such names and result
in a Times font fallback.

To complicate matters further, the way PostScript name of the system
font is created changed too: it is no longer universal for entire
family, but specifies the weight too.

This combined together makes it impossible to store or modify system
fonts.

Fix by not relying on PostScript names internally. Only use them when
serializing font description or where needed, and in such cases obtain
it from CTFontDescriptor on demand.

Still preserve m_postScriptName as a user-provided detail, and treat it
as such: if provided, it is sacred and used to create font descriptors;
if not provided, never fill it in from other data.
This commit is contained in:
Václav Slavík
2020-08-26 19:00:22 +02:00
parent adb7c8a53d
commit e86154fcd2

View File

@@ -27,6 +27,7 @@
#include "wx/tokenzr.h"
#include "wx/osx/private.h"
#include "wx/osx/private/available.h"
#include <map>
#include <string>
@@ -324,10 +325,6 @@ void wxFontRefData::AllocIfNeeded() const
void wxFontRefData::Alloc()
{
wxCHECK_RET(m_info.GetPointSize() > 0, wxT("Point size should not be zero."));
// make sure the font descriptor has been processed properly
// otherwise the Post Script Name may not be valid yet
m_info.RealizeResource();
// use font caching, we cache a font with a certain size and a font with just any size for faster creation
wxString lookupnameNoSize = wxString::Format("%s_%d_%d", m_info.GetPostScriptName(), (int)m_info.GetStyle(), m_info.GetNumericWeight());
@@ -818,7 +815,6 @@ void wxNativeFontInfo::InitFromFontDescriptor(CTFontDescriptorRef desc)
}
wxCFTypeRef(CTFontDescriptorCopyAttribute(m_descriptor, kCTFontFamilyNameAttribute)).GetValue(m_familyName);
wxCFTypeRef(CTFontDescriptorCopyAttribute(m_descriptor, kCTFontNameAttribute)).GetValue(m_postScriptName);
}
void wxNativeFontInfo::Free()
@@ -876,7 +872,6 @@ void wxNativeFontInfo::CreateCTFontDescriptor()
m_descriptor = descriptor;
wxCFTypeRef(CTFontDescriptorCopyAttribute(m_descriptor, kCTFontFamilyNameAttribute)).GetValue(m_familyName);
wxCFTypeRef(CTFontDescriptorCopyAttribute(m_descriptor, kCTFontNameAttribute)).GetValue(m_postScriptName);
#if wxDEBUG_LEVEL >= 2
// for debugging: show all different font names
@@ -1022,10 +1017,6 @@ bool wxNativeFontInfo::FromString(const wxString& s)
wxString wxNativeFontInfo::ToString() const
{
// make sure the font descriptor has been processed properly
// otherwise the Post Script Name may not be valid yet
RealizeResource();
wxString s;
s.Printf(wxT("%d;%s;%d;%d;%d;%d;%d;%s;%d"),
@@ -1064,7 +1055,14 @@ bool wxNativeFontInfo::GetUnderlined() const
wxString wxNativeFontInfo::GetPostScriptName() const
{
return m_postScriptName;
// return user-set PostScript name as-is
if ( !m_postScriptName.empty() )
return m_postScriptName;
// if not explicitly set, obtain it from the font descriptor
wxString ps;
wxCFTypeRef(CTFontDescriptorCopyAttribute(GetCTFontDescriptor(), kCTFontNameAttribute)).GetValue(ps);
return ps;
}
wxString wxNativeFontInfo::GetFaceName() const