]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk1/dcclient.cpp
iconv() really never set the trailing 0.
[wxWidgets.git] / src / gtk1 / dcclient.cpp
index e75b32227e5021fa9c32cca13b6f4a49e429a3ea..2b469dfbea42e5f0efd4d12f513d9456b082feb7 100644 (file)
@@ -1,23 +1,41 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        dcclient.cpp
+// Name:        gtk/dcclient.cpp
 // Purpose:
 // Author:      Robert Roebling
 // RCS-ID:      $Id$
 // Copyright:   (c) 1998 Robert Roebling, Markus Holzem, Chris Breeze
-// Licence:           wxWindows licence
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 #ifdef __GNUG__
 #pragma implementation "dcclient.h"
 #endif
 
+#ifdef __VMS
+#define XCopyPlane XCOPYPLANE
+#endif
+
 #include "wx/dcclient.h"
 #include "wx/dcmemory.h"
 #include "wx/image.h"
+#include "wx/module.h"
+#include "wx/log.h"
+#include "wx/fontutil.h"
+
+#include "wx/gtk/win_gtk.h"
+
 #include <math.h>               // for floating-point functions
 
-#include "gdk/gdk.h"
-#include "gtk/gtk.h"
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkprivate.h>
+#include <gtk/gtk.h>
+
+//-----------------------------------------------------------------------------
+// local defines
+//-----------------------------------------------------------------------------
+
+#define USE_PAINT_REGION 1
 
 //-----------------------------------------------------------------------------
 // local data
 #include "cross.xbm"
 #define  num_hatches 6
 
+#define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH)
+#define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH)
+
+
 static GdkPixmap  *hatches[num_hatches];
 static GdkPixmap **hatch_bitmap = (GdkPixmap **) NULL;
 
+extern GtkWidget *wxGetRootWindow();
+
 //-----------------------------------------------------------------------------
 // constants
 //-----------------------------------------------------------------------------
 
-#define RAD2DEG 57.2957795131
+const double RAD2DEG  = 180.0 / M_PI;
+
+// ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
+
+static inline double dmax(double a, double b) { return a > b ? a : b; }
+static inline double dmin(double a, double b) { return a < b ? a : b; }
+
+static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
 
 //-----------------------------------------------------------------------------
 // temporary implementation of the missing GDK function
@@ -46,34 +79,57 @@ static GdkPixmap **hatch_bitmap = (GdkPixmap **) NULL;
 
 #include "gdk/gdkprivate.h"
 
-void gdk_draw_bitmap     (GdkDrawable  *drawable,
-                          GdkGC               *gc,
-                          GdkDrawable  *src,
-                          gint                xsrc,
-                          gint                ysrc,
-                          gint                xdest,
-                          gint                ydest,
-                          gint                width,
-                          gint                height)
+void gdk_wx_draw_bitmap(GdkDrawable  *drawable,
+                        GdkGC        *gc,
+                        GdkDrawable  *src,
+                        gint         xsrc,
+                        gint         ysrc,
+                        gint         xdest,
+                        gint         ydest,
+                        gint         width,
+                        gint         height)
 {
+    gint src_width, src_height;
+#ifndef __WXGTK20__
     GdkWindowPrivate *drawable_private;
     GdkWindowPrivate *src_private;
     GdkGCPrivate *gc_private;
+#endif
 
     g_return_if_fail (drawable != NULL);
     g_return_if_fail (src != NULL);
     g_return_if_fail (gc != NULL);
 
+#ifdef __WXGTK20__
+    if (GDK_WINDOW_DESTROYED(drawable) || GDK_WINDOW_DESTROYED(src))
+        return;
+
+    gdk_drawable_get_size(src, &src_width, &src_height);
+#else
     drawable_private = (GdkWindowPrivate*) drawable;
     src_private = (GdkWindowPrivate*) src;
     if (drawable_private->destroyed || src_private->destroyed)
         return;
 
+    src_width = src_private->width;
+    src_height = src_private->height;
+
     gc_private = (GdkGCPrivate*) gc;
+#endif
 
-    if (width == -1) width = src_private->width;
-    if (height == -1) height = src_private->height;
+    if (width == -1) width = src_width;
+    if (height == -1) height = src_height;
 
+#ifdef __WXGTK20__
+    XCopyPlane( GDK_WINDOW_XDISPLAY(drawable),
+                GDK_WINDOW_XID(src),
+                GDK_WINDOW_XID(drawable),
+                GDK_GC_XGC(gc),
+                xsrc, ysrc,
+                width, height,
+                xdest, ydest,
+                1 );
+#else
     XCopyPlane( drawable_private->xdisplay,
                 src_private->xwindow,
                 drawable_private->xwindow,
@@ -82,6 +138,146 @@ void gdk_draw_bitmap     (GdkDrawable  *drawable,
                 width, height,
                 xdest, ydest,
                 1 );
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Implement Pool of Graphic contexts. Creating them takes too much time.
+//-----------------------------------------------------------------------------
+
+#define GC_POOL_SIZE 200
+
+enum wxPoolGCType
+{
+   wxGC_ERROR = 0,
+   wxTEXT_MONO,
+   wxBG_MONO,
+   wxPEN_MONO,
+   wxBRUSH_MONO,
+   wxTEXT_COLOUR,
+   wxBG_COLOUR,
+   wxPEN_COLOUR,
+   wxBRUSH_COLOUR,
+   wxTEXT_SCREEN,
+   wxBG_SCREEN,
+   wxPEN_SCREEN,
+   wxBRUSH_SCREEN
+};
+
+struct wxGC
+{
+    GdkGC        *m_gc;
+    wxPoolGCType  m_type;
+    bool          m_used;
+};
+
+#define GC_POOL_ALLOC_SIZE 100
+
+static int wxGCPoolSize = 0;
+
+static wxGC *wxGCPool = NULL;
+
+static void wxInitGCPool()
+{
+    // This really could wait until the first call to
+    // wxGetPoolGC, but we will make the first allocation
+    // now when other initialization is being performed.
+    
+    // Set initial pool size.
+    wxGCPoolSize = GC_POOL_ALLOC_SIZE;
+    
+    // Allocate initial pool.
+    wxGCPool = (wxGC *)malloc(wxGCPoolSize * sizeof(wxGC));
+    if (wxGCPool == NULL)
+    {
+        // If we cannot malloc, then fail with error
+        // when debug is enabled.  If debug is not enabled,
+        // the problem will eventually get caught
+               // in wxGetPoolGC.
+        wxFAIL_MSG( wxT("Cannot allocate GC pool") );
+        return;
+    }
+    
+    // Zero initial pool.
+    memset(wxGCPool, 0, wxGCPoolSize * sizeof(wxGC));
+}
+
+static void wxCleanUpGCPool()
+{
+    for (int i = 0; i < wxGCPoolSize; i++)
+    {
+        if (wxGCPool[i].m_gc)
+            gdk_gc_unref( wxGCPool[i].m_gc );
+    }
+
+    free(wxGCPool);
+    wxGCPool = NULL;
+    wxGCPoolSize = 0;
+}
+
+static GdkGC* wxGetPoolGC( GdkWindow *window, wxPoolGCType type )
+{
+    wxGC *pptr;
+    
+    // Look for an available GC.
+    for (int i = 0; i < wxGCPoolSize; i++)
+    {
+        if (!wxGCPool[i].m_gc)
+        {
+            wxGCPool[i].m_gc = gdk_gc_new( window );
+            gdk_gc_set_exposures( wxGCPool[i].m_gc, FALSE );
+            wxGCPool[i].m_type = type;
+            wxGCPool[i].m_used = FALSE;
+        }
+        if ((!wxGCPool[i].m_used) && (wxGCPool[i].m_type == type))
+        {
+            wxGCPool[i].m_used = TRUE;
+            return wxGCPool[i].m_gc;
+        }
+    }
+
+    // We did not find an available GC.
+    // We need to grow the GC pool.
+    pptr = (wxGC *)realloc(wxGCPool,
+               (wxGCPoolSize + GC_POOL_ALLOC_SIZE)*sizeof(wxGC));
+    if (pptr != NULL)
+    {
+        // Initialize newly allocated pool.
+        wxGCPool = pptr;
+       memset(&wxGCPool[wxGCPoolSize], 0,
+                       GC_POOL_ALLOC_SIZE*sizeof(wxGC));
+    
+        // Initialize entry we will return.    
+        wxGCPool[wxGCPoolSize].m_gc = gdk_gc_new( window );
+        gdk_gc_set_exposures( wxGCPool[wxGCPoolSize].m_gc, FALSE );
+        wxGCPool[wxGCPoolSize].m_type = type;
+        wxGCPool[wxGCPoolSize].m_used = TRUE;
+        
+        // Set new value of pool size.
+        wxGCPoolSize += GC_POOL_ALLOC_SIZE;
+        
+        // Return newly allocated entry.
+        return wxGCPool[wxGCPoolSize-GC_POOL_ALLOC_SIZE].m_gc;
+    }
+    
+    // The realloc failed.  Fall through to error.
+    wxFAIL_MSG( wxT("No GC available") );
+
+    return (GdkGC*) NULL;
+}
+
+static void wxFreePoolGC( GdkGC *gc )
+{
+    for (int i = 0; i < wxGCPoolSize; i++)
+    {
+        if (wxGCPool[i].m_gc == gc)
+        {
+            wxGCPool[i].m_used = FALSE;
+            return;
+        }
+    }
+
+    wxFAIL_MSG( wxT("Wrong GC") );
 }
 
 //-----------------------------------------------------------------------------
@@ -98,11 +294,18 @@ wxWindowDC::wxWindowDC()
     m_bgGC = (GdkGC *) NULL;
     m_cmap = (GdkColormap *) NULL;
     m_isMemDC = FALSE;
+    m_isScreenDC = FALSE;
     m_owner = (wxWindow *)NULL;
+#ifdef __WXGTK20__
+    m_context = (PangoContext *)NULL;
+    m_fontdesc = (PangoFontDescription *)NULL;
+#endif
 }
 
 wxWindowDC::wxWindowDC( wxWindow *window )
 {
+    wxASSERT_MSG( window, wxT("DC needs a window") );
+
     m_penGC = (GdkGC *) NULL;
     m_brushGC = (GdkGC *) NULL;
     m_textGC = (GdkGC *) NULL;
@@ -110,15 +313,30 @@ wxWindowDC::wxWindowDC( wxWindow *window )
     m_cmap = (GdkColormap *) NULL;
     m_owner = (wxWindow *)NULL;
     m_isMemDC = FALSE;
+    m_isScreenDC = FALSE;
     m_font = window->GetFont();
 
-    wxASSERT_MSG( window, _T("DC needs a window") );
-
     GtkWidget *widget = window->m_wxwindow;
 
-    wxASSERT_MSG( widget, _T("DC needs a widget") );
+    // some controls don't have m_wxwindow - like wxStaticBox, but the user
+    // code should still be able to create wxClientDCs for them, so we will
+    // use the parent window here then
+    if ( !widget )
+    {
+        window = window->GetParent();
+        widget = window->m_wxwindow;
+    }
 
-    m_window = widget->window;
+    wxASSERT_MSG( widget, wxT("DC needs a widget") );
+
+#ifdef __WXGTK20__
+    m_context = gtk_widget_get_pango_context( widget );
+    
+    m_fontdesc = widget->style->font_desc;
+#endif
+
+    GtkPizza *pizza = GTK_PIZZA( widget );
+    m_window = pizza->bin_window;
 
     /* not realized ? */
     if (!m_window)
@@ -129,10 +347,7 @@ wxWindowDC::wxWindowDC( wxWindow *window )
          return;
     }
 
-    if (window->m_wxwindow)
-        m_cmap = gtk_widget_get_colormap( window->m_wxwindow );
-    else
-        m_cmap = gtk_widget_get_colormap( window->m_widget );
+    m_cmap = gtk_widget_get_colormap( widget ? widget : window->m_widget );
 
     SetUpDC();
 
@@ -151,21 +366,126 @@ wxWindowDC::~wxWindowDC()
     Destroy();
 }
 
-void wxWindowDC::DoFloodFill( long WXUNUSED(x), long WXUNUSED(y),
-                           const wxColour &WXUNUSED(col), int WXUNUSED(style) )
+void wxWindowDC::SetUpDC()
+{
+    m_ok = TRUE;
+
+    wxASSERT_MSG( !m_penGC, wxT("GCs already created") );
+
+    if (m_isScreenDC)
+    {
+        m_penGC = wxGetPoolGC( m_window, wxPEN_SCREEN );
+        m_brushGC = wxGetPoolGC( m_window, wxBRUSH_SCREEN );
+        m_textGC = wxGetPoolGC( m_window, wxTEXT_SCREEN );
+        m_bgGC = wxGetPoolGC( m_window, wxBG_SCREEN );
+    }
+    else
+    if (m_isMemDC && (((wxMemoryDC*)this)->m_selected.GetDepth() == 1))
+    {
+        m_penGC = wxGetPoolGC( m_window, wxPEN_MONO );
+        m_brushGC = wxGetPoolGC( m_window, wxBRUSH_MONO );
+        m_textGC = wxGetPoolGC( m_window, wxTEXT_MONO );
+        m_bgGC = wxGetPoolGC( m_window, wxBG_MONO );
+    }
+    else
+    {
+        m_penGC = wxGetPoolGC( m_window, wxPEN_COLOUR );
+        m_brushGC = wxGetPoolGC( m_window, wxBRUSH_COLOUR );
+        m_textGC = wxGetPoolGC( m_window, wxTEXT_COLOUR );
+        m_bgGC = wxGetPoolGC( m_window, wxBG_COLOUR );
+    }
+
+    /* background colour */
+    m_backgroundBrush = *wxWHITE_BRUSH;
+    m_backgroundBrush.GetColour().CalcPixel( m_cmap );
+    GdkColor *bg_col = m_backgroundBrush.GetColour().GetColor();
+
+    /* m_textGC */
+    m_textForegroundColour.CalcPixel( m_cmap );
+    gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() );
+
+    m_textBackgroundColour.CalcPixel( m_cmap );
+    gdk_gc_set_background( m_textGC, m_textBackgroundColour.GetColor() );
+
+    gdk_gc_set_fill( m_textGC, GDK_SOLID );
+
+    /* m_penGC */
+    m_pen.GetColour().CalcPixel( m_cmap );
+    gdk_gc_set_foreground( m_penGC, m_pen.GetColour().GetColor() );
+    gdk_gc_set_background( m_penGC, bg_col );
+
+    gdk_gc_set_line_attributes( m_penGC, 0, GDK_LINE_SOLID, GDK_CAP_NOT_LAST, GDK_JOIN_ROUND );
+
+    /* m_brushGC */
+    m_brush.GetColour().CalcPixel( m_cmap );
+    gdk_gc_set_foreground( m_brushGC, m_brush.GetColour().GetColor() );
+    gdk_gc_set_background( m_brushGC, bg_col );
+
+    gdk_gc_set_fill( m_brushGC, GDK_SOLID );
+
+    /* m_bgGC */
+    gdk_gc_set_background( m_bgGC, bg_col );
+    gdk_gc_set_foreground( m_bgGC, bg_col );
+
+    gdk_gc_set_fill( m_bgGC, GDK_SOLID );
+
+    /* ROPs */
+    gdk_gc_set_function( m_textGC, GDK_COPY );
+    gdk_gc_set_function( m_brushGC, GDK_COPY );
+    gdk_gc_set_function( m_penGC, GDK_COPY );
+
+    /* clipping */
+    gdk_gc_set_clip_rectangle( m_penGC, (GdkRectangle *) NULL );
+    gdk_gc_set_clip_rectangle( m_brushGC, (GdkRectangle *) NULL );
+    gdk_gc_set_clip_rectangle( m_textGC, (GdkRectangle *) NULL );
+    gdk_gc_set_clip_rectangle( m_bgGC, (GdkRectangle *) NULL );
+
+    if (!hatch_bitmap)
+    {
+        hatch_bitmap    = hatches;
+        hatch_bitmap[0] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, bdiag_bits, bdiag_width, bdiag_height );
+        hatch_bitmap[1] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, cdiag_bits, cdiag_width, cdiag_height );
+        hatch_bitmap[2] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, fdiag_bits, fdiag_width, fdiag_height );
+        hatch_bitmap[3] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, cross_bits, cross_width, cross_height );
+        hatch_bitmap[4] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, horiz_bits, horiz_width, horiz_height );
+        hatch_bitmap[5] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, verti_bits, verti_width, verti_height );
+    }
+}
+
+void wxWindowDC::DoGetSize( int* width, int* height ) const
 {
-    wxFAIL_MSG( _T("wxWindowDC::DoFloodFill not implemented") );
+    wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
+
+    m_owner->GetSize(width, height);
 }
 
-bool wxWindowDC::DoGetPixel( long WXUNUSED(x1), long WXUNUSED(y1), wxColour *WXUNUSED(col) ) const
+extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y, 
+                          const wxColour & col, int style);
+
+bool wxWindowDC::DoFloodFill(wxCoord x, wxCoord y,
+                             const wxColour& col, int style)
 {
-    wxFAIL_MSG( _T("wxWindowDC::DoGetPixel not implemented") );
-    return FALSE;
+    return wxDoFloodFill(this, x, y, col, style);
 }
 
-void wxWindowDC::DoDrawLine( long x1, long y1, long x2, long y2 )
+bool wxWindowDC::DoGetPixel( wxCoord x1, wxCoord y1, wxColour *col ) const
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    // Generic (and therefore rather inefficient) method.
+    // Could be improved.
+    wxMemoryDC memdc;
+    wxBitmap bitmap(1, 1);
+    memdc.SelectObject(bitmap);
+    memdc.Blit(0, 0, 1, 1, (wxDC*) this, x1, y1);
+    memdc.SelectObject(wxNullBitmap);
+
+    wxImage image = bitmap.ConvertToImage();
+    col->Set(image.GetRed(0, 0), image.GetGreen(0, 0), image.GetBlue(0, 0));
+    return TRUE;
+}
+
+void wxWindowDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
+{
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     if (m_pen.GetStyle() != wxTRANSPARENT)
     {
@@ -177,17 +497,17 @@ void wxWindowDC::DoDrawLine( long x1, long y1, long x2, long y2 )
     }
 }
 
-void wxWindowDC::DoCrossHair( long x, long y )
+void wxWindowDC::DoCrossHair( wxCoord x, wxCoord y )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     if (m_pen.GetStyle() != wxTRANSPARENT)
     {
         int w = 0;
         int h = 0;
         GetSize( &w, &h );
-        long xx = XLOG2DEV(x);
-        long yy = YLOG2DEV(y);
+        wxCoord xx = XLOG2DEV(x);
+        wxCoord yy = YLOG2DEV(y);
         if (m_window)
         {
             gdk_draw_line( m_window, m_penGC, 0, yy, XLOG2DEVREL(w), yy );
@@ -196,21 +516,21 @@ void wxWindowDC::DoCrossHair( long x, long y )
     }
 }
 
-void wxWindowDC::DoDrawArc( long x1, long y1, long x2, long y2,
-                            long xc, long yc )
+void wxWindowDC::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
+                            wxCoord xc, wxCoord yc )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
-
-    long xx1 = XLOG2DEV(x1);
-    long yy1 = YLOG2DEV(y1);
-    long xx2 = XLOG2DEV(x2);
-    long yy2 = YLOG2DEV(y2);
-    long xxc = XLOG2DEV(xc);
-    long yyc = YLOG2DEV(yc);
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
+
+    wxCoord xx1 = XLOG2DEV(x1);
+    wxCoord yy1 = YLOG2DEV(y1);
+    wxCoord xx2 = XLOG2DEV(x2);
+    wxCoord yy2 = YLOG2DEV(y2);
+    wxCoord xxc = XLOG2DEV(xc);
+    wxCoord yyc = YLOG2DEV(yc);
     double dx = xx1 - xxc;
     double dy = yy1 - yyc;
-    double radius = sqrt(dx*dx+dy*dy);
-    long   r      = (long)radius;
+    double radius = sqrt((double)(dx*dx+dy*dy));
+    wxCoord   r      = (wxCoord)radius;
     double radius1, radius2;
 
     if (xx1 == xx2 && yy1 == yy2)
@@ -232,32 +552,70 @@ void wxWindowDC::DoDrawArc( long x1, long y1, long x2, long y2,
             (yy2 - yyc < 0) ? 90.0 : -90.0 :
             -atan2(double(yy2-yyc), double(xx2-xxc)) * RAD2DEG;
     }
-    long alpha1 = long(radius1 * 64.0);
-    long alpha2 = long((radius2 - radius1) * 64.0);
+    wxCoord alpha1 = wxCoord(radius1 * 64.0);
+    wxCoord alpha2 = wxCoord((radius2 - radius1) * 64.0);
     while (alpha2 <= 0) alpha2 += 360*64;
     while (alpha1 > 360*64) alpha1 -= 360*64;
 
     if (m_window)
     {
         if (m_brush.GetStyle() != wxTRANSPARENT)
-            gdk_draw_arc( m_window, m_brushGC, TRUE, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
+        {
+            if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
+            {
+                gdk_gc_set_ts_origin( m_textGC,
+                                      m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
+                                      m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
+                gdk_draw_arc( m_window, m_textGC, TRUE, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
+                gdk_gc_set_ts_origin( m_textGC, 0, 0 );
+            } else
+            if (IS_15_PIX_HATCH(m_brush.GetStyle()))
+            {
+                gdk_gc_set_ts_origin( m_brushGC, m_deviceOriginX % 15, m_deviceOriginY % 15 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            } else
+            if (IS_16_PIX_HATCH(m_brush.GetStyle()))
+            {
+                gdk_gc_set_ts_origin( m_brushGC, m_deviceOriginX % 16, m_deviceOriginY % 16 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            } else
+            if (m_brush.GetStyle() == wxSTIPPLE)
+            {
+                gdk_gc_set_ts_origin( m_brushGC,
+                                      m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
+                                      m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            }
+            else
+            {
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xxc-r, yyc-r, 2*r,2*r, alpha1, alpha2 );
+            }
+        }
 
         if (m_pen.GetStyle() != wxTRANSPARENT)
+        {
             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 );
+        }
     }
 
     CalcBoundingBox (x1, y1);
     CalcBoundingBox (x2, y2);
 }
 
-void wxWindowDC::DoDrawEllipticArc( long x, long y, long width, long height, double sa, double ea )
+void wxWindowDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double sa, double ea )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
-    long xx = XLOG2DEV(x);
-    long yy = YLOG2DEV(y);
-    long ww = m_signX * XLOG2DEVREL(width);
-    long hh = m_signY * YLOG2DEVREL(height);
+    wxCoord xx = XLOG2DEV(x);
+    wxCoord yy = YLOG2DEV(y);
+    wxCoord ww = m_signX * XLOG2DEVREL(width);
+    wxCoord hh = m_signY * YLOG2DEVREL(height);
 
     // CMB: handle -ve width and/or height
     if (ww < 0) { ww = -ww; xx = xx - ww; }
@@ -265,11 +623,44 @@ void wxWindowDC::DoDrawEllipticArc( long x, long y, long width, long height, dou
 
     if (m_window)
     {
-        long start = long(sa * 64.0);
-        long end = long(ea * 64.0);
+        wxCoord start = wxCoord(sa * 64.0);
+        wxCoord end = wxCoord((ea-sa) * 64.0);
 
         if (m_brush.GetStyle() != wxTRANSPARENT)
-            gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, ww, hh, start, end );
+        {
+            if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
+            {
+                gdk_gc_set_ts_origin( m_textGC,
+                                      m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
+                                      m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
+                gdk_draw_arc( m_window, m_textGC, TRUE, xx, yy, ww, hh, start, end );
+                gdk_gc_set_ts_origin( m_textGC, 0, 0 );
+            } else
+            if (IS_15_PIX_HATCH(m_brush.GetStyle()))
+            {
+                gdk_gc_set_ts_origin( m_brushGC, m_deviceOriginX % 15, m_deviceOriginY % 15 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, ww, hh, start, end );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            } else
+            if (IS_16_PIX_HATCH(m_brush.GetStyle()))
+            {
+                gdk_gc_set_ts_origin( m_brushGC, m_deviceOriginX % 16, m_deviceOriginY % 16 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, ww, hh, start, end );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            } else
+            if (m_brush.GetStyle() == wxSTIPPLE)
+            {
+                gdk_gc_set_ts_origin( m_brushGC,
+                                      m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
+                                      m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, ww, hh, start, end );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            }
+            else
+            {
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, ww, hh, start, end );
+            }
+        }
 
         if (m_pen.GetStyle() != wxTRANSPARENT)
             gdk_draw_arc( m_window, m_penGC, FALSE, xx, yy, ww, hh, start, end );
@@ -279,9 +670,9 @@ void wxWindowDC::DoDrawEllipticArc( long x, long y, long width, long height, dou
     CalcBoundingBox (x + width, y + height);
 }
 
-void wxWindowDC::DoDrawPoint( long x, long y )
+void wxWindowDC::DoDrawPoint( wxCoord x, wxCoord y )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     if ((m_pen.GetStyle() != wxTRANSPARENT) && m_window)
         gdk_draw_point( m_window, m_penGC, XLOG2DEV(x), YLOG2DEV(y) );
@@ -289,9 +680,9 @@ void wxWindowDC::DoDrawPoint( long x, long y )
     CalcBoundingBox (x, y);
 }
 
-void wxWindowDC::DoDrawLines( int n, wxPoint points[], long xoffset, long yoffset )
+void wxWindowDC::DoDrawLines( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     if (m_pen.GetStyle() == wxTRANSPARENT) return;
     if (n <= 0) return;
@@ -300,10 +691,10 @@ void wxWindowDC::DoDrawLines( int n, wxPoint points[], long xoffset, long yoffse
 
     for (int i = 0; i < n-1; i++)
     {
-        long x1 = XLOG2DEV(points[i].x + xoffset);
-        long x2 = XLOG2DEV(points[i+1].x + xoffset);
-        long y1 = YLOG2DEV(points[i].y + yoffset);     // oh, what a waste
-        long y2 = YLOG2DEV(points[i+1].y + yoffset);
+        wxCoord x1 = XLOG2DEV(points[i].x + xoffset);
+        wxCoord x2 = XLOG2DEV(points[i+1].x + xoffset);
+        wxCoord y1 = YLOG2DEV(points[i].y + yoffset);     // oh, what a waste
+        wxCoord y2 = YLOG2DEV(points[i+1].y + yoffset);
 
         if (m_window)
             gdk_draw_line( m_window, m_penGC, x1, y1, x2, y2 );
@@ -312,9 +703,9 @@ void wxWindowDC::DoDrawLines( int n, wxPoint points[], long xoffset, long yoffse
     }
 }
 
-void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], long xoffset, long yoffset, int WXUNUSED(fillStyle) )
+void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset, int WXUNUSED(fillStyle) )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     if (n <= 0) return;
 
@@ -328,34 +719,68 @@ void wxWindowDC::DoDrawPolygon( int n, wxPoint points[], long xoffset, long yoff
         CalcBoundingBox( points[i].x + xoffset, points[i].y + yoffset );
     }
 
-    if ((m_brush.GetStyle() != wxTRANSPARENT) && m_window)
-        gdk_draw_polygon (m_window, m_brushGC, TRUE, gdkpoints, n);
-
-    // To do: Fillstyle
-
-    if ((m_pen.GetStyle() != wxTRANSPARENT) && m_window)
+    if (m_window)
     {
-        for (i = 0 ; i < n ; i++)
+        if (m_brush.GetStyle() != wxTRANSPARENT)
+        {
+            if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
+            {
+                gdk_gc_set_ts_origin( m_textGC,
+                                      m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
+                                      m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
+                gdk_draw_polygon( m_window, m_textGC, TRUE, gdkpoints, n );
+                gdk_gc_set_ts_origin( m_textGC, 0, 0 );
+            } else
+            if (IS_15_PIX_HATCH(m_brush.GetStyle()))
+            {
+                gdk_gc_set_ts_origin( m_brushGC, m_deviceOriginX % 15, m_deviceOriginY % 15 );
+                gdk_draw_polygon( m_window, m_brushGC, TRUE, gdkpoints, n );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            } else
+            if (IS_16_PIX_HATCH(m_brush.GetStyle()))
+            {
+                gdk_gc_set_ts_origin( m_brushGC, m_deviceOriginX % 16, m_deviceOriginY % 16 );
+                gdk_draw_polygon( m_window, m_brushGC, TRUE, gdkpoints, n );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            } else
+            if (m_brush.GetStyle() == wxSTIPPLE)
+            {
+                gdk_gc_set_ts_origin( m_brushGC,
+                                      m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
+                                      m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
+                gdk_draw_polygon( m_window, m_brushGC, TRUE, gdkpoints, n );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            }
+            else
+            {
+                gdk_draw_polygon( m_window, m_brushGC, TRUE, gdkpoints, n );
+            }
+        }
+
+        if (m_pen.GetStyle() != wxTRANSPARENT)
         {
-            gdk_draw_line( m_window, m_penGC,
-                           gdkpoints[i%n].x,
-                           gdkpoints[i%n].y,
-                           gdkpoints[(i+1)%n].x,
-                           gdkpoints[(i+1)%n].y);
+            for (i = 0 ; i < n ; i++)
+            {
+                gdk_draw_line( m_window, m_penGC,
+                               gdkpoints[i%n].x,
+                               gdkpoints[i%n].y,
+                               gdkpoints[(i+1)%n].x,
+                               gdkpoints[(i+1)%n].y);
+            }
         }
     }
 
     delete[] gdkpoints;
 }
 
-void wxWindowDC::DoDrawRectangle( long x, long y, long width, long height )
+void wxWindowDC::DoDrawRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
-    long xx = XLOG2DEV(x);
-    long yy = YLOG2DEV(y);
-    long ww = m_signX * XLOG2DEVREL(width);
-    long hh = m_signY * YLOG2DEVREL(height);
+    wxCoord xx = XLOG2DEV(x);
+    wxCoord yy = YLOG2DEV(y);
+    wxCoord ww = m_signX * XLOG2DEVREL(width);
+    wxCoord hh = m_signY * YLOG2DEVREL(height);
 
     // CMB: draw nothing if transformed w or h is 0
     if (ww == 0 || hh == 0) return;
@@ -367,7 +792,40 @@ void wxWindowDC::DoDrawRectangle( long x, long y, long width, long height )
     if (m_window)
     {
         if (m_brush.GetStyle() != wxTRANSPARENT)
-            gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy, ww, hh );
+        {
+            if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
+            {
+                gdk_gc_set_ts_origin( m_textGC,
+                                      m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
+                                      m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
+                gdk_draw_rectangle( m_window, m_textGC, TRUE, xx, yy, ww, hh );
+                gdk_gc_set_ts_origin( m_textGC, 0, 0 );
+            } else
+            if (IS_15_PIX_HATCH(m_brush.GetStyle()))
+            {
+                gdk_gc_set_ts_origin( m_brushGC, m_deviceOriginX % 15, m_deviceOriginY % 15 );
+                gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy, ww, hh );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            } else
+            if (IS_16_PIX_HATCH(m_brush.GetStyle()))
+            {
+                gdk_gc_set_ts_origin( m_brushGC, m_deviceOriginX % 16, m_deviceOriginY % 16 );
+                gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy, ww, hh );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            } else
+            if (m_brush.GetStyle() == wxSTIPPLE)
+            {
+                gdk_gc_set_ts_origin( m_brushGC,
+                                      m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
+                                      m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
+                gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy, ww, hh );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            }
+            else
+            {
+                gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy, ww, hh );
+            }
+        }
 
         if (m_pen.GetStyle() != wxTRANSPARENT)
             gdk_draw_rectangle( m_window, m_penGC, FALSE, xx, yy, ww-1, hh-1 );
@@ -377,17 +835,17 @@ void wxWindowDC::DoDrawRectangle( long x, long y, long width, long height )
     CalcBoundingBox( x + width, y + height );
 }
 
-void wxWindowDC::DoDrawRoundedRectangle( long x, long y, long width, long height, double radius )
+void wxWindowDC::DoDrawRoundedRectangle( wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     if (radius < 0.0) radius = - radius * ((width < height) ? width : height);
 
-    long xx = XLOG2DEV(x);
-    long yy = YLOG2DEV(y);
-    long ww = m_signX * XLOG2DEVREL(width);
-    long hh = m_signY * YLOG2DEVREL(height);
-    long rr = XLOG2DEVREL((long)radius);
+    wxCoord xx = XLOG2DEV(x);
+    wxCoord yy = YLOG2DEV(y);
+    wxCoord ww = m_signX * XLOG2DEVREL(width);
+    wxCoord hh = m_signY * YLOG2DEVREL(height);
+    wxCoord rr = XLOG2DEVREL((wxCoord)radius);
 
     // CMB: handle -ve width and/or height
     if (ww < 0) { ww = -ww; xx = xx - ww; }
@@ -416,27 +874,78 @@ void wxWindowDC::DoDrawRoundedRectangle( long x, long y, long width, long height
     {
         // CMB: ensure dd is not larger than rectangle otherwise we
         // get an hour glass shape
-        long dd = 2 * rr;
+        wxCoord dd = 2 * rr;
         if (dd > ww) dd = ww;
         if (dd > hh) dd = hh;
         rr = dd / 2;
 
         if (m_brush.GetStyle() != wxTRANSPARENT)
         {
-            gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx+rr, yy, ww-dd+1, hh );
-            gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy+rr, ww, hh-dd+1 );
-            gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, dd, dd, 90*64, 90*64 );
-            gdk_draw_arc( m_window, m_brushGC, TRUE, xx+ww-dd, yy, dd, dd, 0, 90*64 );
-            gdk_draw_arc( m_window, m_brushGC, TRUE, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
-            gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
+            if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
+            {
+                gdk_gc_set_ts_origin( m_textGC,
+                                      m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
+                                      m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
+                gdk_draw_rectangle( m_window, m_textGC, TRUE, xx+rr, yy, ww-dd+1, hh );
+                gdk_draw_rectangle( m_window, m_textGC, TRUE, xx, yy+rr, ww, hh-dd+1 );
+                gdk_draw_arc( m_window, m_textGC, TRUE, xx, yy, dd, dd, 90*64, 90*64 );
+                gdk_draw_arc( m_window, m_textGC, TRUE, xx+ww-dd, yy, dd, dd, 0, 90*64 );
+                gdk_draw_arc( m_window, m_textGC, TRUE, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
+                gdk_draw_arc( m_window, m_textGC, TRUE, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
+                gdk_gc_set_ts_origin( m_textGC, 0, 0 );
+            } else
+            if (IS_15_PIX_HATCH(m_brush.GetStyle()))
+            {
+                gdk_gc_set_ts_origin( m_brushGC, m_deviceOriginX % 15, m_deviceOriginY % 15 );
+                gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx+rr, yy, ww-dd+1, hh );
+                gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy+rr, ww, hh-dd+1 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, dd, dd, 90*64, 90*64 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx+ww-dd, yy, dd, dd, 0, 90*64 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            } else
+            if (IS_16_PIX_HATCH(m_brush.GetStyle()))
+            {
+                gdk_gc_set_ts_origin( m_brushGC, m_deviceOriginX % 16, m_deviceOriginY % 16 );
+                gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx+rr, yy, ww-dd+1, hh );
+                gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy+rr, ww, hh-dd+1 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, dd, dd, 90*64, 90*64 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx+ww-dd, yy, dd, dd, 0, 90*64 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            } else
+            if (m_brush.GetStyle() == wxSTIPPLE)
+            {
+                gdk_gc_set_ts_origin( m_brushGC,
+                                      m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
+                                      m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
+                gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx+rr, yy, ww-dd+1, hh );
+                gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy+rr, ww, hh-dd+1 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, dd, dd, 90*64, 90*64 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx+ww-dd, yy, dd, dd, 0, 90*64 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            }
+            else
+            {
+                gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx+rr, yy, ww-dd+1, hh );
+                gdk_draw_rectangle( m_window, m_brushGC, TRUE, xx, yy+rr, ww, hh-dd+1 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, dd, dd, 90*64, 90*64 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx+ww-dd, yy, dd, dd, 0, 90*64 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy+hh-dd, dd, dd, 180*64, 90*64 );
+            }
         }
 
         if (m_pen.GetStyle() != wxTRANSPARENT)
         {
-            gdk_draw_line( m_window, m_penGC, xx+rr, yy, xx+ww-rr, yy );
-            gdk_draw_line( m_window, m_penGC, xx+rr, yy+hh, xx+ww-rr, yy+hh );
-            gdk_draw_line( m_window, m_penGC, xx, yy+rr, xx, yy+hh-rr );
-            gdk_draw_line( m_window, m_penGC, xx+ww, yy+rr, xx+ww, yy+hh-rr );
+            gdk_draw_line( m_window, m_penGC, xx+rr+1, yy, xx+ww-rr, yy );
+            gdk_draw_line( m_window, m_penGC, xx+rr+1, yy+hh, xx+ww-rr, yy+hh );
+            gdk_draw_line( m_window, m_penGC, xx, yy+rr+1, xx, yy+hh-rr );
+            gdk_draw_line( m_window, m_penGC, xx+ww, yy+rr+1, xx+ww, yy+hh-rr );
             gdk_draw_arc( m_window, m_penGC, FALSE, xx, yy, dd, dd, 90*64, 90*64 );
             gdk_draw_arc( m_window, m_penGC, FALSE, xx+ww-dd, yy, dd, dd, 0, 90*64 );
             gdk_draw_arc( m_window, m_penGC, FALSE, xx+ww-dd, yy+hh-dd, dd, dd, 270*64, 90*64 );
@@ -449,14 +958,14 @@ void wxWindowDC::DoDrawRoundedRectangle( long x, long y, long width, long height
     CalcBoundingBox( x + width, y + height );
 }
 
-void wxWindowDC::DoDrawEllipse( long x, long y, long width, long height )
+void wxWindowDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
-    long xx = XLOG2DEV(x);
-    long yy = YLOG2DEV(y);
-    long ww = m_signX * XLOG2DEVREL(width);
-    long hh = m_signY * YLOG2DEVREL(height);
+    wxCoord xx = XLOG2DEV(x);
+    wxCoord yy = YLOG2DEV(y);
+    wxCoord ww = m_signX * XLOG2DEVREL(width);
+    wxCoord hh = m_signY * YLOG2DEVREL(height);
 
     // CMB: handle -ve width and/or height
     if (ww < 0) { ww = -ww; xx = xx - ww; }
@@ -465,32 +974,66 @@ void wxWindowDC::DoDrawEllipse( long x, long y, long width, long height )
     if (m_window)
     {
         if (m_brush.GetStyle() != wxTRANSPARENT)
-            gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, ww, hh, 0, 360*64 );
+        {
+            if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
+            {
+                gdk_gc_set_ts_origin( m_textGC,
+                                      m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
+                                      m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
+                gdk_draw_arc( m_window, m_textGC, TRUE, xx, yy, ww, hh, 0, 360*64 );
+                gdk_gc_set_ts_origin( m_textGC, 0, 0 );
+            } else
+            if (IS_15_PIX_HATCH(m_brush.GetStyle()))
+            {
+                gdk_gc_set_ts_origin( m_brushGC, m_deviceOriginX % 15, m_deviceOriginY % 15 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, ww, hh, 0, 360*64 );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            } else
+            if (IS_16_PIX_HATCH(m_brush.GetStyle()))
+            {
+                gdk_gc_set_ts_origin( m_brushGC, m_deviceOriginX % 16, m_deviceOriginY % 16 );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, ww, hh, 0, 360*64 );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            } else
+            if (m_brush.GetStyle() == wxSTIPPLE)
+            {
+                gdk_gc_set_ts_origin( m_brushGC,
+                                      m_deviceOriginX % m_brush.GetStipple()->GetWidth(),
+                                      m_deviceOriginY % m_brush.GetStipple()->GetHeight() );
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, ww, hh, 0, 360*64 );
+                gdk_gc_set_ts_origin( m_brushGC, 0, 0 );
+            }
+            else
+            {
+                gdk_draw_arc( m_window, m_brushGC, TRUE, xx, yy, ww, hh, 0, 360*64 );
+            }
+        }
 
         if (m_pen.GetStyle() != wxTRANSPARENT)
             gdk_draw_arc( m_window, m_penGC, FALSE, xx, yy, ww, hh, 0, 360*64 );
     }
 
-    CalcBoundingBox( x - width, y - height );
+    CalcBoundingBox( x, y );
     CalcBoundingBox( x + width, y + height );
 }
 
-void wxWindowDC::DoDrawIcon( const wxIcon &icon, long x, long y )
+void wxWindowDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y )
 {
     // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
     DoDrawBitmap( (const wxBitmap&)icon, x, y, (bool)TRUE );
 }
 
 void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
-                               long x, long y,
+                               wxCoord x, wxCoord y,
                                bool useMask )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
-    wxCHECK_RET( bitmap.Ok(), _T("invalid bitmap") );
+    wxCHECK_RET( bitmap.Ok(), wxT("invalid bitmap") );
 
-    /* scale/translate size and position */
+    bool is_mono = (bitmap.GetBitmap() != NULL);
 
+    /* scale/translate size and position */
     int xx = XLOG2DEV(x);
     int yy = YLOG2DEV(y);
 
@@ -505,77 +1048,143 @@ void wxWindowDC::DoDrawBitmap( const wxBitmap &bitmap,
     int ww = XLOG2DEVREL(w);
     int hh = YLOG2DEVREL(h);
 
-    /* scale bitmap if required */
+    /* compare to current clipping region */
+    if (!m_currentClippingRegion.IsNull())
+    {
+        wxRegion tmp( xx,yy,ww,hh );
+        tmp.Intersect( m_currentClippingRegion );
+        if (tmp.IsEmpty())
+            return;
+    }
 
+    /* scale bitmap if required */
     wxBitmap use_bitmap;
-
     if ((w != ww) || (h != hh))
     {
-        wxImage image( bitmap );
-        image = image.Scale( ww, hh );
-
-        use_bitmap = image.ConvertToBitmap();
+        wxImage image = bitmap.ConvertToImage();
+        image.Rescale( ww, hh );
+        if (is_mono)
+            use_bitmap = wxBitmap(image.ConvertToMono(255,255,255), 1);
+        else
+            use_bitmap = wxBitmap(image);
     }
     else
     {
         use_bitmap = bitmap;
     }
-
+    
     /* apply mask if any */
-
     GdkBitmap *mask = (GdkBitmap *) NULL;
     if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
 
-    if (useMask && mask)
-    {
-        gdk_gc_set_clip_mask( m_penGC, mask );
-        gdk_gc_set_clip_origin( m_penGC, xx, yy );
-    }
-
-    /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
-
-    GdkPixmap *pm = use_bitmap.GetPixmap();
-    if (pm)
-    {
-        gdk_draw_pixmap( m_window, m_penGC, pm, 0, 0, xx, yy, -1, -1 );
-    }
-    else
-    {
-        GdkBitmap *bm = use_bitmap.GetBitmap();
-        if (bm)
+        if (useMask && mask)
         {
-            gdk_draw_bitmap( m_window, m_penGC, bm, 0, 0, xx, yy, -1, -1 );
+            GdkBitmap *new_mask = (GdkBitmap*) NULL;
+#ifndef __WXGTK20__  // TODO fix crash
+            if (!m_currentClippingRegion.IsNull())
+            {
+                GdkColor col;
+                new_mask = gdk_pixmap_new( wxGetRootWindow()->window, ww, hh, 1 );
+                GdkGC *gc = gdk_gc_new( new_mask );
+                col.pixel = 0;
+                gdk_gc_set_foreground( gc, &col );
+                gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, ww, hh );
+                col.pixel = 0;
+                gdk_gc_set_background( gc, &col );
+                col.pixel = 1;
+                gdk_gc_set_foreground( gc, &col );
+                gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
+                gdk_gc_set_clip_origin( gc, -xx, -yy );
+                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 );
+                gdk_gc_unref( gc );
+            }
+#endif
+            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 );
+            }
+            
+            if (new_mask)
+                gdk_bitmap_unref( new_mask );
         }
-    }
 
-    /* remove mask again if any */
+    /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
+       drawing a mono-bitmap (XBitmap) we use the current text GC */
+    if (is_mono)
+        gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), 0, 0, xx, yy, -1, -1 );
+    else
+        gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
 
+    /* remove mask again if any */
     if (useMask && mask)
     {
-        gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL );
-        gdk_gc_set_clip_origin( m_penGC, 0, 0 );
+        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() );
+        }
     }
 }
 
-bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height,
-                         wxDC *source, long xsrc, long ysrc,
-                         int logical_func, bool useMask )
+bool wxWindowDC::DoBlit( wxCoord xdest, wxCoord ydest,
+                         wxCoord width, wxCoord height,
+                         wxDC *source,
+                         wxCoord xsrc, wxCoord ysrc,
+                         int logical_func,
+                         bool useMask,
+                         wxCoord xsrcMask, wxCoord ysrcMask )
 {
    /* this is the nth try to get this utterly useless function to
       work. it now completely ignores the scaling or translation
       of the source dc, but scales correctly on the target dc and
       knows about possible mask information in a memory dc. */
 
-    wxCHECK_MSG( Ok(), FALSE, _T("invalid window dc") );
+    wxCHECK_MSG( Ok(), FALSE, wxT("invalid window dc") );
 
-    wxCHECK_MSG( source, FALSE, _T("invalid source dc") );
+    wxCHECK_MSG( source, FALSE, wxT("invalid source dc") );
 
     if (!m_window) return FALSE;
 
+#if 1
+    // transform the source DC coords to the device ones
+    xsrc = source->XLOG2DEV(xsrc);
+    ysrc = source->YLOG2DEV(ysrc);
+#endif
+
     wxClientDC *srcDC = (wxClientDC*)source;
     wxMemoryDC *memDC = (wxMemoryDC*)source;
 
     bool use_bitmap_method = FALSE;
+    bool is_mono = FALSE;
+
+    /* TODO: use the mask origin when drawing transparently */
+    if (xsrcMask == -1 && ysrcMask == -1)
+    {
+        xsrcMask = xsrc; ysrcMask = ysrc;
+    }
 
     if (srcDC->m_isMemDC)
     {
@@ -599,6 +1208,7 @@ bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height,
            /* we HAVE TO use the direct way for memory dcs
               that are bitmaps because XCopyArea doesn't cope
               with different bit depths */
+            is_mono = TRUE;
             use_bitmap_method = TRUE;
         }
         else if ((xsrc == 0) && (ysrc == 0) &&
@@ -620,90 +1230,129 @@ bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height,
     CalcBoundingBox( xdest, ydest );
     CalcBoundingBox( xdest + width, ydest + height );
 
+    /* scale/translate size and position */
+    wxCoord xx = XLOG2DEV(xdest);
+    wxCoord yy = YLOG2DEV(ydest);
+
+    wxCoord ww = XLOG2DEVREL(width);
+    wxCoord hh = YLOG2DEVREL(height);
+
+    /* compare to current clipping region */
+    if (!m_currentClippingRegion.IsNull())
+    {
+        wxRegion tmp( xx,yy,ww,hh );
+        tmp.Intersect( m_currentClippingRegion );
+        if (tmp.IsEmpty())
+            return TRUE;
+    }
+
     int old_logical_func = m_logicalFunction;
     SetLogicalFunction( logical_func );
 
     if (use_bitmap_method)
     {
         /* scale/translate bitmap size */
+        wxCoord bm_width = memDC->m_selected.GetWidth();
+        wxCoord bm_height = memDC->m_selected.GetHeight();
 
-        long bm_width = memDC->m_selected.GetWidth();
-        long bm_height = memDC->m_selected.GetHeight();
-
-        long bm_ww = XLOG2DEVREL( bm_width );
-        long bm_hh = YLOG2DEVREL( bm_height );
+        wxCoord bm_ww = XLOG2DEVREL( bm_width );
+        wxCoord bm_hh = YLOG2DEVREL( bm_height );
 
         /* scale bitmap if required */
-
         wxBitmap use_bitmap;
 
         if ((bm_width != bm_ww) || (bm_height != bm_hh))
         {
-            wxImage image( memDC->m_selected );
+            wxImage image = memDC->m_selected.ConvertToImage();
             image = image.Scale( bm_ww, bm_hh );
 
-            use_bitmap = image.ConvertToBitmap();
+            if (is_mono)
+                use_bitmap = wxBitmap(image.ConvertToMono(255,255,255), 1);
+            else
+                use_bitmap = wxBitmap(image);
         }
         else
         {
             use_bitmap = memDC->m_selected;
         }
 
-        /* scale/translate size and position */
-
-        long xx = XLOG2DEV(xdest);
-        long yy = YLOG2DEV(ydest);
-
-        long ww = XLOG2DEVREL(width);
-        long hh = YLOG2DEVREL(height);
-
         /* apply mask if any */
-
         GdkBitmap *mask = (GdkBitmap *) NULL;
         if (use_bitmap.GetMask()) mask = use_bitmap.GetMask()->GetBitmap();
 
         if (useMask && mask)
         {
-            gdk_gc_set_clip_mask( m_penGC, mask );
-            gdk_gc_set_clip_origin( m_penGC, xx, yy );
+            GdkBitmap *new_mask = (GdkBitmap*) NULL;
+#ifndef __WXGTK20__  // TODO fix crash
+            if (!m_currentClippingRegion.IsNull())
+            {
+                GdkColor col;
+                new_mask = gdk_pixmap_new( wxGetRootWindow()->window, bm_ww, bm_hh, 1 );
+                GdkGC *gc = gdk_gc_new( new_mask );
+                col.pixel = 0;
+                gdk_gc_set_foreground( gc, &col );
+                gdk_draw_rectangle( new_mask, gc, TRUE, 0, 0, bm_ww, bm_hh );
+                col.pixel = 0;
+                gdk_gc_set_background( gc, &col );
+                col.pixel = 1;
+                gdk_gc_set_foreground( gc, &col );
+                gdk_gc_set_clip_region( gc, m_currentClippingRegion.GetRegion() );
+                gdk_gc_set_clip_origin( gc, -xx, -yy );
+                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 );
+                gdk_gc_unref( gc );
+            }
+#endif
+            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 );
+            }
+            if (new_mask)
+                gdk_bitmap_unref( new_mask );
         }
 
-        /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */
+        /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For
+           drawing a mono-bitmap (XBitmap) we use the current text GC */
 
-        GdkPixmap *pm = use_bitmap.GetPixmap();
-        if (pm)
-        {
-            gdk_draw_pixmap( m_window, m_penGC, pm, xsrc, ysrc, xx, yy, ww, hh );
-        }
+        if (is_mono)
+            gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh );
         else
-        {
-            GdkBitmap *bm = use_bitmap.GetBitmap();
-            if (bm)
-            {
-                /* we use the textGC here because blitting a bitmap is done
-                   using the current text colour */
-                gdk_draw_bitmap( m_window, m_textGC, bm, xsrc, ysrc, xx, yy, ww, hh );
-            }
-        }
+            gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh );
 
         /* remove mask again if any */
-
         if (useMask && mask)
         {
-            gdk_gc_set_clip_mask( m_penGC, (GdkBitmap *) NULL );
-            gdk_gc_set_clip_origin( m_penGC, 0, 0 );
+            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() );
+            }
         }
     }
     else /* use_bitmap_method */
     {
-        /* scale/translate size and position */
-
-        long xx = XLOG2DEV(xdest);
-        long yy = YLOG2DEV(ydest);
-
-        long ww = XLOG2DEVREL(width);
-        long hh = YLOG2DEVREL(height);
-
         if ((width != ww) || (height != hh))
         {
             /* draw source window into a bitmap as we cannot scale
@@ -720,31 +1369,35 @@ bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height,
                for a different implementation of the same problem. */
 
             wxBitmap bitmap( width, height );
+
+            /* copy including child window contents */
+            gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
             gdk_window_copy_area( bitmap.GetPixmap(), m_penGC, 0, 0,
                                   srcDC->GetWindow(),
                                   xsrc, ysrc, width, height );
+            gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN );
 
             /* scale image */
-
-            wxImage image( bitmap );
+            wxImage image = bitmap.ConvertToImage();
             image = image.Scale( ww, hh );
 
             /* convert to bitmap */
-
-            bitmap = image.ConvertToBitmap();
+            bitmap = wxBitmap(image);
 
             /* draw scaled bitmap */
-
             gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 );
 
         }
         else
         {
-            /* no scaling and not a memory dc with a mask either */
+            /* No scaling and not a memory dc with a mask either */
 
+            /* copy including child window contents */
+            gdk_gc_set_subwindow( m_penGC, GDK_INCLUDE_INFERIORS );
             gdk_window_copy_area( m_window, m_penGC, xx, yy,
                                   srcDC->GetWindow(),
                                   xsrc, ysrc, width, height );
+            gdk_gc_set_subwindow( m_penGC, GDK_CLIP_BY_CHILDREN );
         }
     }
 
@@ -752,22 +1405,49 @@ bool wxWindowDC::DoBlit( long xdest, long ydest, long width, long height,
     return TRUE;
 }
 
-void wxWindowDC::DoDrawText( const wxString &text, long x, long y )
+void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     if (!m_window) return;
 
     GdkFont *font = m_font.GetInternalFont( m_scaleY );
 
+    wxCHECK_RET( font, wxT("invalid font") );
+
+#if defined(__WXGTK20__)
+    wxCHECK_RET( m_context, wxT("no Pango context") );
+#endif
+
     x = XLOG2DEV(x);
     y = YLOG2DEV(y);
 
-    /* CMB 21/5/98: draw text background if mode is wxSOLID */
-    if (m_backgroundMode == wxSOLID)
+#if defined(__WXGTK20__)
+    // TODO: the layout engine should be abstracted at a higher level!
+    PangoLayout *layout = pango_layout_new(m_context);
+    pango_layout_set_font_description(layout, m_fontdesc);
+    {
+#if wxUSE_UNICODE
+        const wxCharBuffer data = wxConvUTF8.cWC2MB( text );
+        pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
+#else
+        const wxWCharBuffer wdata = wxConvLocal.cMB2WC( text );
+        const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata );
+        pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
+#endif
+    }
+    PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data;
+    PangoRectangle rect;
+    pango_layout_line_get_extents(line, NULL, &rect);
+    wxCoord width = rect.width;
+    wxCoord height = rect.height;
+    gdk_draw_layout( m_window, m_textGC, x, y, layout );
+#else // GTK+ 1.x
+    wxCoord width = gdk_string_width( font, text.mbc_str() );
+    wxCoord height = font->ascent + font->descent;
+
+    if ( m_backgroundMode == wxSOLID )
     {
-        long width = gdk_string_width( font, text.mbc_str() );
-        long height = font->ascent + font->descent;
         gdk_gc_set_foreground( m_textGC, m_textBackgroundColour.GetColor() );
         gdk_draw_rectangle( m_window, m_textGC, TRUE, x, y, width, height );
         gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() );
@@ -779,50 +1459,212 @@ void wxWindowDC::DoDrawText( const wxString &text, long x, long y )
        properties (see wxXt implementation) */
     if (m_font.GetUnderlined())
     {
-        long width = gdk_string_width( font, text.mbc_str() );
-        long ul_y = y + font->ascent;
+        wxCoord ul_y = y + font->ascent;
         if (font->descent > 0) ul_y++;
         gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
     }
+#endif // GTK+ 2.0/1.x
 
-    long w, h;
-    GetTextExtent (text, &w, &h);
-    CalcBoundingBox (x + w, y + h);
+#if defined(__WXGTK20__)
+    g_object_unref( G_OBJECT( layout ) );
+#endif
+
+    width = wxCoord(width / m_scaleX);
+    height = wxCoord(height / m_scaleY);
+    CalcBoundingBox (x + width, y + height);
     CalcBoundingBox (x, y);
 }
 
-void wxWindowDC::GetTextExtent( const wxString &string, long *width, long *height,
-                                long *descent, long *externalLeading,
-                                wxFont *theFont ) const
+void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
+{
+    if (angle == 0.0)
+    {
+        DrawText(text, x, y);
+        return;
+    }
+
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
+
+    if (!m_window) return;
+
+    GdkFont *font = m_font.GetInternalFont( m_scaleY );
+
+    wxCHECK_RET( font, wxT("invalid font") );
+
+    // the size of the text
+    wxCoord w = gdk_string_width( font, text.mbc_str() );
+    wxCoord h = font->ascent + font->descent;
+
+    // draw the string normally
+    wxBitmap src(w, h);
+    wxMemoryDC dc;
+    dc.SelectObject(src);
+    dc.SetFont(GetFont());
+    dc.SetBackground(*wxWHITE_BRUSH);
+    dc.SetBrush(*wxBLACK_BRUSH);
+    dc.Clear();
+    dc.DrawText(text, 0, 0);
+    dc.SelectObject(wxNullBitmap);
+
+    // Calculate the size of the rotated bounding box.
+    double rad = DegToRad(angle);
+    double dx = cos(rad),
+           dy = sin(rad);
+
+    // the rectngle vertices are counted clockwise with the first one being at
+    // (0, 0) (or, rather, at (x, y))
+    double x2 = w*dx,
+           y2 = -w*dy;      // y axis points to the bottom, hence minus
+    double x4 = h*dy,
+           y4 = h*dx;
+    double x3 = x4 + x2,
+           y3 = y4 + y2;
+
+    // calc max and min
+    wxCoord maxX = (wxCoord)(dmax(x2, dmax(x3, x4)) + 0.5),
+            maxY = (wxCoord)(dmax(y2, dmax(y3, y4)) + 0.5),
+            minX = (wxCoord)(dmin(x2, dmin(x3, x4)) - 0.5),
+            minY = (wxCoord)(dmin(y2, dmin(y3, y4)) - 0.5);
+
+    // prepare to blit-with-rotate the bitmap to the DC
+    wxImage image = src.ConvertToImage();
+
+    GdkColor *colText = m_textForegroundColour.GetColor(),
+             *colBack = m_textBackgroundColour.GetColor();
+
+    bool textColSet = TRUE;
+
+    unsigned char *data = image.GetData();
+
+    // paint pixel by pixel
+    for ( wxCoord srcX = 0; srcX < w; srcX++ )
+    {
+        for ( wxCoord srcY = 0; srcY < h; srcY++ )
+        {
+            // transform source coords to dest coords
+            double r = sqrt((double)srcX*srcX + srcY*srcY);
+            double angleOrig = atan2((double)srcY, (double)srcX) - rad;
+            wxCoord dstX = (wxCoord)(r*cos(angleOrig) + 0.5),
+                    dstY = (wxCoord)(r*sin(angleOrig) + 0.5);
+
+            // black pixel?
+            bool textPixel = data[(srcY*w + srcX)*3] == 0;
+            if ( textPixel || (m_backgroundMode == wxSOLID) )
+            {
+                // change colour if needed
+                if ( textPixel != textColSet )
+                {
+                    gdk_gc_set_foreground( m_textGC, textPixel ? colText
+                                                               : colBack );
+
+                    textColSet = textPixel;
+                }
+
+                // don't use DrawPoint() because it uses the current pen
+                // colour, and we don't need it here
+                gdk_draw_point( m_window, m_textGC,
+                                XLOG2DEV(x) + dstX, YLOG2DEV(y) + dstY );
+            }
+        }
+    }
+
+    // it would be better to draw with non underlined font and draw the line
+    // manually here (it would be more straight...)
+#if 0
+    if ( m_font.GetUnderlined() )
+    {
+        gdk_draw_line( m_window, m_textGC,
+                       XLOG2DEV(x + x4), YLOG2DEV(y + y4 + font->descent),
+                       XLOG2DEV(x + x3), YLOG2DEV(y + y3 + font->descent));
+    }
+#endif // 0
+
+    // restore the font colour
+    gdk_gc_set_foreground( m_textGC, colText );
+
+    // update the bounding box
+    CalcBoundingBox(x + minX, y + minY);
+    CalcBoundingBox(x + maxX, y + maxY);
+}
+
+void wxWindowDC::DoGetTextExtent(const wxString &string,
+                                 wxCoord *width, wxCoord *height,
+                                 wxCoord *descent, wxCoord *externalLeading,
+                                 wxFont *theFont) const
 {
     wxFont fontToUse = m_font;
     if (theFont) fontToUse = *theFont;
-
+    if (string.IsEmpty())
+    {
+        if (width) (*width) = 0;
+        if (height) (*height) = 0;
+        return;
+    }
+    
+#ifdef __WXGTK20__
+    PangoFontDescription *desc = fontToUse.GetNativeFontInfo()->description;
+    PangoLayout *layout = pango_layout_new(m_context);
+    pango_layout_set_font_description(layout, desc);
+#if wxUSE_UNICODE
+        const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
+        pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
+#else
+        const wxWCharBuffer wdata = wxConvLocal.cMB2WC( string );
+        const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata );
+        pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
+#endif
+    PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data;
+    PangoRectangle rect;
+    pango_layout_line_get_extents(line, NULL, &rect);
+       
+    
+    if (width) (*width) = (wxCoord) (rect.width / PANGO_SCALE);
+    if (height) (*height) = (wxCoord) (rect.height / PANGO_SCALE);
+    if (descent)
+    {
+        // Do something about metrics here
+        (*descent) = 0;
+    }
+    if (externalLeading) (*externalLeading) = 0;  // ??
+    
+    g_object_unref( G_OBJECT( layout ) );
+#else
     GdkFont *font = fontToUse.GetInternalFont( m_scaleY );
-    if (width) (*width) = long(gdk_string_width( font, string.mbc_str() ) / m_scaleX);
-    if (height) (*height) = long((font->ascent + font->descent) / m_scaleY);
-    if (descent) (*descent) = long(font->descent / m_scaleY);
+    if (width) (*width) = wxCoord(gdk_string_width( font, string.mbc_str() ) / m_scaleX);
+    if (height) (*height) = wxCoord((font->ascent + font->descent) / m_scaleY);
+    if (descent) (*descent) = wxCoord(font->descent / m_scaleY);
     if (externalLeading) (*externalLeading) = 0;  // ??
+#endif
 }
 
-long wxWindowDC::GetCharWidth() const
+wxCoord wxWindowDC::GetCharWidth() const
 {
     GdkFont *font = m_font.GetInternalFont( m_scaleY );
-    return long(gdk_string_width( font, "H" ) / m_scaleX);
+    wxCHECK_MSG( font, -1, wxT("invalid font") );
+
+    return wxCoord(gdk_string_width( font, "H" ) / m_scaleX);
 }
 
-long wxWindowDC::GetCharHeight() const
+wxCoord wxWindowDC::GetCharHeight() const
 {
     GdkFont *font = m_font.GetInternalFont( m_scaleY );
-    return long((font->ascent + font->descent) / m_scaleY);
+    wxCHECK_MSG( font, -1, wxT("invalid font") );
+
+    return wxCoord((font->ascent + font->descent) / m_scaleY);
 }
 
 void wxWindowDC::Clear()
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     if (!m_window) return;
 
+    // VZ: the code below results in infinite recursion and crashes when
+    //     dc.Clear() is done from OnPaint() so I disable it for now.
+    //     I don't know what the correct fix is but Clear() surely should not
+    //     reenter OnPaint()!
+#if 0
     /* - we either are a memory dc or have a window as the
        owner. anything else shouldn't happen.
        - we don't use gdk_window_clear() as we don't set
@@ -832,9 +1674,7 @@ void wxWindowDC::Clear()
 
     if (m_owner)
     {
-        int width,height;
-        m_owner->GetSize( &width, &height );
-        gdk_draw_rectangle( m_window, m_bgGC, TRUE, 0, 0, width, height );
+        m_owner->Clear();
         return;
     }
 
@@ -845,16 +1685,28 @@ void wxWindowDC::Clear()
         gdk_draw_rectangle( m_window, m_bgGC, TRUE, 0, 0, width, height );
         return;
     }
+#else // 1
+    int width,height;
+    GetSize( &width, &height );
+    gdk_draw_rectangle( m_window, m_bgGC, TRUE, 0, 0, width, height );
+#endif // 0/1
 }
 
 void wxWindowDC::SetFont( const wxFont &font )
 {
+    // It is common practice to set the font to wxNullFont, so
+    // don't consider it to be an error
+    //    wxCHECK_RET( font.Ok(), _T("invalid font in wxWindowDC::SetFont") );
+
     m_font = font;
+#ifdef __WXGTK20__
+    m_fontdesc = m_font.GetNativeFontInfo()->description;
+#endif
 }
 
 void wxWindowDC::SetPen( const wxPen &pen )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     if (m_pen == pen) return;
 
@@ -880,15 +1732,15 @@ void wxWindowDC::SetPen( const wxPen &pen )
         width = (int)w;
     }
 
-    static const char dotted[] = {1, 1};
-    static const char short_dashed[] = {2, 2};
-    static const char long_dashed[] = {2, 4};
-    static const char dotted_dashed[] = {3, 3, 1, 3};
+    static const wxGTKDash dotted[] = {1, 1};
+    static const wxGTKDash short_dashed[] = {2, 2};
+    static const wxGTKDash wxCoord_dashed[] = {2, 4};
+    static const wxGTKDash dotted_dashed[] = {3, 3, 1, 3};
 
     // We express dash pattern in pen width unit, so we are
     // independent of zoom factor and so on...
     int req_nb_dash;
-    const char *req_dash;
+    const wxGTKDash *req_dash;
 
     GdkLineStyle lineStyle = GDK_LINE_SOLID;
     switch (m_pen.GetStyle())
@@ -897,7 +1749,7 @@ void wxWindowDC::SetPen( const wxPen &pen )
         {
             lineStyle = GDK_LINE_ON_OFF_DASH;
             req_nb_dash = m_pen.GetDashCount();
-            req_dash = m_pen.GetDash();
+            req_dash = (wxGTKDash*)m_pen.GetDash();
             break;
         }
         case wxDOT:
@@ -911,7 +1763,7 @@ void wxWindowDC::SetPen( const wxPen &pen )
         {
             lineStyle = GDK_LINE_ON_OFF_DASH;
             req_nb_dash = 2;
-            req_dash = long_dashed;
+            req_dash = wxCoord_dashed;
             break;
         }
         case wxSHORT_DASH:
@@ -931,21 +1783,22 @@ void wxWindowDC::SetPen( const wxPen &pen )
         }
 
         case wxTRANSPARENT:
+        case wxSTIPPLE_MASK_OPAQUE:
         case wxSTIPPLE:
         case wxSOLID:
         default:
         {
             lineStyle = GDK_LINE_SOLID;
-            req_dash = (wxDash*)NULL;
+            req_dash = (wxGTKDash*)NULL;
             req_nb_dash = 0;
             break;
         }
     }
 
-#if (GTK_MINOR_VERSION > 0)
+#if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1)
     if (req_dash && req_nb_dash)
     {
-        char *real_req_dash = new char[req_nb_dash];
+        wxGTKDash *real_req_dash = new wxGTKDash[req_nb_dash];
         if (real_req_dash)
         {
             for (int i = 0; i < req_nb_dash; i++)
@@ -956,7 +1809,7 @@ void wxWindowDC::SetPen( const wxPen &pen )
         else
         {
             // No Memory. We use non-scaled dash pattern...
-            gdk_gc_set_dashes( m_penGC, 0, (char*)req_dash, req_nb_dash );
+            gdk_gc_set_dashes( m_penGC, 0, (wxGTKDash*)req_dash, req_nb_dash );
         }
     }
 #endif
@@ -964,17 +1817,31 @@ void wxWindowDC::SetPen( const wxPen &pen )
     GdkCapStyle capStyle = GDK_CAP_ROUND;
     switch (m_pen.GetCap())
     {
-        case wxCAP_ROUND:      { capStyle = (width <= 1) ? GDK_CAP_NOT_LAST : GDK_CAP_ROUND; break; }
         case wxCAP_PROJECTING: { capStyle = GDK_CAP_PROJECTING; break; }
         case wxCAP_BUTT:       { capStyle = GDK_CAP_BUTT;       break; }
+        case wxCAP_ROUND:
+        default:
+        {
+            if (width <= 1)
+            {
+                width = 0;
+                capStyle = GDK_CAP_NOT_LAST;
+            }
+            else
+            {
+                capStyle = GDK_CAP_ROUND;
+            }
+            break;
+        }
     }
 
     GdkJoinStyle joinStyle = GDK_JOIN_ROUND;
     switch (m_pen.GetJoin())
     {
         case wxJOIN_BEVEL: { joinStyle = GDK_JOIN_BEVEL; break; }
-        case wxJOIN_ROUND: { joinStyle = GDK_JOIN_ROUND; break; }
         case wxJOIN_MITER: { joinStyle = GDK_JOIN_MITER; break; }
+        case wxJOIN_ROUND:
+        default:           { joinStyle = GDK_JOIN_ROUND; break; }
     }
 
     gdk_gc_set_line_attributes( m_penGC, width, lineStyle, capStyle, joinStyle );
@@ -985,7 +1852,7 @@ void wxWindowDC::SetPen( const wxPen &pen )
 
 void wxWindowDC::SetBrush( const wxBrush &brush )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     if (m_brush == brush) return;
 
@@ -1014,6 +1881,12 @@ void wxWindowDC::SetBrush( const wxBrush &brush )
         }
     }
 
+    if ((m_brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE) && (m_brush.GetStipple()->GetMask()))
+    {
+        gdk_gc_set_fill( m_textGC, GDK_OPAQUE_STIPPLED);
+        gdk_gc_set_stipple( m_textGC, m_brush.GetStipple()->GetMask()->GetBitmap() );
+    }
+
     if (IS_HATCH(m_brush.GetStyle()))
     {
         gdk_gc_set_fill( m_brushGC, GDK_STIPPLED );
@@ -1027,7 +1900,7 @@ void wxWindowDC::SetBackground( const wxBrush &brush )
    /* CMB 21/7/98: Added SetBackground. Sets background brush
     * for Clear() and bg colour for shapes filled with cross-hatch brush */
 
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     if (m_backgroundBrush == brush) return;
 
@@ -1069,9 +1942,14 @@ void wxWindowDC::SetBackground( const wxBrush &brush )
 
 void wxWindowDC::SetLogicalFunction( int function )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
-    if (m_logicalFunction == function) return;
+    if (m_logicalFunction == function)
+        return;
+
+    // VZ: shouldn't this be a CHECK?
+    if (!m_window)
+        return;
 
     GdkFunction mode = GDK_COPY;
     switch (function)
@@ -1084,9 +1962,7 @@ void wxWindowDC::SetLogicalFunction( int function )
         case wxCLEAR:        mode = GDK_CLEAR;         break;
         case wxSET:          mode = GDK_SET;           break;
         case wxOR_INVERT:    mode = GDK_OR_INVERT;     break;
-        case wxSRC_AND:
         case wxAND:          mode = GDK_AND;           break;
-        case wxSRC_OR:
         case wxOR:           mode = GDK_OR;            break;
         case wxEQUIV:        mode = GDK_EQUIV;         break;
         case wxNAND:         mode = GDK_NAND;          break;
@@ -1094,56 +1970,67 @@ void wxWindowDC::SetLogicalFunction( int function )
         case wxCOPY:         mode = GDK_COPY;          break;
         case wxNO_OP:        mode = GDK_NOOP;          break;
         case wxSRC_INVERT:   mode = GDK_COPY_INVERT;   break;
+
+        // unsupported by GTK
+        case wxNOR:          mode = GDK_COPY;          break;
 #endif
         default:
         {
-           wxFAIL_MSG( _T("unsupported logical function") );
+           wxFAIL_MSG( wxT("unsupported logical function") );
            break;
         }
     }
 
     m_logicalFunction = function;
 
-    if (!m_window) return;
-
     gdk_gc_set_function( m_penGC, mode );
     gdk_gc_set_function( m_brushGC, mode );
+
+    // to stay compatible with wxMSW, we don't apply ROPs to the text
+    // operations (i.e. DrawText/DrawRotatedText).
+    // True, but mono-bitmaps use the m_textGC and they use ROPs as well.
     gdk_gc_set_function( m_textGC, mode );
 }
 
 void wxWindowDC::SetTextForeground( const wxColour &col )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
-    if (m_textForegroundColour == col) return;
+    // don't set m_textForegroundColour to an invalid colour as we'd crash
+    // later then (we use m_textForegroundColour.GetColor() without checking
+    // in a few places)
+    if ( !col.Ok() || (m_textForegroundColour == col) )
+        return;
 
     m_textForegroundColour = col;
-    if (!m_textForegroundColour.Ok()) return;
-
-    if (!m_window) return;
 
-    m_textForegroundColour.CalcPixel( m_cmap );
-    gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() );
+    if ( m_window )
+    {
+        m_textForegroundColour.CalcPixel( m_cmap );
+        gdk_gc_set_foreground( m_textGC, m_textForegroundColour.GetColor() );
+    }
 }
 
 void wxWindowDC::SetTextBackground( const wxColour &col )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
-    if (m_textBackgroundColour == col) return;
+    // same as above
+    if ( !col.Ok() || (m_textBackgroundColour == col) )
+        return;
 
     m_textBackgroundColour = col;
-    if (!m_textBackgroundColour.Ok()) return;
-
-    if (!m_window) return;
 
-    m_textBackgroundColour.CalcPixel( m_cmap );
-    gdk_gc_set_background( m_textGC, m_textBackgroundColour.GetColor() );
+    if ( m_window )
+    {
+        m_textBackgroundColour.CalcPixel( m_cmap );
+        gdk_gc_set_background( m_textGC, m_textBackgroundColour.GetColor() );
+    }
 }
 
 void wxWindowDC::SetBackgroundMode( int mode )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     m_backgroundMode = mode;
 
@@ -1161,31 +2048,44 @@ void wxWindowDC::SetBackgroundMode( int mode )
 
 void wxWindowDC::SetPalette( const wxPalette& WXUNUSED(palette) )
 {
-    wxFAIL_MSG( _T("wxWindowDC::SetPalette not implemented") );
+    wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") );
 }
 
-void wxWindowDC::DoSetClippingRegion( long x, long y, long width, long height )
+void wxWindowDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
-
-    wxDC::DoSetClippingRegion( x, y, width, height );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     if (!m_window) return;
 
-    GdkRectangle rect;
+    wxRect rect;
     rect.x = XLOG2DEV(x);
     rect.y = YLOG2DEV(y);
     rect.width = XLOG2DEVREL(width);
     rect.height = YLOG2DEVREL(height);
-    gdk_gc_set_clip_rectangle( m_penGC, &rect );
-    gdk_gc_set_clip_rectangle( m_brushGC, &rect );
-    gdk_gc_set_clip_rectangle( m_textGC, &rect );
-    gdk_gc_set_clip_rectangle( m_bgGC, &rect );
+
+    if (!m_currentClippingRegion.IsNull())
+        m_currentClippingRegion.Intersect( rect );
+    else
+        m_currentClippingRegion.Union( rect );
+
+#if USE_PAINT_REGION
+    if (!m_paintClippingRegion.IsNull())
+        m_currentClippingRegion.Intersect( m_paintClippingRegion );
+#endif
+
+    wxCoord xx, yy, ww, hh;
+    m_currentClippingRegion.GetBox( xx, yy, ww, hh );
+    wxDC::DoSetClippingRegion( xx, yy, ww, hh );
+
+    gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
+    gdk_gc_set_clip_region( m_brushGC, m_currentClippingRegion.GetRegion() );
+    gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() );
+    gdk_gc_set_clip_region( m_bgGC, m_currentClippingRegion.GetRegion() );
 }
 
 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion &region  )
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     if (region.Empty())
     {
@@ -1195,86 +2095,66 @@ void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion &region  )
 
     if (!m_window) return;
 
-    gdk_gc_set_clip_region( m_penGC, region.GetRegion() );
-    gdk_gc_set_clip_region( m_brushGC, region.GetRegion() );
-    gdk_gc_set_clip_region( m_textGC, region.GetRegion() );
-    gdk_gc_set_clip_region( m_bgGC, region.GetRegion() );
+    if (!m_currentClippingRegion.IsNull())
+        m_currentClippingRegion.Intersect( region );
+    else
+        m_currentClippingRegion.Union( region );
+
+#if USE_PAINT_REGION
+    if (!m_paintClippingRegion.IsNull())
+        m_currentClippingRegion.Intersect( m_paintClippingRegion );
+#endif
+
+    wxCoord xx, yy, ww, hh;
+    m_currentClippingRegion.GetBox( xx, yy, ww, hh );
+    wxDC::DoSetClippingRegion( xx, yy, ww, hh );
+
+    gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
+    gdk_gc_set_clip_region( m_brushGC, m_currentClippingRegion.GetRegion() );
+    gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() );
+    gdk_gc_set_clip_region( m_bgGC, m_currentClippingRegion.GetRegion() );
 }
 
 void wxWindowDC::DestroyClippingRegion()
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( Ok(), wxT("invalid window dc") );
 
     wxDC::DestroyClippingRegion();
 
-    if (!m_window) return;
+    m_currentClippingRegion.Clear();
 
-    gdk_gc_set_clip_rectangle( m_penGC, (GdkRectangle *) NULL );
-    gdk_gc_set_clip_rectangle( m_brushGC, (GdkRectangle *) NULL );
-    gdk_gc_set_clip_rectangle( m_textGC, (GdkRectangle *) NULL );
-    gdk_gc_set_clip_rectangle( m_bgGC, (GdkRectangle *) NULL );
-}
+#if USE_PAINT_REGION
+    if (!m_paintClippingRegion.IsEmpty())
+        m_currentClippingRegion.Union( m_paintClippingRegion );
+#endif
 
-void wxWindowDC::SetUpDC()
-{
-    Destroy();
-    m_ok = TRUE;
-    m_logicalFunction = wxCOPY;
-    m_penGC = gdk_gc_new( m_window );
-    m_brushGC = gdk_gc_new( m_window );
-    m_textGC = gdk_gc_new( m_window );
-    m_bgGC = gdk_gc_new( m_window );
-
-    wxColour tmp_col( m_textForegroundColour );
-    m_textForegroundColour = wxNullColour;
-    SetTextForeground( tmp_col );
-    tmp_col = m_textBackgroundColour;
-    m_textBackgroundColour = wxNullColour;
-    SetTextBackground( tmp_col );
-
-    wxPen tmp_pen( m_pen );
-    m_pen = wxNullPen;
-    SetPen( tmp_pen );
-
-    wxFont tmp_font( m_font );
-    m_font = wxNullFont;
-    SetFont( tmp_font );
-
-    wxBrush tmp_brush( m_brush );
-    m_brush = wxNullBrush;
-    SetBrush( tmp_brush );
-
-/*
-    tmp_brush = m_backgroundBrush;
-    m_backgroundBrush = wxNullBrush;
-    SetBackground( tmp_brush );
-*/
-    tmp_brush = m_backgroundBrush;
-    m_backgroundBrush = wxNullBrush;
-    SetBackground( *wxWHITE_BRUSH );
-    m_backgroundBrush = tmp_brush;
+    if (!m_window) return;
 
-    if (!hatch_bitmap)
+    if (m_currentClippingRegion.IsEmpty())
     {
-        hatch_bitmap    = hatches;
-        hatch_bitmap[0] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, bdiag_bits, bdiag_width, bdiag_height );
-        hatch_bitmap[1] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, cdiag_bits, cdiag_width, cdiag_height );
-        hatch_bitmap[2] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, fdiag_bits, fdiag_width, fdiag_height );
-        hatch_bitmap[3] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, cross_bits, cross_width, cross_height );
-        hatch_bitmap[4] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, horiz_bits, horiz_width, horiz_height );
-        hatch_bitmap[5] = gdk_bitmap_create_from_data( (GdkWindow *) NULL, verti_bits, verti_width, verti_height );
+        gdk_gc_set_clip_rectangle( m_penGC, (GdkRectangle *) NULL );
+        gdk_gc_set_clip_rectangle( m_brushGC, (GdkRectangle *) NULL );
+        gdk_gc_set_clip_rectangle( m_textGC, (GdkRectangle *) NULL );
+        gdk_gc_set_clip_rectangle( m_bgGC, (GdkRectangle *) NULL );
+    }
+    else
+    {
+        gdk_gc_set_clip_region( m_penGC, m_currentClippingRegion.GetRegion() );
+        gdk_gc_set_clip_region( m_brushGC, m_currentClippingRegion.GetRegion() );
+        gdk_gc_set_clip_region( m_textGC, m_currentClippingRegion.GetRegion() );
+        gdk_gc_set_clip_region( m_bgGC, m_currentClippingRegion.GetRegion() );
     }
 }
 
 void wxWindowDC::Destroy()
 {
-    if (m_penGC) gdk_gc_unref( m_penGC );
+    if (m_penGC) wxFreePoolGC( m_penGC );
     m_penGC = (GdkGC*) NULL;
-    if (m_brushGC) gdk_gc_unref( m_brushGC );
+    if (m_brushGC) wxFreePoolGC( m_brushGC );
     m_brushGC = (GdkGC*) NULL;
-    if (m_textGC) gdk_gc_unref( m_textGC );
+    if (m_textGC) wxFreePoolGC( m_textGC );
     m_textGC = (GdkGC*) NULL;
-    if (m_bgGC) gdk_gc_unref( m_bgGC );
+    if (m_bgGC) wxFreePoolGC( m_bgGC );
     m_bgGC = (GdkGC*) NULL;
 }
 
@@ -1301,215 +2181,98 @@ void wxWindowDC::ComputeScaleAndOrigin()
 // Resolution in pixels per logical inch
 wxSize wxWindowDC::GetPPI() const
 {
-    return wxSize(100, 100);
+    return wxSize( (int) (m_mm_to_pix_x * 25.4 + 0.5), (int) (m_mm_to_pix_y * 25.4 + 0.5));
 }
 
 int wxWindowDC::GetDepth() const
 {
-    wxFAIL_MSG(_T("not implemented"));
+    wxFAIL_MSG(wxT("not implemented"));
 
     return -1;
 }
 
-#if wxUSE_SPLINES
-// ----------------------------------- spline code ----------------------------------------
 
-void wx_quadratic_spline(double a1, double b1, double a2, double b2,
-                         double a3, double b3, double a4, double b4);
-void wx_clear_stack();
-int wx_spline_pop(double *x1, double *y1, double *x2, double *y2, double *x3,
-        double *y3, double *x4, double *y4);
-void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3,
-          double x4, double y4);
-static bool wx_spline_add_point(double x, double y);
-static void wx_spline_draw_point_array(wxDC *dc);
+//-----------------------------------------------------------------------------
+// wxPaintDC
+//-----------------------------------------------------------------------------
 
-wxList wx_spline_point_list;
+IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxClientDC)
 
-#define                half(z1, z2)        ((z1+z2)/2.0)
-#define                THRESHOLD        5
+wxPaintDC::wxPaintDC( wxWindow *win )
+         : wxClientDC( win )
+{
+#if USE_PAINT_REGION
+    if (!win->m_clipPaintRegion)
+        return;
 
-/* iterative version */
+    m_paintClippingRegion = win->GetUpdateRegion();
+    GdkRegion *region = m_paintClippingRegion.GetRegion();
+    if ( region )
+    {
+        m_paintClippingRegion = win->GetUpdateRegion();
+        GdkRegion *region = m_paintClippingRegion.GetRegion();
+        if ( region )
+        {
+            m_currentClippingRegion.Union( m_paintClippingRegion );
 
-void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
-                 double b4)
-{
-    register double  xmid, ymid;
-    double           x1, y1, x2, y2, x3, y3, x4, y4;
-
-    wx_clear_stack();
-    wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
-
-    while (wx_spline_pop(&x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4)) {
-        xmid = (double)half(x2, x3);
-        ymid = (double)half(y2, y3);
-        if (fabs(x1 - xmid) < THRESHOLD && fabs(y1 - ymid) < THRESHOLD &&
-            fabs(xmid - x4) < THRESHOLD && fabs(ymid - y4) < THRESHOLD) {
-            wx_spline_add_point( x1, y1 );
-            wx_spline_add_point( xmid, ymid );
-        } else {
-            wx_spline_push(xmid, ymid, (double)half(xmid, x3), (double)half(ymid, y3),
-                 (double)half(x3, x4), (double)half(y3, y4), x4, y4);
-            wx_spline_push(x1, y1, (double)half(x1, x2), (double)half(y1, y2),
-                 (double)half(x2, xmid), (double)half(y2, ymid), xmid, ymid);
+            gdk_gc_set_clip_region( m_penGC, region );
+            gdk_gc_set_clip_region( m_brushGC, region );
+            gdk_gc_set_clip_region( m_textGC, region );
+            gdk_gc_set_clip_region( m_bgGC, region );
         }
     }
+#endif // USE_PAINT_REGION
 }
 
-/* utilities used by spline drawing routines */
-
-typedef struct wx_spline_stack_struct {
-    double           x1, y1, x2, y2, x3, y3, x4, y4;
-} Stack;
-
-#define         SPLINE_STACK_DEPTH             20
-static Stack    wx_spline_stack[SPLINE_STACK_DEPTH];
-static Stack   *wx_stack_top;
-static int      wx_stack_count;
-
-void wx_clear_stack()
-{
-    wx_stack_top = wx_spline_stack;
-    wx_stack_count = 0;
-}
-
-void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
-{
-    wx_stack_top->x1 = x1;
-    wx_stack_top->y1 = y1;
-    wx_stack_top->x2 = x2;
-    wx_stack_top->y2 = y2;
-    wx_stack_top->x3 = x3;
-    wx_stack_top->y3 = y3;
-    wx_stack_top->x4 = x4;
-    wx_stack_top->y4 = y4;
-    wx_stack_top++;
-    wx_stack_count++;
-}
-
-int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
-                  double *x3, double *y3, double *x4, double *y4)
-{
-    if (wx_stack_count == 0)
-        return (0);
-    wx_stack_top--;
-    wx_stack_count--;
-    *x1 = wx_stack_top->x1;
-    *y1 = wx_stack_top->y1;
-    *x2 = wx_stack_top->x2;
-    *y2 = wx_stack_top->y2;
-    *x3 = wx_stack_top->x3;
-    *y3 = wx_stack_top->y3;
-    *x4 = wx_stack_top->x4;
-    *y4 = wx_stack_top->y4;
-    return (1);
-}
+//-----------------------------------------------------------------------------
+// wxClientDC
+//-----------------------------------------------------------------------------
 
-static bool wx_spline_add_point(double x, double y)
-{
-  wxPoint *point = new wxPoint ;
-  point->x = (int) x;
-  point->y = (int) y;
-  wx_spline_point_list.Append((wxObject*)point);
-  return TRUE;
-}
+IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
 
-static void wx_spline_draw_point_array(wxDC *dc)
+wxClientDC::wxClientDC( wxWindow *win )
+          : wxWindowDC( win )
 {
-  dc->DrawLines(&wx_spline_point_list, 0, 0 );
-  wxNode *node = wx_spline_point_list.First();
-  while (node)
-  {
-    wxPoint *point = (wxPoint *)node->Data();
-    delete point;
-    delete node;
-    node = wx_spline_point_list.First();
-  }
+    wxCHECK_RET( win, _T("NULL window in wxClientDC::wxClientDC") );
+
+#ifdef __WXUNIVERSAL__
+    wxPoint ptOrigin = win->GetClientAreaOrigin();
+    SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
+    wxSize size = win->GetClientSize();
+    SetClippingRegion(wxPoint(0, 0), size);
+#endif // __WXUNIVERSAL__
 }
 
-void wxWindowDC::DoDrawSpline( wxList *points )
+void wxClientDC::DoGetSize(int *width, int *height) const
 {
-    wxCHECK_RET( Ok(), _T("invalid window dc") );
+    wxCHECK_RET( m_owner, _T("GetSize() doesn't work without window") );
 
-    wxPoint *p;
-    double           cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
-    double           x1, y1, x2, y2;
-
-    wxNode *node = points->First();
-    p = (wxPoint *)node->Data();
-
-    x1 = p->x;
-    y1 = p->y;
-
-    node = node->Next();
-    p = (wxPoint *)node->Data();
-
-    x2 = p->x;
-    y2 = p->y;
-    cx1 = (double)((x1 + x2) / 2);
-    cy1 = (double)((y1 + y2) / 2);
-    cx2 = (double)((cx1 + x2) / 2);
-    cy2 = (double)((cy1 + y2) / 2);
-
-    wx_spline_add_point(x1, y1);
-
-    while ((node = node->Next()) != NULL)
-    {
-        p = (wxPoint *)node->Data();
-        x1 = x2;
-        y1 = y2;
-        x2 = p->x;
-        y2 = p->y;
-        cx4 = (double)(x1 + x2) / 2;
-        cy4 = (double)(y1 + y2) / 2;
-        cx3 = (double)(x1 + cx4) / 2;
-        cy3 = (double)(y1 + cy4) / 2;
-
-        wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
-
-        cx1 = cx4;
-        cy1 = cy4;
-        cx2 = (double)(cx1 + x2) / 2;
-        cy2 = (double)(cy1 + y2) / 2;
-    }
-
-    wx_spline_add_point( cx1, cy1 );
-    wx_spline_add_point( x2, y2 );
-
-    wx_spline_draw_point_array( this );
+    m_owner->GetClientSize( width, height );
 }
 
-#endif // wxUSE_SPLINE
-
-//-----------------------------------------------------------------------------
-// wxPaintDC
-//-----------------------------------------------------------------------------
-
-IMPLEMENT_DYNAMIC_CLASS(wxPaintDC,wxWindowDC)
+// ----------------------------------------------------------------------------
+// wxDCModule
+// ----------------------------------------------------------------------------
 
-wxPaintDC::wxPaintDC()
-  : wxWindowDC()
-{
-}
-
-wxPaintDC::wxPaintDC( wxWindow *win )
-  : wxWindowDC( win )
+class wxDCModule : public wxModule
 {
-}
+public:
+    bool OnInit();
+    void OnExit();
 
-//-----------------------------------------------------------------------------
-// wxClientDC
-//-----------------------------------------------------------------------------
+private:
+    DECLARE_DYNAMIC_CLASS(wxDCModule)
+};
 
-IMPLEMENT_DYNAMIC_CLASS(wxClientDC,wxWindowDC)
+IMPLEMENT_DYNAMIC_CLASS(wxDCModule, wxModule)
 
-wxClientDC::wxClientDC()
-  : wxWindowDC()
+bool wxDCModule::OnInit()
 {
+    wxInitGCPool();
+    return TRUE;
 }
 
-wxClientDC::wxClientDC( wxWindow *win )
-  : wxWindowDC( win )
+void wxDCModule::OnExit()
 {
+    wxCleanUpGCPool();
 }
-