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