+
+// ----------------------------------------------------------------------------
+// wxNativeFontInfo
+// ----------------------------------------------------------------------------
+
+#if wxOSX_USE_CORE_TEXT
+
+/* from Core Text Manual Common Operations */
+
+static CTFontDescriptorRef wxMacCreateCTFontDescriptor(CFStringRef iFamilyName, CTFontSymbolicTraits iTraits )
+{
+ CTFontDescriptorRef descriptor = NULL;
+ CFMutableDictionaryRef attributes;
+
+ assert(iFamilyName != NULL);
+ // Create a mutable dictionary to hold our attributes.
+ attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ check(attributes != NULL);
+
+ if (attributes != NULL) {
+ // Add a family name to our attributes.
+ CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, iFamilyName);
+
+
+ if ( iTraits ) {
+ CFMutableDictionaryRef traits;
+ CFNumberRef symTraits;
+
+ // Create the traits dictionary.
+ symTraits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
+ &iTraits);
+ check(symTraits != NULL);
+
+ if (symTraits != NULL) {
+ // Create a dictionary to hold our traits values.
+ traits = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ check(traits != NULL);
+
+ if (traits != NULL) {
+ // Add the symbolic traits value to the traits dictionary.
+ CFDictionaryAddValue(traits, kCTFontSymbolicTrait, symTraits);
+
+ // Add the traits attribute to our attributes.
+ CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits);
+ CFRelease(traits);
+ }
+ CFRelease(symTraits);
+ }
+ }
+ // Create the font descriptor with our attributes
+ descriptor = CTFontDescriptorCreateWithAttributes(attributes);
+ check(descriptor != NULL);
+
+ CFRelease(attributes);
+ }
+ // Return our font descriptor.
+ return descriptor ;
+}
+
+#endif
+
+void wxNativeFontInfo::Init()
+{
+#if wxOSX_USE_CORE_TEXT
+ m_ctFontDescriptor = NULL;
+#endif
+#if wxOSX_USE_ATSU_TEXT
+ m_atsuFontID = 0 ;
+ m_atsuAdditionalQDStyles = 0;
+ m_atsuFontValid = false;
+#if wxOSX_USE_CARBON
+ m_qdFontStyle = 0;
+ m_qdFontFamily = 0;
+#endif
+#endif
+#if wxOSX_USE_COCOA
+ m_nsFontDescriptor = NULL;
+#endif
+ m_pointSize = 0;
+ m_family = wxFONTFAMILY_DEFAULT;
+ m_style = wxFONTSTYLE_NORMAL;
+ m_weight = wxFONTWEIGHT_NORMAL;
+ m_underlined = false;
+ m_faceName.clear();
+ m_encoding = wxFont::GetDefaultEncoding();
+ m_descriptorValid = false;
+}
+
+#if wxOSX_USE_CORE_TEXT
+void wxNativeFontInfo::Init(CTFontDescriptorRef descr)
+{
+ Init();
+ m_ctFontDescriptor = wxCFRetain(descr);
+
+ wxCFRef< CFNumberRef > sizevalue( (CFNumberRef) CTFontDescriptorCopyAttribute( m_ctFontDescriptor, kCTFontSizeAttribute ) );
+ float fsize;
+ if ( CFNumberGetValue( sizevalue , kCFNumberFloatType , &fsize ) )
+ m_pointSize = (int)( fsize + 0.5 );
+
+ wxCFRef< CFDictionaryRef > traitsvalue( (CFDictionaryRef) CTFontDescriptorCopyAttribute( m_ctFontDescriptor, kCTFontTraitsAttribute ) );
+ CTFontSymbolicTraits traits;
+ if ( CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(traitsvalue,kCTFontSymbolicTrait),kCFNumberIntType,&traits) )
+ {
+ if ( traits & kCTFontItalicTrait )
+ m_style = wxFONTSTYLE_ITALIC;
+ if ( traits & kCTFontBoldTrait )
+ m_weight = wxFONTWEIGHT_BOLD ;
+ }
+
+ wxCFStringRef familyName( (CFStringRef) CTFontDescriptorCopyAttribute(m_ctFontDescriptor, kCTFontFamilyNameAttribute));
+ m_faceName = familyName.AsString();
+}
+#endif
+
+void wxNativeFontInfo::EnsureValid()
+{
+ if ( m_descriptorValid )
+ return;
+
+#if wxOSX_USE_CORE_TEXT
+ if ( m_ctFontDescriptor == NULL && UMAGetSystemVersion() >= 0x1050 )
+ {
+ CTFontSymbolicTraits traits = 0;
+
+ if (m_weight == wxFONTWEIGHT_BOLD)
+ traits |= kCTFontBoldTrait;
+ if (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT)
+ traits |= kCTFontItalicTrait;
+
+ // use font caching
+ wxString lookupnameWithSize = wxString::Format( "%s_%ld_%ld", m_faceName.c_str(), traits, m_pointSize );
+
+ static std::map< std::wstring , wxCFRef< CTFontDescriptorRef > > fontdescriptorcache ;
+ m_ctFontDescriptor = wxCFRetain((CTFontDescriptorRef)fontdescriptorcache[ std::wstring(lookupnameWithSize.wc_str()) ]);
+ if ( !m_ctFontDescriptor )
+ {
+ // QD selection algorithm is the fastest by orders of magnitude on 10.5
+ if ( m_faceName.IsAscii() )
+ {
+ uint8_t qdstyle = 0;
+ if (m_weight == wxFONTWEIGHT_BOLD)
+ qdstyle |= bold;
+ if (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT)
+ qdstyle |= italic;
+
+ Str255 qdFontName ;
+ wxMacStringToPascal( m_faceName , qdFontName );
+ wxCFRef< CTFontRef > font;
+ font.reset( CTFontCreateWithQuickdrawInstance(qdFontName, 0 , qdstyle, m_pointSize) );
+ m_ctFontDescriptor = CTFontCopyFontDescriptor(font);
+ }
+ else
+ {
+ m_ctFontDescriptor = wxMacCreateCTFontDescriptor( wxCFStringRef(m_faceName),traits );
+ }
+ fontdescriptorcache[ std::wstring(lookupnameWithSize.wc_str()) ].reset(wxCFRetain(m_ctFontDescriptor));
+ }
+ }
+#endif
+#if wxOSX_USE_ATSU_TEXT
+ if ( !m_atsuFontValid )
+ {
+#if !wxOSX_USE_CARBON
+ // not needed outside
+ wxInt16 m_qdFontFamily;
+ wxInt16 m_qdFontStyle;
+#endif
+ wxCFStringRef cf( m_faceName, wxLocale::GetSystemEncoding() );
+ ATSFontFamilyRef atsfamily = ATSFontFamilyFindFromName( cf , kATSOptionFlagsDefault );
+ if ( atsfamily == (ATSFontFamilyRef) -1 )
+ {
+ wxLogDebug( wxT("ATSFontFamilyFindFromName failed for ") + m_faceName );
+ m_qdFontFamily = GetAppFont();
+ }
+ else
+ {
+ m_qdFontFamily = FMGetFontFamilyFromATSFontFamilyRef( atsfamily );
+ }
+
+ m_qdFontStyle = 0;
+ if (m_weight == wxFONTWEIGHT_BOLD)
+ m_qdFontStyle |= bold;
+ if (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT)
+ m_qdFontStyle |= italic;
+ if (m_underlined)
+ m_qdFontStyle |= underline;
+
+
+ // we try to get as much styles as possible into ATSU
+
+ // ATSUFontID and FMFont are equivalent
+ FMFontStyle intrinsicStyle = 0 ;
+ OSStatus status = FMGetFontFromFontFamilyInstance( m_qdFontFamily , m_qdFontStyle , (FMFont*)&m_atsuFontID , &intrinsicStyle);
+ wxASSERT_MSG( status == noErr , wxT("couldn't get an ATSUFont from font family") );
+ m_atsuAdditionalQDStyles = m_qdFontStyle & (~intrinsicStyle );
+ m_atsuFontValid = true;
+ }
+#endif
+#if wxOSX_USE_COCOA
+ if ( m_nsFontDescriptor == NULL )
+ OSXValidateNSFontDescriptor();
+#endif
+#if wxOSX_USE_IPHONE
+ // TODO
+#endif
+ m_descriptorValid = true;
+}
+
+void wxNativeFontInfo::Init(const wxNativeFontInfo& info)
+{
+ Init();
+#if wxOSX_USE_CORE_TEXT
+ m_ctFontDescriptor = wxCFRetain(info.m_ctFontDescriptor);
+#endif
+#if wxOSX_USE_ATSU_TEXT
+ m_atsuFontValid = info.m_atsuFontValid;
+ m_atsuFontID = info.m_atsuFontID ;
+ m_atsuAdditionalQDStyles = info.m_atsuAdditionalQDStyles;
+#if wxOSX_USE_CARBON
+ m_qdFontFamily = info.m_qdFontFamily;
+ m_qdFontStyle = info.m_qdFontStyle;
+#endif
+#endif
+#if wxOSX_USE_COCOA
+ m_nsFontDescriptor = (NSFontDescriptor*) wxMacCocoaRetain(info.m_nsFontDescriptor);
+#endif
+ m_pointSize = info.m_pointSize;
+ m_family = info.m_family;
+ m_style = info.m_style;
+ m_weight = info.m_weight;
+ m_underlined = info.m_underlined;
+ m_faceName = info.m_faceName;
+ m_encoding = info.m_encoding;
+ m_descriptorValid = info.m_descriptorValid;
+}
+
+void wxNativeFontInfo::Init(int size,
+ wxFontFamily family,
+ wxFontStyle style,
+ wxFontWeight weight,
+ bool underlined,
+ const wxString& faceName,
+ wxFontEncoding encoding)
+{
+ Init();
+ m_pointSize = size;
+ m_family = family;
+ m_style = style;
+ m_weight = weight;
+ m_underlined = underlined;
+ m_faceName = faceName;
+ if ( encoding == wxFONTENCODING_DEFAULT )
+ encoding = wxFont::GetDefaultEncoding();
+ m_encoding = encoding;
+
+}
+
+void wxNativeFontInfo::Free()
+{
+#if wxOSX_USE_CORE_TEXT
+ wxCFRelease(m_ctFontDescriptor);
+ m_ctFontDescriptor = NULL;
+#endif
+#if wxOSX_USE_ATSU_TEXT
+ m_atsuFontID = 0 ;
+ m_atsuAdditionalQDStyles = 0;
+ m_atsuFontValid = false;
+#endif
+#if wxOSX_USE_COCOA
+ wxMacCocoaRelease(m_nsFontDescriptor);
+ m_nsFontDescriptor = NULL;
+#endif
+ m_descriptorValid = false;
+}
+
+bool wxNativeFontInfo::FromString(const wxString& s)
+{
+ long l;
+
+ wxStringTokenizer tokenizer(s, _T(";"));
+
+ wxString token = tokenizer.GetNextToken();
+ //
+ // Ignore the version for now
+ //
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return false;
+ m_pointSize = (int)l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return false;
+ m_family = (wxFontFamily)l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return false;
+ m_style = (wxFontStyle)l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return false;
+ m_weight = (wxFontWeight)l;
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return false;
+ m_underlined = l != 0;
+
+ m_faceName = tokenizer.GetNextToken();
+
+#ifndef __WXMAC__
+ if( !faceName )
+ return false;
+#endif
+
+ token = tokenizer.GetNextToken();
+ if ( !token.ToLong(&l) )
+ return false;
+ m_encoding = (wxFontEncoding)l;
+
+ return true;
+}
+
+wxString wxNativeFontInfo::ToString() const
+{
+ wxString s;
+
+ s.Printf(_T("%d;%d;%d;%d;%d;%d;%s;%d"),
+ 0, // version
+ m_pointSize,
+ m_family,
+ (int)m_style,
+ (int)m_weight,
+ m_underlined,
+ m_faceName.GetData(),
+ (int)m_encoding);
+
+ return s;
+}
+
+int wxNativeFontInfo::GetPointSize() const
+{
+ return m_pointSize;
+}
+
+wxFontStyle wxNativeFontInfo::GetStyle() const
+{
+ return m_style;
+}
+
+wxFontWeight wxNativeFontInfo::GetWeight() const
+{
+ return m_weight;
+}
+
+bool wxNativeFontInfo::GetUnderlined() const
+{
+ return m_underlined;
+}
+
+wxString wxNativeFontInfo::GetFaceName() const
+{
+ return m_faceName;
+}
+
+wxFontFamily wxNativeFontInfo::GetFamily() const
+{
+ return m_family;
+}
+
+wxFontEncoding wxNativeFontInfo::GetEncoding() const
+{
+ return m_encoding;
+}
+
+// changing the font descriptor
+
+void wxNativeFontInfo::SetPointSize(int pointsize)
+{
+ if ( m_pointSize != pointsize )
+ {
+ m_pointSize = pointsize;
+ Free();
+ }
+}
+
+void wxNativeFontInfo::SetStyle(wxFontStyle style_)
+{
+ if ( m_style != style_ )
+ {
+ m_style = style_;
+ Free();
+ }
+}
+
+void wxNativeFontInfo::SetWeight(wxFontWeight weight_)
+{
+ if ( m_weight != weight_ )
+ {
+ m_weight = weight_;
+ Free();
+ }
+}
+
+void wxNativeFontInfo::SetUnderlined(bool underlined_)
+{
+ if ( m_underlined != underlined_ )
+ {
+ m_underlined = underlined_;
+ Free();
+ }
+}
+
+bool wxNativeFontInfo::SetFaceName(const wxString& facename_)
+{
+ if ( m_faceName != facename_ )
+ {
+ m_faceName = facename_;
+ Free();
+ }
+ return true;
+}
+
+void wxNativeFontInfo::SetFamily(wxFontFamily family_)
+{
+ if ( m_family != family_ )
+ {
+ m_family = family_;
+ Free();
+ }
+}
+
+void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_)
+{
+ if ( encoding_ == wxFONTENCODING_DEFAULT )
+ encoding_ = wxFont::GetDefaultEncoding();
+ m_encoding = encoding_;
+ // not reflected in native descriptors
+}
\ No newline at end of file