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
44 Init(10, wxDEFAULT
, wxNORMAL
, wxNORMAL
,
45 false, wxT("applicationfont"), wxFONTENCODING_DEFAULT
);
48 wxFontRefData(const wxFontRefData
& data
)
50 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
51 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
54 wxFontRefData(int size
,
59 const wxString
& faceName
,
60 wxFontEncoding encoding
)
62 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
65 virtual ~wxFontRefData();
67 void SetNoAntiAliasing( bool no
= true )
70 bool GetNoAntiAliasing() const
76 // common part of all ctors
82 const wxString
& faceName
,
83 wxFontEncoding encoding
);
85 // font characterstics
92 wxFontEncoding m_encoding
;
93 bool m_noAA
; // No anti-aliasing
96 #if wxMAC_USE_ATSU_TEXT
97 FMFontFamily m_macFontFamily
;
98 FMFontSize m_macFontSize
;
99 FMFontStyle m_macFontStyle
;
101 // ATSU Font Information
103 // this is split into an ATSU font id that may
104 // contain some styles (special bold fonts etc) and
105 // these are the additional qd styles that are not
106 // included in the ATSU font id
107 ATSUFontID m_macATSUFontID
;
108 FMFontStyle m_macATSUAdditionalQDStyles
;
110 // for true themeing support we must store the correct font
111 // information here, as this speeds up and optimizes rendering
112 ThemeFontID m_macThemeFontID
;
113 ATSUStyle m_macATSUStyle
;
115 #if wxMAC_USE_CORE_TEXT
116 wxCFRef
<CTFontRef
> m_ctFont
;
117 CTFontUIFontType m_macUIFontType
;
119 wxNativeFontInfo m_info
;
122 #define M_FONTDATA ((wxFontRefData*)m_refData)
125 // ============================================================================
127 // ============================================================================
129 // ----------------------------------------------------------------------------
131 // ----------------------------------------------------------------------------
133 void wxFontRefData::Init(int pointSize
,
138 const wxString
& faceName
,
139 wxFontEncoding encoding
)
142 m_pointSize
= pointSize
;
146 m_underlined
= underlined
;
147 m_faceName
= faceName
;
148 m_encoding
= encoding
;
150 #if wxMAC_USE_CORE_TEXT
151 m_macUIFontType
= kCTFontNoFontType
;
153 #if wxMAC_USE_ATSU_TEXT
154 m_macFontFamily
= 0 ;
158 m_macATSUAdditionalQDStyles
= 0 ;
159 m_macThemeFontID
= kThemeCurrentPortFont
;
160 m_macATSUStyle
= NULL
;
164 wxFontRefData::~wxFontRefData()
166 if ( m_macATSUStyle
)
168 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUStyle
);
169 m_macATSUStyle
= NULL
;
173 #if wxMAC_USE_CORE_TEXT
175 /* code mixed together from 2 different routines from Core Text Manual Common Operations */
177 static CTFontRef
wxMacCreateCTFont(CFStringRef iFamilyName
, CTFontSymbolicTraits iTraits
, CGFloat iSize
)
179 CTFontDescriptorRef descriptor
= NULL
;
180 CFMutableDictionaryRef attributes
;
182 assert(iFamilyName
!= NULL
);
183 // Create a mutable dictionary to hold our attributes.
184 attributes
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
185 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
186 check(attributes
!= NULL
);
188 if (attributes
!= NULL
) {
189 // Add a family name to our attributes.
190 CFDictionaryAddValue(attributes
, kCTFontFamilyNameAttribute
, iFamilyName
);
194 CFMutableDictionaryRef traits
;
195 CFNumberRef symTraits
;
197 // Create the traits dictionary.
198 symTraits
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
,
200 check(symTraits
!= NULL
);
202 if (symTraits
!= NULL
) {
203 // Create a dictionary to hold our traits values.
204 traits
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
205 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
206 check(traits
!= NULL
);
208 if (traits
!= NULL
) {
209 // Add the symbolic traits value to the traits dictionary.
210 CFDictionaryAddValue(traits
, kCTFontSymbolicTrait
, symTraits
);
212 // Add the traits attribute to our attributes.
213 CFDictionaryAddValue(attributes
, kCTFontTraitsAttribute
, traits
);
216 CFRelease(symTraits
);
219 // Create the font descriptor with our attributes and input size.
220 descriptor
= CTFontDescriptorCreateWithAttributes(attributes
);
221 check(descriptor
!= NULL
);
223 CFRelease(attributes
);
225 // Return our font descriptor.
226 CTFontRef font
= CTFontCreateWithFontDescriptor( descriptor
, iSize
, NULL
);
227 CFRelease( descriptor
);
233 void wxFontRefData::MacFindFont()
235 OSStatus status
= noErr
;
237 #if wxMAC_USE_CORE_TEXT
238 if ( UMAGetSystemVersion() >= 0x1050 )
240 if ( m_faceName
.empty() && m_family
== wxDEFAULT
&& m_macUIFontType
== kCTFontNoFontType
)
242 m_macUIFontType
= kCTFontSystemFontType
;
245 if ( m_macUIFontType
!= kCTFontNoFontType
)
247 m_ctFont
.reset(CTFontCreateUIFontForLanguage( m_macUIFontType
, 0.0, NULL
));
249 wxMacCFStringHolder
name( CTFontCopyFamilyName( m_ctFont
) );
250 m_faceName
= name
.AsString();
251 if ( CTFontGetSize(m_ctFont
) == 0 )
253 m_ctFont
.reset(CTFontCreateUIFontForLanguage( m_macUIFontType
, 12, NULL
));
256 m_pointSize
= CTFontGetSize(m_ctFont
) ;
257 // reset this so that future manipulation don't fall back
258 m_macUIFontType
= kCTFontNoFontType
;
262 if ( m_faceName
.empty() )
269 m_faceName
= wxT("Times");
273 m_faceName
= wxT("Lucida Grande");
278 m_faceName
= wxT("Monaco");
282 m_faceName
= wxT("Times");
287 wxMacCFStringHolder
cf( m_faceName
, wxLocale::GetSystemEncoding() );
288 CTFontSymbolicTraits traits
= 0;
290 if (m_weight
== wxBOLD
)
291 traits
|= kCTFontBoldTrait
;
292 if (m_style
== wxITALIC
|| m_style
== wxSLANT
)
293 traits
|= kCTFontItalicTrait
;
295 m_ctFont
.reset( wxMacCreateCTFont( cf
, traits
, m_pointSize
) );
299 #if wxMAC_USE_ATSU_TEXT
302 if ( m_macThemeFontID
!= kThemeCurrentPortFont
)
305 GetThemeFont( m_macThemeFontID
, GetApplicationScript(), qdFontName
, &m_macFontSize
, &style
);
306 if ( m_macFontSize
== 0 )
308 m_macFontStyle
= style
;
309 m_faceName
= wxMacMakeStringFromPascal( qdFontName
);
310 if ( m_macFontStyle
& bold
)
313 m_weight
= wxNORMAL
;
314 if ( m_macFontStyle
& italic
)
316 if ( m_macFontStyle
& underline
)
317 m_underlined
= true ;
318 m_pointSize
= m_macFontSize
;
319 m_macFontFamily
= FMGetFontFamilyFromName( qdFontName
);
323 if ( m_faceName
.empty() )
325 if ( m_family
== wxDEFAULT
)
327 m_macFontFamily
= GetAppFont();
328 FMGetFontFamilyName(m_macFontFamily
,qdFontName
);
329 m_faceName
= wxMacMakeStringFromPascal( qdFontName
);
338 m_faceName
= wxT("Times");
342 m_faceName
= wxT("Lucida Grande");
347 m_faceName
= wxT("Monaco");
351 m_faceName
= wxT("Times");
354 wxMacStringToPascal( m_faceName
, qdFontName
);
355 m_macFontFamily
= FMGetFontFamilyFromName( qdFontName
);
356 if ( m_macFontFamily
== kInvalidFontFamily
)
358 wxLogDebug( wxT("ATSFontFamilyFindFromName failed for %s"), m_faceName
.c_str() );
359 m_macFontFamily
= GetAppFont();
365 if ( m_faceName
== wxT("systemfont") )
366 m_macFontFamily
= GetSysFont();
367 else if ( m_faceName
== wxT("applicationfont") )
368 m_macFontFamily
= GetAppFont();
371 wxMacCFStringHolder
cf( m_faceName
, wxLocale::GetSystemEncoding() );
372 ATSFontFamilyRef atsfamily
= ATSFontFamilyFindFromName( cf
, kATSOptionFlagsDefault
);
373 if ( atsfamily
== (ATSFontFamilyRef
) -1 )
375 wxLogDebug( wxT("ATSFontFamilyFindFromName failed for ") + m_faceName
);
376 m_macFontFamily
= GetAppFont();
379 m_macFontFamily
= FMGetFontFamilyFromATSFontFamilyRef( atsfamily
);
384 if (m_weight
== wxBOLD
)
385 m_macFontStyle
|= bold
;
386 if (m_style
== wxITALIC
|| m_style
== wxSLANT
)
387 m_macFontStyle
|= italic
;
389 m_macFontStyle
|= underline
;
390 m_macFontSize
= m_pointSize
;
393 // we try to get as much styles as possible into ATSU
396 // ATSUFontID and FMFont are equivalent
397 FMFontStyle intrinsicStyle
= 0 ;
398 status
= FMGetFontFromFontFamilyInstance( m_macFontFamily
, m_macFontStyle
, &m_macATSUFontID
, &intrinsicStyle
);
399 wxASSERT_MSG( status
== noErr
, wxT("couldn't get an ATSUFont from font family") );
400 m_macATSUAdditionalQDStyles
= m_macFontStyle
& (~intrinsicStyle
);
402 if ( m_macATSUStyle
)
404 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUStyle
);
405 m_macATSUStyle
= NULL
;
408 status
= ::ATSUCreateStyle((ATSUStyle
*)&m_macATSUStyle
);
409 wxASSERT_MSG( status
== noErr
, wxT("couldn't create ATSU style") );
411 ATSUAttributeTag atsuTags
[] =
415 kATSUVerticalCharacterTag
,
418 kATSUQDUnderlineTag
,
419 kATSUQDCondensedTag
,
422 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
424 sizeof( ATSUFontID
) ,
426 sizeof( ATSUVerticalCharacterType
),
434 Boolean kTrue
= true ;
435 Boolean kFalse
= false ;
437 Fixed atsuSize
= IntToFixed( m_macFontSize
);
438 ATSUVerticalCharacterType kHorizontal
= kATSUStronglyHorizontal
;
439 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
444 (m_macATSUAdditionalQDStyles
& bold
) ? &kTrue
: &kFalse
,
445 (m_macATSUAdditionalQDStyles
& italic
) ? &kTrue
: &kFalse
,
446 (m_macATSUAdditionalQDStyles
& underline
) ? &kTrue
: &kFalse
,
447 (m_macATSUAdditionalQDStyles
& condense
) ? &kTrue
: &kFalse
,
448 (m_macATSUAdditionalQDStyles
& extend
) ? &kTrue
: &kFalse
,
451 status
= ::ATSUSetAttributes(
452 (ATSUStyle
)m_macATSUStyle
,
453 sizeof(atsuTags
) / sizeof(ATSUAttributeTag
) ,
454 atsuTags
, atsuSizes
, atsuValues
);
456 wxASSERT_MSG( status
== noErr
, wxT("couldn't modify ATSU style") );
462 // ----------------------------------------------------------------------------
464 // ----------------------------------------------------------------------------
466 bool wxFont::Create(const wxNativeFontInfo
& info
)
469 info
.pointSize
, info
.family
, info
.style
, info
.weight
,
470 info
.underlined
, info
.faceName
, info
.encoding
);
473 wxFont::wxFont(const wxString
& fontdesc
)
475 wxNativeFontInfo info
;
476 if ( info
.FromString(fontdesc
) )
480 bool wxFont::Create(int pointSize
,
485 const wxString
& faceName
,
486 wxFontEncoding encoding
)
490 m_refData
= new wxFontRefData(
491 pointSize
, family
, style
, weight
,
492 underlined
, faceName
, encoding
);
499 #if wxMAC_USE_CORE_TEXT
501 bool wxFont::MacCreateUIFont(wxUint32 ctFontType
)
505 m_refData
= new wxFontRefData(
506 12, wxDEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
,
507 false, wxEmptyString
, wxFONTENCODING_DEFAULT
);
509 M_FONTDATA
->m_macUIFontType
= ctFontType
;
517 bool wxFont::MacCreateThemeFont(wxUint16 themeFontID
)
519 #if wxMAC_USE_CORE_TEXT
520 if ( UMAGetSystemVersion() >= 0x1050)
522 return MacCreateUIFont(HIThemeGetUIFontType(themeFontID
));
525 #if wxMAC_USE_CORE_TEXT
529 m_refData
= new wxFontRefData(
530 12, wxDEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
,
531 false, wxEmptyString
, wxFONTENCODING_DEFAULT
);
533 M_FONTDATA
->m_macThemeFontID
= themeFontID
;
544 bool wxFont::RealizeResource()
546 M_FONTDATA
->MacFindFont();
551 void wxFont::SetEncoding(wxFontEncoding encoding
)
555 M_FONTDATA
->m_encoding
= encoding
;
560 void wxFont::Unshare()
562 // Don't change shared data
565 m_refData
= new wxFontRefData();
569 wxFontRefData
* ref
= new wxFontRefData(*(wxFontRefData
*)m_refData
);
575 void wxFont::SetPointSize(int pointSize
)
577 if ( M_FONTDATA
->m_pointSize
== pointSize
)
582 M_FONTDATA
->m_pointSize
= pointSize
;
587 void wxFont::SetFamily(int family
)
591 M_FONTDATA
->m_family
= family
;
596 void wxFont::SetStyle(int style
)
600 M_FONTDATA
->m_style
= style
;
605 void wxFont::SetWeight(int weight
)
609 M_FONTDATA
->m_weight
= weight
;
614 bool wxFont::SetFaceName(const wxString
& faceName
)
618 M_FONTDATA
->m_faceName
= faceName
;
622 return wxFontBase::SetFaceName(faceName
);
625 void wxFont::SetUnderlined(bool underlined
)
629 M_FONTDATA
->m_underlined
= underlined
;
634 void wxFont::SetNoAntiAliasing( bool no
)
638 M_FONTDATA
->SetNoAntiAliasing( no
);
643 // ----------------------------------------------------------------------------
645 // ----------------------------------------------------------------------------
647 // TODO: insert checks everywhere for M_FONTDATA == NULL!
649 int wxFont::GetPointSize() const
651 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
653 return M_FONTDATA
->m_pointSize
;
656 wxSize
wxFont::GetPixelSize() const
658 #if wxUSE_GRAPHICS_CONTEXT
659 // TODO: consider caching the value
660 wxGraphicsContext
* dc
= wxGraphicsContext::CreateFromNative((CGContextRef
) NULL
);
661 dc
->SetFont(*(wxFont
*)this,*wxBLACK
);
662 wxDouble width
, height
= 0;
663 dc
->GetTextExtent( wxT("g"), &width
, &height
, NULL
, NULL
);
665 return wxSize((int)width
, (int)height
);
667 return wxFontBase::GetPixelSize();
671 int wxFont::GetFamily() const
673 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
675 return M_FONTDATA
->m_family
;
678 int wxFont::GetStyle() const
680 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
682 return M_FONTDATA
->m_style
;
685 int wxFont::GetWeight() const
687 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
689 return M_FONTDATA
->m_weight
;
692 bool wxFont::GetUnderlined() const
694 wxCHECK_MSG( M_FONTDATA
!= NULL
, false, wxT("invalid font") );
696 return M_FONTDATA
->m_underlined
;
699 wxString
wxFont::GetFaceName() const
701 wxCHECK_MSG( M_FONTDATA
!= NULL
, wxEmptyString
, wxT("invalid font") );
703 return M_FONTDATA
->m_faceName
;
706 wxFontEncoding
wxFont::GetEncoding() const
708 wxCHECK_MSG( M_FONTDATA
!= NULL
, wxFONTENCODING_DEFAULT
, wxT("invalid font") );
710 return M_FONTDATA
->m_encoding
;
713 bool wxFont::GetNoAntiAliasing() const
715 wxCHECK_MSG( M_FONTDATA
!= NULL
, false, wxT("invalid font") );
717 return M_FONTDATA
->m_noAA
;
720 #if wxMAC_USE_ATSU_TEXT
722 short wxFont::MacGetFontNum() const
724 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
726 return M_FONTDATA
->m_macFontFamily
;
729 short wxFont::MacGetFontSize() const
731 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
733 return M_FONTDATA
->m_macFontSize
;
736 wxByte
wxFont::MacGetFontStyle() const
738 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
740 return M_FONTDATA
->m_macFontStyle
;
743 wxUint32
wxFont::MacGetATSUFontID() const
745 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
747 return M_FONTDATA
->m_macATSUFontID
;
750 void * wxFont::MacGetATSUStyle() const
752 wxCHECK_MSG( M_FONTDATA
!= NULL
, NULL
, wxT("invalid font") );
754 return M_FONTDATA
->m_macATSUStyle
;
757 wxUint32
wxFont::MacGetATSUAdditionalQDStyles() const
759 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
761 return M_FONTDATA
->m_macATSUAdditionalQDStyles
;
764 wxUint16
wxFont::MacGetThemeFontID() const
766 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
768 return M_FONTDATA
->m_macThemeFontID
;
772 #if wxMAC_USE_CORE_TEXT
774 const void * wxFont::MacGetCTFont() const
776 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
778 return (CTFontRef
)(M_FONTDATA
->m_ctFont
);
783 const wxNativeFontInfo
* wxFont::GetNativeFontInfo() const
785 wxCHECK_MSG( M_FONTDATA
!= NULL
, NULL
, wxT("invalid font") );
786 wxCHECK_MSG( Ok(), NULL
, wxT("invalid font") );
788 M_FONTDATA
->m_info
.InitFromFont(*this);
790 return &(M_FONTDATA
->m_info
);