]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk/dcclient.cpp
eea9ffd7c3ae2cffa6d3f3098f90aea01c379e1e
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        gtk/dcclient.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling, Markus Holzem, Chris Breeze 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  11 #pragma implementation "dcclient.h" 
  15 #define XCopyPlane XCOPYPLANE 
  18 #include "wx/dcclient.h" 
  19 #include "wx/dcmemory.h" 
  21 #include "wx/module.h" 
  23 #include "wx/fontutil.h" 
  25 #include "wx/gtk/win_gtk.h" 
  27 #include <math.h>               // for floating-point functions 
  31 #include <gdk/gdkprivate.h> 
  34 //----------------------------------------------------------------------------- 
  36 //----------------------------------------------------------------------------- 
  38 #define USE_PAINT_REGION 1 
  40 //----------------------------------------------------------------------------- 
  42 //----------------------------------------------------------------------------- 
  52 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH) 
  53 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH) 
  56 static GdkPixmap  
*hatches
[num_hatches
]; 
  57 static GdkPixmap 
**hatch_bitmap 
= (GdkPixmap 
**) NULL
; 
  59 extern GtkWidget 
*wxGetRootWindow(); 
  61 //----------------------------------------------------------------------------- 
  63 //----------------------------------------------------------------------------- 
  65 const double RAD2DEG  
= 180.0 / M_PI
; 
  67 // ---------------------------------------------------------------------------- 
  69 // ---------------------------------------------------------------------------- 
  71 static inline double dmax(double a
, double b
) { return a 
> b 
? a 
: b
; } 
  72 static inline double dmin(double a
, double b
) { return a 
< b 
? a 
: b
; } 
  74 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
  76 //----------------------------------------------------------------------------- 
  77 // temporary implementation of the missing GDK function 
  78 //----------------------------------------------------------------------------- 
  80 #include "gdk/gdkprivate.h" 
  82 void gdk_wx_draw_bitmap(GdkDrawable  
*drawable
, 
  92     gint src_width
, src_height
; 
  94     GdkWindowPrivate 
*drawable_private
; 
  95     GdkWindowPrivate 
*src_private
; 
  96     GdkGCPrivate 
*gc_private
; 
  99     g_return_if_fail (drawable 
!= NULL
); 
 100     g_return_if_fail (src 
!= NULL
); 
 101     g_return_if_fail (gc 
!= NULL
); 
 104     if (GDK_WINDOW_DESTROYED(drawable
) || GDK_WINDOW_DESTROYED(src
)) 
 107     gdk_drawable_get_size(src
, &src_width
, &src_height
); 
 109     drawable_private 
= (GdkWindowPrivate
*) drawable
; 
 110     src_private 
= (GdkWindowPrivate
*) src
; 
 111     if (drawable_private
->destroyed 
|| src_private
->destroyed
) 
 114     src_width 
= src_private
->width
; 
 115     src_height 
= src_private
->height
; 
 117     gc_private 
= (GdkGCPrivate
*) gc
; 
 120     if (width 
== -1) width 
= src_width
; 
 121     if (height 
== -1) height 
= src_height
; 
 124     XCopyPlane( GDK_WINDOW_XDISPLAY(drawable
), 
 126                 GDK_WINDOW_XID(drawable
), 
 133     XCopyPlane( drawable_private
->xdisplay
, 
 134                 src_private
->xwindow
, 
 135                 drawable_private
->xwindow
, 
 144 //----------------------------------------------------------------------------- 
 145 // Implement Pool of Graphic contexts. Creating them takes too much time. 
 146 //----------------------------------------------------------------------------- 
 148 #define GC_POOL_SIZE 200 
 174 #define GC_POOL_ALLOC_SIZE 100 
 176 static int wxGCPoolSize 
= 0; 
 178 static wxGC 
*wxGCPool 
= NULL
; 
 180 static void wxInitGCPool() 
 182     // This really could wait until the first call to 
 183     // wxGetPoolGC, but we will make the first allocation 
 184     // now when other initialization is being performed. 
 186     // Set initial pool size. 
 187     wxGCPoolSize 
= GC_POOL_ALLOC_SIZE
; 
 189     // Allocate initial pool. 
 190     wxGCPool 
= (wxGC 
*)malloc(wxGCPoolSize 
* sizeof(wxGC
)); 
 191     if (wxGCPool 
== NULL
) 
 193         // If we cannot malloc, then fail with error 
 194         // when debug is enabled.  If debug is not enabled, 
 195         // the problem will eventually get caught 
 197         wxFAIL_MSG( wxT("Cannot allocate GC pool") ); 
 201     // Zero initial pool. 
 202     memset(wxGCPool
, 0, wxGCPoolSize 
* sizeof(wxGC
)); 
 205 static void wxCleanUpGCPool() 
 207     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 209         if (wxGCPool
[i
].m_gc
) 
 210             gdk_gc_unref( wxGCPool
[i
].m_gc 
); 
 218 static GdkGC
* wxGetPoolGC( GdkWindow 
*window
, wxPoolGCType type 
) 
 222     // Look for an available GC. 
 223     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 225         if (!wxGCPool
[i
].m_gc
) 
 227             wxGCPool
[i
].m_gc 
= gdk_gc_new( window 
); 
 228             gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE 
); 
 229             wxGCPool
[i
].m_type 
= type
; 
 230             wxGCPool
[i
].m_used 
= FALSE
; 
 232         if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type 
== type
)) 
 234             wxGCPool
[i
].m_used 
= TRUE
; 
 235             return wxGCPool
[i
].m_gc
; 
 239     // We did not find an available GC. 
 240     // We need to grow the GC pool. 
 241     pptr 
= (wxGC 
*)realloc(wxGCPool
, 
 242                 (wxGCPoolSize 
+ GC_POOL_ALLOC_SIZE
)*sizeof(wxGC
)); 
 245         // Initialize newly allocated pool. 
 247         memset(&wxGCPool
[wxGCPoolSize
], 0, 
 248                         GC_POOL_ALLOC_SIZE
*sizeof(wxGC
)); 
 250         // Initialize entry we will return.     
 251         wxGCPool
[wxGCPoolSize
].m_gc 
= gdk_gc_new( window 
); 
 252         gdk_gc_set_exposures( wxGCPool
[wxGCPoolSize
].m_gc
, FALSE 
); 
 253         wxGCPool
[wxGCPoolSize
].m_type 
= type
; 
 254         wxGCPool
[wxGCPoolSize
].m_used 
= TRUE
; 
 256         // Set new value of pool size. 
 257         wxGCPoolSize 
+= GC_POOL_ALLOC_SIZE
; 
 259         // Return newly allocated entry. 
 260         return wxGCPool
[wxGCPoolSize
-GC_POOL_ALLOC_SIZE
].m_gc
; 
 263     // The realloc failed.  Fall through to error. 
 264     wxFAIL_MSG( wxT("No GC available") ); 
 266     return (GdkGC
*) NULL
; 
 269 static void wxFreePoolGC( GdkGC 
*gc 
) 
 271     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 273         if (wxGCPool
[i
].m_gc 
== gc
) 
 275             wxGCPool
[i
].m_used 
= FALSE
; 
 280     wxFAIL_MSG( wxT("Wrong GC") ); 
 283 //----------------------------------------------------------------------------- 
 285 //----------------------------------------------------------------------------- 
 287 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
) 
 289 wxWindowDC::wxWindowDC() 
 291     m_penGC 
= (GdkGC 
*) NULL
; 
 292     m_brushGC 
= (GdkGC 
*) NULL
; 
 293     m_textGC 
= (GdkGC 
*) NULL
; 
 294     m_bgGC 
= (GdkGC 
*) NULL
; 
 295     m_cmap 
= (GdkColormap 
*) NULL
; 
 297     m_isScreenDC 
= FALSE
; 
 298     m_owner 
= (wxWindow 
*)NULL
; 
 300     m_context 
= (PangoContext 
*)NULL
; 
 301     m_fontdesc 
= (PangoFontDescription 
*)NULL
; 
 305 wxWindowDC::wxWindowDC( wxWindow 
*window 
) 
 307     wxASSERT_MSG( window
, wxT("DC needs a window") ); 
 309     m_penGC 
= (GdkGC 
*) NULL
; 
 310     m_brushGC 
= (GdkGC 
*) NULL
; 
 311     m_textGC 
= (GdkGC 
*) NULL
; 
 312     m_bgGC 
= (GdkGC 
*) NULL
; 
 313     m_cmap 
= (GdkColormap 
*) NULL
; 
 314     m_owner 
= (wxWindow 
*)NULL
; 
 316     m_isScreenDC 
= FALSE
; 
 317     m_font 
= window
->GetFont(); 
 319     GtkWidget 
*widget 
= window
->m_wxwindow
; 
 321     // some controls don't have m_wxwindow - like wxStaticBox, but the user 
 322     // code should still be able to create wxClientDCs for them, so we will 
 323     // use the parent window here then 
 326         window 
= window
->GetParent(); 
 327         widget 
= window
->m_wxwindow
; 
 330     wxASSERT_MSG( widget
, wxT("DC needs a widget") ); 
 333     m_context 
= gtk_widget_get_pango_context( widget 
); 
 334     m_fontdesc 
= widget
->style
->font_desc
; 
 337     GtkPizza 
*pizza 
= GTK_PIZZA( widget 
); 
 338     m_window 
= pizza
->bin_window
; 
 343          /* don't report problems */ 
 349     m_cmap 
= gtk_widget_get_colormap( widget 
? widget 
: window
->m_widget 
); 
 353     /* this must be done after SetUpDC, bacause SetUpDC calls the 
 354        repective SetBrush, SetPen, SetBackground etc functions 
 355        to set up the DC. SetBackground call m_owner->SetBackground 
 356        and this might not be desired as the standard dc background 
 357        is white whereas a window might assume gray to be the 
 358        standard (as e.g. wxStatusBar) */ 
 363 wxWindowDC::~wxWindowDC() 
 368 void wxWindowDC::SetUpDC() 
 372     wxASSERT_MSG( !m_penGC
, wxT("GCs already created") ); 
 376         m_penGC 
= wxGetPoolGC( m_window
, wxPEN_SCREEN 
); 
 377         m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_SCREEN 
); 
 378         m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_SCREEN 
); 
 379         m_bgGC 
= wxGetPoolGC( m_window
, wxBG_SCREEN 
); 
 382     if (m_isMemDC 
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1)) 
 384         m_penGC 
= wxGetPoolGC( m_window
, wxPEN_MONO 
); 
 385         m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_MONO 
); 
 386         m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_MONO 
); 
 387         m_bgGC 
= wxGetPoolGC( m_window
, wxBG_MONO 
); 
 391         m_penGC 
= wxGetPoolGC( m_window
, wxPEN_COLOUR 
); 
 392         m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR 
); 
 393         m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_COLOUR 
); 
 394         m_bgGC 
= wxGetPoolGC( m_window
, wxBG_COLOUR 
); 
 397     /* background colour */ 
 398     m_backgroundBrush 
= *wxWHITE_BRUSH
; 
 399     m_backgroundBrush
.GetColour().CalcPixel( m_cmap 
); 
 400     GdkColor 
*bg_col 
= m_backgroundBrush
.GetColour().GetColor(); 
 403     m_textForegroundColour
.CalcPixel( m_cmap 
); 
 404     gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
 406     m_textBackgroundColour
.CalcPixel( m_cmap 
); 
 407     gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() ); 
 409     gdk_gc_set_fill( m_textGC
, GDK_SOLID 
); 
 412     m_pen
.GetColour().CalcPixel( m_cmap 
); 
 413     gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() ); 
 414     gdk_gc_set_background( m_penGC
, bg_col 
); 
 416     gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND 
); 
 419     m_brush
.GetColour().CalcPixel( m_cmap 
); 
 420     gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() ); 
 421     gdk_gc_set_background( m_brushGC
, bg_col 
); 
 423     gdk_gc_set_fill( m_brushGC
, GDK_SOLID 
); 
 426     gdk_gc_set_background( m_bgGC
, bg_col 
); 
 427     gdk_gc_set_foreground( m_bgGC
, bg_col 
); 
 429     gdk_gc_set_fill( m_bgGC
, GDK_SOLID 
); 
 432     gdk_gc_set_function( m_textGC
, GDK_COPY 
); 
 433     gdk_gc_set_function( m_brushGC
, GDK_COPY 
); 
 434     gdk_gc_set_function( m_penGC
, GDK_COPY 
); 
 437     gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle 
*) NULL 
); 
 438     gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle 
*) NULL 
); 
 439     gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle 
*) NULL 
); 
 440     gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle 
*) NULL 
); 
 444         hatch_bitmap    
= hatches
; 
 445         hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height 
); 
 446         hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height 
); 
 447         hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height 
); 
 448         hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, cross_bits
, cross_width
, cross_height 
); 
 449         hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, horiz_bits
, horiz_width
, horiz_height 
); 
 450         hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, verti_bits
, verti_width
, verti_height 
); 
 454 void wxWindowDC::DoGetSize( int* width
, int* height 
) const 
 456     wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") ); 
 458     m_owner
->GetSize(width
, height
); 
 461 extern bool wxDoFloodFill(wxDC 
*dc
, wxCoord x
, wxCoord y
,  
 462                           const wxColour 
& col
, int style
); 
 464 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
, 
 465                              const wxColour
& col
, int style
) 
 467     return wxDoFloodFill(this, x
, y
, col
, style
); 
 470 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour 
*col 
) const 
 472     // Generic (and therefore rather inefficient) method. 
 473     // Could be improved. 
 475     wxBitmap 
bitmap(1, 1); 
 476     memdc
.SelectObject(bitmap
); 
 477     memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
); 
 478     memdc
.SelectObject(wxNullBitmap
); 
 480     wxImage image 
= bitmap
.ConvertToImage(); 
 481     col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0)); 
 485 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2 
) 
 487     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 489     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 492             gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) ); 
 494         CalcBoundingBox(x1
, y1
); 
 495         CalcBoundingBox(x2
, y2
); 
 499 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y 
) 
 501     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 503     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 508         wxCoord xx 
= XLOG2DEV(x
); 
 509         wxCoord yy 
= YLOG2DEV(y
); 
 512             gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy 
); 
 513             gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) ); 
 518 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, 
 519                             wxCoord xc
, wxCoord yc 
) 
 521     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 523     wxCoord xx1 
= XLOG2DEV(x1
); 
 524     wxCoord yy1 
= YLOG2DEV(y1
); 
 525     wxCoord xx2 
= XLOG2DEV(x2
); 
 526     wxCoord yy2 
= YLOG2DEV(y2
); 
 527     wxCoord xxc 
= XLOG2DEV(xc
); 
 528     wxCoord yyc 
= YLOG2DEV(yc
); 
 529     double dx 
= xx1 
- xxc
; 
 530     double dy 
= yy1 
- yyc
; 
 531     double radius 
= sqrt((double)(dx
*dx
+dy
*dy
)); 
 532     wxCoord   r      
= (wxCoord
)radius
; 
 533     double radius1
, radius2
; 
 535     if (xx1 
== xx2 
&& yy1 
== yy2
) 
 543         radius1 
= radius2 
= 0.0; 
 547         radius1 
= (xx1 
- xxc 
== 0) ? 
 548             (yy1 
- yyc 
< 0) ? 90.0 : -90.0 : 
 549             -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
; 
 550         radius2 
= (xx2 
- xxc 
== 0) ? 
 551             (yy2 
- yyc 
< 0) ? 90.0 : -90.0 : 
 552             -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
; 
 554     wxCoord alpha1 
= wxCoord(radius1 
* 64.0); 
 555     wxCoord alpha2 
= wxCoord((radius2 
- radius1
) * 64.0); 
 556     while (alpha2 
<= 0) alpha2 
+= 360*64; 
 557     while (alpha1 
> 360*64) alpha1 
-= 360*64; 
 561         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 563             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 565                 gdk_gc_set_ts_origin( m_textGC
, 
 566                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 567                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 568                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 569                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 571             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 573                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 574                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 575                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 577             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 579                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 580                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 581                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 583             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 585                 gdk_gc_set_ts_origin( m_brushGC
, 
 586                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 587                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 588                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 589                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 593                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 597         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 599             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 601             gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc 
); 
 602             gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2 
); 
 606     CalcBoundingBox (x1
, y1
); 
 607     CalcBoundingBox (x2
, y2
); 
 610 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea 
) 
 612     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 614     wxCoord xx 
= XLOG2DEV(x
); 
 615     wxCoord yy 
= YLOG2DEV(y
); 
 616     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 617     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 619     // CMB: handle -ve width and/or height 
 620     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 621     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 625         wxCoord start 
= wxCoord(sa 
* 64.0); 
 626         wxCoord end 
= wxCoord((ea
-sa
) * 64.0); 
 628         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 630             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 632                 gdk_gc_set_ts_origin( m_textGC
, 
 633                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 634                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 635                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 636                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 638             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 640                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 641                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 642                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 644             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 646                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 647                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 648                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 650             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 652                 gdk_gc_set_ts_origin( m_brushGC
, 
 653                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 654                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 655                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 656                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 660                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 664         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 665             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end 
); 
 668     CalcBoundingBox (x
, y
); 
 669     CalcBoundingBox (x 
+ width
, y 
+ height
); 
 672 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y 
) 
 674     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 676     if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
) 
 677         gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) ); 
 679     CalcBoundingBox (x
, y
); 
 682 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset 
) 
 684     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 686     if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 689     CalcBoundingBox( points
[0].x 
+ xoffset
, points
[0].y 
+ yoffset 
); 
 691     for (int i 
= 0; i 
< n
-1; i
++) 
 693         wxCoord x1 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 694         wxCoord x2 
= XLOG2DEV(points
[i
+1].x 
+ xoffset
); 
 695         wxCoord y1 
= YLOG2DEV(points
[i
].y 
+ yoffset
);     // oh, what a waste 
 696         wxCoord y2 
= YLOG2DEV(points
[i
+1].y 
+ yoffset
); 
 699             gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2 
); 
 701         CalcBoundingBox( points
[i
+1].x 
+ xoffset
, points
[i
+1].y 
+ yoffset 
); 
 705 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) ) 
 707     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 711     GdkPoint 
*gdkpoints 
= new GdkPoint
[n
+1]; 
 713     for (i 
= 0 ; i 
< n 
; i
++) 
 715         gdkpoints
[i
].x 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 716         gdkpoints
[i
].y 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 718         CalcBoundingBox( points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset 
); 
 723         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 725             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 727                 gdk_gc_set_ts_origin( m_textGC
, 
 728                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 729                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 730                 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n 
); 
 731                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 733             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 735                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 736                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 737                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 739             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 741                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 742                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 743                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 745             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 747                 gdk_gc_set_ts_origin( m_brushGC
, 
 748                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 749                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 750                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 751                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 755                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 759         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 761             for (i 
= 0 ; i 
< n 
; i
++) 
 763                 gdk_draw_line( m_window
, m_penGC
, 
 766                                gdkpoints
[(i
+1)%n
].x
, 
 767                                gdkpoints
[(i
+1)%n
].y
); 
 775 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 777     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 779     wxCoord xx 
= XLOG2DEV(x
); 
 780     wxCoord yy 
= YLOG2DEV(y
); 
 781     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 782     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 784     // CMB: draw nothing if transformed w or h is 0 
 785     if (ww 
== 0 || hh 
== 0) return; 
 787     // CMB: handle -ve width and/or height 
 788     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 789     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 793         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 795             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 797                 gdk_gc_set_ts_origin( m_textGC
, 
 798                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 799                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 800                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 801                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 803             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 805                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 806                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 807                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 809             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 811                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 812                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 813                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 815             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 817                 gdk_gc_set_ts_origin( m_brushGC
, 
 818                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 819                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 820                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 821                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 825                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 829         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 830             gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 ); 
 833     CalcBoundingBox( x
, y 
); 
 834     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 837 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius 
) 
 839     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 841     if (radius 
< 0.0) radius 
= - radius 
* ((width 
< height
) ? width 
: height
); 
 843     wxCoord xx 
= XLOG2DEV(x
); 
 844     wxCoord yy 
= YLOG2DEV(y
); 
 845     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 846     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 847     wxCoord rr 
= XLOG2DEVREL((wxCoord
)radius
); 
 849     // CMB: handle -ve width and/or height 
 850     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 851     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 853     // CMB: if radius is zero use DrawRectangle() instead to avoid 
 854     // X drawing errors with small radii 
 857         DrawRectangle( x
, y
, width
, height 
); 
 861     // CMB: draw nothing if transformed w or h is 0 
 862     if (ww 
== 0 || hh 
== 0) return; 
 864     // CMB: adjust size if outline is drawn otherwise the result is 
 865     // 1 pixel too wide and high 
 866     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 874         // CMB: ensure dd is not larger than rectangle otherwise we 
 875         // get an hour glass shape 
 877         if (dd 
> ww
) dd 
= ww
; 
 878         if (dd 
> hh
) dd 
= hh
; 
 881         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 883             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 885                 gdk_gc_set_ts_origin( m_textGC
, 
 886                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 887                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 888                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 889                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 890                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 891                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 892                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 893                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 894                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 896             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 898                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 899                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 900                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 901                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 902                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 903                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 904                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 905                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 907             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 909                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 910                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 911                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 912                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 913                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 914                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 915                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 916                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 918             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 920                 gdk_gc_set_ts_origin( m_brushGC
, 
 921                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 922                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 923                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 924                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 925                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 926                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 927                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 928                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 929                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 933                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 934                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 935                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 936                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 937                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 938                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 942         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 944             gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy 
); 
 945             gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh 
); 
 946             gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr 
); 
 947             gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr 
); 
 948             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 949             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 950             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 951             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 955     // this ignores the radius 
 956     CalcBoundingBox( x
, y 
); 
 957     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 960 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 962     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 964     wxCoord xx 
= XLOG2DEV(x
); 
 965     wxCoord yy 
= YLOG2DEV(y
); 
 966     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 967     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 969     // CMB: handle -ve width and/or height 
 970     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 971     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 975         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 977             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 979                 gdk_gc_set_ts_origin( m_textGC
, 
 980                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 981                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 982                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
 983                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 985             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 987                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 988                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
 989                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 991             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 993                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 994                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
 995                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 997             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 999                 gdk_gc_set_ts_origin( m_brushGC
, 
1000                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
1001                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
1002                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1003                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
1007                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1011         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
1012             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1015     CalcBoundingBox( x
, y 
); 
1016     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
1019 void wxWindowDC::DoDrawIcon( const wxIcon 
&icon
, wxCoord x
, wxCoord y 
) 
1021     // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why 
1022     DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE 
); 
1025 void wxWindowDC::DoDrawBitmap( const wxBitmap 
&bitmap
, 
1026                                wxCoord x
, wxCoord y
, 
1029     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1031     wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") ); 
1033     bool is_mono 
= (bitmap
.GetBitmap() != NULL
); 
1035     /* scale/translate size and position */ 
1036     int xx 
= XLOG2DEV(x
); 
1037     int yy 
= YLOG2DEV(y
); 
1039     int w 
= bitmap
.GetWidth(); 
1040     int h 
= bitmap
.GetHeight(); 
1042     CalcBoundingBox( x
, y 
); 
1043     CalcBoundingBox( x 
+ w
, y 
+ h 
); 
1045     if (!m_window
) return; 
1047     int ww 
= XLOG2DEVREL(w
); 
1048     int hh 
= YLOG2DEVREL(h
); 
1050     /* compare to current clipping region */ 
1051     if (!m_currentClippingRegion
.IsNull()) 
1053         wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1054         tmp
.Intersect( m_currentClippingRegion 
); 
1059     /* scale bitmap if required */ 
1060     wxBitmap use_bitmap
; 
1061     if ((w 
!= ww
) || (h 
!= hh
)) 
1063         wxImage image 
= bitmap
.ConvertToImage(); 
1064         image
.Rescale( ww
, hh 
); 
1066             use_bitmap 
= wxBitmap(image
.ConvertToMono(255,255,255), 1); 
1068             use_bitmap 
= wxBitmap(image
); 
1072         use_bitmap 
= bitmap
; 
1075     /* apply mask if any */ 
1076     GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
1077     if (use_bitmap
.GetMask()) mask 
= use_bitmap
.GetMask()->GetBitmap(); 
1079         if (useMask 
&& mask
) 
1081             GdkBitmap 
*new_mask 
= (GdkBitmap
*) NULL
; 
1082 #ifndef __WXGTK20__  // TODO fix crash 
1083             if (!m_currentClippingRegion
.IsNull()) 
1086                 new_mask 
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 ); 
1087                 GdkGC 
*gc 
= gdk_gc_new( new_mask 
); 
1089                 gdk_gc_set_foreground( gc
, &col 
); 
1090                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh 
); 
1092                 gdk_gc_set_background( gc
, &col 
); 
1094                 gdk_gc_set_foreground( gc
, &col 
); 
1095                 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() ); 
1096                 gdk_gc_set_clip_origin( gc
, -xx
, -yy 
); 
1097                 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED 
); 
1098                 gdk_gc_set_stipple( gc
, mask 
); 
1099                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh 
); 
1106                     gdk_gc_set_clip_mask( m_textGC
, new_mask 
); 
1108                     gdk_gc_set_clip_mask( m_textGC
, mask 
); 
1109                 gdk_gc_set_clip_origin( m_textGC
, xx
, yy 
); 
1114                     gdk_gc_set_clip_mask( m_penGC
, new_mask 
); 
1116                     gdk_gc_set_clip_mask( m_penGC
, mask 
); 
1117                 gdk_gc_set_clip_origin( m_penGC
, xx
, yy 
); 
1121                 gdk_bitmap_unref( new_mask 
); 
1124     /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 
1125        drawing a mono-bitmap (XBitmap) we use the current text GC */ 
1127         gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 ); 
1129         gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 ); 
1131     /* remove mask again if any */ 
1132     if (useMask 
&& mask
) 
1136             gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap 
*) NULL 
); 
1137             gdk_gc_set_clip_origin( m_textGC
, 0, 0 ); 
1138             if (!m_currentClippingRegion
.IsNull()) 
1139                 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
1143             gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap 
*) NULL 
); 
1144             gdk_gc_set_clip_origin( m_penGC
, 0, 0 ); 
1145             if (!m_currentClippingRegion
.IsNull()) 
1146                 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
1151 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, 
1152                          wxCoord width
, wxCoord height
, 
1154                          wxCoord xsrc
, wxCoord ysrc
, 
1157                          wxCoord xsrcMask
, wxCoord ysrcMask 
) 
1159    /* this is the nth try to get this utterly useless function to 
1160       work. it now completely ignores the scaling or translation 
1161       of the source dc, but scales correctly on the target dc and 
1162       knows about possible mask information in a memory dc. */ 
1164     wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") ); 
1166     wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") ); 
1168     if (!m_window
) return FALSE
; 
1171     // transform the source DC coords to the device ones 
1172     xsrc 
= source
->XLOG2DEV(xsrc
); 
1173     ysrc 
= source
->YLOG2DEV(ysrc
); 
1176     wxClientDC 
*srcDC 
= (wxClientDC
*)source
; 
1177     wxMemoryDC 
*memDC 
= (wxMemoryDC
*)source
; 
1179     bool use_bitmap_method 
= FALSE
; 
1180     bool is_mono 
= FALSE
; 
1182     /* TODO: use the mask origin when drawing transparently */ 
1183     if (xsrcMask 
== -1 && ysrcMask 
== -1) 
1185         xsrcMask 
= xsrc
; ysrcMask 
= ysrc
; 
1188     if (srcDC
->m_isMemDC
) 
1190         if (!memDC
->m_selected
.Ok()) return FALSE
; 
1192         /* we use the "XCopyArea" way to copy a memory dc into 
1193            y different window if the memory dc BOTH 
1194            a) doesn't have any mask or its mask isn't used 
1198         if (useMask 
&& (memDC
->m_selected
.GetMask())) 
1200            /* we HAVE TO use the direct way for memory dcs 
1201               that have mask since the XCopyArea doesn't know 
1203             use_bitmap_method 
= TRUE
; 
1205         else if (memDC
->m_selected
.GetDepth() == 1) 
1207            /* we HAVE TO use the direct way for memory dcs 
1208               that are bitmaps because XCopyArea doesn't cope 
1209               with different bit depths */ 
1211             use_bitmap_method 
= TRUE
; 
1213         else if ((xsrc 
== 0) && (ysrc 
== 0) && 
1214                  (width 
== memDC
->m_selected
.GetWidth()) && 
1215                  (height 
== memDC
->m_selected
.GetHeight())) 
1217            /* we SHOULD use the direct way if all of the bitmap 
1218               in the memory dc is copied in which case XCopyArea 
1219               wouldn't be able able to boost performace by reducing 
1220               the area to be scaled */ 
1221             use_bitmap_method 
= TRUE
; 
1225             use_bitmap_method 
= FALSE
; 
1229     CalcBoundingBox( xdest
, ydest 
); 
1230     CalcBoundingBox( xdest 
+ width
, ydest 
+ height 
); 
1232     /* scale/translate size and position */ 
1233     wxCoord xx 
= XLOG2DEV(xdest
); 
1234     wxCoord yy 
= YLOG2DEV(ydest
); 
1236     wxCoord ww 
= XLOG2DEVREL(width
); 
1237     wxCoord hh 
= YLOG2DEVREL(height
); 
1239     /* compare to current clipping region */ 
1240     if (!m_currentClippingRegion
.IsNull()) 
1242         wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1243         tmp
.Intersect( m_currentClippingRegion 
); 
1248     int old_logical_func 
= m_logicalFunction
; 
1249     SetLogicalFunction( logical_func 
); 
1251     if (use_bitmap_method
) 
1253         /* scale/translate bitmap size */ 
1254         wxCoord bm_width 
= memDC
->m_selected
.GetWidth(); 
1255         wxCoord bm_height 
= memDC
->m_selected
.GetHeight(); 
1257         wxCoord bm_ww 
= XLOG2DEVREL( bm_width 
); 
1258         wxCoord bm_hh 
= YLOG2DEVREL( bm_height 
); 
1260         /* scale bitmap if required */ 
1261         wxBitmap use_bitmap
; 
1263         if ((bm_width 
!= bm_ww
) || (bm_height 
!= bm_hh
)) 
1265             wxImage image 
= memDC
->m_selected
.ConvertToImage(); 
1266             image 
= image
.Scale( bm_ww
, bm_hh 
); 
1269                 use_bitmap 
= wxBitmap(image
.ConvertToMono(255,255,255), 1); 
1271                 use_bitmap 
= wxBitmap(image
); 
1275             use_bitmap 
= memDC
->m_selected
; 
1278         /* apply mask if any */ 
1279         GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
1280         if (use_bitmap
.GetMask()) mask 
= use_bitmap
.GetMask()->GetBitmap(); 
1282         if (useMask 
&& mask
) 
1284             GdkBitmap 
*new_mask 
= (GdkBitmap
*) NULL
; 
1285 #ifndef __WXGTK20__  // TODO fix crash 
1286             if (!m_currentClippingRegion
.IsNull()) 
1289                 new_mask 
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 ); 
1290                 GdkGC 
*gc 
= gdk_gc_new( new_mask 
); 
1292                 gdk_gc_set_foreground( gc
, &col 
); 
1293                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh 
); 
1295                 gdk_gc_set_background( gc
, &col 
); 
1297                 gdk_gc_set_foreground( gc
, &col 
); 
1298                 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() ); 
1299                 gdk_gc_set_clip_origin( gc
, -xx
, -yy 
); 
1300                 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED 
); 
1301                 gdk_gc_set_stipple( gc
, mask 
); 
1302                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh 
); 
1309                     gdk_gc_set_clip_mask( m_textGC
, new_mask 
); 
1311                     gdk_gc_set_clip_mask( m_textGC
, mask 
); 
1312                 gdk_gc_set_clip_origin( m_textGC
, xx
, yy 
); 
1317                     gdk_gc_set_clip_mask( m_penGC
, new_mask 
); 
1319                     gdk_gc_set_clip_mask( m_penGC
, mask 
); 
1320                 gdk_gc_set_clip_origin( m_penGC
, xx
, yy 
); 
1323                 gdk_bitmap_unref( new_mask 
); 
1326         /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 
1327            drawing a mono-bitmap (XBitmap) we use the current text GC */ 
1330             gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh 
); 
1332             gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh 
); 
1334         /* remove mask again if any */ 
1335         if (useMask 
&& mask
) 
1339                 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap 
*) NULL 
); 
1340                 gdk_gc_set_clip_origin( m_textGC
, 0, 0 ); 
1341                 if (!m_currentClippingRegion
.IsNull()) 
1342                     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
1346                 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap 
*) NULL 
); 
1347                 gdk_gc_set_clip_origin( m_penGC
, 0, 0 ); 
1348                 if (!m_currentClippingRegion
.IsNull()) 
1349                     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
1353     else /* use_bitmap_method */ 
1355         if ((width 
!= ww
) || (height 
!= hh
)) 
1357             /* draw source window into a bitmap as we cannot scale 
1358                a window in contrast to a bitmap. this would actually 
1359                work with memory dcs as well, but we'd lose the mask 
1360                information and waste one step in this process since 
1361                a memory already has a bitmap. all this is slightly 
1362                inefficient as we could take an XImage directly from 
1363                an X window, but we'd then also have to care that 
1364                the window is not outside the screen (in which case 
1365                we'd get a BadMatch or what not). 
1366                Is a double XGetImage and combined XGetPixel and 
1367                XPutPixel really faster? I'm not sure. look at wxXt 
1368                for a different implementation of the same problem. */ 
1370             wxBitmap 
bitmap( width
, height 
); 
1372             /* copy including child window contents */ 
1373             gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS 
); 
1374             gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0, 
1376                                   xsrc
, ysrc
, width
, height 
); 
1377             gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN 
); 
1380             wxImage image 
= bitmap
.ConvertToImage(); 
1381             image 
= image
.Scale( ww
, hh 
); 
1383             /* convert to bitmap */ 
1384             bitmap 
= wxBitmap(image
); 
1386             /* draw scaled bitmap */ 
1387             gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 ); 
1392             /* No scaling and not a memory dc with a mask either */ 
1394             /* copy including child window contents */ 
1395             gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS 
); 
1396             gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
, 
1398                                   xsrc
, ysrc
, width
, height 
); 
1399             gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN 
); 
1403     SetLogicalFunction( old_logical_func 
); 
1407 void wxWindowDC::DoDrawText( const wxString 
&text
, wxCoord x
, wxCoord y 
) 
1409     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1411     if (!m_window
) return; 
1413     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1415     wxCHECK_RET( font
, wxT("invalid font") ); 
1417 #if defined(__WXGTK20__) 
1418     wxCHECK_RET( m_context
, wxT("no Pango context") ); 
1424 #if defined(__WXGTK20__) && wxUSE_WCHAR_T 
1425     // TODO: the layout engine should be abstracted at a higher level! 
1426     PangoLayout 
*layout 
= pango_layout_new(m_context
); 
1427     pango_layout_set_font_description(layout
, m_fontdesc
); 
1429         const wxWX2MBbuf data 
= text
.mb_str(wxConvUTF8
); 
1430         pango_layout_set_text(layout
, data
, strlen(data
)); 
1432     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
1433     PangoRectangle rect
; 
1434     pango_layout_line_get_extents(line
, NULL
, &rect
); 
1435     wxCoord width 
= rect
.width
; 
1436     wxCoord height 
= rect
.height
; 
1437     gdk_draw_layout( m_window
, m_textGC
, x
, y
, layout 
); 
1439     wxCoord width 
= gdk_string_width( font
, text
.mbc_str() ); 
1440     wxCoord height 
= font
->ascent 
+ font
->descent
; 
1442     if ( m_backgroundMode 
== wxSOLID 
) 
1444         gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() ); 
1445         gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height 
); 
1446         gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
1448     gdk_draw_string( m_window
, font
, m_textGC
, x
, y 
+ font
->ascent
, text
.mbc_str() ); 
1449 #endif // GTK+ 2.0/1.x 
1451     /* CMB 17/7/98: simple underline: ignores scaling and underlying 
1452        X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS 
1453        properties (see wxXt implementation) */ 
1454     if (m_font
.GetUnderlined()) 
1456         wxCoord ul_y 
= y 
+ font
->ascent
; 
1457         if (font
->descent 
> 0) ul_y
++; 
1458         gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x 
+ width
, ul_y
); 
1461 #if defined(__WXGTK20__) && wxUSE_WCHAR_T 
1462     g_object_unref( G_OBJECT( layout 
) ); 
1465     width 
= wxCoord(width 
/ m_scaleX
); 
1466     height 
= wxCoord(height 
/ m_scaleY
); 
1467     CalcBoundingBox (x 
+ width
, y 
+ height
); 
1468     CalcBoundingBox (x
, y
); 
1471 void wxWindowDC::DoDrawRotatedText( const wxString 
&text
, wxCoord x
, wxCoord y
, double angle 
) 
1475         DrawText(text
, x
, y
); 
1479     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1481     if (!m_window
) return; 
1483     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1485     wxCHECK_RET( font
, wxT("invalid font") ); 
1487     // the size of the text 
1488     wxCoord w 
= gdk_string_width( font
, text
.mbc_str() ); 
1489     wxCoord h 
= font
->ascent 
+ font
->descent
; 
1491     // draw the string normally 
1494     dc
.SelectObject(src
); 
1495     dc
.SetFont(GetFont()); 
1496     dc
.SetBackground(*wxWHITE_BRUSH
); 
1497     dc
.SetBrush(*wxBLACK_BRUSH
); 
1499     dc
.DrawText(text
, 0, 0); 
1500     dc
.SelectObject(wxNullBitmap
); 
1502     // Calculate the size of the rotated bounding box. 
1503     double rad 
= DegToRad(angle
); 
1504     double dx 
= cos(rad
), 
1507     // the rectngle vertices are counted clockwise with the first one being at 
1508     // (0, 0) (or, rather, at (x, y)) 
1510            y2 
= -w
*dy
;      // y axis points to the bottom, hence minus 
1513     double x3 
= x4 
+ x2
, 
1517     wxCoord maxX 
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5), 
1518             maxY 
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5), 
1519             minX 
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5), 
1520             minY 
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5); 
1522     // prepare to blit-with-rotate the bitmap to the DC 
1523     wxImage image 
= src
.ConvertToImage(); 
1525     GdkColor 
*colText 
= m_textForegroundColour
.GetColor(), 
1526              *colBack 
= m_textBackgroundColour
.GetColor(); 
1528     bool textColSet 
= TRUE
; 
1530     unsigned char *data 
= image
.GetData(); 
1532     // paint pixel by pixel 
1533     for ( wxCoord srcX 
= 0; srcX 
< w
; srcX
++ ) 
1535         for ( wxCoord srcY 
= 0; srcY 
< h
; srcY
++ ) 
1537             // transform source coords to dest coords 
1538             double r 
= sqrt((double)srcX
*srcX 
+ srcY
*srcY
); 
1539             double angleOrig 
= atan2((double)srcY
, (double)srcX
) - rad
; 
1540             wxCoord dstX 
= (wxCoord
)(r
*cos(angleOrig
) + 0.5), 
1541                     dstY 
= (wxCoord
)(r
*sin(angleOrig
) + 0.5); 
1544             bool textPixel 
= data
[(srcY
*w 
+ srcX
)*3] == 0; 
1545             if ( textPixel 
|| (m_backgroundMode 
== wxSOLID
) ) 
1547                 // change colour if needed 
1548                 if ( textPixel 
!= textColSet 
) 
1550                     gdk_gc_set_foreground( m_textGC
, textPixel 
? colText
 
1553                     textColSet 
= textPixel
; 
1556                 // don't use DrawPoint() because it uses the current pen 
1557                 // colour, and we don't need it here 
1558                 gdk_draw_point( m_window
, m_textGC
, 
1559                                 XLOG2DEV(x 
+ dstX
), YLOG2DEV(y 
+ dstY
) ); 
1564     // it would be better to draw with non underlined font and draw the line 
1565     // manually here (it would be more straight...) 
1567     if ( m_font
.GetUnderlined() ) 
1569         gdk_draw_line( m_window
, m_textGC
, 
1570                        XLOG2DEV(x 
+ x4
), YLOG2DEV(y 
+ y4 
+ font
->descent
), 
1571                        XLOG2DEV(x 
+ x3
), YLOG2DEV(y 
+ y3 
+ font
->descent
)); 
1575     // restore the font colour 
1576     gdk_gc_set_foreground( m_textGC
, colText 
); 
1578     // update the bounding box 
1579     CalcBoundingBox(x 
+ minX
, y 
+ minY
); 
1580     CalcBoundingBox(x 
+ maxX
, y 
+ maxY
); 
1583 void wxWindowDC::DoGetTextExtent(const wxString 
&string
, 
1584                                  wxCoord 
*width
, wxCoord 
*height
, 
1585                                  wxCoord 
*descent
, wxCoord 
*externalLeading
, 
1586                                  wxFont 
*theFont
) const 
1588     wxFont fontToUse 
= m_font
; 
1589     if (theFont
) fontToUse 
= *theFont
; 
1591     GdkFont 
*font 
= fontToUse
.GetInternalFont( m_scaleY 
); 
1592     if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
); 
1593     if (height
) (*height
) = wxCoord((font
->ascent 
+ font
->descent
) / m_scaleY
); 
1594     if (descent
) (*descent
) = wxCoord(font
->descent 
/ m_scaleY
); 
1595     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
1598 wxCoord 
wxWindowDC::GetCharWidth() const 
1600     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1601     wxCHECK_MSG( font
, -1, wxT("invalid font") ); 
1603     return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
); 
1606 wxCoord 
wxWindowDC::GetCharHeight() const 
1608     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1609     wxCHECK_MSG( font
, -1, wxT("invalid font") ); 
1611     return wxCoord((font
->ascent 
+ font
->descent
) / m_scaleY
); 
1614 void wxWindowDC::Clear() 
1616     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1618     if (!m_window
) return; 
1620     // VZ: the code below results in infinite recursion and crashes when 
1621     //     dc.Clear() is done from OnPaint() so I disable it for now. 
1622     //     I don't know what the correct fix is but Clear() surely should not 
1623     //     reenter OnPaint()! 
1625     /* - we either are a memory dc or have a window as the 
1626        owner. anything else shouldn't happen. 
1627        - we don't use gdk_window_clear() as we don't set 
1628        the window's background colour anymore. it is too 
1629        much pain to keep the DC's and the window's back- 
1630        ground colour in synch. */ 
1641         GetSize( &width
, &height 
); 
1642         gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height 
); 
1647     GetSize( &width
, &height 
); 
1648     gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height 
); 
1652 void wxWindowDC::SetFont( const wxFont 
&font 
) 
1654     // It is common practice to set the font to wxNullFont, so 
1655     // don't consider it to be an error 
1656     //    wxCHECK_RET( font.Ok(), _T("invalid font in wxWindowDC::SetFont") ); 
1660     m_fontdesc 
= m_font
.GetNativeFontInfo()->description
; 
1664 void wxWindowDC::SetPen( const wxPen 
&pen 
) 
1666     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1668     if (m_pen 
== pen
) return; 
1672     if (!m_pen
.Ok()) return; 
1674     if (!m_window
) return; 
1676     gint width 
= m_pen
.GetWidth(); 
1679         // CMB: if width is non-zero scale it with the dc 
1684         // X doesn't allow different width in x and y and so we take 
1687                    ( fabs((double) XLOG2DEVREL(width
)) + 
1688                      fabs((double) YLOG2DEVREL(width
)) ) / 2.0; 
1692     static const wxGTKDash dotted
[] = {1, 1}; 
1693     static const wxGTKDash short_dashed
[] = {2, 2}; 
1694     static const wxGTKDash wxCoord_dashed
[] = {2, 4}; 
1695     static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3}; 
1697     // We express dash pattern in pen width unit, so we are 
1698     // independent of zoom factor and so on... 
1700     const wxGTKDash 
*req_dash
; 
1702     GdkLineStyle lineStyle 
= GDK_LINE_SOLID
; 
1703     switch (m_pen
.GetStyle()) 
1707             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1708             req_nb_dash 
= m_pen
.GetDashCount(); 
1709             req_dash 
= (wxGTKDash
*)m_pen
.GetDash(); 
1714             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1721             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1723             req_dash 
= wxCoord_dashed
; 
1728             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1730             req_dash 
= short_dashed
; 
1735 //            lineStyle = GDK_LINE_DOUBLE_DASH; 
1736             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1738             req_dash 
= dotted_dashed
; 
1743         case wxSTIPPLE_MASK_OPAQUE
: 
1748             lineStyle 
= GDK_LINE_SOLID
; 
1749             req_dash 
= (wxGTKDash
*)NULL
; 
1755 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1) 
1756     if (req_dash 
&& req_nb_dash
) 
1758         wxGTKDash 
*real_req_dash 
= new wxGTKDash
[req_nb_dash
]; 
1761             for (int i 
= 0; i 
< req_nb_dash
; i
++) 
1762                 real_req_dash
[i
] = req_dash
[i
] * width
; 
1763             gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash 
); 
1764             delete[] real_req_dash
; 
1768             // No Memory. We use non-scaled dash pattern... 
1769             gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash 
); 
1774     GdkCapStyle capStyle 
= GDK_CAP_ROUND
; 
1775     switch (m_pen
.GetCap()) 
1777         case wxCAP_PROJECTING
: { capStyle 
= GDK_CAP_PROJECTING
; break; } 
1778         case wxCAP_BUTT
:       { capStyle 
= GDK_CAP_BUTT
;       break; } 
1785                 capStyle 
= GDK_CAP_NOT_LAST
; 
1789                 capStyle 
= GDK_CAP_ROUND
; 
1795     GdkJoinStyle joinStyle 
= GDK_JOIN_ROUND
; 
1796     switch (m_pen
.GetJoin()) 
1798         case wxJOIN_BEVEL
: { joinStyle 
= GDK_JOIN_BEVEL
; break; } 
1799         case wxJOIN_MITER
: { joinStyle 
= GDK_JOIN_MITER
; break; } 
1801         default:           { joinStyle 
= GDK_JOIN_ROUND
; break; } 
1804     gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle 
); 
1806     m_pen
.GetColour().CalcPixel( m_cmap 
); 
1807     gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() ); 
1810 void wxWindowDC::SetBrush( const wxBrush 
&brush 
) 
1812     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1814     if (m_brush 
== brush
) return; 
1818     if (!m_brush
.Ok()) return; 
1820     if (!m_window
) return; 
1822     m_brush
.GetColour().CalcPixel( m_cmap 
); 
1823     gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() ); 
1825     gdk_gc_set_fill( m_brushGC
, GDK_SOLID 
); 
1827     if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok())) 
1829         if (m_brush
.GetStipple()->GetPixmap()) 
1831             gdk_gc_set_fill( m_brushGC
, GDK_TILED 
); 
1832             gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() ); 
1836             gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED 
); 
1837             gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() ); 
1841     if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
1843         gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
); 
1844         gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() ); 
1847     if (IS_HATCH(m_brush
.GetStyle())) 
1849         gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED 
); 
1850         int num 
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
; 
1851         gdk_gc_set_stipple( m_brushGC
, hatches
[num
] ); 
1855 void wxWindowDC::SetBackground( const wxBrush 
&brush 
) 
1857    /* CMB 21/7/98: Added SetBackground. Sets background brush 
1858     * for Clear() and bg colour for shapes filled with cross-hatch brush */ 
1860     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1862     if (m_backgroundBrush 
== brush
) return; 
1864     m_backgroundBrush 
= brush
; 
1866     if (!m_backgroundBrush
.Ok()) return; 
1868     if (!m_window
) return; 
1870     m_backgroundBrush
.GetColour().CalcPixel( m_cmap 
); 
1871     gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() ); 
1872     gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() ); 
1873     gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() ); 
1874     gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() ); 
1876     gdk_gc_set_fill( m_bgGC
, GDK_SOLID 
); 
1878     if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok())) 
1880         if (m_backgroundBrush
.GetStipple()->GetPixmap()) 
1882             gdk_gc_set_fill( m_bgGC
, GDK_TILED 
); 
1883             gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() ); 
1887             gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED 
); 
1888             gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() ); 
1892     if (IS_HATCH(m_backgroundBrush
.GetStyle())) 
1894         gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED 
); 
1895         int num 
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
; 
1896         gdk_gc_set_stipple( m_bgGC
, hatches
[num
] ); 
1900 void wxWindowDC::SetLogicalFunction( int function 
) 
1902     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1904     if (m_logicalFunction 
== function
) 
1907     // VZ: shouldn't this be a CHECK? 
1911     GdkFunction mode 
= GDK_COPY
; 
1914         case wxXOR
:          mode 
= GDK_XOR
;           break; 
1915         case wxINVERT
:       mode 
= GDK_INVERT
;        break; 
1916 #if (GTK_MINOR_VERSION > 0) 
1917         case wxOR_REVERSE
:   mode 
= GDK_OR_REVERSE
;    break; 
1918         case wxAND_REVERSE
:  mode 
= GDK_AND_REVERSE
;   break; 
1919         case wxCLEAR
:        mode 
= GDK_CLEAR
;         break; 
1920         case wxSET
:          mode 
= GDK_SET
;           break; 
1921         case wxOR_INVERT
:    mode 
= GDK_OR_INVERT
;     break; 
1922         case wxAND
:          mode 
= GDK_AND
;           break; 
1923         case wxOR
:           mode 
= GDK_OR
;            break; 
1924         case wxEQUIV
:        mode 
= GDK_EQUIV
;         break; 
1925         case wxNAND
:         mode 
= GDK_NAND
;          break; 
1926         case wxAND_INVERT
:   mode 
= GDK_AND_INVERT
;    break; 
1927         case wxCOPY
:         mode 
= GDK_COPY
;          break; 
1928         case wxNO_OP
:        mode 
= GDK_NOOP
;          break; 
1929         case wxSRC_INVERT
:   mode 
= GDK_COPY_INVERT
;   break; 
1931         // unsupported by GTK 
1932         case wxNOR
:          mode 
= GDK_COPY
;          break; 
1936            wxFAIL_MSG( wxT("unsupported logical function") ); 
1941     m_logicalFunction 
= function
; 
1943     gdk_gc_set_function( m_penGC
, mode 
); 
1944     gdk_gc_set_function( m_brushGC
, mode 
); 
1946     // to stay compatible with wxMSW, we don't apply ROPs to the text 
1947     // operations (i.e. DrawText/DrawRotatedText). 
1948     // True, but mono-bitmaps use the m_textGC and they use ROPs as well. 
1949     gdk_gc_set_function( m_textGC
, mode 
); 
1952 void wxWindowDC::SetTextForeground( const wxColour 
&col 
) 
1954     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1956     // don't set m_textForegroundColour to an invalid colour as we'd crash 
1957     // later then (we use m_textForegroundColour.GetColor() without checking 
1959     if ( !col
.Ok() || (m_textForegroundColour 
== col
) ) 
1962     m_textForegroundColour 
= col
; 
1966         m_textForegroundColour
.CalcPixel( m_cmap 
); 
1967         gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
1971 void wxWindowDC::SetTextBackground( const wxColour 
&col 
) 
1973     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1976     if ( !col
.Ok() || (m_textBackgroundColour 
== col
) ) 
1979     m_textBackgroundColour 
= col
; 
1983         m_textBackgroundColour
.CalcPixel( m_cmap 
); 
1984         gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() ); 
1988 void wxWindowDC::SetBackgroundMode( int mode 
) 
1990     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1992     m_backgroundMode 
= mode
; 
1994     if (!m_window
) return; 
1996     // CMB 21/7/98: fill style of cross-hatch brushes is affected by 
1997     // transparent/solid background mode 
1999     if (m_brush
.GetStyle() != wxSOLID 
&& m_brush
.GetStyle() != wxTRANSPARENT
) 
2001         gdk_gc_set_fill( m_brushGC
, 
2002           (m_backgroundMode 
== wxTRANSPARENT
) ? GDK_STIPPLED 
: GDK_OPAQUE_STIPPLED
); 
2006 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) ) 
2008     wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") ); 
2011 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
2013     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2015     if (!m_window
) return; 
2018     rect
.x 
= XLOG2DEV(x
); 
2019     rect
.y 
= YLOG2DEV(y
); 
2020     rect
.width 
= XLOG2DEVREL(width
); 
2021     rect
.height 
= YLOG2DEVREL(height
); 
2023     if (!m_currentClippingRegion
.IsNull()) 
2024         m_currentClippingRegion
.Intersect( rect 
); 
2026         m_currentClippingRegion
.Union( rect 
); 
2028 #if USE_PAINT_REGION 
2029     if (!m_paintClippingRegion
.IsNull()) 
2030         m_currentClippingRegion
.Intersect( m_paintClippingRegion 
); 
2033     wxCoord xx
, yy
, ww
, hh
; 
2034     m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh 
); 
2035     wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
2037     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
2038     gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
2039     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
2040     gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
2043 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion 
®ion  
) 
2045     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2049         DestroyClippingRegion(); 
2053     if (!m_window
) return; 
2055     if (!m_currentClippingRegion
.IsNull()) 
2056         m_currentClippingRegion
.Intersect( region 
); 
2058         m_currentClippingRegion
.Union( region 
); 
2060 #if USE_PAINT_REGION 
2061     if (!m_paintClippingRegion
.IsNull()) 
2062         m_currentClippingRegion
.Intersect( m_paintClippingRegion 
); 
2065     wxCoord xx
, yy
, ww
, hh
; 
2066     m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh 
); 
2067     wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
2069     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
2070     gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
2071     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
2072     gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
2075 void wxWindowDC::DestroyClippingRegion() 
2077     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2079     wxDC::DestroyClippingRegion(); 
2081     m_currentClippingRegion
.Clear(); 
2083 #if USE_PAINT_REGION 
2084     if (!m_paintClippingRegion
.IsEmpty()) 
2085         m_currentClippingRegion
.Union( m_paintClippingRegion 
); 
2088     if (!m_window
) return; 
2090     if (m_currentClippingRegion
.IsEmpty()) 
2092         gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle 
*) NULL 
); 
2093         gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle 
*) NULL 
); 
2094         gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle 
*) NULL 
); 
2095         gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle 
*) NULL 
); 
2099         gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
2100         gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
2101         gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
2102         gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
2106 void wxWindowDC::Destroy() 
2108     if (m_penGC
) wxFreePoolGC( m_penGC 
); 
2109     m_penGC 
= (GdkGC
*) NULL
; 
2110     if (m_brushGC
) wxFreePoolGC( m_brushGC 
); 
2111     m_brushGC 
= (GdkGC
*) NULL
; 
2112     if (m_textGC
) wxFreePoolGC( m_textGC 
); 
2113     m_textGC 
= (GdkGC
*) NULL
; 
2114     if (m_bgGC
) wxFreePoolGC( m_bgGC 
); 
2115     m_bgGC 
= (GdkGC
*) NULL
; 
2118 void wxWindowDC::ComputeScaleAndOrigin() 
2120     /* CMB: copy scale to see if it changes */ 
2121     double origScaleX 
= m_scaleX
; 
2122     double origScaleY 
= m_scaleY
; 
2124     wxDC::ComputeScaleAndOrigin(); 
2126     /* CMB: if scale has changed call SetPen to recalulate the line width */ 
2127     if ((m_scaleX 
!= origScaleX 
|| m_scaleY 
!= origScaleY
) && 
2130       /* this is a bit artificial, but we need to force wxDC to think 
2131          the pen has changed */ 
2138 // Resolution in pixels per logical inch 
2139 wxSize 
wxWindowDC::GetPPI() const 
2141     return wxSize( (int) (m_mm_to_pix_x 
* 25.4 + 0.5), (int) (m_mm_to_pix_y 
* 25.4 + 0.5)); 
2144 int wxWindowDC::GetDepth() const 
2146     wxFAIL_MSG(wxT("not implemented")); 
2152 //----------------------------------------------------------------------------- 
2154 //----------------------------------------------------------------------------- 
2156 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
) 
2158 wxPaintDC::wxPaintDC( wxWindow 
*win 
) 
2161 #if USE_PAINT_REGION 
2162     if (!win
->m_clipPaintRegion
) 
2165     m_paintClippingRegion 
= win
->GetUpdateRegion(); 
2166     GdkRegion 
*region 
= m_paintClippingRegion
.GetRegion(); 
2169         m_paintClippingRegion 
= win
->GetUpdateRegion(); 
2170         GdkRegion 
*region 
= m_paintClippingRegion
.GetRegion(); 
2173             m_currentClippingRegion
.Union( m_paintClippingRegion 
); 
2175             gdk_gc_set_clip_region( m_penGC
, region 
); 
2176             gdk_gc_set_clip_region( m_brushGC
, region 
); 
2177             gdk_gc_set_clip_region( m_textGC
, region 
); 
2178             gdk_gc_set_clip_region( m_bgGC
, region 
); 
2181 #endif // USE_PAINT_REGION 
2184 //----------------------------------------------------------------------------- 
2186 //----------------------------------------------------------------------------- 
2188 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
) 
2190 wxClientDC::wxClientDC( wxWindow 
*win 
) 
2193     wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") ); 
2195 #ifdef __WXUNIVERSAL__ 
2196     wxPoint ptOrigin 
= win
->GetClientAreaOrigin(); 
2197     SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
); 
2198     wxSize size 
= win
->GetClientSize(); 
2199     SetClippingRegion(wxPoint(0, 0), size
); 
2200 #endif // __WXUNIVERSAL__ 
2203 void wxClientDC::DoGetSize(int *width
, int *height
) const 
2205     wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") ); 
2207     m_owner
->GetClientSize( width
, height 
); 
2210 // ---------------------------------------------------------------------------- 
2212 // ---------------------------------------------------------------------------- 
2214 class wxDCModule 
: public wxModule
 
2221     DECLARE_DYNAMIC_CLASS(wxDCModule
) 
2224 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
) 
2226 bool wxDCModule::OnInit() 
2232 void wxDCModule::OnExit()