X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/280831d5dddee274a37618fdfd15a166ef4df1fb..eec960fa8987d15fd87e249c8441474188124425:/src/gtk/dcclient.cpp diff --git a/src/gtk/dcclient.cpp b/src/gtk/dcclient.cpp index 7c724b05ae..fc66d7acdd 100644 --- a/src/gtk/dcclient.cpp +++ b/src/gtk/dcclient.cpp @@ -17,14 +17,16 @@ #include "wx/dcclient.h" #ifndef WX_PRECOMP + #include "wx/window.h" #include "wx/log.h" #include "wx/dcmemory.h" #include "wx/math.h" // for floating-point functions #include "wx/image.h" + #include "wx/module.h" #endif -#include "wx/module.h" #include "wx/fontutil.h" +#include "wx/scrolwin.h" #include "wx/gtk/win_gtk.h" #include "wx/gtk/private.h" @@ -322,6 +324,15 @@ wxWindowDC::wxWindowDC( wxWindow *window ) standard (as e.g. wxStatusBar) */ m_owner = window; + + if (m_owner && m_owner->m_wxwindow && (m_owner->GetLayoutDirection() == wxLayout_RightToLeft)) + { + // reverse sense + m_signX = -1; + + // origin in the upper right corner + m_deviceOriginX = m_owner->GetClientSize().x; + } } wxWindowDC::~wxWindowDC() @@ -571,8 +582,11 @@ void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, { gdk_draw_arc( m_window, m_penGC, FALSE, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 ); - gdk_draw_line( m_window, m_penGC, xx1, yy1, xxc, yyc ); - gdk_draw_line( m_window, m_penGC, xxc, yyc, xx2, yy2 ); + if ((m_brush.GetStyle() != wxTRANSPARENT) && (alpha2 - alpha1 != 360*64)) + { + gdk_draw_line( m_window, m_penGC, xx1, yy1, xxc, yyc ); + gdk_draw_line( m_window, m_penGC, xxc, yyc, xx2, yy2 ); + } } } @@ -827,7 +841,36 @@ void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord h } if (m_pen.GetStyle() != wxTRANSPARENT) - gdk_draw_rectangle( m_window, m_penGC, FALSE, xx, yy, ww-1, hh-1 ); + { +#if 1 + if ((m_pen.GetWidth() == 2) && (m_pen.GetCap() == wxCAP_ROUND) && + (m_pen.GetJoin() == wxJOIN_ROUND) && (m_pen.GetStyle() == wxSOLID)) + { + // Use 2 1-line rects instead + gdk_gc_set_line_attributes( m_penGC, 1, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND ); + + if (m_signX == -1) + { + // Different for RTL + gdk_draw_rectangle( m_window, m_penGC, FALSE, xx+1, yy, ww-2, hh-2 ); + gdk_draw_rectangle( m_window, m_penGC, FALSE, xx, yy-1, ww, hh ); + } + else + { + gdk_draw_rectangle( m_window, m_penGC, FALSE, xx, yy, ww-2, hh-2 ); + gdk_draw_rectangle( m_window, m_penGC, FALSE, xx-1, yy-1, ww, hh ); + } + + // reset + gdk_gc_set_line_attributes( m_penGC, 2, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND ); + } + else +#endif + { + // Just use X11 for other cases + gdk_draw_rectangle( m_window, m_penGC, FALSE, xx, yy, ww-1, hh-1 ); + } + } } CalcBoundingBox( x, y ); @@ -1038,7 +1081,10 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, int w = bitmap.GetWidth(); int h = bitmap.GetHeight(); - + + if (m_owner && m_owner->GetLayoutDirection() == wxLayout_RightToLeft) + xx -= w; + CalcBoundingBox( x, y ); CalcBoundingBox( x + w, y + h ); @@ -1166,12 +1212,12 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, if (!m_window) return false; // transform the source DC coords to the device ones - xsrc = source->XLOG2DEV(xsrc); - ysrc = source->YLOG2DEV(ysrc); - - wxClientDC *srcDC = (wxClientDC*)source; - wxMemoryDC *memDC = (wxMemoryDC*)source; + xsrc = source->LogicalToDeviceX(xsrc); + ysrc = source->LogicalToDeviceY(ysrc); + wxMemoryDC *memDC = wxDynamicCast(source, wxMemoryDC); + wxBitmap selected = source->GetSelectedBitmap(); + bool use_bitmap_method = false; bool is_mono = false; @@ -1181,11 +1227,11 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, ysrcMask = ysrc; } - if (srcDC->m_isMemDC) + if (memDC && !selected.Ok()) return false; + + if (selected.Ok()) { - if (!memDC->m_selected.Ok()) return false; - - is_mono = (memDC->m_selected.GetDepth() == 1); + is_mono = (selected.GetDepth() == 1); // we use the "XCopyArea" way to copy a memory dc into // a different window if the memory dc BOTH @@ -1193,7 +1239,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, // b) it is clipped // c) is not 1-bit - if (useMask && (memDC->m_selected.GetMask())) + if (useMask && (selected.GetMask())) { // we HAVE TO use the direct way for memory dcs // that have mask since the XCopyArea doesn't know @@ -1208,8 +1254,8 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, use_bitmap_method = true; } else if ((xsrc == 0) && (ysrc == 0) && - (width == memDC->m_selected.GetWidth()) && - (height == memDC->m_selected.GetHeight())) + (width == selected.GetWidth()) && + (height == selected.GetHeight())) { // we SHOULD use the direct way if all of the bitmap // in the memory dc is copied in which case XCopyArea @@ -1244,8 +1290,8 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, if (use_bitmap_method) { // scale/translate bitmap size - wxCoord bm_width = memDC->m_selected.GetWidth(); - wxCoord bm_height = memDC->m_selected.GetHeight(); + wxCoord bm_width = selected.GetWidth(); + wxCoord bm_height = selected.GetHeight(); // Get clip coords for the bitmap. If we don't // use wxBitmap::Rescale(), which can clip the @@ -1266,8 +1312,8 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord bm_hh = YLOG2DEVREL( bm_height ); // Scale bitmap if required - wxBitmap use_bitmap = memDC->m_selected; - if ((memDC->m_selected.GetWidth()!= bm_ww) || ( memDC->m_selected.GetHeight()!= bm_hh)) + wxBitmap use_bitmap = selected; + if ((selected.GetWidth()!= bm_ww) || ( selected.GetHeight()!= bm_hh)) { // This indicates that the blitting code below will get // a clipped bitmap and therefore needs to move the origin @@ -1277,7 +1323,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, tmp.GetBox(cx,cy,cw,ch); // Scale and clipped bitmap - use_bitmap = memDC->m_selected.Rescale(cx-xx,cy-yy,cw,ch,bm_ww,bm_hh); + use_bitmap = selected.Rescale(cx-xx,cy-yy,cw,ch,bm_ww,bm_hh); } // apply mask if any @@ -1357,7 +1403,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, } else // use_bitmap_method { - if ((width != ww) || (height != hh)) + if (selected.Ok() && ((width != ww) || (height != hh))) { // get clip coords wxRegion tmp( xx,yy,ww,hh ); @@ -1366,7 +1412,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, tmp.GetBox(cx,cy,cw,ch); // rescale bitmap - wxBitmap bitmap = memDC->m_selected.Rescale( cx-xx, cy-yy, cw, ch, ww, hh ); + wxBitmap bitmap = selected.Rescale( cx-xx, cy-yy, cw, ch, ww, hh ); // draw scaled bitmap // was: gdk_draw_drawable( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); @@ -1376,10 +1422,14 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, { // No scaling and not a memory dc with a mask either + GdkWindow* window = source->GetGDKWindow(); + if ( !window ) + return false; + // copy including child window contents gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS ); gdk_draw_drawable( m_window, m_penGC, - srcDC->GetWindow(), + window, xsrc, ysrc, xx, yy, width, height ); gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN ); @@ -1406,13 +1456,53 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) wxCHECK_RET( m_layout, wxT("no Pango layout") ); wxCHECK_RET( m_fontdesc, wxT("no Pango font description") ); + gdk_pango_context_set_colormap( m_context, m_cmap ); + bool underlined = m_font.Ok() && m_font.GetUnderlined(); const wxCharBuffer data = wxGTK_CONV( text ); if ( !data ) return; - const size_t datalen = strlen(data); - pango_layout_set_text( m_layout, data, datalen); + size_t datalen = strlen(data); + + // TODO: as soon as Pango provides a function to check at runtime its + // version, we can use it to disable the underline hack for + // Pango >= 1.16 as the "underline of leading/trailing spaces" + // has been fixed there + bool needshack = underlined; + char *hackstring = NULL; + + 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. + + // need to realloc the string to prepend & append our special characters + hackstring = (char*)malloc((datalen+7)*sizeof(char)); + + // copy the leading U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format + strcpy(hackstring, "\342\200\214"); + + // copy the user string + memcpy(&hackstring[3], data, datalen); + + // copy the trailing U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format + strcpy(&hackstring[datalen+3], "\342\200\214"); + + // the special characters that we added require 6 additional bytes: + datalen += 6; + + pango_layout_set_text(m_layout, hackstring, datalen); + } + else + { + pango_layout_set_text(m_layout, data, datalen); + } if (underlined) { @@ -1421,6 +1511,22 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) 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); } @@ -1450,7 +1556,10 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) } // Draw layout. - gdk_draw_layout( m_window, m_textGC, x, y, m_layout ); + if (m_owner && m_owner->GetLayoutDirection() == wxLayout_RightToLeft) + gdk_draw_layout( m_window, m_textGC, x-w, y, m_layout ); + else + gdk_draw_layout( m_window, m_textGC, x, y, m_layout ); // reset unscaled size pango_font_description_set_size( m_fontdesc, oldSize ); @@ -1467,8 +1576,12 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) gdk_draw_rectangle(m_window, m_textGC, TRUE, x, y, w, h); gdk_gc_set_foreground(m_textGC, m_textForegroundColour.GetColor()); } + // Draw layout. - gdk_draw_layout( m_window, m_textGC, x, y, m_layout ); + if (m_owner && m_owner->GetLayoutDirection() == wxLayout_RightToLeft) + gdk_draw_layout( m_window, m_textGC, x-w, y, m_layout ); + else + gdk_draw_layout( m_window, m_textGC, x, y, m_layout ); } if (underlined) @@ -1484,6 +1597,9 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y ) height = wxCoord(height / m_scaleY); CalcBoundingBox (x + width, y + height); CalcBoundingBox (x, y); + + if (hackstring) + free(hackstring); } @@ -1666,7 +1782,7 @@ wxCoord wxWindowDC::GetCharWidth() const wxCoord wxWindowDC::GetCharHeight() const { - PangoFontMetrics *metrics = pango_context_get_metrics (m_context, m_fontdesc, NULL); + PangoFontMetrics *metrics = pango_context_get_metrics (m_context, m_fontdesc, pango_context_get_language(m_context)); return PANGO_PIXELS (pango_font_metrics_get_descent (metrics) + pango_font_metrics_get_ascent (metrics)); } @@ -2101,6 +2217,11 @@ void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoo rect.width = XLOG2DEVREL(width); rect.height = YLOG2DEVREL(height); + if (m_owner && m_owner->m_wxwindow && (m_owner->GetLayoutDirection() == wxLayout_RightToLeft)) + { + rect.x -= rect.width; + } + if (!m_currentClippingRegion.IsNull()) m_currentClippingRegion.Intersect( rect ); else @@ -2196,6 +2317,25 @@ void wxWindowDC::Destroy() m_bgGC = (GdkGC*) NULL; } +void wxWindowDC::SetDeviceOrigin( wxCoord x, wxCoord y ) +{ + m_deviceOriginX = x; + m_deviceOriginY = y; + + ComputeScaleAndOrigin(); +} + +void wxWindowDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp ) +{ + m_signX = (xLeftRight ? 1 : -1); + m_signY = (yBottomUp ? -1 : 1); + + if (m_owner && m_owner->m_wxwindow && (m_owner->GetLayoutDirection() == wxLayout_RightToLeft)) + m_signX = -m_signX; + + ComputeScaleAndOrigin(); +} + void wxWindowDC::ComputeScaleAndOrigin() { const wxRealPoint origScale(m_scaleX, m_scaleY); @@ -2258,7 +2398,7 @@ wxPaintDC::wxPaintDC( wxWindow *win ) return; wxSize sz = win->GetSize(); - m_paintClippingRegion = win->GetUpdateRegion(); + m_paintClippingRegion = win->m_nativeUpdateRegion; wxLimitRegionToSize(m_paintClippingRegion, sz); GdkRegion *region = m_paintClippingRegion.GetRegion();