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