Fix setting wxGCDC clipping region with device coordinates
Currently region given in device coordinates is decomposed into the stripes which are next transformed to the logical coordinates required by underlying wxGraphicsContext::Clip() function. Some of these stripes given in device coordinates can have 1-pixel height what after transformation to logical coordinates can give zero-height stripes (after rounding). This can lead to the situation that in the region transformed to logical coordinates some stripes can disappear and final transformed region shape is different from the source shape (it has gaps). To fix this issue device coordinates of the region are not manually transformed to the logical coordinates but instead wxGraphicsContext's is temporarily set to the state where its logical coordinates are equivalent to device coordinates and thus clipping region can be applied directly. Closes #17609
This commit is contained in:
@@ -303,31 +303,34 @@ void wxGCDCImpl::DoSetDeviceClippingRegion( const wxRegion ®ion )
|
|||||||
// region is in device coordinates
|
// region is in device coordinates
|
||||||
wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoSetDeviceClippingRegion - invalid DC") );
|
wxCHECK_RET( IsOk(), wxT("wxGCDC(cg)::DoSetDeviceClippingRegion - invalid DC") );
|
||||||
|
|
||||||
// Convert device coordinates to logical coordinates
|
// Because graphics context works with logical coordinates
|
||||||
// for all region components.
|
// and clipping region is given in device coordinates
|
||||||
wxRegion logRegion;
|
// we need temporarily reset graphics context's coordinate system
|
||||||
if ( region.IsEmpty() )
|
// to the initial state in which logical and device coordinate
|
||||||
{
|
// systems are equivalent.
|
||||||
// Empty region is skipped by iterator
|
// So, at first save current transformation parameters.
|
||||||
// so we have to copy it directly.
|
wxGraphicsMatrix currTransform = m_graphicContext->CreateMatrix();
|
||||||
logRegion = region;
|
currTransform = m_graphicContext->GetTransform();
|
||||||
}
|
// Reset coordinate system with identity transformation matrix
|
||||||
else
|
// to make logical coordinates the same as device coordinates.
|
||||||
{
|
wxGraphicsMatrix m = m_graphicContext->CreateMatrix();
|
||||||
wxRegionIterator ri(region);
|
m_graphicContext->SetTransform(m);
|
||||||
while (ri)
|
|
||||||
{
|
|
||||||
logRegion.Union(DeviceToLogicalX(ri.GetX()),
|
|
||||||
DeviceToLogicalY(ri.GetY()),
|
|
||||||
DeviceToLogicalXRel(ri.GetWidth()),
|
|
||||||
DeviceToLogicalYRel(ri.GetHeight()));
|
|
||||||
++ri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_graphicContext->Clip(logRegion);
|
// Set clipping region
|
||||||
|
m_graphicContext->Clip(region);
|
||||||
|
|
||||||
wxRect newRegion = logRegion.GetBox();
|
// Restore original transformation settings.
|
||||||
|
m_graphicContext->SetTransform(currTransform);
|
||||||
|
|
||||||
|
// Convert bounding box of the region to logical coordinates
|
||||||
|
// for further use.
|
||||||
|
wxRect newRegion = region.GetBox();
|
||||||
|
wxPoint logPos = wxPoint(DeviceToLogicalX(newRegion.GetLeft()),
|
||||||
|
DeviceToLogicalY(newRegion.GetTop()));
|
||||||
|
wxSize logSize = wxSize(DeviceToLogicalXRel(newRegion.GetWidth()),
|
||||||
|
DeviceToLogicalYRel(newRegion.GetHeight()));
|
||||||
|
newRegion.SetPosition(logPos);
|
||||||
|
newRegion.SetSize(logSize);
|
||||||
|
|
||||||
wxRect clipRegion;
|
wxRect clipRegion;
|
||||||
if ( m_clipping )
|
if ( m_clipping )
|
||||||
|
Reference in New Issue
Block a user