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