1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/font.cpp
3 // Purpose: wxFont class
4 // Author: Julian Smart
8 // Copyright: (c) wxWidgets 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
, EMPTY_MACROVALUE
, 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, wxSize(0, 0), FALSE
, wxFONTFAMILY_DEFAULT
, wxFONTSTYLE_NORMAL
,
112 wxFONTWEIGHT_NORMAL
, FALSE
, wxEmptyString
,
113 wxFONTENCODING_DEFAULT
);
116 wxFontRefData(int size
,
117 const wxSize
& pixelSize
,
118 bool sizeUsingPixels
,
123 const wxString
& faceName
,
124 wxFontEncoding encoding
)
126 Init(size
, pixelSize
, sizeUsingPixels
, family
, style
, weight
,
127 underlined
, faceName
, encoding
);
130 wxFontRefData(const wxNativeFontInfo
& info
, WXHFONT hFont
= 0)
135 wxFontRefData(const wxFontRefData
& data
)
137 if ( data
.m_nativeFontInfoOk
)
139 Init(data
.m_nativeFontInfo
);
143 Init(data
.m_pointSize
, data
.m_pixelSize
, data
.m_sizeUsingPixels
,
144 data
.m_family
, data
.m_style
, data
.m_weight
,
145 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
149 virtual ~wxFontRefData();
152 bool Alloc(wxFont
*font
);
156 // all wxFont accessors
157 int GetPointSize() const
159 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetPointSize()
163 wxSize
GetPixelSize() const
165 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetPixelSize()
169 bool IsUsingSizeInPixels() const
171 return m_nativeFontInfoOk
? true : m_sizeUsingPixels
;
174 int GetFamily() const
181 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetStyle()
185 int GetWeight() const
187 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetWeight()
191 bool GetUnderlined() const
193 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetUnderlined()
197 wxString
GetFaceName() const
200 if ( m_nativeFontInfoOk
)
201 s
= m_nativeFontInfo
.GetFaceName();
208 wxFontEncoding
GetEncoding() const
210 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetEncoding()
214 WXHFONT
GetHFONT() const { return m_hFont
; }
217 void SetPointSize(int pointSize
)
219 if ( m_nativeFontInfoOk
)
221 m_nativeFontInfo
.SetPointSize(pointSize
);
225 m_pointSize
= pointSize
;
226 m_sizeUsingPixels
= FALSE
;
230 void SetPixelSize(const wxSize
& pixelSize
)
232 if ( m_nativeFontInfoOk
)
234 m_nativeFontInfo
.SetPixelSize(pixelSize
);
238 m_pixelSize
= pixelSize
;
239 m_sizeUsingPixels
= TRUE
;
243 void SetFamily(int family
)
248 void SetStyle(int style
)
250 if ( m_nativeFontInfoOk
)
251 m_nativeFontInfo
.SetStyle((wxFontStyle
)style
);
256 void SetWeight(int weight
)
258 if ( m_nativeFontInfoOk
)
259 m_nativeFontInfo
.SetWeight((wxFontWeight
)weight
);
264 void SetFaceName(const wxString
& faceName
)
266 if ( m_nativeFontInfoOk
)
267 m_nativeFontInfo
.SetFaceName(faceName
);
269 m_faceName
= faceName
;
272 void SetUnderlined(bool underlined
)
274 if ( m_nativeFontInfoOk
)
275 m_nativeFontInfo
.SetUnderlined(underlined
);
277 m_underlined
= underlined
;
280 void SetEncoding(wxFontEncoding encoding
)
282 if ( m_nativeFontInfoOk
)
283 m_nativeFontInfo
.SetEncoding(encoding
);
285 m_encoding
= encoding
;
288 // native font info tests
289 bool HasNativeFontInfo() const { return m_nativeFontInfoOk
; }
291 const wxNativeFontInfo
& GetNativeFontInfo() const
292 { return m_nativeFontInfo
; }
295 // common part of all ctors
297 const wxSize
& pixelSize
,
298 bool sizeUsingPixels
,
303 const wxString
& faceName
,
304 wxFontEncoding encoding
);
306 void Init(const wxNativeFontInfo
& info
, WXHFONT hFont
= 0);
308 // font characterstics
311 bool m_sizeUsingPixels
;
317 wxFontEncoding m_encoding
;
319 // Windows font handle
323 wxNativeFontInfo m_nativeFontInfo
;
324 bool m_nativeFontInfoOk
;
327 // ============================================================================
329 // ============================================================================
331 // ----------------------------------------------------------------------------
333 // ----------------------------------------------------------------------------
335 void wxFontRefData::Init(int pointSize
,
336 const wxSize
& pixelSize
,
337 bool sizeUsingPixels
,
342 const wxString
& faceName
,
343 wxFontEncoding encoding
)
346 m_pointSize
= pointSize
== -1 ? wxNORMAL_FONT
->GetPointSize() : pointSize
;
347 m_pixelSize
= pixelSize
;
348 m_sizeUsingPixels
= sizeUsingPixels
;
352 m_underlined
= underlined
;
353 m_faceName
= faceName
;
354 m_encoding
= encoding
;
358 m_nativeFontInfoOk
= false;
361 void wxFontRefData::Init(const wxNativeFontInfo
& info
, WXHFONT hFont
)
363 // hFont may be zero, or it be passed in case we really want to
364 // use the exact font created in the underlying system
365 // (for example where we can't guarantee conversion from HFONT
366 // to LOGFONT back to HFONT)
369 m_nativeFontInfoOk
= true;
370 m_nativeFontInfo
= info
;
371 // This is the best we can do since we don't have the
372 // correct information at this point.
376 wxFontRefData::~wxFontRefData()
381 bool wxFontRefData::Alloc(wxFont
*font
)
383 if ( !m_nativeFontInfoOk
)
385 wxFillLogFont(&m_nativeFontInfo
.lf
, font
);
386 m_nativeFontInfoOk
= true;
389 HFONT hfont
= ::CreateFontIndirect(&m_nativeFontInfo
.lf
);
392 wxLogLastError(wxT("CreateFont"));
397 m_hFont
= (WXHFONT
)hfont
;
402 void wxFontRefData::Free()
406 if ( !::DeleteObject((HFONT
) m_hFont
) )
408 wxLogLastError(wxT("DeleteObject(font)"));
415 // ----------------------------------------------------------------------------
417 // ----------------------------------------------------------------------------
419 void wxNativeFontInfo::Init()
424 int wxNativeFontInfo::GetPointSize() const
426 // FIXME: using the screen here results in incorrect font size calculation
428 const int ppInch
= ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY
);
430 return (int) (((72.0*(double)abs(lf
.lfHeight
)) / (double) ppInch
) + 0.5);
433 wxSize
wxNativeFontInfo::GetPixelSize() const
436 ret
.SetHeight(lf
.lfHeight
);
437 ret
.SetWidth(lf
.lfWidth
);
441 wxFontStyle
wxNativeFontInfo::GetStyle() const
443 return lf
.lfItalic
? wxFONTSTYLE_ITALIC
: wxFONTSTYLE_NORMAL
;
446 wxFontWeight
wxNativeFontInfo::GetWeight() const
448 if ( lf
.lfWeight
<= 300 )
449 return wxFONTWEIGHT_LIGHT
;
451 if ( lf
.lfWeight
>= 600 )
452 return wxFONTWEIGHT_BOLD
;
454 return wxFONTWEIGHT_NORMAL
;
457 bool wxNativeFontInfo::GetUnderlined() const
459 return lf
.lfUnderline
!= 0;
462 wxString
wxNativeFontInfo::GetFaceName() const
464 return lf
.lfFaceName
;
467 wxFontFamily
wxNativeFontInfo::GetFamily() const
471 // extract family from pitch-and-family
472 switch ( lf
.lfPitchAndFamily
& ~PITCH_MASK
)
475 family
= wxFONTFAMILY_ROMAN
;
479 wxFAIL_MSG( _T("unknown LOGFONT::lfFamily value") );
483 family
= wxFONTFAMILY_SWISS
;
487 family
= wxFONTFAMILY_SCRIPT
;
491 family
= wxFONTFAMILY_MODERN
;
495 family
= wxFONTFAMILY_DECORATIVE
;
502 wxFontEncoding
wxNativeFontInfo::GetEncoding() const
504 return wxGetFontEncFromCharSet(lf
.lfCharSet
);
507 void wxNativeFontInfo::SetPointSize(int pointsize
)
509 #if wxFONT_SIZE_COMPATIBILITY
510 // Incorrect, but compatible with old wxWidgets behaviour
511 lf
.lfHeight
= (pointSize
*ppInch
)/72;
512 #else // wxFONT_SIZE_COMPATIBILITY
513 // FIXME: using the screen here results in incorrect font size calculation
515 const int ppInch
= ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY
);
517 lf
.lfHeight
= -(int)((pointsize
*((double)ppInch
)/72.0) + 0.5);
518 #endif // wxFONT_SIZE_COMPATIBILITY/!wxFONT_SIZE_COMPATIBILITY
521 void wxNativeFontInfo::SetPixelSize(const wxSize
& pixelSize
)
523 lf
.lfHeight
= pixelSize
.GetHeight();
524 lf
.lfWidth
= pixelSize
.GetWidth();
528 void wxNativeFontInfo::SetStyle(wxFontStyle style
)
533 wxFAIL_MSG( _T("unknown font style") );
536 case wxFONTSTYLE_NORMAL
:
540 case wxFONTSTYLE_ITALIC
:
541 case wxFONTSTYLE_SLANT
:
547 void wxNativeFontInfo::SetWeight(wxFontWeight weight
)
552 wxFAIL_MSG( _T("unknown font weight") );
555 case wxFONTWEIGHT_NORMAL
:
556 lf
.lfWeight
= FW_NORMAL
;
559 case wxFONTWEIGHT_LIGHT
:
560 lf
.lfWeight
= FW_LIGHT
;
563 case wxFONTWEIGHT_BOLD
:
564 lf
.lfWeight
= FW_BOLD
;
569 void wxNativeFontInfo::SetUnderlined(bool underlined
)
571 lf
.lfUnderline
= underlined
;
574 void wxNativeFontInfo::SetFaceName(wxString facename
)
576 wxStrncpy(lf
.lfFaceName
, facename
, WXSIZEOF(lf
.lfFaceName
));
579 void wxNativeFontInfo::SetFamily(wxFontFamily family
)
587 ff_family
= FF_SCRIPT
;
588 facename
= _T("Script");
592 ff_family
= FF_DECORATIVE
;
593 facename
= _T("Old English Text MT");
597 ff_family
= FF_ROMAN
;
598 facename
= _T("Times New Roman");
603 ff_family
= FF_MODERN
;
604 facename
= _T("Courier New");
608 ff_family
= FF_SWISS
;
609 facename
= _T("Arial");
614 ff_family
= FF_SWISS
;
615 facename
= _T("MS Sans Serif");
618 lf
.lfPitchAndFamily
= (BYTE
)(DEFAULT_PITCH
) | ff_family
;
620 if ( !wxStrlen(lf
.lfFaceName
) )
622 SetFaceName(facename
);
626 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding
)
628 wxNativeEncodingInfo info
;
629 if ( !wxGetNativeFontEncoding(encoding
, &info
) )
632 if ( wxFontMapper::Get()->GetAltForEncoding(encoding
, &info
) )
634 if ( !info
.facename
.empty() )
636 // if we have this encoding only in some particular facename, use
637 // the facename - it is better to show the correct characters in a
638 // wrong facename than unreadable text in a correct one
639 SetFaceName(info
.facename
);
643 #endif // wxUSE_FONTMAP
645 // unsupported encoding, replace with the default
646 info
.charset
= DEFAULT_CHARSET
;
650 lf
.lfCharSet
= (BYTE
)info
.charset
;
653 bool wxNativeFontInfo::FromString(const wxString
& s
)
657 wxStringTokenizer
tokenizer(s
, _T(";"));
660 wxString token
= tokenizer
.GetNextToken();
661 if ( token
!= _T('0') )
664 token
= tokenizer
.GetNextToken();
665 if ( !token
.ToLong(&l
) )
669 token
= tokenizer
.GetNextToken();
670 if ( !token
.ToLong(&l
) )
674 token
= tokenizer
.GetNextToken();
675 if ( !token
.ToLong(&l
) )
679 token
= tokenizer
.GetNextToken();
680 if ( !token
.ToLong(&l
) )
682 lf
.lfOrientation
= l
;
684 token
= tokenizer
.GetNextToken();
685 if ( !token
.ToLong(&l
) )
689 token
= tokenizer
.GetNextToken();
690 if ( !token
.ToLong(&l
) )
692 lf
.lfItalic
= (BYTE
)l
;
694 token
= tokenizer
.GetNextToken();
695 if ( !token
.ToLong(&l
) )
697 lf
.lfUnderline
= (BYTE
)l
;
699 token
= tokenizer
.GetNextToken();
700 if ( !token
.ToLong(&l
) )
702 lf
.lfStrikeOut
= (BYTE
)l
;
704 token
= tokenizer
.GetNextToken();
705 if ( !token
.ToLong(&l
) )
707 lf
.lfCharSet
= (BYTE
)l
;
709 token
= tokenizer
.GetNextToken();
710 if ( !token
.ToLong(&l
) )
712 lf
.lfOutPrecision
= (BYTE
)l
;
714 token
= tokenizer
.GetNextToken();
715 if ( !token
.ToLong(&l
) )
717 lf
.lfClipPrecision
= (BYTE
)l
;
719 token
= tokenizer
.GetNextToken();
720 if ( !token
.ToLong(&l
) )
722 lf
.lfQuality
= (BYTE
)l
;
724 token
= tokenizer
.GetNextToken();
725 if ( !token
.ToLong(&l
) )
727 lf
.lfPitchAndFamily
= (BYTE
)l
;
729 token
= tokenizer
.GetNextToken();
732 wxStrcpy(lf
.lfFaceName
, token
.c_str());
737 wxString
wxNativeFontInfo::ToString() const
741 s
.Printf(_T("%d;%ld;%ld;%ld;%ld;%ld;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
742 0, // version, in case we want to change the format later
761 // ----------------------------------------------------------------------------
763 // ----------------------------------------------------------------------------
769 bool wxFont::Create(const wxNativeFontInfo
& info
, WXHFONT hFont
)
773 m_refData
= new wxFontRefData(info
, hFont
);
780 wxFont::wxFont(const wxString
& fontdesc
)
782 wxNativeFontInfo info
;
783 if ( info
.FromString(fontdesc
) )
787 /* Constructor for a font. Note that the real construction is done
788 * in wxDC::SetFont, when information is available about scaling etc.
790 bool wxFont::DoCreate(int pointSize
,
791 const wxSize
& pixelSize
,
792 bool sizeUsingPixels
,
797 const wxString
& faceName
,
798 wxFontEncoding encoding
)
802 // wxDEFAULT is a valid value for the font size too so we must treat it
803 // specially here (otherwise the size would be 70 == wxDEFAULT value)
804 if ( pointSize
== wxDEFAULT
)
806 pointSize
= wxNORMAL_FONT
->GetPointSize();
809 m_refData
= new wxFontRefData(pointSize
, pixelSize
, sizeUsingPixels
,
810 family
, style
, weight
,
811 underlined
, faceName
, encoding
);
822 // ----------------------------------------------------------------------------
823 // real implementation
824 // ----------------------------------------------------------------------------
826 bool wxFont::RealizeResource()
828 if ( GetResourceHandle() )
830 // VZ: the old code returned false in this case, but it doesn't seem
831 // to make sense because the font _was_ created
835 return M_FONTDATA
->Alloc(this);
838 bool wxFont::FreeResource(bool WXUNUSED(force
))
840 if ( GetResourceHandle() )
850 WXHANDLE
wxFont::GetResourceHandle() const
852 return (WXHANDLE
)GetHFONT();
855 WXHFONT
wxFont::GetHFONT() const
857 return M_FONTDATA
? M_FONTDATA
->GetHFONT() : 0;
860 bool wxFont::IsFree() const
862 return M_FONTDATA
&& (M_FONTDATA
->GetHFONT() == 0);
865 void wxFont::Unshare()
867 // Don't change shared data
870 m_refData
= new wxFontRefData();
874 wxFontRefData
* ref
= new wxFontRefData(*M_FONTDATA
);
880 // ----------------------------------------------------------------------------
881 // change font attribute: we recreate font when doing it
882 // ----------------------------------------------------------------------------
884 void wxFont::SetPointSize(int pointSize
)
888 M_FONTDATA
->SetPointSize(pointSize
);
893 void wxFont::SetPixelSize(const wxSize
& pixelSize
)
897 M_FONTDATA
->SetPixelSize(pixelSize
);
902 void wxFont::SetFamily(int family
)
906 M_FONTDATA
->SetFamily(family
);
911 void wxFont::SetStyle(int style
)
915 M_FONTDATA
->SetStyle(style
);
920 void wxFont::SetWeight(int weight
)
924 M_FONTDATA
->SetWeight(weight
);
929 void wxFont::SetFaceName(const wxString
& faceName
)
933 M_FONTDATA
->SetFaceName(faceName
);
938 void wxFont::SetUnderlined(bool underlined
)
942 M_FONTDATA
->SetUnderlined(underlined
);
947 void wxFont::SetEncoding(wxFontEncoding encoding
)
951 M_FONTDATA
->SetEncoding(encoding
);
956 void wxFont::DoSetNativeFontInfo(const wxNativeFontInfo
& info
)
962 *M_FONTDATA
= wxFontRefData(info
);
967 // ----------------------------------------------------------------------------
969 // ----------------------------------------------------------------------------
971 int wxFont::GetPointSize() const
973 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
975 return M_FONTDATA
->GetPointSize();
978 wxSize
wxFont::GetPixelSize() const
980 return M_FONTDATA
->GetPixelSize();
983 bool wxFont::IsUsingSizeInPixels() const
985 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
987 return M_FONTDATA
->IsUsingSizeInPixels();
990 int wxFont::GetFamily() const
992 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
994 return M_FONTDATA
->GetFamily();
997 int wxFont::GetStyle() const
999 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1001 return M_FONTDATA
->GetStyle();
1004 int wxFont::GetWeight() const
1006 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
1008 return M_FONTDATA
->GetWeight();
1011 bool wxFont::GetUnderlined() const
1013 wxCHECK_MSG( Ok(), false, wxT("invalid font") );
1015 return M_FONTDATA
->GetUnderlined();
1018 wxString
wxFont::GetFaceName() const
1020 wxCHECK_MSG( Ok(), wxEmptyString
, wxT("invalid font") );
1022 return M_FONTDATA
->GetFaceName();
1025 wxFontEncoding
wxFont::GetEncoding() const
1027 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT
, wxT("invalid font") );
1029 return M_FONTDATA
->GetEncoding();
1032 const wxNativeFontInfo
*wxFont::GetNativeFontInfo() const
1034 return M_FONTDATA
->HasNativeFontInfo() ? &(M_FONTDATA
->GetNativeFontInfo())
1038 bool wxFont::IsFixedWidth() const
1040 if ( M_FONTDATA
->HasNativeFontInfo() )
1042 // the two low-order bits specify the pitch of the font, the rest is
1045 (BYTE
)(M_FONTDATA
->GetNativeFontInfo().lf
.lfPitchAndFamily
& PITCH_MASK
);
1047 return pitch
== FIXED_PITCH
;
1050 return wxFontBase::IsFixedWidth();