29void QTransform::do_map(qreal x, qreal y, qreal &nx, qreal &ny)
const
259QTransform QTransform::adjoint()
const
264 h11 = m_matrix[1][1] * m_matrix[2][2] - m_matrix[1][2] * m_matrix[2][1];
265 h21 = m_matrix[1][2] * m_matrix[2][0] - m_matrix[1][0] * m_matrix[2][2];
266 h31 = m_matrix[1][0] * m_matrix[2][1] - m_matrix[1][1] * m_matrix[2][0];
267 h12 = m_matrix[0][2] * m_matrix[2][1] - m_matrix[0][1] * m_matrix[2][2];
268 h22 = m_matrix[0][0] * m_matrix[2][2] - m_matrix[0][2] * m_matrix[2][0];
269 h32 = m_matrix[0][1] * m_matrix[2][0] - m_matrix[0][0] * m_matrix[2][1];
270 h13 = m_matrix[0][1] * m_matrix[1][2] - m_matrix[0][2] * m_matrix[1][1];
271 h23 = m_matrix[0][2] * m_matrix[1][0] - m_matrix[0][0] * m_matrix[1][2];
272 h33 = m_matrix[0][0] * m_matrix[1][1] - m_matrix[0][1] * m_matrix[1][0];
274 return QTransform(h11, h12, h13,
282QTransform QTransform::transposed()
const
284 QTransform t(m_matrix[0][0], m_matrix[1][0], m_matrix[2][0],
285 m_matrix[0][1], m_matrix[1][1], m_matrix[2][1],
286 m_matrix[0][2], m_matrix[1][2], m_matrix[2][2]);
300QTransform QTransform::inverted(
bool *invertible)
const
305 switch(inline_type()) {
309 invert.m_matrix[2][0] = -m_matrix[2][0];
310 invert.m_matrix[2][1] = -m_matrix[2][1];
313 inv = !qFuzzyIsNull(m_matrix[0][0]);
314 inv &= !qFuzzyIsNull(m_matrix[1][1]);
316 invert.m_matrix[0][0] = 1. / m_matrix[0][0];
317 invert.m_matrix[1][1] = 1. / m_matrix[1][1];
318 invert.m_matrix[2][0] = -m_matrix[2][0] * invert.m_matrix[0][0];
319 invert.m_matrix[2][1] = -m_matrix[2][1] * invert.m_matrix[1][1];
324 qreal det = determinant();
325 inv = !qFuzzyIsNull(det);
327 invert = adjoint() / det;
336 invert.m_type = m_type;
337 invert.m_dirty = m_dirty;
349QTransform &QTransform::translate(qreal dx, qreal dy)
351 if (dx == 0 && dy == 0)
354 if (qIsNaN(dx) || qIsNaN(dy)) {
355 nanWarning(
"translate");
360 switch(inline_type()) {
366 m_matrix[2][0] += dx;
367 m_matrix[2][1] += dy;
370 m_matrix[2][0] += dx * m_matrix[0][0];
371 m_matrix[2][1] += dy * m_matrix[1][1];
374 m_matrix[2][2] += dx * m_matrix[0][2] + dy * m_matrix[1][2];
378 m_matrix[2][0] += dx * m_matrix[0][0] + dy * m_matrix[1][0];
379 m_matrix[2][1] += dy * m_matrix[1][1] + dx * m_matrix[0][1];
382 if (m_dirty < TxTranslate)
383 m_dirty = TxTranslate;
394QTransform QTransform::fromTranslate(qreal dx, qreal dy)
397 if (qIsNaN(dx) || qIsNaN(dy)) {
398 nanWarning(
"fromTranslate");
402 QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1);
403 if (dx == 0 && dy == 0)
404 transform.m_type = TxNone;
406 transform.m_type = TxTranslate;
407 transform.m_dirty = TxNone;
460QTransform QTransform::fromScale(qreal sx, qreal sy)
463 if (qIsNaN(sx) || qIsNaN(sy)) {
464 nanWarning(
"fromScale");
468 QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1);
469 if (sx == 1. && sy == 1.)
470 transform.m_type = TxNone;
472 transform.m_type = TxScale;
473 transform.m_dirty = TxNone;
483QTransform & QTransform::shear(qreal sh, qreal sv)
485 if (sh == 0 && sv == 0)
488 if (qIsNaN(sh) || qIsNaN(sv)) {
494 switch(inline_type()) {
501 m_matrix[0][1] = sv*m_matrix[1][1];
502 m_matrix[1][0] = sh*m_matrix[0][0];
505 qreal tm13 = sv * m_matrix[1][2];
506 qreal tm23 = sh * m_matrix[0][2];
507 m_matrix[0][2] += tm13;
508 m_matrix[1][2] += tm23;
513 qreal tm11 = sv * m_matrix[1][0];
514 qreal tm22 = sh * m_matrix[0][1];
515 qreal tm12 = sv * m_matrix[1][1];
516 qreal tm21 = sh * m_matrix[0][0];
517 m_matrix[0][0] += tm11;
518 m_matrix[0][1] += tm12;
519 m_matrix[1][0] += tm21;
520 m_matrix[1][1] += tm22;
524 if (m_dirty < TxShear)
550QTransform & QTransform::rotate(qreal a, Qt::Axis axis, qreal distanceToPlane)
555 if (qIsNaN(a) || qIsNaN(distanceToPlane)) {
556 nanWarning(
"rotate");
563 if (a == 90. || a == -270.)
565 else if (a == 270. || a == -90.)
570 qreal b = qDegreesToRadians(a);
575 if (axis == Qt::ZAxis) {
576 switch(inline_type()) {
579 m_matrix[0][0] = cosa;
580 m_matrix[0][1] = sina;
581 m_matrix[1][0] = -sina;
582 m_matrix[1][1] = cosa;
585 qreal tm11 = cosa * m_matrix[0][0];
586 qreal tm12 = sina * m_matrix[1][1];
587 qreal tm21 = -sina * m_matrix[0][0];
588 qreal tm22 = cosa * m_matrix[1][1];
589 m_matrix[0][0] = tm11;
590 m_matrix[0][1] = tm12;
591 m_matrix[1][0] = tm21;
592 m_matrix[1][1] = tm22;
596 qreal tm13 = cosa * m_matrix[0][2] + sina * m_matrix[1][2];
597 qreal tm23 = -sina * m_matrix[0][2] + cosa * m_matrix[1][2];
598 m_matrix[0][2] = tm13;
599 m_matrix[1][2] = tm23;
604 qreal tm11 = cosa * m_matrix[0][0] + sina * m_matrix[1][0];
605 qreal tm12 = cosa * m_matrix[0][1] + sina * m_matrix[1][1];
606 qreal tm21 = -sina * m_matrix[0][0] + cosa * m_matrix[1][0];
607 qreal tm22 = -sina * m_matrix[0][1] + cosa * m_matrix[1][1];
608 m_matrix[0][0] = tm11;
609 m_matrix[0][1] = tm12;
610 m_matrix[1][0] = tm21;
611 m_matrix[1][1] = tm22;
615 if (m_dirty < TxRotate)
618 if (!qIsNull(distanceToPlane))
619 sina /= distanceToPlane;
622 if (axis == Qt::YAxis) {
623 result.m_matrix[0][0] = cosa;
624 result.m_matrix[0][2] = -sina;
626 result.m_matrix[1][1] = cosa;
627 result.m_matrix[1][2] = -sina;
629 result.m_type = TxProject;
630 *
this = result * *
this;
675QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis, qreal distanceToPlane)
678 if (qIsNaN(a) || qIsNaN(distanceToPlane)) {
679 nanWarning(
"rotateRadians");
683 qreal sina = qSin(a);
684 qreal cosa = qCos(a);
686 if (axis == Qt::ZAxis) {
687 switch(inline_type()) {
690 m_matrix[0][0] = cosa;
691 m_matrix[0][1] = sina;
692 m_matrix[1][0] = -sina;
693 m_matrix[1][1] = cosa;
696 qreal tm11 = cosa * m_matrix[0][0];
697 qreal tm12 = sina * m_matrix[1][1];
698 qreal tm21 = -sina * m_matrix[0][0];
699 qreal tm22 = cosa * m_matrix[1][1];
700 m_matrix[0][0] = tm11;
701 m_matrix[0][1] = tm12;
702 m_matrix[1][0] = tm21;
703 m_matrix[1][1] = tm22;
707 qreal tm13 = cosa * m_matrix[0][2] + sina * m_matrix[1][2];
708 qreal tm23 = -sina * m_matrix[0][2] + cosa * m_matrix[1][2];
709 m_matrix[0][2] = tm13;
710 m_matrix[1][2] = tm23;
715 qreal tm11 = cosa * m_matrix[0][0] + sina * m_matrix[1][0];
716 qreal tm12 = cosa * m_matrix[0][1] + sina * m_matrix[1][1];
717 qreal tm21 = -sina * m_matrix[0][0] + cosa * m_matrix[1][0];
718 qreal tm22 = -sina * m_matrix[0][1] + cosa * m_matrix[1][1];
719 m_matrix[0][0] = tm11;
720 m_matrix[0][1] = tm12;
721 m_matrix[1][0] = tm21;
722 m_matrix[1][1] = tm22;
726 if (m_dirty < TxRotate)
729 if (!qIsNull(distanceToPlane))
730 sina /= distanceToPlane;
733 if (axis == Qt::YAxis) {
734 result.m_matrix[0][0] = cosa;
735 result.m_matrix[0][2] = -sina;
737 result.m_matrix[1][1] = cosa;
738 result.m_matrix[1][2] = -sina;
740 result.m_type = TxProject;
741 *
this = result * *
this;
769bool QTransform::operator==(
const QTransform &o)
const
771 return m_matrix[0][0] == o.m_matrix[0][0] &&
772 m_matrix[0][1] == o.m_matrix[0][1] &&
773 m_matrix[1][0] == o.m_matrix[1][0] &&
774 m_matrix[1][1] == o.m_matrix[1][1] &&
775 m_matrix[2][0] == o.m_matrix[2][0] &&
776 m_matrix[2][1] == o.m_matrix[2][1] &&
777 m_matrix[0][2] == o.m_matrix[0][2] &&
778 m_matrix[1][2] == o.m_matrix[1][2] &&
779 m_matrix[2][2] == o.m_matrix[2][2];
788 QtPrivate::QHashCombineWithSeed hash(seed);
789 seed = hash(seed, key.m11());
790 seed = hash(seed, key.m12());
791 seed = hash(seed, key.m21());
792 seed = hash(seed, key.m22());
793 seed = hash(seed, key.dx());
794 seed = hash(seed, key.dy());
795 seed = hash(seed, key.m13());
796 seed = hash(seed, key.m23());
797 seed = hash(seed, key.m33());
819QTransform & QTransform::operator*=(
const QTransform &o)
821 const TransformationType otherType = o.inline_type();
822 if (otherType == TxNone)
825 const TransformationType thisType = inline_type();
826 if (thisType == TxNone)
829 TransformationType t = qMax(thisType, otherType);
834 m_matrix[2][0] += o.m_matrix[2][0];
835 m_matrix[2][1] += o.m_matrix[2][1];
839 qreal m11 = m_matrix[0][0] * o.m_matrix[0][0];
840 qreal m22 = m_matrix[1][1] * o.m_matrix[1][1];
842 qreal m31 = m_matrix[2][0] * o.m_matrix[0][0] + o.m_matrix[2][0];
843 qreal m32 = m_matrix[2][1] * o.m_matrix[1][1] + o.m_matrix[2][1];
845 m_matrix[0][0] = m11;
846 m_matrix[1][1] = m22;
847 m_matrix[2][0] = m31; m_matrix[2][1] = m32;
853 qreal m11 = m_matrix[0][0] * o.m_matrix[0][0] + m_matrix[0][1] * o.m_matrix[1][0];
854 qreal m12 = m_matrix[0][0] * o.m_matrix[0][1] + m_matrix[0][1] * o.m_matrix[1][1];
856 qreal m21 = m_matrix[1][0] * o.m_matrix[0][0] + m_matrix[1][1] * o.m_matrix[1][0];
857 qreal m22 = m_matrix[1][0] * o.m_matrix[0][1] + m_matrix[1][1] * o.m_matrix[1][1];
859 qreal m31 = m_matrix[2][0] * o.m_matrix[0][0] + m_matrix[2][1] * o.m_matrix[1][0] + o.m_matrix[2][0];
860 qreal m32 = m_matrix[2][0] * o.m_matrix[0][1] + m_matrix[2][1] * o.m_matrix[1][1] + o.m_matrix[2][1];
862 m_matrix[0][0] = m11;
863 m_matrix[0][1] = m12;
864 m_matrix[1][0] = m21;
865 m_matrix[1][1] = m22;
866 m_matrix[2][0] = m31;
867 m_matrix[2][1] = m32;
872 qreal m11 = m_matrix[0][0] * o.m_matrix[0][0] + m_matrix[0][1] * o.m_matrix[1][0] + m_matrix[0][2] * o.m_matrix[2][0];
873 qreal m12 = m_matrix[0][0] * o.m_matrix[0][1] + m_matrix[0][1] * o.m_matrix[1][1] + m_matrix[0][2] * o.m_matrix[2][1];
874 qreal m13 = m_matrix[0][0] * o.m_matrix[0][2] + m_matrix[0][1] * o.m_matrix[1][2] + m_matrix[0][2] * o.m_matrix[2][2];
876 qreal m21 = m_matrix[1][0] * o.m_matrix[0][0] + m_matrix[1][1] * o.m_matrix[1][0] + m_matrix[1][2] * o.m_matrix[2][0];
877 qreal m22 = m_matrix[1][0] * o.m_matrix[0][1] + m_matrix[1][1] * o.m_matrix[1][1] + m_matrix[1][2] * o.m_matrix[2][1];
878 qreal m23 = m_matrix[1][0] * o.m_matrix[0][2] + m_matrix[1][1] * o.m_matrix[1][2] + m_matrix[1][2] * o.m_matrix[2][2];
880 qreal m31 = m_matrix[2][0] * o.m_matrix[0][0] + m_matrix[2][1] * o.m_matrix[1][0] + m_matrix[2][2] * o.m_matrix[2][0];
881 qreal m32 = m_matrix[2][0] * o.m_matrix[0][1] + m_matrix[2][1] * o.m_matrix[1][1] + m_matrix[2][2] * o.m_matrix[2][1];
882 qreal m33 = m_matrix[2][0] * o.m_matrix[0][2] + m_matrix[2][1] * o.m_matrix[1][2] + m_matrix[2][2] * o.m_matrix[2][2];
884 m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13;
885 m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23;
886 m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33;
904QTransform QTransform::operator*(
const QTransform &m)
const
906 const TransformationType otherType = m.inline_type();
907 if (otherType == TxNone)
910 const TransformationType thisType = inline_type();
911 if (thisType == TxNone)
915 TransformationType type = qMax(thisType, otherType);
920 t.m_matrix[2][0] = m_matrix[2][0] + m.m_matrix[2][0];
921 t.m_matrix[2][1] = m_matrix[2][1] + m.m_matrix[2][1];
925 qreal m11 = m_matrix[0][0] * m.m_matrix[0][0];
926 qreal m22 = m_matrix[1][1] * m.m_matrix[1][1];
928 qreal m31 = m_matrix[2][0] * m.m_matrix[0][0] + m.m_matrix[2][0];
929 qreal m32 = m_matrix[2][1] * m.m_matrix[1][1] + m.m_matrix[2][1];
931 t.m_matrix[0][0] = m11;
932 t.m_matrix[1][1] = m22;
933 t.m_matrix[2][0] = m31;
934 t.m_matrix[2][1] = m32;
940 qreal m11 = m_matrix[0][0] * m.m_matrix[0][0] + m_matrix[0][1] * m.m_matrix[1][0];
941 qreal m12 = m_matrix[0][0] * m.m_matrix[0][1] + m_matrix[0][1] * m.m_matrix[1][1];
943 qreal m21 = m_matrix[1][0] * m.m_matrix[0][0] + m_matrix[1][1] * m.m_matrix[1][0];
944 qreal m22 = m_matrix[1][0] * m.m_matrix[0][1] + m_matrix[1][1] * m.m_matrix[1][1];
946 qreal m31 = m_matrix[2][0] * m.m_matrix[0][0] + m_matrix[2][1] * m.m_matrix[1][0] + m.m_matrix[2][0];
947 qreal m32 = m_matrix[2][0] * m.m_matrix[0][1] + m_matrix[2][1] * m.m_matrix[1][1] + m.m_matrix[2][1];
949 t.m_matrix[0][0] = m11; t.m_matrix[0][1] = m12;
950 t.m_matrix[1][0] = m21; t.m_matrix[1][1] = m22;
951 t.m_matrix[2][0] = m31; t.m_matrix[2][1] = m32;
956 qreal m11 = m_matrix[0][0] * m.m_matrix[0][0] + m_matrix[0][1] * m.m_matrix[1][0] + m_matrix[0][2] * m.m_matrix[2][0];
957 qreal m12 = m_matrix[0][0] * m.m_matrix[0][1] + m_matrix[0][1] * m.m_matrix[1][1] + m_matrix[0][2] * m.m_matrix[2][1];
958 qreal m13 = m_matrix[0][0] * m.m_matrix[0][2] + m_matrix[0][1] * m.m_matrix[1][2] + m_matrix[0][2] * m.m_matrix[2][2];
960 qreal m21 = m_matrix[1][0] * m.m_matrix[0][0] + m_matrix[1][1] * m.m_matrix[1][0] + m_matrix[1][2] * m.m_matrix[2][0];
961 qreal m22 = m_matrix[1][0] * m.m_matrix[0][1] + m_matrix[1][1] * m.m_matrix[1][1] + m_matrix[1][2] * m.m_matrix[2][1];
962 qreal m23 = m_matrix[1][0] * m.m_matrix[0][2] + m_matrix[1][1] * m.m_matrix[1][2] + m_matrix[1][2] * m.m_matrix[2][2];
964 qreal m31 = m_matrix[2][0] * m.m_matrix[0][0] + m_matrix[2][1] * m.m_matrix[1][0] + m_matrix[2][2] * m.m_matrix[2][0];
965 qreal m32 = m_matrix[2][0] * m.m_matrix[0][1] + m_matrix[2][1] * m.m_matrix[1][1] + m_matrix[2][2] * m.m_matrix[2][1];
966 qreal m33 = m_matrix[2][0] * m.m_matrix[0][2] + m_matrix[2][1] * m.m_matrix[1][2] + m_matrix[2][2] * m.m_matrix[2][2];
968 t.m_matrix[0][0] = m11; t.m_matrix[0][1] = m12; t.m_matrix[0][2] = m13;
969 t.m_matrix[1][0] = m21; t.m_matrix[1][1] = m22; t.m_matrix[1][2] = m23;
970 t.m_matrix[2][0] = m31; t.m_matrix[2][1] = m32; t.m_matrix[2][2] = m33;
1204QLine QTransform::map(
const QLine &l)
const
1211 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1213 do_map(fx1, fy1, x1, y1);
1214 do_map(fx2, fy2, x2, y2);
1216 return QLine(qRound(x1), qRound(y1), qRound(x2), qRound(y2));
1230QLineF QTransform::map(
const QLineF &l)
const
1237 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1239 do_map(fx1, fy1, x1, y1);
1240 do_map(fx2, fy2, x2, y2);
1242 return QLineF(x1, y1, x2, y2);
1272QPolygonF QTransform::map(
const QPolygonF &a)
const
1274 TransformationType t = inline_type();
1275 if (t <= TxTranslate)
1276 return a.translated(m_matrix[2][0], m_matrix[2][1]);
1278 int size = a.size();
1281 const QPointF *da = a.constData();
1282 QPointF *dp = p.data();
1284 for(i = 0; i < size; ++i) {
1285 do_map(da[i].x(), da[i].y(), dp[i].rx(), dp[i].ry());
1299QPolygon QTransform::map(
const QPolygon &a)
const
1301 TransformationType t = inline_type();
1302 if (t <= TxTranslate)
1303 return a.translated(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1305 int size = a.size();
1308 const QPoint *da = a.constData();
1309 QPoint *dp = p.data();
1311 for(i = 0; i < size; ++i) {
1312 qreal nx = 0, ny = 0;
1313 do_map(da[i].x(), da[i].y(), nx, ny);
1314 dp[i].rx() = qRound(nx);
1315 dp[i].ry() = qRound(ny);
1341QRegion QTransform::map(
const QRegion &r)
const
1343 TransformationType t = inline_type();
1347 if (t == TxTranslate) {
1349 copy.translate(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1355 if (m11() < 0 || m22() < 0) {
1356 for (
const QRect &rect : r)
1357 res += qt_mapFillRect(QRectF(rect), *
this);
1359 QVarLengthArray<QRect, 32> rects;
1360 rects.reserve(r.rectCount());
1361 for (
const QRect &rect : r) {
1362 QRect nr = qt_mapFillRect(QRectF(rect), *
this);
1366 res.setRects(rects.constData(), rects.size());
1371 QPainterPath p = map(qt_regionToPath(r));
1372 return p.toFillPolygon().toPolygon();
1399static inline bool lineTo_clipped(QPainterPath &path,
const QTransform &transform,
const QPointF &a,
const QPointF &b,
1400 bool needsMoveTo,
bool needsLineTo =
true)
1402 QHomogeneousCoordinate ha = mapHomogeneous(transform, a);
1403 QHomogeneousCoordinate hb = mapHomogeneous(transform, b);
1409 const qreal t = (
Q_NEAR_CLIP - hb.w) / (ha.w - hb.w);
1411 hb.x += (ha.x - hb.x) * t;
1412 hb.y += (ha.y - hb.y) * t;
1415 const qreal t = (
Q_NEAR_CLIP - ha.w) / (hb.w - ha.w);
1417 ha.x += (hb.x - ha.x) * t;
1418 ha.y += (hb.y - ha.y) * t;
1421 const QPointF p = ha.toPoint();
1424 needsMoveTo =
false;
1431 path.moveTo(ha.toPoint());
1434 path.lineTo(hb.toPoint());
1440static inline bool cubicTo_clipped(QPainterPath &path,
const QTransform &transform,
const QPointF &a,
const QPointF &b,
const QPointF &c,
const QPointF &d,
bool needsMoveTo)
1446 qt_scaleForTransform(transform, &scale);
1448 qreal curveThreshold = scale == 0 ? qreal(0.25) : (qreal(0.25) / scale);
1450 QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(curveThreshold);
1452 for (
int i = 0; i < segment.size() - 1; ++i)
1453 if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo))
1454 needsMoveTo =
false;
1456 return !needsMoveTo;
1459static QPainterPath
mapProjective(
const QTransform &transform,
const QPainterPath &path)
1461 QPainterPath result;
1465 bool needsMoveTo =
true;
1466 for (
int i = 0; i < path.elementCount(); ++i) {
1467 switch (path.elementAt(i).type) {
1468 case QPainterPath::MoveToElement:
1469 if (i > 0 && lastMoveTo != last)
1472 lastMoveTo = path.elementAt(i);
1473 last = path.elementAt(i);
1476 case QPainterPath::LineToElement:
1478 needsMoveTo =
false;
1479 last = path.elementAt(i);
1481 case QPainterPath::CurveToElement:
1482 if (
cubicTo_clipped(result
, transform
, last
, path.elementAt(i)
, path.elementAt(i+1)
, path.elementAt(i+2)
, needsMoveTo
))
1483 needsMoveTo =
false;
1485 last = path.elementAt(i);
1492 if (path.elementCount() > 0 && lastMoveTo != last)
1495 result.setFillRule(path.fillRule());
1516QPainterPath QTransform::map(
const QPainterPath &path)
const
1518 TransformationType t = inline_type();
1519 if (t == TxNone || path.elementCount() == 0)
1523 return mapProjective(*
this, path);
1525 QPainterPath copy = path;
1527 if (t == TxTranslate) {
1528 copy.translate(m_matrix[2][0], m_matrix[2][1]);
1530 copy.setDirty(
true);
1532 for (
int i=0; i<path.elementCount(); ++i) {
1533 QPainterPath::Element &e = copy.d_ptr->elements[i];
1534 do_map(e.x, e.y, e.x, e.y);
1561QPolygon QTransform::mapToPolygon(
const QRect &rect)
const
1563 TransformationType t = inline_type();
1566 qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 };
1568 x[0] = m_matrix[0][0]*rect.x() + m_matrix[2][0];
1569 y[0] = m_matrix[1][1]*rect.y() + m_matrix[2][1];
1570 qreal w = m_matrix[0][0]*rect.width();
1571 qreal h = m_matrix[1][1]*rect.height();
1587 auto right = rect.x() + rect.width();
1588 auto bottom = rect.y() + rect.height();
1589 do_map(rect.x(), rect.y(), x[0], y[0]);
1590 do_map(right, rect.y(), x[1], y[1]);
1591 do_map(right, bottom, x[2], y[2]);
1592 do_map(rect.x(), bottom, x[3], y[3]);
1597 a.setPoints(4, qRound(x[0]), qRound(y[0]),
1598 qRound(x[1]), qRound(y[1]),
1599 qRound(x[2]), qRound(y[2]),
1600 qRound(x[3]), qRound(y[3]));
1611bool QTransform::squareToQuad(
const QPolygonF &quad, QTransform &trans)
1613 if (quad.size() != (quad.isClosed() ? 5 : 4))
1616 qreal dx0 = quad[0].x();
1617 qreal dx1 = quad[1].x();
1618 qreal dx2 = quad[2].x();
1619 qreal dx3 = quad[3].x();
1621 qreal dy0 = quad[0].y();
1622 qreal dy1 = quad[1].y();
1623 qreal dy2 = quad[2].y();
1624 qreal dy3 = quad[3].y();
1626 double ax = dx0 - dx1 + dx2 - dx3;
1627 double ay = dy0 - dy1 + dy2 - dy3;
1630 trans.setMatrix(dx1 - dx0, dy1 - dy0, 0,
1631 dx2 - dx1, dy2 - dy1, 0,
1634 double ax1 = dx1 - dx2;
1635 double ax2 = dx3 - dx2;
1636 double ay1 = dy1 - dy2;
1637 double ay2 = dy3 - dy2;
1640 double gtop = ax * ay2 - ax2 * ay;
1641 double htop = ax1 * ay - ax * ay1;
1642 double bottom = ax1 * ay2 - ax2 * ay1;
1644 double a, b, c, d, e, f, g, h;
1652 a = dx1 - dx0 + g * dx1;
1653 b = dx3 - dx0 + h * dx3;
1655 d = dy1 - dy0 + g * dy1;
1656 e = dy3 - dy0 + h * dy3;
1659 trans.setMatrix(a, d, g,
1676bool QTransform::quadToSquare(
const QPolygonF &quad, QTransform &trans)
1678 if (!squareToQuad(quad, trans))
1681 bool invertible =
false;
1682 trans = trans.inverted(&invertible);
1724void QTransform::setMatrix(qreal m11, qreal m12, qreal m13,
1725 qreal m21, qreal m22, qreal m23,
1726 qreal m31, qreal m32, qreal m33)
1728 m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13;
1729 m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23;
1730 m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33;
1732 m_dirty = TxProject;
1735QRect QTransform::mapRect(
const QRect &rect)
const
1737 TransformationType t = inline_type();
1738 if (t <= TxTranslate)
1739 return rect.translated(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
1742 int x = qRound(m_matrix[0][0] * rect.x() + m_matrix[2][0]);
1743 int y = qRound(m_matrix[1][1] * rect.y() + m_matrix[2][1]);
1744 int w = qRound(m_matrix[0][0] * rect.width());
1745 int h = qRound(m_matrix[1][1] * rect.height());
1754 return QRect(x, y, w, h);
1757 do_map(rect.left(), rect.top(), x, y);
1762 do_map(rect.right() + 1, rect.top(), x, y);
1763 xmin = qMin(xmin, x);
1764 ymin = qMin(ymin, y);
1765 xmax = qMax(xmax, x);
1766 ymax = qMax(ymax, y);
1767 do_map(rect.right() + 1, rect.bottom() + 1, x, y);
1768 xmin = qMin(xmin, x);
1769 ymin = qMin(ymin, y);
1770 xmax = qMax(xmax, x);
1771 ymax = qMax(ymax, y);
1772 do_map(rect.left(), rect.bottom() + 1, x, y);
1773 xmin = qMin(xmin, x);
1774 ymin = qMin(ymin, y);
1775 xmax = qMax(xmax, x);
1776 ymax = qMax(ymax, y);
1777 return QRectF(xmin, ymin, xmax-xmin, ymax-ymin).toRect();
1800QRectF QTransform::mapRect(
const QRectF &rect)
const
1802 TransformationType t = inline_type();
1803 if (t <= TxTranslate)
1804 return rect.translated(m_matrix[2][0], m_matrix[2][1]);
1807 qreal x = m_matrix[0][0] * rect.x() + m_matrix[2][0];
1808 qreal y = m_matrix[1][1] * rect.y() + m_matrix[2][1];
1809 qreal w = m_matrix[0][0] * rect.width();
1810 qreal h = m_matrix[1][1] * rect.height();
1819 return QRectF(x, y, w, h);
1822 do_map(rect.x(), rect.y(), x, y);
1827 do_map(rect.x() + rect.width(), rect.y(), x, y);
1828 xmin = qMin(xmin, x);
1829 ymin = qMin(ymin, y);
1830 xmax = qMax(xmax, x);
1831 ymax = qMax(ymax, y);
1832 do_map(rect.x() + rect.width(), rect.y() + rect.height(), x, y);
1833 xmin = qMin(xmin, x);
1834 ymin = qMin(ymin, y);
1835 xmax = qMax(xmax, x);
1836 ymax = qMax(ymax, y);
1837 do_map(rect.x(), rect.y() + rect.height(), x, y);
1838 xmin = qMin(xmin, x);
1839 ymin = qMin(ymin, y);
1840 xmax = qMax(xmax, x);
1841 ymax = qMax(ymax, y);
1842 return QRectF(xmin, ymin, xmax-xmin, ymax - ymin);
1903QTransform::TransformationType QTransform::type()
const
1905 if (m_dirty == TxNone || m_dirty < m_type)
1906 return static_cast<TransformationType>(m_type);
1908 switch (
static_cast<TransformationType>(m_dirty)) {
1910 if (!qFuzzyIsNull(m_matrix[0][2]) || !qFuzzyIsNull(m_matrix[1][2]) || !qFuzzyIsNull(m_matrix[2][2] - 1)) {
1917 if (!qFuzzyIsNull(m_matrix[0][1]) || !qFuzzyIsNull(m_matrix[1][0])) {
1918 const qreal dot = m_matrix[0][0] * m_matrix[1][0] + m_matrix[0][1] * m_matrix[1][1];
1919 if (qFuzzyIsNull(dot))
1927 if (!qFuzzyIsNull(m_matrix[0][0] - 1) || !qFuzzyIsNull(m_matrix[1][1] - 1)) {
1933 if (!qFuzzyIsNull(m_matrix[2][0]) || !qFuzzyIsNull(m_matrix[2][1])) {
1934 m_type = TxTranslate;
1944 return static_cast<TransformationType>(m_type);
2134 const QTransform::TransformationType type = transform.type();
2135 if (type <= QTransform::TxTranslate) {
2139 }
else if (type == QTransform::TxScale) {
2140 const qreal xScale = qAbs(transform.m11());
2141 const qreal yScale = qAbs(transform.m22());
2143 *scale = qMax(xScale, yScale);
2144 return qFuzzyCompare(xScale, yScale);
2148 const qreal xScale1 = transform.m11() * transform.m11()
2149 + transform.m21() * transform.m21();
2150 const qreal yScale1 = transform.m12() * transform.m12()
2151 + transform.m22() * transform.m22();
2154 const qreal xScale2 = transform.m11() * transform.m11()
2155 + transform.m12() * transform.m12();
2156 const qreal yScale2 = transform.m21() * transform.m21()
2157 + transform.m22() * transform.m22();
2160 if (qAbs(xScale1 - yScale1) > qAbs(xScale2 - yScale2)) {
2162 *scale = qSqrt(qMax(xScale1, yScale1));
2164 return type == QTransform::TxRotate && qFuzzyCompare(xScale1, yScale1);
2167 *scale = qSqrt(qMax(xScale2, yScale2));
2169 return type == QTransform::TxRotate && qFuzzyCompare(xScale2, yScale2);
2173QDataStream &
operator>>(QDataStream &s, QTransform::Affine &m)
2175 if (s.version() == 1) {
2176 float m11, m12, m21, m22, dx, dy;
2177 s >> m11; s >> m12; s >> m21; s >> m22; s >> dx; s >> dy;
2179 m.m_matrix[0][0] = m11;
2180 m.m_matrix[0][1] = m12;
2181 m.m_matrix[1][0] = m21;
2182 m.m_matrix[1][1] = m22;
2183 m.m_matrix[2][0] = dx;
2184 m.m_matrix[2][1] = dy;
2186 s >> m.m_matrix[0][0];
2187 s >> m.m_matrix[0][1];
2188 s >> m.m_matrix[1][0];
2189 s >> m.m_matrix[1][1];
2190 s >> m.m_matrix[2][0];
2191 s >> m.m_matrix[2][1];
2193 m.m_matrix[0][2] = 0;
2194 m.m_matrix[1][2] = 0;
2195 m.m_matrix[2][2] = 1;