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