]> git.saurik.com Git - wxWidgets.git/blame - src/msw/font.cpp
Correctly parse times without seconds in wxDateTime::ParseTime().
[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;
7936354d
VZ
666 }
667
76d88590
VZ
668 wxCHECK_RET( ff_family != FF_DONTCARE, "unknown wxFontFamily" );
669
5c519b6c 670 lf.lfPitchAndFamily = (BYTE)(DEFAULT_PITCH) | ff_family;
7936354d 671
060c4f90
FM
672 // reset the facename so that CreateFontIndirect() will automatically choose a
673 // face name based only on the font family.
674 lf.lfFaceName[0] = '\0';
7936354d
VZ
675}
676
a9249b2e
VZ
677void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding)
678{
679 wxNativeEncodingInfo info;
680 if ( !wxGetNativeFontEncoding(encoding, &info) )
681 {
bff67a6a 682#if wxUSE_FONTMAP
142b3bc2 683 if ( wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
e7e52b6d
VZ
684 {
685 if ( !info.facename.empty() )
686 {
687 // if we have this encoding only in some particular facename, use
688 // the facename - it is better to show the correct characters in a
689 // wrong facename than unreadable text in a correct one
690 SetFaceName(info.facename);
691 }
692 }
693 else
bff67a6a
VZ
694#endif // wxUSE_FONTMAP
695 {
696 // unsupported encoding, replace with the default
9cf8de4c 697 info.charset = DEFAULT_CHARSET;
bff67a6a 698 }
a9249b2e
VZ
699 }
700
373a5fb3 701 lf.lfCharSet = (BYTE)info.charset;
a9249b2e
VZ
702}
703
09fcd889
VZ
704bool wxNativeFontInfo::FromString(const wxString& s)
705{
706 long l;
707
d508a9d9 708 wxStringTokenizer tokenizer(s, wxS(";"), wxTOKEN_RET_EMPTY_ALL);
09fcd889 709
a9249b2e 710 // first the version
09fcd889 711 wxString token = tokenizer.GetNextToken();
df898907 712 if ( token != wxS('0') )
cbe874bd 713 return false;
09fcd889
VZ
714
715 token = tokenizer.GetNextToken();
716 if ( !token.ToLong(&l) )
cbe874bd 717 return false;
09fcd889
VZ
718 lf.lfHeight = l;
719
720 token = tokenizer.GetNextToken();
721 if ( !token.ToLong(&l) )
cbe874bd 722 return false;
09fcd889
VZ
723 lf.lfWidth = l;
724
725 token = tokenizer.GetNextToken();
726 if ( !token.ToLong(&l) )
cbe874bd 727 return false;
09fcd889
VZ
728 lf.lfEscapement = l;
729
730 token = tokenizer.GetNextToken();
731 if ( !token.ToLong(&l) )
cbe874bd 732 return false;
09fcd889
VZ
733 lf.lfOrientation = l;
734
735 token = tokenizer.GetNextToken();
736 if ( !token.ToLong(&l) )
cbe874bd 737 return false;
09fcd889
VZ
738 lf.lfWeight = l;
739
740 token = tokenizer.GetNextToken();
741 if ( !token.ToLong(&l) )
cbe874bd 742 return false;
33ac7e6f 743 lf.lfItalic = (BYTE)l;
09fcd889
VZ
744
745 token = tokenizer.GetNextToken();
746 if ( !token.ToLong(&l) )
cbe874bd 747 return false;
33ac7e6f 748 lf.lfUnderline = (BYTE)l;
09fcd889
VZ
749
750 token = tokenizer.GetNextToken();
751 if ( !token.ToLong(&l) )
cbe874bd 752 return false;
33ac7e6f 753 lf.lfStrikeOut = (BYTE)l;
09fcd889
VZ
754
755 token = tokenizer.GetNextToken();
756 if ( !token.ToLong(&l) )
cbe874bd 757 return false;
33ac7e6f 758 lf.lfCharSet = (BYTE)l;
09fcd889
VZ
759
760 token = tokenizer.GetNextToken();
761 if ( !token.ToLong(&l) )
cbe874bd 762 return false;
33ac7e6f 763 lf.lfOutPrecision = (BYTE)l;
09fcd889
VZ
764
765 token = tokenizer.GetNextToken();
766 if ( !token.ToLong(&l) )
cbe874bd 767 return false;
33ac7e6f 768 lf.lfClipPrecision = (BYTE)l;
09fcd889
VZ
769
770 token = tokenizer.GetNextToken();
771 if ( !token.ToLong(&l) )
cbe874bd 772 return false;
33ac7e6f 773 lf.lfQuality = (BYTE)l;
09fcd889
VZ
774
775 token = tokenizer.GetNextToken();
776 if ( !token.ToLong(&l) )
cbe874bd 777 return false;
33ac7e6f 778 lf.lfPitchAndFamily = (BYTE)l;
09fcd889 779
d508a9d9 780 if ( !tokenizer.HasMoreTokens() )
cbe874bd 781 return false;
d508a9d9
VZ
782
783 // the face name may be empty
3515776e 784 SetFaceName(tokenizer.GetNextToken());
09fcd889 785
cbe874bd 786 return true;
09fcd889
VZ
787}
788
789wxString wxNativeFontInfo::ToString() const
790{
791 wxString s;
792
df898907 793 s.Printf(wxS("%d;%ld;%ld;%ld;%ld;%ld;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
09fcd889
VZ
794 0, // version, in case we want to change the format later
795 lf.lfHeight,
796 lf.lfWidth,
797 lf.lfEscapement,
798 lf.lfOrientation,
799 lf.lfWeight,
800 lf.lfItalic,
801 lf.lfUnderline,
802 lf.lfStrikeOut,
803 lf.lfCharSet,
804 lf.lfOutPrecision,
805 lf.lfClipPrecision,
806 lf.lfQuality,
807 lf.lfPitchAndFamily,
d508a9d9 808 lf.lfFaceName);
09fcd889
VZ
809
810 return s;
811}
812
0c5d3e1c
VZ
813// ----------------------------------------------------------------------------
814// wxFont
815// ----------------------------------------------------------------------------
816
d014871d
FM
817wxFont::wxFont(const wxString& fontdesc)
818{
819 wxNativeFontInfo info;
820 if ( info.FromString(fontdesc) )
821 (void)Create(info);
822}
823
04ef50df 824bool wxFont::Create(const wxNativeFontInfo& info, WXHFONT hFont)
76e23cdb 825{
09fcd889
VZ
826 UnRef();
827
04ef50df 828 m_refData = new wxFontRefData(info, hFont);
09fcd889 829
adbd3cbc 830 return RealizeResource();
76e23cdb
VZ
831}
832
df455719
VZ
833bool wxFont::DoCreate(int pointSize,
834 const wxSize& pixelSize,
835 bool sizeUsingPixels,
0c14b6c3
FM
836 wxFontFamily family,
837 wxFontStyle style,
838 wxFontWeight weight,
df455719
VZ
839 bool underlined,
840 const wxString& faceName,
841 wxFontEncoding encoding)
2bda0e17 842{
0c5d3e1c 843 UnRef();
3ca6a5f0
BP
844
845 // wxDEFAULT is a valid value for the font size too so we must treat it
846 // specially here (otherwise the size would be 70 == wxDEFAULT value)
847 if ( pointSize == wxDEFAULT )
a9249b2e
VZ
848 {
849 pointSize = wxNORMAL_FONT->GetPointSize();
850 }
3ca6a5f0 851
544229d1
VZ
852 m_refData = new wxFontRefData(pointSize, pixelSize, sizeUsingPixels,
853 family, style, weight,
0c5d3e1c 854 underlined, faceName, encoding);
2bda0e17 855
adbd3cbc 856 return RealizeResource();
2bda0e17
KB
857}
858
859wxFont::~wxFont()
860{
2bda0e17
KB
861}
862
0c5d3e1c
VZ
863// ----------------------------------------------------------------------------
864// real implementation
865// ----------------------------------------------------------------------------
866
8f884a0d 867wxGDIRefData *wxFont::CreateGDIRefData() const
f030b28c
VZ
868{
869 return new wxFontRefData();
870}
871
8f884a0d 872wxGDIRefData *wxFont::CloneGDIRefData(const wxGDIRefData *data) const
f030b28c 873{
5c33522f 874 return new wxFontRefData(*static_cast<const wxFontRefData *>(data));
f030b28c
VZ
875}
876
0c5d3e1c 877bool wxFont::RealizeResource()
2bda0e17 878{
d014871d 879 // NOTE: the GetHFONT() call automatically triggers a reallocation of
0572fce8 880 // the HFONT if necessary (will do nothing if we already have the resource);
d014871d
FM
881 // it returns NULL only if there is a failure in wxFontRefData::Alloc()...
882 return GetHFONT() != NULL;
2bda0e17
KB
883}
884
33ac7e6f 885bool wxFont::FreeResource(bool WXUNUSED(force))
2bda0e17 886{
d014871d 887 if ( !M_FONTDATA )
adbd3cbc 888 return false;
0c5d3e1c 889
adbd3cbc 890 M_FONTDATA->Free();
a9249b2e 891
adbd3cbc 892 return true;
2bda0e17
KB
893}
894
2b5f62a0 895WXHANDLE wxFont::GetResourceHandle() const
f6bcfd97 896{
2b5f62a0 897 return (WXHANDLE)GetHFONT();
f6bcfd97
BP
898}
899
900WXHFONT wxFont::GetHFONT() const
2bda0e17 901{
d014871d
FM
902 // NOTE: wxFontRefData::GetHFONT() will automatically call
903 // wxFontRefData::Alloc() if necessary
df898907 904 return M_FONTDATA ? M_FONTDATA->GetHFONT() : 0;
2bda0e17
KB
905}
906
e90babdf 907bool wxFont::IsFree() const
2bda0e17 908{
8e34db1d 909 return M_FONTDATA && !M_FONTDATA->HasHFONT();
adbd3cbc
VZ
910}
911
0c5d3e1c
VZ
912// ----------------------------------------------------------------------------
913// change font attribute: we recreate font when doing it
914// ----------------------------------------------------------------------------
915
debe6624 916void wxFont::SetPointSize(int pointSize)
2bda0e17 917{
f030b28c 918 AllocExclusive();
b823f5a1 919
8e34db1d 920 M_FONTDATA->Free();
a9249b2e 921 M_FONTDATA->SetPointSize(pointSize);
2bda0e17
KB
922}
923
544229d1
VZ
924void wxFont::SetPixelSize(const wxSize& pixelSize)
925{
f030b28c 926 AllocExclusive();
544229d1
VZ
927
928 M_FONTDATA->SetPixelSize(pixelSize);
544229d1
VZ
929}
930
0c14b6c3 931void wxFont::SetFamily(wxFontFamily family)
2bda0e17 932{
f030b28c 933 AllocExclusive();
b823f5a1 934
a9249b2e 935 M_FONTDATA->SetFamily(family);
2bda0e17
KB
936}
937
0c14b6c3 938void wxFont::SetStyle(wxFontStyle style)
2bda0e17 939{
f030b28c 940 AllocExclusive();
b823f5a1 941
a9249b2e 942 M_FONTDATA->SetStyle(style);
2bda0e17
KB
943}
944
0c14b6c3 945void wxFont::SetWeight(wxFontWeight weight)
2bda0e17 946{
f030b28c 947 AllocExclusive();
b823f5a1 948
a9249b2e 949 M_FONTDATA->SetWeight(weight);
2bda0e17
KB
950}
951
85ab460e 952bool wxFont::SetFaceName(const wxString& faceName)
2bda0e17 953{
f030b28c 954 AllocExclusive();
b823f5a1 955
8e34db1d
VZ
956 if ( !M_FONTDATA->SetFaceName(faceName) )
957 return false;
85ab460e
VZ
958
959 // NB: using win32's GetObject() API on M_FONTDATA->GetHFONT()
960 // to retrieve a LOGFONT and then compare lf.lfFaceName
961 // with given facename is not reliable at all:
962 // Windows copies the facename given to ::CreateFontIndirect()
963 // without any validity check.
964 // Thus we use wxFontBase::SetFaceName to check if facename
965 // is valid...
8e34db1d 966 return wxFontBase::SetFaceName(faceName);
2bda0e17
KB
967}
968
debe6624 969void wxFont::SetUnderlined(bool underlined)
2bda0e17 970{
f030b28c 971 AllocExclusive();
b823f5a1 972
a9249b2e 973 M_FONTDATA->SetUnderlined(underlined);
2bda0e17
KB
974}
975
0c5d3e1c 976void wxFont::SetEncoding(wxFontEncoding encoding)
2bda0e17 977{
f030b28c 978 AllocExclusive();
0c5d3e1c 979
a9249b2e 980 M_FONTDATA->SetEncoding(encoding);
09fcd889
VZ
981}
982
9045ad9d 983void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo& info)
09fcd889 984{
f030b28c 985 AllocExclusive();
09fcd889 986
8e34db1d 987 M_FONTDATA->SetNativeFontInfo(info);
0c5d3e1c
VZ
988}
989
990// ----------------------------------------------------------------------------
991// accessors
992// ----------------------------------------------------------------------------
993
994int wxFont::GetPointSize() const
995{
d014871d 996 wxCHECK_MSG( IsOk(), 0, wxT("invalid font") );
789034a0 997
a9249b2e 998 return M_FONTDATA->GetPointSize();
0c5d3e1c
VZ
999}
1000
544229d1
VZ
1001wxSize wxFont::GetPixelSize() const
1002{
d014871d 1003 wxCHECK_MSG( IsOk(), wxDefaultSize, wxT("invalid font") );
68585e17 1004
544229d1
VZ
1005 return M_FONTDATA->GetPixelSize();
1006}
1007
1008bool wxFont::IsUsingSizeInPixels() const
1009{
d014871d 1010 wxCHECK_MSG( IsOk(), 0, wxT("invalid font") );
544229d1
VZ
1011
1012 return M_FONTDATA->IsUsingSizeInPixels();
1013}
1014
0c14b6c3 1015wxFontFamily wxFont::GetFamily() const
0c5d3e1c 1016{
d014871d 1017 wxCHECK_MSG( IsOk(), wxFONTFAMILY_MAX, wxT("invalid font") );
789034a0 1018
a9249b2e 1019 return M_FONTDATA->GetFamily();
2bda0e17
KB
1020}
1021
0c14b6c3 1022wxFontStyle wxFont::GetStyle() const
2bda0e17 1023{
d014871d 1024 wxCHECK_MSG( IsOk(), wxFONTSTYLE_MAX, wxT("invalid font") );
789034a0 1025
a9249b2e 1026 return M_FONTDATA->GetStyle();
2bda0e17
KB
1027}
1028
0c14b6c3 1029wxFontWeight wxFont::GetWeight() const
2bda0e17 1030{
d014871d 1031 wxCHECK_MSG( IsOk(), wxFONTWEIGHT_MAX, wxT("invalid font") );
789034a0 1032
a9249b2e 1033 return M_FONTDATA->GetWeight();
2bda0e17
KB
1034}
1035
0c5d3e1c
VZ
1036bool wxFont::GetUnderlined() const
1037{
d014871d 1038 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
789034a0 1039
a9249b2e 1040 return M_FONTDATA->GetUnderlined();
0c5d3e1c
VZ
1041}
1042
1043wxString wxFont::GetFaceName() const
1044{
d014871d 1045 wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") );
789034a0 1046
a9249b2e 1047 return M_FONTDATA->GetFaceName();
0c5d3e1c
VZ
1048}
1049
1050wxFontEncoding wxFont::GetEncoding() const
1051{
d014871d 1052 wxCHECK_MSG( IsOk(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
789034a0 1053
a9249b2e 1054 return M_FONTDATA->GetEncoding();
0c5d3e1c 1055}
a1d58ddc 1056
3bf5a59b 1057const wxNativeFontInfo *wxFont::GetNativeFontInfo() const
1e6feb95 1058{
7c6e85dc 1059 return IsOk() ? &(M_FONTDATA->GetNativeFontInfo()) : NULL;
09fcd889
VZ
1060}
1061
9cf8de4c
VZ
1062bool wxFont::IsFixedWidth() const
1063{
d014871d
FM
1064 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
1065
7c6e85dc
VZ
1066 // the two low-order bits specify the pitch of the font, the rest is
1067 // family
1068 BYTE pitch =
1069 (BYTE)(M_FONTDATA->GetNativeFontInfo().lf.lfPitchAndFamily & PITCH_MASK);
9cf8de4c 1070
7c6e85dc 1071 return pitch == FIXED_PITCH;
9cf8de4c 1072}