]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/font.cpp
9b5e4bb5a773ed5cade3d427b54761cd412ee21c
[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 if ( m_macFontFamily == kInvalidFontFamily )
267 {
268 wxLogDebug( wxT("ATSFontFamilyFindFromName failed for %s"), m_faceName );
269 m_macFontFamily = GetAppFont();
270 }
271 #endif
272 }
273 }
274 else
275 {
276 #ifndef __LP64__
277 if ( m_faceName == wxT("systemfont") )
278 m_macFontFamily = GetSysFont();
279 else if ( m_faceName == wxT("applicationfont") )
280 m_macFontFamily = GetAppFont();
281 else
282 #else
283 if ( m_faceName == wxT("systemfont") )
284 m_faceName = wxT("Lucida Grande");
285 else if ( m_faceName == wxT("applicationfont") )
286 m_faceName = wxT("Lucida Grande");
287 #endif
288 {
289 wxMacCFStringHolder cf( m_faceName, wxLocale::GetSystemEncoding() );
290 ATSFontFamilyRef atsfamily = ATSFontFamilyFindFromName( cf , kATSOptionFlagsDefault );
291 if ( atsfamily == (ATSFontFamilyRef) -1 )
292 {
293 wxLogDebug( wxT("ATSFontFamilyFindFromName failed for %s"), m_faceName );
294 m_macFontFamily = GetAppFont();
295 }
296 else
297 m_macFontFamily = FMGetFontFamilyFromATSFontFamilyRef( atsfamily );
298 }
299 }
300
301 m_macFontStyle = 0;
302 if (m_weight == wxBOLD)
303 m_macFontStyle |= bold;
304 if (m_style == wxITALIC || m_style == wxSLANT)
305 m_macFontStyle |= italic;
306 if (m_underlined)
307 m_macFontStyle |= underline;
308 m_macFontSize = m_pointSize ;
309 }
310
311 // we try to get as much styles as possible into ATSU
312
313
314 // ATSUFontID and FMFont are equivalent
315 FMFontStyle intrinsicStyle = 0 ;
316 #ifndef __LP64__
317 status = FMGetFontFromFontFamilyInstance( m_macFontFamily , m_macFontStyle , &m_macATSUFontID , &intrinsicStyle);
318 wxASSERT_MSG( status == noErr , wxT("couldn't get an ATSUFont from font family") );
319 #endif
320 m_macATSUAdditionalQDStyles = m_macFontStyle & (~intrinsicStyle );
321
322 if ( m_macATSUStyle )
323 {
324 ::ATSUDisposeStyle((ATSUStyle)m_macATSUStyle);
325 m_macATSUStyle = NULL ;
326 }
327
328 status = ::ATSUCreateStyle((ATSUStyle *)&m_macATSUStyle);
329 wxASSERT_MSG( status == noErr , wxT("couldn't create ATSU style") );
330
331 ATSUAttributeTag atsuTags[] =
332 {
333 kATSUFontTag ,
334 kATSUSizeTag ,
335 kATSUVerticalCharacterTag,
336 kATSUQDBoldfaceTag ,
337 kATSUQDItalicTag ,
338 kATSUQDUnderlineTag ,
339 kATSUQDCondensedTag ,
340 kATSUQDExtendedTag ,
341 };
342 ByteCount atsuSizes[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
343 {
344 sizeof( ATSUFontID ) ,
345 sizeof( Fixed ) ,
346 sizeof( ATSUVerticalCharacterType),
347 sizeof( Boolean ) ,
348 sizeof( Boolean ) ,
349 sizeof( Boolean ) ,
350 sizeof( Boolean ) ,
351 sizeof( Boolean ) ,
352 };
353
354 Boolean kTrue = true ;
355 Boolean kFalse = false ;
356
357 Fixed atsuSize = IntToFixed( m_macFontSize );
358 ATSUVerticalCharacterType kHorizontal = kATSUStronglyHorizontal;
359 ATSUAttributeValuePtr atsuValues[sizeof(atsuTags) / sizeof(ATSUAttributeTag)] =
360 {
361 &m_macATSUFontID ,
362 &atsuSize ,
363 &kHorizontal,
364 (m_macATSUAdditionalQDStyles & bold) ? &kTrue : &kFalse ,
365 (m_macATSUAdditionalQDStyles & italic) ? &kTrue : &kFalse ,
366 (m_macATSUAdditionalQDStyles & underline) ? &kTrue : &kFalse ,
367 (m_macATSUAdditionalQDStyles & condense) ? &kTrue : &kFalse ,
368 (m_macATSUAdditionalQDStyles & extend) ? &kTrue : &kFalse ,
369 };
370
371 status = ::ATSUSetAttributes(
372 (ATSUStyle)m_macATSUStyle,
373 sizeof(atsuTags) / sizeof(ATSUAttributeTag) ,
374 atsuTags, atsuSizes, atsuValues);
375
376 wxASSERT_MSG( status == noErr , wxT("couldn't modify ATSU style") );
377 }
378
379 // ----------------------------------------------------------------------------
380 // wxFont
381 // ----------------------------------------------------------------------------
382
383 bool wxFont::Create(const wxNativeFontInfo& info)
384 {
385 return Create(
386 info.pointSize, info.family, info.style, info.weight,
387 info.underlined, info.faceName, info.encoding );
388 }
389
390 wxFont::wxFont(const wxString& fontdesc)
391 {
392 wxNativeFontInfo info;
393 if ( info.FromString(fontdesc) )
394 (void)Create(info);
395 }
396
397 bool wxFont::Create(int pointSize,
398 int family,
399 int style,
400 int weight,
401 bool underlined,
402 const wxString& faceName,
403 wxFontEncoding encoding)
404 {
405 UnRef();
406
407 m_refData = new wxFontRefData(
408 pointSize, family, style, weight,
409 underlined, faceName, encoding);
410
411 RealizeResource();
412
413 return true;
414 }
415
416 bool wxFont::MacCreateThemeFont(wxUint16 themeFontID)
417 {
418 UnRef();
419
420 m_refData = new wxFontRefData(
421 12, wxDEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL,
422 false, wxEmptyString, wxFONTENCODING_DEFAULT );
423
424 M_FONTDATA->m_macThemeFontID = themeFontID ;
425 RealizeResource();
426
427 return true;
428 }
429
430 wxFont::~wxFont()
431 {
432 }
433
434 bool wxFont::RealizeResource()
435 {
436 M_FONTDATA->MacFindFont();
437
438 return true;
439 }
440
441 void wxFont::SetEncoding(wxFontEncoding encoding)
442 {
443 Unshare();
444
445 M_FONTDATA->m_encoding = encoding;
446
447 RealizeResource();
448 }
449
450 void wxFont::Unshare()
451 {
452 // Don't change shared data
453 if (!m_refData)
454 {
455 m_refData = new wxFontRefData();
456 }
457 else
458 {
459 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
460 UnRef();
461 m_refData = ref;
462 }
463 }
464
465 void wxFont::SetPointSize(int pointSize)
466 {
467 Unshare();
468
469 M_FONTDATA->m_pointSize = pointSize;
470
471 RealizeResource();
472 }
473
474 void wxFont::SetFamily(int family)
475 {
476 Unshare();
477
478 M_FONTDATA->m_family = family;
479
480 RealizeResource();
481 }
482
483 void wxFont::SetStyle(int style)
484 {
485 Unshare();
486
487 M_FONTDATA->m_style = style;
488
489 RealizeResource();
490 }
491
492 void wxFont::SetWeight(int weight)
493 {
494 Unshare();
495
496 M_FONTDATA->m_weight = weight;
497
498 RealizeResource();
499 }
500
501 bool wxFont::SetFaceName(const wxString& faceName)
502 {
503 Unshare();
504
505 M_FONTDATA->m_faceName = faceName;
506
507 RealizeResource();
508
509 return wxFontBase::SetFaceName(faceName);
510 }
511
512 void wxFont::SetUnderlined(bool underlined)
513 {
514 Unshare();
515
516 M_FONTDATA->m_underlined = underlined;
517
518 RealizeResource();
519 }
520
521 void wxFont::SetNoAntiAliasing( bool no )
522 {
523 Unshare();
524
525 M_FONTDATA->SetNoAntiAliasing( no );
526
527 RealizeResource();
528 }
529
530 // ----------------------------------------------------------------------------
531 // accessors
532 // ----------------------------------------------------------------------------
533
534 // TODO: insert checks everywhere for M_FONTDATA == NULL!
535
536 int wxFont::GetPointSize() const
537 {
538 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
539
540 return M_FONTDATA->m_pointSize;
541 }
542
543 wxSize wxFont::GetPixelSize() const
544 {
545 #if wxUSE_GRAPHICS_CONTEXT
546 // TODO: consider caching the value
547 wxGraphicsContext* dc = wxGraphicsContext::CreateFromNative((CGContextRef) NULL);
548 dc->SetFont(*(wxFont *)this,*wxBLACK);
549 wxDouble width, height = 0;
550 dc->GetTextExtent( wxT("g"), &width, &height, NULL, NULL);
551 return wxSize((int)width, (int)height);
552 #else
553 wxFontBase::GetPixelSize();
554 #endif
555 }
556
557 int wxFont::GetFamily() const
558 {
559 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
560
561 return M_FONTDATA->m_family;
562 }
563
564 int wxFont::GetStyle() const
565 {
566 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
567
568 return M_FONTDATA->m_style;
569 }
570
571 int wxFont::GetWeight() const
572 {
573 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
574
575 return M_FONTDATA->m_weight;
576 }
577
578 bool wxFont::GetUnderlined() const
579 {
580 wxCHECK_MSG( M_FONTDATA != NULL , false, wxT("invalid font") );
581
582 return M_FONTDATA->m_underlined;
583 }
584
585 wxString wxFont::GetFaceName() const
586 {
587 wxCHECK_MSG( M_FONTDATA != NULL , wxEmptyString , wxT("invalid font") );
588
589 return M_FONTDATA->m_faceName;
590 }
591
592 wxFontEncoding wxFont::GetEncoding() const
593 {
594 wxCHECK_MSG( M_FONTDATA != NULL , wxFONTENCODING_DEFAULT , wxT("invalid font") );
595
596 return M_FONTDATA->m_encoding;
597 }
598
599 bool wxFont::GetNoAntiAliasing() const
600 {
601 wxCHECK_MSG( M_FONTDATA != NULL , false, wxT("invalid font") );
602
603 return M_FONTDATA->m_noAA;
604 }
605
606 short wxFont::MacGetFontNum() const
607 {
608 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
609
610 return M_FONTDATA->m_macFontFamily;
611 }
612
613 short wxFont::MacGetFontSize() const
614 {
615 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
616
617 return M_FONTDATA->m_macFontSize;
618 }
619
620 wxByte wxFont::MacGetFontStyle() const
621 {
622 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
623
624 return M_FONTDATA->m_macFontStyle;
625 }
626
627 wxUint32 wxFont::MacGetATSUFontID() const
628 {
629 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
630
631 return M_FONTDATA->m_macATSUFontID;
632 }
633
634 void * wxFont::MacGetATSUStyle() const
635 {
636 wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") );
637
638 return M_FONTDATA->m_macATSUStyle;
639 }
640
641 wxUint32 wxFont::MacGetATSUAdditionalQDStyles() const
642 {
643 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
644
645 return M_FONTDATA->m_macATSUAdditionalQDStyles;
646 }
647
648 wxUint16 wxFont::MacGetThemeFontID() const
649 {
650 wxCHECK_MSG( M_FONTDATA != NULL , 0, wxT("invalid font") );
651
652 return M_FONTDATA->m_macThemeFontID;
653 }
654
655 const wxNativeFontInfo * wxFont::GetNativeFontInfo() const
656 {
657 wxCHECK_MSG( M_FONTDATA != NULL , NULL, wxT("invalid font") );
658 wxCHECK_MSG( Ok(), NULL, wxT("invalid font") );
659
660 M_FONTDATA->m_info.InitFromFont(*this);
661
662 return &(M_FONTDATA->m_info);
663 }