1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/fontcmn.cpp
3 // Purpose: implementation of wxFontBase methods
4 // Author: Vadim Zeitlin
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
32 #include "wx/dcscreen.h"
34 #include "wx/gdicmn.h"
37 #if defined(__WXMSW__)
38 #include "wx/msw/private.h" // includes windows.h for LOGFONT
39 #include "wx/msw/winundef.h"
42 #include "wx/fontutil.h" // for wxNativeFontInfo
43 #include "wx/fontmap.h"
44 #include "wx/fontenum.h"
46 #include "wx/tokenzr.h"
48 // ============================================================================
50 // ============================================================================
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
56 static inline int flags2Style(int flags
)
58 return flags
& wxFONTFLAG_ITALIC
60 : flags
& wxFONTFLAG_SLANT
65 static inline int flags2Weight(int flags
)
67 return flags
& wxFONTFLAG_LIGHT
69 : flags
& wxFONTFLAG_BOLD
71 : wxFONTWEIGHT_NORMAL
;
74 static inline bool flags2Underlined(int flags
)
76 return (flags
& wxFONTFLAG_UNDERLINED
) != 0;
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
83 wxFontEncoding
wxFontBase::ms_encodingDefault
= wxFONTENCODING_SYSTEM
;
86 void wxFontBase::SetDefaultEncoding(wxFontEncoding encoding
)
88 // GetDefaultEncoding() should return something != wxFONTENCODING_DEFAULT
89 // and, besides, using this value here doesn't make any sense
90 wxCHECK_RET( encoding
!= wxFONTENCODING_DEFAULT
,
91 _T("can't set default encoding to wxFONTENCODING_DEFAULT") );
93 ms_encodingDefault
= encoding
;
96 wxFontBase::~wxFontBase()
98 // this destructor is required for Darwin
102 wxFont
*wxFontBase::New(int size
,
107 const wxString
& face
,
108 wxFontEncoding encoding
)
110 return new wxFont(size
, family
, style
, weight
, underlined
, face
, encoding
);
114 wxFont
*wxFontBase::New(const wxSize
& pixelSize
,
119 const wxString
& face
,
120 wxFontEncoding encoding
)
122 return new wxFont(pixelSize
, family
, style
, weight
, underlined
,
127 wxFont
*wxFontBase::New(int pointSize
,
130 const wxString
& face
,
131 wxFontEncoding encoding
)
133 return New(pointSize
, family
, flags2Style(flags
), flags2Weight(flags
),
134 flags2Underlined(flags
), face
, encoding
);
138 wxFont
*wxFontBase::New(const wxSize
& pixelSize
,
141 const wxString
& face
,
142 wxFontEncoding encoding
)
144 return New(pixelSize
, family
, flags2Style(flags
), flags2Weight(flags
),
145 flags2Underlined(flags
), face
, encoding
);
149 wxFont
*wxFontBase::New(const wxNativeFontInfo
& info
)
151 return new wxFont(info
);
155 wxFont
*wxFontBase::New(const wxString
& strNativeFontDesc
)
157 wxNativeFontInfo fontInfo
;
158 if ( !fontInfo
.FromString(strNativeFontDesc
) )
159 return new wxFont(*wxNORMAL_FONT
);
161 return New(fontInfo
);
164 bool wxFontBase::IsFixedWidth() const
166 return GetFamily() == wxFONTFAMILY_TELETYPE
;
169 wxSize
wxFontBase::GetPixelSize() const
172 dc
.SetFont(*(wxFont
*)this);
173 return wxSize(dc
.GetCharWidth(), dc
.GetCharHeight());
176 bool wxFontBase::IsUsingSizeInPixels() const
181 void wxFontBase::SetPixelSize( const wxSize
& pixelSize
)
183 wxCHECK_RET( pixelSize
.GetWidth() >= 0 && pixelSize
.GetHeight() > 0,
184 "Negative values for the pixel size or zero pixel height are not allowed" );
188 // NOTE: this algorithm for adjusting the font size is used by all
189 // implementations of wxFont except under wxMSW and wxGTK where
190 // native support to font creation using pixel-size is provided.
195 bool initialGoodFound
= false;
196 bool initialBadFound
= false;
198 // NB: this assignment was separated from the variable definition
199 // in order to fix a gcc v3.3.3 compiler crash
200 int currentSize
= GetPointSize();
201 while (currentSize
> 0)
203 dc
.SetFont(*static_cast<wxFont
*>(this));
205 // if currentSize (in points) results in a font that is smaller
206 // than required by pixelSize it is considered a good size
207 // NOTE: the pixel size width may be zero
208 if (dc
.GetCharHeight() <= pixelSize
.GetHeight() &&
209 (pixelSize
.GetWidth() == 0 ||
210 dc
.GetCharWidth() <= pixelSize
.GetWidth()))
212 largestGood
= currentSize
;
213 initialGoodFound
= true;
217 smallestBad
= currentSize
;
218 initialBadFound
= true;
220 if (!initialGoodFound
)
224 else if (!initialBadFound
)
230 int distance
= smallestBad
- largestGood
;
234 currentSize
= largestGood
+ distance
/ 2;
237 SetPointSize(currentSize
);
240 if (currentSize
!= largestGood
)
241 SetPointSize(largestGood
);
244 void wxFontBase::DoSetNativeFontInfo(const wxNativeFontInfo
& info
)
246 #ifdef wxNO_NATIVE_FONTINFO
247 SetPointSize(info
.pointSize
);
248 SetFamily(info
.family
);
249 SetStyle(info
.style
);
250 SetWeight(info
.weight
);
251 SetUnderlined(info
.underlined
);
252 SetFaceName(info
.faceName
);
253 SetEncoding(info
.encoding
);
259 wxString
wxFontBase::GetNativeFontInfoDesc() const
262 const wxNativeFontInfo
*fontInfo
= GetNativeFontInfo();
265 fontDesc
= fontInfo
->ToString();
266 wxASSERT_MSG(!fontDesc
.empty(), wxT("This should be a non-empty string!"));
270 wxFAIL_MSG(wxT("Derived class should have created the wxNativeFontInfo!"));
276 wxString
wxFontBase::GetNativeFontInfoUserDesc() const
279 const wxNativeFontInfo
*fontInfo
= GetNativeFontInfo();
282 fontDesc
= fontInfo
->ToUserString();
283 wxASSERT_MSG(!fontDesc
.empty(), wxT("This should be a non-empty string!"));
287 wxFAIL_MSG(wxT("Derived class should have created the wxNativeFontInfo!"));
293 bool wxFontBase::SetNativeFontInfo(const wxString
& info
)
295 wxNativeFontInfo fontInfo
;
296 if ( !info
.empty() && fontInfo
.FromString(info
) )
298 SetNativeFontInfo(fontInfo
);
305 bool wxFontBase::SetNativeFontInfoUserDesc(const wxString
& info
)
307 wxNativeFontInfo fontInfo
;
308 if ( !info
.empty() && fontInfo
.FromUserString(info
) )
310 SetNativeFontInfo(fontInfo
);
317 bool wxFontBase::operator==(const wxFont
& font
) const
319 // either it is the same font, i.e. they share the same common data or they
320 // have different ref datas but still describe the same font
321 return IsSameAs(font
) ||
323 IsOk() == font
.IsOk() &&
324 GetPointSize() == font
.GetPointSize() &&
325 // in wxGTK1 GetPixelSize() calls GetInternalFont() which uses
326 // operator==() resulting in infinite recursion so we can't use it
328 #if !defined(__WXGTK__) || defined(__WXGTK20__)
329 GetPixelSize() == font
.GetPixelSize() &&
331 GetFamily() == font
.GetFamily() &&
332 GetStyle() == font
.GetStyle() &&
333 GetWeight() == font
.GetWeight() &&
334 GetUnderlined() == font
.GetUnderlined() &&
335 GetFaceName().IsSameAs(font
.GetFaceName(), false) &&
336 GetEncoding() == font
.GetEncoding()
340 wxString
wxFontBase::GetFamilyString() const
342 wxCHECK_MSG( IsOk(), "wxFONTFAMILY_DEFAULT", "invalid font" );
344 switch ( GetFamily() )
346 case wxFONTFAMILY_DECORATIVE
: return "wxFONTFAMILY_DECORATIVE";
347 case wxFONTFAMILY_ROMAN
: return "wxFONTFAMILY_ROMAN";
348 case wxFONTFAMILY_SCRIPT
: return "wxFONTFAMILY_SCRIPT";
349 case wxFONTFAMILY_SWISS
: return "wxFONTFAMILY_SWISS";
350 case wxFONTFAMILY_MODERN
: return "wxFONTFAMILY_MODERN";
351 case wxFONTFAMILY_TELETYPE
: return "wxFONTFAMILY_TELETYPE";
352 default: return "wxFONTFAMILY_DEFAULT";
356 wxString
wxFontBase::GetStyleString() const
358 wxCHECK_MSG( IsOk(), "wxFONTSTYLE_DEFAULT", "invalid font" );
360 switch ( GetStyle() )
362 case wxFONTSTYLE_NORMAL
: return "wxFONTSTYLE_NORMAL";
363 case wxFONTSTYLE_SLANT
: return "wxFONTSTYLE_SLANT";
364 case wxFONTSTYLE_ITALIC
: return "wxFONTSTYLE_ITALIC";
365 default: return "wxFONTSTYLE_DEFAULT";
369 wxString
wxFontBase::GetWeightString() const
371 wxCHECK_MSG( IsOk(), "wxFONTWEIGHT_DEFAULT", "invalid font" );
373 switch ( GetWeight() )
375 case wxFONTWEIGHT_NORMAL
: return "wxFONTWEIGHT_NORMAL";
376 case wxFONTWEIGHT_BOLD
: return "wxFONTWEIGHT_BOLD";
377 case wxFONTWEIGHT_LIGHT
: return "wxFONTWEIGHT_LIGHT";
378 default: return "wxFONTWEIGHT_DEFAULT";
382 bool wxFontBase::SetFaceName(const wxString
& facename
)
385 if (!wxFontEnumerator::IsValidFacename(facename
))
387 UnRef(); // make IsOk() return false
390 #else // !wxUSE_FONTENUM
391 wxUnusedVar(facename
);
392 #endif // wxUSE_FONTENUM/!wxUSE_FONTENUM
398 // ----------------------------------------------------------------------------
400 // ----------------------------------------------------------------------------
402 // Up to now, there are no native implementations of this function:
403 void wxNativeFontInfo::SetFaceName(const wxArrayString
& facenames
)
406 for (size_t i
=0; i
< facenames
.GetCount(); i
++)
408 if (wxFontEnumerator::IsValidFacename(facenames
[i
]))
410 SetFaceName(facenames
[i
]);
415 // set the first valid facename we can find on this system
416 wxString validfacename
= wxFontEnumerator::GetFacenames().Item(0);
417 wxLogTrace(wxT("font"), wxT("Falling back to '%s'"), validfacename
.c_str());
418 SetFaceName(validfacename
);
419 #else // !wxUSE_FONTENUM
420 SetFaceName(facenames
[0]);
421 #endif // wxUSE_FONTENUM/!wxUSE_FONTENUM
425 #ifdef wxNO_NATIVE_FONTINFO
427 // These are the generic forms of FromString()/ToString.
429 // convert to/from the string representation: format is
430 // version;pointsize;family;style;weight;underlined;facename;encoding
432 bool wxNativeFontInfo::FromString(const wxString
& s
)
436 wxStringTokenizer
tokenizer(s
, _T(";"));
438 wxString token
= tokenizer
.GetNextToken();
440 // Ignore the version for now
443 token
= tokenizer
.GetNextToken();
444 if ( !token
.ToLong(&l
) )
448 token
= tokenizer
.GetNextToken();
449 if ( !token
.ToLong(&l
) )
451 family
= (wxFontFamily
)l
;
453 token
= tokenizer
.GetNextToken();
454 if ( !token
.ToLong(&l
) )
456 style
= (wxFontStyle
)l
;
458 token
= tokenizer
.GetNextToken();
459 if ( !token
.ToLong(&l
) )
461 weight
= (wxFontWeight
)l
;
463 token
= tokenizer
.GetNextToken();
464 if ( !token
.ToLong(&l
) )
468 faceName
= tokenizer
.GetNextToken();
475 token
= tokenizer
.GetNextToken();
476 if ( !token
.ToLong(&l
) )
478 encoding
= (wxFontEncoding
)l
;
483 wxString
wxNativeFontInfo::ToString() const
487 s
.Printf(_T("%d;%d;%d;%d;%d;%d;%s;%d"),
500 void wxNativeFontInfo::Init()
503 family
= wxFONTFAMILY_DEFAULT
;
504 style
= wxFONTSTYLE_NORMAL
;
505 weight
= wxFONTWEIGHT_NORMAL
;
508 encoding
= wxFONTENCODING_DEFAULT
;
511 int wxNativeFontInfo::GetPointSize() const
516 wxFontStyle
wxNativeFontInfo::GetStyle() const
521 wxFontWeight
wxNativeFontInfo::GetWeight() const
526 bool wxNativeFontInfo::GetUnderlined() const
531 wxString
wxNativeFontInfo::GetFaceName() const
536 wxFontFamily
wxNativeFontInfo::GetFamily() const
541 wxFontEncoding
wxNativeFontInfo::GetEncoding() const
546 void wxNativeFontInfo::SetPointSize(int pointsize
)
548 pointSize
= pointsize
;
551 void wxNativeFontInfo::SetStyle(wxFontStyle style_
)
556 void wxNativeFontInfo::SetWeight(wxFontWeight weight_
)
561 void wxNativeFontInfo::SetUnderlined(bool underlined_
)
563 underlined
= underlined_
;
566 bool wxNativeFontInfo::SetFaceName(const wxString
& facename_
)
568 faceName
= facename_
;
572 void wxNativeFontInfo::SetFamily(wxFontFamily family_
)
577 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_
)
579 encoding
= encoding_
;
582 #endif // generic wxNativeFontInfo implementation
584 // conversion to/from user-readable string: this is used in the generic
585 // versions and under MSW as well because there is no standard font description
586 // format there anyhow (but there is a well-defined standard for X11 fonts used
587 // by wxGTK and wxMotif)
589 #if defined(wxNO_NATIVE_FONTINFO) || defined(__WXMSW__) || defined (__WXPM__) || defined(__WXOSX__)
591 wxString
wxNativeFontInfo::ToUserString() const
595 // first put the adjectives, if any - this is English-centric, of course,
596 // but what else can we do?
597 if ( GetUnderlined() )
599 desc
<< _("underlined");
602 switch ( GetWeight() )
605 wxFAIL_MSG( _T("unknown font weight") );
608 case wxFONTWEIGHT_NORMAL
:
611 case wxFONTWEIGHT_LIGHT
:
615 case wxFONTWEIGHT_BOLD
:
620 switch ( GetStyle() )
623 wxFAIL_MSG( _T("unknown font style") );
626 case wxFONTSTYLE_NORMAL
:
629 // we don't distinguish between the two for now anyhow...
630 case wxFONTSTYLE_ITALIC
:
631 case wxFONTSTYLE_SLANT
:
632 desc
<< _(" italic");
636 wxString face
= GetFaceName();
639 desc
<< _T(' ') << face
;
642 int size
= GetPointSize();
643 if ( size
!= wxNORMAL_FONT
->GetPointSize() )
645 desc
<< _T(' ') << size
;
649 wxFontEncoding enc
= GetEncoding();
650 if ( enc
!= wxFONTENCODING_DEFAULT
&& enc
!= wxFONTENCODING_SYSTEM
)
652 desc
<< _T(' ') << wxFontMapper::GetEncodingName(enc
);
654 #endif // wxUSE_FONTMAP
656 return desc
.Strip(wxString::both
).MakeLower();
659 bool wxNativeFontInfo::FromUserString(const wxString
& s
)
661 // reset to the default state
664 // parse a more or less free form string
666 // TODO: we should handle at least the quoted facenames
667 wxStringTokenizer
tokenizer(s
, _T(";, "), wxTOKEN_STRTOK
);
671 bool weightfound
= false, pointsizefound
= false;
673 bool encodingfound
= false;
676 while ( tokenizer
.HasMoreTokens() )
678 wxString token
= tokenizer
.GetNextToken();
681 token
.Trim(true).Trim(false).MakeLower();
683 // look for the known tokens
684 if ( token
== _T("underlined") || token
== _("underlined") )
688 else if ( token
== _T("light") || token
== _("light") )
690 SetWeight(wxFONTWEIGHT_LIGHT
);
693 else if ( token
== _T("bold") || token
== _("bold") )
695 SetWeight(wxFONTWEIGHT_BOLD
);
698 else if ( token
== _T("italic") || token
== _("italic") )
700 SetStyle(wxFONTSTYLE_ITALIC
);
702 else if ( token
.ToULong(&size
) )
705 pointsizefound
= true;
710 // try to interpret this as an encoding
711 wxFontEncoding encoding
= wxFontMapper::Get()->CharsetToEncoding(token
, false);
712 if ( encoding
!= wxFONTENCODING_DEFAULT
&&
713 encoding
!= wxFONTENCODING_SYSTEM
) // returned when the recognition failed
715 SetEncoding(encoding
);
716 encodingfound
= true;
720 #endif // wxUSE_FONTMAP
722 // assume it is the face name
730 // skip the code which resets face below
735 #endif // wxUSE_FONTMAP
738 // if we had had the facename, we shouldn't continue appending tokens
739 // to it (i.e. "foo bold bar" shouldn't result in the facename "foo
743 // NB: the check on the facename is implemented in wxFontBase::SetFaceName
744 // and not in wxNativeFontInfo::SetFaceName thus we need to explicitely
745 // call here wxFontEnumerator::IsValidFacename
748 !wxFontEnumerator::IsValidFacename(face
) ||
749 #endif // wxUSE_FONTENUM
752 SetFaceName(wxNORMAL_FONT
->GetFaceName());
759 // we might not have flushed it inside the loop
762 // NB: the check on the facename is implemented in wxFontBase::SetFaceName
763 // and not in wxNativeFontInfo::SetFaceName thus we need to explicitely
764 // call here wxFontEnumerator::IsValidFacename
767 !wxFontEnumerator::IsValidFacename(face
) ||
768 #endif // wxUSE_FONTENUM
771 SetFaceName(wxNORMAL_FONT
->GetFaceName());
775 // set point size to default value if size was not given
776 if ( !pointsizefound
)
777 SetPointSize(wxNORMAL_FONT
->GetPointSize());
779 // set font weight to default value if weight was not given
781 SetWeight(wxFONTWEIGHT_NORMAL
);
784 // set font encoding to default value if encoding was not given
785 if ( !encodingfound
)
786 SetEncoding(wxFONTENCODING_SYSTEM
);
787 #endif // wxUSE_FONTMAP
792 #endif // generic or wxMSW or wxOS2
795 // wxFont <-> wxString utilities, used by wxConfig
796 wxString
wxToString(const wxFontBase
& font
)
798 return font
.IsOk() ? font
.GetNativeFontInfoDesc()
802 bool wxFromString(const wxString
& str
, wxFontBase
*font
)
804 wxCHECK_MSG( font
, false, _T("NULL output parameter") );
812 return font
->SetNativeFontInfo(str
);