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"
40 #include "wx/msw/private.h"
42 #include "wx/fontutil.h"
43 #include "wx/fontmap.h"
45 #include "wx/tokenzr.h"
47 #if wxUSE_EXTENDED_RTTI
49 WX_BEGIN_ENUM( wxFontFamily
)
50 WX_ENUM_MEMBER( wxDEFAULT
)
51 WX_ENUM_MEMBER( wxDECORATIVE
)
52 WX_ENUM_MEMBER( wxROMAN
)
53 WX_ENUM_MEMBER( wxSCRIPT
)
54 WX_ENUM_MEMBER( wxSWISS
)
55 WX_ENUM_MEMBER( wxMODERN
)
56 WX_ENUM_MEMBER( wxTELETYPE
)
57 WX_END_ENUM( wxFontFamily
)
59 WX_BEGIN_ENUM( wxFontStyle
)
60 WX_ENUM_MEMBER( wxNORMAL
)
61 WX_ENUM_MEMBER( wxITALIC
)
62 WX_ENUM_MEMBER( wxSLANT
)
63 WX_END_ENUM( wxFontStyle
)
65 WX_BEGIN_ENUM( wxFontWeight
)
66 WX_ENUM_MEMBER( wxNORMAL
)
67 WX_ENUM_MEMBER( wxLIGHT
)
68 WX_ENUM_MEMBER( wxBOLD
)
69 WX_END_ENUM( wxFontWeight
)
71 IMPLEMENT_DYNAMIC_CLASS_WITH_COPY_XTI(wxFont
, wxGDIObject
,"wx/font.h")
73 WX_BEGIN_PROPERTIES_TABLE(wxFont
)
74 WX_PROPERTY( Size
,int, SetPointSize
, GetPointSize
, 12 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
75 WX_PROPERTY( Family
, int , SetFamily
, GetFamily
, (int)wxDEFAULT
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // wxFontFamily
76 WX_PROPERTY( Style
, int , SetStyle
, GetStyle
, (int)wxNORMAL
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // wxFontStyle
77 WX_PROPERTY( Weight
, int , SetWeight
, GetWeight
, (int)wxNORMAL
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // wxFontWeight
78 WX_PROPERTY( Underlined
, bool , SetUnderlined
, GetUnderlined
, false , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
79 WX_PROPERTY( Face
, wxString
, SetFaceName
, GetFaceName
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
80 WX_PROPERTY( Encoding
, wxFontEncoding
, SetEncoding
, GetEncoding
, wxFONTENCODING_DEFAULT
, 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
81 WX_END_PROPERTIES_TABLE()
83 WX_CONSTRUCTOR_6( wxFont
, int , Size
, int , Family
, int , Style
, int , Weight
, bool , Underlined
, wxString
, Face
)
85 WX_BEGIN_HANDLERS_TABLE(wxFont
)
86 WX_END_HANDLERS_TABLE()
89 IMPLEMENT_DYNAMIC_CLASS(wxFont
, wxGDIObject
)
93 // ----------------------------------------------------------------------------
95 // ----------------------------------------------------------------------------
97 // the mask used to extract the pitch from LOGFONT::lfPitchAndFamily field
98 static const int PITCH_MASK
= FIXED_PITCH
| VARIABLE_PITCH
;
100 // ----------------------------------------------------------------------------
101 // wxFontRefData - the internal description of the font
102 // ----------------------------------------------------------------------------
104 class WXDLLEXPORT wxFontRefData
: public wxGDIRefData
110 Init(-1, wxFONTFAMILY_DEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
,
111 FALSE
, wxEmptyString
, wxFONTENCODING_DEFAULT
);
114 wxFontRefData(int size
,
119 const wxString
& faceName
,
120 wxFontEncoding encoding
)
122 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
125 wxFontRefData(const wxNativeFontInfo
& info
, WXHFONT hFont
= 0)
130 wxFontRefData(const wxFontRefData
& data
)
132 if ( data
.m_nativeFontInfoOk
)
134 Init(data
.m_nativeFontInfo
);
138 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
139 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
143 virtual ~wxFontRefData();
146 bool Alloc(wxFont
*font
);
150 // all wxFont accessors
151 int GetPointSize() const
153 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetPointSize()
157 int GetFamily() const
164 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetStyle()
168 int GetWeight() const
170 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetWeight()
174 bool GetUnderlined() const
176 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetUnderlined()
180 wxString
GetFaceName() const
183 if ( m_nativeFontInfoOk
)
184 s
= m_nativeFontInfo
.GetFaceName();
191 wxFontEncoding
GetEncoding() const
193 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetEncoding()
197 WXHFONT
GetHFONT() const { return m_hFont
; }
200 void SetPointSize(int pointSize
)
202 if ( m_nativeFontInfoOk
)
203 m_nativeFontInfo
.SetPointSize(pointSize
);
205 m_pointSize
= pointSize
;
208 void SetFamily(int family
)
213 void SetStyle(int style
)
215 if ( m_nativeFontInfoOk
)
216 m_nativeFontInfo
.SetStyle((wxFontStyle
)style
);
221 void SetWeight(int weight
)
223 if ( m_nativeFontInfoOk
)
224 m_nativeFontInfo
.SetWeight((wxFontWeight
)weight
);
229 void SetFaceName(const wxString
& faceName
)
231 if ( m_nativeFontInfoOk
)
232 m_nativeFontInfo
.SetFaceName(faceName
);
234 m_faceName
= faceName
;
237 void SetUnderlined(bool underlined
)
239 if ( m_nativeFontInfoOk
)
240 m_nativeFontInfo
.SetUnderlined(underlined
);
242 m_underlined
= underlined
;
245 void SetEncoding(wxFontEncoding encoding
)
247 if ( m_nativeFontInfoOk
)
248 m_nativeFontInfo
.SetEncoding(encoding
);
250 m_encoding
= encoding
;
253 // native font info tests
254 bool HasNativeFontInfo() const { return m_nativeFontInfoOk
; }
256 const wxNativeFontInfo
& GetNativeFontInfo() const
257 { return m_nativeFontInfo
; }
260 // common part of all ctors
266 const wxString
& faceName
,
267 wxFontEncoding encoding
);
269 void Init(const wxNativeFontInfo
& info
, WXHFONT hFont
= 0);
271 // font characterstics
278 wxFontEncoding m_encoding
;
280 // Windows font handle
284 wxNativeFontInfo m_nativeFontInfo
;
285 bool m_nativeFontInfoOk
;
288 // ============================================================================
290 // ============================================================================
292 // ----------------------------------------------------------------------------
294 // ----------------------------------------------------------------------------
296 void wxFontRefData::Init(int pointSize
,
301 const wxString
& faceName
,
302 wxFontEncoding encoding
)
305 m_pointSize
= pointSize
== -1 ? wxNORMAL_FONT
->GetPointSize() : pointSize
;
309 m_underlined
= underlined
;
310 m_faceName
= faceName
;
311 m_encoding
= encoding
;
315 m_nativeFontInfoOk
= FALSE
;
318 void wxFontRefData::Init(const wxNativeFontInfo
& info
, WXHFONT hFont
)
320 // hFont may be zero, or it be passed in case we really want to
321 // use the exact font created in the underlying system
322 // (for example where we can't guarantee conversion from HFONT
323 // to LOGFONT back to HFONT)
326 m_nativeFontInfoOk
= TRUE
;
327 m_nativeFontInfo
= info
;
328 // This is the best we can do since we don't have the
329 // correct information at this point.
333 wxFontRefData::~wxFontRefData()
338 bool wxFontRefData::Alloc(wxFont
*font
)
340 if ( !m_nativeFontInfoOk
)
342 wxFillLogFont(&m_nativeFontInfo
.lf
, font
);
343 m_nativeFontInfoOk
= TRUE
;
346 HFONT hfont
= ::CreateFontIndirect(&m_nativeFontInfo
.lf
);
349 wxLogLastError(wxT("CreateFont"));
354 m_hFont
= (WXHFONT
)hfont
;
359 void wxFontRefData::Free()
363 if ( !::DeleteObject((HFONT
) m_hFont
) )
365 wxLogLastError(wxT("DeleteObject(font)"));
372 // ----------------------------------------------------------------------------
374 // ----------------------------------------------------------------------------
376 void wxNativeFontInfo::Init()
381 int wxNativeFontInfo::GetPointSize() const
383 // FIXME: using the screen here results in incorrect font size calculation
385 const int ppInch
= ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY
);
387 return (int) (((72.0*(double)abs(lf
.lfHeight
)) / (double) ppInch
) + 0.5);
390 wxFontStyle
wxNativeFontInfo::GetStyle() const
392 return lf
.lfItalic
? wxFONTSTYLE_ITALIC
: wxFONTSTYLE_NORMAL
;
395 wxFontWeight
wxNativeFontInfo::GetWeight() const
397 if ( lf
.lfWeight
<= 300 )
398 return wxFONTWEIGHT_LIGHT
;
400 if ( lf
.lfWeight
>= 600 )
401 return wxFONTWEIGHT_BOLD
;
403 return wxFONTWEIGHT_NORMAL
;
406 bool wxNativeFontInfo::GetUnderlined() const
408 return lf
.lfUnderline
!= 0;
411 wxString
wxNativeFontInfo::GetFaceName() const
413 return lf
.lfFaceName
;
416 wxFontFamily
wxNativeFontInfo::GetFamily() const
420 // extract family from pitch-and-family
421 switch ( lf
.lfPitchAndFamily
& ~PITCH_MASK
)
424 family
= wxFONTFAMILY_ROMAN
;
428 wxFAIL_MSG( _T("unknown LOGFONT::lfFamily value") );
432 family
= wxFONTFAMILY_SWISS
;
436 family
= wxFONTFAMILY_SCRIPT
;
440 family
= wxFONTFAMILY_MODERN
;
444 family
= wxFONTFAMILY_DECORATIVE
;
451 wxFontEncoding
wxNativeFontInfo::GetEncoding() const
453 return wxGetFontEncFromCharSet(lf
.lfCharSet
);
456 void wxNativeFontInfo::SetPointSize(int pointsize
)
458 #if wxFONT_SIZE_COMPATIBILITY
459 // Incorrect, but compatible with old wxWindows behaviour
460 lf
.lfHeight
= (pointSize
*ppInch
)/72;
461 #else // wxFONT_SIZE_COMPATIBILITY
462 // FIXME: using the screen here results in incorrect font size calculation
464 const int ppInch
= ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY
);
466 lf
.lfHeight
= -(int)((pointsize
*((double)ppInch
)/72.0) + 0.5);
467 #endif // wxFONT_SIZE_COMPATIBILITY/!wxFONT_SIZE_COMPATIBILITY
470 void wxNativeFontInfo::SetStyle(wxFontStyle style
)
475 wxFAIL_MSG( _T("unknown font style") );
478 case wxFONTSTYLE_NORMAL
:
482 case wxFONTSTYLE_ITALIC
:
483 case wxFONTSTYLE_SLANT
:
489 void wxNativeFontInfo::SetWeight(wxFontWeight weight
)
494 wxFAIL_MSG( _T("unknown font weight") );
497 case wxFONTWEIGHT_NORMAL
:
498 lf
.lfWeight
= FW_NORMAL
;
501 case wxFONTWEIGHT_LIGHT
:
502 lf
.lfWeight
= FW_LIGHT
;
505 case wxFONTWEIGHT_BOLD
:
506 lf
.lfWeight
= FW_BOLD
;
511 void wxNativeFontInfo::SetUnderlined(bool underlined
)
513 lf
.lfUnderline
= underlined
;
516 void wxNativeFontInfo::SetFaceName(wxString facename
)
518 wxStrncpy(lf
.lfFaceName
, facename
, WXSIZEOF(lf
.lfFaceName
));
521 void wxNativeFontInfo::SetFamily(wxFontFamily family
)
529 ff_family
= FF_SCRIPT
;
530 facename
= _T("Script");
534 ff_family
= FF_DECORATIVE
;
535 facename
= _T("Old English Text MT");
539 ff_family
= FF_ROMAN
;
540 facename
= _T("Times New Roman");
545 ff_family
= FF_MODERN
;
546 facename
= _T("Courier New");
550 ff_family
= FF_SWISS
;
551 facename
= _T("Arial");
556 ff_family
= FF_SWISS
;
557 facename
= _T("MS Sans Serif");
560 lf
.lfPitchAndFamily
= DEFAULT_PITCH
| ff_family
;
562 if ( !wxStrlen(lf
.lfFaceName
) )
564 SetFaceName(facename
);
568 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding
)
570 wxNativeEncodingInfo info
;
571 if ( !wxGetNativeFontEncoding(encoding
, &info
) )
574 if ( wxFontMapper::Get()->GetAltForEncoding(encoding
, &info
) )
576 if ( !info
.facename
.empty() )
578 // if we have this encoding only in some particular facename, use
579 // the facename - it is better to show the correct characters in a
580 // wrong facename than unreadable text in a correct one
581 SetFaceName(info
.facename
);
585 #endif // wxUSE_FONTMAP
587 // unsupported encoding, replace with the default
588 info
.charset
= DEFAULT_CHARSET
;
592 lf
.lfCharSet
= info
.charset
;
595 bool wxNativeFontInfo::FromString(const wxString
& s
)
599 wxStringTokenizer
tokenizer(s
, _T(";"));
602 wxString token
= tokenizer
.GetNextToken();
603 if ( token
!= _T('0') )
606 token
= tokenizer
.GetNextToken();
607 if ( !token
.ToLong(&l
) )
611 token
= tokenizer
.GetNextToken();
612 if ( !token
.ToLong(&l
) )
616 token
= tokenizer
.GetNextToken();
617 if ( !token
.ToLong(&l
) )
621 token
= tokenizer
.GetNextToken();
622 if ( !token
.ToLong(&l
) )
624 lf
.lfOrientation
= l
;
626 token
= tokenizer
.GetNextToken();
627 if ( !token
.ToLong(&l
) )
631 token
= tokenizer
.GetNextToken();
632 if ( !token
.ToLong(&l
) )
634 lf
.lfItalic
= (BYTE
)l
;
636 token
= tokenizer
.GetNextToken();
637 if ( !token
.ToLong(&l
) )
639 lf
.lfUnderline
= (BYTE
)l
;
641 token
= tokenizer
.GetNextToken();
642 if ( !token
.ToLong(&l
) )
644 lf
.lfStrikeOut
= (BYTE
)l
;
646 token
= tokenizer
.GetNextToken();
647 if ( !token
.ToLong(&l
) )
649 lf
.lfCharSet
= (BYTE
)l
;
651 token
= tokenizer
.GetNextToken();
652 if ( !token
.ToLong(&l
) )
654 lf
.lfOutPrecision
= (BYTE
)l
;
656 token
= tokenizer
.GetNextToken();
657 if ( !token
.ToLong(&l
) )
659 lf
.lfClipPrecision
= (BYTE
)l
;
661 token
= tokenizer
.GetNextToken();
662 if ( !token
.ToLong(&l
) )
664 lf
.lfQuality
= (BYTE
)l
;
666 token
= tokenizer
.GetNextToken();
667 if ( !token
.ToLong(&l
) )
669 lf
.lfPitchAndFamily
= (BYTE
)l
;
671 token
= tokenizer
.GetNextToken();
674 wxStrcpy(lf
.lfFaceName
, token
.c_str());
679 wxString
wxNativeFontInfo::ToString() const
683 s
.Printf(_T("%d;%ld;%ld;%ld;%ld;%ld;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
684 0, // version, in case we want to change the format later
703 // ----------------------------------------------------------------------------
705 // ----------------------------------------------------------------------------
711 bool wxFont::Create(const wxNativeFontInfo
& info
, WXHFONT hFont
)
715 m_refData
= new wxFontRefData(info
, hFont
);
722 wxFont::wxFont(const wxString
& fontdesc
)
724 wxNativeFontInfo info
;
725 if ( info
.FromString(fontdesc
) )
729 /* Constructor for a font. Note that the real construction is done
730 * in wxDC::SetFont, when information is available about scaling etc.
732 bool wxFont::Create(int pointSize
,
737 const wxString
& faceName
,
738 wxFontEncoding encoding
)
742 // wxDEFAULT is a valid value for the font size too so we must treat it
743 // specially here (otherwise the size would be 70 == wxDEFAULT value)
744 if ( pointSize
== wxDEFAULT
)
746 pointSize
= wxNORMAL_FONT
->GetPointSize();
749 m_refData
= new wxFontRefData(pointSize
, family
, style
, weight
,
750 underlined
, faceName
, encoding
);
761 // ----------------------------------------------------------------------------
762 // real implementation
763 // ----------------------------------------------------------------------------
765 bool wxFont::RealizeResource()
767 if ( GetResourceHandle() )
769 // VZ: the old code returned FALSE in this case, but it doesn't seem
770 // to make sense because the font _was_ created
774 return M_FONTDATA
->Alloc(this);
777 bool wxFont::FreeResource(bool WXUNUSED(force
))
779 if ( GetResourceHandle() )
789 WXHANDLE
wxFont::GetResourceHandle() const
791 return (WXHANDLE
)GetHFONT();
794 WXHFONT
wxFont::GetHFONT() const
796 return M_FONTDATA
? M_FONTDATA
->GetHFONT() : 0;
799 bool wxFont::IsFree() const
801 return M_FONTDATA
&& (M_FONTDATA
->GetHFONT() == 0);
804 void wxFont::Unshare()
806 // Don't change shared data
809 m_refData
= new wxFontRefData();
813 wxFontRefData
* ref
= new wxFontRefData(*M_FONTDATA
);
819 // ----------------------------------------------------------------------------
820 // change font attribute: we recreate font when doing it
821 // ----------------------------------------------------------------------------
823 void wxFont::SetPointSize(int pointSize
)
827 M_FONTDATA
->SetPointSize(pointSize
);
832 void wxFont::SetFamily(int family
)
836 M_FONTDATA
->SetFamily(family
);
841 void wxFont::SetStyle(int style
)
845 M_FONTDATA
->SetStyle(style
);
850 void wxFont::SetWeight(int weight
)
854 M_FONTDATA
->SetWeight(weight
);
859 void wxFont::SetFaceName(const wxString
& faceName
)
863 M_FONTDATA
->SetFaceName(faceName
);
868 void wxFont::SetUnderlined(bool underlined
)
872 M_FONTDATA
->SetUnderlined(underlined
);
877 void wxFont::SetEncoding(wxFontEncoding encoding
)
881 M_FONTDATA
->SetEncoding(encoding
);
886 void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo
& info
)
892 *M_FONTDATA
= wxFontRefData(info
);
897 // ----------------------------------------------------------------------------
899 // ----------------------------------------------------------------------------
901 int wxFont::GetPointSize() const
903 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
905 return M_FONTDATA
->GetPointSize();
908 int wxFont::GetFamily() const
910 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
912 return M_FONTDATA
->GetFamily();
915 int wxFont::GetStyle() const
917 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
919 return M_FONTDATA
->GetStyle();
922 int wxFont::GetWeight() const
924 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
926 return M_FONTDATA
->GetWeight();
929 bool wxFont::GetUnderlined() const
931 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid font") );
933 return M_FONTDATA
->GetUnderlined();
936 wxString
wxFont::GetFaceName() const
938 wxCHECK_MSG( Ok(), wxEmptyString
, wxT("invalid font") );
940 return M_FONTDATA
->GetFaceName();
943 wxFontEncoding
wxFont::GetEncoding() const
945 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT
, wxT("invalid font") );
947 return M_FONTDATA
->GetEncoding();
950 wxNativeFontInfo
*wxFont::GetNativeFontInfo() const
952 if ( M_FONTDATA
->HasNativeFontInfo() )
953 return new wxNativeFontInfo(M_FONTDATA
->GetNativeFontInfo());
958 bool wxFont::IsFixedWidth() const
960 if ( M_FONTDATA
->HasNativeFontInfo() )
962 // the two low-order bits specify the pitch of the font, the rest is
964 BYTE pitch
= M_FONTDATA
->GetNativeFontInfo().
965 lf
.lfPitchAndFamily
& PITCH_MASK
;
967 return pitch
== FIXED_PITCH
;
970 return wxFontBase::IsFixedWidth();