]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk/dcclient.cpp
   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 //----------------------------------------------------------------------------- 
 146 #define GC_POOL_SIZE 200 
 172 #define GC_POOL_ALLOC_SIZE 100 
 174 static int wxGCPoolSize 
= 0; 
 176 static wxGC 
*wxGCPool 
= NULL
; 
 178 static void wxInitGCPool() 
 180     // This really could wait until the first call to 
 181     // wxGetPoolGC, but we will make the first allocation 
 182     // now when other initialization is being performed. 
 184     // Set initial pool size. 
 185     wxGCPoolSize 
= GC_POOL_ALLOC_SIZE
; 
 187     // Allocate initial pool. 
 188     wxGCPool 
= (wxGC 
*)malloc(wxGCPoolSize 
* sizeof(wxGC
)); 
 189     if (wxGCPool 
== NULL
) 
 191         // If we cannot malloc, then fail with error 
 192         // when debug is enabled.  If debug is not enabled, 
 193         // the problem will eventually get caught 
 195         wxFAIL_MSG( wxT("Cannot allocate GC pool") ); 
 199     // Zero initial pool. 
 200     memset(wxGCPool
, 0, wxGCPoolSize 
* sizeof(wxGC
)); 
 203 static void wxCleanUpGCPool() 
 205     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 207         if (wxGCPool
[i
].m_gc
) 
 208             gdk_gc_unref( wxGCPool
[i
].m_gc 
); 
 216 static GdkGC
* wxGetPoolGC( GdkWindow 
*window
, wxPoolGCType type 
) 
 220     // Look for an available GC. 
 221     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 223         if (!wxGCPool
[i
].m_gc
) 
 225             wxGCPool
[i
].m_gc 
= gdk_gc_new( window 
); 
 226             gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE 
); 
 227             wxGCPool
[i
].m_type 
= type
; 
 228             wxGCPool
[i
].m_used 
= false; 
 230         if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type 
== type
)) 
 232             wxGCPool
[i
].m_used 
= true; 
 233             return wxGCPool
[i
].m_gc
; 
 237     // We did not find an available GC. 
 238     // We need to grow the GC pool. 
 239     pptr 
= (wxGC 
*)realloc(wxGCPool
, 
 240         (wxGCPoolSize 
+ GC_POOL_ALLOC_SIZE
)*sizeof(wxGC
)); 
 243         // Initialize newly allocated pool. 
 245         memset(&wxGCPool
[wxGCPoolSize
], 0, 
 246             GC_POOL_ALLOC_SIZE
*sizeof(wxGC
)); 
 248         // Initialize entry we will return. 
 249         wxGCPool
[wxGCPoolSize
].m_gc 
= gdk_gc_new( window 
); 
 250         gdk_gc_set_exposures( wxGCPool
[wxGCPoolSize
].m_gc
, FALSE 
); 
 251         wxGCPool
[wxGCPoolSize
].m_type 
= type
; 
 252         wxGCPool
[wxGCPoolSize
].m_used 
= true; 
 254         // Set new value of pool size. 
 255         wxGCPoolSize 
+= GC_POOL_ALLOC_SIZE
; 
 257         // Return newly allocated entry. 
 258         return wxGCPool
[wxGCPoolSize
-GC_POOL_ALLOC_SIZE
].m_gc
; 
 261     // The realloc failed.  Fall through to error. 
 262     wxFAIL_MSG( wxT("No GC available") ); 
 264     return (GdkGC
*) NULL
; 
 267 static void wxFreePoolGC( GdkGC 
*gc 
) 
 269     for (int i 
= 0; i 
< wxGCPoolSize
; i
++) 
 271         if (wxGCPool
[i
].m_gc 
== gc
) 
 273             wxGCPool
[i
].m_used 
= false; 
 278     wxFAIL_MSG( wxT("Wrong GC") ); 
 281 //----------------------------------------------------------------------------- 
 283 //----------------------------------------------------------------------------- 
 285 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
) 
 287 wxWindowDC::wxWindowDC() 
 289     m_penGC 
= (GdkGC 
*) NULL
; 
 290     m_brushGC 
= (GdkGC 
*) NULL
; 
 291     m_textGC 
= (GdkGC 
*) NULL
; 
 292     m_bgGC 
= (GdkGC 
*) NULL
; 
 293     m_cmap 
= (GdkColormap 
*) NULL
; 
 295     m_isScreenDC 
= false; 
 296     m_owner 
= (wxWindow 
*)NULL
; 
 298     m_context 
= (PangoContext 
*)NULL
; 
 299     m_layout 
= (PangoLayout 
*)NULL
; 
 300     m_fontdesc 
= (PangoFontDescription 
*)NULL
; 
 304 wxWindowDC::wxWindowDC( wxWindow 
*window 
) 
 306     wxASSERT_MSG( window
, wxT("DC needs a window") ); 
 308     m_penGC 
= (GdkGC 
*) NULL
; 
 309     m_brushGC 
= (GdkGC 
*) NULL
; 
 310     m_textGC 
= (GdkGC 
*) NULL
; 
 311     m_bgGC 
= (GdkGC 
*) NULL
; 
 312     m_cmap 
= (GdkColormap 
*) NULL
; 
 313     m_owner 
= (wxWindow 
*)NULL
; 
 315     m_isScreenDC 
= false; 
 316     m_font 
= window
->GetFont(); 
 318     GtkWidget 
*widget 
= window
->m_wxwindow
; 
 320     // Some controls don't have m_wxwindow - like wxStaticBox, but the user 
 321     // code should still be able to create wxClientDCs for them, so we will 
 322     // use the parent window here then. 
 325         window 
= window
->GetParent(); 
 326         widget 
= window
->m_wxwindow
; 
 329     wxASSERT_MSG( widget
, wxT("DC needs a widget") ); 
 332     m_context 
= window
->GtkGetPangoDefaultContext(); 
 333     m_layout 
= pango_layout_new( m_context 
); 
 334     m_fontdesc 
= pango_font_description_copy( widget
->style
->font_desc 
); 
 337     GtkPizza 
*pizza 
= GTK_PIZZA( widget 
); 
 338     m_window 
= pizza
->bin_window
; 
 340     // Window not realized ? 
 343          // Don't report problems as per MSW. 
 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() 
 369         g_object_unref( G_OBJECT( m_layout 
) ); 
 371         pango_font_description_free( m_fontdesc 
); 
 375 void wxWindowDC::SetUpDC() 
 379     wxASSERT_MSG( !m_penGC
, wxT("GCs already created") ); 
 383         m_penGC 
= wxGetPoolGC( m_window
, wxPEN_SCREEN 
); 
 384         m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_SCREEN 
); 
 385         m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_SCREEN 
); 
 386         m_bgGC 
= wxGetPoolGC( m_window
, wxBG_SCREEN 
); 
 389     if (m_isMemDC 
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1)) 
 391         m_penGC 
= wxGetPoolGC( m_window
, wxPEN_MONO 
); 
 392         m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_MONO 
); 
 393         m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_MONO 
); 
 394         m_bgGC 
= wxGetPoolGC( m_window
, wxBG_MONO 
); 
 398         m_penGC 
= wxGetPoolGC( m_window
, wxPEN_COLOUR 
); 
 399         m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR 
); 
 400         m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_COLOUR 
); 
 401         m_bgGC 
= wxGetPoolGC( m_window
, wxBG_COLOUR 
); 
 404     /* background colour */ 
 405     m_backgroundBrush 
= *wxWHITE_BRUSH
; 
 406     m_backgroundBrush
.GetColour().CalcPixel( m_cmap 
); 
 407     GdkColor 
*bg_col 
= m_backgroundBrush
.GetColour().GetColor(); 
 410     m_textForegroundColour
.CalcPixel( m_cmap 
); 
 411     gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
 413     m_textBackgroundColour
.CalcPixel( m_cmap 
); 
 414     gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() ); 
 416     gdk_gc_set_fill( m_textGC
, GDK_SOLID 
); 
 419     m_pen
.GetColour().CalcPixel( m_cmap 
); 
 420     gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() ); 
 421     gdk_gc_set_background( m_penGC
, bg_col 
); 
 423     gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND 
); 
 426     m_brush
.GetColour().CalcPixel( m_cmap 
); 
 427     gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() ); 
 428     gdk_gc_set_background( m_brushGC
, bg_col 
); 
 430     gdk_gc_set_fill( m_brushGC
, GDK_SOLID 
); 
 433     gdk_gc_set_background( m_bgGC
, bg_col 
); 
 434     gdk_gc_set_foreground( m_bgGC
, bg_col 
); 
 436     gdk_gc_set_fill( m_bgGC
, GDK_SOLID 
); 
 439     gdk_gc_set_function( m_textGC
, GDK_COPY 
); 
 440     gdk_gc_set_function( m_brushGC
, GDK_COPY 
); 
 441     gdk_gc_set_function( m_penGC
, GDK_COPY 
); 
 444     gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle 
*) NULL 
); 
 445     gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle 
*) NULL 
); 
 446     gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle 
*) NULL 
); 
 447     gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle 
*) NULL 
); 
 451         hatch_bitmap    
= hatches
; 
 452         hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height 
); 
 453         hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height 
); 
 454         hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height 
); 
 455         hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, cross_bits
, cross_width
, cross_height 
); 
 456         hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, horiz_bits
, horiz_width
, horiz_height 
); 
 457         hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, verti_bits
, verti_width
, verti_height 
); 
 461 void wxWindowDC::DoGetSize( int* width
, int* height 
) const 
 463     wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") ); 
 465     m_owner
->GetSize(width
, height
); 
 468 extern bool wxDoFloodFill(wxDC 
*dc
, wxCoord x
, wxCoord y
, 
 469                           const wxColour 
& col
, int style
); 
 471 bool wxWindowDC::DoFloodFill(wxCoord x
, wxCoord y
, 
 472                              const wxColour
& col
, int style
) 
 474     return wxDoFloodFill(this, x
, y
, col
, style
); 
 477 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour 
*col 
) const 
 479     // Generic (and therefore rather inefficient) method. 
 480     // Could be improved. 
 482     wxBitmap 
bitmap(1, 1); 
 483     memdc
.SelectObject(bitmap
); 
 484     memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
); 
 485     memdc
.SelectObject(wxNullBitmap
); 
 487     wxImage image 
= bitmap
.ConvertToImage(); 
 488     col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0)); 
 492 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2 
) 
 494     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 496     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 499             gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) ); 
 501         CalcBoundingBox(x1
, y1
); 
 502         CalcBoundingBox(x2
, y2
); 
 506 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y 
) 
 508     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 510     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 515         wxCoord xx 
= XLOG2DEV(x
); 
 516         wxCoord yy 
= YLOG2DEV(y
); 
 519             gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy 
); 
 520             gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) ); 
 525 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, 
 526                             wxCoord xc
, wxCoord yc 
) 
 528     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 530     wxCoord xx1 
= XLOG2DEV(x1
); 
 531     wxCoord yy1 
= YLOG2DEV(y1
); 
 532     wxCoord xx2 
= XLOG2DEV(x2
); 
 533     wxCoord yy2 
= YLOG2DEV(y2
); 
 534     wxCoord xxc 
= XLOG2DEV(xc
); 
 535     wxCoord yyc 
= YLOG2DEV(yc
); 
 536     double dx 
= xx1 
- xxc
; 
 537     double dy 
= yy1 
- yyc
; 
 538     double radius 
= sqrt((double)(dx
*dx
+dy
*dy
)); 
 539     wxCoord   r      
= (wxCoord
)radius
; 
 540     double radius1
, radius2
; 
 542     if (xx1 
== xx2 
&& yy1 
== yy2
) 
 550         radius1 
= radius2 
= 0.0; 
 554         radius1 
= (xx1 
- xxc 
== 0) ? 
 555             (yy1 
- yyc 
< 0) ? 90.0 : -90.0 : 
 556             -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
; 
 557         radius2 
= (xx2 
- xxc 
== 0) ? 
 558             (yy2 
- yyc 
< 0) ? 90.0 : -90.0 : 
 559             -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
; 
 561     wxCoord alpha1 
= wxCoord(radius1 
* 64.0); 
 562     wxCoord alpha2 
= wxCoord((radius2 
- radius1
) * 64.0); 
 563     while (alpha2 
<= 0) alpha2 
+= 360*64; 
 564     while (alpha1 
> 360*64) alpha1 
-= 360*64; 
 568         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 570             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 572                 gdk_gc_set_ts_origin( m_textGC
, 
 573                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 574                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 575                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 576                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 578             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 580                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 581                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 582                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 584             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 586                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 587                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 588                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 590             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 592                 gdk_gc_set_ts_origin( m_brushGC
, 
 593                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 594                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 595                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 596                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 600                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 604         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 606             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 608             gdk_draw_line( m_window
, m_penGC
, xx1
, yy1
, xxc
, yyc 
); 
 609             gdk_draw_line( m_window
, m_penGC
, xxc
, yyc
, xx2
, yy2 
); 
 613     CalcBoundingBox (x1
, y1
); 
 614     CalcBoundingBox (x2
, y2
); 
 617 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea 
) 
 619     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 621     wxCoord xx 
= XLOG2DEV(x
); 
 622     wxCoord yy 
= YLOG2DEV(y
); 
 623     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 624     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 626     // CMB: handle -ve width and/or height 
 627     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 628     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 632         wxCoord start 
= wxCoord(sa 
* 64.0); 
 633         wxCoord end 
= wxCoord((ea
-sa
) * 64.0); 
 635         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 637             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 639                 gdk_gc_set_ts_origin( m_textGC
, 
 640                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 641                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 642                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 643                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 645             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 647                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 648                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 649                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 651             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 653                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 654                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 655                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 657             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 659                 gdk_gc_set_ts_origin( m_brushGC
, 
 660                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 661                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 662                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 663                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 667                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 671         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 672             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end 
); 
 675     CalcBoundingBox (x
, y
); 
 676     CalcBoundingBox (x 
+ width
, y 
+ height
); 
 679 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y 
) 
 681     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 683     if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
) 
 684         gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) ); 
 686     CalcBoundingBox (x
, y
); 
 689 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset 
) 
 691     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 693     if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 696     GdkPoint 
*gpts 
= new GdkPoint
[n
]; 
 699         wxFAIL_MSG( wxT("Cannot allocate PolyLine") ); 
 703     for (int i 
= 0; i 
< n
; i
++) 
 705         wxCoord x1 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 706         wxCoord y1 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 708         CalcBoundingBox( x1 
+ xoffset
, y1 
+ yoffset 
); 
 715         gdk_draw_lines( m_window
, m_penGC
, gpts
, n
); 
 720 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) ) 
 722     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 726     GdkPoint 
*gdkpoints 
= new GdkPoint
[n
+1]; 
 728     for (i 
= 0 ; i 
< n 
; i
++) 
 730         gdkpoints
[i
].x 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 731         gdkpoints
[i
].y 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 733         CalcBoundingBox( points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset 
); 
 738         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 740             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 742                 gdk_gc_set_ts_origin( m_textGC
, 
 743                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 744                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 745                 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n 
); 
 746                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 748             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 750                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 751                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 752                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 754             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 756                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 757                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 758                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 760             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 762                 gdk_gc_set_ts_origin( m_brushGC
, 
 763                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 764                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 765                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 766                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 770                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 774         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 777             for (i = 0 ; i < n ; i++) 
 779                 gdk_draw_line( m_window, m_penGC, 
 782                                gdkpoints[(i+1)%n].x, 
 783                                gdkpoints[(i+1)%n].y); 
 786             gdk_draw_polygon( m_window
, m_penGC
, FALSE
, gdkpoints
, n 
); 
 794 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 796     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 798     wxCoord xx 
= XLOG2DEV(x
); 
 799     wxCoord yy 
= YLOG2DEV(y
); 
 800     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 801     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 803     // CMB: draw nothing if transformed w or h is 0 
 804     if (ww 
== 0 || hh 
== 0) return; 
 806     // CMB: handle -ve width and/or height 
 807     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 808     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 812         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 814             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 816                 gdk_gc_set_ts_origin( m_textGC
, 
 817                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 818                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 819                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 820                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 822             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 824                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 825                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 826                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 828             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 830                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 831                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 832                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 834             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 836                 gdk_gc_set_ts_origin( m_brushGC
, 
 837                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 838                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 839                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 840                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 844                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 848         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 849             gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 ); 
 852     CalcBoundingBox( x
, y 
); 
 853     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 856 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius 
) 
 858     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 860     if (radius 
< 0.0) radius 
= - radius 
* ((width 
< height
) ? width 
: height
); 
 862     wxCoord xx 
= XLOG2DEV(x
); 
 863     wxCoord yy 
= YLOG2DEV(y
); 
 864     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 865     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 866     wxCoord rr 
= XLOG2DEVREL((wxCoord
)radius
); 
 868     // CMB: handle -ve width and/or height 
 869     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 870     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 872     // CMB: if radius is zero use DrawRectangle() instead to avoid 
 873     // X drawing errors with small radii 
 876         DrawRectangle( x
, y
, width
, height 
); 
 880     // CMB: draw nothing if transformed w or h is 0 
 881     if (ww 
== 0 || hh 
== 0) return; 
 883     // CMB: adjust size if outline is drawn otherwise the result is 
 884     // 1 pixel too wide and high 
 885     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 893         // CMB: ensure dd is not larger than rectangle otherwise we 
 894         // get an hour glass shape 
 896         if (dd 
> ww
) dd 
= ww
; 
 897         if (dd 
> hh
) dd 
= hh
; 
 900         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 902             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 904                 gdk_gc_set_ts_origin( m_textGC
, 
 905                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 906                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 907                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 908                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 909                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 910                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 911                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 912                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 913                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 915             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
 917                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
 918                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 919                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 920                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 921                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 922                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 923                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 924                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 926             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
 928                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
 929                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 930                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 931                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 932                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 933                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 934                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 935                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 937             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 939                 gdk_gc_set_ts_origin( m_brushGC
, 
 940                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 941                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 942                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 943                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 944                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 945                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 946                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 947                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 948                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 952                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 953                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 954                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 955                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 956                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 957                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 961         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 963             gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
, xx
+ww
-rr
, yy 
); 
 964             gdk_draw_line( m_window
, m_penGC
, xx
+rr
+1, yy
+hh
, xx
+ww
-rr
, yy
+hh 
); 
 965             gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
+1, xx
, yy
+hh
-rr 
); 
 966             gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
+1, xx
+ww
, yy
+hh
-rr 
); 
 967             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 968             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 969             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 970             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 974     // this ignores the radius 
 975     CalcBoundingBox( x
, y 
); 
 976     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 979 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 981     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 983     wxCoord xx 
= XLOG2DEV(x
); 
 984     wxCoord yy 
= YLOG2DEV(y
); 
 985     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 986     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 988     // CMB: handle -ve width and/or height 
 989     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 990     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 994         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 996             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 998                 gdk_gc_set_ts_origin( m_textGC
, 
 999                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
1000                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
1001                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1002                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
1004             if (IS_15_PIX_HATCH(m_brush
.GetStyle())) 
1006                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 15, m_deviceOriginY 
% 15 ); 
1007                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1008                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
1010             if (IS_16_PIX_HATCH(m_brush
.GetStyle())) 
1012                 gdk_gc_set_ts_origin( m_brushGC
, m_deviceOriginX 
% 16, m_deviceOriginY 
% 16 ); 
1013                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1014                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
1016             if (m_brush
.GetStyle() == wxSTIPPLE
) 
1018                 gdk_gc_set_ts_origin( m_brushGC
, 
1019                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
1020                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
1021                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1022                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
1026                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1030         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
1031             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
1034     CalcBoundingBox( x
, y 
); 
1035     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
1038 void wxWindowDC::DoDrawIcon( const wxIcon 
&icon
, wxCoord x
, wxCoord y 
) 
1040     // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why 
1041     DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, true ); 
1044 void wxWindowDC::DoDrawBitmap( const wxBitmap 
&bitmap
, 
1045                                wxCoord x
, wxCoord y
, 
1048     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1050     wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") ); 
1052     bool is_mono 
= (bitmap
.GetBitmap() != NULL
); 
1054     // scale/translate size and position 
1055     int xx 
= XLOG2DEV(x
); 
1056     int yy 
= YLOG2DEV(y
); 
1058     int w 
= bitmap
.GetWidth(); 
1059     int h 
= bitmap
.GetHeight(); 
1061     CalcBoundingBox( x
, y 
); 
1062     CalcBoundingBox( x 
+ w
, y 
+ h 
); 
1064     if (!m_window
) return; 
1066     int ww 
= XLOG2DEVREL(w
); 
1067     int hh 
= YLOG2DEVREL(h
); 
1069     // compare to current clipping region 
1070     if (!m_currentClippingRegion
.IsNull()) 
1072         wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1073         tmp
.Intersect( m_currentClippingRegion 
); 
1078     // scale bitmap if required 
1079     wxBitmap use_bitmap 
= bitmap
; 
1080     if ((w 
!= ww
) || (h 
!= hh
)) 
1081         use_bitmap 
= use_bitmap
.Rescale( 0, 0, ww
, hh
, ww
, hh 
); 
1083 #if !GTK_CHECK_VERSION(2,2,0) 
1084     // NB: We can't render pixbufs with GTK+ < 2.2, we need to use pixmaps code. 
1085     //     Pixbufs-based bitmaps with alpha channel don't have a mask, so we 
1086     //     have to call GetPixmap() here -- it converts the pixbuf into pixmap 
1087     //     and also creates the mask as a side-effect: 
1088     use_bitmap
.GetPixmap(); 
1091     // apply mask if any 
1092     GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
1093     if (use_bitmap
.GetMask()) mask 
= use_bitmap
.GetMask()->GetBitmap(); 
1095     GdkBitmap 
*new_mask 
= (GdkBitmap
*) NULL
; 
1097     if (useMask 
&& mask
) 
1099         if (!m_currentClippingRegion
.IsNull()) 
1102             new_mask 
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, 1 ); 
1103             GdkGC 
*gc 
= gdk_gc_new( new_mask 
); 
1105             gdk_gc_set_foreground( gc
, &col 
); 
1106             gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh 
); 
1108             gdk_gc_set_background( gc
, &col 
); 
1110             gdk_gc_set_foreground( gc
, &col 
); 
1111             gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() ); 
1112             gdk_gc_set_clip_origin( gc
, -xx
, -yy 
); 
1113             gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED 
); 
1114             gdk_gc_set_stipple( gc
, mask 
); 
1115             gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh 
); 
1122                 gdk_gc_set_clip_mask( m_textGC
, new_mask 
); 
1124                 gdk_gc_set_clip_mask( m_textGC
, mask 
); 
1125             gdk_gc_set_clip_origin( m_textGC
, xx
, yy 
); 
1130                 gdk_gc_set_clip_mask( m_penGC
, new_mask 
); 
1132                 gdk_gc_set_clip_mask( m_penGC
, mask 
); 
1133             gdk_gc_set_clip_origin( m_penGC
, xx
, yy 
); 
1137     // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 
1138     // drawing a mono-bitmap (XBitmap) we use the current text GC 
1142         GdkPixmap 
*bitmap 
= gdk_pixmap_new( wxGetRootWindow()->window
, ww
, hh
, -1 ); 
1143         GdkGC 
*gc 
= gdk_gc_new( bitmap 
); 
1144         gdk_gc_set_foreground( gc
, m_textForegroundColour
.GetColor() ); 
1145         gdk_gc_set_background( gc
, m_textBackgroundColour
.GetColor() ); 
1146         gdk_wx_draw_bitmap( bitmap
, gc
, use_bitmap
.GetBitmap(), 0, 0, 0, 0, -1, -1 ); 
1148         gdk_draw_drawable( m_window
, m_textGC
, bitmap
, 0, 0, xx
, yy
, -1, -1 ); 
1150         gdk_bitmap_unref( bitmap 
); 
1153         gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 ); 
1158 #if GTK_CHECK_VERSION(2,2,0) 
1159         if (use_bitmap
.HasPixbuf()) 
1161             gdk_draw_pixbuf(m_window
, m_penGC
, 
1162                             use_bitmap
.GetPixbuf(), 
1163                             0, 0, xx
, yy
, -1, -1, 
1164                             GDK_RGB_DITHER_NORMAL
, xx
, yy
); 
1169             gdk_draw_pixmap(m_window
, m_penGC
, 
1170                             use_bitmap
.GetPixmap(), 
1171                             0, 0, xx
, yy
, -1, -1); 
1175     // remove mask again if any 
1176     if (useMask 
&& mask
) 
1180             gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap 
*) NULL 
); 
1181             gdk_gc_set_clip_origin( m_textGC
, 0, 0 ); 
1182             if (!m_currentClippingRegion
.IsNull()) 
1183                 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
1187             gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap 
*) NULL 
); 
1188             gdk_gc_set_clip_origin( m_penGC
, 0, 0 ); 
1189             if (!m_currentClippingRegion
.IsNull()) 
1190                 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
1195         gdk_bitmap_unref( new_mask 
); 
1198 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, 
1199                          wxCoord width
, wxCoord height
, 
1201                          wxCoord xsrc
, wxCoord ysrc
, 
1204                          wxCoord xsrcMask
, wxCoord ysrcMask 
) 
1206     wxCHECK_MSG( Ok(), false, wxT("invalid window dc") ); 
1208     wxCHECK_MSG( source
, false, wxT("invalid source dc") ); 
1210     if (!m_window
) return false; 
1212     // transform the source DC coords to the device ones 
1213     xsrc 
= source
->XLOG2DEV(xsrc
); 
1214     ysrc 
= source
->YLOG2DEV(ysrc
); 
1216     wxClientDC 
*srcDC 
= (wxClientDC
*)source
; 
1217     wxMemoryDC 
*memDC 
= (wxMemoryDC
*)source
; 
1219     bool use_bitmap_method 
= false; 
1220     bool is_mono 
= false; 
1222     // TODO: use the mask origin when drawing transparently 
1223     if (xsrcMask 
== -1 && ysrcMask 
== -1) 
1229     if (srcDC
->m_isMemDC
) 
1231         if (!memDC
->m_selected
.Ok()) return false; 
1233         is_mono 
= (memDC
->m_selected
.GetDepth() == 1); 
1235         // we use the "XCopyArea" way to copy a memory dc into 
1236         // a different window if the memory dc BOTH 
1237         // a) doesn't have any mask or its mask isn't used 
1241         if (useMask 
&& (memDC
->m_selected
.GetMask())) 
1243             // we HAVE TO use the direct way for memory dcs 
1244             // that have mask since the XCopyArea doesn't know 
1246             use_bitmap_method 
= true; 
1250             // we HAVE TO use the direct way for memory dcs 
1251             // that are bitmaps because XCopyArea doesn't cope 
1252             // with different bit depths 
1253             use_bitmap_method 
= true; 
1255         else if ((xsrc 
== 0) && (ysrc 
== 0) && 
1256                  (width 
== memDC
->m_selected
.GetWidth()) && 
1257                  (height 
== memDC
->m_selected
.GetHeight())) 
1259             // we SHOULD use the direct way if all of the bitmap 
1260             // in the memory dc is copied in which case XCopyArea 
1261             // wouldn't be able able to boost performace by reducing 
1262             // the area to be scaled 
1263             use_bitmap_method 
= true; 
1267             use_bitmap_method 
= false; 
1271     CalcBoundingBox( xdest
, ydest 
); 
1272     CalcBoundingBox( xdest 
+ width
, ydest 
+ height 
); 
1274     // scale/translate size and position 
1275     wxCoord xx 
= XLOG2DEV(xdest
); 
1276     wxCoord yy 
= YLOG2DEV(ydest
); 
1278     wxCoord ww 
= XLOG2DEVREL(width
); 
1279     wxCoord hh 
= YLOG2DEVREL(height
); 
1281     // compare to current clipping region 
1282     if (!m_currentClippingRegion
.IsNull()) 
1284         wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1285         tmp
.Intersect( m_currentClippingRegion 
); 
1290     int old_logical_func 
= m_logicalFunction
; 
1291     SetLogicalFunction( logical_func 
); 
1293     if (use_bitmap_method
) 
1295         // scale/translate bitmap size 
1296         wxCoord bm_width 
= memDC
->m_selected
.GetWidth(); 
1297         wxCoord bm_height 
= memDC
->m_selected
.GetHeight(); 
1299         // Get clip coords for the bitmap. If we don't 
1300         // use wxBitmap::Rescale(), which can clip the 
1301         // bitmap, these are the same as the original 
1308         // interpret userscale of src too 
1310         memDC
->GetUserScale(&xsc
,&ysc
); 
1311         bm_width 
= (int) (bm_width 
/ xsc
); 
1312         bm_height 
= (int) (bm_height 
/ ysc
); 
1314         wxCoord bm_ww 
= XLOG2DEVREL( bm_width 
); 
1315         wxCoord bm_hh 
= YLOG2DEVREL( bm_height 
); 
1317         // Scale bitmap if required 
1318         wxBitmap use_bitmap
; 
1319         if ((memDC
->m_selected
.GetWidth()!= bm_ww
) || ( memDC
->m_selected
.GetHeight()!= bm_hh
)) 
1321             // This indicates that the blitting code below will get 
1322             // a clipped bitmap and therefore needs to move the origin 
1324             wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1325             tmp
.Intersect( m_currentClippingRegion 
); 
1326             tmp
.GetBox(cx
,cy
,cw
,ch
); 
1328             // Scale and clipped bitmap 
1329             use_bitmap 
= memDC
->m_selected
.Rescale(cx
-xx
,cy
-yy
,cw
,ch
,bm_ww
,bm_hh
); 
1333             // Don't scale bitmap 
1334             use_bitmap 
= memDC
->m_selected
; 
1337         // apply mask if any 
1338         GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
1339         if (use_bitmap
.GetMask()) mask 
= use_bitmap
.GetMask()->GetBitmap(); 
1341         GdkBitmap 
*new_mask 
= (GdkBitmap
*) NULL
; 
1343         if (useMask 
&& mask
) 
1345             if (!m_currentClippingRegion
.IsNull()) 
1348                 new_mask 
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, 1 ); 
1349                 GdkGC 
*gc 
= gdk_gc_new( new_mask 
); 
1351                 gdk_gc_set_foreground( gc
, &col 
); 
1352                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh 
); 
1354                 gdk_gc_set_background( gc
, &col 
); 
1356                 gdk_gc_set_foreground( gc
, &col 
); 
1357                 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() ); 
1358                 // was: gdk_gc_set_clip_origin( gc, -xx, -yy ); 
1359                 gdk_gc_set_clip_origin( gc
, -cx
, -cy 
); 
1360                 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED 
); 
1361                 gdk_gc_set_stipple( gc
, mask 
); 
1362                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh 
); 
1369                     gdk_gc_set_clip_mask( m_textGC
, new_mask 
); 
1371                     gdk_gc_set_clip_mask( m_textGC
, mask 
); 
1372                 // was: gdk_gc_set_clip_origin( m_textGC, xx, yy ); 
1373                 gdk_gc_set_clip_origin( m_textGC
, cx
, cy 
); 
1378                     gdk_gc_set_clip_mask( m_penGC
, new_mask 
); 
1380                     gdk_gc_set_clip_mask( m_penGC
, mask 
); 
1381                 // was: gdk_gc_set_clip_origin( m_penGC, xx, yy ); 
1382                 gdk_gc_set_clip_origin( m_penGC
, cx
, cy 
); 
1386         // Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 
1387         // drawing a mono-bitmap (XBitmap) we use the current text GC 
1392             GdkPixmap 
*bitmap 
= gdk_pixmap_new( wxGetRootWindow()->window
, bm_ww
, bm_hh
, -1 ); 
1393             GdkGC 
*gc 
= gdk_gc_new( bitmap 
); 
1394             gdk_gc_set_foreground( gc
, m_textForegroundColour
.GetColor() ); 
1395             gdk_gc_set_background( gc
, m_textBackgroundColour
.GetColor() ); 
1396             gdk_wx_draw_bitmap( bitmap
, gc
, use_bitmap
.GetBitmap(), 0, 0, 0, 0, -1, -1 ); 
1398             gdk_draw_drawable( m_window
, m_textGC
, bitmap
, xsrc
, ysrc
, cx
, cy
, cw
, ch 
); 
1400             gdk_bitmap_unref( bitmap 
); 
1403             // was: gdk_wx_draw_bitmap( m_window, m_textGC, use_bitmap.GetBitmap(), xsrc, ysrc, xx, yy, ww, hh ); 
1404             gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, cx
, cy
, cw
, ch 
); 
1409             // was: gdk_draw_pixmap( m_window, m_penGC, use_bitmap.GetPixmap(), xsrc, ysrc, xx, yy, ww, hh ); 
1410             gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, cx
, cy
, cw
, ch 
); 
1413         // remove mask again if any 
1414         if (useMask 
&& mask
) 
1418                 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap 
*) NULL 
); 
1419                 gdk_gc_set_clip_origin( m_textGC
, 0, 0 ); 
1420                 if (!m_currentClippingRegion
.IsNull()) 
1421                     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
1425                 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap 
*) NULL 
); 
1426                 gdk_gc_set_clip_origin( m_penGC
, 0, 0 ); 
1427                 if (!m_currentClippingRegion
.IsNull()) 
1428                     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
1433             gdk_bitmap_unref( new_mask 
); 
1435     else // use_bitmap_method 
1437         if ((width 
!= ww
) || (height 
!= hh
)) 
1440             wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1441             tmp
.Intersect( m_currentClippingRegion 
); 
1442             wxCoord cx
,cy
,cw
,ch
; 
1443             tmp
.GetBox(cx
,cy
,cw
,ch
); 
1446             wxBitmap bitmap 
= memDC
->m_selected
.Rescale( cx
-xx
, cy
-yy
, cw
, ch
, ww
, hh 
); 
1448             // draw scaled bitmap 
1449             // was: gdk_draw_pixmap( m_window, m_penGC, bitmap.GetPixmap(), 0, 0, xx, yy, -1, -1 ); 
1450             gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, cx
, cy
, -1, -1 ); 
1454             // No scaling and not a memory dc with a mask either 
1456             // copy including child window contents 
1457             gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS 
); 
1458             gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
, 
1460                                   xsrc
, ysrc
, width
, height 
); 
1461             gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN 
); 
1465     SetLogicalFunction( old_logical_func 
); 
1470 void wxWindowDC::DoDrawText( const wxString 
&text
, wxCoord x
, wxCoord y 
) 
1472     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1474     if (!m_window
) return; 
1476     if (text
.empty()) return; 
1479     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1481     wxCHECK_RET( font
, wxT("invalid font") ); 
1488     wxCHECK_RET( m_context
, wxT("no Pango context") ); 
1489     wxCHECK_RET( m_layout
, wxT("no Pango layout") ); 
1490     wxCHECK_RET( m_fontdesc
, wxT("no Pango font description") ); 
1492     bool underlined 
= m_font
.Ok() && m_font
.GetUnderlined(); 
1495     const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( text 
); 
1497     const wxWCharBuffer wdata 
= wxConvLocal
.cMB2WC( text 
); 
1500     const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( wdata 
); 
1502     size_t datalen 
= strlen((const char*)data
); 
1503     pango_layout_set_text( m_layout
, (const char*) data
, datalen
); 
1507         PangoAttrList 
*attrs 
= pango_attr_list_new(); 
1508         PangoAttribute 
*a 
= pango_attr_underline_new(PANGO_UNDERLINE_SINGLE
); 
1510         a
->end_index 
= datalen
; 
1511         pango_attr_list_insert(attrs
, a
); 
1512         pango_layout_set_attributes(m_layout
, attrs
); 
1513         pango_attr_list_unref(attrs
); 
1518     if (fabs(m_scaleY 
- 1.0) > 0.00001) 
1520          // If there is a user or actually any scale applied to 
1521          // the device context, scale the font. 
1523          // scale font description 
1524          gint oldSize 
= pango_font_description_get_size( m_fontdesc 
); 
1525          double size 
= oldSize
; 
1526          size 
= size 
* m_scaleY
; 
1527          pango_font_description_set_size( m_fontdesc
, (gint
)size 
); 
1529          // actually apply scaled font 
1530          pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1532          pango_layout_get_pixel_size( m_layout
, &w
, &h 
); 
1533          if ( m_backgroundMode 
== wxSOLID 
) 
1535             gdk_gc_set_foreground(m_textGC
, m_textBackgroundColour
.GetColor()); 
1536             gdk_draw_rectangle(m_window
, m_textGC
, TRUE
, x
, y
, w
, h
); 
1537             gdk_gc_set_foreground(m_textGC
, m_textForegroundColour
.GetColor()); 
1541          gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout 
); 
1543          // reset unscaled size 
1544          pango_font_description_set_size( m_fontdesc
, oldSize 
); 
1546          // actually apply unscaled font 
1547          pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1551         pango_layout_get_pixel_size( m_layout
, &w
, &h 
); 
1552         if ( m_backgroundMode 
== wxSOLID 
) 
1554             gdk_gc_set_foreground(m_textGC
, m_textBackgroundColour
.GetColor()); 
1555             gdk_draw_rectangle(m_window
, m_textGC
, TRUE
, x
, y
, w
, h
); 
1556             gdk_gc_set_foreground(m_textGC
, m_textForegroundColour
.GetColor()); 
1559         gdk_draw_layout( m_window
, m_textGC
, x
, y
, m_layout 
); 
1564         // undo underline attributes setting: 
1565         pango_layout_set_attributes(m_layout
, NULL
); 
1572     wxCoord width 
= gdk_string_width( font
, text
.mbc_str() ); 
1573     wxCoord height 
= font
->ascent 
+ font
->descent
; 
1575     if ( m_backgroundMode 
== wxSOLID 
) 
1577         gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() ); 
1578         gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height 
); 
1579         gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
1581     gdk_draw_string( m_window
, font
, m_textGC
, x
, y 
+ font
->ascent
, text
.mbc_str() ); 
1583     /* CMB 17/7/98: simple underline: ignores scaling and underlying 
1584        X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS 
1585        properties (see wxXt implementation) */ 
1586     if (m_font
.GetUnderlined()) 
1588         wxCoord ul_y 
= y 
+ font
->ascent
; 
1589         if (font
->descent 
> 0) ul_y
++; 
1590         gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x 
+ width
, ul_y
); 
1592 #endif // GTK+ 2.0/1.x 
1594     width 
= wxCoord(width 
/ m_scaleX
); 
1595     height 
= wxCoord(height 
/ m_scaleY
); 
1596     CalcBoundingBox (x 
+ width
, y 
+ height
); 
1597     CalcBoundingBox (x
, y
); 
1601 // TODO: There is an example of rotating text with GTK2 that would probably be 
1602 // a better approach here: 
1603 //           http://www.daa.com.au/pipermail/pygtk/2003-April/005052.html 
1605 void wxWindowDC::DoDrawRotatedText( const wxString 
&text
, wxCoord x
, wxCoord y
, double angle 
) 
1609         DrawText(text
, x
, y
); 
1613     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1615     if (!m_window
) return; 
1621     // implement later without GdkFont for GTK 2.0 
1622     GetTextExtent(text
, &w
, &h
, NULL
,NULL
, &m_font
); 
1625     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1627     wxCHECK_RET( font
, wxT("invalid font") ); 
1629     // the size of the text 
1630     w 
= gdk_string_width( font
, text
.mbc_str() ); 
1631     h 
= font
->ascent 
+ font
->descent
; 
1633     // draw the string normally 
1636     dc
.SelectObject(src
); 
1637     dc
.SetFont(GetFont()); 
1638     dc
.SetBackground(*wxBLACK_BRUSH
); 
1639     dc
.SetBrush(*wxBLACK_BRUSH
); 
1641     dc
.SetTextForeground( *wxWHITE 
); 
1642     dc
.DrawText(text
, 0, 0); 
1643     dc
.SelectObject(wxNullBitmap
); 
1645     // Calculate the size of the rotated bounding box. 
1646     double rad 
= DegToRad(angle
); 
1647     double dx 
= cos(rad
), 
1650     // the rectngle vertices are counted clockwise with the first one being at 
1651     // (0, 0) (or, rather, at (x, y)) 
1653            y2 
= -w
*dy
;      // y axis points to the bottom, hence minus 
1656     double x3 
= x4 
+ x2
, 
1660     wxCoord maxX 
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5), 
1661             maxY 
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5), 
1662             minX 
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5), 
1663             minY 
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5); 
1666     wxImage image 
= src
.ConvertToImage(); 
1668     image
.ConvertColourToAlpha( m_textForegroundColour
.Red(), 
1669                                 m_textForegroundColour
.Green(), 
1670                                 m_textForegroundColour
.Blue() ); 
1671     image 
= image
.Rotate( rad
, wxPoint(0,0) ); 
1673     int i_angle 
= (int) angle
; 
1674     i_angle 
= i_angle 
% 360; 
1678     if ((i_angle 
>= 90.0) && (i_angle 
< 270.0)) 
1679         xoffset 
= image
.GetWidth(); 
1681     if ((i_angle 
>= 0.0) && (i_angle 
< 180.0)) 
1682         yoffset 
= image
.GetHeight(); 
1684     if ((i_angle 
>= 0) && (i_angle 
< 90)) 
1685         yoffset 
-= (int)( cos(rad
)*h 
); 
1686     if ((i_angle 
>= 90) && (i_angle 
< 180)) 
1687         xoffset 
-= (int)( sin(rad
)*h 
); 
1688     if ((i_angle 
>= 180) && (i_angle 
< 270)) 
1689         yoffset 
-= (int)( cos(rad
)*h 
); 
1690     if ((i_angle 
>= 270) && (i_angle 
< 360)) 
1691         xoffset 
-= (int)( sin(rad
)*h 
); 
1693     int i_x 
= x 
- xoffset
; 
1694     int i_y 
= y 
- yoffset
; 
1697     DoDrawBitmap( src
, i_x
, i_y
, true ); 
1700     // it would be better to draw with non underlined font and draw the line 
1701     // manually here (it would be more straight...) 
1703     if ( m_font
.GetUnderlined() ) 
1705         gdk_draw_line( m_window
, m_textGC
, 
1706                        XLOG2DEV(x 
+ x4
), YLOG2DEV(y 
+ y4 
+ font
->descent
), 
1707                        XLOG2DEV(x 
+ x3
), YLOG2DEV(y 
+ y3 
+ font
->descent
)); 
1711     // update the bounding box 
1712     CalcBoundingBox(x 
+ minX
, y 
+ minY
); 
1713     CalcBoundingBox(x 
+ maxX
, y 
+ maxY
); 
1716 void wxWindowDC::DoGetTextExtent(const wxString 
&string
, 
1717                                  wxCoord 
*width
, wxCoord 
*height
, 
1718                                  wxCoord 
*descent
, wxCoord 
*externalLeading
, 
1719                                  wxFont 
*theFont
) const 
1727     if ( externalLeading 
) 
1728         *externalLeading 
= 0; 
1736     // Set new font description 
1738         pango_layout_set_font_description( m_layout
, theFont
->GetNativeFontInfo()->description 
); 
1740     // Set layout's text 
1742     const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( string 
); 
1743     const char *dataUTF8 
= (const char *)data
; 
1745     const wxWCharBuffer wdata 
= wxConvLocal
.cMB2WC( string 
); 
1748         if (width
) (*width
) = 0; 
1749         if (height
) (*height
) = 0; 
1752     const wxCharBuffer data 
= wxConvUTF8
.cWC2MB( wdata 
); 
1753     const char *dataUTF8 
= (const char *)data
; 
1758         // hardly ideal, but what else can we do if conversion failed? 
1762     pango_layout_set_text( m_layout
, dataUTF8
, strlen(dataUTF8
) ); 
1765     pango_layout_get_pixel_size( m_layout
, &w
, &h 
); 
1768         *width 
= (wxCoord
) w
; 
1770         *height 
= (wxCoord
) h
; 
1773         PangoLayoutIter 
*iter 
= pango_layout_get_iter(m_layout
); 
1774         int baseline 
= pango_layout_iter_get_baseline(iter
); 
1775         pango_layout_iter_free(iter
); 
1776         *descent 
= h 
- PANGO_PIXELS(baseline
); 
1779     // Reset old font description 
1781         pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1783     wxFont fontToUse 
= m_font
; 
1785         fontToUse 
= *theFont
; 
1787     GdkFont 
*font 
= fontToUse
.GetInternalFont( m_scaleY 
); 
1792         *width 
= wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
); 
1794         *height 
= wxCoord((font
->ascent 
+ font
->descent
) / m_scaleY
); 
1796         *descent 
= wxCoord(font
->descent 
/ m_scaleY
); 
1800 wxCoord 
wxWindowDC::GetCharWidth() const 
1803     pango_layout_set_text( m_layout
, "H", 1 ); 
1805     pango_layout_get_pixel_size( m_layout
, &w
, &h 
); 
1808     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1809     wxCHECK_MSG( font
, -1, wxT("invalid font") ); 
1811     return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
); 
1815 wxCoord 
wxWindowDC::GetCharHeight() const 
1818     pango_layout_set_text( m_layout
, "H", 1 ); 
1820     pango_layout_get_pixel_size( m_layout
, &w
, &h 
); 
1823     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1824     wxCHECK_MSG( font
, -1, wxT("invalid font") ); 
1826     return wxCoord((font
->ascent 
+ font
->descent
) / m_scaleY
); 
1830 void wxWindowDC::Clear() 
1832     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1834     if (!m_window
) return; 
1836     // VZ: the code below results in infinite recursion and crashes when 
1837     //     dc.Clear() is done from OnPaint() so I disable it for now. 
1838     //     I don't know what the correct fix is but Clear() surely should not 
1839     //     reenter OnPaint()! 
1841     /* - we either are a memory dc or have a window as the 
1842        owner. anything else shouldn't happen. 
1843        - we don't use gdk_window_clear() as we don't set 
1844        the window's background colour anymore. it is too 
1845        much pain to keep the DC's and the window's back- 
1846        ground colour in synch. */ 
1857         GetSize( &width
, &height 
); 
1858         gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height 
); 
1863     GetSize( &width
, &height 
); 
1864     gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height 
); 
1868 void wxWindowDC::SetFont( const wxFont 
&font 
) 
1876             pango_font_description_free( m_fontdesc 
); 
1878         m_fontdesc 
= pango_font_description_copy( m_font
.GetNativeFontInfo()->description 
); 
1883             PangoContext 
*oldContext 
= m_context
; 
1885             // We might want to use the X11 context for faster 
1886             // rendering on screen 
1887             if (m_font
.GetNoAntiAliasing()) 
1888                 m_context 
= m_owner
->GtkGetPangoX11Context(); 
1890                 m_context 
= m_owner
->GtkGetPangoDefaultContext(); 
1892             // If we switch back/forth between different contexts 
1893             // we also have to create a new layout. I think so, 
1894             // at least, and it doesn't hurt to do it. 
1895             if (oldContext 
!= m_context
) 
1898                     g_object_unref( G_OBJECT( m_layout 
) ); 
1900                 m_layout 
= pango_layout_new( m_context 
); 
1904         pango_layout_set_font_description( m_layout
, m_fontdesc 
); 
1909 void wxWindowDC::SetPen( const wxPen 
&pen 
) 
1911     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1913     if (m_pen 
== pen
) return; 
1917     if (!m_pen
.Ok()) return; 
1919     if (!m_window
) return; 
1921     gint width 
= m_pen
.GetWidth(); 
1924         // CMB: if width is non-zero scale it with the dc 
1929         // X doesn't allow different width in x and y and so we take 
1932                    ( fabs((double) XLOG2DEVREL(width
)) + 
1933                      fabs((double) YLOG2DEVREL(width
)) ) / 2.0; 
1937             // width can't be 0 or an internal GTK error occurs inside 
1938             // gdk_gc_set_dashes() below 
1943     static const wxGTKDash dotted
[] = {1, 1}; 
1944     static const wxGTKDash short_dashed
[] = {2, 2}; 
1945     static const wxGTKDash wxCoord_dashed
[] = {2, 4}; 
1946     static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3}; 
1948     // We express dash pattern in pen width unit, so we are 
1949     // independent of zoom factor and so on... 
1951     const wxGTKDash 
*req_dash
; 
1953     GdkLineStyle lineStyle 
= GDK_LINE_SOLID
; 
1954     switch (m_pen
.GetStyle()) 
1958             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1959             req_nb_dash 
= m_pen
.GetDashCount(); 
1960             req_dash 
= (wxGTKDash
*)m_pen
.GetDash(); 
1965             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1972             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1974             req_dash 
= wxCoord_dashed
; 
1979             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1981             req_dash 
= short_dashed
; 
1986 //            lineStyle = GDK_LINE_DOUBLE_DASH; 
1987             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1989             req_dash 
= dotted_dashed
; 
1994         case wxSTIPPLE_MASK_OPAQUE
: 
1999             lineStyle 
= GDK_LINE_SOLID
; 
2000             req_dash 
= (wxGTKDash
*)NULL
; 
2006 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1) 
2007     if (req_dash 
&& req_nb_dash
) 
2009         wxGTKDash 
*real_req_dash 
= new wxGTKDash
[req_nb_dash
]; 
2012             for (int i 
= 0; i 
< req_nb_dash
; i
++) 
2013                 real_req_dash
[i
] = req_dash
[i
] * width
; 
2014             gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash 
); 
2015             delete[] real_req_dash
; 
2019             // No Memory. We use non-scaled dash pattern... 
2020             gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash 
); 
2023 #endif // GTK+ > 1.0 
2025     GdkCapStyle capStyle 
= GDK_CAP_ROUND
; 
2026     switch (m_pen
.GetCap()) 
2028         case wxCAP_PROJECTING
: { capStyle 
= GDK_CAP_PROJECTING
; break; } 
2029         case wxCAP_BUTT
:       { capStyle 
= GDK_CAP_BUTT
;       break; } 
2036                 capStyle 
= GDK_CAP_NOT_LAST
; 
2040                 capStyle 
= GDK_CAP_ROUND
; 
2046     GdkJoinStyle joinStyle 
= GDK_JOIN_ROUND
; 
2047     switch (m_pen
.GetJoin()) 
2049         case wxJOIN_BEVEL
: { joinStyle 
= GDK_JOIN_BEVEL
; break; } 
2050         case wxJOIN_MITER
: { joinStyle 
= GDK_JOIN_MITER
; break; } 
2052         default:           { joinStyle 
= GDK_JOIN_ROUND
; break; } 
2055     gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle 
); 
2057     m_pen
.GetColour().CalcPixel( m_cmap 
); 
2058     gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() ); 
2061 void wxWindowDC::SetBrush( const wxBrush 
&brush 
) 
2063     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2065     if (m_brush 
== brush
) return; 
2069     if (!m_brush
.Ok()) return; 
2071     if (!m_window
) return; 
2073     m_brush
.GetColour().CalcPixel( m_cmap 
); 
2074     gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() ); 
2076     gdk_gc_set_fill( m_brushGC
, GDK_SOLID 
); 
2078     if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok())) 
2080         if (m_brush
.GetStipple()->GetPixmap()) 
2082             gdk_gc_set_fill( m_brushGC
, GDK_TILED 
); 
2083             gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() ); 
2087             gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED 
); 
2088             gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() ); 
2092     if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
2094         gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
); 
2095         gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() ); 
2098     if (m_brush
.IsHatch()) 
2100         gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED 
); 
2101         int num 
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
; 
2102         gdk_gc_set_stipple( m_brushGC
, hatches
[num
] ); 
2106 void wxWindowDC::SetBackground( const wxBrush 
&brush 
) 
2108    /* CMB 21/7/98: Added SetBackground. Sets background brush 
2109     * for Clear() and bg colour for shapes filled with cross-hatch brush */ 
2111     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2113     if (m_backgroundBrush 
== brush
) return; 
2115     m_backgroundBrush 
= brush
; 
2117     if (!m_backgroundBrush
.Ok()) return; 
2119     if (!m_window
) return; 
2121     m_backgroundBrush
.GetColour().CalcPixel( m_cmap 
); 
2122     gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() ); 
2123     gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() ); 
2124     gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() ); 
2125     gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() ); 
2127     gdk_gc_set_fill( m_bgGC
, GDK_SOLID 
); 
2129     if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok())) 
2131         if (m_backgroundBrush
.GetStipple()->GetPixmap()) 
2133             gdk_gc_set_fill( m_bgGC
, GDK_TILED 
); 
2134             gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() ); 
2138             gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED 
); 
2139             gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() ); 
2143     if (m_backgroundBrush
.IsHatch()) 
2145         gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED 
); 
2146         int num 
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
; 
2147         gdk_gc_set_stipple( m_bgGC
, hatches
[num
] ); 
2151 void wxWindowDC::SetLogicalFunction( int function 
) 
2153     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2155     if (m_logicalFunction 
== function
) 
2158     // VZ: shouldn't this be a CHECK? 
2165         case wxXOR
:          mode 
= GDK_XOR
;           break; 
2166         case wxINVERT
:       mode 
= GDK_INVERT
;        break; 
2167 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1) 
2168         case wxOR_REVERSE
:   mode 
= GDK_OR_REVERSE
;    break; 
2169         case wxAND_REVERSE
:  mode 
= GDK_AND_REVERSE
;   break; 
2170         case wxCLEAR
:        mode 
= GDK_CLEAR
;         break; 
2171         case wxSET
:          mode 
= GDK_SET
;           break; 
2172         case wxOR_INVERT
:    mode 
= GDK_OR_INVERT
;     break; 
2173         case wxAND
:          mode 
= GDK_AND
;           break; 
2174         case wxOR
:           mode 
= GDK_OR
;            break; 
2175         case wxEQUIV
:        mode 
= GDK_EQUIV
;         break; 
2176         case wxNAND
:         mode 
= GDK_NAND
;          break; 
2177         case wxAND_INVERT
:   mode 
= GDK_AND_INVERT
;    break; 
2178         case wxCOPY
:         mode 
= GDK_COPY
;          break; 
2179         case wxNO_OP
:        mode 
= GDK_NOOP
;          break; 
2180         case wxSRC_INVERT
:   mode 
= GDK_COPY_INVERT
;   break; 
2182         // unsupported by GTK 
2183         case wxNOR
:          mode 
= GDK_COPY
;          break; 
2184 #endif // GTK+ > 1.0 
2186            wxFAIL_MSG( wxT("unsupported logical function") ); 
2190     m_logicalFunction 
= function
; 
2192     gdk_gc_set_function( m_penGC
, mode 
); 
2193     gdk_gc_set_function( m_brushGC
, mode 
); 
2195     // to stay compatible with wxMSW, we don't apply ROPs to the text 
2196     // operations (i.e. DrawText/DrawRotatedText). 
2197     // True, but mono-bitmaps use the m_textGC and they use ROPs as well. 
2198     gdk_gc_set_function( m_textGC
, mode 
); 
2201 void wxWindowDC::SetTextForeground( const wxColour 
&col 
) 
2203     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2205     // don't set m_textForegroundColour to an invalid colour as we'd crash 
2206     // later then (we use m_textForegroundColour.GetColor() without checking 
2208     if ( !col
.Ok() || (m_textForegroundColour 
== col
) ) 
2211     m_textForegroundColour 
= col
; 
2215         m_textForegroundColour
.CalcPixel( m_cmap 
); 
2216         gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
2220 void wxWindowDC::SetTextBackground( const wxColour 
&col 
) 
2222     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2225     if ( !col
.Ok() || (m_textBackgroundColour 
== col
) ) 
2228     m_textBackgroundColour 
= col
; 
2232         m_textBackgroundColour
.CalcPixel( m_cmap 
); 
2233         gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() ); 
2237 void wxWindowDC::SetBackgroundMode( int mode 
) 
2239     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2241     m_backgroundMode 
= mode
; 
2243     if (!m_window
) return; 
2245     // CMB 21/7/98: fill style of cross-hatch brushes is affected by 
2246     // transparent/solid background mode 
2248     if (m_brush
.GetStyle() != wxSOLID 
&& m_brush
.GetStyle() != wxTRANSPARENT
) 
2250         gdk_gc_set_fill( m_brushGC
, 
2251           (m_backgroundMode 
== wxTRANSPARENT
) ? GDK_STIPPLED 
: GDK_OPAQUE_STIPPLED
); 
2255 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) ) 
2257     wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") ); 
2260 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
2262     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2264     if (!m_window
) return; 
2267     rect
.x 
= XLOG2DEV(x
); 
2268     rect
.y 
= YLOG2DEV(y
); 
2269     rect
.width 
= XLOG2DEVREL(width
); 
2270     rect
.height 
= YLOG2DEVREL(height
); 
2272     if (!m_currentClippingRegion
.IsNull()) 
2273         m_currentClippingRegion
.Intersect( rect 
); 
2275         m_currentClippingRegion
.Union( rect 
); 
2277 #if USE_PAINT_REGION 
2278     if (!m_paintClippingRegion
.IsNull()) 
2279         m_currentClippingRegion
.Intersect( m_paintClippingRegion 
); 
2282     wxCoord xx
, yy
, ww
, hh
; 
2283     m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh 
); 
2284     wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
2286     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
2287     gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
2288     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
2289     gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
2292 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion 
®ion  
) 
2294     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2298         DestroyClippingRegion(); 
2302     if (!m_window
) return; 
2304     if (!m_currentClippingRegion
.IsNull()) 
2305         m_currentClippingRegion
.Intersect( region 
); 
2307         m_currentClippingRegion
.Union( region 
); 
2309 #if USE_PAINT_REGION 
2310     if (!m_paintClippingRegion
.IsNull()) 
2311         m_currentClippingRegion
.Intersect( m_paintClippingRegion 
); 
2314     wxCoord xx
, yy
, ww
, hh
; 
2315     m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh 
); 
2316     wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
2318     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
2319     gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
2320     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
2321     gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
2324 void wxWindowDC::DestroyClippingRegion() 
2326     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2328     wxDC::DestroyClippingRegion(); 
2330     m_currentClippingRegion
.Clear(); 
2332 #if USE_PAINT_REGION 
2333     if (!m_paintClippingRegion
.IsEmpty()) 
2334         m_currentClippingRegion
.Union( m_paintClippingRegion 
); 
2337     if (!m_window
) return; 
2339     if (m_currentClippingRegion
.IsEmpty()) 
2341         gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle 
*) NULL 
); 
2342         gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle 
*) NULL 
); 
2343         gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle 
*) NULL 
); 
2344         gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle 
*) NULL 
); 
2348         gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
2349         gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
2350         gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
2351         gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
2355 void wxWindowDC::Destroy() 
2357     if (m_penGC
) wxFreePoolGC( m_penGC 
); 
2358     m_penGC 
= (GdkGC
*) NULL
; 
2359     if (m_brushGC
) wxFreePoolGC( m_brushGC 
); 
2360     m_brushGC 
= (GdkGC
*) NULL
; 
2361     if (m_textGC
) wxFreePoolGC( m_textGC 
); 
2362     m_textGC 
= (GdkGC
*) NULL
; 
2363     if (m_bgGC
) wxFreePoolGC( m_bgGC 
); 
2364     m_bgGC 
= (GdkGC
*) NULL
; 
2367 void wxWindowDC::ComputeScaleAndOrigin() 
2369     /* CMB: copy scale to see if it changes */ 
2370     double origScaleX 
= m_scaleX
; 
2371     double origScaleY 
= m_scaleY
; 
2373     wxDC::ComputeScaleAndOrigin(); 
2375     /* CMB: if scale has changed call SetPen to recalulate the line width */ 
2376     if ((m_scaleX 
!= origScaleX 
|| m_scaleY 
!= origScaleY
) && 
2379       /* this is a bit artificial, but we need to force wxDC to think 
2380          the pen has changed */ 
2387 // Resolution in pixels per logical inch 
2388 wxSize 
wxWindowDC::GetPPI() const 
2390     return wxSize( (int) (m_mm_to_pix_x 
* 25.4 + 0.5), (int) (m_mm_to_pix_y 
* 25.4 + 0.5)); 
2393 int wxWindowDC::GetDepth() const 
2395     wxFAIL_MSG(wxT("not implemented")); 
2401 //----------------------------------------------------------------------------- 
2403 //----------------------------------------------------------------------------- 
2405 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxClientDC
) 
2407 // Limit the paint region to the window size. Sometimes 
2408 // the paint region is too big, and this risks X11 errors 
2409 static void wxLimitRegionToSize(wxRegion
& region
, const wxSize
& sz
) 
2411     wxRect originalRect 
= region
.GetBox(); 
2412     wxRect 
rect(originalRect
); 
2413     if (rect
.width 
+ rect
.x 
> sz
.x
) 
2414         rect
.width 
= sz
.x 
- rect
.x
; 
2415     if (rect
.height 
+ rect
.y 
> sz
.y
) 
2416         rect
.height 
= sz
.y 
- rect
.y
; 
2417     if (rect 
!= originalRect
) 
2419         region 
= wxRegion(rect
); 
2420         wxLogTrace(wxT("painting"), wxT("Limiting region from %d, %d, %d, %d to %d, %d, %d, %d\n"), 
2421                    originalRect
.x
, originalRect
.y
, originalRect
.width
, originalRect
.height
, 
2422                    rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
2426 wxPaintDC::wxPaintDC( wxWindow 
*win 
) 
2429 #if USE_PAINT_REGION 
2430     if (!win
->m_clipPaintRegion
) 
2433     wxSize sz 
= win
->GetSize(); 
2434     m_paintClippingRegion 
= win
->GetUpdateRegion(); 
2435     wxLimitRegionToSize(m_paintClippingRegion
, sz
); 
2437     GdkRegion 
*region 
= m_paintClippingRegion
.GetRegion(); 
2440         m_currentClippingRegion
.Union( m_paintClippingRegion 
); 
2441         wxLimitRegionToSize(m_currentClippingRegion
, sz
); 
2443         if (sz
.x 
<= 0 || sz
.y 
<= 0) 
2446         gdk_gc_set_clip_region( m_penGC
, region 
); 
2447         gdk_gc_set_clip_region( m_brushGC
, region 
); 
2448         gdk_gc_set_clip_region( m_textGC
, region 
); 
2449         gdk_gc_set_clip_region( m_bgGC
, region 
); 
2451 #endif // USE_PAINT_REGION 
2454 //----------------------------------------------------------------------------- 
2456 //----------------------------------------------------------------------------- 
2458 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
) 
2460 wxClientDC::wxClientDC( wxWindow 
*win 
) 
2463     wxCHECK_RET( win
, _T("NULL window in wxClientDC::wxClientDC") ); 
2465 #ifdef __WXUNIVERSAL__ 
2466     wxPoint ptOrigin 
= win
->GetClientAreaOrigin(); 
2467     SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
); 
2468     wxSize size 
= win
->GetClientSize(); 
2469     SetClippingRegion(wxPoint(0, 0), size
); 
2470 #endif // __WXUNIVERSAL__ 
2473 void wxClientDC::DoGetSize(int *width
, int *height
) const 
2475     wxCHECK_RET( m_owner
, _T("GetSize() doesn't work without window") ); 
2477     m_owner
->GetClientSize( width
, height 
); 
2480 // ---------------------------------------------------------------------------- 
2482 // ---------------------------------------------------------------------------- 
2484 class wxDCModule 
: public wxModule
 
2491     DECLARE_DYNAMIC_CLASS(wxDCModule
) 
2494 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
) 
2496 bool wxDCModule::OnInit() 
2502 void wxDCModule::OnExit()