]> git.saurik.com Git - wxWidgets.git/blob - src/msw/font.cpp
wxRichTextCtrl::ApplyStyle now applies a paragraph style at the cursor
[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 case wxFONTFAMILY_UNKNOWN:
668 wxFAIL_MSG( "invalid font family" );
669 return;
670 }
671
672 wxCHECK_RET( ff_family != FF_DONTCARE, "unknown wxFontFamily" );
673
674 lf.lfPitchAndFamily = (BYTE)(DEFAULT_PITCH) | ff_family;
675
676 // reset the facename so that CreateFontIndirect() will automatically choose a
677 // face name based only on the font family.
678 lf.lfFaceName[0] = '\0';
679 }
680
681 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding)
682 {
683 wxNativeEncodingInfo info;
684 if ( !wxGetNativeFontEncoding(encoding, &info) )
685 {
686 #if wxUSE_FONTMAP
687 if ( wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
688 {
689 if ( !info.facename.empty() )
690 {
691 // if we have this encoding only in some particular facename, use
692 // the facename - it is better to show the correct characters in a
693 // wrong facename than unreadable text in a correct one
694 SetFaceName(info.facename);
695 }
696 }
697 else
698 #endif // wxUSE_FONTMAP
699 {
700 // unsupported encoding, replace with the default
701 info.charset = DEFAULT_CHARSET;
702 }
703 }
704
705 lf.lfCharSet = (BYTE)info.charset;
706 }
707
708 bool wxNativeFontInfo::FromString(const wxString& s)
709 {
710 long l;
711
712 wxStringTokenizer tokenizer(s, wxS(";"), wxTOKEN_RET_EMPTY_ALL);
713
714 // first the version
715 wxString token = tokenizer.GetNextToken();
716 if ( token != wxS('0') )
717 return false;
718
719 token = tokenizer.GetNextToken();
720 if ( !token.ToLong(&l) )
721 return false;
722 lf.lfHeight = l;
723
724 token = tokenizer.GetNextToken();
725 if ( !token.ToLong(&l) )
726 return false;
727 lf.lfWidth = l;
728
729 token = tokenizer.GetNextToken();
730 if ( !token.ToLong(&l) )
731 return false;
732 lf.lfEscapement = l;
733
734 token = tokenizer.GetNextToken();
735 if ( !token.ToLong(&l) )
736 return false;
737 lf.lfOrientation = l;
738
739 token = tokenizer.GetNextToken();
740 if ( !token.ToLong(&l) )
741 return false;
742 lf.lfWeight = l;
743
744 token = tokenizer.GetNextToken();
745 if ( !token.ToLong(&l) )
746 return false;
747 lf.lfItalic = (BYTE)l;
748
749 token = tokenizer.GetNextToken();
750 if ( !token.ToLong(&l) )
751 return false;
752 lf.lfUnderline = (BYTE)l;
753
754 token = tokenizer.GetNextToken();
755 if ( !token.ToLong(&l) )
756 return false;
757 lf.lfStrikeOut = (BYTE)l;
758
759 token = tokenizer.GetNextToken();
760 if ( !token.ToLong(&l) )
761 return false;
762 lf.lfCharSet = (BYTE)l;
763
764 token = tokenizer.GetNextToken();
765 if ( !token.ToLong(&l) )
766 return false;
767 lf.lfOutPrecision = (BYTE)l;
768
769 token = tokenizer.GetNextToken();
770 if ( !token.ToLong(&l) )
771 return false;
772 lf.lfClipPrecision = (BYTE)l;
773
774 token = tokenizer.GetNextToken();
775 if ( !token.ToLong(&l) )
776 return false;
777 lf.lfQuality = (BYTE)l;
778
779 token = tokenizer.GetNextToken();
780 if ( !token.ToLong(&l) )
781 return false;
782 lf.lfPitchAndFamily = (BYTE)l;
783
784 if ( !tokenizer.HasMoreTokens() )
785 return false;
786
787 // the face name may be empty
788 SetFaceName(tokenizer.GetNextToken());
789
790 return true;
791 }
792
793 wxString wxNativeFontInfo::ToString() const
794 {
795 wxString s;
796
797 s.Printf(wxS("%d;%ld;%ld;%ld;%ld;%ld;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
798 0, // version, in case we want to change the format later
799 lf.lfHeight,
800 lf.lfWidth,
801 lf.lfEscapement,
802 lf.lfOrientation,
803 lf.lfWeight,
804 lf.lfItalic,
805 lf.lfUnderline,
806 lf.lfStrikeOut,
807 lf.lfCharSet,
808 lf.lfOutPrecision,
809 lf.lfClipPrecision,
810 lf.lfQuality,
811 lf.lfPitchAndFamily,
812 lf.lfFaceName);
813
814 return s;
815 }
816
817 // ----------------------------------------------------------------------------
818 // wxFont
819 // ----------------------------------------------------------------------------
820
821 wxFont::wxFont(const wxString& fontdesc)
822 {
823 wxNativeFontInfo info;
824 if ( info.FromString(fontdesc) )
825 (void)Create(info);
826 }
827
828 bool wxFont::Create(const wxNativeFontInfo& info, WXHFONT hFont)
829 {
830 UnRef();
831
832 m_refData = new wxFontRefData(info, hFont);
833
834 return RealizeResource();
835 }
836
837 bool wxFont::DoCreate(int pointSize,
838 const wxSize& pixelSize,
839 bool sizeUsingPixels,
840 wxFontFamily family,
841 wxFontStyle style,
842 wxFontWeight weight,
843 bool underlined,
844 const wxString& faceName,
845 wxFontEncoding encoding)
846 {
847 UnRef();
848
849 // wxDEFAULT is a valid value for the font size too so we must treat it
850 // specially here (otherwise the size would be 70 == wxDEFAULT value)
851 if ( pointSize == wxDEFAULT )
852 {
853 pointSize = wxNORMAL_FONT->GetPointSize();
854 }
855
856 m_refData = new wxFontRefData(pointSize, pixelSize, sizeUsingPixels,
857 family, style, weight,
858 underlined, faceName, encoding);
859
860 return RealizeResource();
861 }
862
863 wxFont::~wxFont()
864 {
865 }
866
867 // ----------------------------------------------------------------------------
868 // real implementation
869 // ----------------------------------------------------------------------------
870
871 wxGDIRefData *wxFont::CreateGDIRefData() const
872 {
873 return new wxFontRefData();
874 }
875
876 wxGDIRefData *wxFont::CloneGDIRefData(const wxGDIRefData *data) const
877 {
878 return new wxFontRefData(*static_cast<const wxFontRefData *>(data));
879 }
880
881 bool wxFont::RealizeResource()
882 {
883 // NOTE: the GetHFONT() call automatically triggers a reallocation of
884 // the HFONT if necessary (will do nothing if we already have the resource);
885 // it returns NULL only if there is a failure in wxFontRefData::Alloc()...
886 return GetHFONT() != NULL;
887 }
888
889 bool wxFont::FreeResource(bool WXUNUSED(force))
890 {
891 if ( !M_FONTDATA )
892 return false;
893
894 M_FONTDATA->Free();
895
896 return true;
897 }
898
899 WXHANDLE wxFont::GetResourceHandle() const
900 {
901 return (WXHANDLE)GetHFONT();
902 }
903
904 WXHFONT wxFont::GetHFONT() const
905 {
906 // NOTE: wxFontRefData::GetHFONT() will automatically call
907 // wxFontRefData::Alloc() if necessary
908 return M_FONTDATA ? M_FONTDATA->GetHFONT() : 0;
909 }
910
911 bool wxFont::IsFree() const
912 {
913 return M_FONTDATA && !M_FONTDATA->HasHFONT();
914 }
915
916 // ----------------------------------------------------------------------------
917 // change font attribute: we recreate font when doing it
918 // ----------------------------------------------------------------------------
919
920 void wxFont::SetPointSize(int pointSize)
921 {
922 AllocExclusive();
923
924 M_FONTDATA->Free();
925 M_FONTDATA->SetPointSize(pointSize);
926 }
927
928 void wxFont::SetPixelSize(const wxSize& pixelSize)
929 {
930 AllocExclusive();
931
932 M_FONTDATA->SetPixelSize(pixelSize);
933 }
934
935 void wxFont::SetFamily(wxFontFamily family)
936 {
937 AllocExclusive();
938
939 M_FONTDATA->SetFamily(family);
940 }
941
942 void wxFont::SetStyle(wxFontStyle style)
943 {
944 AllocExclusive();
945
946 M_FONTDATA->SetStyle(style);
947 }
948
949 void wxFont::SetWeight(wxFontWeight weight)
950 {
951 AllocExclusive();
952
953 M_FONTDATA->SetWeight(weight);
954 }
955
956 bool wxFont::SetFaceName(const wxString& faceName)
957 {
958 AllocExclusive();
959
960 if ( !M_FONTDATA->SetFaceName(faceName) )
961 return false;
962
963 // NB: using win32's GetObject() API on M_FONTDATA->GetHFONT()
964 // to retrieve a LOGFONT and then compare lf.lfFaceName
965 // with given facename is not reliable at all:
966 // Windows copies the facename given to ::CreateFontIndirect()
967 // without any validity check.
968 // Thus we use wxFontBase::SetFaceName to check if facename
969 // is valid...
970 return wxFontBase::SetFaceName(faceName);
971 }
972
973 void wxFont::SetUnderlined(bool underlined)
974 {
975 AllocExclusive();
976
977 M_FONTDATA->SetUnderlined(underlined);
978 }
979
980 void wxFont::SetEncoding(wxFontEncoding encoding)
981 {
982 AllocExclusive();
983
984 M_FONTDATA->SetEncoding(encoding);
985 }
986
987 void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo& info)
988 {
989 AllocExclusive();
990
991 M_FONTDATA->SetNativeFontInfo(info);
992 }
993
994 // ----------------------------------------------------------------------------
995 // accessors
996 // ----------------------------------------------------------------------------
997
998 int wxFont::GetPointSize() const
999 {
1000 wxCHECK_MSG( IsOk(), 0, wxT("invalid font") );
1001
1002 return M_FONTDATA->GetPointSize();
1003 }
1004
1005 wxSize wxFont::GetPixelSize() const
1006 {
1007 wxCHECK_MSG( IsOk(), wxDefaultSize, wxT("invalid font") );
1008
1009 return M_FONTDATA->GetPixelSize();
1010 }
1011
1012 bool wxFont::IsUsingSizeInPixels() const
1013 {
1014 wxCHECK_MSG( IsOk(), 0, wxT("invalid font") );
1015
1016 return M_FONTDATA->IsUsingSizeInPixels();
1017 }
1018
1019 wxFontFamily wxFont::GetFamily() const
1020 {
1021 wxCHECK_MSG( IsOk(), wxFONTFAMILY_MAX, wxT("invalid font") );
1022
1023 return M_FONTDATA->GetFamily();
1024 }
1025
1026 wxFontStyle wxFont::GetStyle() const
1027 {
1028 wxCHECK_MSG( IsOk(), wxFONTSTYLE_MAX, wxT("invalid font") );
1029
1030 return M_FONTDATA->GetStyle();
1031 }
1032
1033 wxFontWeight wxFont::GetWeight() const
1034 {
1035 wxCHECK_MSG( IsOk(), wxFONTWEIGHT_MAX, wxT("invalid font") );
1036
1037 return M_FONTDATA->GetWeight();
1038 }
1039
1040 bool wxFont::GetUnderlined() const
1041 {
1042 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
1043
1044 return M_FONTDATA->GetUnderlined();
1045 }
1046
1047 wxString wxFont::GetFaceName() const
1048 {
1049 wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") );
1050
1051 return M_FONTDATA->GetFaceName();
1052 }
1053
1054 wxFontEncoding wxFont::GetEncoding() const
1055 {
1056 wxCHECK_MSG( IsOk(), wxFONTENCODING_DEFAULT, wxT("invalid font") );
1057
1058 return M_FONTDATA->GetEncoding();
1059 }
1060
1061 const wxNativeFontInfo *wxFont::GetNativeFontInfo() const
1062 {
1063 return IsOk() ? &(M_FONTDATA->GetNativeFontInfo()) : NULL;
1064 }
1065
1066 bool wxFont::IsFixedWidth() const
1067 {
1068 wxCHECK_MSG( IsOk(), false, wxT("invalid font") );
1069
1070 // LOGFONT doesn't contain the correct pitch information so we need to call
1071 // GetTextMetrics() to get it
1072 ScreenHDC hdc;
1073 SelectInHDC selectFont(hdc, M_FONTDATA->GetHFONT());
1074
1075 TEXTMETRIC tm;
1076 if ( !::GetTextMetrics(hdc, &tm) )
1077 {
1078 wxLogLastError(wxT("GetTextMetrics"));
1079 return false;
1080 }
1081
1082 // Quoting MSDN description of TMPF_FIXED_PITCH: "Note very carefully that
1083 // those meanings are the opposite of what the constant name implies."
1084 return !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
1085 }