1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        gtk/dcclient.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling, Markus Holzem, Chris Breeze 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  11 #pragma implementation "dcclient.h" 
  14 #include "wx/dcclient.h" 
  15 #include "wx/dcmemory.h" 
  17 #include "wx/module.h" 
  19 #include "wx/gtk/win_gtk.h" 
  21 #include <math.h>               // for floating-point functions 
  25 #include <gdk/gdkprivate.h> 
  28 //----------------------------------------------------------------------------- 
  30 //----------------------------------------------------------------------------- 
  32 #define USE_PAINT_REGION 1 
  34 //----------------------------------------------------------------------------- 
  36 //----------------------------------------------------------------------------- 
  46 static GdkPixmap  
*hatches
[num_hatches
]; 
  47 static GdkPixmap 
**hatch_bitmap 
= (GdkPixmap 
**) NULL
; 
  49 extern GtkWidget 
*wxRootWindow
; 
  51 //----------------------------------------------------------------------------- 
  53 //----------------------------------------------------------------------------- 
  55 const double RAD2DEG  
= 180.0 / M_PI
; 
  57 // ---------------------------------------------------------------------------- 
  59 // ---------------------------------------------------------------------------- 
  61 static inline double dmax(double a
, double b
) { return a 
> b 
? a 
: b
; } 
  62 static inline double dmin(double a
, double b
) { return a 
< b 
? a 
: b
; } 
  64 static inline double DegToRad(double deg
) { return (deg 
* M_PI
) / 180.0; } 
  66 //----------------------------------------------------------------------------- 
  67 // temporary implementation of the missing GDK function 
  68 //----------------------------------------------------------------------------- 
  70 #include "gdk/gdkprivate.h" 
  72 void gdk_wx_draw_bitmap     (GdkDrawable  
*drawable
, 
  82     gint src_width
, src_height
; 
  84     GdkWindowPrivate 
*drawable_private
; 
  85     GdkWindowPrivate 
*src_private
; 
  86     GdkGCPrivate 
*gc_private
; 
  89     g_return_if_fail (drawable 
!= NULL
); 
  90     g_return_if_fail (src 
!= NULL
); 
  91     g_return_if_fail (gc 
!= NULL
); 
  94     if (GDK_WINDOW_DESTROYED(drawable
) || GDK_WINDOW_DESTROYED(src
)) 
  97     gdk_drawable_get_size(src
, &src_width
, &src_height
); 
  99     drawable_private 
= (GdkWindowPrivate
*) drawable
; 
 100     src_private 
= (GdkWindowPrivate
*) src
; 
 101     if (drawable_private
->destroyed 
|| src_private
->destroyed
) 
 104     src_width 
= src_private
->width
; 
 105     src_height 
= src_private
->height
; 
 107     gc_private 
= (GdkGCPrivate
*) gc
; 
 110     if (width 
== -1) width 
= src_width
; 
 111     if (height 
== -1) height 
= src_height
; 
 114     XCopyPlane( GDK_WINDOW_XDISPLAY(drawable
), 
 116                 GDK_WINDOW_XID(drawable
), 
 123     XCopyPlane( drawable_private
->xdisplay
, 
 124                 src_private
->xwindow
, 
 125                 drawable_private
->xwindow
, 
 134 //----------------------------------------------------------------------------- 
 135 // Implement Pool of Graphic contexts. Creating them takes too much time. 
 136 //----------------------------------------------------------------------------- 
 138 #define GC_POOL_SIZE 200 
 164 static wxGC wxGCPool
[GC_POOL_SIZE
]; 
 166 static void wxInitGCPool() 
 168     memset( wxGCPool
, 0, GC_POOL_SIZE
*sizeof(wxGC
) ); 
 171 static void wxCleanUpGCPool() 
 173     for (int i 
= 0; i 
< GC_POOL_SIZE
; i
++) 
 175         if (wxGCPool
[i
].m_gc
) 
 176             gdk_gc_unref( wxGCPool
[i
].m_gc 
); 
 180 static GdkGC
* wxGetPoolGC( GdkWindow 
*window
, wxPoolGCType type 
) 
 182     for (int i 
= 0; i 
< GC_POOL_SIZE
; i
++) 
 184         if (!wxGCPool
[i
].m_gc
) 
 186             wxGCPool
[i
].m_gc 
= gdk_gc_new( window 
); 
 187             gdk_gc_set_exposures( wxGCPool
[i
].m_gc
, FALSE 
); 
 188             wxGCPool
[i
].m_type 
= type
; 
 189             wxGCPool
[i
].m_used 
= FALSE
; 
 191         if ((!wxGCPool
[i
].m_used
) && (wxGCPool
[i
].m_type 
== type
)) 
 193             wxGCPool
[i
].m_used 
= TRUE
; 
 194             return wxGCPool
[i
].m_gc
; 
 198     wxFAIL_MSG( wxT("No GC available") ); 
 200     return (GdkGC
*) NULL
; 
 203 static void wxFreePoolGC( GdkGC 
*gc 
) 
 205     for (int i 
= 0; i 
< GC_POOL_SIZE
; i
++) 
 207         if (wxGCPool
[i
].m_gc 
== gc
) 
 209             wxGCPool
[i
].m_used 
= FALSE
; 
 214     wxFAIL_MSG( wxT("Wrong GC") ); 
 217 //----------------------------------------------------------------------------- 
 219 //----------------------------------------------------------------------------- 
 221 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
) 
 223 wxWindowDC::wxWindowDC() 
 225     m_penGC 
= (GdkGC 
*) NULL
; 
 226     m_brushGC 
= (GdkGC 
*) NULL
; 
 227     m_textGC 
= (GdkGC 
*) NULL
; 
 228     m_bgGC 
= (GdkGC 
*) NULL
; 
 229     m_cmap 
= (GdkColormap 
*) NULL
; 
 231     m_isScreenDC 
= FALSE
; 
 232     m_owner 
= (wxWindow 
*)NULL
; 
 234     m_context 
= (PangoContext 
*)NULL
; 
 235     m_fontdesc 
= (PangoFontDescription 
*)NULL
; 
 239 wxWindowDC::wxWindowDC( wxWindow 
*window 
) 
 241     m_penGC 
= (GdkGC 
*) NULL
; 
 242     m_brushGC 
= (GdkGC 
*) NULL
; 
 243     m_textGC 
= (GdkGC 
*) NULL
; 
 244     m_bgGC 
= (GdkGC 
*) NULL
; 
 245     m_cmap 
= (GdkColormap 
*) NULL
; 
 246     m_owner 
= (wxWindow 
*)NULL
; 
 248     m_isScreenDC 
= FALSE
; 
 249     m_font 
= window
->GetFont(); 
 251     wxASSERT_MSG( window
, wxT("DC needs a window") ); 
 253     GtkWidget 
*widget 
= window
->m_wxwindow
; 
 255     // some controls don't have m_wxwindow - like wxStaticBox, but the user 
 256     // code should still be able to create wxClientDCs for them, so we will 
 257     // use the parent window here then 
 260         window 
= window
->GetParent(); 
 261         widget 
= window
->m_wxwindow
; 
 264     wxASSERT_MSG( widget
, wxT("DC needs a widget") ); 
 267     m_context 
= gtk_widget_get_pango_context( widget 
); 
 268     m_fontdesc 
= widget
->style
->font_desc
; 
 271     GtkPizza 
*pizza 
= GTK_PIZZA( widget 
); 
 272     m_window 
= pizza
->bin_window
; 
 277          /* don't report problems */ 
 283     m_cmap 
= gtk_widget_get_colormap( widget 
? widget 
: window
->m_widget 
); 
 287     /* this must be done after SetUpDC, bacause SetUpDC calls the 
 288        repective SetBrush, SetPen, SetBackground etc functions 
 289        to set up the DC. SetBackground call m_owner->SetBackground 
 290        and this might not be desired as the standard dc background 
 291        is white whereas a window might assume gray to be the 
 292        standard (as e.g. wxStatusBar) */ 
 297 wxWindowDC::~wxWindowDC() 
 302 void wxWindowDC::SetUpDC() 
 306     wxASSERT_MSG( !m_penGC
, wxT("GCs already created") ); 
 310         m_penGC 
= wxGetPoolGC( m_window
, wxPEN_SCREEN 
); 
 311         m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_SCREEN 
); 
 312         m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_SCREEN 
); 
 313         m_bgGC 
= wxGetPoolGC( m_window
, wxBG_SCREEN 
); 
 316     if (m_isMemDC 
&& (((wxMemoryDC
*)this)->m_selected
.GetDepth() == 1)) 
 318         m_penGC 
= wxGetPoolGC( m_window
, wxPEN_MONO 
); 
 319         m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_MONO 
); 
 320         m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_MONO 
); 
 321         m_bgGC 
= wxGetPoolGC( m_window
, wxBG_MONO 
); 
 325         m_penGC 
= wxGetPoolGC( m_window
, wxPEN_COLOUR 
); 
 326         m_brushGC 
= wxGetPoolGC( m_window
, wxBRUSH_COLOUR 
); 
 327         m_textGC 
= wxGetPoolGC( m_window
, wxTEXT_COLOUR 
); 
 328         m_bgGC 
= wxGetPoolGC( m_window
, wxBG_COLOUR 
); 
 331     /* background colour */ 
 332     m_backgroundBrush 
= *wxWHITE_BRUSH
; 
 333     m_backgroundBrush
.GetColour().CalcPixel( m_cmap 
); 
 334     GdkColor 
*bg_col 
= m_backgroundBrush
.GetColour().GetColor(); 
 337     m_textForegroundColour
.CalcPixel( m_cmap 
); 
 338     gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
 340     m_textBackgroundColour
.CalcPixel( m_cmap 
); 
 341     gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() ); 
 343     gdk_gc_set_fill( m_textGC
, GDK_SOLID 
); 
 346     m_pen
.GetColour().CalcPixel( m_cmap 
); 
 347     gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() ); 
 348     gdk_gc_set_background( m_penGC
, bg_col 
); 
 350     gdk_gc_set_line_attributes( m_penGC
, 0, GDK_LINE_SOLID
, GDK_CAP_NOT_LAST
, GDK_JOIN_ROUND 
); 
 353     m_brush
.GetColour().CalcPixel( m_cmap 
); 
 354     gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() ); 
 355     gdk_gc_set_background( m_brushGC
, bg_col 
); 
 357     gdk_gc_set_fill( m_brushGC
, GDK_SOLID 
); 
 360     gdk_gc_set_background( m_bgGC
, bg_col 
); 
 361     gdk_gc_set_foreground( m_bgGC
, bg_col 
); 
 363     gdk_gc_set_fill( m_bgGC
, GDK_SOLID 
); 
 366     gdk_gc_set_function( m_textGC
, GDK_COPY 
); 
 367     gdk_gc_set_function( m_brushGC
, GDK_COPY 
); 
 368     gdk_gc_set_function( m_penGC
, GDK_COPY 
); 
 371     gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle 
*) NULL 
); 
 372     gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle 
*) NULL 
); 
 373     gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle 
*) NULL 
); 
 374     gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle 
*) NULL 
); 
 378         hatch_bitmap    
= hatches
; 
 379         hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height 
); 
 380         hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height 
); 
 381         hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height 
); 
 382         hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, cross_bits
, cross_width
, cross_height 
); 
 383         hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, horiz_bits
, horiz_width
, horiz_height 
); 
 384         hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, verti_bits
, verti_width
, verti_height 
); 
 388 void wxWindowDC::DoFloodFill( wxCoord 
WXUNUSED(x
), wxCoord 
WXUNUSED(y
), 
 389                            const wxColour 
&WXUNUSED(col
), int WXUNUSED(style
) ) 
 391     wxFAIL_MSG( wxT("wxWindowDC::DoFloodFill not implemented") ); 
 394 bool wxWindowDC::DoGetPixel( wxCoord x1
, wxCoord y1
, wxColour 
*col 
) const 
 396     // Generic (and therefore rather inefficient) method. 
 397     // Could be improved. 
 399     wxBitmap 
bitmap(1, 1); 
 400     memdc
.SelectObject(bitmap
); 
 401     memdc
.Blit(0, 0, 1, 1, (wxDC
*) this, x1
, y1
); 
 402     memdc
.SelectObject(wxNullBitmap
); 
 403     wxImage 
image(bitmap
); 
 404     col
->Set(image
.GetRed(0, 0), image
.GetGreen(0, 0), image
.GetBlue(0, 0)); 
 408 void wxWindowDC::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2 
) 
 410     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 412     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 415             gdk_draw_line( m_window
, m_penGC
, XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) ); 
 417         CalcBoundingBox(x1
, y1
); 
 418         CalcBoundingBox(x2
, y2
); 
 422 void wxWindowDC::DoCrossHair( wxCoord x
, wxCoord y 
) 
 424     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 426     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 431         wxCoord xx 
= XLOG2DEV(x
); 
 432         wxCoord yy 
= YLOG2DEV(y
); 
 435             gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy 
); 
 436             gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) ); 
 441 void wxWindowDC::DoDrawArc( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, 
 442                             wxCoord xc
, wxCoord yc 
) 
 444     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 446     wxCoord xx1 
= XLOG2DEV(x1
); 
 447     wxCoord yy1 
= YLOG2DEV(y1
); 
 448     wxCoord xx2 
= XLOG2DEV(x2
); 
 449     wxCoord yy2 
= YLOG2DEV(y2
); 
 450     wxCoord xxc 
= XLOG2DEV(xc
); 
 451     wxCoord yyc 
= YLOG2DEV(yc
); 
 452     double dx 
= xx1 
- xxc
; 
 453     double dy 
= yy1 
- yyc
; 
 454     double radius 
= sqrt((double)(dx
*dx
+dy
*dy
)); 
 455     wxCoord   r      
= (wxCoord
)radius
; 
 456     double radius1
, radius2
; 
 458     if (xx1 
== xx2 
&& yy1 
== yy2
) 
 466         radius1 
= radius2 
= 0.0; 
 470         radius1 
= (xx1 
- xxc 
== 0) ? 
 471             (yy1 
- yyc 
< 0) ? 90.0 : -90.0 : 
 472             -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
; 
 473         radius2 
= (xx2 
- xxc 
== 0) ? 
 474             (yy2 
- yyc 
< 0) ? 90.0 : -90.0 : 
 475             -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
; 
 477     wxCoord alpha1 
= wxCoord(radius1 
* 64.0); 
 478     wxCoord alpha2 
= wxCoord((radius2 
- radius1
) * 64.0); 
 479     while (alpha2 
<= 0) alpha2 
+= 360*64; 
 480     while (alpha1 
> 360*64) alpha1 
-= 360*64; 
 484         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 486             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 488                 gdk_gc_set_ts_origin( m_textGC
, 
 489                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 490                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 491                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 492                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 494             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 496                 gdk_gc_set_ts_origin( m_brushGC
, 
 497                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 498                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 499                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 500                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 504                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 508         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 509             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 512     CalcBoundingBox (x1
, y1
); 
 513     CalcBoundingBox (x2
, y2
); 
 516 void wxWindowDC::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double sa
, double ea 
) 
 518     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 520     wxCoord xx 
= XLOG2DEV(x
); 
 521     wxCoord yy 
= YLOG2DEV(y
); 
 522     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 523     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 525     // CMB: handle -ve width and/or height 
 526     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 527     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 531         wxCoord start 
= wxCoord(sa 
* 64.0); 
 532         wxCoord end 
= wxCoord(ea 
* 64.0); 
 534         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 536             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 538                 gdk_gc_set_ts_origin( m_textGC
, 
 539                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 540                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 541                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 542                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 544             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 546                 gdk_gc_set_ts_origin( m_brushGC
, 
 547                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 548                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 549                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 550                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 554                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 558         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 559             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end 
); 
 562     CalcBoundingBox (x
, y
); 
 563     CalcBoundingBox (x 
+ width
, y 
+ height
); 
 566 void wxWindowDC::DoDrawPoint( wxCoord x
, wxCoord y 
) 
 568     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 570     if ((m_pen
.GetStyle() != wxTRANSPARENT
) && m_window
) 
 571         gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) ); 
 573     CalcBoundingBox (x
, y
); 
 576 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset 
) 
 578     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 580     if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 583     CalcBoundingBox( points
[0].x 
+ xoffset
, points
[0].y 
+ yoffset 
); 
 585     for (int i 
= 0; i 
< n
-1; i
++) 
 587         wxCoord x1 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 588         wxCoord x2 
= XLOG2DEV(points
[i
+1].x 
+ xoffset
); 
 589         wxCoord y1 
= YLOG2DEV(points
[i
].y 
+ yoffset
);     // oh, what a waste 
 590         wxCoord y2 
= YLOG2DEV(points
[i
+1].y 
+ yoffset
); 
 593             gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2 
); 
 595         CalcBoundingBox( points
[i
+1].x 
+ xoffset
, points
[i
+1].y 
+ yoffset 
); 
 599 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
, int WXUNUSED(fillStyle
) ) 
 601     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 605     GdkPoint 
*gdkpoints 
= new GdkPoint
[n
+1]; 
 607     for (i 
= 0 ; i 
< n 
; i
++) 
 609         gdkpoints
[i
].x 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 610         gdkpoints
[i
].y 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 612         CalcBoundingBox( points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset 
); 
 617         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 619             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 621                 gdk_gc_set_ts_origin( m_textGC
, 
 622                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 623                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 624                 gdk_draw_polygon( m_window
, m_textGC
, TRUE
, gdkpoints
, n 
); 
 625                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 627             if (m_brush
.GetStyle() == wxSTIPPLE
) 
 629                 gdk_gc_set_ts_origin( m_brushGC
, 
 630                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 631                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 632                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 633                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 637                 gdk_draw_polygon( m_window
, m_brushGC
, TRUE
, gdkpoints
, n 
); 
 641         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 643             for (i 
= 0 ; i 
< n 
; i
++) 
 645                 gdk_draw_line( m_window
, m_penGC
, 
 648                                gdkpoints
[(i
+1)%n
].x
, 
 649                                gdkpoints
[(i
+1)%n
].y
); 
 657 void wxWindowDC::DoDrawRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 659     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 661     wxCoord xx 
= XLOG2DEV(x
); 
 662     wxCoord yy 
= YLOG2DEV(y
); 
 663     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 664     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 666     // CMB: draw nothing if transformed w or h is 0 
 667     if (ww 
== 0 || hh 
== 0) return; 
 669     // CMB: handle -ve width and/or height 
 670     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 671     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 675         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 677             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 679                 gdk_gc_set_ts_origin( m_textGC
, 
 680                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 681                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 682                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 683                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 685             else if (m_brush
.GetStyle() == wxSTIPPLE
) 
 687                 gdk_gc_set_ts_origin( m_brushGC
, 
 688                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 689                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 690                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 691                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 695                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 699         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 700             gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 ); 
 703     CalcBoundingBox( x
, y 
); 
 704     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 707 void wxWindowDC::DoDrawRoundedRectangle( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius 
) 
 709     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 711     if (radius 
< 0.0) radius 
= - radius 
* ((width 
< height
) ? width 
: height
); 
 713     wxCoord xx 
= XLOG2DEV(x
); 
 714     wxCoord yy 
= YLOG2DEV(y
); 
 715     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 716     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 717     wxCoord rr 
= XLOG2DEVREL((wxCoord
)radius
); 
 719     // CMB: handle -ve width and/or height 
 720     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 721     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 723     // CMB: if radius is zero use DrawRectangle() instead to avoid 
 724     // X drawing errors with small radii 
 727         DrawRectangle( x
, y
, width
, height 
); 
 731     // CMB: draw nothing if transformed w or h is 0 
 732     if (ww 
== 0 || hh 
== 0) return; 
 734     // CMB: adjust size if outline is drawn otherwise the result is 
 735     // 1 pixel too wide and high 
 736     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 744         // CMB: ensure dd is not larger than rectangle otherwise we 
 745         // get an hour glass shape 
 747         if (dd 
> ww
) dd 
= ww
; 
 748         if (dd 
> hh
) dd 
= hh
; 
 751         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 753             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 755                 gdk_gc_set_ts_origin( m_textGC
, 
 756                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 757                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 758                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 759                 gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 760                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 761                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 762                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 763                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 764                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 766             else if (m_brush
.GetStyle() == wxSTIPPLE
) 
 768                 gdk_gc_set_ts_origin( m_brushGC
, 
 769                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 770                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 771                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 772                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 773                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 774                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 775                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 776                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 777                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 781                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 782                 gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 783                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 784                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 785                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 786                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 790         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 792             gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
, xx
+ww
-rr
, yy 
); 
 793             gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
+hh
, xx
+ww
-rr
, yy
+hh 
); 
 794             gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
, xx
, yy
+hh
-rr 
); 
 795             gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
, xx
+ww
, yy
+hh
-rr 
); 
 796             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 797             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 798             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 799             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 803     // this ignores the radius 
 804     CalcBoundingBox( x
, y 
); 
 805     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 808 void wxWindowDC::DoDrawEllipse( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
 810     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 812     wxCoord xx 
= XLOG2DEV(x
); 
 813     wxCoord yy 
= YLOG2DEV(y
); 
 814     wxCoord ww 
= m_signX 
* XLOG2DEVREL(width
); 
 815     wxCoord hh 
= m_signY 
* YLOG2DEVREL(height
); 
 817     // CMB: handle -ve width and/or height 
 818     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 819     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 823         if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 825             if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
 827                 gdk_gc_set_ts_origin( m_textGC
, 
 828                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 829                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 830                 gdk_draw_arc( m_window
, m_textGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
 831                 gdk_gc_set_ts_origin( m_textGC
, 0, 0 ); 
 833             else if (m_brush
.GetStyle() == wxSTIPPLE
) 
 835                 gdk_gc_set_ts_origin( m_brushGC
, 
 836                                       m_deviceOriginX 
% m_brush
.GetStipple()->GetWidth(), 
 837                                       m_deviceOriginY 
% m_brush
.GetStipple()->GetHeight() ); 
 838                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
 839                 gdk_gc_set_ts_origin( m_brushGC
, 0, 0 ); 
 843                 gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
 847         if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 848             gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
 851     CalcBoundingBox( x 
- width
, y 
- height 
); 
 852     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 855 void wxWindowDC::DoDrawIcon( const wxIcon 
&icon
, wxCoord x
, wxCoord y 
) 
 857     // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why 
 858     DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE 
); 
 861 void wxWindowDC::DoDrawBitmap( const wxBitmap 
&bitmap
, 
 862                                wxCoord x
, wxCoord y
, 
 865     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 867     wxCHECK_RET( bitmap
.Ok(), wxT("invalid bitmap") ); 
 869     bool is_mono 
= (bitmap
.GetBitmap() != NULL
); 
 871     /* scale/translate size and position */ 
 872     int xx 
= XLOG2DEV(x
); 
 873     int yy 
= YLOG2DEV(y
); 
 875     int w 
= bitmap
.GetWidth(); 
 876     int h 
= bitmap
.GetHeight(); 
 878     CalcBoundingBox( x
, y 
); 
 879     CalcBoundingBox( x 
+ w
, y 
+ h 
); 
 881     if (!m_window
) return; 
 883     int ww 
= XLOG2DEVREL(w
); 
 884     int hh 
= YLOG2DEVREL(h
); 
 886     /* compare to current clipping region */ 
 887     if (!m_currentClippingRegion
.IsNull()) 
 889         wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
 890         tmp
.Intersect( m_currentClippingRegion 
); 
 895     /* scale bitmap if required */ 
 897     if ((w 
!= ww
) || (h 
!= hh
)) 
 899         wxImage 
image( bitmap 
); 
 900         image
.Rescale( ww
, hh 
); 
 902             use_bitmap 
= image
.ConvertToMonoBitmap(255,255,255); 
 904             use_bitmap 
= image
.ConvertToBitmap(); 
 911     /* apply mask if any */ 
 912     GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
 913     if (use_bitmap
.GetMask()) mask 
= use_bitmap
.GetMask()->GetBitmap(); 
 917             GdkBitmap 
*new_mask 
= (GdkBitmap
*) NULL
; 
 918             if (!m_currentClippingRegion
.IsNull()) 
 921                 new_mask 
= gdk_pixmap_new( wxRootWindow
->window
, ww
, hh
, 1 ); 
 922                 GdkGC 
*gc 
= gdk_gc_new( new_mask 
); 
 924                 gdk_gc_set_foreground( gc
, &col 
); 
 925                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh 
); 
 927                 gdk_gc_set_background( gc
, &col 
); 
 929                 gdk_gc_set_foreground( gc
, &col 
); 
 930                 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() ); 
 931                 gdk_gc_set_clip_origin( gc
, -xx
, -yy 
); 
 932                 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED 
); 
 933                 gdk_gc_set_stipple( gc
, mask 
); 
 934                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, ww
, hh 
); 
 941                     gdk_gc_set_clip_mask( m_textGC
, new_mask 
); 
 943                     gdk_gc_set_clip_mask( m_textGC
, mask 
); 
 944                 gdk_gc_set_clip_origin( m_textGC
, xx
, yy 
); 
 949                     gdk_gc_set_clip_mask( m_penGC
, new_mask 
); 
 951                     gdk_gc_set_clip_mask( m_penGC
, mask 
); 
 952                 gdk_gc_set_clip_origin( m_penGC
, xx
, yy 
); 
 955                 gdk_bitmap_unref( new_mask 
); 
 958     /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 
 959        drawing a mono-bitmap (XBitmap) we use the current text GC */ 
 961         gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), 0, 0, xx
, yy
, -1, -1 ); 
 963         gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 ); 
 965     /* remove mask again if any */ 
 970             gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap 
*) NULL 
); 
 971             gdk_gc_set_clip_origin( m_textGC
, 0, 0 ); 
 972             if (!m_currentClippingRegion
.IsNull()) 
 973                 gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
 977             gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap 
*) NULL 
); 
 978             gdk_gc_set_clip_origin( m_penGC
, 0, 0 ); 
 979             if (!m_currentClippingRegion
.IsNull()) 
 980                 gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
 985 bool wxWindowDC::DoBlit( wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
, 
 986                          wxDC 
*source
, wxCoord xsrc
, wxCoord ysrc
, 
 987                          int logical_func
, bool useMask 
) 
 989    /* this is the nth try to get this utterly useless function to 
 990       work. it now completely ignores the scaling or translation 
 991       of the source dc, but scales correctly on the target dc and 
 992       knows about possible mask information in a memory dc. */ 
 994     wxCHECK_MSG( Ok(), FALSE
, wxT("invalid window dc") ); 
 996     wxCHECK_MSG( source
, FALSE
, wxT("invalid source dc") ); 
 998     if (!m_window
) return FALSE
; 
1000     wxClientDC 
*srcDC 
= (wxClientDC
*)source
; 
1001     wxMemoryDC 
*memDC 
= (wxMemoryDC
*)source
; 
1003     bool use_bitmap_method 
= FALSE
; 
1004     bool is_mono 
= FALSE
; 
1006     if (srcDC
->m_isMemDC
) 
1008         if (!memDC
->m_selected
.Ok()) return FALSE
; 
1010         /* we use the "XCopyArea" way to copy a memory dc into 
1011            y different window if the memory dc BOTH 
1012            a) doesn't have any mask or its mask isn't used 
1016         if (useMask 
&& (memDC
->m_selected
.GetMask())) 
1018            /* we HAVE TO use the direct way for memory dcs 
1019               that have mask since the XCopyArea doesn't know 
1021             use_bitmap_method 
= TRUE
; 
1023         else if (memDC
->m_selected
.GetDepth() == 1) 
1025            /* we HAVE TO use the direct way for memory dcs 
1026               that are bitmaps because XCopyArea doesn't cope 
1027               with different bit depths */ 
1029             use_bitmap_method 
= TRUE
; 
1031         else if ((xsrc 
== 0) && (ysrc 
== 0) && 
1032                  (width 
== memDC
->m_selected
.GetWidth()) && 
1033                  (height 
== memDC
->m_selected
.GetHeight())) 
1035            /* we SHOULD use the direct way if all of the bitmap 
1036               in the memory dc is copied in which case XCopyArea 
1037               wouldn't be able able to boost performace by reducing 
1038               the area to be scaled */ 
1039             use_bitmap_method 
= TRUE
; 
1043             use_bitmap_method 
= FALSE
; 
1047     CalcBoundingBox( xdest
, ydest 
); 
1048     CalcBoundingBox( xdest 
+ width
, ydest 
+ height 
); 
1050     /* scale/translate size and position */ 
1051     wxCoord xx 
= XLOG2DEV(xdest
); 
1052     wxCoord yy 
= YLOG2DEV(ydest
); 
1054     wxCoord ww 
= XLOG2DEVREL(width
); 
1055     wxCoord hh 
= YLOG2DEVREL(height
); 
1057     /* compare to current clipping region */ 
1058     if (!m_currentClippingRegion
.IsNull()) 
1060         wxRegion 
tmp( xx
,yy
,ww
,hh 
); 
1061         tmp
.Intersect( m_currentClippingRegion 
); 
1066     int old_logical_func 
= m_logicalFunction
; 
1067     SetLogicalFunction( logical_func 
); 
1069     if (use_bitmap_method
) 
1071         /* scale/translate bitmap size */ 
1072         wxCoord bm_width 
= memDC
->m_selected
.GetWidth(); 
1073         wxCoord bm_height 
= memDC
->m_selected
.GetHeight(); 
1075         wxCoord bm_ww 
= XLOG2DEVREL( bm_width 
); 
1076         wxCoord bm_hh 
= YLOG2DEVREL( bm_height 
); 
1078         /* scale bitmap if required */ 
1079         wxBitmap use_bitmap
; 
1081         if ((bm_width 
!= bm_ww
) || (bm_height 
!= bm_hh
)) 
1083             wxImage 
image( memDC
->m_selected 
); 
1084             image 
= image
.Scale( bm_ww
, bm_hh 
); 
1087                 use_bitmap 
= image
.ConvertToMonoBitmap(255,255,255); 
1089                 use_bitmap 
= image
.ConvertToBitmap(); 
1093             use_bitmap 
= memDC
->m_selected
; 
1096         /* apply mask if any */ 
1097         GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
1098         if (use_bitmap
.GetMask()) mask 
= use_bitmap
.GetMask()->GetBitmap(); 
1100         if (useMask 
&& mask
) 
1102             GdkBitmap 
*new_mask 
= (GdkBitmap
*) NULL
; 
1103             if (!m_currentClippingRegion
.IsNull()) 
1106                 new_mask 
= gdk_pixmap_new( wxRootWindow
->window
, bm_ww
, bm_hh
, 1 ); 
1107                 GdkGC 
*gc 
= gdk_gc_new( new_mask 
); 
1109                 gdk_gc_set_foreground( gc
, &col 
); 
1110                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh 
); 
1112                 gdk_gc_set_background( gc
, &col 
); 
1114                 gdk_gc_set_foreground( gc
, &col 
); 
1115                 gdk_gc_set_clip_region( gc
, m_currentClippingRegion
.GetRegion() ); 
1116                 gdk_gc_set_clip_origin( gc
, -xx
, -yy 
); 
1117                 gdk_gc_set_fill( gc
, GDK_OPAQUE_STIPPLED 
); 
1118                 gdk_gc_set_stipple( gc
, mask 
); 
1119                 gdk_draw_rectangle( new_mask
, gc
, TRUE
, 0, 0, bm_ww
, bm_hh 
); 
1126                     gdk_gc_set_clip_mask( m_textGC
, new_mask 
); 
1128                     gdk_gc_set_clip_mask( m_textGC
, mask 
); 
1129                 gdk_gc_set_clip_origin( m_textGC
, xx
, yy 
); 
1134                     gdk_gc_set_clip_mask( m_penGC
, new_mask 
); 
1136                     gdk_gc_set_clip_mask( m_penGC
, mask 
); 
1137                 gdk_gc_set_clip_origin( m_penGC
, xx
, yy 
); 
1140                 gdk_bitmap_unref( new_mask 
); 
1143         /* Draw XPixmap or XBitmap, depending on what the wxBitmap contains. For 
1144            drawing a mono-bitmap (XBitmap) we use the current text GC */ 
1147             gdk_wx_draw_bitmap( m_window
, m_textGC
, use_bitmap
.GetBitmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh 
); 
1149             gdk_draw_pixmap( m_window
, m_penGC
, use_bitmap
.GetPixmap(), xsrc
, ysrc
, xx
, yy
, ww
, hh 
); 
1151         /* remove mask again if any */ 
1152         if (useMask 
&& mask
) 
1156                 gdk_gc_set_clip_mask( m_textGC
, (GdkBitmap 
*) NULL 
); 
1157                 gdk_gc_set_clip_origin( m_textGC
, 0, 0 ); 
1158                 if (!m_currentClippingRegion
.IsNull()) 
1159                     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
1163                 gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap 
*) NULL 
); 
1164                 gdk_gc_set_clip_origin( m_penGC
, 0, 0 ); 
1165                 if (!m_currentClippingRegion
.IsNull()) 
1166                     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
1170     else /* use_bitmap_method */ 
1172         if ((width 
!= ww
) || (height 
!= hh
)) 
1174             /* draw source window into a bitmap as we cannot scale 
1175                a window in contrast to a bitmap. this would actually 
1176                work with memory dcs as well, but we'd lose the mask 
1177                information and waste one step in this process since 
1178                a memory already has a bitmap. all this is slightly 
1179                inefficient as we could take an XImage directly from 
1180                an X window, but we'd then also have to care that 
1181                the window is not outside the screen (in which case 
1182                we'd get a BadMatch or what not). 
1183                Is a double XGetImage and combined XGetPixel and 
1184                XPutPixel really faster? I'm not sure. look at wxXt 
1185                for a different implementation of the same problem. */ 
1187             wxBitmap 
bitmap( width
, height 
); 
1189             /* copy including child window contents */ 
1190             gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS 
); 
1191             gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0, 
1193                                   xsrc
, ysrc
, width
, height 
); 
1194             gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN 
); 
1197             wxImage 
image( bitmap 
); 
1198             image 
= image
.Scale( ww
, hh 
); 
1200             /* convert to bitmap */ 
1201             bitmap 
= image
.ConvertToBitmap(); 
1203             /* draw scaled bitmap */ 
1204             gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 ); 
1209             /* No scaling and not a memory dc with a mask either */ 
1211             /* copy including child window contents */ 
1212             gdk_gc_set_subwindow( m_penGC
, GDK_INCLUDE_INFERIORS 
); 
1213             gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
, 
1215                                   xsrc
, ysrc
, width
, height 
); 
1216             gdk_gc_set_subwindow( m_penGC
, GDK_CLIP_BY_CHILDREN 
); 
1220     SetLogicalFunction( old_logical_func 
); 
1224 void wxWindowDC::DoDrawText( const wxString 
&text
, wxCoord x
, wxCoord y 
) 
1226     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1228     if (!m_window
) return; 
1230     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1232     wxCHECK_RET( font
, wxT("invalid font") ); 
1235     wxCHECK_RET( m_context
, wxT("no Pango context") ); 
1242     /* FIXME: the layout engine should probably be abstracted at a higher level in wxDC... */ 
1243     PangoLayout 
*layout 
= pango_layout_new(m_context
); 
1244     pango_layout_set_font_description(layout
, m_fontdesc
); 
1246         wxWX2MBbuf data 
= text
.mb_str(wxConvUTF8
); 
1247         pango_layout_set_text(layout
, data
, strlen(data
)); 
1249     PangoLayoutLine 
*line 
= (PangoLayoutLine 
*)pango_layout_get_lines(layout
)->data
; 
1250     PangoRectangle rect
; 
1251     pango_layout_line_get_extents(line
, NULL
, &rect
); 
1252     wxCoord width 
= rect
.width
; 
1253     wxCoord height 
= rect
.height
; 
1254     gdk_draw_layout( m_window
, m_textGC
, x
, y
, layout 
); 
1256     wxCoord width 
= gdk_string_width( font
, text
.mbc_str() ); 
1257     wxCoord height 
= font
->ascent 
+ font
->descent
; 
1258     /* CMB 21/5/98: draw text background if mode is wxSOLID */ 
1259     if (m_backgroundMode 
== wxSOLID
) 
1261         gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() ); 
1262         gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height 
); 
1263         gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
1265     gdk_draw_string( m_window
, font
, m_textGC
, x
, y 
+ font
->ascent
, text
.mbc_str() ); 
1268     /* CMB 17/7/98: simple underline: ignores scaling and underlying 
1269        X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS 
1270        properties (see wxXt implementation) */ 
1271     if (m_font
.GetUnderlined()) 
1273         wxCoord ul_y 
= y 
+ font
->ascent
; 
1274         if (font
->descent 
> 0) ul_y
++; 
1275         gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x 
+ width
, ul_y
); 
1279     g_object_unref( G_OBJECT( layout 
) ); 
1282     width 
= wxCoord(width 
/ m_scaleX
); 
1283     height 
= wxCoord(height 
/ m_scaleY
); 
1284     CalcBoundingBox (x 
+ width
, y 
+ height
); 
1285     CalcBoundingBox (x
, y
); 
1288 void wxWindowDC::DoDrawRotatedText( const wxString 
&text
, wxCoord x
, wxCoord y
, double angle 
) 
1292         DrawText(text
, x
, y
); 
1296     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1298     if (!m_window
) return; 
1300     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1302     wxCHECK_RET( font
, wxT("invalid font") ); 
1304     // the size of the text 
1305     wxCoord w 
= gdk_string_width( font
, text
.mbc_str() ); 
1306     wxCoord h 
= font
->ascent 
+ font
->descent
; 
1308     // draw the string normally 
1311     dc
.SelectObject(src
); 
1312     dc
.SetFont(GetFont()); 
1313     dc
.SetBackground(*wxWHITE_BRUSH
); 
1314     dc
.SetBrush(*wxBLACK_BRUSH
); 
1316     dc
.DrawText(text
, 0, 0); 
1317     dc
.SetFont(wxNullFont
); 
1318     dc
.SelectObject(wxNullBitmap
); 
1320     // Calculate the size of the rotated bounding box. 
1321     double rad 
= DegToRad(angle
); 
1322     double dx 
= cos(rad
), 
1325     // the rectngle vertices are counted clockwise with the first one being at 
1326     // (0, 0) (or, rather, at (x, y)) 
1328            y2 
= -w
*dy
;      // y axis points to the bottom, hence minus 
1331     double x3 
= x4 
+ x2
, 
1335     wxCoord maxX 
= (wxCoord
)(dmax(x2
, dmax(x3
, x4
)) + 0.5), 
1336             maxY 
= (wxCoord
)(dmax(y2
, dmax(y3
, y4
)) + 0.5), 
1337             minX 
= (wxCoord
)(dmin(x2
, dmin(x3
, x4
)) - 0.5), 
1338             minY 
= (wxCoord
)(dmin(y2
, dmin(y3
, y4
)) - 0.5); 
1340     // prepare to blit-with-rotate the bitmap to the DC 
1343     GdkColor 
*colText 
= m_textForegroundColour
.GetColor(), 
1344              *colBack 
= m_textBackgroundColour
.GetColor(); 
1346     bool textColSet 
= TRUE
; 
1348     unsigned char *data 
= image
.GetData(); 
1350     // paint pixel by pixel 
1351     for ( wxCoord srcX 
= 0; srcX 
< w
; srcX
++ ) 
1353         for ( wxCoord srcY 
= 0; srcY 
< h
; srcY
++ ) 
1355             // transform source coords to dest coords 
1356             double r 
= sqrt((double)srcX
*srcX 
+ srcY
*srcY
); 
1357             double angleOrig 
= atan2((double)srcY
, (double)srcX
) - rad
; 
1358             wxCoord dstX 
= (wxCoord
)(r
*cos(angleOrig
) + 0.5), 
1359                     dstY 
= (wxCoord
)(r
*sin(angleOrig
) + 0.5); 
1362             bool textPixel 
= data
[(srcY
*w 
+ srcX
)*3] == 0; 
1363             if ( textPixel 
|| (m_backgroundMode 
== wxSOLID
) ) 
1365                 // change colour if needed 
1366                 if ( textPixel 
!= textColSet 
) 
1368                     gdk_gc_set_foreground( m_textGC
, textPixel 
? colText
 
1371                     textColSet 
= textPixel
; 
1374                 // don't use DrawPoint() because it uses the current pen 
1375                 // colour, and we don't need it here 
1376                 gdk_draw_point( m_window
, m_textGC
, 
1377                                 XLOG2DEV(x 
+ dstX
), YLOG2DEV(y 
+ dstY
) ); 
1382     // it would be better to draw with non underlined font and draw the line 
1383     // manually here (it would be more straight...) 
1385     if ( m_font
.GetUnderlined() ) 
1387         gdk_draw_line( m_window
, m_textGC
, 
1388                        XLOG2DEV(x 
+ x4
), YLOG2DEV(y 
+ y4 
+ font
->descent
), 
1389                        XLOG2DEV(x 
+ x3
), YLOG2DEV(y 
+ y3 
+ font
->descent
)); 
1393     // restore the font colour 
1394     gdk_gc_set_foreground( m_textGC
, colText 
); 
1396     // update the bounding box 
1397     CalcBoundingBox(x 
+ minX
, y 
+ minY
); 
1398     CalcBoundingBox(x 
+ maxX
, y 
+ maxY
); 
1401 void wxWindowDC::DoGetTextExtent(const wxString 
&string
, 
1402                                  wxCoord 
*width
, wxCoord 
*height
, 
1403                                  wxCoord 
*descent
, wxCoord 
*externalLeading
, 
1404                                  wxFont 
*theFont
) const 
1406     wxFont fontToUse 
= m_font
; 
1407     if (theFont
) fontToUse 
= *theFont
; 
1409     GdkFont 
*font 
= fontToUse
.GetInternalFont( m_scaleY 
); 
1410     if (width
) (*width
) = wxCoord(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
); 
1411     if (height
) (*height
) = wxCoord((font
->ascent 
+ font
->descent
) / m_scaleY
); 
1412     if (descent
) (*descent
) = wxCoord(font
->descent 
/ m_scaleY
); 
1413     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
1416 wxCoord 
wxWindowDC::GetCharWidth() const 
1418     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1419     wxCHECK_MSG( font
, -1, wxT("invalid font") ); 
1421     return wxCoord(gdk_string_width( font
, "H" ) / m_scaleX
); 
1424 wxCoord 
wxWindowDC::GetCharHeight() const 
1426     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
1427     wxCHECK_MSG( font
, -1, wxT("invalid font") ); 
1429     return wxCoord((font
->ascent 
+ font
->descent
) / m_scaleY
); 
1432 void wxWindowDC::Clear() 
1434     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1436     if (!m_window
) return; 
1438     /* - we either are a memory dc or have a window as the 
1439        owner. anything else shouldn't happen. 
1440        - we don't use gdk_window_clear() as we don't set 
1441        the window's background colour anymore. it is too 
1442        much pain to keep the DC's and the window's back- 
1443        ground colour in synch. */ 
1448         m_owner
->GetSize( &width
, &height 
); 
1449         gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height 
); 
1456         GetSize( &width
, &height 
); 
1457         gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height 
); 
1462 void wxWindowDC::SetFont( const wxFont 
&font 
) 
1470 void wxWindowDC::SetPen( const wxPen 
&pen 
) 
1472     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1474     if (m_pen 
== pen
) return; 
1478     if (!m_pen
.Ok()) return; 
1480     if (!m_window
) return; 
1482     gint width 
= m_pen
.GetWidth(); 
1485         // CMB: if width is non-zero scale it with the dc 
1490         // X doesn't allow different width in x and y and so we take 
1493                    ( fabs((double) XLOG2DEVREL(width
)) + 
1494                      fabs((double) YLOG2DEVREL(width
)) ) / 2.0; 
1498     static const wxGTKDash dotted
[] = {1, 1}; 
1499     static const wxGTKDash short_dashed
[] = {2, 2}; 
1500     static const wxGTKDash wxCoord_dashed
[] = {2, 4}; 
1501     static const wxGTKDash dotted_dashed
[] = {3, 3, 1, 3}; 
1503     // We express dash pattern in pen width unit, so we are 
1504     // independent of zoom factor and so on... 
1506     const wxGTKDash 
*req_dash
; 
1508     GdkLineStyle lineStyle 
= GDK_LINE_SOLID
; 
1509     switch (m_pen
.GetStyle()) 
1513             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1514             req_nb_dash 
= m_pen
.GetDashCount(); 
1515             req_dash 
= (wxGTKDash
*)m_pen
.GetDash(); 
1520             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1527             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1529             req_dash 
= wxCoord_dashed
; 
1534             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1536             req_dash 
= short_dashed
; 
1541 //            lineStyle = GDK_LINE_DOUBLE_DASH; 
1542             lineStyle 
= GDK_LINE_ON_OFF_DASH
; 
1544             req_dash 
= dotted_dashed
; 
1549         case wxSTIPPLE_MASK_OPAQUE
: 
1554             lineStyle 
= GDK_LINE_SOLID
; 
1555             req_dash 
= (wxGTKDash
*)NULL
; 
1561 #if (GTK_MINOR_VERSION > 0) || (GTK_MAJOR_VERSION > 1) 
1562     if (req_dash 
&& req_nb_dash
) 
1564         wxGTKDash 
*real_req_dash 
= new wxGTKDash
[req_nb_dash
]; 
1567             for (int i 
= 0; i 
< req_nb_dash
; i
++) 
1568                 real_req_dash
[i
] = req_dash
[i
] * width
; 
1569             gdk_gc_set_dashes( m_penGC
, 0, real_req_dash
, req_nb_dash 
); 
1570             delete[] real_req_dash
; 
1574             // No Memory. We use non-scaled dash pattern... 
1575             gdk_gc_set_dashes( m_penGC
, 0, (wxGTKDash
*)req_dash
, req_nb_dash 
); 
1580     GdkCapStyle capStyle 
= GDK_CAP_ROUND
; 
1581     switch (m_pen
.GetCap()) 
1583         case wxCAP_PROJECTING
: { capStyle 
= GDK_CAP_PROJECTING
; break; } 
1584         case wxCAP_BUTT
:       { capStyle 
= GDK_CAP_BUTT
;       break; } 
1591                 capStyle 
= GDK_CAP_NOT_LAST
; 
1595                 capStyle 
= GDK_CAP_ROUND
; 
1601     GdkJoinStyle joinStyle 
= GDK_JOIN_ROUND
; 
1602     switch (m_pen
.GetJoin()) 
1604         case wxJOIN_BEVEL
: { joinStyle 
= GDK_JOIN_BEVEL
; break; } 
1605         case wxJOIN_MITER
: { joinStyle 
= GDK_JOIN_MITER
; break; } 
1607         default:           { joinStyle 
= GDK_JOIN_ROUND
; break; } 
1610     gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle 
); 
1612     m_pen
.GetColour().CalcPixel( m_cmap 
); 
1613     gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() ); 
1616 void wxWindowDC::SetBrush( const wxBrush 
&brush 
) 
1618     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1620     if (m_brush 
== brush
) return; 
1624     if (!m_brush
.Ok()) return; 
1626     if (!m_window
) return; 
1628     m_brush
.GetColour().CalcPixel( m_cmap 
); 
1629     gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() ); 
1631     gdk_gc_set_fill( m_brushGC
, GDK_SOLID 
); 
1633     if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok())) 
1635         if (m_brush
.GetStipple()->GetPixmap()) 
1637             gdk_gc_set_fill( m_brushGC
, GDK_TILED 
); 
1638             gdk_gc_set_tile( m_brushGC
, m_brush
.GetStipple()->GetPixmap() ); 
1642             gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED 
); 
1643             gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() ); 
1647     if ((m_brush
.GetStyle() == wxSTIPPLE_MASK_OPAQUE
) && (m_brush
.GetStipple()->GetMask())) 
1649         gdk_gc_set_fill( m_textGC
, GDK_OPAQUE_STIPPLED
); 
1650         gdk_gc_set_stipple( m_textGC
, m_brush
.GetStipple()->GetMask()->GetBitmap() ); 
1653     if (IS_HATCH(m_brush
.GetStyle())) 
1655         gdk_gc_set_fill( m_brushGC
, GDK_STIPPLED 
); 
1656         int num 
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
; 
1657         gdk_gc_set_stipple( m_brushGC
, hatches
[num
] ); 
1661 void wxWindowDC::SetBackground( const wxBrush 
&brush 
) 
1663    /* CMB 21/7/98: Added SetBackground. Sets background brush 
1664     * for Clear() and bg colour for shapes filled with cross-hatch brush */ 
1666     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1668     if (m_backgroundBrush 
== brush
) return; 
1670     m_backgroundBrush 
= brush
; 
1672     if (!m_backgroundBrush
.Ok()) return; 
1674     if (!m_window
) return; 
1676     m_backgroundBrush
.GetColour().CalcPixel( m_cmap 
); 
1677     gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() ); 
1678     gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() ); 
1679     gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() ); 
1680     gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() ); 
1682     gdk_gc_set_fill( m_bgGC
, GDK_SOLID 
); 
1684     if ((m_backgroundBrush
.GetStyle() == wxSTIPPLE
) && (m_backgroundBrush
.GetStipple()->Ok())) 
1686         if (m_backgroundBrush
.GetStipple()->GetPixmap()) 
1688             gdk_gc_set_fill( m_bgGC
, GDK_TILED 
); 
1689             gdk_gc_set_tile( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() ); 
1693             gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED 
); 
1694             gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetBitmap() ); 
1698     if (IS_HATCH(m_backgroundBrush
.GetStyle())) 
1700         gdk_gc_set_fill( m_bgGC
, GDK_STIPPLED 
); 
1701         int num 
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
; 
1702         gdk_gc_set_stipple( m_bgGC
, hatches
[num
] ); 
1706 void wxWindowDC::SetLogicalFunction( int function 
) 
1708     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1710     if (m_logicalFunction 
== function
) 
1713     // VZ: shouldn't this be a CHECK? 
1717     GdkFunction mode 
= GDK_COPY
; 
1720         case wxXOR
:          mode 
= GDK_XOR
;           break; 
1721         case wxINVERT
:       mode 
= GDK_INVERT
;        break; 
1722 #if (GTK_MINOR_VERSION > 0) 
1723         case wxOR_REVERSE
:   mode 
= GDK_OR_REVERSE
;    break; 
1724         case wxAND_REVERSE
:  mode 
= GDK_AND_REVERSE
;   break; 
1725         case wxCLEAR
:        mode 
= GDK_CLEAR
;         break; 
1726         case wxSET
:          mode 
= GDK_SET
;           break; 
1727         case wxOR_INVERT
:    mode 
= GDK_OR_INVERT
;     break; 
1728         case wxAND
:          mode 
= GDK_AND
;           break; 
1729         case wxOR
:           mode 
= GDK_OR
;            break; 
1730         case wxEQUIV
:        mode 
= GDK_EQUIV
;         break; 
1731         case wxNAND
:         mode 
= GDK_NAND
;          break; 
1732         case wxAND_INVERT
:   mode 
= GDK_AND_INVERT
;    break; 
1733         case wxCOPY
:         mode 
= GDK_COPY
;          break; 
1734         case wxNO_OP
:        mode 
= GDK_NOOP
;          break; 
1735         case wxSRC_INVERT
:   mode 
= GDK_COPY_INVERT
;   break; 
1737         // unsupported by GTK 
1738         case wxNOR
:          mode 
= GDK_COPY
;          break; 
1742            wxFAIL_MSG( wxT("unsupported logical function") ); 
1747     m_logicalFunction 
= function
; 
1749     gdk_gc_set_function( m_penGC
, mode 
); 
1750     gdk_gc_set_function( m_brushGC
, mode 
); 
1752     // to stay compatible with wxMSW, we don't apply ROPs to the text 
1753     // operations (i.e. DrawText/DrawRotatedText). 
1754     // True, but mono-bitmaps use the m_textGC and they use ROPs as well. 
1755     gdk_gc_set_function( m_textGC
, mode 
); 
1758 void wxWindowDC::SetTextForeground( const wxColour 
&col 
) 
1760     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1762     if (m_textForegroundColour 
== col
) return; 
1764     m_textForegroundColour 
= col
; 
1765     if (!m_textForegroundColour
.Ok()) return; 
1767     if (!m_window
) return; 
1769     m_textForegroundColour
.CalcPixel( m_cmap 
); 
1770     gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
1773 void wxWindowDC::SetTextBackground( const wxColour 
&col 
) 
1775     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1777     if (m_textBackgroundColour 
== col
) return; 
1779     m_textBackgroundColour 
= col
; 
1780     if (!m_textBackgroundColour
.Ok()) return; 
1782     if (!m_window
) return; 
1784     m_textBackgroundColour
.CalcPixel( m_cmap 
); 
1785     gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() ); 
1788 void wxWindowDC::SetBackgroundMode( int mode 
) 
1790     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1792     m_backgroundMode 
= mode
; 
1794     if (!m_window
) return; 
1796     // CMB 21/7/98: fill style of cross-hatch brushes is affected by 
1797     // transparent/solid background mode 
1799     if (m_brush
.GetStyle() != wxSOLID 
&& m_brush
.GetStyle() != wxTRANSPARENT
) 
1801         gdk_gc_set_fill( m_brushGC
, 
1802           (m_backgroundMode 
== wxTRANSPARENT
) ? GDK_STIPPLED 
: GDK_OPAQUE_STIPPLED
); 
1806 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) ) 
1808     wxFAIL_MSG( wxT("wxWindowDC::SetPalette not implemented") ); 
1811 void wxWindowDC::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height 
) 
1813     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1815     if (!m_window
) return; 
1818     rect
.x 
= XLOG2DEV(x
); 
1819     rect
.y 
= YLOG2DEV(y
); 
1820     rect
.width 
= XLOG2DEVREL(width
); 
1821     rect
.height 
= YLOG2DEVREL(height
); 
1823     if (!m_currentClippingRegion
.IsNull()) 
1824         m_currentClippingRegion
.Intersect( rect 
); 
1826         m_currentClippingRegion
.Union( rect 
); 
1828 #if USE_PAINT_REGION 
1829     if (!m_paintClippingRegion
.IsNull()) 
1830         m_currentClippingRegion
.Intersect( m_paintClippingRegion 
); 
1833     wxCoord xx
, yy
, ww
, hh
; 
1834     m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh 
); 
1835     wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
1837     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
1838     gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
1839     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
1840     gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
1843 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion 
®ion  
) 
1845     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1849         DestroyClippingRegion(); 
1853     if (!m_window
) return; 
1855     if (!m_currentClippingRegion
.IsNull()) 
1856         m_currentClippingRegion
.Intersect( region 
); 
1858         m_currentClippingRegion
.Union( region 
); 
1860 #if USE_PAINT_REGION 
1861     if (!m_paintClippingRegion
.IsNull()) 
1862         m_currentClippingRegion
.Intersect( m_paintClippingRegion 
); 
1865     wxCoord xx
, yy
, ww
, hh
; 
1866     m_currentClippingRegion
.GetBox( xx
, yy
, ww
, hh 
); 
1867     wxDC::DoSetClippingRegion( xx
, yy
, ww
, hh 
); 
1869     gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
1870     gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
1871     gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
1872     gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
1875 void wxWindowDC::DestroyClippingRegion() 
1877     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
1879     wxDC::DestroyClippingRegion(); 
1881     m_currentClippingRegion
.Clear(); 
1883 #if USE_PAINT_REGION 
1884     if (!m_paintClippingRegion
.IsEmpty()) 
1885         m_currentClippingRegion
.Union( m_paintClippingRegion 
); 
1888     if (!m_window
) return; 
1890     if (m_currentClippingRegion
.IsEmpty()) 
1892         gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle 
*) NULL 
); 
1893         gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle 
*) NULL 
); 
1894         gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle 
*) NULL 
); 
1895         gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle 
*) NULL 
); 
1899         gdk_gc_set_clip_region( m_penGC
, m_currentClippingRegion
.GetRegion() ); 
1900         gdk_gc_set_clip_region( m_brushGC
, m_currentClippingRegion
.GetRegion() ); 
1901         gdk_gc_set_clip_region( m_textGC
, m_currentClippingRegion
.GetRegion() ); 
1902         gdk_gc_set_clip_region( m_bgGC
, m_currentClippingRegion
.GetRegion() ); 
1906 void wxWindowDC::Destroy() 
1908     if (m_penGC
) wxFreePoolGC( m_penGC 
); 
1909     m_penGC 
= (GdkGC
*) NULL
; 
1910     if (m_brushGC
) wxFreePoolGC( m_brushGC 
); 
1911     m_brushGC 
= (GdkGC
*) NULL
; 
1912     if (m_textGC
) wxFreePoolGC( m_textGC 
); 
1913     m_textGC 
= (GdkGC
*) NULL
; 
1914     if (m_bgGC
) wxFreePoolGC( m_bgGC 
); 
1915     m_bgGC 
= (GdkGC
*) NULL
; 
1918 void wxWindowDC::ComputeScaleAndOrigin() 
1920     /* CMB: copy scale to see if it changes */ 
1921     double origScaleX 
= m_scaleX
; 
1922     double origScaleY 
= m_scaleY
; 
1924     wxDC::ComputeScaleAndOrigin(); 
1926     /* CMB: if scale has changed call SetPen to recalulate the line width */ 
1927     if ((m_scaleX 
!= origScaleX 
|| m_scaleY 
!= origScaleY
) && 
1930       /* this is a bit artificial, but we need to force wxDC to think 
1931          the pen has changed */ 
1938 // Resolution in pixels per logical inch 
1939 wxSize 
wxWindowDC::GetPPI() const 
1941     return wxSize(100, 100); 
1944 int wxWindowDC::GetDepth() const 
1946     wxFAIL_MSG(wxT("not implemented")); 
1952 // ----------------------------------- spline code ---------------------------------------- 
1954 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, 
1955                          double a3
, double b3
, double a4
, double b4
); 
1956 void wx_clear_stack(); 
1957 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
, 
1958         double *y3
, double *x4
, double *y4
); 
1959 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, 
1960           double x4
, double y4
); 
1961 static bool wx_spline_add_point(double x
, double y
); 
1962 static void wx_spline_draw_point_array(wxDC 
*dc
); 
1964 wxList wx_spline_point_list
; 
1966 #define                half(z1, z2)        ((z1+z2)/2.0) 
1969 /* iterative version */ 
1971 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
, 
1974     register double  xmid
, ymid
; 
1975     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
1978     wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
); 
1980     while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) { 
1981         xmid 
= (double)half(x2
, x3
); 
1982         ymid 
= (double)half(y2
, y3
); 
1983         if (fabs(x1 
- xmid
) < THRESHOLD 
&& fabs(y1 
- ymid
) < THRESHOLD 
&& 
1984             fabs(xmid 
- x4
) < THRESHOLD 
&& fabs(ymid 
- y4
) < THRESHOLD
) { 
1985             wx_spline_add_point( x1
, y1 
); 
1986             wx_spline_add_point( xmid
, ymid 
); 
1988             wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
), 
1989                  (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
); 
1990             wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
), 
1991                  (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
); 
1996 /* utilities used by spline drawing routines */ 
1998 typedef struct wx_spline_stack_struct 
{ 
1999     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
2002 #define         SPLINE_STACK_DEPTH             20 
2003 static Stack    wx_spline_stack
[SPLINE_STACK_DEPTH
]; 
2004 static Stack   
*wx_stack_top
; 
2005 static int      wx_stack_count
; 
2007 void wx_clear_stack() 
2009     wx_stack_top 
= wx_spline_stack
; 
2013 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
) 
2015     wx_stack_top
->x1 
= x1
; 
2016     wx_stack_top
->y1 
= y1
; 
2017     wx_stack_top
->x2 
= x2
; 
2018     wx_stack_top
->y2 
= y2
; 
2019     wx_stack_top
->x3 
= x3
; 
2020     wx_stack_top
->y3 
= y3
; 
2021     wx_stack_top
->x4 
= x4
; 
2022     wx_stack_top
->y4 
= y4
; 
2027 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, 
2028                   double *x3
, double *y3
, double *x4
, double *y4
) 
2030     if (wx_stack_count 
== 0) 
2034     *x1 
= wx_stack_top
->x1
; 
2035     *y1 
= wx_stack_top
->y1
; 
2036     *x2 
= wx_stack_top
->x2
; 
2037     *y2 
= wx_stack_top
->y2
; 
2038     *x3 
= wx_stack_top
->x3
; 
2039     *y3 
= wx_stack_top
->y3
; 
2040     *x4 
= wx_stack_top
->x4
; 
2041     *y4 
= wx_stack_top
->y4
; 
2045 static bool wx_spline_add_point(double x
, double y
) 
2047   wxPoint 
*point 
= new wxPoint 
; 
2050   wx_spline_point_list
.Append((wxObject
*)point
); 
2054 static void wx_spline_draw_point_array(wxDC 
*dc
) 
2056   dc
->DrawLines(&wx_spline_point_list
, 0, 0 ); 
2057   wxNode 
*node 
= wx_spline_point_list
.First(); 
2060     wxPoint 
*point 
= (wxPoint 
*)node
->Data(); 
2063     node 
= wx_spline_point_list
.First(); 
2067 void wxWindowDC::DoDrawSpline( wxList 
*points 
) 
2069     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
2072     double           cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
; 
2073     double           x1
, y1
, x2
, y2
; 
2075     wxNode 
*node 
= points
->First(); 
2076     p 
= (wxPoint 
*)node
->Data(); 
2081     node 
= node
->Next(); 
2082     p 
= (wxPoint 
*)node
->Data(); 
2086     cx1 
= (double)((x1 
+ x2
) / 2); 
2087     cy1 
= (double)((y1 
+ y2
) / 2); 
2088     cx2 
= (double)((cx1 
+ x2
) / 2); 
2089     cy2 
= (double)((cy1 
+ y2
) / 2); 
2091     wx_spline_add_point(x1
, y1
); 
2093     while ((node 
= node
->Next()) != NULL
) 
2095         p 
= (wxPoint 
*)node
->Data(); 
2100         cx4 
= (double)(x1 
+ x2
) / 2; 
2101         cy4 
= (double)(y1 
+ y2
) / 2; 
2102         cx3 
= (double)(x1 
+ cx4
) / 2; 
2103         cy3 
= (double)(y1 
+ cy4
) / 2; 
2105         wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
); 
2109         cx2 
= (double)(cx1 
+ x2
) / 2; 
2110         cy2 
= (double)(cy1 
+ y2
) / 2; 
2113     wx_spline_add_point( cx1
, cy1 
); 
2114     wx_spline_add_point( x2
, y2 
); 
2116     wx_spline_draw_point_array( this ); 
2119 #endif // wxUSE_SPLINE 
2121 //----------------------------------------------------------------------------- 
2123 //----------------------------------------------------------------------------- 
2125 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
,wxWindowDC
) 
2127 wxPaintDC::wxPaintDC() 
2132 wxPaintDC::wxPaintDC( wxWindow 
*win 
) 
2135 #if USE_PAINT_REGION 
2136     if (!win
->m_clipPaintRegion
) 
2139     m_paintClippingRegion 
= win
->GetUpdateRegion(); 
2140     GdkRegion 
*region 
= m_paintClippingRegion
.GetRegion(); 
2143         m_currentClippingRegion
.Union( m_paintClippingRegion 
); 
2145         gdk_gc_set_clip_region( m_penGC
, region 
); 
2146         gdk_gc_set_clip_region( m_brushGC
, region 
); 
2147         gdk_gc_set_clip_region( m_textGC
, region 
); 
2148         gdk_gc_set_clip_region( m_bgGC
, region 
); 
2153 //----------------------------------------------------------------------------- 
2155 //----------------------------------------------------------------------------- 
2157 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
,wxWindowDC
) 
2159 wxClientDC::wxClientDC() 
2164 wxClientDC::wxClientDC( wxWindow 
*win 
) 
2169 // ---------------------------------------------------------------------------- 
2171 // ---------------------------------------------------------------------------- 
2173 class wxDCModule 
: public wxModule
 
2180     DECLARE_DYNAMIC_CLASS(wxDCModule
) 
2183 IMPLEMENT_DYNAMIC_CLASS(wxDCModule
, wxModule
) 
2185 bool wxDCModule::OnInit() 
2191 void wxDCModule::OnExit()