]> git.saurik.com Git - wxWidgets.git/blame - src/common/graphcmn.cpp
avoid conflict between wxBookCtrlBase::DoSetSelection() and the derived classes;...
[wxWidgets.git] / src / common / graphcmn.cpp
CommitLineData
50581042
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/graphcmn.cpp
3// Purpose: graphics context methods common to all platforms
4// Author: Stefan Csomor
5// Modified by:
6// Created:
7// RCS-ID: $Id$
8// Copyright: (c) Stefan Csomor
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#if defined(__BORLANDC__)
24 #pragma hdrstop
25#endif
26
27#include "wx/graphics.h"
28
539872ae
SC
29#ifndef WX_PRECOMP
30 #include "wx/icon.h"
31 #include "wx/bitmap.h"
32 #include "wx/dcmemory.h"
33#endif
34
50581042
SC
35#if wxUSE_GRAPHICS_CONTEXT
36
2f34cf60
RD
37#if !defined(wxMAC_USE_CORE_GRAPHICS_BLEND_MODES)
38#define wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 0
39#endif
40
d94228a2
SC
41//-----------------------------------------------------------------------------
42// constants
43//-----------------------------------------------------------------------------
44
45const double RAD2DEG = 180.0 / M_PI;
46const short kEmulatedMode = -1;
47const short kUnsupportedMode = -2;
48
49//-----------------------------------------------------------------------------
50// Local functions
51//-----------------------------------------------------------------------------
52
53static inline double dmin(double a, double b)
54{
55 return a < b ? a : b;
56}
57static inline double dmax(double a, double b)
58{
59 return a > b ? a : b;
60}
61
62static inline double DegToRad(double deg)
63{
64 return (deg * M_PI) / 180.0;
65}
66static inline double RadToDeg(double deg)
67{
68 return (deg * 180.0) / M_PI;
69}
70
71
50581042
SC
72wxPoint2DDouble wxGraphicsPath::GetCurrentPoint()
73{
74 wxDouble x,y ;
75 GetCurrentPoint(x,y);
76 return wxPoint2DDouble(x,y);
77}
78
79void wxGraphicsPath::MoveToPoint( const wxPoint2DDouble& p)
80{
81 MoveToPoint( p.m_x , p.m_y);
82}
83
84void wxGraphicsPath::AddLineToPoint( const wxPoint2DDouble& p)
85{
86 AddLineToPoint( p.m_x , p.m_y);
87}
88
89void wxGraphicsPath::AddCurveToPoint( const wxPoint2DDouble& c1, const wxPoint2DDouble& c2, const wxPoint2DDouble& e)
90{
91 AddCurveToPoint(c1.m_x, c1.m_y, c2.m_x, c2.m_y, e.m_x, e.m_y);
92}
93
94void wxGraphicsPath::AddArc( const wxPoint2DDouble& c, wxDouble r, wxDouble startAngle, wxDouble endAngle, bool clockwise)
95{
96 AddArc(c.m_x, c.m_y, r, startAngle, endAngle, clockwise);
97}
98
99//
100// Emulations
101//
102
103void wxGraphicsPath::AddQuadCurveToPoint( wxDouble cx, wxDouble cy, wxDouble x, wxDouble y )
104{
105 // calculate using degree elevation to a cubic bezier
106 wxPoint2DDouble c1 ;
107 wxPoint2DDouble c2 ;
108
109 wxPoint2DDouble start = GetCurrentPoint() ;
110 wxPoint2DDouble end(x,y);
111 wxPoint2DDouble c(cx,cy);
5ce3abfb
RD
112 c1 = wxDouble(1/3.0) * start + wxDouble(2/3.0) * c;
113 c2 = wxDouble(2/3.0) * c + wxDouble(1/3.0) * end ;
50581042
SC
114 AddCurveToPoint(c1.m_x,c1.m_y,c2.m_x,c2.m_y,x,y);
115}
116
117void wxGraphicsPath::AddRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h )
118{
119 MoveToPoint(x,y);
120 AddLineToPoint(x,y+h);
121 AddLineToPoint(x+w,y+h);
122 AddLineToPoint(x+w,y);
123 CloseSubpath();
124}
125
126void wxGraphicsPath::AddCircle( wxDouble x, wxDouble y, wxDouble r )
127{
128 MoveToPoint(x+r,y);
129 AddArc( x,y,r,0,2*M_PI,false);
130 CloseSubpath();
131}
132
d94228a2
SC
133// draws a an arc to two tangents connecting (current) to (x1,y1) and (x1,y1) to (x2,y2), also a straight line from (current) to (x1,y1)
134void wxGraphicsPath::AddArcToPoint( wxDouble x1, wxDouble y1 , wxDouble x2, wxDouble y2, wxDouble r )
135{
136 wxPoint2DDouble current = GetCurrentPoint();
137 wxPoint2DDouble p1(x1,y1);
138 wxPoint2DDouble p2(x2,y2);
139
140 wxPoint2DDouble v1 = current - p1 ;
141 v1.Normalize();
142 wxPoint2DDouble v2 = p2 - p1 ;
143 v2.Normalize();
144
145 wxDouble alpha = v1.GetVectorAngle() - v2.GetVectorAngle();
146
147 if ( alpha < 0 )
148 alpha = 360 + alpha ;
149 // TODO obtuse angles
150
151 alpha = DegToRad(alpha);
152
153 wxDouble dist = r / sin(alpha/2) * cos(alpha/2) ;
154 // calculate tangential points
155 wxPoint2DDouble t1 = dist*v1 + p1 ;
156 wxPoint2DDouble t2 = dist*v2 + p1 ;
157
158 wxPoint2DDouble nv1 = v1 ;
159 nv1.SetVectorAngle(v1.GetVectorAngle()-90);
160 wxPoint2DDouble c = t1 + r*nv1;
161
162 wxDouble a1 = v1.GetVectorAngle()+90 ;
163 wxDouble a2 = v2.GetVectorAngle()-90 ;
164
165 AddLineToPoint(t1);
166 AddArc(c.m_x,c.m_y,r,DegToRad(a1),DegToRad(a2),true);
167 AddLineToPoint(p2);
168}
169
50581042
SC
170//-----------------------------------------------------------------------------
171// wxGraphicsContext Convenience Methods
172//-----------------------------------------------------------------------------
173
174void wxGraphicsContext::DrawPath( const wxGraphicsPath *path, int fillStyle )
175{
176 FillPath( path , fillStyle );
177 StrokePath( path );
178}
179
180void wxGraphicsContext::DrawText( const wxString &str, wxDouble x, wxDouble y, wxDouble angle )
181{
182 Translate(x,y) ;
183 Rotate( -angle );
184 DrawText( str , 0, 0 );
185 Rotate( angle );
186 Translate(-x,-y) ;
187}
188
189void wxGraphicsContext::StrokeLine( wxDouble x1, wxDouble y1, wxDouble x2, wxDouble y2)
190{
191 wxGraphicsPath* path = CreatePath();
192 path->MoveToPoint(x1, y1) ;
193 path->AddLineToPoint( x2, y2 );
194 StrokePath( path );
195 delete path;
196}
197
198void wxGraphicsContext::DrawRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h)
199{
200 wxGraphicsPath* path = CreatePath();
201 path->AddRectangle( x , y , w , h );
202 DrawPath( path );
203 delete path;
204}
205
206void wxGraphicsContext::DrawEllipse( wxDouble x, wxDouble y, wxDouble w, wxDouble h)
207{
208 wxGraphicsPath* path = CreatePath();
209 if ( w == h )
210 {
211 path->AddCircle( x+w/2,y+w/2,w/2);
212 DrawPath(path);
213 }
214 else
215 {
216 PushState();
217 Translate(x+w/2,y+h/2);
218 wxDouble factor = ((wxDouble) w) / h ;
219 Scale( factor , 1.0) ;
220 path->AddCircle(0,0,h/2);
221 DrawPath(path);
222 PopState();
223 }
224 delete path;
225}
226
227void wxGraphicsContext::DrawRoundedRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h, wxDouble radius)
228{
229 wxGraphicsPath* path = CreatePath();
230 if ( radius == 0)
231 {
232 path->AddRectangle( x , y , w , h );
233 DrawPath( path );
234 }
235 else
236 {
237 PushState();
238 Translate( x , y );
239
240 double fw = w / radius;
241 double fh = h / radius;
242
243 path->MoveToPoint(w, h / 2);
244 path->AddArcToPoint(w, h, w / 2, h, radius);
245 path->AddArcToPoint(0, h, 0, h / 2, radius);
246 path->AddArcToPoint(0, 0, w / 2, 0, radius);
247 path->AddArcToPoint(w, 0, w, h / 2, radius);
248 path->CloseSubpath();
249 DrawPath( path );
250 PopState();
251 }
252 delete path;
253}
254
255void wxGraphicsContext::StrokeLines( size_t n, const wxPoint2DDouble *points)
256{
257 wxASSERT(n > 1);
258 wxGraphicsPath* path = CreatePath();
259 path->MoveToPoint(points[0].m_x, points[0].m_y) ;
260 for ( int i = 1 ; i < n; ++i)
261 path->AddLineToPoint( points[i].m_x, points[i].m_y );
262 StrokePath( path );
263 delete path;
264}
265
266void wxGraphicsContext::DrawLines( size_t n, const wxPoint2DDouble *points, int fillStyle)
267{
268 wxASSERT(n > 1);
269 wxGraphicsPath* path = CreatePath();
270 path->MoveToPoint(points[0].m_x, points[0].m_y) ;
271 for ( int i = 1 ; i < n; ++i)
272 path->AddLineToPoint( points[i].m_x, points[i].m_y );
273 DrawPath( path , fillStyle);
274 delete path;
275}
276
277void wxGraphicsContext::StrokeLines( size_t n, const wxPoint2DDouble *beginPoints, const wxPoint2DDouble *endPoints)
278{
279 wxASSERT(n > 0);
280 wxGraphicsPath* path = CreatePath();
281 for ( int i = 0 ; i < n; ++i)
282 {
283 path->MoveToPoint(beginPoints[i].m_x, beginPoints[i].m_y) ;
284 path->AddLineToPoint( endPoints[i].m_x, endPoints[i].m_y );
285 }
286 StrokePath( path );
287 delete path;
288}
289
50581042
SC
290IMPLEMENT_ABSTRACT_CLASS(wxGCDC, wxObject)
291
50581042
SC
292//-----------------------------------------------------------------------------
293// wxDC bridge class
294//-----------------------------------------------------------------------------
295
296wxGCDC::wxGCDC()
297{
298 Init();
299}
300
301
302wxGCDC::wxGCDC(const wxWindowDC& dc)
303{
304 Init();
305 m_graphicContext = wxGraphicsContext::Create(dc);
306 m_ok = true;
d94228a2
SC
307 if ( dc.GetFont().Ok())
308 m_graphicContext->SetFont(dc.GetFont());
af863805
SC
309 if ( dc.GetPen().Ok())
310 m_graphicContext->SetPen(dc.GetPen());
311 if ( dc.GetBrush().Ok())
312 m_graphicContext->SetBrush(dc.GetBrush());
313 m_graphicContext->SetTextColor(dc.GetTextForeground());
50581042
SC
314}
315
316void wxGCDC::Init()
317{
318 m_ok = false;
319 m_colour = true;
320 m_mm_to_pix_x = mm2pt;
321 m_mm_to_pix_y = mm2pt;
322
323 m_pen = *wxBLACK_PEN;
324 m_font = *wxNORMAL_FONT;
325 m_brush = *wxWHITE_BRUSH;
326
327 m_graphicContext = NULL;
328}
329
330
331wxGCDC::~wxGCDC()
332{
333 delete m_graphicContext;
334}
335
336void wxGCDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask )
337{
338 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawBitmap - invalid DC") );
339 wxCHECK_RET( bmp.Ok(), wxT("wxGCDC(cg)::DoDrawBitmap - invalid bitmap") );
340
341 wxCoord xx = LogicalToDeviceX(x);
342 wxCoord yy = LogicalToDeviceY(y);
343 wxCoord w = bmp.GetWidth();
344 wxCoord h = bmp.GetHeight();
345 wxCoord ww = LogicalToDeviceXRel(w);
346 wxCoord hh = LogicalToDeviceYRel(h);
347
348 m_graphicContext->DrawBitmap( bmp, xx , yy , ww , hh );
349}
350
351void wxGCDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y )
352{
353 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawIcon - invalid DC") );
354 wxCHECK_RET( icon.Ok(), wxT("wxGCDC(cg)::DoDrawIcon - invalid icon") );
355
356 wxCoord xx = LogicalToDeviceX(x);
357 wxCoord yy = LogicalToDeviceY(y);
358 wxCoord w = icon.GetWidth();
359 wxCoord h = icon.GetHeight();
360 wxCoord ww = LogicalToDeviceXRel(w);
361 wxCoord hh = LogicalToDeviceYRel(h);
362
363 m_graphicContext->DrawIcon( icon , xx, yy, ww, hh );
364}
365
366void wxGCDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
367{
368 // TODO Clipping
369#if 0
370 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoSetClippingRegion - invalid DC") );
371
372 wxCoord xx, yy, ww, hh;
373 xx = LogicalToDeviceX(x);
374 yy = LogicalToDeviceY(y);
375 ww = LogicalToDeviceXRel(width);
376 hh = LogicalToDeviceYRel(height);
377
378 CGContextRef cgContext = ((wxCairoContext*)(m_graphicContext))->GetNativeContext();
379 CGRect clipRect = CGRectMake( xx , yy , ww, hh );
380 CGContextClipToRect( cgContext , clipRect );
381
382 // SetRectRgn( (RgnHandle) m_macCurrentClipRgn , xx , yy , xx + ww , yy + hh );
383 // SectRgn( (RgnHandle) m_macCurrentClipRgn , (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn );
384
385 if ( m_clipping )
386 {
387 m_clipX1 = wxMax( m_clipX1, xx );
388 m_clipY1 = wxMax( m_clipY1, yy );
389 m_clipX2 = wxMin( m_clipX2, (xx + ww) );
390 m_clipY2 = wxMin( m_clipY2, (yy + hh) );
391 }
392 else
393 {
394 m_clipping = true;
395
396 m_clipX1 = xx;
397 m_clipY1 = yy;
398 m_clipX2 = xx + ww;
399 m_clipY2 = yy + hh;
400 }
401
402 // TODO: as soon as we don't reset the context for each operation anymore
403 // we have to update the context as well
404#endif
405
406}
407
408void wxGCDC::DoSetClippingRegionAsRegion( const wxRegion &region )
409{
410 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoSetClippingRegionAsRegion - invalid DC") );
411
412 if (region.Empty())
413 {
414 DestroyClippingRegion();
415 return;
416 }
417
418 wxCoord x, y, w, h;
419 region.GetBox( x, y, w, h );
420 wxCoord xx, yy, ww, hh;
421 xx = LogicalToDeviceX(x);
422 yy = LogicalToDeviceY(y);
423 ww = LogicalToDeviceXRel(w);
424 hh = LogicalToDeviceYRel(h);
425
426 // if we have a scaling that we cannot map onto native regions
427 // we must use the box
428 if ( ww != w || hh != h )
429 {
430 wxGCDC::DoSetClippingRegion( x, y, w, h );
431 }
432 else
433 {
434#if 0
435 CopyRgn( (RgnHandle) region.GetWXHRGN() , (RgnHandle) m_macCurrentClipRgn );
436 if ( xx != x || yy != y )
437 OffsetRgn( (RgnHandle) m_macCurrentClipRgn , xx - x , yy - y );
438 SectRgn( (RgnHandle)m_macCurrentClipRgn , (RgnHandle)m_macBoundaryClipRgn , (RgnHandle)m_macCurrentClipRgn );
439#endif
440
441 if ( m_clipping )
442 {
443 m_clipX1 = wxMax( m_clipX1, xx );
444 m_clipY1 = wxMax( m_clipY1, yy );
445 m_clipX2 = wxMin( m_clipX2, (xx + ww) );
446 m_clipY2 = wxMin( m_clipY2, (yy + hh) );
447 }
448 else
449 {
450 m_clipping = true;
451
452 m_clipX1 = xx;
453 m_clipY1 = yy;
454 m_clipX2 = xx + ww;
455 m_clipY2 = yy + hh;
456 }
457 }
458}
459
460void wxGCDC::DestroyClippingRegion()
461{
462 // TODO Clipping
463#if 0
464 // CopyRgn( (RgnHandle) m_macBoundaryClipRgn , (RgnHandle) m_macCurrentClipRgn );
465
466 CGContextRef cgContext = ((wxCairoContext*)(m_graphicContext))->GetNativeContext();
467 CGContextRestoreGState( cgContext );
468 CGContextSaveGState( cgContext );
469
470 m_graphicContext->SetPen( m_pen );
471 m_graphicContext->SetBrush( m_brush );
472
473 m_clipping = false;
474#endif
475
476}
477
478void wxGCDC::DoGetSizeMM( int* width, int* height ) const
479{
480 int w = 0, h = 0;
481
482 GetSize( &w, &h );
483 if (width)
484 *width = long( double(w) / (m_scaleX * m_mm_to_pix_x) );
485 if (height)
486 *height = long( double(h) / (m_scaleY * m_mm_to_pix_y) );
487}
488
489void wxGCDC::SetTextForeground( const wxColour &col )
490{
491 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::SetTextForeground - invalid DC") );
492
493 if ( col != m_textForegroundColour )
494 {
495 m_textForegroundColour = col;
496 m_graphicContext->SetTextColor( col );
497 }
498}
499
500void wxGCDC::SetTextBackground( const wxColour &col )
501{
502 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::SetTextBackground - invalid DC") );
503
504 m_textBackgroundColour = col;
505}
506
507void wxGCDC::SetMapMode( int mode )
508{
509 switch (mode)
510 {
511 case wxMM_TWIPS:
512 SetLogicalScale( twips2mm * m_mm_to_pix_x, twips2mm * m_mm_to_pix_y );
513 break;
514
515 case wxMM_POINTS:
516 SetLogicalScale( pt2mm * m_mm_to_pix_x, pt2mm * m_mm_to_pix_y );
517 break;
518
519 case wxMM_METRIC:
520 SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y );
521 break;
522
523 case wxMM_LOMETRIC:
524 SetLogicalScale( m_mm_to_pix_x / 10.0, m_mm_to_pix_y / 10.0 );
525 break;
526
527 case wxMM_TEXT:
528 default:
529 SetLogicalScale( 1.0, 1.0 );
530 break;
531 }
532
533 ComputeScaleAndOrigin();
534}
535
536void wxGCDC::SetUserScale( double x, double y )
537{
538 // allow negative ? -> no
539 m_userScaleX = x;
540 m_userScaleY = y;
541 ComputeScaleAndOrigin();
542}
543
544void wxGCDC::SetLogicalScale( double x, double y )
545{
546 // allow negative ?
547 m_logicalScaleX = x;
548 m_logicalScaleY = y;
549 ComputeScaleAndOrigin();
550}
551
552void wxGCDC::SetLogicalOrigin( wxCoord x, wxCoord y )
553{
554 m_logicalOriginX = x * m_signX; // is this still correct ?
555 m_logicalOriginY = y * m_signY;
556 ComputeScaleAndOrigin();
557}
558
559void wxGCDC::SetDeviceOrigin( wxCoord x, wxCoord y )
560{
561 m_deviceOriginX = x;
562 m_deviceOriginY = y;
563 ComputeScaleAndOrigin();
564}
565
566void wxGCDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
567{
568 m_signX = (xLeftRight ? 1 : -1);
569 m_signY = (yBottomUp ? -1 : 1);
570 ComputeScaleAndOrigin();
571}
572
573wxSize wxGCDC::GetPPI() const
574{
575 return wxSize(72, 72);
576}
577
578int wxGCDC::GetDepth() const
579{
580 return 32;
581}
582
583void wxGCDC::ComputeScaleAndOrigin()
584{
585 // this is a bit artificial, but we need to force wxGCDC to think
586 // the pen has changed
587 wxPen pen( GetPen() );
588
589 m_pen = wxNullPen;
590 SetPen( pen );
591}
592
593void wxGCDC::SetPalette( const wxPalette& palette )
594{}
595
596void wxGCDC::SetBackgroundMode( int mode )
597{
598 m_backgroundMode = mode;
599}
600
601void wxGCDC::SetFont( const wxFont &font )
602{
603 m_font = font;
604 if ( m_graphicContext )
605 m_graphicContext->SetFont( font );
606}
607
608void wxGCDC::SetPen( const wxPen &pen )
609{
610 if ( m_pen == pen )
611 return;
612
613 m_pen = pen;
614 if ( m_graphicContext )
615 {
616 if ( m_pen.GetStyle() == wxSOLID || m_pen.GetStyle() == wxTRANSPARENT )
617 {
618 m_graphicContext->SetPen( m_pen );
619 }
620 else
621 {
622 // we have to compensate for moved device origins etc. otherwise patterned pens are standing still
623 // eg when using a wxScrollWindow and scrolling around
624 int origX = LogicalToDeviceX( 0 );
625 int origY = LogicalToDeviceY( 0 );
626 m_graphicContext->Translate( origX , origY );
627 m_graphicContext->SetPen( m_pen );
628 m_graphicContext->Translate( -origX , -origY );
629 }
630 }
631}
632
633void wxGCDC::SetBrush( const wxBrush &brush )
634{
635 if (m_brush == brush)
636 return;
637
638 m_brush = brush;
639 if ( m_graphicContext )
640 {
641 if ( brush.GetStyle() == wxSOLID || brush.GetStyle() == wxTRANSPARENT )
642 {
643 m_graphicContext->SetBrush( m_brush );
644 }
645 else
646 {
647 // we have to compensate for moved device origins etc. otherwise patterned brushes are standing still
648 // eg when using a wxScrollWindow and scrolling around
649 // TODO on MSW / GDIPlus this still occurs with hatched brushes
650 int origX = LogicalToDeviceX(0);
651 int origY = LogicalToDeviceY(0);
652 m_graphicContext->Translate( origX , origY );
653 m_graphicContext->SetBrush( m_brush );
654 m_graphicContext->Translate( -origX , -origY );
655 }
656 }
657}
658
659void wxGCDC::SetBackground( const wxBrush &brush )
660{
661 if (m_backgroundBrush == brush)
662 return;
663
664 m_backgroundBrush = brush;
665 if (!m_backgroundBrush.Ok())
666 return;
667}
668
669void wxGCDC::SetLogicalFunction( int function )
670{
671 if (m_logicalFunction == function)
672 return;
673
674 m_logicalFunction = function;
675#if wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
676
677 CGContextRef cgContext = ((wxCairoContext*)(m_graphicContext))->GetNativeContext();
678 if ( m_logicalFunction == wxCOPY )
679 CGContextSetBlendMode( cgContext, kCGBlendModeNormal );
680 else if ( m_logicalFunction == wxINVERT )
681 CGContextSetBlendMode( cgContext, kCGBlendModeExclusion );
682 else
683 CGContextSetBlendMode( cgContext, kCGBlendModeNormal );
684#endif
685
686}
687
688extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y,
689 const wxColour & col, int style);
690
691bool wxGCDC::DoFloodFill(wxCoord x, wxCoord y,
692 const wxColour& col, int style)
693{
694 // return wxDoFloodFill(this, x, y, col, style);
695 return false;
696}
697
698bool wxGCDC::DoGetPixel( wxCoord x, wxCoord y, wxColour *col ) const
699{
700 // wxCHECK_MSG( 0 , false, wxT("wxGCDC(cg)::DoGetPixel - not implemented") );
701 return false;
702}
703
704void wxGCDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
705{
706 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawLine - invalid DC") );
707
708#if !wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
709
710 if ( m_logicalFunction != wxCOPY )
711 return;
712#endif
713
714 wxCoord xx1 = LogicalToDeviceX(x1);
715 wxCoord yy1 = LogicalToDeviceY(y1);
716 wxCoord xx2 = LogicalToDeviceX(x2);
717 wxCoord yy2 = LogicalToDeviceY(y2);
718
719 m_graphicContext->StrokeLine(xx1,yy1,xx2,yy2);
720
721 CalcBoundingBox(x1, y1);
722 CalcBoundingBox(x2, y2);
723}
724
725void wxGCDC::DoCrossHair( wxCoord x, wxCoord y )
726{
727 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoCrossHair - invalid DC") );
728
729 if ( m_logicalFunction != wxCOPY )
730 return;
731
732 int w = 0, h = 0;
733
734 GetSize( &w, &h );
735
736 wxCoord xx = LogicalToDeviceX(x);
737 wxCoord yy = LogicalToDeviceY(y);
738 wxCoord xw = LogicalToDeviceX(w);
739 wxCoord x0 = LogicalToDeviceX(0);
740 wxCoord y0 = LogicalToDeviceY(0);
741 wxCoord yh = LogicalToDeviceY(h);
742
743 m_graphicContext->StrokeLine(x0,yy,xw,yy);
744 m_graphicContext->StrokeLine(xx,y0,xx,yh);
745
746 CalcBoundingBox(x0, y0);
747 CalcBoundingBox(x0+xw, y0+yh);
748}
749
750void wxGCDC::DoDrawArc( wxCoord x1, wxCoord y1,
751 wxCoord x2, wxCoord y2,
752 wxCoord xc, wxCoord yc )
753{
754 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawArc - invalid DC") );
755
756 if ( m_logicalFunction != wxCOPY )
757 return;
758
759 wxCoord xx1 = LogicalToDeviceX(x1);
760 wxCoord yy1 = LogicalToDeviceY(y1);
761 wxCoord xx2 = LogicalToDeviceX(x2);
762 wxCoord yy2 = LogicalToDeviceY(y2);
763 wxCoord xxc = LogicalToDeviceX(xc);
764 wxCoord yyc = LogicalToDeviceY(yc);
765
766 double dx = xx1 - xxc;
767 double dy = yy1 - yyc;
768 double radius = sqrt((double)(dx * dx + dy * dy));
769 wxCoord rad = (wxCoord)radius;
770 double sa, ea;
771 if (xx1 == xx2 && yy1 == yy2)
772 {
773 sa = 0.0;
774 ea = 360.0;
775 }
776 else if (radius == 0.0)
777 {
778 sa = ea = 0.0;
779 }
780 else
781 {
782 sa = (xx1 - xxc == 0) ?
783 (yy1 - yyc < 0) ? 90.0 : -90.0 :
784 -atan2(double(yy1 - yyc), double(xx1 - xxc)) * RAD2DEG;
785 ea = (xx2 - xxc == 0) ?
786 (yy2 - yyc < 0) ? 90.0 : -90.0 :
787 -atan2(double(yy2 - yyc), double(xx2 - xxc)) * RAD2DEG;
788 }
789
790 bool fill = m_brush.GetStyle() != wxTRANSPARENT;
791
792 wxGraphicsPath* path = m_graphicContext->CreatePath();
793 if ( fill && ((x1!=x2)||(y1!=y2)) )
794 path->MoveToPoint( xxc, yyc );
795 path->AddArc( xxc, yyc , rad , DegToRad(sa) , DegToRad(ea), false );
796 if ( fill && ((x1!=x2)||(y1!=y2)) )
797 path->AddLineToPoint( xxc, yyc );
798 m_graphicContext->DrawPath(path);
799 delete path;
800}
801
802void wxGCDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h,
803 double sa, double ea )
804{
805 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawEllipticArc - invalid DC") );
806
807 if ( m_logicalFunction != wxCOPY )
808 return;
809
810 wxCoord xx = LogicalToDeviceX(x);
811 wxCoord yy = LogicalToDeviceY(y);
812 wxCoord ww = m_signX * LogicalToDeviceXRel(w);
813 wxCoord hh = m_signY * LogicalToDeviceYRel(h);
814
815 // handle -ve width and/or height
816 if (ww < 0)
817 {
818 ww = -ww;
819 xx = xx - ww;
820 }
821 if (hh < 0)
822 {
823 hh = -hh;
824 yy = yy - hh;
825 }
826
827 bool fill = m_brush.GetStyle() != wxTRANSPARENT;
828
829 wxGraphicsPath* path = m_graphicContext->CreatePath();
830 m_graphicContext->PushState();
831 m_graphicContext->Translate(xx+ww/2,yy+hh/2);
832 wxDouble factor = ((wxDouble) ww) / hh ;
833 m_graphicContext->Scale( factor , 1.0) ;
834 if ( fill && (sa!=ea) )
835 path->MoveToPoint(0,0);
d94228a2
SC
836 // since these angles (ea,sa) are measured counter-clockwise, we invert them to
837 // get clockwise angles
838 path->AddArc( 0, 0, hh/2 , DegToRad(-sa) , DegToRad(-ea), sa > ea );
50581042
SC
839 if ( fill && (sa!=ea) )
840 path->AddLineToPoint(0,0);
841 m_graphicContext->DrawPath( path );
842 m_graphicContext->PopState();
843 delete path;
844}
845
846void wxGCDC::DoDrawPoint( wxCoord x, wxCoord y )
847{
848 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawPoint - invalid DC") );
849
850 DoDrawLine( x , y , x + 1 , y + 1 );
851}
852
853void wxGCDC::DoDrawLines(int n, wxPoint points[],
854 wxCoord xoffset, wxCoord yoffset)
855{
856 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawLines - invalid DC") );
857
858#if !wxMAC_USE_CORE_GRAPHICS_BLEND_MODES
859
860 if ( m_logicalFunction != wxCOPY )
861 return;
862#endif
863
864 wxPoint2DDouble* pointsD = new wxPoint2DDouble[n] ;
865 for( int i = 0 ; i < n; ++i)
866 {
867 pointsD[i].m_x = LogicalToDeviceX(points[i].x + xoffset);
868 pointsD[i].m_y = LogicalToDeviceY(points[i].y + yoffset);
869 }
870
871 m_graphicContext->StrokeLines( n , pointsD) ;
872 delete[] pointsD;
873}
874
875#if wxUSE_SPLINES
876void wxGCDC::DoDrawSpline(wxList *points)
877{
878 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawSpline - invalid DC") );
879
880 if ( m_logicalFunction != wxCOPY )
881 return;
882
883 wxGraphicsPath* path = m_graphicContext->CreatePath();
884
885 wxList::compatibility_iterator node = points->GetFirst();
886 if (node == wxList::compatibility_iterator())
887 // empty list
888 return;
889
890 wxPoint *p = (wxPoint *)node->GetData();
891
892 wxCoord x1 = p->x;
893 wxCoord y1 = p->y;
894
895 node = node->GetNext();
896 p = (wxPoint *)node->GetData();
897
898 wxCoord x2 = p->x;
899 wxCoord y2 = p->y;
900 wxCoord cx1 = ( x1 + x2 ) / 2;
901 wxCoord cy1 = ( y1 + y2 ) / 2;
902
903 path->MoveToPoint( LogicalToDeviceX( x1 ) , LogicalToDeviceY( y1 ) );
904 path->AddLineToPoint( LogicalToDeviceX( cx1 ) , LogicalToDeviceY( cy1 ) );
905#if !wxUSE_STL
906
907 while ((node = node->GetNext()) != NULL)
908#else
909
910 while ((node = node->GetNext()))
911#endif // !wxUSE_STL
912
913 {
914 p = (wxPoint *)node->GetData();
915 x1 = x2;
916 y1 = y2;
917 x2 = p->x;
918 y2 = p->y;
919 wxCoord cx4 = (x1 + x2) / 2;
920 wxCoord cy4 = (y1 + y2) / 2;
921
922 path->AddQuadCurveToPoint(
923 LogicalToDeviceX( x1 ) , LogicalToDeviceY( y1 ) ,
924 LogicalToDeviceX( cx4 ) , LogicalToDeviceY( cy4 ) );
925
926 cx1 = cx4;
927 cy1 = cy4;
928 }
929
930 path->AddLineToPoint( LogicalToDeviceX( x2 ) , LogicalToDeviceY( y2 ) );
931
932 m_graphicContext->StrokePath( path );
933 delete path;
934}
935#endif
936
937void wxGCDC::DoDrawPolygon( int n, wxPoint points[],
938 wxCoord xoffset, wxCoord yoffset,
939 int fillStyle )
940{
941 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawPolygon - invalid DC") );
942
943 if ( n <= 0 || (m_brush.GetStyle() == wxTRANSPARENT && m_pen.GetStyle() == wxTRANSPARENT ) )
944 return;
945 if ( m_logicalFunction != wxCOPY )
946 return;
947
948 bool closeIt = false ;
949 if (points[n-1] != points[0])
950 closeIt = true ;
951
952 wxPoint2DDouble* pointsD = new wxPoint2DDouble[n+(closeIt?1:0)] ;
953 for( int i = 0 ; i < n; ++i)
954 {
955 pointsD[i].m_x = LogicalToDeviceX(points[i].x + xoffset);
956 pointsD[i].m_y = LogicalToDeviceY(points[i].y + yoffset);
957 }
958 if ( closeIt )
959 pointsD[n] = pointsD[0];
960
961 m_graphicContext->DrawLines( n+(closeIt?1:0) , pointsD, fillStyle) ;
962 delete[] pointsD;
963}
964
965void wxGCDC::DoDrawPolyPolygon(int n,
966 int count[],
967 wxPoint points[],
968 wxCoord xoffset,
969 wxCoord yoffset,
970 int fillStyle)
971{
972 wxASSERT(n > 1);
973 wxGraphicsPath* path = m_graphicContext->CreatePath();
974
975 int i = 0 ;
976 for ( int j = 0 ; j < n ; ++j)
977 {
978 wxPoint start = points[i];
979 path->MoveToPoint(LogicalToDeviceX(start.x+ xoffset), LogicalToDeviceY(start.y+ yoffset)) ;
980 ++i;
981 int l = count[j];
982 for ( int k = 1 ; k < l ; ++k)
983 {
984 path->AddLineToPoint( LogicalToDeviceX(points[i].x+ xoffset), LogicalToDeviceY(points[i].y+ yoffset));
985 ++i ;
986 }
987 // close the polygon
988 if ( start != points[i-1])
989 path->AddLineToPoint( LogicalToDeviceX(start.x+ xoffset), LogicalToDeviceY(start.y+ yoffset));
990 }
991 m_graphicContext->DrawPath( path , fillStyle);
992 delete path;
993}
994
995void wxGCDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
996{
997 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawRectangle - invalid DC") );
998
999 if ( m_logicalFunction != wxCOPY )
1000 return;
1001
1002 wxCoord xx = LogicalToDeviceX(x);
1003 wxCoord yy = LogicalToDeviceY(y);
1004 wxCoord ww = m_signX * LogicalToDeviceXRel(width);
1005 wxCoord hh = m_signY * LogicalToDeviceYRel(height);
1006
1007 // CMB: draw nothing if transformed w or h is 0
1008 if (ww == 0 || hh == 0)
1009 return;
1010
1011 // CMB: handle -ve width and/or height
1012 if (ww < 0)
1013 {
1014 ww = -ww;
1015 xx = xx - ww;
1016 }
1017 if (hh < 0)
1018 {
1019 hh = -hh;
1020 yy = yy - hh;
1021 }
1022 m_graphicContext->DrawRectangle( xx,yy,ww,hh);
1023}
1024
1025void wxGCDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y,
1026 wxCoord width, wxCoord height,
1027 double radius)
1028{
1029 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawRoundedRectangle - invalid DC") );
1030
1031 if ( m_logicalFunction != wxCOPY )
1032 return;
1033
1034 if (radius < 0.0)
1035 radius = - radius * ((width < height) ? width : height);
1036 wxCoord xx = LogicalToDeviceX(x);
1037 wxCoord yy = LogicalToDeviceY(y);
1038 wxCoord ww = m_signX * LogicalToDeviceXRel(width);
1039 wxCoord hh = m_signY * LogicalToDeviceYRel(height);
1040
1041 // CMB: draw nothing if transformed w or h is 0
1042 if (ww == 0 || hh == 0)
1043 return;
1044
1045 // CMB: handle -ve width and/or height
1046 if (ww < 0)
1047 {
1048 ww = -ww;
1049 xx = xx - ww;
1050 }
1051 if (hh < 0)
1052 {
1053 hh = -hh;
1054 yy = yy - hh;
1055 }
1056
1057 m_graphicContext->DrawRoundedRectangle( xx,yy,ww,hh,radius);
1058}
1059
1060void wxGCDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
1061{
1062 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawEllipse - invalid DC") );
1063
1064 if ( m_logicalFunction != wxCOPY )
1065 return;
1066
1067 wxCoord xx = LogicalToDeviceX(x);
1068 wxCoord yy = LogicalToDeviceY(y);
1069 wxDouble ww = m_signX * LogicalToDeviceXRel(width);
1070 wxCoord hh = m_signY * LogicalToDeviceYRel(height);
1071
1072 // CMB: draw nothing if transformed w or h is 0
1073 if (ww == 0 || hh == 0)
1074 return;
1075
1076 // CMB: handle -ve width and/or height
1077 if (ww < 0)
1078 {
1079 ww = -ww;
1080 xx = xx - ww;
1081 }
1082 if (hh < 0)
1083 {
1084 hh = -hh;
1085 yy = yy - hh;
1086 }
1087
1088 m_graphicContext->DrawEllipse(xx,yy,ww,hh);
1089}
1090
1091bool wxGCDC::CanDrawBitmap() const
1092{
1093 return true;
1094}
1095
1096bool wxGCDC::DoBlit(
1097 wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
1098 wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool useMask,
1099 wxCoord xsrcMask, wxCoord ysrcMask )
1100{
1101 wxCHECK_MSG( Ok(), false, wxT("wxGCDC(cg)::DoBlit - invalid DC") );
1102 wxCHECK_MSG( source->Ok(), false, wxT("wxGCDC(cg)::DoBlit - invalid source DC") );
1103
1104 if ( logical_func == wxNO_OP )
1105 return true;
1106
1107 if (xsrcMask == -1 && ysrcMask == -1)
1108 {
1109 xsrcMask = xsrc;
1110 ysrcMask = ysrc;
1111 }
1112
1113 wxCoord yysrc = source-> LogicalToDeviceY(ysrc);
1114 wxCoord xxsrc = source-> LogicalToDeviceX(xsrc);
1115 wxCoord wwsrc = source-> LogicalToDeviceXRel(width);
1116 wxCoord hhsrc = source-> LogicalToDeviceYRel(height);
1117
1118 wxCoord yydest = LogicalToDeviceY(ydest);
1119 wxCoord xxdest = LogicalToDeviceX(xdest);
1120 wxCoord wwdest = LogicalToDeviceXRel(width);
1121 wxCoord hhdest = LogicalToDeviceYRel(height);
1122
1123 wxMemoryDC* memdc = dynamic_cast<wxMemoryDC*>(source);
1124 if ( memdc && logical_func == wxCOPY )
1125 {
1126#if 0
1127 wxBitmap blit = memdc->GetSelectedObject();
1128
1129 wxASSERT_MSG( blit.Ok() , wxT("Invalid bitmap for blitting") );
1130
1131 wxCoord bmpwidth = blit.GetWidth();
1132 wxCoord bmpheight = blit.GetHeight();
1133
1134 if ( xxsrc != 0 || yysrc != 0 || bmpwidth != wwsrc || bmpheight != hhsrc )
1135 {
1136 wwsrc = wxMin( wwsrc , bmpwidth - xxsrc );
1137 hhsrc = wxMin( hhsrc , bmpheight - yysrc );
1138 if ( wwsrc > 0 && hhsrc > 0 )
1139 {
1140 if ( xxsrc >= 0 && yysrc >= 0 )
1141 {
1142 wxRect subrect( xxsrc, yysrc, wwsrc , hhsrc );
1143 // TODO we perhaps could add a DrawSubBitmap call to dc for performance reasons
1144 blit = blit.GetSubBitmap( subrect );
1145 }
1146 else
1147 {
1148 // in this case we'd probably have to adjust the different coordinates, but
1149 // we have to find out proper contract first
1150 blit = wxNullBitmap;
1151 }
1152 }
1153 else
1154 {
1155 blit = wxNullBitmap;
1156 }
1157 }
1158
1159 if ( blit.Ok() )
1160 {
1161 m_graphicContext->DrawBitmap( blit, xxdest , yydest , wwdest , hhdest );
1162 }
1163#endif
1164
1165 }
1166 else
1167 {
1168 wxFAIL_MSG( wxT("Blitting is only supported from bitmap contexts") );
1169 return false;
1170 }
1171
1172 return true;
1173}
1174
1175void wxGCDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y,
1176 double angle)
1177{
1178 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawRotatedText - invalid DC") );
1179
1180 if ( str.length() == 0 )
1181 return;
1182 if ( m_logicalFunction != wxCOPY )
1183 return;
1184
1185 int drawX = LogicalToDeviceX(x);
1186 int drawY = LogicalToDeviceY(y);
1187
1188 m_graphicContext->DrawText( str, drawX ,drawY , DegToRad(angle ));
1189}
1190
1191void wxGCDC::DoDrawText(const wxString& str, wxCoord x, wxCoord y)
1192{
1193 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawRotatedText - invalid DC") );
1194
1195 if ( str.length() == 0 )
1196 return;
1197 if ( m_logicalFunction != wxCOPY )
1198 return;
1199
1200 int drawX = LogicalToDeviceX(x);
1201 int drawY = LogicalToDeviceY(y);
1202
1203 m_graphicContext->DrawText( str, drawX ,drawY);
1204}
1205
1206bool wxGCDC::CanGetTextExtent() const
1207{
1208 wxCHECK_MSG( Ok(), false, wxT("wxGCDC(cg)::CanGetTextExtent - invalid DC") );
1209
1210 return true;
1211}
1212
1213void wxGCDC::DoGetTextExtent( const wxString &str, wxCoord *width, wxCoord *height,
1214 wxCoord *descent, wxCoord *externalLeading ,
1215 wxFont *theFont ) const
1216{
1217 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoGetTextExtent - invalid DC") );
1218
1219 wxFont formerFont = m_font;
1220 if ( theFont )
1221 {
1222 m_graphicContext->SetFont( *theFont );
1223 }
1224
1225 wxDouble h , d , e , w;
1226
1227 m_graphicContext->GetTextExtent( str, &w, &h, &d, &e );
1228
1229 if ( height )
1230 *height = DeviceToLogicalYRel( h );
1231 if ( descent )
1232 *descent =DeviceToLogicalYRel( d);
1233 if ( externalLeading )
1234 *externalLeading = DeviceToLogicalYRel( e);
1235 if ( width )
1236 *width = DeviceToLogicalXRel( w );
1237
1238 if ( theFont )
1239 {
1240 m_graphicContext->SetFont( m_font );
1241 }
1242}
1243
1244bool wxGCDC::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
1245{
1246 wxCHECK_MSG( Ok(), false, wxT("wxGCDC(cg)::DoGetPartialTextExtents - invalid DC") );
1247 widths.Clear();
1248 widths.Add(0,text.Length());
1249 if ( text.IsEmpty() )
1250 return true ;
1251
1252 wxArrayDouble widthsD ;
1253
1254 m_graphicContext->GetPartialTextExtents( text, widthsD );
1255 for ( size_t i = 0; i < widths.GetCount(); ++i )
1256 widths[i] = DeviceToLogicalXRel( widthsD[i] + 0.5 ) ;
1257
1258 return true;
1259}
1260
1261wxCoord wxGCDC::GetCharWidth(void) const
1262{
1263 wxCoord width;
1264 DoGetTextExtent( wxT("g") , &width , NULL , NULL , NULL , NULL );
1265
1266 return width;
1267}
1268
1269wxCoord wxGCDC::GetCharHeight(void) const
1270{
1271 wxCoord height;
1272 DoGetTextExtent( wxT("g") , NULL , &height , NULL , NULL , NULL );
1273
1274 return height;
1275}
1276
1277void wxGCDC::Clear(void)
1278{
1279 wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::Clear - invalid DC") );
1280 // TODO
1281}
1282
1283void wxGCDC::DoGetSize(int *width, int *height) const
1284{
1285 *width = 1000;
1286 *height = 1000;
1287}
1288
1289void wxGCDC::DoGradientFillLinear(const wxRect& rect,
1290 const wxColour& initialColour,
1291 const wxColour& destColour,
1292 wxDirection nDirection )
1293{
1294 wxPoint start ;
1295 wxPoint end ;
1296 switch( nDirection)
1297 {
1298 case wxWEST :
1299 start = rect.GetRightBottom();
1300 start.x++;
1301 end = rect.GetLeftBottom();
1302 break ;
1303 case wxEAST :
1304 start = rect.GetLeftBottom();
1305 end = rect.GetRightBottom();
1306 end.x++;
1307 break ;
1308 case wxNORTH :
1309 start = rect.GetLeftBottom();
1310 start.y++;
1311 end = rect.GetLeftTop();
1312 break ;
1313 case wxSOUTH :
1314 start = rect.GetLeftTop();
1315 end = rect.GetLeftBottom();
1316 end.y++;
1317 break ;
1318 }
1319
1320 m_graphicContext->SetLinearGradientBrush(
1321 LogicalToDeviceX(start.x),LogicalToDeviceY(start.y),
1322 LogicalToDeviceX(end.x),LogicalToDeviceY(end.y), initialColour, destColour);
1323
1324 wxCoord xx = LogicalToDeviceX(rect.x);
1325 wxCoord yy = LogicalToDeviceY(rect.y);
1326 wxDouble ww = m_signX * LogicalToDeviceXRel(rect.width);
1327 wxCoord hh = m_signY * LogicalToDeviceYRel(rect.height);
1328
1329 if (ww == 0 || hh == 0)
1330 return;
1331
1332 if (ww < 0)
1333 {
1334 ww = -ww;
1335 xx = xx - ww;
1336 }
1337 if (hh < 0)
1338 {
1339 hh = -hh;
1340 yy = yy - hh;
1341 }
1342
1343 m_graphicContext->SetPen(*wxTRANSPARENT_PEN);
1344 m_graphicContext->DrawRectangle(xx,yy,ww,hh);
1345 m_graphicContext->SetPen(m_pen);
1346}
1347
1348void wxGCDC::DoGradientFillConcentric(const wxRect& rect,
1349 const wxColour& initialColour,
1350 const wxColour& destColour,
1351 const wxPoint& circleCenter)
1352{
1353 //Radius
1354 wxInt32 cx = rect.GetWidth() / 2;
1355 wxInt32 cy = rect.GetHeight() / 2;
1356 wxInt32 nRadius;
1357 if (cx < cy)
1358 nRadius = cx;
1359 else
1360 nRadius = cy;
1361
1362 wxCoord xx = LogicalToDeviceX(rect.x);
1363 wxCoord yy = LogicalToDeviceY(rect.y);
1364 wxDouble ww = m_signX * LogicalToDeviceXRel(rect.width);
1365 wxCoord hh = m_signY * LogicalToDeviceYRel(rect.height);
1366
1367 if (ww == 0 || hh == 0)
1368 return;
1369
1370 if (ww < 0)
1371 {
1372 ww = -ww;
1373 xx = xx - ww;
1374 }
1375 if (hh < 0)
1376 {
1377 hh = -hh;
1378 yy = yy - hh;
1379 }
1380
1381 m_graphicContext->SetPen(*wxTRANSPARENT_PEN);
1382 m_graphicContext->SetBrush( wxBrush( destColour) ) ;
1383 m_graphicContext->DrawRectangle( xx,yy,ww,hh);
1384
1385 m_graphicContext->SetRadialGradientBrush(
1386 xx+LogicalToDeviceX(circleCenter.x),yy+LogicalToDeviceY(circleCenter.y),
1387 xx+LogicalToDeviceX(circleCenter.x),yy+LogicalToDeviceY(circleCenter.y),
1388 LogicalToDeviceXRel(nRadius),
1389 initialColour,destColour);
1390
1391 m_graphicContext->DrawRectangle( xx,yy,ww,hh);
1392 m_graphicContext->SetPen(m_pen);
1393}
1394
1395void wxGCDC::DoDrawCheckMark(wxCoord x, wxCoord y,
1396 wxCoord width, wxCoord height)
1397{
1398 wxDCBase::DoDrawCheckMark(x,y,width,height);
1399}
1400
1401#endif
1402