X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6c0aace267b99d3bc1c107611decca0fd202d5b5..472137baebae6c011ad7d70285de454b9ce7796d:/src/common/dcgraph.cpp?ds=sidebyside diff --git a/src/common/dcgraph.cpp b/src/common/dcgraph.cpp index 4b4461dc3e..2b9eb8c97a 100644 --- a/src/common/dcgraph.cpp +++ b/src/common/dcgraph.cpp @@ -19,6 +19,7 @@ #if wxUSE_GRAPHICS_CONTEXT #include "wx/graphics.h" +#include "wx/dcgraph.h" #ifndef WX_PRECOMP #include "wx/icon.h" @@ -27,8 +28,14 @@ #include "wx/region.h" #endif -#ifndef wxMAC_USE_CORE_GRAPHICS_BLEND_MODES - #define wxMAC_USE_CORE_GRAPHICS_BLEND_MODES 0 +#include "wx/dcclient.h" + +#ifdef __WXOSX_OR_COCOA__ +#ifdef __WXOSX_IPHONE__ + #include +#else + #include +#endif #endif //----------------------------------------------------------------------------- @@ -50,18 +57,57 @@ static inline double DegToRad(double deg) // wxDC bridge class //----------------------------------------------------------------------------- -#ifdef __WXMAC__ -IMPLEMENT_DYNAMIC_CLASS(wxGCDC, wxDCBase) -#else IMPLEMENT_DYNAMIC_CLASS(wxGCDC, wxDC) + +wxGCDC::wxGCDC(const wxWindowDC& dc) : + wxDC( new wxGCDCImpl( this, dc ) ) +{ +} + +wxGCDC::wxGCDC( const wxMemoryDC& dc) : + wxDC( new wxGCDCImpl( this, dc ) ) +{ +} + +#if wxUSE_PRINTING_ARCHITECTURE +wxGCDC::wxGCDC( const wxPrinterDC& dc) : + wxDC( new wxGCDCImpl( this, dc ) ) +{ +} #endif -wxGCDC::wxGCDC() +wxGCDC::wxGCDC() : + wxDC( new wxGCDCImpl( this ) ) +{ +} + +wxGCDC::~wxGCDC() { - Init(); +} + +wxGraphicsContext* wxGCDC::GetGraphicsContext() +{ + if (!m_pimpl) return NULL; + wxGCDCImpl *gc_impl = (wxGCDCImpl*) m_pimpl; + return gc_impl->GetGraphicsContext(); } void wxGCDC::SetGraphicsContext( wxGraphicsContext* ctx ) +{ + if (!m_pimpl) return; + wxGCDCImpl *gc_impl = (wxGCDCImpl*) m_pimpl; + gc_impl->SetGraphicsContext( ctx ); +} + +IMPLEMENT_ABSTRACT_CLASS(wxGCDCImpl, wxDCImpl) + +wxGCDCImpl::wxGCDCImpl( wxDC *owner ) : + wxDCImpl( owner ) +{ + Init(); +} + +void wxGCDCImpl::SetGraphicsContext( wxGraphicsContext* ctx ) { delete m_graphicContext; m_graphicContext = ctx; @@ -69,22 +115,39 @@ void wxGCDC::SetGraphicsContext( wxGraphicsContext* ctx ) { m_matrixOriginal = m_graphicContext->GetTransform(); m_ok = true; + // apply the stored transformations to the passed in context + ComputeScaleAndOrigin(); + m_graphicContext->SetFont( m_font , m_textForegroundColour ); + m_graphicContext->SetPen( m_pen ); + m_graphicContext->SetBrush( m_brush); } } -wxGCDC::wxGCDC(const wxWindowDC& dc) +wxGCDCImpl::wxGCDCImpl( wxDC *owner, const wxWindowDC& dc ) : + wxDCImpl( owner ) +{ + Init(); + SetGraphicsContext( wxGraphicsContext::Create(dc) ); + m_window = dc.GetWindow(); +} + +wxGCDCImpl::wxGCDCImpl( wxDC *owner, const wxMemoryDC& dc ) : + wxDCImpl( owner ) { Init(); SetGraphicsContext( wxGraphicsContext::Create(dc) ); - if ( dc.GetFont().Ok()) - m_graphicContext->SetFont( m_graphicContext->CreateFont(dc.GetFont(),dc.GetTextForeground())); - if ( dc.GetPen().Ok()) - m_graphicContext->SetPen( m_graphicContext->CreatePen(dc.GetPen())); - if ( dc.GetBrush().Ok()) - m_graphicContext->SetBrush( m_graphicContext->CreateBrush(dc.GetBrush())); } -void wxGCDC::Init() +#if wxUSE_PRINTING_ARCHITECTURE +wxGCDCImpl::wxGCDCImpl( wxDC *owner, const wxPrinterDC& dc ) : + wxDCImpl( owner ) +{ + Init(); + SetGraphicsContext( wxGraphicsContext::Create(dc) ); +} +#endif + +void wxGCDCImpl::Init() { m_ok = false; m_colour = true; @@ -96,26 +159,49 @@ void wxGCDC::Init() m_brush = *wxWHITE_BRUSH; m_graphicContext = NULL; + m_logicalFunctionSupported = true; } -wxGCDC::~wxGCDC() +wxGCDCImpl::~wxGCDCImpl() { delete m_graphicContext; } -void wxGCDC::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, bool WXUNUSED(useMask) ) +void wxGCDCImpl::DoDrawBitmap( const wxBitmap &bmp, wxCoord x, wxCoord y, + bool useMask ) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawBitmap - invalid DC") ); - wxCHECK_RET( bmp.Ok(), wxT("wxGCDC(cg)::DoDrawBitmap - invalid bitmap") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawBitmap - invalid DC") ); + wxCHECK_RET( bmp.IsOk(), wxT("wxGCDC(cg)::DoDrawBitmap - invalid bitmap") ); - m_graphicContext->DrawBitmap( bmp, x , y , bmp.GetWidth() , bmp.GetHeight() ); + int w = bmp.GetWidth(); + int h = bmp.GetHeight(); + if ( bmp.GetDepth() == 1 ) + { + m_graphicContext->SetPen(*wxTRANSPARENT_PEN); + m_graphicContext->SetBrush( wxBrush( m_textBackgroundColour , wxSOLID ) ); + m_graphicContext->DrawRectangle( x, y, w, h ); + m_graphicContext->SetBrush( wxBrush( m_textForegroundColour , wxSOLID ) ); + m_graphicContext->DrawBitmap( bmp, x, y, w, h ); + m_graphicContext->SetBrush( m_graphicContext->CreateBrush(m_brush)); + m_graphicContext->SetPen( m_graphicContext->CreatePen(m_pen)); + } + else // not a monochrome bitmap, handle it normally + { + // make a copy in case we need to remove its mask, if we don't modify + // it the copy is cheap as bitmaps are reference-counted + wxBitmap bmpCopy(bmp); + if ( !useMask && bmp.GetMask() ) + bmpCopy.SetMask(NULL); + + m_graphicContext->DrawBitmap( bmpCopy, x, y, w, h ); + } } -void wxGCDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y ) +void wxGCDCImpl::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y ) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawIcon - invalid DC") ); - wxCHECK_RET( icon.Ok(), wxT("wxGCDC(cg)::DoDrawIcon - invalid icon") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawIcon - invalid DC") ); + wxCHECK_RET( icon.IsOk(), wxT("wxGCDC(cg)::DoDrawIcon - invalid icon") ); wxCoord w = icon.GetWidth(); wxCoord h = icon.GetHeight(); @@ -123,9 +209,33 @@ void wxGCDC::DoDrawIcon( const wxIcon &icon, wxCoord x, wxCoord y ) m_graphicContext->DrawIcon( icon , x, y, w, h ); } -void wxGCDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) +bool wxGCDCImpl::StartDoc( const wxString& WXUNUSED(message) ) +{ + return true; +} + +void wxGCDCImpl::EndDoc() { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoSetClippingRegion - invalid DC") ); +} + +void wxGCDCImpl::StartPage() +{ +} + +void wxGCDCImpl::EndPage() +{ +} + +void wxGCDCImpl::Flush() +{ +#ifdef __WXOSX_OR_COCOA__ + CGContextFlush( (CGContextRef) m_graphicContext->GetNativeContext() ); +#endif +} + +void wxGCDCImpl::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) +{ + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoSetClippingRegion - invalid DC") ); m_graphicContext->Clip( x, y, w, h ); if ( m_clipping ) @@ -146,20 +256,24 @@ void wxGCDC::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) } } -void wxGCDC::DoSetClippingRegionAsRegion( const wxRegion ®ion ) +void wxGCDCImpl::DoSetDeviceClippingRegion( const wxRegion ®ion ) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoSetClippingRegionAsRegion - invalid DC") ); + // region is in device coordinates + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoSetDeviceClippingRegion - invalid DC") ); if (region.Empty()) { - DestroyClippingRegion(); + //DestroyClippingRegion(); return; } + wxRegion logRegion( region ); wxCoord x, y, w, h; - region.GetBox( x, y, w, h ); - m_graphicContext->Clip( region ); + logRegion.Offset( DeviceToLogicalX(0), DeviceToLogicalY(0) ); + logRegion.GetBox( x, y, w, h ); + + m_graphicContext->Clip( logRegion ); if ( m_clipping ) { m_clipX1 = wxMax( m_clipX1, x ); @@ -178,29 +292,35 @@ void wxGCDC::DoSetClippingRegionAsRegion( const wxRegion ®ion ) } } -void wxGCDC::DestroyClippingRegion() +void wxGCDCImpl::DestroyClippingRegion() { m_graphicContext->ResetClip(); + // currently the clip eg of a window extends to the area between the scrollbars + // so we must explicitely make sure it only covers the area we want it to draw + int width, height ; + GetOwner()->GetSize( &width , &height ) ; + m_graphicContext->Clip( DeviceToLogicalX(0) , DeviceToLogicalY(0) , DeviceToLogicalXRel(width), DeviceToLogicalYRel(height) ); + m_graphicContext->SetPen( m_pen ); m_graphicContext->SetBrush( m_brush ); m_clipping = false; } -void wxGCDC::DoGetSizeMM( int* width, int* height ) const +void wxGCDCImpl::DoGetSizeMM( int* width, int* height ) const { int w = 0, h = 0; - GetSize( &w, &h ); + GetOwner()->GetSize( &w, &h ); if (width) *width = long( double(w) / (m_scaleX * m_mm_to_pix_x) ); if (height) *height = long( double(h) / (m_scaleY * m_mm_to_pix_y) ); } -void wxGCDC::SetTextForeground( const wxColour &col ) +void wxGCDCImpl::SetTextForeground( const wxColour &col ) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::SetTextForeground - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::SetTextForeground - invalid DC") ); if ( col != m_textForegroundColour ) { @@ -209,14 +329,14 @@ void wxGCDC::SetTextForeground( const wxColour &col ) } } -void wxGCDC::SetTextBackground( const wxColour &col ) +void wxGCDCImpl::SetTextBackground( const wxColour &col ) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::SetTextBackground - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::SetTextBackground - invalid DC") ); m_textBackgroundColour = col; } -void wxGCDC::SetMapMode( int mode ) +void wxGCDCImpl::SetMapMode( int mode ) { switch (mode) { @@ -245,91 +365,58 @@ void wxGCDC::SetMapMode( int mode ) ComputeScaleAndOrigin(); } -void wxGCDC::SetUserScale( double x, double y ) -{ - // allow negative ? -> no - - m_userScaleX = x; - m_userScaleY = y; - ComputeScaleAndOrigin(); -} - -void wxGCDC::SetLogicalScale( double x, double y ) -{ - // allow negative ? - m_logicalScaleX = x; - m_logicalScaleY = y; - ComputeScaleAndOrigin(); -} - -void wxGCDC::SetLogicalOrigin( wxCoord x, wxCoord y ) -{ - m_logicalOriginX = x * m_signX; // is this still correct ? - m_logicalOriginY = y * m_signY; - ComputeScaleAndOrigin(); -} - -void wxGCDC::SetDeviceOrigin( wxCoord x, wxCoord y ) -{ - m_deviceOriginX = x; - m_deviceOriginY = y; - ComputeScaleAndOrigin(); -} - -void wxGCDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp ) -{ - m_signX = (xLeftRight ? 1 : -1); - m_signY = (yBottomUp ? -1 : 1); - ComputeScaleAndOrigin(); -} - -wxSize wxGCDC::GetPPI() const +wxSize wxGCDCImpl::GetPPI() const { return wxSize(72, 72); } -int wxGCDC::GetDepth() const +int wxGCDCImpl::GetDepth() const { return 32; } -void wxGCDC::ComputeScaleAndOrigin() +void wxGCDCImpl::ComputeScaleAndOrigin() { - m_scaleX = m_logicalScaleX * m_userScaleX; - m_scaleY = m_logicalScaleY * m_userScaleY; + wxDCImpl::ComputeScaleAndOrigin(); + + if ( m_graphicContext ) + { + m_matrixCurrent = m_graphicContext->CreateMatrix(); - m_matrixCurrent = m_graphicContext->CreateMatrix(); - m_matrixCurrent.Translate( m_deviceOriginX, m_deviceOriginY ); - m_matrixCurrent.Scale( m_scaleX, m_scaleY ); - m_matrixCurrent.Translate( m_logicalOriginX, m_logicalOriginY ); + // the logical origin sets the origin to have new coordinates + m_matrixCurrent.Translate( m_deviceOriginX - m_logicalOriginX * m_signX * m_scaleX, + m_deviceOriginY-m_logicalOriginY * m_signY * m_scaleY); - m_graphicContext->SetTransform( m_matrixOriginal ); - m_graphicContext->ConcatTransform( m_matrixCurrent ); + m_matrixCurrent.Scale( m_scaleX * m_signX, m_scaleY * m_signY ); + + m_graphicContext->SetTransform( m_matrixOriginal ); + m_graphicContext->ConcatTransform( m_matrixCurrent ); + } } -void wxGCDC::SetPalette( const wxPalette& WXUNUSED(palette) ) +void wxGCDCImpl::SetPalette( const wxPalette& WXUNUSED(palette) ) { } -void wxGCDC::SetBackgroundMode( int mode ) +void wxGCDCImpl::SetBackgroundMode( int mode ) { m_backgroundMode = mode; } -void wxGCDC::SetFont( const wxFont &font ) +void wxGCDCImpl::SetFont( const wxFont &font ) { m_font = font; if ( m_graphicContext ) { wxFont f = font; - if ( f.Ok() ) + if ( f.IsOk() ) f.SetPointSize( /*LogicalToDeviceYRel*/(font.GetPointSize())); m_graphicContext->SetFont( f, m_textForegroundColour ); } } -void wxGCDC::SetPen( const wxPen &pen ) +void wxGCDCImpl::SetPen( const wxPen &pen ) { if ( m_pen == pen ) return; @@ -341,7 +428,7 @@ void wxGCDC::SetPen( const wxPen &pen ) } } -void wxGCDC::SetBrush( const wxBrush &brush ) +void wxGCDCImpl::SetBrush( const wxBrush &brush ) { if (m_brush == brush) return; @@ -353,56 +440,46 @@ void wxGCDC::SetBrush( const wxBrush &brush ) } } -void wxGCDC::SetBackground( const wxBrush &brush ) +void wxGCDCImpl::SetBackground( const wxBrush &brush ) { if (m_backgroundBrush == brush) return; m_backgroundBrush = brush; - if (!m_backgroundBrush.Ok()) + if (!m_backgroundBrush.IsOk()) return; } -void wxGCDC::SetLogicalFunction( int function ) +void wxGCDCImpl::SetLogicalFunction( int function ) { if (m_logicalFunction == function) return; m_logicalFunction = function; -#if wxMAC_USE_CORE_GRAPHICS_BLEND_MODES - - CGContextRef cgContext = ((wxCairoContext*)(m_graphicContext))->GetNativeContext(); - if ( m_logicalFunction == wxCOPY ) - CGContextSetBlendMode( cgContext, kCGBlendModeNormal ); - else if ( m_logicalFunction == wxINVERT ) - CGContextSetBlendMode( cgContext, kCGBlendModeExclusion ); + if ( m_graphicContext->SetLogicalFunction( function ) ) + m_logicalFunctionSupported=true; else - CGContextSetBlendMode( cgContext, kCGBlendModeNormal ); -#endif - + m_logicalFunctionSupported=false; } -bool wxGCDC::DoFloodFill(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), +bool wxGCDCImpl::DoFloodFill(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), const wxColour& WXUNUSED(col), int WXUNUSED(style)) { return false; } -bool wxGCDC::DoGetPixel( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxColour *WXUNUSED(col) ) const +bool wxGCDCImpl::DoGetPixel( wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), wxColour *WXUNUSED(col) ) const { // wxCHECK_MSG( 0 , false, wxT("wxGCDC(cg)::DoGetPixel - not implemented") ); return false; } -void wxGCDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) +void wxGCDCImpl::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawLine - invalid DC") ); - -#if !wxMAC_USE_CORE_GRAPHICS_BLEND_MODES + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawLine - invalid DC") ); - if ( m_logicalFunction != wxCOPY ) + if ( !m_logicalFunctionSupported ) return; -#endif m_graphicContext->StrokeLine(x1,y1,x2,y2); @@ -410,16 +487,16 @@ void wxGCDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) CalcBoundingBox(x2, y2); } -void wxGCDC::DoCrossHair( wxCoord x, wxCoord y ) +void wxGCDCImpl::DoCrossHair( wxCoord x, wxCoord y ) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoCrossHair - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoCrossHair - invalid DC") ); - if ( m_logicalFunction != wxCOPY ) + if ( !m_logicalFunctionSupported ) return; int w = 0, h = 0; - GetSize( &w, &h ); + GetOwner()->GetSize( &w, &h ); m_graphicContext->StrokeLine(0,y,w,y); m_graphicContext->StrokeLine(x,0,x,h); @@ -428,13 +505,13 @@ void wxGCDC::DoCrossHair( wxCoord x, wxCoord y ) CalcBoundingBox(0+w, 0+h); } -void wxGCDC::DoDrawArc( wxCoord x1, wxCoord y1, +void wxGCDCImpl::DoDrawArc( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc ) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawArc - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawArc - invalid DC") ); - if ( m_logicalFunction != wxCOPY ) + if ( !m_logicalFunctionSupported ) return; double dx = x1 - xc; @@ -466,55 +543,65 @@ void wxGCDC::DoDrawArc( wxCoord x1, wxCoord y1, wxGraphicsPath path = m_graphicContext->CreatePath(); if ( fill && ((x1!=x2)||(y1!=y2)) ) path.MoveToPoint( xc, yc ); - path.AddArc( xc, yc , rad , DegToRad(sa) , DegToRad(ea), false ); + // since these angles (ea,sa) are measured counter-clockwise, we invert them to + // get clockwise angles + path.AddArc( xc, yc , rad , DegToRad(-sa) , DegToRad(-ea), false ); if ( fill && ((x1!=x2)||(y1!=y2)) ) path.AddLineToPoint( xc, yc ); m_graphicContext->DrawPath(path); } -void wxGCDC::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h, +void wxGCDCImpl::DoDrawEllipticArc( wxCoord x, wxCoord y, wxCoord w, wxCoord h, double sa, double ea ) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawEllipticArc - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawEllipticArc - invalid DC") ); - if ( m_logicalFunction != wxCOPY ) + if ( !m_logicalFunctionSupported ) return; - bool fill = m_brush.GetStyle() != wxTRANSPARENT; - - wxGraphicsPath path = m_graphicContext->CreatePath(); m_graphicContext->PushState(); - m_graphicContext->Translate(x+w/2,y+h/2); + m_graphicContext->Translate(x+w/2.0,y+h/2.0); wxDouble factor = ((wxDouble) w) / h; m_graphicContext->Scale( factor , 1.0); - if ( fill && (sa!=ea) ) - path.MoveToPoint(0,0); + // since these angles (ea,sa) are measured counter-clockwise, we invert them to // get clockwise angles - path.AddArc( 0, 0, h/2 , DegToRad(-sa) , DegToRad(-ea), sa > ea ); - if ( fill && (sa!=ea) ) - path.AddLineToPoint(0,0); - m_graphicContext->DrawPath( path ); + if ( m_brush.GetStyle() != wxTRANSPARENT ) + { + wxGraphicsPath path = m_graphicContext->CreatePath(); + path.MoveToPoint( 0, 0 ); + path.AddArc( 0, 0, h/2.0 , DegToRad(-sa) , DegToRad(-ea), sa > ea ); + path.AddLineToPoint( 0, 0 ); + m_graphicContext->FillPath( path ); + + path = m_graphicContext->CreatePath(); + path.AddArc( 0, 0, h/2.0 , DegToRad(-sa) , DegToRad(-ea), sa > ea ); + m_graphicContext->StrokePath( path ); + } + else + { + wxGraphicsPath path = m_graphicContext->CreatePath(); + path.AddArc( 0, 0, h/2.0 , DegToRad(-sa) , DegToRad(-ea), sa > ea ); + m_graphicContext->DrawPath( path ); + } + m_graphicContext->PopState(); } -void wxGCDC::DoDrawPoint( wxCoord x, wxCoord y ) +void wxGCDCImpl::DoDrawPoint( wxCoord x, wxCoord y ) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawPoint - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawPoint - invalid DC") ); DoDrawLine( x , y , x + 1 , y + 1 ); } -void wxGCDC::DoDrawLines(int n, wxPoint points[], +void wxGCDCImpl::DoDrawLines(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawLines - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawLines - invalid DC") ); -#if !wxMAC_USE_CORE_GRAPHICS_BLEND_MODES - - if ( m_logicalFunction != wxCOPY ) + if ( !m_logicalFunctionSupported ) return; -#endif wxPoint2DDouble* pointsD = new wxPoint2DDouble[n]; for( int i = 0; i < n; ++i) @@ -528,27 +615,27 @@ void wxGCDC::DoDrawLines(int n, wxPoint points[], } #if wxUSE_SPLINES -void wxGCDC::DoDrawSpline(wxList *points) +void wxGCDCImpl::DoDrawSpline(const wxPointList *points) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawSpline - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawSpline - invalid DC") ); - if ( m_logicalFunction != wxCOPY ) + if ( !m_logicalFunctionSupported ) return; wxGraphicsPath path = m_graphicContext->CreatePath(); - wxList::compatibility_iterator node = points->GetFirst(); - if (node == wxList::compatibility_iterator()) + wxPointList::compatibility_iterator node = points->GetFirst(); + if (node == wxPointList::compatibility_iterator()) // empty list return; - wxPoint *p = (wxPoint *)node->GetData(); + wxPoint *p = node->GetData(); wxCoord x1 = p->x; wxCoord y1 = p->y; node = node->GetNext(); - p = (wxPoint *)node->GetData(); + p = node->GetData(); wxCoord x2 = p->x; wxCoord y2 = p->y; @@ -566,7 +653,7 @@ void wxGCDC::DoDrawSpline(wxList *points) #endif // !wxUSE_STL { - p = (wxPoint *)node->GetData(); + p = node->GetData(); x1 = x2; y1 = y2; x2 = p->x; @@ -586,15 +673,15 @@ void wxGCDC::DoDrawSpline(wxList *points) } #endif // wxUSE_SPLINES -void wxGCDC::DoDrawPolygon( int n, wxPoint points[], +void wxGCDCImpl::DoDrawPolygon( int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset, int fillStyle ) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawPolygon - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawPolygon - invalid DC") ); if ( n <= 0 || (m_brush.GetStyle() == wxTRANSPARENT && m_pen.GetStyle() == wxTRANSPARENT ) ) return; - if ( m_logicalFunction != wxCOPY ) + if ( !m_logicalFunctionSupported ) return; bool closeIt = false; @@ -614,7 +701,7 @@ void wxGCDC::DoDrawPolygon( int n, wxPoint points[], delete[] pointsD; } -void wxGCDC::DoDrawPolyPolygon(int n, +void wxGCDCImpl::DoDrawPolyPolygon(int n, int count[], wxPoint points[], wxCoord xoffset, @@ -643,11 +730,11 @@ void wxGCDC::DoDrawPolyPolygon(int n, m_graphicContext->DrawPath( path , fillStyle); } -void wxGCDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h) +void wxGCDCImpl::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawRectangle - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawRectangle - invalid DC") ); - if ( m_logicalFunction != wxCOPY ) + if ( !m_logicalFunctionSupported ) return; // CMB: draw nothing if transformed w or h is 0 @@ -664,13 +751,13 @@ void wxGCDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h) m_graphicContext->DrawRectangle(x,y,w,h); } -void wxGCDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y, +void wxGCDCImpl::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h, double radius) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawRoundedRectangle - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawRoundedRectangle - invalid DC") ); - if ( m_logicalFunction != wxCOPY ) + if ( !m_logicalFunctionSupported ) return; if (radius < 0.0) @@ -680,35 +767,60 @@ void wxGCDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y, if (w == 0 || h == 0) return; + if ( m_graphicContext->ShouldOffset() ) + { + // if we are offsetting the entire rectangle is moved 0.5, so the + // border line gets off by 1 + w -= 1; + h -= 1; + } m_graphicContext->DrawRoundedRectangle( x,y,w,h,radius); } -void wxGCDC::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord w, wxCoord h) +void wxGCDCImpl::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord w, wxCoord h) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawEllipse - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawEllipse - invalid DC") ); - if ( m_logicalFunction != wxCOPY ) + if ( !m_logicalFunctionSupported ) return; + if ( m_graphicContext->ShouldOffset() ) + { + // if we are offsetting the entire rectangle is moved 0.5, so the + // border line gets off by 1 + w -= 1; + h -= 1; + } m_graphicContext->DrawEllipse(x,y,w,h); } -bool wxGCDC::CanDrawBitmap() const +bool wxGCDCImpl::CanDrawBitmap() const { return true; } -bool wxGCDC::DoBlit( +bool wxGCDCImpl::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, - wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool WXUNUSED(useMask), + wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool useMask, wxCoord xsrcMask, wxCoord ysrcMask ) { - wxCHECK_MSG( Ok(), false, wxT("wxGCDC(cg)::DoBlit - invalid DC") ); - wxCHECK_MSG( source->Ok(), false, wxT("wxGCDC(cg)::DoBlit - invalid source DC") ); + return DoStretchBlit( xdest, ydest, width, height, + source, xsrc, ysrc, width, height, logical_func, useMask, + xsrcMask,ysrcMask ); +} + +bool wxGCDCImpl::DoStretchBlit( + wxCoord xdest, wxCoord ydest, wxCoord dstWidth, wxCoord dstHeight, + wxDC *source, wxCoord xsrc, wxCoord ysrc, wxCoord srcWidth, wxCoord srcHeight, + int logical_func , bool useMask, + wxCoord xsrcMask, wxCoord ysrcMask ) +{ + wxCHECK_MSG( IsOk(), false, wxT("wxGCDC(cg)::DoStretchBlit - invalid DC") ); + wxCHECK_MSG( source->IsOk(), false, wxT("wxGCDC(cg)::DoStretchBlit - invalid source DC") ); if ( logical_func == wxNO_OP ) return true; - else if ( logical_func != wxCOPY ) + else if ( !m_graphicContext->SetLogicalFunction( logical_func ) ) { wxFAIL_MSG( wxT("Blitting is only supported with wxCOPY logical operation.") ); return false; @@ -720,14 +832,30 @@ bool wxGCDC::DoBlit( ysrcMask = ysrc; } - wxRect subrect(source-> LogicalToDeviceX(xsrc),source-> LogicalToDeviceY(ysrc), - source-> LogicalToDeviceXRel(width),source-> LogicalToDeviceYRel(height)); + wxRect subrect(source->LogicalToDeviceX(xsrc), + source->LogicalToDeviceY(ysrc), + source->LogicalToDeviceXRel(srcWidth), + source->LogicalToDeviceYRel(srcHeight)); + + // if needed clip the subrect down to the size of the source DC + wxCoord sw, sh; + source->GetSize(&sw, &sh); + sw = source->LogicalToDeviceXRel(sw); + sh = source->LogicalToDeviceYRel(sh); + if (subrect.x + subrect.width > sw) + subrect.width = sw - subrect.x; + if (subrect.y + subrect.height > sh) + subrect.height = sh - subrect.y; wxBitmap blit = source->GetAsBitmap( &subrect ); - if ( blit.Ok() ) + if ( blit.IsOk() ) { - m_graphicContext->DrawBitmap( blit, xdest , ydest , width , height ); + if ( !useMask && blit.GetMask() ) + blit.SetMask(NULL); + + m_graphicContext->DrawBitmap( blit, xdest, ydest, + dstWidth, dstHeight); } else { @@ -735,46 +863,56 @@ bool wxGCDC::DoBlit( return false; } + // reset logical function + m_graphicContext->SetLogicalFunction( m_logicalFunction ); + return true; } -void wxGCDC::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y, +void wxGCDCImpl::DoDrawRotatedText(const wxString& str, wxCoord x, wxCoord y, double angle) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawRotatedText - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawRotatedText - invalid DC") ); if ( str.length() == 0 ) return; - if ( m_logicalFunction != wxCOPY ) + if ( !m_logicalFunctionSupported ) return; - m_graphicContext->DrawText( str, x ,y , DegToRad(angle )); + if ( m_backgroundMode == wxTRANSPARENT ) + m_graphicContext->DrawText( str, x ,y , DegToRad(angle )); + else + m_graphicContext->DrawText( str, x ,y , DegToRad(angle ), m_graphicContext->CreateBrush( wxBrush(m_textBackgroundColour,wxSOLID) ) ); } -void wxGCDC::DoDrawText(const wxString& str, wxCoord x, wxCoord y) +void wxGCDCImpl::DoDrawText(const wxString& str, wxCoord x, wxCoord y) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoDrawRotatedText - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoDrawText - invalid DC") ); if ( str.length() == 0 ) return; - if ( m_logicalFunction != wxCOPY ) + + if ( !m_logicalFunctionSupported ) return; - m_graphicContext->DrawText( str, x ,y); + if ( m_backgroundMode == wxTRANSPARENT ) + m_graphicContext->DrawText( str, x ,y); + else + m_graphicContext->DrawText( str, x ,y , m_graphicContext->CreateBrush( wxBrush(m_textBackgroundColour,wxSOLID) ) ); } -bool wxGCDC::CanGetTextExtent() const +bool wxGCDCImpl::CanGetTextExtent() const { - wxCHECK_MSG( Ok(), false, wxT("wxGCDC(cg)::CanGetTextExtent - invalid DC") ); + wxCHECK_MSG( IsOk(), false, wxT("wxGCDC(cg)::CanGetTextExtent - invalid DC") ); return true; } -void wxGCDC::DoGetTextExtent( const wxString &str, wxCoord *width, wxCoord *height, +void wxGCDCImpl::DoGetTextExtent( const wxString &str, wxCoord *width, wxCoord *height, wxCoord *descent, wxCoord *externalLeading , - wxFont *theFont ) const + const wxFont *theFont ) const { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::DoGetTextExtent - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoGetTextExtent - invalid DC") ); if ( theFont ) { @@ -786,13 +924,13 @@ void wxGCDC::DoGetTextExtent( const wxString &str, wxCoord *width, wxCoord *heig m_graphicContext->GetTextExtent( str, &w, &h, &d, &e ); if ( height ) - *height = h; + *height = (wxCoord)(h+0.5); if ( descent ) - *descent = d; + *descent = (wxCoord)(d+0.5); if ( externalLeading ) - *externalLeading =e; + *externalLeading = (wxCoord)(e+0.5); if ( width ) - *width = w; + *width = (wxCoord)(w+0.5); if ( theFont ) { @@ -800,9 +938,9 @@ void wxGCDC::DoGetTextExtent( const wxString &str, wxCoord *width, wxCoord *heig } } -bool wxGCDC::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const +bool wxGCDCImpl::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const { - wxCHECK_MSG( Ok(), false, wxT("wxGCDC(cg)::DoGetPartialTextExtents - invalid DC") ); + wxCHECK_MSG( IsOk(), false, wxT("wxGCDC(cg)::DoGetPartialTextExtents - invalid DC") ); widths.Clear(); widths.Add(0,text.Length()); if ( text.IsEmpty() ) @@ -817,7 +955,7 @@ bool wxGCDC::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) c return true; } -wxCoord wxGCDC::GetCharWidth(void) const +wxCoord wxGCDCImpl::GetCharWidth(void) const { wxCoord width; DoGetTextExtent( wxT("g") , &width , NULL , NULL , NULL , NULL ); @@ -825,7 +963,7 @@ wxCoord wxGCDC::GetCharWidth(void) const return width; } -wxCoord wxGCDC::GetCharHeight(void) const +wxCoord wxGCDCImpl::GetCharHeight(void) const { wxCoord height; DoGetTextExtent( wxT("g") , NULL , &height , NULL , NULL , NULL ); @@ -833,9 +971,9 @@ wxCoord wxGCDC::GetCharHeight(void) const return height; } -void wxGCDC::Clear(void) +void wxGCDCImpl::Clear(void) { - wxCHECK_RET( Ok(), wxT("wxGCDC(cg)::Clear - invalid DC") ); + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::Clear - invalid DC") ); // TODO better implementation / incorporate size info into wxGCDC or context m_graphicContext->SetBrush( m_backgroundBrush ); wxPen p = *wxTRANSPARENT_PEN; @@ -845,13 +983,18 @@ void wxGCDC::Clear(void) m_graphicContext->SetBrush( m_brush ); } -void wxGCDC::DoGetSize(int *width, int *height) const +void wxGCDCImpl::DoGetSize(int *width, int *height) const { - *width = 1000; - *height = 1000; + wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoGetSize - invalid DC") ); + wxDouble w,h; + m_graphicContext->GetSize( &w, &h ); + if ( height ) + *height = (int) (h+0.5); + if ( width ) + *width = (int) (w+0.5); } -void wxGCDC::DoGradientFillLinear(const wxRect& rect, +void wxGCDCImpl::DoGradientFillLinear(const wxRect& rect, const wxColour& initialColour, const wxColour& destColour, wxDirection nDirection ) @@ -894,7 +1037,7 @@ void wxGCDC::DoGradientFillLinear(const wxRect& rect, m_graphicContext->SetPen(m_pen); } -void wxGCDC::DoGradientFillConcentric(const wxRect& rect, +void wxGCDCImpl::DoGradientFillConcentric(const wxRect& rect, const wxColour& initialColour, const wxColour& destColour, const wxPoint& circleCenter) @@ -922,10 +1065,10 @@ void wxGCDC::DoGradientFillConcentric(const wxRect& rect, m_graphicContext->SetPen(m_pen); } -void wxGCDC::DoDrawCheckMark(wxCoord x, wxCoord y, +void wxGCDCImpl::DoDrawCheckMark(wxCoord x, wxCoord y, wxCoord width, wxCoord height) { - wxDCBase::DoDrawCheckMark(x,y,width,height); + wxDCImpl::DoDrawCheckMark(x,y,width,height); } #endif // wxUSE_GRAPHICS_CONTEXT