diff --git a/include/wx/qt/dc.h b/include/wx/qt/dc.h index 43bd13e070..d1c632f714 100644 --- a/include/wx/qt/dc.h +++ b/include/wx/qt/dc.h @@ -116,7 +116,7 @@ protected: QPainter *m_qtPainter; QPixmap *m_qtPixmap; - wxRegion *m_clippingRegion; + wxRegion m_clippingRegion; private: enum wxQtRasterColourOp { diff --git a/include/wx/qt/region.h b/include/wx/qt/region.h index 7bb2a56d68..d49ad45964 100644 --- a/include/wx/qt/region.h +++ b/include/wx/qt/region.h @@ -48,6 +48,8 @@ protected: virtual bool DoSubtract(const wxRegion& region); virtual bool DoXor(const wxRegion& region); + virtual bool DoCombine(const wxRegion& rgn, wxRegionOp op); + private: wxDECLARE_DYNAMIC_CLASS(wxRegion); }; diff --git a/src/qt/dc.cpp b/src/qt/dc.cpp index 073a10d755..dfde8af7d1 100644 --- a/src/qt/dc.cpp +++ b/src/qt/dc.cpp @@ -48,7 +48,6 @@ wxIMPLEMENT_CLASS(wxQtDCImpl,wxDCImpl); wxQtDCImpl::wxQtDCImpl( wxDC *owner ) : wxDCImpl( owner ) { - m_clippingRegion = new wxRegion; m_qtPixmap = NULL; m_rasterColourOp = wxQtNONE; m_qtPenColor = new QColor; @@ -67,7 +66,6 @@ wxQtDCImpl::~wxQtDCImpl() delete m_qtPainter; } - delete m_clippingRegion; delete m_qtPenColor; delete m_qtBrushColor; } @@ -87,7 +85,7 @@ void wxQtDCImpl::QtPreparePainter( ) if (m_clipping) { - wxRegionIterator ri(*m_clippingRegion); + wxRegionIterator ri(m_clippingRegion); bool append = false; while (ri.HaveRects()) { @@ -416,6 +414,17 @@ void wxQtDCImpl::DoSetClippingRegion(wxCoord x, wxCoord y, } else { + if ( width < 0 ) + { + width = -width; + x -= width - 1; + } + if ( height < 0 ) + { + height = -height; + y -= height - 1; + } + if (m_qtPainter->isActive()) { // Set QPainter clipping (intersection if not the first one) @@ -426,17 +435,21 @@ void wxQtDCImpl::DoSetClippingRegion(wxCoord x, wxCoord y, // Set internal state for getters /* Note: Qt states that QPainter::clipRegion() may be slow, so we * keep the region manually, which should be faster */ - if ( m_clipping ) - m_clippingRegion->Union( wxRect( x, y, width, height ) ); - else - m_clippingRegion->Intersect( wxRect( x, y, width, height ) ); + if ( !m_clipping || m_clippingRegion.IsEmpty() ) + { + int dcwidth, dcheight; + DoGetSize(&dcwidth, &dcheight); - wxRect clipRect = m_clippingRegion->GetBox(); + m_clippingRegion = wxRegion(0, 0, dcwidth, dcheight); + } + m_clippingRegion.Intersect( wxRect(x, y, width, height) ); + + wxRect clipRect = m_clippingRegion.GetBox(); m_clipX1 = clipRect.GetLeft(); - m_clipX2 = clipRect.GetRight(); + m_clipX2 = clipRect.GetRight() + 1; m_clipY1 = clipRect.GetTop(); - m_clipY2 = clipRect.GetBottom(); + m_clipY2 = clipRect.GetBottom() + 1; m_clipping = true; } } @@ -465,16 +478,16 @@ void wxQtDCImpl::DoSetDeviceClippingRegion(const wxRegion& region) /* Note: Qt states that QPainter::clipRegion() may be slow, so we * keep the region manually, which should be faster */ if ( m_clipping ) - m_clippingRegion->Union( region ); + m_clippingRegion.Union( region ); else - m_clippingRegion->Intersect( region ); + m_clippingRegion.Intersect( region ); - wxRect clipRect = m_clippingRegion->GetBox(); + wxRect clipRect = m_clippingRegion.GetBox(); m_clipX1 = clipRect.GetLeft(); - m_clipX2 = clipRect.GetRight(); + m_clipX2 = clipRect.GetRight() + 1; m_clipY1 = clipRect.GetTop(); - m_clipY2 = clipRect.GetBottom(); + m_clipY2 = clipRect.GetBottom() + 1; m_clipping = true; } } @@ -482,7 +495,7 @@ void wxQtDCImpl::DoSetDeviceClippingRegion(const wxRegion& region) void wxQtDCImpl::DestroyClippingRegion() { wxDCImpl::DestroyClippingRegion(); - m_clippingRegion->Clear(); + m_clippingRegion.Clear(); if (m_qtPainter->isActive()) m_qtPainter->setClipping( false ); diff --git a/src/qt/region.cpp b/src/qt/region.cpp index a0c3ea8698..44672de82b 100644 --- a/src/qt/region.cpp +++ b/src/qt/region.cpp @@ -20,35 +20,35 @@ class wxRegionRefData: public wxGDIRefData { - public: - wxRegionRefData() - { - } +public: + wxRegionRefData() + { + } - wxRegionRefData( QRect r ) : m_qtRegion( r ) - { - } + wxRegionRefData( QRect r ) : m_qtRegion( r ) + { + } - wxRegionRefData( QBitmap b ) : m_qtRegion ( b ) - { - } + wxRegionRefData( QBitmap b ) : m_qtRegion ( b ) + { + } - wxRegionRefData( QPolygon p, Qt::FillRule fr ) : m_qtRegion( p, fr ) - { - } + wxRegionRefData( QPolygon p, Qt::FillRule fr ) : m_qtRegion( p, fr ) + { + } - wxRegionRefData( const wxRegionRefData& data ) + wxRegionRefData( const wxRegionRefData& data ) : wxGDIRefData() - { - m_qtRegion = data.m_qtRegion; - } - - bool operator == (const wxRegionRefData& data) const - { - return m_qtRegion == data.m_qtRegion; - } - - QRegion m_qtRegion; + { + m_qtRegion = data.m_qtRegion; + } + + bool operator == (const wxRegionRefData& data) const + { + return m_qtRegion == data.m_qtRegion; + } + + QRegion m_qtRegion; }; #define M_REGIONDATA ((wxRegionRefData *)m_refData)->m_qtRegion @@ -57,7 +57,7 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxRegion,wxGDIObject); wxRegion::wxRegion() { - m_refData = new wxRegionRefData(); + m_refData = NULL; } wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h) @@ -113,16 +113,16 @@ wxRegion::wxRegion(const wxBitmap& bmp, const wxColour& transp, int tolerance) memset(raw.get(), 0, bmp.GetWidth()*bmp.GetHeight()); QImage img(bmp.GetHandle()->toImage()); - int r = transp.Red(), g = transp.Green(), b = transp.Blue(); - for(int y=0; y tolerance || abs(c.green() - g) > tolerance || abs(c.blue() - b) > tolerance) { - int ind = y*img.width()+x; + const int ind = y*img.width()+x; raw[ind>>3] |= 1<<(ind&7); } } @@ -133,14 +133,20 @@ wxRegion::wxRegion(const wxBitmap& bmp, const wxColour& transp, int tolerance) bool wxRegion::IsEmpty() const { - wxCHECK_MSG( IsOk(), true, "Invalid region" ); + if ( IsNull() ) + return true; + + wxCHECK_MSG(IsOk(), true, "Invalid region" ); return M_REGIONDATA.isEmpty(); } void wxRegion::Clear() { - wxCHECK_RET( IsOk(), "Invalid region" ); + if ( IsNull() ) + return; + + wxCHECK_RET(IsOk(), "Invalid region" ); AllocExclusive(); M_REGIONDATA = QRegion(); @@ -148,6 +154,7 @@ void wxRegion::Clear() void wxRegion::QtSetRegion(QRegion region) { + AllocExclusive(); M_REGIONDATA = region; } @@ -171,9 +178,18 @@ bool wxRegion::DoIsEqual(const wxRegion& region) const bool wxRegion::DoGetBox(wxCoord& x, wxCoord& y, wxCoord& w, wxCoord& h) const { + if ( m_refData == NULL ) + { + x = + y = + w = + h = 0; + return false; + } + wxCHECK_MSG( IsOk(), false, "Invalid region" ); - QRect bounding = M_REGIONDATA.boundingRect(); + const QRect bounding = M_REGIONDATA.boundingRect(); x = bounding.x(); y = bounding.y(); w = bounding.width(); @@ -204,47 +220,98 @@ bool wxRegion::DoOffset(wxCoord x, wxCoord y) return true; } -bool wxRegion::DoUnionWithRect(const wxRect& rect) +// combine another region with this one +bool wxRegion::DoCombine(const wxRegion& region, wxRegionOp op) { - wxCHECK_MSG( IsOk(), false, "Invalid region" ); + // we can't use the API functions if we don't have a valid region + if ( !m_refData ) + { + // combining with an empty/invalid region works differently depending + // on the operation + switch ( op ) + { + case wxRGN_COPY: + case wxRGN_OR: + case wxRGN_XOR: + *this = region; + break; - M_REGIONDATA = M_REGIONDATA.united( wxQtConvertRect( rect ) ); + default: + wxFAIL_MSG(wxT("unknown region operation")); + wxFALLTHROUGH; + + case wxRGN_AND: + case wxRGN_DIFF: + // leave empty/invalid + return false; + } + } + else // we have a valid region + { + AllocExclusive(); + + switch ( op ) + { + case wxRGN_AND: + M_REGIONDATA = M_REGIONDATA.intersected(region.GetHandle()); + break; + + case wxRGN_OR: + M_REGIONDATA = M_REGIONDATA.united(region.GetHandle()); + break; + + case wxRGN_XOR: + M_REGIONDATA = M_REGIONDATA.xored(region.GetHandle()); + break; + + case wxRGN_DIFF: + M_REGIONDATA = M_REGIONDATA.subtracted(region.GetHandle()); + break; + + default: + wxFAIL_MSG(wxT("unknown region operation")); + wxFALLTHROUGH; + + case wxRGN_COPY: + M_REGIONDATA = QRegion(region.GetHandle()); + break; + } + } return true; } bool wxRegion::DoUnionWithRegion(const wxRegion& region) { - wxCHECK_MSG( IsOk(), false, "Invalid region" ); - wxCHECK_MSG( region.IsOk(), false, "Invalid parameter region" ); - - M_REGIONDATA = M_REGIONDATA.united( region.GetHandle() ); - return true; + return DoCombine(region, wxRGN_OR); } bool wxRegion::DoIntersect(const wxRegion& region) { - wxCHECK_MSG( IsOk(), false, "Invalid region" ); - wxCHECK_MSG( region.IsOk(), false, "Invalid parameter region" ); - - M_REGIONDATA = M_REGIONDATA.intersected( region.GetHandle() ); - return true; + return DoCombine(region, wxRGN_AND); } bool wxRegion::DoSubtract(const wxRegion& region) { - wxCHECK_MSG( IsOk(), false, "Invalid region" ); - wxCHECK_MSG( region.IsOk(), false, "Invalid parameter region" ); - - M_REGIONDATA = M_REGIONDATA.subtracted( region.GetHandle() ); - return true; + return DoCombine(region, wxRGN_DIFF); } bool wxRegion::DoXor(const wxRegion& region) { + return DoCombine(region, wxRGN_XOR); +} + +bool wxRegion::DoUnionWithRect(const wxRect& rect) +{ + if ( m_refData == NULL ) + { + m_refData = new wxRegionRefData(wxQtConvertRect(rect)); + return true; + } + wxCHECK_MSG( IsOk(), false, "Invalid region" ); - wxCHECK_MSG( region.IsOk(), false, "Invalid parameter region" ); - - M_REGIONDATA = M_REGIONDATA.xored( region.GetHandle() ); + + AllocExclusive(); + M_REGIONDATA = M_REGIONDATA.united( wxQtConvertRect( rect ) ); return true; } @@ -279,14 +346,12 @@ wxRegionIterator::wxRegionIterator(const wxRegionIterator& ri) wxRegionIterator::~wxRegionIterator() { - if ( m_qtRects != NULL ) - delete m_qtRects; + delete m_qtRects; } wxRegionIterator& wxRegionIterator::operator=(const wxRegionIterator& ri) { - if ( m_qtRects != NULL ) - delete m_qtRects; + delete m_qtRects; m_qtRects = new QVector< QRect >( *ri.m_qtRects ); m_pos = ri.m_pos; @@ -300,8 +365,7 @@ void wxRegionIterator::Reset() void wxRegionIterator::Reset(const wxRegion& region) { - if ( m_qtRects != NULL ) - delete m_qtRects; + delete m_qtRects; m_qtRects = new QVector< QRect >( region.GetHandle().rects() ); m_pos = 0;