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/fontutil.h"
41 #include "wx/tokenzr.h"
43 #include "wx/msw/private.h"
44 #include "wx/tokenzr.h"
46 IMPLEMENT_DYNAMIC_CLASS(wxFont
, wxGDIObject
)
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
53 // wxFontRefData - the internal description of the font
54 // ----------------------------------------------------------------------------
56 class WXDLLEXPORT wxFontRefData
: public wxGDIRefData
62 Init(-1, wxFONTFAMILY_DEFAULT
, wxFONTSTYLE_NORMAL
, wxFONTWEIGHT_NORMAL
,
63 FALSE
, _T(""), wxFONTENCODING_DEFAULT
);
66 wxFontRefData(int size
,
71 const wxString
& faceName
,
72 wxFontEncoding encoding
)
74 Init(size
, family
, style
, weight
, underlined
, faceName
, encoding
);
77 wxFontRefData(const wxNativeFontInfo
& info
, WXHFONT hFont
= 0)
82 wxFontRefData(const wxFontRefData
& data
)
84 if ( data
.m_nativeFontInfoOk
)
86 Init(data
.m_nativeFontInfo
);
90 Init(data
.m_pointSize
, data
.m_family
, data
.m_style
, data
.m_weight
,
91 data
.m_underlined
, data
.m_faceName
, data
.m_encoding
);
95 virtual ~wxFontRefData();
98 bool Alloc(wxFont
*font
);
102 // all wxFont accessors
103 int GetPointSize() const
105 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetPointSize()
109 int GetFamily() const
116 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetStyle()
120 int GetWeight() const
122 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetWeight()
126 bool GetUnderlined() const
128 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetUnderlined()
132 wxString
GetFaceName() const
135 if ( m_nativeFontInfoOk
)
136 s
= m_nativeFontInfo
.GetFaceName();
143 wxFontEncoding
GetEncoding() const
145 return m_nativeFontInfoOk
? m_nativeFontInfo
.GetEncoding()
149 WXHFONT
GetHFONT() const { return m_hFont
; }
152 void SetPointSize(int pointSize
)
154 if ( m_nativeFontInfoOk
)
155 m_nativeFontInfo
.SetPointSize(pointSize
);
157 m_pointSize
= pointSize
;
160 void SetFamily(int family
)
165 void SetStyle(int style
)
167 if ( m_nativeFontInfoOk
)
168 m_nativeFontInfo
.SetStyle((wxFontStyle
)style
);
173 void SetWeight(int weight
)
175 if ( m_nativeFontInfoOk
)
176 m_nativeFontInfo
.SetWeight((wxFontWeight
)weight
);
181 void SetFaceName(const wxString
& faceName
)
183 if ( m_nativeFontInfoOk
)
184 m_nativeFontInfo
.SetFaceName(faceName
);
186 m_faceName
= faceName
;
189 void SetUnderlined(bool underlined
)
191 if ( m_nativeFontInfoOk
)
192 m_nativeFontInfo
.SetUnderlined(underlined
);
194 m_underlined
= underlined
;
197 void SetEncoding(wxFontEncoding encoding
)
199 if ( m_nativeFontInfoOk
)
200 m_nativeFontInfo
.SetEncoding(encoding
);
202 m_encoding
= encoding
;
205 // native font info tests
206 bool HasNativeFontInfo() const { return m_nativeFontInfoOk
; }
208 const wxNativeFontInfo
& GetNativeFontInfo() const
209 { return m_nativeFontInfo
; }
212 // common part of all ctors
218 const wxString
& faceName
,
219 wxFontEncoding encoding
);
221 void Init(const wxNativeFontInfo
& info
, WXHFONT hFont
= 0);
223 // font characterstics
230 wxFontEncoding m_encoding
;
232 // Windows font handle
236 wxNativeFontInfo m_nativeFontInfo
;
237 bool m_nativeFontInfoOk
;
240 // ============================================================================
242 // ============================================================================
244 // ----------------------------------------------------------------------------
246 // ----------------------------------------------------------------------------
248 void wxFontRefData::Init(int pointSize
,
253 const wxString
& faceName
,
254 wxFontEncoding encoding
)
257 m_pointSize
= pointSize
== -1 ? wxNORMAL_FONT
->GetPointSize() : pointSize
;
261 m_underlined
= underlined
;
262 m_faceName
= faceName
;
263 m_encoding
= encoding
;
267 m_nativeFontInfoOk
= FALSE
;
270 void wxFontRefData::Init(const wxNativeFontInfo
& info
, WXHFONT hFont
)
272 // we don't really need the family, what for?
274 // extract family from pitch-and-family
275 int lfFamily
= info
.lf
.lfPitchAndFamily
;
276 if ( lfFamily
& FIXED_PITCH
)
277 lfFamily
-= FIXED_PITCH
;
278 if ( lfFamily
& VARIABLE_PITCH
)
279 lfFamily
-= VARIABLE_PITCH
;
300 m_family
= wxDECORATIVE
;
308 // hFont may be zero, or it be passed in case we really want to
309 // use the exact font created in the underlying system
310 // (for example where we can't guarantee conversion from HFONT
311 // to LOGFONT back to HFONT)
314 m_nativeFontInfoOk
= TRUE
;
315 m_nativeFontInfo
= info
;
318 wxFontRefData::~wxFontRefData()
323 bool wxFontRefData::Alloc(wxFont
*font
)
325 if ( !m_nativeFontInfoOk
)
327 wxFillLogFont(&m_nativeFontInfo
.lf
, font
);
328 m_nativeFontInfoOk
= TRUE
;
331 HFONT hfont
= ::CreateFontIndirect(&m_nativeFontInfo
.lf
);
334 wxLogLastError(wxT("CreateFont"));
339 m_hFont
= (WXHFONT
)hfont
;
344 void wxFontRefData::Free()
348 if ( !::DeleteObject((HFONT
) m_hFont
) )
350 wxLogLastError(wxT("DeleteObject(font)"));
357 // ----------------------------------------------------------------------------
359 // ----------------------------------------------------------------------------
361 void wxNativeFontInfo::Init()
366 int wxNativeFontInfo::GetPointSize() const
368 const int ppInch
= ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY
);
370 return (int) (((72.0*(double)abs(lf
.lfHeight
)) / (double) ppInch
) + 0.5);
373 wxFontStyle
wxNativeFontInfo::GetStyle() const
375 return lf
.lfItalic
? wxFONTSTYLE_ITALIC
: wxFONTSTYLE_NORMAL
;
378 wxFontWeight
wxNativeFontInfo::GetWeight() const
380 if ( lf
.lfWeight
<= 300 )
381 return wxFONTWEIGHT_LIGHT
;
383 if ( lf
.lfWeight
>= 600 )
384 return wxFONTWEIGHT_BOLD
;
386 return wxFONTWEIGHT_NORMAL
;
389 bool wxNativeFontInfo::GetUnderlined() const
391 return lf
.lfUnderline
!= 0;
394 wxString
wxNativeFontInfo::GetFaceName() const
396 return lf
.lfFaceName
;
399 wxFontEncoding
wxNativeFontInfo::GetEncoding() const
401 return wxGetFontEncFromCharSet(lf
.lfCharSet
);
404 void wxNativeFontInfo::SetPointSize(int pointsize
)
406 const int ppInch
= ::GetDeviceCaps(ScreenHDC(), LOGPIXELSY
);
408 lf
.lfHeight
= -(int)((pointsize
*((double)ppInch
)/72.0) + 0.5);
411 void wxNativeFontInfo::SetStyle(wxFontStyle style
)
416 wxFAIL_MSG( _T("unknown font style") );
419 case wxFONTSTYLE_NORMAL
:
422 case wxFONTSTYLE_ITALIC
:
423 case wxFONTSTYLE_SLANT
:
429 void wxNativeFontInfo::SetWeight(wxFontWeight weight
)
434 wxFAIL_MSG( _T("unknown font weight") );
437 case wxFONTWEIGHT_NORMAL
:
438 lf
.lfWeight
= FW_NORMAL
;
441 case wxFONTWEIGHT_LIGHT
:
442 lf
.lfWeight
= FW_LIGHT
;
445 case wxFONTWEIGHT_BOLD
:
446 lf
.lfWeight
= FW_BOLD
;
451 void wxNativeFontInfo::SetUnderlined(bool underlined
)
453 lf
.lfUnderline
= underlined
;
456 void wxNativeFontInfo::SetFaceName(wxString facename
)
458 wxStrncpy(lf
.lfFaceName
, facename
, sizeof(lf
.lfFaceName
));
461 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding
)
463 wxNativeEncodingInfo info
;
464 if ( !wxGetNativeFontEncoding(encoding
, &info
) )
466 // unsupported encoding, replace with the default
467 info
.charset
= ANSI_CHARSET
;
470 lf
.lfCharSet
= info
.charset
;
473 bool wxNativeFontInfo::FromString(const wxString
& s
)
477 wxStringTokenizer
tokenizer(s
, _T(";"));
480 wxString token
= tokenizer
.GetNextToken();
481 if ( token
!= _T('0') )
484 token
= tokenizer
.GetNextToken();
485 if ( !token
.ToLong(&l
) )
489 token
= tokenizer
.GetNextToken();
490 if ( !token
.ToLong(&l
) )
494 token
= tokenizer
.GetNextToken();
495 if ( !token
.ToLong(&l
) )
499 token
= tokenizer
.GetNextToken();
500 if ( !token
.ToLong(&l
) )
502 lf
.lfOrientation
= l
;
504 token
= tokenizer
.GetNextToken();
505 if ( !token
.ToLong(&l
) )
509 token
= tokenizer
.GetNextToken();
510 if ( !token
.ToLong(&l
) )
512 lf
.lfItalic
= (BYTE
)l
;
514 token
= tokenizer
.GetNextToken();
515 if ( !token
.ToLong(&l
) )
517 lf
.lfUnderline
= (BYTE
)l
;
519 token
= tokenizer
.GetNextToken();
520 if ( !token
.ToLong(&l
) )
522 lf
.lfStrikeOut
= (BYTE
)l
;
524 token
= tokenizer
.GetNextToken();
525 if ( !token
.ToLong(&l
) )
527 lf
.lfCharSet
= (BYTE
)l
;
529 token
= tokenizer
.GetNextToken();
530 if ( !token
.ToLong(&l
) )
532 lf
.lfOutPrecision
= (BYTE
)l
;
534 token
= tokenizer
.GetNextToken();
535 if ( !token
.ToLong(&l
) )
537 lf
.lfClipPrecision
= (BYTE
)l
;
539 token
= tokenizer
.GetNextToken();
540 if ( !token
.ToLong(&l
) )
542 lf
.lfQuality
= (BYTE
)l
;
544 token
= tokenizer
.GetNextToken();
545 if ( !token
.ToLong(&l
) )
547 lf
.lfPitchAndFamily
= (BYTE
)l
;
549 token
= tokenizer
.GetNextToken();
552 wxStrcpy(lf
.lfFaceName
, token
.c_str());
557 wxString
wxNativeFontInfo::ToString() const
561 s
.Printf(_T("%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%s"),
562 0, // version, in case we want to change the format later
581 // ----------------------------------------------------------------------------
583 // ----------------------------------------------------------------------------
589 bool wxFont::Create(const wxNativeFontInfo
& info
, WXHFONT hFont
)
593 m_refData
= new wxFontRefData(info
, hFont
);
600 wxFont::wxFont(const wxString
& fontdesc
)
602 wxNativeFontInfo info
;
603 if ( info
.FromString(fontdesc
) )
607 /* Constructor for a font. Note that the real construction is done
608 * in wxDC::SetFont, when information is available about scaling etc.
610 bool wxFont::Create(int pointSize
,
615 const wxString
& faceName
,
616 wxFontEncoding encoding
)
620 // wxDEFAULT is a valid value for the font size too so we must treat it
621 // specially here (otherwise the size would be 70 == wxDEFAULT value)
622 if ( pointSize
== wxDEFAULT
)
624 pointSize
= wxNORMAL_FONT
->GetPointSize();
627 m_refData
= new wxFontRefData(pointSize
, family
, style
, weight
,
628 underlined
, faceName
, encoding
);
639 // ----------------------------------------------------------------------------
640 // real implementation
641 // ----------------------------------------------------------------------------
643 bool wxFont::RealizeResource()
645 if ( GetResourceHandle() )
647 // VZ: the old code returned FALSE in this case, but it doesn't seem
648 // to make sense because the font _was_ created
652 return M_FONTDATA
->Alloc(this);
655 bool wxFont::FreeResource(bool WXUNUSED(force
))
657 if ( GetResourceHandle() )
667 WXHANDLE
wxFont::GetResourceHandle()
672 WXHFONT
wxFont::GetHFONT() const
674 return M_FONTDATA
? M_FONTDATA
->GetHFONT() : 0;
677 bool wxFont::IsFree() const
679 return M_FONTDATA
&& (M_FONTDATA
->GetHFONT() == 0);
682 void wxFont::Unshare()
684 // Don't change shared data
687 m_refData
= new wxFontRefData();
691 wxFontRefData
* ref
= new wxFontRefData(*M_FONTDATA
);
697 // ----------------------------------------------------------------------------
698 // change font attribute: we recreate font when doing it
699 // ----------------------------------------------------------------------------
701 void wxFont::SetPointSize(int pointSize
)
705 M_FONTDATA
->SetPointSize(pointSize
);
710 void wxFont::SetFamily(int family
)
714 M_FONTDATA
->SetFamily(family
);
719 void wxFont::SetStyle(int style
)
723 M_FONTDATA
->SetStyle(style
);
728 void wxFont::SetWeight(int weight
)
732 M_FONTDATA
->SetWeight(weight
);
737 void wxFont::SetFaceName(const wxString
& faceName
)
741 M_FONTDATA
->SetFaceName(faceName
);
746 void wxFont::SetUnderlined(bool underlined
)
750 M_FONTDATA
->SetUnderlined(underlined
);
755 void wxFont::SetEncoding(wxFontEncoding encoding
)
759 M_FONTDATA
->SetEncoding(encoding
);
764 void wxFont::SetNativeFontInfo(const wxNativeFontInfo
& info
)
770 *M_FONTDATA
= wxFontRefData(info
);
775 // ----------------------------------------------------------------------------
777 // ----------------------------------------------------------------------------
779 int wxFont::GetPointSize() const
781 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
783 return M_FONTDATA
->GetPointSize();
786 int wxFont::GetFamily() const
788 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
790 return M_FONTDATA
->GetFamily();
793 int wxFont::GetStyle() const
795 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
797 return M_FONTDATA
->GetStyle();
800 int wxFont::GetWeight() const
802 wxCHECK_MSG( Ok(), 0, wxT("invalid font") );
804 return M_FONTDATA
->GetWeight();
807 bool wxFont::GetUnderlined() const
809 wxCHECK_MSG( Ok(), FALSE
, wxT("invalid font") );
811 return M_FONTDATA
->GetUnderlined();
814 wxString
wxFont::GetFaceName() const
816 wxCHECK_MSG( Ok(), wxT(""), wxT("invalid font") );
818 return M_FONTDATA
->GetFaceName();
821 wxFontEncoding
wxFont::GetEncoding() const
823 wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT
, wxT("invalid font") );
825 return M_FONTDATA
->GetEncoding();
828 wxNativeFontInfo
*wxFont::GetNativeFontInfo() const
830 if ( M_FONTDATA
->HasNativeFontInfo() )
831 return new wxNativeFontInfo(M_FONTDATA
->GetNativeFontInfo());