diff --git a/interface/wx/dc.h b/interface/wx/dc.h index ab7660a200..82aa64a36e 100644 --- a/interface/wx/dc.h +++ b/interface/wx/dc.h @@ -767,13 +767,15 @@ public: uses for the clipping region are for clipping text or for speeding up window redraws when only a known area of the screen is damaged. - Notice that you need to call DestroyClippingRegion() if you want to set + @remarks + - Calling GetClippingBox() can only make the clipping region smaller, + never larger. + + - You need to call DestroyClippingRegion() if you want to set the clipping region exactly to the region specified. - Also note that if the clipping region is empty, any previously set - clipping region is destroyed, i.e. it is equivalent to calling - DestroyClippingRegion(), and not to clipping out all drawing on the DC - as might be expected. + - If resulting clipping region is empty, then all drawing on the DC is + clipped out (all changes made by drawing operations are masked out). @see DestroyClippingRegion(), wxRegion */ diff --git a/src/common/dcbase.cpp b/src/common/dcbase.cpp index 63337d7ced..d298ad300c 100644 --- a/src/common/dcbase.cpp +++ b/src/common/dcbase.cpp @@ -368,21 +368,41 @@ wxDCImpl::~wxDCImpl() void wxDCImpl::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h) { + wxASSERT_MSG( w >= 0 && h >= 0, + wxS("Clipping box size values cannot be negative") ); + + wxRect newRegion(x, y, w, h); + + wxRect clipRegion; if ( m_clipping ) { - m_clipX1 = wxMax( m_clipX1, x ); - m_clipY1 = wxMax( m_clipY1, y ); - m_clipX2 = wxMin( m_clipX2, (x + w) ); - m_clipY2 = wxMin( m_clipY2, (y + h) ); + // New clipping box is an intersection + // of required clipping box and the current one. + wxRect curRegion(m_clipX1, m_clipY1, m_clipX2 - m_clipX1, m_clipY2 - m_clipY1); + clipRegion = curRegion.Intersect(newRegion); } else { - m_clipping = true; + // Effective clipping box is an intersection + // of required clipping box and DC surface. + int dcWidth, dcHeight; + DoGetSize(&dcWidth, &dcHeight); + wxRect dcRect(wxSize(dcWidth, dcHeight)); + clipRegion = dcRect.Intersect(newRegion); - m_clipX1 = x; - m_clipY1 = y; - m_clipX2 = x + w; - m_clipY2 = y + h; + m_clipping = true; + } + + if ( clipRegion.IsEmpty() ) + { + m_clipX1 = m_clipY1 = m_clipX2 = m_clipY2 = 0; + } + else + { + m_clipX1 = clipRegion.GetLeftTop().x; + m_clipY1 = clipRegion.GetLeftTop().y; + m_clipX2 = clipRegion.GetBottomRight().x + 1; + m_clipY2 = clipRegion.GetBottomRight().y + 1; } }