diff --git a/interface/wx/dc.h b/interface/wx/dc.h index 40e37cb34a..e7c94b31e9 100644 --- a/interface/wx/dc.h +++ b/interface/wx/dc.h @@ -261,6 +261,9 @@ public: Note that SetBackground() method must be used to set the brush used by Clear(), the brush used for filling the shapes set by SetBrush() is ignored by it. + + If no background brush was set, solid white brush is used to clear the + device context. */ void Clear(); diff --git a/src/common/dcgraph.cpp b/src/common/dcgraph.cpp index 6473675e8b..7630da8859 100644 --- a/src/common/dcgraph.cpp +++ b/src/common/dcgraph.cpp @@ -543,8 +543,6 @@ void wxGCDCImpl::SetBrush( const wxBrush &brush ) void wxGCDCImpl::SetBackground( const wxBrush &brush ) { m_backgroundBrush = brush; - if (!m_backgroundBrush.IsOk()) - return; } void wxGCDCImpl::SetLogicalFunction( wxRasterOperationMode function ) @@ -1286,28 +1284,23 @@ void wxGCDCImpl::Clear() { wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::Clear - invalid DC") ); - 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); + if ( m_backgroundBrush.IsTransparent() ) + return; - double x, y, w, h; - m_graphicContext->GetClipBox(&x, &y, &w, &h); - m_graphicContext->DrawRectangle(x, y, w, h); + m_graphicContext->SetBrush( m_backgroundBrush.IsOk() ? m_backgroundBrush + : *wxWHITE_BRUSH ); + wxPen p = *wxTRANSPARENT_PEN; + m_graphicContext->SetPen( p ); + wxCompositionMode formerMode = m_graphicContext->GetCompositionMode(); + m_graphicContext->SetCompositionMode(wxCOMPOSITION_SOURCE); - m_graphicContext->SetCompositionMode(formerMode); - m_graphicContext->SetPen( m_pen ); - m_graphicContext->SetBrush( m_brush ); - } - else - { - double x, y, w, h; - m_graphicContext->GetClipBox(&x, &y, &w, &h); - m_graphicContext->ClearRectangle(x, y, w, h); - } + double x, y, w, h; + m_graphicContext->GetClipBox(&x, &y, &w, &h); + m_graphicContext->DrawRectangle(x, y, w, h); + + m_graphicContext->SetCompositionMode(formerMode); + m_graphicContext->SetPen( m_pen ); + m_graphicContext->SetBrush( m_brush ); } void wxGCDCImpl::DoGetSize(int *width, int *height) const diff --git a/src/common/prntbase.cpp b/src/common/prntbase.cpp index 3ee6ee2144..dd52c006d8 100644 --- a/src/common/prntbase.cpp +++ b/src/common/prntbase.cpp @@ -2054,7 +2054,6 @@ bool wxPrintPreviewBase::RenderPageIntoBitmap(wxBitmap& bmp, int pageNum) { wxMemoryDC memoryDC; memoryDC.SelectObject(bmp); - memoryDC.SetBackground(*wxWHITE_BRUSH); memoryDC.Clear(); return RenderPageIntoDC(memoryDC, pageNum); diff --git a/src/gtk/dcclient.cpp b/src/gtk/dcclient.cpp index c4ec6109cf..de7fef4706 100644 --- a/src/gtk/dcclient.cpp +++ b/src/gtk/dcclient.cpp @@ -1508,7 +1508,7 @@ void wxWindowDCImpl::Clear() if (!m_gdkwindow) return; - if (!m_backgroundBrush.IsOk() || m_backgroundBrush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT) + if (m_backgroundBrush.IsTransparent()) return; int width,height; @@ -1738,7 +1738,8 @@ void wxWindowDCImpl::SetBackground( const wxBrush &brush ) m_backgroundBrush = brush; - if (!m_backgroundBrush.IsOk()) return; + if (!m_backgroundBrush.IsOk()) + m_backgroundBrush = *wxWHITE_BRUSH; if (!m_gdkwindow) return; diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 9652af4ccf..5260a7085e 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -729,8 +729,23 @@ void wxMSWDCImpl::Clear() return; } + HBRUSH hbr; if ( !m_backgroundBrush.IsOk() ) + { + // By default, use the stock white brush for compatibility with the + // previous wx versions. + hbr = WHITE_BRUSH; + } + else if ( !m_backgroundBrush.IsTransparent() ) + { + hbr = GetHbrushOf(m_backgroundBrush); + } + else // Using transparent background brush. + { + // Clearing with transparent brush doesn't do anything, just as drawing + // with transparent pen doesn't. return; + } RECT rect; ::GetClipBox(GetHdc(), &rect); @@ -738,7 +753,7 @@ void wxMSWDCImpl::Clear() // to compensate rounding errors if DC is the subject // of complex transformation (is e.g. rotated). ::InflateRect(&rect, 1, 1); - ::FillRect(GetHdc(), &rect, GetHbrushOf(m_backgroundBrush)); + ::FillRect(GetHdc(), &rect, hbr); RealizeScaleAndOrigin(); } diff --git a/tests/graphics/bitmap.cpp b/tests/graphics/bitmap.cpp index 0fbad0442c..0032007844 100644 --- a/tests/graphics/bitmap.cpp +++ b/tests/graphics/bitmap.cpp @@ -25,6 +25,8 @@ #include "wx/graphics.h" #endif // wxUSE_GRAPHICS_CONTEXT +#include "testimage.h" + #define ASSERT_EQUAL_RGB(c, r, g, b) \ CHECK( (int)r == (int)c.Red() ); \ CHECK( (int)g == (int)c.Green() ); \ @@ -915,4 +917,118 @@ TEST_CASE("BitmapTestCase::SubBitmapAlphaWithMask", "[bitmap][subbitmap][alpha][ ASSERT_EQUAL_RGB(p, maskClrBottomRight.Red(), maskClrBottomRight.Green(), maskClrBottomRight.Blue()); } } + +namespace Catch +{ + template <> + struct StringMaker + { + static std::string convert(const wxBitmap& bmp) + { + return wxString::Format("bitmap of size %d*%d", + bmp.GetWidth(), + bmp.GetHeight()).ToStdString(); + } + }; +} + +class BitmapColourMatcher : public Catch::MatcherBase +{ +public: + explicit BitmapColourMatcher(const wxColour& col) + : m_col(col) + { + } + + bool match(const wxBitmap& bmp) const wxOVERRIDE + { + const wxImage img(bmp.ConvertToImage()); + + const unsigned char* data = img.GetData(); + for ( int y = 0; y < img.GetHeight(); ++y ) + { + for ( int x = 0; x < img.GetWidth(); ++x, data += 3 ) + { + if ( wxColour(data[0], data[1], data[2]) != m_col ) + return false; + } + } + + return true; + } + + std::string describe() const wxOVERRIDE + { + return wxString::Format("doesn't have all %s pixels", + m_col.GetAsString()).ToStdString(); + } + +private: + const wxColour m_col; +}; + +inline BitmapColourMatcher AllPixelsAre(const wxColour& col) +{ + return BitmapColourMatcher(col); +} + +TEST_CASE("DC::Clear", "[bitmap][dc]") +{ + // Just some arbitrary pixel data. + static unsigned char data[] = + { + 0xff, 0, 0, + 0, 0xff, 0, + 0, 0, 0xff, + 0x7f, 0, 0x7f + }; + + const wxImage img(2, 2, data, true /* don't take ownership of data */); + + wxBitmap bmp(img); + + SECTION("Clearing uses white by default") + { + { + wxMemoryDC dc(bmp); + dc.Clear(); + } + + CHECK_THAT(bmp, AllPixelsAre(*wxWHITE)); + } + + SECTION("Clearing with specified brush works as expected") + { + { + wxMemoryDC dc(bmp); + dc.SetBackground(*wxRED_BRUSH); + dc.Clear(); + } + CHECK_THAT(bmp, AllPixelsAre(*wxRED)); + } + + SECTION("Clearing with transparent brush does nothing") + { + { + wxMemoryDC dc(bmp); + dc.SetBackground(*wxTRANSPARENT_BRUSH); + dc.Clear(); + } + + CHECK_THAT(bmp.ConvertToImage(), RGBSameAs(img)); + } + + SECTION("Clearing with invalid brush uses white too") + { + { + wxMemoryDC dc(bmp); + dc.SetBackground(*wxBLACK_BRUSH); + dc.SetBackground(wxBrush()); + dc.Clear(); + } + + CHECK_THAT(bmp, AllPixelsAre(*wxWHITE)); + } +} + #endif //wxHAS_RAW_BITMAP