]> git.saurik.com Git - wxWidgets.git/blob - src/msw/font.cpp
Add wxFont ctor taking a single flags argument instead of style/weight/...
[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, 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 const wxString& faceName,
78 wxFontEncoding encoding)
79 {
80 Init(size, pixelSize, sizeUsingPixels, family, style, weight,
81 underlined, faceName, encoding);
82 }
83
84 wxFontRefData(const wxNativeFontInfo& info, WXHFONT hFont = 0)
85 {
86 Init(info, hFont);
87 }
88
89 wxFontRefData(const wxFontRefData& data) : wxGDIRefData()
90 {
91 Init(data.m_nativeFontInfo);
92 }
93
94 virtual ~wxFontRefData();
95
96 // operations
97 bool Alloc();
98
99 void Free();
100
101 // all wxFont accessors
102 int GetPointSize() const
103 {
104 return m_nativeFontInfo.GetPointSize();
105 }
106
107 wxSize GetPixelSize() const
108 {
109 return m_nativeFontInfo.GetPixelSize();
110 }
111
112 bool IsUsingSizeInPixels() const
113 {
114 return m_sizeUsingPixels;
115 }
116
117 wxFontFamily GetFamily() const
118 {
119 return m_nativeFontInfo.GetFamily();
120 }
121
122 wxFontStyle GetStyle() const
123 {
124 return m_nativeFontInfo.GetStyle();
125 }
126
127 wxFontWeight GetWeight() const
128 {
129 return m_nativeFontInfo.GetWeight();
130 }
131
132 bool GetUnderlined() const
133 {
134 return m_nativeFontInfo.GetUnderlined();
135 }
136
137 wxString GetFaceName() const
138 {
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;
152 }
153
154 wxFontEncoding GetEncoding() const
155 {
156 return m_nativeFontInfo.GetEncoding();
157 }
158
159 WXHFONT GetHFONT() const
160 {
161 AllocIfNeeded();
162
163 return (WXHFONT)m_hFont;
164 }
165
166 bool HasHFONT() const
167 {
168 return m_hFont != 0;
169 }
170
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
174 void SetPointSize(int pointSize)
175 {
176 Free();
177
178 m_nativeFontInfo.SetPointSize(pointSize);
179 m_sizeUsingPixels = false;
180 }
181
182 void SetPixelSize(const wxSize& pixelSize)
183 {
184 wxCHECK_RET( pixelSize.GetWidth() >= 0, "negative font width" );
185 wxCHECK_RET( pixelSize.GetHeight() != 0, "zero font height" );
186
187 Free();
188
189 m_nativeFontInfo.SetPixelSize(pixelSize);
190 m_sizeUsingPixels = true;
191 }
192
193 void SetFamily(wxFontFamily family)
194 {
195 Free();
196
197 m_nativeFontInfo.SetFamily(family);
198 }
199
200 void SetStyle(wxFontStyle style)
201 {
202 Free();
203
204 m_nativeFontInfo.SetStyle(style);
205 }
206
207 void SetWeight(wxFontWeight weight)
208 {
209 Free();
210
211 m_nativeFontInfo.SetWeight(weight);
212 }
213
214 bool SetFaceName(const wxString& faceName)
215 {
216 Free();
217
218 return m_nativeFontInfo.SetFaceName(faceName);
219 }
220
221 void SetUnderlined(bool underlined)
222 {
223 Free();
224
225 m_nativeFontInfo.SetUnderlined(underlined);
226 }
227
228 void SetEncoding(wxFontEncoding encoding)
229 {
230 Free();
231
232 m_nativeFontInfo.SetEncoding(encoding);
233 }
234
235 const wxNativeFontInfo& GetNativeFontInfo() const
236 {
237 // we need to create the font now to get the corresponding LOGFONT if
238 // it hadn't been done yet
239 AllocIfNeeded();
240
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 }
248
249 void SetNativeFontInfo(const wxNativeFontInfo& nativeFontInfo)
250 {
251 Free();
252
253 m_nativeFontInfo = nativeFontInfo;
254 }
255
256 protected:
257 // common part of all ctors
258 void Init(int size,
259 const wxSize& pixelSize,
260 bool sizeUsingPixels,
261 wxFontFamily family,
262 wxFontStyle style,
263 wxFontWeight weight,
264 bool underlined,
265 const wxString& faceName,
266 wxFontEncoding encoding);
267
268 void Init(const wxNativeFontInfo& info, WXHFONT hFont = 0);
269
270 void AllocIfNeeded() const
271 {
272 if ( !m_hFont )
273 const_cast<wxFontRefData *>(this)->Alloc();
274 }
275
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, (HFONT)GetHFONT());
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
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
308 return reinterpret_cast<wxChar *>(otm) +
309 wxPtrToUInt(otm->otmpFamilyName)/sizeof(wxChar);
310 }
311
312 // are we using m_nativeFontInfo.lf.lfHeight for point size or pixel size?
313 bool m_sizeUsingPixels;
314
315 // Windows font handle, created on demand in GetHFONT()
316 HFONT m_hFont;
317
318 // Native font info
319 wxNativeFontInfo m_nativeFontInfo;
320 };
321
322 #define M_FONTDATA ((wxFontRefData*)m_refData)
323
324 // ============================================================================
325 // implementation
326 // ============================================================================
327
328 // ----------------------------------------------------------------------------
329 // wxFontRefData
330 // ----------------------------------------------------------------------------
331
332 void wxFontRefData::Init(int pointSize,
333 const wxSize& pixelSize,
334 bool sizeUsingPixels,
335 wxFontFamily family,
336 wxFontStyle style,
337 wxFontWeight weight,
338 bool underlined,
339 const wxString& faceName,
340 wxFontEncoding encoding)
341 {
342 m_hFont = NULL;
343
344 m_sizeUsingPixels = sizeUsingPixels;
345 if ( m_sizeUsingPixels )
346 SetPixelSize(pixelSize);
347 else
348 SetPointSize(pointSize);
349
350 SetStyle(style);
351 SetWeight(weight);
352 SetUnderlined(underlined);
353
354 // set the family/facename
355 SetFamily(family);
356 if ( !faceName.empty() )
357 SetFaceName(faceName);
358
359 // deal with encoding now (it may override the font family and facename
360 // so do it after setting them)
361 SetEncoding(encoding);
362 }
363
364 void wxFontRefData::Init(const wxNativeFontInfo& info, WXHFONT hFont)
365 {
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)
370 m_hFont = (HFONT)hFont;
371 m_nativeFontInfo = info;
372
373 // TODO: m_sizeUsingPixels?
374 }
375
376 wxFontRefData::~wxFontRefData()
377 {
378 Free();
379 }
380
381 bool wxFontRefData::Alloc()
382 {
383 m_hFont = ::CreateFontIndirect(&m_nativeFontInfo.lf);
384 if ( !m_hFont )
385 {
386 wxLogLastError(wxT("CreateFont"));
387 return false;
388 }
389
390 return true;
391 }
392
393 void wxFontRefData::Free()
394 {
395 if ( m_hFont )
396 {
397 if ( !::DeleteObject(m_hFont) )
398 {
399 wxLogLastError(wxT("DeleteObject(font)"));
400 }
401
402 m_hFont = 0;
403 }
404 }
405
406 // ----------------------------------------------------------------------------
407 // wxNativeFontInfo
408 // ----------------------------------------------------------------------------
409
410 void wxNativeFontInfo::Init()
411 {
412 wxZeroMemory(lf);
413
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
418 #ifdef __WXWINCE__
419 lf.lfQuality = CLEARTYPE_QUALITY;
420 #else
421 lf.lfQuality = wxSystemOptions::GetOptionInt("msw.font.no-proof-quality")
422 ? DEFAULT_QUALITY
423 : PROOF_QUALITY;
424 #endif
425 }
426
427 int wxNativeFontInfo::GetPointSize() const
428 {
429 // FIXME: using the screen here results in incorrect font size calculation
430 // for printing!
431 const int ppInch = ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY);
432
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);
435 }
436
437 wxSize wxNativeFontInfo::GetPixelSize() const
438 {
439 wxSize ret;
440 ret.SetHeight(abs((int)lf.lfHeight));
441 ret.SetWidth(lf.lfWidth);
442 return ret;
443 }
444
445 wxFontStyle wxNativeFontInfo::GetStyle() const
446 {
447 return lf.lfItalic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL;
448 }
449
450 wxFontWeight 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
461 bool wxNativeFontInfo::GetUnderlined() const
462 {
463 return lf.lfUnderline != 0;
464 }
465
466 wxString wxNativeFontInfo::GetFaceName() const
467 {
468 return lf.lfFaceName;
469 }
470
471 wxFontFamily wxNativeFontInfo::GetFamily() const
472 {
473 wxFontFamily family;
474
475 // extract family from pitch-and-family
476 switch ( lf.lfPitchAndFamily & ~PITCH_MASK )
477 {
478 case 0:
479 family = wxFONTFAMILY_UNKNOWN;
480 break;
481
482 case FF_ROMAN:
483 family = wxFONTFAMILY_ROMAN;
484 break;
485
486 case FF_SWISS:
487 family = wxFONTFAMILY_SWISS;
488 break;
489
490 case FF_SCRIPT:
491 family = wxFONTFAMILY_SCRIPT;
492 break;
493
494 case FF_MODERN:
495 family = wxFONTFAMILY_MODERN;
496 break;
497
498 case FF_DECORATIVE:
499 family = wxFONTFAMILY_DECORATIVE;
500 break;
501
502 default:
503 wxFAIL_MSG( "unknown LOGFONT::lfFamily value" );
504 family = wxFONTFAMILY_UNKNOWN;
505 // just to avoid a warning
506 }
507
508 return family;
509 }
510
511 wxFontEncoding wxNativeFontInfo::GetEncoding() const
512 {
513 return wxGetFontEncFromCharSet(lf.lfCharSet);
514 }
515
516 void wxNativeFontInfo::SetPointSize(int pointsize)
517 {
518 // FIXME: using the screen here results in incorrect font size calculation
519 // for printing!
520 const int ppInch = ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY);
521
522 lf.lfHeight = -(int)((pointsize*((double)ppInch)/72.0) + 0.5);
523 }
524
525 void wxNativeFontInfo::SetPixelSize(const wxSize& pixelSize)
526 {
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());
537 lf.lfWidth = pixelSize.GetWidth();
538 }
539
540 void wxNativeFontInfo::SetStyle(wxFontStyle style)
541 {
542 switch ( style )
543 {
544 default:
545 wxFAIL_MSG( "unknown font style" );
546 // fall through
547
548 case wxFONTSTYLE_NORMAL:
549 lf.lfItalic = FALSE;
550 break;
551
552 case wxFONTSTYLE_ITALIC:
553 case wxFONTSTYLE_SLANT:
554 lf.lfItalic = TRUE;
555 break;
556 }
557 }
558
559 void wxNativeFontInfo::SetWeight(wxFontWeight weight)
560 {
561 switch ( weight )
562 {
563 default:
564 wxFAIL_MSG( "unknown font weight" );
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
581 void wxNativeFontInfo::SetUnderlined(bool underlined)
582 {
583 lf.lfUnderline = underlined;
584 }
585
586 bool wxNativeFontInfo::SetFaceName(const wxString& facename)
587 {
588 wxStrlcpy(lf.lfFaceName, facename.c_str(), WXSIZEOF(lf.lfFaceName));
589 return true;
590 }
591
592 void wxNativeFontInfo::SetFamily(wxFontFamily family)
593 {
594 BYTE ff_family = FF_DONTCARE;
595
596 switch ( family )
597 {
598 case wxFONTFAMILY_SCRIPT:
599 ff_family = FF_SCRIPT;
600 break;
601
602 case wxFONTFAMILY_DECORATIVE:
603 ff_family = FF_DECORATIVE;
604 break;
605
606 case wxFONTFAMILY_ROMAN:
607 ff_family = FF_ROMAN;
608 break;
609
610 case wxFONTFAMILY_TELETYPE:
611 case wxFONTFAMILY_MODERN:
612 ff_family = FF_MODERN;
613 break;
614
615 case wxFONTFAMILY_SWISS:
616 case wxFONTFAMILY_DEFAULT:
617 ff_family = FF_SWISS;
618 break;
619
620 case wxFONTFAMILY_UNKNOWN:
621 wxFAIL_MSG( "invalid font family" );
622 return;
623 }
624
625 wxCHECK_RET( ff_family != FF_DONTCARE, "unknown wxFontFamily" );
626
627 lf.lfPitchAndFamily = (BYTE)(DEFAULT_PITCH) | ff_family;
628
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';
632 }
633
634 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding)
635 {
636 wxNativeEncodingInfo info;
637 if ( !wxGetNativeFontEncoding(encoding, &info) )
638 {
639 #if wxUSE_FONTMAP
640 if ( wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
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
651 #endif // wxUSE_FONTMAP
652 {
653 // unsupported encoding, replace with the default
654 info.charset = DEFAULT_CHARSET;
655 }
656 }
657
658 lf.lfCharSet = (BYTE)info.charset;
659 }
660
661 bool wxNativeFontInfo::FromString(const wxString& s)
662 {
663 long l;
664
665 wxStringTokenizer tokenizer(s, wxS(";"), wxTOKEN_RET_EMPTY_ALL);
666
667 // first the version
668 wxString token = tokenizer.GetNextToken();
669 if ( token != wxS('0') )
670 return false;
671
672 token = tokenizer.GetNextToken();
673 if ( !token.ToLong(&l) )
674 return false;
675 lf.lfHeight = l;
676
677 token = tokenizer.GetNextToken();
678 if ( !token.ToLong(&l) )
679 return false;
680 lf.lfWidth = l;
681
682 token = tokenizer.GetNextToken();
683 if ( !token.ToLong(&l) )
684 return false;
685 lf.lfEscapement = l;
686
687 token = tokenizer.GetNextToken();
688 if ( !token.ToLong(&l) )
689 return false;
690 lf.lfOrientation = l;
691
692 token = tokenizer.GetNextToken();
693 if ( !token.ToLong(&l) )
694 return false;
695 lf.lfWeight = l;
696
697 token = tokenizer.GetNextToken();
698 if ( !token.ToLong(&l) )
699 return false;
700 lf.lfItalic = (BYTE)l;
701
702 token = tokenizer.GetNextToken();
703 if ( !token.ToLong(&l) )
704 return false;
705 lf.lfUnderline = (BYTE)l;
706
707 token = tokenizer.GetNextToken();
708 if ( !token.ToLong(&l) )
709 return false;
710 lf.lfStrikeOut = (BYTE)l;
711
712 token = tokenizer.GetNextToken();
713 if ( !token.ToLong(&l) )
714 return false;
715 lf.lfCharSet = (BYTE)l;
716
717 token = tokenizer.GetNextToken();
718 if ( !token.ToLong(&l) )
719 return false;
720 lf.lfOutPrecision = (BYTE)l;
721
722 token = tokenizer.GetNextToken();
723 if ( !token.ToLong(&l) )
724 return false;
725 lf.lfClipPrecision = (BYTE)l;
726
727 token = tokenizer.GetNextToken();
728 if ( !token.ToLong(&l) )
729 return false;
730 lf.lfQuality = (BYTE)l;
731
732 token = tokenizer.GetNextToken();
733 if ( !token.ToLong(&l) )
734 return false;
735 lf.lfPitchAndFamily = (BYTE)l;
736
737 if ( !tokenizer.HasMoreTokens() )
738 return false;
739
740 // the face name may be empty
741 SetFaceName(tokenizer.GetNextToken());
742
743 return true;
744 }
745
746 wxString wxNativeFontInfo::ToString() const
747 {
748 wxString s;
749
750 s.Printf(wxS("%d;%ld;%ld;%ld;%ld;%ld;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
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,
765 lf.lfFaceName);
766
767 return s;
768 }
769
770 // ----------------------------------------------------------------------------
771 // wxFont
772 // ----------------------------------------------------------------------------
773
774 wxFont::wxFont(const wxString& fontdesc)
775 {
776 wxNativeFontInfo info;
777 if ( info.FromString(fontdesc) )
778 (void)Create(info);
779 }
780
781 wxFont::wxFont(int pointSize,
782 wxFontFamily family,
783 int flags,
784 const wxString& face,
785 wxFontEncoding encoding)
786 {
787 m_refData = new wxFontRefData(pointSize, wxDefaultSize, false,
788 family,
789 GetStyleFromFlags(flags),
790 GetWeightFromFlags(flags),
791 GetUnderlinedFromFlags(flags),
792 face, encoding);
793 }
794
795 bool wxFont::Create(const wxNativeFontInfo& info, WXHFONT hFont)
796 {
797 UnRef();
798
799 m_refData = new wxFontRefData(info, hFont);
800
801 return RealizeResource();
802 }
803
804 bool wxFont::DoCreate(int pointSize,
805 const wxSize& pixelSize,
806 bool sizeUsingPixels,
807 wxFontFamily family,
808 wxFontStyle style,
809 wxFontWeight weight,
810 bool underlined,
811 const wxString& faceName,
812 wxFontEncoding encoding)
813 {
814 UnRef();
815
816 // wxDEFAULT is a valid value for the font size too so we must treat it
817 // specially here (otherwise the size would be 70 == wxDEFAULT value)
818 if ( pointSize == wxDEFAULT )
819 {
820 pointSize = wxNORMAL_FONT->GetPointSize();
821 }
822
823 m_refData = new wxFontRefData(pointSize, pixelSize, sizeUsingPixels,
824 family, style, weight,
825 underlined, faceName, encoding);
826
827 return RealizeResource();
828 }
829
830 wxFont::~wxFont()
831 {
832 }
833
834 // ----------------------------------------------------------------------------
835 // real implementation
836 // ----------------------------------------------------------------------------
837
838 wxGDIRefData *wxFont::CreateGDIRefData() const
839 {
840 return new wxFontRefData();
841 }
842
843 wxGDIRefData *wxFont::CloneGDIRefData(const wxGDIRefData *data) const
844 {
845 return new wxFontRefData(*static_cast<const wxFontRefData *>(data));
846 }
847
848 bool wxFont::RealizeResource()
849 {
850 // NOTE: the GetHFONT() call automatically triggers a reallocation of
851 // the HFONT if necessary (will do nothing if we already have the resource);
852 // it returns NULL only if there is a failure in wxFontRefData::Alloc()...
853 return GetHFONT() != NULL;
854 }
855
856 bool wxFont::FreeResource(bool WXUNUSED(force))
857 {
858 if ( !M_FONTDATA )
859 return false;
860
861 M_FONTDATA->Free();
862
863 return true;
864 }
865
866 WXHANDLE wxFont::GetResourceHandle() const
867 {
868 return (WXHANDLE)GetHFONT();
869 }
870
871 WXHFONT wxFont::GetHFONT() const
872 {
873 // NOTE: wxFontRefData::GetHFONT() will automatically call
874 // wxFontRefData::Alloc() if necessary
875 return M_FONTDATA ? M_FONTDATA->GetHFONT() : 0;
876 }
877
878 bool wxFont::IsFree() const
879 {
880 return M_FONTDATA && !M_FONTDATA->HasHFONT();
881 }
882
883 // ----------------------------------------------------------------------------
884 // change font attribute: we recreate font when doing it
885 // ----------------------------------------------------------------------------
886
887 void wxFont::SetPointSize(int pointSize)
888 {
889 AllocExclusive();
890
891 M_FONTDATA->Free();
892 M_FONTDATA->SetPointSize(pointSize);
893 }
894
895 void wxFont::SetPixelSize(const wxSize& pixelSize)
896 {
897 AllocExclusive();
898
899 M_FONTDATA->SetPixelSize(pixelSize);
900 }
901
902 void wxFont::SetFamily(wxFontFamily family)
903 {
904 AllocExclusive();
905
906 M_FONTDATA->SetFamily(family);
907 }
908
909 void wxFont::SetStyle(wxFontStyle style)
910 {
911 AllocExclusive();
912
913 M_FONTDATA->SetStyle(style);
914 }
915
916 void wxFont::SetWeight(wxFontWeight weight)
917 {
918 AllocExclusive();
919
920 M_FONTDATA->SetWeight(weight);
921 }
922
923 bool wxFont::SetFaceName(const wxString& faceName)
924 {
925 AllocExclusive();
926
927 if ( !M_FONTDATA->SetFaceName(faceName) )
928 return false;
929
930 // NB: using win32's GetObject() API on M_FONTDATA->GetHFONT()
931 // to retrieve a LOGFONT and then compare lf.lfFaceName
932 // with given facename is not reliable at all:
933 // Windows copies the facename given to ::CreateFontIndirect()
934 // without any validity check.
935 // Thus we use wxFontBase::SetFaceName to check if facename
936 // is valid...
937 return wxFontBase::SetFaceName(faceName);
938 }
939
940 void wxFont::SetUnderlined(bool underlined)
941 {
942 AllocExclusive();
943
944 M_FONTDATA->SetUnderlined(underlined);
945 }
946
947 void wxFont::SetEncoding(wxFontEncoding encoding)
948 {
949 AllocExclusive();
950
951 M_FONTDATA->SetEncoding(encoding);
952 }
953
954 void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo& info)
955 {
956 AllocExclusive();
957
958 M_FONTDATA->SetNativeFontInfo(info);
959 }
960
961 // ----------------------------------------------------------------------------
962 // accessors
963 // ----------------------------------------------------------------------------
964
965 int wxFont::GetPointSize() const
966 {
967 wxCHECK_MSG( IsOk(), 0, wxT("invalid font") );
968
969 return M_FONTDATA->GetPointSize();
970 }
971
972 wxSize wxFont::GetPixelSize() const
973 {
974 wxCHECK_MSG( IsOk(), wxDefaultSize, wxT("invalid font") );
975
976 return M_FONTDATA->GetPixelSize();
977 }
978
979 bool wxFont::IsUsingSizeInPixels() const
980 {
981 wxCHECK_MSG( IsOk(), 0, wxT("invalid font") );
982
983 return M_FONTDATA->IsUsingSizeInPixels();
984 }
985
986 wxFontFamily wxFont::DoGetFamily() const
987 {
988 return M_FONTDATA->GetFamily();
989 }
990
991 wxFontStyle wxFont::GetStyle() const
992 {
993 wxCHECK_MSG( IsOk(), wxFONTSTYLE_MAX, wxT("invalid font") );
994
995 return M_FONTDATA->GetStyle();
996 }
997
998 wxFontWeight wxFont::GetWeight() const
999 {
1000 wxCHECK_MSG( IsOk(), wxFONTWEIGHT_MAX, wxT("invalid font") );
1001
1002 return M_FONTDATA->GetWeight();
1003 }
1004
1005 bool wxFont::GetUnderlined() const
1006 {
1007 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
1008
1009 return M_FONTDATA->GetUnderlined();
1010 }
1011
1012 wxString wxFont::GetFaceName() const
1013 {
1014 wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") );
1015
1016 return M_FONTDATA->GetFaceName();
1017 }
1018
1019 wxFontEncoding wxFont::GetEncoding() const
1020 {
1021 wxCHECK_MSG( IsOk(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
1022
1023 return M_FONTDATA->GetEncoding();
1024 }
1025
1026 const wxNativeFontInfo *wxFont::GetNativeFontInfo() const
1027 {
1028 return IsOk() ? &(M_FONTDATA->GetNativeFontInfo()) : NULL;
1029 }
1030
1031 bool wxFont::IsFixedWidth() const
1032 {
1033 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
1034
1035 // LOGFONT doesn't contain the correct pitch information so we need to call
1036 // GetTextMetrics() to get it
1037 ScreenHDC hdc;
1038 SelectInHDC selectFont(hdc, M_FONTDATA->GetHFONT());
1039
1040 TEXTMETRIC tm;
1041 if ( !::GetTextMetrics(hdc, &tm) )
1042 {
1043 wxLogLastError(wxT("GetTextMetrics"));
1044 return false;
1045 }
1046
1047 // Quoting MSDN description of TMPF_FIXED_PITCH: "Note very carefully that
1048 // those meanings are the opposite of what the constant name implies."
1049 return !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
1050 }