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"
33 // bool wxDCBase::sm_cacheing = false;
35 // ============================================================================
37 // ============================================================================
39 // ----------------------------------------------------------------------------
41 // ----------------------------------------------------------------------------
43 void wxDCBase::DoDrawCheckMark(wxCoord x1
, wxCoord y1
,
44 wxCoord width
, wxCoord height
)
46 wxCHECK_RET( Ok(), wxT("invalid window dc") );
48 wxCoord x2
= x1
+ width
,
51 // this is to yield width of 3 for width == height == 10
52 SetPen(wxPen(GetTextForeground(), (width
+ height
+ 1) / 7, wxSOLID
));
54 // we're drawing a scaled version of wx/generic/tick.xpm here
55 wxCoord x3
= x1
+ (4*width
) / 10, // x of the tick bottom
56 y3
= y1
+ height
/ 2; // y of the left tick branch
57 DoDrawLine(x1
, y3
, x3
, y2
);
58 DoDrawLine(x3
, y2
, x2
, y1
);
60 CalcBoundingBox(x1
, y1
);
61 CalcBoundingBox(x2
, y2
);
64 // ----------------------------------------------------------------------------
66 // ----------------------------------------------------------------------------
68 void wxDCBase::DrawLines(const wxList
*list
, wxCoord xoffset
, wxCoord yoffset
)
70 int n
= list
->GetCount();
71 wxPoint
*points
= new wxPoint
[n
];
74 for ( wxList::compatibility_iterator node
= list
->GetFirst(); node
; node
= node
->GetNext(), i
++ )
76 wxPoint
*point
= (wxPoint
*)node
->GetData();
77 points
[i
].x
= point
->x
;
78 points
[i
].y
= point
->y
;
81 DoDrawLines(n
, points
, xoffset
, yoffset
);
87 void wxDCBase::DrawPolygon(const wxList
*list
,
88 wxCoord xoffset
, wxCoord yoffset
,
91 int n
= list
->GetCount();
92 wxPoint
*points
= new wxPoint
[n
];
95 for ( wxList::compatibility_iterator node
= list
->GetFirst(); node
; node
= node
->GetNext(), i
++ )
97 wxPoint
*point
= (wxPoint
*)node
->GetData();
98 points
[i
].x
= point
->x
;
99 points
[i
].y
= point
->y
;
102 DoDrawPolygon(n
, points
, xoffset
, yoffset
, fillStyle
);
108 wxDCBase::DoDrawPolyPolygon(int n
,
111 wxCoord xoffset
, wxCoord yoffset
,
116 DoDrawPolygon(count
[0], points
, xoffset
, yoffset
, fillStyle
);
124 for (i
= j
= lastOfs
= 0; i
< n
; i
++)
129 pts
= new wxPoint
[j
+n
-1];
130 for (i
= 0; i
< j
; i
++)
132 for (i
= 2; i
<= n
; i
++)
134 lastOfs
-= count
[n
-i
];
135 pts
[j
++] = pts
[lastOfs
];
139 SetPen(wxPen(*wxBLACK
, 0, wxTRANSPARENT
));
140 DoDrawPolygon(j
, pts
, xoffset
, yoffset
, fillStyle
);
142 for (i
= j
= 0; i
< n
; i
++)
144 DoDrawLines(count
[i
], pts
+j
, xoffset
, yoffset
);
150 // ----------------------------------------------------------------------------
152 // ----------------------------------------------------------------------------
156 // TODO: this API needs fixing (wxPointList, why (!const) "wxList *"?)
157 void wxDCBase::DrawSpline(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord x3
, wxCoord y3
)
161 wxPoint
*point1
= new wxPoint
;
162 point1
->x
= x1
; point1
->y
= y1
;
163 point_list
.Append((wxObject
*)point1
);
165 wxPoint
*point2
= new wxPoint
;
166 point2
->x
= x2
; point2
->y
= y2
;
167 point_list
.Append((wxObject
*)point2
);
169 wxPoint
*point3
= new wxPoint
;
170 point3
->x
= x3
; point3
->y
= y3
;
171 point_list
.Append((wxObject
*)point3
);
173 DrawSpline(&point_list
);
175 for( wxList::compatibility_iterator node
= point_list
.GetFirst(); node
; node
= node
->GetNext() )
177 wxPoint
*p
= (wxPoint
*)node
->GetData();
182 void wxDCBase::DrawSpline(int n
, wxPoint points
[])
185 for (int i
=0; i
< n
; i
++)
187 list
.Append((wxObject
*)&points
[i
]);
193 // ----------------------------------- spline code ----------------------------------------
195 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
,
196 double a3
, double b3
, double a4
, double b4
);
197 void wx_clear_stack();
198 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
, double *x3
,
199 double *y3
, double *x4
, double *y4
);
200 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
,
201 double x4
, double y4
);
202 static bool wx_spline_add_point(double x
, double y
);
203 static void wx_spline_draw_point_array(wxDCBase
*dc
);
205 wxList wx_spline_point_list
;
207 #define half(z1, z2) ((z1+z2)/2.0)
210 /* iterative version */
212 void wx_quadratic_spline(double a1
, double b1
, double a2
, double b2
, double a3
, double b3
, double a4
,
215 register double xmid
, ymid
;
216 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
219 wx_spline_push(a1
, b1
, a2
, b2
, a3
, b3
, a4
, b4
);
221 while (wx_spline_pop(&x1
, &y1
, &x2
, &y2
, &x3
, &y3
, &x4
, &y4
)) {
222 xmid
= (double)half(x2
, x3
);
223 ymid
= (double)half(y2
, y3
);
224 if (fabs(x1
- xmid
) < THRESHOLD
&& fabs(y1
- ymid
) < THRESHOLD
&&
225 fabs(xmid
- x4
) < THRESHOLD
&& fabs(ymid
- y4
) < THRESHOLD
) {
226 wx_spline_add_point( x1
, y1
);
227 wx_spline_add_point( xmid
, ymid
);
229 wx_spline_push(xmid
, ymid
, (double)half(xmid
, x3
), (double)half(ymid
, y3
),
230 (double)half(x3
, x4
), (double)half(y3
, y4
), x4
, y4
);
231 wx_spline_push(x1
, y1
, (double)half(x1
, x2
), (double)half(y1
, y2
),
232 (double)half(x2
, xmid
), (double)half(y2
, ymid
), xmid
, ymid
);
237 /* utilities used by spline drawing routines */
239 typedef struct wx_spline_stack_struct
{
240 double x1
, y1
, x2
, y2
, x3
, y3
, x4
, y4
;
243 #define SPLINE_STACK_DEPTH 20
244 static Stack wx_spline_stack
[SPLINE_STACK_DEPTH
];
245 static Stack
*wx_stack_top
;
246 static int wx_stack_count
;
248 void wx_clear_stack()
250 wx_stack_top
= wx_spline_stack
;
254 void wx_spline_push(double x1
, double y1
, double x2
, double y2
, double x3
, double y3
, double x4
, double y4
)
256 wx_stack_top
->x1
= x1
;
257 wx_stack_top
->y1
= y1
;
258 wx_stack_top
->x2
= x2
;
259 wx_stack_top
->y2
= y2
;
260 wx_stack_top
->x3
= x3
;
261 wx_stack_top
->y3
= y3
;
262 wx_stack_top
->x4
= x4
;
263 wx_stack_top
->y4
= y4
;
268 int wx_spline_pop(double *x1
, double *y1
, double *x2
, double *y2
,
269 double *x3
, double *y3
, double *x4
, double *y4
)
271 if (wx_stack_count
== 0)
275 *x1
= wx_stack_top
->x1
;
276 *y1
= wx_stack_top
->y1
;
277 *x2
= wx_stack_top
->x2
;
278 *y2
= wx_stack_top
->y2
;
279 *x3
= wx_stack_top
->x3
;
280 *y3
= wx_stack_top
->y3
;
281 *x4
= wx_stack_top
->x4
;
282 *y4
= wx_stack_top
->y4
;
286 static bool wx_spline_add_point(double x
, double y
)
288 wxPoint
*point
= new wxPoint
;
291 wx_spline_point_list
.Append((wxObject
*)point
);
295 static void wx_spline_draw_point_array(wxDCBase
*dc
)
297 dc
->DrawLines(&wx_spline_point_list
, 0, 0 );
298 wxList::compatibility_iterator node
= wx_spline_point_list
.GetFirst();
301 wxPoint
*point
= (wxPoint
*)node
->GetData();
303 wx_spline_point_list
.Erase(node
);
304 node
= wx_spline_point_list
.GetFirst();
308 void wxDCBase::DoDrawSpline( wxList
*points
)
310 wxCHECK_RET( Ok(), wxT("invalid window dc") );
313 double cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
;
314 double x1
, y1
, x2
, y2
;
316 wxList::compatibility_iterator node
= points
->GetFirst();
317 if (node
== wxList::compatibility_iterator())
321 p
= (wxPoint
*)node
->GetData();
326 node
= node
->GetNext();
327 p
= (wxPoint
*)node
->GetData();
331 cx1
= (double)((x1
+ x2
) / 2);
332 cy1
= (double)((y1
+ y2
) / 2);
333 cx2
= (double)((cx1
+ x2
) / 2);
334 cy2
= (double)((cy1
+ y2
) / 2);
336 wx_spline_add_point(x1
, y1
);
338 while ((node
= node
->GetNext())
344 p
= (wxPoint
*)node
->GetData();
349 cx4
= (double)(x1
+ x2
) / 2;
350 cy4
= (double)(y1
+ y2
) / 2;
351 cx3
= (double)(x1
+ cx4
) / 2;
352 cy3
= (double)(y1
+ cy4
) / 2;
354 wx_quadratic_spline(cx1
, cy1
, cx2
, cy2
, cx3
, cy3
, cx4
, cy4
);
358 cx2
= (double)(cx1
+ x2
) / 2;
359 cy2
= (double)(cy1
+ y2
) / 2;
362 wx_spline_add_point( cx1
, cy1
);
363 wx_spline_add_point( x2
, y2
);
365 wx_spline_draw_point_array( this );
368 #endif // wxUSE_SPLINES
370 // ----------------------------------------------------------------------------
371 // Partial Text Extents
372 // ----------------------------------------------------------------------------
375 // Each element of the widths array will be the width of the string up to and
376 // including the coresponding character in text. This is the generic
377 // implementation, the port-specific classes should do this with native APIs
378 // if available and if faster. Note: pango_layout_index_to_pos is much slower
379 // than calling GetTextExtent!!
386 FontWidthCache() : m_scaleX(1), m_widths(NULL
) { }
387 ~FontWidthCache() { delete []m_widths
; }
392 m_widths
= new int[FWC_SIZE
];
394 memset(m_widths
, 0, sizeof(int)*FWC_SIZE
);
402 static FontWidthCache s_fontWidthCache
;
404 bool wxDCBase::DoGetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const
408 size_t i
, len
= text
.Length();
413 // reset the cache if font or horizontal scale have changed
414 if (!s_fontWidthCache
.m_widths
||
415 (s_fontWidthCache
.m_scaleX
!= m_scaleX
) ||
416 (s_fontWidthCache
.m_font
!= GetFont()))
418 s_fontWidthCache
.Reset();
419 s_fontWidthCache
.m_font
= GetFont();
420 s_fontWidthCache
.m_scaleX
= m_scaleX
;
423 // Calculate the position of each character based on the widths of
424 // the previous characters
425 for (i
=0; i
<len
; i
++)
427 const wxChar c
= text
[i
];
428 unsigned int c_int
= (unsigned int)c
;
430 if ((c_int
< FWC_SIZE
) && (s_fontWidthCache
.m_widths
[c_int
] != 0))
432 w
= s_fontWidthCache
.m_widths
[c_int
];
436 GetTextExtent(c
, &w
, &h
);
437 if (c_int
< FWC_SIZE
)
438 s_fontWidthCache
.m_widths
[c_int
] = w
;
442 widths
[i
] = totalWidth
;
449 // ----------------------------------------------------------------------------
450 // enhanced text drawing
451 // ----------------------------------------------------------------------------
453 void wxDCBase::GetMultiLineTextExtent(const wxString
& text
,
459 wxCoord widthTextMax
= 0, widthLine
,
460 heightTextTotal
= 0, heightLineDefault
= 0, heightLine
= 0;
463 for ( const wxChar
*pc
= text
; ; pc
++ )
465 if ( *pc
== _T('\n') || *pc
== _T('\0') )
467 if ( curLine
.empty() )
469 // we can't use GetTextExtent - it will return 0 for both width
470 // and height and an empty line should count in height
473 // assume that this line has the same height as the previous
475 if ( !heightLineDefault
)
476 heightLineDefault
= heightLine
;
478 if ( !heightLineDefault
)
480 // but we don't know it yet - choose something reasonable
481 GetTextExtent(_T("W"), NULL
, &heightLineDefault
,
485 heightTextTotal
+= heightLineDefault
;
489 GetTextExtent(curLine
, &widthLine
, &heightLine
,
491 if ( widthLine
> widthTextMax
)
492 widthTextMax
= widthLine
;
493 heightTextTotal
+= heightLine
;
496 if ( *pc
== _T('\n') )
515 *y
= heightTextTotal
;
520 void wxDCBase::DrawLabel(const wxString
& text
,
521 const wxBitmap
& bitmap
,
525 wxRect
*rectBounding
)
527 // find the text position
528 wxCoord widthText
, heightText
, heightLine
;
529 GetMultiLineTextExtent(text
, &widthText
, &heightText
, &heightLine
);
531 wxCoord width
, height
;
534 width
= widthText
+ bitmap
.GetWidth();
535 height
= bitmap
.GetHeight();
544 if ( alignment
& wxALIGN_RIGHT
)
546 x
= rect
.GetRight() - width
;
548 else if ( alignment
& wxALIGN_CENTRE_HORIZONTAL
)
550 x
= (rect
.GetLeft() + rect
.GetRight() + 1 - width
) / 2;
552 else // alignment & wxALIGN_LEFT
557 if ( alignment
& wxALIGN_BOTTOM
)
559 y
= rect
.GetBottom() - height
;
561 else if ( alignment
& wxALIGN_CENTRE_VERTICAL
)
563 y
= (rect
.GetTop() + rect
.GetBottom() + 1 - height
) / 2;
565 else // alignment & wxALIGN_TOP
570 // draw the bitmap first
576 DrawBitmap(bitmap
, x
, y
, true /* use mask */);
578 wxCoord offset
= bitmap
.GetWidth() + 4;
582 y
+= (height
- heightText
) / 2;
585 // we will draw the underscore under the accel char later
586 wxCoord startUnderscore
= 0,
590 // split the string into lines and draw each of them separately
592 for ( const wxChar
*pc
= text
; ; pc
++ )
594 if ( *pc
== _T('\n') || *pc
== _T('\0') )
596 int xRealStart
= x
; // init it here to avoid compielr warnings
598 if ( !curLine
.empty() )
600 // NB: can't test for !(alignment & wxALIGN_LEFT) because
602 if ( alignment
& (wxALIGN_RIGHT
| wxALIGN_CENTRE_HORIZONTAL
) )
605 GetTextExtent(curLine
, &widthLine
, NULL
);
607 if ( alignment
& wxALIGN_RIGHT
)
609 xRealStart
+= width
- widthLine
;
611 else // if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
613 xRealStart
+= (width
- widthLine
) / 2;
616 //else: left aligned, nothing to do
618 DrawText(curLine
, xRealStart
, y
);
623 // do we have underscore in this line? we can check yUnderscore
624 // because it is set below to just y + heightLine if we do
625 if ( y
== yUnderscore
)
627 // adjust the horz positions to account for the shift
628 startUnderscore
+= xRealStart
;
629 endUnderscore
+= xRealStart
;
632 if ( *pc
== _T('\0') )
637 else // not end of line
639 if ( pc
- text
.c_str() == indexAccel
)
641 // remeber to draw underscore here
642 GetTextExtent(curLine
, &startUnderscore
, NULL
);
644 GetTextExtent(curLine
, &endUnderscore
, NULL
);
646 yUnderscore
= y
+ heightLine
;
655 // draw the underscore if found
656 if ( startUnderscore
!= endUnderscore
)
658 // it should be of the same colour as text
659 SetPen(wxPen(GetTextForeground(), 0, wxSOLID
));
663 DrawLine(startUnderscore
, yUnderscore
, endUnderscore
, yUnderscore
);
666 // return bounding rect if requested
669 *rectBounding
= wxRect(x
, y
- heightText
, widthText
, heightText
);
672 CalcBoundingBox(x0
, y0
);
673 CalcBoundingBox(x0
+ width0
, y0
+ height
);
677 Notes for wxWidgets DrawEllipticArcRot(...)
679 wxDCBase::DrawEllipticArcRot(...) draws a rotated elliptic arc or an ellipse.
680 It uses wxDCBase::CalculateEllipticPoints(...) and wxDCBase::Rotate(...),
683 All methods are generic, so they can be implemented in wxDCBase.
684 DoDrawEllipticArcRot(...) is virtual, so it can be called from deeper
685 methods like (WinCE) wxDC::DoDrawArc(...).
687 CalculateEllipticPoints(...) fills a given list of wxPoints with some points
688 of an elliptic arc. The algorithm is pixel-based: In every row (in flat
689 parts) or every column (in steep parts) only one pixel is calculated.
690 Trigonometric calculation (sin, cos, tan, atan) is only done if the
691 starting angle is not equal to the ending angle. The calculation of the
692 pixels is done using simple arithmetic only and should perform not too
693 bad even on devices without floating point processor. I didn't test this yet.
695 Rotate(...) rotates a list of point pixel-based, you will see rounding errors.
696 For instance: an ellipse rotated 180 degrees is drawn
697 slightly different from the original.
699 The points are then moved to an array and used to draw a polyline and/or polygon
700 (with center added, the pie).
701 The result looks quite similar to the native ellipse, only e few pixels differ.
703 The performance on a desktop system (Athlon 1800, WinXP) is about 7 times
704 slower as DrawEllipse(...), which calls the native API.
705 An rotated ellipse outside the clipping region takes nearly the same time,
706 while an native ellipse outside takes nearly no time to draw.
708 If you draw an arc with this new method, you will see the starting and ending angles
709 are calculated properly.
710 If you use DrawEllipticArc(...), you will see they are only correct for circles
711 and not properly calculated for ellipses.
714 p.lenhard@t-online.de
718 void wxDCBase::DoDrawEllipticArcRot( wxCoord x
, wxCoord y
,
719 wxCoord w
, wxCoord h
,
720 double sa
, double ea
, double angle
)
724 CalculateEllipticPoints( &list
, x
, y
, w
, h
, sa
, ea
);
725 Rotate( &list
, angle
, wxPoint( x
+w
/2, y
+h
/2 ) );
727 // Add center (for polygon/pie)
728 list
.Append( (wxObject
*) new wxPoint( x
+w
/2, y
+h
/2 ) );
730 // copy list into array and delete list elements
731 int n
= list
.Number();
732 wxPoint
*points
= new wxPoint
[n
];
735 for ( node
= list
.First(); node
; node
= node
->Next(), i
++ )
737 wxPoint
*point
= (wxPoint
*)node
->Data();
738 points
[i
].x
= point
->x
;
739 points
[i
].y
= point
->y
;
743 // first draw the pie without pen, if necessary
744 if( GetBrush() != *wxTRANSPARENT_BRUSH
)
746 wxPen
tempPen( GetPen() );
747 SetPen( *wxTRANSPARENT_PEN
);
748 DoDrawPolygon( n
, points
, 0, 0 );
752 // then draw the arc without brush, if necessary
753 if( GetPen() != *wxTRANSPARENT_PEN
)
756 DoDrawLines( n
-1, points
, 0, 0 );
761 } // DrawEllipticArcRot
763 void wxDCBase::Rotate( wxList
* points
, double angle
, wxPoint center
)
768 double dSinA
= -sin(angle
*2.0*pi
/360.0);
769 double dCosA
= cos(angle
*2.0*pi
/360.0);
770 for ( wxNode
* node
= points
->First(); node
; node
= node
->Next() )
772 wxPoint
* point
= (wxPoint
*)node
->Data();
774 // transform coordinates, if necessary
775 if( center
.x
) point
->x
-= center
.x
;
776 if( center
.y
) point
->y
-= center
.y
;
778 // calculate rotation, rounding simply by implicit cast to integer
779 int xTemp
= point
->x
* dCosA
- point
->y
* dSinA
;
780 point
->y
= point
->x
* dSinA
+ point
->y
* dCosA
;
783 // back transform coordinates, if necessary
784 if( center
.x
) point
->x
+= center
.x
;
785 if( center
.y
) point
->y
+= center
.y
;
790 void wxDCBase::CalculateEllipticPoints( wxList
* points
,
791 wxCoord xStart
, wxCoord yStart
,
792 wxCoord w
, wxCoord h
,
793 double sa
, double ea
)
804 bool bUseAngles
= false;
810 // decrement 1 pixel if ellipse is smaller than 2*a, 2*b
812 if( 2*a
== w
) decrX
= 1;
814 if( 2*b
== h
) decrY
= 1;
816 wxCoord xCenter
= xStart
+ a
;
817 wxCoord yCenter
= yStart
+ b
;
818 // calculate data for start and end, if necessary
822 // normalisation of angles
823 while( sa
<0 ) sa
+= 360;
824 while( ea
<0 ) ea
+= 360;
825 while( sa
>=360 ) sa
-= 360;
826 while( ea
>=360 ) ea
-= 360;
827 // calculate quadrant numbers
828 if( sa
> 270 ) sq
= 3;
829 else if( sa
> 180 ) sq
= 2;
830 else if( sa
> 90 ) sq
= 1;
831 if( ea
> 270 ) eq
= 3;
832 else if( ea
> 180 ) eq
= 2;
833 else if( ea
> 90 ) eq
= 1;
834 sar
= sa
* pi
/ 180.0;
835 ear
= ea
* pi
/ 180.0;
836 // correct angle circle -> ellipse
837 sar
= atan( -a
/(double)b
* tan( sar
) );
838 if ( sq
== 1 || sq
== 2 ) sar
+= pi
;
839 ear
= atan( -a
/(double)b
* tan( ear
) );
840 if ( eq
== 1 || eq
== 2 ) ear
+= pi
;
841 // coordinates of points
842 xsa
= xCenter
+ a
* cos( sar
);
843 if( sq
== 0 || sq
== 3 ) xsa
-= decrX
;
844 ysa
= yCenter
+ b
* sin( sar
);
845 if( sq
== 2 || sq
== 3 ) ysa
-= decrY
;
846 xea
= xCenter
+ a
* cos( ear
);
847 if( eq
== 0 || eq
== 3 ) xea
-= decrX
;
848 yea
= yCenter
+ b
* sin( ear
);
849 if( eq
== 2 || eq
== 3 ) yea
-= decrY
;
851 // calculate c1 = b^2, c2 = b^2/a^2 with a = w/2, b = h/2
862 // Lists for quadrant 1 to 4
863 wxList pointsarray
[4];
864 // Calculate points for first quadrant and set in all quadrants
865 for( x
= 0; x
<= a
; ++x
)
870 bool bNewPoint
= false;
871 while( y2
> c1
- c2
* x2
&& y
> 0 )
877 // old y now to big: set point with old y, old x
878 if( bNewPoint
&& x
>1)
881 // remove points on the same line
882 pointsarray
[0].Insert( (wxObject
*) new wxPoint( xCenter
+ x1
- decrX
, yCenter
- y_old
) );
883 pointsarray
[1].Append( (wxObject
*) new wxPoint( xCenter
- x1
, yCenter
- y_old
) );
884 pointsarray
[2].Insert( (wxObject
*) new wxPoint( xCenter
- x1
, yCenter
+ y_old
- decrY
) );
885 pointsarray
[3].Append( (wxObject
*) new wxPoint( xCenter
+ x1
- decrX
, yCenter
+ y_old
- decrY
) );
889 // Starting and/or ending points for the quadrants, first quadrant gets both.
890 pointsarray
[0].Insert( (wxObject
*) new wxPoint( xCenter
+ a
- decrX
, yCenter
) );
891 pointsarray
[0].Append( (wxObject
*) new wxPoint( xCenter
, yCenter
- b
) );
892 pointsarray
[1].Append( (wxObject
*) new wxPoint( xCenter
- a
, yCenter
) );
893 pointsarray
[2].Append( (wxObject
*) new wxPoint( xCenter
, yCenter
+ b
- decrY
) );
894 pointsarray
[3].Append( (wxObject
*) new wxPoint( xCenter
+ a
- decrX
, yCenter
) );
896 // copy quadrants in original list
899 // Copy the right part of the points in the lists
900 // and delete the wxPoints, because they do not leave this method.
901 points
->Append( (wxObject
*) new wxPoint( xsa
, ysa
) );
903 bool bStarted
= false;
905 bool bForceTurn
= ( sq
== eq
&& sa
> ea
);
908 for( wxNode
*node
= pointsarray
[q
].First(); node
; node
= node
->Next() )
910 // once: go to starting point in start quadrant
913 ( (wxPoint
*) node
->Data() )->x
< xsa
+1 && q
<= 1
915 ( (wxPoint
*) node
->Data() )->x
> xsa
-1 && q
>= 2
922 // copy point, if not at ending point
925 if( q
!= eq
|| bForceTurn
927 ( (wxPoint
*) node
->Data() )->x
> xea
+1 && q
<= 1
929 ( (wxPoint
*) node
->Data() )->x
< xea
-1 && q
>= 2
933 wxPoint
* pPoint
= new wxPoint( *((wxPoint
*) node
->Data() ) );
934 points
->Append( (wxObject
*) pPoint
);
936 else if( q
== eq
&& !bForceTurn
|| ( (wxPoint
*) node
->Data() )->x
== xea
)
946 } // while not bReady
947 points
->Append( (wxObject
*) new wxPoint( xea
, yea
) );
950 for( q
= 0; q
< 4; ++q
)
952 for( wxNode
*node
= pointsarray
[q
].First(); node
; node
= node
->Next() )
954 wxPoint
*p
= (wxPoint
*)node
->Data();
961 // copy whole ellipse, wxPoints will be deleted outside
962 for( wxNode
*node
= pointsarray
[0].First(); node
; node
= node
->Next() )
964 wxObject
*p
= node
->Data();
967 for( node
= pointsarray
[1].First(); node
; node
= node
->Next() )
969 wxObject
*p
= node
->Data();
972 for( node
= pointsarray
[2].First(); node
; node
= node
->Next() )
974 wxObject
*p
= node
->Data();
977 for( node
= pointsarray
[3].First(); node
; node
= node
->Next() )
979 wxObject
*p
= node
->Data();
983 } // CalculateEllipticPoints
987 bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
988 const wxColour
& col
, int style
)
991 if (dc
->GetBrush().GetStyle() == wxTRANSPARENT
)
996 dc
->GetSize(&width
, &height
);
998 //it would be nice to fail if we don't get a sensible size...
999 wxCHECK_MSG(width
>= 1 && height
>= 1, false,
1000 wxT("In FloodFill, dc.GetSize routine failed, method not supported by this DC"));
1002 //this is much faster than doing the individual pixels
1004 wxBitmap
bitmap(width
, height
);
1005 memdc
.SelectObject(bitmap
);
1006 memdc
.Blit(0, 0, width
, height
, dc
, 0, 0);
1007 memdc
.SelectObject(wxNullBitmap
);
1009 wxImage image
= bitmap
.ConvertToImage();
1010 wxImageFloodFill(&image
, x
,y
, dc
->GetBrush(), col
, style
,
1011 dc
->GetLogicalFunction());
1012 bitmap
= wxBitmap(image
);
1013 memdc
.SelectObject(bitmap
);
1014 dc
->Blit(0, 0, width
, height
, &memdc
, 0, 0);
1015 memdc
.SelectObject(wxNullBitmap
);