Store clipping box in device units only if it's set with wxDCImpl::DoSetClippingRegion

If derived class sets clipping region in a legitimate way by call to
DoSetClippingRegion() instead of directly storing logical coordinates
of the box in the internal variables we can store coordinates in
device units to determine final logical coordinates more reliably even
in case when coordinate transformations were applied to DC
in the meantime.
This commit is contained in:
Artur Wieczorek
2021-07-27 17:14:50 +02:00
parent 95f1b262a4
commit eb055dba71
2 changed files with 26 additions and 12 deletions

View File

@@ -742,8 +742,7 @@ protected:
// bounding and clipping boxes // bounding and clipping boxes
wxCoord m_minX, m_minY, m_maxX, m_maxY; // Bounding box is stored in device units. wxCoord m_minX, m_minY, m_maxX, m_maxY; // Bounding box is stored in device units.
wxCoord m_clipX1, m_clipY1, m_clipX2, m_clipY2; // Clipping box is stored in device units. wxCoord m_clipX1, m_clipY1, m_clipX2, m_clipY2; // Some derived classes operate directly on clipping box given in logical units.
// Derived classes may store it in logical units.
wxRasterOperationMode m_logicalFunction; wxRasterOperationMode m_logicalFunction;
int m_backgroundMode; int m_backgroundMode;
@@ -765,6 +764,9 @@ private:
// Return the full DC area in logical coordinates. // Return the full DC area in logical coordinates.
wxRect GetLogicalArea() const; wxRect GetLogicalArea() const;
wxCoord m_devClipX1, m_devClipY1, m_devClipX2, m_devClipY2; // For proper calculations of clipping box we need to store it in device units.
bool m_useDevClipCoords;
wxDECLARE_ABSTRACT_CLASS(wxDCImpl); wxDECLARE_ABSTRACT_CLASS(wxDCImpl);
}; };

View File

@@ -345,6 +345,8 @@ wxDCImpl::wxDCImpl( wxDC *owner )
, m_palette() , m_palette()
, m_hasCustomPalette(false) , m_hasCustomPalette(false)
#endif // wxUSE_PALETTE #endif // wxUSE_PALETTE
, m_devClipX1(0), m_devClipY1(0), m_devClipX2(0), m_devClipY2(0)
, m_useDevClipCoords(false)
{ {
m_owner = owner; m_owner = owner;
} }
@@ -362,13 +364,16 @@ void wxDCImpl::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
wxASSERT_MSG( w >= 0 && h >= 0, wxASSERT_MSG( w >= 0 && h >= 0,
wxS("Clipping box size values cannot be negative") ); wxS("Clipping box size values cannot be negative") );
// If we set clipping box with this method we can operate on device coordinates
// and calculate clipping box properly also when transfromations were applied to DC.
m_useDevClipCoords = true;
wxRect clipRegion(LogicalToDevice(x, y), LogicalToDeviceRel(w, h)); wxRect clipRegion(LogicalToDevice(x, y), LogicalToDeviceRel(w, h));
if ( m_clipping ) if ( m_clipping )
{ {
// New clipping box is an intersection // New clipping box is an intersection
// of required clipping box and the current one. // of required clipping box and the current one.
wxRect curRegion(m_clipX1, m_clipY1, m_clipX2 - m_clipX1, m_clipY2 - m_clipY1); wxRect curRegion(m_devClipX1, m_devClipY1, m_devClipX2 - m_devClipX1, m_devClipY2 - m_devClipY1);
clipRegion.Intersect(curRegion); clipRegion.Intersect(curRegion);
} }
else else
@@ -385,14 +390,14 @@ void wxDCImpl::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
if ( clipRegion.IsEmpty() ) if ( clipRegion.IsEmpty() )
{ {
m_clipX1 = m_clipY1 = m_clipX2 = m_clipY2 = 0; m_devClipX1 = m_devClipY1 = m_devClipX2 = m_devClipY2 = 0;
} }
else else
{ {
m_clipX1 = clipRegion.GetLeft(); m_devClipX1 = clipRegion.GetLeft();
m_clipY1 = clipRegion.GetTop(); m_devClipY1 = clipRegion.GetTop();
m_clipX2 = clipRegion.GetRight() + 1; m_devClipX2 = clipRegion.GetRight() + 1;
m_clipY2 = clipRegion.GetBottom() + 1; m_devClipY2 = clipRegion.GetBottom() + 1;
} }
} }
@@ -420,11 +425,18 @@ bool wxDCImpl::DoGetClippingRect(wxRect& rect) const
if ( m_clipping ) if ( m_clipping )
{ {
if ( m_clipX1 == m_clipX2 || m_clipY1 == m_clipY2 ) if ( m_useDevClipCoords )
rect = wxRect(); // empty clip region {
if ( m_devClipX1 == m_devClipX2 || m_devClipY1 == m_devClipY2 )
rect = wxRect(); // empty clip region
else
rect = wxRect(DeviceToLogical(m_devClipX1, m_devClipY1), DeviceToLogicalRel(m_devClipX2 - m_devClipX1, m_devClipY2 - m_devClipY1));
}
else else
rect = wxRect(DeviceToLogical(m_clipX1, m_clipY1), DeviceToLogicalRel(m_clipX2 - m_clipX1, m_clipY2 - m_clipY1)); {
// When derived class set coordinates in logical units directly...
rect = wxRect(m_clipX1, m_clipY1, m_clipX2 - m_clipX1, m_clipY2 - m_clipY1);
}
return true; return true;
} }
else // No active clipping region. else // No active clipping region.