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