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
);
109 // ----------------------------------------------------------------------------
111 // ----------------------------------------------------------------------------
115 // TODO: this API needs fixing (wxPointList, why (!const) "wxList *"?)
116 void wxDCBase::DrawSpline(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord x3
, wxCoord y3
)
120 wxPoint
*point1
= new wxPoint
;
121 point1
->x
= x1
; point1
->y
= y1
;
122 point_list
.Append((wxObject
*)point1
);
124 wxPoint
*point2
= new wxPoint
;
125 point2
->x
= x2
; point2
->y
= y2
;
126 point_list
.Append((wxObject
*)point2
);
128 wxPoint
*point3
= new wxPoint
;
129 point3
->x
= x3
; point3
->y
= y3
;
130 point_list
.Append((wxObject
*)point3
);
132 DrawSpline(&point_list
);
134 for( wxList::compatibility_iterator node
= point_list
.GetFirst(); node
; node
= node
->GetNext() )
136 wxPoint
*p
= (wxPoint
*)node
->GetData();
141 void wxDCBase::DrawSpline(int n
, wxPoint points
[])
144 for (int i
=0; i
< n
; i
++)
146 list
.Append((wxObject
*)&points
[i
]);
152 // ----------------------------------- spline code ----------------------------------------
154 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
155 double a3
, double b3
, double a4
, double b4
);
156 void wx_clear_stack();
157 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
158 double *y3
, double *x4
, double *y4
);
159 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
160 double x4
, double y4
);
161 static bool wx_spline_add_point(double x
, double y
);
162 static void wx_spline_draw_point_array(wxDCBase
*dc
);
164 wxList wx_spline_point_list
;
166 #define half(z1, z2) ((z1+z2)/2.0)
169 /* iterative version */
171 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
174 register double xmid
, ymid
;
175 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
178 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
180 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
181 xmid
= (double)half(x2
, x3
);
182 ymid
= (double)half(y2
, y3
);
183 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
184 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
185 wx_spline_add_point( x1
, y1
);
186 wx_spline_add_point( xmid
, ymid
);
188 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
189 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
190 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
191 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
196 /* utilities used by spline drawing routines */
198 typedef struct wx_spline_stack_struct
{
199 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
202 #define SPLINE_STACK_DEPTH 20
203 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
204 static Stack
*wx_stack_top
;
205 static int wx_stack_count
;
207 void wx_clear_stack()
209 wx_stack_top
= wx_spline_stack
;
213 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
215 wx_stack_top
->x1
= x1
;
216 wx_stack_top
->y1
= y1
;
217 wx_stack_top
->x2
= x2
;
218 wx_stack_top
->y2
= y2
;
219 wx_stack_top
->x3
= x3
;
220 wx_stack_top
->y3
= y3
;
221 wx_stack_top
->x4
= x4
;
222 wx_stack_top
->y4
= y4
;
227 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
228 double *x3
, double *y3
, double *x4
, double *y4
)
230 if (wx_stack_count
== 0)
234 *x1
= wx_stack_top
->x1
;
235 *y1
= wx_stack_top
->y1
;
236 *x2
= wx_stack_top
->x2
;
237 *y2
= wx_stack_top
->y2
;
238 *x3
= wx_stack_top
->x3
;
239 *y3
= wx_stack_top
->y3
;
240 *x4
= wx_stack_top
->x4
;
241 *y4
= wx_stack_top
->y4
;
245 static bool wx_spline_add_point(double x
, double y
)
247 wxPoint
*point
= new wxPoint
;
250 wx_spline_point_list
.Append((wxObject
*)point
);
254 static void wx_spline_draw_point_array(wxDCBase
*dc
)
256 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
257 wxList::compatibility_iterator node
= wx_spline_point_list
.GetFirst();
260 wxPoint
*point
= (wxPoint
*)node
->GetData();
262 wx_spline_point_list
.Erase(node
);
263 node
= wx_spline_point_list
.GetFirst();
267 void wxDCBase::DoDrawSpline( wxList
*points
)
269 wxCHECK_RET( Ok(), wxT("invalid window dc") );
272 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
273 double x1
, y1
, x2
, y2
;
275 wxList::compatibility_iterator node
= points
->GetFirst();
276 p
= (wxPoint
*)node
->GetData();
281 node
= node
->GetNext();
282 p
= (wxPoint
*)node
->GetData();
286 cx1
= (double)((x1
+ x2
) / 2);
287 cy1
= (double)((y1
+ y2
) / 2);
288 cx2
= (double)((cx1
+ x2
) / 2);
289 cy2
= (double)((cy1
+ y2
) / 2);
291 wx_spline_add_point(x1
, y1
);
293 while ((node
= node
->GetNext())
299 p
= (wxPoint
*)node
->GetData();
304 cx4
= (double)(x1
+ x2
) / 2;
305 cy4
= (double)(y1
+ y2
) / 2;
306 cx3
= (double)(x1
+ cx4
) / 2;
307 cy3
= (double)(y1
+ cy4
) / 2;
309 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
313 cx2
= (double)(cx1
+ x2
) / 2;
314 cy2
= (double)(cy1
+ y2
) / 2;
317 wx_spline_add_point( cx1
, cy1
);
318 wx_spline_add_point( x2
, y2
);
320 wx_spline_draw_point_array( this );
323 #endif // wxUSE_SPLINES
325 // ----------------------------------------------------------------------------
326 // enhanced text drawing
327 // ----------------------------------------------------------------------------
329 void wxDCBase::GetMultiLineTextExtent(const wxString
& text
,
335 wxCoord widthTextMax
= 0, widthLine
,
336 heightTextTotal
= 0, heightLineDefault
= 0, heightLine
= 0;
339 for ( const wxChar
*pc
= text
; ; pc
++ )
341 if ( *pc
== _T('\n') || *pc
== _T('\0') )
343 if ( curLine
.empty() )
345 // we can't use GetTextExtent - it will return 0 for both width
346 // and height and an empty line should count in height
349 // assume that this line has the same height as the previous
351 if ( !heightLineDefault
)
352 heightLineDefault
= heightLine
;
354 if ( !heightLineDefault
)
356 // but we don't know it yet - choose something reasonable
357 GetTextExtent(_T("W"), NULL
, &heightLineDefault
,
361 heightTextTotal
+= heightLineDefault
;
365 GetTextExtent(curLine
, &widthLine
, &heightLine
,
367 if ( widthLine
> widthTextMax
)
368 widthTextMax
= widthLine
;
369 heightTextTotal
+= heightLine
;
372 if ( *pc
== _T('\n') )
391 *y
= heightTextTotal
;
396 void wxDCBase::DrawLabel(const wxString
& text
,
397 const wxBitmap
& bitmap
,
401 wxRect
*rectBounding
)
403 // find the text position
404 wxCoord widthText
, heightText
, heightLine
;
405 GetMultiLineTextExtent(text
, &widthText
, &heightText
, &heightLine
);
407 wxCoord width
, height
;
410 width
= widthText
+ bitmap
.GetWidth();
411 height
= bitmap
.GetHeight();
420 if ( alignment
& wxALIGN_RIGHT
)
422 x
= rect
.GetRight() - width
;
424 else if ( alignment
& wxALIGN_CENTRE_HORIZONTAL
)
426 x
= (rect
.GetLeft() + rect
.GetRight() + 1 - width
) / 2;
428 else // alignment & wxALIGN_LEFT
433 if ( alignment
& wxALIGN_BOTTOM
)
435 y
= rect
.GetBottom() - height
;
437 else if ( alignment
& wxALIGN_CENTRE_VERTICAL
)
439 y
= (rect
.GetTop() + rect
.GetBottom() + 1 - height
) / 2;
441 else // alignment & wxALIGN_TOP
446 // draw the bitmap first
452 DrawBitmap(bitmap
, x
, y
, TRUE
/* use mask */);
454 wxCoord offset
= bitmap
.GetWidth() + 4;
458 y
+= (height
- heightText
) / 2;
461 // we will draw the underscore under the accel char later
462 wxCoord startUnderscore
= 0,
466 // split the string into lines and draw each of them separately
468 for ( const wxChar
*pc
= text
; ; pc
++ )
470 if ( *pc
== _T('\n') || *pc
== _T('\0') )
472 int xRealStart
= x
; // init it here to avoid compielr warnings
474 if ( !curLine
.empty() )
476 // NB: can't test for !(alignment & wxALIGN_LEFT) because
478 if ( alignment
& (wxALIGN_RIGHT
| wxALIGN_CENTRE_HORIZONTAL
) )
481 GetTextExtent(curLine
, &widthLine
, NULL
);
483 if ( alignment
& wxALIGN_RIGHT
)
485 xRealStart
+= width
- widthLine
;
487 else // if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
489 xRealStart
+= (width
- widthLine
) / 2;
492 //else: left aligned, nothing to do
494 DrawText(curLine
, xRealStart
, y
);
499 // do we have underscore in this line? we can check yUnderscore
500 // because it is set below to just y + heightLine if we do
501 if ( y
== yUnderscore
)
503 // adjust the horz positions to account for the shift
504 startUnderscore
+= xRealStart
;
505 endUnderscore
+= xRealStart
;
508 if ( *pc
== _T('\0') )
513 else // not end of line
515 if ( pc
- text
.c_str() == indexAccel
)
517 // remeber to draw underscore here
518 GetTextExtent(curLine
, &startUnderscore
, NULL
);
520 GetTextExtent(curLine
, &endUnderscore
, NULL
);
522 yUnderscore
= y
+ heightLine
;
531 // draw the underscore if found
532 if ( startUnderscore
!= endUnderscore
)
534 // it should be of the same colour as text
535 SetPen(wxPen(GetTextForeground(), 0, wxSOLID
));
539 DrawLine(startUnderscore
, yUnderscore
, endUnderscore
, yUnderscore
);
542 // return bounding rect if requested
545 *rectBounding
= wxRect(x
, y
- heightText
, widthText
, heightText
);
548 CalcBoundingBox(x0
, y0
);
549 CalcBoundingBox(x0
+ width0
, y0
+ height
);
553 Notes for wxWindows DrawEllipticArcRot(...)
555 wxDCBase::DrawEllipticArcRot(...) draws a rotated elliptic arc or an ellipse.
556 It uses wxDCBase::CalculateEllipticPoints(...) and wxDCBase::Rotate(...),
559 All methods are generic, so they can be implemented in wxDCBase.
560 DoDrawEllipticArcRot(...) is virtual, so it can be called from deeper
561 methods like (WinCE) wxDC::DoDrawArc(...).
563 CalculateEllipticPoints(...) fills a given list of wxPoints with some points
564 of an elliptic arc. The algorithm is pixel-based: In every row (in flat
565 parts) or every column (in steep parts) only one pixel is calculated.
566 Trigonometric calculation (sin, cos, tan, atan) is only done if the
567 starting angle is not equal to the ending angle. The calculation of the
568 pixels is done using simple arithmetic only and should perform not too
569 bad even on devices without floating point processor. I didn't test this yet.
571 Rotate(...) rotates a list of point pixel-based, you will see rounding errors.
572 For instance: an ellipse rotated 180 degrees is drawn
573 slightly different from the original.
575 The points are then moved to an array and used to draw a polyline and/or polygon
576 (with center added, the pie).
577 The result looks quite similar to the native ellipse, only e few pixels differ.
579 The performance on a desktop system (Athlon 1800, WinXP) is about 7 times
580 slower as DrawEllipse(...), which calls the native API.
581 An rotated ellipse outside the clipping region takes nearly the same time,
582 while an native ellipse outside takes nearly no time to draw.
584 If you draw an arc with this new method, you will see the starting and ending angles
585 are calculated properly.
586 If you use DrawEllipticArc(...), you will see they are only correct for circles
587 and not properly calculated for ellipses.
590 p.lenhard@t-online.de
594 void wxDCBase::DoDrawEllipticArcRot( wxCoord x
, wxCoord y
,
595 wxCoord w
, wxCoord h
,
596 double sa
, double ea
, double angle
)
600 CalculateEllipticPoints( &list
, x
, y
, w
, h
, sa
, ea
);
601 Rotate( &list
, angle
, wxPoint( x
+w
/2, y
+h
/2 ) );
603 // Add center (for polygon/pie)
604 list
.Append( (wxObject
*) new wxPoint( x
+w
/2, y
+h
/2 ) );
606 // copy list into array and delete list elements
607 int n
= list
.Number();
608 wxPoint
*points
= new wxPoint
[n
];
611 for ( node
= list
.First(); node
; node
= node
->Next(), i
++ )
613 wxPoint
*point
= (wxPoint
*)node
->Data();
614 points
[i
].x
= point
->x
;
615 points
[i
].y
= point
->y
;
619 // first draw the pie without pen, if necessary
620 if( GetBrush() != *wxTRANSPARENT_BRUSH
)
622 wxPen
tempPen( GetPen() );
623 SetPen( *wxTRANSPARENT_PEN
);
624 DoDrawPolygon( n
, points
, 0, 0 );
628 // then draw the arc without brush, if necessary
629 if( GetPen() != *wxTRANSPARENT_PEN
)
632 DoDrawLines( n
-1, points
, 0, 0 );
637 } // DrawEllipticArcRot
639 void wxDCBase::Rotate( wxList
* points
, double angle
, wxPoint center
)
643 double pi(3.1415926536);
644 double dSinA
= -sin(angle
*2.0*pi
/360.0);
645 double dCosA
= cos(angle
*2.0*pi
/360.0);
646 for ( wxNode
* node
= points
->First(); node
; node
= node
->Next() )
648 wxPoint
* point
= (wxPoint
*)node
->Data();
650 // transform coordinates, if necessary
651 if( center
.x
) point
->x
-= center
.x
;
652 if( center
.y
) point
->y
-= center
.y
;
654 // calculate rotation, rounding simply by implicit cast to integer
655 int xTemp
= point
->x
* dCosA
- point
->y
* dSinA
;
656 point
->y
= point
->x
* dSinA
+ point
->y
* dCosA
;
659 // back transform coordinates, if necessary
660 if( center
.x
) point
->x
+= center
.x
;
661 if( center
.y
) point
->y
+= center
.y
;
666 void wxDCBase::CalculateEllipticPoints( wxList
* points
,
667 wxCoord xStart
, wxCoord yStart
,
668 wxCoord w
, wxCoord h
,
669 double sa
, double ea
)
671 double pi
= 3.1415926535;
680 bool bUseAngles
= false;
686 // decrement 1 pixel if ellipse is smaller than 2*a, 2*b
688 if( 2*a
== w
) decrX
= 1;
690 if( 2*b
== h
) decrY
= 1;
692 wxCoord xCenter
= xStart
+ a
;
693 wxCoord yCenter
= yStart
+ b
;
694 // calculate data for start and end, if necessary
698 // normalisation of angles
699 while( sa
<0 ) sa
+= 360;
700 while( ea
<0 ) ea
+= 360;
701 while( sa
>=360 ) sa
-= 360;
702 while( ea
>=360 ) ea
-= 360;
703 // calculate quadrant numbers
704 if( sa
> 270 ) sq
= 3;
705 else if( sa
> 180 ) sq
= 2;
706 else if( sa
> 90 ) sq
= 1;
707 if( ea
> 270 ) eq
= 3;
708 else if( ea
> 180 ) eq
= 2;
709 else if( ea
> 90 ) eq
= 1;
710 sar
= sa
* pi
/ 180.0;
711 ear
= ea
* pi
/ 180.0;
712 // correct angle circle -> ellipse
713 sar
= atan( -a
/(double)b
* tan( sar
) );
714 if ( sq
== 1 || sq
== 2 ) sar
+= pi
;
715 ear
= atan( -a
/(double)b
* tan( ear
) );
716 if ( eq
== 1 || eq
== 2 ) ear
+= pi
;
717 // coordinates of points
718 xsa
= xCenter
+ a
* cos( sar
);
719 if( sq
== 0 || sq
== 3 ) xsa
-= decrX
;
720 ysa
= yCenter
+ b
* sin( sar
);
721 if( sq
== 2 || sq
== 3 ) ysa
-= decrY
;
722 xea
= xCenter
+ a
* cos( ear
);
723 if( eq
== 0 || eq
== 3 ) xea
-= decrX
;
724 yea
= yCenter
+ b
* sin( ear
);
725 if( eq
== 2 || eq
== 3 ) yea
-= decrY
;
727 // calculate c1 = b^2, c2 = b^2/a^2 with a = w/2, b = h/2
738 // Lists for quadrant 1 to 4
739 wxList pointsarray
[4];
740 // Calculate points for first quadrant and set in all quadrants
741 for( x
= 0; x
<= a
; ++x
)
746 bool bNewPoint
= false;
747 while( y2
> c1
- c2
* x2
&& y
> 0 )
753 // old y now to big: set point with old y, old x
754 if( bNewPoint
&& x
>1)
757 // remove points on the same line
758 pointsarray
[0].Insert( (wxObject
*) new wxPoint( xCenter
+ x1
- decrX
, yCenter
- y_old
) );
759 pointsarray
[1].Append( (wxObject
*) new wxPoint( xCenter
- x1
, yCenter
- y_old
) );
760 pointsarray
[2].Insert( (wxObject
*) new wxPoint( xCenter
- x1
, yCenter
+ y_old
- decrY
) );
761 pointsarray
[3].Append( (wxObject
*) new wxPoint( xCenter
+ x1
- decrX
, yCenter
+ y_old
- decrY
) );
765 // Starting and/or ending points for the quadrants, first quadrant gets both.
766 pointsarray
[0].Insert( (wxObject
*) new wxPoint( xCenter
+ a
- decrX
, yCenter
) );
767 pointsarray
[0].Append( (wxObject
*) new wxPoint( xCenter
, yCenter
- b
) );
768 pointsarray
[1].Append( (wxObject
*) new wxPoint( xCenter
- a
, yCenter
) );
769 pointsarray
[2].Append( (wxObject
*) new wxPoint( xCenter
, yCenter
+ b
- decrY
) );
770 pointsarray
[3].Append( (wxObject
*) new wxPoint( xCenter
+ a
- decrX
, yCenter
) );
772 // copy quadrants in original list
775 // Copy the right part of the points in the lists
776 // and delete the wxPoints, because they do not leave this method.
777 points
->Append( (wxObject
*) new wxPoint( xsa
, ysa
) );
779 bool bStarted
= false;
781 bool bForceTurn
= ( sq
== eq
&& sa
> ea
);
784 for( wxNode
*node
= pointsarray
[q
].First(); node
; node
= node
->Next() )
786 // once: go to starting point in start quadrant
789 ( (wxPoint
*) node
->Data() )->x
< xsa
+1 && q
<= 1
791 ( (wxPoint
*) node
->Data() )->x
> xsa
-1 && q
>= 2
798 // copy point, if not at ending point
801 if( q
!= eq
|| bForceTurn
803 ( (wxPoint
*) node
->Data() )->x
> xea
+1 && q
<= 1
805 ( (wxPoint
*) node
->Data() )->x
< xea
-1 && q
>= 2
809 wxPoint
* pPoint
= new wxPoint( *((wxPoint
*) node
->Data() ) );
810 points
->Append( (wxObject
*) pPoint
);
812 else if( q
== eq
&& !bForceTurn
|| ( (wxPoint
*) node
->Data() )->x
== xea
)
822 } // while not bReady
823 points
->Append( (wxObject
*) new wxPoint( xea
, yea
) );
826 for( q
= 0; q
< 4; ++q
)
828 for( wxNode
*node
= pointsarray
[q
].First(); node
; node
= node
->Next() )
830 wxPoint
*p
= (wxPoint
*)node
->Data();
838 // copy whole ellipse, wxPoints will be deleted outside
839 for( wxNode
*node
= pointsarray
[0].First(); node
; node
= node
->Next() )
841 wxObject
*p
= node
->Data();
844 for( node
= pointsarray
[1].First(); node
; node
= node
->Next() )
846 wxObject
*p
= node
->Data();
849 for( node
= pointsarray
[2].First(); node
; node
= node
->Next() )
851 wxObject
*p
= node
->Data();
854 for( node
= pointsarray
[3].First(); node
; node
= node
->Next() )
856 wxObject
*p
= node
->Data();
860 } // CalculateEllipticPoints