From 6dfa897b4a0ccd86f13d078931b68a8fbe893b80 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Sun, 25 Jun 2017 22:48:58 +0200 Subject: [PATCH] Adding a native implementation for clearing bitmap/window contexts Filling a bitmap surface is filled with ARGB 0,0,0,0. This way eg buffered transparent layers can be properly cleared. --- include/wx/graphics.h | 3 ++ src/common/dcgraph.cpp | 66 +++++++++++++++++++++++-------------- src/common/graphcmn.cpp | 5 +++ src/generic/graphicc.cpp | 13 ++++++-- src/osx/carbon/graphics.cpp | 13 +++++++- 5 files changed, 72 insertions(+), 28 deletions(-) diff --git a/include/wx/graphics.h b/include/wx/graphics.h index 17915a48af..2af989a3c4 100644 --- a/include/wx/graphics.h +++ b/include/wx/graphics.h @@ -653,6 +653,9 @@ public: // draws a path by first filling and then stroking virtual void DrawPath( const wxGraphicsPath& path, wxPolygonFillMode fillStyle = wxODDEVEN_RULE ); + // paints a transparent rectangle (only useful for bitmaps or windows) + virtual void ClearRectangle(wxDouble x, wxDouble y, wxDouble w, wxDouble h); + // // text // diff --git a/src/common/dcgraph.cpp b/src/common/dcgraph.cpp index b20e449eb8..4504ab270d 100644 --- a/src/common/dcgraph.cpp +++ b/src/common/dcgraph.cpp @@ -1249,33 +1249,49 @@ wxCoord wxGCDCImpl::GetCharHeight(void) const void wxGCDCImpl::Clear(void) { wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::Clear - invalid DC") ); - m_graphicContext->SetBrush( m_backgroundBrush ); - wxPen p = *wxTRANSPARENT_PEN; - m_graphicContext->SetPen( p ); - wxCompositionMode formerMode = m_graphicContext->GetCompositionMode(); - m_graphicContext->SetCompositionMode(wxCOMPOSITION_SOURCE); + + if ( m_backgroundBrush.IsOk() ) + { + m_graphicContext->SetBrush( m_backgroundBrush ); + wxPen p = *wxTRANSPARENT_PEN; + m_graphicContext->SetPen( p ); + wxCompositionMode formerMode = m_graphicContext->GetCompositionMode(); + m_graphicContext->SetCompositionMode(wxCOMPOSITION_SOURCE); + #ifdef __WXOSX__ + // This is a legacy implementation which doesn't take advantage + // of clipping region bounds retrieved by wxMacCoreGraphicsContext::GetClipBox + // because this function is not yet verified. + // Note: Legacy implmentation might not work work properly + // if graphics context is rotated + // TODO: Do the tests of wxMacCoreGraphicsContext::GetClipBox + // and switch to the implmenentation used by other renderers (code below). + // + // maximum positive coordinate Cairo can handle is 2^23 - 1 + // Use a value slightly less than this to be sure we avoid the limit + DoDrawRectangle( + DeviceToLogicalX(0), DeviceToLogicalY(0), + DeviceToLogicalXRel(0x800000 - 64), DeviceToLogicalYRel(0x800000 - 64)); + #else + double x, y, w, h; + m_graphicContext->GetClipBox(&x, &y, &w, &h); + m_graphicContext->DrawRectangle(x, y, w, h); + #endif // __WXOSX__ / !__WXOSX__ + m_graphicContext->SetCompositionMode(formerMode); + m_graphicContext->SetPen( m_pen ); + m_graphicContext->SetBrush( m_brush ); + } + else + { #ifdef __WXOSX__ - // This is a legacy implementation which doesn't take advantage - // of clipping region bounds retrieved by wxMacCoreGraphicsContext::GetClipBox - // because this function is not yet verified. - // Note: Legacy implmentation might not work work properly - // if graphics context is rotated - // TODO: Do the tests of wxMacCoreGraphicsContext::GetClipBox - // and switch to the implmenentation used by other renderers (code below). - // - // maximum positive coordinate Cairo can handle is 2^23 - 1 - // Use a value slightly less than this to be sure we avoid the limit - DoDrawRectangle( - DeviceToLogicalX(0), DeviceToLogicalY(0), - DeviceToLogicalXRel(0x800000 - 64), DeviceToLogicalYRel(0x800000 - 64)); + // same comment as above applies + m_graphicContext->ClearRectangle(DeviceToLogicalX(0), DeviceToLogicalY(0), + DeviceToLogicalXRel(0x8000 - 64), DeviceToLogicalYRel(0x8000 - 64)); #else - double x, y, w, h; - m_graphicContext->GetClipBox(&x, &y, &w, &h); - m_graphicContext->DrawRectangle(x, y, w, h); -#endif // __WXOSX__ / !__WXOSX__ - m_graphicContext->SetCompositionMode(formerMode); - m_graphicContext->SetPen( m_pen ); - m_graphicContext->SetBrush( m_brush ); + double x, y, w, h; + m_graphicContext->GetClipBox(&x, &y, &w, &h); + m_graphicContext->ClearRectangle(x, y, w, h); +#endif + } } void wxGCDCImpl::DoGetSize(int *width, int *height) const diff --git a/src/common/graphcmn.cpp b/src/common/graphcmn.cpp index bdf0597149..979e4423e6 100644 --- a/src/common/graphcmn.cpp +++ b/src/common/graphcmn.cpp @@ -759,6 +759,11 @@ void wxGraphicsContext::DrawRectangle( wxDouble x, wxDouble y, wxDouble w, wxDou DrawPath( path ); } +void wxGraphicsContext::ClearRectangle( wxDouble WXUNUSED(x), wxDouble WXUNUSED(y), wxDouble WXUNUSED(w), wxDouble WXUNUSED(h)) +{ + +} + void wxGraphicsContext::DrawEllipse( wxDouble x, wxDouble y, wxDouble w, wxDouble h) { wxGraphicsPath path = CreatePath(); diff --git a/src/generic/graphicc.cpp b/src/generic/graphicc.cpp index e5583801ce..b52f2bc768 100644 --- a/src/generic/graphicc.cpp +++ b/src/generic/graphicc.cpp @@ -98,7 +98,6 @@ using namespace std; #ifdef __WXMAC__ #include "wx/osx/private.h" #include -#include #endif // Helper functions for dealing with alpha pre-multiplication. @@ -476,7 +475,8 @@ public: virtual void StrokePath( const wxGraphicsPath& p ) wxOVERRIDE; virtual void FillPath( const wxGraphicsPath& p , wxPolygonFillMode fillStyle = wxWINDING_RULE ) wxOVERRIDE; - + virtual void ClearRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) wxOVERRIDE; + virtual void Translate( wxDouble dx , wxDouble dy ) wxOVERRIDE; virtual void Scale( wxDouble xScale , wxDouble yScale ) wxOVERRIDE; virtual void Rotate( wxDouble angle ) wxOVERRIDE; @@ -2440,6 +2440,15 @@ void wxCairoContext::FillPath( const wxGraphicsPath& path , wxPolygonFillMode fi } } +void wxCairoContext::ClearRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) +{ + cairo_save(m_context); + cairo_set_operator(m_context, CAIRO_OPERATOR_CLEAR); + cairo_rectangle (m_context, x, y, w, h); + cairo_fill (m_context); + cairo_restore(m_context); +} + void wxCairoContext::Rotate( wxDouble angle ) { cairo_rotate(m_context,angle); diff --git a/src/osx/carbon/graphics.cpp b/src/osx/carbon/graphics.cpp index ea9ed092ef..7f71a30ea0 100644 --- a/src/osx/carbon/graphics.cpp +++ b/src/osx/carbon/graphics.cpp @@ -1337,7 +1337,10 @@ public: // draws a path by first filling and then stroking virtual void DrawPath( const wxGraphicsPath &path, wxPolygonFillMode fillStyle = wxODDEVEN_RULE ) wxOVERRIDE; - + + // paints a transparent rectangle (only useful for bitmaps or windows) + virtual void ClearRectangle(wxDouble x, wxDouble y, wxDouble w, wxDouble h) wxOVERRIDE; + virtual bool ShouldOffset() const wxOVERRIDE { if ( !m_enableOffset ) @@ -2348,6 +2351,14 @@ void * wxMacCoreGraphicsContext::GetNativeContext() return m_cgContext; } +void wxMacCoreGraphicsContext::ClearRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) +{ + if (!EnsureIsValid()) + return; + + CGRect rect = CGRectMake( (CGFloat) x , (CGFloat) y , (CGFloat) w , (CGFloat) h ); + CGContextClearRect(m_cgContext, rect); +} void wxMacCoreGraphicsContext::DrawRectangle( wxDouble x, wxDouble y, wxDouble w, wxDouble h ) {