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