X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f7b301fa5bae53f03ee6ffbaddde1bf98cbc9146..beb2638a997914bd12c55e81589adebd90af9ed2:/src/common/fontcmn.cpp?ds=sidebyside diff --git a/src/common/fontcmn.cpp b/src/common/fontcmn.cpp index bdc45ec3bc..67ee5bff64 100644 --- a/src/common/fontcmn.cpp +++ b/src/common/fontcmn.cpp @@ -1,12 +1,12 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: common/fontcmn.cpp +// Name: src/common/fontcmn.cpp // Purpose: implementation of wxFontBase methods // Author: Vadim Zeitlin // Modified by: // Created: 20.09.99 // RCS-ID: $Id$ -// Copyright: (c) wxWindows team -// Licence: wxWindows license +// Copyright: (c) wxWidgets team +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -17,25 +17,31 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ -#pragma implementation "fontbase.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif -#ifndef WX_PRECOMP #include "wx/font.h" -#include "wx/intl.h" + +#ifndef WX_PRECOMP + #include "wx/dc.h" + #include "wx/intl.h" + #include "wx/dcscreen.h" + #include "wx/log.h" + #include "wx/gdicmn.h" #endif // WX_PRECOMP -#include "wx/gdicmn.h" +#if defined(__WXMSW__) + #include "wx/msw/private.h" // includes windows.h for LOGFONT + #include "wx/msw/winundef.h" +#endif + #include "wx/fontutil.h" // for wxNativeFontInfo #include "wx/fontmap.h" +#include "wx/fontenum.h" #include "wx/tokenzr.h" @@ -43,17 +49,60 @@ // implementation // ============================================================================ +// ---------------------------------------------------------------------------- +// helper functions +// ---------------------------------------------------------------------------- + +static inline int flags2Style(int flags) +{ + return flags & wxFONTFLAG_ITALIC + ? wxFONTSTYLE_ITALIC + : flags & wxFONTFLAG_SLANT + ? wxFONTSTYLE_SLANT + : wxFONTSTYLE_NORMAL; +} + +static inline int flags2Weight(int flags) +{ + return flags & wxFONTFLAG_LIGHT + ? wxFONTWEIGHT_LIGHT + : flags & wxFONTFLAG_BOLD + ? wxFONTWEIGHT_BOLD + : wxFONTWEIGHT_NORMAL; +} + +static inline bool flags2Underlined(int flags) +{ + return (flags & wxFONTFLAG_UNDERLINED) != 0; +} + // ---------------------------------------------------------------------------- // wxFontBase // ---------------------------------------------------------------------------- wxFontEncoding wxFontBase::ms_encodingDefault = wxFONTENCODING_SYSTEM; +/* static */ +void wxFontBase::SetDefaultEncoding(wxFontEncoding encoding) +{ + // GetDefaultEncoding() should return something != wxFONTENCODING_DEFAULT + // and, besides, using this value here doesn't make any sense + wxCHECK_RET( encoding != wxFONTENCODING_DEFAULT, + _T("can't set default encoding to wxFONTENCODING_DEFAULT") ); + + ms_encodingDefault = encoding; +} + +wxFontBase::~wxFontBase() +{ + // this destructor is required for Darwin +} + /* static */ wxFont *wxFontBase::New(int size, - int family, - int style, - int weight, + wxFontFamily family, + wxFontStyle style, + wxFontWeight weight, bool underlined, const wxString& face, wxFontEncoding encoding) @@ -61,6 +110,41 @@ wxFont *wxFontBase::New(int size, return new wxFont(size, family, style, weight, underlined, face, encoding); } +/* static */ +wxFont *wxFontBase::New(const wxSize& pixelSize, + wxFontFamily family, + wxFontStyle style, + wxFontWeight weight, + bool underlined, + const wxString& face, + wxFontEncoding encoding) +{ + return new wxFont(pixelSize, family, style, weight, underlined, + face, encoding); +} + +/* static */ +wxFont *wxFontBase::New(int pointSize, + wxFontFamily family, + int flags, + const wxString& face, + wxFontEncoding encoding) +{ + return New(pointSize, family, flags2Style(flags), flags2Weight(flags), + flags2Underlined(flags), face, encoding); +} + +/* static */ +wxFont *wxFontBase::New(const wxSize& pixelSize, + wxFontFamily family, + int flags, + const wxString& face, + wxFontEncoding encoding) +{ + return New(pixelSize, family, flags2Style(flags), flags2Weight(flags), + flags2Underlined(flags), face, encoding); +} + /* static */ wxFont *wxFontBase::New(const wxNativeFontInfo& info) { @@ -77,26 +161,87 @@ wxFont *wxFontBase::New(const wxString& strNativeFontDesc) return New(fontInfo); } -wxNativeFontInfo *wxFontBase::GetNativeFontInfo() const +bool wxFontBase::IsFixedWidth() const { -#ifdef wxNO_NATIVE_FONTINFO - wxNativeFontInfo *fontInfo = new wxNativeFontInfo(); + return GetFamily() == wxFONTFAMILY_TELETYPE; +} + +wxSize wxFontBase::GetPixelSize() const +{ + wxScreenDC dc; + dc.SetFont(*(wxFont *)this); + return wxSize(dc.GetCharWidth(), dc.GetCharHeight()); +} + +bool wxFontBase::IsUsingSizeInPixels() const +{ + return false; +} - fontInfo->SetPointSize(GetPointSize()); - fontInfo->SetFamily((wxFontFamily)GetFamily()); - fontInfo->SetStyle((wxFontStyle)GetStyle()); - fontInfo->SetWeight((wxFontWeight)GetWeight()); - fontInfo->SetUnderlined(GetUnderlined()); - fontInfo->SetFaceName(GetFaceName()); - fontInfo->SetEncoding(GetEncoding()); +void wxFontBase::SetPixelSize( const wxSize& pixelSize ) +{ + wxCHECK_RET( pixelSize.GetWidth() >= 0 && pixelSize.GetHeight() > 0, + "Negative values for the pixel size or zero pixel height are not allowed" ); - return fontInfo; -#else - return (wxNativeFontInfo *)NULL; -#endif + wxScreenDC dc; + + // NOTE: this algorithm for adjusting the font size is used by all + // implementations of wxFont except under wxMSW and wxGTK where + // native support to font creation using pixel-size is provided. + + int largestGood = 0; + int smallestBad = 0; + + bool initialGoodFound = false; + bool initialBadFound = false; + + // NB: this assignment was separated from the variable definition + // in order to fix a gcc v3.3.3 compiler crash + int currentSize = GetPointSize(); + while (currentSize > 0) + { + dc.SetFont(*static_cast(this)); + + // if currentSize (in points) results in a font that is smaller + // than required by pixelSize it is considered a good size + // NOTE: the pixel size width may be zero + if (dc.GetCharHeight() <= pixelSize.GetHeight() && + (pixelSize.GetWidth() == 0 || + dc.GetCharWidth() <= pixelSize.GetWidth())) + { + largestGood = currentSize; + initialGoodFound = true; + } + else + { + smallestBad = currentSize; + initialBadFound = true; + } + if (!initialGoodFound) + { + currentSize /= 2; + } + else if (!initialBadFound) + { + currentSize *= 2; + } + else + { + int distance = smallestBad - largestGood; + if (distance == 1) + break; + + currentSize = largestGood + distance / 2; + } + + SetPointSize(currentSize); + } + + if (currentSize != largestGood) + SetPointSize(largestGood); } -void wxFontBase::SetNativeFontInfo(const wxNativeFontInfo& info) +void wxFontBase::DoSetNativeFontInfo(const wxNativeFontInfo& info) { #ifdef wxNO_NATIVE_FONTINFO SetPointSize(info.pointSize); @@ -114,11 +259,15 @@ void wxFontBase::SetNativeFontInfo(const wxNativeFontInfo& info) wxString wxFontBase::GetNativeFontInfoDesc() const { wxString fontDesc; - wxNativeFontInfo *fontInfo = GetNativeFontInfo(); + const wxNativeFontInfo *fontInfo = GetNativeFontInfo(); if ( fontInfo ) { fontDesc = fontInfo->ToString(); - delete fontInfo; + wxASSERT_MSG(!fontDesc.empty(), wxT("This should be a non-empty string!")); + } + else + { + wxFAIL_MSG(wxT("Derived class should have created the wxNativeFontInfo!")); } return fontDesc; @@ -127,110 +276,152 @@ wxString wxFontBase::GetNativeFontInfoDesc() const wxString wxFontBase::GetNativeFontInfoUserDesc() const { wxString fontDesc; - wxNativeFontInfo *fontInfo = GetNativeFontInfo(); + const wxNativeFontInfo *fontInfo = GetNativeFontInfo(); if ( fontInfo ) { fontDesc = fontInfo->ToUserString(); - delete fontInfo; + wxASSERT_MSG(!fontDesc.empty(), wxT("This should be a non-empty string!")); + } + else + { + wxFAIL_MSG(wxT("Derived class should have created the wxNativeFontInfo!")); } return fontDesc; } -void wxFontBase::SetNativeFontInfo(const wxString& info) +bool wxFontBase::SetNativeFontInfo(const wxString& info) { wxNativeFontInfo fontInfo; if ( !info.empty() && fontInfo.FromString(info) ) { SetNativeFontInfo(fontInfo); + return true; } + + return false; } -void wxFontBase::SetNativeFontInfoUserDesc(const wxString& info) +bool wxFontBase::SetNativeFontInfoUserDesc(const wxString& info) { wxNativeFontInfo fontInfo; if ( !info.empty() && fontInfo.FromUserString(info) ) { SetNativeFontInfo(fontInfo); + return true; } -} -wxFont& wxFont::operator=(const wxFont& font) -{ - if ( this != &font ) - Ref(font); - - return (wxFont &)*this; + return false; } bool wxFontBase::operator==(const wxFont& font) const { // either it is the same font, i.e. they share the same common data or they // have different ref datas but still describe the same font - return GetFontData() == font.GetFontData() || + return IsSameAs(font) || ( - Ok() == font.Ok() && + IsOk() == font.IsOk() && GetPointSize() == font.GetPointSize() && + // in wxGTK1 GetPixelSize() calls GetInternalFont() which uses + // operator==() resulting in infinite recursion so we can't use it + // in that port +#if !defined(__WXGTK__) || defined(__WXGTK20__) + GetPixelSize() == font.GetPixelSize() && +#endif GetFamily() == font.GetFamily() && GetStyle() == font.GetStyle() && GetWeight() == font.GetWeight() && GetUnderlined() == font.GetUnderlined() && - GetFaceName() == font.GetFaceName() && + GetFaceName().IsSameAs(font.GetFaceName(), false) && GetEncoding() == font.GetEncoding() ); } -bool wxFontBase::operator!=(const wxFont& font) const -{ - return !(*this == font); -} - wxString wxFontBase::GetFamilyString() const { - wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") ); + wxCHECK_MSG( IsOk(), "wxFONTFAMILY_DEFAULT", "invalid font" ); switch ( GetFamily() ) { - case wxDECORATIVE: return wxT("wxDECORATIVE"); - case wxROMAN: return wxT("wxROMAN"); - case wxSCRIPT: return wxT("wxSCRIPT"); - case wxSWISS: return wxT("wxSWISS"); - case wxMODERN: return wxT("wxMODERN"); - case wxTELETYPE: return wxT("wxTELETYPE"); - default: return wxT("wxDEFAULT"); + case wxFONTFAMILY_DECORATIVE: return "wxFONTFAMILY_DECORATIVE"; + case wxFONTFAMILY_ROMAN: return "wxFONTFAMILY_ROMAN"; + case wxFONTFAMILY_SCRIPT: return "wxFONTFAMILY_SCRIPT"; + case wxFONTFAMILY_SWISS: return "wxFONTFAMILY_SWISS"; + case wxFONTFAMILY_MODERN: return "wxFONTFAMILY_MODERN"; + case wxFONTFAMILY_TELETYPE: return "wxFONTFAMILY_TELETYPE"; + default: return "wxFONTFAMILY_DEFAULT"; } } wxString wxFontBase::GetStyleString() const { - wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") ); + wxCHECK_MSG( IsOk(), "wxFONTSTYLE_DEFAULT", "invalid font" ); switch ( GetStyle() ) { - case wxNORMAL: return wxT("wxNORMAL"); - case wxSLANT: return wxT("wxSLANT"); - case wxITALIC: return wxT("wxITALIC"); - default: return wxT("wxDEFAULT"); + case wxFONTSTYLE_NORMAL: return "wxFONTSTYLE_NORMAL"; + case wxFONTSTYLE_SLANT: return "wxFONTSTYLE_SLANT"; + case wxFONTSTYLE_ITALIC: return "wxFONTSTYLE_ITALIC"; + default: return "wxFONTSTYLE_DEFAULT"; } } wxString wxFontBase::GetWeightString() const { - wxCHECK_MSG( Ok(), wxT("wxDEFAULT"), wxT("invalid font") ); + wxCHECK_MSG( IsOk(), "wxFONTWEIGHT_DEFAULT", "invalid font" ); switch ( GetWeight() ) { - case wxNORMAL: return wxT("wxNORMAL"); - case wxBOLD: return wxT("wxBOLD"); - case wxLIGHT: return wxT("wxLIGHT"); - default: return wxT("wxDEFAULT"); + case wxFONTWEIGHT_NORMAL: return "wxFONTWEIGHT_NORMAL"; + case wxFONTWEIGHT_BOLD: return "wxFONTWEIGHT_BOLD"; + case wxFONTWEIGHT_LIGHT: return "wxFONTWEIGHT_LIGHT"; + default: return "wxFONTWEIGHT_DEFAULT"; + } +} + +bool wxFontBase::SetFaceName(const wxString& facename) +{ +#if wxUSE_FONTENUM + if (!wxFontEnumerator::IsValidFacename(facename)) + { + UnRef(); // make IsOk() return false + return false; } +#else // !wxUSE_FONTENUM + wxUnusedVar(facename); +#endif // wxUSE_FONTENUM/!wxUSE_FONTENUM + + return true; } + // ---------------------------------------------------------------------------- // wxNativeFontInfo // ---------------------------------------------------------------------------- +// Up to now, there are no native implementations of this function: +void wxNativeFontInfo::SetFaceName(const wxArrayString& facenames) +{ +#if wxUSE_FONTENUM + for (size_t i=0; i < facenames.GetCount(); i++) + { + if (wxFontEnumerator::IsValidFacename(facenames[i])) + { + SetFaceName(facenames[i]); + return; + } + } + + // set the first valid facename we can find on this system + wxString validfacename = wxFontEnumerator::GetFacenames().Item(0); + wxLogTrace(wxT("font"), wxT("Falling back to '%s'"), validfacename.c_str()); + SetFaceName(validfacename); +#else // !wxUSE_FONTENUM + SetFaceName(facenames[0]); +#endif // wxUSE_FONTENUM/!wxUSE_FONTENUM +} + + #ifdef wxNO_NATIVE_FONTINFO // These are the generic forms of FromString()/ToString. @@ -251,39 +442,42 @@ bool wxNativeFontInfo::FromString(const wxString& s) token = tokenizer.GetNextToken(); if ( !token.ToLong(&l) ) - return FALSE; + return false; pointSize = (int)l; token = tokenizer.GetNextToken(); if ( !token.ToLong(&l) ) - return FALSE; + return false; family = (wxFontFamily)l; token = tokenizer.GetNextToken(); if ( !token.ToLong(&l) ) - return FALSE; + return false; style = (wxFontStyle)l; token = tokenizer.GetNextToken(); if ( !token.ToLong(&l) ) - return FALSE; + return false; weight = (wxFontWeight)l; token = tokenizer.GetNextToken(); if ( !token.ToLong(&l) ) - return FALSE; + return false; underlined = l != 0; faceName = tokenizer.GetNextToken(); + +#ifndef __WXMAC__ if( !faceName ) - return FALSE; + return false; +#endif token = tokenizer.GetNextToken(); if ( !token.ToLong(&l) ) - return FALSE; + return false; encoding = (wxFontEncoding)l; - return TRUE; + return true; } wxString wxNativeFontInfo::ToString() const @@ -305,11 +499,11 @@ wxString wxNativeFontInfo::ToString() const void wxNativeFontInfo::Init() { - pointSize = wxNORMAL_FONT->GetPointSize(); + pointSize = 0; family = wxFONTFAMILY_DEFAULT; style = wxFONTSTYLE_NORMAL; weight = wxFONTWEIGHT_NORMAL; - underlined = FALSE; + underlined = false; faceName.clear(); encoding = wxFONTENCODING_DEFAULT; } @@ -369,9 +563,10 @@ void wxNativeFontInfo::SetUnderlined(bool underlined_) underlined = underlined_; } -void wxNativeFontInfo::SetFaceName(wxString facename_) +bool wxNativeFontInfo::SetFaceName(const wxString& facename_) { faceName = facename_; + return true; } void wxNativeFontInfo::SetFamily(wxFontFamily family_) @@ -391,7 +586,7 @@ void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding_) // format there anyhow (but there is a well-defined standard for X11 fonts used // by wxGTK and wxMotif) -#if defined(wxNO_NATIVE_FONTINFO) || defined(__WXMSW__) +#if defined(wxNO_NATIVE_FONTINFO) || defined(__WXMSW__) || defined (__WXPM__) || defined(__WXOSX__) wxString wxNativeFontInfo::ToUserString() const { @@ -401,7 +596,7 @@ wxString wxNativeFontInfo::ToUserString() const // but what else can we do? if ( GetUnderlined() ) { - desc << _("underlined "); + desc << _("underlined"); } switch ( GetWeight() ) @@ -414,11 +609,11 @@ wxString wxNativeFontInfo::ToUserString() const break; case wxFONTWEIGHT_LIGHT: - desc << _("light "); + desc << _(" light"); break; case wxFONTWEIGHT_BOLD: - desc << _("bold "); + desc << _(" bold"); break; } @@ -434,7 +629,7 @@ wxString wxNativeFontInfo::ToUserString() const // we don't distinguish between the two for now anyhow... case wxFONTSTYLE_ITALIC: case wxFONTSTYLE_SLANT: - desc << _("italic"); + desc << _(" italic"); break; } @@ -450,13 +645,15 @@ wxString wxNativeFontInfo::ToUserString() const desc << _T(' ') << size; } +#if wxUSE_FONTMAP wxFontEncoding enc = GetEncoding(); if ( enc != wxFONTENCODING_DEFAULT && enc != wxFONTENCODING_SYSTEM ) { - desc << _T(' ') << wxTheFontMapper->GetEncodingName(enc); + desc << _T(' ') << wxFontMapper::GetEncodingName(enc); } +#endif // wxUSE_FONTMAP - return desc; + return desc.Strip(wxString::both).MakeLower(); } bool wxNativeFontInfo::FromUserString(const wxString& s) @@ -471,27 +668,32 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) wxString face; unsigned long size; - wxFontEncoding encoding; + bool weightfound = false, pointsizefound = false; +#if wxUSE_FONTMAP + bool encodingfound = false; +#endif while ( tokenizer.HasMoreTokens() ) { wxString token = tokenizer.GetNextToken(); // normalize it - token.Trim(TRUE).Trim(FALSE).MakeLower(); + token.Trim(true).Trim(false).MakeLower(); // look for the known tokens if ( token == _T("underlined") || token == _("underlined") ) { - SetUnderlined(TRUE); + SetUnderlined(true); } else if ( token == _T("light") || token == _("light") ) { SetWeight(wxFONTWEIGHT_LIGHT); + weightfound = true; } else if ( token == _T("bold") || token == _("bold") ) { SetWeight(wxFONTWEIGHT_BOLD); + weightfound = true; } else if ( token == _T("italic") || token == _("italic") ) { @@ -500,14 +702,24 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) else if ( token.ToULong(&size) ) { SetPointSize(size); + pointsizefound = true; } - else if ( (encoding = wxTheFontMapper->CharsetToEncoding(token, FALSE)) - != wxFONTENCODING_DEFAULT ) + else + { +#if wxUSE_FONTMAP + // try to interpret this as an encoding + wxFontEncoding encoding = wxFontMapper::Get()->CharsetToEncoding(token, false); + if ( encoding != wxFONTENCODING_DEFAULT && + encoding != wxFONTENCODING_SYSTEM ) // returned when the recognition failed { SetEncoding(encoding); + encodingfound = true; } - else // assume it is the face name + else { +#endif // wxUSE_FONTMAP + + // assume it is the face name if ( !face.empty() ) { face += _T(' '); @@ -517,6 +729,10 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) // skip the code which resets face below continue; + +#if wxUSE_FONTMAP + } +#endif // wxUSE_FONTMAP } // if we had had the facename, we shouldn't continue appending tokens @@ -524,7 +740,18 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) // bar") if ( !face.empty() ) { - SetFaceName(face); + // NB: the check on the facename is implemented in wxFontBase::SetFaceName + // and not in wxNativeFontInfo::SetFaceName thus we need to explicitely + // call here wxFontEnumerator::IsValidFacename + if ( +#if wxUSE_FONTENUM + !wxFontEnumerator::IsValidFacename(face) || +#endif // wxUSE_FONTENUM + !SetFaceName(face) ) + { + SetFaceName(wxNORMAL_FONT->GetFaceName()); + } + face.clear(); } } @@ -532,11 +759,57 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) // we might not have flushed it inside the loop if ( !face.empty() ) { - SetFaceName(face); + // NB: the check on the facename is implemented in wxFontBase::SetFaceName + // and not in wxNativeFontInfo::SetFaceName thus we need to explicitely + // call here wxFontEnumerator::IsValidFacename + if ( +#if wxUSE_FONTENUM + !wxFontEnumerator::IsValidFacename(face) || +#endif // wxUSE_FONTENUM + !SetFaceName(face) ) + { + SetFaceName(wxNORMAL_FONT->GetFaceName()); + } + } + + // set point size to default value if size was not given + if ( !pointsizefound ) + SetPointSize(wxNORMAL_FONT->GetPointSize()); + + // set font weight to default value if weight was not given + if ( !weightfound ) + SetWeight(wxFONTWEIGHT_NORMAL); + +#if wxUSE_FONTMAP + // set font encoding to default value if encoding was not given + if ( !encodingfound ) + SetEncoding(wxFONTENCODING_SYSTEM); +#endif // wxUSE_FONTMAP + + return true; +} + +#endif // generic or wxMSW or wxOS2 + + +// wxFont <-> wxString utilities, used by wxConfig +wxString wxToString(const wxFontBase& font) +{ + return font.IsOk() ? font.GetNativeFontInfoDesc() + : wxString(); +} + +bool wxFromString(const wxString& str, wxFontBase *font) +{ + wxCHECK_MSG( font, false, _T("NULL output parameter") ); + + if ( str.empty() ) + { + *font = wxNullFont; + return true; } - return TRUE; + return font->SetNativeFontInfo(str); } -#endif // generic or wxMSW