X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0c14b6c3241d48d9cc36a2fd0aeab0ba330d96de..0cb9ba2518e309fadf30ae39daba683ccd80e417:/src/common/fontcmn.cpp diff --git a/src/common/fontcmn.cpp b/src/common/fontcmn.cpp index a5ff16a10f..ef779b3fb4 100644 --- a/src/common/fontcmn.cpp +++ b/src/common/fontcmn.cpp @@ -45,6 +45,32 @@ #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 + ? _T("normal") + : weight == wxFONTWEIGHT_BOLD + ? _T("bold") + : _T("light"), + font->GetStyle() == wxFONTSTYLE_NORMAL + ? _T("regular") + : _T("italic"), + font->GetPointSize(), + font->GetEncoding()); + + wxStrlcpy(buf, s.mb_str(), WXSIZEOF(buf)); + return buf; +} + // ============================================================================ // implementation // ============================================================================ @@ -53,57 +79,27 @@ // helper functions // ---------------------------------------------------------------------------- -static void AdjustFontSize(wxFont& font, wxDC& dc, const wxSize& pixelSize) +static inline int flags2Style(int flags) { - 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 = font.GetPointSize(); - while (currentSize > 0) - { - dc.SetFont(font); - - // if currentSize (in points) results in a font that is smaller - // than required by pixelSize it is considered a good size - if (dc.GetCharHeight() <= pixelSize.GetHeight() && - (!pixelSize.GetWidth() || - 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; - } + return flags & wxFONTFLAG_ITALIC + ? wxFONTSTYLE_ITALIC + : flags & wxFONTFLAG_SLANT + ? wxFONTSTYLE_SLANT + : wxFONTSTYLE_NORMAL; +} - font.SetPointSize(currentSize); - } +static inline int flags2Weight(int flags) +{ + return flags & wxFONTFLAG_LIGHT + ? wxFONTWEIGHT_LIGHT + : flags & wxFONTFLAG_BOLD + ? wxFONTWEIGHT_BOLD + : wxFONTWEIGHT_NORMAL; +} - if (currentSize != largestGood) - font.SetPointSize(largestGood); +static inline bool flags2Underlined(int flags) +{ + return (flags & wxFONTFLAG_UNDERLINED) != 0; } // ---------------------------------------------------------------------------- @@ -140,27 +136,17 @@ wxFont *wxFontBase::New(int size, return new wxFont(size, family, style, weight, underlined, face, encoding); } -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) +/* static */ +wxFont *wxFontBase::New(const wxSize& pixelSize, + wxFontFamily family, + wxFontStyle style, + wxFontWeight weight, + bool underlined, + const wxString& face, + wxFontEncoding encoding) { - return (flags & wxFONTFLAG_UNDERLINED) != 0; + return new wxFont(pixelSize, family, style, weight, underlined, + face, encoding); } /* static */ @@ -177,32 +163,33 @@ wxFont *wxFontBase::New(int pointSize, /* static */ wxFont *wxFontBase::New(const wxSize& pixelSize, wxFontFamily family, - wxFontStyle style, - wxFontWeight weight, - bool underlined, + int flags, const wxString& face, wxFontEncoding encoding) { -#if defined(__WXMSW__) - return new wxFont(pixelSize, family, style, weight, underlined, - face, encoding); -#else - wxFont *self = New(10, family, style, weight, underlined, face, encoding); - wxScreenDC dc; - AdjustFontSize(*(wxFont *)self, dc, pixelSize); - return self; -#endif + return New(pixelSize, 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) +wxFont *wxFontBase::New(const wxNativeFontInfo& info) { - return New(pixelSize, family, flags2Style(flags), flags2Weight(flags), - flags2Underlined(flags), face, encoding); + return new wxFont(info); +} + +/* static */ +wxFont *wxFontBase::New(const wxString& strNativeFontDesc) +{ + wxNativeFontInfo fontInfo; + if ( !fontInfo.FromString(strNativeFontDesc) ) + return new wxFont(*wxNORMAL_FONT); + + return New(fontInfo); +} + +bool wxFontBase::IsFixedWidth() const +{ + return GetFamily() == wxFONTFAMILY_TELETYPE; } wxSize wxFontBase::GetPixelSize() const @@ -219,29 +206,65 @@ bool wxFontBase::IsUsingSizeInPixels() const 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" ); + wxScreenDC dc; - AdjustFontSize(*(wxFont *)this, dc, pixelSize); -} -/* static */ -wxFont *wxFontBase::New(const wxNativeFontInfo& info) -{ - return new wxFont(info); -} + // 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; -/* static */ -wxFont *wxFontBase::New(const wxString& strNativeFontDesc) -{ - wxNativeFontInfo fontInfo; - if ( !fontInfo.FromString(strNativeFontDesc) ) - return new wxFont(*wxNORMAL_FONT); + bool initialGoodFound = false; + bool initialBadFound = false; - return New(fontInfo); -} + // 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)); -bool wxFontBase::IsFixedWidth() const -{ - return GetFamily() == wxFONTFAMILY_TELETYPE; + // 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::DoSetNativeFontInfo(const wxNativeFontInfo& info) @@ -323,7 +346,7 @@ bool wxFontBase::operator==(const wxFont& font) const // have different ref datas but still describe the same font 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 @@ -342,43 +365,44 @@ bool wxFontBase::operator==(const wxFont& font) const 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"; + case wxFONTFAMILY_UNKNOWN: return "wxFONTFAMILY_UNKNOWN"; + 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"; } } @@ -387,7 +411,7 @@ bool wxFontBase::SetFaceName(const wxString& facename) #if wxUSE_FONTENUM if (!wxFontEnumerator::IsValidFacename(facename)) { - UnRef(); // make Ok() return false + UnRef(); // make IsOk() return false return false; } #else // !wxUSE_FONTENUM @@ -589,7 +613,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__) || defined (__WXPM__) +#if defined(wxNO_NATIVE_FONTINFO) || defined(__WXMSW__) || defined (__WXPM__) || defined(__WXOSX__) wxString wxNativeFontInfo::ToUserString() const { @@ -639,7 +663,61 @@ 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 << _T(" '") << face << _("'"); + } + else + desc << _T(' ') << 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(); @@ -664,10 +742,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, _T(";, "), wxTOKEN_STRTOK); wxString face; unsigned long size; @@ -675,6 +756,7 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) #if wxUSE_FONTMAP bool encodingfound = false; #endif + bool insideQuotes = false; while ( tokenizer.HasMoreTokens() ) { @@ -682,8 +764,36 @@ 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 ( insideQuotes ) + { + // only the facename may be quoted: + face += " " + token; + continue; + } if ( token == _T("underlined") || token == _("underlined") ) { SetUnderlined(true); @@ -743,10 +853,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 // call here wxFontEnumerator::IsValidFacename - if ( + else if ( #if wxUSE_FONTENUM !wxFontEnumerator::IsValidFacename(face) || #endif // wxUSE_FONTENUM