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 wxMAC_USE_ATSU_TEXT
167 if ( m_macATSUStyle
)
169 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUStyle
);
170 m_macATSUStyle
= NULL
;
175 #if wxMAC_USE_CORE_TEXT
177 /* code mixed together from 2 different routines from Core Text Manual Common Operations */
179 static CTFontRef
wxMacCreateCTFont(CFStringRef iFamilyName
, CTFontSymbolicTraits iTraits
, CGFloat iSize
)
181 CTFontDescriptorRef descriptor
= NULL
;
182 CFMutableDictionaryRef attributes
;
184 assert(iFamilyName
!= NULL
);
185 // Create a mutable dictionary to hold our attributes.
186 attributes
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
187 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
188 check(attributes
!= NULL
);
190 if (attributes
!= NULL
) {
191 // Add a family name to our attributes.
192 CFDictionaryAddValue(attributes
, kCTFontFamilyNameAttribute
, iFamilyName
);
196 CFMutableDictionaryRef traits
;
197 CFNumberRef symTraits
;
199 // Create the traits dictionary.
200 symTraits
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
,
202 check(symTraits
!= NULL
);
204 if (symTraits
!= NULL
) {
205 // Create a dictionary to hold our traits values.
206 traits
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0,
207 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
208 check(traits
!= NULL
);
210 if (traits
!= NULL
) {
211 // Add the symbolic traits value to the traits dictionary.
212 CFDictionaryAddValue(traits
, kCTFontSymbolicTrait
, symTraits
);
214 // Add the traits attribute to our attributes.
215 CFDictionaryAddValue(attributes
, kCTFontTraitsAttribute
, traits
);
218 CFRelease(symTraits
);
221 // Create the font descriptor with our attributes and input size.
222 descriptor
= CTFontDescriptorCreateWithAttributes(attributes
);
223 check(descriptor
!= NULL
);
225 CFRelease(attributes
);
227 // Return our font descriptor.
228 CTFontRef font
= CTFontCreateWithFontDescriptor( descriptor
, iSize
, NULL
);
229 CFRelease( descriptor
);
235 void wxFontRefData::MacFindFont()
238 #if wxMAC_USE_CORE_TEXT
239 if ( UMAGetSystemVersion() >= 0x1050 )
241 if ( m_faceName
.empty() && m_family
== wxDEFAULT
&& m_macUIFontType
== kCTFontNoFontType
)
243 m_macUIFontType
= kCTFontSystemFontType
;
246 if ( m_macUIFontType
!= kCTFontNoFontType
)
248 m_ctFont
.reset(CTFontCreateUIFontForLanguage( m_macUIFontType
, 0.0, NULL
));
250 wxMacCFStringHolder
name( CTFontCopyFamilyName( m_ctFont
) );
251 m_faceName
= name
.AsString();
252 if ( CTFontGetSize(m_ctFont
) == 0 )
254 m_ctFont
.reset(CTFontCreateUIFontForLanguage( m_macUIFontType
, 12, NULL
));
257 m_pointSize
= CTFontGetSize(m_ctFont
) ;
258 // reset this so that future manipulation don't fall back
259 m_macUIFontType
= kCTFontNoFontType
;
263 if ( m_faceName
.empty() )
270 m_faceName
= wxT("Times");
274 m_faceName
= wxT("Lucida Grande");
279 m_faceName
= wxT("Monaco");
283 m_faceName
= wxT("Times");
288 wxMacCFStringHolder
cf( m_faceName
, wxLocale::GetSystemEncoding() );
289 CTFontSymbolicTraits traits
= 0;
291 if (m_weight
== wxBOLD
)
292 traits
|= kCTFontBoldTrait
;
293 if (m_style
== wxITALIC
|| m_style
== wxSLANT
)
294 traits
|= kCTFontItalicTrait
;
296 m_ctFont
.reset( wxMacCreateCTFont( cf
, traits
, m_pointSize
) );
300 #if wxMAC_USE_ATSU_TEXT
302 OSStatus status
= noErr
;
304 if ( m_macThemeFontID
!= kThemeCurrentPortFont
)
307 GetThemeFont( m_macThemeFontID
, GetApplicationScript(), qdFontName
, &m_macFontSize
, &style
);
308 if ( m_macFontSize
== 0 )
310 m_macFontStyle
= style
;
311 m_faceName
= wxMacMakeStringFromPascal( qdFontName
);
312 if ( m_macFontStyle
& bold
)
315 m_weight
= wxNORMAL
;
316 if ( m_macFontStyle
& italic
)
318 if ( m_macFontStyle
& underline
)
319 m_underlined
= true ;
320 m_pointSize
= m_macFontSize
;
321 m_macFontFamily
= FMGetFontFamilyFromName( qdFontName
);
325 if ( m_faceName
.empty() )
327 if ( m_family
== wxDEFAULT
)
329 m_macFontFamily
= GetAppFont();
330 FMGetFontFamilyName(m_macFontFamily
,qdFontName
);
331 m_faceName
= wxMacMakeStringFromPascal( qdFontName
);
340 m_faceName
= wxT("Times");
344 m_faceName
= wxT("Lucida Grande");
349 m_faceName
= wxT("Monaco");
353 m_faceName
= wxT("Times");
356 wxMacStringToPascal( m_faceName
, qdFontName
);
357 m_macFontFamily
= FMGetFontFamilyFromName( qdFontName
);
358 if ( m_macFontFamily
== kInvalidFontFamily
)
360 wxLogDebug( wxT("ATSFontFamilyFindFromName failed for %s"), m_faceName
.c_str() );
361 m_macFontFamily
= GetAppFont();
367 if ( m_faceName
== wxT("systemfont") )
368 m_macFontFamily
= GetSysFont();
369 else if ( m_faceName
== wxT("applicationfont") )
370 m_macFontFamily
= GetAppFont();
373 wxMacCFStringHolder
cf( m_faceName
, wxLocale::GetSystemEncoding() );
374 ATSFontFamilyRef atsfamily
= ATSFontFamilyFindFromName( cf
, kATSOptionFlagsDefault
);
375 if ( atsfamily
== (ATSFontFamilyRef
) -1 )
377 wxLogDebug( wxT("ATSFontFamilyFindFromName failed for ") + m_faceName
);
378 m_macFontFamily
= GetAppFont();
381 m_macFontFamily
= FMGetFontFamilyFromATSFontFamilyRef( atsfamily
);
386 if (m_weight
== wxBOLD
)
387 m_macFontStyle
|= bold
;
388 if (m_style
== wxITALIC
|| m_style
== wxSLANT
)
389 m_macFontStyle
|= italic
;
391 m_macFontStyle
|= underline
;
392 m_macFontSize
= m_pointSize
;
395 // we try to get as much styles as possible into ATSU
398 // ATSUFontID and FMFont are equivalent
399 FMFontStyle intrinsicStyle
= 0 ;
400 status
= FMGetFontFromFontFamilyInstance( m_macFontFamily
, m_macFontStyle
, &m_macATSUFontID
, &intrinsicStyle
);
401 wxASSERT_MSG( status
== noErr
, wxT("couldn't get an ATSUFont from font family") );
402 m_macATSUAdditionalQDStyles
= m_macFontStyle
& (~intrinsicStyle
);
404 if ( m_macATSUStyle
)
406 ::ATSUDisposeStyle((ATSUStyle
)m_macATSUStyle
);
407 m_macATSUStyle
= NULL
;
410 status
= ::ATSUCreateStyle((ATSUStyle
*)&m_macATSUStyle
);
411 wxASSERT_MSG( status
== noErr
, wxT("couldn't create ATSU style") );
413 ATSUAttributeTag atsuTags
[] =
417 kATSUVerticalCharacterTag
,
420 kATSUQDUnderlineTag
,
421 kATSUQDCondensedTag
,
424 ByteCount atsuSizes
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
426 sizeof( ATSUFontID
) ,
428 sizeof( ATSUVerticalCharacterType
),
436 Boolean kTrue
= true ;
437 Boolean kFalse
= false ;
439 Fixed atsuSize
= IntToFixed( m_macFontSize
);
440 ATSUVerticalCharacterType kHorizontal
= kATSUStronglyHorizontal
;
441 ATSUAttributeValuePtr atsuValues
[sizeof(atsuTags
) / sizeof(ATSUAttributeTag
)] =
446 (m_macATSUAdditionalQDStyles
& bold
) ? &kTrue
: &kFalse
,
447 (m_macATSUAdditionalQDStyles
& italic
) ? &kTrue
: &kFalse
,
448 (m_macATSUAdditionalQDStyles
& underline
) ? &kTrue
: &kFalse
,
449 (m_macATSUAdditionalQDStyles
& condense
) ? &kTrue
: &kFalse
,
450 (m_macATSUAdditionalQDStyles
& extend
) ? &kTrue
: &kFalse
,
453 status
= ::ATSUSetAttributes(
454 (ATSUStyle
)m_macATSUStyle
,
455 sizeof(atsuTags
) / sizeof(ATSUAttributeTag
) ,
456 atsuTags
, atsuSizes
, atsuValues
);
458 wxASSERT_MSG( status
== noErr
, wxT("couldn't modify ATSU style") );
464 // ----------------------------------------------------------------------------
466 // ----------------------------------------------------------------------------
468 bool wxFont::Create(const wxNativeFontInfo
& info
)
471 info
.pointSize
, info
.family
, info
.style
, info
.weight
,
472 info
.underlined
, info
.faceName
, info
.encoding
);
475 wxFont::wxFont(const wxString
& fontdesc
)
477 wxNativeFontInfo info
;
478 if ( info
.FromString(fontdesc
) )
482 bool wxFont::Create(int pointSize
,
487 const wxString
& faceName
,
488 wxFontEncoding encoding
)
492 m_refData
= new wxFontRefData(
493 pointSize
, family
, style
, weight
,
494 underlined
, faceName
, encoding
);
501 #if wxMAC_USE_CORE_TEXT
503 bool wxFont::MacCreateUIFont(wxUint32 ctFontType
)
507 m_refData
= new wxFontRefData(
508 12, wxDEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
,
509 false, wxEmptyString
, wxFONTENCODING_DEFAULT
);
511 M_FONTDATA
->m_macUIFontType
= ctFontType
;
519 bool wxFont::MacCreateThemeFont(wxUint16 themeFontID
)
521 #if wxMAC_USE_CORE_TEXT
522 if ( UMAGetSystemVersion() >= 0x1050)
524 return MacCreateUIFont(HIThemeGetUIFontType(themeFontID
));
527 #if wxMAC_USE_ATSU_TEXT
531 m_refData
= new wxFontRefData(
532 12, wxDEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
,
533 false, wxEmptyString
, wxFONTENCODING_DEFAULT
);
535 M_FONTDATA
->m_macThemeFontID
= themeFontID
;
547 bool wxFont::RealizeResource()
549 M_FONTDATA
->MacFindFont();
554 void wxFont::SetEncoding(wxFontEncoding encoding
)
558 M_FONTDATA
->m_encoding
= encoding
;
563 void wxFont::Unshare()
565 // Don't change shared data
568 m_refData
= new wxFontRefData();
572 wxFontRefData
* ref
= new wxFontRefData(*(wxFontRefData
*)m_refData
);
578 void wxFont::SetPointSize(int pointSize
)
580 if ( M_FONTDATA
->m_pointSize
== pointSize
)
585 M_FONTDATA
->m_pointSize
= pointSize
;
590 void wxFont::SetFamily(int family
)
594 M_FONTDATA
->m_family
= family
;
599 void wxFont::SetStyle(int style
)
603 M_FONTDATA
->m_style
= style
;
608 void wxFont::SetWeight(int weight
)
612 M_FONTDATA
->m_weight
= weight
;
617 bool wxFont::SetFaceName(const wxString
& faceName
)
621 M_FONTDATA
->m_faceName
= faceName
;
625 return wxFontBase::SetFaceName(faceName
);
628 void wxFont::SetUnderlined(bool underlined
)
632 M_FONTDATA
->m_underlined
= underlined
;
637 void wxFont::SetNoAntiAliasing( bool no
)
641 M_FONTDATA
->SetNoAntiAliasing( no
);
646 // ----------------------------------------------------------------------------
648 // ----------------------------------------------------------------------------
650 // TODO: insert checks everywhere for M_FONTDATA == NULL!
652 int wxFont::GetPointSize() const
654 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
656 return M_FONTDATA
->m_pointSize
;
659 wxSize
wxFont::GetPixelSize() const
661 #if wxUSE_GRAPHICS_CONTEXT
662 // TODO: consider caching the value
663 wxGraphicsContext
* dc
= wxGraphicsContext::CreateFromNative((CGContextRef
) NULL
);
664 dc
->SetFont(*(wxFont
*)this,*wxBLACK
);
665 wxDouble width
, height
= 0;
666 dc
->GetTextExtent( wxT("g"), &width
, &height
, NULL
, NULL
);
668 return wxSize((int)width
, (int)height
);
670 return wxFontBase::GetPixelSize();
674 int wxFont::GetFamily() const
676 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
678 return M_FONTDATA
->m_family
;
681 int wxFont::GetStyle() const
683 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
685 return M_FONTDATA
->m_style
;
688 int wxFont::GetWeight() const
690 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
692 return M_FONTDATA
->m_weight
;
695 bool wxFont::GetUnderlined() const
697 wxCHECK_MSG( M_FONTDATA
!= NULL
, false, wxT("invalid font") );
699 return M_FONTDATA
->m_underlined
;
702 wxString
wxFont::GetFaceName() const
704 wxCHECK_MSG( M_FONTDATA
!= NULL
, wxEmptyString
, wxT("invalid font") );
706 return M_FONTDATA
->m_faceName
;
709 wxFontEncoding
wxFont::GetEncoding() const
711 wxCHECK_MSG( M_FONTDATA
!= NULL
, wxFONTENCODING_DEFAULT
, wxT("invalid font") );
713 return M_FONTDATA
->m_encoding
;
716 bool wxFont::GetNoAntiAliasing() const
718 wxCHECK_MSG( M_FONTDATA
!= NULL
, false, wxT("invalid font") );
720 return M_FONTDATA
->m_noAA
;
723 #if wxMAC_USE_ATSU_TEXT
725 short wxFont::MacGetFontNum() const
727 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
729 return M_FONTDATA
->m_macFontFamily
;
732 short wxFont::MacGetFontSize() const
734 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
736 return M_FONTDATA
->m_macFontSize
;
739 wxByte
wxFont::MacGetFontStyle() const
741 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
743 return M_FONTDATA
->m_macFontStyle
;
746 wxUint32
wxFont::MacGetATSUFontID() const
748 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
750 return M_FONTDATA
->m_macATSUFontID
;
753 void * wxFont::MacGetATSUStyle() const
755 wxCHECK_MSG( M_FONTDATA
!= NULL
, NULL
, wxT("invalid font") );
757 return M_FONTDATA
->m_macATSUStyle
;
760 wxUint32
wxFont::MacGetATSUAdditionalQDStyles() const
762 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
764 return M_FONTDATA
->m_macATSUAdditionalQDStyles
;
767 wxUint16
wxFont::MacGetThemeFontID() const
769 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
771 return M_FONTDATA
->m_macThemeFontID
;
775 #if wxMAC_USE_CORE_TEXT
777 const void * wxFont::MacGetCTFont() const
779 wxCHECK_MSG( M_FONTDATA
!= NULL
, 0, wxT("invalid font") );
781 return (CTFontRef
)(M_FONTDATA
->m_ctFont
);
786 const wxNativeFontInfo
* wxFont::GetNativeFontInfo() const
788 wxCHECK_MSG( M_FONTDATA
!= NULL
, NULL
, wxT("invalid font") );
789 wxCHECK_MSG( Ok(), NULL
, wxT("invalid font") );
791 M_FONTDATA
->m_info
.InitFromFont(*this);
793 return &(M_FONTDATA
->m_info
);