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