]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/osx/carbon/font.cpp
Applied #10858: wxListCtrl on Mac does not route Freeze/Thaw/Update to m_genericImpl
[wxWidgets.git] / src / osx / carbon / font.cpp
... / ...
CommitLineData
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
34IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
35
36class WXDLLEXPORT wxFontRefData: public wxGDIRefData
37{
38public:
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
151protected:
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
158public:
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
183wxFontRefData::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
220void 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
238wxFontRefData::~wxFontRefData()
239{
240 Free();
241}
242
243void 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
276wxFontRefData::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
392void 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
496bool wxFont::Create(const wxNativeFontInfo& info)
497{
498 UnRef();
499
500 m_refData = new wxFontRefData( info );
501 RealizeResource();
502
503 return true;
504}
505
506wxFont::wxFont(const wxString& fontdesc)
507{
508 wxNativeFontInfo info;
509 if ( info.FromString(fontdesc) )
510 (void)Create(info);
511}
512
513bool 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
564bool wxFont::CreateSystemFont(wxOSXSystemFont font)
565{
566 UnRef();
567
568 m_refData = new wxFontRefData( font, 0 );
569
570 return true;
571}
572
573wxFont::~wxFont()
574{
575}
576
577void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo& info)
578{
579 UnRef();
580
581 m_refData = new wxFontRefData( info);
582}
583
584
585bool wxFont::RealizeResource()
586{
587 M_FONTDATA->MacFindFont();
588
589 return true;
590}
591
592void wxFont::SetEncoding(wxFontEncoding encoding)
593{
594 AllocExclusive();
595
596 M_FONTDATA->SetEncoding( encoding );
597}
598
599wxGDIRefData *wxFont::CreateGDIRefData() const
600{
601 return new wxFontRefData;
602}
603
604wxGDIRefData *wxFont::CloneGDIRefData(const wxGDIRefData *data) const
605{
606 return new wxFontRefData(*static_cast<const wxFontRefData *>(data));
607}
608
609void wxFont::SetPointSize(int pointSize)
610{
611 if ( M_FONTDATA->GetPointSize() == pointSize )
612 return;
613
614 AllocExclusive();
615
616 M_FONTDATA->SetPointSize( pointSize );
617}
618
619void wxFont::SetFamily(wxFontFamily family)
620{
621 AllocExclusive();
622
623 M_FONTDATA->SetFamily( family );
624}
625
626void wxFont::SetStyle(wxFontStyle style)
627{
628 AllocExclusive();
629
630 M_FONTDATA->SetStyle( style );
631}
632
633void wxFont::SetWeight(wxFontWeight weight)
634{
635 AllocExclusive();
636
637 M_FONTDATA->SetWeight( weight );
638}
639
640bool wxFont::SetFaceName(const wxString& faceName)
641{
642 AllocExclusive();
643
644 M_FONTDATA->SetFaceName( faceName );
645
646 return wxFontBase::SetFaceName(faceName);
647}
648
649void wxFont::SetUnderlined(bool underlined)
650{
651 AllocExclusive();
652
653 M_FONTDATA->SetUnderlined( underlined );
654}
655
656void 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
669int wxFont::GetPointSize() const
670{
671 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
672
673 return M_FONTDATA->GetPointSize();
674}
675
676wxSize 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
691wxFontFamily wxFont::GetFamily() const
692{
693 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTFAMILY_MAX, wxT("invalid font") );
694
695 return M_FONTDATA->GetFamily();
696}
697
698wxFontStyle wxFont::GetStyle() const
699{
700 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTSTYLE_MAX, wxT("invalid font") );
701
702 return M_FONTDATA->GetStyle() ;
703}
704
705wxFontWeight wxFont::GetWeight() const
706{
707 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTWEIGHT_MAX, wxT("invalid font") );
708
709 return M_FONTDATA->GetWeight();
710}
711
712bool wxFont::GetUnderlined() const
713{
714 wxCHECK_MSG( M_FONTDATA != NULL , false, wxT("invalid font") );
715
716 return M_FONTDATA->GetUnderlined();
717}
718
719wxString wxFont::GetFaceName() const
720{
721 wxCHECK_MSG( M_FONTDATA != NULL , wxEmptyString , wxT("invalid font") );
722
723 return M_FONTDATA->GetFaceName() ;
724}
725
726wxFontEncoding wxFont::GetEncoding() const
727{
728 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTENCODING_DEFAULT , wxT("invalid font") );
729
730 return M_FONTDATA->GetEncoding() ;
731}
732
733bool 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
742short 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
752wxByte 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
762wxUint16 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
772void * 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
783wxUint32 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
793wxUint32 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
808CTFontRef 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
822CGFontRef 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
837NSFont* 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
849const 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
870static 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
924void 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
952void 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
977void 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
1074void 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
1102void 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
1123void 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
1141bool 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
1192wxString 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
1209int wxNativeFontInfo::GetPointSize() const
1210{
1211 return m_pointSize;
1212}
1213
1214wxFontStyle wxNativeFontInfo::GetStyle() const
1215{
1216 return m_style;
1217}
1218
1219wxFontWeight wxNativeFontInfo::GetWeight() const
1220{
1221 return m_weight;
1222}
1223
1224bool wxNativeFontInfo::GetUnderlined() const
1225{
1226 return m_underlined;
1227}
1228
1229wxString wxNativeFontInfo::GetFaceName() const
1230{
1231 return m_faceName;
1232}
1233
1234wxFontFamily wxNativeFontInfo::GetFamily() const
1235{
1236 return m_family;
1237}
1238
1239wxFontEncoding wxNativeFontInfo::GetEncoding() const
1240{
1241 return m_encoding;
1242}
1243
1244// changing the font descriptor
1245
1246void wxNativeFontInfo::SetPointSize(int pointsize)
1247{
1248 if ( m_pointSize != pointsize )
1249 {
1250 m_pointSize = pointsize;
1251 Free();
1252 }
1253}
1254
1255void wxNativeFontInfo::SetStyle(wxFontStyle style_)
1256{
1257 if ( m_style != style_ )
1258 {
1259 m_style = style_;
1260 Free();
1261 }
1262}
1263
1264void wxNativeFontInfo::SetWeight(wxFontWeight weight_)
1265{
1266 if ( m_weight != weight_ )
1267 {
1268 m_weight = weight_;
1269 Free();
1270 }
1271}
1272
1273void wxNativeFontInfo::SetUnderlined(bool underlined_)
1274{
1275 if ( m_underlined != underlined_ )
1276 {
1277 m_underlined = underlined_;
1278 Free();
1279 }
1280}
1281
1282bool wxNativeFontInfo::SetFaceName(const wxString& facename_)
1283{
1284 if ( m_faceName != facename_ )
1285 {
1286 m_faceName = facename_;
1287 Free();
1288 }
1289 return true;
1290}
1291
1292void wxNativeFontInfo::SetFamily(wxFontFamily family_)
1293{
1294 if ( m_family != family_ )
1295 {
1296 m_family = family_;
1297 Free();
1298 }
1299}
1300
1301void 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}