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