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