1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/dcbase.cpp
3 // Purpose: generic methods of the wxDC Class
4 // Author: Vadim Zeitlin
8 // Copyright: (c) wxWidgets 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(count
[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
-= count
[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(count
[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 widths array will be the width of the string up to and
374 // including the coresponding character in text. This is the generic
375 // implementation, the port-specific classes should do this with native APIs
376 // if available and if faster. Note: pango_layout_index_to_pos is much slower
377 // than calling GetTextExtent!!
384 FontWidthCache() : m_scaleX(1), m_widths(NULL
) { }
385 ~FontWidthCache() { delete []m_widths
; }
390 m_widths
= new int[FWC_SIZE
];
392 memset(m_widths
, 0, sizeof(int)*FWC_SIZE
);
400 static FontWidthCache s_fontWidthCache
;
402 bool wxDCBase::DoGetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const
406 size_t i
, len
= text
.Length();
411 // reset the cache if font or horizontal scale have changed
412 if (!s_fontWidthCache
.m_widths
||
413 (s_fontWidthCache
.m_scaleX
!= m_scaleX
) ||
414 (s_fontWidthCache
.m_font
!= GetFont()))
416 s_fontWidthCache
.Reset();
417 s_fontWidthCache
.m_font
= GetFont();
418 s_fontWidthCache
.m_scaleX
= m_scaleX
;
421 // Calculate the position of each character based on the widths of
422 // the previous characters
423 for (i
=0; i
<len
; i
++)
425 const wxChar c
= text
[i
];
426 unsigned int c_int
= (unsigned int)c
;
428 if ((c_int
< FWC_SIZE
) && (s_fontWidthCache
.m_widths
[c_int
] != 0))
430 w
= s_fontWidthCache
.m_widths
[c_int
];
434 GetTextExtent(c
, &w
, &h
);
435 if (c_int
< FWC_SIZE
)
436 s_fontWidthCache
.m_widths
[c_int
] = w
;
440 widths
[i
] = totalWidth
;
447 // ----------------------------------------------------------------------------
448 // enhanced text drawing
449 // ----------------------------------------------------------------------------
451 void wxDCBase::GetMultiLineTextExtent(const wxString
& text
,
457 wxCoord widthTextMax
= 0, widthLine
,
458 heightTextTotal
= 0, heightLineDefault
= 0, heightLine
= 0;
461 for ( const wxChar
*pc
= text
; ; pc
++ )
463 if ( *pc
== _T('\n') || *pc
== _T('\0') )
465 if ( curLine
.empty() )
467 // we can't use GetTextExtent - it will return 0 for both width
468 // and height and an empty line should count in height
471 // assume that this line has the same height as the previous
473 if ( !heightLineDefault
)
474 heightLineDefault
= heightLine
;
476 if ( !heightLineDefault
)
478 // but we don't know it yet - choose something reasonable
479 GetTextExtent(_T("W"), NULL
, &heightLineDefault
,
483 heightTextTotal
+= heightLineDefault
;
487 GetTextExtent(curLine
, &widthLine
, &heightLine
,
489 if ( widthLine
> widthTextMax
)
490 widthTextMax
= widthLine
;
491 heightTextTotal
+= heightLine
;
494 if ( *pc
== _T('\n') )
513 *y
= heightTextTotal
;
518 void wxDCBase::DrawLabel(const wxString
& text
,
519 const wxBitmap
& bitmap
,
523 wxRect
*rectBounding
)
525 // find the text position
526 wxCoord widthText
, heightText
, heightLine
;
527 GetMultiLineTextExtent(text
, &widthText
, &heightText
, &heightLine
);
529 wxCoord width
, height
;
532 width
= widthText
+ bitmap
.GetWidth();
533 height
= bitmap
.GetHeight();
542 if ( alignment
& wxALIGN_RIGHT
)
544 x
= rect
.GetRight() - width
;
546 else if ( alignment
& wxALIGN_CENTRE_HORIZONTAL
)
548 x
= (rect
.GetLeft() + rect
.GetRight() + 1 - width
) / 2;
550 else // alignment & wxALIGN_LEFT
555 if ( alignment
& wxALIGN_BOTTOM
)
557 y
= rect
.GetBottom() - height
;
559 else if ( alignment
& wxALIGN_CENTRE_VERTICAL
)
561 y
= (rect
.GetTop() + rect
.GetBottom() + 1 - height
) / 2;
563 else // alignment & wxALIGN_TOP
568 // draw the bitmap first
574 DrawBitmap(bitmap
, x
, y
, TRUE
/* use mask */);
576 wxCoord offset
= bitmap
.GetWidth() + 4;
580 y
+= (height
- heightText
) / 2;
583 // we will draw the underscore under the accel char later
584 wxCoord startUnderscore
= 0,
588 // split the string into lines and draw each of them separately
590 for ( const wxChar
*pc
= text
; ; pc
++ )
592 if ( *pc
== _T('\n') || *pc
== _T('\0') )
594 int xRealStart
= x
; // init it here to avoid compielr warnings
596 if ( !curLine
.empty() )
598 // NB: can't test for !(alignment & wxALIGN_LEFT) because
600 if ( alignment
& (wxALIGN_RIGHT
| wxALIGN_CENTRE_HORIZONTAL
) )
603 GetTextExtent(curLine
, &widthLine
, NULL
);
605 if ( alignment
& wxALIGN_RIGHT
)
607 xRealStart
+= width
- widthLine
;
609 else // if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
611 xRealStart
+= (width
- widthLine
) / 2;
614 //else: left aligned, nothing to do
616 DrawText(curLine
, xRealStart
, y
);
621 // do we have underscore in this line? we can check yUnderscore
622 // because it is set below to just y + heightLine if we do
623 if ( y
== yUnderscore
)
625 // adjust the horz positions to account for the shift
626 startUnderscore
+= xRealStart
;
627 endUnderscore
+= xRealStart
;
630 if ( *pc
== _T('\0') )
635 else // not end of line
637 if ( pc
- text
.c_str() == indexAccel
)
639 // remeber to draw underscore here
640 GetTextExtent(curLine
, &startUnderscore
, NULL
);
642 GetTextExtent(curLine
, &endUnderscore
, NULL
);
644 yUnderscore
= y
+ heightLine
;
653 // draw the underscore if found
654 if ( startUnderscore
!= endUnderscore
)
656 // it should be of the same colour as text
657 SetPen(wxPen(GetTextForeground(), 0, wxSOLID
));
661 DrawLine(startUnderscore
, yUnderscore
, endUnderscore
, yUnderscore
);
664 // return bounding rect if requested
667 *rectBounding
= wxRect(x
, y
- heightText
, widthText
, heightText
);
670 CalcBoundingBox(x0
, y0
);
671 CalcBoundingBox(x0
+ width0
, y0
+ height
);
675 Notes for wxWidgets DrawEllipticArcRot(...)
677 wxDCBase::DrawEllipticArcRot(...) draws a rotated elliptic arc or an ellipse.
678 It uses wxDCBase::CalculateEllipticPoints(...) and wxDCBase::Rotate(...),
681 All methods are generic, so they can be implemented in wxDCBase.
682 DoDrawEllipticArcRot(...) is virtual, so it can be called from deeper
683 methods like (WinCE) wxDC::DoDrawArc(...).
685 CalculateEllipticPoints(...) fills a given list of wxPoints with some points
686 of an elliptic arc. The algorithm is pixel-based: In every row (in flat
687 parts) or every column (in steep parts) only one pixel is calculated.
688 Trigonometric calculation (sin, cos, tan, atan) is only done if the
689 starting angle is not equal to the ending angle. The calculation of the
690 pixels is done using simple arithmetic only and should perform not too
691 bad even on devices without floating point processor. I didn't test this yet.
693 Rotate(...) rotates a list of point pixel-based, you will see rounding errors.
694 For instance: an ellipse rotated 180 degrees is drawn
695 slightly different from the original.
697 The points are then moved to an array and used to draw a polyline and/or polygon
698 (with center added, the pie).
699 The result looks quite similar to the native ellipse, only e few pixels differ.
701 The performance on a desktop system (Athlon 1800, WinXP) is about 7 times
702 slower as DrawEllipse(...), which calls the native API.
703 An rotated ellipse outside the clipping region takes nearly the same time,
704 while an native ellipse outside takes nearly no time to draw.
706 If you draw an arc with this new method, you will see the starting and ending angles
707 are calculated properly.
708 If you use DrawEllipticArc(...), you will see they are only correct for circles
709 and not properly calculated for ellipses.
712 p.lenhard@t-online.de
716 void wxDCBase::DoDrawEllipticArcRot( wxCoord x
, wxCoord y
,
717 wxCoord w
, wxCoord h
,
718 double sa
, double ea
, double angle
)
722 CalculateEllipticPoints( &list
, x
, y
, w
, h
, sa
, ea
);
723 Rotate( &list
, angle
, wxPoint( x
+w
/2, y
+h
/2 ) );
725 // Add center (for polygon/pie)
726 list
.Append( (wxObject
*) new wxPoint( x
+w
/2, y
+h
/2 ) );
728 // copy list into array and delete list elements
729 int n
= list
.Number();
730 wxPoint
*points
= new wxPoint
[n
];
733 for ( node
= list
.First(); node
; node
= node
->Next(), i
++ )
735 wxPoint
*point
= (wxPoint
*)node
->Data();
736 points
[i
].x
= point
->x
;
737 points
[i
].y
= point
->y
;
741 // first draw the pie without pen, if necessary
742 if( GetBrush() != *wxTRANSPARENT_BRUSH
)
744 wxPen
tempPen( GetPen() );
745 SetPen( *wxTRANSPARENT_PEN
);
746 DoDrawPolygon( n
, points
, 0, 0 );
750 // then draw the arc without brush, if necessary
751 if( GetPen() != *wxTRANSPARENT_PEN
)
754 DoDrawLines( n
-1, points
, 0, 0 );
759 } // DrawEllipticArcRot
761 void wxDCBase::Rotate( wxList
* points
, double angle
, wxPoint center
)
765 double pi(3.1415926536);
766 double dSinA
= -sin(angle
*2.0*pi
/360.0);
767 double dCosA
= cos(angle
*2.0*pi
/360.0);
768 for ( wxNode
* node
= points
->First(); node
; node
= node
->Next() )
770 wxPoint
* point
= (wxPoint
*)node
->Data();
772 // transform coordinates, if necessary
773 if( center
.x
) point
->x
-= center
.x
;
774 if( center
.y
) point
->y
-= center
.y
;
776 // calculate rotation, rounding simply by implicit cast to integer
777 int xTemp
= point
->x
* dCosA
- point
->y
* dSinA
;
778 point
->y
= point
->x
* dSinA
+ point
->y
* dCosA
;
781 // back transform coordinates, if necessary
782 if( center
.x
) point
->x
+= center
.x
;
783 if( center
.y
) point
->y
+= center
.y
;
788 void wxDCBase::CalculateEllipticPoints( wxList
* points
,
789 wxCoord xStart
, wxCoord yStart
,
790 wxCoord w
, wxCoord h
,
791 double sa
, double ea
)
793 double pi
= 3.1415926535;
802 bool bUseAngles
= false;
808 // decrement 1 pixel if ellipse is smaller than 2*a, 2*b
810 if( 2*a
== w
) decrX
= 1;
812 if( 2*b
== h
) decrY
= 1;
814 wxCoord xCenter
= xStart
+ a
;
815 wxCoord yCenter
= yStart
+ b
;
816 // calculate data for start and end, if necessary
820 // normalisation of angles
821 while( sa
<0 ) sa
+= 360;
822 while( ea
<0 ) ea
+= 360;
823 while( sa
>=360 ) sa
-= 360;
824 while( ea
>=360 ) ea
-= 360;
825 // calculate quadrant numbers
826 if( sa
> 270 ) sq
= 3;
827 else if( sa
> 180 ) sq
= 2;
828 else if( sa
> 90 ) sq
= 1;
829 if( ea
> 270 ) eq
= 3;
830 else if( ea
> 180 ) eq
= 2;
831 else if( ea
> 90 ) eq
= 1;
832 sar
= sa
* pi
/ 180.0;
833 ear
= ea
* pi
/ 180.0;
834 // correct angle circle -> ellipse
835 sar
= atan( -a
/(double)b
* tan( sar
) );
836 if ( sq
== 1 || sq
== 2 ) sar
+= pi
;
837 ear
= atan( -a
/(double)b
* tan( ear
) );
838 if ( eq
== 1 || eq
== 2 ) ear
+= pi
;
839 // coordinates of points
840 xsa
= xCenter
+ a
* cos( sar
);
841 if( sq
== 0 || sq
== 3 ) xsa
-= decrX
;
842 ysa
= yCenter
+ b
* sin( sar
);
843 if( sq
== 2 || sq
== 3 ) ysa
-= decrY
;
844 xea
= xCenter
+ a
* cos( ear
);
845 if( eq
== 0 || eq
== 3 ) xea
-= decrX
;
846 yea
= yCenter
+ b
* sin( ear
);
847 if( eq
== 2 || eq
== 3 ) yea
-= decrY
;
849 // calculate c1 = b^2, c2 = b^2/a^2 with a = w/2, b = h/2
860 // Lists for quadrant 1 to 4
861 wxList pointsarray
[4];
862 // Calculate points for first quadrant and set in all quadrants
863 for( x
= 0; x
<= a
; ++x
)
868 bool bNewPoint
= false;
869 while( y2
> c1
- c2
* x2
&& y
> 0 )
875 // old y now to big: set point with old y, old x
876 if( bNewPoint
&& x
>1)
879 // remove points on the same line
880 pointsarray
[0].Insert( (wxObject
*) new wxPoint( xCenter
+ x1
- decrX
, yCenter
- y_old
) );
881 pointsarray
[1].Append( (wxObject
*) new wxPoint( xCenter
- x1
, yCenter
- y_old
) );
882 pointsarray
[2].Insert( (wxObject
*) new wxPoint( xCenter
- x1
, yCenter
+ y_old
- decrY
) );
883 pointsarray
[3].Append( (wxObject
*) new wxPoint( xCenter
+ x1
- decrX
, yCenter
+ y_old
- decrY
) );
887 // Starting and/or ending points for the quadrants, first quadrant gets both.
888 pointsarray
[0].Insert( (wxObject
*) new wxPoint( xCenter
+ a
- decrX
, yCenter
) );
889 pointsarray
[0].Append( (wxObject
*) new wxPoint( xCenter
, yCenter
- b
) );
890 pointsarray
[1].Append( (wxObject
*) new wxPoint( xCenter
- a
, yCenter
) );
891 pointsarray
[2].Append( (wxObject
*) new wxPoint( xCenter
, yCenter
+ b
- decrY
) );
892 pointsarray
[3].Append( (wxObject
*) new wxPoint( xCenter
+ a
- decrX
, yCenter
) );
894 // copy quadrants in original list
897 // Copy the right part of the points in the lists
898 // and delete the wxPoints, because they do not leave this method.
899 points
->Append( (wxObject
*) new wxPoint( xsa
, ysa
) );
901 bool bStarted
= false;
903 bool bForceTurn
= ( sq
== eq
&& sa
> ea
);
906 for( wxNode
*node
= pointsarray
[q
].First(); node
; node
= node
->Next() )
908 // once: go to starting point in start quadrant
911 ( (wxPoint
*) node
->Data() )->x
< xsa
+1 && q
<= 1
913 ( (wxPoint
*) node
->Data() )->x
> xsa
-1 && q
>= 2
920 // copy point, if not at ending point
923 if( q
!= eq
|| bForceTurn
925 ( (wxPoint
*) node
->Data() )->x
> xea
+1 && q
<= 1
927 ( (wxPoint
*) node
->Data() )->x
< xea
-1 && q
>= 2
931 wxPoint
* pPoint
= new wxPoint( *((wxPoint
*) node
->Data() ) );
932 points
->Append( (wxObject
*) pPoint
);
934 else if( q
== eq
&& !bForceTurn
|| ( (wxPoint
*) node
->Data() )->x
== xea
)
944 } // while not bReady
945 points
->Append( (wxObject
*) new wxPoint( xea
, yea
) );
948 for( q
= 0; q
< 4; ++q
)
950 for( wxNode
*node
= pointsarray
[q
].First(); node
; node
= node
->Next() )
952 wxPoint
*p
= (wxPoint
*)node
->Data();
959 // copy whole ellipse, wxPoints will be deleted outside
960 for( wxNode
*node
= pointsarray
[0].First(); node
; node
= node
->Next() )
962 wxObject
*p
= node
->Data();
965 for( node
= pointsarray
[1].First(); node
; node
= node
->Next() )
967 wxObject
*p
= node
->Data();
970 for( node
= pointsarray
[2].First(); node
; node
= node
->Next() )
972 wxObject
*p
= node
->Data();
975 for( node
= pointsarray
[3].First(); node
; node
= node
->Next() )
977 wxObject
*p
= node
->Data();
981 } // CalculateEllipticPoints