diff --git a/interface/wx/dc.h b/interface/wx/dc.h
index bf1ca7db64..10a0392df5 100644
--- a/interface/wx/dc.h
+++ b/interface/wx/dc.h
@@ -206,52 +206,80 @@ public:
/**
Convert @e device X coordinate to logical coordinate, using the current
mapping mode, user scale factor, device origin and axis orientation.
+
+ @note Affine transformation applied to the coordinate system
+ with SetTransformMatrix() is not taken into account.
*/
wxCoord DeviceToLogicalX(wxCoord x) const;
/**
Convert @e device X coordinate to relative logical coordinate, using the
current mapping mode and user scale factor but ignoring the
- axis orientation. Use this for converting a width, for example.
+ axis orientation. Use this for converting a horizontal distance like
+ for example a width.
+
+ @note Affine transformation applied to the coordinate system
+ with SetTransformMatrix() is not taken into account.
*/
wxCoord DeviceToLogicalXRel(wxCoord x) const;
/**
Converts @e device Y coordinate to logical coordinate, using the current
mapping mode, user scale factor, device origin and axis orientation.
+
+ @note Affine transformation applied to the coordinate system
+ with SetTransformMatrix() is not taken into account.
*/
wxCoord DeviceToLogicalY(wxCoord y) const;
/**
Convert @e device Y coordinate to relative logical coordinate, using the
current mapping mode and user scale factor but ignoring the
- axis orientation. Use this for converting a height, for example.
+ axis orientation. Use this for converting a vertical distance like
+ for example a height.
+
+ @note Affine transformation applied to the coordinate system
+ with SetTransformMatrix() is not taken into account.
*/
wxCoord DeviceToLogicalYRel(wxCoord y) const;
/**
Converts logical X coordinate to device coordinate, using the current
mapping mode, user scale factor, device origin and axis orientation.
+
+ @note Affine transformation applied to the coordinate system
+ with SetTransformMatrix() is not taken into account.
*/
wxCoord LogicalToDeviceX(wxCoord x) const;
/**
Converts logical X coordinate to relative device coordinate, using the
current mapping mode and user scale factor but ignoring the
- axis orientation. Use this for converting a width, for example.
+ axis orientation. Use this for converting a horizontal distance like
+ for example a width.
+
+ @note Affine transformation applied to the coordinate system
+ with SetTransformMatrix() is not taken into account.
*/
wxCoord LogicalToDeviceXRel(wxCoord x) const;
/**
Converts logical Y coordinate to device coordinate, using the current
mapping mode, user scale factor, device origin and axis orientation.
+
+ @note Affine transformation applied to the coordinate system
+ with SetTransformMatrix() is not taken into account.
*/
wxCoord LogicalToDeviceY(wxCoord y) const;
/**
Converts logical Y coordinate to relative device coordinate, using the
current mapping mode and user scale factor but ignoring the
- axis orientation. Use this for converting a height, for example.
+ axis orientation. Use this for converting a vertical distance like
+ for example a height.
+
+ @note Affine transformation applied to the coordinate system
+ with SetTransformMatrix() is not taken into account.
*/
wxCoord LogicalToDeviceYRel(wxCoord y) const;
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 5cd6cc7bda..eb43137e9d 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -185,6 +185,7 @@ TEST_GUI_OBJECTS = \
test_gui_affinematrix.o \
test_gui_boundingbox.o \
test_gui_clippingbox.o \
+ test_gui_coords.o \
test_gui_graphmatrix.o \
test_gui_graphpath.o \
test_gui_config.o \
@@ -899,6 +900,9 @@ test_gui_boundingbox.o: $(srcdir)/graphics/boundingbox.cpp $(TEST_GUI_ODEP)
test_gui_clippingbox.o: $(srcdir)/graphics/clippingbox.cpp $(TEST_GUI_ODEP)
$(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/graphics/clippingbox.cpp
+test_gui_coords.o: $(srcdir)/graphics/coords.cpp $(TEST_GUI_ODEP)
+ $(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/graphics/coords.cpp
+
test_gui_graphmatrix.o: $(srcdir)/graphics/graphmatrix.cpp $(TEST_GUI_ODEP)
$(CXXC) -c -o $@ $(TEST_GUI_CXXFLAGS) $(srcdir)/graphics/graphmatrix.cpp
diff --git a/tests/graphics/coords.cpp b/tests/graphics/coords.cpp
new file mode 100644
index 0000000000..67e376ebcd
--- /dev/null
+++ b/tests/graphics/coords.cpp
@@ -0,0 +1,852 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: tests/graphics/coords.cpp
+// Purpose: Coordinates conversion unit tests
+// Author: Artur Wieczorek
+// Created: 2020-09-25
+// Copyright: (c) 2020 wxWidgets development team
+///////////////////////////////////////////////////////////////////////////////
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+#include "testprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#include "wx/bitmap.h"
+#include "wx/dcgraph.h"
+#include "wx/dcmemory.h"
+
+
+// ----------------------------------------------------------------------------
+// test class
+// ----------------------------------------------------------------------------
+
+static const wxSize s_dcSize(100, 100);
+static const wxPoint s_posDev(24, 57);
+static const wxSize s_dimDev(40, 15);
+
+// ====================
+// wxDC / wxGCDC tests
+// ====================
+
+class CoordinatesDCTestCaseBase
+{
+public:
+ CoordinatesDCTestCaseBase()
+ {
+ m_bmp.Create(s_dcSize);
+ m_dc = NULL;
+ }
+
+ virtual ~CoordinatesDCTestCaseBase()
+ {
+ m_bmp = wxNullBitmap;
+ }
+
+protected:
+ wxBitmap m_bmp;
+ wxDC* m_dc;
+};
+
+// ===========
+// wxDC tests
+// ===========
+
+class CoordinatesDCTestCase : public CoordinatesDCTestCaseBase
+{
+public:
+ CoordinatesDCTestCase()
+ {
+ m_mdc.SelectObject(m_bmp);
+ m_dc = &m_mdc;
+ }
+
+ virtual ~CoordinatesDCTestCase()
+ {
+ m_mdc.SelectObject(wxNullBitmap);
+ }
+
+protected:
+ wxMemoryDC m_mdc;
+};
+
+#if wxUSE_GRAPHICS_CONTEXT
+// =============
+// wxGCDC tests
+// =============
+
+class CoordinatesGCDCTestCase : public CoordinatesDCTestCase
+{
+public:
+ CoordinatesGCDCTestCase()
+ {
+ m_gcdc = new wxGCDC(m_mdc);
+
+ wxGraphicsContext* ctx = m_gcdc->GetGraphicsContext();
+ ctx->SetAntialiasMode(wxANTIALIAS_NONE);
+ ctx->DisableOffset();
+
+ m_dc = m_gcdc;
+ }
+
+ virtual ~CoordinatesGCDCTestCase()
+ {
+ delete m_gcdc;
+ }
+
+protected:
+ wxGCDC* m_gcdc;
+};
+#endif // wxUSE_GRAPHICS_CONTEXT
+
+// ===== Implementation =====
+
+static void InitialState(wxDC* dc)
+{
+ // Check initial state
+
+ wxPoint origin = dc->GetDeviceOrigin();
+ CHECK(origin.x == 0);
+ CHECK(origin.y == 0);
+
+ origin = dc->GetLogicalOrigin();
+ CHECK(origin.x == 0);
+ CHECK(origin.y == 0);
+
+ double sx, sy;
+ dc->GetUserScale(&sx, &sy);
+ CHECK(sx == 1.0);
+ CHECK(sy == 1.0);
+
+ dc->GetLogicalScale(&sx, &sy);
+ CHECK(sx == 1.0);
+ CHECK(sy == 1.0);
+
+#if wxUSE_DC_TRANSFORM_MATRIX
+ if ( dc->CanUseTransformMatrix() )
+ {
+ wxAffineMatrix2D m = dc->GetTransformMatrix();
+ CHECK(m.IsIdentity() == true);
+ }
+#endif // wxUSE_DC_TRANSFORM_MATRIX
+}
+
+static void NoTransform(wxDC *dc)
+{
+ // No transformations
+
+ // First convert from device to logical coordinates
+ wxPoint posLog;
+ posLog.x = dc->DeviceToLogicalX(s_posDev.x);
+ posLog.y = dc->DeviceToLogicalY(s_posDev.y);
+ CHECK(posLog.x == s_posDev.x);
+ CHECK(posLog.y == s_posDev.y);
+
+ wxSize dimLog;
+ dimLog.x = dc->DeviceToLogicalXRel(s_dimDev.x);
+ dimLog.y = dc->DeviceToLogicalYRel(s_dimDev.y);
+ CHECK(dimLog.x == s_dimDev.x);
+ CHECK(dimLog.y == s_dimDev.y);
+
+ // And next back from logical to device coordinates
+ wxPoint posDev;
+ posDev.x = dc->LogicalToDeviceX(posLog.x);
+ posDev.y = dc->LogicalToDeviceY(posLog.y);
+ CHECK(posDev.x == s_posDev.x);
+ CHECK(posDev.y == s_posDev.y);
+
+ wxSize dimDev;
+ dimDev.x = dc->LogicalToDeviceXRel(dimLog.x);
+ dimDev.y = dc->LogicalToDeviceYRel(dimLog.y);
+ CHECK(dimDev.x == s_dimDev.x);
+ CHECK(dimDev.y == s_dimDev.y);
+}
+
+static void DeviceOriginChanged(wxDC* dc)
+{
+ // Only device origin is changed
+ const wxCoord dx = 10;
+ const wxCoord dy = 15;
+ dc->SetDeviceOrigin(dx, dy);
+
+ // First convert from device to logical coordinates
+ wxPoint posLog;
+ posLog.x = dc->DeviceToLogicalX(s_posDev.x);
+ posLog.y = dc->DeviceToLogicalY(s_posDev.y);
+ CHECK(posLog.x == s_posDev.x - dx);
+ CHECK(posLog.y == s_posDev.y - dy);
+
+ wxSize dimLog;
+ dimLog.x = dc->DeviceToLogicalXRel(s_dimDev.x);
+ dimLog.y = dc->DeviceToLogicalYRel(s_dimDev.y);
+ CHECK(dimLog.x == s_dimDev.x);
+ CHECK(dimLog.y == s_dimDev.y);
+
+ // And next back from logical to device coordinates
+ wxPoint posDev;
+ posDev.x = dc->LogicalToDeviceX(posLog.x);
+ posDev.y = dc->LogicalToDeviceY(posLog.y);
+ CHECK(posDev.x == s_posDev.x);
+ CHECK(posDev.y == s_posDev.y);
+
+ wxSize dimDev;
+ dimDev.x = dc->LogicalToDeviceXRel(dimLog.x);
+ dimDev.y = dc->LogicalToDeviceYRel(dimLog.y);
+ CHECK(dimDev.x == s_dimDev.x);
+ CHECK(dimDev.y == s_dimDev.y);
+}
+
+static void LogicalOriginChanged(wxDC* dc)
+{
+ // Only logical origin is changed
+ const wxCoord dx = -15;
+ const wxCoord dy = -20;
+ dc->SetLogicalOrigin(dx, dy);
+
+ // First convert from device to logical coordinates
+ wxPoint posLog;
+ posLog.x = dc->DeviceToLogicalX(s_posDev.x);
+ posLog.y = dc->DeviceToLogicalY(s_posDev.y);
+ CHECK(posLog.x == s_posDev.x + dx);
+ CHECK(posLog.y == s_posDev.y + dy);
+
+ wxSize dimLog;
+ dimLog.x = dc->DeviceToLogicalXRel(s_dimDev.x);
+ dimLog.y = dc->DeviceToLogicalYRel(s_dimDev.y);
+ CHECK(dimLog.x == s_dimDev.x);
+ CHECK(dimLog.y == s_dimDev.y);
+
+ // And next back from logical to device coordinates
+ wxPoint posDev;
+ posDev.x = dc->LogicalToDeviceX(posLog.x);
+ posDev.y = dc->LogicalToDeviceY(posLog.y);
+ CHECK(posDev.x == s_posDev.x);
+ CHECK(posDev.y == s_posDev.y);
+
+ wxSize dimDev;
+ dimDev.x = dc->LogicalToDeviceXRel(dimLog.x);
+ dimDev.y = dc->LogicalToDeviceYRel(dimLog.y);
+ CHECK(dimDev.x == s_dimDev.x);
+ CHECK(dimDev.y == s_dimDev.y);
+}
+
+static void UserScaleChanged(wxDC* dc)
+{
+ // Only user scale is changed
+ const double sx = 2.0;
+ const double sy = 3.0;
+ dc->SetUserScale(sx, sy);
+
+ // First convert from device to logical coordinates
+ wxPoint posLog;
+ posLog.x = dc->DeviceToLogicalX(s_posDev.x);
+ posLog.y = dc->DeviceToLogicalY(s_posDev.y);
+ CHECK(posLog.x == wxRound(s_posDev.x / sx));
+ CHECK(posLog.y == wxRound(s_posDev.y / sy));
+
+ wxSize dimLog;
+ dimLog.x = dc->DeviceToLogicalXRel(s_dimDev.x);
+ dimLog.y = dc->DeviceToLogicalYRel(s_dimDev.y);
+ CHECK(dimLog.x == wxRound(s_dimDev.x / sx));
+ CHECK(dimLog.y == wxRound(s_dimDev.y / sy));
+
+ // And next back from logical to device coordinates
+ wxPoint posDev;
+ posDev.x = dc->LogicalToDeviceX(posLog.x);
+ posDev.y = dc->LogicalToDeviceY(posLog.y);
+ CHECK(posDev.x == s_posDev.x);
+ CHECK(posDev.y == s_posDev.y);
+
+ wxSize dimDev;
+ dimDev.x = dc->LogicalToDeviceXRel(dimLog.x);
+ dimDev.y = dc->LogicalToDeviceYRel(dimLog.y);
+ CHECK(dimDev.x == s_dimDev.x);
+ CHECK(dimDev.y == s_dimDev.y);
+}
+
+static void LogicalScaleChanged(wxDC* dc)
+{
+ // Only logical scale is changed
+ const double sx = 2.0;
+ const double sy = 3.0;
+ dc->SetLogicalScale(sx, sy);
+
+ // First convert from device to logical coordinates
+ wxPoint posLog;
+ posLog.x = dc->DeviceToLogicalX(s_posDev.x);
+ posLog.y = dc->DeviceToLogicalY(s_posDev.y);
+ CHECK(posLog.x == wxRound(s_posDev.x / sx));
+ CHECK(posLog.y == wxRound(s_posDev.y / sy));
+
+ wxSize dimLog;
+ dimLog.x = dc->DeviceToLogicalXRel(s_dimDev.x);
+ dimLog.y = dc->DeviceToLogicalYRel(s_dimDev.y);
+ CHECK(dimLog.x == wxRound(s_dimDev.x / sx));
+ CHECK(dimLog.y == wxRound(s_dimDev.y / sy));
+
+ // And next back from logical to device coordinates
+ wxPoint posDev;
+ posDev.x = dc->LogicalToDeviceX(posLog.x);
+ posDev.y = dc->LogicalToDeviceY(posLog.y);
+ CHECK(posDev.x == s_posDev.x);
+ CHECK(posDev.y == s_posDev.y);
+
+ wxSize dimDev;
+ dimDev.x = dc->LogicalToDeviceXRel(dimLog.x);
+ dimDev.y = dc->LogicalToDeviceYRel(dimLog.y);
+ CHECK(dimDev.x == s_dimDev.x);
+ CHECK(dimDev.y == s_dimDev.y);
+}
+
+static void TransformedStd(wxDC* dc)
+{
+ // Apply all standardd transformations
+ dc->SetDeviceOrigin(10, 15);
+ dc->SetUserScale(0.5, 2.0);
+ dc->SetLogicalScale(4.0, 1.5);
+ dc->SetLogicalOrigin(-15, -20);
+
+ // First convert from device to logical coordinates
+ wxPoint posLog;
+ posLog.x = dc->DeviceToLogicalX(s_posDev.x);
+ posLog.y = dc->DeviceToLogicalY(s_posDev.y);
+ CHECK(posLog.x == -8);
+ CHECK(posLog.y == -6);
+
+ wxSize dimLog;
+ dimLog.x = dc->DeviceToLogicalXRel(s_dimDev.x);
+ dimLog.y = dc->DeviceToLogicalYRel(s_dimDev.y);
+ CHECK(dimLog.x == 20);
+ CHECK(dimLog.y == 5);
+
+ // And next back from logical to device coordinates
+ wxPoint posDev;
+ posDev.x = dc->LogicalToDeviceX(posLog.x);
+ posDev.y = dc->LogicalToDeviceY(posLog.y);
+ CHECK(posDev.x == s_posDev.x);
+ CHECK(posDev.y == s_posDev.y);
+
+ wxSize dimDev;
+ dimDev.x = dc->LogicalToDeviceXRel(dimLog.x);
+ dimDev.y = dc->LogicalToDeviceYRel(dimLog.y);
+ CHECK(dimDev.x == s_dimDev.x);
+ CHECK(dimDev.y == s_dimDev.y);
+}
+
+static void TransformedWithMatrix(wxDC* dc)
+{
+ // Apply transformation matrix only
+#if wxUSE_DC_TRANSFORM_MATRIX
+ if ( dc->CanUseTransformMatrix() )
+ {
+ // Apply translation and scaling only
+ wxAffineMatrix2D m = dc->GetTransformMatrix();
+ m.Translate(10, 15);
+ m.Scale(2.0, 3.0);
+ dc->SetTransformMatrix(m);
+
+ // First convert from device to logical coordinates
+ // Results should be nagative because legacy functions
+ // don't take affine transformation into account.
+ m.Invert();
+ wxPoint2DDouble posLogRef = m.TransformPoint(wxPoint2DDouble(s_posDev));
+ wxPoint posLog;
+ posLog.x = dc->DeviceToLogicalX(s_posDev.x);
+ posLog.y = dc->DeviceToLogicalY(s_posDev.y);
+ CHECK_FALSE(posLog.x == wxRound(posLogRef.m_x));
+ CHECK_FALSE(posLog.y == wxRound(posLogRef.m_y));
+ CHECK(posLog.x == s_posDev.x);
+ CHECK(posLog.y == s_posDev.y);
+
+ wxPoint2DDouble dimLogRef = m.TransformDistance(wxPoint2DDouble(s_dimDev.x, s_dimDev.y));
+ wxSize dimLog;
+ dimLog.x = dc->DeviceToLogicalXRel(s_dimDev.x);
+ dimLog.y = dc->DeviceToLogicalYRel(s_dimDev.y);
+ CHECK_FALSE(dimLog.x == wxRound(dimLogRef.m_x));
+ CHECK_FALSE(dimLog.y == wxRound(dimLogRef.m_y));
+ CHECK(dimLog.x == s_dimDev.x);
+ CHECK(dimLog.y == s_dimDev.y);
+
+ // And next back from logical to device coordinates
+ wxPoint posDev;
+ posDev.x = dc->LogicalToDeviceX(posLog.x);
+ posDev.y = dc->LogicalToDeviceY(posLog.y);
+ CHECK(posDev.x == s_posDev.x);
+ CHECK(posDev.y == s_posDev.y);
+
+ wxSize dimDev;
+ dimDev.x = dc->LogicalToDeviceXRel(dimLog.x);
+ dimDev.y = dc->LogicalToDeviceYRel(dimLog.y);
+ CHECK(dimDev.x == s_dimDev.x);
+ CHECK(dimDev.y == s_dimDev.y);
+ }
+#endif // wxUSE_DC_TRANSFORM_MATRIX
+}
+
+static void TransformedWithMatrixAndStd(wxDC* dc)
+{
+ // Apply combination of standard and matrix transformations
+#if wxUSE_DC_TRANSFORM_MATRIX
+ if ( dc->CanUseTransformMatrix() )
+ {
+ dc->SetDeviceOrigin(10, 15);
+
+ dc->SetUserScale(0.5, 1.5);
+ dc->SetLogicalScale(4.0, 2.0);
+ dc->SetLogicalOrigin(-15, -20);
+
+ wxAffineMatrix2D m = dc->GetTransformMatrix();
+ m.Translate(10, 18);
+ m.Scale(2.0, 0.5);
+ dc->SetTransformMatrix(m);
+
+ // First convert from device to logical coordinates
+ // Results should be nagative because legacy functions
+ // don't take affine transformation into account.
+ wxAffineMatrix2D m1;
+ m1.Translate(10 - (-15) * (0.5 * 4.0), 15 - (-20) * (1.5 * 2.0));
+ m1.Scale(0.5 * 4.0, 1.5 * 2.0);
+ m1.Concat(m);
+ m1.Invert();
+
+ wxPoint2DDouble posLogRef = m1.TransformPoint(wxPoint2DDouble(s_posDev));
+ wxPoint posLog;
+ posLog.x = dc->DeviceToLogicalX(s_posDev.x);
+ posLog.y = dc->DeviceToLogicalY(s_posDev.y);
+ CHECK_FALSE(posLog.x == wxRound(posLogRef.m_x));
+ CHECK_FALSE(posLog.y == wxRound(posLogRef.m_y));
+
+ wxPoint2DDouble dimLogRef = m1.TransformDistance(wxPoint2DDouble(s_dimDev.x, s_dimDev.y));
+ wxSize dimLog;
+ dimLog.x = dc->DeviceToLogicalXRel(s_dimDev.x);
+ dimLog.y = dc->DeviceToLogicalYRel(s_dimDev.y);
+ CHECK_FALSE(dimLog.x == wxRound(dimLogRef.m_x));
+ CHECK_FALSE(dimLog.y == wxRound(dimLogRef.m_y));
+
+ // And next back from logical to device coordinates
+ wxPoint posDev;
+ posDev.x = dc->LogicalToDeviceX(posLog.x);
+ posDev.y = dc->LogicalToDeviceY(posLog.y);
+ CHECK(posDev.x == s_posDev.x);
+ CHECK(posDev.y == s_posDev.y);
+
+ wxSize dimDev;
+ dimDev.x = dc->LogicalToDeviceXRel(dimLog.x);
+ dimDev.y = dc->LogicalToDeviceYRel(dimLog.y);
+ CHECK(dimDev.x == s_dimDev.x);
+ CHECK(dimDev.y == s_dimDev.y);
+ }
+#endif // wxUSE_DC_TRANSFORM_MATRIX
+}
+
+static void RotatedWithMatrix(wxDC* dc)
+{
+ // Apply matrix transformations with rotation component
+#if wxUSE_DC_TRANSFORM_MATRIX
+ if ( dc->CanUseTransformMatrix() )
+ {
+ wxAffineMatrix2D m = dc->GetTransformMatrix();
+ m.Rotate(6 * M_PI / 180.0);
+ m.Translate(10, 15);
+ m.Scale(2.0, 3.0);
+ dc->SetTransformMatrix(m);
+
+ // First convert from device to logical coordinates
+ // Results should be nagative because legacy functions
+ // don't take affine transformation into account.
+ m.Invert();
+ wxPoint2DDouble posLogRef = m.TransformPoint(wxPoint2DDouble(s_posDev));
+ wxPoint posLog;
+ posLog.x = dc->DeviceToLogicalX(s_posDev.x);
+ posLog.y = dc->DeviceToLogicalY(s_posDev.y);
+ CHECK_FALSE(posLog.x == wxRound(posLogRef.m_x));
+ CHECK_FALSE(posLog.y == wxRound(posLogRef.m_y));
+ CHECK(posLog.x == s_posDev.x);
+ CHECK(posLog.y == s_posDev.y);
+
+ wxPoint2DDouble dimLogRef = m.TransformDistance(wxPoint2DDouble(s_dimDev.x, s_dimDev.y));
+ wxSize dimLog;
+ dimLog.x = dc->DeviceToLogicalXRel(s_dimDev.x);
+ dimLog.y = dc->DeviceToLogicalYRel(s_dimDev.y);
+ CHECK_FALSE(dimLog.x == wxRound(dimLogRef.m_x));
+ CHECK_FALSE(dimLog.y == wxRound(dimLogRef.m_y));
+ CHECK(dimLog.x == s_dimDev.x);
+ CHECK(dimLog.y == s_dimDev.y);
+
+ // And next back from logical to device coordinates
+ wxPoint posDev;
+ posDev.x = dc->LogicalToDeviceX(posLog.x);
+ posDev.y = dc->LogicalToDeviceY(posLog.y);
+ CHECK(posDev.x == s_posDev.x);
+ CHECK(posDev.y == s_posDev.y);
+
+ wxSize dimDev;
+ dimDev.x = dc->LogicalToDeviceXRel(dimLog.x);
+ dimDev.y = dc->LogicalToDeviceYRel(dimLog.y);
+ CHECK(dimDev.x == s_dimDev.x);
+ CHECK(dimDev.y == s_dimDev.y);
+ }
+#endif // wxUSE_DC_TRANSFORM_MATRIX
+}
+
+// For GTK+ 3 and OSX wxDC is equivalent to wxGCDC
+// so it doesn't need to be tested individually.
+#if !defined(__WXGTK3__) && !defined(__WXOSX__)
+TEST_CASE_METHOD(CoordinatesDCTestCase, "CoordinatesDC::InitialState", "[coordinates]")
+{
+ // Check initial state
+ InitialState(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesDCTestCase, "CoordinatesDC::NoTransform", "[coordinates]")
+{
+ // No transformations
+ NoTransform(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesDCTestCase, "CoordinatesDC::DeviceOriginChanged", "[coordinates]")
+{
+ // Only device origin is changed
+ DeviceOriginChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesDCTestCase, "CoordinatesDC::LogicalOriginChanged", "[coordinates]")
+{
+ // Only logical origin is changed
+ LogicalOriginChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesDCTestCase, "CoordinatesDC::UserScaleChanged", "[coordinates]")
+{
+ // Only user scale is changed
+ UserScaleChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesDCTestCase, "CoordinatesDC::LogicalScaleChanged", "[coordinates]")
+{
+ // Only logical scale is changed
+ LogicalScaleChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesDCTestCase, "CoordinatesDC::TransformedStd", "[coordinates]")
+{
+ // Apply all standardd transformations
+ TransformedStd(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesDCTestCase, "CoordinatesDC::TransformedWithMatrix", "[coordinates]")
+{
+ // Apply transformation matrix only
+ TransformedWithMatrix(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesDCTestCase, "CoordinatesDC::TransformedWithMatrixAndStd", "[coordinates]")
+{
+ // Apply combination of standard and matrix transformations
+ TransformedWithMatrixAndStd(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesDCTestCase, "CoordinatesDC::RotatedWithMatrix", "[coordinates]")
+{
+ // Apply matrix transformations with rotation component
+ RotatedWithMatrix(m_dc);
+}
+#endif // !__WXGTK3__ && !_WXOSX__
+
+#if wxUSE_GRAPHICS_CONTEXT
+// For MSW we have individual test cases for each graphics renderer
+// so we don't need to test wxGCDC with default renderer.
+#ifndef __WXMSW__
+TEST_CASE_METHOD(CoordinatesGCDCTestCase, "CoordinatesGCDC::InitialState", "[coordinates]")
+{
+ // Check initial state
+ InitialState(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCTestCase, "CoordinatesGCDC::NoTransform", "[coordinates]")
+{
+ // No transformations
+ NoTransform(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCTestCase, "CoordinatesGCDC::DeviceOriginChanged", "[coordinates]")
+{
+ // Only device origin is changed
+ DeviceOriginChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCTestCase, "CoordinatesGCDC::LogicalOriginChanged", "[coordinates]")
+{
+ // Only logical origin is changed
+ LogicalOriginChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCTestCase, "CoordinatesGCDC::UserScaleChanged", "[coordinates]")
+{
+ // Only user scale is changed
+ UserScaleChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCTestCase, "CoordinatesGCDC::LogicalScaleChanged", "[coordinates]")
+{
+ // Only logical scale is changed
+ LogicalScaleChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCTestCase, "CoordinatesGCDC::TransformedStd", "[coordinates]")
+{
+ // Apply all standardd transformations
+ TransformedStd(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCTestCase, "CoordinatesGCDC::TransformedWithMatrix", "[coordinates]")
+{
+ // Apply transformation matrix only
+ TransformedWithMatrix(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCTestCase, "CoordinatesGCDC::TransformedWithMatrixAndStd", "[coordinates]")
+{
+ // Apply combination of standard and matrix transformations
+ TransformedWithMatrixAndStd(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCTestCase, "CoordinatesGCDC::RotatedWithMatrix", "[coordinates]")
+{
+ // Apply matrix transformations with rotation component
+ RotatedWithMatrix(m_dc);
+}
+#else// GDI+ and Direct2D are available only under MSW.
+#if wxUSE_GRAPHICS_GDIPLUS
+class CoordinatesGCDCGDIPlusTestCase : public CoordinatesGCDCTestCase
+{
+public:
+ CoordinatesGCDCGDIPlusTestCase()
+ {
+ wxGraphicsRenderer* rend = wxGraphicsRenderer::GetGDIPlusRenderer();
+ wxGraphicsContext* ctx = rend->CreateContext(m_mdc);
+ REQUIRE(ctx != NULL);
+ m_gcdc->SetGraphicsContext(ctx);
+ }
+
+ virtual ~CoordinatesGCDCGDIPlusTestCase() {}
+};
+
+TEST_CASE_METHOD(CoordinatesGCDCGDIPlusTestCase, "CoordinatesGCDCGDIPlus::InitialState", "[coordinates]")
+{
+ // Check initial state
+ InitialState(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCGDIPlusTestCase, "CoordinatesGCDCGDIPlus::NoTransform", "[coordinates]")
+{
+ // No transformations
+ NoTransform(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCGDIPlusTestCase, "CoordinatesGCDCGDIPlus::DeviceOriginChanged", "[coordinates]")
+{
+ // Only device origin is changed
+ DeviceOriginChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCGDIPlusTestCase, "CoordinatesGCDCGDIPlus::LogicalOriginChanged", "[coordinates]")
+{
+ // Only logical origin is changed
+ LogicalOriginChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCGDIPlusTestCase, "CoordinatesGCDCGDIPlus::UserScaleChanged", "[coordinates]")
+{
+ // Only user scale is changed
+ UserScaleChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCGDIPlusTestCase, "CoordinatesGCDCGDIPlus::LogicalScaleChanged", "[coordinates]")
+{
+ // Only logical scale is changed
+ LogicalScaleChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCGDIPlusTestCase, "CoordinatesGCDCGDIPlus::TransformedStd", "[coordinates]")
+{
+ // Apply all standardd transformations
+ TransformedStd(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCGDIPlusTestCase, "CoordinatesGCDCGDIPlus::TransformedWithMatrix", "[coordinates]")
+{
+ // Apply transformation matrix only
+ TransformedWithMatrix(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCGDIPlusTestCase, "CoordinatesGCDCGDIPlus::TransformedWithMatrixAndStd", "[coordinates]")
+{
+ // Apply combination of standard and matrix transformations
+ TransformedWithMatrixAndStd(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCGDIPlusTestCase, "CoordinatesGCDCGDIPlus::RotatedWithMatrix", "[coordinates]")
+{
+ // Apply matrix transformations with rotation component
+ RotatedWithMatrix(m_dc);
+}
+#endif // wxUSE_GRAPHICS_GDIPLUS
+
+#if wxUSE_GRAPHICS_DIRECT2D
+class CoordinatesGCDCDirect2DTestCase : public CoordinatesGCDCTestCase
+{
+public:
+ CoordinatesGCDCDirect2DTestCase()
+ {
+ wxGraphicsRenderer* rend = wxGraphicsRenderer::GetDirect2DRenderer();
+ wxGraphicsContext* ctx = rend->CreateContext(m_mdc);
+ REQUIRE(ctx != NULL);
+ m_gcdc->SetGraphicsContext(ctx);
+ }
+
+ virtual ~CoordinatesGCDCDirect2DTestCase() {}
+};
+
+TEST_CASE_METHOD(CoordinatesGCDCDirect2DTestCase, "CoordinatesGCDCDirect2D::InitialState", "[coordinates]")
+{
+ // Check initial state
+ InitialState(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCDirect2DTestCase, "CoordinatesGCDCDirect2D::NoTransform", "[coordinates]")
+{
+ // No transformations
+ NoTransform(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCDirect2DTestCase, "CoordinatesGCDCDirect2D::DeviceOriginChanged", "[coordinates]")
+{
+ // Only device origin is changed
+ DeviceOriginChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCDirect2DTestCase, "CoordinatesGCDCDirect2D::LogicalOriginChanged", "[coordinates]")
+{
+ // Only logical origin is changed
+ LogicalOriginChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCDirect2DTestCase, "CoordinatesGCDCDirect2D::UserScaleChanged", "[coordinates]")
+{
+ // Only user scale is changed
+ UserScaleChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCDirect2DTestCase, "CoordinatesGCDCDirect2D::LogicalScaleChanged", "[coordinates]")
+{
+ // Only logical scale is changed
+ LogicalScaleChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCDirect2DTestCase, "CoordinatesGCDCDirect2D::TransformedStd", "[coordinates]")
+{
+ // Apply all standardd transformations
+ TransformedStd(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCDirect2DTestCase, "CoordinatesGCDCDirect2D::TransformedWithMatrix", "[coordinates]")
+{
+ // Apply transformation matrix only
+ TransformedWithMatrix(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCDirect2DTestCase, "CoordinatesGCDCDirect2D::TransformedWithMatrixAndStd", "[coordinates]")
+{
+ // Apply combination of standard and matrix transformations
+ TransformedWithMatrixAndStd(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCDirect2DTestCase, "CoordinatesGCDCDirect2D::RotatedWithMatrix", "[coordinates]")
+{
+ // Apply matrix transformations with rotation component
+ RotatedWithMatrix(m_dc);
+}
+#endif // wxUSE_GRAPHICS_DIRECT2D
+#endif // __WXMSW__/!__WXMSW__
+
+#if wxUSE_CAIRO
+class CoordinatesGCDCCairoTestCase : public CoordinatesGCDCTestCase
+{
+public:
+ CoordinatesGCDCCairoTestCase()
+ {
+ wxGraphicsRenderer* rend = wxGraphicsRenderer::GetCairoRenderer();
+ wxGraphicsContext* ctx = rend->CreateContext(m_mdc);
+ REQUIRE(ctx != NULL);
+ m_gcdc->SetGraphicsContext(ctx);
+ }
+
+ virtual ~CoordinatesGCDCCairoTestCase() {}
+};
+
+TEST_CASE_METHOD(CoordinatesGCDCCairoTestCase, "CoordinatesGCDCCairo::InitialState", "[coordinates]")
+{
+ // Check initial state
+ InitialState(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCCairoTestCase, "CoordinatesGCDCCairo::NoTransform", "[coordinates]")
+{
+ // No transformations
+ NoTransform(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCCairoTestCase, "CoordinatesGCDCCairo::DeviceOriginChanged", "[coordinates]")
+{
+ // Only device origin is changed
+ DeviceOriginChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCCairoTestCase, "CoordinatesGCDCCairo::LogicalOriginChanged", "[coordinates]")
+{
+ // Only logical origin is changed
+ LogicalOriginChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCCairoTestCase, "CoordinatesGCDCCairo::UserScaleChanged", "[coordinates]")
+{
+ // Only user scale is changed
+ UserScaleChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCCairoTestCase, "CoordinatesGCDCCairo::LogicalScaleChanged", "[coordinates]")
+{
+ // Only logical scale is changed
+ LogicalScaleChanged(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCCairoTestCase, "CoordinatesGCDCCairo::TransformedStd", "[coordinates]")
+{
+ // Apply all standardd transformations
+ TransformedStd(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCCairoTestCase, "CoordinatesGCDCCairo::TransformedWithMatrix", "[coordinates]")
+{
+ // Apply transformation matrix only
+ TransformedWithMatrix(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCCairoTestCase, "CoordinatesGCDCCairo::TransformedWithMatrixAndStd", "[coordinates]")
+{
+ // Apply combination of standard and matrix transformations
+ TransformedWithMatrixAndStd(m_dc);
+}
+
+TEST_CASE_METHOD(CoordinatesGCDCCairoTestCase, "CoordinatesGCDCCairo::RotatedWithMatrix", "[coordinates]")
+{
+ // Apply matrix transformations with rotation component
+ RotatedWithMatrix(m_dc);
+}
+#endif // wxUSE_CAIRO
+#endif // wxUSE_GRAPHICS_CONTEXT
diff --git a/tests/makefile.bcc b/tests/makefile.bcc
index 6be3ae8a33..2a503e7998 100644
--- a/tests/makefile.bcc
+++ b/tests/makefile.bcc
@@ -168,6 +168,7 @@ TEST_GUI_OBJECTS = \
$(OBJS)\test_gui_affinematrix.obj \
$(OBJS)\test_gui_boundingbox.obj \
$(OBJS)\test_gui_clippingbox.obj \
+ $(OBJS)\test_gui_coords.obj \
$(OBJS)\test_gui_graphmatrix.obj \
$(OBJS)\test_gui_graphpath.obj \
$(OBJS)\test_gui_config.obj \
@@ -907,6 +908,9 @@ $(OBJS)\test_gui_boundingbox.obj: .\graphics\boundingbox.cpp
$(OBJS)\test_gui_clippingbox.obj: .\graphics\clippingbox.cpp
$(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\graphics\clippingbox.cpp
+$(OBJS)\test_gui_coords.obj: .\graphics\coords.cpp
+ $(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\graphics\coords.cpp
+
$(OBJS)\test_gui_graphmatrix.obj: .\graphics\graphmatrix.cpp
$(CXX) -q -c -P -o$@ $(TEST_GUI_CXXFLAGS) .\graphics\graphmatrix.cpp
diff --git a/tests/makefile.gcc b/tests/makefile.gcc
index 88cb64af69..adfa87505e 100644
--- a/tests/makefile.gcc
+++ b/tests/makefile.gcc
@@ -163,6 +163,7 @@ TEST_GUI_OBJECTS = \
$(OBJS)\test_gui_affinematrix.o \
$(OBJS)\test_gui_boundingbox.o \
$(OBJS)\test_gui_clippingbox.o \
+ $(OBJS)\test_gui_coords.o \
$(OBJS)\test_gui_graphmatrix.o \
$(OBJS)\test_gui_graphpath.o \
$(OBJS)\test_gui_config.o \
@@ -892,6 +893,9 @@ $(OBJS)\test_gui_boundingbox.o: ./graphics/boundingbox.cpp
$(OBJS)\test_gui_clippingbox.o: ./graphics/clippingbox.cpp
$(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<
+$(OBJS)\test_gui_coords.o: ./graphics/coords.cpp
+ $(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<
+
$(OBJS)\test_gui_graphmatrix.o: ./graphics/graphmatrix.cpp
$(CXX) -c -o $@ $(TEST_GUI_CXXFLAGS) $(CPPDEPS) $<
diff --git a/tests/makefile.vc b/tests/makefile.vc
index 990d47e105..4ba6a5643d 100644
--- a/tests/makefile.vc
+++ b/tests/makefile.vc
@@ -177,6 +177,7 @@ TEST_GUI_OBJECTS = \
$(OBJS)\test_gui_affinematrix.obj \
$(OBJS)\test_gui_boundingbox.obj \
$(OBJS)\test_gui_clippingbox.obj \
+ $(OBJS)\test_gui_coords.obj \
$(OBJS)\test_gui_graphmatrix.obj \
$(OBJS)\test_gui_graphpath.obj \
$(OBJS)\test_gui_config.obj \
@@ -1320,6 +1321,9 @@ $(OBJS)\test_gui_boundingbox.obj: .\graphics\boundingbox.cpp
$(OBJS)\test_gui_clippingbox.obj: .\graphics\clippingbox.cpp
$(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\graphics\clippingbox.cpp
+$(OBJS)\test_gui_coords.obj: .\graphics\coords.cpp
+ $(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\graphics\coords.cpp
+
$(OBJS)\test_gui_graphmatrix.obj: .\graphics\graphmatrix.cpp
$(CXX) /c /nologo /TP /Fo$@ $(TEST_GUI_CXXFLAGS) .\graphics\graphmatrix.cpp
diff --git a/tests/test.bkl b/tests/test.bkl
index 2588593b05..74d0cc1c50 100644
--- a/tests/test.bkl
+++ b/tests/test.bkl
@@ -181,6 +181,7 @@
graphics/affinematrix.cpp
graphics/boundingbox.cpp
graphics/clippingbox.cpp
+ graphics/coords.cpp
graphics/graphmatrix.cpp
graphics/graphpath.cpp
config/config.cpp
diff --git a/tests/test_gui.vcxproj b/tests/test_gui.vcxproj
index 754fdb8d44..7032b4ce33 100644
--- a/tests/test_gui.vcxproj
+++ b/tests/test_gui.vcxproj
@@ -547,6 +547,7 @@
+
diff --git a/tests/test_gui.vcxproj.filters b/tests/test_gui.vcxproj.filters
index e61c1bf4fd..0eede89fd6 100644
--- a/tests/test_gui.vcxproj.filters
+++ b/tests/test_gui.vcxproj.filters
@@ -293,6 +293,9 @@
Source Files
+
+ Source Files
+
Source Files
diff --git a/tests/test_vc7_test_gui.vcproj b/tests/test_vc7_test_gui.vcproj
index f18a1a38ce..ec237145b5 100644
--- a/tests/test_vc7_test_gui.vcproj
+++ b/tests/test_vc7_test_gui.vcproj
@@ -358,6 +358,9 @@
+
+
diff --git a/tests/test_vc8_test_gui.vcproj b/tests/test_vc8_test_gui.vcproj
index ccc8576f4a..dd1700c187 100644
--- a/tests/test_vc8_test_gui.vcproj
+++ b/tests/test_vc8_test_gui.vcproj
@@ -914,6 +914,10 @@
RelativePath=".\config\config.cpp"
>
+
+
diff --git a/tests/test_vc9_test_gui.vcproj b/tests/test_vc9_test_gui.vcproj
index c9c6d5a4e8..ff01099d23 100644
--- a/tests/test_vc9_test_gui.vcproj
+++ b/tests/test_vc9_test_gui.vcproj
@@ -886,6 +886,10 @@
RelativePath=".\config\config.cpp"
>
+
+