]> git.saurik.com Git - wxWidgets.git/blob - src/osx/carbon/font.cpp
reworked font handling for osx
[wxWidgets.git] / src / osx / carbon / font.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/font.cpp
3 // Purpose: wxFont class
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #include "wx/font.h"
15
16 #ifndef WX_PRECOMP
17 #include "wx/string.h"
18 #include "wx/utils.h"
19 #include "wx/intl.h"
20 #include "wx/gdicmn.h"
21 #include "wx/log.h"
22 #endif
23
24 #include "wx/fontutil.h"
25 #include "wx/graphics.h"
26 #include "wx/settings.h"
27 #include "wx/tokenzr.h"
28
29 #include "wx/osx/private.h"
30
31 #if wxOSX_USE_ATSU_TEXT && !wxOSX_USE_CARBON
32 // include themeing support
33 #include <Carbon/Carbon.h>
34 #endif
35
36 #include <map>
37 #include <string>
38
39 IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
40
41 class WXDLLEXPORT wxFontRefData: public wxGDIRefData
42 {
43 public:
44
45 wxFontRefData()
46 {
47 Init();
48 m_info.Init(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL,
49 false, wxEmptyString, wxFONTENCODING_DEFAULT);
50 }
51
52 wxFontRefData(const wxFontRefData& data);
53
54 wxFontRefData( const wxNativeFontInfo& info ) : m_info(info)
55 {
56 Init();
57 }
58
59 wxFontRefData(wxOSXSystemFont font, int size);
60
61 #if wxOSX_USE_CORE_TEXT
62 wxFontRefData( wxUint32 coreTextFontType );
63 wxFontRefData( CTFontRef font );
64 wxFontRefData( CTFontDescriptorRef fontdescriptor, int size );
65 #endif
66
67 virtual ~wxFontRefData();
68
69 void SetNoAntiAliasing( bool no = true ) { m_noAA = no; }
70
71 bool GetNoAntiAliasing() const { return m_noAA; }
72
73 void SetPointSize( int size )
74 {
75 if( GetPointSize() != size )
76 {
77 m_info.SetPointSize(size);
78 Free();
79 }
80 }
81
82 int GetPointSize() const { return m_info.GetPointSize(); }
83
84 void SetFamily( wxFontFamily family )
85 {
86 if ( m_info.m_family != family )
87 {
88 m_info.SetFamily( family );
89 Free();
90 }
91 }
92
93 wxFontFamily GetFamily() const { return m_info.GetFamily(); }
94
95 void SetStyle( wxFontStyle style )
96 {
97 if ( m_info.m_style != style )
98 {
99 m_info.SetStyle( style );
100 Free();
101 }
102 }
103
104
105 wxFontStyle GetStyle() const { return m_info.GetStyle(); }
106
107 void SetWeight( wxFontWeight weight )
108 {
109 if ( m_info.m_weight != weight )
110 {
111 m_info.SetWeight( weight );
112 Free();
113 }
114 }
115
116
117 wxFontWeight GetWeight() const { return m_info.GetWeight(); }
118
119 void SetUnderlined( bool u )
120 {
121 if ( m_info.m_underlined != u )
122 {
123 m_info.SetUnderlined( u );
124 Free();
125 }
126 }
127
128 bool GetUnderlined() const { return m_info.GetUnderlined(); }
129
130 void SetFaceName( const wxString& facename )
131 {
132 if ( m_info.m_faceName != facename )
133 {
134 m_info.SetFaceName( facename );
135 Free();
136 }
137 }
138
139 wxString GetFaceName() const { return m_info.GetFaceName(); }
140
141 void SetEncoding( wxFontEncoding encoding )
142 {
143 if ( m_info.m_encoding != encoding )
144 {
145 m_info.SetEncoding( encoding );
146 Free();
147 }
148 }
149
150 wxFontEncoding GetEncoding() const { return m_info.GetEncoding(); }
151
152 void Free();
153
154 void MacFindFont();
155
156 protected:
157 // common part of all ctors
158 void Init();
159 #if wxOSX_USE_CORE_TEXT
160 // void Init( CTFontRef font );
161 #endif
162 bool m_noAA; // No anti-aliasing
163 public:
164 bool m_fontValid;
165 #if wxOSX_USE_CARBON && wxOSX_USE_ATSU_TEXT
166 // for true themeing support we must store the correct font
167 // information here, as this speeds up and optimizes rendering
168 ThemeFontID m_macThemeFontID ;
169 #endif
170 #if wxOSX_USE_CORE_TEXT
171 wxCFRef<CTFontRef> m_ctFont;
172 #endif
173 #if wxOSX_USE_CORE_TEXT || wxOSX_USE_ATSU_TEXT
174 ATSUStyle m_macATSUStyle ;
175 #endif
176 #if wxOSX_USE_COCOA
177 WX_NSFont m_nsFont;
178 #endif
179 #if wxOSX_USE_IPHONE
180 WX_UIFont m_uiFont;
181 #endif
182 wxNativeFontInfo m_info;
183 };
184
185 #define M_FONTDATA ((wxFontRefData*)m_refData)
186
187 wxFontRefData::wxFontRefData(const wxFontRefData& data)
188 {
189 Init();
190 m_info = data.m_info;
191 m_noAA = data.m_noAA;
192 m_fontValid = data.m_fontValid;
193 #if wxOSX_USE_CARBON && wxOSX_USE_ATSU_TEXT
194 m_macThemeFontID = data.m_macThemeFontID;
195 #endif
196 #if wxOSX_USE_CORE_TEXT
197 m_ctFont = data.m_ctFont;
198 #endif
199 #if wxOSX_USE_CORE_TEXT || wxOSX_USE_ATSU_TEXT
200 if ( data.m_macATSUStyle != NULL )
201 {
202 ATSUCreateStyle(&m_macATSUStyle) ;
203 ATSUCopyAttributes(data.m_macATSUStyle, m_macATSUStyle);
204 }
205 #endif
206 #if wxOSX_USE_COCOA
207 m_nsFont = (NSFont*) wxMacCocoaRetain(data.m_nsFont);
208 #endif
209 #if wxOSX_USE_IPHONE
210 m_uiFont = wxMacCocoaRetain(data.m_uiFont);
211 #endif
212
213 }
214
215 // ============================================================================
216 // implementation
217 // ============================================================================
218
219 // ----------------------------------------------------------------------------
220 // wxFontRefData
221 // ----------------------------------------------------------------------------
222
223 void wxFontRefData::Init()
224 {
225 m_noAA = false;
226 #if wxOSX_USE_CARBON && wxOSX_USE_ATSU_TEXT
227 m_macThemeFontID = kThemeCurrentPortFont ;
228 #endif
229 #if wxOSX_USE_CORE_TEXT || wxOSX_USE_ATSU_TEXT
230 m_macATSUStyle = NULL ;
231 #endif
232 #if wxOSX_USE_COCOA
233 m_nsFont = NULL;
234 #endif
235 #if wxOSX_USE_IPHONE
236 m_uiFont = NULL;
237 #endif
238 m_fontValid = false;
239 }
240
241 wxFontRefData::~wxFontRefData()
242 {
243 Free();
244 }
245
246 void wxFontRefData::Free()
247 {
248 #if wxOSX_USE_CORE_TEXT
249 m_ctFont.reset();
250 #endif
251 #if wxOSX_USE_CORE_TEXT || wxOSX_USE_ATSU_TEXT
252 if ( m_macATSUStyle )
253 {
254 ::ATSUDisposeStyle((ATSUStyle)m_macATSUStyle);
255 m_macATSUStyle = NULL ;
256 }
257 #endif
258 #if wxOSX_USE_COCOA
259 if (m_nsFont != NULL)
260 {
261 wxMacCocoaRelease(m_nsFont);
262 m_nsFont = NULL;
263 }
264 #endif
265 #if wxOSX_USE_IPHONE
266 if (m_uiFont != NULL)
267 {
268 wxMacCocoaRelease(m_uiFont);
269 m_uiFont = NULL;
270 }
271 #endif
272 m_fontValid = false;
273 }
274
275 wxFontRefData::wxFontRefData(wxOSXSystemFont font, int size)
276 {
277 wxASSERT( font != wxOSX_SYSTEM_FONT_NONE );
278 Init();
279
280 #if wxOSX_USE_CORE_TEXT
281 if ( UMAGetSystemVersion() >= 0x1050 )
282 {
283 CTFontUIFontType uifont;
284 switch( font )
285 {
286 case wxOSX_SYSTEM_FONT_NORMAL:
287 uifont = kCTFontSystemFontType;
288 break;
289 case wxOSX_SYSTEM_FONT_BOLD:
290 uifont = kCTFontEmphasizedSystemFontType;
291 break;
292 case wxOSX_SYSTEM_FONT_SMALL:
293 uifont = kCTFontSmallSystemFontType;
294 break;
295 case wxOSX_SYSTEM_FONT_SMALL_BOLD:
296 uifont = kCTFontSmallEmphasizedSystemFontType;
297 break;
298 case wxOSX_SYSTEM_FONT_MINI:
299 uifont = kCTFontMiniSystemFontType;
300 break;
301 case wxOSX_SYSTEM_FONT_MINI_BOLD:
302 uifont = kCTFontMiniEmphasizedSystemFontType;
303 break;
304 case wxOSX_SYSTEM_FONT_LABELS:
305 uifont = kCTFontLabelFontType;
306 break;
307 case wxOSX_SYSTEM_FONT_VIEWS:
308 uifont = kCTFontViewsFontType;
309 break;
310 default:
311 break;
312 }
313 m_ctFont.reset(CTFontCreateUIFontForLanguage( uifont, (CGFloat) size, NULL ));
314 wxCFRef<CTFontDescriptorRef> descr;
315 descr.reset( CTFontCopyFontDescriptor( m_ctFont ) );
316 m_info.Init(descr);
317 }
318 #endif
319 #if wxOSX_USE_ATSU_TEXT
320 {
321 switch( font )
322 {
323 case wxOSX_SYSTEM_FONT_NORMAL:
324 m_macThemeFontID = kThemeSystemFont;
325 break;
326 case wxOSX_SYSTEM_FONT_BOLD:
327 m_macThemeFontID = kThemeEmphasizedSystemFont;
328 break;
329 case wxOSX_SYSTEM_FONT_SMALL:
330 m_macThemeFontID = kThemeSmallSystemFont;
331 break;
332 case wxOSX_SYSTEM_FONT_SMALL_BOLD:
333 m_macThemeFontID = kThemeSmallEmphasizedSystemFont;
334 break;
335 case wxOSX_SYSTEM_FONT_MINI:
336 m_macThemeFontID = kThemeMiniSystemFont;
337 break;
338 case wxOSX_SYSTEM_FONT_MINI_BOLD:
339 // bold not available under themeing
340 m_macThemeFontID = kThemeMiniSystemFont;
341 break;
342 case wxOSX_SYSTEM_FONT_LABELS:
343 m_macThemeFontID = kThemeLabelFont;
344 break;
345 case wxOSX_SYSTEM_FONT_VIEWS:
346 m_macThemeFontID = kThemeViewsFont;
347 break;
348 default:
349 break;
350 }
351 if ( m_info.m_faceName.empty() )
352 {
353 Style style ;
354 FMFontSize fontSize;
355 Str255 qdFontName ;
356
357 GetThemeFont( m_macThemeFontID, GetApplicationScript(), qdFontName, &fontSize, &style );
358 if ( size != 0 )
359 fontSize = size;
360
361 wxFontStyle fontstyle = wxFONTSTYLE_NORMAL;
362 wxFontWeight fontweight = wxFONTWEIGHT_NORMAL;
363 bool underlined = false;
364
365 if ( style & bold )
366 fontweight = wxFONTWEIGHT_BOLD ;
367 else
368 fontweight = wxFONTWEIGHT_NORMAL ;
369 if ( style & italic )
370 fontstyle = wxFONTSTYLE_ITALIC ;
371 if ( style & underline )
372 underlined = true ;
373
374 m_info.Init(size,wxFONTFAMILY_DEFAULT,fontstyle,fontweight,underlined,
375 wxMacMakeStringFromPascal( qdFontName ), wxFONTENCODING_DEFAULT);
376 }
377 }
378 #endif
379 #if wxOSX_USE_COCOA
380 m_nsFont = wxFont::CreateNSFont( font, &m_info );
381 #endif
382 #if wxOSX_USE_IPHONE
383 m_uiFont = wxFont::CreateUIFont( font, &m_info );
384 #endif
385 }
386
387 void wxFontRefData::MacFindFont()
388 {
389 if ( m_fontValid )
390 return;
391
392 m_info.EnsureValid();
393
394 #if wxOSX_USE_CORE_TEXT
395 if ( UMAGetSystemVersion() >= 0x1050 )
396 {
397 CTFontSymbolicTraits traits = 0;
398
399 if (m_info.m_weight == wxFONTWEIGHT_BOLD)
400 traits |= kCTFontBoldTrait;
401 if (m_info.m_style == wxFONTSTYLE_ITALIC || m_info.m_style == wxFONTSTYLE_SLANT)
402 traits |= kCTFontItalicTrait;
403
404 // use font caching
405 wxString lookupnameWithSize = wxString::Format( "%s_%ld_%ld", m_info.m_faceName.c_str(), traits, m_info.m_pointSize );
406
407 static std::map< std::wstring , wxCFRef< CTFontRef > > fontcache ;
408 m_ctFont = fontcache[ std::wstring(lookupnameWithSize.wc_str()) ];
409 if ( !m_ctFont )
410 {
411 m_ctFont.reset( CTFontCreateWithFontDescriptor( m_info.m_ctFontDescriptor, 0/*m_pointSize */, NULL ) );
412 }
413 }
414
415 #endif
416 #if wxOSX_USE_ATSU_TEXT
417 {
418 // we try to get as much styles as possible into ATSU
419
420 OSStatus status = ::ATSUCreateStyle(&m_macATSUStyle);
421 wxASSERT_MSG( status == noErr , wxT("couldn't create ATSU style") );
422
423 ATSUAttributeTag atsuTags[] =
424 {
425 kATSUFontTag ,
426 kATSUSizeTag ,
427 kATSUVerticalCharacterTag,
428 kATSUQDBoldfaceTag ,
429 kATSUQDItalicTag ,
430 kATSUQDUnderlineTag ,
431 kATSUQDCondensedTag ,
432 kATSUQDExtendedTag ,
433 };
434 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
435 {
436 sizeof( ATSUFontID ) ,
437 sizeof( Fixed ) ,
438 sizeof( ATSUVerticalCharacterType),
439 sizeof( Boolean ) ,
440 sizeof( Boolean ) ,
441 sizeof( Boolean ) ,
442 sizeof( Boolean ) ,
443 sizeof( Boolean ) ,
444 };
445
446 Boolean kTrue = true ;
447 Boolean kFalse = false ;
448
449 Fixed atsuSize = IntToFixed( m_info.m_pointSize );
450 ATSUVerticalCharacterType kHorizontal = kATSUStronglyHorizontal;
451 FMFontStyle addQDStyle = m_info.m_atsuAdditionalQDStyles;
452 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
453 {
454 &m_info.m_atsuFontID ,
455 &atsuSize ,
456 &kHorizontal,
457 (addQDStyle & bold) ? &kTrue : &kFalse ,
458 (addQDStyle & italic) ? &kTrue : &kFalse ,
459 (addQDStyle & underline) ? &kTrue : &kFalse ,
460 (addQDStyle & condense) ? &kTrue : &kFalse ,
461 (addQDStyle & extend) ? &kTrue : &kFalse ,
462 };
463
464 status = ::ATSUSetAttributes(
465 (ATSUStyle)m_macATSUStyle,
466 sizeof(atsuTags) / sizeof(ATSUAttributeTag) ,
467 atsuTags, atsuSizes, atsuValues);
468
469 wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") );
470 return;
471 }
472 #endif
473 #if wxOSX_USE_COCOA
474 m_nsFont = wxFont::CreateNSFont( &m_info );
475 #endif
476 #if wxOSX_USE_IPHONE
477 m_uiFont = wxFont::CreateUIFont( &m_info );
478 #endif
479 m_fontValid = true;
480 }
481
482 // ----------------------------------------------------------------------------
483 // wxFont
484 // ----------------------------------------------------------------------------
485
486 bool wxFont::Create(const wxNativeFontInfo& info)
487 {
488 UnRef();
489
490 m_refData = new wxFontRefData( info );
491 RealizeResource();
492
493 return true;
494 }
495
496 wxFont::wxFont(const wxString& fontdesc)
497 {
498 wxNativeFontInfo info;
499 if ( info.FromString(fontdesc) )
500 (void)Create(info);
501 }
502
503 bool wxFont::Create(int pointSize,
504 wxFontFamily family,
505 wxFontStyle style,
506 wxFontWeight weight,
507 bool underlined,
508 const wxString& faceNameParam,
509 wxFontEncoding encoding)
510 {
511 UnRef();
512
513 wxString faceName = faceNameParam;
514
515 if ( faceName.empty() )
516 {
517 switch ( family )
518 {
519 case wxFONTFAMILY_DEFAULT :
520 faceName = wxT("Lucida Grande");
521 break;
522
523 case wxFONTFAMILY_SCRIPT :
524 case wxFONTFAMILY_ROMAN :
525 case wxFONTFAMILY_DECORATIVE :
526 faceName = wxT("Times");
527 break ;
528
529 case wxFONTFAMILY_SWISS :
530 faceName = wxT("Helvetica");
531 break ;
532
533 case wxFONTFAMILY_MODERN :
534 case wxFONTFAMILY_TELETYPE:
535 faceName = wxT("Courier");
536 break ;
537
538 default:
539 faceName = wxT("Times");
540 break ;
541 }
542 }
543
544 wxNativeFontInfo info;
545
546 info.Init(pointSize, family, style, weight,
547 underlined, faceName, encoding);
548
549 m_refData = new wxFontRefData(info);
550
551 return true;
552 }
553
554 bool wxFont::CreateSystemFont(wxOSXSystemFont font)
555 {
556 UnRef();
557
558 m_refData = new wxFontRefData( font, 0 );
559
560 return true;
561 }
562
563 wxFont::~wxFont()
564 {
565 }
566
567 bool wxFont::RealizeResource()
568 {
569 M_FONTDATA->MacFindFont();
570
571 return true;
572 }
573
574 void wxFont::SetEncoding(wxFontEncoding encoding)
575 {
576 AllocExclusive();
577
578 M_FONTDATA->SetEncoding( encoding );
579 }
580
581 wxGDIRefData *wxFont::CreateGDIRefData() const
582 {
583 return new wxFontRefData;
584 }
585
586 wxGDIRefData *wxFont::CloneGDIRefData(const wxGDIRefData *data) const
587 {
588 return new wxFontRefData(*static_cast<const wxFontRefData *>(data));
589 }
590
591 void wxFont::SetPointSize(int pointSize)
592 {
593 if ( M_FONTDATA->GetPointSize() == pointSize )
594 return;
595
596 AllocExclusive();
597
598 M_FONTDATA->SetPointSize( pointSize );
599 }
600
601 void wxFont::SetFamily(wxFontFamily family)
602 {
603 AllocExclusive();
604
605 M_FONTDATA->SetFamily( family );
606 }
607
608 void wxFont::SetStyle(wxFontStyle style)
609 {
610 AllocExclusive();
611
612 M_FONTDATA->SetStyle( style );
613 }
614
615 void wxFont::SetWeight(wxFontWeight weight)
616 {
617 AllocExclusive();
618
619 M_FONTDATA->SetWeight( weight );
620 }
621
622 bool wxFont::SetFaceName(const wxString& faceName)
623 {
624 AllocExclusive();
625
626 M_FONTDATA->SetFaceName( faceName );
627
628 return wxFontBase::SetFaceName(faceName);
629 }
630
631 void wxFont::SetUnderlined(bool underlined)
632 {
633 AllocExclusive();
634
635 M_FONTDATA->SetUnderlined( underlined );
636 }
637
638 void wxFont::SetNoAntiAliasing( bool no )
639 {
640 AllocExclusive();
641
642 M_FONTDATA->SetNoAntiAliasing( no );
643 }
644
645 // ----------------------------------------------------------------------------
646 // accessors
647 // ----------------------------------------------------------------------------
648
649 // TODO: insert checks everywhere for M_FONTDATA == NULL!
650
651 int wxFont::GetPointSize() const
652 {
653 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
654
655 return M_FONTDATA->GetPointSize();
656 }
657
658 wxSize wxFont::GetPixelSize() const
659 {
660 #if wxUSE_GRAPHICS_CONTEXT
661 // TODO: consider caching the value
662 wxGraphicsContext* dc = wxGraphicsContext::CreateFromNative((CGContextRef) NULL);
663 dc->SetFont(*(wxFont *)this,*wxBLACK);
664 wxDouble width, height = 0;
665 dc->GetTextExtent( wxT("g"), &width, &height, NULL, NULL);
666 delete dc;
667 return wxSize((int)width, (int)height);
668 #else
669 return wxFontBase::GetPixelSize();
670 #endif
671 }
672
673 wxFontFamily wxFont::GetFamily() const
674 {
675 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTFAMILY_MAX, wxT("invalid font") );
676
677 return M_FONTDATA->GetFamily();
678 }
679
680 wxFontStyle wxFont::GetStyle() const
681 {
682 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTSTYLE_MAX, wxT("invalid font") );
683
684 return M_FONTDATA->GetStyle() ;
685 }
686
687 wxFontWeight wxFont::GetWeight() const
688 {
689 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTWEIGHT_MAX, wxT("invalid font") );
690
691 return M_FONTDATA->GetWeight();
692 }
693
694 bool wxFont::GetUnderlined() const
695 {
696 wxCHECK_MSG( M_FONTDATA != NULL , false, wxT("invalid font") );
697
698 return M_FONTDATA->GetUnderlined();
699 }
700
701 wxString wxFont::GetFaceName() const
702 {
703 wxCHECK_MSG( M_FONTDATA != NULL , wxEmptyString , wxT("invalid font") );
704
705 return M_FONTDATA->GetFaceName() ;
706 }
707
708 wxFontEncoding wxFont::GetEncoding() const
709 {
710 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTENCODING_DEFAULT , wxT("invalid font") );
711
712 return M_FONTDATA->GetEncoding() ;
713 }
714
715 bool wxFont::GetNoAntiAliasing() const
716 {
717 wxCHECK_MSG( M_FONTDATA != NULL , false, wxT("invalid font") );
718
719 return M_FONTDATA->GetNoAntiAliasing();
720 }
721
722 #if wxOSX_USE_ATSU_TEXT && wxOSX_USE_CARBON
723
724 short wxFont::MacGetFontNum() const
725 {
726 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
727
728 // cast away constness otherwise lazy font resolution is not possible
729 const_cast<wxFont *>(this)->RealizeResource();
730
731 return M_FONTDATA->m_info.m_qdFontFamily;
732 }
733
734 wxByte wxFont::MacGetFontStyle() const
735 {
736 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
737
738 // cast away constness otherwise lazy font resolution is not possible
739 const_cast<wxFont *>(this)->RealizeResource();
740
741 return M_FONTDATA->m_info.m_qdFontStyle;
742 }
743
744 wxUint16 wxFont::MacGetThemeFontID() const
745 {
746 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
747
748 return M_FONTDATA->m_macThemeFontID;
749 }
750
751 #endif
752
753 #if wxOSX_USE_CORE_TEXT || wxOSX_USE_ATSU_TEXT
754 void * wxFont::MacGetATSUStyle() const
755 {
756 wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") );
757
758 // cast away constness otherwise lazy font resolution is not possible
759 const_cast<wxFont *>(this)->RealizeResource();
760
761 return M_FONTDATA->m_macATSUStyle;
762 }
763 #endif
764
765 #if wxOSX_USE_CORE_TEXT
766
767 CTFontRef wxFont::GetCTFont() const
768 {
769 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
770
771 // cast away constness otherwise lazy font resolution is not possible
772 const_cast<wxFont *>(this)->RealizeResource();
773
774 return (CTFontRef)(M_FONTDATA->m_ctFont);
775 }
776
777 #endif
778
779 #if wxOSX_USE_COCOA
780
781 NSFont* wxFont::GetNSFont() const
782 {
783 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
784
785 // cast away constness otherwise lazy font resolution is not possible
786 const_cast<wxFont *>(this)->RealizeResource();
787
788 return (M_FONTDATA->m_nsFont);
789 }
790
791 #endif
792
793 const wxNativeFontInfo * wxFont::GetNativeFontInfo() const
794 {
795 wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") );
796 wxCHECK_MSG( Ok(), NULL, wxT("invalid font") );
797
798 // cast away constness otherwise lazy font resolution is not possible
799 const_cast<wxFont *>(this)->RealizeResource();
800
801 // M_FONTDATA->m_info.InitFromFont(*this);
802
803 return &(M_FONTDATA->m_info);
804 }
805
806 // ----------------------------------------------------------------------------
807 // wxNativeFontInfo
808 // ----------------------------------------------------------------------------
809
810 #if wxOSX_USE_CORE_TEXT
811
812 /* from Core Text Manual Common Operations */
813
814 static CTFontDescriptorRef wxMacCreateCTFontDescriptor(CFStringRef iFamilyName, CTFontSymbolicTraits iTraits )
815 {
816 CTFontDescriptorRef descriptor = NULL;
817 CFMutableDictionaryRef attributes;
818
819 assert(iFamilyName != NULL);
820 // Create a mutable dictionary to hold our attributes.
821 attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
822 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
823 check(attributes != NULL);
824
825 if (attributes != NULL) {
826 // Add a family name to our attributes.
827 CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, iFamilyName);
828
829
830 if ( iTraits ) {
831 CFMutableDictionaryRef traits;
832 CFNumberRef symTraits;
833
834 // Create the traits dictionary.
835 symTraits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
836 &iTraits);
837 check(symTraits != NULL);
838
839 if (symTraits != NULL) {
840 // Create a dictionary to hold our traits values.
841 traits = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
842 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
843 check(traits != NULL);
844
845 if (traits != NULL) {
846 // Add the symbolic traits value to the traits dictionary.
847 CFDictionaryAddValue(traits, kCTFontSymbolicTrait, symTraits);
848
849 // Add the traits attribute to our attributes.
850 CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits);
851 CFRelease(traits);
852 }
853 CFRelease(symTraits);
854 }
855 }
856 // Create the font descriptor with our attributes
857 descriptor = CTFontDescriptorCreateWithAttributes(attributes);
858 check(descriptor != NULL);
859
860 CFRelease(attributes);
861 }
862 // Return our font descriptor.
863 return descriptor ;
864 }
865
866 #endif
867
868 void wxNativeFontInfo::Init()
869 {
870 #if wxOSX_USE_CORE_TEXT
871 m_ctFontDescriptor = NULL;
872 #endif
873 #if wxOSX_USE_ATSU_TEXT
874 m_atsuFontID = 0 ;
875 m_atsuAdditionalQDStyles = 0;
876 m_atsuFontValid = false;
877 #if wxOSX_USE_CARBON
878 m_qdFontStyle = 0;
879 m_qdFontFamily = 0;
880 #endif
881 #endif
882 #if wxOSX_USE_COCOA
883 m_nsFontDescriptor = NULL;
884 #endif
885 #if wxOSX_USE_IPHONE
886 m_uiFontDescriptor = NULL;
887 #endif
888 m_pointSize = 0;
889 m_family = wxFONTFAMILY_DEFAULT;
890 m_style = wxFONTSTYLE_NORMAL;
891 m_weight = wxFONTWEIGHT_NORMAL;
892 m_underlined = false;
893 m_faceName.clear();
894 m_encoding = wxFONTENCODING_DEFAULT;
895 m_descriptorValid = false;
896 }
897
898 #if wxOSX_USE_CORE_TEXT
899 void wxNativeFontInfo::Init(CTFontDescriptorRef descr)
900 {
901 Init();
902 m_ctFontDescriptor = wxCFRetain(descr);
903
904 wxCFRef< CFNumberRef > sizevalue( (CFNumberRef) CTFontDescriptorCopyAttribute( m_ctFontDescriptor, kCTFontSizeAttribute ) );
905 float fsize;
906 if ( CFNumberGetValue( sizevalue , kCFNumberFloatType , &fsize ) )
907 m_pointSize = (int)( fsize + 0.5 );
908
909 wxCFRef< CFDictionaryRef > traitsvalue( (CFDictionaryRef) CTFontDescriptorCopyAttribute( m_ctFontDescriptor, kCTFontTraitsAttribute ) );
910 CTFontSymbolicTraits traits;
911 if ( CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(traitsvalue,kCTFontSymbolicTrait),kCFNumberIntType,&traits) )
912 {
913 if ( traits & kCTFontItalicTrait )
914 m_style = wxFONTSTYLE_ITALIC;
915 if ( traits & kCTFontBoldTrait )
916 m_weight = wxFONTWEIGHT_BOLD ;
917 }
918
919 wxCFStringRef familyName( (CFStringRef) CTFontDescriptorCopyAttribute(m_ctFontDescriptor, kCTFontFamilyNameAttribute));
920 m_faceName = familyName.AsString();
921 }
922 #endif
923
924 void wxNativeFontInfo::EnsureValid()
925 {
926 if ( m_descriptorValid )
927 return;
928
929 #if wxOSX_USE_CORE_TEXT
930 if ( m_ctFontDescriptor == NULL && UMAGetSystemVersion() >= 0x1050 )
931 {
932 CTFontSymbolicTraits traits = 0;
933
934 if (m_weight == wxFONTWEIGHT_BOLD)
935 traits |= kCTFontBoldTrait;
936 if (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT)
937 traits |= kCTFontItalicTrait;
938
939 // use font caching
940 wxString lookupnameWithSize = wxString::Format( "%s_%ld_%ld", m_faceName.c_str(), traits, m_pointSize );
941
942 static std::map< std::wstring , wxCFRef< CTFontDescriptorRef > > fontdescriptorcache ;
943 m_ctFontDescriptor = wxCFRetain((CTFontDescriptorRef)fontdescriptorcache[ std::wstring(lookupnameWithSize.wc_str()) ]);
944 if ( !m_ctFontDescriptor )
945 {
946 // QD selection algorithm is the fastest by orders of magnitude on 10.5
947 if ( m_faceName.IsAscii() )
948 {
949 uint8_t qdstyle = 0;
950 if (m_weight == wxFONTWEIGHT_BOLD)
951 qdstyle |= bold;
952 if (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT)
953 qdstyle |= italic;
954
955 Str255 qdFontName ;
956 wxMacStringToPascal( m_faceName , qdFontName );
957 wxCFRef< CTFontRef > font;
958 font.reset( CTFontCreateWithQuickdrawInstance(qdFontName, 0 , qdstyle, m_pointSize) );
959 m_ctFontDescriptor = CTFontCopyFontDescriptor(font);
960 }
961 else
962 {
963 m_ctFontDescriptor = wxMacCreateCTFontDescriptor( wxCFStringRef(m_faceName),traits );
964 }
965 fontdescriptorcache[ std::wstring(lookupnameWithSize.wc_str()) ].reset(wxCFRetain(m_ctFontDescriptor));
966 }
967 }
968 #endif
969 #if wxOSX_USE_ATSU_TEXT
970 if ( !m_atsuFontValid )
971 {
972 wxCFStringRef cf( m_faceName, wxLocale::GetSystemEncoding() );
973 ATSFontFamilyRef atsfamily = ATSFontFamilyFindFromName( cf , kATSOptionFlagsDefault );
974 if ( atsfamily == (ATSFontFamilyRef) -1 )
975 {
976 wxLogDebug( wxT("ATSFontFamilyFindFromName failed for ") + m_faceName );
977 m_qdFontFamily = GetAppFont();
978 }
979 else
980 {
981 m_qdFontFamily = FMGetFontFamilyFromATSFontFamilyRef( atsfamily );
982 }
983
984 m_qdFontStyle = 0;
985 if (m_weight == wxFONTWEIGHT_BOLD)
986 m_qdFontStyle |= bold;
987 if (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT)
988 m_qdFontStyle |= italic;
989 if (m_underlined)
990 m_qdFontStyle |= underline;
991
992
993 // we try to get as much styles as possible into ATSU
994
995 // ATSUFontID and FMFont are equivalent
996 FMFontStyle intrinsicStyle = 0 ;
997 OSStatus status = FMGetFontFromFontFamilyInstance( m_qdFontFamily , m_qdFontStyle , (FMFont*)&m_atsuFontID , &intrinsicStyle);
998 wxASSERT_MSG( status == noErr , wxT("couldn't get an ATSUFont from font family") );
999 m_atsuAdditionalQDStyles = m_qdFontStyle & (~intrinsicStyle );
1000 m_atsuFontValid = true;
1001 }
1002 #endif
1003 #if wxOSX_USE_COCOA
1004 if ( m_nsFontDescriptor == NULL )
1005 ValidateNSFontDescriptor();
1006 #endif
1007 #if wxOSX_USE_IPHONE
1008 // TODO
1009 #endif
1010 m_descriptorValid = true;
1011 }
1012
1013 void wxNativeFontInfo::Init(const wxNativeFontInfo& info)
1014 {
1015 Init();
1016 #if wxOSX_USE_CORE_TEXT
1017 m_ctFontDescriptor = wxCFRetain(info.m_ctFontDescriptor);
1018 #endif
1019 #if wxOSX_USE_ATSU_TEXT
1020 m_atsuFontValid = info.m_atsuFontValid;
1021 m_atsuFontID = info.m_atsuFontID ;
1022 m_atsuAdditionalQDStyles = info.m_atsuAdditionalQDStyles;
1023 #if wxOSX_USE_CARBON
1024 m_qdFontFamily = info.m_qdFontFamily;
1025 m_qdFontStyle = info.m_qdFontStyle;
1026 #endif
1027 #endif
1028 #if wxOSX_USE_COCOA
1029 m_nsFontDescriptor = (NSFontDescriptor*) wxMacCocoaRetain(info.m_nsFontDescriptor);
1030 #endif
1031 #if wxOSX_USE_IPHONE
1032 m_uiFontDescriptor = wxMacCocoaRetain(info.m_uiFontDescriptor);;
1033 #endif
1034 m_pointSize = info.m_pointSize;
1035 m_family = info.m_family;
1036 m_style = info.m_style;
1037 m_weight = info.m_weight;
1038 m_underlined = info.m_underlined;
1039 m_faceName = info.m_faceName;
1040 m_encoding = info.m_encoding;
1041 m_descriptorValid = info.m_descriptorValid;
1042 }
1043
1044 void wxNativeFontInfo::Init(int size,
1045 wxFontFamily family,
1046 wxFontStyle style,
1047 wxFontWeight weight,
1048 bool underlined,
1049 const wxString& faceName,
1050 wxFontEncoding encoding)
1051 {
1052 Init();
1053 m_pointSize = size;
1054 m_family = family;
1055 m_style = style;
1056 m_weight = weight;
1057 m_underlined = underlined;
1058 m_faceName = faceName;
1059 m_encoding = encoding;
1060
1061 }
1062
1063 void wxNativeFontInfo::Free()
1064 {
1065 #if wxOSX_USE_CORE_TEXT
1066 wxCFRelease(m_ctFontDescriptor);
1067 m_ctFontDescriptor = NULL;
1068 #endif
1069 #if wxOSX_USE_ATSU_TEXT
1070 m_atsuFontID = 0 ;
1071 m_atsuAdditionalQDStyles = 0;
1072 m_atsuFontValid = false;
1073 #endif
1074 #if wxOSX_USE_COCOA
1075 wxMacCocoaRelease(m_nsFontDescriptor);
1076 m_nsFontDescriptor = NULL;
1077 #endif
1078 #if wxOSX_USE_IPHONE
1079 wxMacCocoaRelease(m_uiFontDescriptor);
1080 m_uiFontDescriptor = NULL
1081 #endif
1082 m_descriptorValid = false;
1083 }
1084
1085 bool wxNativeFontInfo::FromString(const wxString& s)
1086 {
1087 long l;
1088
1089 wxStringTokenizer tokenizer(s, _T(";"));
1090
1091 wxString token = tokenizer.GetNextToken();
1092 //
1093 // Ignore the version for now
1094 //
1095
1096 token = tokenizer.GetNextToken();
1097 if ( !token.ToLong(&l) )
1098 return false;
1099 m_pointSize = (int)l;
1100
1101 token = tokenizer.GetNextToken();
1102 if ( !token.ToLong(&l) )
1103 return false;
1104 m_family = (wxFontFamily)l;
1105
1106 token = tokenizer.GetNextToken();
1107 if ( !token.ToLong(&l) )
1108 return false;
1109 m_style = (wxFontStyle)l;
1110
1111 token = tokenizer.GetNextToken();
1112 if ( !token.ToLong(&l) )
1113 return false;
1114 m_weight = (wxFontWeight)l;
1115
1116 token = tokenizer.GetNextToken();
1117 if ( !token.ToLong(&l) )
1118 return false;
1119 m_underlined = l != 0;
1120
1121 m_faceName = tokenizer.GetNextToken();
1122
1123 #ifndef __WXMAC__
1124 if( !faceName )
1125 return false;
1126 #endif
1127
1128 token = tokenizer.GetNextToken();
1129 if ( !token.ToLong(&l) )
1130 return false;
1131 m_encoding = (wxFontEncoding)l;
1132
1133 return true;
1134 }
1135
1136 wxString wxNativeFontInfo::ToString() const
1137 {
1138 wxString s;
1139
1140 s.Printf(_T("%d;%d;%d;%d;%d;%d;%s;%d"),
1141 0, // version
1142 m_pointSize,
1143 m_family,
1144 (int)m_style,
1145 (int)m_weight,
1146 m_underlined,
1147 m_faceName.GetData(),
1148 (int)m_encoding);
1149
1150 return s;
1151 }
1152
1153 int wxNativeFontInfo::GetPointSize() const
1154 {
1155 return m_pointSize;
1156 }
1157
1158 wxFontStyle wxNativeFontInfo::GetStyle() const
1159 {
1160 return m_style;
1161 }
1162
1163 wxFontWeight wxNativeFontInfo::GetWeight() const
1164 {
1165 return m_weight;
1166 }
1167
1168 bool wxNativeFontInfo::GetUnderlined() const
1169 {
1170 return m_underlined;
1171 }
1172
1173 wxString wxNativeFontInfo::GetFaceName() const
1174 {
1175 return m_faceName;
1176 }
1177
1178 wxFontFamily wxNativeFontInfo::GetFamily() const
1179 {
1180 return m_family;
1181 }
1182
1183 wxFontEncoding wxNativeFontInfo::GetEncoding() const
1184 {
1185 return m_encoding;
1186 }
1187
1188 // changing the font descriptor
1189
1190 void wxNativeFontInfo::SetPointSize(int pointsize)
1191 {
1192 if ( m_pointSize != pointsize )
1193 {
1194 m_pointSize = pointsize;
1195 Free();
1196 }
1197 }
1198
1199 void wxNativeFontInfo::SetStyle(wxFontStyle style_)
1200 {
1201 if ( m_style != style_ )
1202 {
1203 m_style = style_;
1204 Free();
1205 }
1206 }
1207
1208 void wxNativeFontInfo::SetWeight(wxFontWeight weight_)
1209 {
1210 if ( m_weight != weight_ )
1211 {
1212 m_weight = weight_;
1213 Free();
1214 }
1215 }
1216
1217 void wxNativeFontInfo::SetUnderlined(bool underlined_)
1218 {
1219 if ( m_underlined != underlined_ )
1220 {
1221 m_underlined = underlined_;
1222 Free();
1223 }
1224 }
1225
1226 bool wxNativeFontInfo::SetFaceName(const wxString& facename_)
1227 {
1228 if ( m_faceName != facename_ )
1229 {
1230 m_faceName = facename_;
1231 Free();
1232 }
1233 return true;
1234 }
1235
1236 void wxNativeFontInfo::SetFamily(wxFontFamily family_)
1237 {
1238 if ( m_family != family_ )
1239 {
1240 m_family = family_;
1241 Free();
1242 }
1243 }
1244
1245 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_)
1246 {
1247 m_encoding = encoding_;
1248 // not reflected in native descriptors
1249 }