diff --git a/autotests/output_transform_test.cpp b/autotests/output_transform_test.cpp index 8746d6e119..12c4fe1d1c 100644 --- a/autotests/output_transform_test.cpp +++ b/autotests/output_transform_test.cpp @@ -103,9 +103,9 @@ void TestOutputTransform::mapRectF_data() 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(140, 10, 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(140, 60, 40, 30); + 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(20, 10, 40, 30); + QTest::addRow("flip-270") << OutputTransform::Flipped270 << QRectF(10, 20, 30, 40) << QRectF(140, 60, 40, 30); } void TestOutputTransform::mapRectF() @@ -128,9 +128,9 @@ void TestOutputTransform::mapRect_data() QTest::addRow("rotate-180") << OutputTransform::Rotated180 << QRect(10, 20, 30, 40) << QRect(60, 140, 30, 40); QTest::addRow("rotate-270") << OutputTransform::Rotated270 << QRect(10, 20, 30, 40) << QRect(140, 10, 40, 30); QTest::addRow("flip-0") << OutputTransform::Flipped << QRect(10, 20, 30, 40) << QRect(60, 20, 30, 40); - QTest::addRow("flip-90") << OutputTransform::Flipped90 << QRect(10, 20, 30, 40) << QRect(140, 60, 40, 30); + QTest::addRow("flip-90") << OutputTransform::Flipped90 << QRect(10, 20, 30, 40) << QRect(20, 10, 40, 30); QTest::addRow("flip-180") << OutputTransform::Flipped180 << QRect(10, 20, 30, 40) << QRect(10, 140, 30, 40); - QTest::addRow("flip-270") << OutputTransform::Flipped270 << QRect(10, 20, 30, 40) << QRect(20, 10, 40, 30); + QTest::addRow("flip-270") << OutputTransform::Flipped270 << QRect(10, 20, 30, 40) << QRect(140, 60, 40, 30); } void TestOutputTransform::mapRect() @@ -153,9 +153,9 @@ void TestOutputTransform::mapPointF_data() QTest::addRow("rotate-180") << OutputTransform::Rotated180 << QPointF(10, 20) << QPointF(90, 180); QTest::addRow("rotate-270") << OutputTransform::Rotated270 << QPointF(10, 20) << QPointF(180, 10); QTest::addRow("flip-0") << OutputTransform::Flipped << QPointF(10, 20) << QPointF(90, 20); - QTest::addRow("flip-90") << OutputTransform::Flipped90 << QPointF(10, 20) << QPointF(180, 90); + QTest::addRow("flip-90") << OutputTransform::Flipped90 << QPointF(10, 20) << QPointF(20, 10); QTest::addRow("flip-180") << OutputTransform::Flipped180 << QPointF(10, 20) << QPointF(10, 180); - QTest::addRow("flip-270") << OutputTransform::Flipped270 << QPointF(10, 20) << QPointF(20, 10); + QTest::addRow("flip-270") << OutputTransform::Flipped270 << QPointF(10, 20) << QPointF(180, 90); } void TestOutputTransform::mapPointF() @@ -181,9 +181,9 @@ void TestOutputTransform::mapPoint_data() QTest::addRow("rotate-180") << OutputTransform::Rotated180 << QPoint(10, 20) << QPoint(90, 180); QTest::addRow("rotate-270") << OutputTransform::Rotated270 << QPoint(10, 20) << QPoint(180, 10); QTest::addRow("flip-0") << OutputTransform::Flipped << QPoint(10, 20) << QPoint(90, 20); - QTest::addRow("flip-90") << OutputTransform::Flipped90 << QPoint(10, 20) << QPoint(180, 90); + QTest::addRow("flip-90") << OutputTransform::Flipped90 << QPoint(10, 20) << QPoint(20, 10); QTest::addRow("flip-180") << OutputTransform::Flipped180 << QPoint(10, 20) << QPoint(10, 180); - QTest::addRow("flip-270") << OutputTransform::Flipped270 << QPoint(10, 20) << QPoint(20, 10); + QTest::addRow("flip-270") << OutputTransform::Flipped270 << QPoint(10, 20) << QPoint(180, 90); } void TestOutputTransform::mapPoint() @@ -240,10 +240,10 @@ void TestOutputTransform::combine_data() QTest::addRow("rotate-90 | rotate-90") << OutputTransform::Rotated90 << OutputTransform::Rotated90 << OutputTransform::Rotated180; QTest::addRow("rotate-180 | rotate-90") << OutputTransform::Rotated180 << OutputTransform::Rotated90 << OutputTransform::Rotated270; QTest::addRow("rotate-270 | rotate-90") << OutputTransform::Rotated270 << OutputTransform::Rotated90 << OutputTransform::Normal; - QTest::addRow("flip-0 | rotate-90") << OutputTransform::Flipped << OutputTransform::Rotated90 << OutputTransform::Flipped270; - QTest::addRow("flip-90 | rotate-90") << OutputTransform::Flipped90 << OutputTransform::Rotated90 << OutputTransform::Flipped; - QTest::addRow("flip-180 | rotate-90") << OutputTransform::Flipped180 << OutputTransform::Rotated90 << OutputTransform::Flipped90; - QTest::addRow("flip-270 | rotate-90") << OutputTransform::Flipped270 << OutputTransform::Rotated90 << OutputTransform::Flipped180; + QTest::addRow("flip-0 | rotate-90") << OutputTransform::Flipped << OutputTransform::Rotated90 << OutputTransform::Flipped90; + QTest::addRow("flip-90 | rotate-90") << OutputTransform::Flipped90 << OutputTransform::Rotated90 << OutputTransform::Flipped180; + QTest::addRow("flip-180 | rotate-90") << OutputTransform::Flipped180 << OutputTransform::Rotated90 << OutputTransform::Flipped270; + QTest::addRow("flip-270 | rotate-90") << OutputTransform::Flipped270 << OutputTransform::Rotated90 << OutputTransform::Flipped; QTest::addRow("rotate-0 | rotate-180") << OutputTransform::Normal << OutputTransform::Rotated180 << OutputTransform::Rotated180; QTest::addRow("rotate-90 | rotate-180") << OutputTransform::Rotated90 << OutputTransform::Rotated180 << OutputTransform::Rotated270; @@ -258,45 +258,45 @@ void TestOutputTransform::combine_data() QTest::addRow("rotate-90 | rotate-270") << OutputTransform::Rotated90 << OutputTransform::Rotated270 << OutputTransform::Normal; QTest::addRow("rotate-180 | rotate-270") << OutputTransform::Rotated180 << OutputTransform::Rotated270 << OutputTransform::Rotated90; QTest::addRow("rotate-270 | rotate-270") << OutputTransform::Rotated270 << OutputTransform::Rotated270 << OutputTransform::Rotated180; - QTest::addRow("flip-0 | rotate-270") << OutputTransform::Flipped << OutputTransform::Rotated270 << OutputTransform::Flipped90; - QTest::addRow("flip-90 | rotate-270") << OutputTransform::Flipped90 << OutputTransform::Rotated270 << OutputTransform::Flipped180; - QTest::addRow("flip-180 | rotate-270") << OutputTransform::Flipped180 << OutputTransform::Rotated270 << OutputTransform::Flipped270; - QTest::addRow("flip-270 | rotate-270") << OutputTransform::Flipped270 << OutputTransform::Rotated270 << OutputTransform::Flipped; + QTest::addRow("flip-0 | rotate-270") << OutputTransform::Flipped << OutputTransform::Rotated270 << OutputTransform::Flipped270; + QTest::addRow("flip-90 | rotate-270") << OutputTransform::Flipped90 << OutputTransform::Rotated270 << OutputTransform::Flipped; + QTest::addRow("flip-180 | rotate-270") << OutputTransform::Flipped180 << OutputTransform::Rotated270 << OutputTransform::Flipped90; + QTest::addRow("flip-270 | rotate-270") << OutputTransform::Flipped270 << OutputTransform::Rotated270 << OutputTransform::Flipped180; QTest::addRow("rotate-0 | flip-0") << OutputTransform::Normal << OutputTransform::Flipped << OutputTransform::Flipped; - QTest::addRow("rotate-90 | flip-0") << OutputTransform::Rotated90 << OutputTransform::Flipped << OutputTransform::Flipped90; + QTest::addRow("rotate-90 | flip-0") << OutputTransform::Rotated90 << OutputTransform::Flipped << OutputTransform::Flipped270; QTest::addRow("rotate-180 | flip-0") << OutputTransform::Rotated180 << OutputTransform::Flipped << OutputTransform::Flipped180; - QTest::addRow("rotate-270 | flip-0") << OutputTransform::Rotated270 << OutputTransform::Flipped << OutputTransform::Flipped270; + QTest::addRow("rotate-270 | flip-0") << OutputTransform::Rotated270 << OutputTransform::Flipped << OutputTransform::Flipped90; QTest::addRow("flip-0 | flip-0") << OutputTransform::Flipped << OutputTransform::Flipped << OutputTransform::Normal; - QTest::addRow("flip-90 | flip-0") << OutputTransform::Flipped90 << OutputTransform::Flipped << OutputTransform::Rotated90; + QTest::addRow("flip-90 | flip-0") << OutputTransform::Flipped90 << OutputTransform::Flipped << OutputTransform::Rotated270; QTest::addRow("flip-180 | flip-0") << OutputTransform::Flipped180 << OutputTransform::Flipped << OutputTransform::Rotated180; - QTest::addRow("flip-270 | flip-0") << OutputTransform::Flipped270 << OutputTransform::Flipped << OutputTransform::Rotated270; + QTest::addRow("flip-270 | flip-0") << OutputTransform::Flipped270 << OutputTransform::Flipped << OutputTransform::Rotated90; QTest::addRow("rotate-0 | flip-90") << OutputTransform::Normal << OutputTransform::Flipped90 << OutputTransform::Flipped90; - QTest::addRow("rotate-90 | flip-90") << OutputTransform::Rotated90 << OutputTransform::Flipped90 << OutputTransform::Flipped180; + QTest::addRow("rotate-90 | flip-90") << OutputTransform::Rotated90 << OutputTransform::Flipped90 << OutputTransform::Flipped; QTest::addRow("rotate-180 | flip-90") << OutputTransform::Rotated180 << OutputTransform::Flipped90 << OutputTransform::Flipped270; - QTest::addRow("rotate-270 | flip-90") << OutputTransform::Rotated270 << OutputTransform::Flipped90 << OutputTransform::Flipped; - QTest::addRow("flip-0 | flip-90") << OutputTransform::Flipped << OutputTransform::Flipped90 << OutputTransform::Rotated270; + QTest::addRow("rotate-270 | flip-90") << OutputTransform::Rotated270 << OutputTransform::Flipped90 << OutputTransform::Flipped180; + QTest::addRow("flip-0 | flip-90") << OutputTransform::Flipped << OutputTransform::Flipped90 << OutputTransform::Rotated90; QTest::addRow("flip-90 | flip-90") << OutputTransform::Flipped90 << OutputTransform::Flipped90 << OutputTransform::Normal; - QTest::addRow("flip-180 | flip-90") << OutputTransform::Flipped180 << OutputTransform::Flipped90 << OutputTransform::Rotated90; + QTest::addRow("flip-180 | flip-90") << OutputTransform::Flipped180 << OutputTransform::Flipped90 << OutputTransform::Rotated270; QTest::addRow("flip-270 | flip-90") << OutputTransform::Flipped270 << OutputTransform::Flipped90 << OutputTransform::Rotated180; QTest::addRow("rotate-0 | flip-180") << OutputTransform::Normal << OutputTransform::Flipped180 << OutputTransform::Flipped180; - QTest::addRow("rotate-90 | flip-180") << OutputTransform::Rotated90 << OutputTransform::Flipped180 << OutputTransform::Flipped270; + QTest::addRow("rotate-90 | flip-180") << OutputTransform::Rotated90 << OutputTransform::Flipped180 << OutputTransform::Flipped90; QTest::addRow("rotate-180 | flip-180") << OutputTransform::Rotated180 << OutputTransform::Flipped180 << OutputTransform::Flipped; - QTest::addRow("rotate-270 | flip-180") << OutputTransform::Rotated270 << OutputTransform::Flipped180 << OutputTransform::Flipped90; + QTest::addRow("rotate-270 | flip-180") << OutputTransform::Rotated270 << OutputTransform::Flipped180 << OutputTransform::Flipped270; QTest::addRow("flip-0 | flip-180") << OutputTransform::Flipped << OutputTransform::Flipped180 << OutputTransform::Rotated180; - QTest::addRow("flip-90 | flip-180") << OutputTransform::Flipped90 << OutputTransform::Flipped180 << OutputTransform::Rotated270; + QTest::addRow("flip-90 | flip-180") << OutputTransform::Flipped90 << OutputTransform::Flipped180 << OutputTransform::Rotated90; QTest::addRow("flip-180 | flip-180") << OutputTransform::Flipped180 << OutputTransform::Flipped180 << OutputTransform::Normal; - QTest::addRow("flip-270 | flip-180") << OutputTransform::Flipped270 << OutputTransform::Flipped180 << OutputTransform::Rotated90; + QTest::addRow("flip-270 | flip-180") << OutputTransform::Flipped270 << OutputTransform::Flipped180 << OutputTransform::Rotated270; QTest::addRow("rotate-0 | flip-270") << OutputTransform::Normal << OutputTransform::Flipped270 << OutputTransform::Flipped270; - QTest::addRow("rotate-90 | flip-270") << OutputTransform::Rotated90 << OutputTransform::Flipped270 << OutputTransform::Flipped; + QTest::addRow("rotate-90 | flip-270") << OutputTransform::Rotated90 << OutputTransform::Flipped270 << OutputTransform::Flipped180; QTest::addRow("rotate-180 | flip-270") << OutputTransform::Rotated180 << OutputTransform::Flipped270 << OutputTransform::Flipped90; - QTest::addRow("rotate-270 | flip-270") << OutputTransform::Rotated270 << OutputTransform::Flipped270 << OutputTransform::Flipped180; - QTest::addRow("flip-0 | flip-270") << OutputTransform::Flipped << OutputTransform::Flipped270 << OutputTransform::Rotated90; + QTest::addRow("rotate-270 | flip-270") << OutputTransform::Rotated270 << OutputTransform::Flipped270 << OutputTransform::Flipped; + QTest::addRow("flip-0 | flip-270") << OutputTransform::Flipped << OutputTransform::Flipped270 << OutputTransform::Rotated270; QTest::addRow("flip-90 | flip-270") << OutputTransform::Flipped90 << OutputTransform::Flipped270 << OutputTransform::Rotated180; - QTest::addRow("flip-180 | flip-270") << OutputTransform::Flipped180 << OutputTransform::Flipped270 << OutputTransform::Rotated270; + QTest::addRow("flip-180 | flip-270") << OutputTransform::Flipped180 << OutputTransform::Flipped270 << OutputTransform::Rotated90; QTest::addRow("flip-270 | flip-270") << OutputTransform::Flipped270 << OutputTransform::Flipped270 << OutputTransform::Normal; } @@ -327,9 +327,9 @@ void TestOutputTransform::matrix_data() 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(140, 10, 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(140, 60, 40, 30); + 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(20, 10, 40, 30); + QTest::addRow("flip-270") << OutputTransform::Flipped270 << QRectF(10, 20, 30, 40) << QRectF(140, 60, 40, 30); } void TestOutputTransform::matrix() diff --git a/src/core/output.cpp b/src/core/output.cpp index 3d88a37ec7..2962256c45 100644 --- a/src/core/output.cpp +++ b/src/core/output.cpp @@ -113,8 +113,8 @@ QRectF OutputTransform::map(const QRectF &rect, const QSizeF &bounds) const rect.width(), rect.height()); case Kind::Flipped90: - return QRectF(bounds.height() - (rect.y() + rect.height()), - bounds.width() - (rect.x() + rect.width()), + return QRectF(rect.y(), + rect.x(), rect.height(), rect.width()); case Kind::Flipped180: @@ -123,8 +123,8 @@ QRectF OutputTransform::map(const QRectF &rect, const QSizeF &bounds) const rect.width(), rect.height()); case Kind::Flipped270: - return QRectF(rect.y(), - rect.x(), + return QRectF(bounds.height() - (rect.y() + rect.height()), + bounds.width() - (rect.x() + rect.width()), rect.height(), rect.width()); default: @@ -158,8 +158,8 @@ QRect OutputTransform::map(const QRect &rect, const QSize &bounds) const rect.width(), rect.height()); case Kind::Flipped90: - return QRect(bounds.height() - (rect.y() + rect.height()), - bounds.width() - (rect.x() + rect.width()), + return QRect(rect.y(), + rect.x(), rect.height(), rect.width()); case Kind::Flipped180: @@ -168,8 +168,8 @@ QRect OutputTransform::map(const QRect &rect, const QSize &bounds) const rect.width(), rect.height()); case Kind::Flipped270: - return QRect(rect.y(), - rect.x(), + return QRect(bounds.height() - (rect.y() + rect.height()), + bounds.width() - (rect.x() + rect.width()), rect.height(), rect.width()); default: @@ -195,14 +195,14 @@ QPointF OutputTransform::map(const QPointF &point, const QSizeF &bounds) const return QPointF(bounds.width() - point.x(), point.y()); case Kind::Flipped90: - return QPointF(bounds.height() - point.y(), - bounds.width() - point.x()); + return QPointF(point.y(), + point.x()); case Kind::Flipped180: return QPointF(point.x(), bounds.height() - point.y()); case Kind::Flipped270: - return QPointF(point.y(), - point.x()); + return QPointF(bounds.height() - point.y(), + bounds.width() - point.x()); default: Q_UNREACHABLE(); } @@ -226,14 +226,14 @@ QPoint OutputTransform::map(const QPoint &point, const QSize &bounds) const return QPoint(bounds.width() - point.x(), point.y()); case Kind::Flipped90: - return QPoint(bounds.height() - point.y(), - bounds.width() - point.x()); + return QPoint(point.y(), + point.x()); case Kind::Flipped180: return QPoint(point.x(), bounds.height() - point.y()); case Kind::Flipped270: - return QPoint(point.y(), - point.x()); + return QPoint(bounds.height() - point.y(), + bounds.width() - point.x()); default: Q_UNREACHABLE(); } @@ -267,10 +267,30 @@ QSize OutputTransform::map(const QSize &size) const OutputTransform OutputTransform::combine(OutputTransform other) const { + // Combining a rotate-N or flip-N (mirror-x | rotate-N) transform with a rotate-M + // transform involves only adding rotation angles: + // rotate-N | rotate-M => rotate-(N + M) + // flip-N | rotate-M => mirror-x | rotate-N | rotate-M + // => mirror-x | rotate-(N + M) + // => flip-(N + M) + // + // rotate-N | mirror-x is the same as mirror-x | rotate-(360 - N). This can be used + // to derive the resulting transform if the other transform flips the x axis + // rotate-N | flip-M => rotate-N | mirror-x | rotate-M + // => mirror-x | rotate-(360 - N + M) + // => flip-(M - N) + // flip-N | flip-M => mirror-x | rotate-N | mirror-x | rotate-M + // => mirror-x | mirror-x | rotate-(360 - N + M) + // => rotate-(360 - N + M) + // => rotate-(M - N) + // + // The remaining code here relies on the bit pattern of transform enums, i.e. the + // lower two bits specify the rotation, the third bit indicates mirroring along the x axis. + const int flip = (m_kind ^ other.m_kind) & 0x4; int rotate; - if (m_kind & 0x4) { - rotate = (m_kind - other.m_kind) & 0x3; // rotate counter-clockwise if flipped + if (other.m_kind & 0x4) { + rotate = (other.m_kind - m_kind) & 0x3; } else { rotate = (m_kind + other.m_kind) & 0x3; } @@ -296,16 +316,16 @@ QMatrix4x4 OutputTransform::toMatrix() const matrix.scale(-1, 1); break; case Kind::Flipped90: - matrix.scale(-1, 1); matrix.rotate(-90, 0, 0, 1); + matrix.scale(-1, 1); break; case Kind::Flipped180: - matrix.scale(-1, 1); matrix.rotate(-180, 0, 0, 1); + matrix.scale(-1, 1); break; case Kind::Flipped270: - matrix.scale(-1, 1); matrix.rotate(-270, 0, 0, 1); + matrix.scale(-1, 1); break; default: Q_UNREACHABLE(); diff --git a/src/core/output.h b/src/core/output.h index 4f48f53626..e13be286ae 100644 --- a/src/core/output.h +++ b/src/core/output.h @@ -43,9 +43,9 @@ public: Rotated180 = 2, // rotate 180 degrees counterclockwise Rotated270 = 3, // rotate 270 degrees counterclockwise Flipped = 4, // mirror horizontally - Flipped90 = 5, // rotate 90 degrees counterclockwise, then mirror horizontally - Flipped180 = 6, // rotate 180 degrees counterclockwise, then mirror horizontally - Flipped270 = 7, // rotate 270 degrees counterclockwise, then mirror horizontally + Flipped90 = 5, // mirror horizontally, then rotate 90 degrees counterclockwise + Flipped180 = 6, // mirror horizontally, then rotate 180 degrees counterclockwise + Flipped270 = 7, // mirror horizontally, then rotate 270 degrees counterclockwise }; OutputTransform() = default;