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