1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/font.cpp
3 // Purpose: wxFont class
4 // Author: Julian Smart
8 // Copyright: (c) wxWindows team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "font.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
40 #include "wx/msw/private.h"
42 #include "wx/fontutil.h"
43 #include "wx/fontmap.h"
45 #include "wx/tokenzr.h"
47 IMPLEMENT_DYNAMIC_CLASS(wxFont
, wxGDIObject
)
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 // the mask used to extract the pitch from LOGFONT::lfPitchAndFamily field
54 static const int PITCH_MASK
= FIXED_PITCH
| VARIABLE_PITCH
;
56 // ----------------------------------------------------------------------------
57 // wxFontRefData - the internal description of the font
58 // ----------------------------------------------------------------------------
60 class WXDLLEXPORT wxFontRefData
: public wxGDIRefData
66 Init(-1, wxFONTFAMILY_DEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
,
67 FALSE
, _T(""), wxFONTENCODING_DEFAULT
);
70 wxFontRefData(int size
,
75 const wxString
& faceName
,
76 wxFontEncoding encoding
)
78 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
81 wxFontRefData(const wxNativeFontInfo
& info
, WXHFONT hFont
= 0)
86 wxFontRefData(const wxFontRefData
& data
)
88 if ( data
.m_nativeFontInfoOk
)
90 Init(data
.m_nativeFontInfo
);
94 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
95 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
99 virtual ~wxFontRefData();
102 bool Alloc(wxFont
*font
);
106 // all wxFont accessors
107 int GetPointSize() const
109 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetPointSize()
113 int GetFamily() const
120 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetStyle()
124 int GetWeight() const
126 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetWeight()
130 bool GetUnderlined() const
132 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetUnderlined()
136 wxString
GetFaceName() const
139 if ( m_nativeFontInfoOk
)
140 s
= m_nativeFontInfo
.GetFaceName();
147 wxFontEncoding
GetEncoding() const
149 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetEncoding()
153 WXHFONT
GetHFONT() const { return m_hFont
; }
156 void SetPointSize(int pointSize
)
158 if ( m_nativeFontInfoOk
)
159 m_nativeFontInfo
.SetPointSize(pointSize
);
161 m_pointSize
= pointSize
;
164 void SetFamily(int family
)
169 void SetStyle(int style
)
171 if ( m_nativeFontInfoOk
)
172 m_nativeFontInfo
.SetStyle((wxFontStyle
)style
);
177 void SetWeight(int weight
)
179 if ( m_nativeFontInfoOk
)
180 m_nativeFontInfo
.SetWeight((wxFontWeight
)weight
);
185 void SetFaceName(const wxString
& faceName
)
187 if ( m_nativeFontInfoOk
)
188 m_nativeFontInfo
.SetFaceName(faceName
);
190 m_faceName
= faceName
;
193 void SetUnderlined(bool underlined
)
195 if ( m_nativeFontInfoOk
)
196 m_nativeFontInfo
.SetUnderlined(underlined
);
198 m_underlined
= underlined
;
201 void SetEncoding(wxFontEncoding encoding
)
203 if ( m_nativeFontInfoOk
)
204 m_nativeFontInfo
.SetEncoding(encoding
);
206 m_encoding
= encoding
;
209 // native font info tests
210 bool HasNativeFontInfo() const { return m_nativeFontInfoOk
; }
212 const wxNativeFontInfo
& GetNativeFontInfo() const
213 { return m_nativeFontInfo
; }
216 // common part of all ctors
222 const wxString
& faceName
,
223 wxFontEncoding encoding
);
225 void Init(const wxNativeFontInfo
& info
, WXHFONT hFont
= 0);
227 // font characterstics
234 wxFontEncoding m_encoding
;
236 // Windows font handle
240 wxNativeFontInfo m_nativeFontInfo
;
241 bool m_nativeFontInfoOk
;
244 // ============================================================================
246 // ============================================================================
248 // ----------------------------------------------------------------------------
250 // ----------------------------------------------------------------------------
252 void wxFontRefData::Init(int pointSize
,
257 const wxString
& faceName
,
258 wxFontEncoding encoding
)
261 m_pointSize
= pointSize
== -1 ? wxNORMAL_FONT
->GetPointSize() : pointSize
;
265 m_underlined
= underlined
;
266 m_faceName
= faceName
;
267 m_encoding
= encoding
;
271 m_nativeFontInfoOk
= FALSE
;
274 void wxFontRefData::Init(const wxNativeFontInfo
& info
, WXHFONT hFont
)
276 // hFont may be zero, or it be passed in case we really want to
277 // use the exact font created in the underlying system
278 // (for example where we can't guarantee conversion from HFONT
279 // to LOGFONT back to HFONT)
282 m_nativeFontInfoOk
= TRUE
;
283 m_nativeFontInfo
= info
;
284 // This is the best we can do since we don't have the
285 // correct information at this point.
289 wxFontRefData::~wxFontRefData()
294 bool wxFontRefData::Alloc(wxFont
*font
)
296 if ( !m_nativeFontInfoOk
)
298 wxFillLogFont(&m_nativeFontInfo
.lf
, font
);
299 m_nativeFontInfoOk
= TRUE
;
302 HFONT hfont
= ::CreateFontIndirect(&m_nativeFontInfo
.lf
);
305 wxLogLastError(wxT("CreateFont"));
310 m_hFont
= (WXHFONT
)hfont
;
315 void wxFontRefData::Free()
319 if ( !::DeleteObject((HFONT
) m_hFont
) )
321 wxLogLastError(wxT("DeleteObject(font)"));
328 // ----------------------------------------------------------------------------
330 // ----------------------------------------------------------------------------
332 void wxNativeFontInfo::Init()
337 int wxNativeFontInfo::GetPointSize() const
339 // FIXME: using the screen here results in incorrect font size calculation
341 const int ppInch
= ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY
);
343 return (int) (((72.0*(double)abs(lf
.lfHeight
)) / (double) ppInch
) + 0.5);
346 wxFontStyle
wxNativeFontInfo::GetStyle() const
348 return lf
.lfItalic
? wxFONTSTYLE_ITALIC
: wxFONTSTYLE_NORMAL
;
351 wxFontWeight
wxNativeFontInfo::GetWeight() const
353 if ( lf
.lfWeight
<= 300 )
354 return wxFONTWEIGHT_LIGHT
;
356 if ( lf
.lfWeight
>= 600 )
357 return wxFONTWEIGHT_BOLD
;
359 return wxFONTWEIGHT_NORMAL
;
362 bool wxNativeFontInfo::GetUnderlined() const
364 return lf
.lfUnderline
!= 0;
367 wxString
wxNativeFontInfo::GetFaceName() const
369 return lf
.lfFaceName
;
372 wxFontFamily
wxNativeFontInfo::GetFamily() const
376 // extract family from pitch-and-family
377 switch ( lf
.lfPitchAndFamily
& ~PITCH_MASK
)
380 family
= wxFONTFAMILY_ROMAN
;
384 wxFAIL_MSG( _T("unknown LOGFONT::lfFamily value") );
388 family
= wxFONTFAMILY_SWISS
;
392 family
= wxFONTFAMILY_SCRIPT
;
396 family
= wxFONTFAMILY_MODERN
;
400 family
= wxFONTFAMILY_DECORATIVE
;
407 wxFontEncoding
wxNativeFontInfo::GetEncoding() const
409 return wxGetFontEncFromCharSet(lf
.lfCharSet
);
412 void wxNativeFontInfo::SetPointSize(int pointsize
)
414 #if wxFONT_SIZE_COMPATIBILITY
415 // Incorrect, but compatible with old wxWindows behaviour
416 lf
.lfHeight
= (pointSize
*ppInch
)/72;
417 #else // wxFONT_SIZE_COMPATIBILITY
418 // FIXME: using the screen here results in incorrect font size calculation
420 const int ppInch
= ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY
);
422 lf
.lfHeight
= -(int)((pointsize
*((double)ppInch
)/72.0) + 0.5);
423 #endif // wxFONT_SIZE_COMPATIBILITY/!wxFONT_SIZE_COMPATIBILITY
426 void wxNativeFontInfo::SetStyle(wxFontStyle style
)
431 wxFAIL_MSG( _T("unknown font style") );
434 case wxFONTSTYLE_NORMAL
:
438 case wxFONTSTYLE_ITALIC
:
439 case wxFONTSTYLE_SLANT
:
445 void wxNativeFontInfo::SetWeight(wxFontWeight weight
)
450 wxFAIL_MSG( _T("unknown font weight") );
453 case wxFONTWEIGHT_NORMAL
:
454 lf
.lfWeight
= FW_NORMAL
;
457 case wxFONTWEIGHT_LIGHT
:
458 lf
.lfWeight
= FW_LIGHT
;
461 case wxFONTWEIGHT_BOLD
:
462 lf
.lfWeight
= FW_BOLD
;
467 void wxNativeFontInfo::SetUnderlined(bool underlined
)
469 lf
.lfUnderline
= underlined
;
472 void wxNativeFontInfo::SetFaceName(wxString facename
)
474 wxStrncpy(lf
.lfFaceName
, facename
, WXSIZEOF(lf
.lfFaceName
));
477 void wxNativeFontInfo::SetFamily(wxFontFamily family
)
485 ff_family
= FF_SCRIPT
;
486 facename
= _T("Script");
490 ff_family
= FF_DECORATIVE
;
491 facename
= _T("Old English Text MT");
495 ff_family
= FF_ROMAN
;
496 facename
= _T("Times New Roman");
501 ff_family
= FF_MODERN
;
502 facename
= _T("Courier New");
506 ff_family
= FF_SWISS
;
507 facename
= _T("Arial");
512 ff_family
= FF_SWISS
;
513 facename
= _T("MS Sans Serif");
516 lf
.lfPitchAndFamily
= DEFAULT_PITCH
| ff_family
;
518 if ( !wxStrlen(lf
.lfFaceName
) )
520 SetFaceName(facename
);
524 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding
)
526 wxNativeEncodingInfo info
;
527 if ( !wxGetNativeFontEncoding(encoding
, &info
) )
530 if ( wxFontMapper::Get()->GetAltForEncoding(encoding
, &info
) )
532 if ( !info
.facename
.empty() )
534 // if we have this encoding only in some particular facename, use
535 // the facename - it is better to show the correct characters in a
536 // wrong facename than unreadable text in a correct one
537 SetFaceName(info
.facename
);
541 #endif // wxUSE_FONTMAP
543 // unsupported encoding, replace with the default
544 info
.charset
= DEFAULT_CHARSET
;
548 lf
.lfCharSet
= info
.charset
;
551 bool wxNativeFontInfo::FromString(const wxString
& s
)
555 wxStringTokenizer
tokenizer(s
, _T(";"));
558 wxString token
= tokenizer
.GetNextToken();
559 if ( token
!= _T('0') )
562 token
= tokenizer
.GetNextToken();
563 if ( !token
.ToLong(&l
) )
567 token
= tokenizer
.GetNextToken();
568 if ( !token
.ToLong(&l
) )
572 token
= tokenizer
.GetNextToken();
573 if ( !token
.ToLong(&l
) )
577 token
= tokenizer
.GetNextToken();
578 if ( !token
.ToLong(&l
) )
580 lf
.lfOrientation
= l
;
582 token
= tokenizer
.GetNextToken();
583 if ( !token
.ToLong(&l
) )
587 token
= tokenizer
.GetNextToken();
588 if ( !token
.ToLong(&l
) )
590 lf
.lfItalic
= (BYTE
)l
;
592 token
= tokenizer
.GetNextToken();
593 if ( !token
.ToLong(&l
) )
595 lf
.lfUnderline
= (BYTE
)l
;
597 token
= tokenizer
.GetNextToken();
598 if ( !token
.ToLong(&l
) )
600 lf
.lfStrikeOut
= (BYTE
)l
;
602 token
= tokenizer
.GetNextToken();
603 if ( !token
.ToLong(&l
) )
605 lf
.lfCharSet
= (BYTE
)l
;
607 token
= tokenizer
.GetNextToken();
608 if ( !token
.ToLong(&l
) )
610 lf
.lfOutPrecision
= (BYTE
)l
;
612 token
= tokenizer
.GetNextToken();
613 if ( !token
.ToLong(&l
) )
615 lf
.lfClipPrecision
= (BYTE
)l
;
617 token
= tokenizer
.GetNextToken();
618 if ( !token
.ToLong(&l
) )
620 lf
.lfQuality
= (BYTE
)l
;
622 token
= tokenizer
.GetNextToken();
623 if ( !token
.ToLong(&l
) )
625 lf
.lfPitchAndFamily
= (BYTE
)l
;
627 token
= tokenizer
.GetNextToken();
630 wxStrcpy(lf
.lfFaceName
, token
.c_str());
635 wxString
wxNativeFontInfo::ToString() const
639 s
.Printf(_T("%d;%ld;%ld;%ld;%ld;%ld;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
640 0, // version, in case we want to change the format later
659 // ----------------------------------------------------------------------------
661 // ----------------------------------------------------------------------------
667 bool wxFont::Create(const wxNativeFontInfo
& info
, WXHFONT hFont
)
671 m_refData
= new wxFontRefData(info
, hFont
);
678 wxFont::wxFont(const wxString
& fontdesc
)
680 wxNativeFontInfo info
;
681 if ( info
.FromString(fontdesc
) )
685 /* Constructor for a font. Note that the real construction is done
686 * in wxDC::SetFont, when information is available about scaling etc.
688 bool wxFont::Create(int pointSize
,
693 const wxString
& faceName
,
694 wxFontEncoding encoding
)
698 // wxDEFAULT is a valid value for the font size too so we must treat it
699 // specially here (otherwise the size would be 70 == wxDEFAULT value)
700 if ( pointSize
== wxDEFAULT
)
702 pointSize
= wxNORMAL_FONT
->GetPointSize();
705 m_refData
= new wxFontRefData(pointSize
, family
, style
, weight
,
706 underlined
, faceName
, encoding
);
717 // ----------------------------------------------------------------------------
718 // real implementation
719 // ----------------------------------------------------------------------------
721 bool wxFont::RealizeResource()
723 if ( GetResourceHandle() )
725 // VZ: the old code returned FALSE in this case, but it doesn't seem
726 // to make sense because the font _was_ created
730 return M_FONTDATA
->Alloc(this);
733 bool wxFont::FreeResource(bool WXUNUSED(force
))
735 if ( GetResourceHandle() )
745 WXHANDLE
wxFont::GetResourceHandle()
750 WXHFONT
wxFont::GetHFONT() const
752 return M_FONTDATA
? M_FONTDATA
->GetHFONT() : 0;
755 bool wxFont::IsFree() const
757 return M_FONTDATA
&& (M_FONTDATA
->GetHFONT() == 0);
760 void wxFont::Unshare()
762 // Don't change shared data
765 m_refData
= new wxFontRefData();
769 wxFontRefData
* ref
= new wxFontRefData(*M_FONTDATA
);
775 // ----------------------------------------------------------------------------
776 // change font attribute: we recreate font when doing it
777 // ----------------------------------------------------------------------------
779 void wxFont::SetPointSize(int pointSize
)
783 M_FONTDATA
->SetPointSize(pointSize
);
788 void wxFont::SetFamily(int family
)
792 M_FONTDATA
->SetFamily(family
);
797 void wxFont::SetStyle(int style
)
801 M_FONTDATA
->SetStyle(style
);
806 void wxFont::SetWeight(int weight
)
810 M_FONTDATA
->SetWeight(weight
);
815 void wxFont::SetFaceName(const wxString
& faceName
)
819 M_FONTDATA
->SetFaceName(faceName
);
824 void wxFont::SetUnderlined(bool underlined
)
828 M_FONTDATA
->SetUnderlined(underlined
);
833 void wxFont::SetEncoding(wxFontEncoding encoding
)
837 M_FONTDATA
->SetEncoding(encoding
);
842 void wxFont::SetNativeFontInfo(const wxNativeFontInfo
& info
)
848 *M_FONTDATA
= wxFontRefData(info
);
853 // ----------------------------------------------------------------------------
855 // ----------------------------------------------------------------------------
857 int wxFont::GetPointSize() const
859 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
861 return M_FONTDATA
->GetPointSize();
864 int wxFont::GetFamily() const
866 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
868 return M_FONTDATA
->GetFamily();
871 int wxFont::GetStyle() const
873 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
875 return M_FONTDATA
->GetStyle();
878 int wxFont::GetWeight() const
880 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
882 return M_FONTDATA
->GetWeight();
885 bool wxFont::GetUnderlined() const
887 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid font") );
889 return M_FONTDATA
->GetUnderlined();
892 wxString
wxFont::GetFaceName() const
894 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
896 return M_FONTDATA
->GetFaceName();
899 wxFontEncoding
wxFont::GetEncoding() const
901 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT
, wxT("invalid font") );
903 return M_FONTDATA
->GetEncoding();
906 wxNativeFontInfo
*wxFont::GetNativeFontInfo() const
908 if ( M_FONTDATA
->HasNativeFontInfo() )
909 return new wxNativeFontInfo(M_FONTDATA
->GetNativeFontInfo());
914 bool wxFont::IsFixedWidth() const
916 if ( M_FONTDATA
->HasNativeFontInfo() )
918 // the two low-order bits specify the pitch of the font, the rest is
920 BYTE pitch
= M_FONTDATA
->GetNativeFontInfo().
921 lf
.lfPitchAndFamily
& PITCH_MASK
;
923 return pitch
== FIXED_PITCH
;
926 return wxFontBase::IsFixedWidth();