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