Fix retrieving clipping box after changing wxDC coordinates (MSW)

Member data containing clipping box have to be updated not only when the clipping region is explicitly changed by SetClippingRegion()/DestroyClippingRegion() but also when existing HDC is associated with wxDC using SetHDC() or when wxDC coordinates are transformed with SetDeviceOrigin(), SetLogicalOrigin(), SetUserScale(), SetLogicalScale(), SetTransformMatrix() or ResetTransformMatrix().
When any of these functions is called then clipping box data are marked as invalid and updated using GetClipBox() Win API at nearest call to GetClippingBox().

See #17646.
This commit is contained in:
Artur Wieczorek 2016-09-01 20:48:26 +02:00
parent a37ed9a2b5
commit dfc966bf1e
3 changed files with 27 additions and 6 deletions

View File

@ -124,6 +124,7 @@ wxMSW:
- Restore dispatching wxThreadEvent while resizing the window broken in 3.1.0.
- Fix wxGraphicsMatrix::TransformDistance for Direct2D renderer.
- Fix wxDC::Clear() for rotated DC.
- Fix wxDC::GetClippingBox() for transformed wxDC.
wxOSX:

View File

@ -121,8 +121,7 @@ public:
// return it if asked -- but avoid calling ::GetClipBox() right now as
// it could be unnecessary wasteful
m_clipping = true;
m_clipX1 =
m_clipX2 = 0;
m_isClipBoxValid = false;
}
void* GetHandle() const { return (void*)GetHDC(); }
@ -164,6 +163,7 @@ protected:
#if wxUSE_PALETTE
m_oldPalette = NULL;
#endif // wxUSE_PALETTE
m_isClipBoxValid = false;
}
// create an uninitialized DC: this should be only used by the derived
@ -323,6 +323,8 @@ protected:
static wxObjectList sm_dcCache;
#endif
bool m_isClipBoxValid;
wxDECLARE_CLASS(wxMSWDCImpl);
wxDECLARE_NO_COPY_CLASS(wxMSWDCImpl);
};

View File

@ -579,21 +579,32 @@ void wxMSWDCImpl::UpdateClipBox()
m_clipY1 = (wxCoord) YDEV2LOG(rect.top);
m_clipX2 = (wxCoord) XDEV2LOG(rect.right);
m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom);
m_isClipBoxValid = true;
}
void
wxMSWDCImpl::DoGetClippingBox(wxCoord *x, wxCoord *y, wxCoord *w, wxCoord *h) const
{
// check if we should try to retrieve the clipping region possibly not set
// by our SetClippingRegion() but preset by Windows:this can only happen
// when we're associated with an existing HDC usign SetHDC(), see there
if ( m_clipping && !m_clipX1 && !m_clipX2 )
// by our SetClippingRegion() but preset or modified by Windows: this
// can happen when we're associated with an existing HDC using SetHDC() or
// when wxDC logical coordinates are transformed with SetDeviceOrigin(),
// SetLogicalOrigin(), SetUserScale(), SetLogicalScale(),
// SetTransformMatrix(), ResetTransformMatrix().
if ( !m_isClipBoxValid )
{
wxMSWDCImpl *self = wxConstCast(this, wxMSWDCImpl);
self->UpdateClipBox();
}
wxDCImpl::DoGetClippingBox(x, y, w, h);
if ( x )
*x = m_clipX1;
if ( y )
*y = m_clipY1;
if ( w )
*w = m_clipX2 - m_clipX1;
if ( h )
*h = m_clipY2 - m_clipY1;
}
// common part of DoSetClippingRegion() and DoSetDeviceClippingRegion()
@ -679,6 +690,7 @@ void wxMSWDCImpl::DestroyClippingRegion()
}
wxDCImpl::DestroyClippingRegion();
m_isClipBoxValid = false;
}
// ---------------------------------------------------------------------------
@ -1868,6 +1880,8 @@ void wxMSWDCImpl::RealizeScaleAndOrigin()
::SetViewportOrgEx(GetHdc(), m_deviceOriginX, m_deviceOriginY, NULL);
::SetWindowOrgEx(GetHdc(), m_logicalOriginX, m_logicalOriginY, NULL);
m_isClipBoxValid = false;
}
void wxMSWDCImpl::SetMapMode(wxMappingMode mode)
@ -1977,6 +1991,8 @@ void wxMSWDCImpl::SetDeviceOrigin(wxCoord x, wxCoord y)
wxDCImpl::SetDeviceOrigin( x, y );
::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
m_isClipBoxValid = false;
}
// ----------------------------------------------------------------------------
@ -2022,6 +2038,7 @@ bool wxMSWDCImpl::SetTransformMatrix(const wxAffineMatrix2D &matrix)
return false;
}
m_isClipBoxValid = false;
return true;
}
@ -2047,6 +2064,7 @@ void wxMSWDCImpl::ResetTransformMatrix()
{
::ModifyWorldTransform(GetHdc(), NULL, MWT_IDENTITY);
::SetGraphicsMode(GetHdc(), GM_COMPATIBLE);
m_isClipBoxValid = false;
}
#endif // wxUSE_DC_TRANSFORM_MATRIX