X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1fdb23edd611d62b48a8678268bee8900c0bb4fa..47e175a24f862aa8b7ca7dd4a2bb5957991e7f2d:/src/osx/carbon/font.cpp diff --git a/src/osx/carbon/font.cpp b/src/osx/carbon/font.cpp index a03c463027..634453ec6a 100644 --- a/src/osx/carbon/font.cpp +++ b/src/osx/carbon/font.cpp @@ -24,46 +24,33 @@ #include "wx/fontutil.h" #include "wx/graphics.h" #include "wx/settings.h" +#include "wx/tokenzr.h" #include "wx/osx/private.h" -#if wxOSX_USE_ATSU_TEXT && !wxOSX_USE_CARBON -// include themeing support -#include -#endif - #include #include -IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject) - - class WXDLLEXPORT wxFontRefData: public wxGDIRefData { public: + wxFontRefData() { - Init(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, - false, wxT("applicationfont"), wxFONTENCODING_DEFAULT); + Init(); + m_info.Init(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, + false, wxEmptyString, wxFONTENCODING_DEFAULT); } - wxFontRefData(const wxFontRefData& data) - { - Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight, - data.m_underlined, data.m_faceName, data.m_encoding); - } + wxFontRefData(const wxFontRefData& data); - wxFontRefData(int size, - wxFontFamily family, - wxFontStyle style, - wxFontWeight weight, - bool underlined, - const wxString& faceName, - wxFontEncoding encoding) + wxFontRefData( const wxNativeFontInfo& info ) : m_info(info) { - Init(size, family, style, weight, underlined, faceName, encoding); + Init(); } + wxFontRefData(wxOSXSystemFont font, int size); + #if wxOSX_USE_CORE_TEXT wxFontRefData( wxUint32 coreTextFontType ); wxFontRefData( CTFontRef font ); @@ -72,126 +59,151 @@ public: virtual ~wxFontRefData(); - void SetNoAntiAliasing( bool no = true ) { m_noAA = no; } - - bool GetNoAntiAliasing() const { return m_noAA; } - void SetPointSize( int size ) { - m_pointSize = size; - MacInvalidateNativeFont(); + if( GetPointSize() != size ) + { + m_info.SetPointSize(size); + Free(); + } } - int GetPointSize() const { return m_pointSize; } + int GetPointSize() const { return m_info.GetPointSize(); } void SetFamily( wxFontFamily family ) { - m_family = family; - MacInvalidateNativeFont(); + if ( m_info.m_family != family ) + { + m_info.SetFamily( family ); + Free(); + } } - - wxFontFamily GetFamily() const { return m_family; } + wxFontFamily GetFamily() const { return m_info.GetFamily(); } void SetStyle( wxFontStyle style ) { - m_style = style; - MacInvalidateNativeFont(); + if ( m_info.m_style != style ) + { + m_info.SetStyle( style ); + Free(); + } } - wxFontStyle GetStyle() const { return m_style; } + wxFontStyle GetStyle() const { return m_info.GetStyle(); } void SetWeight( wxFontWeight weight ) { - m_weight = weight; - MacInvalidateNativeFont(); + if ( m_info.m_weight != weight ) + { + m_info.SetWeight( weight ); + Free(); + } } - wxFontWeight GetWeight() const { return m_weight; } + wxFontWeight GetWeight() const { return m_info.GetWeight(); } void SetUnderlined( bool u ) { - m_underlined = u; - MacInvalidateNativeFont(); + if ( m_info.m_underlined != u ) + { + m_info.SetUnderlined( u ); + Free(); + } } - bool GetUnderlined() const { return m_underlined; } + bool GetUnderlined() const { return m_info.GetUnderlined(); } void SetFaceName( const wxString& facename ) { - m_faceName = facename; - MacInvalidateNativeFont(); + if ( m_info.m_faceName != facename ) + { + m_info.SetFaceName( facename ); + Free(); + } } - const wxString& GetFaceName() const { return m_faceName; } + wxString GetFaceName() const { return m_info.GetFaceName(); } void SetEncoding( wxFontEncoding encoding ) { - m_encoding = encoding; - MacInvalidateNativeFont(); + if ( m_info.m_encoding != encoding ) + { + m_info.SetEncoding( encoding ); + Free(); + } } - wxFontEncoding GetEncoding() const { return m_encoding; } + wxFontEncoding GetEncoding() const { return m_info.GetEncoding(); } + + bool IsFixedWidth() const; - void MacInvalidateNativeFont(); + void Free(); void MacFindFont(); protected: // common part of all ctors - void Init(int size, - wxFontFamily family, - wxFontStyle style, - wxFontWeight weight, - bool underlined, - const wxString& faceName, - wxFontEncoding encoding); - + void Init(); #if wxOSX_USE_CORE_TEXT - void Init( CTFontRef font ); + // void Init( CTFontRef font ); #endif - // font characterstics - int m_pointSize; - wxFontFamily m_family; - wxFontStyle m_style; - wxFontWeight m_weight; - bool m_underlined; - wxString m_faceName; - wxFontEncoding m_encoding; - bool m_noAA; // No anti-aliasing - public: -#if wxOSX_USE_ATSU_TEXT - FMFontFamily m_macFontFamily; - FMFontSize m_macFontSize; - FMFontStyle m_macFontStyle; - - // ATSU Font Information - - // this is split into an ATSU font id that may - // contain some styles (special bold fonts etc) and - // these are the additional qd styles that are not - // included in the ATSU font id - ATSUFontID m_macATSUFontID; - FMFontStyle m_macATSUAdditionalQDStyles ; - - // for true themeing support we must store the correct font + bool m_fontValid; +#if wxOSX_USE_CARBON && wxOSX_USE_ATSU_TEXT + // for true theming support we must store the correct font // information here, as this speeds up and optimizes rendering ThemeFontID m_macThemeFontID ; #endif #if wxOSX_USE_CORE_TEXT wxCFRef m_ctFont; #endif -#if wxOSX_USE_CORE_TEXT || wxOSX_USE_ATSU_TEXT +#if wxOSX_USE_ATSU_TEXT + void CreateATSUFont(); + ATSUStyle m_macATSUStyle ; +#endif + wxCFRef m_cgFont; +#if wxOSX_USE_COCOA + WX_NSFont m_nsFont; +#endif +#if wxOSX_USE_IPHONE + WX_UIFont m_uiFont; #endif wxNativeFontInfo m_info; }; #define M_FONTDATA ((wxFontRefData*)m_refData) +wxFontRefData::wxFontRefData(const wxFontRefData& data) : wxGDIRefData() +{ + Init(); + m_info = data.m_info; + m_fontValid = data.m_fontValid; +#if wxOSX_USE_CARBON && wxOSX_USE_ATSU_TEXT + m_macThemeFontID = data.m_macThemeFontID; +#endif +#if wxOSX_USE_CORE_TEXT + m_ctFont = data.m_ctFont; +#endif + m_cgFont = data.m_cgFont; +#if wxOSX_USE_ATSU_TEXT + if ( data.m_macATSUStyle != NULL ) + { + ATSUCreateStyle(&m_macATSUStyle) ; + ATSUCopyAttributes(data.m_macATSUStyle, m_macATSUStyle); + } +#endif +#if wxOSX_USE_COCOA + m_nsFont = (NSFont*) wxMacCocoaRetain(data.m_nsFont); +#endif +#if wxOSX_USE_IPHONE + m_uiFont = (UIFont*) wxMacCocoaRetain(data.m_uiFont); +#endif + +} // ============================================================================ // implementation @@ -201,494 +213,342 @@ public: // wxFontRefData // ---------------------------------------------------------------------------- -void wxFontRefData::Init(int pointSize, - wxFontFamily family, - wxFontStyle style, - wxFontWeight weight, - bool underlined, - const wxString& faceName, - wxFontEncoding encoding) +void wxFontRefData::Init() { - m_style = style; - m_pointSize = (pointSize == -1) ? wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).GetPointSize() : pointSize; - m_family = family; - m_style = style; - m_weight = weight; - m_underlined = underlined; - m_faceName = faceName; - m_encoding = encoding; - m_noAA = false; -#if wxOSX_USE_ATSU_TEXT - m_macFontFamily = 0 ; - m_macFontSize = 0; - m_macFontStyle = 0; - m_macATSUFontID = 0; - m_macATSUAdditionalQDStyles = 0 ; +#if wxOSX_USE_CARBON && wxOSX_USE_ATSU_TEXT m_macThemeFontID = kThemeCurrentPortFont ; #endif -#if wxOSX_USE_CORE_TEXT || wxOSX_USE_ATSU_TEXT +#if wxOSX_USE_ATSU_TEXT m_macATSUStyle = NULL ; #endif +#if wxOSX_USE_COCOA + m_nsFont = NULL; +#endif +#if wxOSX_USE_IPHONE + m_uiFont = NULL; +#endif + m_fontValid = false; } wxFontRefData::~wxFontRefData() { -#if wxOSX_USE_CORE_TEXT || wxOSX_USE_ATSU_TEXT - if ( m_macATSUStyle ) - { - ::ATSUDisposeStyle((ATSUStyle)m_macATSUStyle); - m_macATSUStyle = NULL ; - } -#endif + Free(); } -void wxFontRefData::MacInvalidateNativeFont() +void wxFontRefData::Free() { #if wxOSX_USE_CORE_TEXT m_ctFont.reset(); #endif -#if wxOSX_USE_CORE_TEXT || wxOSX_USE_ATSU_TEXT + m_cgFont.reset(); +#if wxOSX_USE_ATSU_TEXT +#if wxOSX_USE_CARBON + m_macThemeFontID = kThemeCurrentPortFont ; +#endif if ( m_macATSUStyle ) { ::ATSUDisposeStyle((ATSUStyle)m_macATSUStyle); m_macATSUStyle = NULL ; } #endif -} - -#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); +#if wxOSX_USE_COCOA + if (m_nsFont != NULL) + { + wxMacCocoaRelease(m_nsFont); + m_nsFont = NULL; } - // Return our font descriptor. - return descriptor ; -} - -wxFontRefData::wxFontRefData( wxUint32 coreTextFontType ) -{ - CTFontRef font = CTFontCreateUIFontForLanguage( coreTextFontType, 0.0, NULL ) ; - if ( CTFontGetSize(font) == 0 ) +#endif +#if wxOSX_USE_IPHONE + if (m_uiFont != NULL) { - CFRelease(font); - font = CTFontCreateUIFontForLanguage( coreTextFontType, 12.0, NULL ); + wxMacCocoaRelease(m_uiFont); + m_uiFont = NULL; } - Init( font ); +#endif + m_fontValid = false; } -wxFontRefData::wxFontRefData( CTFontRef font ) +wxFontRefData::wxFontRefData(wxOSXSystemFont font, int size) { - Init( font ); -} + wxASSERT( font != wxOSX_SYSTEM_FONT_NONE ); + Init(); -wxFontRefData::wxFontRefData( CTFontDescriptorRef fontdescriptor, int size ) -{ - if ( size == 0 ) +#if wxOSX_USE_CORE_TEXT { - wxCFRef< CFNumberRef > value( (CFNumberRef) CTFontDescriptorCopyAttribute( fontdescriptor, kCTFontSizeAttribute ) ); - - float fsize; - if ( CFNumberGetValue( value , kCFNumberFloatType , &fsize ) ) + CTFontUIFontType uifont = kCTFontSystemFontType; + switch( font ) { - size = (int)( fsize + 0.5 ); + 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; + default: + break; } + m_ctFont.reset(CTFontCreateUIFontForLanguage( uifont, (CGFloat) size, NULL )); + wxCFRef descr; + descr.reset( CTFontCopyFontDescriptor( m_ctFont ) ); + m_info.Init(descr); } - Init( CTFontCreateWithFontDescriptor(fontdescriptor, size,NULL) ); -} +#endif +#if wxOSX_USE_ATSU_TEXT + { +#if !wxOSX_USE_CARBON + // not needed outside + ThemeFontID m_macThemeFontID = kThemeSystemFont; +#endif + switch( font ) + { + case wxOSX_SYSTEM_FONT_NORMAL: + m_macThemeFontID = kThemeSystemFont; + break; + case wxOSX_SYSTEM_FONT_BOLD: + m_macThemeFontID = kThemeEmphasizedSystemFont; + break; + case wxOSX_SYSTEM_FONT_SMALL: + m_macThemeFontID = kThemeSmallSystemFont; + break; + case wxOSX_SYSTEM_FONT_SMALL_BOLD: + m_macThemeFontID = kThemeSmallEmphasizedSystemFont; + break; + case wxOSX_SYSTEM_FONT_MINI: + m_macThemeFontID = kThemeMiniSystemFont; + break; + case wxOSX_SYSTEM_FONT_MINI_BOLD: + // bold not available under theming + m_macThemeFontID = kThemeMiniSystemFont; + break; + case wxOSX_SYSTEM_FONT_LABELS: + m_macThemeFontID = kThemeLabelFont; + break; + case wxOSX_SYSTEM_FONT_VIEWS: + m_macThemeFontID = kThemeViewsFont; + break; + default: + break; + } + if ( m_info.m_faceName.empty() ) + { + Style style ; + FMFontSize fontSize; + Str255 qdFontName ; -void wxFontRefData::Init( CTFontRef font ) -{ - Init(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, - false, wxT("applicationfont"), wxFONTENCODING_DEFAULT); + GetThemeFont( m_macThemeFontID, GetApplicationScript(), qdFontName, &fontSize, &style ); + if ( size != 0 ) + fontSize = size; - m_ctFont.reset( font ); -} + wxFontStyle fontstyle = wxFONTSTYLE_NORMAL; + wxFontWeight fontweight = wxFONTWEIGHT_NORMAL; + bool underlined = false; + if ( style & bold ) + fontweight = wxFONTWEIGHT_BOLD ; + else + fontweight = wxFONTWEIGHT_NORMAL ; + if ( style & italic ) + fontstyle = wxFONTSTYLE_ITALIC ; + if ( style & underline ) + underlined = true ; + + m_info.Init(fontSize,wxFONTFAMILY_DEFAULT,fontstyle,fontweight,underlined, + wxMacMakeStringFromPascal( qdFontName ), wxFONTENCODING_DEFAULT); + } + } +#endif +#if wxOSX_USE_COCOA + m_nsFont = wxFont::OSXCreateNSFont( font, &m_info ); +#endif +#if wxOSX_USE_IPHONE + m_uiFont = wxFont::OSXCreateUIFont( font, &m_info ); +#endif + m_info.EnsureValid(); +#if wxOSX_USE_ATSU_TEXT + CreateATSUFont(); #endif -void wxFontRefData::MacFindFont() -{ + m_fontValid = true; +} -#if wxOSX_USE_CORE_TEXT - if ( UMAGetSystemVersion() >= 0x1050 ) - { - if ( m_faceName.empty() && m_family == wxFONTFAMILY_DEFAULT ) - { - m_ctFont.reset(CTFontCreateUIFontForLanguage( kCTFontSystemFontType, 0.0, NULL )); - } +#if wxOSX_USE_ATSU_TEXT +void wxFontRefData::CreateATSUFont() +{ + // we try to get as much styles as possible into ATSU - if ( m_ctFont ) - { - wxCFStringRef name( CTFontCopyFamilyName( m_ctFont ) ); - m_faceName = name.AsString(); - m_pointSize = CTFontGetSize(m_ctFont) ; - CTFontSymbolicTraits traits = CTFontGetSymbolicTraits( m_ctFont ); - if ( traits & kCTFontItalicTrait ) - m_style = wxFONTSTYLE_ITALIC; - if ( traits & kCTFontBoldTrait ) - m_weight = wxFONTWEIGHT_BOLD ; - } - else - { - if ( m_faceName.empty() ) - { - switch ( m_family ) - { - case wxFONTFAMILY_SCRIPT : - case wxFONTFAMILY_ROMAN : - case wxFONTFAMILY_DECORATIVE : - m_faceName = wxT("Times"); - break ; - - case wxFONTFAMILY_SWISS : - m_faceName = wxT("Helvetica"); - break ; - - case wxFONTFAMILY_MODERN : - case wxFONTFAMILY_TELETYPE: - m_faceName = wxT("Courier"); - if ( m_style == wxFONTFAMILY_ITALIC && m_weight == wxFONTFAMILY_NORMAL ) - { - m_style = wxFONTFAMILY_ITALIC; - } - break ; + OSStatus status = ::ATSUCreateStyle(&m_macATSUStyle); + wxASSERT_MSG( status == noErr , wxT("couldn't create ATSU style") ); - default: - m_faceName = wxT("Times"); - break ; - } - } + ATSUAttributeTag atsuTags[] = + { + kATSUFontTag , + kATSUSizeTag , + kATSUVerticalCharacterTag, + kATSUQDBoldfaceTag , + kATSUQDItalicTag , + kATSUQDUnderlineTag , + kATSUQDCondensedTag , + kATSUQDExtendedTag , + }; + ByteCount atsuSizes[WXSIZEOF(atsuTags)] = + { + sizeof( ATSUFontID ) , + sizeof( Fixed ) , + sizeof( ATSUVerticalCharacterType), + sizeof( Boolean ) , + sizeof( Boolean ) , + sizeof( Boolean ) , + sizeof( Boolean ) , + sizeof( Boolean ) , + }; + + Boolean kTrue = true ; + Boolean kFalse = false ; + + Fixed atsuSize = IntToFixed( m_info.m_pointSize ); + ATSUVerticalCharacterType kHorizontal = kATSUStronglyHorizontal; + FMFontStyle addQDStyle = m_info.m_atsuAdditionalQDStyles; + ATSUAttributeValuePtr atsuValues[WXSIZEOF(atsuTags)] = + { + &m_info.m_atsuFontID , + &atsuSize , + &kHorizontal, + (addQDStyle & bold) ? &kTrue : &kFalse , + (addQDStyle & italic) ? &kTrue : &kFalse , + (addQDStyle & underline) ? &kTrue : &kFalse , + (addQDStyle & condense) ? &kTrue : &kFalse , + (addQDStyle & extend) ? &kTrue : &kFalse , + }; + + status = ::ATSUSetAttributes( + (ATSUStyle)m_macATSUStyle, + WXSIZEOF(atsuTags), + atsuTags, atsuSizes, atsuValues); + + wxASSERT_MSG( status == noErr , wxString::Format(wxT("couldn't modify ATSU style. Status was %d"), (int) status).c_str() ); + + if ( m_cgFont.get() == NULL ) + { + ATSFontRef fontRef = FMGetATSFontRefFromFont(m_info.m_atsuFontID); + m_cgFont.reset( CGFontCreateWithPlatformFont( &fontRef ) ); + } +} +#endif +static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } +static const CGAffineTransform kSlantTransform = CGAffineTransformMake( 1, 0, tan(DegToRad(11)), 1, 0, 0 ); - CTFontSymbolicTraits traits = 0; +void wxFontRefData::MacFindFont() +{ + if ( m_fontValid ) + return; - if (m_weight == wxFONTWEIGHT_BOLD) - traits |= kCTFontBoldTrait; - if (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT) - traits |= kCTFontItalicTrait; + wxCHECK_RET( m_info.m_pointSize > 0, wxT("Point size should not be zero.") ); - // use font caching - wxString lookupnameWithSize = wxString::Format( "%s_%ld_%ld", m_faceName.c_str(), traits, m_pointSize ); + m_info.EnsureValid(); - static std::map< std::wstring , wxCFRef< CTFontRef > > fontcache ; - m_ctFont = fontcache[ std::wstring(lookupnameWithSize.wc_str()) ]; - if ( !m_ctFont ) - { - // QD selection algorithm is the fastest by orders of magnitude on 10.5 - if ( m_faceName.IsAscii() ) - { - uint8 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 ); - m_ctFont.reset( CTFontCreateWithQuickdrawInstance(qdFontName, 0 , qdstyle, m_pointSize) ); - } - else - { +#if wxOSX_USE_CORE_TEXT + { + CTFontSymbolicTraits traits = 0; - static std::map< std::wstring , wxCFRef< CTFontDescriptorRef > > fontdescriptorcache ; - wxString lookupname = wxString::Format( "%s_%ld", m_faceName.c_str(), traits ); - // descriptor caching - wxCFRef< CTFontDescriptorRef > descriptor = fontdescriptorcache[ std::wstring(lookupname.wc_str()) ]; - if ( !descriptor ) - { - wxCFStringRef cf( m_faceName, wxLocale::GetSystemEncoding() ); - descriptor.reset( wxMacCreateCTFontDescriptor( cf, traits ) ); - fontdescriptorcache[ std::wstring(lookupname.wc_str()) ] = descriptor; - } - m_ctFont.reset( CTFontCreateWithFontDescriptor( descriptor, m_pointSize, NULL ) ); - CTFontSymbolicTraits received = CTFontGetSymbolicTraits( m_ctFont ) & 0x03; - if ( traits != received ) - { - // TODO further fallbacks, synthesizing bold and italic, trying direct PostScript names etc - } - } + if (m_info.m_weight == wxFONTWEIGHT_BOLD) + traits |= kCTFontBoldTrait; + if (m_info.m_style == wxFONTSTYLE_ITALIC || m_info.m_style == wxFONTSTYLE_SLANT) + traits |= kCTFontItalicTrait; - fontcache[ std::wstring(lookupnameWithSize.wc_str()) ] = m_ctFont; -#if 1 // debugging coretext font matching - CTFontSymbolicTraits received = CTFontGetSymbolicTraits( m_ctFont ) & 0x03; - if ( received != traits ) - { - float angle = CTFontGetSlantAngle( m_ctFont ); - CFDictionaryRef dict = CTFontCopyTraits( m_ctFont ); - CFNumberRef number = (CFNumberRef) CFDictionaryGetValue(dict, kCTFontWeightTrait ); - float floatnumber; - CFNumberGetValue( number, kCFNumberFloatType, &floatnumber ); - { - wxString msg = wxString::Format( "font %s expected %d but got %d traits, %f angle \n" , - m_faceName.c_str(), traits, received, angle ); - printf( msg.c_str() ); - } - CFShow( dict ); - CFRelease( dict ); - } -#endif - } + // use font caching + wxString lookupnameWithSize = wxString::Format( "%s_%u_%d", m_info.m_faceName, traits, m_info.m_pointSize ); - } -#if wxOSX_USE_ATSU_TEXT - OSStatus status = noErr; - ATSFontRef atsfont = CTFontGetPlatformFont( m_ctFont, NULL ); - FMFont fmfont = FMGetFontFromATSFontRef( atsfont ); - ATSUAttributeTag atsuTags[] = - { - kATSUFontTag , - kATSUSizeTag , - kATSUVerticalCharacterTag, - kATSUQDBoldfaceTag , - kATSUQDItalicTag , - kATSUQDUnderlineTag , - }; - ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] = - { - sizeof( ATSUFontID ) , - sizeof( Fixed ) , - sizeof( ATSUVerticalCharacterType), - sizeof( Boolean ) , - sizeof( Boolean ) , - sizeof( Boolean ) , - }; - Boolean kTrue = true ; - Boolean kFalse = false ; - - Fixed atsuSize = IntToFixed( m_pointSize ); - ATSUVerticalCharacterType kHorizontal = kATSUStronglyHorizontal; - ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] = - { - &fmfont , - &atsuSize , - &kHorizontal, - (m_weight == wxFONTWEIGHT_BOLD) ? &kTrue : &kFalse , - (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT) ? &kTrue : &kFalse , - (m_underlined) ? &kTrue : &kFalse , - }; - - if ( m_macATSUStyle ) - { - ::ATSUDisposeStyle((ATSUStyle)m_macATSUStyle); - m_macATSUStyle = NULL ; - } - status = ::ATSUCreateStyle((ATSUStyle *)&m_macATSUStyle); - wxASSERT_MSG( status == noErr , wxT("couldn't create ATSU style") ); - status = ::ATSUSetAttributes( - (ATSUStyle)m_macATSUStyle, - sizeof(atsuTags) / sizeof(ATSUAttributeTag) , - atsuTags, atsuSizes, atsuValues); -#endif - } -#endif -#if wxOSX_USE_ATSU_TEXT - { - OSStatus status = noErr; - Str255 qdFontName ; - if ( m_macThemeFontID != kThemeCurrentPortFont ) - { - Style style ; - GetThemeFont( m_macThemeFontID, GetApplicationScript(), qdFontName, &m_macFontSize, &style ); - if ( m_macFontSize == 0 ) - m_macFontSize = 12; - m_macFontStyle = style ; - m_faceName = wxMacMakeStringFromPascal( qdFontName ); - if ( m_macFontStyle & bold ) - m_weight = wxFONTWEIGHT_BOLD ; - else - m_weight = wxFONTWEIGHT_NORMAL ; - if ( m_macFontStyle & italic ) - m_style = wxFONTSTYLE_ITALIC ; - if ( m_macFontStyle & underline ) - m_underlined = true ; - m_pointSize = m_macFontSize ; - m_macFontFamily = FMGetFontFamilyFromName( qdFontName ); - } - else + static std::map< std::wstring , wxCFRef< CTFontRef > > fontcache ; + m_ctFont = fontcache[ std::wstring(lookupnameWithSize.wc_str()) ]; + if ( !m_ctFont ) { - if ( m_faceName.empty() ) + m_ctFont.reset(CTFontCreateWithName( wxCFStringRef(m_info.m_faceName), m_info.m_pointSize , NULL )); + if ( m_ctFont.get() == NULL ) { - if ( m_family == wxFONTFAMILY_DEFAULT ) - { - m_macFontFamily = GetAppFont(); - FMGetFontFamilyName(m_macFontFamily,qdFontName); - m_faceName = wxMacMakeStringFromPascal( qdFontName ); - } - else - { - switch ( m_family ) - { - case wxFONTFAMILY_SCRIPT : - case wxFONTFAMILY_ROMAN : - case wxFONTFAMILY_DECORATIVE : - m_faceName = wxT("Times"); - break ; - - case wxFONTFAMILY_SWISS : - m_faceName = wxT("Helvetica"); - break ; - - case wxFONTFAMILY_MODERN : - case wxFONTFAMILY_TELETYPE: - m_faceName = wxT("Courier"); - break ; - - default: - m_faceName = wxT("Times"); - break ; - } - wxMacStringToPascal( m_faceName , qdFontName ); - m_macFontFamily = FMGetFontFamilyFromName( qdFontName ); - if ( m_macFontFamily == kInvalidFontFamily ) - { - wxLogDebug( wxT("ATSFontFamilyFindFromName failed for %s"), m_faceName.c_str() ); - m_macFontFamily = GetAppFont(); - } - } + // TODO try fallbacks according to font type + m_ctFont.reset(CTFontCreateUIFontForLanguage( kCTFontSystemFontType, m_info.m_pointSize , NULL )); } else { - if ( m_faceName == wxT("systemfont") ) - m_macFontFamily = GetSysFont(); - else if ( m_faceName == wxT("applicationfont") ) - m_macFontFamily = GetAppFont(); - else + if ( traits != 0 ) { - wxCFStringRef cf( m_faceName, wxLocale::GetSystemEncoding() ); - ATSFontFamilyRef atsfamily = ATSFontFamilyFindFromName( cf , kATSOptionFlagsDefault ); - if ( atsfamily == (ATSFontFamilyRef) -1 ) + // attempt native font variant, if not available, fallback to italic emulation mode and remove bold + CTFontRef fontWithTraits = CTFontCreateCopyWithSymbolicTraits( m_ctFont, 0, NULL, traits, traits ); + if ( fontWithTraits == NULL ) { - wxLogDebug( wxT("ATSFontFamilyFindFromName failed for ") + m_faceName ); - m_macFontFamily = GetAppFont(); + CTFontSymbolicTraits remainingTraits = traits; + const CGAffineTransform* remainingTransform = NULL; + + if( remainingTraits & kCTFontItalicTrait ) + { + remainingTraits &= ~kCTFontItalicTrait; + remainingTransform = &kSlantTransform; + if ( remainingTraits & kCTFontBoldTrait ) + { + // first try an emulated oblique with an existing bold font + fontWithTraits = CTFontCreateCopyWithSymbolicTraits( m_ctFont, 0, remainingTransform, remainingTraits, remainingTraits ); + if ( fontWithTraits == NULL ) + { + // give in on the bold, try native oblique + fontWithTraits = CTFontCreateCopyWithSymbolicTraits( m_ctFont, 0, NULL, kCTFontItalicTrait, kCTFontItalicTrait ); + } + } + } + + if ( fontWithTraits == NULL ) + { + fontWithTraits = CTFontCreateWithName( wxCFStringRef(m_info.m_faceName), m_info.m_pointSize, remainingTransform ); + } + } - else - m_macFontFamily = FMGetFontFamilyFromATSFontFamilyRef( atsfamily ); + if ( fontWithTraits != NULL ) + m_ctFont.reset(fontWithTraits); } } - - m_macFontStyle = 0; - if (m_weight == wxFONTWEIGHT_BOLD) - m_macFontStyle |= bold; - if (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT) - m_macFontStyle |= italic; - if (m_underlined) - m_macFontStyle |= underline; - m_macFontSize = m_pointSize ; } - // we try to get as much styles as possible into ATSU - - - // ATSUFontID and FMFont are equivalent - FMFontStyle intrinsicStyle = 0 ; - status = FMGetFontFromFontFamilyInstance( m_macFontFamily , m_macFontStyle , &m_macATSUFontID , &intrinsicStyle); - wxASSERT_MSG( status == noErr , wxT("couldn't get an ATSUFont from font family") ); - m_macATSUAdditionalQDStyles = m_macFontStyle & (~intrinsicStyle ); - - if ( m_macATSUStyle ) - { - ::ATSUDisposeStyle((ATSUStyle)m_macATSUStyle); - m_macATSUStyle = NULL ; - } + m_cgFont.reset(CTFontCopyGraphicsFont(m_ctFont, NULL)); + } - status = ::ATSUCreateStyle((ATSUStyle *)&m_macATSUStyle); - wxASSERT_MSG( status == noErr , wxT("couldn't create ATSU style") ); +#endif +#if wxOSX_USE_ATSU_TEXT + CreateATSUFont(); +#endif +#if wxOSX_USE_COCOA + m_nsFont = wxFont::OSXCreateNSFont( &m_info ); +#endif +#if wxOSX_USE_IPHONE + m_uiFont = wxFont::OSXCreateUIFont( &m_info ); +#endif + m_fontValid = true; +} - ATSUAttributeTag atsuTags[] = - { - kATSUFontTag , - kATSUSizeTag , - kATSUVerticalCharacterTag, - kATSUQDBoldfaceTag , - kATSUQDItalicTag , - kATSUQDUnderlineTag , - kATSUQDCondensedTag , - kATSUQDExtendedTag , - }; - ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] = - { - sizeof( ATSUFontID ) , - sizeof( Fixed ) , - sizeof( ATSUVerticalCharacterType), - sizeof( Boolean ) , - sizeof( Boolean ) , - sizeof( Boolean ) , - sizeof( Boolean ) , - sizeof( Boolean ) , - }; - - Boolean kTrue = true ; - Boolean kFalse = false ; - - Fixed atsuSize = IntToFixed( m_macFontSize ); - ATSUVerticalCharacterType kHorizontal = kATSUStronglyHorizontal; - ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] = - { - &m_macATSUFontID , - &atsuSize , - &kHorizontal, - (m_macATSUAdditionalQDStyles & bold) ? &kTrue : &kFalse , - (m_macATSUAdditionalQDStyles & italic) ? &kTrue : &kFalse , - (m_macATSUAdditionalQDStyles & underline) ? &kTrue : &kFalse , - (m_macATSUAdditionalQDStyles & condense) ? &kTrue : &kFalse , - (m_macATSUAdditionalQDStyles & extend) ? &kTrue : &kFalse , - }; - - status = ::ATSUSetAttributes( - (ATSUStyle)m_macATSUStyle, - sizeof(atsuTags) / sizeof(ATSUAttributeTag) , - atsuTags, atsuSizes, atsuValues); - - wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") ); - return; - } +bool wxFontRefData::IsFixedWidth() const +{ +#if wxOSX_USE_CORE_TEXT + CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(m_ctFont); + return (traits & kCTFontMonoSpaceTrait) != 0; +#else + return false; #endif } @@ -698,10 +558,18 @@ void wxFontRefData::MacFindFont() bool wxFont::Create(const wxNativeFontInfo& info) { - return Create( - info.pointSize, info.family, info.style, info.weight, - info.underlined, info.faceName, info.encoding ); -} + UnRef(); + + m_refData = new wxFontRefData( info ); + RealizeResource(); + + return true; +} + +wxFont::wxFont(wxOSXSystemFont font) +{ + m_refData = new wxFontRefData( font, 0 ); +} wxFont::wxFont(const wxString& fontdesc) { @@ -715,74 +583,63 @@ bool wxFont::Create(int pointSize, wxFontStyle style, wxFontWeight weight, bool underlined, - const wxString& faceName, + const wxString& faceNameParam, wxFontEncoding encoding) { UnRef(); - m_refData = new wxFontRefData( - pointSize, family, style, weight, - underlined, faceName, encoding); + wxString faceName = faceNameParam; - RealizeResource(); + if ( faceName.empty() ) + { + switch ( family ) + { + case wxFONTFAMILY_DEFAULT : + faceName = wxT("Lucida Grande"); + break; + + case wxFONTFAMILY_SCRIPT : + case wxFONTFAMILY_ROMAN : + case wxFONTFAMILY_DECORATIVE : + faceName = wxT("Times"); + break ; + + case wxFONTFAMILY_SWISS : + faceName = wxT("Helvetica"); + break ; + + case wxFONTFAMILY_MODERN : + case wxFONTFAMILY_TELETYPE: + faceName = wxT("Courier"); + break ; + + default: + faceName = wxT("Times"); + break ; + } + } - return true; -} + wxNativeFontInfo info; -#if wxOSX_USE_CORE_TEXT + info.Init(pointSize, family, style, weight, + underlined, faceName, encoding); -bool wxFont::MacCreateFromUIFont(wxUint32 ctFontType ) -{ - UnRef(); - - m_refData = new wxFontRefData(ctFontType); - RealizeResource(); + m_refData = new wxFontRefData(info); return true; } -bool wxFont::MacCreateFromCTFontDescriptor( const void * ctFontDescriptor , int size ) +wxFont::~wxFont() { - UnRef(); - - m_refData = new wxFontRefData((CTFontDescriptorRef)ctFontDescriptor, size);; - RealizeResource(); - - return true; } - -#endif - -#if wxOSX_USE_CARBON -bool wxFont::MacCreateFromThemeFont(wxUint16 themeFontID) +void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo& info) { -#if wxOSX_USE_CORE_TEXT - if ( UMAGetSystemVersion() >= 0x1050) - { - return MacCreateFromUIFont(HIThemeGetUIFontType(themeFontID)); - } -#endif -#if wxOSX_USE_ATSU_TEXT - { - UnRef(); - - m_refData = new wxFontRefData( - 12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, - false, wxEmptyString, wxFONTENCODING_DEFAULT ); + UnRef(); - M_FONTDATA->m_macThemeFontID = themeFontID ; - RealizeResource(); - return true; - } -#endif - return false; + m_refData = new wxFontRefData( info); } -#endif -wxFont::~wxFont() -{ -} bool wxFont::RealizeResource() { @@ -793,26 +650,9 @@ bool wxFont::RealizeResource() void wxFont::SetEncoding(wxFontEncoding encoding) { - Unshare(); + AllocExclusive(); M_FONTDATA->SetEncoding( encoding ); - - RealizeResource(); -} - -void wxFont::Unshare() -{ - // Don't change shared data - if (!m_refData) - { - m_refData = new wxFontRefData(); - } - else - { - wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData); - UnRef(); - m_refData = ref; - } } wxGDIRefData *wxFont::CreateGDIRefData() const @@ -827,70 +667,49 @@ wxGDIRefData *wxFont::CloneGDIRefData(const wxGDIRefData *data) const void wxFont::SetPointSize(int pointSize) { - if ( M_FONTDATA->GetPointSize() == pointSize ) + if ( M_FONTDATA != NULL && M_FONTDATA->GetPointSize() == pointSize ) return; - Unshare(); + AllocExclusive(); M_FONTDATA->SetPointSize( pointSize ); - - RealizeResource(); } void wxFont::SetFamily(wxFontFamily family) { - Unshare(); + AllocExclusive(); M_FONTDATA->SetFamily( family ); - - RealizeResource(); } void wxFont::SetStyle(wxFontStyle style) { - Unshare(); + AllocExclusive(); M_FONTDATA->SetStyle( style ); - - RealizeResource(); } void wxFont::SetWeight(wxFontWeight weight) { - Unshare(); + AllocExclusive(); M_FONTDATA->SetWeight( weight ); - - RealizeResource(); } bool wxFont::SetFaceName(const wxString& faceName) { - Unshare(); + AllocExclusive(); M_FONTDATA->SetFaceName( faceName ); - RealizeResource(); - return wxFontBase::SetFaceName(faceName); } void wxFont::SetUnderlined(bool underlined) { - Unshare(); + AllocExclusive(); M_FONTDATA->SetUnderlined( underlined ); - - RealizeResource(); -} - -void wxFont::SetNoAntiAliasing( bool no ) -{ - Unshare(); - - M_FONTDATA->SetNoAntiAliasing( no ); - - RealizeResource(); } // ---------------------------------------------------------------------------- @@ -921,10 +740,18 @@ wxSize wxFont::GetPixelSize() const #endif } -wxFontFamily wxFont::GetFamily() const +bool wxFont::IsFixedWidth() const { - wxCHECK_MSG( M_FONTDATA != NULL , wxFONTFAMILY_MAX, wxT("invalid font") ); + wxCHECK_MSG( M_FONTDATA != NULL , false, wxT("invalid font") ); + + // cast away constness otherwise lazy font resolution is not possible + const_cast(this)->RealizeResource(); + + return M_FONTDATA->IsFixedWidth(); +} +wxFontFamily wxFont::DoGetFamily() const +{ return M_FONTDATA->GetFamily(); } @@ -963,74 +790,122 @@ wxFontEncoding wxFont::GetEncoding() const return M_FONTDATA->GetEncoding() ; } -bool wxFont::GetNoAntiAliasing() const +#if wxOSX_USE_ATSU_TEXT && wxOSX_USE_CARBON + +short wxFont::MacGetFontNum() const { - wxCHECK_MSG( M_FONTDATA != NULL , false, wxT("invalid font") ); + wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") ); - return M_FONTDATA->GetNoAntiAliasing(); -} + // cast away constness otherwise lazy font resolution is not possible + const_cast(this)->RealizeResource(); -#if wxOSX_USE_ATSU_TEXT + return M_FONTDATA->m_info.m_qdFontFamily; +} -short wxFont::MacGetFontNum() const +wxByte wxFont::MacGetFontStyle() const { wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") ); - return M_FONTDATA->m_macFontFamily; + // cast away constness otherwise lazy font resolution is not possible + const_cast(this)->RealizeResource(); + + return M_FONTDATA->m_info.m_qdFontStyle; } -short wxFont::MacGetFontSize() const +wxUint16 wxFont::MacGetThemeFontID() const { wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") ); - return M_FONTDATA->m_macFontSize; + return M_FONTDATA->m_macThemeFontID; } -wxByte wxFont::MacGetFontStyle() const +#endif + +#if wxOSX_USE_ATSU_TEXT +void * wxFont::MacGetATSUStyle() const { - wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") ); + wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") ); + + // cast away constness otherwise lazy font resolution is not possible + const_cast(this)->RealizeResource(); - return M_FONTDATA->m_macFontStyle; + return M_FONTDATA->m_macATSUStyle; } wxUint32 wxFont::MacGetATSUFontID() const { - wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") ); + wxCHECK_MSG( M_FONTDATA != NULL, 0, wxT("invalid font") ); + + // cast away constness otherwise lazy font resolution is not possible + const_cast(this)->RealizeResource(); - return M_FONTDATA->m_macATSUFontID; + return M_FONTDATA->m_info.m_atsuFontID; } wxUint32 wxFont::MacGetATSUAdditionalQDStyles() const +{ + wxCHECK_MSG( M_FONTDATA != NULL, 0, wxT("invalid font") ); + + // cast away constness otherwise lazy font resolution is not possible + const_cast(this)->RealizeResource(); + + return M_FONTDATA->m_info.m_atsuAdditionalQDStyles; +} +#endif + +#if wxOSX_USE_CORE_TEXT + +CTFontRef wxFont::OSXGetCTFont() const { wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") ); - return M_FONTDATA->m_macATSUAdditionalQDStyles; + // cast away constness otherwise lazy font resolution is not possible + const_cast(this)->RealizeResource(); + + return (CTFontRef)(M_FONTDATA->m_ctFont); } -wxUint16 wxFont::MacGetThemeFontID() const +#endif + +#if wxOSX_USE_COCOA_OR_CARBON + +CGFontRef wxFont::OSXGetCGFont() const { wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") ); - return M_FONTDATA->m_macThemeFontID; + // cast away constness otherwise lazy font resolution is not possible + const_cast(this)->RealizeResource(); + + return (M_FONTDATA->m_cgFont); } + #endif -#if wxOSX_USE_CORE_TEXT || wxOSX_USE_ATSU_TEXT -void * wxFont::MacGetATSUStyle() const + +#if wxOSX_USE_COCOA + +NSFont* wxFont::OSXGetNSFont() const { - wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") ); + wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") ); - return M_FONTDATA->m_macATSUStyle; + // cast away constness otherwise lazy font resolution is not possible + const_cast(this)->RealizeResource(); + + return (M_FONTDATA->m_nsFont); } + #endif -#if wxOSX_USE_CORE_TEXT +#if wxOSX_USE_IPHONE -const void * wxFont::MacGetCTFont() const +UIFont* wxFont::OSXGetUIFont() const { wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") ); - return (CTFontRef)(M_FONTDATA->m_ctFont); + // cast away constness otherwise lazy font resolution is not possible + const_cast(this)->RealizeResource(); + + return (M_FONTDATA->m_uiFont); } #endif @@ -1038,9 +913,403 @@ const void * wxFont::MacGetCTFont() const const wxNativeFontInfo * wxFont::GetNativeFontInfo() const { wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") ); - wxCHECK_MSG( Ok(), NULL, wxT("invalid font") ); + wxCHECK_MSG( IsOk(), NULL, wxT("invalid font") ); + + // cast away constness otherwise lazy font resolution is not possible + const_cast(this)->RealizeResource(); - M_FONTDATA->m_info.InitFromFont(*this); + // M_FONTDATA->m_info.InitFromFont(*this); return &(M_FONTDATA->m_info); } + +// ---------------------------------------------------------------------------- +// wxNativeFontInfo +// ---------------------------------------------------------------------------- + +#if 0 // wxOSX_USE_CORE_TEXT + +/* from Core Text Manual Common Operations */ + +static CTFontDescriptorRef wxMacCreateCTFontDescriptor(CFStringRef iFamilyName, CTFontSymbolicTraits iTraits ) +{ + CTFontDescriptorRef descriptor = NULL; + CFMutableDictionaryRef attributes; + + wxASSERT(iFamilyName != NULL); + // Create a mutable dictionary to hold our attributes. + attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + wxASSERT(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); + wxASSERT(symTraits != NULL); + + if (symTraits != NULL) { + // Create a dictionary to hold our traits values. + traits = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + wxASSERT(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); + wxASSERT(descriptor != NULL); + + CFRelease(attributes); + } + // Return our font descriptor. + return descriptor ; +} + +#endif + +void wxNativeFontInfo::Init() +{ +#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 + 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(); + + wxCFRef< CFNumberRef > sizevalue( (CFNumberRef) CTFontDescriptorCopyAttribute( descr, kCTFontSizeAttribute ) ); + float fsize; + if ( CFNumberGetValue( sizevalue , kCFNumberFloatType , &fsize ) ) + m_pointSize = (int)( fsize + 0.5 ); + + wxCFRef< CFDictionaryRef > traitsvalue( (CFDictionaryRef) CTFontDescriptorCopyAttribute( descr, 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(descr, kCTFontFamilyNameAttribute)); + m_faceName = familyName.AsString(); +} +#endif + +void wxNativeFontInfo::EnsureValid() +{ + if ( m_descriptorValid ) + return; + +#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); + if ( status != noErr ) + { + wxFAIL_MSG( wxT("couldn't get an ATSUFont from font family") ); + } + m_atsuAdditionalQDStyles = m_qdFontStyle & (~intrinsicStyle ); + m_atsuFontValid = true; + } +#endif + m_descriptorValid = true; +} + +void wxNativeFontInfo::Init(const wxNativeFontInfo& info) +{ + Init(); +#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 + 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_ATSU_TEXT + m_atsuFontID = 0 ; + m_atsuAdditionalQDStyles = 0; + m_atsuFontValid = false; +#endif + m_descriptorValid = false; +} + +bool wxNativeFontInfo::FromString(const wxString& s) +{ + long l; + + wxStringTokenizer tokenizer(s, wxT(";")); + + 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(wxT("%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; +} + +bool wxNativeFontInfo::GetStrikethrough() const +{ + return false; +} + + +// 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 +} + +void wxNativeFontInfo::SetStrikethrough(bool WXUNUSED(strikethrough)) +{ +} + +