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 // ----------------------------------------------------------------------------
54 // wxFontRefData - the internal description of the font
55 // ----------------------------------------------------------------------------
57 class WXDLLEXPORT wxFontRefData
: public wxGDIRefData
63 Init(-1, wxFONTFAMILY_DEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
,
64 FALSE
, _T(""), wxFONTENCODING_DEFAULT
);
67 wxFontRefData(int size
,
72 const wxString
& faceName
,
73 wxFontEncoding encoding
)
75 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
78 wxFontRefData(const wxNativeFontInfo
& info
, WXHFONT hFont
= 0)
83 wxFontRefData(const wxFontRefData
& data
)
85 if ( data
.m_nativeFontInfoOk
)
87 Init(data
.m_nativeFontInfo
);
91 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
92 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
96 virtual ~wxFontRefData();
99 bool Alloc(wxFont
*font
);
103 // all wxFont accessors
104 int GetPointSize() const
106 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetPointSize()
110 int GetFamily() const
117 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetStyle()
121 int GetWeight() const
123 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetWeight()
127 bool GetUnderlined() const
129 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetUnderlined()
133 wxString
GetFaceName() const
136 if ( m_nativeFontInfoOk
)
137 s
= m_nativeFontInfo
.GetFaceName();
144 wxFontEncoding
GetEncoding() const
146 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetEncoding()
150 WXHFONT
GetHFONT() const { return m_hFont
; }
153 void SetPointSize(int pointSize
)
155 if ( m_nativeFontInfoOk
)
156 m_nativeFontInfo
.SetPointSize(pointSize
);
158 m_pointSize
= pointSize
;
161 void SetFamily(int family
)
166 void SetStyle(int style
)
168 if ( m_nativeFontInfoOk
)
169 m_nativeFontInfo
.SetStyle((wxFontStyle
)style
);
174 void SetWeight(int weight
)
176 if ( m_nativeFontInfoOk
)
177 m_nativeFontInfo
.SetWeight((wxFontWeight
)weight
);
182 void SetFaceName(const wxString
& faceName
)
184 if ( m_nativeFontInfoOk
)
185 m_nativeFontInfo
.SetFaceName(faceName
);
187 m_faceName
= faceName
;
190 void SetUnderlined(bool underlined
)
192 if ( m_nativeFontInfoOk
)
193 m_nativeFontInfo
.SetUnderlined(underlined
);
195 m_underlined
= underlined
;
198 void SetEncoding(wxFontEncoding encoding
)
200 if ( m_nativeFontInfoOk
)
201 m_nativeFontInfo
.SetEncoding(encoding
);
203 m_encoding
= encoding
;
206 // native font info tests
207 bool HasNativeFontInfo() const { return m_nativeFontInfoOk
; }
209 const wxNativeFontInfo
& GetNativeFontInfo() const
210 { return m_nativeFontInfo
; }
213 // common part of all ctors
219 const wxString
& faceName
,
220 wxFontEncoding encoding
);
222 void Init(const wxNativeFontInfo
& info
, WXHFONT hFont
= 0);
224 // font characterstics
231 wxFontEncoding m_encoding
;
233 // Windows font handle
237 wxNativeFontInfo m_nativeFontInfo
;
238 bool m_nativeFontInfoOk
;
241 // ============================================================================
243 // ============================================================================
245 // ----------------------------------------------------------------------------
247 // ----------------------------------------------------------------------------
249 void wxFontRefData::Init(int pointSize
,
254 const wxString
& faceName
,
255 wxFontEncoding encoding
)
258 m_pointSize
= pointSize
== -1 ? wxNORMAL_FONT
->GetPointSize() : pointSize
;
262 m_underlined
= underlined
;
263 m_faceName
= faceName
;
264 m_encoding
= encoding
;
268 m_nativeFontInfoOk
= FALSE
;
271 void wxFontRefData::Init(const wxNativeFontInfo
& info
, WXHFONT hFont
)
273 // we don't really need the family, what for?
275 // extract family from pitch-and-family
276 int lfFamily
= info
.lf
.lfPitchAndFamily
;
277 if ( lfFamily
& FIXED_PITCH
)
278 lfFamily
-= FIXED_PITCH
;
279 if ( lfFamily
& VARIABLE_PITCH
)
280 lfFamily
-= VARIABLE_PITCH
;
301 m_family
= wxDECORATIVE
;
309 // hFont may be zero, or it be passed in case we really want to
310 // use the exact font created in the underlying system
311 // (for example where we can't guarantee conversion from HFONT
312 // to LOGFONT back to HFONT)
315 m_nativeFontInfoOk
= TRUE
;
316 m_nativeFontInfo
= info
;
319 wxFontRefData::~wxFontRefData()
324 bool wxFontRefData::Alloc(wxFont
*font
)
326 if ( !m_nativeFontInfoOk
)
328 wxFillLogFont(&m_nativeFontInfo
.lf
, font
);
329 m_nativeFontInfoOk
= TRUE
;
332 HFONT hfont
= ::CreateFontIndirect(&m_nativeFontInfo
.lf
);
335 wxLogLastError(wxT("CreateFont"));
340 m_hFont
= (WXHFONT
)hfont
;
345 void wxFontRefData::Free()
349 if ( !::DeleteObject((HFONT
) m_hFont
) )
351 wxLogLastError(wxT("DeleteObject(font)"));
358 // ----------------------------------------------------------------------------
360 // ----------------------------------------------------------------------------
362 void wxNativeFontInfo::Init()
367 int wxNativeFontInfo::GetPointSize() const
369 // FIXME: using the screen here results in incorrect font size calculation
371 const int ppInch
= ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY
);
373 return (int) (((72.0*(double)abs(lf
.lfHeight
)) / (double) ppInch
) + 0.5);
376 wxFontStyle
wxNativeFontInfo::GetStyle() const
378 return lf
.lfItalic
? wxFONTSTYLE_ITALIC
: wxFONTSTYLE_NORMAL
;
381 wxFontWeight
wxNativeFontInfo::GetWeight() const
383 if ( lf
.lfWeight
<= 300 )
384 return wxFONTWEIGHT_LIGHT
;
386 if ( lf
.lfWeight
>= 600 )
387 return wxFONTWEIGHT_BOLD
;
389 return wxFONTWEIGHT_NORMAL
;
392 bool wxNativeFontInfo::GetUnderlined() const
394 return lf
.lfUnderline
!= 0;
397 wxString
wxNativeFontInfo::GetFaceName() const
399 return lf
.lfFaceName
;
402 wxFontFamily
wxNativeFontInfo::GetFamily() const
404 // extract family from pitch-and-family
405 int lfFamily
= lf
.lfPitchAndFamily
;
408 if ( lfFamily
& FIXED_PITCH
)
409 lfFamily
-= FIXED_PITCH
;
410 if ( lfFamily
& VARIABLE_PITCH
)
411 lfFamily
-= VARIABLE_PITCH
;
432 family
= wxDECORATIVE
;
438 return (wxFontFamily
)family
;
441 wxFontEncoding
wxNativeFontInfo::GetEncoding() const
443 return wxGetFontEncFromCharSet(lf
.lfCharSet
);
446 void wxNativeFontInfo::SetPointSize(int pointsize
)
448 #if wxFONT_SIZE_COMPATIBILITY
449 // Incorrect, but compatible with old wxWindows behaviour
450 lf
.lfHeight
= (pointSize
*ppInch
)/72;
451 #else // wxFONT_SIZE_COMPATIBILITY
452 // FIXME: using the screen here results in incorrect font size calculation
454 const int ppInch
= ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY
);
456 lf
.lfHeight
= -(int)((pointsize
*((double)ppInch
)/72.0) + 0.5);
457 #endif // wxFONT_SIZE_COMPATIBILITY/!wxFONT_SIZE_COMPATIBILITY
460 void wxNativeFontInfo::SetStyle(wxFontStyle style
)
465 wxFAIL_MSG( _T("unknown font style") );
468 case wxFONTSTYLE_NORMAL
:
471 case wxFONTSTYLE_ITALIC
:
472 case wxFONTSTYLE_SLANT
:
478 void wxNativeFontInfo::SetWeight(wxFontWeight weight
)
483 wxFAIL_MSG( _T("unknown font weight") );
486 case wxFONTWEIGHT_NORMAL
:
487 lf
.lfWeight
= FW_NORMAL
;
490 case wxFONTWEIGHT_LIGHT
:
491 lf
.lfWeight
= FW_LIGHT
;
494 case wxFONTWEIGHT_BOLD
:
495 lf
.lfWeight
= FW_BOLD
;
500 void wxNativeFontInfo::SetUnderlined(bool underlined
)
502 lf
.lfUnderline
= underlined
;
505 void wxNativeFontInfo::SetFaceName(wxString facename
)
507 wxStrncpy(lf
.lfFaceName
, facename
, WXSIZEOF(lf
.lfFaceName
));
510 void wxNativeFontInfo::SetFamily(wxFontFamily family
)
518 ff_family
= FF_SCRIPT
;
519 facename
= _T("Script");
523 ff_family
= FF_DECORATIVE
;
524 facename
= _T("Old English Text MT");
528 ff_family
= FF_ROMAN
;
529 facename
= _T("Times New Roman");
534 ff_family
= FF_MODERN
;
535 facename
= _T("Courier New");
539 ff_family
= FF_SWISS
;
540 facename
= _T("Arial");
545 ff_family
= FF_SWISS
;
546 facename
= _T("MS Sans Serif");
549 lf
.lfPitchAndFamily
= DEFAULT_PITCH
| ff_family
;
551 if ( !wxStrlen(lf
.lfFaceName
) )
553 SetFaceName(facename
);
557 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding
)
559 wxNativeEncodingInfo info
;
560 if ( !wxGetNativeFontEncoding(encoding
, &info
) )
563 if ( wxTheFontMapper
->GetAltForEncoding(encoding
, &info
) )
565 if ( !info
.facename
.empty() )
567 // if we have this encoding only in some particular facename, use
568 // the facename - it is better to show the correct characters in a
569 // wrong facename than unreadable text in a correct one
570 SetFaceName(info
.facename
);
574 #endif // wxUSE_FONTMAP
576 // unsupported encoding, replace with the default
577 info
.charset
= ANSI_CHARSET
;
581 lf
.lfCharSet
= info
.charset
;
584 bool wxNativeFontInfo::FromString(const wxString
& s
)
588 wxStringTokenizer
tokenizer(s
, _T(";"));
591 wxString token
= tokenizer
.GetNextToken();
592 if ( token
!= _T('0') )
595 token
= tokenizer
.GetNextToken();
596 if ( !token
.ToLong(&l
) )
600 token
= tokenizer
.GetNextToken();
601 if ( !token
.ToLong(&l
) )
605 token
= tokenizer
.GetNextToken();
606 if ( !token
.ToLong(&l
) )
610 token
= tokenizer
.GetNextToken();
611 if ( !token
.ToLong(&l
) )
613 lf
.lfOrientation
= l
;
615 token
= tokenizer
.GetNextToken();
616 if ( !token
.ToLong(&l
) )
620 token
= tokenizer
.GetNextToken();
621 if ( !token
.ToLong(&l
) )
623 lf
.lfItalic
= (BYTE
)l
;
625 token
= tokenizer
.GetNextToken();
626 if ( !token
.ToLong(&l
) )
628 lf
.lfUnderline
= (BYTE
)l
;
630 token
= tokenizer
.GetNextToken();
631 if ( !token
.ToLong(&l
) )
633 lf
.lfStrikeOut
= (BYTE
)l
;
635 token
= tokenizer
.GetNextToken();
636 if ( !token
.ToLong(&l
) )
638 lf
.lfCharSet
= (BYTE
)l
;
640 token
= tokenizer
.GetNextToken();
641 if ( !token
.ToLong(&l
) )
643 lf
.lfOutPrecision
= (BYTE
)l
;
645 token
= tokenizer
.GetNextToken();
646 if ( !token
.ToLong(&l
) )
648 lf
.lfClipPrecision
= (BYTE
)l
;
650 token
= tokenizer
.GetNextToken();
651 if ( !token
.ToLong(&l
) )
653 lf
.lfQuality
= (BYTE
)l
;
655 token
= tokenizer
.GetNextToken();
656 if ( !token
.ToLong(&l
) )
658 lf
.lfPitchAndFamily
= (BYTE
)l
;
660 token
= tokenizer
.GetNextToken();
663 wxStrcpy(lf
.lfFaceName
, token
.c_str());
668 wxString
wxNativeFontInfo::ToString() const
672 s
.Printf(_T("%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
673 0, // version, in case we want to change the format later
692 // ----------------------------------------------------------------------------
694 // ----------------------------------------------------------------------------
700 bool wxFont::Create(const wxNativeFontInfo
& info
, WXHFONT hFont
)
704 m_refData
= new wxFontRefData(info
, hFont
);
711 wxFont::wxFont(const wxString
& fontdesc
)
713 wxNativeFontInfo info
;
714 if ( info
.FromString(fontdesc
) )
718 /* Constructor for a font. Note that the real construction is done
719 * in wxDC::SetFont, when information is available about scaling etc.
721 bool wxFont::Create(int pointSize
,
726 const wxString
& faceName
,
727 wxFontEncoding encoding
)
731 // wxDEFAULT is a valid value for the font size too so we must treat it
732 // specially here (otherwise the size would be 70 == wxDEFAULT value)
733 if ( pointSize
== wxDEFAULT
)
735 pointSize
= wxNORMAL_FONT
->GetPointSize();
738 m_refData
= new wxFontRefData(pointSize
, family
, style
, weight
,
739 underlined
, faceName
, encoding
);
750 // ----------------------------------------------------------------------------
751 // real implementation
752 // ----------------------------------------------------------------------------
754 bool wxFont::RealizeResource()
756 if ( GetResourceHandle() )
758 // VZ: the old code returned FALSE in this case, but it doesn't seem
759 // to make sense because the font _was_ created
763 return M_FONTDATA
->Alloc(this);
766 bool wxFont::FreeResource(bool WXUNUSED(force
))
768 if ( GetResourceHandle() )
778 WXHANDLE
wxFont::GetResourceHandle()
783 WXHFONT
wxFont::GetHFONT() const
785 return M_FONTDATA
? M_FONTDATA
->GetHFONT() : 0;
788 bool wxFont::IsFree() const
790 return M_FONTDATA
&& (M_FONTDATA
->GetHFONT() == 0);
793 void wxFont::Unshare()
795 // Don't change shared data
798 m_refData
= new wxFontRefData();
802 wxFontRefData
* ref
= new wxFontRefData(*M_FONTDATA
);
808 // ----------------------------------------------------------------------------
809 // change font attribute: we recreate font when doing it
810 // ----------------------------------------------------------------------------
812 void wxFont::SetPointSize(int pointSize
)
816 M_FONTDATA
->SetPointSize(pointSize
);
821 void wxFont::SetFamily(int family
)
825 M_FONTDATA
->SetFamily(family
);
830 void wxFont::SetStyle(int style
)
834 M_FONTDATA
->SetStyle(style
);
839 void wxFont::SetWeight(int weight
)
843 M_FONTDATA
->SetWeight(weight
);
848 void wxFont::SetFaceName(const wxString
& faceName
)
852 M_FONTDATA
->SetFaceName(faceName
);
857 void wxFont::SetUnderlined(bool underlined
)
861 M_FONTDATA
->SetUnderlined(underlined
);
866 void wxFont::SetEncoding(wxFontEncoding encoding
)
870 M_FONTDATA
->SetEncoding(encoding
);
875 void wxFont::SetNativeFontInfo(const wxNativeFontInfo
& info
)
881 *M_FONTDATA
= wxFontRefData(info
);
886 // ----------------------------------------------------------------------------
888 // ----------------------------------------------------------------------------
890 int wxFont::GetPointSize() const
892 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
894 return M_FONTDATA
->GetPointSize();
897 int wxFont::GetFamily() const
899 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
901 return M_FONTDATA
->GetFamily();
904 int wxFont::GetStyle() const
906 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
908 return M_FONTDATA
->GetStyle();
911 int wxFont::GetWeight() const
913 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
915 return M_FONTDATA
->GetWeight();
918 bool wxFont::GetUnderlined() const
920 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid font") );
922 return M_FONTDATA
->GetUnderlined();
925 wxString
wxFont::GetFaceName() const
927 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
929 return M_FONTDATA
->GetFaceName();
932 wxFontEncoding
wxFont::GetEncoding() const
934 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT
, wxT("invalid font") );
936 return M_FONTDATA
->GetEncoding();
939 wxNativeFontInfo
*wxFont::GetNativeFontInfo() const
941 if ( M_FONTDATA
->HasNativeFontInfo() )
942 return new wxNativeFontInfo(M_FONTDATA
->GetNativeFontInfo());