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