macOS wxNativeFontInfo changes (#2045)
* adding native font descriptor serialization = v2 * remove common xml prefix from serialized string * Update src/osx/carbon/font.cpp Co-authored-by: VZ <vz-github@zeitlins.org> * Update src/osx/carbon/font.cpp Co-authored-by: VZ <vz-github@zeitlins.org> * static string via accessor * striping off xml preamble unconditionally if we use a different format in the future, we will have to increase our version number * applying italic directly to the font descriptor thus preserving attributes in the native font descriptor which we don’t store explicitly yet * Adding support for preserving font width Although we don’t express this in the public API yet, we try to preserve eg condensed, when changing the font width * Adding reference, bug fix double checked the font weight constants, Co-authored-by: VZ <vz-github@zeitlins.org>
This commit is contained in:
@@ -173,6 +173,7 @@ public:
|
||||
|
||||
static CGFloat GetCTWeight( CTFontRef font );
|
||||
static CGFloat GetCTWeight( CTFontDescriptorRef font );
|
||||
static CGFloat GetCTwidth( CTFontDescriptorRef font );
|
||||
static CGFloat GetCTSlant( CTFontDescriptorRef font );
|
||||
|
||||
CTFontDescriptorRef GetCTFontDescriptor() const;
|
||||
@@ -182,6 +183,7 @@ private:
|
||||
// attributes for regenerating a CTFontDescriptor, stay close to native values
|
||||
// for better roundtrip fidelity
|
||||
CGFloat m_ctWeight;
|
||||
CGFloat m_ctWidth;
|
||||
wxFontStyle m_style;
|
||||
CGFloat m_ctSize;
|
||||
wxFontFamily m_family;
|
||||
|
@@ -170,15 +170,15 @@ namespace
|
||||
const int kCTWeightsCount = 12;
|
||||
static CGFloat gCTWeights[kCTWeightsCount] = {
|
||||
-1.000, // 0
|
||||
-0.800, // 100
|
||||
-0.600, // 200
|
||||
-0.400, // 300
|
||||
0.000, // 400
|
||||
0.230, // 500
|
||||
0.300, // 600
|
||||
0.400, // 700
|
||||
0.560, // 800
|
||||
0.620, // 900
|
||||
-0.800, // 100, NSFontWeightUltraLight
|
||||
-0.600, // 200, NSFontWeightThin
|
||||
-0.400, // 300, NSFontWeightLight
|
||||
0.000, // 400, NSFontWeightRegular
|
||||
0.230, // 500, NSFontWeightMedium
|
||||
0.300, // 600, NSFontWeightSemibold
|
||||
0.400, // 700, NSFontWeightBold
|
||||
0.560, // 800, NSFontWeightHeavy
|
||||
0.620, // 900, NSFontWeightBlack
|
||||
0.750, // 1000
|
||||
};
|
||||
|
||||
@@ -746,6 +746,7 @@ void wxNativeFontInfo::Init()
|
||||
m_encoding = wxFONTENCODING_UTF8;
|
||||
|
||||
m_ctWeight = 0.0;
|
||||
m_ctWidth = 0.0;
|
||||
m_style = wxFONTSTYLE_NORMAL;
|
||||
m_ctSize = 0.0;
|
||||
m_family = wxFONTFAMILY_DEFAULT;
|
||||
@@ -765,6 +766,7 @@ void wxNativeFontInfo::Init(const wxNativeFontInfo& info)
|
||||
m_encoding = info.m_encoding;
|
||||
|
||||
m_ctWeight = info.m_ctWeight;
|
||||
m_ctWidth = info.m_ctWidth;
|
||||
m_style = info.m_style;
|
||||
m_ctSize = info.m_ctSize;
|
||||
m_family = info.m_family;
|
||||
@@ -787,6 +789,7 @@ void wxNativeFontInfo::InitFromFontDescriptor(CTFontDescriptorRef desc)
|
||||
m_descriptor.reset(wxCFRetain(desc));
|
||||
|
||||
m_ctWeight = GetCTWeight(desc);
|
||||
m_ctWidth = GetCTwidth(desc);
|
||||
m_style = GetCTSlant(desc) > 0.01 ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL;
|
||||
wxCFTypeRef(CTFontDescriptorCopyAttribute(desc, kCTFontSizeAttribute)).GetValue(m_ctSize, CGFloat(0.0));
|
||||
|
||||
@@ -861,6 +864,7 @@ void wxNativeFontInfo::CreateCTFontDescriptor()
|
||||
traits.SetValue(kCTFontSymbolicTrait, kCTFontItalicTrait);
|
||||
|
||||
traits.SetValue(kCTFontWeightTrait,m_ctWeight);
|
||||
traits.SetValue(kCTFontWidthTrait,m_ctWidth);
|
||||
|
||||
attributes.SetValue(kCTFontTraitsAttribute,traits.get());
|
||||
attributes.SetValue(kCTFontSizeAttribute, m_ctSize);
|
||||
@@ -925,6 +929,15 @@ CGFloat wxNativeFontInfo::GetCTWeight(CTFontDescriptorRef descr)
|
||||
return weight;
|
||||
}
|
||||
|
||||
CGFloat wxNativeFontInfo::GetCTwidth(CTFontDescriptorRef descr)
|
||||
{
|
||||
CGFloat weight;
|
||||
CFTypeRef fonttraitstype = CTFontDescriptorCopyAttribute(descr, kCTFontTraitsAttribute);
|
||||
wxCFDictionaryRef traits((CFDictionaryRef)fonttraitstype);
|
||||
traits.GetValue(kCTFontWidthTrait).GetValue(&weight, CGFloat(0.0));
|
||||
return weight;
|
||||
}
|
||||
|
||||
CGFloat wxNativeFontInfo::GetCTSlant(CTFontDescriptorRef descr)
|
||||
{
|
||||
CGFloat slant;
|
||||
@@ -934,8 +947,18 @@ CGFloat wxNativeFontInfo::GetCTSlant(CTFontDescriptorRef descr)
|
||||
return slant;
|
||||
}
|
||||
|
||||
// recipe taken from
|
||||
// https://developer.apple.com/library/archive/documentation/StringsTextFonts/Conceptual/CoreText_Programming/FontOperations/FontOperations.html
|
||||
|
||||
// common prefix of plist serializiation, gets removed and readded
|
||||
|
||||
static const wxString& GetPListPrefix()
|
||||
{
|
||||
static const wxString s_plistPrefix = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE plist PUBLIC "
|
||||
"\"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">";
|
||||
return s_plistPrefix;
|
||||
}
|
||||
|
||||
//
|
||||
bool wxNativeFontInfo::FromString(const wxString& s)
|
||||
{
|
||||
double d;
|
||||
@@ -949,10 +972,9 @@ bool wxNativeFontInfo::FromString(const wxString& s)
|
||||
if ( !token.ToLong(&l) )
|
||||
return false;
|
||||
version = l;
|
||||
//
|
||||
// Ignore the version for now
|
||||
//
|
||||
|
||||
if ( version == 0 || version == 1 )
|
||||
{
|
||||
token = tokenizer.GetNextToken();
|
||||
if ( !token.ToCDouble(&d) )
|
||||
return false;
|
||||
@@ -1011,14 +1033,78 @@ bool wxNativeFontInfo::FromString(const wxString& s)
|
||||
if ( !token.ToLong(&l) )
|
||||
return false;
|
||||
m_encoding = (wxFontEncoding)l;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if ( version == 2 )
|
||||
{
|
||||
token = tokenizer.GetNextToken();
|
||||
if ( !token.ToLong(&l) )
|
||||
return false;
|
||||
bool underlined = l != 0;
|
||||
|
||||
token = tokenizer.GetNextToken();
|
||||
if ( !token.ToLong(&l) )
|
||||
return false;
|
||||
bool strikethrough = l != 0;
|
||||
|
||||
token = tokenizer.GetNextToken();
|
||||
if ( !token.ToLong(&l) )
|
||||
return false;
|
||||
wxFontEncoding encoding = (wxFontEncoding)l;
|
||||
|
||||
wxString xml = tokenizer.GetString();
|
||||
xml = GetPListPrefix()+xml;
|
||||
wxCFStringRef plist(xml);
|
||||
wxCFDataRef listData(CFStringCreateExternalRepresentation(kCFAllocatorDefault,plist,kCFStringEncodingUTF8,0));
|
||||
wxCFDictionaryRef attributes((CFDictionaryRef) CFPropertyListCreateWithData(kCFAllocatorDefault, listData, 0, NULL, NULL));
|
||||
CTFontDescriptorRef descriptor = NULL;
|
||||
if (attributes != NULL)
|
||||
descriptor = CTFontDescriptorCreateWithAttributes(attributes);
|
||||
if (descriptor != NULL)
|
||||
{
|
||||
InitFromFontDescriptor(descriptor);
|
||||
m_underlined = underlined;
|
||||
m_strikethrough = strikethrough;
|
||||
m_encoding = encoding;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString wxNativeFontInfo::ToString() const
|
||||
{
|
||||
wxString s;
|
||||
|
||||
// version 2 is a streamed property list of the font descriptor as recommended by Apple
|
||||
// prefixed by the attributes that are non-native to the native font ref like underline, strikethrough etc.
|
||||
wxCFDictionaryRef attributes(CTFontDescriptorCopyAttributes(GetCTFontDescriptor()));
|
||||
|
||||
if (attributes != NULL)
|
||||
{
|
||||
CFPropertyListFormat format = kCFPropertyListXMLFormat_v1_0;
|
||||
if (CFPropertyListIsValid(attributes, format))
|
||||
{
|
||||
wxCFDataRef listData(CFPropertyListCreateData(kCFAllocatorDefault, attributes, format, 0, NULL));
|
||||
wxCFStringRef cfString( CFStringCreateFromExternalRepresentation( kCFAllocatorDefault, listData, kCFStringEncodingUTF8) );
|
||||
wxString xml = cfString.AsString();
|
||||
xml.Replace("\r",wxEmptyString,true);
|
||||
xml.Replace("\t",wxEmptyString,true);
|
||||
xml = xml.Mid(xml.Find("<plist"));
|
||||
|
||||
s.Printf("%d;%d;%d;%d;%s",
|
||||
2, // version
|
||||
GetUnderlined(),
|
||||
GetStrikethrough(),
|
||||
(int)GetEncoding(),
|
||||
xml);
|
||||
}
|
||||
}
|
||||
|
||||
if ( s.empty() )
|
||||
{
|
||||
// fallback to version 1
|
||||
s.Printf(wxT("%d;%s;%d;%d;%d;%d;%d;%s;%d"),
|
||||
1, // version
|
||||
wxString::FromCDouble(GetFractionalPointSize()),
|
||||
@@ -1030,6 +1116,8 @@ wxString wxNativeFontInfo::ToString() const
|
||||
GetPostScriptName().GetData(),
|
||||
(int)GetEncoding());
|
||||
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -1122,7 +1210,13 @@ void wxNativeFontInfo::SetStyle(wxFontStyle style_)
|
||||
|
||||
if (formerIsItalic != newIsItalic)
|
||||
{
|
||||
Free();
|
||||
if ( m_descriptor )
|
||||
{
|
||||
if ( m_style != wxFONTSTYLE_NORMAL )
|
||||
m_descriptor = CTFontDescriptorCreateCopyWithSymbolicTraits(m_descriptor, kCTFontItalicTrait, kCTFontItalicTrait);
|
||||
else
|
||||
m_descriptor = CTFontDescriptorCreateCopyWithSymbolicTraits(m_descriptor, 0, kCTFontItalicTrait);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user