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