]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk1/dcclient.cpp
3f69545b3c2fc998d337ca88b5eaebf1eb2ff499
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        gtk/dcclient.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling, Chris Breeze 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  11 #pragma implementation "dcclient.h" 
  14 // For compilers that support precompilation, includes "wx.h". 
  15 #include "wx/wxprec.h" 
  18 #define XCopyPlane XCOPYPLANE 
  21 #include "wx/dcclient.h" 
  22 #include "wx/dcmemory.h" 
  24 #include "wx/module.h" 
  26 #include "wx/fontutil.h" 
  28 #include "wx/gtk/win_gtk.h" 
  30 #include "wx/math.h" // for floating-point functions 
  34 #include <gdk/gdkprivate.h> 
  37 //----------------------------------------------------------------------------- 
  39 //----------------------------------------------------------------------------- 
  41 #define USE_PAINT_REGION 1 
  43 //----------------------------------------------------------------------------- 
  45 //----------------------------------------------------------------------------- 
  55 #define IS_15_PIX_HATCH(s) ((s)==wxCROSSDIAG_HATCH || (s)==wxHORIZONTAL_HATCH || (s)==wxVERTICAL_HATCH) 
  56 #define IS_16_PIX_HATCH(s) ((s)!=wxCROSSDIAG_HATCH && (s)!=wxHORIZONTAL_HATCH && (s)!=wxVERTICAL_HATCH) 
  59 static GdkPixmap  
*hatches
[num_hatches
]; 
  60 static GdkPixmap 
**hatch_bitmap 
= (GdkPixmap 
**) NULL
; 
  62 extern GtkWidget 
*wxGetRootWindow(); 
  64 //----------------------------------------------------------------------------- 
  66 //----------------------------------------------------------------------------- 
  68 const double RAD2DEG  
= 180.0 / M_PI
; 
  70 // ---------------------------------------------------------------------------- 
  72 // ---------------------------------------------------------------------------- 
  74 static inline double dmax(double a
, double b
) { return a 
> b 
? a 
: b
; } 
  75 static inline double dmin(double a
, double b
) { return a 
< b 
? a 
: b
; } 
  77 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
  79 //----------------------------------------------------------------------------- 
  80 // temporary implementation of the missing GDK function 
  81 //----------------------------------------------------------------------------- 
  83 #include "gdk/gdkprivate.h" 
  85 void gdk_wx_draw_bitmap(GdkDrawable  
*drawable
, 
  95     g_return_if_fail (drawable 
!= NULL
); 
  96     g_return_if_fail (src 
!= NULL
); 
  97     g_return_if_fail (gc 
!= NULL
); 
 100     gint src_width
, src_height
; 
 101     gdk_drawable_get_size(src
, &src_width
, &src_height
); 
 102     if (width 
== -1) width 
= src_width
; 
 103     if (height 
== -1) height 
= src_height
; 
 105     XCopyPlane( GDK_WINDOW_XDISPLAY(drawable
), 
 107                 GDK_WINDOW_XID(drawable
), 
 114     GdkWindowPrivate 
*drawable_private
; 
 115     GdkWindowPrivate 
*src_private
; 
 116     GdkGCPrivate 
*gc_private
; 
 118     drawable_private 
= (GdkWindowPrivate
*) drawable
; 
 119     src_private 
= (GdkWindowPrivate
*) src
; 
 120     if (drawable_private
->destroyed 
|| src_private
->destroyed
) 
 123     gint src_width 
= src_private
->width
; 
 124     gint src_height 
= src_private
->height
; 
 126     gc_private 
= (GdkGCPrivate
*) gc
; 
 128     if (width 
== -1) width 
= src_width
; 
 129     if (height 
== -1) height 
= src_height
; 
 131     XCopyPlane( drawable_private
->xdisplay
, 
 132                 src_private
->xwindow
, 
 133                 drawable_private
->xwindow
, 
 142 //----------------------------------------------------------------------------- 
 143 // Implement Pool of Graphic contexts. Creating them takes too much time. 
 144 //----------------------------------------------------------------------------- 
 170 #define GC_POOL_ALLOC_SIZE 100 
 172 static int wxGCPoolSize 
= 0; 
 174 static wxGC 
*wxGCPool 
= NULL
; 
 176 static void wxInitGCPool() 
 178     // This really could wait until the first call to 
 179     // wxGetPoolGC, but we will make the first allocation 
 180     // now when other initialization is being performed. 
 182     // Set initial pool size. 
 183     wxGCPoolSize 
= GC_POOL_ALLOC_SIZE
; 
 185     // Allocate initial pool. 
 186     wxGCPool 
= (wxGC 
*)malloc(wxGCPoolSize 
* sizeof(wxGC
)); 
 187     if (wxGCPool 
== NULL
) 
 189         // If we cannot malloc, then fail with error 
 190         // when debug is enabled.  If debug is not enabled, 
 191         // the problem will eventually get caught 
 193         wxFAIL_MSG( wxT("Cannot allocate GC pool") ); 
 197     // Zero initial pool. 
 198     memset(wxGCPool
, 0, wxGCPoolSize 
* sizeof(wxGC
)); 
 201 static void wxCleanUpGCPool() 
 203     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 205         if (wxGCPool
[i
].m_gc
) 
 206             gdk_gc_unref( wxGCPool
[i
].m_gc 
); 
 214 static GdkGC
* wxGetPoolGC( GdkWindow 
*window
, wxPoolGCType type 
) 
 218     // Look for an available GC. 
 219     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 221         if (!wxGCPool
[i
].m_gc
) 
 223             wxGCPool
[i
].m_gc 
= gdk_gc_new( window 
); 
 224             gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE 
); 
 225             wxGCPool
[i
].m_type 
= type
; 
 226             wxGCPool
[i
].m_used 
= false; 
 228         if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type 
== type
)) 
 230             wxGCPool
[i
].m_used 
= true; 
 231             return wxGCPool
[i
].m_gc
; 
 235     // We did not find an available GC. 
 236     // We need to grow the GC pool. 
 237     pptr 
= (wxGC 
*)realloc(wxGCPool
, 
 238         (wxGCPoolSize 
+ GC_POOL_ALLOC_SIZE
)*sizeof(wxGC
)); 
 241         // Initialize newly allocated pool. 
 243         memset(&wxGCPool
[wxGCPoolSize
], 0, 
 244             GC_POOL_ALLOC_SIZE
*sizeof(wxGC
)); 
 246         // Initialize entry we will return. 
 247         wxGCPool
[wxGCPoolSize
].m_gc 
= gdk_gc_new( window 
); 
 248         gdk_gc_set_exposures( wxGCPool
[wxGCPoolSize
].m_gc
, FALSE 
); 
 249         wxGCPool
[wxGCPoolSize
].m_type 
= type
; 
 250         wxGCPool
[wxGCPoolSize
].m_used 
= true; 
 252         // Set new value of pool size. 
 253         wxGCPoolSize 
+= GC_POOL_ALLOC_SIZE
; 
 255         // Return newly allocated entry. 
 256         return wxGCPool
[wxGCPoolSize
-GC_POOL_ALLOC_SIZE
].m_gc
; 
 259     // The realloc failed.  Fall through to error. 
 260     wxFAIL_MSG( wxT("No GC available") ); 
 262     return (GdkGC
*) NULL
; 
 265 static void wxFreePoolGC( GdkGC 
*gc 
) 
 267     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 269         if (wxGCPool
[i
].m_gc 
== gc
) 
 271             wxGCPool
[i
].m_used 
= false; 
 276     wxFAIL_MSG( wxT("Wrong GC") ); 
 279 //----------------------------------------------------------------------------- 
 281 //----------------------------------------------------------------------------- 
 283 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
) 
 285 wxWindowDC::wxWindowDC() 
 287     m_penGC 
= (GdkGC 
*) NULL
; 
 288     m_brushGC 
= (GdkGC 
*) NULL
; 
 289     m_textGC 
= (GdkGC 
*) NULL
; 
 290     m_bgGC 
= (GdkGC 
*) NULL
; 
 291     m_cmap 
= (GdkColormap 
*) NULL
; 
 293     m_isScreenDC 
= false; 
 294     m_owner 
= (wxWindow 
*)NULL
; 
 296     m_context 
= (PangoContext 
*)NULL
; 
 297     m_layout 
= (PangoLayout 
*)NULL
; 
 298     m_fontdesc 
= (PangoFontDescription 
*)NULL
; 
 302 wxWindowDC::wxWindowDC( wxWindow 
*window 
) 
 304     wxASSERT_MSG( window
, wxT("DC needs a window") ); 
 306     m_penGC 
= (GdkGC 
*) NULL
; 
 307     m_brushGC 
= (GdkGC 
*) NULL
; 
 308     m_textGC 
= (GdkGC 
*) NULL
; 
 309     m_bgGC 
= (GdkGC 
*) NULL
; 
 310     m_cmap 
= (GdkColormap 
*) NULL
; 
 311     m_owner 
= (wxWindow 
*)NULL
; 
 313     m_isScreenDC 
= false; 
 314     m_font 
= window
->GetFont(); 
 316     GtkWidget 
*widget 
= window
->m_wxwindow
; 
 318     // Some controls don't have m_wxwindow - like wxStaticBox, but the user 
 319     // code should still be able to create wxClientDCs for them, so we will 
 320     // use the parent window here then. 
 323         window 
= window
->GetParent(); 
 324         widget 
= window
->m_wxwindow
; 
 327     wxASSERT_MSG( widget
, wxT("DC needs a widget") ); 
 330     m_context 
= window
->GtkGetPangoDefaultContext(); 
 331     m_layout 
= pango_layout_new( m_context 
); 
 332     m_fontdesc 
= pango_font_description_copy( widget
->style
->font_desc 
); 
 335     GtkPizza 
*pizza 
= GTK_PIZZA( widget 
); 
 336     m_window 
= pizza
->bin_window
; 
 338     // Window not realized ? 
 341          // Don't report problems as per MSW. 
 347     m_cmap 
= gtk_widget_get_colormap( widget 
? widget 
: window
->m_widget 
); 
 351     /* this must be done after SetUpDC, bacause SetUpDC calls the 
 352        repective SetBrush, SetPen, SetBackground etc functions 
 353        to set up the DC. SetBackground call m_owner->SetBackground 
 354        and this might not be desired as the standard dc background 
 355        is white whereas a window might assume gray to be the 
 356        standard (as e.g. wxStatusBar) */ 
 361 wxWindowDC::~wxWindowDC() 
 367         g_object_unref( G_OBJECT( m_layout 
) ); 
 369         pango_font_description_free( m_fontdesc 
); 
 373 void wxWindowDC::SetUpDC() 
 377     wxASSERT_MSG( !m_penGC
, wxT("GCs already created") ); 
 381         m_penGC 
= wxGetPoolGC( m_window
, wxPEN_SCREEN 
); 
 382         m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_SCREEN 
); 
 383         m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_SCREEN 
); 
 384         m_bgGC 
= wxGetPoolGC( m_window
, wxBG_SCREEN 
); 
 387     if (m_isMemDC 
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1)) 
 389         m_penGC 
= wxGetPoolGC( m_window
, wxPEN_MONO 
); 
 390         m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_MONO 
); 
 391         m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_MONO 
); 
 392         m_bgGC 
= wxGetPoolGC( m_window
, wxBG_MONO 
); 
 396         m_penGC 
= wxGetPoolGC( m_window
, wxPEN_COLOUR 
); 
 397         m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR 
); 
 398         m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_COLOUR 
); 
 399         m_bgGC 
= wxGetPoolGC( m_window
, wxBG_COLOUR 
); 
 402     /* background colour */ 
 403     m_backgroundBrush 
= *wxWHITE_BRUSH
; 
 404     m_backgroundBrush
.GetColour().CalcPixel( m_cmap 
); 
 405     GdkColor 
*bg_col 
= m_backgroundBrush
.GetColour().GetColor(); 
 408     m_textForegroundColour
.CalcPixel( m_cmap 
); 
 409     gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
 411     m_textBackgroundColour
.CalcPixel( m_cmap 
); 
 412     gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() ); 
 414     gdk_gc_set_fill( m_textGC
, GDK_SOLID 
); 
 417     m_pen
.GetColour().CalcPixel( m_cmap 
); 
 418     gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() ); 
 419     gdk_gc_set_background( m_penGC
, bg_col 
); 
 421     gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND 
); 
 424     m_brush
.GetColour().CalcPixel( m_cmap 
); 
 425     gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() ); 
 426     gdk_gc_set_background( m_brushGC
, bg_col 
); 
 428     gdk_gc_set_fill( m_brushGC
, GDK_SOLID 
); 
 431     gdk_gc_set_background( m_bgGC
, bg_col 
); 
 432     gdk_gc_set_foreground( m_bgGC
, bg_col 
); 
 434     gdk_gc_set_fill( m_bgGC
, GDK_SOLID 
); 
 437     gdk_gc_set_function( m_textGC
, GDK_COPY 
); 
 438     gdk_gc_set_function( m_brushGC
, GDK_COPY 
); 
 439     gdk_gc_set_function( m_penGC
, GDK_COPY 
); 
 442     gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle 
*) NULL 
); 
 443     gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle 
*) NULL 
); 
 444     gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle 
*) NULL 
); 
 445     gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle 
*) NULL 
); 
 449         hatch_bitmap    
= hatches
; 
 450         hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height 
); 
 451         hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height 
); 
 452         hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height 
); 
 453         hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, cross_bits
, cross_width
, cross_height 
); 
 454         hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, horiz_bits
, horiz_width
, horiz_height 
); 
 455         hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, verti_bits
, verti_width
, verti_height 
); 
 459 void wxWindowDC::DoGetSize( int* width
, int* height 
) const 
 461     wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") ); 
 463     m_owner
->GetSize(width
, height
); 
 466 extern bool wxDoFloodFill(wxDC 
*dc
, wxCoord x
, wxCoord y
, 
 467                           const wxColour 
& col
, int style
); 
 469 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
, 
 470                              const wxColour
& col
, int style
) 
 472     return wxDoFloodFill(this, x
, y
, col
, style
); 
 475 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour 
*col 
) const 
 477     // Generic (and therefore rather inefficient) method. 
 478     // Could be improved. 
 480     wxBitmap 
bitmap(1, 1); 
 481     memdc
.SelectObject(bitmap
); 
 482     memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
); 
 483     memdc
.SelectObject(wxNullBitmap
); 
 485     wxImage image 
= bitmap
.ConvertToImage(); 
 486     col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0)); 
 490 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2 
) 
 492     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 494     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 497             gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) ); 
 499         CalcBoundingBox(x1
, y1
); 
 500         CalcBoundingBox(x2
, y2
); 
 504 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y 
) 
 506     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 508     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 513         wxCoord xx 
= XLOG2DEV(x
); 
 514         wxCoord yy 
= YLOG2DEV(y
); 
 517             gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy 
); 
 518             gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) ); 
 523 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, 
 524                             wxCoord xc
, wxCoord yc 
) 
 526     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 528     wxCoord xx1 
= XLOG2DEV(x1
); 
 529     wxCoord yy1 
= YLOG2DEV(y1
); 
 530     wxCoord xx2 
= XLOG2DEV(x2
); 
 531     wxCoord yy2 
= YLOG2DEV(y2
); 
 532     wxCoord xxc 
= XLOG2DEV(xc
); 
 533     wxCoord yyc 
= YLOG2DEV(yc
); 
 534     double dx 
= xx1 
- xxc
; 
 535     double dy 
= yy1 
- yyc
; 
 536     double radius 
= sqrt((double)(dx
*dx
+dy
*dy
)); 
 537     wxCoord   r      
= (wxCoord
)radius
; 
 538     double radius1
, radius2
; 
 540     if (xx1 
== xx2 
&& yy1 
== yy2
) 
 548         radius1 
= radius2 
= 0.0; 
 552         radius1 
= (xx1 
- xxc 
== 0) ? 
 553             (yy1 
- yyc 
< 0) ? 90.0 : -90.0 : 
 554             -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
; 
 555         radius2 
= (xx2 
- xxc 
== 0) ? 
 556             (yy2 
- yyc 
< 0) ? 90.0 : -90.0 : 
 557             -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
; 
 559     wxCoord alpha1 
= wxCoord(radius1 
* 64.0); 
 560     wxCoord alpha2 
= wxCoord((radius2 
- radius1
) * 64.0); 
 561     while (alpha2 
<= 0) alpha2 
+= 360*64; 
 562     while (alpha1 
> 360*64) alpha1 
-= 360*64; 
 566         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 568             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 570                 gdk_gc_set_ts_origin( m_textGC
, 
 571                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 572                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 573                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 574                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 576             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 578                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 579                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 580                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 582             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 584                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 585                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 586                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 588             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 590                 gdk_gc_set_ts_origin( m_brushGC
, 
 591                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 592                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 593                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 594                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 598                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 602         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 604             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 606             gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc 
); 
 607             gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2 
); 
 611     CalcBoundingBox (x1
, y1
); 
 612     CalcBoundingBox (x2
, y2
); 
 615 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea 
) 
 617     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 619     wxCoord xx 
= XLOG2DEV(x
); 
 620     wxCoord yy 
= YLOG2DEV(y
); 
 621     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 622     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 624     // CMB: handle -ve width and/or height 
 625     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 626     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 630         wxCoord start 
= wxCoord(sa 
* 64.0); 
 631         wxCoord end 
= wxCoord((ea
-sa
) * 64.0); 
 633         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 635             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 637                 gdk_gc_set_ts_origin( m_textGC
, 
 638                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 639                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 640                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 641                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 643             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 645                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 646                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 647                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 649             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 651                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 652                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 653                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 655             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 657                 gdk_gc_set_ts_origin( m_brushGC
, 
 658                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 659                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 660                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 661                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 665                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 669         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 670             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end 
); 
 673     CalcBoundingBox (x
, y
); 
 674     CalcBoundingBox (x 
+ width
, y 
+ height
); 
 677 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y 
) 
 679     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 681     if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
) 
 682         gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) ); 
 684     CalcBoundingBox (x
, y
); 
 687 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset 
) 
 689     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 691     if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 694     GdkPoint 
*gpts 
= new GdkPoint
[n
]; 
 697         wxFAIL_MSG( wxT("Cannot allocate PolyLine") ); 
 701     for (int i 
= 0; i 
< n
; i
++) 
 703         wxCoord x1 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 704         wxCoord y1 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 706         CalcBoundingBox( x1 
+ xoffset
, y1 
+ yoffset 
); 
 713         gdk_draw_lines( m_window
, m_penGC
, gpts
, n
); 
 718 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) ) 
 720     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 724     GdkPoint 
*gdkpoints 
= new GdkPoint
[n
+1]; 
 726     for (i 
= 0 ; i 
< n 
; i
++) 
 728         gdkpoints
[i
].x 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 729         gdkpoints
[i
].y 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 731         CalcBoundingBox( points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset 
); 
 736         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 738             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 740                 gdk_gc_set_ts_origin( m_textGC
, 
 741                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 742                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 743                 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n 
); 
 744                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 746             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 748                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 749                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 750                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 752             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 754                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 755                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 756                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 758             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 760                 gdk_gc_set_ts_origin( m_brushGC
, 
 761                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 762                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 763                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 764                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 768                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 772         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 775             for (i = 0 ; i < n ; i++) 
 777                 gdk_draw_line( m_window, m_penGC, 
 780                                gdkpoints[(i+1)%n].x, 
 781                                gdkpoints[(i+1)%n].y); 
 784             gdk_draw_polygon( m_window
, m_penGC
, FALSE
, gdkpoints
, n 
); 
 792 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 794     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 796     wxCoord xx 
= XLOG2DEV(x
); 
 797     wxCoord yy 
= YLOG2DEV(y
); 
 798     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 799     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 801     // CMB: draw nothing if transformed w or h is 0 
 802     if (ww 
== 0 || hh 
== 0) return; 
 804     // CMB: handle -ve width and/or height 
 805     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 806     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 810         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 812             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 814                 gdk_gc_set_ts_origin( m_textGC
, 
 815                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 816                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 817                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 818                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 820             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 822                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 823                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 824                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 826             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 828                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 829                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 830                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 832             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 834                 gdk_gc_set_ts_origin( m_brushGC
, 
 835                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 836                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 837                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 838                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 842                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 846         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 847             gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 ); 
 850     CalcBoundingBox( x
, y 
); 
 851     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 854 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius 
) 
 856     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 858     if (radius 
< 0.0) radius 
= - radius 
* ((width 
< height
) ? width 
: height
); 
 860     wxCoord xx 
= XLOG2DEV(x
); 
 861     wxCoord yy 
= YLOG2DEV(y
); 
 862     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 863     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 864     wxCoord rr 
= XLOG2DEVREL((wxCoord
)radius
); 
 866     // CMB: handle -ve width and/or height 
 867     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 868     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 870     // CMB: if radius is zero use DrawRectangle() instead to avoid 
 871     // X drawing errors with small radii 
 874         DrawRectangle( x
, y
, width
, height 
); 
 878     // CMB: draw nothing if transformed w or h is 0 
 879     if (ww 
== 0 || hh 
== 0) return; 
 881     // CMB: adjust size if outline is drawn otherwise the result is 
 882     // 1 pixel too wide and high 
 883     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 891         // CMB: ensure dd is not larger than rectangle otherwise we 
 892         // get an hour glass shape 
 894         if (dd 
> ww
) dd 
= ww
; 
 895         if (dd 
> hh
) dd 
= hh
; 
 898         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 900             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 902                 gdk_gc_set_ts_origin( m_textGC
, 
 903                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 904                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 905                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 906                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 907                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 908                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 909                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 910                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 911                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 913             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 915                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 916                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 917                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 918                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 919                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 920                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 921                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 922                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 924             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 926                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 927                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 928                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 929                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 930                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 931                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 932                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 933                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 935             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 937                 gdk_gc_set_ts_origin( m_brushGC
, 
 938                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 939                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 940                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 941                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 942                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 943                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 944                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 945                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 946                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 950                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 951                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 952                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 953                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 954                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 955                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 959         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 961             gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy 
); 
 962             gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh 
); 
 963             gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr 
); 
 964             gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr 
); 
 965             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 966             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 967             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 968             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 972     // this ignores the radius 
 973     CalcBoundingBox( x
, y 
); 
 974     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 977 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 979     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 981     wxCoord xx 
= XLOG2DEV(x
); 
 982     wxCoord yy 
= YLOG2DEV(y
); 
 983     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 984     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 986     // CMB: handle -ve width and/or height 
 987     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 988     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 992         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 994             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 996                 gdk_gc_set_ts_origin( m_textGC
, 
 997                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 998                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 999                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1000                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
1002             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
1004                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
1005                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1006                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
1008             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
1010                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
1011                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1012                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
1014             if (m_brush
.GetStyle() == wxSTIPPLE
) 
1016                 gdk_gc_set_ts_origin( m_brushGC
, 
1017                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
1018                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
1019                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1020                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
1024                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1028         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
1029             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1032     CalcBoundingBox( x
, y 
); 
1033     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
1036 void wxWindowDC::DoDrawIcon( const wxIcon 
&icon
, wxCoord x
, wxCoord y 
) 
1038     // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why 
1039     DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, true ); 
1042 void wxWindowDC::DoDrawBitmap( const wxBitmap 
&bitmap
, 
1043                                wxCoord x
, wxCoord y
, 
1046     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1048     wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") ); 
1050     bool is_mono 
= (bitmap
.GetBitmap() != NULL
); 
1052     // scale/translate size and position 
1053     int xx 
= XLOG2DEV(x
); 
1054     int yy 
= YLOG2DEV(y
); 
1056     int w 
= bitmap
.GetWidth(); 
1057     int h 
= bitmap
.GetHeight(); 
1059     CalcBoundingBox( x
, y 
); 
1060     CalcBoundingBox( x 
+ w
, y 
+ h 
); 
1062     if (!m_window
) return; 
1064     int ww 
= XLOG2DEVREL(w
); 
1065     int hh 
= YLOG2DEVREL(h
); 
1067     // compare to current clipping region 
1068     if (!m_currentClippingRegion
.IsNull()) 
1070         wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1071         tmp
.Intersect( m_currentClippingRegion 
); 
1076     // scale bitmap if required 
1077     wxBitmap use_bitmap 
= bitmap
; 
1078     if ((w 
!= ww
) || (h 
!= hh
)) 
1079         use_bitmap 
= use_bitmap
.Rescale( 0, 0, ww
, hh
, ww
, hh 
); 
1081 #if !GTK_CHECK_VERSION(2,2,0) 
1082     // NB: We can't render pixbufs with GTK+ < 2.2, we need to use pixmaps code. 
1083     //     Pixbufs-based bitmaps with alpha channel don't have a mask, so we 
1084     //     have to call GetPixmap() here -- it converts the pixbuf into pixmap 
1085     //     and also creates the mask as a side-effect: 
1086     use_bitmap
.GetPixmap(); 
1089     // apply mask if any 
1090     GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
1091     if (use_bitmap
.GetMask()) mask 
= use_bitmap
.GetMask()->GetBitmap(); 
1093     GdkBitmap 
*new_mask 
= (GdkBitmap
*) NULL
; 
1095     if (useMask 
&& mask
) 
1097         if (!m_currentClippingRegion
.IsNull()) 
1100             new_mask 
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 ); 
1101             GdkGC 
*gc 
= gdk_gc_new( new_mask 
); 
1103             gdk_gc_set_foreground( gc
, &col 
); 
1104             gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh 
); 
1106             gdk_gc_set_background( gc
, &col 
); 
1108             gdk_gc_set_foreground( gc
, &col 
); 
1109             gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() ); 
1110             gdk_gc_set_clip_origin( gc
, -xx
, -yy 
); 
1111             gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED 
); 
1112             gdk_gc_set_stipple( gc
, mask 
); 
1113             gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh 
); 
1120                 gdk_gc_set_clip_mask( m_textGC
, new_mask 
); 
1122                 gdk_gc_set_clip_mask( m_textGC
, mask 
); 
1123             gdk_gc_set_clip_origin( m_textGC
, xx
, yy 
); 
1128                 gdk_gc_set_clip_mask( m_penGC
, new_mask 
); 
1130                 gdk_gc_set_clip_mask( m_penGC
, mask 
); 
1131             gdk_gc_set_clip_origin( m_penGC
, xx
, yy 
); 
1135     // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 
1136     // drawing a mono-bitmap (XBitmap) we use the current text GC 
1140         GdkPixmap 
*bitmap 
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, -1 ); 
1141         GdkGC 
*gc 
= gdk_gc_new( bitmap 
); 
1142         gdk_gc_set_foreground( gc
, m_textForegroundColour
.GetColor() ); 
1143         gdk_gc_set_background( gc
, m_textBackgroundColour
.GetColor() ); 
1144         gdk_wx_draw_bitmap( bitmap
, gc
, use_bitmap
.GetBitmap(), 0, 0, 0, 0, -1, -1 ); 
1146         gdk_draw_drawable( m_window
, m_textGC
, bitmap
, 0, 0, xx
, yy
, -1, -1 ); 
1148         gdk_bitmap_unref( bitmap 
); 
1151         gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 ); 
1156 #if GTK_CHECK_VERSION(2,2,0) 
1157         if (!gtk_check_version(2,2,0) && use_bitmap
.HasPixbuf()) 
1159             gdk_draw_pixbuf(m_window
, m_penGC
, 
1160                             use_bitmap
.GetPixbuf(), 
1161                             0, 0, xx
, yy
, -1, -1, 
1162                             GDK_RGB_DITHER_NORMAL
, xx
, yy
); 
1167             gdk_draw_pixmap(m_window
, m_penGC
, 
1168                             use_bitmap
.GetPixmap(), 
1169                             0, 0, xx
, yy
, -1, -1); 
1173     // remove mask again if any 
1174     if (useMask 
&& mask
) 
1178             gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap 
*) NULL 
); 
1179             gdk_gc_set_clip_origin( m_textGC
, 0, 0 ); 
1180             if (!m_currentClippingRegion
.IsNull()) 
1181                 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
1185             gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap 
*) NULL 
); 
1186             gdk_gc_set_clip_origin( m_penGC
, 0, 0 ); 
1187             if (!m_currentClippingRegion
.IsNull()) 
1188                 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
1193         gdk_bitmap_unref( new_mask 
); 
1196 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, 
1197                          wxCoord width
, wxCoord height
, 
1199                          wxCoord xsrc
, wxCoord ysrc
, 
1202                          wxCoord xsrcMask
, wxCoord ysrcMask 
) 
1204     wxCHECK_MSG( Ok(), false, wxT("invalid window dc") ); 
1206     wxCHECK_MSG( source
, false, wxT("invalid source dc") ); 
1208     if (!m_window
) return false; 
1210     // transform the source DC coords to the device ones 
1211     xsrc 
= source
->XLOG2DEV(xsrc
); 
1212     ysrc 
= source
->YLOG2DEV(ysrc
); 
1214     wxClientDC 
*srcDC 
= (wxClientDC
*)source
; 
1215     wxMemoryDC 
*memDC 
= (wxMemoryDC
*)source
; 
1217     bool use_bitmap_method 
= false; 
1218     bool is_mono 
= false; 
1220     // TODO: use the mask origin when drawing transparently 
1221     if (xsrcMask 
== -1 && ysrcMask 
== -1) 
1227     if (srcDC
->m_isMemDC
) 
1229         if (!memDC
->m_selected
.Ok()) return false; 
1231         is_mono 
= (memDC
->m_selected
.GetDepth() == 1); 
1233         // we use the "XCopyArea" way to copy a memory dc into 
1234         // a different window if the memory dc BOTH 
1235         // a) doesn't have any mask or its mask isn't used 
1239         if (useMask 
&& (memDC
->m_selected
.GetMask())) 
1241             // we HAVE TO use the direct way for memory dcs 
1242             // that have mask since the XCopyArea doesn't know 
1244             use_bitmap_method 
= true; 
1248             // we HAVE TO use the direct way for memory dcs 
1249             // that are bitmaps because XCopyArea doesn't cope 
1250             // with different bit depths 
1251             use_bitmap_method 
= true; 
1253         else if ((xsrc 
== 0) && (ysrc 
== 0) && 
1254                  (width 
== memDC
->m_selected
.GetWidth()) && 
1255                  (height 
== memDC
->m_selected
.GetHeight())) 
1257             // we SHOULD use the direct way if all of the bitmap 
1258             // in the memory dc is copied in which case XCopyArea 
1259             // wouldn't be able able to boost performace by reducing 
1260             // the area to be scaled 
1261             use_bitmap_method 
= true; 
1265             use_bitmap_method 
= false; 
1269     CalcBoundingBox( xdest
, ydest 
); 
1270     CalcBoundingBox( xdest 
+ width
, ydest 
+ height 
); 
1272     // scale/translate size and position 
1273     wxCoord xx 
= XLOG2DEV(xdest
); 
1274     wxCoord yy 
= YLOG2DEV(ydest
); 
1276     wxCoord ww 
= XLOG2DEVREL(width
); 
1277     wxCoord hh 
= YLOG2DEVREL(height
); 
1279     // compare to current clipping region 
1280     if (!m_currentClippingRegion
.IsNull()) 
1282         wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1283         tmp
.Intersect( m_currentClippingRegion 
); 
1288     int old_logical_func 
= m_logicalFunction
; 
1289     SetLogicalFunction( logical_func 
); 
1291     if (use_bitmap_method
) 
1293         // scale/translate bitmap size 
1294         wxCoord bm_width 
= memDC
->m_selected
.GetWidth(); 
1295         wxCoord bm_height 
= memDC
->m_selected
.GetHeight(); 
1297         // Get clip coords for the bitmap. If we don't 
1298         // use wxBitmap::Rescale(), which can clip the 
1299         // bitmap, these are the same as the original 
1306         // interpret userscale of src too 
1308         memDC
->GetUserScale(&xsc
,&ysc
); 
1309         bm_width 
= (int) (bm_width 
/ xsc
); 
1310         bm_height 
= (int) (bm_height 
/ ysc
); 
1312         wxCoord bm_ww 
= XLOG2DEVREL( bm_width 
); 
1313         wxCoord bm_hh 
= YLOG2DEVREL( bm_height 
); 
1315         // Scale bitmap if required 
1316         wxBitmap use_bitmap
; 
1317         if ((memDC
->m_selected
.GetWidth()!= bm_ww
) || ( memDC
->m_selected
.GetHeight()!= bm_hh
)) 
1319             // This indicates that the blitting code below will get 
1320             // a clipped bitmap and therefore needs to move the origin 
1322             wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1323             tmp
.Intersect( m_currentClippingRegion 
); 
1324             tmp
.GetBox(cx
,cy
,cw
,ch
); 
1326             // Scale and clipped bitmap 
1327             use_bitmap 
= memDC
->m_selected
.Rescale(cx
-xx
,cy
-yy
,cw
,ch
,bm_ww
,bm_hh
); 
1331             // Don't scale bitmap 
1332             use_bitmap 
= memDC
->m_selected
; 
1335         // apply mask if any 
1336         GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
1337         if (use_bitmap
.GetMask()) mask 
= use_bitmap
.GetMask()->GetBitmap(); 
1339         GdkBitmap 
*new_mask 
= (GdkBitmap
*) NULL
; 
1341         if (useMask 
&& mask
) 
1343             if (!m_currentClippingRegion
.IsNull()) 
1346                 new_mask 
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 ); 
1347                 GdkGC 
*gc 
= gdk_gc_new( new_mask 
); 
1349                 gdk_gc_set_foreground( gc
, &col 
); 
1350                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh 
); 
1352                 gdk_gc_set_background( gc
, &col 
); 
1354                 gdk_gc_set_foreground( gc
, &col 
); 
1355                 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() ); 
1356                 // was: gdk_gc_set_clip_origin( gc, -xx, -yy ); 
1357                 gdk_gc_set_clip_origin( gc
, -cx
, -cy 
); 
1358                 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED 
); 
1359                 gdk_gc_set_stipple( gc
, mask 
); 
1360                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh 
); 
1367                     gdk_gc_set_clip_mask( m_textGC
, new_mask 
); 
1369                     gdk_gc_set_clip_mask( m_textGC
, mask 
); 
1370                 // was: gdk_gc_set_clip_origin( m_textGC, xx, yy ); 
1371                 gdk_gc_set_clip_origin( m_textGC
, cx
, cy 
); 
1376                     gdk_gc_set_clip_mask( m_penGC
, new_mask 
); 
1378                     gdk_gc_set_clip_mask( m_penGC
, mask 
); 
1379                 // was: gdk_gc_set_clip_origin( m_penGC, xx, yy ); 
1380                 gdk_gc_set_clip_origin( m_penGC
, cx
, cy 
); 
1384         // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 
1385         // drawing a mono-bitmap (XBitmap) we use the current text GC 
1390             GdkPixmap 
*bitmap 
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, -1 ); 
1391             GdkGC 
*gc 
= gdk_gc_new( bitmap 
); 
1392             gdk_gc_set_foreground( gc
, m_textForegroundColour
.GetColor() ); 
1393             gdk_gc_set_background( gc
, m_textBackgroundColour
.GetColor() ); 
1394             gdk_wx_draw_bitmap( bitmap
, gc
, use_bitmap
.GetBitmap(), 0, 0, 0, 0, -1, -1 ); 
1396             gdk_draw_drawable( m_window
, m_textGC
, bitmap
, xsrc
, ysrc
, cx
, cy
, cw
, ch 
); 
1398             gdk_bitmap_unref( bitmap 
); 
1401             // was: gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh ); 
1402             gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, cx
, cy
, cw
, ch 
); 
1407             // was: gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh ); 
1408             gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, cx
, cy
, cw
, ch 
); 
1411         // remove mask again if any 
1412         if (useMask 
&& mask
) 
1416                 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap 
*) NULL 
); 
1417                 gdk_gc_set_clip_origin( m_textGC
, 0, 0 ); 
1418                 if (!m_currentClippingRegion
.IsNull()) 
1419                     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
1423                 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap 
*) NULL 
); 
1424                 gdk_gc_set_clip_origin( m_penGC
, 0, 0 ); 
1425                 if (!m_currentClippingRegion
.IsNull()) 
1426                     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
1431             gdk_bitmap_unref( new_mask 
); 
1433     else // use_bitmap_method 
1435         if ((width 
!= ww
) || (height 
!= hh
)) 
1438             wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1439             tmp
.Intersect( m_currentClippingRegion 
); 
1440             wxCoord cx
,cy
,cw
,ch
; 
1441             tmp
.GetBox(cx
,cy
,cw
,ch
); 
1444             wxBitmap bitmap 
= memDC
->m_selected
.Rescale( cx
-xx
, cy
-yy
, cw
, ch
, ww
, hh 
); 
1446             // draw scaled bitmap 
1447             // was: gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); 
1448             gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, cx
, cy
, -1, -1 ); 
1452             // No scaling and not a memory dc with a mask either 
1454             // copy including child window contents 
1455             gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS 
); 
1456             gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
, 
1458                                   xsrc
, ysrc
, width
, height 
); 
1459             gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN 
); 
1463     SetLogicalFunction( old_logical_func 
); 
1468 void wxWindowDC::DoDrawText( const wxString 
&text
, wxCoord x
, wxCoord y 
) 
1470     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1472     if (!m_window
) return; 
1474     if (text
.empty()) return; 
1477     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1479     wxCHECK_RET( font
, wxT("invalid font") ); 
1486     wxCHECK_RET( m_context
, wxT("no Pango context") ); 
1487     wxCHECK_RET( m_layout
, wxT("no Pango layout") ); 
1488     wxCHECK_RET( m_fontdesc
, wxT("no Pango font description") ); 
1490     bool underlined 
= m_font
.Ok() && m_font
.GetUnderlined(); 
1493     const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( text 
); 
1495     const wxWCharBuffer wdata 
= wxConvLocal
.cMB2WC( text 
); 
1498     const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( wdata 
); 
1500     size_t datalen 
= strlen((const char*)data
); 
1501     pango_layout_set_text( m_layout
, (const char*) data
, datalen
); 
1505         PangoAttrList 
*attrs 
= pango_attr_list_new(); 
1506         PangoAttribute 
*a 
= pango_attr_underline_new(PANGO_UNDERLINE_SINGLE
); 
1508         a
->end_index 
= datalen
; 
1509         pango_attr_list_insert(attrs
, a
); 
1510         pango_layout_set_attributes(m_layout
, attrs
); 
1511         pango_attr_list_unref(attrs
); 
1516     if (fabs(m_scaleY 
- 1.0) > 0.00001) 
1518          // If there is a user or actually any scale applied to 
1519          // the device context, scale the font. 
1521          // scale font description 
1522          gint oldSize 
= pango_font_description_get_size( m_fontdesc 
); 
1523          double size 
= oldSize
; 
1524          size 
= size 
* m_scaleY
; 
1525          pango_font_description_set_size( m_fontdesc
, (gint
)size 
); 
1527          // actually apply scaled font 
1528          pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1530          pango_layout_get_pixel_size( m_layout
, &w
, &h 
); 
1531          if ( m_backgroundMode 
== wxSOLID 
) 
1533             gdk_gc_set_foreground(m_textGC
, m_textBackgroundColour
.GetColor()); 
1534             gdk_draw_rectangle(m_window
, m_textGC
, TRUE
, x
, y
, w
, h
); 
1535             gdk_gc_set_foreground(m_textGC
, m_textForegroundColour
.GetColor()); 
1539          gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout 
); 
1541          // reset unscaled size 
1542          pango_font_description_set_size( m_fontdesc
, oldSize 
); 
1544          // actually apply unscaled font 
1545          pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1549         pango_layout_get_pixel_size( m_layout
, &w
, &h 
); 
1550         if ( m_backgroundMode 
== wxSOLID 
) 
1552             gdk_gc_set_foreground(m_textGC
, m_textBackgroundColour
.GetColor()); 
1553             gdk_draw_rectangle(m_window
, m_textGC
, TRUE
, x
, y
, w
, h
); 
1554             gdk_gc_set_foreground(m_textGC
, m_textForegroundColour
.GetColor()); 
1557         gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout 
); 
1562         // undo underline attributes setting: 
1563         pango_layout_set_attributes(m_layout
, NULL
); 
1570     wxCoord width 
= gdk_string_width( font
, text
.mbc_str() ); 
1571     wxCoord height 
= font
->ascent 
+ font
->descent
; 
1573     if ( m_backgroundMode 
== wxSOLID 
) 
1575         gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() ); 
1576         gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height 
); 
1577         gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
1579     gdk_draw_string( m_window
, font
, m_textGC
, x
, y 
+ font
->ascent
, text
.mbc_str() ); 
1581     /* CMB 17/7/98: simple underline: ignores scaling and underlying 
1582        X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS 
1583        properties (see wxXt implementation) */ 
1584     if (m_font
.GetUnderlined()) 
1586         wxCoord ul_y 
= y 
+ font
->ascent
; 
1587         if (font
->descent 
> 0) ul_y
++; 
1588         gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x 
+ width
, ul_y
); 
1590 #endif // GTK+ 2.0/1.x 
1592     width 
= wxCoord(width 
/ m_scaleX
); 
1593     height 
= wxCoord(height 
/ m_scaleY
); 
1594     CalcBoundingBox (x 
+ width
, y 
+ height
); 
1595     CalcBoundingBox (x
, y
); 
1599 // TODO: There is an example of rotating text with GTK2 that would probably be 
1600 // a better approach here: 
1601 //           http://www.daa.com.au/pipermail/pygtk/2003-April/005052.html 
1603 void wxWindowDC::DoDrawRotatedText( const wxString 
&text
, wxCoord x
, wxCoord y
, double angle 
) 
1607         DrawText(text
, x
, y
); 
1611     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1613     if (!m_window
) return; 
1619     // implement later without GdkFont for GTK 2.0 
1620     GetTextExtent(text
, &w
, &h
, NULL
,NULL
, &m_font
); 
1623     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1625     wxCHECK_RET( font
, wxT("invalid font") ); 
1627     // the size of the text 
1628     w 
= gdk_string_width( font
, text
.mbc_str() ); 
1629     h 
= font
->ascent 
+ font
->descent
; 
1631     // draw the string normally 
1634     dc
.SelectObject(src
); 
1635     dc
.SetFont(GetFont()); 
1636     dc
.SetBackground(*wxBLACK_BRUSH
); 
1637     dc
.SetBrush(*wxBLACK_BRUSH
); 
1639     dc
.SetTextForeground( *wxWHITE 
); 
1640     dc
.DrawText(text
, 0, 0); 
1641     dc
.SelectObject(wxNullBitmap
); 
1643     // Calculate the size of the rotated bounding box. 
1644     double rad 
= DegToRad(angle
); 
1645     double dx 
= cos(rad
), 
1648     // the rectngle vertices are counted clockwise with the first one being at 
1649     // (0, 0) (or, rather, at (x, y)) 
1651            y2 
= -w
*dy
;      // y axis points to the bottom, hence minus 
1654     double x3 
= x4 
+ x2
, 
1658     wxCoord maxX 
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5), 
1659             maxY 
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5), 
1660             minX 
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5), 
1661             minY 
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5); 
1664     wxImage image 
= src
.ConvertToImage(); 
1666     image
.ConvertColourToAlpha( m_textForegroundColour
.Red(), 
1667                                 m_textForegroundColour
.Green(), 
1668                                 m_textForegroundColour
.Blue() ); 
1669     image 
= image
.Rotate( rad
, wxPoint(0,0) ); 
1671     int i_angle 
= (int) angle
; 
1672     i_angle 
= i_angle 
% 360; 
1676     if ((i_angle 
>= 90.0) && (i_angle 
< 270.0)) 
1677         xoffset 
= image
.GetWidth(); 
1679     if ((i_angle 
>= 0.0) && (i_angle 
< 180.0)) 
1680         yoffset 
= image
.GetHeight(); 
1682     if ((i_angle 
>= 0) && (i_angle 
< 90)) 
1683         yoffset 
-= (int)( cos(rad
)*h 
); 
1684     if ((i_angle 
>= 90) && (i_angle 
< 180)) 
1685         xoffset 
-= (int)( sin(rad
)*h 
); 
1686     if ((i_angle 
>= 180) && (i_angle 
< 270)) 
1687         yoffset 
-= (int)( cos(rad
)*h 
); 
1688     if ((i_angle 
>= 270) && (i_angle 
< 360)) 
1689         xoffset 
-= (int)( sin(rad
)*h 
); 
1691     int i_x 
= x 
- xoffset
; 
1692     int i_y 
= y 
- yoffset
; 
1695     DoDrawBitmap( src
, i_x
, i_y
, true ); 
1698     // it would be better to draw with non underlined font and draw the line 
1699     // manually here (it would be more straight...) 
1701     if ( m_font
.GetUnderlined() ) 
1703         gdk_draw_line( m_window
, m_textGC
, 
1704                        XLOG2DEV(x 
+ x4
), YLOG2DEV(y 
+ y4 
+ font
->descent
), 
1705                        XLOG2DEV(x 
+ x3
), YLOG2DEV(y 
+ y3 
+ font
->descent
)); 
1709     // update the bounding box 
1710     CalcBoundingBox(x 
+ minX
, y 
+ minY
); 
1711     CalcBoundingBox(x 
+ maxX
, y 
+ maxY
); 
1714 void wxWindowDC::DoGetTextExtent(const wxString 
&string
, 
1715                                  wxCoord 
*width
, wxCoord 
*height
, 
1716                                  wxCoord 
*descent
, wxCoord 
*externalLeading
, 
1717                                  wxFont 
*theFont
) const 
1725     if ( externalLeading 
) 
1726         *externalLeading 
= 0; 
1734     // Set new font description 
1736         pango_layout_set_font_description( m_layout
, theFont
->GetNativeFontInfo()->description 
); 
1738     // Set layout's text 
1740     const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( string 
); 
1741     const char *dataUTF8 
= (const char *)data
; 
1743     const wxWCharBuffer wdata 
= wxConvLocal
.cMB2WC( string 
); 
1747     const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( wdata 
); 
1748     const char *dataUTF8 
= (const char *)data
; 
1753         // hardly ideal, but what else can we do if conversion failed? 
1757     pango_layout_set_text( m_layout
, dataUTF8
, strlen(dataUTF8
) ); 
1762         pango_layout_get_pixel_size( m_layout
, width
, &h 
); 
1763         PangoLayoutIter 
*iter 
= pango_layout_get_iter(m_layout
); 
1764         int baseline 
= pango_layout_iter_get_baseline(iter
); 
1765         pango_layout_iter_free(iter
); 
1766         *descent 
= h 
- PANGO_PIXELS(baseline
); 
1769             *height 
= (wxCoord
) h
; 
1773         pango_layout_get_pixel_size( m_layout
, width
, height 
); 
1776     // Reset old font description 
1778         pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1780     wxFont fontToUse 
= m_font
; 
1782         fontToUse 
= *theFont
; 
1784     GdkFont 
*font 
= fontToUse
.GetInternalFont( m_scaleY 
); 
1789         *width 
= wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
); 
1791         *height 
= wxCoord((font
->ascent 
+ font
->descent
) / m_scaleY
); 
1793         *descent 
= wxCoord(font
->descent 
/ m_scaleY
); 
1797 wxCoord 
wxWindowDC::GetCharWidth() const 
1800     pango_layout_set_text( m_layout
, "H", 1 ); 
1802     pango_layout_get_pixel_size( m_layout
, &w
, NULL 
); 
1805     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1806     wxCHECK_MSG( font
, -1, wxT("invalid font") ); 
1808     return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
); 
1812 wxCoord 
wxWindowDC::GetCharHeight() const 
1815     pango_layout_set_text( m_layout
, "H", 1 ); 
1817     pango_layout_get_pixel_size( m_layout
, NULL
, &h 
); 
1820     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1821     wxCHECK_MSG( font
, -1, wxT("invalid font") ); 
1823     return wxCoord((font
->ascent 
+ font
->descent
) / m_scaleY
); 
1827 void wxWindowDC::Clear() 
1829     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1831     if (!m_window
) return; 
1833     // VZ: the code below results in infinite recursion and crashes when 
1834     //     dc.Clear() is done from OnPaint() so I disable it for now. 
1835     //     I don't know what the correct fix is but Clear() surely should not 
1836     //     reenter OnPaint()! 
1838     /* - we either are a memory dc or have a window as the 
1839        owner. anything else shouldn't happen. 
1840        - we don't use gdk_window_clear() as we don't set 
1841        the window's background colour anymore. it is too 
1842        much pain to keep the DC's and the window's back- 
1843        ground colour in synch. */ 
1854         GetSize( &width
, &height 
); 
1855         gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height 
); 
1860     GetSize( &width
, &height 
); 
1861     gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height 
); 
1865 void wxWindowDC::SetFont( const wxFont 
&font 
) 
1873             pango_font_description_free( m_fontdesc 
); 
1875         m_fontdesc 
= pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
1880             PangoContext 
*oldContext 
= m_context
; 
1882             // We might want to use the X11 context for faster 
1883             // rendering on screen 
1884             if (m_font
.GetNoAntiAliasing()) 
1885                 m_context 
= m_owner
->GtkGetPangoX11Context(); 
1887                 m_context 
= m_owner
->GtkGetPangoDefaultContext(); 
1889             // If we switch back/forth between different contexts 
1890             // we also have to create a new layout. I think so, 
1891             // at least, and it doesn't hurt to do it. 
1892             if (oldContext 
!= m_context
) 
1895                     g_object_unref( G_OBJECT( m_layout 
) ); 
1897                 m_layout 
= pango_layout_new( m_context 
); 
1901         pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1906 void wxWindowDC::SetPen( const wxPen 
&pen 
) 
1908     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1910     if (m_pen 
== pen
) return; 
1914     if (!m_pen
.Ok()) return; 
1916     if (!m_window
) return; 
1918     gint width 
= m_pen
.GetWidth(); 
1921         // CMB: if width is non-zero scale it with the dc 
1926         // X doesn't allow different width in x and y and so we take 
1929                    ( fabs((double) XLOG2DEVREL(width
)) + 
1930                      fabs((double) YLOG2DEVREL(width
)) ) / 2.0; 
1934             // width can't be 0 or an internal GTK error occurs inside 
1935             // gdk_gc_set_dashes() below 
1940     static const wxGTKDash dotted
[] = {1, 1}; 
1941     static const wxGTKDash short_dashed
[] = {2, 2}; 
1942     static const wxGTKDash wxCoord_dashed
[] = {2, 4}; 
1943     static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3}; 
1945     // We express dash pattern in pen width unit, so we are 
1946     // independent of zoom factor and so on... 
1948     const wxGTKDash 
*req_dash
; 
1950     GdkLineStyle lineStyle 
= GDK_LINE_SOLID
; 
1951     switch (m_pen
.GetStyle()) 
1955             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1956             req_nb_dash 
= m_pen
.GetDashCount(); 
1957             req_dash 
= (wxGTKDash
*)m_pen
.GetDash(); 
1962             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1969             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1971             req_dash 
= wxCoord_dashed
; 
1976             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1978             req_dash 
= short_dashed
; 
1983 //            lineStyle = GDK_LINE_DOUBLE_DASH; 
1984             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1986             req_dash 
= dotted_dashed
; 
1991         case wxSTIPPLE_MASK_OPAQUE
: 
1996             lineStyle 
= GDK_LINE_SOLID
; 
1997             req_dash 
= (wxGTKDash
*)NULL
; 
2003     if (req_dash 
&& req_nb_dash
) 
2005         wxGTKDash 
*real_req_dash 
= new wxGTKDash
[req_nb_dash
]; 
2008             for (int i 
= 0; i 
< req_nb_dash
; i
++) 
2009                 real_req_dash
[i
] = req_dash
[i
] * width
; 
2010             gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash 
); 
2011             delete[] real_req_dash
; 
2015             // No Memory. We use non-scaled dash pattern... 
2016             gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash 
); 
2020     GdkCapStyle capStyle 
= GDK_CAP_ROUND
; 
2021     switch (m_pen
.GetCap()) 
2023         case wxCAP_PROJECTING
: { capStyle 
= GDK_CAP_PROJECTING
; break; } 
2024         case wxCAP_BUTT
:       { capStyle 
= GDK_CAP_BUTT
;       break; } 
2031                 capStyle 
= GDK_CAP_NOT_LAST
; 
2035                 capStyle 
= GDK_CAP_ROUND
; 
2041     GdkJoinStyle joinStyle 
= GDK_JOIN_ROUND
; 
2042     switch (m_pen
.GetJoin()) 
2044         case wxJOIN_BEVEL
: { joinStyle 
= GDK_JOIN_BEVEL
; break; } 
2045         case wxJOIN_MITER
: { joinStyle 
= GDK_JOIN_MITER
; break; } 
2047         default:           { joinStyle 
= GDK_JOIN_ROUND
; break; } 
2050     gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle 
); 
2052     m_pen
.GetColour().CalcPixel( m_cmap 
); 
2053     gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() ); 
2056 void wxWindowDC::SetBrush( const wxBrush 
&brush 
) 
2058     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2060     if (m_brush 
== brush
) return; 
2064     if (!m_brush
.Ok()) return; 
2066     if (!m_window
) return; 
2068     m_brush
.GetColour().CalcPixel( m_cmap 
); 
2069     gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() ); 
2071     gdk_gc_set_fill( m_brushGC
, GDK_SOLID 
); 
2073     if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok())) 
2075         if (m_brush
.GetStipple()->GetPixmap()) 
2077             gdk_gc_set_fill( m_brushGC
, GDK_TILED 
); 
2078             gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() ); 
2082             gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED 
); 
2083             gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() ); 
2087     if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
2089         gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
); 
2090         gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() ); 
2093     if (m_brush
.IsHatch()) 
2095         gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED 
); 
2096         int num 
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
; 
2097         gdk_gc_set_stipple( m_brushGC
, hatches
[num
] ); 
2101 void wxWindowDC::SetBackground( const wxBrush 
&brush 
) 
2103    /* CMB 21/7/98: Added SetBackground. Sets background brush 
2104     * for Clear() and bg colour for shapes filled with cross-hatch brush */ 
2106     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2108     if (m_backgroundBrush 
== brush
) return; 
2110     m_backgroundBrush 
= brush
; 
2112     if (!m_backgroundBrush
.Ok()) return; 
2114     if (!m_window
) return; 
2116     m_backgroundBrush
.GetColour().CalcPixel( m_cmap 
); 
2117     gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() ); 
2118     gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() ); 
2119     gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() ); 
2120     gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() ); 
2122     gdk_gc_set_fill( m_bgGC
, GDK_SOLID 
); 
2124     if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok())) 
2126         if (m_backgroundBrush
.GetStipple()->GetPixmap()) 
2128             gdk_gc_set_fill( m_bgGC
, GDK_TILED 
); 
2129             gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() ); 
2133             gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED 
); 
2134             gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() ); 
2138     if (m_backgroundBrush
.IsHatch()) 
2140         gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED 
); 
2141         int num 
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
; 
2142         gdk_gc_set_stipple( m_bgGC
, hatches
[num
] ); 
2146 void wxWindowDC::SetLogicalFunction( int function 
) 
2148     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2150     if (m_logicalFunction 
== function
) 
2153     // VZ: shouldn't this be a CHECK? 
2160         case wxXOR
:          mode 
= GDK_XOR
;           break; 
2161         case wxINVERT
:       mode 
= GDK_INVERT
;        break; 
2162         case wxOR_REVERSE
:   mode 
= GDK_OR_REVERSE
;    break; 
2163         case wxAND_REVERSE
:  mode 
= GDK_AND_REVERSE
;   break; 
2164         case wxCLEAR
:        mode 
= GDK_CLEAR
;         break; 
2165         case wxSET
:          mode 
= GDK_SET
;           break; 
2166         case wxOR_INVERT
:    mode 
= GDK_OR_INVERT
;     break; 
2167         case wxAND
:          mode 
= GDK_AND
;           break; 
2168         case wxOR
:           mode 
= GDK_OR
;            break; 
2169         case wxEQUIV
:        mode 
= GDK_EQUIV
;         break; 
2170         case wxNAND
:         mode 
= GDK_NAND
;          break; 
2171         case wxAND_INVERT
:   mode 
= GDK_AND_INVERT
;    break; 
2172         case wxCOPY
:         mode 
= GDK_COPY
;          break; 
2173         case wxNO_OP
:        mode 
= GDK_NOOP
;          break; 
2174         case wxSRC_INVERT
:   mode 
= GDK_COPY_INVERT
;   break; 
2176         // unsupported by GTK 
2177         case wxNOR
:          mode 
= GDK_COPY
;          break; 
2179            wxFAIL_MSG( wxT("unsupported logical function") ); 
2183     m_logicalFunction 
= function
; 
2185     gdk_gc_set_function( m_penGC
, mode 
); 
2186     gdk_gc_set_function( m_brushGC
, mode 
); 
2188     // to stay compatible with wxMSW, we don't apply ROPs to the text 
2189     // operations (i.e. DrawText/DrawRotatedText). 
2190     // True, but mono-bitmaps use the m_textGC and they use ROPs as well. 
2191     gdk_gc_set_function( m_textGC
, mode 
); 
2194 void wxWindowDC::SetTextForeground( const wxColour 
&col 
) 
2196     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2198     // don't set m_textForegroundColour to an invalid colour as we'd crash 
2199     // later then (we use m_textForegroundColour.GetColor() without checking 
2201     if ( !col
.Ok() || (m_textForegroundColour 
== col
) ) 
2204     m_textForegroundColour 
= col
; 
2208         m_textForegroundColour
.CalcPixel( m_cmap 
); 
2209         gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
2213 void wxWindowDC::SetTextBackground( const wxColour 
&col 
) 
2215     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2218     if ( !col
.Ok() || (m_textBackgroundColour 
== col
) ) 
2221     m_textBackgroundColour 
= col
; 
2225         m_textBackgroundColour
.CalcPixel( m_cmap 
); 
2226         gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() ); 
2230 void wxWindowDC::SetBackgroundMode( int mode 
) 
2232     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2234     m_backgroundMode 
= mode
; 
2236     if (!m_window
) return; 
2238     // CMB 21/7/98: fill style of cross-hatch brushes is affected by 
2239     // transparent/solid background mode 
2241     if (m_brush
.GetStyle() != wxSOLID 
&& m_brush
.GetStyle() != wxTRANSPARENT
) 
2243         gdk_gc_set_fill( m_brushGC
, 
2244           (m_backgroundMode 
== wxTRANSPARENT
) ? GDK_STIPPLED 
: GDK_OPAQUE_STIPPLED
); 
2248 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) ) 
2250     wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") ); 
2253 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
2255     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2257     if (!m_window
) return; 
2260     rect
.x 
= XLOG2DEV(x
); 
2261     rect
.y 
= YLOG2DEV(y
); 
2262     rect
.width 
= XLOG2DEVREL(width
); 
2263     rect
.height 
= YLOG2DEVREL(height
); 
2265     if (!m_currentClippingRegion
.IsNull()) 
2266         m_currentClippingRegion
.Intersect( rect 
); 
2268         m_currentClippingRegion
.Union( rect 
); 
2270 #if USE_PAINT_REGION 
2271     if (!m_paintClippingRegion
.IsNull()) 
2272         m_currentClippingRegion
.Intersect( m_paintClippingRegion 
); 
2275     wxCoord xx
, yy
, ww
, hh
; 
2276     m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh 
); 
2277     wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
2279     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
2280     gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
2281     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
2282     gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
2285 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion 
®ion  
) 
2287     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2291         DestroyClippingRegion(); 
2295     if (!m_window
) return; 
2297     if (!m_currentClippingRegion
.IsNull()) 
2298         m_currentClippingRegion
.Intersect( region 
); 
2300         m_currentClippingRegion
.Union( region 
); 
2302 #if USE_PAINT_REGION 
2303     if (!m_paintClippingRegion
.IsNull()) 
2304         m_currentClippingRegion
.Intersect( m_paintClippingRegion 
); 
2307     wxCoord xx
, yy
, ww
, hh
; 
2308     m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh 
); 
2309     wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
2311     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
2312     gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
2313     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
2314     gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
2317 void wxWindowDC::DestroyClippingRegion() 
2319     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2321     wxDC::DestroyClippingRegion(); 
2323     m_currentClippingRegion
.Clear(); 
2325 #if USE_PAINT_REGION 
2326     if (!m_paintClippingRegion
.IsEmpty()) 
2327         m_currentClippingRegion
.Union( m_paintClippingRegion 
); 
2330     if (!m_window
) return; 
2332     if (m_currentClippingRegion
.IsEmpty()) 
2334         gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle 
*) NULL 
); 
2335         gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle 
*) NULL 
); 
2336         gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle 
*) NULL 
); 
2337         gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle 
*) NULL 
); 
2341         gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
2342         gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
2343         gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
2344         gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
2348 void wxWindowDC::Destroy() 
2350     if (m_penGC
) wxFreePoolGC( m_penGC 
); 
2351     m_penGC 
= (GdkGC
*) NULL
; 
2352     if (m_brushGC
) wxFreePoolGC( m_brushGC 
); 
2353     m_brushGC 
= (GdkGC
*) NULL
; 
2354     if (m_textGC
) wxFreePoolGC( m_textGC 
); 
2355     m_textGC 
= (GdkGC
*) NULL
; 
2356     if (m_bgGC
) wxFreePoolGC( m_bgGC 
); 
2357     m_bgGC 
= (GdkGC
*) NULL
; 
2360 void wxWindowDC::ComputeScaleAndOrigin() 
2362     /* CMB: copy scale to see if it changes */ 
2363     double origScaleX 
= m_scaleX
; 
2364     double origScaleY 
= m_scaleY
; 
2366     wxDC::ComputeScaleAndOrigin(); 
2368     /* CMB: if scale has changed call SetPen to recalulate the line width */ 
2369     if ((m_scaleX 
!= origScaleX 
|| m_scaleY 
!= origScaleY
) && 
2372       /* this is a bit artificial, but we need to force wxDC to think 
2373          the pen has changed */ 
2380 // Resolution in pixels per logical inch 
2381 wxSize 
wxWindowDC::GetPPI() const 
2383     return wxSize( (int) (m_mm_to_pix_x 
* 25.4 + 0.5), (int) (m_mm_to_pix_y 
* 25.4 + 0.5)); 
2386 int wxWindowDC::GetDepth() const 
2389     return gdk_drawable_get_depth(m_window
); 
2391     wxFAIL_MSG(wxT("not implemented")); 
2398 //----------------------------------------------------------------------------- 
2400 //----------------------------------------------------------------------------- 
2402 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
) 
2404 // Limit the paint region to the window size. Sometimes 
2405 // the paint region is too big, and this risks X11 errors 
2406 static void wxLimitRegionToSize(wxRegion
& region
, const wxSize
& sz
) 
2408     wxRect originalRect 
= region
.GetBox(); 
2409     wxRect 
rect(originalRect
); 
2410     if (rect
.width 
+ rect
.x 
> sz
.x
) 
2411         rect
.width 
= sz
.x 
- rect
.x
; 
2412     if (rect
.height 
+ rect
.y 
> sz
.y
) 
2413         rect
.height 
= sz
.y 
- rect
.y
; 
2414     if (rect 
!= originalRect
) 
2416         region 
= wxRegion(rect
); 
2417         wxLogTrace(wxT("painting"), wxT("Limiting region from %d, %d, %d, %d to %d, %d, %d, %d\n"), 
2418                    originalRect
.x
, originalRect
.y
, originalRect
.width
, originalRect
.height
, 
2419                    rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
2423 wxPaintDC::wxPaintDC( wxWindow 
*win 
) 
2426 #if USE_PAINT_REGION 
2427     if (!win
->m_clipPaintRegion
) 
2430     wxSize sz 
= win
->GetSize(); 
2431     m_paintClippingRegion 
= win
->GetUpdateRegion(); 
2432     wxLimitRegionToSize(m_paintClippingRegion
, sz
); 
2434     GdkRegion 
*region 
= m_paintClippingRegion
.GetRegion(); 
2437         m_currentClippingRegion
.Union( m_paintClippingRegion 
); 
2438         wxLimitRegionToSize(m_currentClippingRegion
, sz
); 
2440         if (sz
.x 
<= 0 || sz
.y 
<= 0) 
2443         gdk_gc_set_clip_region( m_penGC
, region 
); 
2444         gdk_gc_set_clip_region( m_brushGC
, region 
); 
2445         gdk_gc_set_clip_region( m_textGC
, region 
); 
2446         gdk_gc_set_clip_region( m_bgGC
, region 
); 
2448 #endif // USE_PAINT_REGION 
2451 //----------------------------------------------------------------------------- 
2453 //----------------------------------------------------------------------------- 
2455 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
) 
2457 wxClientDC::wxClientDC( wxWindow 
*win 
) 
2460     wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") ); 
2462 #ifdef __WXUNIVERSAL__ 
2463     wxPoint ptOrigin 
= win
->GetClientAreaOrigin(); 
2464     SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
); 
2465     wxSize size 
= win
->GetClientSize(); 
2466     SetClippingRegion(wxPoint(0, 0), size
); 
2467 #endif // __WXUNIVERSAL__ 
2470 void wxClientDC::DoGetSize(int *width
, int *height
) const 
2472     wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") ); 
2474     m_owner
->GetClientSize( width
, height 
); 
2477 // ---------------------------------------------------------------------------- 
2479 // ---------------------------------------------------------------------------- 
2481 class wxDCModule 
: public wxModule
 
2488     DECLARE_DYNAMIC_CLASS(wxDCModule
) 
2491 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
) 
2493 bool wxDCModule::OnInit() 
2499 void wxDCModule::OnExit()