1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/dcgraph.cpp 
   3 // Purpose:     graphics context methods common to all platforms 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  15 #if defined(__BORLANDC__) 
  19 #if wxUSE_GRAPHICS_CONTEXT 
  21 #include "wx/graphics.h" 
  22 #include "wx/dcgraph.h" 
  26     #include "wx/bitmap.h" 
  27     #include "wx/dcmemory.h" 
  28     #include "wx/region.h" 
  31 #include "wx/dcclient.h" 
  33 #ifdef __WXOSX_OR_COCOA__ 
  34 #ifdef __WXOSX_IPHONE__ 
  35     #include <CoreGraphics/CoreGraphics.h> 
  37     #include <ApplicationServices/ApplicationServices.h> 
  41 //----------------------------------------------------------------------------- 
  43 //----------------------------------------------------------------------------- 
  45 static const double RAD2DEG 
= 180.0 / M_PI
; 
  47 //----------------------------------------------------------------------------- 
  49 //----------------------------------------------------------------------------- 
  51 static inline double DegToRad(double deg
) 
  53     return (deg 
* M_PI
) / 180.0; 
  56 static bool TranslateRasterOp(wxRasterOperationMode function
, wxCompositionMode 
*op
) 
  61             // since we are supporting alpha, _OVER is closer to the intention than _SOURCE 
  62             // since the latter would overwrite even when alpha is not set to opaque 
  63             *op 
= wxCOMPOSITION_OVER
;  
  65         case wxOR
:         // src OR dst 
  66             *op 
= wxCOMPOSITION_ADD
; 
  69             *op 
= wxCOMPOSITION_DEST
; // ignore the source 
  72             *op 
= wxCOMPOSITION_CLEAR
;// clear dst 
  74         case wxXOR
:        // src XOR dst 
  75             *op 
= wxCOMPOSITION_XOR
; 
  78         case wxAND
:        // src AND dst 
  79         case wxAND_INVERT
: // (NOT src) AND dst 
  80         case wxAND_REVERSE
:// src AND (NOT dst) 
  81         case wxEQUIV
:      // (NOT src) XOR dst 
  82         case wxINVERT
:     // NOT dst 
  83         case wxNAND
:       // (NOT src) OR (NOT dst) 
  84         case wxNOR
:        // (NOT src) AND (NOT dst) 
  85         case wxOR_INVERT
:  // (NOT src) OR dst 
  86         case wxOR_REVERSE
: // src OR (NOT dst) 
  88         case wxSRC_INVERT
: // NOT src 
  95 //----------------------------------------------------------------------------- 
  97 //----------------------------------------------------------------------------- 
  99 IMPLEMENT_DYNAMIC_CLASS(wxGCDC
, wxDC
) 
 101 wxGCDC::wxGCDC(const wxWindowDC
& dc
) : 
 102   wxDC( new wxGCDCImpl( this, dc 
) ) 
 106 wxGCDC::wxGCDC( const wxMemoryDC
& dc
) : 
 107   wxDC( new wxGCDCImpl( this, dc 
) ) 
 111 #if wxUSE_PRINTING_ARCHITECTURE 
 112 wxGCDC::wxGCDC( const wxPrinterDC
& dc
) : 
 113   wxDC( new wxGCDCImpl( this, dc 
) ) 
 119   wxDC( new wxGCDCImpl( this ) ) 
 127 wxGraphicsContext
* wxGCDC::GetGraphicsContext() 
 129     if (!m_pimpl
) return NULL
; 
 130     wxGCDCImpl 
*gc_impl 
= (wxGCDCImpl
*) m_pimpl
; 
 131     return gc_impl
->GetGraphicsContext(); 
 134 void wxGCDC::SetGraphicsContext( wxGraphicsContext
* ctx 
) 
 136     if (!m_pimpl
) return; 
 137     wxGCDCImpl 
*gc_impl 
= (wxGCDCImpl
*) m_pimpl
; 
 138     gc_impl
->SetGraphicsContext( ctx 
); 
 141 IMPLEMENT_ABSTRACT_CLASS(wxGCDCImpl
, wxDCImpl
) 
 143 wxGCDCImpl::wxGCDCImpl( wxDC 
*owner 
) : 
 149 void wxGCDCImpl::SetGraphicsContext( wxGraphicsContext
* ctx 
) 
 151     delete m_graphicContext
; 
 152     m_graphicContext 
= ctx
; 
 153     if ( m_graphicContext 
) 
 155         m_matrixOriginal 
= m_graphicContext
->GetTransform(); 
 157         // apply the stored transformations to the passed in context 
 158         ComputeScaleAndOrigin(); 
 159         m_graphicContext
->SetFont( m_font 
, m_textForegroundColour 
); 
 160         m_graphicContext
->SetPen( m_pen 
); 
 161         m_graphicContext
->SetBrush( m_brush
); 
 165 wxGCDCImpl::wxGCDCImpl( wxDC 
*owner
, const wxWindowDC
& dc 
) : 
 169     SetGraphicsContext( wxGraphicsContext::Create(dc
) ); 
 170     m_window 
= dc
.GetWindow(); 
 173 wxGCDCImpl::wxGCDCImpl( wxDC 
*owner
, const wxMemoryDC
& dc 
) : 
 177     wxGraphicsContext
* context
; 
 179     wxGraphicsRenderer
* renderer 
= wxGraphicsRenderer::GetCairoRenderer(); 
 180     context 
= renderer
->CreateContext(dc
); 
 182     context 
= wxGraphicsContext::Create(dc
); 
 185     SetGraphicsContext( context 
); 
 188 #if wxUSE_PRINTING_ARCHITECTURE 
 189 wxGCDCImpl::wxGCDCImpl( wxDC 
*owner
, const wxPrinterDC
& dc 
) : 
 193     SetGraphicsContext( wxGraphicsContext::Create(dc
) ); 
 197 void wxGCDCImpl::Init() 
 201     m_mm_to_pix_x 
= mm2pt
; 
 202     m_mm_to_pix_y 
= mm2pt
; 
 204     m_pen 
= *wxBLACK_PEN
; 
 205     m_font 
= *wxNORMAL_FONT
; 
 206     m_brush 
= *wxWHITE_BRUSH
; 
 208     m_graphicContext 
= wxGraphicsContext::Create(); 
 209     m_logicalFunctionSupported 
= true; 
 213 wxGCDCImpl::~wxGCDCImpl() 
 215     delete m_graphicContext
; 
 218 void wxGCDCImpl::DoDrawBitmap( const wxBitmap 
&bmp
, wxCoord x
, wxCoord y
, 
 221     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawBitmap - invalid DC") ); 
 222     wxCHECK_RET( bmp
.IsOk(), wxT("wxGCDC(cg)::DoDrawBitmap - invalid bitmap") ); 
 224     int w 
= bmp
.GetWidth(); 
 225     int h 
= bmp
.GetHeight(); 
 226     if ( bmp
.GetDepth() == 1 ) 
 228         m_graphicContext
->SetPen(*wxTRANSPARENT_PEN
); 
 229         m_graphicContext
->SetBrush( wxBrush( m_textBackgroundColour 
, wxSOLID 
) ); 
 230         m_graphicContext
->DrawRectangle( x
, y
, w
, h 
); 
 231         m_graphicContext
->SetBrush( wxBrush( m_textForegroundColour 
, wxSOLID 
) ); 
 232         m_graphicContext
->DrawBitmap( bmp
, x
, y
, w
, h 
); 
 233         m_graphicContext
->SetBrush( m_graphicContext
->CreateBrush(m_brush
)); 
 234         m_graphicContext
->SetPen( m_graphicContext
->CreatePen(m_pen
)); 
 236     else // not a monochrome bitmap, handle it normally 
 238         // make a copy in case we need to remove its mask, if we don't modify 
 239         // it the copy is cheap as bitmaps are reference-counted 
 240         wxBitmap 
bmpCopy(bmp
); 
 241         if ( !useMask 
&& bmp
.GetMask() ) 
 242             bmpCopy
.SetMask(NULL
); 
 244         m_graphicContext
->DrawBitmap( bmpCopy
, x
, y
, w
, h 
); 
 248 void wxGCDCImpl::DoDrawIcon( const wxIcon 
&icon
, wxCoord x
, wxCoord y 
) 
 250     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawIcon - invalid DC") ); 
 251     wxCHECK_RET( icon
.IsOk(), wxT("wxGCDC(cg)::DoDrawIcon - invalid icon") ); 
 253     wxCoord w 
= icon
.GetWidth(); 
 254     wxCoord h 
= icon
.GetHeight(); 
 256     m_graphicContext
->DrawIcon( icon 
, x
, y
, w
, h 
); 
 259 bool wxGCDCImpl::StartDoc( const wxString
& WXUNUSED(message
) ) 
 264 void wxGCDCImpl::EndDoc() 
 268 void wxGCDCImpl::StartPage() 
 272 void wxGCDCImpl::EndPage() 
 276 void wxGCDCImpl::Flush() 
 278     m_graphicContext
->Flush(); 
 281 void wxGCDCImpl::DoSetClippingRegion( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h 
) 
 283     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoSetClippingRegion - invalid DC") ); 
 285     m_graphicContext
->Clip( x
, y
, w
, h 
); 
 288         m_clipX1 
= wxMax( m_clipX1
, x 
); 
 289         m_clipY1 
= wxMax( m_clipY1
, y 
); 
 290         m_clipX2 
= wxMin( m_clipX2
, (x 
+ w
) ); 
 291         m_clipY2 
= wxMin( m_clipY2
, (y 
+ h
) ); 
 304 void wxGCDCImpl::DoSetDeviceClippingRegion( const wxRegion 
®ion 
) 
 306     // region is in device coordinates 
 307     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoSetDeviceClippingRegion - invalid DC") ); 
 311         //DestroyClippingRegion(); 
 315     wxRegion 
logRegion( region 
); 
 318     logRegion
.Offset( DeviceToLogicalX(0), DeviceToLogicalY(0) ); 
 319     logRegion
.GetBox( x
, y
, w
, h 
); 
 321     m_graphicContext
->Clip( logRegion 
); 
 324         m_clipX1 
= wxMax( m_clipX1
, x 
); 
 325         m_clipY1 
= wxMax( m_clipY1
, y 
); 
 326         m_clipX2 
= wxMin( m_clipX2
, (x 
+ w
) ); 
 327         m_clipY2 
= wxMin( m_clipY2
, (y 
+ h
) ); 
 340 void wxGCDCImpl::DestroyClippingRegion() 
 342     m_graphicContext
->ResetClip(); 
 343     // currently the clip eg of a window extends to the area between the scrollbars 
 344     // so we must explicitly make sure it only covers the area we want it to draw 
 346     GetOwner()->GetSize( &width 
, &height 
) ; 
 347     m_graphicContext
->Clip( DeviceToLogicalX(0) , DeviceToLogicalY(0) , DeviceToLogicalXRel(width
), DeviceToLogicalYRel(height
) ); 
 349     m_graphicContext
->SetPen( m_pen 
); 
 350     m_graphicContext
->SetBrush( m_brush 
); 
 355 void wxGCDCImpl::DoGetSizeMM( int* width
, int* height 
) const 
 359     GetOwner()->GetSize( &w
, &h 
); 
 361         *width 
= long( double(w
) / (m_scaleX 
* m_mm_to_pix_x
) ); 
 363         *height 
= long( double(h
) / (m_scaleY 
* m_mm_to_pix_y
) ); 
 366 void wxGCDCImpl::SetTextForeground( const wxColour 
&col 
) 
 368     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::SetTextForeground - invalid DC") ); 
 370     if ( col 
!= m_textForegroundColour 
) 
 372         m_textForegroundColour 
= col
; 
 373         m_graphicContext
->SetFont( m_font
, m_textForegroundColour 
); 
 377 void wxGCDCImpl::SetTextBackground( const wxColour 
&col 
) 
 379     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::SetTextBackground - invalid DC") ); 
 381     m_textBackgroundColour 
= col
; 
 384 void wxGCDCImpl::SetMapMode( wxMappingMode mode 
) 
 389         SetLogicalScale( twips2mm 
* m_mm_to_pix_x
, twips2mm 
* m_mm_to_pix_y 
); 
 393         SetLogicalScale( pt2mm 
* m_mm_to_pix_x
, pt2mm 
* m_mm_to_pix_y 
); 
 397         SetLogicalScale( m_mm_to_pix_x
, m_mm_to_pix_y 
); 
 401         SetLogicalScale( m_mm_to_pix_x 
/ 10.0, m_mm_to_pix_y 
/ 10.0 ); 
 406         SetLogicalScale( 1.0, 1.0 ); 
 410     ComputeScaleAndOrigin(); 
 413 wxSize 
wxGCDCImpl::GetPPI() const 
 415     return wxSize(72, 72); 
 418 int wxGCDCImpl::GetDepth() const 
 423 void wxGCDCImpl::ComputeScaleAndOrigin() 
 425     wxDCImpl::ComputeScaleAndOrigin(); 
 427     if ( m_graphicContext 
) 
 429         m_matrixCurrent 
= m_graphicContext
->CreateMatrix(); 
 431         // the logical origin sets the origin to have new coordinates 
 432         m_matrixCurrent
.Translate( m_deviceOriginX 
- m_logicalOriginX 
* m_signX 
* m_scaleX
, 
 433                                    m_deviceOriginY
-m_logicalOriginY 
* m_signY 
* m_scaleY
); 
 435         m_matrixCurrent
.Scale( m_scaleX 
* m_signX
, m_scaleY 
* m_signY 
); 
 437         m_graphicContext
->SetTransform( m_matrixOriginal 
); 
 438         m_graphicContext
->ConcatTransform( m_matrixCurrent 
); 
 442 void wxGCDCImpl::SetPalette( const wxPalette
& WXUNUSED(palette
) ) 
 447 void wxGCDCImpl::SetBackgroundMode( int mode 
) 
 449     m_backgroundMode 
= mode
; 
 452 void wxGCDCImpl::SetFont( const wxFont 
&font 
) 
 455     if ( m_graphicContext 
) 
 459             f
.SetPointSize( /*LogicalToDeviceYRel*/(font
.GetPointSize())); 
 460         m_graphicContext
->SetFont( f
, m_textForegroundColour 
); 
 464 void wxGCDCImpl::SetPen( const wxPen 
&pen 
) 
 470     if ( m_graphicContext 
) 
 472         m_graphicContext
->SetPen( m_pen 
); 
 476 void wxGCDCImpl::SetBrush( const wxBrush 
&brush 
) 
 478     if (m_brush 
== brush
) 
 482     if ( m_graphicContext 
) 
 484         m_graphicContext
->SetBrush( m_brush 
); 
 488 void wxGCDCImpl::SetBackground( const wxBrush 
&brush 
) 
 490     if (m_backgroundBrush 
== brush
) 
 493     m_backgroundBrush 
= brush
; 
 494     if (!m_backgroundBrush
.IsOk()) 
 498 void wxGCDCImpl::SetLogicalFunction( wxRasterOperationMode function 
) 
 500     if (m_logicalFunction 
== function
) 
 503     m_logicalFunction 
= function
; 
 505     wxCompositionMode mode
; 
 506     m_logicalFunctionSupported 
= TranslateRasterOp( function
, &mode
); 
 507     if (m_logicalFunctionSupported
) 
 508         m_logicalFunctionSupported 
= m_graphicContext
->SetCompositionMode(mode
); 
 510     if ( function 
== wxXOR 
) 
 511         m_graphicContext
->SetAntialiasMode(wxANTIALIAS_NONE
); 
 513         m_graphicContext
->SetAntialiasMode(wxANTIALIAS_DEFAULT
); 
 516 bool wxGCDCImpl::DoFloodFill(wxCoord 
WXUNUSED(x
), wxCoord 
WXUNUSED(y
), 
 517                              const wxColour
& WXUNUSED(col
), 
 518                              wxFloodFillStyle 
WXUNUSED(style
)) 
 523 bool wxGCDCImpl::DoGetPixel( wxCoord 
WXUNUSED(x
), wxCoord 
WXUNUSED(y
), wxColour 
*WXUNUSED(col
) ) const 
 525     //  wxCHECK_MSG( 0 , false, wxT("wxGCDC(cg)::DoGetPixel - not implemented") ); 
 529 void wxGCDCImpl::DoDrawLine( wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2 
) 
 531     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawLine - invalid DC") ); 
 533     if ( !m_logicalFunctionSupported 
) 
 536     m_graphicContext
->StrokeLine(x1
,y1
,x2
,y2
); 
 538     CalcBoundingBox(x1
, y1
); 
 539     CalcBoundingBox(x2
, y2
); 
 542 void wxGCDCImpl::DoCrossHair( wxCoord x
, wxCoord y 
) 
 544     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoCrossHair - invalid DC") ); 
 546     if ( !m_logicalFunctionSupported 
) 
 551     GetOwner()->GetSize( &w
, &h 
); 
 553     m_graphicContext
->StrokeLine(0,y
,w
,y
); 
 554     m_graphicContext
->StrokeLine(x
,0,x
,h
); 
 556     CalcBoundingBox(0, 0); 
 557     CalcBoundingBox(0+w
, 0+h
); 
 560 void wxGCDCImpl::DoDrawArc( wxCoord x1
, wxCoord y1
, 
 561                         wxCoord x2
, wxCoord y2
, 
 562                         wxCoord xc
, wxCoord yc 
) 
 564     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawArc - invalid DC") ); 
 566     if ( !m_logicalFunctionSupported 
) 
 571     double radius 
= sqrt((double)(dx 
* dx 
+ dy 
* dy
)); 
 572     wxCoord rad 
= (wxCoord
)radius
; 
 574     if (x1 
== x2 
&& y1 
== y2
) 
 579     else if (radius 
== 0.0) 
 585         sa 
= (x1 
- xc 
== 0) ? 
 586      (y1 
- yc 
< 0) ? 90.0 : -90.0 : 
 587              -atan2(double(y1 
- yc
), double(x1 
- xc
)) * RAD2DEG
; 
 588         ea 
= (x2 
- xc 
== 0) ? 
 589      (y2 
- yc 
< 0) ? 90.0 : -90.0 : 
 590              -atan2(double(y2 
- yc
), double(x2 
- xc
)) * RAD2DEG
; 
 593     bool fill 
= m_brush
.GetStyle() != wxTRANSPARENT
; 
 595     wxGraphicsPath path 
= m_graphicContext
->CreatePath(); 
 596     if ( fill 
&& ((x1
!=x2
)||(y1
!=y2
)) ) 
 597         path
.MoveToPoint( xc
, yc 
); 
 598     // since these angles (ea,sa) are measured counter-clockwise, we invert them to 
 599     // get clockwise angles 
 600     path
.AddArc( xc
, yc 
, rad 
, DegToRad(-sa
) , DegToRad(-ea
), false ); 
 601     if ( fill 
&& ((x1
!=x2
)||(y1
!=y2
)) ) 
 602         path
.AddLineToPoint( xc
, yc 
); 
 603     m_graphicContext
->DrawPath(path
); 
 606 void wxGCDCImpl::DoDrawEllipticArc( wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
, 
 607                                 double sa
, double ea 
) 
 609     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawEllipticArc - invalid DC") ); 
 611     if ( !m_logicalFunctionSupported 
) 
 614     m_graphicContext
->PushState(); 
 615     m_graphicContext
->Translate(x
+w
/2.0,y
+h
/2.0); 
 616     wxDouble factor 
= ((wxDouble
) w
) / h
; 
 617     m_graphicContext
->Scale( factor 
, 1.0); 
 619     // since these angles (ea,sa) are measured counter-clockwise, we invert them to 
 620     // get clockwise angles 
 621     if ( m_brush
.GetStyle() != wxTRANSPARENT 
) 
 623         wxGraphicsPath path 
= m_graphicContext
->CreatePath(); 
 624         path
.MoveToPoint( 0, 0 ); 
 625         path
.AddArc( 0, 0, h
/2.0 , DegToRad(-sa
) , DegToRad(-ea
), sa 
> ea 
); 
 626         path
.AddLineToPoint( 0, 0 ); 
 627         m_graphicContext
->FillPath( path 
); 
 629         path 
= m_graphicContext
->CreatePath(); 
 630         path
.AddArc( 0, 0, h
/2.0 , DegToRad(-sa
) , DegToRad(-ea
), sa 
> ea 
); 
 631         m_graphicContext
->StrokePath( path 
); 
 635         wxGraphicsPath path 
= m_graphicContext
->CreatePath(); 
 636         path
.AddArc( 0, 0, h
/2.0 , DegToRad(-sa
) , DegToRad(-ea
), sa 
> ea 
); 
 637         m_graphicContext
->DrawPath( path 
); 
 640     m_graphicContext
->PopState(); 
 643 void wxGCDCImpl::DoDrawPoint( wxCoord x
, wxCoord y 
) 
 645     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawPoint - invalid DC") ); 
 647     DoDrawLine( x 
, y 
, x 
+ 1 , y 
+ 1 ); 
 650 void wxGCDCImpl::DoDrawLines(int n
, wxPoint points
[], 
 651                          wxCoord xoffset
, wxCoord yoffset
) 
 653     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawLines - invalid DC") ); 
 655     if ( !m_logicalFunctionSupported 
) 
 658     wxPoint2DDouble
* pointsD 
= new wxPoint2DDouble
[n
]; 
 659     for( int i 
= 0; i 
< n
; ++i
) 
 661         pointsD
[i
].m_x 
= points
[i
].x 
+ xoffset
; 
 662         pointsD
[i
].m_y 
= points
[i
].y 
+ yoffset
; 
 665     m_graphicContext
->StrokeLines( n 
, pointsD
); 
 670 void wxGCDCImpl::DoDrawSpline(const wxPointList 
*points
) 
 672     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawSpline - invalid DC") ); 
 674     if ( !m_logicalFunctionSupported 
) 
 677     wxGraphicsPath path 
= m_graphicContext
->CreatePath(); 
 679     wxPointList::compatibility_iterator node 
= points
->GetFirst(); 
 684     wxPoint 
*p 
= node
->GetData(); 
 689     node 
= node
->GetNext(); 
 694     wxCoord cx1 
= ( x1 
+ x2 
) / 2; 
 695     wxCoord cy1 
= ( y1 
+ y2 
) / 2; 
 697     path
.MoveToPoint( x1 
, y1 
); 
 698     path
.AddLineToPoint( cx1 
, cy1 
); 
 699 #if !wxUSE_STD_CONTAINERS 
 701     while ((node 
= node
->GetNext()) != NULL
) 
 704     while ((node 
= node
->GetNext())) 
 705 #endif // !wxUSE_STD_CONTAINERS 
 713         wxCoord cx4 
= (x1 
+ x2
) / 2; 
 714         wxCoord cy4 
= (y1 
+ y2
) / 2; 
 716         path
.AddQuadCurveToPoint(x1 
, y1 
,cx4 
, cy4 
); 
 722     path
.AddLineToPoint( x2 
, y2 
); 
 724     m_graphicContext
->StrokePath( path 
); 
 726 #endif // wxUSE_SPLINES 
 728 void wxGCDCImpl::DoDrawPolygon( int n
, wxPoint points
[], 
 729                                 wxCoord xoffset
, wxCoord yoffset
, 
 730                                 wxPolygonFillMode fillStyle 
) 
 732     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawPolygon - invalid DC") ); 
 734     if ( n 
<= 0 || (m_brush
.GetStyle() == wxTRANSPARENT 
&& m_pen
.GetStyle() == wxTRANSPARENT 
) ) 
 736     if ( !m_logicalFunctionSupported 
) 
 739     bool closeIt 
= false; 
 740     if (points
[n
-1] != points
[0]) 
 743     wxPoint2DDouble
* pointsD 
= new wxPoint2DDouble
[n
+(closeIt
?1:0)]; 
 744     for( int i 
= 0; i 
< n
; ++i
) 
 746         pointsD
[i
].m_x 
= points
[i
].x 
+ xoffset
; 
 747         pointsD
[i
].m_y 
= points
[i
].y 
+ yoffset
; 
 750         pointsD
[n
] = pointsD
[0]; 
 752     m_graphicContext
->DrawLines( n
+(closeIt
?1:0) , pointsD
, fillStyle
); 
 756 void wxGCDCImpl::DoDrawPolyPolygon(int n
, 
 761                                wxPolygonFillMode fillStyle
) 
 764     wxGraphicsPath path 
= m_graphicContext
->CreatePath(); 
 767     for ( int j 
= 0; j 
< n
; ++j
) 
 769         wxPoint start 
= points
[i
]; 
 770         path
.MoveToPoint( start
.x
+ xoffset
, start
.y
+ yoffset
); 
 773         for ( int k 
= 1; k 
< l
; ++k
) 
 775             path
.AddLineToPoint( points
[i
].x
+ xoffset
, points
[i
].y
+ yoffset
); 
 779         if ( start 
!= points
[i
-1]) 
 780             path
.AddLineToPoint( start
.x
+ xoffset
, start
.y
+ yoffset
); 
 782     m_graphicContext
->DrawPath( path 
, fillStyle
); 
 785 void wxGCDCImpl::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) 
 787     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawRectangle - invalid DC") ); 
 789     if ( !m_logicalFunctionSupported 
) 
 792     // CMB: draw nothing if transformed w or h is 0 
 793     if (w 
== 0 || h 
== 0) 
 796     if ( m_graphicContext
->ShouldOffset() ) 
 798         // if we are offsetting the entire rectangle is moved 0.5, so the 
 799         // border line gets off by 1 
 803     m_graphicContext
->DrawRectangle(x
,y
,w
,h
); 
 806 void wxGCDCImpl::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, 
 807                                     wxCoord w
, wxCoord h
, 
 810     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawRoundedRectangle - invalid DC") ); 
 812     if ( !m_logicalFunctionSupported 
) 
 816         radius 
= - radius 
* ((w 
< h
) ? w 
: h
); 
 818     // CMB: draw nothing if transformed w or h is 0 
 819     if (w 
== 0 || h 
== 0) 
 822     if ( m_graphicContext
->ShouldOffset() ) 
 824         // if we are offsetting the entire rectangle is moved 0.5, so the 
 825         // border line gets off by 1 
 829     m_graphicContext
->DrawRoundedRectangle( x
,y
,w
,h
,radius
); 
 832 void wxGCDCImpl::DoDrawEllipse(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) 
 834     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawEllipse - invalid DC") ); 
 836     if ( !m_logicalFunctionSupported 
) 
 839     if ( m_graphicContext
->ShouldOffset() ) 
 841         // if we are offsetting the entire rectangle is moved 0.5, so the 
 842         // border line gets off by 1 
 846     m_graphicContext
->DrawEllipse(x
,y
,w
,h
); 
 849 bool wxGCDCImpl::CanDrawBitmap() const 
 854 bool wxGCDCImpl::DoBlit( 
 855     wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
, 
 856     wxDC 
*source
, wxCoord xsrc
, wxCoord ysrc
, 
 857     wxRasterOperationMode logical_func 
, bool useMask
, 
 858     wxCoord xsrcMask
, wxCoord ysrcMask 
) 
 860     return DoStretchBlit( xdest
, ydest
, width
, height
, 
 861         source
, xsrc
, ysrc
, width
, height
, logical_func
, useMask
, 
 865 bool wxGCDCImpl::DoStretchBlit( 
 866     wxCoord xdest
, wxCoord ydest
, wxCoord dstWidth
, wxCoord dstHeight
, 
 867     wxDC 
*source
, wxCoord xsrc
, wxCoord ysrc
, wxCoord srcWidth
, wxCoord srcHeight
, 
 868     wxRasterOperationMode logical_func 
, bool useMask
, 
 869     wxCoord xsrcMask
, wxCoord ysrcMask 
) 
 871     wxCHECK_MSG( IsOk(), false, wxT("wxGCDC(cg)::DoStretchBlit - invalid DC") ); 
 872     wxCHECK_MSG( source
->IsOk(), false, wxT("wxGCDC(cg)::DoStretchBlit - invalid source DC") ); 
 874     if ( logical_func 
== wxNO_OP 
) 
 877     wxCompositionMode mode
; 
 878     if ( !TranslateRasterOp(logical_func
, &mode
) ) 
 880         wxFAIL_MSG( wxT("Blitting is not supported with this logical operation.") ); 
 886     wxCompositionMode formerMode 
= m_graphicContext
->GetCompositionMode(); 
 887     if (m_graphicContext
->SetCompositionMode(mode
)) 
 889         wxAntialiasMode formerAa 
= m_graphicContext
->GetAntialiasMode(); 
 890         if (mode 
== wxCOMPOSITION_XOR
) 
 892             m_graphicContext
->SetAntialiasMode(wxANTIALIAS_NONE
); 
 895         if (xsrcMask 
== -1 && ysrcMask 
== -1) 
 901         wxRect 
subrect(source
->LogicalToDeviceX(xsrc
), 
 902                        source
->LogicalToDeviceY(ysrc
), 
 903                        source
->LogicalToDeviceXRel(srcWidth
), 
 904                        source
->LogicalToDeviceYRel(srcHeight
)); 
 906         // if needed clip the subrect down to the size of the source DC 
 908         source
->GetSize(&sw
, &sh
); 
 909         sw 
= source
->LogicalToDeviceXRel(sw
); 
 910         sh 
= source
->LogicalToDeviceYRel(sh
); 
 911         if (subrect
.x 
+ subrect
.width 
> sw
) 
 912             subrect
.width 
= sw 
- subrect
.x
; 
 913         if (subrect
.y 
+ subrect
.height 
> sh
) 
 914             subrect
.height 
= sh 
- subrect
.y
; 
 916         wxBitmap blit 
= source
->GetAsBitmap( &subrect 
); 
 920             if ( !useMask 
&& blit
.GetMask() ) 
 923             m_graphicContext
->DrawBitmap( blit
, xdest
, ydest
, 
 924                                           dstWidth
, dstHeight
); 
 928             wxFAIL_MSG( wxT("Cannot Blit. Unable to get contents of DC as bitmap.") ); 
 932         if (mode 
== wxCOMPOSITION_XOR
) 
 934             m_graphicContext
->SetAntialiasMode(formerAa
); 
 938     m_graphicContext
->SetCompositionMode(formerMode
); 
 943 void wxGCDCImpl::DoDrawRotatedText(const wxString
& str
, wxCoord x
, wxCoord y
, 
 946     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawRotatedText - invalid DC") ); 
 950     if ( !m_logicalFunctionSupported 
) 
 953     if ( m_backgroundMode 
== wxTRANSPARENT 
) 
 954         m_graphicContext
->DrawText( str
, x 
,y 
, DegToRad(angle 
)); 
 956         m_graphicContext
->DrawText( str
, x 
,y 
, DegToRad(angle 
), m_graphicContext
->CreateBrush( wxBrush(m_textBackgroundColour
,wxSOLID
) ) ); 
 959 void wxGCDCImpl::DoDrawText(const wxString
& str
, wxCoord x
, wxCoord y
) 
 961     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawText - invalid DC") ); 
 966     if ( !m_logicalFunctionSupported 
) 
 969     if ( m_backgroundMode 
== wxTRANSPARENT 
) 
 970         m_graphicContext
->DrawText( str
, x 
,y
); 
 972         m_graphicContext
->DrawText( str
, x 
,y 
, m_graphicContext
->CreateBrush( wxBrush(m_textBackgroundColour
,wxSOLID
) ) ); 
 975 bool wxGCDCImpl::CanGetTextExtent() const 
 977     wxCHECK_MSG( IsOk(), false, wxT("wxGCDC(cg)::CanGetTextExtent - invalid DC") ); 
 982 void wxGCDCImpl::DoGetTextExtent( const wxString 
&str
, wxCoord 
*width
, wxCoord 
*height
, 
 983                               wxCoord 
*descent
, wxCoord 
*externalLeading 
, 
 984                               const wxFont 
*theFont 
) const 
 986     wxCHECK_RET( m_graphicContext
, wxT("wxGCDC(cg)::DoGetTextExtent - invalid DC") ); 
 990         m_graphicContext
->SetFont( *theFont
, m_textForegroundColour 
); 
 993     wxDouble h 
, d 
, e 
, w
; 
 995     m_graphicContext
->GetTextExtent( str
, &w
, &h
, &d
, &e 
); 
 998         *height 
= (wxCoord
)(h
+0.5); 
1000         *descent 
= (wxCoord
)(d
+0.5); 
1001     if ( externalLeading 
) 
1002         *externalLeading 
= (wxCoord
)(e
+0.5); 
1004         *width 
= (wxCoord
)(w
+0.5); 
1008         m_graphicContext
->SetFont( m_font
, m_textForegroundColour 
); 
1012 bool wxGCDCImpl::DoGetPartialTextExtents(const wxString
& text
, wxArrayInt
& widths
) const 
1014     wxCHECK_MSG( m_graphicContext
, false, wxT("wxGCDC(cg)::DoGetPartialTextExtents - invalid DC") ); 
1016     widths
.Add(0,text
.Length()); 
1017     if ( text
.IsEmpty() ) 
1020     wxArrayDouble widthsD
; 
1022     m_graphicContext
->GetPartialTextExtents( text
, widthsD 
); 
1023     for ( size_t i 
= 0; i 
< widths
.GetCount(); ++i 
) 
1024         widths
[i
] = (wxCoord
)(widthsD
[i
] + 0.5); 
1029 wxCoord 
wxGCDCImpl::GetCharWidth(void) const 
1032     DoGetTextExtent( wxT("g") , &width 
, NULL 
, NULL 
, NULL 
, NULL 
); 
1037 wxCoord 
wxGCDCImpl::GetCharHeight(void) const 
1040     DoGetTextExtent( wxT("g") , NULL 
, &height 
, NULL 
, NULL 
, NULL 
); 
1045 void wxGCDCImpl::Clear(void) 
1047     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::Clear - invalid DC") ); 
1048     // TODO better implementation / incorporate size info into wxGCDC or context 
1049     m_graphicContext
->SetBrush( m_backgroundBrush 
); 
1050     wxPen p 
= *wxTRANSPARENT_PEN
; 
1051     m_graphicContext
->SetPen( p 
); 
1052     wxCompositionMode formerMode 
= m_graphicContext
->GetCompositionMode(); 
1053     m_graphicContext
->SetCompositionMode(wxCOMPOSITION_SOURCE
); 
1054     DoDrawRectangle( 0, 0, 32000 , 32000 ); 
1055     m_graphicContext
->SetCompositionMode(formerMode
); 
1056     m_graphicContext
->SetPen( m_pen 
); 
1057     m_graphicContext
->SetBrush( m_brush 
); 
1060 void wxGCDCImpl::DoGetSize(int *width
, int *height
) const 
1062     wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoGetSize - invalid DC") ); 
1064     m_graphicContext
->GetSize( &w
, &h 
); 
1066         *height 
= (int) (h
+0.5); 
1068         *width 
= (int) (w
+0.5); 
1071 void wxGCDCImpl::DoGradientFillLinear(const wxRect
& rect
, 
1072                                   const wxColour
& initialColour
, 
1073                                   const wxColour
& destColour
, 
1074                                   wxDirection nDirection 
) 
1081         start 
= rect
.GetRightBottom(); 
1083         end 
= rect
.GetLeftBottom(); 
1086         start 
= rect
.GetLeftBottom(); 
1087         end 
= rect
.GetRightBottom(); 
1091         start 
= rect
.GetLeftBottom(); 
1093         end 
= rect
.GetLeftTop(); 
1096         start 
= rect
.GetLeftTop(); 
1097         end 
= rect
.GetLeftBottom(); 
1104     if (rect
.width 
== 0 || rect
.height 
== 0) 
1107     m_graphicContext
->SetBrush( m_graphicContext
->CreateLinearGradientBrush( 
1108         start
.x
,start
.y
,end
.x
,end
.y
, initialColour
, destColour
)); 
1109     m_graphicContext
->SetPen(*wxTRANSPARENT_PEN
); 
1110     m_graphicContext
->DrawRectangle(rect
.x
,rect
.y
,rect
.width
,rect
.height
); 
1111     m_graphicContext
->SetPen(m_pen
); 
1114 void wxGCDCImpl::DoGradientFillConcentric(const wxRect
& rect
, 
1115                                       const wxColour
& initialColour
, 
1116                                       const wxColour
& destColour
, 
1117                                       const wxPoint
& circleCenter
) 
1120     wxInt32 cx 
= rect
.GetWidth() / 2; 
1121     wxInt32 cy 
= rect
.GetHeight() / 2; 
1128     // make sure the background is filled (todo move into specific platform implementation ?) 
1129     m_graphicContext
->SetPen(*wxTRANSPARENT_PEN
); 
1130     m_graphicContext
->SetBrush( wxBrush( destColour
) ); 
1131     m_graphicContext
->DrawRectangle(rect
.x
,rect
.y
,rect
.width
,rect
.height
); 
1133     m_graphicContext
->SetBrush( m_graphicContext
->CreateRadialGradientBrush( 
1134         rect
.x
+circleCenter
.x
,rect
.y
+circleCenter
.y
, 
1135         rect
.x
+circleCenter
.x
,rect
.y
+circleCenter
.y
, 
1136         nRadius
,initialColour
,destColour
)); 
1138     m_graphicContext
->DrawRectangle(rect
.x
,rect
.y
,rect
.width
,rect
.height
); 
1139     m_graphicContext
->SetPen(m_pen
); 
1142 void wxGCDCImpl::DoDrawCheckMark(wxCoord x
, wxCoord y
, 
1143                              wxCoord width
, wxCoord height
) 
1145     wxDCImpl::DoDrawCheckMark(x
,y
,width
,height
); 
1148 #endif // wxUSE_GRAPHICS_CONTEXT