1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/font.cpp
3 // Purpose: wxFont class
4 // Author: Stefan Csomor
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
17 #include "wx/string.h"
20 #include "wx/gdicmn.h"
24 #include "wx/fontutil.h"
25 #include "wx/graphics.h"
27 #include "wx/mac/uma.h"
30 #include <ATSUnicode.h>
34 IMPLEMENT_DYNAMIC_CLASS(wxFont
, wxGDIObject
)
37 class WXDLLEXPORT wxFontRefData
: public wxGDIRefData
42 Init(10, wxDEFAULT
, wxNORMAL
, wxNORMAL
,
43 false, wxT("applicationfont"), wxFONTENCODING_DEFAULT
);
46 wxFontRefData(const wxFontRefData
& data
)
48 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
49 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
52 wxFontRefData(int size
,
57 const wxString
& faceName
,
58 wxFontEncoding encoding
)
60 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
63 #if wxMAC_USE_CORE_TEXT
64 wxFontRefData( wxUint32 coreTextFontType
);
65 wxFontRefData( CTFontRef font
);
66 wxFontRefData( CTFontDescriptorRef fontdescriptor
, int size
);
69 virtual ~wxFontRefData();
71 void SetNoAntiAliasing( bool no
= true ) { m_noAA
= no
; }
73 bool GetNoAntiAliasing() const { return m_noAA
; }
75 void SetPointSize( int size
)
78 MacInvalidateNativeFont();
81 int GetPointSize() const { return m_pointSize
; }
83 void SetFamily( int family
)
86 MacInvalidateNativeFont();
90 int GetFamily() const { return m_family
; }
92 void SetStyle( int style
)
95 MacInvalidateNativeFont();
99 int GetStyle() const { return m_style
; }
101 void SetWeight( int weight
)
104 MacInvalidateNativeFont();
108 int GetWeight() const { return m_weight
; }
110 void SetUnderlined( bool u
)
113 MacInvalidateNativeFont();
116 bool GetUnderlined() const { return m_underlined
; }
118 void SetFaceName( const wxString
& facename
)
120 m_faceName
= facename
;
121 MacInvalidateNativeFont();
124 const wxString
& GetFaceName() const { return m_faceName
; }
126 void SetEncoding( wxFontEncoding encoding
)
128 m_encoding
= encoding
;
129 MacInvalidateNativeFont();
132 wxFontEncoding
GetEncoding() const { return m_encoding
; }
134 void MacInvalidateNativeFont();
139 // common part of all ctors
145 const wxString
& faceName
,
146 wxFontEncoding encoding
);
148 #if wxMAC_USE_CORE_TEXT
149 void Init( CTFontRef font
);
151 // font characterstics
158 wxFontEncoding m_encoding
;
159 bool m_noAA
; // No anti-aliasing
162 #if wxMAC_USE_ATSU_TEXT
163 FMFontFamily m_macFontFamily
;
164 FMFontSize m_macFontSize
;
165 FMFontStyle m_macFontStyle
;
167 // ATSU Font Information
169 // this is split into an ATSU font id that may
170 // contain some styles (special bold fonts etc) and
171 // these are the additional qd styles that are not
172 // included in the ATSU font id
173 ATSUFontID m_macATSUFontID
;
174 FMFontStyle m_macATSUAdditionalQDStyles
;
176 // for true themeing support we must store the correct font
177 // information here, as this speeds up and optimizes rendering
178 ThemeFontID m_macThemeFontID
;
179 ATSUStyle m_macATSUStyle
;
181 #if wxMAC_USE_CORE_TEXT
182 wxCFRef
<CTFontRef
> m_ctFont
;
183 wxCFRef
<CTFontDescriptorRef
> m_ctFontDescriptor
;
185 wxNativeFontInfo m_info
;
188 #define M_FONTDATA ((wxFontRefData*)m_refData)
191 // ============================================================================
193 // ============================================================================
195 // ----------------------------------------------------------------------------
197 // ----------------------------------------------------------------------------
199 void wxFontRefData::Init(int pointSize
,
204 const wxString
& faceName
,
205 wxFontEncoding encoding
)
208 m_pointSize
= pointSize
;
212 m_underlined
= underlined
;
213 m_faceName
= faceName
;
214 m_encoding
= encoding
;
216 #if wxMAC_USE_ATSU_TEXT
217 m_macFontFamily
= 0 ;
221 m_macATSUAdditionalQDStyles
= 0 ;
222 m_macThemeFontID
= kThemeCurrentPortFont
;
223 m_macATSUStyle
= NULL
;
227 wxFontRefData::~wxFontRefData()
229 #if wxMAC_USE_ATSU_TEXT
230 if ( m_macATSUStyle
)
232 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUStyle
);
233 m_macATSUStyle
= NULL
;
238 void wxFontRefData::MacInvalidateNativeFont()
240 #if wxMAC_USE_CORE_TEXT
242 m_ctFontDescriptor
.reset();
244 #if wxMAC_USE_ATSU_TEXT
245 if ( m_macATSUStyle
)
247 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUStyle
);
248 m_macATSUStyle
= NULL
;
253 #if wxMAC_USE_CORE_TEXT
255 /* from Core Text Manual Common Operations */
257 static CTFontDescriptorRef
wxMacCreateCTFontDescriptor(CFStringRef iFamilyName
, CTFontSymbolicTraits iTraits
)
259 CTFontDescriptorRef descriptor
= NULL
;
260 CFMutableDictionaryRef attributes
;
262 assert(iFamilyName
!= NULL
);
263 // Create a mutable dictionary to hold our attributes.
264 attributes
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
265 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
266 check(attributes
!= NULL
);
268 if (attributes
!= NULL
) {
269 // Add a family name to our attributes.
270 CFDictionaryAddValue(attributes
, kCTFontFamilyNameAttribute
, iFamilyName
);
274 CFMutableDictionaryRef traits
;
275 CFNumberRef symTraits
;
277 // Create the traits dictionary.
278 symTraits
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
,
280 check(symTraits
!= NULL
);
282 if (symTraits
!= NULL
) {
283 // Create a dictionary to hold our traits values.
284 traits
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
285 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
286 check(traits
!= NULL
);
288 if (traits
!= NULL
) {
289 // Add the symbolic traits value to the traits dictionary.
290 CFDictionaryAddValue(traits
, kCTFontSymbolicTrait
, symTraits
);
292 // Add the traits attribute to our attributes.
293 CFDictionaryAddValue(attributes
, kCTFontTraitsAttribute
, traits
);
296 CFRelease(symTraits
);
299 // Create the font descriptor with our attributes and input size.
300 descriptor
= CTFontDescriptorCreateWithAttributes(attributes
);
301 check(descriptor
!= NULL
);
303 CFRelease(attributes
);
305 // Return our font descriptor.
309 wxFontRefData::wxFontRefData( wxUint32 coreTextFontType
)
311 CTFontRef font
= CTFontCreateUIFontForLanguage( coreTextFontType
, 0.0, NULL
) ;
312 if ( CTFontGetSize(m_ctFont
) == 0 )
315 font
= CTFontCreateUIFontForLanguage( coreTextFontType
, 12.0, NULL
);
320 wxFontRefData::wxFontRefData( CTFontRef font
)
325 wxFontRefData::wxFontRefData( CTFontDescriptorRef fontdescriptor
, int size
)
329 wxCFRef
< CFNumberRef
> value( (CFNumberRef
) CTFontDescriptorCopyAttribute( fontdescriptor
, kCTFontSizeAttribute
) );
332 if ( CFNumberGetValue( value
, kCFNumberFloatType
, &fsize
) )
334 size
= (int) fsize
+ 0.5 ;
337 Init( CTFontCreateWithFontDescriptor(fontdescriptor
, size
,NULL
) );
340 void wxFontRefData::Init( CTFontRef font
)
342 Init(10, wxDEFAULT
, wxNORMAL
, wxNORMAL
,
343 false, wxT("applicationfont"), wxFONTENCODING_DEFAULT
);
345 m_ctFont
.reset( font
);
350 void wxFontRefData::MacFindFont()
353 #if wxMAC_USE_CORE_TEXT
354 if ( UMAGetSystemVersion() >= 0x1050 )
356 if ( m_faceName
.empty() && m_family
== wxDEFAULT
)
358 m_ctFont
.reset(CTFontCreateUIFontForLanguage( kCTFontSystemFontType
, 0.0, NULL
));
361 if ( m_ctFont
.get() )
363 wxMacCFStringHolder
name( CTFontCopyFamilyName( m_ctFont
) );
364 m_faceName
= name
.AsString();
365 m_pointSize
= CTFontGetSize(m_ctFont
) ;
366 CTFontSymbolicTraits traits
= CTFontGetSymbolicTraits( m_ctFont
);
367 if ( traits
& kCTFontItalicTrait
)
369 if ( traits
& kCTFontBoldTrait
)
371 if ( !m_ctFontDescriptor
.get() )
372 m_ctFontDescriptor
.reset( CTFontCopyFontDescriptor( m_ctFont
) );
376 if ( m_faceName
.empty() )
383 m_faceName
= wxT("Times");
387 m_faceName
= wxT("Lucida Grande");
392 m_faceName
= wxT("Monaco");
396 m_faceName
= wxT("Times");
401 wxMacCFStringHolder
cf( m_faceName
, wxLocale::GetSystemEncoding() );
402 CTFontSymbolicTraits traits
= 0;
404 if (m_weight
== wxBOLD
)
405 traits
|= kCTFontBoldTrait
;
406 if (m_style
== wxITALIC
|| m_style
== wxSLANT
)
407 traits
|= kCTFontItalicTrait
;
409 m_ctFontDescriptor
.reset( wxMacCreateCTFontDescriptor( cf
, traits
) );
411 m_ctFont
.reset( CTFontCreateWithFontDescriptor( m_ctFontDescriptor
, m_pointSize
, NULL
) );
415 #if wxMAC_USE_ATSU_TEXT
417 OSStatus status
= noErr
;
419 if ( m_macThemeFontID
!= kThemeCurrentPortFont
)
422 GetThemeFont( m_macThemeFontID
, GetApplicationScript(), qdFontName
, &m_macFontSize
, &style
);
423 if ( m_macFontSize
== 0 )
425 m_macFontStyle
= style
;
426 m_faceName
= wxMacMakeStringFromPascal( qdFontName
);
427 if ( m_macFontStyle
& bold
)
430 m_weight
= wxNORMAL
;
431 if ( m_macFontStyle
& italic
)
433 if ( m_macFontStyle
& underline
)
434 m_underlined
= true ;
435 m_pointSize
= m_macFontSize
;
436 m_macFontFamily
= FMGetFontFamilyFromName( qdFontName
);
440 if ( m_faceName
.empty() )
442 if ( m_family
== wxDEFAULT
)
444 m_macFontFamily
= GetAppFont();
445 FMGetFontFamilyName(m_macFontFamily
,qdFontName
);
446 m_faceName
= wxMacMakeStringFromPascal( qdFontName
);
455 m_faceName
= wxT("Times");
459 m_faceName
= wxT("Lucida Grande");
464 m_faceName
= wxT("Monaco");
468 m_faceName
= wxT("Times");
471 wxMacStringToPascal( m_faceName
, qdFontName
);
472 m_macFontFamily
= FMGetFontFamilyFromName( qdFontName
);
473 if ( m_macFontFamily
== kInvalidFontFamily
)
475 wxLogDebug( wxT("ATSFontFamilyFindFromName failed for %s"), m_faceName
.c_str() );
476 m_macFontFamily
= GetAppFont();
482 if ( m_faceName
== wxT("systemfont") )
483 m_macFontFamily
= GetSysFont();
484 else if ( m_faceName
== wxT("applicationfont") )
485 m_macFontFamily
= GetAppFont();
488 wxMacCFStringHolder
cf( m_faceName
, wxLocale::GetSystemEncoding() );
489 ATSFontFamilyRef atsfamily
= ATSFontFamilyFindFromName( cf
, kATSOptionFlagsDefault
);
490 if ( atsfamily
== (ATSFontFamilyRef
) -1 )
492 wxLogDebug( wxT("ATSFontFamilyFindFromName failed for ") + m_faceName
);
493 m_macFontFamily
= GetAppFont();
496 m_macFontFamily
= FMGetFontFamilyFromATSFontFamilyRef( atsfamily
);
501 if (m_weight
== wxBOLD
)
502 m_macFontStyle
|= bold
;
503 if (m_style
== wxITALIC
|| m_style
== wxSLANT
)
504 m_macFontStyle
|= italic
;
506 m_macFontStyle
|= underline
;
507 m_macFontSize
= m_pointSize
;
510 // we try to get as much styles as possible into ATSU
513 // ATSUFontID and FMFont are equivalent
514 FMFontStyle intrinsicStyle
= 0 ;
515 status
= FMGetFontFromFontFamilyInstance( m_macFontFamily
, m_macFontStyle
, &m_macATSUFontID
, &intrinsicStyle
);
516 wxASSERT_MSG( status
== noErr
, wxT("couldn't get an ATSUFont from font family") );
517 m_macATSUAdditionalQDStyles
= m_macFontStyle
& (~intrinsicStyle
);
519 if ( m_macATSUStyle
)
521 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUStyle
);
522 m_macATSUStyle
= NULL
;
525 status
= ::ATSUCreateStyle((ATSUStyle
*)&m_macATSUStyle
);
526 wxASSERT_MSG( status
== noErr
, wxT("couldn't create ATSU style") );
528 ATSUAttributeTag atsuTags
[] =
532 kATSUVerticalCharacterTag
,
535 kATSUQDUnderlineTag
,
536 kATSUQDCondensedTag
,
539 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
541 sizeof( ATSUFontID
) ,
543 sizeof( ATSUVerticalCharacterType
),
551 Boolean kTrue
= true ;
552 Boolean kFalse
= false ;
554 Fixed atsuSize
= IntToFixed( m_macFontSize
);
555 ATSUVerticalCharacterType kHorizontal
= kATSUStronglyHorizontal
;
556 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
561 (m_macATSUAdditionalQDStyles
& bold
) ? &kTrue
: &kFalse
,
562 (m_macATSUAdditionalQDStyles
& italic
) ? &kTrue
: &kFalse
,
563 (m_macATSUAdditionalQDStyles
& underline
) ? &kTrue
: &kFalse
,
564 (m_macATSUAdditionalQDStyles
& condense
) ? &kTrue
: &kFalse
,
565 (m_macATSUAdditionalQDStyles
& extend
) ? &kTrue
: &kFalse
,
568 status
= ::ATSUSetAttributes(
569 (ATSUStyle
)m_macATSUStyle
,
570 sizeof(atsuTags
) / sizeof(ATSUAttributeTag
) ,
571 atsuTags
, atsuSizes
, atsuValues
);
573 wxASSERT_MSG( status
== noErr
, wxT("couldn't modify ATSU style") );
579 // ----------------------------------------------------------------------------
581 // ----------------------------------------------------------------------------
583 bool wxFont::Create(const wxNativeFontInfo
& info
)
586 info
.pointSize
, info
.family
, info
.style
, info
.weight
,
587 info
.underlined
, info
.faceName
, info
.encoding
);
590 wxFont::wxFont(const wxString
& fontdesc
)
592 wxNativeFontInfo info
;
593 if ( info
.FromString(fontdesc
) )
597 bool wxFont::Create(int pointSize
,
602 const wxString
& faceName
,
603 wxFontEncoding encoding
)
607 m_refData
= new wxFontRefData(
608 pointSize
, family
, style
, weight
,
609 underlined
, faceName
, encoding
);
616 #if wxMAC_USE_CORE_TEXT
618 bool wxFont::MacCreateFromUIFont(wxUint32 ctFontType
)
622 m_refData
= new wxFontRefData(ctFontType
);
628 bool wxFont::MacCreateFromCTFontDescriptor( const void * ctFontDescriptor
, int size
)
632 m_refData
= new wxFontRefData((CTFontDescriptorRef
)ctFontDescriptor
, size
);;
641 bool wxFont::MacCreateFromThemeFont(wxUint16 themeFontID
)
643 #if wxMAC_USE_CORE_TEXT
644 if ( UMAGetSystemVersion() >= 0x1050)
646 return MacCreateFromUIFont(HIThemeGetUIFontType(themeFontID
));
649 #if wxMAC_USE_ATSU_TEXT
653 m_refData
= new wxFontRefData(
654 12, wxDEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
,
655 false, wxEmptyString
, wxFONTENCODING_DEFAULT
);
657 M_FONTDATA
->m_macThemeFontID
= themeFontID
;
669 bool wxFont::RealizeResource()
671 M_FONTDATA
->MacFindFont();
676 void wxFont::SetEncoding(wxFontEncoding encoding
)
680 M_FONTDATA
->SetEncoding( encoding
);
685 void wxFont::Unshare()
687 // Don't change shared data
690 m_refData
= new wxFontRefData();
694 wxFontRefData
* ref
= new wxFontRefData(*(wxFontRefData
*)m_refData
);
700 void wxFont::SetPointSize(int pointSize
)
702 if ( M_FONTDATA
->GetPointSize() == pointSize
)
707 M_FONTDATA
->SetPointSize( pointSize
);
712 void wxFont::SetFamily(int family
)
716 M_FONTDATA
->SetFamily( family
);
721 void wxFont::SetStyle(int style
)
725 M_FONTDATA
->SetStyle( style
);
730 void wxFont::SetWeight(int weight
)
734 M_FONTDATA
->SetWeight( weight
);
739 bool wxFont::SetFaceName(const wxString
& faceName
)
743 M_FONTDATA
->SetFaceName( faceName
);
747 return wxFontBase::SetFaceName(faceName
);
750 void wxFont::SetUnderlined(bool underlined
)
754 M_FONTDATA
->SetUnderlined( underlined
);
759 void wxFont::SetNoAntiAliasing( bool no
)
763 M_FONTDATA
->SetNoAntiAliasing( no
);
768 // ----------------------------------------------------------------------------
770 // ----------------------------------------------------------------------------
772 // TODO: insert checks everywhere for M_FONTDATA == NULL!
774 int wxFont::GetPointSize() const
776 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
778 return M_FONTDATA
->GetPointSize();
781 wxSize
wxFont::GetPixelSize() const
783 #if wxUSE_GRAPHICS_CONTEXT
784 // TODO: consider caching the value
785 wxGraphicsContext
* dc
= wxGraphicsContext::CreateFromNative((CGContextRef
) NULL
);
786 dc
->SetFont(*(wxFont
*)this,*wxBLACK
);
787 wxDouble width
, height
= 0;
788 dc
->GetTextExtent( wxT("g"), &width
, &height
, NULL
, NULL
);
790 return wxSize((int)width
, (int)height
);
792 return wxFontBase::GetPixelSize();
796 int wxFont::GetFamily() const
798 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
800 return M_FONTDATA
->GetFamily();
803 int wxFont::GetStyle() const
805 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
807 return M_FONTDATA
->GetStyle() ;
810 int wxFont::GetWeight() const
812 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
814 return M_FONTDATA
->GetWeight();
817 bool wxFont::GetUnderlined() const
819 wxCHECK_MSG( M_FONTDATA
!= NULL
, false, wxT("invalid font") );
821 return M_FONTDATA
->GetUnderlined();
824 wxString
wxFont::GetFaceName() const
826 wxCHECK_MSG( M_FONTDATA
!= NULL
, wxEmptyString
, wxT("invalid font") );
828 return M_FONTDATA
->GetFaceName() ;
831 wxFontEncoding
wxFont::GetEncoding() const
833 wxCHECK_MSG( M_FONTDATA
!= NULL
, wxFONTENCODING_DEFAULT
, wxT("invalid font") );
835 return M_FONTDATA
->GetEncoding() ;
838 bool wxFont::GetNoAntiAliasing() const
840 wxCHECK_MSG( M_FONTDATA
!= NULL
, false, wxT("invalid font") );
842 return M_FONTDATA
->GetNoAntiAliasing();
845 #if wxMAC_USE_ATSU_TEXT
847 short wxFont::MacGetFontNum() const
849 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
851 return M_FONTDATA
->m_macFontFamily
;
854 short wxFont::MacGetFontSize() const
856 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
858 return M_FONTDATA
->m_macFontSize
;
861 wxByte
wxFont::MacGetFontStyle() const
863 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
865 return M_FONTDATA
->m_macFontStyle
;
868 wxUint32
wxFont::MacGetATSUFontID() const
870 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
872 return M_FONTDATA
->m_macATSUFontID
;
875 void * wxFont::MacGetATSUStyle() const
877 wxCHECK_MSG( M_FONTDATA
!= NULL
, NULL
, wxT("invalid font") );
879 return M_FONTDATA
->m_macATSUStyle
;
882 wxUint32
wxFont::MacGetATSUAdditionalQDStyles() const
884 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
886 return M_FONTDATA
->m_macATSUAdditionalQDStyles
;
889 wxUint16
wxFont::MacGetThemeFontID() const
891 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
893 return M_FONTDATA
->m_macThemeFontID
;
897 #if wxMAC_USE_CORE_TEXT
899 const void * wxFont::MacGetCTFont() const
901 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
903 return (CTFontRef
)(M_FONTDATA
->m_ctFont
);
906 const void * wxFont::MacGetCTFontDescriptor() const
908 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
910 return (CTFontDescriptorRef
)(M_FONTDATA
->m_ctFontDescriptor
);
915 const wxNativeFontInfo
* wxFont::GetNativeFontInfo() const
917 wxCHECK_MSG( M_FONTDATA
!= NULL
, NULL
, wxT("invalid font") );
918 wxCHECK_MSG( Ok(), NULL
, wxT("invalid font") );
920 M_FONTDATA
->m_info
.InitFromFont(*this);
922 return &(M_FONTDATA
->m_info
);