]> git.saurik.com Git - wxWidgets.git/blame - src/msw/font.cpp
Don't use "Cancel" button in the about dialog of the listctrl sample.
[wxWidgets.git] / src / msw / font.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
a9249b2e 2// Name: src/msw/font.cpp
2bda0e17
KB
3// Purpose: wxFont class
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
77ffb593 8// Copyright: (c) wxWidgets team
65571936 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
0c5d3e1c
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17
KB
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
0c5d3e1c 24 #pragma hdrstop
2bda0e17
KB
25#endif
26
48a1108e
WS
27#include "wx/font.h"
28
2bda0e17 29#ifndef WX_PRECOMP
0c5d3e1c
VZ
30 #include "wx/list.h"
31 #include "wx/utils.h"
32 #include "wx/app.h"
f94dfb38 33 #include "wx/log.h"
081d8d96 34 #include "wx/msw/private.h"
0c5d3e1c 35#endif // WX_PRECOMP
2bda0e17 36
081d8d96 37#include "wx/encinfo.h"
76e23cdb 38#include "wx/fontutil.h"
bff67a6a 39#include "wx/fontmap.h"
76e23cdb 40
66160760
VZ
41#ifndef __WXWINCE__
42 #include "wx/sysopt.h"
43#endif
44
14ba694c 45#include "wx/scopeguard.h"
1e6feb95 46#include "wx/tokenzr.h"
2bda0e17 47
3ca6a5f0
BP
48// ----------------------------------------------------------------------------
49// constants
50// ----------------------------------------------------------------------------
51
9cf8de4c
VZ
52// the mask used to extract the pitch from LOGFONT::lfPitchAndFamily field
53static const int PITCH_MASK = FIXED_PITCH | VARIABLE_PITCH;
54
0c5d3e1c
VZ
55// ----------------------------------------------------------------------------
56// wxFontRefData - the internal description of the font
57// ----------------------------------------------------------------------------
2bda0e17 58
0c5d3e1c 59class WXDLLEXPORT wxFontRefData: public wxGDIRefData
2bda0e17 60{
0c5d3e1c 61public:
a9249b2e 62 // constructors
0c5d3e1c
VZ
63 wxFontRefData()
64 {
c47addef 65 Init(-1, wxSize(0,0), false, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL,
c7a49742 66 wxFONTWEIGHT_NORMAL, false, false, wxEmptyString,
544229d1 67 wxFONTENCODING_DEFAULT);
0c5d3e1c
VZ
68 }
69
70 wxFontRefData(int size,
544229d1
VZ
71 const wxSize& pixelSize,
72 bool sizeUsingPixels,
0c14b6c3
FM
73 wxFontFamily family,
74 wxFontStyle style,
75 wxFontWeight weight,
0c5d3e1c 76 bool underlined,
c7a49742 77 bool strikethrough,
0c5d3e1c
VZ
78 const wxString& faceName,
79 wxFontEncoding encoding)
80 {
544229d1 81 Init(size, pixelSize, sizeUsingPixels, family, style, weight,
c7a49742 82 underlined, strikethrough, faceName, encoding);
0c5d3e1c 83 }
2bda0e17 84
04ef50df 85 wxFontRefData(const wxNativeFontInfo& info, WXHFONT hFont = 0)
09fcd889 86 {
04ef50df 87 Init(info, hFont);
09fcd889
VZ
88 }
89
04a18b0d 90 wxFontRefData(const wxFontRefData& data) : wxGDIRefData()
a9249b2e 91 {
df898907 92 Init(data.m_nativeFontInfo);
a9249b2e
VZ
93 }
94
0c5d3e1c
VZ
95 virtual ~wxFontRefData();
96
a9249b2e 97 // operations
df898907 98 bool Alloc();
a9249b2e
VZ
99
100 void Free();
101
102 // all wxFont accessors
103 int GetPointSize() const
104 {
df898907 105 return m_nativeFontInfo.GetPointSize();
a9249b2e
VZ
106 }
107
544229d1
VZ
108 wxSize GetPixelSize() const
109 {
df898907 110 return m_nativeFontInfo.GetPixelSize();
544229d1 111 }
907173e5 112
544229d1
VZ
113 bool IsUsingSizeInPixels() const
114 {
df898907 115 return m_sizeUsingPixels;
544229d1
VZ
116 }
117
9817be8a 118 wxFontFamily GetFamily() const
a9249b2e 119 {
df898907 120 return m_nativeFontInfo.GetFamily();
a9249b2e
VZ
121 }
122
9817be8a 123 wxFontStyle GetStyle() const
a9249b2e 124 {
df898907 125 return m_nativeFontInfo.GetStyle();
a9249b2e
VZ
126 }
127
9817be8a 128 wxFontWeight GetWeight() const
a9249b2e 129 {
df898907 130 return m_nativeFontInfo.GetWeight();
a9249b2e
VZ
131 }
132
133 bool GetUnderlined() const
134 {
df898907 135 return m_nativeFontInfo.GetUnderlined();
a9249b2e
VZ
136 }
137
c7a49742
VZ
138 bool GetStrikethrough() const
139 {
140 return m_nativeFontInfo.GetStrikethrough();
141 }
142
a9249b2e
VZ
143 wxString GetFaceName() const
144 {
9bd26720
VZ
145 wxString facename = m_nativeFontInfo.GetFaceName();
146 if ( facename.empty() )
147 {
148 facename = GetMSWFaceName();
149 if ( !facename.empty() )
150 {
151 // cache the face name, it shouldn't change unless the family
152 // does and wxNativeFontInfo::SetFamily() resets the face name
153 const_cast<wxFontRefData *>(this)->SetFaceName(facename);
154 }
155 }
156
157 return facename;
a9249b2e
VZ
158 }
159
160 wxFontEncoding GetEncoding() const
161 {
df898907 162 return m_nativeFontInfo.GetEncoding();
a9249b2e
VZ
163 }
164
df898907 165 WXHFONT GetHFONT() const
8e34db1d 166 {
64932e41 167 AllocIfNeeded();
8e34db1d
VZ
168
169 return (WXHFONT)m_hFont;
170 }
171
172 bool HasHFONT() const
173 {
174 return m_hFont != 0;
175 }
a9249b2e 176
8e34db1d
VZ
177 // ... and setters: notice that all of them invalidate the currently
178 // allocated HFONT, if any, so that the next call to GetHFONT() recreates a
179 // new one
a9249b2e
VZ
180 void SetPointSize(int pointSize)
181 {
8e34db1d
VZ
182 Free();
183
df898907
FM
184 m_nativeFontInfo.SetPointSize(pointSize);
185 m_sizeUsingPixels = false;
544229d1
VZ
186 }
187
188 void SetPixelSize(const wxSize& pixelSize)
189 {
5414d62e
VZ
190 wxCHECK_RET( pixelSize.GetWidth() >= 0, "negative font width" );
191 wxCHECK_RET( pixelSize.GetHeight() != 0, "zero font height" );
192
8e34db1d
VZ
193 Free();
194
df898907
FM
195 m_nativeFontInfo.SetPixelSize(pixelSize);
196 m_sizeUsingPixels = true;
a9249b2e
VZ
197 }
198
0c14b6c3 199 void SetFamily(wxFontFamily family)
a9249b2e 200 {
8e34db1d
VZ
201 Free();
202
df898907 203 m_nativeFontInfo.SetFamily(family);
a9249b2e
VZ
204 }
205
0c14b6c3 206 void SetStyle(wxFontStyle style)
a9249b2e 207 {
8e34db1d
VZ
208 Free();
209
df898907 210 m_nativeFontInfo.SetStyle(style);
a9249b2e
VZ
211 }
212
0c14b6c3 213 void SetWeight(wxFontWeight weight)
a9249b2e 214 {
8e34db1d
VZ
215 Free();
216
df898907 217 m_nativeFontInfo.SetWeight(weight);
a9249b2e
VZ
218 }
219
85ab460e 220 bool SetFaceName(const wxString& faceName)
a9249b2e 221 {
8e34db1d
VZ
222 Free();
223
df898907 224 return m_nativeFontInfo.SetFaceName(faceName);
a9249b2e
VZ
225 }
226
227 void SetUnderlined(bool underlined)
228 {
8e34db1d
VZ
229 Free();
230
df898907 231 m_nativeFontInfo.SetUnderlined(underlined);
a9249b2e
VZ
232 }
233
c7a49742
VZ
234 void SetStrikethrough(bool strikethrough)
235 {
236 Free();
237
238 m_nativeFontInfo.SetStrikethrough(strikethrough);
239 }
240
a9249b2e
VZ
241 void SetEncoding(wxFontEncoding encoding)
242 {
8e34db1d
VZ
243 Free();
244
df898907 245 m_nativeFontInfo.SetEncoding(encoding);
a9249b2e
VZ
246 }
247
a9249b2e 248 const wxNativeFontInfo& GetNativeFontInfo() const
a77c05ea 249 {
64932e41
VZ
250 // we need to create the font now to get the corresponding LOGFONT if
251 // it hadn't been done yet
252 AllocIfNeeded();
253
a77c05ea
VZ
254 // ensure that we have a valid face name in our font information:
255 // GetFaceName() will try to retrieve it from our HFONT and save it if
256 // it was successful
257 (void)GetFaceName();
258
259 return m_nativeFontInfo;
260 }
a9249b2e 261
8e34db1d 262 void SetNativeFontInfo(const wxNativeFontInfo& nativeFontInfo)
9cc79dd6
VZ
263 {
264 Free();
265
266 m_nativeFontInfo = nativeFontInfo;
9cc79dd6 267 }
8e34db1d 268
0c5d3e1c
VZ
269protected:
270 // common part of all ctors
271 void Init(int size,
544229d1
VZ
272 const wxSize& pixelSize,
273 bool sizeUsingPixels,
0c14b6c3
FM
274 wxFontFamily family,
275 wxFontStyle style,
276 wxFontWeight weight,
0c5d3e1c 277 bool underlined,
c7a49742 278 bool strikethrough,
0c5d3e1c
VZ
279 const wxString& faceName,
280 wxFontEncoding encoding);
281
04ef50df 282 void Init(const wxNativeFontInfo& info, WXHFONT hFont = 0);
09fcd889 283
64932e41
VZ
284 void AllocIfNeeded() const
285 {
286 if ( !m_hFont )
287 const_cast<wxFontRefData *>(this)->Alloc();
288 }
289
9bd26720
VZ
290 // retrieve the face name really being used by the font: this is used to
291 // get the face name selected by the system when we don't specify it (but
292 // use just the family for example)
293 wxString GetMSWFaceName() const
294 {
295 ScreenHDC hdc;
792339b9 296 SelectInHDC selectFont(hdc, (HFONT)GetHFONT());
9bd26720
VZ
297
298 UINT otmSize = GetOutlineTextMetrics(hdc, 0, NULL);
299 if ( !otmSize )
300 {
301 wxLogLastError("GetOutlineTextMetrics(NULL)");
302 return wxString();
303 }
304
305 OUTLINETEXTMETRIC * const
306 otm = static_cast<OUTLINETEXTMETRIC *>(malloc(otmSize));
307 wxON_BLOCK_EXIT1( free, otm );
308
309 otm->otmSize = otmSize;
310 if ( !GetOutlineTextMetrics(hdc, otmSize, otm) )
311 {
312 wxLogLastError("GetOutlineTextMetrics()");
313 return wxString();
314 }
315
d395f181
VZ
316 // in spite of its type, the otmpFamilyName field of OUTLINETEXTMETRIC
317 // gives an offset in _bytes_ of the face (not family!) name from the
318 // struct start while the name itself is an array of TCHARs
319 //
320 // FWIW otmpFaceName contains the same thing as otmpFamilyName followed
321 // by a possible " Italic" or " Bold" or something else suffix
9bd26720 322 return reinterpret_cast<wxChar *>(otm) +
d395f181 323 wxPtrToUInt(otm->otmpFamilyName)/sizeof(wxChar);
9bd26720
VZ
324 }
325
0572fce8 326 // are we using m_nativeFontInfo.lf.lfHeight for point size or pixel size?
df898907 327 bool m_sizeUsingPixels;
0c5d3e1c 328
8e34db1d 329 // Windows font handle, created on demand in GetHFONT()
df898907 330 HFONT m_hFont;
789034a0 331
09fcd889
VZ
332 // Native font info
333 wxNativeFontInfo m_nativeFontInfo;
0c5d3e1c
VZ
334};
335
68c95704 336#define M_FONTDATA ((wxFontRefData*)m_refData)
873fd4af 337
0c5d3e1c
VZ
338// ============================================================================
339// implementation
340// ============================================================================
341
342// ----------------------------------------------------------------------------
343// wxFontRefData
344// ----------------------------------------------------------------------------
345
346void wxFontRefData::Init(int pointSize,
544229d1
VZ
347 const wxSize& pixelSize,
348 bool sizeUsingPixels,
0c14b6c3
FM
349 wxFontFamily family,
350 wxFontStyle style,
351 wxFontWeight weight,
0c5d3e1c 352 bool underlined,
c7a49742 353 bool strikethrough,
0c5d3e1c
VZ
354 const wxString& faceName,
355 wxFontEncoding encoding)
b823f5a1 356{
0572fce8
VZ
357 m_hFont = NULL;
358
544229d1 359 m_sizeUsingPixels = sizeUsingPixels;
0572fce8
VZ
360 if ( m_sizeUsingPixels )
361 SetPixelSize(pixelSize);
362 else
363 SetPointSize(pointSize);
df898907 364
0572fce8
VZ
365 SetStyle(style);
366 SetWeight(weight);
367 SetUnderlined(underlined);
c7a49742 368 SetStrikethrough(strikethrough);
0c5d3e1c 369
0572fce8
VZ
370 // set the family/facename
371 SetFamily(family);
372 if ( !faceName.empty() )
373 SetFaceName(faceName);
789034a0 374
0572fce8
VZ
375 // deal with encoding now (it may override the font family and facename
376 // so do it after setting them)
377 SetEncoding(encoding);
09fcd889
VZ
378}
379
04ef50df 380void wxFontRefData::Init(const wxNativeFontInfo& info, WXHFONT hFont)
09fcd889 381{
04ef50df
JS
382 // hFont may be zero, or it be passed in case we really want to
383 // use the exact font created in the underlying system
384 // (for example where we can't guarantee conversion from HFONT
385 // to LOGFONT back to HFONT)
8e34db1d 386 m_hFont = (HFONT)hFont;
09fcd889 387 m_nativeFontInfo = info;
d014871d 388
df898907 389 // TODO: m_sizeUsingPixels?
b823f5a1
JS
390}
391
0c5d3e1c 392wxFontRefData::~wxFontRefData()
a9249b2e
VZ
393{
394 Free();
395}
396
df898907 397bool wxFontRefData::Alloc()
a9249b2e 398{
8e34db1d
VZ
399 m_hFont = ::CreateFontIndirect(&m_nativeFontInfo.lf);
400 if ( !m_hFont )
a9249b2e
VZ
401 {
402 wxLogLastError(wxT("CreateFont"));
cbe874bd 403 return false;
a9249b2e
VZ
404 }
405
cbe874bd 406 return true;
a9249b2e
VZ
407}
408
409void wxFontRefData::Free()
2bda0e17 410{
b9b3ccd9 411 if ( m_hFont )
0c5d3e1c 412 {
8e34db1d 413 if ( !::DeleteObject(m_hFont) )
0c5d3e1c 414 {
f6bcfd97 415 wxLogLastError(wxT("DeleteObject(font)"));
0c5d3e1c 416 }
a9249b2e
VZ
417
418 m_hFont = 0;
0c5d3e1c 419 }
2bda0e17
KB
420}
421
09fcd889
VZ
422// ----------------------------------------------------------------------------
423// wxNativeFontInfo
424// ----------------------------------------------------------------------------
425
a9249b2e
VZ
426void wxNativeFontInfo::Init()
427{
428 wxZeroMemory(lf);
64c1effe 429
66160760
VZ
430 // we get better font quality if we use PROOF_QUALITY instead of
431 // DEFAULT_QUALITY but some fonts (e.g. "Terminal 6pt") are not available
432 // then so we allow to set a global option to choose between quality and
433 // wider font selection
99ae6124
WS
434#ifdef __WXWINCE__
435 lf.lfQuality = CLEARTYPE_QUALITY;
436#else
df898907 437 lf.lfQuality = wxSystemOptions::GetOptionInt("msw.font.no-proof-quality")
66160760
VZ
438 ? DEFAULT_QUALITY
439 : PROOF_QUALITY;
99ae6124 440#endif
a9249b2e
VZ
441}
442
443int wxNativeFontInfo::GetPointSize() const
444{
7936354d
VZ
445 // FIXME: using the screen here results in incorrect font size calculation
446 // for printing!
a9249b2e
VZ
447 const int ppInch = ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY);
448
ee8fd6b1
VZ
449 // BC++ 2007 doesn't provide abs(long) overload, hence the cast
450 return (int) (((72.0*abs((int)lf.lfHeight)) / (double) ppInch) + 0.5);
a9249b2e
VZ
451}
452
544229d1
VZ
453wxSize wxNativeFontInfo::GetPixelSize() const
454{
455 wxSize ret;
cde96954 456 ret.SetHeight(abs((int)lf.lfHeight));
544229d1
VZ
457 ret.SetWidth(lf.lfWidth);
458 return ret;
459}
460
a9249b2e
VZ
461wxFontStyle wxNativeFontInfo::GetStyle() const
462{
463 return lf.lfItalic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL;
464}
465
466wxFontWeight wxNativeFontInfo::GetWeight() const
467{
468 if ( lf.lfWeight <= 300 )
469 return wxFONTWEIGHT_LIGHT;
470
471 if ( lf.lfWeight >= 600 )
472 return wxFONTWEIGHT_BOLD;
473
474 return wxFONTWEIGHT_NORMAL;
475}
476
477bool wxNativeFontInfo::GetUnderlined() const
478{
479 return lf.lfUnderline != 0;
480}
481
c7a49742
VZ
482bool wxNativeFontInfo::GetStrikethrough() const
483{
484 return lf.lfStrikeOut != 0;
485}
486
a9249b2e
VZ
487wxString wxNativeFontInfo::GetFaceName() const
488{
489 return lf.lfFaceName;
490}
491
36e2bb4e
RD
492wxFontFamily wxNativeFontInfo::GetFamily() const
493{
9cf8de4c 494 wxFontFamily family;
36e2bb4e 495
9cf8de4c
VZ
496 // extract family from pitch-and-family
497 switch ( lf.lfPitchAndFamily & ~PITCH_MASK )
36e2bb4e 498 {
df898907
FM
499 case 0:
500 family = wxFONTFAMILY_UNKNOWN;
501 break;
502
36e2bb4e 503 case FF_ROMAN:
9cf8de4c 504 family = wxFONTFAMILY_ROMAN;
36e2bb4e
RD
505 break;
506
507 case FF_SWISS:
9cf8de4c 508 family = wxFONTFAMILY_SWISS;
36e2bb4e
RD
509 break;
510
511 case FF_SCRIPT:
9cf8de4c 512 family = wxFONTFAMILY_SCRIPT;
36e2bb4e
RD
513 break;
514
515 case FF_MODERN:
9cf8de4c 516 family = wxFONTFAMILY_MODERN;
36e2bb4e
RD
517 break;
518
519 case FF_DECORATIVE:
9cf8de4c 520 family = wxFONTFAMILY_DECORATIVE;
36e2bb4e 521 break;
df898907
FM
522
523 default:
524 wxFAIL_MSG( "unknown LOGFONT::lfFamily value" );
525 family = wxFONTFAMILY_UNKNOWN;
526 // just to avoid a warning
36e2bb4e 527 }
9cf8de4c
VZ
528
529 return family;
36e2bb4e
RD
530}
531
a9249b2e
VZ
532wxFontEncoding wxNativeFontInfo::GetEncoding() const
533{
534 return wxGetFontEncFromCharSet(lf.lfCharSet);
535}
536
537void wxNativeFontInfo::SetPointSize(int pointsize)
538{
7936354d
VZ
539 // FIXME: using the screen here results in incorrect font size calculation
540 // for printing!
a9249b2e
VZ
541 const int ppInch = ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY);
542
543 lf.lfHeight = -(int)((pointsize*((double)ppInch)/72.0) + 0.5);
544}
545
544229d1
VZ
546void wxNativeFontInfo::SetPixelSize(const wxSize& pixelSize)
547{
5414d62e
VZ
548 // MSW accepts both positive and negative heights here but they mean
549 // different things: positive specifies the cell height while negative
550 // specifies the character height. We used to just pass the value to MSW
551 // unchanged but changed the behaviour for positive values in 2.9.1 to
552 // match other ports and, more importantly, the expected behaviour. So now
553 // passing the negative height doesn't make sense at all any more but we
554 // still accept it for compatibility with the existing code which worked
555 // around the wrong interpretation of the height argument in older wxMSW
556 // versions by passing a negative value explicitly itself.
557 lf.lfHeight = -abs(pixelSize.GetHeight());
544229d1
VZ
558 lf.lfWidth = pixelSize.GetWidth();
559}
560
a9249b2e
VZ
561void wxNativeFontInfo::SetStyle(wxFontStyle style)
562{
563 switch ( style )
564 {
565 default:
df898907 566 wxFAIL_MSG( "unknown font style" );
a9249b2e
VZ
567 // fall through
568
569 case wxFONTSTYLE_NORMAL:
a38d0585 570 lf.lfItalic = FALSE;
a9249b2e
VZ
571 break;
572
573 case wxFONTSTYLE_ITALIC:
574 case wxFONTSTYLE_SLANT:
575 lf.lfItalic = TRUE;
576 break;
577 }
578}
579
580void wxNativeFontInfo::SetWeight(wxFontWeight weight)
581{
582 switch ( weight )
583 {
584 default:
df898907 585 wxFAIL_MSG( "unknown font weight" );
a9249b2e
VZ
586 // fall through
587
588 case wxFONTWEIGHT_NORMAL:
589 lf.lfWeight = FW_NORMAL;
590 break;
591
592 case wxFONTWEIGHT_LIGHT:
593 lf.lfWeight = FW_LIGHT;
594 break;
595
596 case wxFONTWEIGHT_BOLD:
597 lf.lfWeight = FW_BOLD;
598 break;
599 }
600}
601
602void wxNativeFontInfo::SetUnderlined(bool underlined)
603{
604 lf.lfUnderline = underlined;
605}
606
c7a49742
VZ
607void wxNativeFontInfo::SetStrikethrough(bool strikethrough)
608{
609 lf.lfStrikeOut = strikethrough;
610}
611
85ab460e 612bool wxNativeFontInfo::SetFaceName(const wxString& facename)
a9249b2e 613{
64accea5 614 wxStrlcpy(lf.lfFaceName, facename.c_str(), WXSIZEOF(lf.lfFaceName));
85ab460e 615 return true;
a9249b2e
VZ
616}
617
7936354d
VZ
618void wxNativeFontInfo::SetFamily(wxFontFamily family)
619{
76d88590 620 BYTE ff_family = FF_DONTCARE;
7936354d
VZ
621
622 switch ( family )
623 {
df898907 624 case wxFONTFAMILY_SCRIPT:
7936354d 625 ff_family = FF_SCRIPT;
7936354d
VZ
626 break;
627
df898907 628 case wxFONTFAMILY_DECORATIVE:
7936354d 629 ff_family = FF_DECORATIVE;
7936354d
VZ
630 break;
631
df898907 632 case wxFONTFAMILY_ROMAN:
7936354d 633 ff_family = FF_ROMAN;
7936354d
VZ
634 break;
635
df898907
FM
636 case wxFONTFAMILY_TELETYPE:
637 case wxFONTFAMILY_MODERN:
7936354d 638 ff_family = FF_MODERN;
7936354d
VZ
639 break;
640
df898907 641 case wxFONTFAMILY_SWISS:
df898907 642 case wxFONTFAMILY_DEFAULT:
7936354d 643 ff_family = FF_SWISS;
76d88590 644 break;
a4a0bff1
VZ
645
646 case wxFONTFAMILY_UNKNOWN:
647 wxFAIL_MSG( "invalid font family" );
648 return;
7936354d
VZ
649 }
650
76d88590
VZ
651 wxCHECK_RET( ff_family != FF_DONTCARE, "unknown wxFontFamily" );
652
5c519b6c 653 lf.lfPitchAndFamily = (BYTE)(DEFAULT_PITCH) | ff_family;
7936354d 654
060c4f90
FM
655 // reset the facename so that CreateFontIndirect() will automatically choose a
656 // face name based only on the font family.
657 lf.lfFaceName[0] = '\0';
7936354d
VZ
658}
659
a9249b2e
VZ
660void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding)
661{
662 wxNativeEncodingInfo info;
663 if ( !wxGetNativeFontEncoding(encoding, &info) )
664 {
bff67a6a 665#if wxUSE_FONTMAP
142b3bc2 666 if ( wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
e7e52b6d
VZ
667 {
668 if ( !info.facename.empty() )
669 {
670 // if we have this encoding only in some particular facename, use
671 // the facename - it is better to show the correct characters in a
672 // wrong facename than unreadable text in a correct one
673 SetFaceName(info.facename);
674 }
675 }
676 else
bff67a6a
VZ
677#endif // wxUSE_FONTMAP
678 {
679 // unsupported encoding, replace with the default
9cf8de4c 680 info.charset = DEFAULT_CHARSET;
bff67a6a 681 }
a9249b2e
VZ
682 }
683
373a5fb3 684 lf.lfCharSet = (BYTE)info.charset;
a9249b2e
VZ
685}
686
09fcd889
VZ
687bool wxNativeFontInfo::FromString(const wxString& s)
688{
689 long l;
690
d508a9d9 691 wxStringTokenizer tokenizer(s, wxS(";"), wxTOKEN_RET_EMPTY_ALL);
09fcd889 692
a9249b2e 693 // first the version
09fcd889 694 wxString token = tokenizer.GetNextToken();
df898907 695 if ( token != wxS('0') )
cbe874bd 696 return false;
09fcd889
VZ
697
698 token = tokenizer.GetNextToken();
699 if ( !token.ToLong(&l) )
cbe874bd 700 return false;
09fcd889
VZ
701 lf.lfHeight = l;
702
703 token = tokenizer.GetNextToken();
704 if ( !token.ToLong(&l) )
cbe874bd 705 return false;
09fcd889
VZ
706 lf.lfWidth = l;
707
708 token = tokenizer.GetNextToken();
709 if ( !token.ToLong(&l) )
cbe874bd 710 return false;
09fcd889
VZ
711 lf.lfEscapement = l;
712
713 token = tokenizer.GetNextToken();
714 if ( !token.ToLong(&l) )
cbe874bd 715 return false;
09fcd889
VZ
716 lf.lfOrientation = l;
717
718 token = tokenizer.GetNextToken();
719 if ( !token.ToLong(&l) )
cbe874bd 720 return false;
09fcd889
VZ
721 lf.lfWeight = l;
722
723 token = tokenizer.GetNextToken();
724 if ( !token.ToLong(&l) )
cbe874bd 725 return false;
33ac7e6f 726 lf.lfItalic = (BYTE)l;
09fcd889
VZ
727
728 token = tokenizer.GetNextToken();
729 if ( !token.ToLong(&l) )
cbe874bd 730 return false;
33ac7e6f 731 lf.lfUnderline = (BYTE)l;
09fcd889
VZ
732
733 token = tokenizer.GetNextToken();
734 if ( !token.ToLong(&l) )
cbe874bd 735 return false;
33ac7e6f 736 lf.lfStrikeOut = (BYTE)l;
09fcd889
VZ
737
738 token = tokenizer.GetNextToken();
739 if ( !token.ToLong(&l) )
cbe874bd 740 return false;
33ac7e6f 741 lf.lfCharSet = (BYTE)l;
09fcd889
VZ
742
743 token = tokenizer.GetNextToken();
744 if ( !token.ToLong(&l) )
cbe874bd 745 return false;
33ac7e6f 746 lf.lfOutPrecision = (BYTE)l;
09fcd889
VZ
747
748 token = tokenizer.GetNextToken();
749 if ( !token.ToLong(&l) )
cbe874bd 750 return false;
33ac7e6f 751 lf.lfClipPrecision = (BYTE)l;
09fcd889
VZ
752
753 token = tokenizer.GetNextToken();
754 if ( !token.ToLong(&l) )
cbe874bd 755 return false;
33ac7e6f 756 lf.lfQuality = (BYTE)l;
09fcd889
VZ
757
758 token = tokenizer.GetNextToken();
759 if ( !token.ToLong(&l) )
cbe874bd 760 return false;
33ac7e6f 761 lf.lfPitchAndFamily = (BYTE)l;
09fcd889 762
d508a9d9 763 if ( !tokenizer.HasMoreTokens() )
cbe874bd 764 return false;
d508a9d9
VZ
765
766 // the face name may be empty
3515776e 767 SetFaceName(tokenizer.GetNextToken());
09fcd889 768
cbe874bd 769 return true;
09fcd889
VZ
770}
771
772wxString wxNativeFontInfo::ToString() const
773{
774 wxString s;
775
df898907 776 s.Printf(wxS("%d;%ld;%ld;%ld;%ld;%ld;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
09fcd889
VZ
777 0, // version, in case we want to change the format later
778 lf.lfHeight,
779 lf.lfWidth,
780 lf.lfEscapement,
781 lf.lfOrientation,
782 lf.lfWeight,
783 lf.lfItalic,
784 lf.lfUnderline,
785 lf.lfStrikeOut,
786 lf.lfCharSet,
787 lf.lfOutPrecision,
788 lf.lfClipPrecision,
789 lf.lfQuality,
790 lf.lfPitchAndFamily,
d508a9d9 791 lf.lfFaceName);
09fcd889
VZ
792
793 return s;
794}
795
0c5d3e1c
VZ
796// ----------------------------------------------------------------------------
797// wxFont
798// ----------------------------------------------------------------------------
799
d014871d
FM
800wxFont::wxFont(const wxString& fontdesc)
801{
802 wxNativeFontInfo info;
803 if ( info.FromString(fontdesc) )
804 (void)Create(info);
805}
806
0634700a
VZ
807wxFont::wxFont(int pointSize,
808 wxFontFamily family,
809 int flags,
810 const wxString& face,
811 wxFontEncoding encoding)
812{
813 m_refData = new wxFontRefData(pointSize, wxDefaultSize, false,
814 family,
815 GetStyleFromFlags(flags),
816 GetWeightFromFlags(flags),
817 GetUnderlinedFromFlags(flags),
c7a49742 818 false, face, encoding);
0634700a
VZ
819}
820
04ef50df 821bool wxFont::Create(const wxNativeFontInfo& info, WXHFONT hFont)
76e23cdb 822{
09fcd889
VZ
823 UnRef();
824
04ef50df 825 m_refData = new wxFontRefData(info, hFont);
09fcd889 826
adbd3cbc 827 return RealizeResource();
76e23cdb
VZ
828}
829
df455719
VZ
830bool wxFont::DoCreate(int pointSize,
831 const wxSize& pixelSize,
832 bool sizeUsingPixels,
0c14b6c3
FM
833 wxFontFamily family,
834 wxFontStyle style,
835 wxFontWeight weight,
df455719
VZ
836 bool underlined,
837 const wxString& faceName,
838 wxFontEncoding encoding)
2bda0e17 839{
0c5d3e1c 840 UnRef();
3ca6a5f0
BP
841
842 // wxDEFAULT is a valid value for the font size too so we must treat it
843 // specially here (otherwise the size would be 70 == wxDEFAULT value)
d180df5c 844 if ( pointSize == wxDEFAULT || pointSize == -1 )
a9249b2e
VZ
845 {
846 pointSize = wxNORMAL_FONT->GetPointSize();
847 }
3ca6a5f0 848
544229d1
VZ
849 m_refData = new wxFontRefData(pointSize, pixelSize, sizeUsingPixels,
850 family, style, weight,
c7a49742 851 underlined, false, faceName, encoding);
2bda0e17 852
adbd3cbc 853 return RealizeResource();
2bda0e17
KB
854}
855
856wxFont::~wxFont()
857{
2bda0e17
KB
858}
859
0c5d3e1c
VZ
860// ----------------------------------------------------------------------------
861// real implementation
862// ----------------------------------------------------------------------------
863
8f884a0d 864wxGDIRefData *wxFont::CreateGDIRefData() const
f030b28c
VZ
865{
866 return new wxFontRefData();
867}
868
8f884a0d 869wxGDIRefData *wxFont::CloneGDIRefData(const wxGDIRefData *data) const
f030b28c 870{
5c33522f 871 return new wxFontRefData(*static_cast<const wxFontRefData *>(data));
f030b28c
VZ
872}
873
0c5d3e1c 874bool wxFont::RealizeResource()
2bda0e17 875{
d014871d 876 // NOTE: the GetHFONT() call automatically triggers a reallocation of
0572fce8 877 // the HFONT if necessary (will do nothing if we already have the resource);
d014871d
FM
878 // it returns NULL only if there is a failure in wxFontRefData::Alloc()...
879 return GetHFONT() != NULL;
2bda0e17
KB
880}
881
33ac7e6f 882bool wxFont::FreeResource(bool WXUNUSED(force))
2bda0e17 883{
d014871d 884 if ( !M_FONTDATA )
adbd3cbc 885 return false;
0c5d3e1c 886
adbd3cbc 887 M_FONTDATA->Free();
a9249b2e 888
adbd3cbc 889 return true;
2bda0e17
KB
890}
891
2b5f62a0 892WXHANDLE wxFont::GetResourceHandle() const
f6bcfd97 893{
2b5f62a0 894 return (WXHANDLE)GetHFONT();
f6bcfd97
BP
895}
896
897WXHFONT wxFont::GetHFONT() const
2bda0e17 898{
d014871d
FM
899 // NOTE: wxFontRefData::GetHFONT() will automatically call
900 // wxFontRefData::Alloc() if necessary
df898907 901 return M_FONTDATA ? M_FONTDATA->GetHFONT() : 0;
2bda0e17
KB
902}
903
e90babdf 904bool wxFont::IsFree() const
2bda0e17 905{
8e34db1d 906 return M_FONTDATA && !M_FONTDATA->HasHFONT();
adbd3cbc
VZ
907}
908
0c5d3e1c
VZ
909// ----------------------------------------------------------------------------
910// change font attribute: we recreate font when doing it
911// ----------------------------------------------------------------------------
912
debe6624 913void wxFont::SetPointSize(int pointSize)
2bda0e17 914{
f030b28c 915 AllocExclusive();
b823f5a1 916
8e34db1d 917 M_FONTDATA->Free();
a9249b2e 918 M_FONTDATA->SetPointSize(pointSize);
2bda0e17
KB
919}
920
544229d1
VZ
921void wxFont::SetPixelSize(const wxSize& pixelSize)
922{
f030b28c 923 AllocExclusive();
544229d1
VZ
924
925 M_FONTDATA->SetPixelSize(pixelSize);
544229d1
VZ
926}
927
0c14b6c3 928void wxFont::SetFamily(wxFontFamily family)
2bda0e17 929{
f030b28c 930 AllocExclusive();
b823f5a1 931
a9249b2e 932 M_FONTDATA->SetFamily(family);
2bda0e17
KB
933}
934
0c14b6c3 935void wxFont::SetStyle(wxFontStyle style)
2bda0e17 936{
f030b28c 937 AllocExclusive();
b823f5a1 938
a9249b2e 939 M_FONTDATA->SetStyle(style);
2bda0e17
KB
940}
941
0c14b6c3 942void wxFont::SetWeight(wxFontWeight weight)
2bda0e17 943{
f030b28c 944 AllocExclusive();
b823f5a1 945
a9249b2e 946 M_FONTDATA->SetWeight(weight);
2bda0e17
KB
947}
948
85ab460e 949bool wxFont::SetFaceName(const wxString& faceName)
2bda0e17 950{
f030b28c 951 AllocExclusive();
b823f5a1 952
8e34db1d
VZ
953 if ( !M_FONTDATA->SetFaceName(faceName) )
954 return false;
85ab460e
VZ
955
956 // NB: using win32's GetObject() API on M_FONTDATA->GetHFONT()
957 // to retrieve a LOGFONT and then compare lf.lfFaceName
958 // with given facename is not reliable at all:
959 // Windows copies the facename given to ::CreateFontIndirect()
960 // without any validity check.
961 // Thus we use wxFontBase::SetFaceName to check if facename
962 // is valid...
8e34db1d 963 return wxFontBase::SetFaceName(faceName);
2bda0e17
KB
964}
965
debe6624 966void wxFont::SetUnderlined(bool underlined)
2bda0e17 967{
f030b28c 968 AllocExclusive();
b823f5a1 969
a9249b2e 970 M_FONTDATA->SetUnderlined(underlined);
2bda0e17
KB
971}
972
c7a49742
VZ
973void wxFont::SetStrikethrough(bool strikethrough)
974{
975 AllocExclusive();
976
977 M_FONTDATA->SetStrikethrough(strikethrough);
978}
979
0c5d3e1c 980void wxFont::SetEncoding(wxFontEncoding encoding)
2bda0e17 981{
f030b28c 982 AllocExclusive();
0c5d3e1c 983
a9249b2e 984 M_FONTDATA->SetEncoding(encoding);
09fcd889
VZ
985}
986
9045ad9d 987void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo& info)
09fcd889 988{
f030b28c 989 AllocExclusive();
09fcd889 990
8e34db1d 991 M_FONTDATA->SetNativeFontInfo(info);
0c5d3e1c
VZ
992}
993
994// ----------------------------------------------------------------------------
995// accessors
996// ----------------------------------------------------------------------------
997
998int wxFont::GetPointSize() const
999{
d014871d 1000 wxCHECK_MSG( IsOk(), 0, wxT("invalid font") );
789034a0 1001
a9249b2e 1002 return M_FONTDATA->GetPointSize();
0c5d3e1c
VZ
1003}
1004
544229d1
VZ
1005wxSize wxFont::GetPixelSize() const
1006{
d014871d 1007 wxCHECK_MSG( IsOk(), wxDefaultSize, wxT("invalid font") );
68585e17 1008
544229d1
VZ
1009 return M_FONTDATA->GetPixelSize();
1010}
1011
1012bool wxFont::IsUsingSizeInPixels() const
1013{
d014871d 1014 wxCHECK_MSG( IsOk(), 0, wxT("invalid font") );
544229d1
VZ
1015
1016 return M_FONTDATA->IsUsingSizeInPixels();
1017}
1018
59b7da02 1019wxFontFamily wxFont::DoGetFamily() const
0c5d3e1c 1020{
a9249b2e 1021 return M_FONTDATA->GetFamily();
2bda0e17
KB
1022}
1023
0c14b6c3 1024wxFontStyle wxFont::GetStyle() const
2bda0e17 1025{
d014871d 1026 wxCHECK_MSG( IsOk(), wxFONTSTYLE_MAX, wxT("invalid font") );
789034a0 1027
a9249b2e 1028 return M_FONTDATA->GetStyle();
2bda0e17
KB
1029}
1030
0c14b6c3 1031wxFontWeight wxFont::GetWeight() const
2bda0e17 1032{
d014871d 1033 wxCHECK_MSG( IsOk(), wxFONTWEIGHT_MAX, wxT("invalid font") );
789034a0 1034
a9249b2e 1035 return M_FONTDATA->GetWeight();
2bda0e17
KB
1036}
1037
0c5d3e1c
VZ
1038bool wxFont::GetUnderlined() const
1039{
d014871d 1040 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
789034a0 1041
a9249b2e 1042 return M_FONTDATA->GetUnderlined();
0c5d3e1c
VZ
1043}
1044
c7a49742
VZ
1045bool wxFont::GetStrikethrough() const
1046{
1047 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
1048
1049 return M_FONTDATA->GetStrikethrough();
1050}
1051
0c5d3e1c
VZ
1052wxString wxFont::GetFaceName() const
1053{
d014871d 1054 wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") );
789034a0 1055
a9249b2e 1056 return M_FONTDATA->GetFaceName();
0c5d3e1c
VZ
1057}
1058
1059wxFontEncoding wxFont::GetEncoding() const
1060{
d014871d 1061 wxCHECK_MSG( IsOk(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
789034a0 1062
a9249b2e 1063 return M_FONTDATA->GetEncoding();
0c5d3e1c 1064}
a1d58ddc 1065
3bf5a59b 1066const wxNativeFontInfo *wxFont::GetNativeFontInfo() const
1e6feb95 1067{
7c6e85dc 1068 return IsOk() ? &(M_FONTDATA->GetNativeFontInfo()) : NULL;
09fcd889
VZ
1069}
1070
9cf8de4c
VZ
1071bool wxFont::IsFixedWidth() const
1072{
d014871d
FM
1073 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
1074
cd49ac33
VZ
1075 // LOGFONT doesn't contain the correct pitch information so we need to call
1076 // GetTextMetrics() to get it
1077 ScreenHDC hdc;
1078 SelectInHDC selectFont(hdc, M_FONTDATA->GetHFONT());
9cf8de4c 1079
cd49ac33
VZ
1080 TEXTMETRIC tm;
1081 if ( !::GetTextMetrics(hdc, &tm) )
1082 {
1083 wxLogLastError(wxT("GetTextMetrics"));
1084 return false;
1085 }
1086
1087 // Quoting MSDN description of TMPF_FIXED_PITCH: "Note very carefully that
1088 // those meanings are the opposite of what the constant name implies."
1089 return !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
9cf8de4c 1090}