]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/font.cpp
Add more sanity checks to virtual list item nums as the native control sometimes...
[wxWidgets.git] / src / mac / carbon / font.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/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 #endif
22
23 #include "wx/fontutil.h"
24 #include "wx/graphics.h"
25
26 #include "wx/mac/private.h"
27
28 #ifndef __DARWIN__
29 #include <ATSUnicode.h>
30 #endif
31
32
33 IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
34
35
36 class WXDLLEXPORT wxFontRefData: public wxGDIRefData
37 {
38 friend class WXDLLEXPORT wxFont;
39
40 public:
41 wxFontRefData()
42 : m_fontId(0)
43 , m_pointSize(10)
44 , m_family(wxDEFAULT)
45 , m_style(wxNORMAL)
46 , m_weight(wxNORMAL)
47 , m_underlined(false)
48 , m_faceName(wxT("applicationfont"))
49 , m_encoding(wxFONTENCODING_DEFAULT)
50 , m_macFontFamily(0)
51 , m_macFontSize(0)
52 , m_macFontStyle(0)
53 , m_macATSUStyle(0)
54 , m_macATSUFontID(0)
55 {
56 Init(m_pointSize, m_family, m_style, m_weight,
57 m_underlined, m_faceName, m_encoding);
58 }
59
60 wxFontRefData(const wxFontRefData& data)
61 : wxGDIRefData()
62 , m_fontId(data.m_fontId)
63 , m_pointSize(data.m_pointSize)
64 , m_family(data.m_family)
65 , m_style(data.m_style)
66 , m_weight(data.m_weight)
67 , m_underlined(data.m_underlined)
68 , m_faceName(data.m_faceName)
69 , m_encoding(data.m_encoding)
70 , m_macFontFamily(data.m_macFontFamily)
71 , m_macFontSize(data.m_macFontSize)
72 , m_macFontStyle(data.m_macFontStyle)
73 , m_macATSUStyle(0)
74 , m_macATSUFontID(data.m_macATSUFontID)
75 {
76 Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight,
77 data.m_underlined, data.m_faceName, data.m_encoding);
78 }
79
80 wxFontRefData(int size,
81 int family,
82 int style,
83 int weight,
84 bool underlined,
85 const wxString& faceName,
86 wxFontEncoding encoding)
87 : m_fontId(0)
88 , m_pointSize(size)
89 , m_family(family)
90 , m_style(style)
91 , m_weight(weight)
92 , m_underlined(underlined)
93 , m_faceName(faceName)
94 , m_encoding(encoding)
95 , m_macFontFamily(0)
96 , m_macFontSize(0)
97 , m_macFontStyle(0)
98 , m_macATSUStyle(0)
99 , m_macATSUFontID(0)
100 {
101 Init(size, family, style, weight, underlined, faceName, encoding);
102 }
103
104 virtual ~wxFontRefData();
105
106 void SetNoAntiAliasing( bool no = true )
107 { m_noAA = no; }
108
109 bool GetNoAntiAliasing() const
110 { return m_noAA; }
111
112 void MacFindFont();
113
114 protected:
115 // common part of all ctors
116 void Init(int size,
117 int family,
118 int style,
119 int weight,
120 bool underlined,
121 const wxString& faceName,
122 wxFontEncoding encoding);
123
124 // font characterstics
125 int m_fontId;
126 int m_pointSize;
127 int m_family;
128 int m_style;
129 int m_weight;
130 bool m_underlined;
131 wxString m_faceName;
132 wxFontEncoding m_encoding;
133 bool m_noAA; // No anti-aliasing
134
135 public:
136 FMFontFamily m_macFontFamily;
137 FMFontSize m_macFontSize;
138 FMFontStyle m_macFontStyle;
139
140 // ATSU Font Information
141
142 // this is split into an ATSU font id that may
143 // contain some styles (special bold fonts etc) and
144 // these are the additional qd styles that are not
145 // included in the ATSU font id
146 ATSUStyle m_macATSUStyle ;
147 ATSUFontID m_macATSUFontID;
148 FMFontStyle m_macATSUAdditionalQDStyles ;
149
150 // for true themeing support we must store the correct font
151 // information here, as this speeds up and optimizes rendering
152 ThemeFontID m_macThemeFontID ;
153
154 wxNativeFontInfo m_info;
155 };
156
157 #define M_FONTDATA ((wxFontRefData*)m_refData)
158
159
160 // ============================================================================
161 // implementation
162 // ============================================================================
163
164 // ----------------------------------------------------------------------------
165 // wxFontRefData
166 // ----------------------------------------------------------------------------
167
168 void wxFontRefData::Init(int pointSize,
169 int family,
170 int style,
171 int weight,
172 bool underlined,
173 const wxString& faceName,
174 wxFontEncoding encoding)
175 {
176 m_style = style;
177 m_pointSize = pointSize;
178 m_family = family;
179 m_style = style;
180 m_weight = weight;
181 m_underlined = underlined;
182 m_faceName = faceName;
183 m_encoding = encoding;
184
185 m_macFontFamily = 0 ;
186 m_macFontSize = 0;
187 m_macFontStyle = 0;
188 m_macATSUFontID = 0;
189 m_macATSUAdditionalQDStyles = 0 ;
190 m_macATSUStyle = NULL ;
191
192 m_macThemeFontID = kThemeCurrentPortFont ;
193 m_noAA = false;
194 }
195
196 wxFontRefData::~wxFontRefData()
197 {
198 if ( m_macATSUStyle )
199 {
200 ::ATSUDisposeStyle((ATSUStyle)m_macATSUStyle);
201 m_macATSUStyle = NULL ;
202 }
203 }
204
205 void wxFontRefData::MacFindFont()
206 {
207 OSStatus status ;
208
209 Str255 qdFontName ;
210 if ( m_macThemeFontID != kThemeCurrentPortFont )
211 {
212 Style style ;
213 GetThemeFont( m_macThemeFontID, GetApplicationScript(), qdFontName, &m_macFontSize, &style );
214 m_macFontStyle = style ;
215 m_faceName = wxMacMakeStringFromPascal( qdFontName );
216 if ( m_macFontStyle & bold )
217 m_weight = wxBOLD ;
218 else
219 m_weight = wxNORMAL ;
220 if ( m_macFontStyle & italic )
221 m_style = wxITALIC ;
222 if ( m_macFontStyle & underline )
223 m_underlined = true ;
224 m_pointSize = m_macFontSize ;
225 #ifndef __LP64__
226 m_macFontFamily = FMGetFontFamilyFromName( qdFontName );
227 #endif
228 }
229 else
230 {
231 if ( m_faceName.empty() )
232 {
233 if ( m_family == wxDEFAULT )
234 {
235 #ifndef __LP64__
236 m_macFontFamily = GetAppFont();
237 FMGetFontFamilyName(m_macFontFamily,qdFontName);
238 m_faceName = wxMacMakeStringFromPascal( qdFontName );
239 #endif
240 }
241 else
242 {
243 switch ( m_family )
244 {
245 case wxSCRIPT :
246 case wxROMAN :
247 case wxDECORATIVE :
248 m_faceName = wxT("Times");
249 break ;
250
251 case wxSWISS :
252 m_faceName = wxT("Lucida Grande");
253 break ;
254
255 case wxMODERN :
256 m_faceName = wxT("Monaco");
257 break ;
258
259 default:
260 m_faceName = wxT("Times");
261 break ;
262 }
263 #ifndef __LP64__
264 wxMacStringToPascal( m_faceName , qdFontName );
265 m_macFontFamily = FMGetFontFamilyFromName( qdFontName );
266 #endif
267 }
268 }
269 else
270 {
271 #ifndef __LP64__
272 if ( m_faceName == wxT("systemfont") )
273 m_macFontFamily = GetSysFont();
274 else if ( m_faceName == wxT("applicationfont") )
275 m_macFontFamily = GetAppFont();
276 else
277 #else
278 if ( m_faceName == wxT("systemfont") )
279 m_faceName = wxT("Lucida Grande");
280 else if ( m_faceName == wxT("applicationfont") )
281 m_faceName = wxT("Lucida Grande");
282 #endif
283 {
284 wxMacCFStringHolder cf( m_faceName, wxLocale::GetSystemEncoding() );
285 ATSFontFamilyRef atsfamily = ATSFontFamilyFindFromName( cf , kATSOptionFlagsDefault );
286 wxASSERT_MSG( atsfamily != (ATSFontFamilyRef) -1 , wxT("ATSFontFamilyFindFromName failed") );
287 m_macFontFamily = FMGetFontFamilyFromATSFontFamilyRef( atsfamily );
288 }
289 }
290
291 m_macFontStyle = 0;
292 if (m_weight == wxBOLD)
293 m_macFontStyle |= bold;
294 if (m_style == wxITALIC || m_style == wxSLANT)
295 m_macFontStyle |= italic;
296 if (m_underlined)
297 m_macFontStyle |= underline;
298 m_macFontSize = m_pointSize ;
299 }
300
301 // we try to get as much styles as possible into ATSU
302
303
304 // ATSUFontID and FMFont are equivalent
305 FMFontStyle intrinsicStyle = 0 ;
306 #ifndef __LP64__
307 status = FMGetFontFromFontFamilyInstance( m_macFontFamily , m_macFontStyle , &m_macATSUFontID , &intrinsicStyle);
308 wxASSERT_MSG( status == noErr , wxT("couldn't get an ATSUFont from font family") );
309 #endif
310 m_macATSUAdditionalQDStyles = m_macFontStyle & (~intrinsicStyle );
311
312 if ( m_macATSUStyle )
313 {
314 ::ATSUDisposeStyle((ATSUStyle)m_macATSUStyle);
315 m_macATSUStyle = NULL ;
316 }
317
318 status = ::ATSUCreateStyle((ATSUStyle *)&m_macATSUStyle);
319 wxASSERT_MSG( status == noErr , wxT("couldn't create ATSU style") );
320
321 ATSUAttributeTag atsuTags[] =
322 {
323 kATSUFontTag ,
324 kATSUSizeTag ,
325 kATSUVerticalCharacterTag,
326 kATSUQDBoldfaceTag ,
327 kATSUQDItalicTag ,
328 kATSUQDUnderlineTag ,
329 kATSUQDCondensedTag ,
330 kATSUQDExtendedTag ,
331 };
332 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
333 {
334 sizeof( ATSUFontID ) ,
335 sizeof( Fixed ) ,
336 sizeof( ATSUVerticalCharacterType),
337 sizeof( Boolean ) ,
338 sizeof( Boolean ) ,
339 sizeof( Boolean ) ,
340 sizeof( Boolean ) ,
341 sizeof( Boolean ) ,
342 };
343
344 Boolean kTrue = true ;
345 Boolean kFalse = false ;
346
347 Fixed atsuSize = IntToFixed( m_macFontSize );
348 ATSUVerticalCharacterType kHorizontal = kATSUStronglyHorizontal;
349 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
350 {
351 &m_macATSUFontID ,
352 &atsuSize ,
353 &kHorizontal,
354 (m_macATSUAdditionalQDStyles & bold) ? &kTrue : &kFalse ,
355 (m_macATSUAdditionalQDStyles & italic) ? &kTrue : &kFalse ,
356 (m_macATSUAdditionalQDStyles & underline) ? &kTrue : &kFalse ,
357 (m_macATSUAdditionalQDStyles & condense) ? &kTrue : &kFalse ,
358 (m_macATSUAdditionalQDStyles & extend) ? &kTrue : &kFalse ,
359 };
360
361 status = ::ATSUSetAttributes(
362 (ATSUStyle)m_macATSUStyle,
363 sizeof(atsuTags) / sizeof(ATSUAttributeTag) ,
364 atsuTags, atsuSizes, atsuValues);
365
366 wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") );
367 }
368
369 // ----------------------------------------------------------------------------
370 // wxFont
371 // ----------------------------------------------------------------------------
372
373 bool wxFont::Create(const wxNativeFontInfo& info)
374 {
375 return Create(
376 info.pointSize, info.family, info.style, info.weight,
377 info.underlined, info.faceName, info.encoding );
378 }
379
380 wxFont::wxFont(const wxString& fontdesc)
381 {
382 wxNativeFontInfo info;
383 if ( info.FromString(fontdesc) )
384 (void)Create(info);
385 }
386
387 bool wxFont::Create(int pointSize,
388 int family,
389 int style,
390 int weight,
391 bool underlined,
392 const wxString& faceName,
393 wxFontEncoding encoding)
394 {
395 UnRef();
396
397 m_refData = new wxFontRefData(
398 pointSize, family, style, weight,
399 underlined, faceName, encoding);
400
401 RealizeResource();
402
403 return true;
404 }
405
406 bool wxFont::MacCreateThemeFont(wxUint16 themeFontID)
407 {
408 UnRef();
409
410 m_refData = new wxFontRefData(
411 12, wxDEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL,
412 false, wxEmptyString, wxFONTENCODING_DEFAULT );
413
414 M_FONTDATA->m_macThemeFontID = themeFontID ;
415 RealizeResource();
416
417 return true;
418 }
419
420 wxFont::~wxFont()
421 {
422 }
423
424 bool wxFont::RealizeResource()
425 {
426 M_FONTDATA->MacFindFont();
427
428 return true;
429 }
430
431 void wxFont::SetEncoding(wxFontEncoding encoding)
432 {
433 Unshare();
434
435 M_FONTDATA->m_encoding = encoding;
436
437 RealizeResource();
438 }
439
440 void wxFont::Unshare()
441 {
442 // Don't change shared data
443 if (!m_refData)
444 {
445 m_refData = new wxFontRefData();
446 }
447 else
448 {
449 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
450 UnRef();
451 m_refData = ref;
452 }
453 }
454
455 void wxFont::SetPointSize(int pointSize)
456 {
457 Unshare();
458
459 M_FONTDATA->m_pointSize = pointSize;
460
461 RealizeResource();
462 }
463
464 void wxFont::SetFamily(int family)
465 {
466 Unshare();
467
468 M_FONTDATA->m_family = family;
469
470 RealizeResource();
471 }
472
473 void wxFont::SetStyle(int style)
474 {
475 Unshare();
476
477 M_FONTDATA->m_style = style;
478
479 RealizeResource();
480 }
481
482 void wxFont::SetWeight(int weight)
483 {
484 Unshare();
485
486 M_FONTDATA->m_weight = weight;
487
488 RealizeResource();
489 }
490
491 bool wxFont::SetFaceName(const wxString& faceName)
492 {
493 Unshare();
494
495 M_FONTDATA->m_faceName = faceName;
496
497 RealizeResource();
498
499 return wxFontBase::SetFaceName(faceName);
500 }
501
502 void wxFont::SetUnderlined(bool underlined)
503 {
504 Unshare();
505
506 M_FONTDATA->m_underlined = underlined;
507
508 RealizeResource();
509 }
510
511 void wxFont::SetNoAntiAliasing( bool no )
512 {
513 Unshare();
514
515 M_FONTDATA->SetNoAntiAliasing( no );
516
517 RealizeResource();
518 }
519
520 // ----------------------------------------------------------------------------
521 // accessors
522 // ----------------------------------------------------------------------------
523
524 // TODO: insert checks everywhere for M_FONTDATA == NULL!
525
526 int wxFont::GetPointSize() const
527 {
528 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
529
530 return M_FONTDATA->m_pointSize;
531 }
532
533 wxSize wxFont::GetPixelSize() const
534 {
535 #if wxUSE_GRAPHICS_CONTEXT
536 // TODO: consider caching the value
537 wxGraphicsContext* dc = wxGraphicsContext::CreateFromNative((CGContextRef) NULL);
538 dc->SetFont(*(wxFont *)this,*wxBLACK);
539 wxDouble width, height = 0;
540 dc->GetTextExtent( wxT("g"), &width, &height, NULL, NULL);
541 return wxSize((int)width, (int)height);
542 #else
543 wxFontBase::GetPixelSize();
544 #endif
545 }
546
547 int wxFont::GetFamily() const
548 {
549 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
550
551 return M_FONTDATA->m_family;
552 }
553
554 int wxFont::GetStyle() const
555 {
556 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
557
558 return M_FONTDATA->m_style;
559 }
560
561 int wxFont::GetWeight() const
562 {
563 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
564
565 return M_FONTDATA->m_weight;
566 }
567
568 bool wxFont::GetUnderlined() const
569 {
570 wxCHECK_MSG( M_FONTDATA != NULL , false, wxT("invalid font") );
571
572 return M_FONTDATA->m_underlined;
573 }
574
575 wxString wxFont::GetFaceName() const
576 {
577 wxCHECK_MSG( M_FONTDATA != NULL , wxEmptyString , wxT("invalid font") );
578
579 return M_FONTDATA->m_faceName;
580 }
581
582 wxFontEncoding wxFont::GetEncoding() const
583 {
584 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTENCODING_DEFAULT , wxT("invalid font") );
585
586 return M_FONTDATA->m_encoding;
587 }
588
589 bool wxFont::GetNoAntiAliasing() const
590 {
591 wxCHECK_MSG( M_FONTDATA != NULL , false, wxT("invalid font") );
592
593 return M_FONTDATA->m_noAA;
594 }
595
596 short wxFont::MacGetFontNum() const
597 {
598 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
599
600 return M_FONTDATA->m_macFontFamily;
601 }
602
603 short wxFont::MacGetFontSize() const
604 {
605 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
606
607 return M_FONTDATA->m_macFontSize;
608 }
609
610 wxByte wxFont::MacGetFontStyle() const
611 {
612 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
613
614 return M_FONTDATA->m_macFontStyle;
615 }
616
617 wxUint32 wxFont::MacGetATSUFontID() const
618 {
619 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
620
621 return M_FONTDATA->m_macATSUFontID;
622 }
623
624 void * wxFont::MacGetATSUStyle() const
625 {
626 wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") );
627
628 return M_FONTDATA->m_macATSUStyle;
629 }
630
631 wxUint32 wxFont::MacGetATSUAdditionalQDStyles() const
632 {
633 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
634
635 return M_FONTDATA->m_macATSUAdditionalQDStyles;
636 }
637
638 wxUint16 wxFont::MacGetThemeFontID() const
639 {
640 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
641
642 return M_FONTDATA->m_macThemeFontID;
643 }
644
645 const wxNativeFontInfo * wxFont::GetNativeFontInfo() const
646 {
647 wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") );
648 wxCHECK_MSG( Ok(), NULL, wxT("invalid font") );
649
650 M_FONTDATA->m_info.InitFromFont(*this);
651
652 return &(M_FONTDATA->m_info);
653 }