1 ///////////////////////////////////////////////////////////////////////////// 
   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" 
  22 //----------------------------------------------------------------------------- 
  24 //----------------------------------------------------------------------------- 
  34 static GdkPixmap  
*hatches
[num_hatches
]; 
  35 static GdkPixmap 
**hatch_bitmap 
= (GdkPixmap 
**) NULL
; 
  37 //----------------------------------------------------------------------------- 
  39 //----------------------------------------------------------------------------- 
  41 #define RAD2DEG 57.2957795131 
  43 //----------------------------------------------------------------------------- 
  44 // temporary implementation of the missing GDK function 
  45 //----------------------------------------------------------------------------- 
  47 #include "gdk/gdkprivate.h" 
  49 void gdk_draw_bitmap     (GdkDrawable  
*drawable
, 
  59     GdkWindowPrivate 
*drawable_private
; 
  60     GdkWindowPrivate 
*src_private
; 
  61     GdkGCPrivate 
*gc_private
; 
  63     g_return_if_fail (drawable 
!= NULL
); 
  64     g_return_if_fail (src 
!= NULL
); 
  65     g_return_if_fail (gc 
!= NULL
); 
  67     drawable_private 
= (GdkWindowPrivate
*) drawable
; 
  68     src_private 
= (GdkWindowPrivate
*) src
; 
  69     if (drawable_private
->destroyed 
|| src_private
->destroyed
) 
  72     gc_private 
= (GdkGCPrivate
*) gc
; 
  74     if (width 
== -1) width 
= src_private
->width
; 
  75     if (height 
== -1) height 
= src_private
->height
; 
  77     XCopyPlane( drawable_private
->xdisplay
, 
  79                 drawable_private
->xwindow
, 
  87 //----------------------------------------------------------------------------- 
  89 //----------------------------------------------------------------------------- 
  91 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
) 
  93 wxWindowDC::wxWindowDC() 
  95     m_penGC 
= (GdkGC 
*) NULL
; 
  96     m_brushGC 
= (GdkGC 
*) NULL
; 
  97     m_textGC 
= (GdkGC 
*) NULL
; 
  98     m_bgGC 
= (GdkGC 
*) NULL
; 
  99     m_cmap 
= (GdkColormap 
*) NULL
; 
 101     m_owner 
= (wxWindow 
*)NULL
; 
 104 wxWindowDC::wxWindowDC( wxWindow 
*window 
) 
 106     m_penGC 
= (GdkGC 
*) NULL
; 
 107     m_brushGC 
= (GdkGC 
*) NULL
; 
 108     m_textGC 
= (GdkGC 
*) NULL
; 
 109     m_bgGC 
= (GdkGC 
*) NULL
; 
 110     m_cmap 
= (GdkColormap 
*) NULL
; 
 111     m_owner 
= (wxWindow 
*)NULL
; 
 116     GtkWidget 
*widget 
= window
->m_wxwindow
; 
 120     m_window 
= widget
->window
; 
 125          /* force realization */ 
 126          gtk_widget_realize( widget 
); 
 127          m_window 
= widget
->window
; 
 130     /* still not realized ? */ 
 134     if (window
->m_wxwindow
) 
 135         m_cmap 
= gtk_widget_get_colormap( window
->m_wxwindow 
); 
 137         m_cmap 
= gtk_widget_get_colormap( window
->m_widget 
); 
 143     /* this must be done after SetUpDC, bacause SetUpDC calls the 
 144        repective SetBrush, SetPen, SetBackground etc functions 
 145        to set up the DC. SetBackground call m_owner->SetBackground 
 146        and this might not be desired as the standard dc background 
 147        is white whereas a window might assume gray to be the 
 148        standard (as e.g. wxStatusBar) */ 
 153 wxWindowDC::~wxWindowDC() 
 158 void wxWindowDC::DoFloodFill( long WXUNUSED(x
), long WXUNUSED(y
),  
 159                            const wxColour 
&WXUNUSED(col
), int WXUNUSED(style
) ) 
 161     wxFAIL_MSG( _T("wxWindowDC::DoFloodFill not implemented") ); 
 164 bool wxWindowDC::DoGetPixel( long WXUNUSED(x1
), long WXUNUSED(y1
), wxColour 
*WXUNUSED(col
) ) const 
 166     wxFAIL_MSG( _T("wxWindowDC::DoGetPixel not implemented") ); 
 170 void wxWindowDC::DoDrawLine( long x1
, long y1
, long x2
, long y2 
) 
 172     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 174     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 176         gdk_draw_line( m_window
, m_penGC
,  
 177                        XLOG2DEV(x1
), YLOG2DEV(y1
), XLOG2DEV(x2
), YLOG2DEV(y2
) ); 
 179         CalcBoundingBox(x1
, y1
); 
 180         CalcBoundingBox(x2
, y2
); 
 184 void wxWindowDC::DoCrossHair( long x
, long y 
) 
 186     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 188     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 193         long xx 
= XLOG2DEV(x
); 
 194         long yy 
= YLOG2DEV(y
); 
 195         gdk_draw_line( m_window
, m_penGC
, 0, yy
, XLOG2DEVREL(w
), yy 
); 
 196         gdk_draw_line( m_window
, m_penGC
, xx
, 0, xx
, YLOG2DEVREL(h
) ); 
 200 void wxWindowDC::DoDrawArc( long x1
, long y1
, long x2
, long y2
, 
 203     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 205     long xx1 
= XLOG2DEV(x1
);  
 206     long yy1 
= YLOG2DEV(y1
); 
 207     long xx2 
= XLOG2DEV(x2
);  
 208     long yy2 
= YLOG2DEV(y2
); 
 209     long xxc 
= XLOG2DEV(xc
);  
 210     long yyc 
= YLOG2DEV(yc
); 
 211     double dx 
= xx1 
- xxc
;  
 212     double dy 
= yy1 
- yyc
; 
 213     double radius 
= sqrt(dx
*dx
+dy
*dy
); 
 214     long   r      
= (long)radius
; 
 215     double radius1
, radius2
; 
 217     if (xx1 
== xx2 
&& yy1 
== yy2
)  
 225         radius1 
= radius2 
= 0.0; 
 229         radius1 
= (xx1 
- xxc 
== 0) ? 
 230             (yy1 
- yyc 
< 0) ? 90.0 : -90.0 : 
 231             -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
; 
 232         radius2 
= (xx2 
- xxc 
== 0) ? 
 233             (yy2 
- yyc 
< 0) ? 90.0 : -90.0 : 
 234             -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
; 
 236     long alpha1 
= long(radius1 
* 64.0); 
 237     long alpha2 
= long((radius2 
- radius1
) * 64.0); 
 238     while (alpha2 
<= 0) alpha2 
+= 360*64; 
 239     while (alpha1 
> 360*64) alpha1 
-= 360*64; 
 241     if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 242         gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 244     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 245         gdk_draw_arc( m_window
, m_penGC
, FALSE
, xxc
-r
, yyc
-r
, 2*r
,2*r
, alpha1
, alpha2 
); 
 247     CalcBoundingBox (x1
, y1
); 
 248     CalcBoundingBox (x2
, y2
); 
 251 void wxWindowDC::DoDrawEllipticArc( long x
, long y
, long width
, long height
, double sa
, double ea 
) 
 253     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 255     long xx 
= XLOG2DEV(x
);     
 256     long yy 
= YLOG2DEV(y
); 
 257     long ww 
= m_signX 
* XLOG2DEVREL(width
);  
 258     long hh 
= m_signY 
* YLOG2DEVREL(height
); 
 260     // CMB: handle -ve width and/or height 
 261     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 262     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 264     long start 
= long(sa 
* 64.0); 
 265     long end 
= long(ea 
* 64.0); 
 266     if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 267         gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, start
, end 
); 
 269     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 270         gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, start
, end 
); 
 272     CalcBoundingBox (x
, y
); 
 273     CalcBoundingBox (x 
+ width
, y 
+ height
); 
 276 void wxWindowDC::DoDrawPoint( long x
, long y 
) 
 278     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 280     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 281         gdk_draw_point( m_window
, m_penGC
, XLOG2DEV(x
), YLOG2DEV(y
) ); 
 283     CalcBoundingBox (x
, y
); 
 286 void wxWindowDC::DoDrawLines( int n
, wxPoint points
[], long xoffset
, long yoffset 
) 
 288     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 290     if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 293     CalcBoundingBox( points
[0].x 
+ xoffset
, points
[0].y 
+ yoffset 
); 
 295     for (int i 
= 0; i 
< n
-1; i
++) 
 297         long x1 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 298         long x2 
= XLOG2DEV(points
[i
+1].x 
+ xoffset
); 
 299         long y1 
= YLOG2DEV(points
[i
].y 
+ yoffset
);     // oh, what a waste 
 300         long y2 
= YLOG2DEV(points
[i
+1].y 
+ yoffset
); 
 301         gdk_draw_line( m_window
, m_penGC
, x1
, y1
, x2
, y2 
); 
 303         CalcBoundingBox( points
[i
+1].x 
+ xoffset
, points
[i
+1].y 
+ yoffset 
); 
 307 void wxWindowDC::DoDrawPolygon( int n
, wxPoint points
[], long xoffset
, long yoffset
, int WXUNUSED(fillStyle
) ) 
 309     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 313     GdkPoint 
*gdkpoints 
= new GdkPoint
[n
+1]; 
 315     for (i 
= 0 ; i 
< n 
; i
++) 
 317         gdkpoints
[i
].x 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 318         gdkpoints
[i
].y 
= YLOG2DEV(points
[i
].y 
+ yoffset
); 
 320         CalcBoundingBox( points
[i
].x 
+ xoffset
, points
[i
].y 
+ yoffset 
); 
 323     if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 324         gdk_draw_polygon (m_window
, m_brushGC
, TRUE
, gdkpoints
, n
); 
 328     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 329         for (i 
= 0 ; i 
< n 
; i
++) 
 331             gdk_draw_line( m_window
, m_penGC
,  
 334                            gdkpoints
[(i
+1)%n
].x
, 
 335                            gdkpoints
[(i
+1)%n
].y
); 
 341 void wxWindowDC::DoDrawRectangle( long x
, long y
, long width
, long height 
) 
 343     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 345     long xx 
= XLOG2DEV(x
); 
 346     long yy 
= YLOG2DEV(y
); 
 347     long ww 
= m_signX 
* XLOG2DEVREL(width
); 
 348     long hh 
= m_signY 
* YLOG2DEVREL(height
); 
 350     // CMB: draw nothing if transformed w or h is 0 
 351     if (ww 
== 0 || hh 
== 0) return; 
 353     // CMB: handle -ve width and/or height 
 354     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 355     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 357     if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 358       gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh 
); 
 360     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 361       gdk_draw_rectangle( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
-1, hh
-1 ); 
 363     CalcBoundingBox( x
, y 
); 
 364     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 367 void wxWindowDC::DoDrawRoundedRectangle( long x
, long y
, long width
, long height
, double radius 
) 
 369     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 371     if (radius 
< 0.0) radius 
= - radius 
* ((width 
< height
) ? width 
: height
); 
 373     long xx 
= XLOG2DEV(x
);     
 374     long yy 
= YLOG2DEV(y
); 
 375     long ww 
= m_signX 
* XLOG2DEVREL(width
);  
 376     long hh 
= m_signY 
* YLOG2DEVREL(height
); 
 377     long rr 
= XLOG2DEVREL((long)radius
); 
 379     // CMB: handle -ve width and/or height 
 380     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 381     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 383     // CMB: if radius is zero use DrawRectangle() instead to avoid 
 384     // X drawing errors with small radii 
 387         DrawRectangle( x
, y
, width
, height 
); 
 391     // CMB: draw nothing if transformed w or h is 0 
 392     if (ww 
== 0 || hh 
== 0) return; 
 394     // CMB: adjust size if outline is drawn otherwise the result is 
 395     // 1 pixel too wide and high 
 396     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 402     // CMB: ensure dd is not larger than rectangle otherwise we 
 403     // get an hour glass shape 
 405     if (dd 
> ww
) dd 
= ww
; 
 406     if (dd 
> hh
) dd 
= hh
; 
 409     if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 411         gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
+rr
, yy
, ww
-dd
+1, hh 
); 
 412         gdk_draw_rectangle( m_window
, m_brushGC
, TRUE
, xx
, yy
+rr
, ww
, hh
-dd
+1 ); 
 413         gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 414         gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 415         gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 416         gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 419     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 421         gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
, xx
+ww
-rr
, yy 
); 
 422         gdk_draw_line( m_window
, m_penGC
, xx
+rr
, yy
+hh
, xx
+ww
-rr
, yy
+hh 
); 
 423         gdk_draw_line( m_window
, m_penGC
, xx
, yy
+rr
, xx
, yy
+hh
-rr 
); 
 424         gdk_draw_line( m_window
, m_penGC
, xx
+ww
, yy
+rr
, xx
+ww
, yy
+hh
-rr 
); 
 425         gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, dd
, dd
, 90*64, 90*64 ); 
 426         gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
, dd
, dd
, 0, 90*64 ); 
 427         gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
+ww
-dd
, yy
+hh
-dd
, dd
, dd
, 270*64, 90*64 ); 
 428         gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
+hh
-dd
, dd
, dd
, 180*64, 90*64 ); 
 431     // this ignores the radius 
 432     CalcBoundingBox( x
, y 
); 
 433     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 436 void wxWindowDC::DoDrawEllipse( long x
, long y
, long width
, long height 
) 
 438     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 440     long xx 
= XLOG2DEV(x
);     
 441     long yy 
= YLOG2DEV(y
); 
 442     long ww 
= m_signX 
* XLOG2DEVREL(width
);  
 443     long hh 
= m_signY 
* YLOG2DEVREL(height
); 
 445     // CMB: handle -ve width and/or height 
 446     if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 447     if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 449     if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 450         gdk_draw_arc( m_window
, m_brushGC
, TRUE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
 452     if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 453         gdk_draw_arc( m_window
, m_penGC
, FALSE
, xx
, yy
, ww
, hh
, 0, 360*64 ); 
 455     CalcBoundingBox( x 
- width
, y 
- height 
); 
 456     CalcBoundingBox( x 
+ width
, y 
+ height 
); 
 459 void wxWindowDC::DoDrawIcon( const wxIcon 
&icon
, long x
, long y 
) 
 461     // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why 
 462     DoDrawBitmap( (const wxBitmap
&)icon
, x
, y
, (bool)TRUE 
); 
 465 void wxWindowDC::DoDrawBitmap( const wxBitmap 
&bitmap
, 
 469     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 471     wxCHECK_RET( bitmap
.Ok(), _T("invalid bitmap") ); 
 473     /* scale/translate size and position */ 
 475     int xx 
= XLOG2DEV(x
); 
 476     int yy 
= YLOG2DEV(y
); 
 478     int w 
= bitmap
.GetWidth(); 
 479     int h 
= bitmap
.GetHeight(); 
 481     int ww 
= XLOG2DEVREL(w
); 
 482     int hh 
= YLOG2DEVREL(h
); 
 484     /* scale bitmap if required */ 
 488     if ((w 
!= ww
) || (h 
!= hh
)) 
 490         wxImage 
image( bitmap 
); 
 491         image 
= image
.Scale( ww
, hh 
); 
 493         use_bitmap 
= image
.ConvertToBitmap(); 
 500     /* apply mask if any */ 
 502     GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
 503     if (use_bitmap
.GetMask()) mask 
= use_bitmap
.GetMask()->GetBitmap(); 
 507         gdk_gc_set_clip_mask( m_penGC
, mask 
); 
 508         gdk_gc_set_clip_origin( m_penGC
, xx
, yy 
); 
 511     /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */ 
 513     GdkPixmap 
*pm 
= use_bitmap
.GetPixmap(); 
 516         gdk_draw_pixmap( m_window
, m_penGC
, pm
, 0, 0, xx
, yy
, -1, -1 ); 
 520         GdkBitmap 
*bm 
= use_bitmap
.GetBitmap(); 
 523             gdk_draw_bitmap( m_window
, m_penGC
, bm
, 0, 0, xx
, yy
, -1, -1 ); 
 527     /* remove mask again if any */ 
 531         gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap 
*) NULL 
); 
 532         gdk_gc_set_clip_origin( m_penGC
, 0, 0 ); 
 535     CalcBoundingBox( x
, y 
); 
 536     CalcBoundingBox( x 
+ w
, y 
+ h 
); 
 539 bool wxWindowDC::DoBlit( long xdest
, long ydest
, long width
, long height
, 
 540                          wxDC 
*source
, long xsrc
, long ysrc
, 
 541                          int logical_func
, bool useMask 
) 
 543    /* this is the nth try to get this utterly useless function to 
 544       work. it now completely ignores the scaling or translation 
 545       of the source dc, but scales correctly on the target dc and 
 546       knows about possible mask information in a memory dc. */ 
 548     wxCHECK_MSG( Ok(), FALSE
, _T("invalid window dc") ); 
 550     wxCHECK_MSG( source
, FALSE
, _T("invalid source dc") ); 
 552     wxClientDC 
*srcDC 
= (wxClientDC
*)source
; 
 553     wxMemoryDC 
*memDC 
= (wxMemoryDC
*)source
; 
 555     bool use_bitmap_method 
= FALSE
; 
 557     if (srcDC
->m_isMemDC
) 
 559         if (!memDC
->m_selected
.Ok()) return FALSE
; 
 561         /* we use the "XCopyArea" way to copy a memory dc into 
 562            y different window if the memory dc BOTH 
 563            a) doesn't have any mask or its mask isn't used 
 567         if (useMask 
&& (memDC
->m_selected
.GetMask())) 
 569            /* we HAVE TO use the direct way for memory dcs 
 570               that have mask since the XCopyArea doesn't know 
 572             use_bitmap_method 
= TRUE
; 
 574         else if (memDC
->m_selected
.GetDepth() == 1) 
 576            /* we HAVE TO use the direct way for memory dcs 
 577               that are bitmaps because XCopyArea doesn't cope 
 578               with different bit depths */ 
 579             use_bitmap_method 
= TRUE
; 
 581         else if ((xsrc 
== 0) && (ysrc 
== 0) && 
 582                  (width 
== memDC
->m_selected
.GetWidth()) && 
 583                  (height 
== memDC
->m_selected
.GetHeight())) 
 585            /* we SHOULD use the direct way if all of the bitmap  
 586               in the memory dc is copied in which case XCopyArea  
 587               wouldn't be able able to boost performace by reducing  
 588               the area to be scaled */ 
 589             use_bitmap_method 
= TRUE
; 
 593             use_bitmap_method 
= FALSE
; 
 597     CalcBoundingBox( xdest
, ydest 
); 
 598     CalcBoundingBox( xdest 
+ width
, ydest 
+ height 
); 
 600     int old_logical_func 
= m_logicalFunction
; 
 601     SetLogicalFunction( logical_func 
); 
 603     if (use_bitmap_method
) 
 605         /* scale/translate bitmap size */ 
 607         long bm_width 
= memDC
->m_selected
.GetWidth(); 
 608         long bm_height 
= memDC
->m_selected
.GetHeight(); 
 610         long bm_ww 
= XLOG2DEVREL( bm_width 
); 
 611         long bm_hh 
= YLOG2DEVREL( bm_height 
); 
 613         /* scale bitmap if required */ 
 617         if ((bm_width 
!= bm_ww
) || (bm_height 
!= bm_hh
)) 
 619             wxImage 
image( memDC
->m_selected 
); 
 620             image 
= image
.Scale( bm_ww
, bm_hh 
); 
 622             use_bitmap 
= image
.ConvertToBitmap(); 
 626             use_bitmap 
= memDC
->m_selected
; 
 629         /* scale/translate size and position */ 
 631         long xx 
= XLOG2DEV(xdest
); 
 632         long yy 
= YLOG2DEV(ydest
); 
 634         long ww 
= XLOG2DEVREL(width
); 
 635         long hh 
= YLOG2DEVREL(height
); 
 637         /* apply mask if any */ 
 639         GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
 640         if (use_bitmap
.GetMask()) mask 
= use_bitmap
.GetMask()->GetBitmap(); 
 644             gdk_gc_set_clip_mask( m_penGC
, mask 
); 
 645             gdk_gc_set_clip_origin( m_penGC
, xx
, yy 
); 
 648         /* draw XPixmap or XBitmap, depending on what the wxBitmap contains */ 
 650         GdkPixmap 
*pm 
= use_bitmap
.GetPixmap(); 
 653             gdk_draw_pixmap( m_window
, m_penGC
, pm
, xsrc
, ysrc
, xx
, yy
, ww
, hh 
); 
 657             GdkBitmap 
*bm 
= use_bitmap
.GetBitmap(); 
 660                 /* we use the textGC here because blitting a bitmap is done 
 661                    using the current text colour */ 
 662                 gdk_draw_bitmap( m_window
, m_textGC
, bm
, xsrc
, ysrc
, xx
, yy
, ww
, hh 
); 
 666         /* remove mask again if any */ 
 670             gdk_gc_set_clip_mask( m_penGC
, (GdkBitmap 
*) NULL 
); 
 671             gdk_gc_set_clip_origin( m_penGC
, 0, 0 ); 
 674     else /* use_bitmap_method */ 
 676         /* scale/translate size and position */ 
 678         long xx 
= XLOG2DEV(xdest
); 
 679         long yy 
= YLOG2DEV(ydest
); 
 681         long ww 
= XLOG2DEVREL(width
); 
 682         long hh 
= YLOG2DEVREL(height
); 
 684         if ((width 
!= ww
) || (height 
!= hh
)) 
 686             /* draw source window into a bitmap as we cannot scale 
 687                a window in contrast to a bitmap. this would actually 
 688                work with memory dcs as well, but we'd lose the mask 
 689                information and waste one step in this process since 
 690                a memory already has a bitmap. all this is slightly 
 691                inefficient as we could take an XImage directly from 
 692                an X window, but we'd then also have to care that 
 693                the window is not outside the screen (in which case 
 694                we'd get a BadMatch or what not). 
 695                Is a double XGetImage and combined XGetPixel and 
 696                XPutPixel really faster? I'm not sure. look at wxXt 
 697                for a different implementation of the same problem. */ 
 699             wxBitmap 
bitmap( width
, height 
); 
 700             gdk_window_copy_area( bitmap
.GetPixmap(), m_penGC
, 0, 0,  
 702                                   xsrc
, ysrc
, width
, height 
); 
 706             wxImage 
image( bitmap 
); 
 707             image 
= image
.Scale( ww
, hh 
); 
 709             /* convert to bitmap */ 
 711             bitmap 
= image
.ConvertToBitmap(); 
 713             /* draw scaled bitmap */ 
 715             gdk_draw_pixmap( m_window
, m_penGC
, bitmap
.GetPixmap(), 0, 0, xx
, yy
, -1, -1 ); 
 720             /* no scaling and not a memory dc with a mask either */ 
 722             gdk_window_copy_area( m_window
, m_penGC
, xx
, yy
, 
 724                                   xsrc
, ysrc
, width
, height 
); 
 728     SetLogicalFunction( old_logical_func 
); 
 732 void wxWindowDC::DoDrawText( const wxString 
&text
, long x
, long y 
) 
 734     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 736     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
 741     /* CMB 21/5/98: draw text background if mode is wxSOLID */ 
 742     if (m_backgroundMode 
== wxSOLID
) 
 744         long width 
= gdk_string_width( font
, text
.mbc_str() ); 
 745         long height 
= font
->ascent 
+ font
->descent
; 
 746         gdk_gc_set_foreground( m_textGC
, m_textBackgroundColour
.GetColor() ); 
 747         gdk_draw_rectangle( m_window
, m_textGC
, TRUE
, x
, y
, width
, height 
); 
 748         gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
 750     gdk_draw_string( m_window
, font
, m_textGC
, x
, y 
+ font
->ascent
, text
.mbc_str() ); 
 752     /* CMB 17/7/98: simple underline: ignores scaling and underlying 
 753        X font's XA_UNDERLINE_POSITION and XA_UNDERLINE_THICKNESS 
 754        properties (see wxXt implementation) */ 
 755     if (m_font
.GetUnderlined()) 
 757         long width 
= gdk_string_width( font
, text
.mbc_str() ); 
 758         long ul_y 
= y 
+ font
->ascent
; 
 759         if (font
->descent 
> 0) ul_y
++; 
 760         gdk_draw_line( m_window
, m_textGC
, x
, ul_y
, x 
+ width
, ul_y
); 
 764     GetTextExtent (text
, &w
, &h
); 
 765     CalcBoundingBox (x 
+ w
, y 
+ h
); 
 766     CalcBoundingBox (x
, y
); 
 769 void wxWindowDC::GetTextExtent( const wxString 
&string
, long *width
, long *height
, 
 770                                 long *descent
, long *externalLeading
, 
 771                                 wxFont 
*theFont 
) const 
 773     wxFont fontToUse 
= m_font
; 
 774     if (theFont
) fontToUse 
= *theFont
; 
 776     GdkFont 
*font 
= fontToUse
.GetInternalFont( m_scaleY 
); 
 777     if (width
) (*width
) = long(gdk_string_width( font
, string
.mbc_str() ) / m_scaleX
); 
 778     if (height
) (*height
) = long((font
->ascent 
+ font
->descent
) / m_scaleY
); 
 779     if (descent
) (*descent
) = long(font
->descent 
/ m_scaleY
); 
 780     if (externalLeading
) (*externalLeading
) = 0;  // ?? 
 783 long wxWindowDC::GetCharWidth() const 
 785     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
 786     return long(gdk_string_width( font
, "H" ) / m_scaleX
); 
 789 long wxWindowDC::GetCharHeight() const 
 791     GdkFont 
*font 
= m_font
.GetInternalFont( m_scaleY 
); 
 792     return long((font
->ascent 
+ font
->descent
) / m_scaleY
); 
 795 void wxWindowDC::Clear() 
 797     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 799     /* - we either are a memory dc or have a window as the 
 800        owner. anything else shouldn't happen. 
 801        - we don't use gdk_window_clear() as we don't set 
 802        the window's background colour anymore. it is too 
 803        much pain to keep the DC's and the window's back- 
 804        ground colour in synch. */ 
 809         m_owner
->GetSize( &width
, &height 
); 
 810         gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height 
); 
 817         GetSize( &width
, &height 
); 
 818         gdk_draw_rectangle( m_window
, m_bgGC
, TRUE
, 0, 0, width
, height 
); 
 823 void wxWindowDC::SetFont( const wxFont 
&font 
) 
 828 void wxWindowDC::SetPen( const wxPen 
&pen 
) 
 830     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 832     if (m_pen 
== pen
) return; 
 836     if (!m_pen
.Ok()) return; 
 838     gint width 
= m_pen
.GetWidth(); 
 839     // CMB: if width is non-zero scale it with the dc 
 846         // X doesn't allow different width in x and y and so we take 
 848         double w 
= 0.5 + (abs(XLOG2DEVREL(width
)) + abs(YLOG2DEVREL(width
))) / 2.0; 
 852     GdkLineStyle lineStyle 
= GDK_LINE_SOLID
; 
 853     switch (m_pen
.GetStyle()) 
 855         case wxSOLID
:      { lineStyle 
= GDK_LINE_SOLID
;       break; } 
 856         case wxDOT
:        { lineStyle 
= GDK_LINE_ON_OFF_DASH
; break; } 
 857         case wxLONG_DASH
:  { lineStyle 
= GDK_LINE_ON_OFF_DASH
; break; } 
 858         case wxSHORT_DASH
: { lineStyle 
= GDK_LINE_ON_OFF_DASH
; break; } 
 859         case wxDOT_DASH
:   { lineStyle 
= GDK_LINE_DOUBLE_DASH
; break; } 
 862     GdkCapStyle capStyle 
= GDK_CAP_ROUND
; 
 863     switch (m_pen
.GetCap()) 
 865         case wxCAP_ROUND
:      { capStyle 
= (width 
<= 1) ? GDK_CAP_NOT_LAST 
: GDK_CAP_ROUND
; break; } 
 866         case wxCAP_PROJECTING
: { capStyle 
= GDK_CAP_PROJECTING
; break; } 
 867         case wxCAP_BUTT
:       { capStyle 
= GDK_CAP_BUTT
;       break; } 
 870     GdkJoinStyle joinStyle 
= GDK_JOIN_ROUND
; 
 871     switch (m_pen
.GetJoin()) 
 873         case wxJOIN_BEVEL
: { joinStyle 
= GDK_JOIN_BEVEL
; break; } 
 874         case wxJOIN_ROUND
: { joinStyle 
= GDK_JOIN_ROUND
; break; } 
 875         case wxJOIN_MITER
: { joinStyle 
= GDK_JOIN_MITER
; break; } 
 878     gdk_gc_set_line_attributes( m_penGC
, width
, lineStyle
, capStyle
, joinStyle 
); 
 880     m_pen
.GetColour().CalcPixel( m_cmap 
); 
 881     gdk_gc_set_foreground( m_penGC
, m_pen
.GetColour().GetColor() ); 
 884 void wxWindowDC::SetBrush( const wxBrush 
&brush 
) 
 886     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 888     if (m_brush 
== brush
) return; 
 892     if (!m_brush
.Ok()) return; 
 894     m_brush
.GetColour().CalcPixel( m_cmap 
); 
 895     gdk_gc_set_foreground( m_brushGC
, m_brush
.GetColour().GetColor() ); 
 897     GdkFill fillStyle 
= GDK_SOLID
; 
 898     switch (m_brush
.GetStyle()) 
 904          fillStyle 
= GDK_STIPPLED
; 
 907     gdk_gc_set_fill( m_brushGC
, fillStyle 
); 
 909     if ((m_brush
.GetStyle() == wxSTIPPLE
) && (m_brush
.GetStipple()->Ok())) 
 911         if (m_brush
.GetStipple()->GetPixmap()) 
 912             gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetPixmap() ); 
 914             gdk_gc_set_stipple( m_brushGC
, m_brush
.GetStipple()->GetBitmap() ); 
 917     if (IS_HATCH(m_brush
.GetStyle())) 
 919         int num 
= m_brush
.GetStyle() - wxBDIAGONAL_HATCH
; 
 920         gdk_gc_set_stipple( m_brushGC
, hatches
[num
] ); 
 924 void wxWindowDC::SetBackground( const wxBrush 
&brush 
) 
 926    /* CMB 21/7/98: Added SetBackground. Sets background brush 
 927     * for Clear() and bg colour for shapes filled with cross-hatch brush */ 
 929     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 931     if (m_backgroundBrush 
== brush
) return; 
 933     m_backgroundBrush 
= brush
; 
 935     if (!m_backgroundBrush
.Ok()) return; 
 937     m_backgroundBrush
.GetColour().CalcPixel( m_cmap 
); 
 938     gdk_gc_set_background( m_brushGC
, m_backgroundBrush
.GetColour().GetColor() ); 
 939     gdk_gc_set_background( m_penGC
, m_backgroundBrush
.GetColour().GetColor() ); 
 940     gdk_gc_set_background( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() ); 
 941     gdk_gc_set_foreground( m_bgGC
, m_backgroundBrush
.GetColour().GetColor() ); 
 943     GdkFill fillStyle 
= GDK_SOLID
; 
 944     switch (m_backgroundBrush
.GetStyle()) 
 950             fillStyle 
= GDK_STIPPLED
; 
 953     gdk_gc_set_fill( m_bgGC
, fillStyle 
); 
 955     if (m_backgroundBrush
.GetStyle() == wxSTIPPLE
) 
 957         gdk_gc_set_stipple( m_bgGC
, m_backgroundBrush
.GetStipple()->GetPixmap() ); 
 960     if (IS_HATCH(m_backgroundBrush
.GetStyle())) 
 962         int num 
= m_backgroundBrush
.GetStyle() - wxBDIAGONAL_HATCH
; 
 963         gdk_gc_set_stipple( m_bgGC
, hatches
[num
] ); 
 967 void wxWindowDC::SetLogicalFunction( int function 
) 
 969     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
 971     if (m_logicalFunction 
== function
) return; 
 973     GdkFunction mode 
= GDK_COPY
; 
 976         case wxXOR
:          mode 
= GDK_INVERT
; break; 
 977         case wxINVERT
:       mode 
= GDK_XOR
; break; 
 978 #if (GDK_MINOR_VERSION > 0) 
 979         case wxOR_REVERSE
:   mode 
= GDK_OR_REVERSE
; break; 
 980         case wxAND_REVERSE
:  mode 
= GDK_AND_REVERSE
; break; 
 981         case wxCLEAR
:        mode 
= GDK_CLEAR
; break; 
 982         case wxSET
:          mode 
= GDK_SET
; break; 
 983         case wxOR_INVERT
:    mode 
= GDK_OR_INVERT
; break; 
 984         case wxAND
:          mode 
= GDK_AND
; break; 
 985         case wxOR
:           mode 
= GDK_OR
; break; 
 986         case wxEQUIV
:        mode 
= GDK_EQUIV
; break; 
 987         case wxNAND
:         mode 
= GDK_NAND
; break; 
 988         case wxAND_INVERT
:   mode 
= GDK_AND_INVERT
; break; 
 989 /*   ?   wxSRC_INVERT   GDK_AND_REVERSE, GDK_OR_REVERSE, GDK_OR_INVERT */ 
 994     m_logicalFunction 
= function
; 
 995     gdk_gc_set_function( m_penGC
, mode 
); 
 996     gdk_gc_set_function( m_brushGC
, mode 
); 
 997     gdk_gc_set_function( m_textGC
, mode 
); 
1000 void wxWindowDC::SetTextForeground( const wxColour 
&col 
) 
1002     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
1004     if (m_textForegroundColour 
== col
) return; 
1006     m_textForegroundColour 
= col
; 
1007     if (!m_textForegroundColour
.Ok()) return; 
1009     m_textForegroundColour
.CalcPixel( m_cmap 
); 
1010     gdk_gc_set_foreground( m_textGC
, m_textForegroundColour
.GetColor() ); 
1013 void wxWindowDC::SetTextBackground( const wxColour 
&col 
) 
1015     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
1017     if (m_textBackgroundColour 
== col
) return; 
1019     m_textBackgroundColour 
= col
; 
1020     if (!m_textBackgroundColour
.Ok()) return; 
1022     m_textBackgroundColour
.CalcPixel( m_cmap 
); 
1023     gdk_gc_set_background( m_textGC
, m_textBackgroundColour
.GetColor() ); 
1026 void wxWindowDC::SetBackgroundMode( int mode 
) 
1028     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
1030     m_backgroundMode 
= mode
; 
1032     // CMB 21/7/98: fill style of cross-hatch brushes is affected by 
1033     // transparent/solid background mode 
1035     if (m_brush
.GetStyle() != wxSOLID 
&& m_brush
.GetStyle() != wxTRANSPARENT
) 
1037         gdk_gc_set_fill( m_brushGC
, 
1038           (m_backgroundMode 
== wxTRANSPARENT
) ? GDK_STIPPLED 
: GDK_OPAQUE_STIPPLED
); 
1042 void wxWindowDC::SetPalette( const wxPalette
& WXUNUSED(palette
) ) 
1044     wxFAIL_MSG( _T("wxWindowDC::SetPalette not implemented") ); 
1047 void wxWindowDC::DoSetClippingRegion( long x
, long y
, long width
, long height 
) 
1049     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
1051     wxDC::DoSetClippingRegion( x
, y
, width
, height 
); 
1054     rect
.x 
= XLOG2DEV(x
); 
1055     rect
.y 
= YLOG2DEV(y
); 
1056     rect
.width 
= XLOG2DEVREL(width
); 
1057     rect
.height 
= YLOG2DEVREL(height
); 
1058     gdk_gc_set_clip_rectangle( m_penGC
, &rect 
); 
1059     gdk_gc_set_clip_rectangle( m_brushGC
, &rect 
); 
1060     gdk_gc_set_clip_rectangle( m_textGC
, &rect 
); 
1061     gdk_gc_set_clip_rectangle( m_bgGC
, &rect 
); 
1064 void wxWindowDC::DoSetClippingRegionAsRegion( const wxRegion 
®ion  
) 
1066     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
1070         DestroyClippingRegion(); 
1074     gdk_gc_set_clip_region( m_penGC
, region
.GetRegion() ); 
1075     gdk_gc_set_clip_region( m_brushGC
, region
.GetRegion() ); 
1076     gdk_gc_set_clip_region( m_textGC
, region
.GetRegion() ); 
1077     gdk_gc_set_clip_region( m_bgGC
, region
.GetRegion() ); 
1080 void wxWindowDC::DestroyClippingRegion() 
1082     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
1084     wxDC::DestroyClippingRegion(); 
1086     gdk_gc_set_clip_rectangle( m_penGC
, (GdkRectangle 
*) NULL 
); 
1087     gdk_gc_set_clip_rectangle( m_brushGC
, (GdkRectangle 
*) NULL 
); 
1088     gdk_gc_set_clip_rectangle( m_textGC
, (GdkRectangle 
*) NULL 
); 
1089     gdk_gc_set_clip_rectangle( m_bgGC
, (GdkRectangle 
*) NULL 
); 
1092 void wxWindowDC::SetUpDC() 
1096     m_logicalFunction 
= wxCOPY
; 
1097     m_penGC 
= gdk_gc_new( m_window 
); 
1098     m_brushGC 
= gdk_gc_new( m_window 
); 
1099     m_textGC 
= gdk_gc_new( m_window 
); 
1100     m_bgGC 
= gdk_gc_new( m_window 
); 
1102     wxColour 
tmp_col( m_textForegroundColour 
); 
1103     m_textForegroundColour 
= wxNullColour
; 
1104     SetTextForeground( tmp_col 
); 
1105     tmp_col 
= m_textBackgroundColour
; 
1106     m_textBackgroundColour 
= wxNullColour
; 
1107     SetTextBackground( tmp_col 
); 
1109     wxPen 
tmp_pen( m_pen 
); 
1113     wxFont 
tmp_font( m_font 
); 
1114     m_font 
= wxNullFont
; 
1115     SetFont( tmp_font 
); 
1117     wxBrush 
tmp_brush( m_brush 
); 
1118     m_brush 
= wxNullBrush
; 
1119     SetBrush( tmp_brush 
); 
1121     tmp_brush 
= m_backgroundBrush
; 
1122     m_backgroundBrush 
= wxNullBrush
; 
1123     SetBackground( tmp_brush 
); 
1127         hatch_bitmap    
= hatches
; 
1128         hatch_bitmap
[0] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, bdiag_bits
, bdiag_width
, bdiag_height 
); 
1129         hatch_bitmap
[1] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, cdiag_bits
, cdiag_width
, cdiag_height 
); 
1130         hatch_bitmap
[2] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, fdiag_bits
, fdiag_width
, fdiag_height 
); 
1131         hatch_bitmap
[3] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, cross_bits
, cross_width
, cross_height 
); 
1132         hatch_bitmap
[4] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, horiz_bits
, horiz_width
, horiz_height 
); 
1133         hatch_bitmap
[5] = gdk_bitmap_create_from_data( (GdkWindow 
*) NULL
, verti_bits
, verti_width
, verti_height 
); 
1137 void wxWindowDC::Destroy() 
1139     if (m_penGC
) gdk_gc_unref( m_penGC 
); 
1140     m_penGC 
= (GdkGC
*) NULL
; 
1141     if (m_brushGC
) gdk_gc_unref( m_brushGC 
); 
1142     m_brushGC 
= (GdkGC
*) NULL
; 
1143     if (m_textGC
) gdk_gc_unref( m_textGC 
); 
1144     m_textGC 
= (GdkGC
*) NULL
; 
1145     if (m_bgGC
) gdk_gc_unref( m_bgGC 
); 
1146     m_bgGC 
= (GdkGC
*) NULL
; 
1149 // Resolution in pixels per logical inch 
1150 wxSize 
wxWindowDC::GetPPI() const 
1152     return wxSize(100, 100); 
1155 int wxWindowDC::GetDepth() const 
1157     wxFAIL_MSG(_T("not implemented")); 
1163 // ----------------------------------- spline code ---------------------------------------- 
1165 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, 
1166                          double a3
, double b3
, double a4
, double b4
); 
1167 void wx_clear_stack(); 
1168 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
, 
1169         double *y3
, double *x4
, double *y4
); 
1170 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, 
1171           double x4
, double y4
); 
1172 static bool wx_spline_add_point(double x
, double y
); 
1173 static void wx_spline_draw_point_array(wxDC 
*dc
); 
1175 wxList wx_spline_point_list
; 
1177 #define                half(z1, z2)        ((z1+z2)/2.0) 
1180 /* iterative version */ 
1182 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
, 
1185     register double  xmid
, ymid
; 
1186     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
1189     wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
); 
1191     while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) { 
1192         xmid 
= (double)half(x2
, x3
); 
1193         ymid 
= (double)half(y2
, y3
); 
1194         if (fabs(x1 
- xmid
) < THRESHOLD 
&& fabs(y1 
- ymid
) < THRESHOLD 
&& 
1195             fabs(xmid 
- x4
) < THRESHOLD 
&& fabs(ymid 
- y4
) < THRESHOLD
) { 
1196             wx_spline_add_point( x1
, y1 
); 
1197             wx_spline_add_point( xmid
, ymid 
); 
1199             wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
), 
1200                  (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
); 
1201             wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
), 
1202                  (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
); 
1207 /* utilities used by spline drawing routines */ 
1209 typedef struct wx_spline_stack_struct 
{ 
1210     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
1213 #define         SPLINE_STACK_DEPTH             20 
1214 static Stack    wx_spline_stack
[SPLINE_STACK_DEPTH
]; 
1215 static Stack   
*wx_stack_top
; 
1216 static int      wx_stack_count
; 
1218 void wx_clear_stack() 
1220     wx_stack_top 
= wx_spline_stack
; 
1224 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
) 
1226     wx_stack_top
->x1 
= x1
; 
1227     wx_stack_top
->y1 
= y1
; 
1228     wx_stack_top
->x2 
= x2
; 
1229     wx_stack_top
->y2 
= y2
; 
1230     wx_stack_top
->x3 
= x3
; 
1231     wx_stack_top
->y3 
= y3
; 
1232     wx_stack_top
->x4 
= x4
; 
1233     wx_stack_top
->y4 
= y4
; 
1238 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, 
1239                   double *x3
, double *y3
, double *x4
, double *y4
) 
1241     if (wx_stack_count 
== 0) 
1245     *x1 
= wx_stack_top
->x1
; 
1246     *y1 
= wx_stack_top
->y1
; 
1247     *x2 
= wx_stack_top
->x2
; 
1248     *y2 
= wx_stack_top
->y2
; 
1249     *x3 
= wx_stack_top
->x3
; 
1250     *y3 
= wx_stack_top
->y3
; 
1251     *x4 
= wx_stack_top
->x4
; 
1252     *y4 
= wx_stack_top
->y4
; 
1256 static bool wx_spline_add_point(double x
, double y
) 
1258   wxPoint 
*point 
= new wxPoint 
; 
1261   wx_spline_point_list
.Append((wxObject
*)point
); 
1265 static void wx_spline_draw_point_array(wxDC 
*dc
) 
1267   dc
->DrawLines(&wx_spline_point_list
, 0, 0 ); 
1268   wxNode 
*node 
= wx_spline_point_list
.First(); 
1271     wxPoint 
*point 
= (wxPoint 
*)node
->Data(); 
1274     node 
= wx_spline_point_list
.First(); 
1278 void wxWindowDC::DoDrawSpline( wxList 
*points 
) 
1280     wxCHECK_RET( Ok(), _T("invalid window dc") ); 
1283     double           cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
; 
1284     double           x1
, y1
, x2
, y2
; 
1286     wxNode 
*node 
= points
->First(); 
1287     p 
= (wxPoint 
*)node
->Data(); 
1292     node 
= node
->Next(); 
1293     p 
= (wxPoint 
*)node
->Data(); 
1297     cx1 
= (double)((x1 
+ x2
) / 2); 
1298     cy1 
= (double)((y1 
+ y2
) / 2); 
1299     cx2 
= (double)((cx1 
+ x2
) / 2); 
1300     cy2 
= (double)((cy1 
+ y2
) / 2); 
1302     wx_spline_add_point(x1
, y1
); 
1304     while ((node 
= node
->Next()) != NULL
) 
1306         p 
= (wxPoint 
*)node
->Data(); 
1311         cx4 
= (double)(x1 
+ x2
) / 2; 
1312         cy4 
= (double)(y1 
+ y2
) / 2; 
1313         cx3 
= (double)(x1 
+ cx4
) / 2; 
1314         cy3 
= (double)(y1 
+ cy4
) / 2; 
1316         wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
); 
1320         cx2 
= (double)(cx1 
+ x2
) / 2; 
1321         cy2 
= (double)(cy1 
+ y2
) / 2; 
1324     wx_spline_add_point( cx1
, cy1 
); 
1325     wx_spline_add_point( x2
, y2 
); 
1327     wx_spline_draw_point_array( this ); 
1330 #endif // wxUSE_SPLINE 
1332 //----------------------------------------------------------------------------- 
1334 //----------------------------------------------------------------------------- 
1336 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
,wxWindowDC
) 
1338 wxPaintDC::wxPaintDC() 
1343 wxPaintDC::wxPaintDC( wxWindow 
*win 
) 
1348 //----------------------------------------------------------------------------- 
1350 //----------------------------------------------------------------------------- 
1352 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
,wxWindowDC
) 
1354 wxClientDC::wxClientDC() 
1359 wxClientDC::wxClientDC( wxWindow 
*win 
)