1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        common/dcbase.cpp 
   3 // Purpose:     generic methods of the wxDC Class 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) wxWindows team 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  17     #pragma implementation "dcbase.h" 
  20 // ---------------------------------------------------------------------------- 
  22 // ---------------------------------------------------------------------------- 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  35 // bool wxDCBase::sm_cacheing = FALSE; 
  37 // ============================================================================ 
  39 // ============================================================================ 
  41 // ---------------------------------------------------------------------------- 
  43 // ---------------------------------------------------------------------------- 
  45 void wxDCBase::DoDrawCheckMark(wxCoord x1
, wxCoord y1
, 
  46                                wxCoord width
, wxCoord height
) 
  48     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
  50     wxCoord x2 
= x1 
+ width
, 
  53     // this is to yield width of 3 for width == height == 10 
  54     SetPen(wxPen(GetTextForeground(), (width 
+ height 
+ 1) / 7, wxSOLID
)); 
  56     // we're drawing a scaled version of wx/generic/tick.xpm here 
  57     wxCoord x3 
= x1 
+ (4*width
) / 10,   // x of the tick bottom 
  58             y3 
= y1 
+ height 
/ 2;       // y of the left tick branch 
  59     DoDrawLine(x1
, y3
, x3
, y2
); 
  60     DoDrawLine(x3
, y2
, x2
, y1
); 
  62     CalcBoundingBox(x1
, y1
); 
  63     CalcBoundingBox(x2
, y2
); 
  66 // ---------------------------------------------------------------------------- 
  68 // ---------------------------------------------------------------------------- 
  70 void wxDCBase::DrawLines(const wxList 
*list
, wxCoord xoffset
, wxCoord yoffset
) 
  72     int n 
= list
->GetCount(); 
  73     wxPoint 
*points 
= new wxPoint
[n
]; 
  76     for ( wxList::compatibility_iterator node 
= list
->GetFirst(); node
; node 
= node
->GetNext(), i
++ ) 
  78         wxPoint 
*point 
= (wxPoint 
*)node
->GetData(); 
  79         points
[i
].x 
= point
->x
; 
  80         points
[i
].y 
= point
->y
; 
  83     DoDrawLines(n
, points
, xoffset
, yoffset
); 
  89 void wxDCBase::DrawPolygon(const wxList 
*list
, 
  90                            wxCoord xoffset
, wxCoord yoffset
, 
  93     int n 
= list
->GetCount(); 
  94     wxPoint 
*points 
= new wxPoint
[n
]; 
  97     for ( wxList::compatibility_iterator node 
= list
->GetFirst(); node
; node 
= node
->GetNext(), i
++ ) 
  99         wxPoint 
*point 
= (wxPoint 
*)node
->GetData(); 
 100         points
[i
].x 
= point
->x
; 
 101         points
[i
].y 
= point
->y
; 
 104     DoDrawPolygon(n
, points
, xoffset
, yoffset
, fillStyle
); 
 110 wxDCBase::DoDrawPolyPolygon(int n
, 
 113                             wxCoord xoffset
, wxCoord yoffset
, 
 118         DoDrawPolygon(start
[0], points
, xoffset
, yoffset
, fillStyle
); 
 126     for (i 
= j 
= lastOfs 
= 0; i 
< n
; i
++) 
 131     pts 
= new wxPoint
[j
+n
-1]; 
 132     for (i 
= 0; i 
< j
; i
++) 
 134     for (i 
= 2; i 
<= n
; i
++) 
 136         lastOfs 
-= start
[n
-i
]; 
 137         pts
[j
++] = pts
[lastOfs
]; 
 141     SetPen(wxPen(*wxBLACK
, 0, wxTRANSPARENT
)); 
 142     DoDrawPolygon(j
, pts
, xoffset
, yoffset
, fillStyle
); 
 144     for (i 
= j 
= 0; i 
< n
; i
++) 
 146         DoDrawLines(start
[i
], pts
+j
, xoffset
, yoffset
); 
 152 // ---------------------------------------------------------------------------- 
 154 // ---------------------------------------------------------------------------- 
 158 // TODO: this API needs fixing (wxPointList, why (!const) "wxList *"?) 
 159 void wxDCBase::DrawSpline(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord x3
, wxCoord y3
) 
 163     wxPoint 
*point1 
= new wxPoint
; 
 164     point1
->x 
= x1
; point1
->y 
= y1
; 
 165     point_list
.Append((wxObject
*)point1
); 
 167     wxPoint 
*point2 
= new wxPoint
; 
 168     point2
->x 
= x2
; point2
->y 
= y2
; 
 169     point_list
.Append((wxObject
*)point2
); 
 171     wxPoint 
*point3 
= new wxPoint
; 
 172     point3
->x 
= x3
; point3
->y 
= y3
; 
 173     point_list
.Append((wxObject
*)point3
); 
 175     DrawSpline(&point_list
); 
 177     for( wxList::compatibility_iterator node 
= point_list
.GetFirst(); node
; node 
= node
->GetNext() ) 
 179         wxPoint 
*p 
= (wxPoint 
*)node
->GetData(); 
 184 void wxDCBase::DrawSpline(int n
, wxPoint points
[]) 
 187     for (int i 
=0; i 
< n
; i
++) 
 189         list
.Append((wxObject
*)&points
[i
]); 
 195 // ----------------------------------- spline code ---------------------------------------- 
 197 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, 
 198                          double a3
, double b3
, double a4
, double b4
); 
 199 void wx_clear_stack(); 
 200 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
, 
 201         double *y3
, double *x4
, double *y4
); 
 202 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, 
 203           double x4
, double y4
); 
 204 static bool wx_spline_add_point(double x
, double y
); 
 205 static void wx_spline_draw_point_array(wxDCBase 
*dc
); 
 207 wxList wx_spline_point_list
; 
 209 #define                half(z1, z2)        ((z1+z2)/2.0) 
 212 /* iterative version */ 
 214 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
, 
 217     register double  xmid
, ymid
; 
 218     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
 221     wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
); 
 223     while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) { 
 224         xmid 
= (double)half(x2
, x3
); 
 225         ymid 
= (double)half(y2
, y3
); 
 226         if (fabs(x1 
- xmid
) < THRESHOLD 
&& fabs(y1 
- ymid
) < THRESHOLD 
&& 
 227             fabs(xmid 
- x4
) < THRESHOLD 
&& fabs(ymid 
- y4
) < THRESHOLD
) { 
 228             wx_spline_add_point( x1
, y1 
); 
 229             wx_spline_add_point( xmid
, ymid 
); 
 231             wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
), 
 232                  (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
); 
 233             wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
), 
 234                  (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
); 
 239 /* utilities used by spline drawing routines */ 
 241 typedef struct wx_spline_stack_struct 
{ 
 242     double           x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
; 
 245 #define         SPLINE_STACK_DEPTH             20 
 246 static Stack    wx_spline_stack
[SPLINE_STACK_DEPTH
]; 
 247 static Stack   
*wx_stack_top
; 
 248 static int      wx_stack_count
; 
 250 void wx_clear_stack() 
 252     wx_stack_top 
= wx_spline_stack
; 
 256 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
) 
 258     wx_stack_top
->x1 
= x1
; 
 259     wx_stack_top
->y1 
= y1
; 
 260     wx_stack_top
->x2 
= x2
; 
 261     wx_stack_top
->y2 
= y2
; 
 262     wx_stack_top
->x3 
= x3
; 
 263     wx_stack_top
->y3 
= y3
; 
 264     wx_stack_top
->x4 
= x4
; 
 265     wx_stack_top
->y4 
= y4
; 
 270 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, 
 271                   double *x3
, double *y3
, double *x4
, double *y4
) 
 273     if (wx_stack_count 
== 0) 
 277     *x1 
= wx_stack_top
->x1
; 
 278     *y1 
= wx_stack_top
->y1
; 
 279     *x2 
= wx_stack_top
->x2
; 
 280     *y2 
= wx_stack_top
->y2
; 
 281     *x3 
= wx_stack_top
->x3
; 
 282     *y3 
= wx_stack_top
->y3
; 
 283     *x4 
= wx_stack_top
->x4
; 
 284     *y4 
= wx_stack_top
->y4
; 
 288 static bool wx_spline_add_point(double x
, double y
) 
 290   wxPoint 
*point 
= new wxPoint 
; 
 293   wx_spline_point_list
.Append((wxObject
*)point
); 
 297 static void wx_spline_draw_point_array(wxDCBase 
*dc
) 
 299   dc
->DrawLines(&wx_spline_point_list
, 0, 0 ); 
 300   wxList::compatibility_iterator node 
= wx_spline_point_list
.GetFirst(); 
 303     wxPoint 
*point 
= (wxPoint 
*)node
->GetData(); 
 305     wx_spline_point_list
.Erase(node
); 
 306     node 
= wx_spline_point_list
.GetFirst(); 
 310 void wxDCBase::DoDrawSpline( wxList 
*points 
) 
 312     wxCHECK_RET( Ok(), wxT("invalid window dc") ); 
 315     double           cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
; 
 316     double           x1
, y1
, x2
, y2
; 
 318     wxList::compatibility_iterator node 
= points
->GetFirst(); 
 319     p 
= (wxPoint 
*)node
->GetData(); 
 324     node 
= node
->GetNext(); 
 325     p 
= (wxPoint 
*)node
->GetData(); 
 329     cx1 
= (double)((x1 
+ x2
) / 2); 
 330     cy1 
= (double)((y1 
+ y2
) / 2); 
 331     cx2 
= (double)((cx1 
+ x2
) / 2); 
 332     cy2 
= (double)((cy1 
+ y2
) / 2); 
 334     wx_spline_add_point(x1
, y1
); 
 336     while ((node 
= node
->GetNext()) 
 342         p 
= (wxPoint 
*)node
->GetData(); 
 347         cx4 
= (double)(x1 
+ x2
) / 2; 
 348         cy4 
= (double)(y1 
+ y2
) / 2; 
 349         cx3 
= (double)(x1 
+ cx4
) / 2; 
 350         cy3 
= (double)(y1 
+ cy4
) / 2; 
 352         wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
); 
 356         cx2 
= (double)(cx1 
+ x2
) / 2; 
 357         cy2 
= (double)(cy1 
+ y2
) / 2; 
 360     wx_spline_add_point( cx1
, cy1 
); 
 361     wx_spline_add_point( x2
, y2 
); 
 363     wx_spline_draw_point_array( this ); 
 366 #endif // wxUSE_SPLINES 
 368 // ---------------------------------------------------------------------------- 
 369 // Partial Text Extents 
 370 // ---------------------------------------------------------------------------- 
 373 // Each element of the array will be the width of the string up to and 
 374 // including the coresoponding character in text.  This is the generic 
 375 // implementation, the port-specific classes should do this with native APIs 
 378 bool wxDCBase::DoGetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const 
 384     widths
.Add(0, text
.Length()); 
 386     // Calculate the position of each character based on the widths of 
 387     // the previous characters 
 388     for (i
=0; i
<text
.Length(); i
++) { 
 390         GetTextExtent(text
[i
], &w
, &h
); 
 392         widths
[i
] = totalWidth
; 
 398 // ---------------------------------------------------------------------------- 
 399 // enhanced text drawing 
 400 // ---------------------------------------------------------------------------- 
 402 void wxDCBase::GetMultiLineTextExtent(const wxString
& text
, 
 408     wxCoord widthTextMax 
= 0, widthLine
, 
 409             heightTextTotal 
= 0, heightLineDefault 
= 0, heightLine 
= 0; 
 412     for ( const wxChar 
*pc 
= text
; ; pc
++ ) 
 414         if ( *pc 
== _T('\n') || *pc 
== _T('\0') ) 
 416             if ( curLine
.empty() ) 
 418                 // we can't use GetTextExtent - it will return 0 for both width 
 419                 // and height and an empty line should count in height 
 422                 // assume that this line has the same height as the previous 
 424                 if ( !heightLineDefault 
) 
 425                     heightLineDefault 
= heightLine
; 
 427                 if ( !heightLineDefault 
) 
 429                     // but we don't know it yet - choose something reasonable 
 430                     GetTextExtent(_T("W"), NULL
, &heightLineDefault
, 
 434                 heightTextTotal 
+= heightLineDefault
; 
 438                 GetTextExtent(curLine
, &widthLine
, &heightLine
, 
 440                 if ( widthLine 
> widthTextMax 
) 
 441                     widthTextMax 
= widthLine
; 
 442                 heightTextTotal 
+= heightLine
; 
 445             if ( *pc 
== _T('\n') ) 
 464         *y 
= heightTextTotal
; 
 469 void wxDCBase::DrawLabel(const wxString
& text
, 
 470                          const wxBitmap
& bitmap
, 
 474                          wxRect 
*rectBounding
) 
 476     // find the text position 
 477     wxCoord widthText
, heightText
, heightLine
; 
 478     GetMultiLineTextExtent(text
, &widthText
, &heightText
, &heightLine
); 
 480     wxCoord width
, height
; 
 483         width 
= widthText 
+ bitmap
.GetWidth(); 
 484         height 
= bitmap
.GetHeight(); 
 493     if ( alignment 
& wxALIGN_RIGHT 
) 
 495         x 
= rect
.GetRight() - width
; 
 497     else if ( alignment 
& wxALIGN_CENTRE_HORIZONTAL 
) 
 499         x 
= (rect
.GetLeft() + rect
.GetRight() + 1 - width
) / 2; 
 501     else // alignment & wxALIGN_LEFT 
 506     if ( alignment 
& wxALIGN_BOTTOM 
) 
 508         y 
= rect
.GetBottom() - height
; 
 510     else if ( alignment 
& wxALIGN_CENTRE_VERTICAL 
) 
 512         y 
= (rect
.GetTop() + rect
.GetBottom() + 1 - height
) / 2; 
 514     else // alignment & wxALIGN_TOP 
 519     // draw the bitmap first 
 525         DrawBitmap(bitmap
, x
, y
, TRUE 
/* use mask */); 
 527         wxCoord offset 
= bitmap
.GetWidth() + 4; 
 531         y 
+= (height 
- heightText
) / 2; 
 534     // we will draw the underscore under the accel char later 
 535     wxCoord startUnderscore 
= 0, 
 539     // split the string into lines and draw each of them separately 
 541     for ( const wxChar 
*pc 
= text
; ; pc
++ ) 
 543         if ( *pc 
== _T('\n') || *pc 
== _T('\0') ) 
 545             int xRealStart 
= x
; // init it here to avoid compielr warnings 
 547             if ( !curLine
.empty() ) 
 549                 // NB: can't test for !(alignment & wxALIGN_LEFT) because 
 551                 if ( alignment 
& (wxALIGN_RIGHT 
| wxALIGN_CENTRE_HORIZONTAL
) ) 
 554                     GetTextExtent(curLine
, &widthLine
, NULL
); 
 556                     if ( alignment 
& wxALIGN_RIGHT 
) 
 558                         xRealStart 
+= width 
- widthLine
; 
 560                     else // if ( alignment & wxALIGN_CENTRE_HORIZONTAL ) 
 562                         xRealStart 
+= (width 
- widthLine
) / 2; 
 565                 //else: left aligned, nothing to do 
 567                 DrawText(curLine
, xRealStart
, y
); 
 572             // do we have underscore in this line? we can check yUnderscore 
 573             // because it is set below to just y + heightLine if we do 
 574             if ( y 
== yUnderscore 
) 
 576                 // adjust the horz positions to account for the shift 
 577                 startUnderscore 
+= xRealStart
; 
 578                 endUnderscore 
+= xRealStart
; 
 581             if ( *pc 
== _T('\0') ) 
 586         else // not end of line 
 588             if ( pc 
- text
.c_str() == indexAccel 
) 
 590                 // remeber to draw underscore here 
 591                 GetTextExtent(curLine
, &startUnderscore
, NULL
); 
 593                 GetTextExtent(curLine
, &endUnderscore
, NULL
); 
 595                 yUnderscore 
= y 
+ heightLine
; 
 604     // draw the underscore if found 
 605     if ( startUnderscore 
!= endUnderscore 
) 
 607         // it should be of the same colour as text 
 608         SetPen(wxPen(GetTextForeground(), 0, wxSOLID
)); 
 612         DrawLine(startUnderscore
, yUnderscore
, endUnderscore
, yUnderscore
); 
 615     // return bounding rect if requested 
 618         *rectBounding 
= wxRect(x
, y 
- heightText
, widthText
, heightText
); 
 621     CalcBoundingBox(x0
, y0
); 
 622     CalcBoundingBox(x0 
+ width0
, y0 
+ height
); 
 626 Notes for wxWindows DrawEllipticArcRot(...) 
 628 wxDCBase::DrawEllipticArcRot(...) draws a rotated elliptic arc or an ellipse. 
 629 It uses wxDCBase::CalculateEllipticPoints(...) and wxDCBase::Rotate(...), 
 632 All methods are generic, so they can be implemented in wxDCBase. 
 633 DoDrawEllipticArcRot(...) is virtual, so it can be called from deeper 
 634 methods like (WinCE) wxDC::DoDrawArc(...). 
 636 CalculateEllipticPoints(...) fills a given list of wxPoints with some points 
 637 of an elliptic arc. The algorithm is pixel-based: In every row (in flat  
 638 parts) or every column (in steep parts) only one pixel is calculated. 
 639 Trigonometric calculation (sin, cos, tan, atan) is only done if the 
 640 starting angle is not equal to the ending angle. The calculation of the  
 641 pixels is done using simple arithmetic only and should perform not too 
 642 bad even on devices without floating point processor. I didn't test this yet. 
 644 Rotate(...) rotates a list of point pixel-based, you will see rounding errors. 
 645 For instance: an ellipse rotated 180 degrees is drawn  
 646 slightly different from the original. 
 648 The points are then moved to an array and used to draw a polyline and/or polygon  
 649 (with center added, the pie).  
 650 The result looks quite similar to the native ellipse, only e few pixels differ. 
 652 The performance on a desktop system (Athlon 1800, WinXP) is about 7 times 
 653 slower as DrawEllipse(...), which calls the native API. 
 654 An rotated ellipse outside the clipping region takes nearly the same time, 
 655 while an native ellipse outside takes nearly no time to draw. 
 657 If you draw an arc with this new method, you will see the starting and ending angles  
 658 are calculated properly. 
 659 If you use DrawEllipticArc(...), you will see they are only correct for circles 
 660 and not properly calculated for ellipses. 
 663 p.lenhard@t-online.de 
 667 void wxDCBase::DoDrawEllipticArcRot( wxCoord x
, wxCoord y
,  
 668                                      wxCoord w
, wxCoord h
,  
 669                                      double sa
, double ea
, double angle 
) 
 673     CalculateEllipticPoints( &list
, x
, y
, w
, h
, sa
, ea 
); 
 674     Rotate( &list
, angle
, wxPoint( x
+w
/2, y
+h
/2 ) ); 
 676     // Add center (for polygon/pie) 
 677     list
.Append( (wxObject
*) new wxPoint( x
+w
/2, y
+h
/2 ) ); 
 679     // copy list into array and delete list elements 
 680     int n 
= list
.Number(); 
 681     wxPoint 
*points 
= new wxPoint
[n
]; 
 684     for ( node 
= list
.First(); node
; node 
= node
->Next(), i
++ ) 
 686         wxPoint 
*point 
= (wxPoint 
*)node
->Data(); 
 687         points
[i
].x 
= point
->x
; 
 688         points
[i
].y 
= point
->y
; 
 692     // first draw the pie without pen, if necessary 
 693     if( GetBrush() != *wxTRANSPARENT_BRUSH 
) 
 695         wxPen 
tempPen( GetPen() ); 
 696         SetPen( *wxTRANSPARENT_PEN 
); 
 697         DoDrawPolygon( n
, points
, 0, 0 ); 
 701     // then draw the arc without brush, if necessary 
 702     if( GetPen() != *wxTRANSPARENT_PEN 
) 
 705         DoDrawLines( n
-1, points
, 0, 0 ); 
 710 } // DrawEllipticArcRot 
 712 void wxDCBase::Rotate( wxList
* points
, double angle
, wxPoint center 
) 
 716         double pi(3.1415926536); 
 717         double dSinA 
= -sin(angle
*2.0*pi
/360.0); 
 718         double dCosA 
= cos(angle
*2.0*pi
/360.0); 
 719         for ( wxNode
* node 
= points
->First(); node
; node 
= node
->Next() ) 
 721             wxPoint
* point 
= (wxPoint
*)node
->Data(); 
 723             // transform coordinates, if necessary 
 724             if( center
.x 
) point
->x 
-= center
.x
; 
 725             if( center
.y 
) point
->y 
-= center
.y
; 
 727             // calculate rotation, rounding simply by implicit cast to integer 
 728             int xTemp 
= point
->x 
* dCosA 
- point
->y 
* dSinA
; 
 729             point
->y 
= point
->x 
* dSinA 
+ point
->y 
* dCosA
; 
 732             // back transform coordinates, if necessary 
 733             if( center
.x 
) point
->x 
+= center
.x
; 
 734             if( center
.y 
) point
->y 
+= center
.y
; 
 739 void wxDCBase::CalculateEllipticPoints( wxList
* points
,  
 740                                         wxCoord xStart
, wxCoord yStart
,  
 741                                         wxCoord w
, wxCoord h
,  
 742                                         double sa
, double ea 
) 
 744     double pi 
= 3.1415926535; 
 753     bool bUseAngles 
= false; 
 759     // decrement 1 pixel if ellipse is smaller than 2*a, 2*b 
 761     if( 2*a 
== w 
) decrX 
= 1;  
 763     if( 2*b 
== h 
) decrY 
= 1;  
 765     wxCoord xCenter 
= xStart 
+ a
; 
 766     wxCoord yCenter 
= yStart 
+ b
; 
 767     // calculate data for start and end, if necessary 
 771         // normalisation of angles 
 772         while( sa
<0 ) sa 
+= 360; 
 773         while( ea
<0 ) ea 
+= 360; 
 774         while( sa
>=360 ) sa 
-= 360; 
 775         while( ea
>=360 ) ea 
-= 360; 
 776         // calculate quadrant numbers 
 777         if( sa 
> 270 ) sq 
= 3; 
 778         else if( sa 
> 180 ) sq 
= 2; 
 779         else if( sa 
> 90 ) sq 
= 1; 
 780         if( ea 
> 270 ) eq 
= 3; 
 781         else if( ea 
> 180 ) eq 
= 2; 
 782         else if( ea 
> 90 ) eq 
= 1; 
 783         sar 
= sa 
* pi 
/ 180.0; 
 784         ear 
= ea 
* pi 
/ 180.0; 
 785         // correct angle circle -> ellipse 
 786         sar 
= atan( -a
/(double)b 
* tan( sar 
) ); 
 787         if ( sq 
== 1 || sq 
== 2 ) sar 
+= pi
;  
 788         ear 
= atan( -a
/(double)b 
* tan( ear 
) ); 
 789         if ( eq 
== 1 || eq 
== 2 ) ear 
+= pi
; 
 790         // coordinates of points 
 791         xsa 
= xCenter 
+ a 
* cos( sar 
); 
 792         if( sq 
== 0 || sq 
== 3 ) xsa 
-= decrX
; 
 793         ysa 
= yCenter 
+ b 
* sin( sar 
); 
 794         if( sq 
== 2 || sq 
== 3 ) ysa 
-= decrY
; 
 795         xea 
= xCenter 
+ a 
* cos( ear 
); 
 796         if( eq 
== 0 || eq 
== 3 ) xea 
-= decrX
; 
 797         yea 
= yCenter 
+ b 
* sin( ear 
); 
 798         if( eq 
== 2 || eq 
== 3 ) yea 
-= decrY
; 
 800     // calculate c1 = b^2, c2 = b^2/a^2 with a = w/2, b = h/2 
 811     // Lists for quadrant 1 to 4 
 812     wxList pointsarray
[4]; 
 813     // Calculate points for first quadrant and set in all quadrants 
 814     for( x 
= 0; x 
<= a
; ++x 
) 
 819         bool bNewPoint 
= false; 
 820         while( y2 
> c1 
- c2 
* x2 
&& y 
> 0 ) 
 826         // old y now to big: set point with old y, old x  
 827         if( bNewPoint 
&& x
>1) 
 830             // remove points on the same line 
 831             pointsarray
[0].Insert( (wxObject
*) new wxPoint( xCenter 
+ x1 
- decrX
, yCenter 
- y_old 
) ); 
 832             pointsarray
[1].Append( (wxObject
*) new wxPoint( xCenter 
- x1
, yCenter 
- y_old 
) ); 
 833             pointsarray
[2].Insert( (wxObject
*) new wxPoint( xCenter 
- x1
, yCenter 
+ y_old 
- decrY 
) ); 
 834             pointsarray
[3].Append( (wxObject
*) new wxPoint( xCenter 
+ x1 
- decrX
, yCenter 
+ y_old 
- decrY 
) ); 
 838     // Starting and/or ending points for the quadrants, first quadrant gets both. 
 839     pointsarray
[0].Insert( (wxObject
*) new wxPoint( xCenter 
+ a 
- decrX
, yCenter 
) ); 
 840     pointsarray
[0].Append( (wxObject
*) new wxPoint( xCenter
, yCenter 
- b 
) ); 
 841     pointsarray
[1].Append( (wxObject
*) new wxPoint( xCenter 
- a
, yCenter 
) ); 
 842     pointsarray
[2].Append( (wxObject
*) new wxPoint( xCenter
, yCenter 
+ b 
- decrY 
) ); 
 843     pointsarray
[3].Append( (wxObject
*) new wxPoint( xCenter 
+ a 
- decrX
, yCenter 
) ); 
 845     // copy quadrants in original list 
 848         // Copy the right part of the points in the lists 
 849         // and delete the wxPoints, because they do not leave this method. 
 850         points
->Append( (wxObject
*) new wxPoint( xsa
, ysa 
) ); 
 852         bool bStarted 
= false; 
 854         bool bForceTurn 
= ( sq 
== eq 
&& sa 
> ea 
); 
 857             for( wxNode 
*node 
= pointsarray
[q
].First(); node
; node 
= node
->Next() ) 
 859                 // once: go to starting point in start quadrant 
 862                       ( (wxPoint
*) node
->Data() )->x 
< xsa
+1 && q 
<= 1  
 864                       ( (wxPoint
*) node
->Data() )->x 
> xsa
-1 && q 
>= 2 
 871                 // copy point, if not at ending point 
 874                     if( q 
!= eq 
|| bForceTurn
 
 876                         ( (wxPoint
*) node
->Data() )->x 
> xea
+1 && q 
<= 1  
 878                         ( (wxPoint
*) node
->Data() )->x 
< xea
-1 && q 
>= 2 
 882                         wxPoint
* pPoint 
= new wxPoint( *((wxPoint
*) node
->Data() ) ); 
 883                         points
->Append( (wxObject
*) pPoint 
); 
 885                     else if( q 
== eq 
&& !bForceTurn 
|| ( (wxPoint
*) node
->Data() )->x 
== xea
) 
 895         } // while not bReady 
 896         points
->Append( (wxObject
*) new wxPoint( xea
, yea 
) ); 
 899         for( q 
= 0; q 
< 4; ++q 
) 
 901             for( wxNode 
*node 
= pointsarray
[q
].First(); node
; node 
= node
->Next() ) 
 903                 wxPoint 
*p 
= (wxPoint 
*)node
->Data(); 
 911         // copy whole ellipse, wxPoints will be deleted outside 
 912         for( wxNode 
*node 
= pointsarray
[0].First(); node
; node 
= node
->Next() ) 
 914             wxObject 
*p 
= node
->Data(); 
 917         for( node 
= pointsarray
[1].First(); node
; node 
= node
->Next() ) 
 919             wxObject 
*p 
= node
->Data(); 
 922         for( node 
= pointsarray
[2].First(); node
; node 
= node
->Next() ) 
 924             wxObject 
*p 
= node
->Data(); 
 927         for( node 
= pointsarray
[3].First(); node
; node 
= node
->Next() ) 
 929             wxObject 
*p 
= node
->Data(); 
 933 } // CalculateEllipticPoints