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