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/gtk/dcclient.h" 
  20     #include "wx/window.h" 
  22     #include "wx/dcmemory.h" 
  25     #include "wx/module.h" 
  28 #include "wx/fontutil.h" 
  30 #include "wx/gtk/private.h" 
  34 //----------------------------------------------------------------------------- 
  36 //----------------------------------------------------------------------------- 
  38 #define XLOG2DEV(x)    LogicalToDeviceX(x) 
  39 #define XLOG2DEVREL(x) LogicalToDeviceXRel(x) 
  40 #define YLOG2DEV(y)    LogicalToDeviceY(y) 
  41 #define YLOG2DEVREL(y) LogicalToDeviceYRel(y) 
  43 #define USE_PAINT_REGION 1 
  45 //----------------------------------------------------------------------------- 
  47 //----------------------------------------------------------------------------- 
  56 static GdkPixmap
* hatches
[wxBRUSHSTYLE_LAST_HATCH 
- wxBRUSHSTYLE_FIRST_HATCH 
+ 1]; 
  58 extern GtkWidget 
*wxGetRootWindow(); 
  60 //----------------------------------------------------------------------------- 
  62 //----------------------------------------------------------------------------- 
  64 static const double RAD2DEG  
= 180.0 / M_PI
; 
  66 // ---------------------------------------------------------------------------- 
  68 // ---------------------------------------------------------------------------- 
  70 static inline double dmax(double a
, double b
) { return a 
> b 
? a 
: b
; } 
  71 static inline double dmin(double a
, double b
) { return a 
< b 
? a 
: b
; } 
  73 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
  75 static GdkPixmap
* GetHatch(int style
) 
  77     wxASSERT(style 
>= wxBRUSHSTYLE_FIRST_HATCH 
&& style 
<= wxBRUSHSTYLE_LAST_HATCH
); 
  78     const int i 
= style 
- wxBRUSHSTYLE_FIRST_HATCH
; 
  79     if (hatches
[i
] == NULL
) 
  83         case wxBRUSHSTYLE_BDIAGONAL_HATCH
: 
  84             hatches
[i
] = gdk_bitmap_create_from_data(NULL
, bdiag_bits
, bdiag_width
, bdiag_height
); 
  86         case wxBRUSHSTYLE_CROSSDIAG_HATCH
: 
  87             hatches
[i
] = gdk_bitmap_create_from_data(NULL
, cdiag_bits
, cdiag_width
, cdiag_height
); 
  89         case wxBRUSHSTYLE_CROSS_HATCH
: 
  90             hatches
[i
] = gdk_bitmap_create_from_data(NULL
, cross_bits
, cross_width
, cross_height
); 
  92         case wxBRUSHSTYLE_FDIAGONAL_HATCH
: 
  93             hatches
[i
] = gdk_bitmap_create_from_data(NULL
, fdiag_bits
, fdiag_width
, fdiag_height
); 
  95         case wxBRUSHSTYLE_HORIZONTAL_HATCH
: 
  96             hatches
[i
] = gdk_bitmap_create_from_data(NULL
, horiz_bits
, horiz_width
, horiz_height
); 
  98         case wxBRUSHSTYLE_VERTICAL_HATCH
: 
  99             hatches
[i
] = gdk_bitmap_create_from_data(NULL
, verti_bits
, verti_width
, verti_height
); 
 106 //----------------------------------------------------------------------------- 
 107 // temporary implementation of the missing GDK function 
 108 //----------------------------------------------------------------------------- 
 111 void gdk_wx_draw_bitmap(GdkDrawable  
*drawable
, 
 117     wxCHECK_RET( drawable
, _T("NULL drawable in gdk_wx_draw_bitmap") ); 
 118     wxCHECK_RET( src
, _T("NULL src in gdk_wx_draw_bitmap") ); 
 119     wxCHECK_RET( gc
, _T("NULL gc in gdk_wx_draw_bitmap") ); 
 121     gint src_width
, src_height
; 
 122     gdk_drawable_get_size(src
, &src_width
, &src_height
); 
 124     XCopyPlane( GDK_WINDOW_XDISPLAY(drawable
), 
 126                 GDK_WINDOW_XID(drawable
), 
 129                 src_width
, src_height
, 
 134 //----------------------------------------------------------------------------- 
 135 // Implement Pool of Graphic contexts. Creating them takes too much time. 
 136 //----------------------------------------------------------------------------- 
 162 #define GC_POOL_ALLOC_SIZE 100 
 164 static int wxGCPoolSize 
= 0; 
 166 static wxGC 
*wxGCPool 
= NULL
; 
 168 static void wxInitGCPool() 
 170     // This really could wait until the first call to 
 171     // wxGetPoolGC, but we will make the first allocation 
 172     // now when other initialization is being performed. 
 174     // Set initial pool size. 
 175     wxGCPoolSize 
= GC_POOL_ALLOC_SIZE
; 
 177     // Allocate initial pool. 
 178     wxGCPool 
= (wxGC 
*)malloc(wxGCPoolSize 
* sizeof(wxGC
)); 
 179     if (wxGCPool 
== NULL
) 
 181         // If we cannot malloc, then fail with error 
 182         // when debug is enabled.  If debug is not enabled, 
 183         // the problem will eventually get caught 
 185         wxFAIL_MSG( wxT("Cannot allocate GC pool") ); 
 189     // Zero initial pool. 
 190     memset(wxGCPool
, 0, wxGCPoolSize 
* sizeof(wxGC
)); 
 193 static void wxCleanUpGCPool() 
 195     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 197         if (wxGCPool
[i
].m_gc
) 
 198             g_object_unref (wxGCPool
[i
].m_gc
); 
 206 static GdkGC
* wxGetPoolGC( GdkWindow 
*window
, wxPoolGCType type 
) 
 210     // Look for an available GC. 
 211     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 213         if (!wxGCPool
[i
].m_gc
) 
 215             wxGCPool
[i
].m_gc 
= gdk_gc_new( window 
); 
 216             gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE 
); 
 217             wxGCPool
[i
].m_type 
= type
; 
 218             wxGCPool
[i
].m_used 
= false; 
 220         if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type 
== type
)) 
 222             wxGCPool
[i
].m_used 
= true; 
 223             return wxGCPool
[i
].m_gc
; 
 227     // We did not find an available GC. 
 228     // We need to grow the GC pool. 
 229     pptr 
= (wxGC 
*)realloc(wxGCPool
, 
 230         (wxGCPoolSize 
+ GC_POOL_ALLOC_SIZE
)*sizeof(wxGC
)); 
 233         // Initialize newly allocated pool. 
 235         memset(&wxGCPool
[wxGCPoolSize
], 0, 
 236             GC_POOL_ALLOC_SIZE
*sizeof(wxGC
)); 
 238         // Initialize entry we will return. 
 239         wxGCPool
[wxGCPoolSize
].m_gc 
= gdk_gc_new( window 
); 
 240         gdk_gc_set_exposures( wxGCPool
[wxGCPoolSize
].m_gc
, FALSE 
); 
 241         wxGCPool
[wxGCPoolSize
].m_type 
= type
; 
 242         wxGCPool
[wxGCPoolSize
].m_used 
= true; 
 244         // Set new value of pool size. 
 245         wxGCPoolSize 
+= GC_POOL_ALLOC_SIZE
; 
 247         // Return newly allocated entry. 
 248         return wxGCPool
[wxGCPoolSize
-GC_POOL_ALLOC_SIZE
].m_gc
; 
 251     // The realloc failed.  Fall through to error. 
 252     wxFAIL_MSG( wxT("No GC available") ); 
 254     return (GdkGC
*) NULL
; 
 257 static void wxFreePoolGC( GdkGC 
*gc 
) 
 259     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 261         if (wxGCPool
[i
].m_gc 
== gc
) 
 263             wxGCPool
[i
].m_used 
= false; 
 268     wxFAIL_MSG( wxT("Wrong GC") ); 
 271 //----------------------------------------------------------------------------- 
 273 //----------------------------------------------------------------------------- 
 275 IMPLEMENT_ABSTRACT_CLASS(wxWindowDCImpl
, wxGTKDCImpl
) 
 277 wxWindowDCImpl::wxWindowDCImpl( wxDC 
*owner 
) : 
 280     m_gdkwindow 
= (GdkWindow
*) NULL
; 
 281     m_penGC 
= (GdkGC 
*) NULL
; 
 282     m_brushGC 
= (GdkGC 
*) NULL
; 
 283     m_textGC 
= (GdkGC 
*) NULL
; 
 284     m_bgGC 
= (GdkGC 
*) NULL
; 
 285     m_cmap 
= (GdkColormap 
*) NULL
; 
 286     m_isScreenDC 
= false; 
 287     m_context 
= (PangoContext 
*)NULL
; 
 288     m_layout 
= (PangoLayout 
*)NULL
; 
 289     m_fontdesc 
= (PangoFontDescription 
*)NULL
; 
 292 wxWindowDCImpl::wxWindowDCImpl( wxDC 
*owner
, wxWindow 
*window 
) : 
 295     wxASSERT_MSG( window
, wxT("DC needs a window") ); 
 297     m_gdkwindow 
= (GdkWindow
*) NULL
; 
 298     m_penGC 
= (GdkGC 
*) NULL
; 
 299     m_brushGC 
= (GdkGC 
*) NULL
; 
 300     m_textGC 
= (GdkGC 
*) NULL
; 
 301     m_bgGC 
= (GdkGC 
*) NULL
; 
 302     m_cmap 
= (GdkColormap 
*) NULL
; 
 303     m_isScreenDC 
= false; 
 304     m_font 
= window
->GetFont(); 
 306     GtkWidget 
*widget 
= window
->m_wxwindow
; 
 308     // Some controls don't have m_wxwindow - like wxStaticBox, but the user 
 309     // code should still be able to create wxClientDCs for them, so we will 
 310     // use the parent window here then. 
 313         window 
= window
->GetParent(); 
 314         widget 
= window
->m_wxwindow
; 
 317     wxASSERT_MSG( widget
, wxT("DC needs a widget") ); 
 319     m_context 
= window
->GtkGetPangoDefaultContext(); 
 320     m_layout 
= pango_layout_new( m_context 
); 
 321     m_fontdesc 
= pango_font_description_copy( widget
->style
->font_desc 
); 
 323     m_gdkwindow 
= widget
->window
; 
 325     // Window not realized ? 
 328          // Don't report problems as per MSW. 
 334     m_cmap 
= gtk_widget_get_colormap( widget 
? widget 
: window
->m_widget 
); 
 338     /* this must be done after SetUpDC, bacause SetUpDC calls the 
 339        repective SetBrush, SetPen, SetBackground etc functions 
 340        to set up the DC. SetBackground call m_owner->SetBackground 
 341        and this might not be desired as the standard dc background 
 342        is white whereas a window might assume gray to be the 
 343        standard (as e.g. wxStatusBar) */ 
 347     if (m_window 
&& m_window
->m_wxwindow 
&&  
 348         (m_window
->GetLayoutDirection() == wxLayout_RightToLeft
)) 
 353         // origin in the upper right corner 
 354         m_deviceOriginX 
= m_window
->GetClientSize().x
; 
 358 wxWindowDCImpl::~wxWindowDCImpl() 
 363         g_object_unref (m_layout
); 
 365         pango_font_description_free( m_fontdesc 
); 
 368 void wxWindowDCImpl::SetUpDC( bool isMemDC 
) 
 372     wxASSERT_MSG( !m_penGC
, wxT("GCs already created") ); 
 376     if ((isMemDC
) && (GetSelectedBitmap().IsOk())) 
 378         if (GetSelectedBitmap().GetDepth() == 1) 
 380             m_penGC 
= wxGetPoolGC( m_gdkwindow
, wxPEN_MONO 
); 
 381             m_brushGC 
= wxGetPoolGC( m_gdkwindow
, wxBRUSH_MONO 
); 
 382             m_textGC 
= wxGetPoolGC( m_gdkwindow
, wxTEXT_MONO 
); 
 383             m_bgGC 
= wxGetPoolGC( m_gdkwindow
, wxBG_MONO 
); 
 392             m_penGC 
= wxGetPoolGC( m_gdkwindow
, wxPEN_SCREEN 
); 
 393             m_brushGC 
= wxGetPoolGC( m_gdkwindow
, wxBRUSH_SCREEN 
); 
 394             m_textGC 
= wxGetPoolGC( m_gdkwindow
, wxTEXT_SCREEN 
); 
 395             m_bgGC 
= wxGetPoolGC( m_gdkwindow
, wxBG_SCREEN 
); 
 399             m_penGC 
= wxGetPoolGC( m_gdkwindow
, wxPEN_COLOUR 
); 
 400             m_brushGC 
= wxGetPoolGC( m_gdkwindow
, wxBRUSH_COLOUR 
); 
 401             m_textGC 
= wxGetPoolGC( m_gdkwindow
, wxTEXT_COLOUR 
); 
 402             m_bgGC 
= wxGetPoolGC( m_gdkwindow
, wxBG_COLOUR 
); 
 406     /* background colour */ 
 407     m_backgroundBrush 
= *wxWHITE_BRUSH
; 
 408     m_backgroundBrush
.GetColour().CalcPixel( m_cmap 
); 
 409     const GdkColor 
*bg_col 
= m_backgroundBrush
.GetColour().GetColor(); 
 412     m_textForegroundColour
.CalcPixel( m_cmap 
); 
 413     gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
 415     m_textBackgroundColour
.CalcPixel( m_cmap 
); 
 416     gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() ); 
 418     gdk_gc_set_fill( m_textGC
, GDK_SOLID 
); 
 420     gdk_gc_set_colormap( m_textGC
, m_cmap 
); 
 423     m_pen
.GetColour().CalcPixel( m_cmap 
); 
 424     gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() ); 
 425     gdk_gc_set_background( m_penGC
, bg_col 
); 
 427     gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND 
); 
 430     m_brush
.GetColour().CalcPixel( m_cmap 
); 
 431     gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() ); 
 432     gdk_gc_set_background( m_brushGC
, bg_col 
); 
 434     gdk_gc_set_fill( m_brushGC
, GDK_SOLID 
); 
 437     gdk_gc_set_background( m_bgGC
, bg_col 
); 
 438     gdk_gc_set_foreground( m_bgGC
, bg_col 
); 
 440     gdk_gc_set_fill( m_bgGC
, GDK_SOLID 
); 
 443     gdk_gc_set_function( m_textGC
, GDK_COPY 
); 
 444     gdk_gc_set_function( m_brushGC
, GDK_COPY 
); 
 445     gdk_gc_set_function( m_penGC
, GDK_COPY 
); 
 448     gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle 
*) NULL 
); 
 449     gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle 
*) NULL 
); 
 450     gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle 
*) NULL 
); 
 451     gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle 
*) NULL 
); 
 454 void wxWindowDCImpl::DoGetSize( int* width
, int* height 
) const 
 456     wxCHECK_RET( m_window
, _T("GetSize() doesn't work without window") ); 
 458     m_window
->GetSize(width
, height
); 
 461 bool wxWindowDCImpl::DoFloodFill(wxCoord x
, wxCoord y
, 
 462                              const wxColour
& col
, int style
) 
 465     extern bool wxDoFloodFill(wxDC 
*dc
, wxCoord x
, wxCoord y
, 
 466                               const wxColour 
& col
, int style
); 
 468     return wxDoFloodFill( GetOwner(), x
, y
, col
, style
); 
 479 bool wxWindowDCImpl::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour 
*col 
) const 
 482     // Generic (and therefore rather inefficient) method. 
 483     // Could be improved. 
 485     wxBitmap 
bitmap(1, 1); 
 486     memdc
.SelectObject(bitmap
); 
 487     memdc
.Blit(0, 0, 1, 1, GetOwner(), x1
, y1
); 
 488     memdc
.SelectObject(wxNullBitmap
); 
 490     wxImage image 
= bitmap
.ConvertToImage(); 
 491     col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0)); 
 493 #else // !wxUSE_IMAGE 
 499 #endif // wxUSE_IMAGE/!wxUSE_IMAGE 
 502 void wxWindowDCImpl::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2 
) 
 504     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 506     if (m_pen
.GetStyle() != wxPENSTYLE_TRANSPARENT
) 
 509             gdk_draw_line( m_gdkwindow
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) ); 
 511         CalcBoundingBox(x1
, y1
); 
 512         CalcBoundingBox(x2
, y2
); 
 516 void wxWindowDCImpl::DoCrossHair( wxCoord x
, wxCoord y 
) 
 518     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 520     if (m_pen
.GetStyle() != wxPENSTYLE_TRANSPARENT
) 
 524         GetOwner()->GetSize( &w
, &h 
); 
 525         wxCoord xx 
= XLOG2DEV(x
); 
 526         wxCoord yy 
= YLOG2DEV(y
); 
 529             gdk_draw_line( m_gdkwindow
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy 
); 
 530             gdk_draw_line( m_gdkwindow
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) ); 
 535 void wxWindowDCImpl::DrawingSetup(GdkGC
*& gc
, bool& originChanged
) 
 538     GdkPixmap
* pixmap 
= NULL
; 
 539     const int style 
= m_brush
.GetStyle(); 
 541     if (style 
== wxBRUSHSTYLE_STIPPLE 
|| style 
== wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE
) 
 543         const wxBitmap
* stipple 
= m_brush
.GetStipple(); 
 546             if (style 
== wxBRUSHSTYLE_STIPPLE
) 
 547                 pixmap 
= stipple
->GetPixmap(); 
 548             else if (stipple
->GetMask()) 
 550                 pixmap 
= stipple
->GetPixmap(); 
 555     else if (m_brush
.IsHatch()) 
 557         pixmap 
= GetHatch(style
); 
 565         gdk_drawable_get_size(pixmap
, &w
, &h
); 
 566         origin_x 
= m_deviceOriginX 
% w
; 
 567         origin_y 
= m_deviceOriginY 
% h
; 
 570     originChanged 
= origin_x 
|| origin_y
; 
 572         gdk_gc_set_ts_origin(gc
, origin_x
, origin_y
); 
 575 void wxWindowDCImpl::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, 
 576                             wxCoord xc
, wxCoord yc 
) 
 578     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 580     wxCoord xx1 
= XLOG2DEV(x1
); 
 581     wxCoord yy1 
= YLOG2DEV(y1
); 
 582     wxCoord xx2 
= XLOG2DEV(x2
); 
 583     wxCoord yy2 
= YLOG2DEV(y2
); 
 584     wxCoord xxc 
= XLOG2DEV(xc
); 
 585     wxCoord yyc 
= YLOG2DEV(yc
); 
 586     double dx 
= xx1 
- xxc
; 
 587     double dy 
= yy1 
- yyc
; 
 588     double radius 
= sqrt((double)(dx
*dx
+dy
*dy
)); 
 589     wxCoord   r      
= (wxCoord
)radius
; 
 590     double radius1
, radius2
; 
 592     if (xx1 
== xx2 
&& yy1 
== yy2
) 
 597     else if ( wxIsNullDouble(radius
) ) 
 604         radius1 
= (xx1 
- xxc 
== 0) ? 
 605             (yy1 
- yyc 
< 0) ? 90.0 : -90.0 : 
 606             -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
; 
 607         radius2 
= (xx2 
- xxc 
== 0) ? 
 608             (yy2 
- yyc 
< 0) ? 90.0 : -90.0 : 
 609             -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
; 
 611     wxCoord alpha1 
= wxCoord(radius1 
* 64.0); 
 612     wxCoord alpha2 
= wxCoord((radius2 
- radius1
) * 64.0); 
 613     while (alpha2 
<= 0) alpha2 
+= 360*64; 
 614     while (alpha1 
> 360*64) alpha1 
-= 360*64; 
 618         if (m_brush
.GetStyle() != wxBRUSHSTYLE_TRANSPARENT
) 
 622             DrawingSetup(gc
, originChanged
); 
 624             gdk_draw_arc(m_gdkwindow
, gc
, true, xxc
-r
, yyc
-r
, 2*r
, 2*r
, alpha1
, alpha2
); 
 627                 gdk_gc_set_ts_origin(gc
, 0, 0); 
 630         if (m_pen
.GetStyle() != wxPENSTYLE_TRANSPARENT
) 
 632             gdk_draw_arc( m_gdkwindow
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 634             if ((m_brush
.GetStyle() != wxBRUSHSTYLE_TRANSPARENT
) && (alpha2 
- alpha1 
!= 360*64)) 
 636                 gdk_draw_line( m_gdkwindow
, m_penGC
, xx1
, yy1
, xxc
, yyc 
); 
 637                 gdk_draw_line( m_gdkwindow
, m_penGC
, xxc
, yyc
, xx2
, yy2 
); 
 642     CalcBoundingBox (x1
, y1
); 
 643     CalcBoundingBox (x2
, y2
); 
 646 void wxWindowDCImpl::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea 
) 
 648     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 650     wxCoord xx 
= XLOG2DEV(x
); 
 651     wxCoord yy 
= YLOG2DEV(y
); 
 652     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 653     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 655     // CMB: handle -ve width and/or height 
 656     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 657     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 661         wxCoord start 
= wxCoord(sa 
* 64.0); 
 662         wxCoord end 
= wxCoord((ea
-sa
) * 64.0); 
 664         if (m_brush
.GetStyle() != wxBRUSHSTYLE_TRANSPARENT
) 
 668             DrawingSetup(gc
, originChanged
); 
 670             gdk_draw_arc(m_gdkwindow
, gc
, true, xx
, yy
, ww
, hh
, start
, end
); 
 673                 gdk_gc_set_ts_origin(gc
, 0, 0); 
 676         if (m_pen
.GetStyle() != wxPENSTYLE_TRANSPARENT
) 
 677             gdk_draw_arc( m_gdkwindow
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end 
); 
 680     CalcBoundingBox (x
, y
); 
 681     CalcBoundingBox (x 
+ width
, y 
+ height
); 
 684 void wxWindowDCImpl::DoDrawPoint( wxCoord x
, wxCoord y 
) 
 686     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 688     if ((m_pen
.GetStyle() != wxPENSTYLE_TRANSPARENT
) && m_gdkwindow
) 
 689         gdk_draw_point( m_gdkwindow
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) ); 
 691     CalcBoundingBox (x
, y
); 
 694 void wxWindowDCImpl::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset 
) 
 696     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 698     if (m_pen
.GetStyle() == wxPENSTYLE_TRANSPARENT
) return; 
 701     //Check, if scaling is necessary 
 703         xoffset 
!= 0 || yoffset 
!= 0 || XLOG2DEV(10) != 10 || YLOG2DEV(10) != 10; 
 705     // GdkPoint and wxPoint have the same memory layout, so we can cast one to the other 
 706     GdkPoint
* gpts 
= reinterpret_cast<GdkPoint
*>(points
); 
 709         gpts 
= new GdkPoint
[n
]; 
 711     for (int i 
= 0; i 
< n
; i
++) 
 715             gpts
[i
].x 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 716             gpts
[i
].y 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 718         CalcBoundingBox(points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 722         gdk_draw_lines( m_gdkwindow
, m_penGC
, gpts
, n
); 
 728 void wxWindowDCImpl::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) ) 
 730     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 734     //Check, if scaling is necessary 
 736         xoffset 
!= 0 || yoffset 
!= 0 || XLOG2DEV(10) != 10 || YLOG2DEV(10) != 10; 
 738     // GdkPoint and wxPoint have the same memory layout, so we can cast one to the other 
 739     GdkPoint
* gdkpoints 
= reinterpret_cast<GdkPoint
*>(points
); 
 742         gdkpoints 
= new GdkPoint
[n
]; 
 745     for (i 
= 0 ; i 
< n 
; i
++) 
 749             gdkpoints
[i
].x 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 750             gdkpoints
[i
].y 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 752         CalcBoundingBox(points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset
); 
 757         if (m_brush
.GetStyle() != wxBRUSHSTYLE_TRANSPARENT
) 
 761             DrawingSetup(gc
, originChanged
); 
 763             gdk_draw_polygon(m_gdkwindow
, gc
, true, gdkpoints
, n
); 
 766                 gdk_gc_set_ts_origin(gc
, 0, 0); 
 769         if (m_pen
.GetStyle() != wxPENSTYLE_TRANSPARENT
) 
 772             for (i = 0 ; i < n ; i++) 
 774                 gdk_draw_line( m_gdkwindow, m_penGC, 
 777                                gdkpoints[(i+1)%n].x, 
 778                                gdkpoints[(i+1)%n].y); 
 781             gdk_draw_polygon( m_gdkwindow
, m_penGC
, FALSE
, gdkpoints
, n 
); 
 790 void wxWindowDCImpl::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 792     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 794     wxCoord xx 
= XLOG2DEV(x
); 
 795     wxCoord yy 
= YLOG2DEV(y
); 
 796     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 797     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 799     // CMB: draw nothing if transformed w or h is 0 
 800     if (ww 
== 0 || hh 
== 0) return; 
 802     // CMB: handle -ve width and/or height 
 803     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 804     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 808         if (m_brush
.GetStyle() != wxBRUSHSTYLE_TRANSPARENT
) 
 812             DrawingSetup(gc
, originChanged
); 
 814             gdk_draw_rectangle(m_gdkwindow
, gc
, true, xx
, yy
, ww
, hh
); 
 817                 gdk_gc_set_ts_origin(gc
, 0, 0); 
 820         if (m_pen
.GetStyle() != wxPENSTYLE_TRANSPARENT
) 
 823             if ((m_pen
.GetWidth() == 2) && (m_pen
.GetCap() == wxCAP_ROUND
) && 
 824                 (m_pen
.GetJoin() == wxJOIN_ROUND
) && (m_pen
.GetStyle() == wxPENSTYLE_SOLID
)) 
 826                 // Use 2 1-line rects instead 
 827                 gdk_gc_set_line_attributes( m_penGC
, 1, GDK_LINE_SOLID
, GDK_CAP_ROUND
, GDK_JOIN_ROUND 
); 
 832                     gdk_draw_rectangle( m_gdkwindow
, m_penGC
, FALSE
, xx
+1, yy
, ww
-2, hh
-2 ); 
 833                     gdk_draw_rectangle( m_gdkwindow
, m_penGC
, FALSE
, xx
, yy
-1, ww
, hh 
); 
 837                     gdk_draw_rectangle( m_gdkwindow
, m_penGC
, FALSE
, xx
, yy
, ww
-2, hh
-2 ); 
 838                     gdk_draw_rectangle( m_gdkwindow
, m_penGC
, FALSE
, xx
-1, yy
-1, ww
, hh 
); 
 842                 gdk_gc_set_line_attributes( m_penGC
, 2, GDK_LINE_SOLID
, GDK_CAP_ROUND
, GDK_JOIN_ROUND 
); 
 847                 // Just use X11 for other cases 
 848                 gdk_draw_rectangle( m_gdkwindow
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 ); 
 853     CalcBoundingBox( x
, y 
); 
 854     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 857 void wxWindowDCImpl::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius 
) 
 859     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 861     if (radius 
< 0.0) radius 
= - radius 
* ((width 
< height
) ? width 
: height
); 
 863     wxCoord xx 
= XLOG2DEV(x
); 
 864     wxCoord yy 
= YLOG2DEV(y
); 
 865     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 866     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 867     wxCoord rr 
= XLOG2DEVREL((wxCoord
)radius
); 
 869     // CMB: handle -ve width and/or height 
 870     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 871     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 873     // CMB: if radius is zero use DrawRectangle() instead to avoid 
 874     // X drawing errors with small radii 
 877         DoDrawRectangle( x
, y
, width
, height 
); 
 881     // CMB: draw nothing if transformed w or h is 0 
 882     if (ww 
== 0 || hh 
== 0) return; 
 884     // CMB: adjust size if outline is drawn otherwise the result is 
 885     // 1 pixel too wide and high 
 886     if (m_pen
.GetStyle() != wxPENSTYLE_TRANSPARENT
) 
 894         // CMB: ensure dd is not larger than rectangle otherwise we 
 895         // get an hour glass shape 
 897         if (dd 
> ww
) dd 
= ww
; 
 898         if (dd 
> hh
) dd 
= hh
; 
 901         if (m_brush
.GetStyle() != wxBRUSHSTYLE_TRANSPARENT
) 
 905             DrawingSetup(gc
, originChanged
); 
 907             gdk_draw_rectangle(m_gdkwindow
, gc
, true, xx
+rr
, yy
, ww
-dd
+1, hh
); 
 908             gdk_draw_rectangle(m_gdkwindow
, gc
, true, xx
, yy
+rr
, ww
, hh
-dd
+1); 
 909             gdk_draw_arc(m_gdkwindow
, gc
, true, xx
, yy
, dd
, dd
, 90*64, 90*64); 
 910             gdk_draw_arc(m_gdkwindow
, gc
, true, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64); 
 911             gdk_draw_arc(m_gdkwindow
, gc
, true, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64); 
 912             gdk_draw_arc(m_gdkwindow
, gc
, true, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64); 
 915                 gdk_gc_set_ts_origin(gc
, 0, 0); 
 918         if (m_pen
.GetStyle() != wxPENSTYLE_TRANSPARENT
) 
 920             gdk_draw_line( m_gdkwindow
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy 
); 
 921             gdk_draw_line( m_gdkwindow
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh 
); 
 922             gdk_draw_line( m_gdkwindow
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr 
); 
 923             gdk_draw_line( m_gdkwindow
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr 
); 
 924             gdk_draw_arc( m_gdkwindow
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 925             gdk_draw_arc( m_gdkwindow
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 926             gdk_draw_arc( m_gdkwindow
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 927             gdk_draw_arc( m_gdkwindow
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 931     // this ignores the radius 
 932     CalcBoundingBox( x
, y 
); 
 933     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 936 void wxWindowDCImpl::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 938     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 940     wxCoord xx 
= XLOG2DEV(x
); 
 941     wxCoord yy 
= YLOG2DEV(y
); 
 942     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 943     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 945     // CMB: handle -ve width and/or height 
 946     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 947     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 951         if (m_brush
.GetStyle() != wxBRUSHSTYLE_TRANSPARENT
) 
 955             DrawingSetup(gc
, originChanged
); 
 957             gdk_draw_arc(m_gdkwindow
, gc
, true, xx
, yy
, ww
, hh
, 0, 360*64); 
 960                 gdk_gc_set_ts_origin(gc
, 0, 0); 
 963         if (m_pen
.GetStyle() != wxPENSTYLE_TRANSPARENT
) 
 964             gdk_draw_arc( m_gdkwindow
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
 967     CalcBoundingBox( x
, y 
); 
 968     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 971 void wxWindowDCImpl::DoDrawIcon( const wxIcon 
&icon
, wxCoord x
, wxCoord y 
) 
 973     // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why 
 974     DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, true ); 
 977 void wxWindowDCImpl::DoDrawBitmap( const wxBitmap 
&bitmap
, 
 978                                wxCoord x
, wxCoord y
, 
 981     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
 983     wxCHECK_RET( bitmap
.IsOk(), wxT("invalid bitmap") ); 
 985     bool is_mono 
= bitmap
.GetDepth() == 1; 
 987     // scale/translate size and position 
 988     int xx 
= XLOG2DEV(x
); 
 989     int yy 
= YLOG2DEV(y
); 
 991     int w 
= bitmap
.GetWidth(); 
 992     int h 
= bitmap
.GetHeight(); 
 994     if (m_window 
&& m_window
->GetLayoutDirection() == wxLayout_RightToLeft
) 
 997     CalcBoundingBox( x
, y 
); 
 998     CalcBoundingBox( x 
+ w
, y 
+ h 
); 
1000     if (!m_gdkwindow
) return; 
1002     int ww 
= XLOG2DEVREL(w
); 
1003     int hh 
= YLOG2DEVREL(h
); 
1005     // compare to current clipping region 
1006     if (!m_currentClippingRegion
.IsNull()) 
1008         wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1009         tmp
.Intersect( m_currentClippingRegion 
); 
1014     // scale bitmap if required 
1015     wxBitmap use_bitmap 
= bitmap
; 
1016     if ((w 
!= ww
) || (h 
!= hh
)) 
1017         use_bitmap 
= use_bitmap
.Rescale( 0, 0, ww
, hh
, ww
, hh 
); 
1019     // apply mask if any 
1020     GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
1021     if (useMask 
&& use_bitmap
.GetMask()) 
1022         mask 
= use_bitmap
.GetMask()->GetBitmap(); 
1024     GdkGC
* use_gc 
= is_mono 
? m_textGC 
: m_penGC
; 
1026     GdkBitmap 
*new_mask 
= (GdkBitmap
*) NULL
; 
1030         if (!m_currentClippingRegion
.IsNull()) 
1033             new_mask 
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 ); 
1034             GdkGC 
*gc 
= gdk_gc_new( new_mask 
); 
1036             gdk_gc_set_foreground( gc
, &col 
); 
1037             gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh 
); 
1039             gdk_gc_set_background( gc
, &col 
); 
1041             gdk_gc_set_foreground( gc
, &col 
); 
1042             gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() ); 
1043             gdk_gc_set_clip_origin( gc
, -xx
, -yy 
); 
1044             gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED 
); 
1045             gdk_gc_set_stipple( gc
, mask 
); 
1046             gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh 
); 
1048             g_object_unref (gc
); 
1051         gdk_gc_set_clip_mask(use_gc
, mask
); 
1052         gdk_gc_set_clip_origin(use_gc
, xx
, yy
); 
1055     // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 
1056     // drawing a mono-bitmap (XBitmap) we use the current text GC 
1059         GdkPixmap 
*bitmap2 
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, -1 ); 
1060         GdkGC 
*gc 
= gdk_gc_new( bitmap2 
); 
1061         gdk_gc_set_foreground( gc
, m_textForegroundColour
.GetColor() ); 
1062         gdk_gc_set_background( gc
, m_textBackgroundColour
.GetColor() ); 
1063         gdk_wx_draw_bitmap(bitmap2
, gc
, use_bitmap
.GetPixmap(), 0, 0); 
1065         gdk_draw_drawable(m_gdkwindow
, use_gc
, bitmap2
, 0, 0, xx
, yy
, -1, -1); 
1067         g_object_unref (bitmap2
); 
1068         g_object_unref (gc
); 
1072         if (use_bitmap
.HasPixbuf()) 
1074             gdk_draw_pixbuf(m_gdkwindow
, use_gc
, 
1075                             use_bitmap
.GetPixbuf(), 
1076                             0, 0, xx
, yy
, -1, -1, 
1077                             GDK_RGB_DITHER_NORMAL
, xx
, yy
); 
1081             gdk_draw_drawable(m_gdkwindow
, use_gc
, 
1082                               use_bitmap
.GetPixmap(), 
1083                               0, 0, xx
, yy
, -1, -1); 
1087     // remove mask again if any 
1090         gdk_gc_set_clip_mask(use_gc
, NULL
); 
1091         gdk_gc_set_clip_origin(use_gc
, 0, 0); 
1092         if (!m_currentClippingRegion
.IsNull()) 
1093             gdk_gc_set_clip_region(use_gc
, m_currentClippingRegion
.GetRegion()); 
1094         if (new_mask 
!= NULL
) 
1095             g_object_unref(new_mask
); 
1099 bool wxWindowDCImpl::DoBlit( wxCoord xdest
, wxCoord ydest
, 
1100                          wxCoord width
, wxCoord height
, 
1102                          wxCoord xsrc
, wxCoord ysrc
, 
1105                          wxCoord xsrcMask
, wxCoord ysrcMask 
) 
1107     wxCHECK_MSG( IsOk(), false, wxT("invalid window dc") ); 
1109     wxCHECK_MSG( source
, false, wxT("invalid source dc") ); 
1111     if (!m_gdkwindow
) return false; 
1113     // transform the source DC coords to the device ones 
1114     xsrc 
= source
->LogicalToDeviceX(xsrc
); 
1115     ysrc 
= source
->LogicalToDeviceY(ysrc
); 
1118     wxMemoryDC 
*memDC 
= wxDynamicCast(source
, wxMemoryDC
); 
1121         selected 
= memDC
->GetSelectedBitmap(); 
1122         if ( !selected
.IsOk() ) 
1126     bool use_bitmap_method 
= false; 
1127     bool is_mono 
= false; 
1129     if (xsrcMask 
== -1 && ysrcMask 
== -1) 
1135     if (selected
.IsOk()) 
1137         is_mono 
= (selected
.GetDepth() == 1); 
1139         // we use the "XCopyArea" way to copy a memory dc into 
1140         // a different window if the memory dc BOTH 
1141         // a) doesn't have any mask or its mask isn't used 
1145         if (useMask 
&& (selected
.GetMask())) 
1147             // we HAVE TO use the direct way for memory dcs 
1148             // that have mask since the XCopyArea doesn't know 
1150             use_bitmap_method 
= true; 
1154             // we HAVE TO use the direct way for memory dcs 
1155             // that are bitmaps because XCopyArea doesn't cope 
1156             // with different bit depths 
1157             use_bitmap_method 
= true; 
1159         else if ((xsrc 
== 0) && (ysrc 
== 0) && 
1160                  (width 
== selected
.GetWidth()) && 
1161                  (height 
== selected
.GetHeight())) 
1163             // we SHOULD use the direct way if all of the bitmap 
1164             // in the memory dc is copied in which case XCopyArea 
1165             // wouldn't be able able to boost performace by reducing 
1166             // the area to be scaled 
1167             use_bitmap_method 
= true; 
1171     CalcBoundingBox( xdest
, ydest 
); 
1172     CalcBoundingBox( xdest 
+ width
, ydest 
+ height 
); 
1174     // scale/translate size and position 
1175     wxCoord xx 
= XLOG2DEV(xdest
); 
1176     wxCoord yy 
= YLOG2DEV(ydest
); 
1178     wxCoord ww 
= XLOG2DEVREL(width
); 
1179     wxCoord hh 
= YLOG2DEVREL(height
); 
1181     // compare to current clipping region 
1182     if (!m_currentClippingRegion
.IsNull()) 
1184         wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1185         tmp
.Intersect( m_currentClippingRegion 
); 
1190     int old_logical_func 
= m_logicalFunction
; 
1191     SetLogicalFunction( logical_func 
); 
1193     if (use_bitmap_method
) 
1195         // scale/translate bitmap size 
1196         wxCoord bm_width 
= selected
.GetWidth(); 
1197         wxCoord bm_height 
= selected
.GetHeight(); 
1199         // Get clip coords for the bitmap. If we don't 
1200         // use wxBitmap::Rescale(), which can clip the 
1201         // bitmap, these are the same as the original 
1208         // interpret userscale of src too 
1210         memDC
->GetUserScale(&xsc
,&ysc
); 
1211         bm_width 
= (int) (bm_width 
/ xsc
); 
1212         bm_height 
= (int) (bm_height 
/ ysc
); 
1214         wxCoord bm_ww 
= XLOG2DEVREL( bm_width 
); 
1215         wxCoord bm_hh 
= YLOG2DEVREL( bm_height 
); 
1217         // Scale bitmap if required 
1218         wxBitmap use_bitmap 
= selected
; 
1219         if ((selected
.GetWidth()!= bm_ww
) || ( selected
.GetHeight()!= bm_hh
)) 
1221             // This indicates that the blitting code below will get 
1222             // a clipped bitmap and therefore needs to move the origin 
1224             wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1225             if (!m_currentClippingRegion
.IsNull()) 
1226                 tmp
.Intersect( m_currentClippingRegion 
); 
1227             tmp
.GetBox(cx
,cy
,cw
,ch
); 
1229             // Scale and clipped bitmap 
1230             use_bitmap 
= selected
.Rescale(cx
-xx
,cy
-yy
,cw
,ch
,bm_ww
,bm_hh
); 
1233         // apply mask if any 
1234         GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
1235         if (useMask 
&& use_bitmap
.GetMask()) 
1236             mask 
= use_bitmap
.GetMask()->GetBitmap(); 
1238         GdkGC
* use_gc 
= is_mono 
? m_textGC 
: m_penGC
; 
1240         GdkBitmap 
*new_mask 
= (GdkBitmap
*) NULL
; 
1244             if (!m_currentClippingRegion
.IsNull()) 
1247                 new_mask 
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 ); 
1248                 GdkGC 
*gc 
= gdk_gc_new( new_mask 
); 
1250                 gdk_gc_set_foreground( gc
, &col 
); 
1251                 gdk_gc_set_ts_origin( gc
, -xsrcMask
, -ysrcMask
); 
1252                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh 
); 
1254                 gdk_gc_set_background( gc
, &col 
); 
1256                 gdk_gc_set_foreground( gc
, &col 
); 
1257                 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() ); 
1258                 // was: gdk_gc_set_clip_origin( gc, -xx, -yy ); 
1259                 gdk_gc_set_clip_origin( gc
, -cx
, -cy 
); 
1260                 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED 
); 
1261                 gdk_gc_set_stipple( gc
, mask 
); 
1262                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh 
); 
1264                 g_object_unref (gc
); 
1267             gdk_gc_set_clip_mask(use_gc
, mask
); 
1268             if (new_mask 
!= NULL
) 
1269                 gdk_gc_set_clip_origin(use_gc
, cx
, cy
); 
1271                 gdk_gc_set_clip_origin(use_gc
, cx 
- xsrcMask
, cy 
- ysrcMask
); 
1274         // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 
1275         // drawing a mono-bitmap (XBitmap) we use the current text GC 
1279             GdkPixmap 
*bitmap 
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, -1 ); 
1280             GdkGC 
*gc 
= gdk_gc_new( bitmap 
); 
1281             gdk_gc_set_foreground( gc
, m_textForegroundColour
.GetColor() ); 
1282             gdk_gc_set_background( gc
, m_textBackgroundColour
.GetColor() ); 
1283             gdk_wx_draw_bitmap(bitmap
, gc
, use_bitmap
.GetPixmap(), 0, 0); 
1285             gdk_draw_drawable(m_gdkwindow
, use_gc
, bitmap
, xsrc
, ysrc
, cx
, cy
, cw
, ch
); 
1287             g_object_unref (bitmap
); 
1288             g_object_unref (gc
); 
1292             // was: gdk_draw_drawable( m_gdkwindow, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh ); 
1293             gdk_draw_drawable(m_gdkwindow
, use_gc
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, cx
, cy
, cw
, ch
); 
1296         // remove mask again if any 
1299             gdk_gc_set_clip_mask(use_gc
, NULL
); 
1300             gdk_gc_set_clip_origin(use_gc
, 0, 0); 
1301             if (!m_currentClippingRegion
.IsNull()) 
1302                 gdk_gc_set_clip_region(use_gc
, m_currentClippingRegion
.GetRegion()); 
1306             g_object_unref (new_mask
); 
1308     else // use_bitmap_method 
1310         if (selected
.IsOk() && ((width 
!= ww
) || (height 
!= hh
))) 
1313             wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1314             tmp
.Intersect( m_currentClippingRegion 
); 
1315             wxCoord cx
,cy
,cw
,ch
; 
1316             tmp
.GetBox(cx
,cy
,cw
,ch
); 
1319             wxBitmap bitmap 
= selected
.Rescale( cx
-xx
, cy
-yy
, cw
, ch
, ww
, hh 
); 
1321             // draw scaled bitmap 
1322             // was: gdk_draw_drawable( m_gdkwindow, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); 
1323             gdk_draw_drawable( m_gdkwindow
, m_penGC
, bitmap
.GetPixmap(), 0, 0, cx
, cy
, -1, -1 ); 
1327             // No scaling and not a memory dc with a mask either 
1328             GdkWindow
* window 
= NULL
; 
1329             wxDCImpl 
*impl 
= source
->GetImpl(); 
1330             wxWindowDCImpl 
*gtk_impl 
= wxDynamicCast(impl
, wxWindowDCImpl
); 
1332                 window 
= gtk_impl
->GetGDKWindow(); 
1335                 SetLogicalFunction( old_logical_func 
); 
1339             // copy including child window contents 
1340             gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS 
); 
1341             gdk_draw_drawable( m_gdkwindow
, m_penGC
, 
1345             gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN 
); 
1349     SetLogicalFunction( old_logical_func 
); 
1354 void wxWindowDCImpl::DoDrawText( const wxString 
&text
, wxCoord x
, wxCoord y 
) 
1356     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
1358     if (!m_gdkwindow
) return; 
1360     if (text
.empty()) return; 
1365     wxCHECK_RET( m_context
, wxT("no Pango context") ); 
1366     wxCHECK_RET( m_layout
, wxT("no Pango layout") ); 
1367     wxCHECK_RET( m_fontdesc
, wxT("no Pango font description") ); 
1369     gdk_pango_context_set_colormap( m_context
, m_cmap 
);  // not needed in gtk+ >= 2.6 
1371     bool underlined 
= m_font
.IsOk() && m_font
.GetUnderlined(); 
1373     wxCharBuffer data 
= wxGTK_CONV(text
); 
1376     size_t datalen 
= strlen(data
); 
1378     // in Pango >= 1.16 the "underline of leading/trailing spaces" bug 
1379     // has been fixed and thus the hack implemented below should never be used 
1380     static bool pangoOk 
= !wx_pango_version_check(1, 16, 0); 
1382     bool needshack 
= underlined 
&& !pangoOk
; 
1386         // a PangoLayout which has leading/trailing spaces with underlined font 
1387         // is not correctly drawn by this pango version: Pango won't underline the spaces. 
1388         // This can be a problem; e.g. wxHTML rendering of underlined text relies on 
1389         // this behaviour. To workaround this problem, we use a special hack here 
1390         // suggested by pango maintainer Behdad Esfahbod: we prepend and append two 
1391         // empty space characters and give them a dummy colour attribute. 
1392         // This will force Pango to underline the leading/trailing spaces, too. 
1394         wxCharBuffer 
data_tmp(datalen 
+ 6); 
1395         // copy the leading U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format 
1396         memcpy(data_tmp
.data(), "\342\200\214", 3); 
1397         // copy the user string 
1398         memcpy(data_tmp
.data() + 3, data
, datalen
); 
1399         // copy the trailing U+200C ZERO WIDTH NON-JOINER encoded in UTF8 format 
1400         memcpy(data_tmp
.data() + 3 + datalen
, "\342\200\214", 3); 
1406     pango_layout_set_text(m_layout
, data
, datalen
); 
1410         PangoAttrList 
*attrs 
= pango_attr_list_new(); 
1411         PangoAttribute 
*a 
= pango_attr_underline_new(PANGO_UNDERLINE_SINGLE
); 
1413         a
->end_index 
= datalen
; 
1414         pango_attr_list_insert(attrs
, a
); 
1418             // dummy colour for the leading space 
1419             a 
= pango_attr_foreground_new (0x0057, 0x52A9, 0xD614); 
1422             pango_attr_list_insert(attrs
, a
); 
1424             // dummy colour for the trailing space 
1425             a 
= pango_attr_foreground_new (0x0057, 0x52A9, 0xD614); 
1426             a
->start_index 
= datalen 
- 1; 
1427             a
->end_index 
= datalen
; 
1428             pango_attr_list_insert(attrs
, a
); 
1431         pango_layout_set_attributes(m_layout
, attrs
); 
1432         pango_attr_list_unref(attrs
); 
1436     const bool isScaled 
= fabs(m_scaleY 
- 1.0) > 0.00001; 
1439         // If there is a user or actually any scale applied to 
1440         // the device context, scale the font. 
1442         // scale font description 
1443         oldSize 
= pango_font_description_get_size(m_fontdesc
); 
1444         pango_font_description_set_size(m_fontdesc
, int(oldSize 
* m_scaleY
)); 
1446         // actually apply scaled font 
1447         pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1451     pango_layout_get_pixel_size(m_layout
, &w
, &h
); 
1455     if (m_window 
&& m_window
->GetLayoutDirection() == wxLayout_RightToLeft
) 
1458     const GdkColor
* bg_col 
= NULL
; 
1459     if (m_backgroundMode 
== wxBRUSHSTYLE_SOLID
)  
1460         bg_col 
= m_textBackgroundColour
.GetColor(); 
1462     gdk_draw_layout_with_colors(m_gdkwindow
, m_textGC
, x_rtl
, y
, m_layout
, NULL
, bg_col
); 
1466          // reset unscaled size 
1467          pango_font_description_set_size( m_fontdesc
, oldSize 
); 
1469          // actually apply unscaled font 
1470          pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1474         // undo underline attributes setting: 
1475         pango_layout_set_attributes(m_layout
, NULL
); 
1478     CalcBoundingBox(x 
+ int(w 
/ m_scaleX
), y 
+ int(h 
/ m_scaleY
)); 
1479     CalcBoundingBox(x
, y
); 
1482 // TODO: When GTK2.6 is required, merge DoDrawText and DoDrawRotatedText to  
1483 // avoid code duplication 
1484 void wxWindowDCImpl::DoDrawRotatedText( const wxString 
&text
, wxCoord x
, wxCoord y
, double angle 
) 
1486     if (!m_gdkwindow 
|| text
.empty()) 
1489     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
1492     if (!gtk_check_version(2,6,0)) 
1497         pango_layout_set_text(m_layout
, wxGTK_CONV(text
), -1); 
1499         if (m_font
.GetUnderlined()) 
1501             PangoAttrList 
*attrs 
= pango_attr_list_new(); 
1502             PangoAttribute 
*a 
= pango_attr_underline_new(PANGO_UNDERLINE_SINGLE
); 
1503             pango_attr_list_insert(attrs
, a
); 
1504             pango_layout_set_attributes(m_layout
, attrs
); 
1505             pango_attr_list_unref(attrs
); 
1509         const bool isScaled 
= fabs(m_scaleY 
- 1.0) > 0.00001; 
1512             //TODO: when Pango >= 1.6 is required, use pango_matrix_scale() 
1513              // If there is a user or actually any scale applied to 
1514              // the device context, scale the font. 
1516              // scale font description 
1517             oldSize 
= pango_font_description_get_size(m_fontdesc
); 
1518             pango_font_description_set_size(m_fontdesc
, int(oldSize 
* m_scaleY
)); 
1520              // actually apply scaled font 
1521              pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1525         pango_layout_get_pixel_size(m_layout
, &w
, &h
); 
1527         const GdkColor
* bg_col 
= NULL
; 
1528         if (m_backgroundMode 
== wxBRUSHSTYLE_SOLID
)  
1529             bg_col 
= m_textBackgroundColour
.GetColor(); 
1532         PangoMatrix matrix 
= PANGO_MATRIX_INIT
; 
1533         pango_matrix_rotate (&matrix
, angle
); 
1534         pango_context_set_matrix (m_context
, &matrix
); 
1535         pango_layout_context_changed (m_layout
); 
1537         // To be compatible with MSW, the rotation axis must be in the old  
1539         // Calculate the vertices of the rotated rectangle containing the text,  
1540         // relative to the old top-left vertex. 
1541         // We could use the matrix for this, but it's simpler with trignonometry.  
1542         double rad 
= DegToRad(angle
); 
1543         // the rectangle vertices are counted clockwise with the first one  
1545         double x2 
= w 
* cos(rad
); 
1546         double y2 
= -w 
* sin(rad
);   // y axis points to the bottom, hence minus 
1547         double x4 
= h 
* sin(rad
); 
1548         double y4 
= h 
* cos(rad
); 
1549         double x3 
= x4 
+ x2
; 
1550         double y3 
= y4 
+ y2
; 
1551         // Then we calculate max and min of the rotated rectangle. 
1552         wxCoord maxX 
= (wxCoord
)(dmax(dmax(0, x2
), dmax(x3
, x4
)) + 0.5), 
1553                 maxY 
= (wxCoord
)(dmax(dmax(0, y2
), dmax(y3
, y4
)) + 0.5), 
1554                 minX 
= (wxCoord
)(dmin(dmin(0, x2
), dmin(x3
, x4
)) - 0.5), 
1555                 minY 
= (wxCoord
)(dmin(dmin(0, y2
), dmin(y3
, y4
)) - 0.5); 
1557         gdk_draw_layout_with_colors(m_gdkwindow
, m_textGC
, x
+minX
, y
+minY
,  
1558                                     m_layout
, NULL
, bg_col
); 
1560         if (m_font
.GetUnderlined()) 
1561             pango_layout_set_attributes(m_layout
, NULL
); 
1563         // clean up the transformation matrix 
1564         pango_context_set_matrix(m_context
, NULL
); 
1568              // reset unscaled size 
1569              pango_font_description_set_size( m_fontdesc
, oldSize 
); 
1571              // actually apply unscaled font 
1572              pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1575         CalcBoundingBox(x
+minX
, y
+minY
); 
1576         CalcBoundingBox(x
+maxX
, y
+maxY
); 
1579 #endif //__WXGTK26__ 
1582     if ( wxIsNullDouble(angle
) ) 
1584         DoDrawText(text
, x
, y
); 
1591     // TODO: implement later without GdkFont for GTK 2.0 
1592     DoGetTextExtent(text
, &w
, &h
, NULL
,NULL
, &m_font
); 
1594     // draw the string normally 
1597     dc
.SelectObject(src
); 
1598     dc
.SetFont(GetFont()); 
1599     dc
.SetBackground(*wxBLACK_BRUSH
); 
1600     dc
.SetBrush(*wxBLACK_BRUSH
); 
1602     dc
.SetTextForeground( *wxWHITE 
); 
1603     dc
.DrawText(text
, 0, 0); 
1604     dc
.SelectObject(wxNullBitmap
); 
1606     // Calculate the size of the rotated bounding box. 
1607     double rad 
= DegToRad(angle
); 
1608     double dx 
= cos(rad
), 
1611     // the rectngle vertices are counted clockwise with the first one being at 
1612     // (0, 0) (or, rather, at (x, y)) 
1614            y2 
= -w
*dy
;      // y axis points to the bottom, hence minus 
1617     double x3 
= x4 
+ x2
, 
1621     wxCoord maxX 
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5), 
1622             maxY 
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5), 
1623             minX 
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5), 
1624             minY 
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5); 
1627     wxImage image 
= src
.ConvertToImage(); 
1629     image
.ConvertColourToAlpha( m_textForegroundColour
.Red(), 
1630                                 m_textForegroundColour
.Green(), 
1631                                 m_textForegroundColour
.Blue() ); 
1632     image 
= image
.Rotate( rad
, wxPoint(0,0) ); 
1634     int i_angle 
= (int) angle
; 
1635     i_angle 
= i_angle 
% 360; 
1639     if ((i_angle 
>= 90.0) && (i_angle 
< 270.0)) 
1640         xoffset 
= image
.GetWidth(); 
1642     if ((i_angle 
>= 0.0) && (i_angle 
< 180.0)) 
1643         yoffset 
= image
.GetHeight(); 
1645     if ((i_angle 
>= 0) && (i_angle 
< 90)) 
1646         yoffset 
-= (int)( cos(rad
)*h 
); 
1647     if ((i_angle 
>= 90) && (i_angle 
< 180)) 
1648         xoffset 
-= (int)( sin(rad
)*h 
); 
1649     if ((i_angle 
>= 180) && (i_angle 
< 270)) 
1650         yoffset 
-= (int)( cos(rad
)*h 
); 
1651     if ((i_angle 
>= 270) && (i_angle 
< 360)) 
1652         xoffset 
-= (int)( sin(rad
)*h 
); 
1654     int i_x 
= x 
- xoffset
; 
1655     int i_y 
= y 
- yoffset
; 
1658     DoDrawBitmap( src
, i_x
, i_y
, true ); 
1661     // it would be better to draw with non underlined font and draw the line 
1662     // manually here (it would be more straight...) 
1664     if ( m_font
.GetUnderlined() ) 
1666         gdk_draw_line( m_gdkwindow
, m_textGC
, 
1667                        XLOG2DEV(x 
+ x4
), YLOG2DEV(y 
+ y4 
+ font
->descent
), 
1668                        XLOG2DEV(x 
+ x3
), YLOG2DEV(y 
+ y3 
+ font
->descent
)); 
1672     // update the bounding box 
1673     CalcBoundingBox(x 
+ minX
, y 
+ minY
); 
1674     CalcBoundingBox(x 
+ maxX
, y 
+ maxY
); 
1675 #else // !wxUSE_IMAGE 
1680 #endif // wxUSE_IMAGE/!wxUSE_IMAGE 
1684 void wxWindowDCImpl::DoGetTextExtent(const wxString 
&string
, 
1685                                  wxCoord 
*width
, wxCoord 
*height
, 
1686                                  wxCoord 
*descent
, wxCoord 
*externalLeading
, 
1687                                  const wxFont 
*theFont
) const 
1695     if ( externalLeading 
) 
1696         *externalLeading 
= 0; 
1701     // ensure that theFont is always non-NULL 
1702     if ( !theFont 
|| !theFont
->IsOk() ) 
1705     // and use it if it's valid 
1706     if ( theFont
->IsOk() ) 
1708         pango_layout_set_font_description
 
1711             theFont
->GetNativeFontInfo()->description
 
1715     // Set layout's text 
1716     const wxCharBuffer dataUTF8 
= wxGTK_CONV_FONT(string
, *theFont
); 
1719         // hardly ideal, but what else can we do if conversion failed? 
1723     pango_layout_set_text(m_layout
, dataUTF8
, -1); 
1726     pango_layout_get_pixel_size(m_layout
, width
, &h
); 
1729         PangoLayoutIter 
*iter 
= pango_layout_get_iter(m_layout
); 
1730         int baseline 
= pango_layout_iter_get_baseline(iter
); 
1731         pango_layout_iter_free(iter
); 
1732         *descent 
= h 
- PANGO_PIXELS(baseline
); 
1737     // Reset old font description 
1738     if (theFont
->IsOk()) 
1739         pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1743 bool wxWindowDCImpl::DoGetPartialTextExtents(const wxString
& text
, 
1744                                          wxArrayInt
& widths
) const 
1746     const size_t len 
= text
.length(); 
1753     // Set layout's text 
1754     const wxCharBuffer dataUTF8 
= wxGTK_CONV_FONT(text
, m_font
); 
1757         // hardly ideal, but what else can we do if conversion failed? 
1758         wxLogLastError(wxT("DoGetPartialTextExtents")); 
1762     pango_layout_set_text(m_layout
, dataUTF8
, -1); 
1764     // Calculate the position of each character based on the widths of 
1765     // the previous characters 
1767     // Code borrowed from Scintilla's PlatGTK 
1768     PangoLayoutIter 
*iter 
= pango_layout_get_iter(m_layout
); 
1770     pango_layout_iter_get_cluster_extents(iter
, NULL
, &pos
); 
1772     while (pango_layout_iter_next_cluster(iter
)) 
1774         pango_layout_iter_get_cluster_extents(iter
, NULL
, &pos
); 
1775         int position 
= PANGO_PIXELS(pos
.x
); 
1776         widths
[i
++] = position
; 
1779         widths
[i
++] = PANGO_PIXELS(pos
.x 
+ pos
.width
); 
1780     pango_layout_iter_free(iter
); 
1786 wxCoord 
wxWindowDCImpl::GetCharWidth() const 
1788     pango_layout_set_text( m_layout
, "H", 1 ); 
1790     pango_layout_get_pixel_size( m_layout
, &w
, NULL 
); 
1794 wxCoord 
wxWindowDCImpl::GetCharHeight() const 
1796     PangoFontMetrics 
*metrics 
= pango_context_get_metrics (m_context
, m_fontdesc
, pango_context_get_language(m_context
)); 
1797     wxCHECK_MSG( metrics
, -1, _T("failed to get pango font metrics") ); 
1799     wxCoord h 
= PANGO_PIXELS (pango_font_metrics_get_descent (metrics
) + 
1800                 pango_font_metrics_get_ascent (metrics
)); 
1801     pango_font_metrics_unref (metrics
); 
1805 void wxWindowDCImpl::Clear() 
1807     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
1809     if (!m_gdkwindow
) return; 
1812     DoGetSize( &width
, &height 
); 
1813     gdk_draw_rectangle( m_gdkwindow
, m_bgGC
, TRUE
, 0, 0, width
, height 
); 
1816 void wxWindowDCImpl::SetFont( const wxFont 
&font 
) 
1823             pango_font_description_free( m_fontdesc 
); 
1825         m_fontdesc 
= pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
1830             PangoContext 
*oldContext 
= m_context
; 
1832             m_context 
= m_window
->GtkGetPangoDefaultContext(); 
1834             // If we switch back/forth between different contexts 
1835             // we also have to create a new layout. I think so, 
1836             // at least, and it doesn't hurt to do it. 
1837             if (oldContext 
!= m_context
) 
1840                     g_object_unref (m_layout
); 
1842                 m_layout 
= pango_layout_new( m_context 
); 
1846         pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1850 void wxWindowDCImpl::SetPen( const wxPen 
&pen 
) 
1852     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
1854     if (m_pen 
== pen
) return; 
1858     if (!m_pen
.IsOk()) return; 
1860     if (!m_gdkwindow
) return; 
1862     gint width 
= m_pen
.GetWidth(); 
1865         // CMB: if width is non-zero scale it with the dc 
1870         // X doesn't allow different width in x and y and so we take 
1873                    ( fabs((double) XLOG2DEVREL(width
)) + 
1874                      fabs((double) YLOG2DEVREL(width
)) ) / 2.0; 
1878             // width can't be 0 or an internal GTK error occurs inside 
1879             // gdk_gc_set_dashes() below 
1884     static const wxGTKDash dotted
[] = {1, 1}; 
1885     static const wxGTKDash short_dashed
[] = {2, 2}; 
1886     static const wxGTKDash wxCoord_dashed
[] = {2, 4}; 
1887     static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3}; 
1889     // We express dash pattern in pen width unit, so we are 
1890     // independent of zoom factor and so on... 
1892     const wxGTKDash 
*req_dash
; 
1894     GdkLineStyle lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1895     switch (m_pen
.GetStyle()) 
1897         case wxPENSTYLE_USER_DASH
: 
1898             req_nb_dash 
= m_pen
.GetDashCount(); 
1899             req_dash 
= (wxGTKDash
*)m_pen
.GetDash(); 
1901         case wxPENSTYLE_DOT
: 
1905         case wxPENSTYLE_LONG_DASH
: 
1907             req_dash 
= wxCoord_dashed
; 
1909         case wxPENSTYLE_SHORT_DASH
: 
1911             req_dash 
= short_dashed
; 
1913         case wxPENSTYLE_DOT_DASH
: 
1915             req_dash 
= dotted_dashed
; 
1918         case wxPENSTYLE_TRANSPARENT
: 
1919         case wxPENSTYLE_STIPPLE_MASK_OPAQUE
: 
1920         case wxPENSTYLE_STIPPLE
: 
1921         case wxPENSTYLE_SOLID
: 
1923             lineStyle 
= GDK_LINE_SOLID
; 
1924             req_dash 
= (wxGTKDash
*)NULL
; 
1929     if (req_dash 
&& req_nb_dash
) 
1931         wxGTKDash 
*real_req_dash 
= new wxGTKDash
[req_nb_dash
]; 
1934             for (int i 
= 0; i 
< req_nb_dash
; i
++) 
1935                 real_req_dash
[i
] = req_dash
[i
] * width
; 
1936             gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash 
); 
1937             delete[] real_req_dash
; 
1941             // No Memory. We use non-scaled dash pattern... 
1942             gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash 
); 
1946     GdkCapStyle capStyle 
= GDK_CAP_ROUND
; 
1947     switch (m_pen
.GetCap()) 
1949         case wxCAP_PROJECTING
: { capStyle 
= GDK_CAP_PROJECTING
; break; } 
1950         case wxCAP_BUTT
:       { capStyle 
= GDK_CAP_BUTT
;       break; } 
1956                 capStyle 
= GDK_CAP_NOT_LAST
; 
1961     GdkJoinStyle joinStyle 
= GDK_JOIN_ROUND
; 
1962     switch (m_pen
.GetJoin()) 
1964         case wxJOIN_BEVEL
: { joinStyle 
= GDK_JOIN_BEVEL
; break; } 
1965         case wxJOIN_MITER
: { joinStyle 
= GDK_JOIN_MITER
; break; } 
1967         default:           { joinStyle 
= GDK_JOIN_ROUND
; break; } 
1970     gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle 
); 
1972     m_pen
.GetColour().CalcPixel( m_cmap 
); 
1973     gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() ); 
1976 void wxWindowDCImpl::SetBrush( const wxBrush 
&brush 
) 
1978     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
1980     if (m_brush 
== brush
) return; 
1984     if (!m_brush
.IsOk()) return; 
1986     if (!m_gdkwindow
) return; 
1988     m_brush
.GetColour().CalcPixel( m_cmap 
); 
1989     gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() ); 
1991     gdk_gc_set_fill( m_brushGC
, GDK_SOLID 
); 
1993     if ((m_brush
.GetStyle() == wxBRUSHSTYLE_STIPPLE
) && (m_brush
.GetStipple()->IsOk())) 
1995         if (m_brush
.GetStipple()->GetDepth() != 1) 
1997             gdk_gc_set_fill( m_brushGC
, GDK_TILED 
); 
1998             gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() ); 
2002             gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED 
); 
2003             gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetPixmap() ); 
2007     if ((m_brush
.GetStyle() == wxBRUSHSTYLE_STIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
2009         gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
); 
2010         gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() ); 
2013     if (m_brush
.IsHatch()) 
2015         gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED 
); 
2016         gdk_gc_set_stipple(m_brushGC
, GetHatch(m_brush
.GetStyle())); 
2020 void wxWindowDCImpl::SetBackground( const wxBrush 
&brush 
) 
2022    /* CMB 21/7/98: Added SetBackground. Sets background brush 
2023     * for Clear() and bg colour for shapes filled with cross-hatch brush */ 
2025     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2027     if (m_backgroundBrush 
== brush
) return; 
2029     m_backgroundBrush 
= brush
; 
2031     if (!m_backgroundBrush
.IsOk()) return; 
2033     if (!m_gdkwindow
) return; 
2035     wxColor color 
= m_backgroundBrush
.GetColour(); 
2036     color
.CalcPixel(m_cmap
); 
2037     const GdkColor
* gdkColor 
= color
.GetColor(); 
2038     gdk_gc_set_background(m_brushGC
, gdkColor
); 
2039     gdk_gc_set_background(m_penGC
,   gdkColor
); 
2040     gdk_gc_set_background(m_bgGC
,    gdkColor
); 
2041     gdk_gc_set_foreground(m_bgGC
,    gdkColor
); 
2044     gdk_gc_set_fill( m_bgGC
, GDK_SOLID 
); 
2046     if (m_backgroundBrush
.GetStyle() == wxBRUSHSTYLE_STIPPLE
) 
2048         const wxBitmap
* stipple 
= m_backgroundBrush
.GetStipple(); 
2049         if (stipple
->IsOk()) 
2051             if (stipple
->GetDepth() != 1) 
2053                 gdk_gc_set_fill(m_bgGC
, GDK_TILED
); 
2054                 gdk_gc_set_tile(m_bgGC
, stipple
->GetPixmap()); 
2058                 gdk_gc_set_fill(m_bgGC
, GDK_STIPPLED
); 
2059                 gdk_gc_set_stipple(m_bgGC
, stipple
->GetPixmap()); 
2063     else if (m_backgroundBrush
.IsHatch()) 
2065         gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED 
); 
2066         gdk_gc_set_stipple(m_bgGC
, GetHatch(m_backgroundBrush
.GetStyle())); 
2070 void wxWindowDCImpl::SetLogicalFunction( int function 
) 
2072     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2074     if (m_logicalFunction 
== function
) 
2077     // VZ: shouldn't this be a CHECK? 
2084         case wxXOR
:          mode 
= GDK_XOR
;           break; 
2085         case wxINVERT
:       mode 
= GDK_INVERT
;        break; 
2086         case wxOR_REVERSE
:   mode 
= GDK_OR_REVERSE
;    break; 
2087         case wxAND_REVERSE
:  mode 
= GDK_AND_REVERSE
;   break; 
2088         case wxCLEAR
:        mode 
= GDK_CLEAR
;         break; 
2089         case wxSET
:          mode 
= GDK_SET
;           break; 
2090         case wxOR_INVERT
:    mode 
= GDK_OR_INVERT
;     break; 
2091         case wxAND
:          mode 
= GDK_AND
;           break; 
2092         case wxOR
:           mode 
= GDK_OR
;            break; 
2093         case wxEQUIV
:        mode 
= GDK_EQUIV
;         break; 
2094         case wxNAND
:         mode 
= GDK_NAND
;          break; 
2095         case wxAND_INVERT
:   mode 
= GDK_AND_INVERT
;    break; 
2096         case wxCOPY
:         mode 
= GDK_COPY
;          break; 
2097         case wxNO_OP
:        mode 
= GDK_NOOP
;          break; 
2098         case wxSRC_INVERT
:   mode 
= GDK_COPY_INVERT
;   break; 
2099         case wxNOR
:          mode 
= GDK_NOR
;           break; 
2101            wxFAIL_MSG( wxT("unsupported logical function") ); 
2105     m_logicalFunction 
= function
; 
2107     gdk_gc_set_function( m_penGC
, mode 
); 
2108     gdk_gc_set_function( m_brushGC
, mode 
); 
2110     // to stay compatible with wxMSW, we don't apply ROPs to the text 
2111     // operations (i.e. DrawText/DrawRotatedText). 
2112     // True, but mono-bitmaps use the m_textGC and they use ROPs as well. 
2113     gdk_gc_set_function( m_textGC
, mode 
); 
2116 void wxWindowDCImpl::SetTextForeground( const wxColour 
&col 
) 
2118     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2120     // don't set m_textForegroundColour to an invalid colour as we'd crash 
2121     // later then (we use m_textForegroundColour.GetColor() without checking 
2123     if ( !col
.IsOk() || (m_textForegroundColour 
== col
) ) 
2126     m_textForegroundColour 
= col
; 
2130         m_textForegroundColour
.CalcPixel( m_cmap 
); 
2131         gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
2135 void wxWindowDCImpl::SetTextBackground( const wxColour 
&col 
) 
2137     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2140     if ( !col
.IsOk() || (m_textBackgroundColour 
== col
) ) 
2143     m_textBackgroundColour 
= col
; 
2147         m_textBackgroundColour
.CalcPixel( m_cmap 
); 
2148         gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() ); 
2152 void wxWindowDCImpl::SetBackgroundMode( int mode 
) 
2154     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2156     m_backgroundMode 
= mode
; 
2159 void wxWindowDCImpl::SetPalette( const wxPalette
& WXUNUSED(palette
) ) 
2161     wxFAIL_MSG( wxT("wxWindowDCImpl::SetPalette not implemented") ); 
2164 void wxWindowDCImpl::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
2166     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2168     if (!m_gdkwindow
) return; 
2171     rect
.x 
= XLOG2DEV(x
); 
2172     rect
.y 
= YLOG2DEV(y
); 
2173     rect
.width 
= XLOG2DEVREL(width
); 
2174     rect
.height 
= YLOG2DEVREL(height
); 
2176     if (m_window 
&& m_window
->m_wxwindow 
&&  
2177         (m_window
->GetLayoutDirection() == wxLayout_RightToLeft
)) 
2179         rect
.x 
-= rect
.width
; 
2182     if (!m_currentClippingRegion
.IsNull()) 
2183         m_currentClippingRegion
.Intersect( rect 
); 
2185         m_currentClippingRegion
.Union( rect 
); 
2187 #if USE_PAINT_REGION 
2188     if (!m_paintClippingRegion
.IsNull()) 
2189         m_currentClippingRegion
.Intersect( m_paintClippingRegion 
); 
2192     wxCoord xx
, yy
, ww
, hh
; 
2193     m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh 
); 
2194     wxGTKDCImpl::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
2196     GdkRegion
* gdkRegion 
= m_currentClippingRegion
.GetRegion(); 
2197     gdk_gc_set_clip_region(m_penGC
,   gdkRegion
); 
2198     gdk_gc_set_clip_region(m_brushGC
, gdkRegion
); 
2199     gdk_gc_set_clip_region(m_textGC
,  gdkRegion
); 
2200     gdk_gc_set_clip_region(m_bgGC
,    gdkRegion
); 
2203 void wxWindowDCImpl::DoSetDeviceClippingRegion( const wxRegion 
®ion  
) 
2205     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2209         DestroyClippingRegion(); 
2213     if (!m_gdkwindow
) return; 
2215     if (!m_currentClippingRegion
.IsNull()) 
2216         m_currentClippingRegion
.Intersect( region 
); 
2218         m_currentClippingRegion
.Union( region 
); 
2220 #if USE_PAINT_REGION 
2221     if (!m_paintClippingRegion
.IsNull()) 
2222         m_currentClippingRegion
.Intersect( m_paintClippingRegion 
); 
2225     wxCoord xx
, yy
, ww
, hh
; 
2226     m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh 
); 
2227     wxGTKDCImpl::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
2229     GdkRegion
* gdkRegion 
= m_currentClippingRegion
.GetRegion(); 
2230     gdk_gc_set_clip_region(m_penGC
,   gdkRegion
); 
2231     gdk_gc_set_clip_region(m_brushGC
, gdkRegion
); 
2232     gdk_gc_set_clip_region(m_textGC
,  gdkRegion
); 
2233     gdk_gc_set_clip_region(m_bgGC
,    gdkRegion
); 
2236 void wxWindowDCImpl::DestroyClippingRegion() 
2238     wxCHECK_RET( IsOk(), wxT("invalid window dc") ); 
2240     wxDCImpl::DestroyClippingRegion(); 
2242     m_currentClippingRegion
.Clear(); 
2244 #if USE_PAINT_REGION 
2245     if (!m_paintClippingRegion
.IsEmpty()) 
2246         m_currentClippingRegion
.Union( m_paintClippingRegion 
); 
2249     if (!m_gdkwindow
) return; 
2251     GdkRegion
* gdkRegion 
= NULL
; 
2252     if (!m_currentClippingRegion
.IsEmpty()) 
2253         gdkRegion 
= m_currentClippingRegion
.GetRegion(); 
2255     gdk_gc_set_clip_region(m_penGC
,   gdkRegion
); 
2256     gdk_gc_set_clip_region(m_brushGC
, gdkRegion
); 
2257     gdk_gc_set_clip_region(m_textGC
,  gdkRegion
); 
2258     gdk_gc_set_clip_region(m_bgGC
,    gdkRegion
); 
2261 void wxWindowDCImpl::Destroy() 
2263     if (m_penGC
) wxFreePoolGC( m_penGC 
); 
2264     m_penGC 
= (GdkGC
*) NULL
; 
2265     if (m_brushGC
) wxFreePoolGC( m_brushGC 
); 
2266     m_brushGC 
= (GdkGC
*) NULL
; 
2267     if (m_textGC
) wxFreePoolGC( m_textGC 
); 
2268     m_textGC 
= (GdkGC
*) NULL
; 
2269     if (m_bgGC
) wxFreePoolGC( m_bgGC 
); 
2270     m_bgGC 
= (GdkGC
*) NULL
; 
2273 void wxWindowDCImpl::SetDeviceOrigin( wxCoord x
, wxCoord y 
) 
2275     m_deviceOriginX 
= x
; 
2276     m_deviceOriginY 
= y
; 
2278     ComputeScaleAndOrigin(); 
2281 void wxWindowDCImpl::SetAxisOrientation( bool xLeftRight
, bool yBottomUp 
) 
2283     m_signX 
= (xLeftRight 
?  1 : -1); 
2284     m_signY 
= (yBottomUp  
? -1 :  1); 
2286     if (m_window 
&& m_window
->m_wxwindow 
&&  
2287         (m_window
->GetLayoutDirection() == wxLayout_RightToLeft
)) 
2290     ComputeScaleAndOrigin(); 
2293 void wxWindowDCImpl::ComputeScaleAndOrigin() 
2295     const wxRealPoint 
origScale(m_scaleX
, m_scaleY
); 
2297     wxDCImpl::ComputeScaleAndOrigin(); 
2299     // if scale has changed call SetPen to recalulate the line width 
2300     if ( wxRealPoint(m_scaleX
, m_scaleY
) != origScale 
&& m_pen
.IsOk() ) 
2302         // this is a bit artificial, but we need to force wxDC to think the pen 
2310 // Resolution in pixels per logical inch 
2311 wxSize 
wxWindowDCImpl::GetPPI() const 
2313     return wxSize( (int) (m_mm_to_pix_x 
* 25.4 + 0.5), (int) (m_mm_to_pix_y 
* 25.4 + 0.5)); 
2316 int wxWindowDCImpl::GetDepth() const 
2318     return gdk_drawable_get_depth(m_gdkwindow
); 
2322 //----------------------------------------------------------------------------- 
2324 //----------------------------------------------------------------------------- 
2326 IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl
, wxWindowDCImpl
) 
2328 wxClientDCImpl::wxClientDCImpl( wxDC 
*owner 
) 
2329           : wxWindowDCImpl( owner 
) 
2333 wxClientDCImpl::wxClientDCImpl( wxDC 
*owner
, wxWindow 
*win 
) 
2334           : wxWindowDCImpl( owner
, win 
) 
2336     wxCHECK_RET( win
, _T("NULL window in wxClientDCImpl::wxClientDC") ); 
2338 #ifdef __WXUNIVERSAL__ 
2339     wxPoint ptOrigin 
= win
->GetClientAreaOrigin(); 
2340     SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
); 
2341     wxSize size 
= win
->GetClientSize(); 
2342     DoSetClippingRegion(0, 0, size
.x
, size
.y
); 
2347 void wxClientDCImpl::DoGetSize(int *width
, int *height
) const 
2349     wxCHECK_RET( m_window
, _T("GetSize() doesn't work without window") ); 
2351     m_window
->GetClientSize( width
, height 
); 
2354 //----------------------------------------------------------------------------- 
2356 //----------------------------------------------------------------------------- 
2358 IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl
, wxClientDCImpl
) 
2360 // Limit the paint region to the window size. Sometimes 
2361 // the paint region is too big, and this risks X11 errors 
2362 static void wxLimitRegionToSize(wxRegion
& region
, const wxSize
& sz
) 
2364     wxRect originalRect 
= region
.GetBox(); 
2365     wxRect 
rect(originalRect
); 
2366     if (rect
.width 
+ rect
.x 
> sz
.x
) 
2367         rect
.width 
= sz
.x 
- rect
.x
; 
2368     if (rect
.height 
+ rect
.y 
> sz
.y
) 
2369         rect
.height 
= sz
.y 
- rect
.y
; 
2370     if (rect 
!= originalRect
) 
2372         region 
= wxRegion(rect
); 
2373         wxLogTrace(wxT("painting"), wxT("Limiting region from %d, %d, %d, %d to %d, %d, %d, %d\n"), 
2374                    originalRect
.x
, originalRect
.y
, originalRect
.width
, originalRect
.height
, 
2375                    rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
2379 wxPaintDCImpl::wxPaintDCImpl( wxDC 
*owner 
) 
2380          : wxClientDCImpl( owner 
) 
2384 wxPaintDCImpl::wxPaintDCImpl( wxDC 
*owner
, wxWindow 
*win 
) 
2385          : wxClientDCImpl( owner
, win 
) 
2387 #if USE_PAINT_REGION 
2388     if (!win
->m_clipPaintRegion
) 
2391     wxSize sz 
= win
->GetSize(); 
2392     m_paintClippingRegion 
= win
->m_nativeUpdateRegion
; 
2393     wxLimitRegionToSize(m_paintClippingRegion
, sz
); 
2395     GdkRegion 
*region 
= m_paintClippingRegion
.GetRegion(); 
2398         m_currentClippingRegion
.Union( m_paintClippingRegion 
); 
2399         wxLimitRegionToSize(m_currentClippingRegion
, sz
); 
2401         if (sz
.x 
<= 0 || sz
.y 
<= 0) 
2404         gdk_gc_set_clip_region( m_penGC
, region 
); 
2405         gdk_gc_set_clip_region( m_brushGC
, region 
); 
2406         gdk_gc_set_clip_region( m_textGC
, region 
); 
2407         gdk_gc_set_clip_region( m_bgGC
, region 
); 
2412 // ---------------------------------------------------------------------------- 
2414 // ---------------------------------------------------------------------------- 
2416 class wxDCModule 
: public wxModule
 
2423     DECLARE_DYNAMIC_CLASS(wxDCModule
) 
2426 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
) 
2428 bool wxDCModule::OnInit() 
2434 void wxDCModule::OnExit() 
2438     for (int i 
= wxBRUSHSTYLE_LAST_HATCH 
- wxBRUSHSTYLE_FIRST_HATCH
; i
--; ) 
2441             g_object_unref(hatches
[i
]);