From e86154fcd2d943b39164d861ef2998264bc0ed25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Va=CC=81clav=20Slavi=CC=81k?= Date: Wed, 26 Aug 2020 19:00:22 +0200 Subject: [PATCH 1/2] 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. --- src/osx/carbon/font.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/osx/carbon/font.cpp b/src/osx/carbon/font.cpp index 2137281d7b..78020a603d 100644 --- a/src/osx/carbon/font.cpp +++ b/src/osx/carbon/font.cpp @@ -27,6 +27,7 @@ #include "wx/tokenzr.h" #include "wx/osx/private.h" +#include "wx/osx/private/available.h" #include #include @@ -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 From b03fa9c37f97230130b37fdf99eb8517235c32c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Va=CC=81clav=20Slavi=CC=81k?= Date: Thu, 27 Aug 2020 13:10:45 +0200 Subject: [PATCH 2/2] Fix UI font serialization on macOS 11 e86154fc is insufficient, because there's still one situation when PostScript names can't be avoided: when storing them using wxNativeFontInfo::ToString(). Co-authored-by: Stefan Csomor --- src/osx/carbon/font.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/osx/carbon/font.cpp b/src/osx/carbon/font.cpp index 78020a603d..1c7e767eda 100644 --- a/src/osx/carbon/font.cpp +++ b/src/osx/carbon/font.cpp @@ -1062,6 +1062,17 @@ wxString wxNativeFontInfo::GetPostScriptName() const // if not explicitly set, obtain it from the font descriptor wxString ps; wxCFTypeRef(CTFontDescriptorCopyAttribute(GetCTFontDescriptor(), kCTFontNameAttribute)).GetValue(ps); + + if ( WX_IS_MACOS_AVAILABLE(10, 16) ) + { + // the PostScript names reported in macOS start with a dot for System Fonts, this has to be corrected + // otherwise round-trips are not possible, resulting in a Times Fallback, therefore we replace these with + // their official PostScript Name + wxString rest; + if ( ps.StartsWith(".SFNS", &rest) ) + return "SFPro" + rest; + } + return ps; }