From 4e4317e71d41dc0d2d84edca1b9343bef71612fc Mon Sep 17 00:00:00 2001 From: Artur Wieczorek Date: Fri, 15 Jul 2016 21:00:49 +0200 Subject: [PATCH] Fixed setting clipping region for wxGCDC using device coordinates. Because source wxRegion contains regions given in device coordinates and underlying wxGraphicsContext::Clip() function expects regions in logical coordinates so we have to convert device coordinates of all region components to source coordinates prior to calling this function. Effective clipping box (always calculated in logical units) is the result of intersection of clipping box of the provided region with either clipping box of previously set clipping region (if set) or with wxGCDC surface extents if no clipping region is set. This way effective clipping box is always inside the wxGCDC surface. Note: Effective clipping box can be an empty region. See #17596 --- src/common/dcgraph.cpp | 75 +++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/src/common/dcgraph.cpp b/src/common/dcgraph.cpp index d42a4f4659..2ae0e6b178 100644 --- a/src/common/dcgraph.cpp +++ b/src/common/dcgraph.cpp @@ -303,34 +303,63 @@ void wxGCDCImpl::DoSetDeviceClippingRegion( const wxRegion ®ion ) // region is in device coordinates wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoSetDeviceClippingRegion - invalid DC") ); - if (region.Empty()) + // Convert device coordinates to logical coordinates + // for all region components. + wxRegion logRegion; + if ( region.IsEmpty() ) { - //DestroyClippingRegion(); - return; - } - - wxRegion logRegion( region ); - wxCoord x, y, w, h; - - 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 ); - m_clipY1 = wxMax( m_clipY1, y ); - m_clipX2 = wxMin( m_clipX2, (x + w) ); - m_clipY2 = wxMin( m_clipY2, (y + h) ); + // Empty region is skipped by iterator + // so we have to copy it directly. + logRegion = region; } else { - m_clipping = true; + wxRegionIterator ri(region); + while (ri) + { + logRegion.Union(DeviceToLogicalX(ri.GetX()), + DeviceToLogicalY(ri.GetY()), + DeviceToLogicalXRel(ri.GetWidth()), + DeviceToLogicalYRel(ri.GetHeight())); + ++ri; + } + } - m_clipX1 = x; - m_clipY1 = y; - m_clipX2 = x + w; - m_clipY2 = y + h; + m_graphicContext->Clip(logRegion); + + wxRect newRegion = logRegion.GetBox(); + + wxRect clipRegion; + if ( m_clipping ) + { + // 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 + { + // Effective clipping box is an intersection + // of required clipping box and DC surface. + int dcWidth, dcHeight; + DoGetSize(&dcWidth, &dcHeight); + wxRect dcRect(DeviceToLogicalX(0), DeviceToLogicalY(0), + DeviceToLogicalXRel(dcWidth), DeviceToLogicalYRel(dcHeight)); + clipRegion = dcRect.Intersect(newRegion); + + m_clipping = true; + } + + if ( clipRegion.IsEmpty() ) + { + m_clipX1 = m_clipY1 = m_clipX2 = m_clipY2 = 0; + } + else + { + m_clipX1 = clipRegion.GetLeft(); + m_clipY1 = clipRegion.GetTop(); + m_clipX2 = clipRegion.GetRight() + 1; + m_clipY2 = clipRegion.GetBottom() + 1; } }