Implement platform-specific coordinate conversion functions

Generic wxDC::DeviceToLogical{X|Y}() and wxDC::LogicalToDevice{X|Y}()
functions don't take into account transformations applied with
wxDC::SetTransformMatrix() so conversion results are invalid if wxDC is
transformed with both e.g. wxDC::SetUserScale() and
wxDC::SetTransformMatrix().
We need to implement functions in wxDCImpl and its platform-specific
derivates to do this conversion with taking into account all applied
transformations.

See #18916.
This commit is contained in:
Artur Wieczorek
2020-09-13 23:47:26 +02:00
parent 4ebfe0059a
commit 014bd2ae54
6 changed files with 59 additions and 0 deletions

View File

@@ -323,6 +323,10 @@ public:
// flushing the content of this dc immediately eg onto screen
virtual void Flush() { }
// coordinates conversions and transforms
virtual wxPoint DeviceToLogical(wxCoord x, wxCoord y) const;
virtual wxPoint LogicalToDevice(wxCoord x, wxCoord y) const;
// bounding box
virtual void CalcBoundingBox(wxCoord x, wxCoord y)

View File

@@ -121,6 +121,10 @@ public:
virtual void ResetTransformMatrix() wxOVERRIDE;
#endif // wxUSE_DC_TRANSFORM_MATRIX
// coordinates conversions and transforms
virtual wxPoint DeviceToLogical(wxCoord x, wxCoord y) const wxOVERRIDE;
virtual wxPoint LogicalToDevice(wxCoord x, wxCoord y) const wxOVERRIDE;
// the true implementations
virtual bool DoFloodFill(wxCoord x, wxCoord y, const wxColour& col,
wxFloodFillStyle style = wxFLOOD_SURFACE) wxOVERRIDE;
@@ -225,6 +229,7 @@ protected:
bool m_logicalFunctionSupported;
wxGraphicsMatrix m_matrixOriginal;
wxGraphicsMatrix m_matrixCurrent;
wxGraphicsMatrix m_matrixCurrentInv;
#if wxUSE_DC_TRANSFORM_MATRIX
wxAffineMatrix2D m_matrixExtTransform;
#endif // wxUSE_DC_TRANSFORM_MATRIX

View File

@@ -86,6 +86,9 @@ public:
virtual void SetDeviceOrigin(wxCoord x, wxCoord y) wxOVERRIDE;
virtual void SetAxisOrientation(bool xLeftRight, bool yBottomUp) wxOVERRIDE;
virtual wxPoint DeviceToLogical(wxCoord x, wxCoord y) const wxOVERRIDE;
virtual wxPoint LogicalToDevice(wxCoord x, wxCoord y) const wxOVERRIDE;
#if wxUSE_DC_TRANSFORM_MATRIX
virtual bool CanUseTransformMatrix() const wxOVERRIDE;
virtual bool SetTransformMatrix(const wxAffineMatrix2D& matrix) wxOVERRIDE;

View File

@@ -502,6 +502,16 @@ wxCoord wxDCImpl::LogicalToDeviceYRel(wxCoord y) const
return wxRound((double)(y) * m_scaleY);
}
wxPoint wxDCImpl::DeviceToLogical(wxCoord x, wxCoord y) const
{
return wxPoint(DeviceToLogicalX(x), DeviceToLogicalY(y));
}
wxPoint wxDCImpl::LogicalToDevice(wxCoord x, wxCoord y) const
{
return wxPoint(LogicalToDeviceX(x), LogicalToDeviceY(y));
}
void wxDCImpl::ComputeScaleAndOrigin()
{
m_scaleX = m_logicalScaleX * m_userScaleX;

View File

@@ -487,6 +487,8 @@ void wxGCDCImpl::ComputeScaleAndOrigin()
m_matrixCurrent.Concat(mtxExt);
#endif // wxUSE_DC_TRANSFORM_MATRIX
m_graphicContext->ConcatTransform( m_matrixCurrent );
m_matrixCurrentInv = m_matrixCurrent;
m_matrixCurrentInv.Invert();
m_isClipBoxValid = false;
}
}
@@ -594,6 +596,23 @@ void wxGCDCImpl::ResetTransformMatrix()
#endif // wxUSE_DC_TRANSFORM_MATRIX
// coordinates conversions and transforms
wxPoint wxGCDCImpl::DeviceToLogical(wxCoord x, wxCoord y) const
{
wxDouble px = x;
wxDouble py = y;
m_matrixCurrentInv.TransformPoint(&px, &py);
return wxPoint(wxRound(px), wxRound(py));
}
wxPoint wxGCDCImpl::LogicalToDevice(wxCoord x, wxCoord y) const
{
wxDouble px = x;
wxDouble py = y;
m_matrixCurrent.TransformPoint(&px, &py);
return wxPoint(wxRound(px), wxRound(py));
}
bool wxGCDCImpl::DoFloodFill(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
const wxColour& WXUNUSED(col),
wxFloodFillStyle WXUNUSED(style))

View File

@@ -2100,6 +2100,24 @@ void wxMSWDCImpl::SetDeviceOrigin(wxCoord x, wxCoord y)
m_isClipBoxValid = false;
}
wxPoint wxMSWDCImpl::DeviceToLogical(wxCoord x, wxCoord y) const
{
POINT p[1];
p[0].x = x;
p[0].y = y;
::DPtoLP(GetHdc(), p, WXSIZEOF(p));
return wxPoint(p[0].x, p[0].y);
}
wxPoint wxMSWDCImpl::LogicalToDevice(wxCoord x, wxCoord y) const
{
POINT p[1];
p[0].x = x;
p[0].y = y;
::LPtoDP(GetHdc(), p, WXSIZEOF(p));
return wxPoint(p[0].x, p[0].y);
}
// ----------------------------------------------------------------------------
// Transform matrix
// ----------------------------------------------------------------------------