]> git.saurik.com Git - wxWidgets.git/blob - src/common/dcbase.cpp
wxUniversal STL-ification.
[wxWidgets.git] / src / common / dcbase.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: common/dcbase.cpp
3 // Purpose: generic methods of the wxDC Class
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 05/25/99
7 // RCS-ID: $Id$
8 // Copyright: (c) wxWindows team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
17 #pragma implementation "dcbase.h"
18 #endif
19
20 // ----------------------------------------------------------------------------
21 // headers
22 // ----------------------------------------------------------------------------
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #include "wx/dc.h"
32
33 #include <math.h>
34
35 // bool wxDCBase::sm_cacheing = FALSE;
36
37 // ============================================================================
38 // implementation
39 // ============================================================================
40
41 // ----------------------------------------------------------------------------
42 // special symbols
43 // ----------------------------------------------------------------------------
44
45 void wxDCBase::DoDrawCheckMark(wxCoord x1, wxCoord y1,
46 wxCoord width, wxCoord height)
47 {
48 wxCHECK_RET( Ok(), wxT("invalid window dc") );
49
50 wxCoord x2 = x1 + width,
51 y2 = y1 + height;
52
53 // this is to yield width of 3 for width == height == 10
54 SetPen(wxPen(GetTextForeground(), (width + height + 1) / 7, wxSOLID));
55
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);
61
62 CalcBoundingBox(x1, y1);
63 CalcBoundingBox(x2, y2);
64 }
65
66 // ----------------------------------------------------------------------------
67 // line/polygons
68 // ----------------------------------------------------------------------------
69
70 void wxDCBase::DrawLines(const wxList *list, wxCoord xoffset, wxCoord yoffset)
71 {
72 int n = list->GetCount();
73 wxPoint *points = new wxPoint[n];
74
75 int i = 0;
76 for ( wxList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ )
77 {
78 wxPoint *point = (wxPoint *)node->GetData();
79 points[i].x = point->x;
80 points[i].y = point->y;
81 }
82
83 DoDrawLines(n, points, xoffset, yoffset);
84
85 delete [] points;
86 }
87
88
89 void wxDCBase::DrawPolygon(const wxList *list,
90 wxCoord xoffset, wxCoord yoffset,
91 int fillStyle)
92 {
93 int n = list->GetCount();
94 wxPoint *points = new wxPoint[n];
95
96 int i = 0;
97 for ( wxList::compatibility_iterator node = list->GetFirst(); node; node = node->GetNext(), i++ )
98 {
99 wxPoint *point = (wxPoint *)node->GetData();
100 points[i].x = point->x;
101 points[i].y = point->y;
102 }
103
104 DoDrawPolygon(n, points, xoffset, yoffset, fillStyle);
105
106 delete [] points;
107 }
108
109 // ----------------------------------------------------------------------------
110 // splines
111 // ----------------------------------------------------------------------------
112
113 #if wxUSE_SPLINES
114
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)
117 {
118 wxList point_list;
119
120 wxPoint *point1 = new wxPoint;
121 point1->x = x1; point1->y = y1;
122 point_list.Append((wxObject*)point1);
123
124 wxPoint *point2 = new wxPoint;
125 point2->x = x2; point2->y = y2;
126 point_list.Append((wxObject*)point2);
127
128 wxPoint *point3 = new wxPoint;
129 point3->x = x3; point3->y = y3;
130 point_list.Append((wxObject*)point3);
131
132 DrawSpline(&point_list);
133
134 for( wxList::compatibility_iterator node = point_list.GetFirst(); node; node = node->GetNext() )
135 {
136 wxPoint *p = (wxPoint *)node->GetData();
137 delete p;
138 }
139 }
140
141 void wxDCBase::DrawSpline(int n, wxPoint points[])
142 {
143 wxList list;
144 for (int i =0; i < n; i++)
145 {
146 list.Append((wxObject*)&points[i]);
147 }
148
149 DrawSpline(&list);
150 }
151
152 // ----------------------------------- spline code ----------------------------------------
153
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);
163
164 wxList wx_spline_point_list;
165
166 #define half(z1, z2) ((z1+z2)/2.0)
167 #define THRESHOLD 5
168
169 /* iterative version */
170
171 void wx_quadratic_spline(double a1, double b1, double a2, double b2, double a3, double b3, double a4,
172 double b4)
173 {
174 register double xmid, ymid;
175 double x1, y1, x2, y2, x3, y3, x4, y4;
176
177 wx_clear_stack();
178 wx_spline_push(a1, b1, a2, b2, a3, b3, a4, b4);
179
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 );
187 } else {
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);
192 }
193 }
194 }
195
196 /* utilities used by spline drawing routines */
197
198 typedef struct wx_spline_stack_struct {
199 double x1, y1, x2, y2, x3, y3, x4, y4;
200 } Stack;
201
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;
206
207 void wx_clear_stack()
208 {
209 wx_stack_top = wx_spline_stack;
210 wx_stack_count = 0;
211 }
212
213 void wx_spline_push(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
214 {
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;
223 wx_stack_top++;
224 wx_stack_count++;
225 }
226
227 int wx_spline_pop(double *x1, double *y1, double *x2, double *y2,
228 double *x3, double *y3, double *x4, double *y4)
229 {
230 if (wx_stack_count == 0)
231 return (0);
232 wx_stack_top--;
233 wx_stack_count--;
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;
242 return (1);
243 }
244
245 static bool wx_spline_add_point(double x, double y)
246 {
247 wxPoint *point = new wxPoint ;
248 point->x = (int) x;
249 point->y = (int) y;
250 wx_spline_point_list.Append((wxObject*)point);
251 return TRUE;
252 }
253
254 static void wx_spline_draw_point_array(wxDCBase *dc)
255 {
256 dc->DrawLines(&wx_spline_point_list, 0, 0 );
257 wxList::compatibility_iterator node = wx_spline_point_list.GetFirst();
258 while (node)
259 {
260 wxPoint *point = (wxPoint *)node->GetData();
261 delete point;
262 wx_spline_point_list.Erase(node);
263 node = wx_spline_point_list.GetFirst();
264 }
265 }
266
267 void wxDCBase::DoDrawSpline( wxList *points )
268 {
269 wxCHECK_RET( Ok(), wxT("invalid window dc") );
270
271 wxPoint *p;
272 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
273 double x1, y1, x2, y2;
274
275 wxList::compatibility_iterator node = points->GetFirst();
276 p = (wxPoint *)node->GetData();
277
278 x1 = p->x;
279 y1 = p->y;
280
281 node = node->GetNext();
282 p = (wxPoint *)node->GetData();
283
284 x2 = p->x;
285 y2 = p->y;
286 cx1 = (double)((x1 + x2) / 2);
287 cy1 = (double)((y1 + y2) / 2);
288 cx2 = (double)((cx1 + x2) / 2);
289 cy2 = (double)((cy1 + y2) / 2);
290
291 wx_spline_add_point(x1, y1);
292
293 while ((node = node->GetNext())
294 #if !wxUSE_STL
295 != NULL
296 #endif // !wxUSE_STL
297 )
298 {
299 p = (wxPoint *)node->GetData();
300 x1 = x2;
301 y1 = y2;
302 x2 = p->x;
303 y2 = p->y;
304 cx4 = (double)(x1 + x2) / 2;
305 cy4 = (double)(y1 + y2) / 2;
306 cx3 = (double)(x1 + cx4) / 2;
307 cy3 = (double)(y1 + cy4) / 2;
308
309 wx_quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
310
311 cx1 = cx4;
312 cy1 = cy4;
313 cx2 = (double)(cx1 + x2) / 2;
314 cy2 = (double)(cy1 + y2) / 2;
315 }
316
317 wx_spline_add_point( cx1, cy1 );
318 wx_spline_add_point( x2, y2 );
319
320 wx_spline_draw_point_array( this );
321 }
322
323 #endif // wxUSE_SPLINES
324
325 // ----------------------------------------------------------------------------
326 // enhanced text drawing
327 // ----------------------------------------------------------------------------
328
329 void wxDCBase::GetMultiLineTextExtent(const wxString& text,
330 wxCoord *x,
331 wxCoord *y,
332 wxCoord *h,
333 wxFont *font)
334 {
335 wxCoord widthTextMax = 0, widthLine,
336 heightTextTotal = 0, heightLineDefault = 0, heightLine = 0;
337
338 wxString curLine;
339 for ( const wxChar *pc = text; ; pc++ )
340 {
341 if ( *pc == _T('\n') || *pc == _T('\0') )
342 {
343 if ( curLine.empty() )
344 {
345 // we can't use GetTextExtent - it will return 0 for both width
346 // and height and an empty line should count in height
347 // calculation
348
349 // assume that this line has the same height as the previous
350 // one
351 if ( !heightLineDefault )
352 heightLineDefault = heightLine;
353
354 if ( !heightLineDefault )
355 {
356 // but we don't know it yet - choose something reasonable
357 GetTextExtent(_T("W"), NULL, &heightLineDefault,
358 NULL, NULL, font);
359 }
360
361 heightTextTotal += heightLineDefault;
362 }
363 else
364 {
365 GetTextExtent(curLine, &widthLine, &heightLine,
366 NULL, NULL, font);
367 if ( widthLine > widthTextMax )
368 widthTextMax = widthLine;
369 heightTextTotal += heightLine;
370 }
371
372 if ( *pc == _T('\n') )
373 {
374 curLine.clear();
375 }
376 else
377 {
378 // the end of string
379 break;
380 }
381 }
382 else
383 {
384 curLine += *pc;
385 }
386 }
387
388 if ( x )
389 *x = widthTextMax;
390 if ( y )
391 *y = heightTextTotal;
392 if ( h )
393 *h = heightLine;
394 }
395
396 void wxDCBase::DrawLabel(const wxString& text,
397 const wxBitmap& bitmap,
398 const wxRect& rect,
399 int alignment,
400 int indexAccel,
401 wxRect *rectBounding)
402 {
403 // find the text position
404 wxCoord widthText, heightText, heightLine;
405 GetMultiLineTextExtent(text, &widthText, &heightText, &heightLine);
406
407 wxCoord width, height;
408 if ( bitmap.Ok() )
409 {
410 width = widthText + bitmap.GetWidth();
411 height = bitmap.GetHeight();
412 }
413 else // no bitmap
414 {
415 width = widthText;
416 height = heightText;
417 }
418
419 wxCoord x, y;
420 if ( alignment & wxALIGN_RIGHT )
421 {
422 x = rect.GetRight() - width;
423 }
424 else if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
425 {
426 x = (rect.GetLeft() + rect.GetRight() + 1 - width) / 2;
427 }
428 else // alignment & wxALIGN_LEFT
429 {
430 x = rect.GetLeft();
431 }
432
433 if ( alignment & wxALIGN_BOTTOM )
434 {
435 y = rect.GetBottom() - height;
436 }
437 else if ( alignment & wxALIGN_CENTRE_VERTICAL )
438 {
439 y = (rect.GetTop() + rect.GetBottom() + 1 - height) / 2;
440 }
441 else // alignment & wxALIGN_TOP
442 {
443 y = rect.GetTop();
444 }
445
446 // draw the bitmap first
447 wxCoord x0 = x,
448 y0 = y,
449 width0 = width;
450 if ( bitmap.Ok() )
451 {
452 DrawBitmap(bitmap, x, y, TRUE /* use mask */);
453
454 wxCoord offset = bitmap.GetWidth() + 4;
455 x += offset;
456 width -= offset;
457
458 y += (height - heightText) / 2;
459 }
460
461 // we will draw the underscore under the accel char later
462 wxCoord startUnderscore = 0,
463 endUnderscore = 0,
464 yUnderscore = 0;
465
466 // split the string into lines and draw each of them separately
467 wxString curLine;
468 for ( const wxChar *pc = text; ; pc++ )
469 {
470 if ( *pc == _T('\n') || *pc == _T('\0') )
471 {
472 int xRealStart = x; // init it here to avoid compielr warnings
473
474 if ( !curLine.empty() )
475 {
476 // NB: can't test for !(alignment & wxALIGN_LEFT) because
477 // wxALIGN_LEFT is 0
478 if ( alignment & (wxALIGN_RIGHT | wxALIGN_CENTRE_HORIZONTAL) )
479 {
480 wxCoord widthLine;
481 GetTextExtent(curLine, &widthLine, NULL);
482
483 if ( alignment & wxALIGN_RIGHT )
484 {
485 xRealStart += width - widthLine;
486 }
487 else // if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
488 {
489 xRealStart += (width - widthLine) / 2;
490 }
491 }
492 //else: left aligned, nothing to do
493
494 DrawText(curLine, xRealStart, y);
495 }
496
497 y += heightLine;
498
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 )
502 {
503 // adjust the horz positions to account for the shift
504 startUnderscore += xRealStart;
505 endUnderscore += xRealStart;
506 }
507
508 if ( *pc == _T('\0') )
509 break;
510
511 curLine.clear();
512 }
513 else // not end of line
514 {
515 if ( pc - text.c_str() == indexAccel )
516 {
517 // remeber to draw underscore here
518 GetTextExtent(curLine, &startUnderscore, NULL);
519 curLine += *pc;
520 GetTextExtent(curLine, &endUnderscore, NULL);
521
522 yUnderscore = y + heightLine;
523 }
524 else
525 {
526 curLine += *pc;
527 }
528 }
529 }
530
531 // draw the underscore if found
532 if ( startUnderscore != endUnderscore )
533 {
534 // it should be of the same colour as text
535 SetPen(wxPen(GetTextForeground(), 0, wxSOLID));
536
537 yUnderscore--;
538
539 DrawLine(startUnderscore, yUnderscore, endUnderscore, yUnderscore);
540 }
541
542 // return bounding rect if requested
543 if ( rectBounding )
544 {
545 *rectBounding = wxRect(x, y - heightText, widthText, heightText);
546 }
547
548 CalcBoundingBox(x0, y0);
549 CalcBoundingBox(x0 + width0, y0 + height);
550 }
551
552 /*
553 Notes for wxWindows DrawEllipticArcRot(...)
554
555 wxDCBase::DrawEllipticArcRot(...) draws a rotated elliptic arc or an ellipse.
556 It uses wxDCBase::CalculateEllipticPoints(...) and wxDCBase::Rotate(...),
557 which are also new.
558
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(...).
562
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.
570
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.
574
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.
578
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.
583
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.
588
589 Peter Lenhard
590 p.lenhard@t-online.de
591 */
592
593 #ifdef __WXWINCE__
594 void wxDCBase::DoDrawEllipticArcRot( wxCoord x, wxCoord y,
595 wxCoord w, wxCoord h,
596 double sa, double ea, double angle )
597 {
598 wxList list;
599
600 CalculateEllipticPoints( &list, x, y, w, h, sa, ea );
601 Rotate( &list, angle, wxPoint( x+w/2, y+h/2 ) );
602
603 // Add center (for polygon/pie)
604 list.Append( (wxObject*) new wxPoint( x+w/2, y+h/2 ) );
605
606 // copy list into array and delete list elements
607 int n = list.Number();
608 wxPoint *points = new wxPoint[n];
609 int i = 0;
610 wxNode* node = 0;
611 for ( node = list.First(); node; node = node->Next(), i++ )
612 {
613 wxPoint *point = (wxPoint *)node->Data();
614 points[i].x = point->x;
615 points[i].y = point->y;
616 delete point;
617 }
618
619 // first draw the pie without pen, if necessary
620 if( GetBrush() != *wxTRANSPARENT_BRUSH )
621 {
622 wxPen tempPen( GetPen() );
623 SetPen( *wxTRANSPARENT_PEN );
624 DoDrawPolygon( n, points, 0, 0 );
625 SetPen( tempPen );
626 }
627
628 // then draw the arc without brush, if necessary
629 if( GetPen() != *wxTRANSPARENT_PEN )
630 {
631 // without center
632 DoDrawLines( n-1, points, 0, 0 );
633 }
634
635 delete [] points;
636
637 } // DrawEllipticArcRot
638
639 void wxDCBase::Rotate( wxList* points, double angle, wxPoint center )
640 {
641 if( angle != 0.0 )
642 {
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() )
647 {
648 wxPoint* point = (wxPoint*)node->Data();
649
650 // transform coordinates, if necessary
651 if( center.x ) point->x -= center.x;
652 if( center.y ) point->y -= center.y;
653
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;
657 point->x = xTemp;
658
659 // back transform coordinates, if necessary
660 if( center.x ) point->x += center.x;
661 if( center.y ) point->y += center.y;
662 }
663 }
664 }
665
666 void wxDCBase::CalculateEllipticPoints( wxList* points,
667 wxCoord xStart, wxCoord yStart,
668 wxCoord w, wxCoord h,
669 double sa, double ea )
670 {
671 double pi = 3.1415926535;
672 double sar = 0;
673 double ear = 0;
674 int xsa = 0;
675 int ysa = 0;
676 int xea = 0;
677 int yea = 0;
678 int sq = 0;
679 int eq = 0;
680 bool bUseAngles = false;
681 if( w<0 ) w = -w;
682 if( h<0 ) h = -h;
683 // half-axes
684 wxCoord a = w/2;
685 wxCoord b = h/2;
686 // decrement 1 pixel if ellipse is smaller than 2*a, 2*b
687 int decrX = 0;
688 if( 2*a == w ) decrX = 1;
689 int decrY = 0;
690 if( 2*b == h ) decrY = 1;
691 // center
692 wxCoord xCenter = xStart + a;
693 wxCoord yCenter = yStart + b;
694 // calculate data for start and end, if necessary
695 if( sa != ea )
696 {
697 bUseAngles = true;
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;
726 } // if iUseAngles
727 // calculate c1 = b^2, c2 = b^2/a^2 with a = w/2, b = h/2
728 double c1 = b * b;
729 double c2 = 2.0 / w;
730 c2 *= c2;
731 c2 *= c1;
732 wxCoord x = 0;
733 wxCoord y = b;
734 long x2 = 1;
735 long y2 = y*y;
736 long y2_old = 0;
737 long y_old = 0;
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 )
742 {
743 x2 = x2+x+x-1;
744 y2_old = y2;
745 y_old = y;
746 bool bNewPoint = false;
747 while( y2 > c1 - c2 * x2 && y > 0 )
748 {
749 bNewPoint = true;
750 y2 = y2-y-y+1;
751 --y;
752 }
753 // old y now to big: set point with old y, old x
754 if( bNewPoint && x>1)
755 {
756 int x1 = 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 ) );
762 } // set point
763 } // calculate point
764
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 ) );
771
772 // copy quadrants in original list
773 if( bUseAngles )
774 {
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 ) );
778 int q = sq;
779 bool bStarted = false;
780 bool bReady = false;
781 bool bForceTurn = ( sq == eq && sa > ea );
782 while( !bReady )
783 {
784 for( wxNode *node = pointsarray[q].First(); node; node = node->Next() )
785 {
786 // once: go to starting point in start quadrant
787 if( !bStarted &&
788 (
789 ( (wxPoint*) node->Data() )->x < xsa+1 && q <= 1
790 ||
791 ( (wxPoint*) node->Data() )->x > xsa-1 && q >= 2
792 )
793 )
794 {
795 bStarted = true;
796 }
797
798 // copy point, if not at ending point
799 if( bStarted )
800 {
801 if( q != eq || bForceTurn
802 ||
803 ( (wxPoint*) node->Data() )->x > xea+1 && q <= 1
804 ||
805 ( (wxPoint*) node->Data() )->x < xea-1 && q >= 2
806 )
807 {
808 // copy point
809 wxPoint* pPoint = new wxPoint( *((wxPoint*) node->Data() ) );
810 points->Append( (wxObject*) pPoint );
811 }
812 else if( q == eq && !bForceTurn || ( (wxPoint*) node->Data() )->x == xea)
813 {
814 bReady = true;
815 }
816 }
817 } // for node
818 ++q;
819 if( q > 3 ) q = 0;
820 bForceTurn = false;
821 bStarted = true;
822 } // while not bReady
823 points->Append( (wxObject*) new wxPoint( xea, yea ) );
824
825 // delete points
826 for( q = 0; q < 4; ++q )
827 {
828 for( wxNode *node = pointsarray[q].First(); node; node = node->Next() )
829 {
830 wxPoint *p = (wxPoint *)node->Data();
831 delete p;
832 }
833 }
834
835 }
836 else
837 {
838 // copy whole ellipse, wxPoints will be deleted outside
839 for( wxNode *node = pointsarray[0].First(); node; node = node->Next() )
840 {
841 wxObject *p = node->Data();
842 points->Append( p );
843 }
844 for( node = pointsarray[1].First(); node; node = node->Next() )
845 {
846 wxObject *p = node->Data();
847 points->Append( p );
848 }
849 for( node = pointsarray[2].First(); node; node = node->Next() )
850 {
851 wxObject *p = node->Data();
852 points->Append( p );
853 }
854 for( node = pointsarray[3].First(); node; node = node->Next() )
855 {
856 wxObject *p = node->Data();
857 points->Append( p );
858 }
859 } // not iUseAngles
860 } // CalculateEllipticPoints
861
862 #endif
863