From 85ab460e7d62b52b105b3dc0bbdd36cebc14fb4b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 29 May 2006 00:03:36 +0000 Subject: [PATCH] miscellaneous wxFont enhancements (patch 1496606): - made SetFaceName() bool and return false if the face name is not available - corrected To/FromUserString() to complement each other git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39411 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/font.tex | 20 +++--- docs/latex/wx/fontenum.tex | 8 +++ include/wx/cocoa/font.h | 2 +- include/wx/font.h | 8 +-- include/wx/fontenum.h | 4 ++ include/wx/fontutil.h | 15 ++-- include/wx/gtk/font.h | 2 +- include/wx/gtk1/font.h | 2 +- include/wx/mac/carbon/font.h | 2 +- include/wx/mac/classic/font.h | 2 +- include/wx/mgl/font.h | 2 +- include/wx/motif/font.h | 2 +- include/wx/msw/font.h | 6 +- include/wx/os2/font.h | 2 +- include/wx/palmos/font.h | 2 +- include/wx/x11/font.h | 2 +- samples/font/font.cpp | 80 ++++++++++++++++++---- src/cocoa/font.cpp | 4 +- src/common/fontcmn.cpp | 124 ++++++++++++++++++++++++++++------ src/common/fontenumcmn.cpp | 28 ++++++++ src/gtk/font.cpp | 11 +-- src/gtk1/font.cpp | 11 +-- src/mac/carbon/font.cpp | 4 +- src/mac/classic/font.cpp | 4 +- src/mgl/font.cpp | 4 +- src/motif/font.cpp | 4 +- src/msw/font.cpp | 87 +++++++++++++++++++----- src/os2/font.cpp | 14 ++-- src/palmos/font.cpp | 5 +- src/unix/fontutil.cpp | 11 ++- src/x11/font.cpp | 10 +-- 31 files changed, 378 insertions(+), 104 deletions(-) diff --git a/docs/latex/wx/font.tex b/docs/latex/wx/font.tex index 0f74d6c2db..5561188f3d 100644 --- a/docs/latex/wx/font.tex +++ b/docs/latex/wx/font.tex @@ -304,8 +304,8 @@ family identifiers. \constfunc{wxString}{GetNativeFontInfoDesc}{\void} -Returns the platform-dependent string completely describing this font or an -empty string if the font wasn't constructed using the native font description. +Returns the platform-dependent string completely describing this font. +Returned string is always non-empty. Note that the returned string is not meant to be shown or edited by the user: a typical use of this function is for serializing in string-form a wxFont object. @@ -318,7 +318,8 @@ use of this function is for serializing in string-form a wxFont object. \func{wxString}{GetNativeFontInfoUserDesc}{\void} -Returns a user-friendly string for this font object. Some examples of the formats of returned strings (which are platform-dependent) are in \helpref{SetNativeFontInfoUserDesc}{wxfontsetnativefontinfouserdesc}. +Returns a user-friendly string for this font object. Returned string is always non-empty. +Some examples of the formats of returned strings (which are platform-dependent) are in \helpref{SetNativeFontInfoUserDesc}{wxfontsetnativefontinfouserdesc}. \wxheading{See also} @@ -417,9 +418,10 @@ Sets the default font encoding. \membersection{wxFont::SetFaceName}\label{wxfontsetfacename} -\func{void}{SetFaceName}{\param{const wxString\& }{faceName}} +\func{bool}{SetFaceName}{\param{const wxString\& }{faceName}} Sets the facename for the font. +Returns \true if the given face name exists; \false otherwise. \wxheading{Parameters} @@ -465,9 +467,10 @@ Sets the font family. \membersection{wxFont::SetNativeFontInfo}\label{wxfontsetnativefontinfo} -\func{void}{SetNativeFontInfo}{\param{const wxString\& }{info}} +\func{bool}{SetNativeFontInfo}{\param{const wxString\& }{info}} -Creates the font corresponding to the given native font description string +Creates the font corresponding to the given native font description string and returns \true if +the creation was successful. which must have been previously returned by \helpref{GetNativeFontInfoDesc}{wxfontgetnativefontinfodesc}. If the string is invalid, font is unchanged. This function is typically used for de-serializing a wxFont @@ -480,9 +483,10 @@ object previously saved in a string-form. \membersection{wxFont::SetNativeFontInfoUserDesc}\label{wxfontsetnativefontinfouserdesc} -\func{void}{SetNativeFontInfoUserDesc}{\param{const wxString\& }{info}} +\func{bool}{SetNativeFontInfoUserDesc}{\param{const wxString\& }{info}} -Creates the font corresponding to the given native font description string. +Creates the font corresponding to the given native font description string and returns \true if +the creation was successful. Unlike \helpref{SetNativeFontInfo}{wxfontsetnativefontinfo}, this function accepts strings which are user-friendly. Examples of accepted string formats are: diff --git a/docs/latex/wx/fontenum.tex b/docs/latex/wx/fontenum.tex index 749f1d77b9..12f3a90c90 100644 --- a/docs/latex/wx/fontenum.tex +++ b/docs/latex/wx/fontenum.tex @@ -91,6 +91,14 @@ Return array of strings containing all facenames found by \helpref{EnumerateFacenames}{wxfontenumeratorenumeratefacenames}. +\membersection{wxFontEnumerator::IsValidFacename}\label{wxfontenumeratorisvalidfacename} + +\func{static bool}{IsValidFacename}{\param{const wxString \&}{ facename}} + +Returns \true if the given string is valid face name, i.e. it's the face name of an installed +font and it can safely be used with \helpref{wxFont::SetFaceName}{wxfontsetfacename}. + + \membersection{wxFontEnumerator::OnFacename}\label{wxfontenumeratoronfacename} \func{virtual bool}{OnFacename}{\param{const wxString\& }{font}} diff --git a/include/wx/cocoa/font.h b/include/wx/cocoa/font.h index c0743e4441..b230ab76a3 100644 --- a/include/wx/cocoa/font.h +++ b/include/wx/cocoa/font.h @@ -141,7 +141,7 @@ public: virtual void SetFamily(int family); virtual void SetStyle(int style); virtual void SetWeight(int weight); - virtual void SetFaceName(const wxString& faceName); + virtual bool SetFaceName(const wxString& faceName); virtual void SetUnderlined(bool underlined); virtual void SetEncoding(wxFontEncoding encoding); diff --git a/include/wx/font.h b/include/wx/font.h index 33f6068e09..9ffccef70c 100644 --- a/include/wx/font.h +++ b/include/wx/font.h @@ -106,7 +106,7 @@ enum // ---------------------------------------------------------------------------- class WXDLLEXPORT wxFontRefData; -struct WXDLLEXPORT wxNativeFontInfo; +class WXDLLEXPORT wxNativeFontInfo; class WXDLLEXPORT wxFontBase : public wxGDIObject { @@ -186,14 +186,14 @@ public: virtual void SetFamily( int family ) = 0; virtual void SetStyle( int style ) = 0; virtual void SetWeight( int weight ) = 0; - virtual void SetFaceName( const wxString& faceName ) = 0; virtual void SetUnderlined( bool underlined ) = 0; virtual void SetEncoding(wxFontEncoding encoding) = 0; + virtual bool SetFaceName( const wxString& faceName ); void SetNativeFontInfo(const wxNativeFontInfo& info) { DoSetNativeFontInfo(info); } - void SetNativeFontInfo(const wxString& info); - void SetNativeFontInfoUserDesc(const wxString& info); + bool SetNativeFontInfo(const wxString& info); + bool SetNativeFontInfoUserDesc(const wxString& info); // translate the fonts into human-readable string (i.e. GetStyleString() // will return "wxITALIC" for an italic font, ...) diff --git a/include/wx/fontenum.h b/include/wx/fontenum.h index 58218c892d..387081e73d 100644 --- a/include/wx/fontenum.h +++ b/include/wx/fontenum.h @@ -67,6 +67,10 @@ public: // convenience function that returns array of all available encodings. static wxArrayString GetEncodings(const wxString& facename = wxEmptyString); + // convenience function that returns true if the given face name exist + // in the user's system + static bool IsValidFacename(const wxString &str); + private: DECLARE_NO_COPY_CLASS(wxFontEnumerator) }; diff --git a/include/wx/fontutil.h b/include/wx/fontutil.h index d2491dcbc5..00ea14727f 100644 --- a/include/wx/fontutil.h +++ b/include/wx/fontutil.h @@ -64,11 +64,9 @@ enum wxXLFDField // functions, the user code can only get the objects of this type from // somewhere and pass it somewhere else (possibly save them somewhere using // ToString() and restore them using FromString()) -// -// NB: it is a POD currently for max efficiency but if it continues to grow -// further it might make sense to make it a real class with virtual methods -struct WXDLLEXPORT wxNativeFontInfo +class WXDLLEXPORT wxNativeFontInfo { +public: #if wxUSE_PANGO PangoFontDescription *description; #elif defined(_WX_X_FONTLIKE) @@ -195,10 +193,17 @@ public: void SetStyle(wxFontStyle style); void SetWeight(wxFontWeight weight); void SetUnderlined(bool underlined); - void SetFaceName(const wxString& facename); + bool SetFaceName(const wxString& facename); void SetFamily(wxFontFamily family); void SetEncoding(wxFontEncoding encoding); + // sets the first facename in the given array which is found + // to be valid. If no valid facename is given, sets the + // first valid facename returned by wxFontEnumerator::GetFacenames(). + // Does not return a bool since it cannot fail. + void SetFaceName(const wxArrayString &facenames); + + // it is important to be able to serialize wxNativeFontInfo objects to be // able to store them (in config file, for example) bool FromString(const wxString& s); diff --git a/include/wx/gtk/font.h b/include/wx/gtk/font.h index 1f2840764b..7e597c249b 100644 --- a/include/wx/gtk/font.h +++ b/include/wx/gtk/font.h @@ -78,7 +78,7 @@ public: virtual void SetFamily( int family ); virtual void SetStyle( int style ); virtual void SetWeight( int weight ); - virtual void SetFaceName( const wxString& faceName ); + virtual bool SetFaceName( const wxString& faceName ); virtual void SetUnderlined( bool underlined ); virtual void SetEncoding(wxFontEncoding encoding); diff --git a/include/wx/gtk1/font.h b/include/wx/gtk1/font.h index ca0c71af87..e6033d971a 100644 --- a/include/wx/gtk1/font.h +++ b/include/wx/gtk1/font.h @@ -79,7 +79,7 @@ public: virtual void SetFamily( int family ); virtual void SetStyle( int style ); virtual void SetWeight( int weight ); - virtual void SetFaceName( const wxString& faceName ); + virtual bool SetFaceName( const wxString& faceName ); virtual void SetUnderlined( bool underlined ); virtual void SetEncoding(wxFontEncoding encoding); diff --git a/include/wx/mac/carbon/font.h b/include/wx/mac/carbon/font.h index f513354e35..352a9a79f8 100644 --- a/include/wx/mac/carbon/font.h +++ b/include/wx/mac/carbon/font.h @@ -68,7 +68,7 @@ public: virtual void SetFamily(int family); virtual void SetStyle(int style); virtual void SetWeight(int weight); - virtual void SetFaceName(const wxString& faceName); + virtual bool SetFaceName(const wxString& faceName); virtual void SetUnderlined(bool underlined); virtual void SetEncoding(wxFontEncoding encoding); diff --git a/include/wx/mac/classic/font.h b/include/wx/mac/classic/font.h index 4fdbfef398..07e8f7107a 100644 --- a/include/wx/mac/classic/font.h +++ b/include/wx/mac/classic/font.h @@ -66,7 +66,7 @@ public: virtual void SetFamily(int family); virtual void SetStyle(int style); virtual void SetWeight(int weight); - virtual void SetFaceName(const wxString& faceName); + virtual bool SetFaceName(const wxString& faceName); virtual void SetUnderlined(bool underlined); virtual void SetEncoding(wxFontEncoding encoding); diff --git a/include/wx/mgl/font.h b/include/wx/mgl/font.h index 2437ede286..3f748c413a 100644 --- a/include/wx/mgl/font.h +++ b/include/wx/mgl/font.h @@ -75,7 +75,7 @@ public: virtual void SetFamily(int family); virtual void SetStyle(int style); virtual void SetWeight(int weight); - virtual void SetFaceName(const wxString& faceName); + virtual bool SetFaceName(const wxString& faceName); virtual void SetUnderlined(bool underlined); virtual void SetEncoding(wxFontEncoding encoding); diff --git a/include/wx/motif/font.h b/include/wx/motif/font.h index 3c7fb4b05c..4fb5e08a3d 100644 --- a/include/wx/motif/font.h +++ b/include/wx/motif/font.h @@ -71,7 +71,7 @@ public: virtual void SetFamily(int family); virtual void SetStyle(int style); virtual void SetWeight(int weight); - virtual void SetFaceName(const wxString& faceName); + virtual bool SetFaceName(const wxString& faceName); virtual void SetUnderlined(bool underlined); virtual void SetEncoding(wxFontEncoding encoding); diff --git a/include/wx/msw/font.h b/include/wx/msw/font.h index c94d02a71c..4ad4c11526 100644 --- a/include/wx/msw/font.h +++ b/include/wx/msw/font.h @@ -82,6 +82,10 @@ public: virtual ~wxFont(); + // wxFontBase overridden functions + virtual wxString GetNativeFontInfoDesc() const; + virtual wxString GetNativeFontInfoUserDesc() const; + // implement base class pure virtuals virtual int GetPointSize() const; virtual wxSize GetPixelSize() const; @@ -99,7 +103,7 @@ public: virtual void SetFamily(int family); virtual void SetStyle(int style); virtual void SetWeight(int weight); - virtual void SetFaceName(const wxString& faceName); + virtual bool SetFaceName(const wxString& faceName); virtual void SetUnderlined(bool underlined); virtual void SetEncoding(wxFontEncoding encoding); diff --git a/include/wx/os2/font.h b/include/wx/os2/font.h index ba85180513..08e7ade7e3 100644 --- a/include/wx/os2/font.h +++ b/include/wx/os2/font.h @@ -88,7 +88,7 @@ public: virtual void SetFamily(int nFamily); virtual void SetStyle(int nStyle); virtual void SetWeight(int nWeight); - virtual void SetFaceName(const wxString& rsFaceName); + virtual bool SetFaceName(const wxString& rsFaceName); virtual void SetUnderlined(bool bUnderlined); virtual void SetEncoding(wxFontEncoding vEncoding); diff --git a/include/wx/palmos/font.h b/include/wx/palmos/font.h index 146e45eeff..31fc7dba5d 100644 --- a/include/wx/palmos/font.h +++ b/include/wx/palmos/font.h @@ -99,7 +99,7 @@ public: virtual void SetFamily(int family); virtual void SetStyle(int style); virtual void SetWeight(int weight); - virtual void SetFaceName(const wxString& faceName); + virtual bool SetFaceName(const wxString& faceName); virtual void SetUnderlined(bool underlined); virtual void SetEncoding(wxFontEncoding encoding); diff --git a/include/wx/x11/font.h b/include/wx/x11/font.h index fa9d1c9edb..2e8a80258c 100644 --- a/include/wx/x11/font.h +++ b/include/wx/x11/font.h @@ -69,7 +69,7 @@ public: virtual void SetFamily(int family); virtual void SetStyle(int style); virtual void SetWeight(int weight); - virtual void SetFaceName(const wxString& faceName); + virtual bool SetFaceName(const wxString& faceName); virtual void SetUnderlined(bool underlined); virtual void SetEncoding(wxFontEncoding encoding); diff --git a/samples/font/font.cpp b/samples/font/font.cpp index 8203a16d64..7fe8717618 100644 --- a/samples/font/font.cpp +++ b/samples/font/font.cpp @@ -112,6 +112,8 @@ public: void OnEnumerateEncodings(wxCommandEvent& event); void OnCheckNativeToFromString(wxCommandEvent& event); + void OnCheckNativeToFromUserString(wxCommandEvent& event); + void OnCheckFaceName(wxCommandEvent& event); protected: bool DoEnumerateFamilies(bool fixedWidthOnly, @@ -159,6 +161,8 @@ enum Font_EnumFixedFamilies, Font_EnumEncodings, Font_CheckNativeToFromString, + Font_CheckNativeToFromUserString, + Font_CheckFaceName, Font_Max }; @@ -185,7 +189,10 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(Font_wxITALIC_FONT, MyFrame::OnwxPointerFont) EVT_MENU(Font_wxSWISS_FONT, MyFrame::OnwxPointerFont) + EVT_MENU(Font_CheckNativeToFromString, MyFrame::OnCheckNativeToFromString) + EVT_MENU(Font_CheckNativeToFromUserString, MyFrame::OnCheckNativeToFromUserString) + EVT_MENU(Font_CheckFaceName, MyFrame::OnCheckFaceName) EVT_MENU(Font_Choose, MyFrame::OnSelectFont) EVT_MENU(Font_EnumFamiliesForEncoding, MyFrame::OnEnumerateFamiliesForEncoding) @@ -260,6 +267,10 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) menuFont->AppendSeparator(); menuFont->Append(Font_CheckNativeToFromString, wxT("Check Native Font Info To/From String")); + menuFont->Append(Font_CheckNativeToFromUserString, + wxT("Check Native Font Info User String")); + menuFont->Append(Font_CheckFaceName, + wxT("Check font face name")); wxMenu *menuSelect = new wxMenu; menuSelect->Append(Font_Choose, wxT("&Select font...\tCtrl-S"), @@ -488,6 +499,53 @@ void MyFrame::OnCheckNativeToFromString(wxCommandEvent& WXUNUSED(event)) } } +void MyFrame::OnCheckFaceName(wxCommandEvent& WXUNUSED(event)) +{ + wxString facename = GetCanvas()->GetTextFont().GetFaceName(); + wxString newFaceName = wxGetTextFromUser( + wxT("Here you can edit current font face name."), + wxT("Input font facename"), facename, + this); + if (newFaceName.IsEmpty()) + return; // user clicked "Cancel" - do nothing + + wxFont font(GetCanvas()->GetTextFont()); + if (font.SetFaceName(newFaceName)) // change facename only + { + wxASSERT_MSG(font.Ok(), wxT("The font should now be valid")); + DoChangeFont(font); + } + else + { + wxASSERT_MSG(!font.Ok(), wxT("The font should now be invalid")); + wxMessageBox(wxT("There is no font with such face name..."), + wxT("Invalid face name"), wxOK|wxICON_ERROR, this); + } +} + +void MyFrame::OnCheckNativeToFromUserString(wxCommandEvent& WXUNUSED(event)) +{ + wxString fontdesc = GetCanvas()->GetTextFont().GetNativeFontInfoUserDesc(); + wxString fontUserInfo = wxGetTextFromUser( + wxT("Here you can edit current font description"), + wxT("Input font description"), fontdesc, + this); + if (fontUserInfo.IsEmpty()) + return; // user clicked "Cancel" - do nothing + + wxFont font; + if (font.SetNativeFontInfoUserDesc(fontUserInfo)) + { + wxASSERT_MSG(font.Ok(), wxT("The font should now be valid")); + DoChangeFont(font); + } + else + { + wxASSERT_MSG(!font.Ok(), wxT("The font should now be invalid")); + wxMessageBox(wxT("Error trying to create a font with such description...")); + } +} + void MyFrame::DoResizeFont(int diff) { wxFont font = m_canvas->GetTextFont(); @@ -533,10 +591,6 @@ void MyFrame::OnwxPointerFont(wxCommandEvent& event) default : font = wxFont(*wxNORMAL_FONT); break; } - GetMenuBar()->Check(Font_Bold, false); - GetMenuBar()->Check(Font_Italic, false); - GetMenuBar()->Check(Font_Underlined, false); - DoChangeFont(font); } @@ -550,6 +604,15 @@ void MyFrame::DoChangeFont(const wxFont& font, const wxColour& col) m_textctrl->SetFont(font); if ( col.Ok() ) m_textctrl->SetForegroundColour(col); + + // update the state of the bold/italic/underlined menu items + wxMenuBar *mbar = GetMenuBar(); + if ( mbar ) + { + mbar->Check(Font_Bold, font.GetWeight() == wxFONTWEIGHT_BOLD); + mbar->Check(Font_Italic, font.GetStyle() == wxFONTSTYLE_ITALIC); + mbar->Check(Font_Underlined, font.GetUnderlined()); + } } void MyFrame::OnSelectFont(wxCommandEvent& WXUNUSED(event)) @@ -566,15 +629,6 @@ void MyFrame::OnSelectFont(wxCommandEvent& WXUNUSED(event)) wxColour colour = retData.GetColour(); DoChangeFont(font, colour); - - // update the state of the bold/italic/underlined menu items - wxMenuBar *mbar = GetMenuBar(); - if ( mbar ) - { - mbar->Check(Font_Bold, font.GetWeight() == wxFONTWEIGHT_BOLD); - mbar->Check(Font_Italic, font.GetStyle() == wxFONTSTYLE_ITALIC); - mbar->Check(Font_Underlined, font.GetUnderlined()); - } } } diff --git a/src/cocoa/font.cpp b/src/cocoa/font.cpp index c8aa187d02..606e2e3d72 100644 --- a/src/cocoa/font.cpp +++ b/src/cocoa/font.cpp @@ -160,13 +160,15 @@ void wxFont::SetWeight(int weight) RealizeResource(); } -void wxFont::SetFaceName(const wxString& faceName) +bool wxFont::SetFaceName(const wxString& faceName) { Unshare(); M_FONTDATA->m_faceName = faceName; RealizeResource(); + + return wxFontBase::SetFaceName(faceName); } void wxFont::SetUnderlined(bool underlined) diff --git a/src/common/fontcmn.cpp b/src/common/fontcmn.cpp index 29bce8a1eb..2857fa71b8 100644 --- a/src/common/fontcmn.cpp +++ b/src/common/fontcmn.cpp @@ -41,6 +41,7 @@ #include "wx/fontutil.h" // for wxNativeFontInfo #include "wx/fontmap.h" +#include "wx/fontenum.h" #include "wx/tokenzr.h" @@ -266,6 +267,11 @@ wxString wxFontBase::GetNativeFontInfoDesc() const if ( fontInfo ) { fontDesc = fontInfo->ToString(); + wxASSERT_MSG(!fontDesc.IsEmpty(), wxT("This should be a non-empty string!")); + } + else + { + wxASSERT_MSG(0, wxT("Derived class should have created the wxNativeFontInfo!")); } return fontDesc; @@ -278,27 +284,40 @@ wxString wxFontBase::GetNativeFontInfoUserDesc() const if ( fontInfo ) { fontDesc = fontInfo->ToUserString(); + wxASSERT_MSG(!fontDesc.IsEmpty(), wxT("This should be a non-empty string!")); + } + else + { + wxASSERT_MSG(0, 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; } + + UnRef(); + 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; } + + UnRef(); + return false; } bool wxFontBase::operator==(const wxFont& font) const @@ -313,7 +332,7 @@ bool wxFontBase::operator==(const wxFont& font) const GetStyle() == font.GetStyle() && GetWeight() == font.GetWeight() && GetUnderlined() == font.GetUnderlined() && - GetFaceName() == font.GetFaceName() && + GetFaceName().IsSameAs(font.GetFaceName(), false) && GetEncoding() == font.GetEncoding() ); } @@ -365,10 +384,41 @@ wxString wxFontBase::GetWeightString() const } } +bool wxFontBase::SetFaceName(const wxString &facename) +{ + if (!wxFontEnumerator::IsValidFacename(facename)) + { + UnRef(); // make Ok() return false + return false; + } + + return true; +} + + // ---------------------------------------------------------------------------- // wxNativeFontInfo // ---------------------------------------------------------------------------- +// Up to now, there are no native implementations of this function: +void wxNativeFontInfo::SetFaceName(const wxArrayString &facenames) +{ + 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); +} + + #ifdef wxNO_NATIVE_FONTINFO // These are the generic forms of FromString()/ToString. @@ -510,9 +560,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_) @@ -542,7 +593,7 @@ wxString wxNativeFontInfo::ToUserString() const // but what else can we do? if ( GetUnderlined() ) { - desc << _("underlined "); + desc << _("underlined"); } switch ( GetWeight() ) @@ -555,11 +606,11 @@ wxString wxNativeFontInfo::ToUserString() const break; case wxFONTWEIGHT_LIGHT: - desc << _("light "); + desc << _(" light"); break; case wxFONTWEIGHT_BOLD: - desc << _("bold "); + desc << _(" bold"); break; } @@ -575,7 +626,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; } @@ -599,7 +650,7 @@ wxString wxNativeFontInfo::ToUserString() const } #endif // wxUSE_FONTMAP - return desc; + return desc.Strip(wxString::both).MakeLower(); } bool wxNativeFontInfo::FromUserString(const wxString& s) @@ -614,10 +665,7 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) wxString face; unsigned long size; - -#if wxUSE_FONTMAP - wxFontEncoding encoding; -#endif // wxUSE_FONTMAP + bool weightfound = false, pointsizefound = false, encodingfound = false; while ( tokenizer.HasMoreTokens() ) { @@ -634,10 +682,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") ) { @@ -646,16 +696,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(' '); @@ -665,6 +723,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 @@ -672,7 +734,12 @@ 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 (!wxFontEnumerator::IsValidFacename(face) || + !SetFaceName(face)) + SetFaceName(wxNORMAL_FONT->GetFaceName()); face.clear(); } } @@ -680,9 +747,28 @@ 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 (!wxFontEnumerator::IsValidFacename(face) || + !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; } diff --git a/src/common/fontenumcmn.cpp b/src/common/fontenumcmn.cpp index f06fcf1269..fb57dd9104 100644 --- a/src/common/fontenumcmn.cpp +++ b/src/common/fontenumcmn.cpp @@ -72,3 +72,31 @@ wxArrayString wxFontEnumerator::GetEncodings(const wxString& facename) temp.EnumerateEncodings(facename); return temp.m_arrEncodings; } + +/* static */ +bool wxFontEnumerator::IsValidFacename(const wxString &facename) +{ + // we cache the result of wxFontEnumerator::GetFacenames supposing that + // the array of face names won't change in the session of this program + static wxArrayString s_arr = wxFontEnumerator::GetFacenames(); + +#ifdef __WXMSW__ + // Quoting the MSDN: + // "MS Shell Dlg is a mapping mechanism that enables + // U.S. English Microsoft Windows NT, and Microsoft Windows 2000 to + // support locales that have characters that are not contained in code + // page 1252. It is not a font but a face name for a nonexistent font." + // Thus we need to consider "Ms Shell Dlg" and "Ms Shell Dlg 2" as valid + // font face names even if they are enumerated by wxFontEnumerator + if (facename.IsSameAs(wxT("Ms Shell Dlg"), false) || + facename.IsSameAs(wxT("Ms Shell Dlg 2"), false)) + return true; +#endif + + // is given font face name a valid one ? + if (s_arr.Index(facename, false) == wxNOT_FOUND) + return false; + + return true; +} + diff --git a/src/gtk/font.cpp b/src/gtk/font.cpp index 6c9e102f31..ca71f41a55 100644 --- a/src/gtk/font.cpp +++ b/src/gtk/font.cpp @@ -88,7 +88,7 @@ public: void SetStyle(int style); void SetWeight(int weight); void SetUnderlined(bool underlined); - void SetFaceName(const wxString& facename); + bool SetFaceName(const wxString& facename); void SetEncoding(wxFontEncoding encoding); void SetNoAntiAliasing( bool no = true ) { m_noAA = no; } @@ -321,11 +321,11 @@ void wxFontRefData::SetUnderlined(bool underlined) // the XLFD doesn't have "underlined" field anyhow } -void wxFontRefData::SetFaceName(const wxString& facename) +bool wxFontRefData::SetFaceName(const wxString& facename) { m_faceName = facename; - m_nativeFontInfo.SetFaceName(facename); + return m_nativeFontInfo.SetFaceName(facename); } void wxFontRefData::SetEncoding(wxFontEncoding encoding) @@ -548,11 +548,12 @@ void wxFont::SetWeight(int weight) M_FONTDATA->SetWeight(weight); } -void wxFont::SetFaceName(const wxString& faceName) +bool wxFont::SetFaceName(const wxString& faceName) { Unshare(); - M_FONTDATA->SetFaceName(faceName); + return M_FONTDATA->SetFaceName(faceName) && + wxFontBase::SetFaceName(faceName); } void wxFont::SetUnderlined(bool underlined) diff --git a/src/gtk1/font.cpp b/src/gtk1/font.cpp index a926b22363..ca4044af47 100644 --- a/src/gtk1/font.cpp +++ b/src/gtk1/font.cpp @@ -88,7 +88,7 @@ public: void SetStyle(int style); void SetWeight(int weight); void SetUnderlined(bool underlined); - void SetFaceName(const wxString& facename); + bool SetFaceName(const wxString& facename); void SetEncoding(wxFontEncoding encoding); void SetNoAntiAliasing( bool no = true ) { m_noAA = no; } @@ -436,7 +436,7 @@ void wxFontRefData::SetUnderlined(bool underlined) // the XLFD doesn't have "underlined" field anyhow } -void wxFontRefData::SetFaceName(const wxString& facename) +bool wxFontRefData::SetFaceName(const wxString& facename) { m_faceName = facename; @@ -444,6 +444,8 @@ void wxFontRefData::SetFaceName(const wxString& facename) { m_nativeFontInfo.SetXFontComponent(wxXLFD_FAMILY, facename); } + + return true; } void wxFontRefData::SetEncoding(wxFontEncoding encoding) @@ -688,11 +690,12 @@ void wxFont::SetWeight(int weight) M_FONTDATA->SetWeight(weight); } -void wxFont::SetFaceName(const wxString& faceName) +bool wxFont::SetFaceName(const wxString& faceName) { Unshare(); - M_FONTDATA->SetFaceName(faceName); + return M_FONTDATA->SetFaceName(faceName) && + wxFontBase::SetFaceName(faceName); } void wxFont::SetUnderlined(bool underlined) diff --git a/src/mac/carbon/font.cpp b/src/mac/carbon/font.cpp index 9f08a80e6b..404b356b05 100644 --- a/src/mac/carbon/font.cpp +++ b/src/mac/carbon/font.cpp @@ -473,13 +473,15 @@ void wxFont::SetWeight(int weight) RealizeResource(); } -void wxFont::SetFaceName(const wxString& faceName) +bool wxFont::SetFaceName(const wxString& faceName) { Unshare(); M_FONTDATA->m_faceName = faceName; RealizeResource(); + + return wxFontBase::SetFaceName(faceName); } void wxFont::SetUnderlined(bool underlined) diff --git a/src/mac/classic/font.cpp b/src/mac/classic/font.cpp index 09feb155c6..daad04f0d7 100644 --- a/src/mac/classic/font.cpp +++ b/src/mac/classic/font.cpp @@ -339,13 +339,15 @@ void wxFont::SetWeight(int weight) RealizeResource(); } -void wxFont::SetFaceName(const wxString& faceName) +bool wxFont::SetFaceName(const wxString& faceName) { Unshare(); M_FONTDATA->m_faceName = faceName; RealizeResource(); + + return wxFontBase::SetFaceName(faceName); } void wxFont::SetUnderlined(bool underlined) diff --git a/src/mgl/font.cpp b/src/mgl/font.cpp index 2cce8212f1..ddd6799cc8 100644 --- a/src/mgl/font.cpp +++ b/src/mgl/font.cpp @@ -311,12 +311,14 @@ void wxFont::SetWeight(int weight) M_FONTDATA->m_valid = false; } -void wxFont::SetFaceName(const wxString& faceName) +bool wxFont::SetFaceName(const wxString& faceName) { AllocExclusive(); M_FONTDATA->m_faceName = faceName; M_FONTDATA->m_valid = false; + + return wxFontBase::SetFaceName(faceName); } void wxFont::SetUnderlined(bool underlined) diff --git a/src/motif/font.cpp b/src/motif/font.cpp index 08f6720b64..382fcb71b4 100644 --- a/src/motif/font.cpp +++ b/src/motif/font.cpp @@ -393,12 +393,14 @@ void wxFont::SetWeight(int weight) M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now } -void wxFont::SetFaceName(const wxString& faceName) +bool wxFont::SetFaceName(const wxString& faceName) { Unshare(); M_FONTDATA->m_faceName = faceName; M_FONTDATA->m_nativeFontInfo.GetXFontName().Clear(); // invalid now + + return wxFontBase::SetFaceName(faceName); } void wxFont::SetUnderlined(bool underlined) diff --git a/src/msw/font.cpp b/src/msw/font.cpp index 059e4bdb59..308a36e837 100644 --- a/src/msw/font.cpp +++ b/src/msw/font.cpp @@ -256,12 +256,13 @@ public: m_weight = weight; } - void SetFaceName(const wxString& faceName) + bool SetFaceName(const wxString& faceName) { if ( m_nativeFontInfoOk ) - m_nativeFontInfo.SetFaceName(faceName); - else + return m_nativeFontInfo.SetFaceName(faceName); + m_faceName = faceName; + return true; } void SetUnderlined(bool underlined) @@ -385,12 +386,10 @@ bool wxFontRefData::Alloc(wxFont *font) if ( !hfont ) { wxLogLastError(wxT("CreateFont")); - return false; } m_hFont = (WXHFONT)hfont; - return true; } @@ -561,42 +560,66 @@ void wxNativeFontInfo::SetUnderlined(bool underlined) lf.lfUnderline = underlined; } -void wxNativeFontInfo::SetFaceName(const wxString& facename) +bool wxNativeFontInfo::SetFaceName(const wxString& facename) { - wxStrncpy(lf.lfFaceName, facename, WXSIZEOF(lf.lfFaceName)); + size_t len = WXSIZEOF(lf.lfFaceName); + wxStrncpy(lf.lfFaceName, facename, len); + lf.lfFaceName[len - 1] = '\0'; // truncate the face name + return true; } void wxNativeFontInfo::SetFamily(wxFontFamily family) { BYTE ff_family; - wxString facename; + wxArrayString facename; + + // the list of fonts associated with a family was partially + // taken from http://www.codestyle.org/css/font-family switch ( family ) { case wxSCRIPT: ff_family = FF_SCRIPT; - facename = _T("Script"); + facename.Add(_T("Script")); + facename.Add(_T("Brush Script MT")); + facename.Add(_T("Comic Sans MS")); + facename.Add(_T("Lucida Handwriting")); break; case wxDECORATIVE: ff_family = FF_DECORATIVE; - facename = _T("Old English Text MT"); + facename.Add(_T("Old English Text MT")); + facename.Add(_T("Comic Sans MS")); + facename.Add(_T("Lucida Handwriting")); break; case wxROMAN: ff_family = FF_ROMAN; - facename = _T("Times New Roman"); + facename.Add(_T("Times New Roman")); + facename.Add(_T("Georgia")); + facename.Add(_T("Garamond")); + facename.Add(_T("Bookman Old Style")); + facename.Add(_T("Book Antiqua")); break; case wxTELETYPE: case wxMODERN: ff_family = FF_MODERN; - facename = _T("Courier New"); + facename.Add(_T("Courier New")); + facename.Add(_T("Lucida Console")); + facename.Add(_T("Andale Mono")); + facename.Add(_T("OCR A Extended")); + facename.Add(_T("Terminal")); break; case wxSWISS: ff_family = FF_SWISS; - facename = _T("Arial"); + facename.Add(_T("Arial")); + facename.Add(_T("Century Gothic")); + facename.Add(_T("Lucida Sans Unicode")); + facename.Add(_T("Tahoma")); + facename.Add(_T("Trebuchet MS")); + facename.Add(_T("Verdana")); break; case wxDEFAULT: @@ -607,9 +630,15 @@ void wxNativeFontInfo::SetFamily(wxFontFamily family) int verMaj; ff_family = FF_SWISS; if(wxGetOsVersion(&verMaj) == wxWINDOWS_NT && verMaj >= 5) - facename = _T("MS Shell Dlg 2"); + facename.Add(_T("MS Shell Dlg 2")); else - facename = _T("MS Shell Dlg"); + facename.Add(_T("MS Shell Dlg")); + + // Quoting the MSDN: + // "MS Shell Dlg is a mapping mechanism that enables + // U.S. English Microsoft Windows NT, and Microsoft Windows 2000 to + // support locales that have characters that are not contained in code + // page 1252. It is not a font but a face name for a nonexistent font." } } @@ -920,13 +949,22 @@ void wxFont::SetWeight(int weight) RealizeResource(); } -void wxFont::SetFaceName(const wxString& faceName) +bool wxFont::SetFaceName(const wxString& faceName) { Unshare(); - M_FONTDATA->SetFaceName(faceName); + bool refdataok = M_FONTDATA->SetFaceName(faceName); RealizeResource(); + + // NB: using win32's GetObject() API on M_FONTDATA->GetHFONT() + // to retrieve a LOGFONT and then compare lf.lfFaceName + // with given facename is not reliable at all: + // Windows copies the facename given to ::CreateFontIndirect() + // without any validity check. + // Thus we use wxFontBase::SetFaceName to check if facename + // is valid... + return refdataok && wxFontBase::SetFaceName(faceName); } void wxFont::SetUnderlined(bool underlined) @@ -1029,6 +1067,20 @@ const wxNativeFontInfo *wxFont::GetNativeFontInfo() const : NULL; } +wxString wxFont::GetNativeFontInfoDesc() const +{ + // be sure we have an HFONT associated... + wxConstCast(this, wxFont)->RealizeResource(); + return wxFontBase::GetNativeFontInfoDesc(); +} + +wxString wxFont::GetNativeFontInfoUserDesc() const +{ + // be sure we have an HFONT associated... + wxConstCast(this, wxFont)->RealizeResource(); + return wxFontBase::GetNativeFontInfoUserDesc(); +} + bool wxFont::IsFixedWidth() const { if ( M_FONTDATA->HasNativeFontInfo() ) @@ -1043,3 +1095,4 @@ bool wxFont::IsFixedWidth() const return wxFontBase::IsFixedWidth(); } + diff --git a/src/os2/font.cpp b/src/os2/font.cpp index 63be231df6..9871769c77 100644 --- a/src/os2/font.cpp +++ b/src/os2/font.cpp @@ -195,12 +195,13 @@ public: m_nWeight = nWeight; } - inline void SetFaceName(const wxString& sFaceName) + inline bool SetFaceName(const wxString& sFaceName) { if (m_bNativeFontInfoOk) - m_vNativeFontInfo.SetFaceName(sFaceName); + return m_vNativeFontInfo.SetFaceName(sFaceName); else m_sFaceName = sFaceName; + return true; } inline void SetUnderlined(bool bUnderlined) @@ -689,11 +690,12 @@ void wxNativeFontInfo::SetUnderlined( fa.fsSelection |= FATTR_SEL_UNDERSCORE; } // end of wxNativeFontInfo::SetUnderlined -void wxNativeFontInfo::SetFaceName( +bool wxNativeFontInfo::SetFaceName( const wxString& sFacename ) { wxStrncpy((wxChar*)fa.szFacename, sFacename, WXSIZEOF(fa.szFacename)); + return true; } // end of wxNativeFontInfo::SetFaceName void wxNativeFontInfo::SetFamily( @@ -1023,15 +1025,17 @@ void wxFont::SetWeight( RealizeResource(); } // end of wxFont::SetWeight -void wxFont::SetFaceName( +bool wxFont::SetFaceName( const wxString& rsFaceName ) { Unshare(); - M_FONTDATA->SetFaceName(rsFaceName); + bool refdataok = M_FONTDATA->SetFaceName(rsFaceName); RealizeResource(); + + return refdataok && wxFontBase::SetFaceName(rsFaceName); } // end of wxFont::SetFaceName void wxFont::SetUnderlined( diff --git a/src/palmos/font.cpp b/src/palmos/font.cpp index 3f1f84d7b6..5eebd464f5 100644 --- a/src/palmos/font.cpp +++ b/src/palmos/font.cpp @@ -251,7 +251,7 @@ public: m_weight = weight; } - void SetFaceName(const wxString& faceName) + bool SetFaceName(const wxString& faceName) { if ( m_nativeFontInfoOk ) m_nativeFontInfo.SetFaceName(faceName); @@ -444,8 +444,9 @@ void wxFont::SetWeight(int weight) { } -void wxFont::SetFaceName(const wxString& faceName) +bool wxFont::SetFaceName(const wxString& faceName) { + return true; } void wxFont::SetUnderlined(bool underlined) diff --git a/src/unix/fontutil.cpp b/src/unix/fontutil.cpp index 501393ac7b..93df3b0ced 100644 --- a/src/unix/fontutil.cpp +++ b/src/unix/fontutil.cpp @@ -37,6 +37,7 @@ #include "wx/fontmap.h" #include "wx/tokenzr.h" #include "wx/module.h" +#include "wx/fontenum.h" #if wxUSE_PANGO @@ -260,9 +261,10 @@ void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined)) wxFAIL_MSG( _T("not implemented") ); } -void wxNativeFontInfo::SetFaceName(const wxString& facename) +bool wxNativeFontInfo::SetFaceName(const wxString& facename) { pango_font_description_set_family(description, wxGTK_CONV_SYS(facename)); + return true; } void wxNativeFontInfo::SetFamily(wxFontFamily WXUNUSED(family)) @@ -309,6 +311,10 @@ bool wxNativeFontInfo::FromString(const wxString& s) description = pango_font_description_from_string( wxGTK_CONV_SYS( str ) ); + // ensure a valid facename is selected + if (!wxFontEnumerator::IsValidFacename(GetFaceName())) + SetFaceName(wxNORMAL_FONT->GetFaceName()); + return true; } @@ -776,9 +782,10 @@ void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined)) // can't do this under X } -void wxNativeFontInfo::SetFaceName(const wxString& facename) +bool wxNativeFontInfo::SetFaceName(const wxString& facename) { SetXFontComponent(wxXLFD_FAMILY, facename); + return true; } void wxNativeFontInfo::SetFamily(wxFontFamily WXUNUSED(family)) diff --git a/src/x11/font.cpp b/src/x11/font.cpp index 7215b89230..675acc54bd 100644 --- a/src/x11/font.cpp +++ b/src/x11/font.cpp @@ -121,7 +121,7 @@ public: void SetStyle(int style); void SetWeight(int weight); void SetUnderlined(bool underlined); - void SetFaceName(const wxString& facename); + bool SetFaceName(const wxString& facename); void SetEncoding(wxFontEncoding encoding); void SetNoAntiAliasing( bool no = true ) { m_noAA = no; } @@ -503,9 +503,10 @@ void wxFontRefData::SetUnderlined(bool underlined) // the XLFD doesn't have "underlined" field anyhow } -void wxFontRefData::SetFaceName(const wxString& facename) +bool wxFontRefData::SetFaceName(const wxString& facename) { m_faceName = facename; + return true; } void wxFontRefData::SetEncoding(wxFontEncoding encoding) @@ -816,11 +817,12 @@ void wxFont::SetWeight(int weight) M_FONTDATA->SetWeight(weight); } -void wxFont::SetFaceName(const wxString& faceName) +bool wxFont::SetFaceName(const wxString& faceName) { Unshare(); - M_FONTDATA->SetFaceName(faceName); + return M_FONTDATA->SetFaceName(faceName) && + wxFontBase::SetFaceName(faceName); } void wxFont::SetUnderlined(bool underlined) -- 2.45.2