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/private.h"
30 #include <ATSUnicode.h>
34 IMPLEMENT_DYNAMIC_CLASS(wxFont
, wxGDIObject
)
37 class WXDLLEXPORT wxFontRefData
: public wxGDIRefData
49 , m_faceName(wxT("applicationfont"))
50 , m_encoding(wxFONTENCODING_DEFAULT
)
60 Init(m_pointSize
, m_family
, m_style
, m_weight
,
61 m_underlined
, m_faceName
, m_encoding
);
64 wxFontRefData(const wxFontRefData
& data
)
66 , m_fontId(data
.m_fontId
)
67 , m_pointSize(data
.m_pointSize
)
68 , m_family(data
.m_family
)
69 , m_style(data
.m_style
)
70 , m_weight(data
.m_weight
)
71 , m_underlined(data
.m_underlined
)
72 , m_faceName(data
.m_faceName
)
73 , m_encoding(data
.m_encoding
)
76 , m_macFontFamily(data
.m_macFontFamily
)
77 , m_macFontSize(data
.m_macFontSize
)
78 , m_macFontStyle(data
.m_macFontStyle
)
79 , m_macATSUFontID(data
.m_macATSUFontID
)
83 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
84 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
87 wxFontRefData(int size
,
92 const wxString
& faceName
,
93 wxFontEncoding encoding
)
99 , m_underlined(underlined
)
100 , m_faceName(faceName
)
101 , m_encoding(encoding
)
111 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
114 virtual ~wxFontRefData();
116 void SetNoAntiAliasing( bool no
= true )
119 bool GetNoAntiAliasing() const
125 // common part of all ctors
131 const wxString
& faceName
,
132 wxFontEncoding encoding
);
134 // font characterstics
142 wxFontEncoding m_encoding
;
143 bool m_noAA
; // No anti-aliasing
147 FMFontFamily m_macFontFamily
;
148 FMFontSize m_macFontSize
;
149 FMFontStyle m_macFontStyle
;
151 // ATSU Font Information
153 // this is split into an ATSU font id that may
154 // contain some styles (special bold fonts etc) and
155 // these are the additional qd styles that are not
156 // included in the ATSU font id
157 ATSUFontID m_macATSUFontID
;
158 FMFontStyle m_macATSUAdditionalQDStyles
;
160 // for true themeing support we must store the correct font
161 // information here, as this speeds up and optimizes rendering
162 ThemeFontID m_macThemeFontID
;
164 CTFontRef m_macFontRef
;
165 CTFontUIFontType m_macUIFontType
;
167 ATSUStyle m_macATSUStyle
;
168 wxNativeFontInfo m_info
;
171 #define M_FONTDATA ((wxFontRefData*)m_refData)
174 // ============================================================================
176 // ============================================================================
178 // ----------------------------------------------------------------------------
180 // ----------------------------------------------------------------------------
182 void wxFontRefData::Init(int pointSize
,
187 const wxString
& faceName
,
188 wxFontEncoding encoding
)
191 m_pointSize
= pointSize
;
195 m_underlined
= underlined
;
196 m_faceName
= faceName
;
197 m_encoding
= encoding
;
199 m_macUIFontType
= kCTFontNoFontType
;
202 m_macFontFamily
= 0 ;
206 m_macATSUAdditionalQDStyles
= 0 ;
208 m_macThemeFontID
= kThemeCurrentPortFont
;
210 m_macATSUStyle
= NULL
;
214 wxFontRefData::~wxFontRefData()
216 if ( m_macATSUStyle
)
218 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUStyle
);
219 m_macATSUStyle
= NULL
;
223 void wxFontRefData::MacFindFont()
225 OSStatus status
= noErr
;
229 if ( m_faceName
.empty() && m_family
== wxDEFAULT
)
231 m_macUIFontType
= kCTFontSystemFontType
;
234 if ( m_macUIFontType
!= kCTFontNoFontType
)
236 m_macFontRef
= CTFontCreateUIFontForLanguage( m_macUIFontType
, 0.0, NULL
);
237 wxMacCFStringHolder
name( CTFontCopyFamilyName( m_macFontRef
) );
238 m_faceName
= name
.AsString();
242 if ( m_faceName
.empty() )
249 m_faceName
= wxT("Times");
253 m_faceName
= wxT("Lucida Grande");
258 m_faceName
= wxT("Monaco");
262 m_faceName
= wxT("Times");
267 wxMacCFStringHolder
cf( m_faceName
, wxLocale::GetSystemEncoding() );
268 m_macFontRef
= CTFontCreateWithName( cf
, m_pointSize
, NULL
);
271 if ( m_macATSUStyle
)
273 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUStyle
);
274 m_macATSUStyle
= NULL
;
277 status
= ::ATSUCreateStyle((ATSUStyle
*)&m_macATSUStyle
);
278 wxASSERT_MSG( status
== noErr
, wxT("couldn't create ATSU style") );
280 ATSUAttributeTag atsuTags
[] =
283 kATSUVerticalCharacterTag
,
286 kATSUQDUnderlineTag
,
287 kATSUQDCondensedTag
,
291 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
294 sizeof( ATSUVerticalCharacterType
),
300 sizeof( ATSUFontID
) ,
303 Boolean kTrue
= true ;
304 Boolean kFalse
= false ;
306 Fixed atsuSize
= IntToFixed( m_pointSize
);
307 short m_macATSUAdditionalQDStyles
= 0;
308 ATSUVerticalCharacterType kHorizontal
= kATSUStronglyHorizontal
;
309 ATSUFontID atsuFontID
= 0;
310 int attributeCount
= sizeof(atsuTags
) / sizeof(ATSUAttributeTag
) ;
312 // attempt to add atsu font
313 status
= ATSUFindFontFromName(m_faceName
.c_str(), strlen(m_faceName
.c_str()), kFontFamilyName
, kFontNoPlatform
, kFontNoScript
, kFontNoLanguage
, &atsuFontID
);
314 if ( status
!= noErr
)
319 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
323 (m_macATSUAdditionalQDStyles
& bold
) ? &kTrue
: &kFalse
,
324 (m_macATSUAdditionalQDStyles
& italic
) ? &kTrue
: &kFalse
,
325 (m_macATSUAdditionalQDStyles
& underline
) ? &kTrue
: &kFalse
,
326 (m_macATSUAdditionalQDStyles
& condense
) ? &kTrue
: &kFalse
,
327 (m_macATSUAdditionalQDStyles
& extend
) ? &kTrue
: &kFalse
,
331 status
= ::ATSUSetAttributes( (ATSUStyle
)m_macATSUStyle
, attributeCount
, atsuTags
, atsuSizes
, atsuValues
);
333 wxASSERT_MSG( status
== noErr
, wxT("couldn't modify ATSU style") );
335 if ( m_macThemeFontID
!= kThemeCurrentPortFont
)
338 GetThemeFont( m_macThemeFontID
, GetApplicationScript(), qdFontName
, &m_macFontSize
, &style
);
339 m_macFontStyle
= style
;
340 m_faceName
= wxMacMakeStringFromPascal( qdFontName
);
341 if ( m_macFontStyle
& bold
)
344 m_weight
= wxNORMAL
;
345 if ( m_macFontStyle
& italic
)
347 if ( m_macFontStyle
& underline
)
348 m_underlined
= true ;
349 m_pointSize
= m_macFontSize
;
350 m_macFontFamily
= FMGetFontFamilyFromName( qdFontName
);
354 if ( m_faceName
.empty() )
356 if ( m_family
== wxDEFAULT
)
358 m_macFontFamily
= GetAppFont();
359 FMGetFontFamilyName(m_macFontFamily
,qdFontName
);
360 m_faceName
= wxMacMakeStringFromPascal( qdFontName
);
369 m_faceName
= wxT("Times");
373 m_faceName
= wxT("Lucida Grande");
378 m_faceName
= wxT("Monaco");
382 m_faceName
= wxT("Times");
385 wxMacStringToPascal( m_faceName
, qdFontName
);
386 m_macFontFamily
= FMGetFontFamilyFromName( qdFontName
);
387 if ( m_macFontFamily
== kInvalidFontFamily
)
389 wxLogDebug( wxT("ATSFontFamilyFindFromName failed for %s"), m_faceName
.c_str() );
390 m_macFontFamily
= GetAppFont();
396 if ( m_faceName
== wxT("systemfont") )
397 m_macFontFamily
= GetSysFont();
398 else if ( m_faceName
== wxT("applicationfont") )
399 m_macFontFamily
= GetAppFont();
402 wxMacCFStringHolder
cf( m_faceName
, wxLocale::GetSystemEncoding() );
403 ATSFontFamilyRef atsfamily
= ATSFontFamilyFindFromName( cf
, kATSOptionFlagsDefault
);
404 if ( atsfamily
== (ATSFontFamilyRef
) -1 )
406 wxLogDebug( wxT("ATSFontFamilyFindFromName failed for ") + m_faceName
);
407 m_macFontFamily
= GetAppFont();
410 m_macFontFamily
= FMGetFontFamilyFromATSFontFamilyRef( atsfamily
);
415 if (m_weight
== wxBOLD
)
416 m_macFontStyle
|= bold
;
417 if (m_style
== wxITALIC
|| m_style
== wxSLANT
)
418 m_macFontStyle
|= italic
;
420 m_macFontStyle
|= underline
;
421 m_macFontSize
= m_pointSize
;
424 // we try to get as much styles as possible into ATSU
427 // ATSUFontID and FMFont are equivalent
428 FMFontStyle intrinsicStyle
= 0 ;
429 status
= FMGetFontFromFontFamilyInstance( m_macFontFamily
, m_macFontStyle
, &m_macATSUFontID
, &intrinsicStyle
);
430 wxASSERT_MSG( status
== noErr
, wxT("couldn't get an ATSUFont from font family") );
431 m_macATSUAdditionalQDStyles
= m_macFontStyle
& (~intrinsicStyle
);
433 if ( m_macATSUStyle
)
435 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUStyle
);
436 m_macATSUStyle
= NULL
;
439 status
= ::ATSUCreateStyle((ATSUStyle
*)&m_macATSUStyle
);
440 wxASSERT_MSG( status
== noErr
, wxT("couldn't create ATSU style") );
442 ATSUAttributeTag atsuTags
[] =
446 kATSUVerticalCharacterTag
,
449 kATSUQDUnderlineTag
,
450 kATSUQDCondensedTag
,
453 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
455 sizeof( ATSUFontID
) ,
457 sizeof( ATSUVerticalCharacterType
),
465 Boolean kTrue
= true ;
466 Boolean kFalse
= false ;
468 Fixed atsuSize
= IntToFixed( m_macFontSize
);
469 ATSUVerticalCharacterType kHorizontal
= kATSUStronglyHorizontal
;
470 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
475 (m_macATSUAdditionalQDStyles
& bold
) ? &kTrue
: &kFalse
,
476 (m_macATSUAdditionalQDStyles
& italic
) ? &kTrue
: &kFalse
,
477 (m_macATSUAdditionalQDStyles
& underline
) ? &kTrue
: &kFalse
,
478 (m_macATSUAdditionalQDStyles
& condense
) ? &kTrue
: &kFalse
,
479 (m_macATSUAdditionalQDStyles
& extend
) ? &kTrue
: &kFalse
,
482 status
= ::ATSUSetAttributes(
483 (ATSUStyle
)m_macATSUStyle
,
484 sizeof(atsuTags
) / sizeof(ATSUAttributeTag
) ,
485 atsuTags
, atsuSizes
, atsuValues
);
487 wxASSERT_MSG( status
== noErr
, wxT("couldn't modify ATSU style") );
491 // ----------------------------------------------------------------------------
493 // ----------------------------------------------------------------------------
495 bool wxFont::Create(const wxNativeFontInfo
& info
)
498 info
.pointSize
, info
.family
, info
.style
, info
.weight
,
499 info
.underlined
, info
.faceName
, info
.encoding
);
502 wxFont::wxFont(const wxString
& fontdesc
)
504 wxNativeFontInfo info
;
505 if ( info
.FromString(fontdesc
) )
509 bool wxFont::Create(int pointSize
,
514 const wxString
& faceName
,
515 wxFontEncoding encoding
)
519 m_refData
= new wxFontRefData(
520 pointSize
, family
, style
, weight
,
521 underlined
, faceName
, encoding
);
530 bool wxFont::MacCreateUIFont(wxUint32 ctFontType
)
534 m_refData
= new wxFontRefData(
535 12, wxDEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
,
536 false, wxEmptyString
, wxFONTENCODING_DEFAULT
);
538 M_FONTDATA
->m_macUIFontType
= ctFontType
;
546 bool wxFont::MacCreateThemeFont(wxUint16 themeFontID
)
549 return MacCreateUIFont(HIThemeGetUIFontType(themeFontID
));
553 m_refData
= new wxFontRefData(
554 12, wxDEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
,
555 false, wxEmptyString
, wxFONTENCODING_DEFAULT
);
557 M_FONTDATA
->m_macThemeFontID
= themeFontID
;
568 bool wxFont::RealizeResource()
570 M_FONTDATA
->MacFindFont();
575 void wxFont::SetEncoding(wxFontEncoding encoding
)
579 M_FONTDATA
->m_encoding
= encoding
;
584 void wxFont::Unshare()
586 // Don't change shared data
589 m_refData
= new wxFontRefData();
593 wxFontRefData
* ref
= new wxFontRefData(*(wxFontRefData
*)m_refData
);
599 void wxFont::SetPointSize(int pointSize
)
603 M_FONTDATA
->m_pointSize
= pointSize
;
608 void wxFont::SetFamily(int family
)
612 M_FONTDATA
->m_family
= family
;
617 void wxFont::SetStyle(int style
)
621 M_FONTDATA
->m_style
= style
;
626 void wxFont::SetWeight(int weight
)
630 M_FONTDATA
->m_weight
= weight
;
635 bool wxFont::SetFaceName(const wxString
& faceName
)
639 M_FONTDATA
->m_faceName
= faceName
;
643 return wxFontBase::SetFaceName(faceName
);
646 void wxFont::SetUnderlined(bool underlined
)
650 M_FONTDATA
->m_underlined
= underlined
;
655 void wxFont::SetNoAntiAliasing( bool no
)
659 M_FONTDATA
->SetNoAntiAliasing( no
);
664 // ----------------------------------------------------------------------------
666 // ----------------------------------------------------------------------------
668 // TODO: insert checks everywhere for M_FONTDATA == NULL!
670 int wxFont::GetPointSize() const
672 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
674 return M_FONTDATA
->m_pointSize
;
677 wxSize
wxFont::GetPixelSize() const
679 #if wxUSE_GRAPHICS_CONTEXT
680 // TODO: consider caching the value
681 wxGraphicsContext
* dc
= wxGraphicsContext::CreateFromNative((CGContextRef
) NULL
);
682 dc
->SetFont(*(wxFont
*)this,*wxBLACK
);
683 wxDouble width
, height
= 0;
684 dc
->GetTextExtent( wxT("g"), &width
, &height
, NULL
, NULL
);
686 return wxSize((int)width
, (int)height
);
688 return wxFontBase::GetPixelSize();
692 int wxFont::GetFamily() const
694 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
696 return M_FONTDATA
->m_family
;
699 int wxFont::GetStyle() const
701 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
703 return M_FONTDATA
->m_style
;
706 int wxFont::GetWeight() const
708 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
710 return M_FONTDATA
->m_weight
;
713 bool wxFont::GetUnderlined() const
715 wxCHECK_MSG( M_FONTDATA
!= NULL
, false, wxT("invalid font") );
717 return M_FONTDATA
->m_underlined
;
720 wxString
wxFont::GetFaceName() const
722 wxCHECK_MSG( M_FONTDATA
!= NULL
, wxEmptyString
, wxT("invalid font") );
724 return M_FONTDATA
->m_faceName
;
727 wxFontEncoding
wxFont::GetEncoding() const
729 wxCHECK_MSG( M_FONTDATA
!= NULL
, wxFONTENCODING_DEFAULT
, wxT("invalid font") );
731 return M_FONTDATA
->m_encoding
;
734 bool wxFont::GetNoAntiAliasing() const
736 wxCHECK_MSG( M_FONTDATA
!= NULL
, false, wxT("invalid font") );
738 return M_FONTDATA
->m_noAA
;
743 short wxFont::MacGetFontNum() const
745 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
747 return M_FONTDATA
->m_macFontFamily
;
750 short wxFont::MacGetFontSize() const
752 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
754 return M_FONTDATA
->m_macFontSize
;
757 wxByte
wxFont::MacGetFontStyle() const
759 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
761 return M_FONTDATA
->m_macFontStyle
;
764 wxUint32
wxFont::MacGetATSUFontID() const
766 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
768 return M_FONTDATA
->m_macATSUFontID
;
771 void * wxFont::MacGetATSUStyle() const
773 wxCHECK_MSG( M_FONTDATA
!= NULL
, NULL
, wxT("invalid font") );
775 return M_FONTDATA
->m_macATSUStyle
;
778 wxUint32
wxFont::MacGetATSUAdditionalQDStyles() const
780 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
782 return M_FONTDATA
->m_macATSUAdditionalQDStyles
;
785 wxUint16
wxFont::MacGetThemeFontID() const
787 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
789 return M_FONTDATA
->m_macThemeFontID
;
792 const void * wxFont::MacGetCTFont() const
794 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
796 return M_FONTDATA
->m_macFontRef
;
800 void * wxFont::MacGetATSUStyle() const
802 wxCHECK_MSG( M_FONTDATA
!= NULL
, NULL
, wxT("invalid font") );
804 return M_FONTDATA
->m_macATSUStyle
;
809 const wxNativeFontInfo
* wxFont::GetNativeFontInfo() const
811 wxCHECK_MSG( M_FONTDATA
!= NULL
, NULL
, wxT("invalid font") );
812 wxCHECK_MSG( Ok(), NULL
, wxT("invalid font") );
814 M_FONTDATA
->m_info
.InitFromFont(*this);
816 return &(M_FONTDATA
->m_info
);