diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index df57d2c190e..6326fd4e27e 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -26,40 +26,38 @@ static void nanWarning(const char *func) #define Q_NEAR_CLIP (sizeof(qreal) == sizeof(double) ? 0.000001 : 0.0001) -#ifdef MAP -# undef MAP -#endif -#define MAP(x, y, nx, ny) \ - do { \ - qreal FX_ = x; \ - qreal FY_ = y; \ - switch(t) { \ - case TxNone: \ - nx = FX_; \ - ny = FY_; \ - break; \ - case TxTranslate: \ - nx = FX_ + m_matrix[2][0]; \ - ny = FY_ + m_matrix[2][1]; \ - break; \ - case TxScale: \ - nx = m_matrix[0][0] * FX_ + m_matrix[2][0]; \ - ny = m_matrix[1][1] * FY_ + m_matrix[2][1]; \ - break; \ - case TxRotate: \ - case TxShear: \ - case TxProject: \ - nx = m_matrix[0][0] * FX_ + m_matrix[1][0] * FY_ + m_matrix[2][0]; \ - ny = m_matrix[0][1] * FX_ + m_matrix[1][1] * FY_ + m_matrix[2][1]; \ - if (t == TxProject) { \ - qreal w = (m_matrix[0][2] * FX_ + m_matrix[1][2] * FY_ + m_matrix[2][2]); \ - if (w < qreal(Q_NEAR_CLIP)) w = qreal(Q_NEAR_CLIP); \ - w = qreal(1.)/w; \ - nx *= w; \ - ny *= w; \ - } \ - } \ - } while (0) +void QTransform::do_map(qreal x, qreal y, qreal &nx, qreal &ny) const +{ + const TransformationType t = inline_type(); + switch (t) { + case QTransform::TxNone: + nx = x; + ny = y; + return; + case QTransform::TxTranslate: + nx = x + m_matrix[2][0]; + ny = y + m_matrix[2][1]; + return; + case QTransform::TxScale: + nx = m_matrix[0][0] * x + m_matrix[2][0]; + ny = m_matrix[1][1] * y + m_matrix[2][1]; + return; + case QTransform::TxRotate: + case QTransform::TxShear: + case QTransform::TxProject: + nx = m_matrix[0][0] * x + m_matrix[1][0] * y + m_matrix[2][0]; + ny = m_matrix[0][1] * x + m_matrix[1][1] * y + m_matrix[2][1]; + if (t == QTransform::TxProject) { + qreal w = (m_matrix[0][2] * x + m_matrix[1][2] * y + m_matrix[2][2]); + if (w < qreal(Q_NEAR_CLIP)) w = qreal(Q_NEAR_CLIP); + w = qreal(1.)/w; + nx *= w; + ny *= w; + } + return; + } + Q_UNREACHABLE_RETURN(); +} /*! \class QTransform @@ -1144,8 +1142,7 @@ QPoint QTransform::map(const QPoint &p) const qreal x = 0, y = 0; - TransformationType t = inline_type(); - MAP(fx, fy, x, y); + do_map(fx, fy, x, y); return QPoint(qRound(x), qRound(y)); } @@ -1173,8 +1170,7 @@ QPointF QTransform::map(const QPointF &p) const qreal x = 0, y = 0; - TransformationType t = inline_type(); - MAP(fx, fy, x, y); + do_map(fx, fy, x, y); return QPointF(x, y); } @@ -1222,9 +1218,8 @@ QLine QTransform::map(const QLine &l) const qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0; - TransformationType t = inline_type(); - MAP(fx1, fy1, x1, y1); - MAP(fx2, fy2, x2, y2); + do_map(fx1, fy1, x1, y1); + do_map(fx2, fy2, x2, y2); return QLine(qRound(x1), qRound(y1), qRound(x2), qRound(y2)); } @@ -1249,9 +1244,8 @@ QLineF QTransform::map(const QLineF &l) const qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0; - TransformationType t = inline_type(); - MAP(fx1, fy1, x1, y1); - MAP(fx2, fy2, x2, y2); + do_map(fx1, fy1, x1, y1); + do_map(fx2, fy2, x2, y2); return QLineF(x1, y1, x2, y2); } @@ -1296,7 +1290,7 @@ QPolygonF QTransform::map(const QPolygonF &a) const QPointF *dp = p.data(); for(i = 0; i < size; ++i) { - MAP(da[i].xp, da[i].yp, dp[i].xp, dp[i].yp); + do_map(da[i].xp, da[i].yp, dp[i].xp, dp[i].yp); } return p; } @@ -1324,7 +1318,7 @@ QPolygon QTransform::map(const QPolygon &a) const for(i = 0; i < size; ++i) { qreal nx = 0, ny = 0; - MAP(da[i].xp, da[i].yp, nx, ny); + do_map(da[i].xp, da[i].yp, nx, ny); dp[i].xp = qRound(nx); dp[i].yp = qRound(ny); } @@ -1545,7 +1539,7 @@ QPainterPath QTransform::map(const QPainterPath &path) const // Full xform for (int i=0; ielements[i]; - MAP(e.x, e.y, e.x, e.y); + do_map(e.x, e.y, e.x, e.y); } } @@ -1598,12 +1592,12 @@ QPolygon QTransform::mapToPolygon(const QRect &rect) const y[2] = y[0]+h; y[3] = y[2]; } else { - qreal right = rect.x() + rect.width(); - qreal bottom = rect.y() + rect.height(); - MAP(rect.x(), rect.y(), x[0], y[0]); - MAP(right, rect.y(), x[1], y[1]); - MAP(right, bottom, x[2], y[2]); - MAP(rect.x(), bottom, x[3], y[3]); + auto right = rect.x() + rect.width(); + auto bottom = rect.y() + rect.height(); + do_map(rect.x(), rect.y(), x[0], y[0]); + do_map(right, rect.y(), x[1], y[1]); + do_map(right, bottom, x[2], y[2]); + do_map(rect.x(), bottom, x[3], y[3]); } // all coordinates are correctly, transform to a pointarray @@ -1768,22 +1762,22 @@ QRect QTransform::mapRect(const QRect &rect) const return QRect(x, y, w, h); } else { qreal x = 0, y = 0; - MAP(rect.left(), rect.top(), x, y); + do_map(rect.left(), rect.top(), x, y); qreal xmin = x; qreal ymin = y; qreal xmax = x; qreal ymax = y; - MAP(rect.right() + 1, rect.top(), x, y); + do_map(rect.right() + 1, rect.top(), x, y); xmin = qMin(xmin, x); ymin = qMin(ymin, y); xmax = qMax(xmax, x); ymax = qMax(ymax, y); - MAP(rect.right() + 1, rect.bottom() + 1, x, y); + do_map(rect.right() + 1, rect.bottom() + 1, x, y); xmin = qMin(xmin, x); ymin = qMin(ymin, y); xmax = qMax(xmax, x); ymax = qMax(ymax, y); - MAP(rect.left(), rect.bottom() + 1, x, y); + do_map(rect.left(), rect.bottom() + 1, x, y); xmin = qMin(xmin, x); ymin = qMin(ymin, y); xmax = qMax(xmax, x); @@ -1833,22 +1827,22 @@ QRectF QTransform::mapRect(const QRectF &rect) const return QRectF(x, y, w, h); } else { qreal x = 0, y = 0; - MAP(rect.x(), rect.y(), x, y); + do_map(rect.x(), rect.y(), x, y); qreal xmin = x; qreal ymin = y; qreal xmax = x; qreal ymax = y; - MAP(rect.x() + rect.width(), rect.y(), x, y); + do_map(rect.x() + rect.width(), rect.y(), x, y); xmin = qMin(xmin, x); ymin = qMin(ymin, y); xmax = qMax(xmax, x); ymax = qMax(ymax, y); - MAP(rect.x() + rect.width(), rect.y() + rect.height(), x, y); + do_map(rect.x() + rect.width(), rect.y() + rect.height(), x, y); xmin = qMin(xmin, x); ymin = qMin(ymin, y); xmax = qMax(xmax, x); ymax = qMax(ymax, y); - MAP(rect.x(), rect.y() + rect.height(), x, y); + do_map(rect.x(), rect.y() + rect.height(), x, y); xmin = qMin(xmin, x); ymin = qMin(ymin, y); xmax = qMax(xmax, x); @@ -1883,8 +1877,7 @@ QRectF QTransform::mapRect(const QRectF &rect) const */ void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty) const { - TransformationType t = inline_type(); - MAP(x, y, *tx, *ty); + do_map(x, y, *tx, *ty); } /*! @@ -1897,9 +1890,8 @@ void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty) const */ void QTransform::map(int x, int y, int *tx, int *ty) const { - TransformationType t = inline_type(); qreal fx = 0, fy = 0; - MAP(x, y, fx, fy); + do_map(x, y, fx, fy); *tx = qRound(fx); *ty = qRound(fy); } diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h index e5b245d8c9a..3a858383373 100644 --- a/src/gui/painting/qtransform.h +++ b/src/gui/painting/qtransform.h @@ -145,6 +145,7 @@ public: private: inline TransformationType inline_type() const; + void do_map(qreal x, qreal y, qreal &nx, qreal &ny) const; qreal m_matrix[3][3]; mutable uint m_type : 5; diff --git a/tests/auto/gui/painting/qtransform/tst_qtransform.cpp b/tests/auto/gui/painting/qtransform/tst_qtransform.cpp index 428174bfc6f..9da3cb568dd 100644 --- a/tests/auto/gui/painting/qtransform/tst_qtransform.cpp +++ b/tests/auto/gui/painting/qtransform/tst_qtransform.cpp @@ -34,6 +34,7 @@ private slots: void projectivePathMapping(); void mapInt(); void mapPathWithPoint(); + void mapRectToPolygon(); // QTBUG-127723 private: void mapping_data(); @@ -700,6 +701,19 @@ void tst_QTransform::mapPathWithPoint() QCOMPARE(p.currentPosition(), QPointF(20, 20)); } +void tst_QTransform::mapRectToPolygon() +{ + QRectF r(7, 7, 36, 36); + QTransform tx(2, 0, 0, 2, 0, 0); + QPolygonF polygon1 = tx.mapToPolygon(r.toRect()).toPolygonF(); + QPolygonF polygon2 = tx.map(QPolygonF(r)); + if (polygon1.size() > 4) + polygon1.removeLast(); + if (polygon2.size() > 4) + polygon2.removeLast(); + QCOMPARE(polygon1, polygon2); +} + QTEST_APPLESS_MAIN(tst_QTransform)