diff --git a/autotests/output_transform_test.cpp b/autotests/output_transform_test.cpp index a6d499b3a4..2fd2de6b33 100644 --- a/autotests/output_transform_test.cpp +++ b/autotests/output_transform_test.cpp @@ -26,6 +26,8 @@ private Q_SLOTS: void inverted(); void combine_data(); void combine(); + void matrix_data(); + void matrix(); }; TestOutputTransform::TestOutputTransform() @@ -200,6 +202,46 @@ void TestOutputTransform::combine() QCOMPARE(combinedTransform.map(box, bounds), secondTransform.map(firstTransform.map(box, bounds), firstTransform.map(bounds))); } +void TestOutputTransform::matrix_data() +{ + QTest::addColumn("kind"); + QTest::addColumn("source"); + QTest::addColumn("target"); + + QTest::addRow("rotate-0") << OutputTransform::Normal << QRectF(10, 20, 30, 40) << QRectF(10, 20, 30, 40); + QTest::addRow("rotate-90") << OutputTransform::Rotated90 << QRectF(10, 20, 30, 40) << QRectF(140, 10, 40, 30); + QTest::addRow("rotate-180") << OutputTransform::Rotated180 << QRectF(10, 20, 30, 40) << QRectF(60, 140, 30, 40); + QTest::addRow("rotate-270") << OutputTransform::Rotated270 << QRectF(10, 20, 30, 40) << QRectF(20, 60, 40, 30); + QTest::addRow("flip-0") << OutputTransform::Flipped << QRectF(10, 20, 30, 40) << QRectF(60, 20, 30, 40); + QTest::addRow("flip-90") << OutputTransform::Flipped90 << QRectF(10, 20, 30, 40) << QRectF(20, 10, 40, 30); + QTest::addRow("flip-180") << OutputTransform::Flipped180 << QRectF(10, 20, 30, 40) << QRectF(10, 140, 30, 40); + QTest::addRow("flip-270") << OutputTransform::Flipped270 << QRectF(10, 20, 30, 40) << QRectF(140, 60, 40, 30); +} + +void TestOutputTransform::matrix() +{ + QFETCH(OutputTransform::Kind, kind); + QFETCH(QRectF, source); + QFETCH(QRectF, target); + + const OutputTransform transform = kind; + const QSizeF sourceBounds = QSizeF(100, 200); + const QSizeF targetBounds = transform.map(sourceBounds); + + QMatrix4x4 matrix; + matrix.scale(targetBounds.width(), targetBounds.height()); + matrix.translate(0.5, 0.5); + matrix.scale(0.5, -0.5); + matrix.scale(1, -1); // flip the y axis back + matrix *= transform.toMatrix(); + matrix.scale(1, -1); // undo ortho() flipping the y axis + matrix.ortho(QRectF(0, 0, sourceBounds.width(), sourceBounds.height())); + + const QRectF mapped = matrix.mapRect(source); + QCOMPARE(mapped, target); + QCOMPARE(mapped, transform.map(source, sourceBounds)); +} + QTEST_MAIN(TestOutputTransform) #include "output_transform_test.moc" diff --git a/src/core/output.cpp b/src/core/output.cpp index 7be9137d21..ae909c9018 100644 --- a/src/core/output.cpp +++ b/src/core/output.cpp @@ -168,6 +168,42 @@ OutputTransform OutputTransform::combine(OutputTransform other) const return OutputTransform(Kind(flip | rotate)); } +QMatrix4x4 OutputTransform::toMatrix() const +{ + QMatrix4x4 matrix; + switch (m_kind) { + case Kind::Normal: + break; + case Kind::Rotated90: + matrix.rotate(90, 0, 0, 1); + break; + case Kind::Rotated180: + matrix.rotate(180, 0, 0, 1); + break; + case Kind::Rotated270: + matrix.rotate(270, 0, 0, 1); + break; + case Kind::Flipped: + matrix.scale(-1, 1); + break; + case Kind::Flipped90: + matrix.scale(-1, 1); + matrix.rotate(90, 0, 0, 1); + break; + case Kind::Flipped180: + matrix.scale(-1, 1); + matrix.rotate(180, 0, 0, 1); + break; + case Kind::Flipped270: + matrix.scale(-1, 1); + matrix.rotate(270, 0, 0, 1); + break; + default: + Q_UNREACHABLE(); + } + return matrix; +} + Output::Output(QObject *parent) : QObject(parent) { diff --git a/src/core/output.h b/src/core/output.h index 2f027378ce..6bc30fda7a 100644 --- a/src/core/output.h +++ b/src/core/output.h @@ -83,6 +83,11 @@ public: */ OutputTransform combine(OutputTransform other) const; + /** + * Returns the matrix corresponding to this output transform. + */ + QMatrix4x4 toMatrix() const; + private: Kind m_kind = Kind::Normal; };