]> git.saurik.com Git - wxWidgets.git/blob - src/osx/carbon/font.cpp
Create an autorelease pool to catch objects created during several special situations...
[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(const wxString& fontdesc)
503 {
504 wxNativeFontInfo info;
505 if ( info.FromString(fontdesc) )
506 (void)Create(info);
507 }
508
509 bool wxFont::Create(int pointSize,
510 wxFontFamily family,
511 wxFontStyle style,
512 wxFontWeight weight,
513 bool underlined,
514 const wxString& faceNameParam,
515 wxFontEncoding encoding)
516 {
517 UnRef();
518
519 wxString faceName = faceNameParam;
520
521 if ( faceName.empty() )
522 {
523 switch ( family )
524 {
525 case wxFONTFAMILY_DEFAULT :
526 faceName = wxT("Lucida Grande");
527 break;
528
529 case wxFONTFAMILY_SCRIPT :
530 case wxFONTFAMILY_ROMAN :
531 case wxFONTFAMILY_DECORATIVE :
532 faceName = wxT("Times");
533 break ;
534
535 case wxFONTFAMILY_SWISS :
536 faceName = wxT("Helvetica");
537 break ;
538
539 case wxFONTFAMILY_MODERN :
540 case wxFONTFAMILY_TELETYPE:
541 faceName = wxT("Courier");
542 break ;
543
544 default:
545 faceName = wxT("Times");
546 break ;
547 }
548 }
549
550 wxNativeFontInfo info;
551
552 info.Init(pointSize, family, style, weight,
553 underlined, faceName, encoding);
554
555 m_refData = new wxFontRefData(info);
556
557 return true;
558 }
559
560 bool wxFont::CreateSystemFont(wxOSXSystemFont font)
561 {
562 UnRef();
563
564 m_refData = new wxFontRefData( font, 0 );
565
566 return true;
567 }
568
569 wxFont::~wxFont()
570 {
571 }
572
573 void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo& info)
574 {
575 UnRef();
576
577 m_refData = new wxFontRefData( info);
578 }
579
580
581 bool wxFont::RealizeResource()
582 {
583 M_FONTDATA->MacFindFont();
584
585 return true;
586 }
587
588 void wxFont::SetEncoding(wxFontEncoding encoding)
589 {
590 AllocExclusive();
591
592 M_FONTDATA->SetEncoding( encoding );
593 }
594
595 wxGDIRefData *wxFont::CreateGDIRefData() const
596 {
597 return new wxFontRefData;
598 }
599
600 wxGDIRefData *wxFont::CloneGDIRefData(const wxGDIRefData *data) const
601 {
602 return new wxFontRefData(*static_cast<const wxFontRefData *>(data));
603 }
604
605 void wxFont::SetPointSize(int pointSize)
606 {
607 if ( M_FONTDATA->GetPointSize() == pointSize )
608 return;
609
610 AllocExclusive();
611
612 M_FONTDATA->SetPointSize( pointSize );
613 }
614
615 void wxFont::SetFamily(wxFontFamily family)
616 {
617 AllocExclusive();
618
619 M_FONTDATA->SetFamily( family );
620 }
621
622 void wxFont::SetStyle(wxFontStyle style)
623 {
624 AllocExclusive();
625
626 M_FONTDATA->SetStyle( style );
627 }
628
629 void wxFont::SetWeight(wxFontWeight weight)
630 {
631 AllocExclusive();
632
633 M_FONTDATA->SetWeight( weight );
634 }
635
636 bool wxFont::SetFaceName(const wxString& faceName)
637 {
638 AllocExclusive();
639
640 M_FONTDATA->SetFaceName( faceName );
641
642 return wxFontBase::SetFaceName(faceName);
643 }
644
645 void wxFont::SetUnderlined(bool underlined)
646 {
647 AllocExclusive();
648
649 M_FONTDATA->SetUnderlined( underlined );
650 }
651
652 // ----------------------------------------------------------------------------
653 // accessors
654 // ----------------------------------------------------------------------------
655
656 // TODO: insert checks everywhere for M_FONTDATA == NULL!
657
658 int wxFont::GetPointSize() const
659 {
660 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
661
662 return M_FONTDATA->GetPointSize();
663 }
664
665 wxSize wxFont::GetPixelSize() const
666 {
667 #if wxUSE_GRAPHICS_CONTEXT
668 // TODO: consider caching the value
669 wxGraphicsContext* dc = wxGraphicsContext::CreateFromNative((CGContextRef) NULL);
670 dc->SetFont(*(wxFont *)this,*wxBLACK);
671 wxDouble width, height = 0;
672 dc->GetTextExtent( wxT("g"), &width, &height, NULL, NULL);
673 delete dc;
674 return wxSize((int)width, (int)height);
675 #else
676 return wxFontBase::GetPixelSize();
677 #endif
678 }
679
680 wxFontFamily wxFont::GetFamily() const
681 {
682 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTFAMILY_MAX, wxT("invalid font") );
683
684 return M_FONTDATA->GetFamily();
685 }
686
687 wxFontStyle wxFont::GetStyle() const
688 {
689 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTSTYLE_MAX, wxT("invalid font") );
690
691 return M_FONTDATA->GetStyle() ;
692 }
693
694 wxFontWeight wxFont::GetWeight() const
695 {
696 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTWEIGHT_MAX, wxT("invalid font") );
697
698 return M_FONTDATA->GetWeight();
699 }
700
701 bool wxFont::GetUnderlined() const
702 {
703 wxCHECK_MSG( M_FONTDATA != NULL , false, wxT("invalid font") );
704
705 return M_FONTDATA->GetUnderlined();
706 }
707
708 wxString wxFont::GetFaceName() const
709 {
710 wxCHECK_MSG( M_FONTDATA != NULL , wxEmptyString , wxT("invalid font") );
711
712 return M_FONTDATA->GetFaceName() ;
713 }
714
715 wxFontEncoding wxFont::GetEncoding() const
716 {
717 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTENCODING_DEFAULT , wxT("invalid font") );
718
719 return M_FONTDATA->GetEncoding() ;
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_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
764 #if WXWIN_COMPATIBILITY_2_8
765 wxUint32 wxFont::MacGetATSUFontID() const
766 {
767 wxCHECK_MSG( M_FONTDATA != NULL, 0, wxT("invalid font") );
768
769 // cast away constness otherwise lazy font resolution is not possible
770 const_cast<wxFont *>(this)->RealizeResource();
771
772 return M_FONTDATA->m_info.m_atsuFontID;
773 }
774
775 wxUint32 wxFont::MacGetATSUAdditionalQDStyles() const
776 {
777 wxCHECK_MSG( M_FONTDATA != NULL, 0, wxT("invalid font") );
778
779 // cast away constness otherwise lazy font resolution is not possible
780 const_cast<wxFont *>(this)->RealizeResource();
781
782 return M_FONTDATA->m_info.m_atsuAdditionalQDStyles;
783 }
784 #endif
785
786 #endif
787
788 #if wxOSX_USE_CORE_TEXT
789
790 CTFontRef wxFont::OSXGetCTFont() const
791 {
792 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
793
794 // cast away constness otherwise lazy font resolution is not possible
795 const_cast<wxFont *>(this)->RealizeResource();
796
797 return (CTFontRef)(M_FONTDATA->m_ctFont);
798 }
799
800 #endif
801
802 #if wxOSX_USE_COCOA_OR_CARBON
803
804 CGFontRef wxFont::OSXGetCGFont() const
805 {
806 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
807
808 // cast away constness otherwise lazy font resolution is not possible
809 const_cast<wxFont *>(this)->RealizeResource();
810
811 return (M_FONTDATA->m_cgFont);
812 }
813
814 #endif
815
816
817 #if wxOSX_USE_COCOA
818
819 NSFont* wxFont::OSXGetNSFont() const
820 {
821 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
822
823 // cast away constness otherwise lazy font resolution is not possible
824 const_cast<wxFont *>(this)->RealizeResource();
825
826 return (M_FONTDATA->m_nsFont);
827 }
828
829 #endif
830
831 const wxNativeFontInfo * wxFont::GetNativeFontInfo() const
832 {
833 wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") );
834 wxCHECK_MSG( Ok(), NULL, wxT("invalid font") );
835
836 // cast away constness otherwise lazy font resolution is not possible
837 const_cast<wxFont *>(this)->RealizeResource();
838
839 // M_FONTDATA->m_info.InitFromFont(*this);
840
841 return &(M_FONTDATA->m_info);
842 }
843
844 // ----------------------------------------------------------------------------
845 // wxNativeFontInfo
846 // ----------------------------------------------------------------------------
847
848 #if wxOSX_USE_CORE_TEXT
849
850 /* from Core Text Manual Common Operations */
851
852 static CTFontDescriptorRef wxMacCreateCTFontDescriptor(CFStringRef iFamilyName, CTFontSymbolicTraits iTraits )
853 {
854 CTFontDescriptorRef descriptor = NULL;
855 CFMutableDictionaryRef attributes;
856
857 wxASSERT(iFamilyName != NULL);
858 // Create a mutable dictionary to hold our attributes.
859 attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
860 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
861 wxASSERT(attributes != NULL);
862
863 if (attributes != NULL) {
864 // Add a family name to our attributes.
865 CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, iFamilyName);
866
867
868 if ( iTraits ) {
869 CFMutableDictionaryRef traits;
870 CFNumberRef symTraits;
871
872 // Create the traits dictionary.
873 symTraits = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
874 &iTraits);
875 wxASSERT(symTraits != NULL);
876
877 if (symTraits != NULL) {
878 // Create a dictionary to hold our traits values.
879 traits = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
880 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
881 wxASSERT(traits != NULL);
882
883 if (traits != NULL) {
884 // Add the symbolic traits value to the traits dictionary.
885 CFDictionaryAddValue(traits, kCTFontSymbolicTrait, symTraits);
886
887 // Add the traits attribute to our attributes.
888 CFDictionaryAddValue(attributes, kCTFontTraitsAttribute, traits);
889 CFRelease(traits);
890 }
891 CFRelease(symTraits);
892 }
893 }
894 // Create the font descriptor with our attributes
895 descriptor = CTFontDescriptorCreateWithAttributes(attributes);
896 wxASSERT(descriptor != NULL);
897
898 CFRelease(attributes);
899 }
900 // Return our font descriptor.
901 return descriptor ;
902 }
903
904 #endif
905
906 void wxNativeFontInfo::Init()
907 {
908 #if wxOSX_USE_CORE_TEXT
909 m_ctFontDescriptor = NULL;
910 #endif
911 #if wxOSX_USE_ATSU_TEXT
912 m_atsuFontID = 0 ;
913 m_atsuAdditionalQDStyles = 0;
914 m_atsuFontValid = false;
915 #if wxOSX_USE_CARBON
916 m_qdFontStyle = 0;
917 m_qdFontFamily = 0;
918 #endif
919 #endif
920 #if wxOSX_USE_COCOA
921 m_nsFontDescriptor = NULL;
922 #endif
923 m_pointSize = 0;
924 m_family = wxFONTFAMILY_DEFAULT;
925 m_style = wxFONTSTYLE_NORMAL;
926 m_weight = wxFONTWEIGHT_NORMAL;
927 m_underlined = false;
928 m_faceName.clear();
929 m_encoding = wxFont::GetDefaultEncoding();
930 m_descriptorValid = false;
931 }
932
933 #if wxOSX_USE_CORE_TEXT
934 void wxNativeFontInfo::Init(CTFontDescriptorRef descr)
935 {
936 Init();
937 m_ctFontDescriptor = wxCFRetain(descr);
938
939 wxCFRef< CFNumberRef > sizevalue( (CFNumberRef) CTFontDescriptorCopyAttribute( m_ctFontDescriptor, kCTFontSizeAttribute ) );
940 float fsize;
941 if ( CFNumberGetValue( sizevalue , kCFNumberFloatType , &fsize ) )
942 m_pointSize = (int)( fsize + 0.5 );
943
944 wxCFRef< CFDictionaryRef > traitsvalue( (CFDictionaryRef) CTFontDescriptorCopyAttribute( m_ctFontDescriptor, kCTFontTraitsAttribute ) );
945 CTFontSymbolicTraits traits;
946 if ( CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(traitsvalue,kCTFontSymbolicTrait),kCFNumberIntType,&traits) )
947 {
948 if ( traits & kCTFontItalicTrait )
949 m_style = wxFONTSTYLE_ITALIC;
950 if ( traits & kCTFontBoldTrait )
951 m_weight = wxFONTWEIGHT_BOLD ;
952 }
953
954 wxCFStringRef familyName( (CFStringRef) CTFontDescriptorCopyAttribute(m_ctFontDescriptor, kCTFontFamilyNameAttribute));
955 m_faceName = familyName.AsString();
956 }
957 #endif
958
959 void wxNativeFontInfo::EnsureValid()
960 {
961 if ( m_descriptorValid )
962 return;
963
964 #if wxOSX_USE_CORE_TEXT
965 if ( m_ctFontDescriptor == NULL && UMAGetSystemVersion() >= 0x1050 )
966 {
967 CTFontSymbolicTraits traits = 0;
968
969 if (m_weight == wxFONTWEIGHT_BOLD)
970 traits |= kCTFontBoldTrait;
971 if (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT)
972 traits |= kCTFontItalicTrait;
973
974 // use font caching
975 wxString lookupnameWithSize = wxString::Format( "%s_%ld_%ld", m_faceName.c_str(), traits, m_pointSize );
976
977 static std::map< std::wstring , wxCFRef< CTFontDescriptorRef > > fontdescriptorcache ;
978 m_ctFontDescriptor = wxCFRetain((CTFontDescriptorRef)fontdescriptorcache[ std::wstring(lookupnameWithSize.wc_str()) ]);
979 if ( !m_ctFontDescriptor )
980 {
981 // QD selection algorithm is the fastest by orders of magnitude on 10.5
982 if ( m_faceName.IsAscii() )
983 {
984 uint8_t qdstyle = 0;
985 if (m_weight == wxFONTWEIGHT_BOLD)
986 qdstyle |= bold;
987 if (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT)
988 qdstyle |= italic;
989
990 Str255 qdFontName ;
991 wxMacStringToPascal( m_faceName , qdFontName );
992 wxCFRef< CTFontRef > font;
993 font.reset( CTFontCreateWithQuickdrawInstance(qdFontName, 0 , qdstyle, m_pointSize) );
994 m_ctFontDescriptor = CTFontCopyFontDescriptor(font);
995 }
996 else
997 {
998 m_ctFontDescriptor = wxMacCreateCTFontDescriptor( wxCFStringRef(m_faceName),traits );
999 }
1000 fontdescriptorcache[ std::wstring(lookupnameWithSize.wc_str()) ].reset(wxCFRetain(m_ctFontDescriptor));
1001 }
1002 }
1003 #endif
1004 #if wxOSX_USE_ATSU_TEXT
1005 if ( !m_atsuFontValid )
1006 {
1007 #if !wxOSX_USE_CARBON
1008 // not needed outside
1009 wxInt16 m_qdFontFamily;
1010 wxInt16 m_qdFontStyle;
1011 #endif
1012 wxCFStringRef cf( m_faceName, wxLocale::GetSystemEncoding() );
1013 ATSFontFamilyRef atsfamily = ATSFontFamilyFindFromName( cf , kATSOptionFlagsDefault );
1014 if ( atsfamily == (ATSFontFamilyRef) -1 )
1015 {
1016 wxLogDebug( wxT("ATSFontFamilyFindFromName failed for ") + m_faceName );
1017 m_qdFontFamily = GetAppFont();
1018 }
1019 else
1020 {
1021 m_qdFontFamily = FMGetFontFamilyFromATSFontFamilyRef( atsfamily );
1022 }
1023
1024 m_qdFontStyle = 0;
1025 if (m_weight == wxFONTWEIGHT_BOLD)
1026 m_qdFontStyle |= bold;
1027 if (m_style == wxFONTSTYLE_ITALIC || m_style == wxFONTSTYLE_SLANT)
1028 m_qdFontStyle |= italic;
1029 if (m_underlined)
1030 m_qdFontStyle |= underline;
1031
1032
1033 // we try to get as much styles as possible into ATSU
1034
1035 // ATSUFontID and FMFont are equivalent
1036 FMFontStyle intrinsicStyle = 0 ;
1037 OSStatus status = FMGetFontFromFontFamilyInstance( m_qdFontFamily , m_qdFontStyle , (FMFont*)&m_atsuFontID , &intrinsicStyle);
1038 if ( status != noErr )
1039 {
1040 wxFAIL_MSG( wxT("couldn't get an ATSUFont from font family") );
1041 }
1042 m_atsuAdditionalQDStyles = m_qdFontStyle & (~intrinsicStyle );
1043 m_atsuFontValid = true;
1044 }
1045 #endif
1046 #if wxOSX_USE_COCOA
1047 if ( m_nsFontDescriptor == NULL )
1048 OSXValidateNSFontDescriptor();
1049 #endif
1050 #if wxOSX_USE_IPHONE
1051 // TODO
1052 #endif
1053 m_descriptorValid = true;
1054 }
1055
1056 void wxNativeFontInfo::Init(const wxNativeFontInfo& info)
1057 {
1058 Init();
1059 #if wxOSX_USE_CORE_TEXT
1060 m_ctFontDescriptor = wxCFRetain(info.m_ctFontDescriptor);
1061 #endif
1062 #if wxOSX_USE_ATSU_TEXT
1063 m_atsuFontValid = info.m_atsuFontValid;
1064 m_atsuFontID = info.m_atsuFontID ;
1065 m_atsuAdditionalQDStyles = info.m_atsuAdditionalQDStyles;
1066 #if wxOSX_USE_CARBON
1067 m_qdFontFamily = info.m_qdFontFamily;
1068 m_qdFontStyle = info.m_qdFontStyle;
1069 #endif
1070 #endif
1071 #if wxOSX_USE_COCOA
1072 m_nsFontDescriptor = (NSFontDescriptor*) wxMacCocoaRetain(info.m_nsFontDescriptor);
1073 #endif
1074 m_pointSize = info.m_pointSize;
1075 m_family = info.m_family;
1076 m_style = info.m_style;
1077 m_weight = info.m_weight;
1078 m_underlined = info.m_underlined;
1079 m_faceName = info.m_faceName;
1080 m_encoding = info.m_encoding;
1081 m_descriptorValid = info.m_descriptorValid;
1082 }
1083
1084 void wxNativeFontInfo::Init(int size,
1085 wxFontFamily family,
1086 wxFontStyle style,
1087 wxFontWeight weight,
1088 bool underlined,
1089 const wxString& faceName,
1090 wxFontEncoding encoding)
1091 {
1092 Init();
1093 m_pointSize = size;
1094 m_family = family;
1095 m_style = style;
1096 m_weight = weight;
1097 m_underlined = underlined;
1098 m_faceName = faceName;
1099 if ( encoding == wxFONTENCODING_DEFAULT )
1100 encoding = wxFont::GetDefaultEncoding();
1101 m_encoding = encoding;
1102
1103 }
1104
1105 void wxNativeFontInfo::Free()
1106 {
1107 #if wxOSX_USE_CORE_TEXT
1108 wxCFRelease(m_ctFontDescriptor);
1109 m_ctFontDescriptor = NULL;
1110 #endif
1111 #if wxOSX_USE_ATSU_TEXT
1112 m_atsuFontID = 0 ;
1113 m_atsuAdditionalQDStyles = 0;
1114 m_atsuFontValid = false;
1115 #endif
1116 #if wxOSX_USE_COCOA
1117 wxMacCocoaRelease(m_nsFontDescriptor);
1118 m_nsFontDescriptor = NULL;
1119 #endif
1120 m_descriptorValid = false;
1121 }
1122
1123 bool wxNativeFontInfo::FromString(const wxString& s)
1124 {
1125 long l;
1126
1127 wxStringTokenizer tokenizer(s, wxT(";"));
1128
1129 wxString token = tokenizer.GetNextToken();
1130 //
1131 // Ignore the version for now
1132 //
1133
1134 token = tokenizer.GetNextToken();
1135 if ( !token.ToLong(&l) )
1136 return false;
1137 m_pointSize = (int)l;
1138
1139 token = tokenizer.GetNextToken();
1140 if ( !token.ToLong(&l) )
1141 return false;
1142 m_family = (wxFontFamily)l;
1143
1144 token = tokenizer.GetNextToken();
1145 if ( !token.ToLong(&l) )
1146 return false;
1147 m_style = (wxFontStyle)l;
1148
1149 token = tokenizer.GetNextToken();
1150 if ( !token.ToLong(&l) )
1151 return false;
1152 m_weight = (wxFontWeight)l;
1153
1154 token = tokenizer.GetNextToken();
1155 if ( !token.ToLong(&l) )
1156 return false;
1157 m_underlined = l != 0;
1158
1159 m_faceName = tokenizer.GetNextToken();
1160
1161 #ifndef __WXMAC__
1162 if( !faceName )
1163 return false;
1164 #endif
1165
1166 token = tokenizer.GetNextToken();
1167 if ( !token.ToLong(&l) )
1168 return false;
1169 m_encoding = (wxFontEncoding)l;
1170
1171 return true;
1172 }
1173
1174 wxString wxNativeFontInfo::ToString() const
1175 {
1176 wxString s;
1177
1178 s.Printf(wxT("%d;%d;%d;%d;%d;%d;%s;%d"),
1179 0, // version
1180 m_pointSize,
1181 m_family,
1182 (int)m_style,
1183 (int)m_weight,
1184 m_underlined,
1185 m_faceName.GetData(),
1186 (int)m_encoding);
1187
1188 return s;
1189 }
1190
1191 int wxNativeFontInfo::GetPointSize() const
1192 {
1193 return m_pointSize;
1194 }
1195
1196 wxFontStyle wxNativeFontInfo::GetStyle() const
1197 {
1198 return m_style;
1199 }
1200
1201 wxFontWeight wxNativeFontInfo::GetWeight() const
1202 {
1203 return m_weight;
1204 }
1205
1206 bool wxNativeFontInfo::GetUnderlined() const
1207 {
1208 return m_underlined;
1209 }
1210
1211 wxString wxNativeFontInfo::GetFaceName() const
1212 {
1213 return m_faceName;
1214 }
1215
1216 wxFontFamily wxNativeFontInfo::GetFamily() const
1217 {
1218 return m_family;
1219 }
1220
1221 wxFontEncoding wxNativeFontInfo::GetEncoding() const
1222 {
1223 return m_encoding;
1224 }
1225
1226 // changing the font descriptor
1227
1228 void wxNativeFontInfo::SetPointSize(int pointsize)
1229 {
1230 if ( m_pointSize != pointsize )
1231 {
1232 m_pointSize = pointsize;
1233 Free();
1234 }
1235 }
1236
1237 void wxNativeFontInfo::SetStyle(wxFontStyle style_)
1238 {
1239 if ( m_style != style_ )
1240 {
1241 m_style = style_;
1242 Free();
1243 }
1244 }
1245
1246 void wxNativeFontInfo::SetWeight(wxFontWeight weight_)
1247 {
1248 if ( m_weight != weight_ )
1249 {
1250 m_weight = weight_;
1251 Free();
1252 }
1253 }
1254
1255 void wxNativeFontInfo::SetUnderlined(bool underlined_)
1256 {
1257 if ( m_underlined != underlined_ )
1258 {
1259 m_underlined = underlined_;
1260 Free();
1261 }
1262 }
1263
1264 bool wxNativeFontInfo::SetFaceName(const wxString& facename_)
1265 {
1266 if ( m_faceName != facename_ )
1267 {
1268 m_faceName = facename_;
1269 Free();
1270 }
1271 return true;
1272 }
1273
1274 void wxNativeFontInfo::SetFamily(wxFontFamily family_)
1275 {
1276 if ( m_family != family_ )
1277 {
1278 m_family = family_;
1279 Free();
1280 }
1281 }
1282
1283 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_)
1284 {
1285 if ( encoding_ == wxFONTENCODING_DEFAULT )
1286 encoding_ = wxFont::GetDefaultEncoding();
1287 m_encoding = encoding_;
1288 // not reflected in native descriptors
1289 }