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 // ----------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "font.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
38 #include "wx/encinfo.h"
41 #include "wx/msw/private.h"
43 #include "wx/fontutil.h"
44 #include "wx/fontmap.h"
46 #include "wx/tokenzr.h"
48 #if wxUSE_EXTENDED_RTTI
50 wxBEGIN_ENUM( wxFontFamily
)
51 wxENUM_MEMBER( wxDEFAULT
)
52 wxENUM_MEMBER( wxDECORATIVE
)
53 wxENUM_MEMBER( wxROMAN
)
54 wxENUM_MEMBER( wxSCRIPT
)
55 wxENUM_MEMBER( wxSWISS
)
56 wxENUM_MEMBER( wxMODERN
)
57 wxENUM_MEMBER( wxTELETYPE
)
58 wxEND_ENUM( wxFontFamily
)
60 wxBEGIN_ENUM( wxFontStyle
)
61 wxENUM_MEMBER( wxNORMAL
)
62 wxENUM_MEMBER( wxITALIC
)
63 wxENUM_MEMBER( wxSLANT
)
64 wxEND_ENUM( wxFontStyle
)
66 wxBEGIN_ENUM( wxFontWeight
)
67 wxENUM_MEMBER( wxNORMAL
)
68 wxENUM_MEMBER( wxLIGHT
)
69 wxENUM_MEMBER( wxBOLD
)
70 wxEND_ENUM( wxFontWeight
)
72 IMPLEMENT_DYNAMIC_CLASS_WITH_COPY_XTI(wxFont
, wxGDIObject
,"wx/font.h")
74 wxBEGIN_PROPERTIES_TABLE(wxFont
)
75 wxPROPERTY( Size
,int, SetPointSize
, GetPointSize
, 12 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
76 wxPROPERTY( Family
, int , SetFamily
, GetFamily
, (int)wxDEFAULT
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // wxFontFamily
77 wxPROPERTY( Style
, int , SetStyle
, GetStyle
, (int)wxNORMAL
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // wxFontStyle
78 wxPROPERTY( Weight
, int , SetWeight
, GetWeight
, (int)wxNORMAL
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // wxFontWeight
79 wxPROPERTY( Underlined
, bool , SetUnderlined
, GetUnderlined
, false , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
80 wxPROPERTY( Face
, wxString
, SetFaceName
, GetFaceName
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
81 wxPROPERTY( Encoding
, wxFontEncoding
, SetEncoding
, GetEncoding
, wxFONTENCODING_DEFAULT
, 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
82 wxEND_PROPERTIES_TABLE()
84 wxCONSTRUCTOR_6( wxFont
, int , Size
, int , Family
, int , Style
, int , Weight
, bool , Underlined
, wxString
, Face
)
86 wxBEGIN_HANDLERS_TABLE(wxFont
)
87 wxEND_HANDLERS_TABLE()
90 IMPLEMENT_DYNAMIC_CLASS(wxFont
, wxGDIObject
)
94 // ----------------------------------------------------------------------------
96 // ----------------------------------------------------------------------------
98 // the mask used to extract the pitch from LOGFONT::lfPitchAndFamily field
99 static const int PITCH_MASK
= FIXED_PITCH
| VARIABLE_PITCH
;
101 // ----------------------------------------------------------------------------
102 // wxFontRefData - the internal description of the font
103 // ----------------------------------------------------------------------------
105 class WXDLLEXPORT wxFontRefData
: public wxGDIRefData
111 Init(-1, wxFONTFAMILY_DEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
,
112 FALSE
, wxEmptyString
, wxFONTENCODING_DEFAULT
);
115 wxFontRefData(int size
,
120 const wxString
& faceName
,
121 wxFontEncoding encoding
)
123 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
126 wxFontRefData(const wxNativeFontInfo
& info
, WXHFONT hFont
= 0)
131 wxFontRefData(const wxFontRefData
& data
)
133 if ( data
.m_nativeFontInfoOk
)
135 Init(data
.m_nativeFontInfo
);
139 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
140 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
144 virtual ~wxFontRefData();
147 bool Alloc(wxFont
*font
);
151 // all wxFont accessors
152 int GetPointSize() const
154 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetPointSize()
158 int GetFamily() const
165 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetStyle()
169 int GetWeight() const
171 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetWeight()
175 bool GetUnderlined() const
177 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetUnderlined()
181 wxString
GetFaceName() const
184 if ( m_nativeFontInfoOk
)
185 s
= m_nativeFontInfo
.GetFaceName();
192 wxFontEncoding
GetEncoding() const
194 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetEncoding()
198 WXHFONT
GetHFONT() const { return m_hFont
; }
201 void SetPointSize(int pointSize
)
203 if ( m_nativeFontInfoOk
)
204 m_nativeFontInfo
.SetPointSize(pointSize
);
206 m_pointSize
= pointSize
;
209 void SetFamily(int family
)
214 void SetStyle(int style
)
216 if ( m_nativeFontInfoOk
)
217 m_nativeFontInfo
.SetStyle((wxFontStyle
)style
);
222 void SetWeight(int weight
)
224 if ( m_nativeFontInfoOk
)
225 m_nativeFontInfo
.SetWeight((wxFontWeight
)weight
);
230 void SetFaceName(const wxString
& faceName
)
232 if ( m_nativeFontInfoOk
)
233 m_nativeFontInfo
.SetFaceName(faceName
);
235 m_faceName
= faceName
;
238 void SetUnderlined(bool underlined
)
240 if ( m_nativeFontInfoOk
)
241 m_nativeFontInfo
.SetUnderlined(underlined
);
243 m_underlined
= underlined
;
246 void SetEncoding(wxFontEncoding encoding
)
248 if ( m_nativeFontInfoOk
)
249 m_nativeFontInfo
.SetEncoding(encoding
);
251 m_encoding
= encoding
;
254 // native font info tests
255 bool HasNativeFontInfo() const { return m_nativeFontInfoOk
; }
257 const wxNativeFontInfo
& GetNativeFontInfo() const
258 { return m_nativeFontInfo
; }
261 // common part of all ctors
267 const wxString
& faceName
,
268 wxFontEncoding encoding
);
270 void Init(const wxNativeFontInfo
& info
, WXHFONT hFont
= 0);
272 // font characterstics
279 wxFontEncoding m_encoding
;
281 // Windows font handle
285 wxNativeFontInfo m_nativeFontInfo
;
286 bool m_nativeFontInfoOk
;
289 // ============================================================================
291 // ============================================================================
293 // ----------------------------------------------------------------------------
295 // ----------------------------------------------------------------------------
297 void wxFontRefData::Init(int pointSize
,
302 const wxString
& faceName
,
303 wxFontEncoding encoding
)
306 m_pointSize
= pointSize
== -1 ? wxNORMAL_FONT
->GetPointSize() : pointSize
;
310 m_underlined
= underlined
;
311 m_faceName
= faceName
;
312 m_encoding
= encoding
;
316 m_nativeFontInfoOk
= FALSE
;
319 void wxFontRefData::Init(const wxNativeFontInfo
& info
, WXHFONT hFont
)
321 // hFont may be zero, or it be passed in case we really want to
322 // use the exact font created in the underlying system
323 // (for example where we can't guarantee conversion from HFONT
324 // to LOGFONT back to HFONT)
327 m_nativeFontInfoOk
= TRUE
;
328 m_nativeFontInfo
= info
;
329 // This is the best we can do since we don't have the
330 // correct information at this point.
334 wxFontRefData::~wxFontRefData()
339 bool wxFontRefData::Alloc(wxFont
*font
)
341 if ( !m_nativeFontInfoOk
)
343 wxFillLogFont(&m_nativeFontInfo
.lf
, font
);
344 m_nativeFontInfoOk
= TRUE
;
347 HFONT hfont
= ::CreateFontIndirect(&m_nativeFontInfo
.lf
);
350 wxLogLastError(wxT("CreateFont"));
355 m_hFont
= (WXHFONT
)hfont
;
360 void wxFontRefData::Free()
364 if ( !::DeleteObject((HFONT
) m_hFont
) )
366 wxLogLastError(wxT("DeleteObject(font)"));
373 // ----------------------------------------------------------------------------
375 // ----------------------------------------------------------------------------
377 void wxNativeFontInfo::Init()
382 int wxNativeFontInfo::GetPointSize() const
384 // FIXME: using the screen here results in incorrect font size calculation
386 const int ppInch
= ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY
);
388 return (int) (((72.0*(double)abs(lf
.lfHeight
)) / (double) ppInch
) + 0.5);
391 wxFontStyle
wxNativeFontInfo::GetStyle() const
393 return lf
.lfItalic
? wxFONTSTYLE_ITALIC
: wxFONTSTYLE_NORMAL
;
396 wxFontWeight
wxNativeFontInfo::GetWeight() const
398 if ( lf
.lfWeight
<= 300 )
399 return wxFONTWEIGHT_LIGHT
;
401 if ( lf
.lfWeight
>= 600 )
402 return wxFONTWEIGHT_BOLD
;
404 return wxFONTWEIGHT_NORMAL
;
407 bool wxNativeFontInfo::GetUnderlined() const
409 return lf
.lfUnderline
!= 0;
412 wxString
wxNativeFontInfo::GetFaceName() const
414 return lf
.lfFaceName
;
417 wxFontFamily
wxNativeFontInfo::GetFamily() const
421 // extract family from pitch-and-family
422 switch ( lf
.lfPitchAndFamily
& ~PITCH_MASK
)
425 family
= wxFONTFAMILY_ROMAN
;
429 wxFAIL_MSG( _T("unknown LOGFONT::lfFamily value") );
433 family
= wxFONTFAMILY_SWISS
;
437 family
= wxFONTFAMILY_SCRIPT
;
441 family
= wxFONTFAMILY_MODERN
;
445 family
= wxFONTFAMILY_DECORATIVE
;
452 wxFontEncoding
wxNativeFontInfo::GetEncoding() const
454 return wxGetFontEncFromCharSet(lf
.lfCharSet
);
457 void wxNativeFontInfo::SetPointSize(int pointsize
)
459 #if wxFONT_SIZE_COMPATIBILITY
460 // Incorrect, but compatible with old wxWindows behaviour
461 lf
.lfHeight
= (pointSize
*ppInch
)/72;
462 #else // wxFONT_SIZE_COMPATIBILITY
463 // FIXME: using the screen here results in incorrect font size calculation
465 const int ppInch
= ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY
);
467 lf
.lfHeight
= -(int)((pointsize
*((double)ppInch
)/72.0) + 0.5);
468 #endif // wxFONT_SIZE_COMPATIBILITY/!wxFONT_SIZE_COMPATIBILITY
471 void wxNativeFontInfo::SetStyle(wxFontStyle style
)
476 wxFAIL_MSG( _T("unknown font style") );
479 case wxFONTSTYLE_NORMAL
:
483 case wxFONTSTYLE_ITALIC
:
484 case wxFONTSTYLE_SLANT
:
490 void wxNativeFontInfo::SetWeight(wxFontWeight weight
)
495 wxFAIL_MSG( _T("unknown font weight") );
498 case wxFONTWEIGHT_NORMAL
:
499 lf
.lfWeight
= FW_NORMAL
;
502 case wxFONTWEIGHT_LIGHT
:
503 lf
.lfWeight
= FW_LIGHT
;
506 case wxFONTWEIGHT_BOLD
:
507 lf
.lfWeight
= FW_BOLD
;
512 void wxNativeFontInfo::SetUnderlined(bool underlined
)
514 lf
.lfUnderline
= underlined
;
517 void wxNativeFontInfo::SetFaceName(wxString facename
)
519 wxStrncpy(lf
.lfFaceName
, facename
, WXSIZEOF(lf
.lfFaceName
));
522 void wxNativeFontInfo::SetFamily(wxFontFamily family
)
530 ff_family
= FF_SCRIPT
;
531 facename
= _T("Script");
535 ff_family
= FF_DECORATIVE
;
536 facename
= _T("Old English Text MT");
540 ff_family
= FF_ROMAN
;
541 facename
= _T("Times New Roman");
546 ff_family
= FF_MODERN
;
547 facename
= _T("Courier New");
551 ff_family
= FF_SWISS
;
552 facename
= _T("Arial");
557 ff_family
= FF_SWISS
;
558 facename
= _T("MS Sans Serif");
561 lf
.lfPitchAndFamily
= DEFAULT_PITCH
| ff_family
;
563 if ( !wxStrlen(lf
.lfFaceName
) )
565 SetFaceName(facename
);
569 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding
)
571 wxNativeEncodingInfo info
;
572 if ( !wxGetNativeFontEncoding(encoding
, &info
) )
575 if ( wxFontMapper::Get()->GetAltForEncoding(encoding
, &info
) )
577 if ( !info
.facename
.empty() )
579 // if we have this encoding only in some particular facename, use
580 // the facename - it is better to show the correct characters in a
581 // wrong facename than unreadable text in a correct one
582 SetFaceName(info
.facename
);
586 #endif // wxUSE_FONTMAP
588 // unsupported encoding, replace with the default
589 info
.charset
= DEFAULT_CHARSET
;
593 lf
.lfCharSet
= info
.charset
;
596 bool wxNativeFontInfo::FromString(const wxString
& s
)
600 wxStringTokenizer
tokenizer(s
, _T(";"));
603 wxString token
= tokenizer
.GetNextToken();
604 if ( token
!= _T('0') )
607 token
= tokenizer
.GetNextToken();
608 if ( !token
.ToLong(&l
) )
612 token
= tokenizer
.GetNextToken();
613 if ( !token
.ToLong(&l
) )
617 token
= tokenizer
.GetNextToken();
618 if ( !token
.ToLong(&l
) )
622 token
= tokenizer
.GetNextToken();
623 if ( !token
.ToLong(&l
) )
625 lf
.lfOrientation
= l
;
627 token
= tokenizer
.GetNextToken();
628 if ( !token
.ToLong(&l
) )
632 token
= tokenizer
.GetNextToken();
633 if ( !token
.ToLong(&l
) )
635 lf
.lfItalic
= (BYTE
)l
;
637 token
= tokenizer
.GetNextToken();
638 if ( !token
.ToLong(&l
) )
640 lf
.lfUnderline
= (BYTE
)l
;
642 token
= tokenizer
.GetNextToken();
643 if ( !token
.ToLong(&l
) )
645 lf
.lfStrikeOut
= (BYTE
)l
;
647 token
= tokenizer
.GetNextToken();
648 if ( !token
.ToLong(&l
) )
650 lf
.lfCharSet
= (BYTE
)l
;
652 token
= tokenizer
.GetNextToken();
653 if ( !token
.ToLong(&l
) )
655 lf
.lfOutPrecision
= (BYTE
)l
;
657 token
= tokenizer
.GetNextToken();
658 if ( !token
.ToLong(&l
) )
660 lf
.lfClipPrecision
= (BYTE
)l
;
662 token
= tokenizer
.GetNextToken();
663 if ( !token
.ToLong(&l
) )
665 lf
.lfQuality
= (BYTE
)l
;
667 token
= tokenizer
.GetNextToken();
668 if ( !token
.ToLong(&l
) )
670 lf
.lfPitchAndFamily
= (BYTE
)l
;
672 token
= tokenizer
.GetNextToken();
675 wxStrcpy(lf
.lfFaceName
, token
.c_str());
680 wxString
wxNativeFontInfo::ToString() const
684 s
.Printf(_T("%d;%ld;%ld;%ld;%ld;%ld;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
685 0, // version, in case we want to change the format later
704 // ----------------------------------------------------------------------------
706 // ----------------------------------------------------------------------------
712 bool wxFont::Create(const wxNativeFontInfo
& info
, WXHFONT hFont
)
716 m_refData
= new wxFontRefData(info
, hFont
);
723 wxFont::wxFont(const wxString
& fontdesc
)
725 wxNativeFontInfo info
;
726 if ( info
.FromString(fontdesc
) )
730 /* Constructor for a font. Note that the real construction is done
731 * in wxDC::SetFont, when information is available about scaling etc.
733 bool wxFont::Create(int pointSize
,
738 const wxString
& faceName
,
739 wxFontEncoding encoding
)
743 // wxDEFAULT is a valid value for the font size too so we must treat it
744 // specially here (otherwise the size would be 70 == wxDEFAULT value)
745 if ( pointSize
== wxDEFAULT
)
747 pointSize
= wxNORMAL_FONT
->GetPointSize();
750 m_refData
= new wxFontRefData(pointSize
, family
, style
, weight
,
751 underlined
, faceName
, encoding
);
762 // ----------------------------------------------------------------------------
763 // real implementation
764 // ----------------------------------------------------------------------------
766 bool wxFont::RealizeResource()
768 if ( GetResourceHandle() )
770 // VZ: the old code returned FALSE in this case, but it doesn't seem
771 // to make sense because the font _was_ created
775 return M_FONTDATA
->Alloc(this);
778 bool wxFont::FreeResource(bool WXUNUSED(force
))
780 if ( GetResourceHandle() )
790 WXHANDLE
wxFont::GetResourceHandle() const
792 return (WXHANDLE
)GetHFONT();
795 WXHFONT
wxFont::GetHFONT() const
797 return M_FONTDATA
? M_FONTDATA
->GetHFONT() : 0;
800 bool wxFont::IsFree() const
802 return M_FONTDATA
&& (M_FONTDATA
->GetHFONT() == 0);
805 void wxFont::Unshare()
807 // Don't change shared data
810 m_refData
= new wxFontRefData();
814 wxFontRefData
* ref
= new wxFontRefData(*M_FONTDATA
);
820 // ----------------------------------------------------------------------------
821 // change font attribute: we recreate font when doing it
822 // ----------------------------------------------------------------------------
824 void wxFont::SetPointSize(int pointSize
)
828 M_FONTDATA
->SetPointSize(pointSize
);
833 void wxFont::SetFamily(int family
)
837 M_FONTDATA
->SetFamily(family
);
842 void wxFont::SetStyle(int style
)
846 M_FONTDATA
->SetStyle(style
);
851 void wxFont::SetWeight(int weight
)
855 M_FONTDATA
->SetWeight(weight
);
860 void wxFont::SetFaceName(const wxString
& faceName
)
864 M_FONTDATA
->SetFaceName(faceName
);
869 void wxFont::SetUnderlined(bool underlined
)
873 M_FONTDATA
->SetUnderlined(underlined
);
878 void wxFont::SetEncoding(wxFontEncoding encoding
)
882 M_FONTDATA
->SetEncoding(encoding
);
887 void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo
& info
)
893 *M_FONTDATA
= wxFontRefData(info
);
898 // ----------------------------------------------------------------------------
900 // ----------------------------------------------------------------------------
902 int wxFont::GetPointSize() const
904 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
906 return M_FONTDATA
->GetPointSize();
909 int wxFont::GetFamily() const
911 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
913 return M_FONTDATA
->GetFamily();
916 int wxFont::GetStyle() const
918 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
920 return M_FONTDATA
->GetStyle();
923 int wxFont::GetWeight() const
925 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
927 return M_FONTDATA
->GetWeight();
930 bool wxFont::GetUnderlined() const
932 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid font") );
934 return M_FONTDATA
->GetUnderlined();
937 wxString
wxFont::GetFaceName() const
939 wxCHECK_MSG( Ok(), wxEmptyString
, wxT("invalid font") );
941 return M_FONTDATA
->GetFaceName();
944 wxFontEncoding
wxFont::GetEncoding() const
946 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT
, wxT("invalid font") );
948 return M_FONTDATA
->GetEncoding();
951 wxNativeFontInfo
*wxFont::GetNativeFontInfo() const
953 if ( M_FONTDATA
->HasNativeFontInfo() )
954 return new wxNativeFontInfo(M_FONTDATA
->GetNativeFontInfo());
959 bool wxFont::IsFixedWidth() const
961 if ( M_FONTDATA
->HasNativeFontInfo() )
963 // the two low-order bits specify the pitch of the font, the rest is
965 BYTE pitch
= M_FONTDATA
->GetNativeFontInfo().
966 lf
.lfPitchAndFamily
& PITCH_MASK
;
968 return pitch
== FIXED_PITCH
;
971 return wxFontBase::IsFixedWidth();