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