move Pango underline workaround into wxFont::GTKSetPangoAttrs

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@70476 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Paul Cornett 2012-01-29 08:14:34 +00:00
parent c7e99122a0
commit 99f8cf22db
3 changed files with 38 additions and 65 deletions

View File

@ -104,16 +104,12 @@ public:
wxDECLARE_COMMON_FONT_METHODS();
// Set Pango attributes for the span 0..len (or
// without any bounds if len == 0) in the specified layout. Currently only
// Set Pango attributes 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.
bool GTKSetPangoAttrs(PangoLayout* layout, size_t len = 0, bool addDummyAttrs = false) const;
bool GTKSetPangoAttrs(PangoLayout* layout) const;
// implementation from now on
void Unshare();

View File

@ -1372,44 +1372,12 @@ void wxWindowDCImpl::DoDrawText(const wxString& text,
gdk_pango_context_set_colormap( m_context, m_cmap ); // not needed in gtk+ >= 2.6
bool underlined = m_font.IsOk() && m_font.GetUnderlined();
wxCharBuffer data = wxGTK_CONV(text);
if ( !data )
return;
size_t datalen = strlen(data);
// in Pango >= 1.16 the "underline of leading/trailing spaces" bug
// has been fixed and thus the hack implemented below should never be used
static bool pangoOk = !wx_pango_version_check(1, 16, 0);
bool needshack = underlined && !pangoOk;
if (needshack)
{
// a PangoLayout which has leading/trailing spaces with underlined font
// is not correctly drawn by this pango version: Pango won't underline the spaces.
// This can be a problem; e.g. wxHTML rendering of underlined text relies on
// this behaviour. To workaround this problem, we use a special hack here
// suggested by pango maintainer Behdad Esfahbod: we prepend and append two
// empty space characters and give them a dummy colour attribute.
// This will force Pango to underline the leading/trailing spaces, too.
wxCharBuffer data_tmp(datalen + 6);
// copy the leading U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format
memcpy(data_tmp.data(), "\342\200\214", 3);
// copy the user string
memcpy(data_tmp.data() + 3, data, datalen);
// copy the trailing U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format
memcpy(data_tmp.data() + 3 + datalen, "\342\200\214", 3);
data = data_tmp;
datalen += 6;
}
pango_layout_set_text(m_layout, data, datalen);
const bool
setAttrs = m_font.GTKSetPangoAttrs(m_layout, datalen, needshack);
pango_layout_set_text(m_layout, data, data.length());
const bool setAttrs = m_font.GTKSetPangoAttrs(m_layout);
int oldSize = 0;
const bool isScaled = fabs(m_scaleY - 1.0) > 0.00001;
@ -1474,7 +1442,7 @@ void wxWindowDCImpl::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord
y = YLOG2DEV(y);
pango_layout_set_text(m_layout, wxGTK_CONV(text), -1);
m_font.GTKSetPangoAttrs(m_layout);
const bool setAttrs = m_font.GTKSetPangoAttrs(m_layout);
int oldSize = 0;
const bool isScaled = fabs(m_scaleY - 1.0) > 0.00001;
if (isScaled)
@ -1527,7 +1495,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() || m_font.GetStrikethrough())
if (setAttrs)
pango_layout_set_attributes(m_layout, NULL);
// clean up the transformation matrix

View File

@ -488,7 +488,7 @@ wxGDIRefData* wxFont::CloneGDIRefData(const wxGDIRefData* data) const
return new wxFontRefData(*static_cast<const wxFontRefData*>(data));
}
bool wxFont::GTKSetPangoAttrs(PangoLayout* layout, size_t len, bool addDummyAttrs) const
bool wxFont::GTKSetPangoAttrs(PangoLayout* layout) const
{
if (!IsOk() || !(GetUnderlined() || GetStrikethrough()))
return false;
@ -496,43 +496,52 @@ bool wxFont::GTKSetPangoAttrs(PangoLayout* layout, size_t len, bool addDummyAttr
PangoAttrList* attrs = pango_attr_list_new();
PangoAttribute* a;
if (GetUnderlined())
if (wx_pango_version_check(1,16,0))
{
a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
if (len)
{
a->start_index = 0;
a->end_index = len;
}
pango_attr_list_insert(attrs, a);
// a PangoLayout which has leading/trailing spaces with underlined font
// is not correctly drawn by this pango version: Pango won't underline the spaces.
// This can be a problem; e.g. wxHTML rendering of underlined text relies on
// this behaviour. To workaround this problem, we use a special hack here
// suggested by pango maintainer Behdad Esfahbod: we prepend and append two
// empty space characters and give them a dummy colour attribute.
// This will force Pango to underline the leading/trailing spaces, too.
// 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 )
const char* text = pango_layout_get_text(layout);
const size_t n = strlen(text);
if ((n > 0 && text[0] == ' ') || (n > 1 && text[n - 1] == ' '))
{
wxASSERT_MSG( len > 2, "Must have 0-width spaces at string ends" );
wxCharBuffer buf(n + 6);
// copy the leading U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format
memcpy(buf.data(), "\342\200\214", 3);
// copy the user string
memcpy(buf.data() + 3, text, n);
// copy the trailing U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format
memcpy(buf.data() + 3 + n, "\342\200\214", 3);
pango_layout_set_text(layout, buf, n + 6);
// 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.
a = pango_attr_foreground_new(0x0057, 0x52A9, 0xD614);
a->start_index = 0;
a->end_index = 1;
a->end_index = 3;
pango_attr_list_insert(attrs, a);
a = pango_attr_foreground_new(0x0057, 0x52A9, 0xD614);
a->start_index = len - 1;
a->end_index = len;
a->start_index = n + 3;
a->end_index = n + 6;
pango_attr_list_insert(attrs, a);
}
}
if (GetUnderlined())
{
a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
pango_attr_list_insert(attrs, a);
}
if (GetStrikethrough())
{
a = pango_attr_strikethrough_new(true);
if (len)
{
a->start_index = 0;
a->end_index = len;
}
pango_attr_list_insert(attrs, a);
}