1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxClientDC class 
   8 // Copyright:   (c) AUTHOR 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "dcclient.h" 
  16 #include "wx/dcclient.h" 
  17 #include "wx/dcmemory.h" 
  20 //----------------------------------------------------------------------------- 
  22 //----------------------------------------------------------------------------- 
  24 #define RAD2DEG 57.2957795131 
  26 //----------------------------------------------------------------------------- 
  28 //----------------------------------------------------------------------------- 
  30 //IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxDC) 
  31 //IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC) 
  32 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxDC
) 
  35 wxPaintDC::wxPaintDC(void) 
  39 wxPaintDC::wxPaintDC( wxWindow 
*window 
) 
  43 wxPaintDC::~wxPaintDC(void) 
  47 void wxPaintDC::FloodFill( long WXUNUSED(x1
), long WXUNUSED(y1
),  
  48   wxColour 
*WXUNUSED(col
), int WXUNUSED(style
) ) 
  52 bool wxPaintDC::GetPixel( long WXUNUSED(x1
), long WXUNUSED(y1
), wxColour 
*WXUNUSED(col
) ) const 
  57 void wxPaintDC::DrawLine( long x1
, long y1
, long x2
, long y2 
) 
  63 void wxPaintDC::CrossHair( long x
, long y 
) 
  69 void wxPaintDC::DrawArc( long x1
, long y1
, long x2
, long y2
, double xc
, double yc 
) 
  73   long xx1 
= XLOG2DEV(x1
);  
  74   long yy1 
= YLOG2DEV(y1
); 
  75   long xx2 
= XLOG2DEV(x2
);  
  76   long yy2 
= YLOG2DEV(y2
); 
  77   long xxc 
= XLOG2DEV((long)xc
);  
  78   long yyc 
= YLOG2DEV((long)yc
); 
  79   double dx 
= xx1 
- xxc
;  
  80   double dy 
= yy1 
- yyc
; 
  81   double radius 
= sqrt(dx
*dx
+dy
*dy
); 
  82   long   r      
= (long)radius
; 
  83   double radius1
, radius2
; 
  85   if (xx1 
== xx2 
&& yy1 
== yy2
)  
  93     radius1 
= radius2 
= 0.0; 
  97     radius1 
= (xx1 
- xxc 
== 0) ? 
  98             (yy1 
- yyc 
< 0) ? 90.0 : -90.0 : 
  99             -atan2(double(yy1
-yyc
), double(xx1
-xxc
)) * RAD2DEG
; 
 100     radius2 
= (xx2 
- xxc 
== 0) ? 
 101             (yy2 
- yyc 
< 0) ? 90.0 : -90.0 : 
 102             -atan2(double(yy2
-yyc
), double(xx2
-xxc
)) * RAD2DEG
; 
 104   long alpha1 
= long(radius1 
* 64.0); 
 105   long alpha2 
= long((radius2 
- radius1
) * 64.0); 
 106   while (alpha2 
<= 0) alpha2 
+= 360*64; 
 107   while (alpha1 
> 360*64) alpha1 
-= 360*64; 
 109   if (m_brush
.GetStyle() != wxTRANSPARENT
) {}; 
 111   if (m_pen
.GetStyle() != wxTRANSPARENT
) {}; 
 115 void wxPaintDC::DrawEllipticArc( long x
, long y
, long width
, long height
, double sa
, double ea 
) 
 119   long xx 
= XLOG2DEV(x
);     
 120   long yy 
= YLOG2DEV(y
); 
 121   long ww 
= m_signX 
* XLOG2DEVREL(width
);  
 122   long hh 
= m_signY 
* YLOG2DEVREL(height
); 
 124   // CMB: handle -ve width and/or height 
 125   if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 126   if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 128   long start 
= long(sa 
* 64.0); 
 129   long end 
= long(ea 
* 64.0); 
 130   if (m_brush
.GetStyle() != wxTRANSPARENT
) {}; 
 132   if (m_pen
.GetStyle() != wxTRANSPARENT
) {}; 
 135 void wxPaintDC::DrawPoint( long x
, long y 
) 
 139   if (m_pen
.GetStyle() != wxTRANSPARENT
) {}; 
 142 void wxPaintDC::DrawLines( int n
, wxPoint points
[], long xoffset
, long yoffset 
) 
 146   if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 148   for (int i 
= 0; i 
< n
-1; i
++) 
 150     long x1 
= XLOG2DEV(points
[i
].x 
+ xoffset
); 
 151     long x2 
= XLOG2DEV(points
[i
+1].x 
+ xoffset
); 
 152     long y1 
= YLOG2DEV(points
[i
].y 
+ yoffset
);     // oh, what a waste 
 153     long y2 
= YLOG2DEV(points
[i
+1].y 
+ yoffset
); 
 157 void wxPaintDC::DrawLines( wxList 
*points
, long xoffset
, long yoffset 
) 
 161   if (m_pen
.GetStyle() == wxTRANSPARENT
) return; 
 163   wxNode 
*node 
= points
->First(); 
 166     wxPoint 
*point 
= (wxPoint
*)node
->Data(); 
 167     wxPoint 
*npoint 
= (wxPoint
*)node
->Next()->Data(); 
 168     long x1 
= XLOG2DEV(point
->x 
+ xoffset
); 
 169     long x2 
= XLOG2DEV(npoint
->x 
+ xoffset
); 
 170     long y1 
= YLOG2DEV(point
->y 
+ yoffset
);    // and again... 
 171     long y2 
= YLOG2DEV(npoint
->y 
+ yoffset
); 
 176 void wxPaintDC::DrawPolygon( int WXUNUSED(n
), wxPoint 
WXUNUSED(points
)[],  
 177   long WXUNUSED(xoffset
), long WXUNUSED(yoffset
), int WXUNUSED(fillStyle
) ) 
 182 void wxPaintDC::DrawPolygon( wxList 
*WXUNUSED(lines
), long WXUNUSED(xoffset
),  
 183                              long WXUNUSED(yoffset
), int WXUNUSED(fillStyle
) ) 
 188 void wxPaintDC::DrawRectangle( long x
, long y
, long width
, long height 
) 
 192   long xx 
= XLOG2DEV(x
); 
 193   long yy 
= YLOG2DEV(y
); 
 194   long ww 
= m_signX 
* XLOG2DEVREL(width
); 
 195   long hh 
= m_signY 
* YLOG2DEVREL(height
); 
 197   // CMB: draw nothing if transformed w or h is 0 
 198   if (ww 
== 0 || hh 
== 0) return; 
 200   // CMB: handle -ve width and/or height 
 201   if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 202   if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 204   if (m_brush
.GetStyle() != wxTRANSPARENT
) {}; 
 206   if (m_pen
.GetStyle() != wxTRANSPARENT
) {}; 
 209 void wxPaintDC::DrawRoundedRectangle( long x
, long y
, long width
, long height
, double radius 
) 
 213   if (radius 
< 0.0) radius 
= - radius 
* ((width 
< height
) ? width 
: height
); 
 215   long xx 
= XLOG2DEV(x
);     
 216   long yy 
= YLOG2DEV(y
); 
 217   long ww 
= m_signX 
* XLOG2DEVREL(width
);  
 218   long hh 
= m_signY 
* YLOG2DEVREL(height
); 
 219   long rr 
= XLOG2DEVREL((long)radius
); 
 221   // CMB: handle -ve width and/or height 
 222   if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 223   if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 225   // CMB: if radius is zero use DrawRectangle() instead to avoid 
 226   // X drawing errors with small radii 
 229     DrawRectangle( x
, y
, width
, height 
); 
 233   // CMB: draw nothing if transformed w or h is 0 
 234   if (ww 
== 0 || hh 
== 0) return; 
 236   // CMB: adjust size if outline is drawn otherwise the result is 
 237   // 1 pixel too wide and high 
 238   if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 244   // CMB: ensure dd is not larger than rectangle otherwise we 
 245   // get an hour glass shape 
 247   if (dd 
> ww
) dd 
= ww
; 
 248   if (dd 
> hh
) dd 
= hh
; 
 251   if (m_brush
.GetStyle() != wxTRANSPARENT
) 
 255   if (m_pen
.GetStyle() != wxTRANSPARENT
) 
 260 void wxPaintDC::DrawEllipse( long x
, long y
, long width
, long height 
) 
 264   long xx 
= XLOG2DEV(x
);     
 265   long yy 
= YLOG2DEV(y
); 
 266   long ww 
= m_signX 
* XLOG2DEVREL(width
);  
 267   long hh 
= m_signY 
* YLOG2DEVREL(height
); 
 269   // CMB: handle -ve width and/or height 
 270   if (ww 
< 0) { ww 
= -ww
; xx 
= xx 
- ww
; } 
 271   if (hh 
< 0) { hh 
= -hh
; yy 
= yy 
- hh
; } 
 273   if (m_brush
.GetStyle() != wxTRANSPARENT
) {}; 
 275   if (m_pen
.GetStyle() != wxTRANSPARENT
) {}; 
 278 bool wxPaintDC::CanDrawBitmap(void) const 
 283 void wxPaintDC::DrawIcon( const wxIcon 
&icon
, long x
, long y
, bool useMask 
) 
 287   if (!icon
.Ok()) return; 
 289   int xx 
= XLOG2DEV(x
); 
 290   int yy 
= YLOG2DEV(y
); 
 294 bool wxPaintDC::Blit( long xdest
, long ydest
, long width
, long height
, 
 295        wxDC 
*source
, long xsrc
, long ysrc
, int WXUNUSED(logical_func
), bool WXUNUSED(useMask
) ) 
 297   if (!Ok()) return FALSE
; 
 299   // CMB 20/5/98: add blitting of bitmaps 
 300   if (source
->IsKindOf(CLASSINFO(wxMemoryDC
))) 
 302     wxMemoryDC
* srcDC 
= (wxMemoryDC
*)source
; 
 304      GdkBitmap* bmap = srcDC->m_selected.GetBitmap(); 
 311           source->DeviceToLogicalX(xsrc), source->DeviceToLogicalY(ysrc), 
 312           XLOG2DEV(xdest), YLOG2DEV(ydest), 
 313           source->DeviceToLogicalXRel(width), source->DeviceToLogicalYRel(height) 
 323 void wxPaintDC::DrawText( const wxString 
&text
, long x
, long y
, bool 
 332 bool wxPaintDC::CanGetTextExtent(void) const 
 337 void wxPaintDC::GetTextExtent( const wxString 
&string
, long *width
, long *height
, 
 338                      long *WXUNUSED(descent
), long *WXUNUSED(externalLeading
), 
 339                      wxFont 
*WXUNUSED(theFont
), bool WXUNUSED(use16
) ) 
 345 long wxPaintDC::GetCharWidth(void) 
 351 long wxPaintDC::GetCharHeight(void) 
 357 void wxPaintDC::Clear(void) 
 363 void wxPaintDC::SetFont( const wxFont 
&font 
) 
 370 void wxPaintDC::SetPen( const wxPen 
&pen 
) 
 374   if (m_pen 
== pen
) return; 
 378   if (!m_pen
.Ok()) return; 
 381 void wxPaintDC::SetBrush( const wxBrush 
&brush 
) 
 385   if (m_brush 
== brush
) return; 
 389   if (!m_brush
.Ok()) return; 
 393 void wxPaintDC::SetBackground( const wxBrush 
&brush 
) 
 397   if (m_backgroundBrush 
== brush
) return; 
 399   m_backgroundBrush 
= brush
; 
 401   if (!m_backgroundBrush
.Ok()) return; 
 405 void wxPaintDC::SetLogicalFunction( int function 
) 
 407   if (m_logicalFunction 
== function
) return; 
 410 void wxPaintDC::SetTextForeground( const wxColour 
&col 
) 
 414   if (m_textForegroundColour 
== col
) return; 
 416   m_textForegroundColour 
= col
; 
 417   if (!m_textForegroundColour
.Ok()) return; 
 420 void wxPaintDC::SetTextBackground( const wxColour 
&col 
) 
 424   if (m_textBackgroundColour 
== col
) return; 
 426   m_textBackgroundColour 
= col
; 
 427   if (!m_textBackgroundColour
.Ok()) return; 
 430 void wxPaintDC::SetBackgroundMode( int mode 
) 
 432   m_backgroundMode 
= mode
; 
 434   if (m_brush
.GetStyle() != wxSOLID 
&& m_brush
.GetStyle() != wxTRANSPARENT
) 
 439 void wxPaintDC::SetPalette( const wxPalette
& WXUNUSED(palette
) ) 
 443 void wxPaintDC::SetClippingRegion( long x
, long y
, long width
, long height 
) 
 445   wxDC::SetClippingRegion( x
, y
, width
, height 
); 
 449 void wxPaintDC::DestroyClippingRegion(void) 
 451   wxDC::DestroyClippingRegion(); 
 455 // ----------------------------------- spline code ---------------------------------------- 
 457 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, 
 458                          double a3
, double b3
, double a4
, double b4
); 
 459 void wx_clear_stack(void); 
 460 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
, 
 461         double *y3
, double *x4
, double *y4
); 
 462 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, 
 463           double x4
, double y4
); 
 464 static bool wx_spline_add_point(double x
, double y
); 
 465 static void wx_spline_draw_point_array(wxDC 
*dc
); 
 467 wxList wx_spline_point_list
; 
 469 #define         half(z1, z2)    ((z1+z2)/2.0) 
 472 /* iterative version */ 
 474 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
, 
 477     register double  xmid
, ymid
; 
 478     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
 481     wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
); 
 483     while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) { 
 484         xmid 
= (double)half(x2
, x3
); 
 485         ymid 
= (double)half(y2
, y3
); 
 486         if (fabs(x1 
- xmid
) < THRESHOLD 
&& fabs(y1 
- ymid
) < THRESHOLD 
&& 
 487             fabs(xmid 
- x4
) < THRESHOLD 
&& fabs(ymid 
- y4
) < THRESHOLD
) { 
 488             wx_spline_add_point( x1
, y1 
); 
 489             wx_spline_add_point( xmid
, ymid 
); 
 491             wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
), 
 492                  (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
); 
 493             wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
), 
 494                  (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
); 
 499 /* utilities used by spline drawing routines */ 
 501 typedef struct wx_spline_stack_struct 
{ 
 502     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
 505 #define         SPLINE_STACK_DEPTH             20 
 506 static Stack    wx_spline_stack
[SPLINE_STACK_DEPTH
]; 
 507 static Stack   
*wx_stack_top
; 
 508 static int      wx_stack_count
; 
 510 void wx_clear_stack(void) 
 512     wx_stack_top 
= wx_spline_stack
; 
 516 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
) 
 518     wx_stack_top
->x1 
= x1
; 
 519     wx_stack_top
->y1 
= y1
; 
 520     wx_stack_top
->x2 
= x2
; 
 521     wx_stack_top
->y2 
= y2
; 
 522     wx_stack_top
->x3 
= x3
; 
 523     wx_stack_top
->y3 
= y3
; 
 524     wx_stack_top
->x4 
= x4
; 
 525     wx_stack_top
->y4 
= y4
; 
 530 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, 
 531                   double *x3
, double *y3
, double *x4
, double *y4
) 
 533     if (wx_stack_count 
== 0) 
 537     *x1 
= wx_stack_top
->x1
; 
 538     *y1 
= wx_stack_top
->y1
; 
 539     *x2 
= wx_stack_top
->x2
; 
 540     *y2 
= wx_stack_top
->y2
; 
 541     *x3 
= wx_stack_top
->x3
; 
 542     *y3 
= wx_stack_top
->y3
; 
 543     *x4 
= wx_stack_top
->x4
; 
 544     *y4 
= wx_stack_top
->y4
; 
 548 static bool wx_spline_add_point(double x
, double y
) 
 550   wxPoint 
*point 
= new wxPoint 
; 
 553   wx_spline_point_list
.Append((wxObject
*)point
); 
 557 static void wx_spline_draw_point_array(wxDC 
*dc
) 
 559   dc
->DrawLines(&wx_spline_point_list
, 0, 0 ); 
 560   wxNode 
*node 
= wx_spline_point_list
.First(); 
 563     wxPoint 
*point 
= (wxPoint 
*)node
->Data(); 
 566     node 
= wx_spline_point_list
.First(); 
 570 void wxPaintDC::DrawOpenSpline( wxList 
*points 
) 
 573     double           cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
; 
 574     double           x1
, y1
, x2
, y2
; 
 576     wxNode 
*node 
= points
->First(); 
 577     p 
= (wxPoint 
*)node
->Data(); 
 583     p 
= (wxPoint 
*)node
->Data(); 
 587     cx1 
= (double)((x1 
+ x2
) / 2); 
 588     cy1 
= (double)((y1 
+ y2
) / 2); 
 589     cx2 
= (double)((cx1 
+ x2
) / 2); 
 590     cy2 
= (double)((cy1 
+ y2
) / 2); 
 592     wx_spline_add_point(x1
, y1
); 
 594     while ((node 
= node
->Next()) != NULL
) 
 596         p 
= (wxPoint 
*)node
->Data(); 
 601         cx4 
= (double)(x1 
+ x2
) / 2; 
 602         cy4 
= (double)(y1 
+ y2
) / 2; 
 603         cx3 
= (double)(x1 
+ cx4
) / 2; 
 604         cy3 
= (double)(y1 
+ cy4
) / 2; 
 606         wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
); 
 610         cx2 
= (double)(cx1 
+ x2
) / 2; 
 611         cy2 
= (double)(cy1 
+ y2
) / 2; 
 614     wx_spline_add_point( cx1
, cy1 
); 
 615     wx_spline_add_point( x2
, y2 
); 
 617     wx_spline_draw_point_array( this );