]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/fontcmn.cpp
blind build fix for STL builds
[wxWidgets.git] / src / common / fontcmn.cpp
index 743667fa2ae922e9befe0b821759c48fcdef7b7e..96407bbfd6be9fa84117b6402c8fdbdc6740e052 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        common/fontcmn.cpp
+// Name:        src/common/fontcmn.cpp
 // Purpose:     implementation of wxFontBase methods
 // Author:      Vadim Zeitlin
 // Modified by:
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
-#pragma hdrstop
+    #pragma hdrstop
 #endif
 
+#include "wx/font.h"
+
 #ifndef WX_PRECOMP
     #include "wx/dc.h"
-    #include "wx/font.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"
+    #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"
 
 // helper functions
 // ----------------------------------------------------------------------------
 
-static void AdjustFontSize(wxFont& font, wxDC& dc, const wxSize& pixelSize)
+static inline int flags2Style(int flags)
 {
-    int currentSize = 0;
-    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
-    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;
 }
 
 // ----------------------------------------------------------------------------
@@ -129,9 +100,9 @@ wxFontBase::~wxFontBase()
 
 /* 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)
@@ -139,27 +110,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 */
@@ -173,26 +134,6 @@ wxFont *wxFontBase::New(int pointSize,
                flags2Underlined(flags), face, encoding);
 }
 
-/* static */
-wxFont *wxFontBase::New(const wxSize& pixelSize,
-                        int family,
-                        int style,
-                        int weight,
-                        bool underlined,
-                        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
-}
-
 /* static */
 wxFont *wxFontBase::New(const wxSize& pixelSize,
                         wxFontFamily family,
@@ -204,24 +145,6 @@ wxFont *wxFontBase::New(const wxSize& pixelSize,
                flags2Underlined(flags), face, encoding);
 }
 
-wxSize wxFontBase::GetPixelSize() const
-{
-    wxScreenDC dc;
-    dc.SetFont(*(wxFont *)this);
-    return wxSize(dc.GetCharWidth(), dc.GetCharHeight());
-}
-
-bool wxFontBase::IsUsingSizeInPixels() const
-{
-    return false;
-}
-
-void wxFontBase::SetPixelSize( const wxSize& pixelSize )
-{
-    wxScreenDC dc;
-    AdjustFontSize(*(wxFont *)this, dc, pixelSize);
-}
-
 /* static */
 wxFont *wxFontBase::New(const wxNativeFontInfo& info)
 {
@@ -243,6 +166,81 @@ bool wxFontBase::IsFixedWidth() const
     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;
+}
+
+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;
+
+    // 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<wxFont*>(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::DoSetNativeFontInfo(const wxNativeFontInfo& info)
 {
 #ifdef wxNO_NATIVE_FONTINFO
@@ -265,6 +263,11 @@ wxString wxFontBase::GetNativeFontInfoDesc() const
     if ( fontInfo )
     {
         fontDesc = fontInfo->ToString();
+        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;
@@ -277,97 +280,148 @@ wxString wxFontBase::GetNativeFontInfoUserDesc() const
     if ( fontInfo )
     {
         fontDesc = fontInfo->ToUserString();
+        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;
     }
+
+    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.
@@ -509,9 +563,10 @@ void wxNativeFontInfo::SetUnderlined(bool underlined_)
     underlined = underlined_;
 }
 
-void wxNativeFontInfo::SetFaceName(const wxString& facename_)
+bool wxNativeFontInfo::SetFaceName(const wxString& facename_)
 {
     faceName = facename_;
+    return true;
 }
 
 void wxNativeFontInfo::SetFamily(wxFontFamily family_)
@@ -541,7 +596,7 @@ wxString wxNativeFontInfo::ToUserString() const
     // but what else can we do?
     if ( GetUnderlined() )
     {
-        desc << _("underlined ");
+        desc << _("underlined");
     }
 
     switch ( GetWeight() )
@@ -554,11 +609,11 @@ wxString wxNativeFontInfo::ToUserString() const
             break;
 
         case wxFONTWEIGHT_LIGHT:
-            desc << _("light ");
+            desc << _(" light");
             break;
 
         case wxFONTWEIGHT_BOLD:
-            desc << _("bold ");
+            desc << _(" bold");
             break;
     }
 
@@ -574,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;
     }
 
@@ -598,7 +653,7 @@ wxString wxNativeFontInfo::ToUserString() const
     }
 #endif // wxUSE_FONTMAP
 
-    return desc;
+    return desc.Strip(wxString::both).MakeLower();
 }
 
 bool wxNativeFontInfo::FromUserString(const wxString& s)
@@ -613,10 +668,10 @@ bool wxNativeFontInfo::FromUserString(const wxString& s)
 
     wxString face;
     unsigned long size;
-
+    bool weightfound = false, pointsizefound = false;
 #if wxUSE_FONTMAP
-    wxFontEncoding encoding;
-#endif // wxUSE_FONTMAP
+    bool encodingfound = false;
+#endif
 
     while ( tokenizer.HasMoreTokens() )
     {
@@ -633,10 +688,12 @@ bool wxNativeFontInfo::FromUserString(const wxString& s)
         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") )
         {
@@ -645,16 +702,24 @@ bool wxNativeFontInfo::FromUserString(const wxString& s)
         else if ( token.ToULong(&size) )
         {
             SetPointSize(size);
+            pointsizefound = true;
         }
+        else
+        {
 #if wxUSE_FONTMAP
-        else if ( (encoding = wxFontMapper::Get()->CharsetToEncoding(token, false))
-                    != wxFONTENCODING_DEFAULT )
+            // 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;
         }
-#endif // wxUSE_FONTMAP
-        else // assume it is the face name
+            else
         {
+#endif // wxUSE_FONTMAP
+
+                // assume it is the face name
             if ( !face.empty() )
             {
                 face += _T(' ');
@@ -664,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
@@ -671,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();
         }
     }
@@ -679,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 font->SetNativeFontInfo(str);
+}
+
+