X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f1c40652a0c2d6752c57df1b8aed22fae7e118dd..7198c3368055d88249a338eb33b21f051f674806:/src/common/fontcmn.cpp?ds=inline diff --git a/src/common/fontcmn.cpp b/src/common/fontcmn.cpp index 67ee5bff64..d54521c449 100644 --- a/src/common/fontcmn.cpp +++ b/src/common/fontcmn.cpp @@ -29,6 +29,7 @@ #ifndef WX_PRECOMP #include "wx/dc.h" #include "wx/intl.h" + #include "wx/math.h" #include "wx/dcscreen.h" #include "wx/log.h" #include "wx/gdicmn.h" @@ -45,6 +46,84 @@ #include "wx/tokenzr.h" +// debugger helper: this function can be called from a debugger to show what +// the date really is +extern const char *wxDumpFont(const wxFont *font) +{ + static char buf[256]; + + const wxFontWeight weight = font->GetWeight(); + + wxString s; + s.Printf(wxS("%s-%s-%s-%d-%d"), + font->GetFaceName(), + weight == wxFONTWEIGHT_NORMAL + ? wxT("normal") + : weight == wxFONTWEIGHT_BOLD + ? wxT("bold") + : wxT("light"), + font->GetStyle() == wxFONTSTYLE_NORMAL + ? wxT("regular") + : wxT("italic"), + font->GetPointSize(), + font->GetEncoding()); + + wxStrlcpy(buf, s.mb_str(), WXSIZEOF(buf)); + return buf; +} + +// ---------------------------------------------------------------------------- +// XTI +// ---------------------------------------------------------------------------- + +wxBEGIN_ENUM( wxFontFamily ) +wxENUM_MEMBER( wxFONTFAMILY_DEFAULT ) +wxENUM_MEMBER( wxFONTFAMILY_DECORATIVE ) +wxENUM_MEMBER( wxFONTFAMILY_ROMAN ) +wxENUM_MEMBER( wxFONTFAMILY_SCRIPT ) +wxENUM_MEMBER( wxFONTFAMILY_SWISS ) +wxENUM_MEMBER( wxFONTFAMILY_MODERN ) +wxENUM_MEMBER( wxFONTFAMILY_TELETYPE ) +wxEND_ENUM( wxFontFamily ) + +wxBEGIN_ENUM( wxFontStyle ) +wxENUM_MEMBER( wxFONTSTYLE_NORMAL ) +wxENUM_MEMBER( wxFONTSTYLE_ITALIC ) +wxENUM_MEMBER( wxFONTSTYLE_SLANT ) +wxEND_ENUM( wxFontStyle ) + +wxBEGIN_ENUM( wxFontWeight ) +wxENUM_MEMBER( wxFONTWEIGHT_NORMAL ) +wxENUM_MEMBER( wxFONTWEIGHT_LIGHT ) +wxENUM_MEMBER( wxFONTWEIGHT_BOLD ) +wxEND_ENUM( wxFontWeight ) + +wxIMPLEMENT_DYNAMIC_CLASS_WITH_COPY_XTI(wxFont, wxGDIObject, "wx/font.h") + +//WX_IMPLEMENT_ANY_VALUE_TYPE(wxAnyValueTypeImpl) + +wxBEGIN_PROPERTIES_TABLE(wxFont) +wxPROPERTY( Size,int, SetPointSize, GetPointSize, 12, 0 /*flags*/, \ + wxT("Helpstring"), wxT("group")) +wxPROPERTY( Family, wxFontFamily , SetFamily, GetFamily, (wxFontFamily)wxDEFAULT, \ + 0 /*flags*/, wxT("Helpstring"), wxT("group")) // wxFontFamily +wxPROPERTY( Style, wxFontStyle, SetStyle, GetStyle, (wxFontStyle)wxNORMAL, 0 /*flags*/, \ + wxT("Helpstring"), wxT("group")) // wxFontStyle +wxPROPERTY( Weight, wxFontWeight, SetWeight, GetWeight, (wxFontWeight)wxNORMAL, 0 /*flags*/, \ + wxT("Helpstring"), wxT("group")) // wxFontWeight +wxPROPERTY( Underlined, bool, SetUnderlined, GetUnderlined, false, 0 /*flags*/, \ + wxT("Helpstring"), wxT("group")) +wxPROPERTY( Face, wxString, SetFaceName, GetFaceName, wxEMPTY_PARAMETER_VALUE, \ + 0 /*flags*/, wxT("Helpstring"), wxT("group")) +wxPROPERTY( Encoding, wxFontEncoding, SetEncoding, GetEncoding, \ + wxFONTENCODING_DEFAULT, 0 /*flags*/, wxT("Helpstring"), wxT("group")) +wxEND_PROPERTIES_TABLE() + +wxCONSTRUCTOR_6( wxFont, int, Size, wxFontFamily, Family, wxFontStyle, Style, wxFontWeight, Weight, \ + bool, Underlined, wxString, Face ) + +wxEMPTY_HANDLERS_TABLE(wxFont) + // ============================================================================ // implementation // ============================================================================ @@ -88,7 +167,7 @@ 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") ); + wxT("can't set default encoding to wxFONTENCODING_DEFAULT") ); ms_encodingDefault = encoding; } @@ -188,7 +267,7 @@ void wxFontBase::SetPixelSize( const wxSize& pixelSize ) // 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; @@ -258,6 +337,8 @@ void wxFontBase::DoSetNativeFontInfo(const wxNativeFontInfo& info) wxString wxFontBase::GetNativeFontInfoDesc() const { + wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") ); + wxString fontDesc; const wxNativeFontInfo *fontInfo = GetNativeFontInfo(); if ( fontInfo ) @@ -275,6 +356,8 @@ wxString wxFontBase::GetNativeFontInfoDesc() const wxString wxFontBase::GetNativeFontInfoUserDesc() const { + wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") ); + wxString fontDesc; const wxNativeFontInfo *fontInfo = GetNativeFontInfo(); if ( fontInfo ) @@ -337,6 +420,20 @@ bool wxFontBase::operator==(const wxFont& font) const ); } +wxFontFamily wxFontBase::GetFamily() const +{ + wxCHECK_MSG( IsOk(), wxFONTFAMILY_UNKNOWN, wxS("invalid font") ); + + // Don't return wxFONTFAMILY_UNKNOWN from here because it prevents the code + // like wxFont(size, wxNORMAL_FONT->GetFamily(), ...) from working (see + // #12330). This is really just a hack but it allows to keep compatibility + // and doesn't really have any bad drawbacks so do this until someone comes + // up with a better idea. + const wxFontFamily family = DoGetFamily(); + + return family == wxFONTFAMILY_UNKNOWN ? wxFONTFAMILY_DEFAULT : family; +} + wxString wxFontBase::GetFamilyString() const { wxCHECK_MSG( IsOk(), "wxFONTFAMILY_DEFAULT", "invalid font" ); @@ -349,6 +446,7 @@ wxString wxFontBase::GetFamilyString() const case wxFONTFAMILY_SWISS: return "wxFONTFAMILY_SWISS"; case wxFONTFAMILY_MODERN: return "wxFONTFAMILY_MODERN"; case wxFONTFAMILY_TELETYPE: return "wxFONTFAMILY_TELETYPE"; + case wxFONTFAMILY_UNKNOWN: return "wxFONTFAMILY_UNKNOWN"; default: return "wxFONTFAMILY_DEFAULT"; } } @@ -394,6 +492,80 @@ bool wxFontBase::SetFaceName(const wxString& facename) return true; } +void wxFontBase::SetSymbolicSize(wxFontSymbolicSize size) +{ + SetSymbolicSizeRelativeTo(size, wxNORMAL_FONT->GetPointSize()); +} + +/* static */ +int wxFontBase::AdjustToSymbolicSize(wxFontSymbolicSize size, int base) +{ + // Using a fixed factor (1.2, from CSS2) is a bad idea as explained at + // http://www.w3.org/TR/CSS21/fonts.html#font-size-props so use the values + // from http://style.cleverchimp.com/font_size_intervals/altintervals.html + // instead. + static const float factors[] = { 0.60f, 0.75f, 0.89f, 1.f, 1.2f, 1.5f, 2.f }; + + wxCOMPILE_TIME_ASSERT + ( + WXSIZEOF(factors) == wxFONTSIZE_XX_LARGE - wxFONTSIZE_XX_SMALL + 1, + WrongFontSizeFactorsSize + ); + + return wxRound(factors[size - wxFONTSIZE_XX_SMALL]*base); +} + +wxFont& wxFont::MakeBold() +{ + SetWeight(wxFONTWEIGHT_BOLD); + return *this; +} + +wxFont wxFont::Bold() const +{ + wxFont font(*this); + font.MakeBold(); + return font; +} + +wxFont& wxFont::MakeItalic() +{ + SetStyle(wxFONTSTYLE_ITALIC); + return *this; +} + +wxFont wxFont::Italic() const +{ + wxFont font(*this); + font.MakeItalic(); + return font; +} + +wxFont& wxFont::MakeUnderlined() +{ + SetUnderlined(true); + return *this; +} + +wxFont wxFont::Underlined() const +{ + wxFont font(*this); + font.MakeUnderlined(); + return font; +} + +wxFont& wxFont::Scale(float x) +{ + SetPointSize(int(x*GetPointSize() + 0.5)); + return *this; +} + +wxFont wxFont::Scaled(float x) const +{ + wxFont font(*this); + font.Scale(x); + return font; +} // ---------------------------------------------------------------------------- // wxNativeFontInfo @@ -433,7 +605,7 @@ bool wxNativeFontInfo::FromString(const wxString& s) { long l; - wxStringTokenizer tokenizer(s, _T(";")); + wxStringTokenizer tokenizer(s, wxT(";")); wxString token = tokenizer.GetNextToken(); // @@ -484,7 +656,7 @@ wxString wxNativeFontInfo::ToString() const { wxString s; - s.Printf(_T("%d;%d;%d;%d;%d;%d;%s;%d"), + s.Printf(wxT("%d;%d;%d;%d;%d;%d;%s;%d"), 0, // version pointSize, family, @@ -602,7 +774,7 @@ wxString wxNativeFontInfo::ToUserString() const switch ( GetWeight() ) { default: - wxFAIL_MSG( _T("unknown font weight") ); + wxFAIL_MSG( wxT("unknown font weight") ); // fall through case wxFONTWEIGHT_NORMAL: @@ -620,7 +792,7 @@ wxString wxNativeFontInfo::ToUserString() const switch ( GetStyle() ) { default: - wxFAIL_MSG( _T("unknown font style") ); + wxFAIL_MSG( wxT("unknown font style") ); // fall through case wxFONTSTYLE_NORMAL: @@ -636,20 +808,74 @@ wxString wxNativeFontInfo::ToUserString() const wxString face = GetFaceName(); if ( !face.empty() ) { - desc << _T(' ') << face; + if (face.Contains(' ') || face.Contains(';') || face.Contains(',')) + { + face.Replace("'", ""); + // eventually remove quote characters: most systems do not + // allow them in a facename anyway so this usually does nothing + + // make it possible for FromUserString() function to understand + // that the different words which compose this facename are + // not different adjectives or other data but rather all parts + // of the facename + desc << wxT(" '") << face << _("'"); + } + else + desc << wxT(' ') << face; + } + else // no face name specified + { + // use the family + wxString familyStr; + switch ( GetFamily() ) + { + case wxFONTFAMILY_DECORATIVE: + familyStr = "decorative"; + break; + + case wxFONTFAMILY_ROMAN: + familyStr = "roman"; + break; + + case wxFONTFAMILY_SCRIPT: + familyStr = "script"; + break; + + case wxFONTFAMILY_SWISS: + familyStr = "swiss"; + break; + + case wxFONTFAMILY_MODERN: + familyStr = "modern"; + break; + + case wxFONTFAMILY_TELETYPE: + familyStr = "teletype"; + break; + + case wxFONTFAMILY_DEFAULT: + case wxFONTFAMILY_UNKNOWN: + break; + + default: + wxFAIL_MSG( "unknown font family" ); + } + + if ( !familyStr.empty() ) + desc << " '" << familyStr << " family'"; } int size = GetPointSize(); if ( size != wxNORMAL_FONT->GetPointSize() ) { - desc << _T(' ') << size; + desc << wxT(' ') << size; } #if wxUSE_FONTMAP wxFontEncoding enc = GetEncoding(); if ( enc != wxFONTENCODING_DEFAULT && enc != wxFONTENCODING_SYSTEM ) { - desc << _T(' ') << wxFontMapper::GetEncodingName(enc); + desc << wxT(' ') << wxFontMapper::GetEncodingName(enc); } #endif // wxUSE_FONTMAP @@ -661,10 +887,13 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) // reset to the default state Init(); + // ToUserString() will quote the facename if it contains spaces, commas + // or semicolons: we must be able to understand that quoted text is + // a single token: + wxString toparse(s); + // parse a more or less free form string - // - // TODO: we should handle at least the quoted facenames - wxStringTokenizer tokenizer(s, _T(";, "), wxTOKEN_STRTOK); + wxStringTokenizer tokenizer(toparse, wxT(";, "), wxTOKEN_STRTOK); wxString face; unsigned long size; @@ -672,6 +901,7 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) #if wxUSE_FONTMAP bool encodingfound = false; #endif + bool insideQuotes = false; while ( tokenizer.HasMoreTokens() ) { @@ -679,23 +909,51 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) // normalize it token.Trim(true).Trim(false).MakeLower(); + if (insideQuotes) + { + if (token.StartsWith("'") || + token.EndsWith("'")) + { + insideQuotes = false; + + // add this last token to the facename: + face += " " + token; + + // normalize facename: + face = face.Trim(true).Trim(false); + face.Replace("'", ""); + + continue; + } + } + else + { + if (token.StartsWith("'")) + insideQuotes = true; + } // look for the known tokens - if ( token == _T("underlined") || token == _("underlined") ) + if ( insideQuotes ) + { + // only the facename may be quoted: + face += " " + token; + continue; + } + if ( token == wxT("underlined") || token == _("underlined") ) { SetUnderlined(true); } - else if ( token == _T("light") || token == _("light") ) + else if ( token == wxT("light") || token == _("light") ) { SetWeight(wxFONTWEIGHT_LIGHT); weightfound = true; } - else if ( token == _T("bold") || token == _("bold") ) + else if ( token == wxT("bold") || token == _("bold") ) { SetWeight(wxFONTWEIGHT_BOLD); weightfound = true; } - else if ( token == _T("italic") || token == _("italic") ) + else if ( token == wxT("italic") || token == _("italic") ) { SetStyle(wxFONTSTYLE_ITALIC); } @@ -722,7 +980,7 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) // assume it is the face name if ( !face.empty() ) { - face += _T(' '); + face += wxT(' '); } face += token; @@ -740,10 +998,32 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) // bar") if ( !face.empty() ) { + wxString familyStr; + if ( face.EndsWith(" family", &familyStr) ) + { + // it's not a facename but rather a font family + wxFontFamily family; + if ( familyStr == "decorative" ) + family = wxFONTFAMILY_DECORATIVE; + else if ( familyStr == "roman" ) + family = wxFONTFAMILY_ROMAN; + else if ( familyStr == "script" ) + family = wxFONTFAMILY_SCRIPT; + else if ( familyStr == "swiss" ) + family = wxFONTFAMILY_SWISS; + else if ( familyStr == "modern" ) + family = wxFONTFAMILY_MODERN; + else if ( familyStr == "teletype" ) + family = wxFONTFAMILY_TELETYPE; + else + return false; + + SetFamily(family); + } // NB: the check on the facename is implemented in wxFontBase::SetFaceName - // and not in wxNativeFontInfo::SetFaceName thus we need to explicitely + // and not in wxNativeFontInfo::SetFaceName thus we need to explicitly // call here wxFontEnumerator::IsValidFacename - if ( + else if ( #if wxUSE_FONTENUM !wxFontEnumerator::IsValidFacename(face) || #endif // wxUSE_FONTENUM @@ -760,7 +1040,7 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) if ( !face.empty() ) { // NB: the check on the facename is implemented in wxFontBase::SetFaceName - // and not in wxNativeFontInfo::SetFaceName thus we need to explicitely + // and not in wxNativeFontInfo::SetFaceName thus we need to explicitly // call here wxFontEnumerator::IsValidFacename if ( #if wxUSE_FONTENUM @@ -801,7 +1081,7 @@ wxString wxToString(const wxFontBase& font) bool wxFromString(const wxString& str, wxFontBase *font) { - wxCHECK_MSG( font, false, _T("NULL output parameter") ); + wxCHECK_MSG( font, false, wxT("NULL output parameter") ); if ( str.empty() ) {