From c7a49742ec6b4effe012dc7204db307e1267bf6a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 23 Jan 2012 11:28:28 +0000 Subject: [PATCH] Add support for stricken-through fonts. Support stricken-through fonts in wxMSW and wxGTK (including special support in wxStaticText and wxTextCtrl). Closes #9907. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@70446 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 1 + include/wx/font.h | 4 ++ include/wx/fontutil.h | 5 ++ include/wx/gtk/font.h | 2 + include/wx/gtk/private.h | 15 ++++++ include/wx/msw/font.h | 2 + include/wx/textctrl.h | 7 ++- interface/wx/font.h | 52 +++++++++++++++++++- samples/font/font.cpp | 14 ++++++ src/common/fontcmn.cpp | 63 +++++++++++++++++++++--- src/common/textcmn.cpp | 15 ++++++ src/gtk/dcclient.cpp | 102 ++++++++++++++++++++++++--------------- src/gtk/font.cpp | 36 ++++++++++++-- src/gtk/gnome/gprint.cpp | 16 ++---- src/gtk/print.cpp | 17 ++----- src/gtk/stattext.cpp | 51 +++++++++++++------- src/gtk/textctrl.cpp | 12 +++++ src/msw/font.cpp | 48 ++++++++++++++++-- 18 files changed, 361 insertions(+), 101 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 236c2c93ef..f058577236 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -457,6 +457,7 @@ All: All (GUI): +- Added strike-through support to wxFont (Igor Korot). - Added wxFilePickerCtrl::SetInitialDirectory(). - Added wxDataViewItemAttr::SetBackgroundColour() and implemented it in generic wxDataViewCtrl (Andrew Xu). diff --git a/include/wx/font.h b/include/wx/font.h index 0a7623ee49..27f42bbca8 100644 --- a/include/wx/font.h +++ b/include/wx/font.h @@ -227,6 +227,7 @@ public: virtual wxFontStyle GetStyle() const = 0; virtual wxFontWeight GetWeight() const = 0; virtual bool GetUnderlined() const = 0; + virtual bool GetStrikethrough() const { return false; } virtual wxString GetFaceName() const = 0; virtual wxFontEncoding GetEncoding() const = 0; virtual const wxNativeFontInfo *GetNativeFontInfo() const = 0; @@ -244,6 +245,7 @@ public: virtual void SetWeight( wxFontWeight weight ) = 0; virtual void SetUnderlined( bool underlined ) = 0; + virtual void SetStrikethrough( bool WXUNUSED(strikethrough) ) {} virtual void SetEncoding(wxFontEncoding encoding) = 0; virtual bool SetFaceName( const wxString& faceName ); void SetNativeFontInfo(const wxNativeFontInfo& info) @@ -356,6 +358,7 @@ WXDLLIMPEXP_CORE bool wxFromString(const wxString& str, wxFontBase* font); wxFont& MakeBold(); \ wxFont& MakeItalic(); \ wxFont& MakeUnderlined(); \ + wxFont& MakeStrikethrough(); \ wxFont& MakeLarger() { return Scale(1.2f); } \ wxFont& MakeSmaller() { return Scale(1/1.2f); } \ wxFont& Scale(float x); \ @@ -363,6 +366,7 @@ WXDLLIMPEXP_CORE bool wxFromString(const wxString& str, wxFontBase* font); wxFont Bold() const; \ wxFont Italic() const; \ wxFont Underlined() const; \ + wxFont Strikethrough() const; \ wxFont Larger() const { return Scaled(1.2f); } \ wxFont Smaller() const { return Scaled(1/1.2f); } \ wxFont Scaled(float x) const diff --git a/include/wx/fontutil.h b/include/wx/fontutil.h index d52a6e3b77..0291b92176 100644 --- a/include/wx/fontutil.h +++ b/include/wx/fontutil.h @@ -172,6 +172,7 @@ public: wxFontStyle m_style; wxFontWeight m_weight; bool m_underlined; + bool m_strikethrough; wxString m_faceName; wxFontEncoding m_encoding; public : @@ -187,6 +188,7 @@ public : wxFontStyle style; wxFontWeight weight; bool underlined; + bool strikethrough; wxString faceName; wxFontEncoding encoding; #endif // platforms @@ -224,6 +226,7 @@ public: SetStyle((wxFontStyle)font.GetStyle()); SetWeight((wxFontWeight)font.GetWeight()); SetUnderlined(font.GetUnderlined()); + SetStrikethrough(font.GetStrikethrough()); #if defined(__WXMSW__) if ( font.IsUsingSizeInPixels() ) SetPixelSize(font.GetPixelSize()); @@ -252,6 +255,7 @@ public: wxFontStyle GetStyle() const; wxFontWeight GetWeight() const; bool GetUnderlined() const; + bool GetStrikethrough() const; wxString GetFaceName() const; wxFontFamily GetFamily() const; wxFontEncoding GetEncoding() const; @@ -261,6 +265,7 @@ public: void SetStyle(wxFontStyle style); void SetWeight(wxFontWeight weight); void SetUnderlined(bool underlined); + void SetStrikethrough(bool strikethrough); bool SetFaceName(const wxString& facename); void SetFamily(wxFontFamily family); void SetEncoding(wxFontEncoding encoding); diff --git a/include/wx/gtk/font.h b/include/wx/gtk/font.h index a73e9669cb..d1c04e2d8b 100644 --- a/include/wx/gtk/font.h +++ b/include/wx/gtk/font.h @@ -88,6 +88,7 @@ public: virtual wxFontWeight GetWeight() const; virtual wxString GetFaceName() const; virtual bool GetUnderlined() const; + virtual bool GetStrikethrough() const; virtual wxFontEncoding GetEncoding() const; virtual const wxNativeFontInfo *GetNativeFontInfo() const; virtual bool IsFixedWidth() const; @@ -98,6 +99,7 @@ public: virtual void SetWeight(wxFontWeight weight); virtual bool SetFaceName( const wxString& faceName ); virtual void SetUnderlined( bool underlined ); + virtual void SetStrikethrough(bool strikethrough); virtual void SetEncoding(wxFontEncoding encoding); wxDECLARE_COMMON_FONT_METHODS(); diff --git a/include/wx/gtk/private.h b/include/wx/gtk/private.h index 3ac71b7f5c..261f483ee9 100644 --- a/include/wx/gtk/private.h +++ b/include/wx/gtk/private.h @@ -111,6 +111,21 @@ GtkWidget *GetSplitterWidget(); GtkWidget *GetTextEntryWidget(); GtkWidget *GetTreeWidget(); +// Set Pango attributes corresponding to the given font for the span 0..len (or +// without any bounds if len == 0) in the specified layout. Currently only +// underlined and strike-through attributes are handled by this function. +// +// Special "addDummyAttrs" parameter is used to work around a bug in old Pango +// versions in wxWindowDCImpl::DoDrawText(), see comment there. +// +// If neither of them is specified, returns false, otherwise sets up the +// attributes and returns true. +// +// This function is implemented in src/gtk/dcclient.cpp. +bool +SetPangoAttrsForFont(const wxFont& font, PangoLayout* layout, size_t len = 0, + bool addDummyAttrs = false); + } // wxGTKPrivate #endif // _WX_GTK_PRIVATE_H_ diff --git a/include/wx/msw/font.h b/include/wx/msw/font.h index eb4ed5b17e..7a83f76653 100644 --- a/include/wx/msw/font.h +++ b/include/wx/msw/font.h @@ -123,6 +123,7 @@ public: virtual wxFontStyle GetStyle() const; virtual wxFontWeight GetWeight() const; virtual bool GetUnderlined() const; + virtual bool GetStrikethrough() const; virtual wxString GetFaceName() const; virtual wxFontEncoding GetEncoding() const; virtual const wxNativeFontInfo *GetNativeFontInfo() const; @@ -134,6 +135,7 @@ public: virtual void SetWeight(wxFontWeight weight); virtual bool SetFaceName(const wxString& faceName); virtual void SetUnderlined(bool underlined); + virtual void SetStrikethrough(bool strikethrough); virtual void SetEncoding(wxFontEncoding encoding); wxDECLARE_COMMON_FONT_METHODS(); diff --git a/include/wx/textctrl.h b/include/wx/textctrl.h index 94a7d55ed5..f6833830de 100644 --- a/include/wx/textctrl.h +++ b/include/wx/textctrl.h @@ -171,11 +171,12 @@ enum wxTextAttrFlags wxTEXT_ATTR_FONT_WEIGHT = 0x00000010, wxTEXT_ATTR_FONT_ITALIC = 0x00000020, wxTEXT_ATTR_FONT_UNDERLINE = 0x00000040, + wxTEXT_ATTR_FONT_STRIKETHROUGH = 0x08000000, wxTEXT_ATTR_FONT_ENCODING = 0x02000000, wxTEXT_ATTR_FONT_FAMILY = 0x04000000, wxTEXT_ATTR_FONT = \ ( wxTEXT_ATTR_FONT_FACE | wxTEXT_ATTR_FONT_SIZE | wxTEXT_ATTR_FONT_WEIGHT | \ - wxTEXT_ATTR_FONT_ITALIC | wxTEXT_ATTR_FONT_UNDERLINE | wxTEXT_ATTR_FONT_ENCODING | wxTEXT_ATTR_FONT_FAMILY ), + wxTEXT_ATTR_FONT_ITALIC | wxTEXT_ATTR_FONT_UNDERLINE | wxTEXT_ATTR_FONT_STRIKETHROUGH | wxTEXT_ATTR_FONT_ENCODING | wxTEXT_ATTR_FONT_FAMILY ), wxTEXT_ATTR_ALIGNMENT = 0x00000080, wxTEXT_ATTR_LEFT_INDENT = 0x00000100, @@ -317,6 +318,7 @@ public: void SetFontWeight(wxFontWeight fontWeight) { m_fontWeight = fontWeight; m_flags |= wxTEXT_ATTR_FONT_WEIGHT; } void SetFontFaceName(const wxString& faceName) { m_fontFaceName = faceName; m_flags |= wxTEXT_ATTR_FONT_FACE; } void SetFontUnderlined(bool underlined) { m_fontUnderlined = underlined; m_flags |= wxTEXT_ATTR_FONT_UNDERLINE; } + void SetFontStrikethrough(bool strikethrough) { m_fontStrikethrough = strikethrough; m_flags |= wxTEXT_ATTR_FONT_STRIKETHROUGH; } void SetFontEncoding(wxFontEncoding encoding) { m_fontEncoding = encoding; m_flags |= wxTEXT_ATTR_FONT_ENCODING; } void SetFontFamily(wxFontFamily family) { m_fontFamily = family; m_flags |= wxTEXT_ATTR_FONT_FAMILY; } @@ -355,6 +357,7 @@ public: wxFontStyle GetFontStyle() const { return m_fontStyle; } wxFontWeight GetFontWeight() const { return m_fontWeight; } bool GetFontUnderlined() const { return m_fontUnderlined; } + bool GetFontStrikethrough() const { return m_fontStrikethrough; } const wxString& GetFontFaceName() const { return m_fontFaceName; } wxFontEncoding GetFontEncoding() const { return m_fontEncoding; } wxFontFamily GetFontFamily() const { return m_fontFamily; } @@ -389,6 +392,7 @@ public: bool HasFontSize() const { return HasFlag(wxTEXT_ATTR_FONT_SIZE); } bool HasFontItalic() const { return HasFlag(wxTEXT_ATTR_FONT_ITALIC); } bool HasFontUnderlined() const { return HasFlag(wxTEXT_ATTR_FONT_UNDERLINE); } + bool HasFontStrikethrough() const { return HasFlag(wxTEXT_ATTR_FONT_STRIKETHROUGH); } bool HasFontFaceName() const { return HasFlag(wxTEXT_ATTR_FONT_FACE); } bool HasFontEncoding() const { return HasFlag(wxTEXT_ATTR_FONT_ENCODING); } bool HasFontFamily() const { return HasFlag(wxTEXT_ATTR_FONT_FAMILY); } @@ -500,6 +504,7 @@ private: wxFontWeight m_fontWeight; wxFontFamily m_fontFamily; bool m_fontUnderlined; + bool m_fontStrikethrough; wxString m_fontFaceName; // Character style diff --git a/interface/wx/font.h b/interface/wx/font.h index cde804883b..1304eaecb5 100644 --- a/interface/wx/font.h +++ b/interface/wx/font.h @@ -112,8 +112,10 @@ enum wxFontFlag wxFONTFLAG_ANTIALIASED = 1 << 4, wxFONTFLAG_NOT_ANTIALIASED = 1 << 5, - /// underlined/strikethrough flags (default: no lines) + /// Underlined style (not underlined by default). wxFONTFLAG_UNDERLINED = 1 << 6, + + /// Strike-through style (only supported in wxMSW and wxGTK currently). wxFONTFLAG_STRIKETHROUGH = 1 << 7, /// the mask of all currently used flags @@ -404,6 +406,9 @@ public: The meaning of the remaining arguments is the same as in the other constructors, please see their documentation for details. + Notice that this constructor provides the only way of creating fonts + with strike-through style. + @since 2.9.4 */ wxFont(int pointSize, wxFontFamily family, int flags, @@ -541,6 +546,15 @@ public: */ virtual bool GetUnderlined() const; + /** + Returns @true if the font is stricken-through, @false otherwise. + + @see SetStrikethrough() + + @since 2.9.4 + */ + virtual bool GetStrikethrough() const; + /** Gets the font weight. See ::wxFontWeight for a list of valid weight identifiers. @@ -627,6 +641,17 @@ public: */ wxFont Underlined() const; + /** + Returns stricken-through version of this font. + + Currently stricken-through fonts are only supported in wxMSW and wxGTK. + + @see MakeStrikethrough() + + @since 2.9.4 + */ + wxFont Strikethrough() const; + /** Changes this font to be bold. @@ -678,6 +703,17 @@ public: */ wxFont& MakeUnderlined(); + /** + Changes this font to be stricken-through. + + Currently stricken-through fonts are only supported in wxMSW and wxGTK. + + @see Strikethrough() + + @since 2.9.4 + */ + wxFont& MakeStrikethrough(); + /** Changes the size of this font. @@ -869,6 +905,20 @@ public: */ virtual void SetUnderlined(bool underlined); + /** + Sets strike-through attribute of the font. + + Currently stricken-through fonts are only supported in wxMSW and wxGTK. + + @param strikethrough + @true to add strike-through style, @false to remove it. + + @see GetStrikethrough() + + @since 2.9.4 + */ + virtual void SetStrikethrough(bool strikethrough); + /** Sets the font weight. diff --git a/samples/font/font.cpp b/samples/font/font.cpp index 14d2679231..4c78adc24d 100644 --- a/samples/font/font.cpp +++ b/samples/font/font.cpp @@ -107,6 +107,7 @@ public: void OnSlant(wxCommandEvent& event); void OnUnderline(wxCommandEvent& event); + void OnStrikethrough(wxCommandEvent& event); void OnwxPointerFont(wxCommandEvent& event); void OnwxSystemSettingsFont(wxCommandEvent& event); @@ -178,6 +179,7 @@ enum Font_Slant, Font_Underlined, + Font_Strikethrough, // standard global wxFont objects: Font_wxNORMAL_FONT, @@ -231,6 +233,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(Font_Slant, MyFrame::OnSlant) EVT_MENU(Font_Underlined, MyFrame::OnUnderline) + EVT_MENU(Font_Strikethrough, MyFrame::OnStrikethrough) EVT_MENU(Font_wxNORMAL_FONT, MyFrame::OnwxPointerFont) EVT_MENU(Font_wxSMALL_FONT, MyFrame::OnwxPointerFont) @@ -330,6 +333,8 @@ MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) menuFont->AppendSeparator(); menuFont->AppendCheckItem(Font_Underlined, wxT("&Underlined\tCtrl-U"), wxT("Toggle underlined state")); + menuFont->AppendCheckItem(Font_Strikethrough, wxT("&Strikethrough"), + wxT("Toggle strikethrough state")); menuFont->AppendSeparator(); menuFont->Append(Font_SetNativeDesc, @@ -735,6 +740,13 @@ void MyFrame::OnUnderline(wxCommandEvent& event) DoChangeFont(font); } +void MyFrame::OnStrikethrough(wxCommandEvent& event) +{ + wxFont font = m_canvas->GetTextFont(); + font.SetStrikethrough(event.IsChecked()); + DoChangeFont(font); +} + void MyFrame::OnwxPointerFont(wxCommandEvent& event) { wxFont font; @@ -813,6 +825,7 @@ void MyFrame::DoChangeFont(const wxFont& font, const wxColour& col) m_textctrl->SetFont(font); if ( col.IsOk() ) m_textctrl->SetForegroundColour(col); + m_textctrl->Refresh(); // update the state of the bold/italic/underlined menu items wxMenuBar *mbar = GetMenuBar(); @@ -827,6 +840,7 @@ void MyFrame::DoChangeFont(const wxFont& font, const wxColour& col) #endif mbar->Check(Font_Underlined, font.GetUnderlined()); + mbar->Check(Font_Strikethrough, font.GetStrikethrough()); } } diff --git a/src/common/fontcmn.cpp b/src/common/fontcmn.cpp index de35aa96d1..fed694a96d 100644 --- a/src/common/fontcmn.cpp +++ b/src/common/fontcmn.cpp @@ -113,6 +113,8 @@ wxPROPERTY( Weight, wxFontWeight, SetWeight, GetWeight, (wxFontWeight)wxNORMAL, wxT("Helpstring"), wxT("group")) // wxFontWeight wxPROPERTY( Underlined, bool, SetUnderlined, GetUnderlined, false, 0 /*flags*/, \ wxT("Helpstring"), wxT("group")) +wxPROPERTY( Strikethrough, bool, SetStrikethrough, GetStrikethrough, false, 0, \ + wxT("Helpstring"), wxT("group")) wxPROPERTY( Face, wxString, SetFaceName, GetFaceName, wxEMPTY_PARAMETER_VALUE, \ 0 /*flags*/, wxT("Helpstring"), wxT("group")) wxPROPERTY( Encoding, wxFontEncoding, SetEncoding, GetEncoding, \ @@ -307,6 +309,7 @@ void wxFontBase::DoSetNativeFontInfo(const wxNativeFontInfo& info) SetStyle(info.style); SetWeight(info.weight); SetUnderlined(info.underlined); + SetStrikethrough(info.strikethrough); SetFaceName(info.faceName); SetEncoding(info.encoding); #else @@ -394,6 +397,7 @@ bool wxFontBase::operator==(const wxFont& font) const GetStyle() == font.GetStyle() && GetWeight() == font.GetWeight() && GetUnderlined() == font.GetUnderlined() && + GetStrikethrough() == font.GetStrikethrough() && GetFaceName().IsSameAs(font.GetFaceName(), false) && GetEncoding() == font.GetEncoding() ); @@ -533,6 +537,19 @@ wxFont wxFont::Underlined() const return font; } +wxFont wxFont::Strikethrough() const +{ + wxFont font(*this); + font.MakeStrikethrough(); + return font; +} + +wxFont& wxFont::MakeStrikethrough() +{ + SetStrikethrough(true); + return *this; +} + wxFont& wxFont::Scale(float x) { SetPointSize(int(x*GetPointSize() + 0.5)); @@ -577,19 +594,22 @@ void wxNativeFontInfo::SetFaceName(const wxArrayString& facenames) // These are the generic forms of FromString()/ToString. // -// convert to/from the string representation: format is -// version;pointsize;family;style;weight;underlined;facename;encoding +// convert to/from the string representation: the general format is +// "version;the rest..." with currently defined versions being: +// +// 0;pointsize;family;style;weight;underlined;facename;encoding +// 1;pointsize;family;style;weight;underlined;strikethrough;facename;encoding bool wxNativeFontInfo::FromString(const wxString& s) { long l; + short version; wxStringTokenizer tokenizer(s, wxT(";")); wxString token = tokenizer.GetNextToken(); - // - // Ignore the version for now - // + if ( !token.ToLong(&version) || version < 0 || version > 1 ) + return false; token = tokenizer.GetNextToken(); if ( !token.ToLong(&l) ) @@ -616,6 +636,14 @@ bool wxNativeFontInfo::FromString(const wxString& s) return false; underlined = l != 0; + if ( version == 1 ) + { + token = tokenizer.GetNextToken(); + if ( !token.ToLong(&l) ) + return false; + strikethrough = l != 0; + } + faceName = tokenizer.GetNextToken(); #ifndef __WXMAC__ @@ -635,13 +663,14 @@ wxString wxNativeFontInfo::ToString() const { wxString s; - s.Printf(wxT("%d;%d;%d;%d;%d;%d;%s;%d"), - 0, // version + s.Printf(wxT("%d;%d;%d;%d;%d;%d;%d;%s;%d"), + 1, // version pointSize, family, (int)style, (int)weight, underlined, + strikethrough, faceName.GetData(), (int)encoding); @@ -655,6 +684,7 @@ void wxNativeFontInfo::Init() style = wxFONTSTYLE_NORMAL; weight = wxFONTWEIGHT_NORMAL; underlined = false; + strikethrough = false; faceName.clear(); encoding = wxFONTENCODING_DEFAULT; } @@ -679,6 +709,11 @@ bool wxNativeFontInfo::GetUnderlined() const return underlined; } +bool wxNativeFontInfo::GetStrikethrough() const +{ + return strikethrough; +} + wxString wxNativeFontInfo::GetFaceName() const { return faceName; @@ -714,6 +749,11 @@ void wxNativeFontInfo::SetUnderlined(bool underlined_) underlined = underlined_; } +void wxNativeFontInfo::SetStrikethrough(bool strikethrough_) +{ + strikethrough = strikethrough_; +} + bool wxNativeFontInfo::SetFaceName(const wxString& facename_) { faceName = facename_; @@ -750,6 +790,11 @@ wxString wxNativeFontInfo::ToUserString() const desc << _("underlined"); } + if ( GetStrikethrough() ) + { + desc << _("strikethrough"); + } + switch ( GetWeight() ) { default: @@ -922,6 +967,10 @@ bool wxNativeFontInfo::FromUserString(const wxString& s) { SetUnderlined(true); } + else if ( token == wxT("strikethrough") || token == _("strikethrough") ) + { + SetStrikethrough(true); + } else if ( token == wxT("light") || token == _("light") ) { SetWeight(wxFONTWEIGHT_LIGHT); diff --git a/src/common/textcmn.cpp b/src/common/textcmn.cpp index d64baccfb7..3b75cba9c8 100644 --- a/src/common/textcmn.cpp +++ b/src/common/textcmn.cpp @@ -403,6 +403,10 @@ wxFont wxTextAttr::GetFont() const if (HasFontUnderlined()) underlined = GetFontUnderlined(); + bool strikethrough = false; + if ( HasFontStrikethrough() ) + strikethrough = GetFontStrikethrough(); + wxString fontFaceName; if (HasFontFaceName()) fontFaceName = GetFontFaceName(); @@ -416,6 +420,8 @@ wxFont wxTextAttr::GetFont() const fontFamily = GetFontFamily(); wxFont font(fontSize, fontFamily, fontStyle, fontWeight, underlined, fontFaceName, encoding); + if ( strikethrough ) + font.SetStrikethrough( true ); return font; } @@ -437,6 +443,9 @@ bool wxTextAttr::GetFontAttributes(const wxFont& font, int flags) if (flags & wxTEXT_ATTR_FONT_UNDERLINE) m_fontUnderlined = font.GetUnderlined(); + if (flags & wxTEXT_ATTR_FONT_STRIKETHROUGH) + m_fontStrikethrough = font.GetStrikethrough(); + if (flags & wxTEXT_ATTR_FONT_FACE) m_fontFaceName = font.GetFaceName(); @@ -500,6 +509,12 @@ bool wxTextAttr::Apply(const wxTextAttr& style, const wxTextAttr* compareWith) destStyle.SetFontUnderlined(style.GetFontUnderlined()); } + if (style.HasFontStrikethrough()) + { + if (!(compareWith && compareWith->HasFontStrikethrough() && compareWith->GetFontStrikethrough() == style.GetFontStrikethrough())) + destStyle.SetFontStrikethrough(style.GetFontStrikethrough()); + } + if (style.HasFontFaceName()) { if (!(compareWith && compareWith->HasFontFaceName() && compareWith->GetFontFaceName() == style.GetFontFaceName())) diff --git a/src/gtk/dcclient.cpp b/src/gtk/dcclient.cpp index f9a123a20f..398d319bd8 100644 --- a/src/gtk/dcclient.cpp +++ b/src/gtk/dcclient.cpp @@ -26,6 +26,8 @@ #include "wx/gtk/private.h" #include "wx/gtk/private/object.h" +using wxGTKPrivate::SetPangoAttrsForFont; + //----------------------------------------------------------------------------- // local defines //----------------------------------------------------------------------------- @@ -1408,33 +1410,8 @@ void wxWindowDCImpl::DoDrawText(const wxString& text, } pango_layout_set_text(m_layout, data, datalen); - - if (underlined) - { - PangoAttrList *attrs = pango_attr_list_new(); - PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); - a->start_index = 0; - a->end_index = datalen; - pango_attr_list_insert(attrs, a); - - if (needshack) - { - // dummy colour for the leading space - a = pango_attr_foreground_new (0x0057, 0x52A9, 0xD614); - a->start_index = 0; - a->end_index = 1; - pango_attr_list_insert(attrs, a); - - // dummy colour for the trailing space - a = pango_attr_foreground_new (0x0057, 0x52A9, 0xD614); - a->start_index = datalen - 1; - a->end_index = datalen; - pango_attr_list_insert(attrs, a); - } - - pango_layout_set_attributes(m_layout, attrs); - pango_attr_list_unref(attrs); - } + const bool + setAttrs = SetPangoAttrsForFont(m_font, m_layout, datalen, needshack); int oldSize = 0; const bool isScaled = fabs(m_scaleY - 1.0) > 0.00001; @@ -1473,7 +1450,7 @@ void wxWindowDCImpl::DoDrawText(const wxString& text, // actually apply unscaled font pango_layout_set_font_description( m_layout, m_fontdesc ); } - if (underlined) + if (setAttrs) { // undo underline attributes setting: pango_layout_set_attributes(m_layout, NULL); @@ -1499,16 +1476,7 @@ void wxWindowDCImpl::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y = YLOG2DEV(y); pango_layout_set_text(m_layout, wxGTK_CONV(text), -1); - - if (m_font.GetUnderlined()) - { - PangoAttrList *attrs = pango_attr_list_new(); - PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); - pango_attr_list_insert(attrs, a); - pango_layout_set_attributes(m_layout, attrs); - pango_attr_list_unref(attrs); - } - + SetPangoAttrsForFont( m_font, m_layout ); int oldSize = 0; const bool isScaled = fabs(m_scaleY - 1.0) > 0.00001; if (isScaled) @@ -1561,7 +1529,7 @@ void wxWindowDCImpl::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord gdk_draw_layout_with_colors(m_gdkwindow, m_textGC, x+minX, y+minY, m_layout, NULL, bg_col); - if (m_font.GetUnderlined()) + if (m_font.GetUnderlined() || m_font.GetStrikethrough()) pango_layout_set_attributes(m_layout, NULL); // clean up the transformation matrix @@ -2304,6 +2272,62 @@ int wxWindowDCImpl::GetDepth() const return gdk_drawable_get_depth(m_gdkwindow); } +bool +wxGTKPrivate::SetPangoAttrsForFont(const wxFont& font, + PangoLayout *layout, + size_t len, + bool addDummyAttrs) +{ + if ( !font.IsOk() || !(font.GetUnderlined() || font.GetStrikethrough()) ) + return false; + + PangoAttrList* attrs = pango_attr_list_new(); + + if ( font.GetUnderlined() ) + { + PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); + if ( len ) + { + a->start_index = 0; + a->end_index = len; + } + pango_attr_list_insert(attrs, a); + + // Add dummy attributes (use colour as it's invisible anyhow for 0 + // width spaces) to ensure that the spaces in the beginning/end of the + // string are underlined too. + if ( addDummyAttrs ) + { + wxASSERT_MSG( len > 2, "Must have 0-width spaces at string ends" ); + + a = pango_attr_foreground_new (0x0057, 0x52A9, 0xD614); + a->start_index = 0; + a->end_index = 1; + pango_attr_list_insert(attrs, a); + + a = pango_attr_foreground_new (0x0057, 0x52A9, 0xD614); + a->start_index = len - 1; + a->end_index = len; + pango_attr_list_insert(attrs, a); + } + } + + if ( font.GetStrikethrough() ) + { + PangoAttribute *a = pango_attr_strikethrough_new( TRUE ); + if ( len ) + { + a->start_index = 0; + a->end_index = len; + } + pango_attr_list_insert(attrs, a); + } + + pango_layout_set_attributes(layout, attrs); + pango_attr_list_unref(attrs); + + return true; +} //----------------------------------------------------------------------------- // wxClientDCImpl diff --git a/src/gtk/font.cpp b/src/gtk/font.cpp index 5ca1b2b600..1ae79d7eb7 100644 --- a/src/gtk/font.cpp +++ b/src/gtk/font.cpp @@ -52,6 +52,7 @@ public: wxFontStyle style = wxFONTSTYLE_NORMAL, wxFontWeight weight = wxFONTWEIGHT_NORMAL, bool underlined = false, + bool strikethrough = false, const wxString& faceName = wxEmptyString, wxFontEncoding encoding = wxFONTENCODING_DEFAULT); @@ -69,6 +70,7 @@ public: void SetStyle(wxFontStyle style); void SetWeight(wxFontWeight weight); void SetUnderlined(bool underlined); + void SetStrikethrough(bool strikethrough); bool SetFaceName(const wxString& facename); void SetEncoding(wxFontEncoding encoding); @@ -82,6 +84,7 @@ protected: wxFontStyle style, wxFontWeight weight, bool underlined, + bool strikethrough, const wxString& faceName, wxFontEncoding encoding); @@ -90,7 +93,7 @@ protected: private: bool m_underlined; - + bool m_strikethrough; // The native font info: basically a PangoFontDescription wxNativeFontInfo m_nativeFontInfo; @@ -108,6 +111,7 @@ void wxFontRefData::Init(int pointSize, wxFontStyle style, wxFontWeight weight, bool underlined, + bool strikethrough, const wxString& faceName, wxFontEncoding WXUNUSED(encoding)) { @@ -115,6 +119,7 @@ void wxFontRefData::Init(int pointSize, family = wxFONTFAMILY_SWISS; m_underlined = underlined; + m_strikethrough = strikethrough; // Create native font info m_nativeFontInfo.description = pango_font_description_new(); @@ -149,12 +154,14 @@ void wxFontRefData::InitFromNative() // Pango description are never underlined m_underlined = false; + m_strikethrough = false; } wxFontRefData::wxFontRefData( const wxFontRefData& data ) : wxGDIRefData() { m_underlined = data.m_underlined; + m_strikethrough = data.m_strikethrough; // Forces a copy of the internal data. wxNativeFontInfo should probably // have a copy ctor and assignment operator to fix this properly but that @@ -163,11 +170,11 @@ wxFontRefData::wxFontRefData( const wxFontRefData& data ) } wxFontRefData::wxFontRefData(int size, wxFontFamily family, wxFontStyle style, - wxFontWeight weight, bool underlined, + wxFontWeight weight, bool underlined, bool strikethrough, const wxString& faceName, wxFontEncoding encoding) { - Init(size, family, style, weight, underlined, faceName, encoding); + Init(size, family, style, weight, underlined, strikethrough, faceName, encoding); } wxFontRefData::wxFontRefData(const wxString& nativeFontInfoString) @@ -244,6 +251,11 @@ void wxFontRefData::SetUnderlined(bool underlined) // here we just need to save the underlined attribute } +void wxFontRefData::SetStrikethrough(bool strikethrough) +{ + m_strikethrough = strikethrough; +} + bool wxFontRefData::SetFaceName(const wxString& facename) { return m_nativeFontInfo.SetFaceName(facename); @@ -287,7 +299,7 @@ wxFont::wxFont(int pointSize, GetStyleFromFlags(flags), GetWeightFromFlags(flags), GetUnderlinedFromFlags(flags), - face, encoding); + false, face, encoding); } bool wxFont::Create( int pointSize, @@ -301,7 +313,7 @@ bool wxFont::Create( int pointSize, UnRef(); m_refData = new wxFontRefData(pointSize, family, style, weight, - underlined, face, encoding); + underlined, false, face, encoding); return true; } @@ -369,6 +381,13 @@ bool wxFont::GetUnderlined() const return M_FONTDATA->m_underlined; } +bool wxFont::GetStrikethrough() const +{ + wxCHECK_MSG( IsOk(), false, wxT("invalid font") ); + + return M_FONTDATA->m_strikethrough; +} + wxFontEncoding wxFont::GetEncoding() const { wxCHECK_MSG( IsOk(), wxFONTENCODING_SYSTEM, wxT("invalid font") ); @@ -438,6 +457,13 @@ void wxFont::SetUnderlined(bool underlined) M_FONTDATA->SetUnderlined(underlined); } +void wxFont::SetStrikethrough(bool strikethrough) +{ + AllocExclusive(); + + M_FONTDATA->SetStrikethrough(strikethrough); +} + void wxFont::SetEncoding(wxFontEncoding encoding) { AllocExclusive(); diff --git a/src/gtk/gnome/gprint.cpp b/src/gtk/gnome/gprint.cpp index 5902314417..807477e2e0 100644 --- a/src/gtk/gnome/gprint.cpp +++ b/src/gtk/gnome/gprint.cpp @@ -1592,23 +1592,13 @@ void wxGnomePrinterDCImpl::DoDrawRotatedText(const wxString& text, wxCoord x, wx double xx = XLOG2DEV(x); double yy = YLOG2DEV(y); - bool underlined = m_font.IsOk() && m_font.GetUnderlined(); - const wxScopedCharBuffer data(text.utf8_str()); size_t datalen = strlen(data); pango_layout_set_text( m_layout, data, datalen); - if (underlined) - { - PangoAttrList *attrs = pango_attr_list_new(); - PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); - a->start_index = 0; - a->end_index = datalen; - pango_attr_list_insert(attrs, a); - pango_layout_set_attributes(m_layout, attrs); - pango_attr_list_unref(attrs); - } + const bool + setAttrs = wxGTKPrivate::SetPangoAttrsForFont(m_font, m_layout, datalen); if (m_textForegroundColour.IsOk()) { @@ -1656,7 +1646,7 @@ void wxGnomePrinterDCImpl::DoDrawRotatedText(const wxString& text, wxCoord x, wx gs_libGnomePrint->gnome_print_grestore( m_gpc ); - if (underlined) + if (setAttrs) { // undo underline attributes setting: pango_layout_set_attributes(m_layout, NULL); diff --git a/src/gtk/print.cpp b/src/gtk/print.cpp index ec14f2c4c9..bb207524c0 100644 --- a/src/gtk/print.cpp +++ b/src/gtk/print.cpp @@ -1738,24 +1738,13 @@ void wxGtkPrinterDCImpl::DoDrawRotatedText(const wxString& text, wxCoord x, wxCo angle = -angle; - bool underlined = m_font.IsOk() && m_font.GetUnderlined(); - const wxScopedCharBuffer data = text.utf8_str(); size_t datalen = strlen(data); pango_layout_set_text( m_layout, data, datalen); - if (underlined) - { - PangoAttrList *attrs = pango_attr_list_new(); - PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); - a->start_index = 0; - a->end_index = datalen; - pango_attr_list_insert(attrs, a); - pango_layout_set_attributes(m_layout, attrs); - pango_attr_list_unref(attrs); - } - + const bool + setAttrs = wxGTKPrivate::SetPangoAttrsForFont(m_font, m_layout, datalen); if (m_textForegroundColour.IsOk()) { unsigned char red = m_textForegroundColour.Red(); @@ -1816,7 +1805,7 @@ void wxGtkPrinterDCImpl::DoDrawRotatedText(const wxString& text, wxCoord x, wxCo cairo_restore( m_cairo ); - if (underlined) + if (setAttrs) { // Undo underline attributes setting pango_layout_set_attributes(m_layout, NULL); diff --git a/src/gtk/stattext.cpp b/src/gtk/stattext.cpp index 7e8bfead1e..2461821714 100644 --- a/src/gtk/stattext.cpp +++ b/src/gtk/stattext.cpp @@ -153,31 +153,48 @@ bool wxStaticText::DoSetLabelMarkup(const wxString& markup) bool wxStaticText::SetFont( const wxFont &font ) { const bool wasUnderlined = GetFont().GetUnderlined(); + const bool wasStrickenThrough = GetFont().GetStrikethrough(); bool ret = wxControl::SetFont(font); - if ( font.GetUnderlined() != wasUnderlined ) - { - // the underlines for mnemonics are incompatible with using attributes - // so turn them off when setting underlined font and restore them when - // unsetting it - gtk_label_set_use_underline(GTK_LABEL(m_widget), wasUnderlined); + const bool isUnderlined = GetFont().GetUnderlined(); + const bool isStrickenThrough = GetFont().GetStrikethrough(); - if ( wasUnderlined ) - { - // it's not underlined any more, remove the attributes we set - gtk_label_set_attributes(GTK_LABEL(m_widget), NULL); - } - else // the text is underlined now + if ( (isUnderlined != wasUnderlined) || + (isStrickenThrough != wasStrickenThrough) ) + { + // We need to update the Pango attributes used for the text. + if ( isUnderlined || isStrickenThrough ) { - PangoAttrList *attrs = pango_attr_list_new(); - PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); - a->start_index = 0; - a->end_index = (guint)-1; - pango_attr_list_insert(attrs, a); + PangoAttrList* const attrs = pango_attr_list_new(); + if ( isUnderlined ) + { + PangoAttribute *a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE); + a->start_index = 0; + a->end_index = (guint)-1; + pango_attr_list_insert(attrs, a); + } + + if ( isStrickenThrough ) + { + PangoAttribute *a = pango_attr_strikethrough_new( TRUE ); + a->start_index = 0; + a->end_index = (guint) -1; + pango_attr_list_insert(attrs, a); + } + gtk_label_set_attributes(GTK_LABEL(m_widget), attrs); pango_attr_list_unref(attrs); } + else // No special attributes any more. + { + // Just remove any attributes we had set. + gtk_label_set_attributes(GTK_LABEL(m_widget), NULL); + } + + // The underlines for mnemonics are incompatible with using attributes + // so turn them off when setting underlined font. + gtk_label_set_use_underline(GTK_LABEL(m_widget), !isUnderlined); } // adjust the label size to the new label unless disabled diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index 6920e299b6..8a39558799 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -110,6 +110,18 @@ static void wxGtkTextApplyTagsFromAttr(GtkWidget *text, NULL ); gtk_text_buffer_apply_tag (text_buffer, tag, start, end); } + if ( font.GetStrikethrough() ) + { + g_snprintf(buf, sizeof(buf), "WXFONTSTRIKETHROUGH"); + tag = gtk_text_tag_table_lookup( gtk_text_buffer_get_tag_table( text_buffer ), + buf ); + if (!tag) + tag = gtk_text_buffer_create_tag( text_buffer, buf, + "strikethrough-set", TRUE, + "strikethrough", TRUE, + NULL ); + gtk_text_buffer_apply_tag (text_buffer, tag, start, end); + } } if (attr.HasTextColour()) diff --git a/src/msw/font.cpp b/src/msw/font.cpp index 72294a58b1..b0e73148cb 100644 --- a/src/msw/font.cpp +++ b/src/msw/font.cpp @@ -63,7 +63,7 @@ public: wxFontRefData() { Init(-1, wxSize(0,0), false, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, - wxFONTWEIGHT_NORMAL, false, wxEmptyString, + wxFONTWEIGHT_NORMAL, false, false, wxEmptyString, wxFONTENCODING_DEFAULT); } @@ -74,11 +74,12 @@ public: wxFontStyle style, wxFontWeight weight, bool underlined, + bool strikethrough, const wxString& faceName, wxFontEncoding encoding) { Init(size, pixelSize, sizeUsingPixels, family, style, weight, - underlined, faceName, encoding); + underlined, strikethrough, faceName, encoding); } wxFontRefData(const wxNativeFontInfo& info, WXHFONT hFont = 0) @@ -134,6 +135,11 @@ public: return m_nativeFontInfo.GetUnderlined(); } + bool GetStrikethrough() const + { + return m_nativeFontInfo.GetStrikethrough(); + } + wxString GetFaceName() const { wxString facename = m_nativeFontInfo.GetFaceName(); @@ -225,6 +231,13 @@ public: m_nativeFontInfo.SetUnderlined(underlined); } + void SetStrikethrough(bool strikethrough) + { + Free(); + + m_nativeFontInfo.SetStrikethrough(strikethrough); + } + void SetEncoding(wxFontEncoding encoding) { Free(); @@ -262,6 +275,7 @@ protected: wxFontStyle style, wxFontWeight weight, bool underlined, + bool strikethrough, const wxString& faceName, wxFontEncoding encoding); @@ -336,6 +350,7 @@ void wxFontRefData::Init(int pointSize, wxFontStyle style, wxFontWeight weight, bool underlined, + bool strikethrough, const wxString& faceName, wxFontEncoding encoding) { @@ -350,6 +365,7 @@ void wxFontRefData::Init(int pointSize, SetStyle(style); SetWeight(weight); SetUnderlined(underlined); + SetStrikethrough(strikethrough); // set the family/facename SetFamily(family); @@ -463,6 +479,11 @@ bool wxNativeFontInfo::GetUnderlined() const return lf.lfUnderline != 0; } +bool wxNativeFontInfo::GetStrikethrough() const +{ + return lf.lfStrikeOut != 0; +} + wxString wxNativeFontInfo::GetFaceName() const { return lf.lfFaceName; @@ -583,6 +604,11 @@ void wxNativeFontInfo::SetUnderlined(bool underlined) lf.lfUnderline = underlined; } +void wxNativeFontInfo::SetStrikethrough(bool strikethrough) +{ + lf.lfStrikeOut = strikethrough; +} + bool wxNativeFontInfo::SetFaceName(const wxString& facename) { wxStrlcpy(lf.lfFaceName, facename.c_str(), WXSIZEOF(lf.lfFaceName)); @@ -789,7 +815,7 @@ wxFont::wxFont(int pointSize, GetStyleFromFlags(flags), GetWeightFromFlags(flags), GetUnderlinedFromFlags(flags), - face, encoding); + false, face, encoding); } bool wxFont::Create(const wxNativeFontInfo& info, WXHFONT hFont) @@ -822,7 +848,7 @@ bool wxFont::DoCreate(int pointSize, m_refData = new wxFontRefData(pointSize, pixelSize, sizeUsingPixels, family, style, weight, - underlined, faceName, encoding); + underlined, false, faceName, encoding); return RealizeResource(); } @@ -944,6 +970,13 @@ void wxFont::SetUnderlined(bool underlined) M_FONTDATA->SetUnderlined(underlined); } +void wxFont::SetStrikethrough(bool strikethrough) +{ + AllocExclusive(); + + M_FONTDATA->SetStrikethrough(strikethrough); +} + void wxFont::SetEncoding(wxFontEncoding encoding) { AllocExclusive(); @@ -1009,6 +1042,13 @@ bool wxFont::GetUnderlined() const return M_FONTDATA->GetUnderlined(); } +bool wxFont::GetStrikethrough() const +{ + wxCHECK_MSG( IsOk(), false, wxT("invalid font") ); + + return M_FONTDATA->GetStrikethrough(); +} + wxString wxFont::GetFaceName() const { wxCHECK_MSG( IsOk(), wxEmptyString, wxT("invalid font") ); -- 2.45.2