X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2796f657c95eb1e96b9fbd2efd9eed9c6dacccbc..26af4dbd0a733de7df04c50acde5b4747f7fff24:/src/gtk/dcclient.cpp diff --git a/src/gtk/dcclient.cpp b/src/gtk/dcclient.cpp index 06b60cd000..7d8b303bc6 100644 --- a/src/gtk/dcclient.cpp +++ b/src/gtk/dcclient.cpp @@ -17,22 +17,21 @@ #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/image.h" -#include "wx/module.h" #include "wx/fontutil.h" +#include "wx/scrolwin.h" #include "wx/gtk/win_gtk.h" #include "wx/gtk/private.h" -#include #include -#include -#include //----------------------------------------------------------------------------- // local defines @@ -82,6 +81,7 @@ static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } #include "gdk/gdkprivate.h" +static void gdk_wx_draw_bitmap(GdkDrawable *drawable, GdkGC *gc, GdkDrawable *src, @@ -324,6 +324,45 @@ 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 + + int scroll_lines = 0; + int scroll_step = 0; + + // Are we using scrolling? + wxScrollHelper *sh = (wxScrollHelper*) m_owner->GetScrollHelper(); + if (sh) + { + scroll_lines = sh->GetScrollLines(wxHORIZONTAL); + sh->GetScrollPixelsPerUnit( &scroll_step, NULL ); + } + + if (scroll_lines == 0) + { + int client_width = m_owner->GetClientSize().x; + m_deviceOriginX = client_width; + } + else + { + // We cannot use just the virtual size here, because + // the virtual size may be less than the visible area + // due to rounding errors of the scroll steps. If the + // horizontal scroll step is 10 pixels and the virtual + // area is 97 pixels, we should be able to see or scroll + // to 100 pixels, so the origin is at -100, not -97. + int client_width = sh->GetTargetWindow()->GetClientSize().x; + int virtual_size = m_owner->GetVirtualSize().x; + int steps = (virtual_size + scroll_step - 1) / scroll_step; + int width = steps * scroll_step + (client_width % scroll_step); + m_deviceOriginX = width; + } + } } wxWindowDC::~wxWindowDC() @@ -662,49 +701,30 @@ void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord if (n <= 0) return; //Check, if scaling is necessary - bool doScale(true); - long val(10); - if (!xoffset) - if (!yoffset) - if (XLOG2DEV(val)==val) - if (YLOG2DEV(val)==val) - doScale = false; + const bool doScale = + xoffset != 0 || yoffset != 0 || XLOG2DEV(10) != 10 || YLOG2DEV(10) != 10; - GdkPoint *gpts = NULL; + // GdkPoint and wxPoint have the same memory layout, so we can cast one to the other + GdkPoint* gpts = reinterpret_cast(points); - if (doScale){ + if (doScale) gpts = new GdkPoint[n]; - if (! gpts) - { - wxFAIL_MSG( wxT("Cannot allocate PolyLine") ); - return; - } for (int i = 0; i < n; i++) { - wxCoord x1 = XLOG2DEV(points[i].x + xoffset); - wxCoord y1 = YLOG2DEV(points[i].y + yoffset); - - CalcBoundingBox( x1 + xoffset, y1 + yoffset ); - - gpts[i].x = x1; - gpts[i].y = y1; - } - } - else { - for (int i = 0; i < n; i++) { - CalcBoundingBox( points[i].x, points[i].y ); + if (doScale) + { + gpts[i].x = XLOG2DEV(points[i].x + xoffset); + gpts[i].y = YLOG2DEV(points[i].y + yoffset); } - - //GdkPoint and wxPoint have the same memory allignment, so we can cast one into another - gpts = reinterpret_cast(points); + CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset); } if (m_window) gdk_draw_lines( m_window, m_penGC, gpts, n); if (doScale) - delete[] gpts; + delete[] gpts; } void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset, int WXUNUSED(fillStyle) ) @@ -714,46 +734,28 @@ void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoor if (n <= 0) return; //Check, if scaling is necessary - bool doScale(true); - long val(10); - if (!xoffset) - if (!yoffset) - if (XLOG2DEV(val)==val) - if (YLOG2DEV(val)==val){ - doScale = false; - } + const bool doScale = + xoffset != 0 || yoffset != 0 || XLOG2DEV(10) != 10 || YLOG2DEV(10) != 10; - GdkPoint *gdkpoints = NULL; + // GdkPoint and wxPoint have the same memory layout, so we can cast one to the other + GdkPoint* gdkpoints = reinterpret_cast(points); - if (doScale){ - gdkpoints = new GdkPoint[n+1]; //FIXME: Why the "+1" + if (doScale) + gdkpoints = new GdkPoint[n]; int i; for (i = 0 ; i < n ; i++) { - gdkpoints[i].x = XLOG2DEV(points[i].x + xoffset); - gdkpoints[i].y = YLOG2DEV(points[i].y + yoffset); - - CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset ); - } - } - else { - int i(0); - for (; i < n ; ++i) { - CalcBoundingBox( points[i].x, points[i].y ); + if (doScale) + { + gdkpoints[i].x = XLOG2DEV(points[i].x + xoffset); + gdkpoints[i].y = YLOG2DEV(points[i].y + yoffset); } - //GdkPoint and wxPoint have the same memory allignment, so we can cast one into another - gdkpoints = reinterpret_cast (points); + CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset); } if (m_window) { - //I think wxSOLID is the most often used style (it is for me), - //so I put it in front of the if ... ifelse's - if (m_brush.GetStyle() == wxSOLID) - { - gdk_draw_polygon( m_window, m_brushGC, TRUE, gdkpoints, n ); - }else if (m_brush.GetStyle() != wxTRANSPARENT) { if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask())) @@ -808,7 +810,7 @@ void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoor } if (doScale) - delete[] gdkpoints; + delete[] gdkpoints; } void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height ) @@ -1077,7 +1079,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 ); @@ -1110,11 +1115,14 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, // apply mask if any GdkBitmap *mask = (GdkBitmap *) NULL; - if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); + if (useMask && use_bitmap.GetMask()) + mask = use_bitmap.GetMask()->GetBitmap(); + + GdkGC* use_gc = is_mono ? m_textGC : m_penGC; GdkBitmap *new_mask = (GdkBitmap*) NULL; - if (useMask && mask) + if (mask != NULL) { if (!m_currentClippingRegion.IsNull()) { @@ -1133,25 +1141,12 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED ); gdk_gc_set_stipple( gc, mask ); gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh ); + mask = new_mask; g_object_unref (gc); } - if (is_mono) - { - if (new_mask) - gdk_gc_set_clip_mask( m_textGC, new_mask ); - else - gdk_gc_set_clip_mask( m_textGC, mask ); - gdk_gc_set_clip_origin( m_textGC, xx, yy ); - } - else - { - if (new_mask) - gdk_gc_set_clip_mask( m_penGC, new_mask ); - else - gdk_gc_set_clip_mask( m_penGC, mask ); - gdk_gc_set_clip_origin( m_penGC, xx, yy ); - } + gdk_gc_set_clip_mask(use_gc, mask); + gdk_gc_set_clip_origin(use_gc, xx, yy); } // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For @@ -1164,7 +1159,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, gdk_gc_set_background( gc, m_textBackgroundColour.GetColor() ); gdk_wx_draw_bitmap( bitmap2, gc, use_bitmap.GetPixmap(), 0, 0, 0, 0, -1, -1 ); - gdk_draw_drawable( m_window, m_textGC, bitmap2, 0, 0, xx, yy, -1, -1 ); + gdk_draw_drawable(m_window, use_gc, bitmap2, 0, 0, xx, yy, -1, -1); g_object_unref (bitmap2); g_object_unref (gc); @@ -1174,7 +1169,7 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, #if GTK_CHECK_VERSION(2,2,0) if (!gtk_check_version(2,2,0) && use_bitmap.HasPixbuf()) { - gdk_draw_pixbuf(m_window, m_penGC, + gdk_draw_pixbuf(m_window, use_gc, use_bitmap.GetPixbuf(), 0, 0, xx, yy, -1, -1, GDK_RGB_DITHER_NORMAL, xx, yy); @@ -1182,33 +1177,22 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap, else #endif { - gdk_draw_drawable(m_window, m_penGC, + gdk_draw_drawable(m_window, use_gc, use_bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1); } } // remove mask again if any - if (useMask && mask) + if (mask != NULL) { - if (is_mono) - { - gdk_gc_set_clip_mask( m_textGC, (GdkBitmap *) NULL ); - gdk_gc_set_clip_origin( m_textGC, 0, 0 ); - if (!m_currentClippingRegion.IsNull()) - gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() ); - } - else - { - gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL ); - gdk_gc_set_clip_origin( m_penGC, 0, 0 ); - if (!m_currentClippingRegion.IsNull()) - gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() ); - } + gdk_gc_set_clip_mask(use_gc, NULL); + gdk_gc_set_clip_origin(use_gc, 0, 0); + if (!m_currentClippingRegion.IsNull()) + gdk_gc_set_clip_region(use_gc, m_currentClippingRegion.GetRegion()); + if (new_mask != NULL) + g_object_unref(new_mask); } - - if (new_mask) - g_object_unref (new_mask); } bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, @@ -1226,8 +1210,8 @@ 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); + xsrc = source->LogicalToDeviceX(xsrc); + ysrc = source->LogicalToDeviceY(ysrc); wxClientDC *srcDC = (wxClientDC*)source; wxMemoryDC *memDC = (wxMemoryDC*)source; @@ -1277,10 +1261,6 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, // the area to be scaled use_bitmap_method = true; } - else - { - use_bitmap_method = false; - } } CalcBoundingBox( xdest, ydest ); @@ -1330,7 +1310,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord bm_hh = YLOG2DEVREL( bm_height ); // Scale bitmap if required - wxBitmap use_bitmap; + wxBitmap use_bitmap = memDC->m_selected; if ((memDC->m_selected.GetWidth()!= bm_ww) || ( memDC->m_selected.GetHeight()!= bm_hh)) { // This indicates that the blitting code below will get @@ -1343,19 +1323,17 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, // Scale and clipped bitmap use_bitmap = memDC->m_selected.Rescale(cx-xx,cy-yy,cw,ch,bm_ww,bm_hh); } - else - { - // Don't scale bitmap - use_bitmap = memDC->m_selected; - } // apply mask if any GdkBitmap *mask = (GdkBitmap *) NULL; - if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap(); + if (useMask && use_bitmap.GetMask()) + mask = use_bitmap.GetMask()->GetBitmap(); + + GdkGC* use_gc = is_mono ? m_textGC : m_penGC; GdkBitmap *new_mask = (GdkBitmap*) NULL; - if (useMask && mask) + if (mask != NULL) { if (!m_currentClippingRegion.IsNull()) { @@ -1376,35 +1354,15 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, gdk_gc_set_fill( gc, GDK_OPAQUE_STIPPLED ); gdk_gc_set_stipple( gc, mask ); gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh ); + mask = new_mask; g_object_unref (gc); } - if (is_mono) - { - if (new_mask) - { - gdk_gc_set_clip_mask( m_textGC, new_mask ); - gdk_gc_set_clip_origin( m_textGC, cx, cy ); - } - else - { - gdk_gc_set_clip_mask( m_textGC, mask ); - gdk_gc_set_clip_origin( m_textGC, cx-xsrcMask, cy-ysrcMask ); - } - } + gdk_gc_set_clip_mask(use_gc, mask); + if (new_mask != NULL) + gdk_gc_set_clip_origin(use_gc, cx, cy); else - { - if (new_mask) - { - gdk_gc_set_clip_mask( m_penGC, new_mask ); - gdk_gc_set_clip_origin( m_penGC, cx, cy ); - } - else - { - gdk_gc_set_clip_mask( m_penGC, mask ); - gdk_gc_set_clip_origin( m_penGC, cx-xsrcMask, cy-ysrcMask ); - } - } + gdk_gc_set_clip_origin(use_gc, cx - xsrcMask, cy - ysrcMask); } // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For @@ -1418,7 +1376,7 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, gdk_gc_set_background( gc, m_textBackgroundColour.GetColor() ); gdk_wx_draw_bitmap( bitmap, gc, use_bitmap.GetPixmap(), 0, 0, 0, 0, -1, -1 ); - gdk_draw_drawable( m_window, m_textGC, bitmap, xsrc, ysrc, cx, cy, cw, ch ); + gdk_draw_drawable(m_window, use_gc, bitmap, xsrc, ysrc, cx, cy, cw, ch); g_object_unref (bitmap); g_object_unref (gc); @@ -1426,26 +1384,16 @@ bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest, else { // was: gdk_draw_drawable( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh ); - gdk_draw_drawable( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, cx, cy, cw, ch ); + gdk_draw_drawable(m_window, use_gc, use_bitmap.GetPixmap(), xsrc, ysrc, cx, cy, cw, ch); } // remove mask again if any - if (useMask && mask) + if (mask != NULL) { - if (is_mono) - { - gdk_gc_set_clip_mask( m_textGC, (GdkBitmap *) NULL ); - gdk_gc_set_clip_origin( m_textGC, 0, 0 ); - if (!m_currentClippingRegion.IsNull()) - gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() ); - } - else - { - gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL ); - gdk_gc_set_clip_origin( m_penGC, 0, 0 ); - if (!m_currentClippingRegion.IsNull()) - gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() ); - } + gdk_gc_set_clip_mask(use_gc, NULL); + gdk_gc_set_clip_origin(use_gc, 0, 0); + if (!m_currentClippingRegion.IsNull()) + gdk_gc_set_clip_region(use_gc, m_currentClippingRegion.GetRegion()); } if (new_mask) @@ -1546,7 +1494,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 ); @@ -1563,8 +1514,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) @@ -1762,10 +1717,8 @@ wxCoord wxWindowDC::GetCharWidth() const wxCoord wxWindowDC::GetCharHeight() const { - pango_layout_set_text( m_layout, "H", 1 ); - int h; - pango_layout_get_pixel_size( m_layout, NULL, &h ); - return h; + 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)); } void wxWindowDC::Clear() @@ -2199,6 +2152,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 @@ -2294,6 +2252,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);