1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/dcclient.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling, Chris Breeze 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  14 #define XCopyPlane XCOPYPLANE 
  17 #include "wx/dcclient.h" 
  20     #include "wx/window.h" 
  22     #include "wx/dcmemory.h" 
  23     #include "wx/math.h" // for floating-point functions 
  25     #include "wx/module.h" 
  28 #include "wx/fontutil.h" 
  29 #include "wx/scrolwin.h" 
  31 #include "wx/gtk/win_gtk.h" 
  32 #include "wx/gtk/private.h" 
  36 //----------------------------------------------------------------------------- 
  38 //----------------------------------------------------------------------------- 
  40 #define USE_PAINT_REGION 1 
  42 //----------------------------------------------------------------------------- 
  44 //----------------------------------------------------------------------------- 
  54 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH) 
  55 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH) 
  58 static GdkPixmap  
*hatches
[num_hatches
]; 
  59 static GdkPixmap 
**hatch_bitmap 
= (GdkPixmap 
**) NULL
; 
  61 extern GtkWidget 
*wxGetRootWindow(); 
  63 //----------------------------------------------------------------------------- 
  65 //----------------------------------------------------------------------------- 
  67 const double RAD2DEG  
= 180.0 / M_PI
; 
  69 // ---------------------------------------------------------------------------- 
  71 // ---------------------------------------------------------------------------- 
  73 static inline double dmax(double a
, double b
) { return a 
> b 
? a 
: b
; } 
  74 static inline double dmin(double a
, double b
) { return a 
< b 
? a 
: b
; } 
  76 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
  78 //----------------------------------------------------------------------------- 
  79 // temporary implementation of the missing GDK function 
  80 //----------------------------------------------------------------------------- 
  82 #include "gdk/gdkprivate.h" 
  85 void gdk_wx_draw_bitmap(GdkDrawable  
*drawable
, 
  95     wxCHECK_RET( drawable
, _T("NULL drawable in gdk_wx_draw_bitmap") ); 
  96     wxCHECK_RET( src
, _T("NULL src in gdk_wx_draw_bitmap") ); 
  97     wxCHECK_RET( gc
, _T("NULL gc in gdk_wx_draw_bitmap") ); 
  99     gint src_width
, src_height
; 
 100     gdk_drawable_get_size(src
, &src_width
, &src_height
); 
 101     if (width 
== -1) width 
= src_width
; 
 102     if (height 
== -1) height 
= src_height
; 
 104     XCopyPlane( GDK_WINDOW_XDISPLAY(drawable
), 
 106                 GDK_WINDOW_XID(drawable
), 
 114 //----------------------------------------------------------------------------- 
 115 // Implement Pool of Graphic contexts. Creating them takes too much time. 
 116 //----------------------------------------------------------------------------- 
 142 #define GC_POOL_ALLOC_SIZE 100 
 144 static int wxGCPoolSize 
= 0; 
 146 static wxGC 
*wxGCPool 
= NULL
; 
 148 static void wxInitGCPool() 
 150     // This really could wait until the first call to 
 151     // wxGetPoolGC, but we will make the first allocation 
 152     // now when other initialization is being performed. 
 154     // Set initial pool size. 
 155     wxGCPoolSize 
= GC_POOL_ALLOC_SIZE
; 
 157     // Allocate initial pool. 
 158     wxGCPool 
= (wxGC 
*)malloc(wxGCPoolSize 
* sizeof(wxGC
)); 
 159     if (wxGCPool 
== NULL
) 
 161         // If we cannot malloc, then fail with error 
 162         // when debug is enabled.  If debug is not enabled, 
 163         // the problem will eventually get caught 
 165         wxFAIL_MSG( wxT("Cannot allocate GC pool") ); 
 169     // Zero initial pool. 
 170     memset(wxGCPool
, 0, wxGCPoolSize 
* sizeof(wxGC
)); 
 173 static void wxCleanUpGCPool() 
 175     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 177         if (wxGCPool
[i
].m_gc
) 
 178             g_object_unref (wxGCPool
[i
].m_gc
); 
 186 static GdkGC
* wxGetPoolGC( GdkWindow 
*window
, wxPoolGCType type 
) 
 190     // Look for an available GC. 
 191     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 193         if (!wxGCPool
[i
].m_gc
) 
 195             wxGCPool
[i
].m_gc 
= gdk_gc_new( window 
); 
 196             gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE 
); 
 197             wxGCPool
[i
].m_type 
= type
; 
 198             wxGCPool
[i
].m_used 
= false; 
 200         if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type 
== type
)) 
 202             wxGCPool
[i
].m_used 
= true; 
 203             return wxGCPool
[i
].m_gc
; 
 207     // We did not find an available GC. 
 208     // We need to grow the GC pool. 
 209     pptr 
= (wxGC 
*)realloc(wxGCPool
, 
 210         (wxGCPoolSize 
+ GC_POOL_ALLOC_SIZE
)*sizeof(wxGC
)); 
 213         // Initialize newly allocated pool. 
 215         memset(&wxGCPool
[wxGCPoolSize
], 0, 
 216             GC_POOL_ALLOC_SIZE
*sizeof(wxGC
)); 
 218         // Initialize entry we will return. 
 219         wxGCPool
[wxGCPoolSize
].m_gc 
= gdk_gc_new( window 
); 
 220         gdk_gc_set_exposures( wxGCPool
[wxGCPoolSize
].m_gc
, FALSE 
); 
 221         wxGCPool
[wxGCPoolSize
].m_type 
= type
; 
 222         wxGCPool
[wxGCPoolSize
].m_used 
= true; 
 224         // Set new value of pool size. 
 225         wxGCPoolSize 
+= GC_POOL_ALLOC_SIZE
; 
 227         // Return newly allocated entry. 
 228         return wxGCPool
[wxGCPoolSize
-GC_POOL_ALLOC_SIZE
].m_gc
; 
 231     // The realloc failed.  Fall through to error. 
 232     wxFAIL_MSG( wxT("No GC available") ); 
 234     return (GdkGC
*) NULL
; 
 237 static void wxFreePoolGC( GdkGC 
*gc 
) 
 239     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 241         if (wxGCPool
[i
].m_gc 
== gc
) 
 243             wxGCPool
[i
].m_used 
= false; 
 248     wxFAIL_MSG( wxT("Wrong GC") ); 
 251 //----------------------------------------------------------------------------- 
 253 //----------------------------------------------------------------------------- 
 256 IMPLEMENT_ABSTRACT_CLASS(wxGTKWindowImplDC
, wxGTKImplDC
) 
 258 IMPLEMENT_ABSTRACT_CLASS(wxWindowDC
, wxDC
) 
 262 wxGTKWindowImplDC::wxGTKWindowImplDC( wxDC 
*owner 
) : 
 265 wxWindowDC::wxWindowDC() 
 268     m_penGC 
= (GdkGC 
*) NULL
; 
 269     m_brushGC 
= (GdkGC 
*) NULL
; 
 270     m_textGC 
= (GdkGC 
*) NULL
; 
 271     m_bgGC 
= (GdkGC 
*) NULL
; 
 272     m_cmap 
= (GdkColormap 
*) NULL
; 
 273     m_isScreenDC 
= false; 
 274     m_owningWindow 
= (wxWindow 
*)NULL
; 
 275     m_context 
= (PangoContext 
*)NULL
; 
 276     m_layout 
= (PangoLayout 
*)NULL
; 
 277     m_fontdesc 
= (PangoFontDescription 
*)NULL
; 
 281 wxGTKWindowImplDC::wxGTKWindowImplDC( wxDC 
*owner
, wxWindow 
*window 
) : 
 284 wxWindowDC::wxWindowDC( wxWindow 
*window 
) 
 287     wxASSERT_MSG( window
, wxT("DC needs a window") ); 
 289     m_penGC 
= (GdkGC 
*) NULL
; 
 290     m_brushGC 
= (GdkGC 
*) NULL
; 
 291     m_textGC 
= (GdkGC 
*) NULL
; 
 292     m_bgGC 
= (GdkGC 
*) NULL
; 
 293     m_cmap 
= (GdkColormap 
*) NULL
; 
 294     m_owningWindow 
= (wxWindow 
*)NULL
; 
 295     m_isScreenDC 
= false; 
 296     m_font 
= window
->GetFont(); 
 298     GtkWidget 
*widget 
= window
->m_wxwindow
; 
 300     // Some controls don't have m_wxwindow - like wxStaticBox, but the user 
 301     // code should still be able to create wxClientDCs for them, so we will 
 302     // use the parent window here then. 
 305         window 
= window
->GetParent(); 
 306         widget 
= window
->m_wxwindow
; 
 309     wxASSERT_MSG( widget
, wxT("DC needs a widget") ); 
 311     m_context 
= window
->GtkGetPangoDefaultContext(); 
 312     m_layout 
= pango_layout_new( m_context 
); 
 313     m_fontdesc 
= pango_font_description_copy( widget
->style
->font_desc 
); 
 315     GtkPizza 
*pizza 
= GTK_PIZZA( widget 
); 
 316     m_window 
= pizza
->bin_window
; 
 318     // Window not realized ? 
 321          // Don't report problems as per MSW. 
 327     m_cmap 
= gtk_widget_get_colormap( widget 
? widget 
: window
->m_widget 
); 
 331     /* this must be done after SetUpDC, bacause SetUpDC calls the 
 332        repective SetBrush, SetPen, SetBackground etc functions 
 333        to set up the DC. SetBackground call m_owner->SetBackground 
 334        and this might not be desired as the standard dc background 
 335        is white whereas a window might assume gray to be the 
 336        standard (as e.g. wxStatusBar) */ 
 338     m_owningWindow 
= window
; 
 340     if (m_owningWindow 
&& m_owningWindow
->m_wxwindow 
&&  
 341         (m_owningWindow
->GetLayoutDirection() == wxLayout_RightToLeft
)) 
 346         // origin in the upper right corner 
 347         m_deviceOriginX 
= m_owningWindow
->GetClientSize().x
; 
 351 wxGTKWindowImplDC::~wxGTKWindowImplDC() 
 356         g_object_unref (m_layout
); 
 358         pango_font_description_free( m_fontdesc 
); 
 361 void wxGTKWindowImplDC::SetUpDC( bool isMemDC 
) 
 365     wxASSERT_MSG( !m_penGC
, wxT("GCs already created") ); 
 371         wxGTKMemoryImplDC 
*mem_dc 
= (wxGTKMemoryImplDC
*) this; 
 372         if (mem_dc
->GetSelectedBitmap().GetDepth() == 1) 
 374             m_penGC 
= wxGetPoolGC( m_window
, wxPEN_MONO 
); 
 375             m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_MONO 
); 
 376             m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_MONO 
); 
 377             m_bgGC 
= wxGetPoolGC( m_window
, wxBG_MONO 
); 
 386             m_penGC 
= wxGetPoolGC( m_window
, wxPEN_SCREEN 
); 
 387             m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_SCREEN 
); 
 388             m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_SCREEN 
); 
 389             m_bgGC 
= wxGetPoolGC( m_window
, wxBG_SCREEN 
); 
 393             m_penGC 
= wxGetPoolGC( m_window
, wxPEN_COLOUR 
); 
 394             m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR 
); 
 395             m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_COLOUR 
); 
 396             m_bgGC 
= wxGetPoolGC( m_window
, wxBG_COLOUR 
); 
 400     /* background colour */ 
 401     m_backgroundBrush 
= *wxWHITE_BRUSH
; 
 402     m_backgroundBrush
.GetColour().CalcPixel( m_cmap 
); 
 404     const GdkColor 
*bg_col 
= m_backgroundBrush
.GetColour().GetColor(); 
 406           GdkColor 
*bg_col 
= m_backgroundBrush
.GetColour().GetColor(); 
 410     m_textForegroundColour
.CalcPixel( m_cmap 
); 
 411     gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
 413     m_textBackgroundColour
.CalcPixel( m_cmap 
); 
 414     gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() ); 
 416     gdk_gc_set_fill( m_textGC
, GDK_SOLID 
); 
 418     gdk_gc_set_colormap( m_textGC
, m_cmap 
); 
 421     m_pen
.GetColour().CalcPixel( m_cmap 
); 
 422     gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() ); 
 423     gdk_gc_set_background( m_penGC
, bg_col 
); 
 425     gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND 
); 
 428     m_brush
.GetColour().CalcPixel( m_cmap 
); 
 429     gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() ); 
 430     gdk_gc_set_background( m_brushGC
, bg_col 
); 
 432     gdk_gc_set_fill( m_brushGC
, GDK_SOLID 
); 
 435     gdk_gc_set_background( m_bgGC
, bg_col 
); 
 436     gdk_gc_set_foreground( m_bgGC
, bg_col 
); 
 438     gdk_gc_set_fill( m_bgGC
, GDK_SOLID 
); 
 441     gdk_gc_set_function( m_textGC
, GDK_COPY 
); 
 442     gdk_gc_set_function( m_brushGC
, GDK_COPY 
); 
 443     gdk_gc_set_function( m_penGC
, GDK_COPY 
); 
 446     gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle 
*) NULL 
); 
 447     gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle 
*) NULL 
); 
 448     gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle 
*) NULL 
); 
 449     gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle 
*) NULL 
); 
 453         hatch_bitmap    
= hatches
; 
 454         hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height 
); 
 455         hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height 
); 
 456         hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height 
); 
 457         hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, cross_bits
, cross_width
, cross_height 
); 
 458         hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, horiz_bits
, horiz_width
, horiz_height 
); 
 459         hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, verti_bits
, verti_width
, verti_height 
); 
 463 void wxGTKWindowImplDC::DoGetSize( int* width
, int* height 
) const 
 465     wxCHECK_RET( m_owningWindow
, _T("GetSize() doesn't work without window") ); 
 467     m_owningWindow
->GetSize(width
, height
); 
 470 bool wxGTKWindowImplDC::DoFloodFill(wxCoord x
, wxCoord y
, 
 471                              const wxColour
& col
, int style
) 
 474     extern bool wxDoFloodFill(wxDC 
*dc
, wxCoord x
, wxCoord y
, 
 475                               const wxColour 
& col
, int style
); 
 477     return wxDoFloodFill( GetOwner(), x
, y
, col
, style
); 
 483 bool wxGTKWindowImplDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour 
*col 
) const 
 486     // Generic (and therefore rather inefficient) method. 
 487     // Could be improved. 
 489     wxBitmap 
bitmap(1, 1); 
 490     memdc
.SelectObject(bitmap
); 
 491     memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
); 
 492     memdc
.SelectObject(wxNullBitmap
); 
 494     wxImage image 
= bitmap
.ConvertToImage(); 
 495     col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0)); 
 497 #else // !wxUSE_IMAGE 
 499 #endif // wxUSE_IMAGE/!wxUSE_IMAGE 
 502 void wxGTKWindowImplDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2 
) 
 504     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 506     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 509             gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) ); 
 511         CalcBoundingBox(x1
, y1
); 
 512         CalcBoundingBox(x2
, y2
); 
 516 void wxGTKWindowImplDC::DoCrossHair( wxCoord x
, wxCoord y 
) 
 518     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 520     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 524         GetOwner()->GetSize( &w
, &h 
); 
 525         wxCoord xx 
= XLOG2DEV(x
); 
 526         wxCoord yy 
= YLOG2DEV(y
); 
 529             gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy 
); 
 530             gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) ); 
 535 void wxGTKWindowImplDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, 
 536                             wxCoord xc
, wxCoord yc 
) 
 538     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 540     wxCoord xx1 
= XLOG2DEV(x1
); 
 541     wxCoord yy1 
= YLOG2DEV(y1
); 
 542     wxCoord xx2 
= XLOG2DEV(x2
); 
 543     wxCoord yy2 
= YLOG2DEV(y2
); 
 544     wxCoord xxc 
= XLOG2DEV(xc
); 
 545     wxCoord yyc 
= YLOG2DEV(yc
); 
 546     double dx 
= xx1 
- xxc
; 
 547     double dy 
= yy1 
- yyc
; 
 548     double radius 
= sqrt((double)(dx
*dx
+dy
*dy
)); 
 549     wxCoord   r      
= (wxCoord
)radius
; 
 550     double radius1
, radius2
; 
 552     if (xx1 
== xx2 
&& yy1 
== yy2
) 
 557     else if ( wxIsNullDouble(radius
) ) 
 564         radius1 
= (xx1 
- xxc 
== 0) ? 
 565             (yy1 
- yyc 
< 0) ? 90.0 : -90.0 : 
 566             -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
; 
 567         radius2 
= (xx2 
- xxc 
== 0) ? 
 568             (yy2 
- yyc 
< 0) ? 90.0 : -90.0 : 
 569             -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
; 
 571     wxCoord alpha1 
= wxCoord(radius1 
* 64.0); 
 572     wxCoord alpha2 
= wxCoord((radius2 
- radius1
) * 64.0); 
 573     while (alpha2 
<= 0) alpha2 
+= 360*64; 
 574     while (alpha1 
> 360*64) alpha1 
-= 360*64; 
 578         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 580             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 582                 gdk_gc_set_ts_origin( m_textGC
, 
 583                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 584                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 585                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 586                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 588             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 590                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 591                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 592                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 594             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 596                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 597                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 598                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 600             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 602                 gdk_gc_set_ts_origin( m_brushGC
, 
 603                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 604                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 605                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 606                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 610                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 614         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 616             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 618             if ((m_brush
.GetStyle() != wxTRANSPARENT
) && (alpha2 
- alpha1 
!= 360*64)) 
 620                 gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc 
); 
 621                 gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2 
); 
 626     CalcBoundingBox (x1
, y1
); 
 627     CalcBoundingBox (x2
, y2
); 
 630 void wxGTKWindowImplDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea 
) 
 632     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 634     wxCoord xx 
= XLOG2DEV(x
); 
 635     wxCoord yy 
= YLOG2DEV(y
); 
 636     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 637     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 639     // CMB: handle -ve width and/or height 
 640     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 641     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 645         wxCoord start 
= wxCoord(sa 
* 64.0); 
 646         wxCoord end 
= wxCoord((ea
-sa
) * 64.0); 
 648         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 650             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 652                 gdk_gc_set_ts_origin( m_textGC
, 
 653                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 654                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 655                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 656                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 658             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 660                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 661                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 662                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 664             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 666                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 667                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 668                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 670             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 672                 gdk_gc_set_ts_origin( m_brushGC
, 
 673                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 674                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 675                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 676                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 680                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 684         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 685             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end 
); 
 688     CalcBoundingBox (x
, y
); 
 689     CalcBoundingBox (x 
+ width
, y 
+ height
); 
 692 void wxGTKWindowImplDC::DoDrawPoint( wxCoord x
, wxCoord y 
) 
 694     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 696     if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
) 
 697         gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) ); 
 699     CalcBoundingBox (x
, y
); 
 702 void wxGTKWindowImplDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset 
) 
 704     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 706     if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 709     //Check, if scaling is necessary 
 711         xoffset 
!= 0 || yoffset 
!= 0 || XLOG2DEV(10) != 10 || YLOG2DEV(10) != 10; 
 713     // GdkPoint and wxPoint have the same memory layout, so we can cast one to the other 
 714     GdkPoint
* gpts 
= reinterpret_cast<GdkPoint
*>(points
); 
 717         gpts 
= new GdkPoint
[n
]; 
 719     for (int i 
= 0; i 
< n
; i
++) 
 723             gpts
[i
].x 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 724             gpts
[i
].y 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 726         CalcBoundingBox(points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 730         gdk_draw_lines( m_window
, m_penGC
, gpts
, n
); 
 736 void wxGTKWindowImplDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) ) 
 738     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 742     //Check, if scaling is necessary 
 744         xoffset 
!= 0 || yoffset 
!= 0 || XLOG2DEV(10) != 10 || YLOG2DEV(10) != 10; 
 746     // GdkPoint and wxPoint have the same memory layout, so we can cast one to the other 
 747     GdkPoint
* gdkpoints 
= reinterpret_cast<GdkPoint
*>(points
); 
 750         gdkpoints 
= new GdkPoint
[n
]; 
 753     for (i 
= 0 ; i 
< n 
; i
++) 
 757             gdkpoints
[i
].x 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 758             gdkpoints
[i
].y 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 760         CalcBoundingBox(points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 765         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 767             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 769                 gdk_gc_set_ts_origin( m_textGC
, 
 770                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 771                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 772                 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n 
); 
 773                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 775             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 777                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 778                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 779                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 781             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 783                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 784                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 785                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 787             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 789                 gdk_gc_set_ts_origin( m_brushGC
, 
 790                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 791                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 792                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 793                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 797                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 801         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 804             for (i = 0 ; i < n ; i++) 
 806                 gdk_draw_line( m_window, m_penGC, 
 809                                gdkpoints[(i+1)%n].x, 
 810                                gdkpoints[(i+1)%n].y); 
 813             gdk_draw_polygon( m_window
, m_penGC
, FALSE
, gdkpoints
, n 
); 
 822 void wxGTKWindowImplDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 824     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 826     wxCoord xx 
= XLOG2DEV(x
); 
 827     wxCoord yy 
= YLOG2DEV(y
); 
 828     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 829     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 831     // CMB: draw nothing if transformed w or h is 0 
 832     if (ww 
== 0 || hh 
== 0) return; 
 834     // CMB: handle -ve width and/or height 
 835     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 836     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 840         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 842             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 844                 gdk_gc_set_ts_origin( m_textGC
, 
 845                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 846                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 847                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 848                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 850             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 852                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 853                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 854                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 856             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 858                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 859                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 860                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 862             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 864                 gdk_gc_set_ts_origin( m_brushGC
, 
 865                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 866                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 867                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 868                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 872                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 876         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 879             if ((m_pen
.GetWidth() == 2) && (m_pen
.GetCap() == wxCAP_ROUND
) && 
 880                 (m_pen
.GetJoin() == wxJOIN_ROUND
) && (m_pen
.GetStyle() == wxSOLID
)) 
 882                 // Use 2 1-line rects instead 
 883                 gdk_gc_set_line_attributes( m_penGC
, 1, GDK_LINE_SOLID
, GDK_CAP_ROUND
, GDK_JOIN_ROUND 
); 
 888                     gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
+1, yy
, ww
-2, hh
-2 ); 
 889                     gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
-1, ww
, hh 
); 
 893                     gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-2, hh
-2 ); 
 894                     gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
-1, yy
-1, ww
, hh 
); 
 898                 gdk_gc_set_line_attributes( m_penGC
, 2, GDK_LINE_SOLID
, GDK_CAP_ROUND
, GDK_JOIN_ROUND 
); 
 903                 // Just use X11 for other cases 
 904                 gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 ); 
 909     CalcBoundingBox( x
, y 
); 
 910     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 913 void wxGTKWindowImplDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius 
) 
 915     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 917     if (radius 
< 0.0) radius 
= - radius 
* ((width 
< height
) ? width 
: height
); 
 919     wxCoord xx 
= XLOG2DEV(x
); 
 920     wxCoord yy 
= YLOG2DEV(y
); 
 921     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 922     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 923     wxCoord rr 
= XLOG2DEVREL((wxCoord
)radius
); 
 925     // CMB: handle -ve width and/or height 
 926     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 927     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 929     // CMB: if radius is zero use DrawRectangle() instead to avoid 
 930     // X drawing errors with small radii 
 933         DoDrawRectangle( x
, y
, width
, height 
); 
 937     // CMB: draw nothing if transformed w or h is 0 
 938     if (ww 
== 0 || hh 
== 0) return; 
 940     // CMB: adjust size if outline is drawn otherwise the result is 
 941     // 1 pixel too wide and high 
 942     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 950         // CMB: ensure dd is not larger than rectangle otherwise we 
 951         // get an hour glass shape 
 953         if (dd 
> ww
) dd 
= ww
; 
 954         if (dd 
> hh
) dd 
= hh
; 
 957         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 959             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 961                 gdk_gc_set_ts_origin( m_textGC
, 
 962                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 963                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 964                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 965                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 966                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 967                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 968                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 969                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 970                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 972             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 974                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 975                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 976                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 977                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 978                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 979                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 980                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 981                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 983             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 985                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 986                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 987                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 988                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 989                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 990                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 991                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 992                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 994             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 996                 gdk_gc_set_ts_origin( m_brushGC
, 
 997                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 998                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 999                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
1000                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
1001                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
1002                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
1003                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
1004                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
1005                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
1009                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
1010                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
1011                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
1012                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
1013                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
1014                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
1018         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
1020             gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy 
); 
1021             gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh 
); 
1022             gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr 
); 
1023             gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr 
); 
1024             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
1025             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
1026             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
1027             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
1031     // this ignores the radius 
1032     CalcBoundingBox( x
, y 
); 
1033     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
1036 void wxGTKWindowImplDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
1038     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
1040     wxCoord xx 
= XLOG2DEV(x
); 
1041     wxCoord yy 
= YLOG2DEV(y
); 
1042     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
1043     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
1045     // CMB: handle -ve width and/or height 
1046     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
1047     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
1051         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
1053             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
1055                 gdk_gc_set_ts_origin( m_textGC
, 
1056                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
1057                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
1058                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1059                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
1061             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
1063                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
1064                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1065                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
1067             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
1069                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
1070                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1071                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
1073             if (m_brush
.GetStyle() == wxSTIPPLE
) 
1075                 gdk_gc_set_ts_origin( m_brushGC
, 
1076                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
1077                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
1078                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1079                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
1083                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1087         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
1088             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1091     CalcBoundingBox( x
, y 
); 
1092     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
1095 void wxGTKWindowImplDC::DoDrawIcon( const wxIcon 
&icon
, wxCoord x
, wxCoord y 
) 
1097     // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why 
1098     DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, true ); 
1101 void wxGTKWindowImplDC::DoDrawBitmap( const wxBitmap 
&bitmap
, 
1102                                wxCoord x
, wxCoord y
, 
1105     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
1107     wxCHECK_RET( bitmap
.IsOk(), wxT("invalid bitmap") ); 
1109     bool is_mono 
= bitmap
.GetDepth() == 1; 
1111     // scale/translate size and position 
1112     int xx 
= XLOG2DEV(x
); 
1113     int yy 
= YLOG2DEV(y
); 
1115     int w 
= bitmap
.GetWidth(); 
1116     int h 
= bitmap
.GetHeight(); 
1118     if (m_owningWindow 
&& m_owningWindow
->GetLayoutDirection() == wxLayout_RightToLeft
) 
1121     CalcBoundingBox( x
, y 
); 
1122     CalcBoundingBox( x 
+ w
, y 
+ h 
); 
1124     if (!m_window
) return; 
1126     int ww 
= XLOG2DEVREL(w
); 
1127     int hh 
= YLOG2DEVREL(h
); 
1129     // compare to current clipping region 
1130     if (!m_currentClippingRegion
.IsNull()) 
1132         wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1133         tmp
.Intersect( m_currentClippingRegion 
); 
1138     // scale bitmap if required 
1139     wxBitmap use_bitmap 
= bitmap
; 
1140     if ((w 
!= ww
) || (h 
!= hh
)) 
1141         use_bitmap 
= use_bitmap
.Rescale( 0, 0, ww
, hh
, ww
, hh 
); 
1143     // NB: We can't render pixbufs with GTK+ < 2.2, we need to use pixmaps code. 
1144     //     Pixbufs-based bitmaps with alpha channel don't have a mask, so we 
1145     //     have to call GetPixmap() here -- it converts the pixbuf into pixmap 
1146     //     and also creates the mask as a side-effect: 
1147     if (gtk_check_version(2,2,0)) 
1148         use_bitmap
.GetPixmap(); 
1150     // apply mask if any 
1151     GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
1152     if (useMask 
&& use_bitmap
.GetMask()) 
1153         mask 
= use_bitmap
.GetMask()->GetBitmap(); 
1155     GdkGC
* use_gc 
= is_mono 
? m_textGC 
: m_penGC
; 
1157     GdkBitmap 
*new_mask 
= (GdkBitmap
*) NULL
; 
1161         if (!m_currentClippingRegion
.IsNull()) 
1164             new_mask 
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 ); 
1165             GdkGC 
*gc 
= gdk_gc_new( new_mask 
); 
1167             gdk_gc_set_foreground( gc
, &col 
); 
1168             gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh 
); 
1170             gdk_gc_set_background( gc
, &col 
); 
1172             gdk_gc_set_foreground( gc
, &col 
); 
1173             gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() ); 
1174             gdk_gc_set_clip_origin( gc
, -xx
, -yy 
); 
1175             gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED 
); 
1176             gdk_gc_set_stipple( gc
, mask 
); 
1177             gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh 
); 
1179             g_object_unref (gc
); 
1182         gdk_gc_set_clip_mask(use_gc
, mask
); 
1183         gdk_gc_set_clip_origin(use_gc
, xx
, yy
); 
1186     // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 
1187     // drawing a mono-bitmap (XBitmap) we use the current text GC 
1190         GdkPixmap 
*bitmap2 
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, -1 ); 
1191         GdkGC 
*gc 
= gdk_gc_new( bitmap2 
); 
1192         gdk_gc_set_foreground( gc
, m_textForegroundColour
.GetColor() ); 
1193         gdk_gc_set_background( gc
, m_textBackgroundColour
.GetColor() ); 
1194         gdk_wx_draw_bitmap( bitmap2
, gc
, use_bitmap
.GetPixmap(), 0, 0, 0, 0, -1, -1 ); 
1196         gdk_draw_drawable(m_window
, use_gc
, bitmap2
, 0, 0, xx
, yy
, -1, -1); 
1198         g_object_unref (bitmap2
); 
1199         g_object_unref (gc
); 
1203 #if GTK_CHECK_VERSION(2,2,0) 
1204         if (!gtk_check_version(2,2,0) && use_bitmap
.HasPixbuf()) 
1206             gdk_draw_pixbuf(m_window
, use_gc
, 
1207                             use_bitmap
.GetPixbuf(), 
1208                             0, 0, xx
, yy
, -1, -1, 
1209                             GDK_RGB_DITHER_NORMAL
, xx
, yy
); 
1214             gdk_draw_drawable(m_window
, use_gc
, 
1215                               use_bitmap
.GetPixmap(), 
1216                               0, 0, xx
, yy
, -1, -1); 
1220     // remove mask again if any 
1223         gdk_gc_set_clip_mask(use_gc
, NULL
); 
1224         gdk_gc_set_clip_origin(use_gc
, 0, 0); 
1225         if (!m_currentClippingRegion
.IsNull()) 
1226             gdk_gc_set_clip_region(use_gc
, m_currentClippingRegion
.GetRegion()); 
1227         if (new_mask 
!= NULL
) 
1228             g_object_unref(new_mask
); 
1232 bool wxGTKWindowImplDC::DoBlit( wxCoord xdest
, wxCoord ydest
, 
1233                          wxCoord width
, wxCoord height
, 
1235                          wxCoord xsrc
, wxCoord ysrc
, 
1238                          wxCoord xsrcMask
, wxCoord ysrcMask 
) 
1240     wxCHECK_MSG( IsOk(), false, wxT("invalid window dc") ); 
1242     wxCHECK_MSG( source
, false, wxT("invalid source dc") ); 
1244     if (!m_window
) return false; 
1246     // transform the source DC coords to the device ones 
1247     xsrc 
= source
->LogicalToDeviceX(xsrc
); 
1248     ysrc 
= source
->LogicalToDeviceY(ysrc
); 
1251     wxMemoryDC 
*memDC 
= wxDynamicCast(source
, wxMemoryDC
); 
1254         selected 
= memDC
->GetSelectedBitmap(); 
1255         if ( !selected
.IsOk() ) 
1259     bool use_bitmap_method 
= false; 
1260     bool is_mono 
= false; 
1262     if (xsrcMask 
== -1 && ysrcMask 
== -1) 
1268     if (selected
.IsOk()) 
1270         is_mono 
= (selected
.GetDepth() == 1); 
1272         // we use the "XCopyArea" way to copy a memory dc into 
1273         // a different window if the memory dc BOTH 
1274         // a) doesn't have any mask or its mask isn't used 
1278         if (useMask 
&& (selected
.GetMask())) 
1280             // we HAVE TO use the direct way for memory dcs 
1281             // that have mask since the XCopyArea doesn't know 
1283             use_bitmap_method 
= true; 
1287             // we HAVE TO use the direct way for memory dcs 
1288             // that are bitmaps because XCopyArea doesn't cope 
1289             // with different bit depths 
1290             use_bitmap_method 
= true; 
1292         else if ((xsrc 
== 0) && (ysrc 
== 0) && 
1293                  (width 
== selected
.GetWidth()) && 
1294                  (height 
== selected
.GetHeight())) 
1296             // we SHOULD use the direct way if all of the bitmap 
1297             // in the memory dc is copied in which case XCopyArea 
1298             // wouldn't be able able to boost performace by reducing 
1299             // the area to be scaled 
1300             use_bitmap_method 
= true; 
1304     CalcBoundingBox( xdest
, ydest 
); 
1305     CalcBoundingBox( xdest 
+ width
, ydest 
+ height 
); 
1307     // scale/translate size and position 
1308     wxCoord xx 
= XLOG2DEV(xdest
); 
1309     wxCoord yy 
= YLOG2DEV(ydest
); 
1311     wxCoord ww 
= XLOG2DEVREL(width
); 
1312     wxCoord hh 
= YLOG2DEVREL(height
); 
1314     // compare to current clipping region 
1315     if (!m_currentClippingRegion
.IsNull()) 
1317         wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1318         tmp
.Intersect( m_currentClippingRegion 
); 
1323     int old_logical_func 
= m_logicalFunction
; 
1324     SetLogicalFunction( logical_func 
); 
1326     if (use_bitmap_method
) 
1328         // scale/translate bitmap size 
1329         wxCoord bm_width 
= selected
.GetWidth(); 
1330         wxCoord bm_height 
= selected
.GetHeight(); 
1332         // Get clip coords for the bitmap. If we don't 
1333         // use wxBitmap::Rescale(), which can clip the 
1334         // bitmap, these are the same as the original 
1341         // interpret userscale of src too 
1343         memDC
->GetUserScale(&xsc
,&ysc
); 
1344         bm_width 
= (int) (bm_width 
/ xsc
); 
1345         bm_height 
= (int) (bm_height 
/ ysc
); 
1347         wxCoord bm_ww 
= XLOG2DEVREL( bm_width 
); 
1348         wxCoord bm_hh 
= YLOG2DEVREL( bm_height 
); 
1350         // Scale bitmap if required 
1351         wxBitmap use_bitmap 
= selected
; 
1352         if ((selected
.GetWidth()!= bm_ww
) || ( selected
.GetHeight()!= bm_hh
)) 
1354             // This indicates that the blitting code below will get 
1355             // a clipped bitmap and therefore needs to move the origin 
1357             wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1358             if (!m_currentClippingRegion
.IsNull()) 
1359                 tmp
.Intersect( m_currentClippingRegion 
); 
1360             tmp
.GetBox(cx
,cy
,cw
,ch
); 
1362             // Scale and clipped bitmap 
1363             use_bitmap 
= selected
.Rescale(cx
-xx
,cy
-yy
,cw
,ch
,bm_ww
,bm_hh
); 
1366         // apply mask if any 
1367         GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
1368         if (useMask 
&& use_bitmap
.GetMask()) 
1369             mask 
= use_bitmap
.GetMask()->GetBitmap(); 
1371         GdkGC
* use_gc 
= is_mono 
? m_textGC 
: m_penGC
; 
1373         GdkBitmap 
*new_mask 
= (GdkBitmap
*) NULL
; 
1377             if (!m_currentClippingRegion
.IsNull()) 
1380                 new_mask 
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 ); 
1381                 GdkGC 
*gc 
= gdk_gc_new( new_mask 
); 
1383                 gdk_gc_set_foreground( gc
, &col 
); 
1384                 gdk_gc_set_ts_origin( gc
, -xsrcMask
, -ysrcMask
); 
1385                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh 
); 
1387                 gdk_gc_set_background( gc
, &col 
); 
1389                 gdk_gc_set_foreground( gc
, &col 
); 
1390                 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() ); 
1391                 // was: gdk_gc_set_clip_origin( gc, -xx, -yy ); 
1392                 gdk_gc_set_clip_origin( gc
, -cx
, -cy 
); 
1393                 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED 
); 
1394                 gdk_gc_set_stipple( gc
, mask 
); 
1395                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh 
); 
1397                 g_object_unref (gc
); 
1400             gdk_gc_set_clip_mask(use_gc
, mask
); 
1401             if (new_mask 
!= NULL
) 
1402                 gdk_gc_set_clip_origin(use_gc
, cx
, cy
); 
1404                 gdk_gc_set_clip_origin(use_gc
, cx 
- xsrcMask
, cy 
- ysrcMask
); 
1407         // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 
1408         // drawing a mono-bitmap (XBitmap) we use the current text GC 
1412             GdkPixmap 
*bitmap 
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, -1 ); 
1413             GdkGC 
*gc 
= gdk_gc_new( bitmap 
); 
1414             gdk_gc_set_foreground( gc
, m_textForegroundColour
.GetColor() ); 
1415             gdk_gc_set_background( gc
, m_textBackgroundColour
.GetColor() ); 
1416             gdk_wx_draw_bitmap( bitmap
, gc
, use_bitmap
.GetPixmap(), 0, 0, 0, 0, -1, -1 ); 
1418             gdk_draw_drawable(m_window
, use_gc
, bitmap
, xsrc
, ysrc
, cx
, cy
, cw
, ch
); 
1420             g_object_unref (bitmap
); 
1421             g_object_unref (gc
); 
1425             // was: gdk_draw_drawable( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh ); 
1426             gdk_draw_drawable(m_window
, use_gc
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, cx
, cy
, cw
, ch
); 
1429         // remove mask again if any 
1432             gdk_gc_set_clip_mask(use_gc
, NULL
); 
1433             gdk_gc_set_clip_origin(use_gc
, 0, 0); 
1434             if (!m_currentClippingRegion
.IsNull()) 
1435                 gdk_gc_set_clip_region(use_gc
, m_currentClippingRegion
.GetRegion()); 
1439             g_object_unref (new_mask
); 
1441     else // use_bitmap_method 
1443         if (selected
.IsOk() && ((width 
!= ww
) || (height 
!= hh
))) 
1446             wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1447             tmp
.Intersect( m_currentClippingRegion 
); 
1448             wxCoord cx
,cy
,cw
,ch
; 
1449             tmp
.GetBox(cx
,cy
,cw
,ch
); 
1452             wxBitmap bitmap 
= selected
.Rescale( cx
-xx
, cy
-yy
, cw
, ch
, ww
, hh 
); 
1454             // draw scaled bitmap 
1455             // was: gdk_draw_drawable( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); 
1456             gdk_draw_drawable( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, cx
, cy
, -1, -1 ); 
1460             // No scaling and not a memory dc with a mask either 
1462             GdkWindow
* window 
= NULL
; 
1463             wxImplDC 
*impl 
= source
->GetImpl(); 
1464             wxGTKWindowImplDC 
*gtk_impl 
= wxDynamicCast(impl
, wxGTKWindowImplDC
); 
1466                 window 
= gtk_impl
->GetGDKWindow(); 
1468             GdkWindow
* window 
= source
->GetGDKWindow(); 
1473             // copy including child window contents 
1474             gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS 
); 
1475             gdk_draw_drawable( m_window
, m_penGC
, 
1479             gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN 
); 
1483     SetLogicalFunction( old_logical_func 
); 
1488 void wxGTKWindowImplDC::DoDrawText( const wxString 
&text
, wxCoord x
, wxCoord y 
) 
1490     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
1492     if (!m_window
) return; 
1494     if (text
.empty()) return; 
1499     wxCHECK_RET( m_context
, wxT("no Pango context") ); 
1500     wxCHECK_RET( m_layout
, wxT("no Pango layout") ); 
1501     wxCHECK_RET( m_fontdesc
, wxT("no Pango font description") ); 
1503     gdk_pango_context_set_colormap( m_context
, m_cmap 
); 
1505     bool underlined 
= m_font
.IsOk() && m_font
.GetUnderlined(); 
1507     const wxCharBuffer data 
= wxGTK_CONV( text 
); 
1510     size_t datalen 
= strlen(data
); 
1512     // in Pango >= 1.16 the "underline of leading/trailing spaces" bug 
1513     // has been fixed and thus the hack implemented below should never be used 
1514     static bool pangoOk 
= !wx_pango_version_check(1, 16, 0); 
1516     bool needshack 
= underlined 
&& !pangoOk
; 
1517     char *hackstring 
= NULL
; 
1521         // a PangoLayout which has leading/trailing spaces with underlined font 
1522         // is not correctly drawn by this pango version: Pango won't underline the spaces. 
1523         // This can be a problem; e.g. wxHTML rendering of underlined text relies on 
1524         // this behaviour. To workaround this problem, we use a special hack here 
1525         // suggested by pango maintainer Behdad Esfahbod: we prepend and append two 
1526         // empty space characters and give them a dummy colour attribute. 
1527         // This will force Pango to underline the leading/trailing spaces, too. 
1529         // need to realloc the string to prepend & append our special characters 
1530         hackstring 
= (char*)malloc((datalen
+7)*sizeof(char)); 
1532         // copy the leading U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format 
1533         strcpy(hackstring
, "\342\200\214"); 
1535         // copy the user string 
1536         memcpy(&hackstring
[3], data
, datalen
); 
1538         // copy the trailing U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format 
1539         strcpy(&hackstring
[datalen
+3], "\342\200\214"); 
1541         // the special characters that we added require 6 additional bytes: 
1544         pango_layout_set_text(m_layout
, hackstring
, datalen
); 
1548         pango_layout_set_text(m_layout
, data
, datalen
); 
1553         PangoAttrList 
*attrs 
= pango_attr_list_new(); 
1554         PangoAttribute 
*a 
= pango_attr_underline_new(PANGO_UNDERLINE_SINGLE
); 
1556         a
->end_index 
= datalen
; 
1557         pango_attr_list_insert(attrs
, a
); 
1561             // dummy colour for the leading space 
1562             a 
= pango_attr_foreground_new (0x0057, 0x52A9, 0xD614); 
1565             pango_attr_list_insert(attrs
, a
); 
1567             // dummy colour for the trailing space 
1568             a 
= pango_attr_foreground_new (0x0057, 0x52A9, 0xD614); 
1569             a
->start_index 
= datalen 
- 1; 
1570             a
->end_index 
= datalen
; 
1571             pango_attr_list_insert(attrs
, a
); 
1574         pango_layout_set_attributes(m_layout
, attrs
); 
1575         pango_attr_list_unref(attrs
); 
1580     if (fabs(m_scaleY 
- 1.0) > 0.00001) 
1582          // If there is a user or actually any scale applied to 
1583          // the device context, scale the font. 
1585          // scale font description 
1586          gint oldSize 
= pango_font_description_get_size( m_fontdesc 
); 
1587          double size 
= oldSize
; 
1588          size 
= size 
* m_scaleY
; 
1589          pango_font_description_set_size( m_fontdesc
, (gint
)size 
); 
1591          // actually apply scaled font 
1592          pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1594          pango_layout_get_pixel_size( m_layout
, &w
, &h 
); 
1595          if ( m_backgroundMode 
== wxSOLID 
) 
1597             gdk_gc_set_foreground(m_textGC
, m_textBackgroundColour
.GetColor()); 
1598             gdk_draw_rectangle(m_window
, m_textGC
, TRUE
, x
, y
, w
, h
); 
1599             gdk_gc_set_foreground(m_textGC
, m_textForegroundColour
.GetColor()); 
1603          if (m_owningWindow 
&& m_owningWindow
->GetLayoutDirection() == wxLayout_RightToLeft
) 
1604              gdk_draw_layout( m_window
, m_textGC
, x
-w
, y
, m_layout 
); 
1606              gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout 
); 
1608          // reset unscaled size 
1609          pango_font_description_set_size( m_fontdesc
, oldSize 
); 
1611          // actually apply unscaled font 
1612          pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1616         pango_layout_get_pixel_size( m_layout
, &w
, &h 
); 
1617         if ( m_backgroundMode 
== wxSOLID 
) 
1619             gdk_gc_set_foreground(m_textGC
, m_textBackgroundColour
.GetColor()); 
1620             gdk_draw_rectangle(m_window
, m_textGC
, TRUE
, x
, y
, w
, h
); 
1621             gdk_gc_set_foreground(m_textGC
, m_textForegroundColour
.GetColor()); 
1625         if (m_owningWindow 
&& m_owningWindow
->GetLayoutDirection() == wxLayout_RightToLeft
) 
1626             gdk_draw_layout( m_window
, m_textGC
, x
-w
, y
, m_layout 
); 
1628             gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout 
); 
1633         // undo underline attributes setting: 
1634         pango_layout_set_attributes(m_layout
, NULL
); 
1640     width 
= wxCoord(width 
/ m_scaleX
); 
1641     height 
= wxCoord(height 
/ m_scaleY
); 
1642     CalcBoundingBox (x 
+ width
, y 
+ height
); 
1643     CalcBoundingBox (x
, y
); 
1650 // TODO: There is an example of rotating text with GTK2 that would probably be 
1651 // a better approach here: 
1652 //           http://www.daa.com.au/pipermail/pygtk/2003-April/005052.html 
1654 void wxGTKWindowImplDC::DoDrawRotatedText( const wxString 
&text
, wxCoord x
, wxCoord y
, double angle 
) 
1657     if (!m_window 
|| text
.empty()) 
1660     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
1662     if ( wxIsNullDouble(angle
) ) 
1664         DoDrawText(text
, x
, y
); 
1671     // TODO: implement later without GdkFont for GTK 2.0 
1672     DoGetTextExtent(text
, &w
, &h
, NULL
,NULL
, &m_font
); 
1674     // draw the string normally 
1677     dc
.SelectObject(src
); 
1678     dc
.SetFont(GetFont()); 
1679     dc
.SetBackground(*wxBLACK_BRUSH
); 
1680     dc
.SetBrush(*wxBLACK_BRUSH
); 
1682     dc
.SetTextForeground( *wxWHITE 
); 
1683     dc
.DrawText(text
, 0, 0); 
1684     dc
.SelectObject(wxNullBitmap
); 
1686     // Calculate the size of the rotated bounding box. 
1687     double rad 
= DegToRad(angle
); 
1688     double dx 
= cos(rad
), 
1691     // the rectngle vertices are counted clockwise with the first one being at 
1692     // (0, 0) (or, rather, at (x, y)) 
1694            y2 
= -w
*dy
;      // y axis points to the bottom, hence minus 
1697     double x3 
= x4 
+ x2
, 
1701     wxCoord maxX 
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5), 
1702             maxY 
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5), 
1703             minX 
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5), 
1704             minY 
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5); 
1707     wxImage image 
= src
.ConvertToImage(); 
1709     image
.ConvertColourToAlpha( m_textForegroundColour
.Red(), 
1710                                 m_textForegroundColour
.Green(), 
1711                                 m_textForegroundColour
.Blue() ); 
1712     image 
= image
.Rotate( rad
, wxPoint(0,0) ); 
1714     int i_angle 
= (int) angle
; 
1715     i_angle 
= i_angle 
% 360; 
1719     if ((i_angle 
>= 90.0) && (i_angle 
< 270.0)) 
1720         xoffset 
= image
.GetWidth(); 
1722     if ((i_angle 
>= 0.0) && (i_angle 
< 180.0)) 
1723         yoffset 
= image
.GetHeight(); 
1725     if ((i_angle 
>= 0) && (i_angle 
< 90)) 
1726         yoffset 
-= (int)( cos(rad
)*h 
); 
1727     if ((i_angle 
>= 90) && (i_angle 
< 180)) 
1728         xoffset 
-= (int)( sin(rad
)*h 
); 
1729     if ((i_angle 
>= 180) && (i_angle 
< 270)) 
1730         yoffset 
-= (int)( cos(rad
)*h 
); 
1731     if ((i_angle 
>= 270) && (i_angle 
< 360)) 
1732         xoffset 
-= (int)( sin(rad
)*h 
); 
1734     int i_x 
= x 
- xoffset
; 
1735     int i_y 
= y 
- yoffset
; 
1738     DoDrawBitmap( src
, i_x
, i_y
, true ); 
1741     // it would be better to draw with non underlined font and draw the line 
1742     // manually here (it would be more straight...) 
1744     if ( m_font
.GetUnderlined() ) 
1746         gdk_draw_line( m_window
, m_textGC
, 
1747                        XLOG2DEV(x 
+ x4
), YLOG2DEV(y 
+ y4 
+ font
->descent
), 
1748                        XLOG2DEV(x 
+ x3
), YLOG2DEV(y 
+ y3 
+ font
->descent
)); 
1752     // update the bounding box 
1753     CalcBoundingBox(x 
+ minX
, y 
+ minY
); 
1754     CalcBoundingBox(x 
+ maxX
, y 
+ maxY
); 
1755 #endif // wxUSE_IMAGE 
1758 void wxGTKWindowImplDC::DoGetTextExtent(const wxString 
&string
, 
1759                                  wxCoord 
*width
, wxCoord 
*height
, 
1760                                  wxCoord 
*descent
, wxCoord 
*externalLeading
, 
1761                                  const wxFont 
*theFont
) const 
1769     if ( externalLeading 
) 
1770         *externalLeading 
= 0; 
1775     // ensure that theFont is always non-NULL 
1776     if ( !theFont 
|| !theFont
->IsOk() ) 
1777         theFont 
= wx_const_cast(wxFont 
*, &m_font
); 
1779     // and use it if it's valid 
1780     if ( theFont
->IsOk() ) 
1782         pango_layout_set_font_description
 
1785             theFont
->GetNativeFontInfo()->description
 
1789     // Set layout's text 
1790     const wxCharBuffer dataUTF8 
= wxGTK_CONV_FONT(string
, *theFont
); 
1793         // hardly ideal, but what else can we do if conversion failed? 
1797     pango_layout_set_text( m_layout
, dataUTF8
, strlen(dataUTF8
) ); 
1802         pango_layout_get_pixel_size( m_layout
, width
, &h 
); 
1803         PangoLayoutIter 
*iter 
= pango_layout_get_iter(m_layout
); 
1804         int baseline 
= pango_layout_iter_get_baseline(iter
); 
1805         pango_layout_iter_free(iter
); 
1806         *descent 
= h 
- PANGO_PIXELS(baseline
); 
1809             *height 
= (wxCoord
) h
; 
1813         pango_layout_get_pixel_size( m_layout
, width
, height 
); 
1816     // Reset old font description 
1817     if (theFont
->IsOk()) 
1818         pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1822 bool wxGTKWindowImplDC::DoGetPartialTextExtents(const wxString
& text
, 
1823                                          wxArrayInt
& widths
) const 
1825     const size_t len 
= text
.length(); 
1832     // Set layout's text 
1833     const wxCharBuffer dataUTF8 
= wxGTK_CONV_FONT(text
, m_font
); 
1836         // hardly ideal, but what else can we do if conversion failed? 
1837         wxLogLastError(wxT("DoGetPartialTextExtents")); 
1841     pango_layout_set_text( m_layout
, dataUTF8
, strlen(dataUTF8
) ); 
1843     // Calculate the position of each character based on the widths of 
1844     // the previous characters 
1846     // Code borrowed from Scintilla's PlatGTK 
1847     PangoLayoutIter 
*iter 
= pango_layout_get_iter(m_layout
); 
1849     pango_layout_iter_get_cluster_extents(iter
, NULL
, &pos
); 
1851     while (pango_layout_iter_next_cluster(iter
)) 
1853         pango_layout_iter_get_cluster_extents(iter
, NULL
, &pos
); 
1854         int position 
= PANGO_PIXELS(pos
.x
); 
1855         widths
[i
++] = position
; 
1858         widths
[i
++] = PANGO_PIXELS(pos
.x 
+ pos
.width
); 
1859     pango_layout_iter_free(iter
); 
1865 wxCoord 
wxGTKWindowImplDC::GetCharWidth() const 
1867     pango_layout_set_text( m_layout
, "H", 1 ); 
1869     pango_layout_get_pixel_size( m_layout
, &w
, NULL 
); 
1873 wxCoord 
wxGTKWindowImplDC::GetCharHeight() const 
1875     PangoFontMetrics 
*metrics 
= pango_context_get_metrics (m_context
, m_fontdesc
, pango_context_get_language(m_context
)); 
1876     wxCHECK_MSG( metrics
, -1, _T("failed to get pango font metrics") ); 
1878     wxCoord h 
= PANGO_PIXELS (pango_font_metrics_get_descent (metrics
) + 
1879                 pango_font_metrics_get_ascent (metrics
)); 
1880     pango_font_metrics_unref (metrics
); 
1884 void wxGTKWindowImplDC::Clear() 
1886     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
1888     if (!m_window
) return; 
1891     DoGetSize( &width
, &height 
); 
1892     gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height 
); 
1895 void wxGTKWindowImplDC::SetFont( const wxFont 
&font 
) 
1902             pango_font_description_free( m_fontdesc 
); 
1904         m_fontdesc 
= pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
1909             PangoContext 
*oldContext 
= m_context
; 
1911             m_context 
= m_owningWindow
->GtkGetPangoDefaultContext(); 
1913             // If we switch back/forth between different contexts 
1914             // we also have to create a new layout. I think so, 
1915             // at least, and it doesn't hurt to do it. 
1916             if (oldContext 
!= m_context
) 
1919                     g_object_unref (m_layout
); 
1921                 m_layout 
= pango_layout_new( m_context 
); 
1925         pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1929 void wxGTKWindowImplDC::SetPen( const wxPen 
&pen 
) 
1931     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
1933     if (m_pen 
== pen
) return; 
1937     if (!m_pen
.IsOk()) return; 
1939     if (!m_window
) return; 
1941     gint width 
= m_pen
.GetWidth(); 
1944         // CMB: if width is non-zero scale it with the dc 
1949         // X doesn't allow different width in x and y and so we take 
1952                    ( fabs((double) XLOG2DEVREL(width
)) + 
1953                      fabs((double) YLOG2DEVREL(width
)) ) / 2.0; 
1957             // width can't be 0 or an internal GTK error occurs inside 
1958             // gdk_gc_set_dashes() below 
1963     static const wxGTKDash dotted
[] = {1, 1}; 
1964     static const wxGTKDash short_dashed
[] = {2, 2}; 
1965     static const wxGTKDash wxCoord_dashed
[] = {2, 4}; 
1966     static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3}; 
1968     // We express dash pattern in pen width unit, so we are 
1969     // independent of zoom factor and so on... 
1971     const wxGTKDash 
*req_dash
; 
1973     GdkLineStyle lineStyle 
= GDK_LINE_SOLID
; 
1974     switch (m_pen
.GetStyle()) 
1978             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1979             req_nb_dash 
= m_pen
.GetDashCount(); 
1980             req_dash 
= (wxGTKDash
*)m_pen
.GetDash(); 
1985             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1992             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1994             req_dash 
= wxCoord_dashed
; 
1999             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
2001             req_dash 
= short_dashed
; 
2006 //            lineStyle = GDK_LINE_DOUBLE_DASH; 
2007             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
2009             req_dash 
= dotted_dashed
; 
2014         case wxSTIPPLE_MASK_OPAQUE
: 
2019             lineStyle 
= GDK_LINE_SOLID
; 
2020             req_dash 
= (wxGTKDash
*)NULL
; 
2026     if (req_dash 
&& req_nb_dash
) 
2028         wxGTKDash 
*real_req_dash 
= new wxGTKDash
[req_nb_dash
]; 
2031             for (int i 
= 0; i 
< req_nb_dash
; i
++) 
2032                 real_req_dash
[i
] = req_dash
[i
] * width
; 
2033             gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash 
); 
2034             delete[] real_req_dash
; 
2038             // No Memory. We use non-scaled dash pattern... 
2039             gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash 
); 
2043     GdkCapStyle capStyle 
= GDK_CAP_ROUND
; 
2044     switch (m_pen
.GetCap()) 
2046         case wxCAP_PROJECTING
: { capStyle 
= GDK_CAP_PROJECTING
; break; } 
2047         case wxCAP_BUTT
:       { capStyle 
= GDK_CAP_BUTT
;       break; } 
2054                 capStyle 
= GDK_CAP_NOT_LAST
; 
2058                 capStyle 
= GDK_CAP_ROUND
; 
2064     GdkJoinStyle joinStyle 
= GDK_JOIN_ROUND
; 
2065     switch (m_pen
.GetJoin()) 
2067         case wxJOIN_BEVEL
: { joinStyle 
= GDK_JOIN_BEVEL
; break; } 
2068         case wxJOIN_MITER
: { joinStyle 
= GDK_JOIN_MITER
; break; } 
2070         default:           { joinStyle 
= GDK_JOIN_ROUND
; break; } 
2073     gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle 
); 
2075     m_pen
.GetColour().CalcPixel( m_cmap 
); 
2076     gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() ); 
2079 void wxGTKWindowImplDC::SetBrush( const wxBrush 
&brush 
) 
2081     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2083     if (m_brush 
== brush
) return; 
2087     if (!m_brush
.IsOk()) return; 
2089     if (!m_window
) return; 
2091     m_brush
.GetColour().CalcPixel( m_cmap 
); 
2092     gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() ); 
2094     gdk_gc_set_fill( m_brushGC
, GDK_SOLID 
); 
2096     if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->IsOk())) 
2098         if (m_brush
.GetStipple()->GetDepth() != 1) 
2100             gdk_gc_set_fill( m_brushGC
, GDK_TILED 
); 
2101             gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() ); 
2105             gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED 
); 
2106             gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetPixmap() ); 
2110     if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
2112         gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
); 
2113         gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() ); 
2116     if (m_brush
.IsHatch()) 
2118         gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED 
); 
2119         int num 
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
; 
2120         gdk_gc_set_stipple( m_brushGC
, hatches
[num
] ); 
2124 void wxGTKWindowImplDC::SetBackground( const wxBrush 
&brush 
) 
2126    /* CMB 21/7/98: Added SetBackground. Sets background brush 
2127     * for Clear() and bg colour for shapes filled with cross-hatch brush */ 
2129     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2131     if (m_backgroundBrush 
== brush
) return; 
2133     m_backgroundBrush 
= brush
; 
2135     if (!m_backgroundBrush
.IsOk()) return; 
2137     if (!m_window
) return; 
2139     m_backgroundBrush
.GetColour().CalcPixel( m_cmap 
); 
2140     gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() ); 
2141     gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() ); 
2142     gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() ); 
2143     gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() ); 
2145     gdk_gc_set_fill( m_bgGC
, GDK_SOLID 
); 
2147     if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->IsOk())) 
2149         if (m_backgroundBrush
.GetStipple()->GetDepth() != 1) 
2151             gdk_gc_set_fill( m_bgGC
, GDK_TILED 
); 
2152             gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() ); 
2156             gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED 
); 
2157             gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() ); 
2161     if (m_backgroundBrush
.IsHatch()) 
2163         gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED 
); 
2164         int num 
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
; 
2165         gdk_gc_set_stipple( m_bgGC
, hatches
[num
] ); 
2169 void wxGTKWindowImplDC::SetLogicalFunction( int function 
) 
2171     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2173     if (m_logicalFunction 
== function
) 
2176     // VZ: shouldn't this be a CHECK? 
2183         case wxXOR
:          mode 
= GDK_XOR
;           break; 
2184         case wxINVERT
:       mode 
= GDK_INVERT
;        break; 
2185         case wxOR_REVERSE
:   mode 
= GDK_OR_REVERSE
;    break; 
2186         case wxAND_REVERSE
:  mode 
= GDK_AND_REVERSE
;   break; 
2187         case wxCLEAR
:        mode 
= GDK_CLEAR
;         break; 
2188         case wxSET
:          mode 
= GDK_SET
;           break; 
2189         case wxOR_INVERT
:    mode 
= GDK_OR_INVERT
;     break; 
2190         case wxAND
:          mode 
= GDK_AND
;           break; 
2191         case wxOR
:           mode 
= GDK_OR
;            break; 
2192         case wxEQUIV
:        mode 
= GDK_EQUIV
;         break; 
2193         case wxNAND
:         mode 
= GDK_NAND
;          break; 
2194         case wxAND_INVERT
:   mode 
= GDK_AND_INVERT
;    break; 
2195         case wxCOPY
:         mode 
= GDK_COPY
;          break; 
2196         case wxNO_OP
:        mode 
= GDK_NOOP
;          break; 
2197         case wxSRC_INVERT
:   mode 
= GDK_COPY_INVERT
;   break; 
2199         // unsupported by GTK 
2200         case wxNOR
:          mode 
= GDK_COPY
;          break; 
2202            wxFAIL_MSG( wxT("unsupported logical function") ); 
2206     m_logicalFunction 
= function
; 
2208     gdk_gc_set_function( m_penGC
, mode 
); 
2209     gdk_gc_set_function( m_brushGC
, mode 
); 
2211     // to stay compatible with wxMSW, we don't apply ROPs to the text 
2212     // operations (i.e. DrawText/DrawRotatedText). 
2213     // True, but mono-bitmaps use the m_textGC and they use ROPs as well. 
2214     gdk_gc_set_function( m_textGC
, mode 
); 
2217 void wxGTKWindowImplDC::SetTextForeground( const wxColour 
&col 
) 
2219     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2221     // don't set m_textForegroundColour to an invalid colour as we'd crash 
2222     // later then (we use m_textForegroundColour.GetColor() without checking 
2224     if ( !col
.IsOk() || (m_textForegroundColour 
== col
) ) 
2227     m_textForegroundColour 
= col
; 
2231         m_textForegroundColour
.CalcPixel( m_cmap 
); 
2232         gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
2236 void wxGTKWindowImplDC::SetTextBackground( const wxColour 
&col 
) 
2238     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2241     if ( !col
.IsOk() || (m_textBackgroundColour 
== col
) ) 
2244     m_textBackgroundColour 
= col
; 
2248         m_textBackgroundColour
.CalcPixel( m_cmap 
); 
2249         gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() ); 
2253 void wxGTKWindowImplDC::SetBackgroundMode( int mode 
) 
2255     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2257     m_backgroundMode 
= mode
; 
2259     if (!m_window
) return; 
2261     // CMB 21/7/98: fill style of cross-hatch brushes is affected by 
2262     // transparent/solid background mode 
2264     if (m_brush
.GetStyle() != wxSOLID 
&& m_brush
.GetStyle() != wxTRANSPARENT
) 
2266         gdk_gc_set_fill( m_brushGC
, 
2267           (m_backgroundMode 
== wxTRANSPARENT
) ? GDK_STIPPLED 
: GDK_OPAQUE_STIPPLED
); 
2271 void wxGTKWindowImplDC::SetPalette( const wxPalette
& WXUNUSED(palette
) ) 
2273     wxFAIL_MSG( wxT("wxGTKWindowImplDC::SetPalette not implemented") ); 
2276 void wxGTKWindowImplDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
2278     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2280     if (!m_window
) return; 
2283     rect
.x 
= XLOG2DEV(x
); 
2284     rect
.y 
= YLOG2DEV(y
); 
2285     rect
.width 
= XLOG2DEVREL(width
); 
2286     rect
.height 
= YLOG2DEVREL(height
); 
2288     if (m_owningWindow 
&& m_owningWindow
->m_wxwindow 
&&  
2289         (m_owningWindow
->GetLayoutDirection() == wxLayout_RightToLeft
)) 
2291         rect
.x 
-= rect
.width
; 
2294     if (!m_currentClippingRegion
.IsNull()) 
2295         m_currentClippingRegion
.Intersect( rect 
); 
2297         m_currentClippingRegion
.Union( rect 
); 
2299 #if USE_PAINT_REGION 
2300     if (!m_paintClippingRegion
.IsNull()) 
2301         m_currentClippingRegion
.Intersect( m_paintClippingRegion 
); 
2304     wxCoord xx
, yy
, ww
, hh
; 
2305     m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh 
); 
2307     wxImplDC::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
2309     wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
2312     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
2313     gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
2314     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
2315     gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
2318 void wxGTKWindowImplDC::DoSetClippingRegionAsRegion( const wxRegion 
®ion  
) 
2320     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2324         DestroyClippingRegion(); 
2328     if (!m_window
) return; 
2330     if (!m_currentClippingRegion
.IsNull()) 
2331         m_currentClippingRegion
.Intersect( region 
); 
2333         m_currentClippingRegion
.Union( region 
); 
2335 #if USE_PAINT_REGION 
2336     if (!m_paintClippingRegion
.IsNull()) 
2337         m_currentClippingRegion
.Intersect( m_paintClippingRegion 
); 
2340     wxCoord xx
, yy
, ww
, hh
; 
2341     m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh 
); 
2343     wxImplDC::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
2345     wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
2348     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
2349     gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
2350     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
2351     gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
2354 void wxGTKWindowImplDC::DestroyClippingRegion() 
2356     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2359     wxImplDC::DestroyClippingRegion(); 
2361     wxDC::DestroyClippingRegion(); 
2364     m_currentClippingRegion
.Clear(); 
2366 #if USE_PAINT_REGION 
2367     if (!m_paintClippingRegion
.IsEmpty()) 
2368         m_currentClippingRegion
.Union( m_paintClippingRegion 
); 
2371     if (!m_window
) return; 
2373     if (m_currentClippingRegion
.IsEmpty()) 
2375         gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle 
*) NULL 
); 
2376         gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle 
*) NULL 
); 
2377         gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle 
*) NULL 
); 
2378         gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle 
*) NULL 
); 
2382         gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
2383         gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
2384         gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
2385         gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
2389 void wxGTKWindowImplDC::Destroy() 
2391     if (m_penGC
) wxFreePoolGC( m_penGC 
); 
2392     m_penGC 
= (GdkGC
*) NULL
; 
2393     if (m_brushGC
) wxFreePoolGC( m_brushGC 
); 
2394     m_brushGC 
= (GdkGC
*) NULL
; 
2395     if (m_textGC
) wxFreePoolGC( m_textGC 
); 
2396     m_textGC 
= (GdkGC
*) NULL
; 
2397     if (m_bgGC
) wxFreePoolGC( m_bgGC 
); 
2398     m_bgGC 
= (GdkGC
*) NULL
; 
2401 void wxGTKWindowImplDC::SetDeviceOrigin( wxCoord x
, wxCoord y 
) 
2403     m_deviceOriginX 
= x
; 
2404     m_deviceOriginY 
= y
; 
2406     ComputeScaleAndOrigin(); 
2409 void wxGTKWindowImplDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp 
) 
2411     m_signX 
= (xLeftRight 
?  1 : -1); 
2412     m_signY 
= (yBottomUp  
? -1 :  1); 
2414     if (m_owningWindow 
&& m_owningWindow
->m_wxwindow 
&&  
2415         (m_owningWindow
->GetLayoutDirection() == wxLayout_RightToLeft
)) 
2418     ComputeScaleAndOrigin(); 
2421 void wxGTKWindowImplDC::ComputeScaleAndOrigin() 
2423     const wxRealPoint 
origScale(m_scaleX
, m_scaleY
); 
2426     wxImplDC::ComputeScaleAndOrigin(); 
2428     wxDC::ComputeScaleAndOrigin(); 
2431     // if scale has changed call SetPen to recalulate the line width 
2432     if ( wxRealPoint(m_scaleX
, m_scaleY
) != origScale 
&& m_pen
.IsOk() ) 
2434         // this is a bit artificial, but we need to force wxDC to think the pen 
2442 // Resolution in pixels per logical inch 
2443 wxSize 
wxGTKWindowImplDC::GetPPI() const 
2445     return wxSize( (int) (m_mm_to_pix_x 
* 25.4 + 0.5), (int) (m_mm_to_pix_y 
* 25.4 + 0.5)); 
2448 int wxGTKWindowImplDC::GetDepth() const 
2450     return gdk_drawable_get_depth(m_window
); 
2454 //----------------------------------------------------------------------------- 
2456 //----------------------------------------------------------------------------- 
2459 IMPLEMENT_ABSTRACT_CLASS(wxGTKClientImplDC
, wxGTKWindowImplDC
) 
2461 IMPLEMENT_ABSTRACT_CLASS(wxClientDC
, wxWindowDC
) 
2465 wxGTKClientImplDC::wxGTKClientImplDC( wxDC 
*owner 
) 
2466           : wxGTKWindowImplDC( owner 
) 
2470 wxGTKClientImplDC::wxGTKClientImplDC( wxDC 
*owner
, wxWindow 
*win 
) 
2471           : wxGTKWindowImplDC( owner
, win 
) 
2473 wxClientDC::wxClientDC() 
2477 wxClientDC::wxClientDC( wxWindow 
*win 
) 
2482     wxCHECK_RET( win
, _T("NULL window in wxGTKClientImplDC::wxClientDC") ); 
2484 #ifdef __WXUNIVERSAL__ 
2485     wxPoint ptOrigin 
= win
->GetClientAreaOrigin(); 
2486     SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
); 
2487     wxSize size 
= win
->GetClientSize(); 
2488     SetClippingRegion(wxPoint(0, 0), size
); 
2489 #endif // __WXUNIVERSAL__ 
2492 void wxGTKClientImplDC::DoGetSize(int *width
, int *height
) const 
2494     wxCHECK_RET( m_owningWindow
, _T("GetSize() doesn't work without window") ); 
2496     m_owningWindow
->GetClientSize( width
, height 
); 
2499 //----------------------------------------------------------------------------- 
2501 //----------------------------------------------------------------------------- 
2504 IMPLEMENT_ABSTRACT_CLASS(wxGTKPaintImplDC
, wxGTKClientImplDC
) 
2506 IMPLEMENT_ABSTRACT_CLASS(wxPaintDC
, wxClientDC
) 
2509 // Limit the paint region to the window size. Sometimes 
2510 // the paint region is too big, and this risks X11 errors 
2511 static void wxLimitRegionToSize(wxRegion
& region
, const wxSize
& sz
) 
2513     wxRect originalRect 
= region
.GetBox(); 
2514     wxRect 
rect(originalRect
); 
2515     if (rect
.width 
+ rect
.x 
> sz
.x
) 
2516         rect
.width 
= sz
.x 
- rect
.x
; 
2517     if (rect
.height 
+ rect
.y 
> sz
.y
) 
2518         rect
.height 
= sz
.y 
- rect
.y
; 
2519     if (rect 
!= originalRect
) 
2521         region 
= wxRegion(rect
); 
2522         wxLogTrace(wxT("painting"), wxT("Limiting region from %d, %d, %d, %d to %d, %d, %d, %d\n"), 
2523                    originalRect
.x
, originalRect
.y
, originalRect
.width
, originalRect
.height
, 
2524                    rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
2529 wxGTKPaintImplDC::wxGTKPaintImplDC( wxDC 
*owner 
) 
2530          : wxGTKClientImplDC( owner 
) 
2534 wxGTKPaintImplDC::wxGTKPaintImplDC( wxDC 
*owner
, wxWindow 
*win 
) 
2535          : wxGTKClientImplDC( owner
, win 
) 
2537 wxPaintDC::wxPaintDC() 
2542 wxPaintDC::wxPaintDC( wxWindow 
*win 
) 
2546 #if USE_PAINT_REGION 
2547     if (!win
->m_clipPaintRegion
) 
2550     wxSize sz 
= win
->GetSize(); 
2551     m_paintClippingRegion 
= win
->m_nativeUpdateRegion
; 
2552     wxLimitRegionToSize(m_paintClippingRegion
, sz
); 
2554     GdkRegion 
*region 
= m_paintClippingRegion
.GetRegion(); 
2557         m_currentClippingRegion
.Union( m_paintClippingRegion 
); 
2558         wxLimitRegionToSize(m_currentClippingRegion
, sz
); 
2560         if (sz
.x 
<= 0 || sz
.y 
<= 0) 
2563         gdk_gc_set_clip_region( m_penGC
, region 
); 
2564         gdk_gc_set_clip_region( m_brushGC
, region 
); 
2565         gdk_gc_set_clip_region( m_textGC
, region 
); 
2566         gdk_gc_set_clip_region( m_bgGC
, region 
); 
2568 #endif // USE_PAINT_REGION 
2571 // ---------------------------------------------------------------------------- 
2573 // ---------------------------------------------------------------------------- 
2575 class wxDCModule 
: public wxModule
 
2582     DECLARE_DYNAMIC_CLASS(wxDCModule
) 
2585 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
) 
2587 bool wxDCModule::OnInit() 
2593 void wxDCModule::OnExit()