diff --git a/docs/changes.txt b/docs/changes.txt index b162a6863c..a1c2b040d3 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -76,6 +76,7 @@ wxBase: All (GUI): +- significantly improved native font support - added IFF image handler - fixed using custom renderers in wxGrid which was broken in 2.3.2 - support for multiple images in one file added to wxImage (TIFF and ICO formats) diff --git a/include/wx/font.h b/include/wx/font.h index eb507cfd24..a95b73d002 100644 --- a/include/wx/font.h +++ b/include/wx/font.h @@ -36,7 +36,10 @@ class WXDLLEXPORT wxFont; // font constants // ---------------------------------------------------------------------------- -// standard font families +// standard font families: these may be used only for the font creation, it +// doesn't make sense to query an existing font for its font family as, +// especially if the font had been created from a native font description, it +// may be unknown enum wxFontFamily { wxFONTFAMILY_DEFAULT = wxDEFAULT, @@ -46,7 +49,8 @@ enum wxFontFamily wxFONTFAMILY_SWISS = wxSWISS, wxFONTFAMILY_MODERN = wxMODERN, wxFONTFAMILY_TELETYPE = wxTELETYPE, - wxFONTFAMILY_MAX + wxFONTFAMILY_MAX, + wxFONTFAMILY_UNKNOWN = wxFONTFAMILY_MAX }; // font styles diff --git a/include/wx/fontutil.h b/include/wx/fontutil.h index 8305e1417a..0fba847731 100644 --- a/include/wx/fontutil.h +++ b/include/wx/fontutil.h @@ -34,6 +34,9 @@ #if defined(_WX_X_FONTLIKE) // the symbolic names for the XLFD fields (with examples for their value) +// +// NB: we suppose that the font always starts with the empty token (font name +// registry field) as we never use nor generate it anyhow enum wxXLFDField { wxXLFD_FOUNDRY, // adobe @@ -70,24 +73,39 @@ enum wxXLFDField struct WXDLLEXPORT wxNativeFontInfo { #if defined(_WX_X_FONTLIKE) - // the fonts array can't be accessed directly as we only parse the - // xFontName when needed + // the members can't be accessed directly as we only parse the + // xFontName on demand private: // the components of the XLFD wxString fontElements[wxXLFD_MAX]; -public: // the full XLFD wxString xFontName; + // true until SetXFontName() is called + bool m_isDefault; + + // return true if we have already initialized fontElements + inline bool HasElements() const; + +public: // init the elements from an XLFD, return TRUE if ok bool FromXFontName(const wxString& xFontName); - // generate an XLFD using the fontElements + // return false if we were never initialized with a valid XLFD + bool IsDefault() const { return m_isDefault; } + + // return the XLFD (using the fontElements if necessary) wxString GetXFontName() const; // get the given XFLD component wxString GetXFontComponent(wxXLFDField field) const; + + // change the font component + void SetXFontComponent(wxXLFDField field, const wxString& value); + + // set the XFLD + void SetXFontName(const wxString& xFontName); #elif defined(__WXMSW__) LOGFONT lf; #elif defined(__WXPM__) diff --git a/include/wx/gtk/font.h b/include/wx/gtk/font.h index de17523e9f..90448b3704 100644 --- a/include/wx/gtk/font.h +++ b/include/wx/gtk/font.h @@ -36,12 +36,13 @@ public: // ctors and such wxFont() { Init(); } wxFont(const wxFont& font) : wxFontBase() { Init(); Ref(font); } - wxFont(const wxString& fontname, - wxFontEncoding fontenc = wxFONTENCODING_DEFAULT) + + // wxGTK-specific + wxFont(const wxString& fontname) { Init(); - Create(fontname, fontenc); + Create(fontname); } wxFont(const wxNativeFontInfo& info); @@ -68,9 +69,7 @@ public: wxFontEncoding encoding = wxFONTENCODING_DEFAULT); // wxGTK-specific - bool Create(const wxString& fontname, - wxFontEncoding fontenc = wxFONTENCODING_DEFAULT); - bool Create(const wxNativeFontInfo& fontinfo); + bool Create(const wxString& fontname); ~wxFont(); @@ -108,9 +107,6 @@ protected: // common part of all ctors void Init(); - // do we have the XFLD for this font (or just wxWin description)? - inline bool HasNativeFont() const; - private: DECLARE_DYNAMIC_CLASS(wxFont) }; diff --git a/include/wx/gtk1/font.h b/include/wx/gtk1/font.h index de17523e9f..90448b3704 100644 --- a/include/wx/gtk1/font.h +++ b/include/wx/gtk1/font.h @@ -36,12 +36,13 @@ public: // ctors and such wxFont() { Init(); } wxFont(const wxFont& font) : wxFontBase() { Init(); Ref(font); } - wxFont(const wxString& fontname, - wxFontEncoding fontenc = wxFONTENCODING_DEFAULT) + + // wxGTK-specific + wxFont(const wxString& fontname) { Init(); - Create(fontname, fontenc); + Create(fontname); } wxFont(const wxNativeFontInfo& info); @@ -68,9 +69,7 @@ public: wxFontEncoding encoding = wxFONTENCODING_DEFAULT); // wxGTK-specific - bool Create(const wxString& fontname, - wxFontEncoding fontenc = wxFONTENCODING_DEFAULT); - bool Create(const wxNativeFontInfo& fontinfo); + bool Create(const wxString& fontname); ~wxFont(); @@ -108,9 +107,6 @@ protected: // common part of all ctors void Init(); - // do we have the XFLD for this font (or just wxWin description)? - inline bool HasNativeFont() const; - private: DECLARE_DYNAMIC_CLASS(wxFont) }; diff --git a/include/wx/unix/fontutil.h b/include/wx/unix/fontutil.h index b021ac6fd1..3c7bbd69c9 100644 --- a/include/wx/unix/fontutil.h +++ b/include/wx/unix/fontutil.h @@ -31,4 +31,7 @@ wxLoadQueryNearestFont(int pointSize, wxFontEncoding encoding, wxString* xFontName = (wxString *)NULL); +// returns the font specified by the given XLFD +extern inline wxNativeFont wxLoadFont(const wxString& fontSpec); + #endif // _WX_UNIX_FONTUTIL_H_ diff --git a/samples/font/font.cpp b/samples/font/font.cpp index 69e2621c5b..aad214f94c 100644 --- a/samples/font/font.cpp +++ b/samples/font/font.cpp @@ -85,9 +85,14 @@ public: // event handlers (these functions should _not_ be virtual) void OnQuit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); + void OnIncFont(wxCommandEvent& event) { DoResizeFont(+2); } void OnDecFont(wxCommandEvent& event) { DoResizeFont(-2); } + void OnBold(wxCommandEvent& event); + void OnItalic(wxCommandEvent& event); + void OnUnderline(wxCommandEvent& event); + void OnViewMsg(wxCommandEvent& event); void OnSelectFont(wxCommandEvent& event); void OnEnumerateFamiliesForEncoding(wxCommandEvent& event); @@ -130,6 +135,9 @@ enum Font_ViewMsg, Font_IncSize, Font_DecSize, + Font_Bold, + Font_Italic, + Font_Underlined, Font_Choose = 100, Font_EnumFamiliesForEncoding, Font_EnumFamilies, @@ -148,16 +156,21 @@ enum // simple menu events like this the static method is much simpler. BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(Font_Quit, MyFrame::OnQuit) + EVT_MENU(Font_ViewMsg, MyFrame::OnViewMsg) EVT_MENU(Font_About, MyFrame::OnAbout) + EVT_MENU(Font_IncSize, MyFrame::OnIncFont) EVT_MENU(Font_DecSize, MyFrame::OnDecFont) - EVT_MENU(Font_ViewMsg, MyFrame::OnViewMsg) + EVT_MENU(Font_Bold, MyFrame::OnBold) + EVT_MENU(Font_Italic, MyFrame::OnItalic) + EVT_MENU(Font_Underlined, MyFrame::OnUnderline) + EVT_MENU(Font_CheckNativeToFromString, MyFrame::OnCheckNativeToFromString) + EVT_MENU(Font_Choose, MyFrame::OnSelectFont) EVT_MENU(Font_EnumFamiliesForEncoding, MyFrame::OnEnumerateFamiliesForEncoding) EVT_MENU(Font_EnumFamilies, MyFrame::OnEnumerateFamilies) EVT_MENU(Font_EnumFixedFamilies, MyFrame::OnEnumerateFixedFamilies) EVT_MENU(Font_EnumEncodings, MyFrame::OnEnumerateEncodings) - EVT_MENU(Font_CheckNativeToFromString, MyFrame::OnCheckNativeToFromString) END_EVENT_TABLE() // Create a new application object: this macro will allow wxWindows to create @@ -216,25 +229,32 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) menuFont->Append(Font_IncSize, "&Increase font size by 2 points\tCtrl-I"); menuFont->Append(Font_DecSize, "&Decrease font size by 2 points\tCtrl-D"); menuFont->AppendSeparator(); - menuFont->Append(Font_Choose, "&Select font...\tCtrl-S", - "Select a standard font"); - menuFont->AppendSeparator(); - menuFont->Append(Font_EnumFamilies, "Enumerate font &families\tCtrl-F"); - menuFont->Append(Font_EnumFixedFamilies, - "Enumerate fi&xed font families\tCtrl-X"); - menuFont->Append(Font_EnumEncodings, - "Enumerate &encodings\tCtrl-E"); - menuFont->Append(Font_EnumFamiliesForEncoding, - "Find font for en&coding...\tCtrl-C", - "Find font families for given encoding"); + menuFont->Append(Font_Bold, "&Bold\tCtrl-B", "Toggle bold state", TRUE); + menuFont->Append(Font_Italic, "&Oblique\tCtrl-O", "Toggle italic state", TRUE); + menuFont->Append(Font_Underlined, "&Underlined\tCtrl-U", + "Toggle underlined state", TRUE); menuFont->AppendSeparator(); menuFont->Append(Font_CheckNativeToFromString, "Check Native Font Info To/From String"); + wxMenu *menuSelect = new wxMenu; + menuSelect->Append(Font_Choose, "&Select font...\tCtrl-S", + "Select a standard font"); + menuSelect->AppendSeparator(); + menuSelect->Append(Font_EnumFamilies, "Enumerate font &families\tCtrl-F"); + menuSelect->Append(Font_EnumFixedFamilies, + "Enumerate fi&xed font families\tCtrl-X"); + menuSelect->Append(Font_EnumEncodings, + "Enumerate &encodings\tCtrl-E"); + menuSelect->Append(Font_EnumFamiliesForEncoding, + "Find font for en&coding...\tCtrl-C", + "Find font families for given encoding"); + // now append the freshly created menu to the menu bar... wxMenuBar *menuBar = new wxMenuBar; menuBar->Append(menuFile, "&File"); menuBar->Append(menuFont, "F&ont"); + menuBar->Append(menuSelect, "&Select"); // ... and attach this menu bar to the frame SetMenuBar(menuBar); @@ -440,6 +460,30 @@ void MyFrame::DoResizeFont(int diff) DoChangeFont(font); } +void MyFrame::OnBold(wxCommandEvent& event) +{ + wxFont font = m_canvas->GetTextFont(); + + font.SetWeight(event.IsChecked() ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL); + DoChangeFont(font); +} + +void MyFrame::OnItalic(wxCommandEvent& event) +{ + wxFont font = m_canvas->GetTextFont(); + + font.SetStyle(event.IsChecked() ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL); + DoChangeFont(font); +} + +void MyFrame::OnUnderline(wxCommandEvent& event) +{ + wxFont font = m_canvas->GetTextFont(); + + font.SetUnderlined(event.IsChecked()); + DoChangeFont(font); +} + void MyFrame::DoChangeFont(const wxFont& font, const wxColour& col) { m_canvas->SetTextFont(font); @@ -466,6 +510,15 @@ 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()); + } } } @@ -653,11 +706,17 @@ void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) ) if ( m_font.Ok() ) { - wxString fontDesc = m_font.GetNativeFontInfoUserDesc(); - fontInfo.Printf(wxT("Native font info: %s"), fontDesc.c_str()); + wxNativeFontInfo *info = m_font.GetNativeFontInfo(); + if ( info ) + { + delete info; - dc.DrawText(fontInfo, x, y); - y += hLine; + wxString fontDesc = m_font.GetNativeFontInfoUserDesc(); + fontInfo.Printf(wxT("Native font info: %s"), fontDesc.c_str()); + + dc.DrawText(fontInfo, x, y); + y += hLine; + } } y += hLine; diff --git a/src/gtk/font.cpp b/src/gtk/font.cpp index 940b38d81a..1637fb8a9a 100644 --- a/src/gtk/font.cpp +++ b/src/gtk/font.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: font.cpp +// Name: gtk/font.cpp // Purpose: // Author: Robert Roebling // Id: $Id$ @@ -34,6 +34,24 @@ #include #include +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// the default size (in points) for the fonts +static const int wxDEFAULT_FONT_SIZE = 12; + +// ---------------------------------------------------------------------------- +// wxScaledFontList +// ---------------------------------------------------------------------------- + +// TODO: replace this with a type safe list or hash!! +class wxScaledFontList : public wxList +{ +public: + wxScaledFontList() : wxList(wxKEY_INTEGER) { } +}; + // ---------------------------------------------------------------------------- // wxFontRefData // ---------------------------------------------------------------------------- @@ -41,16 +59,59 @@ class wxFontRefData : public wxObjectRefData { public: - wxFontRefData(int size = wxDEFAULT, - int family = wxDEFAULT, - int style = wxDEFAULT, - int weight = wxDEFAULT, + // from broken down font parameters, also default ctor + wxFontRefData(int size = -1, + int family = wxFONTFAMILY_DEFAULT, + int style = wxFONTSTYLE_NORMAL, + int weight = wxFONTWEIGHT_NORMAL, bool underlined = FALSE, const wxString& faceName = wxEmptyString, wxFontEncoding encoding = wxFONTENCODING_DEFAULT); + + // from XFLD + wxFontRefData(const wxString& fontname); + + // copy ctor wxFontRefData( const wxFontRefData& data ); + virtual ~wxFontRefData(); + // do we have the native font info? + bool HasNativeFont() const + { + return !m_nativeFontInfo.IsDefault(); + } + + // setters: all of them also take care to modify m_nativeFontInfo if we + // have it so as to not lose the information not carried by our fields + void SetPointSize(int pointSize); + void SetFamily(int family); + void SetStyle(int style); + void SetWeight(int weight); + void SetUnderlined(bool underlined); + void SetFaceName(const wxString& facename); + void SetEncoding(wxFontEncoding encoding); + + // debugger helper: shows what the font really is + // + // VZ: I need this as my gdb either shows wildly wrong values or crashes + // when I ask it to "p fontRefData" :-( +#ifdef __WXDEBUG__ + void Dump() const + { + wxPrintf(_T("%s-%s-%s-%d-%d\n"), + m_faceName.c_str(), + m_weight == wxFONTWEIGHT_NORMAL + ? _T("normal") + : m_weight == wxFONTWEIGHT_BOLD + ? _T("bold") + : _T("light"), + m_style == wxFONTSTYLE_NORMAL ? _T("regular") : _T("italic"), + m_pointSize, + m_encoding); + } +#endif // Debug + protected: // common part of all ctors void Init(int pointSize, @@ -62,7 +123,10 @@ protected: wxFontEncoding encoding); private: - wxList m_scaled_xfonts; + // the map of font sizes to "GdkFont *" + wxScaledFontList m_scaled_xfonts; + + // the broken down font parameters int m_pointSize; int m_family, m_style, @@ -71,17 +135,18 @@ private: wxString m_faceName; wxFontEncoding m_encoding; + // the native font info, basicly an XFLD wxNativeFontInfo m_nativeFontInfo; friend class wxFont; }; // ============================================================================ -// implementation +// wxFontRefData implementation // ============================================================================ // ---------------------------------------------------------------------------- -// wxFontRefData +// wxFontRefData creation // ---------------------------------------------------------------------------- void wxFontRefData::Init(int pointSize, @@ -92,48 +157,150 @@ void wxFontRefData::Init(int pointSize, const wxString& faceName, wxFontEncoding encoding) { - if (family == wxDEFAULT) - m_family = wxSWISS; - else - m_family = family; + m_family = family == wxFONTFAMILY_DEFAULT ? wxFONTFAMILY_SWISS : family; m_faceName = faceName; - if (style == wxDEFAULT) - m_style = wxNORMAL; - else - m_style = style; + // we accept both wxDEFAULT and wxNORMAL here - should we? + m_style = style == wxDEFAULT ? wxFONTSTYLE_NORMAL : style; + m_weight = weight == wxDEFAULT ? wxFONTWEIGHT_NORMAL : weight; - if (weight == wxDEFAULT) - m_weight = wxNORMAL; - else - m_weight = weight; - - if (pointSize == wxDEFAULT) - m_pointSize = 12; - else - m_pointSize = pointSize; + // and here, do we really want to forbid creation of the font of the size + // 90 (the value of wxDEFAULT)?? + m_pointSize = pointSize == wxDEFAULT || + pointSize == -1 ? wxDEFAULT_FONT_SIZE : pointSize; m_underlined = underlined; m_encoding = encoding; } wxFontRefData::wxFontRefData( const wxFontRefData& data ) - : m_scaled_xfonts(wxKEY_INTEGER) { - Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight, - data.m_underlined, data.m_faceName, data.m_encoding); + m_pointSize = data.m_pointSize; + m_family = data.m_family; + m_style = data.m_style; + m_weight = data.m_weight; + + m_underlined = data.m_underlined; + + m_faceName = data.m_faceName; + m_encoding = data.m_encoding; + + m_nativeFontInfo = data.m_nativeFontInfo; } wxFontRefData::wxFontRefData(int size, int family, int style, int weight, bool underlined, const wxString& faceName, wxFontEncoding encoding) - : m_scaled_xfonts(wxKEY_INTEGER) { Init(size, family, style, weight, underlined, faceName, encoding); } +wxFontRefData::wxFontRefData(const wxString& fontname) +{ + // remember the X font name + m_nativeFontInfo.SetXFontName(fontname); + + // get the font parameters from the XLFD + // ------------------------------------- + + m_faceName = m_nativeFontInfo.GetXFontComponent(wxXLFD_FAMILY); + + m_weight = wxFONTWEIGHT_NORMAL; + + wxString w = m_nativeFontInfo.GetXFontComponent(wxXLFD_WEIGHT).Upper(); + if ( !w.empty() && w != _T('*') ) + { + // the test below catches all of BOLD, EXTRABOLD, DEMIBOLD, ULTRABOLD + // and BLACK + if ( ((w[0u] == _T('B') && (!strcmp(w.c_str() + 1, _T("OLD")) || + !strcmp(w.c_str() + 1, _T("LACK"))))) || + strstr(w.c_str() + 1, _T("BOLD")) ) + { + m_weight = wxFONTWEIGHT_BOLD; + } + else if ( w == _T("LIGHT") || w == _T("THIN") ) + { + m_weight = wxFONTWEIGHT_LIGHT; + } + } + + switch ( wxToupper(*m_nativeFontInfo. + GetXFontComponent(wxXLFD_SLANT).c_str()) ) + { + case _T('I'): // italique + m_style = wxFONTSTYLE_ITALIC; + break; + + case _T('O'): // oblique + m_style = wxFONTSTYLE_SLANT; + break; + + default: + m_style = wxFONTSTYLE_NORMAL; + } + + long ptSize; + if ( m_nativeFontInfo.GetXFontComponent(wxXLFD_POINTSIZE).ToLong(&ptSize) ) + { + // size in XLFD is in 10 point units + m_pointSize = (int)(ptSize / 10); + } + else + { + m_pointSize = wxDEFAULT_FONT_SIZE; + } + + // examine the spacing: if the font is monospaced, assume wxTELETYPE + // family for compatibility with the old code which used it instead of + // IsFixedWidth() + if ( m_nativeFontInfo.GetXFontComponent(wxXLFD_SPACING).Upper() == _T('M') ) + { + m_family = wxFONTFAMILY_TELETYPE; + } + else // not monospaceed + { + // don't even try guessing it, it doesn't work for too many fonts + // anyhow + m_family = wxFONTFAMILY_UNKNOWN; + } + + // X fonts are never underlined... + m_underlined = FALSE; + + // deal with font encoding + wxString + registry = m_nativeFontInfo.GetXFontComponent(wxXLFD_REGISTRY).Upper(), + encoding = m_nativeFontInfo.GetXFontComponent(wxXLFD_ENCODING).Upper(); + + if ( registry == _T("ISO8859") ) + { + int cp; + if ( wxSscanf(encoding, wxT("%d"), &cp) == 1 ) + { + m_encoding = (wxFontEncoding)(wxFONTENCODING_ISO8859_1 + cp - 1); + } + } + else if ( registry == _T("MICROSOFT") ) + { + int cp; + if ( wxSscanf(encoding, wxT("cp125%d"), &cp) == 1 ) + { + m_encoding = (wxFontEncoding)(wxFONTENCODING_CP1250 + cp); + } + } + else if ( registry == _T("KOI8") ) + { + m_encoding = wxFONTENCODING_KOI8; + } + else // unknown encoding + { + // may be give a warning here? + m_encoding = wxFONTENCODING_SYSTEM; + } +} + wxFontRefData::~wxFontRefData() { wxNode *node = m_scaled_xfonts.First(); @@ -147,7 +314,129 @@ wxFontRefData::~wxFontRefData() } // ---------------------------------------------------------------------------- -// wxFont +// wxFontRefData SetXXX() +// ---------------------------------------------------------------------------- + +void wxFontRefData::SetPointSize(int pointSize) +{ + m_pointSize = pointSize; + + if ( HasNativeFont() ) + { + wxString size; + if ( pointSize == -1 ) + size = _T('*'); + else + size.Printf(_T("%d"), 10*pointSize); + + m_nativeFontInfo.SetXFontComponent(wxXLFD_POINTSIZE, size); + } +} + +void wxFontRefData::SetFamily(int family) +{ + m_family = family; + + // TODO: what are we supposed to do with m_nativeFontInfo here? +} + +void wxFontRefData::SetStyle(int style) +{ + m_style = style; + + if ( HasNativeFont() ) + { + wxString slant; + switch ( style ) + { + case wxFONTSTYLE_ITALIC: + slant = _T('i'); + break; + + case wxFONTSTYLE_SLANT: + slant = _T('o'); + break; + + default: + wxFAIL_MSG( _T("unknown font style") ); + // fall through + + case wxFONTSTYLE_NORMAL: + slant = _T('r'); + } + + m_nativeFontInfo.SetXFontComponent(wxXLFD_SLANT, slant); + } +} + +void wxFontRefData::SetWeight(int weight) +{ + m_weight = weight; + + if ( HasNativeFont() ) + { + wxString boldness; + switch ( weight ) + { + case wxFONTWEIGHT_BOLD: + boldness = _T("bold"); + break; + + case wxFONTWEIGHT_LIGHT: + boldness = _T("light"); + break; + + default: + wxFAIL_MSG( _T("unknown font weight") ); + // fall through + + case wxFONTWEIGHT_NORMAL: + // unspecified + boldness = _T("medium"); + } + + m_nativeFontInfo.SetXFontComponent(wxXLFD_WEIGHT, boldness); + } +} + +void wxFontRefData::SetUnderlined(bool underlined) +{ + m_underlined = underlined; + + // the XLFD doesn't have "underlined" field anyhow +} + +void wxFontRefData::SetFaceName(const wxString& facename) +{ + m_faceName = facename; + + if ( HasNativeFont() ) + { + m_nativeFontInfo.SetXFontComponent(wxXLFD_FAMILY, facename); + } +} + +void wxFontRefData::SetEncoding(wxFontEncoding encoding) +{ + m_encoding = encoding; + + if ( HasNativeFont() ) + { + wxNativeEncodingInfo info; + if ( wxGetNativeFontEncoding(encoding, &info) ) + { + m_nativeFontInfo.SetXFontComponent(wxXLFD_REGISTRY, info.xregistry); + m_nativeFontInfo.SetXFontComponent(wxXLFD_ENCODING, info.xencoding); + } + } +} + +// ============================================================================ +// wxFont implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxFont creation // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject) @@ -160,12 +449,7 @@ wxFont::wxFont(const wxNativeFontInfo& info) { Init(); - Create(info.xFontName); -} - -bool wxFont::Create(const wxNativeFontInfo& info) -{ - return Create(info.xFontName); + Create(info.GetXFontName()); } bool wxFont::Create( int pointSize, @@ -182,106 +466,18 @@ bool wxFont::Create( int pointSize, return TRUE; } -bool wxFont::Create(const wxString& fontname, wxFontEncoding enc) +bool wxFont::Create(const wxString& fontname) { - if( !fontname ) + // VZ: does this really happen? + if ( fontname.empty() ) { - *this = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT); - return TRUE; + *this = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + + return TRUE; } - m_refData = new wxFontRefData(); + m_refData = new wxFontRefData(fontname); - M_FONTDATA->m_nativeFontInfo.xFontName = fontname; // X font name - - wxString tmp; - - wxStringTokenizer tn( fontname, wxT("-") ); - - tn.GetNextToken(); // skip initial empty token - tn.GetNextToken(); // foundry - - - M_FONTDATA->m_faceName = tn.GetNextToken(); // family - - tmp = tn.GetNextToken().MakeUpper(); // weight - if (tmp == wxT("BOLD")) M_FONTDATA->m_weight = wxBOLD; - if (tmp == wxT("BLACK")) M_FONTDATA->m_weight = wxBOLD; - if (tmp == wxT("EXTRABOLD")) M_FONTDATA->m_weight = wxBOLD; - if (tmp == wxT("DEMIBOLD")) M_FONTDATA->m_weight = wxBOLD; - if (tmp == wxT("ULTRABOLD")) M_FONTDATA->m_weight = wxBOLD; - - if (tmp == wxT("LIGHT")) M_FONTDATA->m_weight = wxLIGHT; - if (tmp == wxT("THIN")) M_FONTDATA->m_weight = wxLIGHT; - - tmp = tn.GetNextToken().MakeUpper(); // slant - if (tmp == wxT("I")) M_FONTDATA->m_style = wxITALIC; - if (tmp == wxT("O")) M_FONTDATA->m_style = wxITALIC; - - tn.GetNextToken(); // set width - tn.GetNextToken(); // add. style - tn.GetNextToken(); // pixel size - - tmp = tn.GetNextToken(); // pointsize - if (tmp != wxT("*")) - { - long num = wxStrtol (tmp.c_str(), (wxChar **) NULL, 10); - M_FONTDATA->m_pointSize = (int)(num / 10); - } - - tn.GetNextToken(); // x-res - tn.GetNextToken(); // y-res - - tmp = tn.GetNextToken().MakeUpper(); // spacing - - if (tmp == wxT("M")) - M_FONTDATA->m_family = wxMODERN; - else if (M_FONTDATA->m_faceName == wxT("TIMES")) - M_FONTDATA->m_family = wxROMAN; - else if (M_FONTDATA->m_faceName == wxT("HELVETICA")) - M_FONTDATA->m_family = wxSWISS; - else if (M_FONTDATA->m_faceName == wxT("LUCIDATYPEWRITER")) - M_FONTDATA->m_family = wxTELETYPE; - else if (M_FONTDATA->m_faceName == wxT("LUCIDA")) - M_FONTDATA->m_family = wxDECORATIVE; - else if (M_FONTDATA->m_faceName == wxT("UTOPIA")) - M_FONTDATA->m_family = wxSCRIPT; - - tn.GetNextToken(); // avg width - - // deal with font encoding - M_FONTDATA->m_encoding = enc; - if ( M_FONTDATA->m_encoding == wxFONTENCODING_SYSTEM ) - { - wxString registry = tn.GetNextToken().MakeUpper(), - encoding = tn.GetNextToken().MakeUpper(); - - if ( registry == _T("ISO8859") ) - { - int cp; - if ( wxSscanf(encoding, wxT("%d"), &cp) == 1 ) - { - M_FONTDATA->m_encoding = - (wxFontEncoding)(wxFONTENCODING_ISO8859_1 + cp - 1); - } - } - else if ( registry == _T("MICROSOFT") ) - { - int cp; - if ( wxSscanf(encoding, wxT("cp125%d"), &cp) == 1 ) - { - M_FONTDATA->m_encoding = - (wxFontEncoding)(wxFONTENCODING_CP1250 + cp); - } - } - else if ( registry == _T("KOI8") ) - { - M_FONTDATA->m_encoding = wxFONTENCODING_KOI8; - } - //else: unknown encoding - may be give a warning here? - else - return FALSE; - } return TRUE; } @@ -307,10 +503,8 @@ wxFont::~wxFont() // accessors // ---------------------------------------------------------------------------- -bool wxFont::HasNativeFont() const -{ - return !M_FONTDATA->m_nativeFontInfo.xFontName.empty(); -} +// all accessors are just forwarded to wxFontRefData which has everything we +// need int wxFont::GetPointSize() const { @@ -354,7 +548,6 @@ bool wxFont::GetUnderlined() const return M_FONTDATA->m_underlined; } - wxFontEncoding wxFont::GetEncoding() const { wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") ); @@ -366,7 +559,7 @@ wxNativeFontInfo *wxFont::GetNativeFontInfo() const { wxCHECK_MSG( Ok(), (wxNativeFontInfo *)NULL, wxT("invalid font") ); - if(M_FONTDATA->m_nativeFontInfo.xFontName.IsEmpty()) + if ( M_FONTDATA->m_nativeFontInfo.GetXFontName().empty() ) GetInternalFont(); return new wxNativeFontInfo(M_FONTDATA->m_nativeFontInfo); @@ -376,7 +569,7 @@ bool wxFont::IsFixedWidth() const { wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") ); - if ( HasNativeFont() ) + if ( M_FONTDATA->HasNativeFont() ) { // the monospace fonts are supposed to have "M" in the spacing field wxString spacing = M_FONTDATA-> @@ -396,55 +589,49 @@ void wxFont::SetPointSize(int pointSize) { Unshare(); - M_FONTDATA->m_pointSize = pointSize; - M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now + M_FONTDATA->SetPointSize(pointSize); } void wxFont::SetFamily(int family) { Unshare(); - M_FONTDATA->m_family = family; - M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now + M_FONTDATA->SetFamily(family); } void wxFont::SetStyle(int style) { Unshare(); - M_FONTDATA->m_style = style; - M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now + M_FONTDATA->SetStyle(style); } void wxFont::SetWeight(int weight) { Unshare(); - M_FONTDATA->m_weight = weight; - M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now + M_FONTDATA->SetWeight(weight); } void wxFont::SetFaceName(const wxString& faceName) { Unshare(); - M_FONTDATA->m_faceName = faceName; - M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now + M_FONTDATA->SetFaceName(faceName); } void wxFont::SetUnderlined(bool underlined) { Unshare(); - M_FONTDATA->m_underlined = underlined; + M_FONTDATA->SetUnderlined(underlined); } void wxFont::SetEncoding(wxFontEncoding encoding) { Unshare(); - M_FONTDATA->m_encoding = encoding; - M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now + M_FONTDATA->SetEncoding(encoding); } void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info) @@ -460,7 +647,8 @@ void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info) static GdkFont *g_systemDefaultGuiFont = (GdkFont*) NULL; -GdkFont *GtkGetDefaultGuiFont() +// this is also used from tbargtk.cpp and tooltip.cpp, hence extern +extern GdkFont *GtkGetDefaultGuiFont() { if (!g_systemDefaultGuiFont) { @@ -489,41 +677,56 @@ GdkFont *GtkGetDefaultGuiFont() GdkFont *wxFont::GetInternalFont( float scale ) const { - if (!Ok()) - { - wxFAIL_MSG( wxT("invalid font") ); + GdkFont *font = (GdkFont *) NULL; - return (GdkFont*) NULL; - } + wxCHECK_MSG( Ok(), font, wxT("invalid font") ) long int_scale = long(scale * 100.0 + 0.5); /* key for fontlist */ int point_scale = (int)((M_FONTDATA->m_pointSize * 10 * int_scale) / 100); - GdkFont *font = (GdkFont *) NULL; wxNode *node = M_FONTDATA->m_scaled_xfonts.Find(int_scale); if (node) { font = (GdkFont*)node->Data(); } - else + else // we don't have this font in this size yet { if (*this == wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT)) { font = GtkGetDefaultGuiFont(); } - if (!font) + + if ( !font ) { - font = wxLoadQueryNearestFont( point_scale, - M_FONTDATA->m_family, - M_FONTDATA->m_style, - M_FONTDATA->m_weight, - M_FONTDATA->m_underlined, - M_FONTDATA->m_faceName, - M_FONTDATA->m_encoding, - &M_FONTDATA->m_nativeFontInfo.xFontName ); + // do we have the XLFD? + if ( M_FONTDATA->HasNativeFont() ) + { + font = wxLoadFont(M_FONTDATA->m_nativeFontInfo.GetXFontName()); + } + + // no XLFD of no exact match - try the approximate one now + if ( !font ) + { + wxString xfontname; + font = wxLoadQueryNearestFont( point_scale, + M_FONTDATA->m_family, + M_FONTDATA->m_style, + M_FONTDATA->m_weight, + M_FONTDATA->m_underlined, + M_FONTDATA->m_faceName, + M_FONTDATA->m_encoding, + &xfontname); + if ( font ) + { + M_FONTDATA->m_nativeFontInfo.SetXFontName(xfontname); + } + } } - M_FONTDATA->m_scaled_xfonts.Append( int_scale, (wxObject*)font ); + if ( font ) + { + M_FONTDATA->m_scaled_xfonts.Append( int_scale, (wxObject*)font ); + } } // it's quite useless to make it a wxCHECK because we're going to crash diff --git a/src/gtk/fontdlg.cpp b/src/gtk/fontdlg.cpp index b799105717..8a9846b1e7 100644 --- a/src/gtk/fontdlg.cpp +++ b/src/gtk/fontdlg.cpp @@ -76,43 +76,7 @@ void gtk_fontdialog_ok_callback( GtkWidget *WXUNUSED(widget), wxFontDialog *dial gchar *fontname = gtk_font_selection_dialog_get_font_name(fontdlg); - // extract the relevant bits from it - wxString xregistry, xencoding; - char *dash = strrchr(fontname, '-'); // find the last dash - if ( dash ) - { - xencoding = dash + 1; - *dash = '\0'; - dash = strrchr(fontname, '-'); // the last before one - if ( dash ) - { - xregistry = dash + 1; - } - else - { - wxFAIL_MSG( wxT("no registry in X font spec?") ); - } - - // restore the dash we changed to NUL above - *(fontname + strlen(fontname)) = '-'; - } - else - { - wxFAIL_MSG( wxT("no encoding in X font spec?") ); - } - - // transfer the X registry/encoding to wxFontData - they are used by - // wxFontMapper after wxFontDialog returns - wxFontData& fontdata = dialog->m_fontData; - - // we ignore the facename here - should be enough to choose an arbitrary - // one if the registry/encoding are specified - fontdata.EncodingInfo().xregistry = xregistry; - fontdata.EncodingInfo().xencoding = xencoding; - - // pass fontdata to wxFont ctor so that it can get the encoding from there - // if it is already known (otherwise it will try to deduce it itself) - dialog->m_fontData.SetChosenFont(wxFont(fontname, fontdata.GetEncoding())); + dialog->m_fontData.SetChosenFont(wxFont(fontname)); g_free( fontname ); @@ -187,11 +151,14 @@ wxFontDialog::wxFontDialog( wxWindow *parent, wxFontData *fontdata ) if ( info ) { - const wxString& fontname = info->xFontName; + const wxString& fontname = info->GetXFontName(); if ( !fontname ) font.GetInternalFont(); - gtk_font_selection_dialog_set_font_name(sel, - wxConvCurrent->cWX2MB(fontname)); + gtk_font_selection_dialog_set_font_name + ( + sel, + wxConvCurrent->cWX2MB(fontname) + ); } else { diff --git a/src/gtk/settings.cpp b/src/gtk/settings.cpp index eab86263f5..76a1b0565d 100644 --- a/src/gtk/settings.cpp +++ b/src/gtk/settings.cpp @@ -21,9 +21,6 @@ #include #include -extern GdkFont *GtkGetDefaultGuiFont(); - - /* #define wxSYS_COLOUR_SCROLLBAR 0 #define wxSYS_COLOUR_BACKGROUND 1 @@ -348,19 +345,6 @@ wxFont wxSystemSettingsNative::GetFont( wxSystemFont index ) { if (!g_systemFont) { -#if 0 - GdkFont *gdk_font = GtkGetDefaultGuiFont(); - if (gdk_font) - { - GSList *font_list = ((GdkFontPrivate*)gdk_font)->names; - char *name = (char*)font_list->data; - wxString font_string( name ); - wxFontData font_data; - g_systemFont = new wxFont( font_string, font_data ); - } - gtk_widget_destroy( widget ); -#endif - g_systemFont = new wxFont( 12, wxSWISS, wxNORMAL, wxNORMAL ); } diff --git a/src/gtk1/font.cpp b/src/gtk1/font.cpp index 940b38d81a..1637fb8a9a 100644 --- a/src/gtk1/font.cpp +++ b/src/gtk1/font.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: font.cpp +// Name: gtk/font.cpp // Purpose: // Author: Robert Roebling // Id: $Id$ @@ -34,6 +34,24 @@ #include #include +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// the default size (in points) for the fonts +static const int wxDEFAULT_FONT_SIZE = 12; + +// ---------------------------------------------------------------------------- +// wxScaledFontList +// ---------------------------------------------------------------------------- + +// TODO: replace this with a type safe list or hash!! +class wxScaledFontList : public wxList +{ +public: + wxScaledFontList() : wxList(wxKEY_INTEGER) { } +}; + // ---------------------------------------------------------------------------- // wxFontRefData // ---------------------------------------------------------------------------- @@ -41,16 +59,59 @@ class wxFontRefData : public wxObjectRefData { public: - wxFontRefData(int size = wxDEFAULT, - int family = wxDEFAULT, - int style = wxDEFAULT, - int weight = wxDEFAULT, + // from broken down font parameters, also default ctor + wxFontRefData(int size = -1, + int family = wxFONTFAMILY_DEFAULT, + int style = wxFONTSTYLE_NORMAL, + int weight = wxFONTWEIGHT_NORMAL, bool underlined = FALSE, const wxString& faceName = wxEmptyString, wxFontEncoding encoding = wxFONTENCODING_DEFAULT); + + // from XFLD + wxFontRefData(const wxString& fontname); + + // copy ctor wxFontRefData( const wxFontRefData& data ); + virtual ~wxFontRefData(); + // do we have the native font info? + bool HasNativeFont() const + { + return !m_nativeFontInfo.IsDefault(); + } + + // setters: all of them also take care to modify m_nativeFontInfo if we + // have it so as to not lose the information not carried by our fields + void SetPointSize(int pointSize); + void SetFamily(int family); + void SetStyle(int style); + void SetWeight(int weight); + void SetUnderlined(bool underlined); + void SetFaceName(const wxString& facename); + void SetEncoding(wxFontEncoding encoding); + + // debugger helper: shows what the font really is + // + // VZ: I need this as my gdb either shows wildly wrong values or crashes + // when I ask it to "p fontRefData" :-( +#ifdef __WXDEBUG__ + void Dump() const + { + wxPrintf(_T("%s-%s-%s-%d-%d\n"), + m_faceName.c_str(), + m_weight == wxFONTWEIGHT_NORMAL + ? _T("normal") + : m_weight == wxFONTWEIGHT_BOLD + ? _T("bold") + : _T("light"), + m_style == wxFONTSTYLE_NORMAL ? _T("regular") : _T("italic"), + m_pointSize, + m_encoding); + } +#endif // Debug + protected: // common part of all ctors void Init(int pointSize, @@ -62,7 +123,10 @@ protected: wxFontEncoding encoding); private: - wxList m_scaled_xfonts; + // the map of font sizes to "GdkFont *" + wxScaledFontList m_scaled_xfonts; + + // the broken down font parameters int m_pointSize; int m_family, m_style, @@ -71,17 +135,18 @@ private: wxString m_faceName; wxFontEncoding m_encoding; + // the native font info, basicly an XFLD wxNativeFontInfo m_nativeFontInfo; friend class wxFont; }; // ============================================================================ -// implementation +// wxFontRefData implementation // ============================================================================ // ---------------------------------------------------------------------------- -// wxFontRefData +// wxFontRefData creation // ---------------------------------------------------------------------------- void wxFontRefData::Init(int pointSize, @@ -92,48 +157,150 @@ void wxFontRefData::Init(int pointSize, const wxString& faceName, wxFontEncoding encoding) { - if (family == wxDEFAULT) - m_family = wxSWISS; - else - m_family = family; + m_family = family == wxFONTFAMILY_DEFAULT ? wxFONTFAMILY_SWISS : family; m_faceName = faceName; - if (style == wxDEFAULT) - m_style = wxNORMAL; - else - m_style = style; + // we accept both wxDEFAULT and wxNORMAL here - should we? + m_style = style == wxDEFAULT ? wxFONTSTYLE_NORMAL : style; + m_weight = weight == wxDEFAULT ? wxFONTWEIGHT_NORMAL : weight; - if (weight == wxDEFAULT) - m_weight = wxNORMAL; - else - m_weight = weight; - - if (pointSize == wxDEFAULT) - m_pointSize = 12; - else - m_pointSize = pointSize; + // and here, do we really want to forbid creation of the font of the size + // 90 (the value of wxDEFAULT)?? + m_pointSize = pointSize == wxDEFAULT || + pointSize == -1 ? wxDEFAULT_FONT_SIZE : pointSize; m_underlined = underlined; m_encoding = encoding; } wxFontRefData::wxFontRefData( const wxFontRefData& data ) - : m_scaled_xfonts(wxKEY_INTEGER) { - Init(data.m_pointSize, data.m_family, data.m_style, data.m_weight, - data.m_underlined, data.m_faceName, data.m_encoding); + m_pointSize = data.m_pointSize; + m_family = data.m_family; + m_style = data.m_style; + m_weight = data.m_weight; + + m_underlined = data.m_underlined; + + m_faceName = data.m_faceName; + m_encoding = data.m_encoding; + + m_nativeFontInfo = data.m_nativeFontInfo; } wxFontRefData::wxFontRefData(int size, int family, int style, int weight, bool underlined, const wxString& faceName, wxFontEncoding encoding) - : m_scaled_xfonts(wxKEY_INTEGER) { Init(size, family, style, weight, underlined, faceName, encoding); } +wxFontRefData::wxFontRefData(const wxString& fontname) +{ + // remember the X font name + m_nativeFontInfo.SetXFontName(fontname); + + // get the font parameters from the XLFD + // ------------------------------------- + + m_faceName = m_nativeFontInfo.GetXFontComponent(wxXLFD_FAMILY); + + m_weight = wxFONTWEIGHT_NORMAL; + + wxString w = m_nativeFontInfo.GetXFontComponent(wxXLFD_WEIGHT).Upper(); + if ( !w.empty() && w != _T('*') ) + { + // the test below catches all of BOLD, EXTRABOLD, DEMIBOLD, ULTRABOLD + // and BLACK + if ( ((w[0u] == _T('B') && (!strcmp(w.c_str() + 1, _T("OLD")) || + !strcmp(w.c_str() + 1, _T("LACK"))))) || + strstr(w.c_str() + 1, _T("BOLD")) ) + { + m_weight = wxFONTWEIGHT_BOLD; + } + else if ( w == _T("LIGHT") || w == _T("THIN") ) + { + m_weight = wxFONTWEIGHT_LIGHT; + } + } + + switch ( wxToupper(*m_nativeFontInfo. + GetXFontComponent(wxXLFD_SLANT).c_str()) ) + { + case _T('I'): // italique + m_style = wxFONTSTYLE_ITALIC; + break; + + case _T('O'): // oblique + m_style = wxFONTSTYLE_SLANT; + break; + + default: + m_style = wxFONTSTYLE_NORMAL; + } + + long ptSize; + if ( m_nativeFontInfo.GetXFontComponent(wxXLFD_POINTSIZE).ToLong(&ptSize) ) + { + // size in XLFD is in 10 point units + m_pointSize = (int)(ptSize / 10); + } + else + { + m_pointSize = wxDEFAULT_FONT_SIZE; + } + + // examine the spacing: if the font is monospaced, assume wxTELETYPE + // family for compatibility with the old code which used it instead of + // IsFixedWidth() + if ( m_nativeFontInfo.GetXFontComponent(wxXLFD_SPACING).Upper() == _T('M') ) + { + m_family = wxFONTFAMILY_TELETYPE; + } + else // not monospaceed + { + // don't even try guessing it, it doesn't work for too many fonts + // anyhow + m_family = wxFONTFAMILY_UNKNOWN; + } + + // X fonts are never underlined... + m_underlined = FALSE; + + // deal with font encoding + wxString + registry = m_nativeFontInfo.GetXFontComponent(wxXLFD_REGISTRY).Upper(), + encoding = m_nativeFontInfo.GetXFontComponent(wxXLFD_ENCODING).Upper(); + + if ( registry == _T("ISO8859") ) + { + int cp; + if ( wxSscanf(encoding, wxT("%d"), &cp) == 1 ) + { + m_encoding = (wxFontEncoding)(wxFONTENCODING_ISO8859_1 + cp - 1); + } + } + else if ( registry == _T("MICROSOFT") ) + { + int cp; + if ( wxSscanf(encoding, wxT("cp125%d"), &cp) == 1 ) + { + m_encoding = (wxFontEncoding)(wxFONTENCODING_CP1250 + cp); + } + } + else if ( registry == _T("KOI8") ) + { + m_encoding = wxFONTENCODING_KOI8; + } + else // unknown encoding + { + // may be give a warning here? + m_encoding = wxFONTENCODING_SYSTEM; + } +} + wxFontRefData::~wxFontRefData() { wxNode *node = m_scaled_xfonts.First(); @@ -147,7 +314,129 @@ wxFontRefData::~wxFontRefData() } // ---------------------------------------------------------------------------- -// wxFont +// wxFontRefData SetXXX() +// ---------------------------------------------------------------------------- + +void wxFontRefData::SetPointSize(int pointSize) +{ + m_pointSize = pointSize; + + if ( HasNativeFont() ) + { + wxString size; + if ( pointSize == -1 ) + size = _T('*'); + else + size.Printf(_T("%d"), 10*pointSize); + + m_nativeFontInfo.SetXFontComponent(wxXLFD_POINTSIZE, size); + } +} + +void wxFontRefData::SetFamily(int family) +{ + m_family = family; + + // TODO: what are we supposed to do with m_nativeFontInfo here? +} + +void wxFontRefData::SetStyle(int style) +{ + m_style = style; + + if ( HasNativeFont() ) + { + wxString slant; + switch ( style ) + { + case wxFONTSTYLE_ITALIC: + slant = _T('i'); + break; + + case wxFONTSTYLE_SLANT: + slant = _T('o'); + break; + + default: + wxFAIL_MSG( _T("unknown font style") ); + // fall through + + case wxFONTSTYLE_NORMAL: + slant = _T('r'); + } + + m_nativeFontInfo.SetXFontComponent(wxXLFD_SLANT, slant); + } +} + +void wxFontRefData::SetWeight(int weight) +{ + m_weight = weight; + + if ( HasNativeFont() ) + { + wxString boldness; + switch ( weight ) + { + case wxFONTWEIGHT_BOLD: + boldness = _T("bold"); + break; + + case wxFONTWEIGHT_LIGHT: + boldness = _T("light"); + break; + + default: + wxFAIL_MSG( _T("unknown font weight") ); + // fall through + + case wxFONTWEIGHT_NORMAL: + // unspecified + boldness = _T("medium"); + } + + m_nativeFontInfo.SetXFontComponent(wxXLFD_WEIGHT, boldness); + } +} + +void wxFontRefData::SetUnderlined(bool underlined) +{ + m_underlined = underlined; + + // the XLFD doesn't have "underlined" field anyhow +} + +void wxFontRefData::SetFaceName(const wxString& facename) +{ + m_faceName = facename; + + if ( HasNativeFont() ) + { + m_nativeFontInfo.SetXFontComponent(wxXLFD_FAMILY, facename); + } +} + +void wxFontRefData::SetEncoding(wxFontEncoding encoding) +{ + m_encoding = encoding; + + if ( HasNativeFont() ) + { + wxNativeEncodingInfo info; + if ( wxGetNativeFontEncoding(encoding, &info) ) + { + m_nativeFontInfo.SetXFontComponent(wxXLFD_REGISTRY, info.xregistry); + m_nativeFontInfo.SetXFontComponent(wxXLFD_ENCODING, info.xencoding); + } + } +} + +// ============================================================================ +// wxFont implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxFont creation // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject) @@ -160,12 +449,7 @@ wxFont::wxFont(const wxNativeFontInfo& info) { Init(); - Create(info.xFontName); -} - -bool wxFont::Create(const wxNativeFontInfo& info) -{ - return Create(info.xFontName); + Create(info.GetXFontName()); } bool wxFont::Create( int pointSize, @@ -182,106 +466,18 @@ bool wxFont::Create( int pointSize, return TRUE; } -bool wxFont::Create(const wxString& fontname, wxFontEncoding enc) +bool wxFont::Create(const wxString& fontname) { - if( !fontname ) + // VZ: does this really happen? + if ( fontname.empty() ) { - *this = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT); - return TRUE; + *this = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + + return TRUE; } - m_refData = new wxFontRefData(); + m_refData = new wxFontRefData(fontname); - M_FONTDATA->m_nativeFontInfo.xFontName = fontname; // X font name - - wxString tmp; - - wxStringTokenizer tn( fontname, wxT("-") ); - - tn.GetNextToken(); // skip initial empty token - tn.GetNextToken(); // foundry - - - M_FONTDATA->m_faceName = tn.GetNextToken(); // family - - tmp = tn.GetNextToken().MakeUpper(); // weight - if (tmp == wxT("BOLD")) M_FONTDATA->m_weight = wxBOLD; - if (tmp == wxT("BLACK")) M_FONTDATA->m_weight = wxBOLD; - if (tmp == wxT("EXTRABOLD")) M_FONTDATA->m_weight = wxBOLD; - if (tmp == wxT("DEMIBOLD")) M_FONTDATA->m_weight = wxBOLD; - if (tmp == wxT("ULTRABOLD")) M_FONTDATA->m_weight = wxBOLD; - - if (tmp == wxT("LIGHT")) M_FONTDATA->m_weight = wxLIGHT; - if (tmp == wxT("THIN")) M_FONTDATA->m_weight = wxLIGHT; - - tmp = tn.GetNextToken().MakeUpper(); // slant - if (tmp == wxT("I")) M_FONTDATA->m_style = wxITALIC; - if (tmp == wxT("O")) M_FONTDATA->m_style = wxITALIC; - - tn.GetNextToken(); // set width - tn.GetNextToken(); // add. style - tn.GetNextToken(); // pixel size - - tmp = tn.GetNextToken(); // pointsize - if (tmp != wxT("*")) - { - long num = wxStrtol (tmp.c_str(), (wxChar **) NULL, 10); - M_FONTDATA->m_pointSize = (int)(num / 10); - } - - tn.GetNextToken(); // x-res - tn.GetNextToken(); // y-res - - tmp = tn.GetNextToken().MakeUpper(); // spacing - - if (tmp == wxT("M")) - M_FONTDATA->m_family = wxMODERN; - else if (M_FONTDATA->m_faceName == wxT("TIMES")) - M_FONTDATA->m_family = wxROMAN; - else if (M_FONTDATA->m_faceName == wxT("HELVETICA")) - M_FONTDATA->m_family = wxSWISS; - else if (M_FONTDATA->m_faceName == wxT("LUCIDATYPEWRITER")) - M_FONTDATA->m_family = wxTELETYPE; - else if (M_FONTDATA->m_faceName == wxT("LUCIDA")) - M_FONTDATA->m_family = wxDECORATIVE; - else if (M_FONTDATA->m_faceName == wxT("UTOPIA")) - M_FONTDATA->m_family = wxSCRIPT; - - tn.GetNextToken(); // avg width - - // deal with font encoding - M_FONTDATA->m_encoding = enc; - if ( M_FONTDATA->m_encoding == wxFONTENCODING_SYSTEM ) - { - wxString registry = tn.GetNextToken().MakeUpper(), - encoding = tn.GetNextToken().MakeUpper(); - - if ( registry == _T("ISO8859") ) - { - int cp; - if ( wxSscanf(encoding, wxT("%d"), &cp) == 1 ) - { - M_FONTDATA->m_encoding = - (wxFontEncoding)(wxFONTENCODING_ISO8859_1 + cp - 1); - } - } - else if ( registry == _T("MICROSOFT") ) - { - int cp; - if ( wxSscanf(encoding, wxT("cp125%d"), &cp) == 1 ) - { - M_FONTDATA->m_encoding = - (wxFontEncoding)(wxFONTENCODING_CP1250 + cp); - } - } - else if ( registry == _T("KOI8") ) - { - M_FONTDATA->m_encoding = wxFONTENCODING_KOI8; - } - //else: unknown encoding - may be give a warning here? - else - return FALSE; - } return TRUE; } @@ -307,10 +503,8 @@ wxFont::~wxFont() // accessors // ---------------------------------------------------------------------------- -bool wxFont::HasNativeFont() const -{ - return !M_FONTDATA->m_nativeFontInfo.xFontName.empty(); -} +// all accessors are just forwarded to wxFontRefData which has everything we +// need int wxFont::GetPointSize() const { @@ -354,7 +548,6 @@ bool wxFont::GetUnderlined() const return M_FONTDATA->m_underlined; } - wxFontEncoding wxFont::GetEncoding() const { wxCHECK_MSG( Ok(), wxFONTENCODING_DEFAULT, wxT("invalid font") ); @@ -366,7 +559,7 @@ wxNativeFontInfo *wxFont::GetNativeFontInfo() const { wxCHECK_MSG( Ok(), (wxNativeFontInfo *)NULL, wxT("invalid font") ); - if(M_FONTDATA->m_nativeFontInfo.xFontName.IsEmpty()) + if ( M_FONTDATA->m_nativeFontInfo.GetXFontName().empty() ) GetInternalFont(); return new wxNativeFontInfo(M_FONTDATA->m_nativeFontInfo); @@ -376,7 +569,7 @@ bool wxFont::IsFixedWidth() const { wxCHECK_MSG( Ok(), FALSE, wxT("invalid font") ); - if ( HasNativeFont() ) + if ( M_FONTDATA->HasNativeFont() ) { // the monospace fonts are supposed to have "M" in the spacing field wxString spacing = M_FONTDATA-> @@ -396,55 +589,49 @@ void wxFont::SetPointSize(int pointSize) { Unshare(); - M_FONTDATA->m_pointSize = pointSize; - M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now + M_FONTDATA->SetPointSize(pointSize); } void wxFont::SetFamily(int family) { Unshare(); - M_FONTDATA->m_family = family; - M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now + M_FONTDATA->SetFamily(family); } void wxFont::SetStyle(int style) { Unshare(); - M_FONTDATA->m_style = style; - M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now + M_FONTDATA->SetStyle(style); } void wxFont::SetWeight(int weight) { Unshare(); - M_FONTDATA->m_weight = weight; - M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now + M_FONTDATA->SetWeight(weight); } void wxFont::SetFaceName(const wxString& faceName) { Unshare(); - M_FONTDATA->m_faceName = faceName; - M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now + M_FONTDATA->SetFaceName(faceName); } void wxFont::SetUnderlined(bool underlined) { Unshare(); - M_FONTDATA->m_underlined = underlined; + M_FONTDATA->SetUnderlined(underlined); } void wxFont::SetEncoding(wxFontEncoding encoding) { Unshare(); - M_FONTDATA->m_encoding = encoding; - M_FONTDATA->m_nativeFontInfo.xFontName.Clear(); // invalid now + M_FONTDATA->SetEncoding(encoding); } void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info) @@ -460,7 +647,8 @@ void wxFont::SetNativeFontInfo(const wxNativeFontInfo& info) static GdkFont *g_systemDefaultGuiFont = (GdkFont*) NULL; -GdkFont *GtkGetDefaultGuiFont() +// this is also used from tbargtk.cpp and tooltip.cpp, hence extern +extern GdkFont *GtkGetDefaultGuiFont() { if (!g_systemDefaultGuiFont) { @@ -489,41 +677,56 @@ GdkFont *GtkGetDefaultGuiFont() GdkFont *wxFont::GetInternalFont( float scale ) const { - if (!Ok()) - { - wxFAIL_MSG( wxT("invalid font") ); + GdkFont *font = (GdkFont *) NULL; - return (GdkFont*) NULL; - } + wxCHECK_MSG( Ok(), font, wxT("invalid font") ) long int_scale = long(scale * 100.0 + 0.5); /* key for fontlist */ int point_scale = (int)((M_FONTDATA->m_pointSize * 10 * int_scale) / 100); - GdkFont *font = (GdkFont *) NULL; wxNode *node = M_FONTDATA->m_scaled_xfonts.Find(int_scale); if (node) { font = (GdkFont*)node->Data(); } - else + else // we don't have this font in this size yet { if (*this == wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT)) { font = GtkGetDefaultGuiFont(); } - if (!font) + + if ( !font ) { - font = wxLoadQueryNearestFont( point_scale, - M_FONTDATA->m_family, - M_FONTDATA->m_style, - M_FONTDATA->m_weight, - M_FONTDATA->m_underlined, - M_FONTDATA->m_faceName, - M_FONTDATA->m_encoding, - &M_FONTDATA->m_nativeFontInfo.xFontName ); + // do we have the XLFD? + if ( M_FONTDATA->HasNativeFont() ) + { + font = wxLoadFont(M_FONTDATA->m_nativeFontInfo.GetXFontName()); + } + + // no XLFD of no exact match - try the approximate one now + if ( !font ) + { + wxString xfontname; + font = wxLoadQueryNearestFont( point_scale, + M_FONTDATA->m_family, + M_FONTDATA->m_style, + M_FONTDATA->m_weight, + M_FONTDATA->m_underlined, + M_FONTDATA->m_faceName, + M_FONTDATA->m_encoding, + &xfontname); + if ( font ) + { + M_FONTDATA->m_nativeFontInfo.SetXFontName(xfontname); + } + } } - M_FONTDATA->m_scaled_xfonts.Append( int_scale, (wxObject*)font ); + if ( font ) + { + M_FONTDATA->m_scaled_xfonts.Append( int_scale, (wxObject*)font ); + } } // it's quite useless to make it a wxCHECK because we're going to crash diff --git a/src/gtk1/fontdlg.cpp b/src/gtk1/fontdlg.cpp index b799105717..8a9846b1e7 100644 --- a/src/gtk1/fontdlg.cpp +++ b/src/gtk1/fontdlg.cpp @@ -76,43 +76,7 @@ void gtk_fontdialog_ok_callback( GtkWidget *WXUNUSED(widget), wxFontDialog *dial gchar *fontname = gtk_font_selection_dialog_get_font_name(fontdlg); - // extract the relevant bits from it - wxString xregistry, xencoding; - char *dash = strrchr(fontname, '-'); // find the last dash - if ( dash ) - { - xencoding = dash + 1; - *dash = '\0'; - dash = strrchr(fontname, '-'); // the last before one - if ( dash ) - { - xregistry = dash + 1; - } - else - { - wxFAIL_MSG( wxT("no registry in X font spec?") ); - } - - // restore the dash we changed to NUL above - *(fontname + strlen(fontname)) = '-'; - } - else - { - wxFAIL_MSG( wxT("no encoding in X font spec?") ); - } - - // transfer the X registry/encoding to wxFontData - they are used by - // wxFontMapper after wxFontDialog returns - wxFontData& fontdata = dialog->m_fontData; - - // we ignore the facename here - should be enough to choose an arbitrary - // one if the registry/encoding are specified - fontdata.EncodingInfo().xregistry = xregistry; - fontdata.EncodingInfo().xencoding = xencoding; - - // pass fontdata to wxFont ctor so that it can get the encoding from there - // if it is already known (otherwise it will try to deduce it itself) - dialog->m_fontData.SetChosenFont(wxFont(fontname, fontdata.GetEncoding())); + dialog->m_fontData.SetChosenFont(wxFont(fontname)); g_free( fontname ); @@ -187,11 +151,14 @@ wxFontDialog::wxFontDialog( wxWindow *parent, wxFontData *fontdata ) if ( info ) { - const wxString& fontname = info->xFontName; + const wxString& fontname = info->GetXFontName(); if ( !fontname ) font.GetInternalFont(); - gtk_font_selection_dialog_set_font_name(sel, - wxConvCurrent->cWX2MB(fontname)); + gtk_font_selection_dialog_set_font_name + ( + sel, + wxConvCurrent->cWX2MB(fontname) + ); } else { diff --git a/src/gtk1/settings.cpp b/src/gtk1/settings.cpp index eab86263f5..76a1b0565d 100644 --- a/src/gtk1/settings.cpp +++ b/src/gtk1/settings.cpp @@ -21,9 +21,6 @@ #include #include -extern GdkFont *GtkGetDefaultGuiFont(); - - /* #define wxSYS_COLOUR_SCROLLBAR 0 #define wxSYS_COLOUR_BACKGROUND 1 @@ -348,19 +345,6 @@ wxFont wxSystemSettingsNative::GetFont( wxSystemFont index ) { if (!g_systemFont) { -#if 0 - GdkFont *gdk_font = GtkGetDefaultGuiFont(); - if (gdk_font) - { - GSList *font_list = ((GdkFontPrivate*)gdk_font)->names; - char *name = (char*)font_list->data; - wxString font_string( name ); - wxFontData font_data; - g_systemFont = new wxFont( font_string, font_data ); - } - gtk_widget_destroy( widget ); -#endif - g_systemFont = new wxFont( 12, wxSWISS, wxNORMAL, wxNORMAL ); } diff --git a/src/unix/fontutil.cpp b/src/unix/fontutil.cpp index 27c2de464a..9e976bd3f0 100644 --- a/src/unix/fontutil.cpp +++ b/src/unix/fontutil.cpp @@ -71,22 +71,22 @@ static wxHashTable *g_fontHash = (wxHashTable*) NULL; // define the functions to create and destroy native fonts for this toolkit #ifdef __X__ - static inline wxNativeFont wxLoadFont(const wxString& fontSpec) + inline wxNativeFont wxLoadFont(const wxString& fontSpec) { return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec); } - static inline void wxFreeFont(wxNativeFont font) + inline void wxFreeFont(wxNativeFont font) { XFreeFont((Display *)wxGetDisplay(), (XFontStruct *)font); } #elif defined(__WXGTK__) - static inline wxNativeFont wxLoadFont(const wxString& fontSpec) + inline wxNativeFont wxLoadFont(const wxString& fontSpec) { return gdk_font_load( wxConvertWX2MB(fontSpec) ); } - static inline void wxFreeFont(wxNativeFont font) + inline void wxFreeFont(wxNativeFont font) { gdk_font_unref(font); } @@ -159,7 +159,7 @@ wxString wxNativeEncodingInfo::ToString() const void wxNativeFontInfo::Init() { - xFontName.clear(); + m_isDefault = TRUE; } bool wxNativeFontInfo::FromString(const wxString& s) @@ -196,11 +196,18 @@ wxString wxNativeFontInfo::ToUserString() const return GetXFontName(); } +bool wxNativeFontInfo::HasElements() const +{ + // we suppose that the foundry is never empty, so if it is it means that we + // had never parsed the XLFD + return !fontElements[0].empty(); +} + wxString wxNativeFontInfo::GetXFontComponent(wxXLFDField field) const { wxCHECK_MSG( field < wxXLFD_MAX, _T(""), _T("invalid XLFD field") ); - if ( fontElements[0].empty() ) + if ( !HasElements() ) { // const_cast if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) ) @@ -213,7 +220,13 @@ wxString wxNativeFontInfo::GetXFontComponent(wxXLFDField field) const bool wxNativeFontInfo::FromXFontName(const wxString& fontname) { // TODO: we should be able to handle the font aliases here, but how? - wxStringTokenizer tokenizer(fontname, _T("-"), wxTOKEN_STRTOK); + wxStringTokenizer tokenizer(fontname, _T("-")); + + // skip the leading, usually empty field (font name registry) + if ( !tokenizer.HasMoreTokens() ) + return FALSE; + + (void)tokenizer.GetNextToken(); for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ ) { @@ -239,7 +252,7 @@ wxString wxNativeFontInfo::GetXFontName() const // replace the non specified elements with '*' except for the // additional style which is usually just omitted wxString elt = fontElements[n]; - if ( elt.empty() && n != 5 ) + if ( elt.empty() && n != wxXLFD_ADDSTYLE ) { elt = _T('*'); } @@ -252,6 +265,42 @@ wxString wxNativeFontInfo::GetXFontName() const return xFontName; } +void +wxNativeFontInfo::SetXFontComponent(wxXLFDField field, const wxString& value) +{ + wxCHECK_RET( field < wxXLFD_MAX, _T("invalid XLFD field") ); + + // this class should be initialized with a valid font spec first and only + // then the fields may be modified! + wxASSERT_MSG( !IsDefault(), _T("can't modify an uninitialized XLFD") ); + + if ( !HasElements() ) + { + // const_cast + if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) ) + { + wxFAIL_MSG( _T("can't set font element for invalid XLFD") ); + + return; + } + } + + fontElements[field] = value; + + // invalidate the XFLD, it doesn't correspond to the font elements any more + xFontName.clear(); +} + +void wxNativeFontInfo::SetXFontName(const wxString& xFontName_) +{ + // invalidate the font elements, GetXFontComponent() will reparse the XLFD + fontElements[0].clear(); + + xFontName = xFontName_; + + m_isDefault = FALSE; +} + // ---------------------------------------------------------------------------- // common functions // ----------------------------------------------------------------------------