Qt 4.8
qtransform.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include "qtransform.h"
42 
43 #include "qdatastream.h"
44 #include "qdebug.h"
45 #include "qmatrix.h"
46 #include "qregion.h"
47 #include "qpainterpath.h"
48 #include "qvariant.h"
49 #include <qmath.h>
50 #include <qnumeric.h>
51 
52 #include <private/qbezier_p.h>
53 
55 
56 #define Q_NEAR_CLIP (sizeof(qreal) == sizeof(double) ? 0.000001 : 0.0001)
57 
58 #ifdef MAP
59 # undef MAP
60 #endif
61 #define MAP(x, y, nx, ny) \
62  do { \
63  qreal FX_ = x; \
64  qreal FY_ = y; \
65  switch(t) { \
66  case TxNone: \
67  nx = FX_; \
68  ny = FY_; \
69  break; \
70  case TxTranslate: \
71  nx = FX_ + affine._dx; \
72  ny = FY_ + affine._dy; \
73  break; \
74  case TxScale: \
75  nx = affine._m11 * FX_ + affine._dx; \
76  ny = affine._m22 * FY_ + affine._dy; \
77  break; \
78  case TxRotate: \
79  case TxShear: \
80  case TxProject: \
81  nx = affine._m11 * FX_ + affine._m21 * FY_ + affine._dx; \
82  ny = affine._m12 * FX_ + affine._m22 * FY_ + affine._dy; \
83  if (t == TxProject) { \
84  qreal w = (m_13 * FX_ + m_23 * FY_ + m_33); \
85  if (w < qreal(Q_NEAR_CLIP)) w = qreal(Q_NEAR_CLIP); \
86  w = 1./w; \
87  nx *= w; \
88  ny *= w; \
89  } \
90  } \
91  } while (0)
92 
253  : affine(true)
254  , m_13(0), m_23(0), m_33(1)
255  , m_type(TxNone)
256  , m_dirty(TxNone)
257 {
258 }
259 
272  qreal h21, qreal h22, qreal h23,
273  qreal h31, qreal h32, qreal h33)
274  : affine(h11, h12, h21, h22, h31, h32, true)
275  , m_13(h13), m_23(h23), m_33(h33)
276  , m_type(TxNone)
277  , m_dirty(TxProject)
278 {
279 }
280 
292  qreal h22, qreal dx, qreal dy)
293  : affine(h11, h12, h21, h22, dx, dy, true)
294  , m_13(0), m_23(0), m_33(1)
295  , m_type(TxNone)
296  , m_dirty(TxShear)
297 {
298 }
299 
311  : affine(mtx._m11, mtx._m12, mtx._m21, mtx._m22, mtx._dx, mtx._dy, true),
312  m_13(0), m_23(0), m_33(1)
313  , m_type(TxNone)
314  , m_dirty(TxShear)
315 {
316 }
317 
322 {
323  qreal h11, h12, h13,
324  h21, h22, h23,
325  h31, h32, h33;
326  h11 = affine._m22*m_33 - m_23*affine._dy;
327  h21 = m_23*affine._dx - affine._m21*m_33;
329  h12 = m_13*affine._dy - affine._m12*m_33;
330  h22 = affine._m11*m_33 - m_13*affine._dx;
332  h13 = affine._m12*m_23 - m_13*affine._m22;
333  h23 = m_13*affine._m21 - affine._m11*m_23;
335 
336  return QTransform(h11, h12, h13,
337  h21, h22, h23,
338  h31, h32, h33, true);
339 }
340 
345 {
348  m_13, m_23, m_33, true);
349  t.m_type = m_type;
350  t.m_dirty = m_dirty;
351  return t;
352 }
353 
364 QTransform QTransform::inverted(bool *invertible) const
365 {
366  QTransform invert(true);
367  bool inv = true;
368 
369  switch(inline_type()) {
370  case TxNone:
371  break;
372  case TxTranslate:
373  invert.affine._dx = -affine._dx;
374  invert.affine._dy = -affine._dy;
375  break;
376  case TxScale:
377  inv = !qFuzzyIsNull(affine._m11);
378  inv &= !qFuzzyIsNull(affine._m22);
379  if (inv) {
380  invert.affine._m11 = 1. / affine._m11;
381  invert.affine._m22 = 1. / affine._m22;
382  invert.affine._dx = -affine._dx * invert.affine._m11;
383  invert.affine._dy = -affine._dy * invert.affine._m22;
384  }
385  break;
386  case TxRotate:
387  case TxShear:
388  invert.affine = affine.inverted(&inv);
389  break;
390  default:
391  // general case
392  qreal det = determinant();
393  inv = !qFuzzyIsNull(det);
394  if (inv)
395  invert = adjoint() / det;
396  break;
397  }
398 
399  if (invertible)
400  *invertible = inv;
401 
402  if (inv) {
403  // inverting doesn't change the type
404  invert.m_type = m_type;
405  invert.m_dirty = m_dirty;
406  }
407 
408  return invert;
409 }
410 
418 {
419  if (dx == 0 && dy == 0)
420  return *this;
421 #ifndef QT_NO_DEBUG
422  if (qIsNaN(dx) | qIsNaN(dy)) {
423  qWarning() << "QTransform::translate with NaN called";
424  return *this;
425  }
426 #endif
427 
428  switch(inline_type()) {
429  case TxNone:
430  affine._dx = dx;
431  affine._dy = dy;
432  break;
433  case TxTranslate:
434  affine._dx += dx;
435  affine._dy += dy;
436  break;
437  case TxScale:
438  affine._dx += dx*affine._m11;
439  affine._dy += dy*affine._m22;
440  break;
441  case TxProject:
442  m_33 += dx*m_13 + dy*m_23;
443  // Fall through
444  case TxShear:
445  case TxRotate:
446  affine._dx += dx*affine._m11 + dy*affine._m21;
447  affine._dy += dy*affine._m22 + dx*affine._m12;
448  break;
449  }
450  if (m_dirty < TxTranslate)
452  return *this;
453 }
454 
463 {
464 #ifndef QT_NO_DEBUG
465  if (qIsNaN(dx) | qIsNaN(dy)) {
466  qWarning() << "QTransform::fromTranslate with NaN called";
467  return QTransform();
468 }
469 #endif
470  QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1, true);
471  if (dx == 0 && dy == 0)
472  transform.m_type = TxNone;
473  else
474  transform.m_type = TxTranslate;
475  transform.m_dirty = TxNone;
476  return transform;
477 }
478 
486 {
487  if (sx == 1 && sy == 1)
488  return *this;
489 #ifndef QT_NO_DEBUG
490  if (qIsNaN(sx) | qIsNaN(sy)) {
491  qWarning() << "QTransform::scale with NaN called";
492  return *this;
493  }
494 #endif
495 
496  switch(inline_type()) {
497  case TxNone:
498  case TxTranslate:
499  affine._m11 = sx;
500  affine._m22 = sy;
501  break;
502  case TxProject:
503  m_13 *= sx;
504  m_23 *= sy;
505  // fall through
506  case TxRotate:
507  case TxShear:
508  affine._m12 *= sx;
509  affine._m21 *= sy;
510  // fall through
511  case TxScale:
512  affine._m11 *= sx;
513  affine._m22 *= sy;
514  break;
515  }
516  if (m_dirty < TxScale)
517  m_dirty = TxScale;
518  return *this;
519 }
520 
529 {
530 #ifndef QT_NO_DEBUG
531  if (qIsNaN(sx) | qIsNaN(sy)) {
532  qWarning() << "QTransform::fromScale with NaN called";
533  return QTransform();
534 }
535 #endif
536  QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1, true);
537  if (sx == 1. && sy == 1.)
538  transform.m_type = TxNone;
539  else
540  transform.m_type = TxScale;
541  transform.m_dirty = TxNone;
542  return transform;
543 }
544 
552 {
553  if (sh == 0 && sv == 0)
554  return *this;
555 #ifndef QT_NO_DEBUG
556  if (qIsNaN(sh) | qIsNaN(sv)) {
557  qWarning() << "QTransform::shear with NaN called";
558  return *this;
559  }
560 #endif
561 
562  switch(inline_type()) {
563  case TxNone:
564  case TxTranslate:
565  affine._m12 = sv;
566  affine._m21 = sh;
567  break;
568  case TxScale:
569  affine._m12 = sv*affine._m22;
570  affine._m21 = sh*affine._m11;
571  break;
572  case TxProject: {
573  qreal tm13 = sv*m_23;
574  qreal tm23 = sh*m_13;
575  m_13 += tm13;
576  m_23 += tm23;
577  }
578  // fall through
579  case TxRotate:
580  case TxShear: {
581  qreal tm11 = sv*affine._m21;
582  qreal tm22 = sh*affine._m12;
583  qreal tm12 = sv*affine._m22;
584  qreal tm21 = sh*affine._m11;
585  affine._m11 += tm11; affine._m12 += tm12;
586  affine._m21 += tm21; affine._m22 += tm22;
587  break;
588  }
589  }
590  if (m_dirty < TxShear)
591  m_dirty = TxShear;
592  return *this;
593 }
594 
595 const qreal deg2rad = qreal(0.017453292519943295769); // pi/180
596 const qreal inv_dist_to_plane = 1. / 1024.;
597 
616 {
617  if (a == 0)
618  return *this;
619 #ifndef QT_NO_DEBUG
620  if (qIsNaN(a)) {
621  qWarning() << "QTransform::rotate with NaN called";
622  return *this;
623  }
624 #endif
625 
626  qreal sina = 0;
627  qreal cosa = 0;
628  if (a == 90. || a == -270.)
629  sina = 1.;
630  else if (a == 270. || a == -90.)
631  sina = -1.;
632  else if (a == 180.)
633  cosa = -1.;
634  else{
635  qreal b = deg2rad*a; // convert to radians
636  sina = qSin(b); // fast and convenient
637  cosa = qCos(b);
638  }
639 
640  if (axis == Qt::ZAxis) {
641  switch(inline_type()) {
642  case TxNone:
643  case TxTranslate:
644  affine._m11 = cosa;
645  affine._m12 = sina;
646  affine._m21 = -sina;
647  affine._m22 = cosa;
648  break;
649  case TxScale: {
650  qreal tm11 = cosa*affine._m11;
651  qreal tm12 = sina*affine._m22;
652  qreal tm21 = -sina*affine._m11;
653  qreal tm22 = cosa*affine._m22;
654  affine._m11 = tm11; affine._m12 = tm12;
655  affine._m21 = tm21; affine._m22 = tm22;
656  break;
657  }
658  case TxProject: {
659  qreal tm13 = cosa*m_13 + sina*m_23;
660  qreal tm23 = -sina*m_13 + cosa*m_23;
661  m_13 = tm13;
662  m_23 = tm23;
663  // fall through
664  }
665  case TxRotate:
666  case TxShear: {
667  qreal tm11 = cosa*affine._m11 + sina*affine._m21;
668  qreal tm12 = cosa*affine._m12 + sina*affine._m22;
669  qreal tm21 = -sina*affine._m11 + cosa*affine._m21;
670  qreal tm22 = -sina*affine._m12 + cosa*affine._m22;
671  affine._m11 = tm11; affine._m12 = tm12;
672  affine._m21 = tm21; affine._m22 = tm22;
673  break;
674  }
675  }
676  if (m_dirty < TxRotate)
677  m_dirty = TxRotate;
678  } else {
679  QTransform result;
680  if (axis == Qt::YAxis) {
681  result.affine._m11 = cosa;
682  result.m_13 = -sina * inv_dist_to_plane;
683  } else {
684  result.affine._m22 = cosa;
685  result.m_23 = -sina * inv_dist_to_plane;
686  }
687  result.m_type = TxProject;
688  *this = result * *this;
689  }
690 
691  return *this;
692 }
693 
712 {
713 #ifndef QT_NO_DEBUG
714  if (qIsNaN(a)) {
715  qWarning() << "QTransform::rotateRadians with NaN called";
716  return *this;
717  }
718 #endif
719  qreal sina = qSin(a);
720  qreal cosa = qCos(a);
721 
722  if (axis == Qt::ZAxis) {
723  switch(inline_type()) {
724  case TxNone:
725  case TxTranslate:
726  affine._m11 = cosa;
727  affine._m12 = sina;
728  affine._m21 = -sina;
729  affine._m22 = cosa;
730  break;
731  case TxScale: {
732  qreal tm11 = cosa*affine._m11;
733  qreal tm12 = sina*affine._m22;
734  qreal tm21 = -sina*affine._m11;
735  qreal tm22 = cosa*affine._m22;
736  affine._m11 = tm11; affine._m12 = tm12;
737  affine._m21 = tm21; affine._m22 = tm22;
738  break;
739  }
740  case TxProject: {
741  qreal tm13 = cosa*m_13 + sina*m_23;
742  qreal tm23 = -sina*m_13 + cosa*m_23;
743  m_13 = tm13;
744  m_23 = tm23;
745  // fall through
746  }
747  case TxRotate:
748  case TxShear: {
749  qreal tm11 = cosa*affine._m11 + sina*affine._m21;
750  qreal tm12 = cosa*affine._m12 + sina*affine._m22;
751  qreal tm21 = -sina*affine._m11 + cosa*affine._m21;
752  qreal tm22 = -sina*affine._m12 + cosa*affine._m22;
753  affine._m11 = tm11; affine._m12 = tm12;
754  affine._m21 = tm21; affine._m22 = tm22;
755  break;
756  }
757  }
758  if (m_dirty < TxRotate)
759  m_dirty = TxRotate;
760  } else {
761  QTransform result;
762  if (axis == Qt::YAxis) {
763  result.affine._m11 = cosa;
764  result.m_13 = -sina * inv_dist_to_plane;
765  } else {
766  result.affine._m22 = cosa;
767  result.m_23 = -sina * inv_dist_to_plane;
768  }
769  result.m_type = TxProject;
770  *this = result * *this;
771  }
772  return *this;
773 }
774 
783 bool QTransform::operator==(const QTransform &o) const
784 {
785  return affine._m11 == o.affine._m11 &&
786  affine._m12 == o.affine._m12 &&
787  affine._m21 == o.affine._m21 &&
788  affine._m22 == o.affine._m22 &&
789  affine._dx == o.affine._dx &&
790  affine._dy == o.affine._dy &&
791  m_13 == o.m_13 &&
792  m_23 == o.m_23 &&
793  m_33 == o.m_33;
794 }
795 
804 bool QTransform::operator!=(const QTransform &o) const
805 {
806  return !operator==(o);
807 }
808 
817 {
818  const TransformationType otherType = o.inline_type();
819  if (otherType == TxNone)
820  return *this;
821 
822  const TransformationType thisType = inline_type();
823  if (thisType == TxNone)
824  return operator=(o);
825 
826  TransformationType t = qMax(thisType, otherType);
827  switch(t) {
828  case TxNone:
829  break;
830  case TxTranslate:
831  affine._dx += o.affine._dx;
832  affine._dy += o.affine._dy;
833  break;
834  case TxScale:
835  {
838 
841 
842  affine._m11 = m11;
843  affine._m22 = m22;
844  affine._dx = m31; affine._dy = m32;
845  break;
846  }
847  case TxRotate:
848  case TxShear:
849  {
852 
855 
858 
859  affine._m11 = m11; affine._m12 = m12;
860  affine._m21 = m21; affine._m22 = m22;
861  affine._dx = m31; affine._dy = m32;
862  break;
863  }
864  case TxProject:
865  {
869 
873 
876  qreal m33 = affine._dx*o.m_13 + affine._dy*o.m_23 + m_33*o.m_33;
877 
878  affine._m11 = m11; affine._m12 = m12; m_13 = m13;
879  affine._m21 = m21; affine._m22 = m22; m_23 = m23;
880  affine._dx = m31; affine._dy = m32; m_33 = m33;
881  }
882  }
883 
884  m_dirty = t;
885  m_type = t;
886 
887  return *this;
888 }
889 
899 {
900  const TransformationType otherType = m.inline_type();
901  if (otherType == TxNone)
902  return *this;
903 
904  const TransformationType thisType = inline_type();
905  if (thisType == TxNone)
906  return m;
907 
908  QTransform t(true);
909  TransformationType type = qMax(thisType, otherType);
910  switch(type) {
911  case TxNone:
912  break;
913  case TxTranslate:
914  t.affine._dx = affine._dx + m.affine._dx;
915  t.affine._dy += affine._dy + m.affine._dy;
916  break;
917  case TxScale:
918  {
921 
924 
925  t.affine._m11 = m11;
926  t.affine._m22 = m22;
927  t.affine._dx = m31; t.affine._dy = m32;
928  break;
929  }
930  case TxRotate:
931  case TxShear:
932  {
935 
938 
941 
942  t.affine._m11 = m11; t.affine._m12 = m12;
943  t.affine._m21 = m21; t.affine._m22 = m22;
944  t.affine._dx = m31; t.affine._dy = m32;
945  break;
946  }
947  case TxProject:
948  {
952 
956 
959  qreal m33 = affine._dx*m.m_13 + affine._dy*m.m_23 + m_33*m.m_33;
960 
961  t.affine._m11 = m11; t.affine._m12 = m12; t.m_13 = m13;
962  t.affine._m21 = m21; t.affine._m22 = m22; t.m_23 = m23;
963  t.affine._dx = m31; t.affine._dy = m32; t.m_33 = m33;
964  }
965  }
966 
967  t.m_dirty = type;
968  t.m_type = type;
969 
970  return t;
971 }
972 
1018 {
1019  affine._m11 = matrix.affine._m11;
1020  affine._m12 = matrix.affine._m12;
1021  affine._m21 = matrix.affine._m21;
1022  affine._m22 = matrix.affine._m22;
1023  affine._dx = matrix.affine._dx;
1024  affine._dy = matrix.affine._dy;
1025  m_13 = matrix.m_13;
1026  m_23 = matrix.m_23;
1027  m_33 = matrix.m_33;
1028  m_type = matrix.m_type;
1029  m_dirty = matrix.m_dirty;
1030 
1031  return *this;
1032 }
1033 
1043 {
1044  affine._m11 = affine._m22 = m_33 = 1.0;
1045  affine._m12 = m_13 = affine._m21 = m_23 = affine._dx = affine._dy = 0;
1046  m_type = TxNone;
1047  m_dirty = TxNone;
1048 }
1049 
1050 #ifndef QT_NO_DATASTREAM
1051 
1065 {
1066  s << double(m.m11())
1067  << double(m.m12())
1068  << double(m.m13())
1069  << double(m.m21())
1070  << double(m.m22())
1071  << double(m.m23())
1072  << double(m.m31())
1073  << double(m.m32())
1074  << double(m.m33());
1075  return s;
1076 }
1077 
1092 {
1093  double m11, m12, m13,
1094  m21, m22, m23,
1095  m31, m32, m33;
1096 
1097  s >> m11;
1098  s >> m12;
1099  s >> m13;
1100  s >> m21;
1101  s >> m22;
1102  s >> m23;
1103  s >> m31;
1104  s >> m32;
1105  s >> m33;
1106  t.setMatrix(m11, m12, m13,
1107  m21, m22, m23,
1108  m31, m32, m33);
1109  return s;
1110 }
1111 
1112 #endif // QT_NO_DATASTREAM
1113 
1114 #ifndef QT_NO_DEBUG_STREAM
1116 {
1117  static const char *typeStr[] =
1118  {
1119  "TxNone",
1120  "TxTranslate",
1121  "TxScale",
1122  0,
1123  "TxRotate",
1124  0, 0, 0,
1125  "TxShear",
1126  0, 0, 0, 0, 0, 0, 0,
1127  "TxProject"
1128  };
1129 
1130  dbg.nospace() << "QTransform(type=" << typeStr[m.type()] << ','
1131  << " 11=" << m.m11()
1132  << " 12=" << m.m12()
1133  << " 13=" << m.m13()
1134  << " 21=" << m.m21()
1135  << " 22=" << m.m22()
1136  << " 23=" << m.m23()
1137  << " 31=" << m.m31()
1138  << " 32=" << m.m32()
1139  << " 33=" << m.m33()
1140  << ')';
1141 
1142  return dbg.space();
1143 }
1144 #endif
1145 
1155 {
1156  qreal fx = p.x();
1157  qreal fy = p.y();
1158 
1159  qreal x = 0, y = 0;
1160 
1162  switch(t) {
1163  case TxNone:
1164  x = fx;
1165  y = fy;
1166  break;
1167  case TxTranslate:
1168  x = fx + affine._dx;
1169  y = fy + affine._dy;
1170  break;
1171  case TxScale:
1172  x = affine._m11 * fx + affine._dx;
1173  y = affine._m22 * fy + affine._dy;
1174  break;
1175  case TxRotate:
1176  case TxShear:
1177  case TxProject:
1178  x = affine._m11 * fx + affine._m21 * fy + affine._dx;
1179  y = affine._m12 * fx + affine._m22 * fy + affine._dy;
1180  if (t == TxProject) {
1181  qreal w = 1./(m_13 * fx + m_23 * fy + m_33);
1182  x *= w;
1183  y *= w;
1184  }
1185  }
1186  return QPoint(qRound(x), qRound(y));
1187 }
1188 
1189 
1209 {
1210  qreal fx = p.x();
1211  qreal fy = p.y();
1212 
1213  qreal x = 0, y = 0;
1214 
1216  switch(t) {
1217  case TxNone:
1218  x = fx;
1219  y = fy;
1220  break;
1221  case TxTranslate:
1222  x = fx + affine._dx;
1223  y = fy + affine._dy;
1224  break;
1225  case TxScale:
1226  x = affine._m11 * fx + affine._dx;
1227  y = affine._m22 * fy + affine._dy;
1228  break;
1229  case TxRotate:
1230  case TxShear:
1231  case TxProject:
1232  x = affine._m11 * fx + affine._m21 * fy + affine._dx;
1233  y = affine._m12 * fx + affine._m22 * fy + affine._dy;
1234  if (t == TxProject) {
1235  qreal w = 1./(m_13 * fx + m_23 * fy + m_33);
1236  x *= w;
1237  y *= w;
1238  }
1239  }
1240  return QPointF(x, y);
1241 }
1242 
1284 {
1285  qreal fx1 = l.x1();
1286  qreal fy1 = l.y1();
1287  qreal fx2 = l.x2();
1288  qreal fy2 = l.y2();
1289 
1290  qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1291 
1293  switch(t) {
1294  case TxNone:
1295  x1 = fx1;
1296  y1 = fy1;
1297  x2 = fx2;
1298  y2 = fy2;
1299  break;
1300  case TxTranslate:
1301  x1 = fx1 + affine._dx;
1302  y1 = fy1 + affine._dy;
1303  x2 = fx2 + affine._dx;
1304  y2 = fy2 + affine._dy;
1305  break;
1306  case TxScale:
1307  x1 = affine._m11 * fx1 + affine._dx;
1308  y1 = affine._m22 * fy1 + affine._dy;
1309  x2 = affine._m11 * fx2 + affine._dx;
1310  y2 = affine._m22 * fy2 + affine._dy;
1311  break;
1312  case TxRotate:
1313  case TxShear:
1314  case TxProject:
1315  x1 = affine._m11 * fx1 + affine._m21 * fy1 + affine._dx;
1316  y1 = affine._m12 * fx1 + affine._m22 * fy1 + affine._dy;
1317  x2 = affine._m11 * fx2 + affine._m21 * fy2 + affine._dx;
1318  y2 = affine._m12 * fx2 + affine._m22 * fy2 + affine._dy;
1319  if (t == TxProject) {
1320  qreal w = 1./(m_13 * fx1 + m_23 * fy1 + m_33);
1321  x1 *= w;
1322  y1 *= w;
1323  w = 1./(m_13 * fx2 + m_23 * fy2 + m_33);
1324  x2 *= w;
1325  y2 *= w;
1326  }
1327  }
1328  return QLine(qRound(x1), qRound(y1), qRound(x2), qRound(y2));
1329 }
1330 
1346 {
1347  qreal fx1 = l.x1();
1348  qreal fy1 = l.y1();
1349  qreal fx2 = l.x2();
1350  qreal fy2 = l.y2();
1351 
1352  qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1353 
1355  switch(t) {
1356  case TxNone:
1357  x1 = fx1;
1358  y1 = fy1;
1359  x2 = fx2;
1360  y2 = fy2;
1361  break;
1362  case TxTranslate:
1363  x1 = fx1 + affine._dx;
1364  y1 = fy1 + affine._dy;
1365  x2 = fx2 + affine._dx;
1366  y2 = fy2 + affine._dy;
1367  break;
1368  case TxScale:
1369  x1 = affine._m11 * fx1 + affine._dx;
1370  y1 = affine._m22 * fy1 + affine._dy;
1371  x2 = affine._m11 * fx2 + affine._dx;
1372  y2 = affine._m22 * fy2 + affine._dy;
1373  break;
1374  case TxRotate:
1375  case TxShear:
1376  case TxProject:
1377  x1 = affine._m11 * fx1 + affine._m21 * fy1 + affine._dx;
1378  y1 = affine._m12 * fx1 + affine._m22 * fy1 + affine._dy;
1379  x2 = affine._m11 * fx2 + affine._m21 * fy2 + affine._dx;
1380  y2 = affine._m12 * fx2 + affine._m22 * fy2 + affine._dy;
1381  if (t == TxProject) {
1382  qreal w = 1./(m_13 * fx1 + m_23 * fy1 + m_33);
1383  x1 *= w;
1384  y1 *= w;
1385  w = 1./(m_13 * fx2 + m_23 * fy2 + m_33);
1386  x2 *= w;
1387  y2 *= w;
1388  }
1389  }
1390  return QLineF(x1, y1, x2, y2);
1391 }
1392 
1393 static QPolygonF mapProjective(const QTransform &transform, const QPolygonF &poly)
1394 {
1395  if (poly.size() == 0)
1396  return poly;
1397 
1398  if (poly.size() == 1)
1399  return QPolygonF() << transform.map(poly.at(0));
1400 
1401  QPainterPath path;
1402  path.addPolygon(poly);
1403 
1404  path = transform.map(path);
1405 
1406  QPolygonF result;
1407  for (int i = 0; i < path.elementCount(); ++i)
1408  result << path.elementAt(i);
1409  return result;
1410 }
1411 
1412 
1444 {
1446  if (t <= TxTranslate)
1447  return a.translated(affine._dx, affine._dy);
1448 
1449  if (t >= QTransform::TxProject)
1450  return mapProjective(*this, a);
1451 
1452  int size = a.size();
1453  int i;
1454  QPolygonF p(size);
1455  const QPointF *da = a.constData();
1456  QPointF *dp = p.data();
1457 
1458  for(i = 0; i < size; ++i) {
1459  MAP(da[i].xp, da[i].yp, dp[i].xp, dp[i].yp);
1460  }
1461  return p;
1462 }
1463 
1477 {
1479  if (t <= TxTranslate)
1480  return a.translated(qRound(affine._dx), qRound(affine._dy));
1481 
1482  if (t >= QTransform::TxProject)
1483  return mapProjective(*this, QPolygonF(a)).toPolygon();
1484 
1485  int size = a.size();
1486  int i;
1487  QPolygon p(size);
1488  const QPoint *da = a.constData();
1489  QPoint *dp = p.data();
1490 
1491  for(i = 0; i < size; ++i) {
1492  qreal nx = 0, ny = 0;
1493  MAP(da[i].xp, da[i].yp, nx, ny);
1494  dp[i].xp = qRound(nx);
1495  dp[i].yp = qRound(ny);
1496  }
1497  return p;
1498 }
1499 
1510 
1525 {
1527  if (t == TxNone)
1528  return r;
1529 
1530  if (t == TxTranslate) {
1531  QRegion copy(r);
1533  return copy;
1534  }
1535 
1536  if (t == TxScale && r.rectCount() == 1)
1537  return QRegion(mapRect(r.boundingRect()));
1538 
1540  return p.toFillPolygon(QTransform()).toPolygon();
1541 }
1542 
1544 {
1548 
1550  QHomogeneousCoordinate(qreal x_, qreal y_, qreal w_) : x(x_), y(y_), w(w_) {}
1551 
1552  const QPointF toPoint() const {
1553  qreal iw = 1. / w;
1554  return QPointF(x * iw, y * iw);
1555  }
1556 };
1557 
1558 static inline QHomogeneousCoordinate mapHomogeneous(const QTransform &transform, const QPointF &p)
1559 {
1561  c.x = transform.m11() * p.x() + transform.m21() * p.y() + transform.m31();
1562  c.y = transform.m12() * p.x() + transform.m22() * p.y() + transform.m32();
1563  c.w = transform.m13() * p.x() + transform.m23() * p.y() + transform.m33();
1564  return c;
1565 }
1566 
1567 static inline bool lineTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b,
1568  bool needsMoveTo, bool needsLineTo = true)
1569 {
1570  QHomogeneousCoordinate ha = mapHomogeneous(transform, a);
1571  QHomogeneousCoordinate hb = mapHomogeneous(transform, b);
1572 
1573  if (ha.w < Q_NEAR_CLIP && hb.w < Q_NEAR_CLIP)
1574  return false;
1575 
1576  if (hb.w < Q_NEAR_CLIP) {
1577  const qreal t = (Q_NEAR_CLIP - hb.w) / (ha.w - hb.w);
1578 
1579  hb.x += (ha.x - hb.x) * t;
1580  hb.y += (ha.y - hb.y) * t;
1581  hb.w = qreal(Q_NEAR_CLIP);
1582  } else if (ha.w < Q_NEAR_CLIP) {
1583  const qreal t = (Q_NEAR_CLIP - ha.w) / (hb.w - ha.w);
1584 
1585  ha.x += (hb.x - ha.x) * t;
1586  ha.y += (hb.y - ha.y) * t;
1587  ha.w = qreal(Q_NEAR_CLIP);
1588 
1589  const QPointF p = ha.toPoint();
1590  if (needsMoveTo) {
1591  path.moveTo(p);
1592  needsMoveTo = false;
1593  } else {
1594  path.lineTo(p);
1595  }
1596  }
1597 
1598  if (needsMoveTo)
1599  path.moveTo(ha.toPoint());
1600 
1601  if (needsLineTo)
1602  path.lineTo(hb.toPoint());
1603 
1604  return true;
1605 }
1606 Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
1607 
1608 static inline bool cubicTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, bool needsMoveTo)
1609 {
1610  // Convert projective xformed curves to line
1611  // segments so they can be transformed more accurately
1612 
1613  qreal scale;
1614  qt_scaleForTransform(transform, &scale);
1615 
1616  qreal curveThreshold = scale == 0 ? qreal(0.25) : (qreal(0.25) / scale);
1617 
1618  QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(curveThreshold);
1619 
1620  for (int i = 0; i < segment.size() - 1; ++i)
1621  if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo))
1622  needsMoveTo = false;
1623 
1624  return !needsMoveTo;
1625 }
1626 
1627 static QPainterPath mapProjective(const QTransform &transform, const QPainterPath &path)
1628 {
1629  QPainterPath result;
1630 
1631  QPointF last;
1632  QPointF lastMoveTo;
1633  bool needsMoveTo = true;
1634  for (int i = 0; i < path.elementCount(); ++i) {
1635  switch (path.elementAt(i).type) {
1637  if (i > 0 && lastMoveTo != last)
1638  lineTo_clipped(result, transform, last, lastMoveTo, needsMoveTo);
1639 
1640  lastMoveTo = path.elementAt(i);
1641  last = path.elementAt(i);
1642  needsMoveTo = true;
1643  break;
1645  if (lineTo_clipped(result, transform, last, path.elementAt(i), needsMoveTo))
1646  needsMoveTo = false;
1647  last = path.elementAt(i);
1648  break;
1650  if (cubicTo_clipped(result, transform, last, path.elementAt(i), path.elementAt(i+1), path.elementAt(i+2), needsMoveTo))
1651  needsMoveTo = false;
1652  i += 2;
1653  last = path.elementAt(i);
1654  break;
1655  default:
1656  Q_ASSERT(false);
1657  }
1658  }
1659 
1660  if (path.elementCount() > 0 && lastMoveTo != last)
1661  lineTo_clipped(result, transform, last, lastMoveTo, needsMoveTo, false);
1662 
1663  result.setFillRule(path.fillRule());
1664  return result;
1665 }
1666 
1688 {
1690  if (t == TxNone || path.elementCount() == 0)
1691  return path;
1692 
1693  if (t >= TxProject)
1694  return mapProjective(*this, path);
1695 
1696  QPainterPath copy = path;
1697 
1698  if (t == TxTranslate) {
1699  copy.translate(affine._dx, affine._dy);
1700  } else {
1701  copy.detach();
1702  // Full xform
1703  for (int i=0; i<path.elementCount(); ++i) {
1704  QPainterPath::Element &e = copy.d_ptr->elements[i];
1705  MAP(e.x, e.y, e.x, e.y);
1706  }
1707  }
1708 
1709  return copy;
1710 }
1711 
1736 {
1738 
1739  QPolygon a(4);
1740  qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 };
1741  if (t <= TxScale) {
1742  x[0] = affine._m11*rect.x() + affine._dx;
1743  y[0] = affine._m22*rect.y() + affine._dy;
1744  qreal w = affine._m11*rect.width();
1745  qreal h = affine._m22*rect.height();
1746  if (w < 0) {
1747  w = -w;
1748  x[0] -= w;
1749  }
1750  if (h < 0) {
1751  h = -h;
1752  y[0] -= h;
1753  }
1754  x[1] = x[0]+w;
1755  x[2] = x[1];
1756  x[3] = x[0];
1757  y[1] = y[0];
1758  y[2] = y[0]+h;
1759  y[3] = y[2];
1760  } else {
1761  qreal right = rect.x() + rect.width();
1762  qreal bottom = rect.y() + rect.height();
1763  MAP(rect.x(), rect.y(), x[0], y[0]);
1764  MAP(right, rect.y(), x[1], y[1]);
1765  MAP(right, bottom, x[2], y[2]);
1766  MAP(rect.x(), bottom, x[3], y[3]);
1767  }
1768 
1769  // all coordinates are correctly, tranform to a pointarray
1770  // (rounding to the next integer)
1771  a.setPoints(4, qRound(x[0]), qRound(y[0]),
1772  qRound(x[1]), qRound(y[1]),
1773  qRound(x[2]), qRound(y[2]),
1774  qRound(x[3]), qRound(y[3]));
1775  return a;
1776 }
1777 
1786 {
1787  if (quad.count() != 4)
1788  return false;
1789 
1790  qreal dx0 = quad[0].x();
1791  qreal dx1 = quad[1].x();
1792  qreal dx2 = quad[2].x();
1793  qreal dx3 = quad[3].x();
1794 
1795  qreal dy0 = quad[0].y();
1796  qreal dy1 = quad[1].y();
1797  qreal dy2 = quad[2].y();
1798  qreal dy3 = quad[3].y();
1799 
1800  double ax = dx0 - dx1 + dx2 - dx3;
1801  double ay = dy0 - dy1 + dy2 - dy3;
1802 
1803  if (!ax && !ay) { //afine transform
1804  trans.setMatrix(dx1 - dx0, dy1 - dy0, 0,
1805  dx2 - dx1, dy2 - dy1, 0,
1806  dx0, dy0, 1);
1807  } else {
1808  double ax1 = dx1 - dx2;
1809  double ax2 = dx3 - dx2;
1810  double ay1 = dy1 - dy2;
1811  double ay2 = dy3 - dy2;
1812 
1813  /*determinants */
1814  double gtop = ax * ay2 - ax2 * ay;
1815  double htop = ax1 * ay - ax * ay1;
1816  double bottom = ax1 * ay2 - ax2 * ay1;
1817 
1818  double a, b, c, d, e, f, g, h; /*i is always 1*/
1819 
1820  if (!bottom)
1821  return false;
1822 
1823  g = gtop/bottom;
1824  h = htop/bottom;
1825 
1826  a = dx1 - dx0 + g * dx1;
1827  b = dx3 - dx0 + h * dx3;
1828  c = dx0;
1829  d = dy1 - dy0 + g * dy1;
1830  e = dy3 - dy0 + h * dy3;
1831  f = dy0;
1832 
1833  trans.setMatrix(a, d, g,
1834  b, e, h,
1835  c, f, 1.0);
1836  }
1837 
1838  return true;
1839 }
1840 
1854 {
1855  if (!squareToQuad(quad, trans))
1856  return false;
1857 
1858  bool invertible = false;
1859  trans = trans.inverted(&invertible);
1860 
1861  return invertible;
1862 }
1863 
1877  const QPolygonF &two,
1878  QTransform &trans)
1879 {
1880  QTransform stq;
1881  if (!quadToSquare(one, trans))
1882  return false;
1883  if (!squareToQuad(two, stq))
1884  return false;
1885  trans *= stq;
1886  //qDebug()<<"Final = "<<trans;
1887  return true;
1888 }
1889 
1902  qreal m21, qreal m22, qreal m23,
1903  qreal m31, qreal m32, qreal m33)
1904 {
1905  affine._m11 = m11; affine._m12 = m12; m_13 = m13;
1906  affine._m21 = m21; affine._m22 = m22; m_23 = m23;
1907  affine._dx = m31; affine._dy = m32; m_33 = m33;
1908  m_type = TxNone;
1909  m_dirty = TxProject;
1910 }
1911 
1912 static inline bool needsPerspectiveClipping(const QRectF &rect, const QTransform &transform)
1913 {
1914  const qreal wx = qMin(transform.m13() * rect.left(), transform.m13() * rect.right());
1915  const qreal wy = qMin(transform.m23() * rect.top(), transform.m23() * rect.bottom());
1916 
1917  return wx + wy + transform.m33() < Q_NEAR_CLIP;
1918 }
1919 
1920 QRect QTransform::mapRect(const QRect &rect) const
1921 {
1923  if (t <= TxTranslate)
1924  return rect.translated(qRound(affine._dx), qRound(affine._dy));
1925 
1926  if (t <= TxScale) {
1927  int x = qRound(affine._m11*rect.x() + affine._dx);
1928  int y = qRound(affine._m22*rect.y() + affine._dy);
1929  int w = qRound(affine._m11*rect.width());
1930  int h = qRound(affine._m22*rect.height());
1931  if (w < 0) {
1932  w = -w;
1933  x -= w;
1934  }
1935  if (h < 0) {
1936  h = -h;
1937  y -= h;
1938  }
1939  return QRect(x, y, w, h);
1940  } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
1941  // see mapToPolygon for explanations of the algorithm.
1942  qreal x = 0, y = 0;
1943  MAP(rect.left(), rect.top(), x, y);
1944  qreal xmin = x;
1945  qreal ymin = y;
1946  qreal xmax = x;
1947  qreal ymax = y;
1948  MAP(rect.right() + 1, rect.top(), x, y);
1949  xmin = qMin(xmin, x);
1950  ymin = qMin(ymin, y);
1951  xmax = qMax(xmax, x);
1952  ymax = qMax(ymax, y);
1953  MAP(rect.right() + 1, rect.bottom() + 1, x, y);
1954  xmin = qMin(xmin, x);
1955  ymin = qMin(ymin, y);
1956  xmax = qMax(xmax, x);
1957  ymax = qMax(ymax, y);
1958  MAP(rect.left(), rect.bottom() + 1, x, y);
1959  xmin = qMin(xmin, x);
1960  ymin = qMin(ymin, y);
1961  xmax = qMax(xmax, x);
1962  ymax = qMax(ymax, y);
1963  return QRect(qRound(xmin), qRound(ymin), qRound(xmax)-qRound(xmin), qRound(ymax)-qRound(ymin));
1964  } else {
1965  QPainterPath path;
1966  path.addRect(rect);
1967  return map(path).boundingRect().toRect();
1968  }
1969 }
1970 
1994 {
1996  if (t <= TxTranslate)
1997  return rect.translated(affine._dx, affine._dy);
1998 
1999  if (t <= TxScale) {
2000  qreal x = affine._m11*rect.x() + affine._dx;
2001  qreal y = affine._m22*rect.y() + affine._dy;
2002  qreal w = affine._m11*rect.width();
2003  qreal h = affine._m22*rect.height();
2004  if (w < 0) {
2005  w = -w;
2006  x -= w;
2007  }
2008  if (h < 0) {
2009  h = -h;
2010  y -= h;
2011  }
2012  return QRectF(x, y, w, h);
2013  } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
2014  qreal x = 0, y = 0;
2015  MAP(rect.x(), rect.y(), x, y);
2016  qreal xmin = x;
2017  qreal ymin = y;
2018  qreal xmax = x;
2019  qreal ymax = y;
2020  MAP(rect.x() + rect.width(), rect.y(), x, y);
2021  xmin = qMin(xmin, x);
2022  ymin = qMin(ymin, y);
2023  xmax = qMax(xmax, x);
2024  ymax = qMax(ymax, y);
2025  MAP(rect.x() + rect.width(), rect.y() + rect.height(), x, y);
2026  xmin = qMin(xmin, x);
2027  ymin = qMin(ymin, y);
2028  xmax = qMax(xmax, x);
2029  ymax = qMax(ymax, y);
2030  MAP(rect.x(), rect.y() + rect.height(), x, y);
2031  xmin = qMin(xmin, x);
2032  ymin = qMin(ymin, y);
2033  xmax = qMax(xmax, x);
2034  ymax = qMax(ymax, y);
2035  return QRectF(xmin, ymin, xmax-xmin, ymax - ymin);
2036  } else {
2037  QPainterPath path;
2038  path.addRect(rect);
2039  return map(path).boundingRect();
2040  }
2041 }
2042 
2070 void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty) const
2071 {
2073  MAP(x, y, *tx, *ty);
2074 }
2075 
2084 void QTransform::map(int x, int y, int *tx, int *ty) const
2085 {
2087  qreal fx = 0, fy = 0;
2088  MAP(x, y, fx, fy);
2089  *tx = qRound(fx);
2090  *ty = qRound(fy);
2091 }
2092 
2100 {
2101  return affine;
2102 }
2103 
2117 {
2118  if(m_dirty == TxNone || m_dirty < m_type)
2119  return static_cast<TransformationType>(m_type);
2120 
2121  switch (static_cast<TransformationType>(m_dirty)) {
2122  case TxProject:
2123  if (!qFuzzyIsNull(m_13) || !qFuzzyIsNull(m_23) || !qFuzzyIsNull(m_33 - 1)) {
2124  m_type = TxProject;
2125  break;
2126  }
2127  case TxShear:
2128  case TxRotate:
2130  const qreal dot = affine._m11 * affine._m12 + affine._m21 * affine._m22;
2131  if (qFuzzyIsNull(dot))
2132  m_type = TxRotate;
2133  else
2134  m_type = TxShear;
2135  break;
2136  }
2137  case TxScale:
2138  if (!qFuzzyIsNull(affine._m11 - 1) || !qFuzzyIsNull(affine._m22 - 1)) {
2139  m_type = TxScale;
2140  break;
2141  }
2142  case TxTranslate:
2144  m_type = TxTranslate;
2145  break;
2146  }
2147  case TxNone:
2148  m_type = TxNone;
2149  break;
2150  }
2151 
2152  m_dirty = TxNone;
2153  return static_cast<TransformationType>(m_type);
2154 }
2155 
2160 QTransform::operator QVariant() const
2161 {
2162  return QVariant(QVariant::Transform, this);
2163 }
2164 
2165 
2403 // returns true if the transform is uniformly scaling
2404 // (same scale in x and y direction)
2405 // scale is set to the max of x and y scaling factors
2407 bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
2408 {
2409  const QTransform::TransformationType type = transform.type();
2410  if (type <= QTransform::TxTranslate) {
2411  if (scale)
2412  *scale = 1;
2413  return true;
2414  } else if (type == QTransform::TxScale) {
2415  const qreal xScale = qAbs(transform.m11());
2416  const qreal yScale = qAbs(transform.m22());
2417  if (scale)
2418  *scale = qMax(xScale, yScale);
2419  return qFuzzyCompare(xScale, yScale);
2420  }
2421 
2422  const qreal xScale = transform.m11() * transform.m11()
2423  + transform.m21() * transform.m21();
2424  const qreal yScale = transform.m12() * transform.m12()
2425  + transform.m22() * transform.m22();
2426  if (scale)
2427  *scale = qSqrt(qMax(xScale, yScale));
2428  return type == QTransform::TxRotate && qFuzzyCompare(xScale, yScale);
2429 }
2430 
ElementType type
the type of element
Definition: qpainterpath.h:81
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:62
qreal m_13
Definition: qtransform.h:180
The QPainterPath::Element class specifies the position and type of a subpath.
Definition: qpainterpath.h:77
#define Q_NEAR_CLIP
Definition: qtransform.cpp:56
qreal y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:667
qreal dy() const
Returns the vertical translation factor.
Definition: qtransform.h:277
qreal right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:527
double qreal
Definition: qglobal.h:1193
qreal determinant() const
Returns the matrix&#39;s determinant.
Definition: qtransform.h:228
unsigned char c[8]
Definition: qnumeric_p.h:62
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QDataStream & operator<<(QDataStream &stream, const QTransform &matrix)
Writes the given matrix to the given stream and returns a reference to the stream.
void translate(qreal dx, qreal dy)
Translates all elements in the path by ({dx}, {dy}).
qreal m32() const
Returns the vertical translation factor.
Definition: qtransform.h:265
The QLine class provides a two-dimensional vector using integer precision.
Definition: qline.h:57
QPolygon translated(int dx, int dy) const
Returns a copy of the polygon that is translated by ({dx}, {dy}).
Definition: qpolygon.cpp:270
The QMatrix class specifies 2D transformations of a coordinate system.
Definition: qmatrix.h:61
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:67
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Definition: qvector.h:742
qreal x2() const
Returns the x-coordinate of the line&#39;s end point.
Definition: qline.h:304
Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
QTransform & shear(qreal sh, qreal sv)
Shears the coordinate system by sh horizontally and sv vertically, and returns a reference to the mat...
Definition: qtransform.cpp:551
QDebug & nospace()
Clears the stream&#39;s internal flag that records whether the last character was a space and returns a r...
Definition: qdebug.h:92
static const uchar inv
Definition: qisciicodec.cpp:91
#define Q_GUI_EXPORT
Definition: qglobal.h:1450
qreal m21() const
Returns the horizontal shearing factor.
Definition: qtransform.h:249
qreal y2() const
Returns the y-coordinate of the line&#39;s end point.
Definition: qline.h:309
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
qreal left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:525
void setMatrix(qreal m11, qreal m12, qreal m13, qreal m21, qreal m22, qreal m23, qreal m31, qreal m32, qreal m33)
Sets the matrix elements to the specified values, m11, m12, m13 m21, m22, m23 m31, m32 and m33.
qreal m22() const
Returns the vertical scaling factor.
Definition: qtransform.h:253
int left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:240
QRect translated(int dx, int dy) const
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis...
Definition: qrect.h:328
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
#define MAP(x, y, nx, ny)
Definition: qtransform.cpp:61
long ASN1_INTEGER_get ASN1_INTEGER * a
QRect boundingRect() const
Returns the bounding rectangle of this region.
Definition: qregion.cpp:4363
The QPolygon class provides a vector of points using integer precision.
Definition: qpolygon.h:60
const qreal deg2rad
Definition: qtransform.cpp:595
void addPolygon(const QPolygonF &polygon)
Adds the given polygon to the path as an (unclosed) subpath.
QTransform & translate(qreal dx, qreal dy)
Moves the coordinate system dx along the x axis and dy along the y axis, and returns a reference to t...
Definition: qtransform.cpp:417
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
qreal y
the y coordinate of the element&#39;s position.
Definition: qpainterpath.h:80
int bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:249
qreal _m22
Definition: qmatrix.h:144
uint m_dirty
Definition: qtransform.h:185
Q_DECL_CONSTEXPR T qAbs(const T &t)
Definition: qglobal.h:1201
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
TransformationType type() const
Returns the transformation type of this matrix.
QPolygon toPolygon() const
Creates and returns a QPolygon by converting each QPointF to a QPoint.
Definition: qpolygon.cpp:772
int y1() const
Returns the y-coordinate of the line&#39;s start point.
Definition: qline.h:117
void moveTo(const QPointF &p)
Moves the current point to the given point, implicitly starting a new subpath and closing the previou...
const QPainterPath::Element & elementAt(int i) const
Returns the element at the given index in the painter path.
Definition: qpainterpath.h:402
bool qFuzzyCompare(const QTransform &t1, const QTransform &t2)
Returns true if t1 and t2 are equal, allowing for a small fuzziness factor for floating-point compari...
Definition: qtransform.h:339
int rectCount() const
Returns the number of rectangles that will be returned in rects().
Definition: qregion.cpp:4461
Q_CORE_EXPORT QTextStream & right(QTextStream &s)
QTransform operator*(const QTransform &o) const
Returns the result of multiplying this matrix by the given matrix.
Definition: qtransform.cpp:898
static bool quadToSquare(const QPolygonF &quad, QTransform &result)
Creates a transformation matrix, trans, that maps a four-sided polygon, quad, to a unit square...
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
QTransform inverted(bool *invertible=0) const
Returns an inverted copy of this matrix.
Definition: qtransform.cpp:364
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
QPolygon mapToPolygon(const QRect &r) const
Creates and returns a QPolygon representation of the given rectangle, mapped into the coordinate syst...
The QLineF class provides a two-dimensional vector using floating point precision.
Definition: qline.h:212
qreal m_23
Definition: qtransform.h:181
void lineTo(const QPointF &p)
Adds a straight line from the current position to the given endPoint.
static QHomogeneousCoordinate mapHomogeneous(const QTransform &transform, const QPointF &p)
void setFillRule(Qt::FillRule fillRule)
Sets the fill rule of the painter path to the given fillRule.
QPolygonF translated(qreal dx, qreal dy) const
Returns a copy of the polygon that is translated by ({dx}, {dy}).
Definition: qpolygon.h:182
qreal m12() const
Returns the vertical shearing factor.
Definition: qtransform.h:241
static QBezier fromPoints(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
Definition: qbezier.cpp:71
QRect mapRect(const QRect &) const
Creates and returns a QRect object that is a copy of the given rectangle, mapped into the coordinate ...
TransformationType
Definition: qtransform.h:68
const QPointF toPoint() const
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
const QMatrix & toAffine() const
Returns the QTransform as an affine matrix.
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
QPolygonF toFillPolygon(const QMatrix &matrix=QMatrix()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
qreal qSin(qreal v)
Definition: qmath.h:93
static bool lineTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b, bool needsMoveTo, bool needsLineTo=true)
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
QTransform & rotate(qreal a, Qt::Axis axis=Qt::ZAxis)
Rotates the coordinate system counterclockwise by the given angle about the specified axis and return...
Definition: qtransform.cpp:615
qreal y1() const
Returns the y-coordinate of the line&#39;s start point.
Definition: qline.h:299
The QPolygonF class provides a vector of points using floating point precision.
Definition: qpolygon.h:134
QTransform transposed() const
Returns the transpose of this matrix.
Definition: qtransform.cpp:344
Q_CORE_EXPORT void qWarning(const char *,...)
QPoint map(const QPoint &p) const
Creates and returns a QPoint object that is a copy of the given point, mapped into the coordinate sys...
int x2() const
Returns the x-coordinate of the line&#39;s end point.
Definition: qline.h:122
void addRect(const QRectF &rect)
Adds the given rectangle to this path as a closed subpath.
qreal width() const
Returns the width of the rectangle.
Definition: qrect.h:707
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
Qt::FillRule fillRule() const
Returns the painter path&#39;s currently set fill rule.
uint m_type
Definition: qtransform.h:184
Q_CORE_EXPORT bool qIsNaN(double d)
Returns true if the double {d} is not a number (NaN).
Definition: qnumeric.cpp:55
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
qreal m31() const
Returns the horizontal translation factor.
Definition: qtransform.h:261
qreal _m12
Definition: qmatrix.h:143
int xp
Definition: qpoint.h:98
qreal det() const
Returns the matrix&#39;s determinant.
Definition: qtransform.h:233
void reset()
Resets the matrix to an identity matrix, i.e.
QTransform & operator*=(const QTransform &)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qtransform.cpp:816
const qreal inv_dist_to_plane
Definition: qtransform.cpp:596
int top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:243
static QPolygonF mapProjective(const QTransform &transform, const QPolygonF &poly)
qreal _dx
Definition: qmatrix.h:145
QPolygonF toPolygon(qreal bezier_flattening_threshold=0.5) const
Definition: qbezier.cpp:89
int right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:246
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
static bool quadToQuad(const QPolygonF &one, const QPolygonF &two, QTransform &result)
Creates a transformation matrix, trans, that maps a four-sided polygon, one, to another four-sided po...
qreal x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:664
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
qreal m_33
Definition: qtransform.h:182
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
qreal m23() const
Returns the vertical projection factor.
Definition: qtransform.h:257
qreal _dy
Definition: qmatrix.h:145
QVector< QPainterPath::Element > elements
Definition: qpainterpath.h:254
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
#define Q_AUTOTEST_EXPORT
Definition: qglobal.h:1510
QFactoryLoader * l
qreal dx() const
Returns the horizontal translation factor.
Definition: qtransform.h:273
qreal x
the x coordinate of the element&#39;s position.
Definition: qpainterpath.h:79
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
qreal top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:526
qreal _m21
Definition: qmatrix.h:144
static Q_DECL_CONSTEXPR bool qFuzzyIsNull(double d)
Definition: qglobal.h:2043
qreal _m11
Definition: qmatrix.h:143
void translate(int dx, int dy)
Translates (moves) the region dx along the X axis and dy along the Y axis.
Definition: qregion.cpp:4116
static bool squareToQuad(const QPolygonF &square, QTransform &result)
Creates a transformation matrix, trans, that maps a unit square to a four-sided polygon, quad.
T * data()
Returns a pointer to the data stored in the vector.
Definition: qvector.h:152
QDataStream & operator>>(QDataStream &stream, QTransform &matrix)
Reads the given matrix from the given stream and returns a reference to the stream.
static QTransform fromTranslate(qreal dx, qreal dy)
Creates a matrix which corresponds to a translation of dx along the x axis and dy along the y axis...
Definition: qtransform.cpp:462
void setPoints(int nPoints, const int *points)
Resizes the polygon to nPoints and populates it with the given points.
Definition: qpolygon.cpp:350
QTransform & scale(qreal sx, qreal sy)
Scales the coordinate system by sx horizontally and sy vertically, and returns a reference to the mat...
Definition: qtransform.cpp:485
static QTransform fromScale(qreal dx, qreal dy)
Creates a matrix which corresponds to a scaling of sx horizontally and sy vertically.
Definition: qtransform.cpp:528
int elementCount() const
Returns the number of path elements in the painter path.
Definition: qpainterpath.h:397
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:71
bool operator!=(const QTransform &) const
Returns true if this matrix is not equal to the given matrix, otherwise returns false.
Definition: qtransform.cpp:804
const T * constData() const
Returns a const pointer to the data stored in the vector.
Definition: qvector.h:154
int y2() const
Returns the y-coordinate of the line&#39;s end point.
Definition: qline.h:127
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
static bool cubicTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, bool needsMoveTo)
qreal m13() const
Returns the horizontal projection factor.
Definition: qtransform.h:245
qreal bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:528
QHomogeneousCoordinate(qreal x_, qreal y_, qreal w_)
QTransform()
Constructs an identity matrix.
Definition: qtransform.cpp:252
QRectF translated(qreal dx, qreal dy) const
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis...
Definition: qrect.h:740
QTransform & operator=(const QTransform &)
Assigns the given matrix&#39;s values to this matrix.
int yp
Definition: qpoint.h:97
qreal x1() const
Returns the x-coordinate of the line&#39;s start point.
Definition: qline.h:294
int x1() const
Returns the x-coordinate of the line&#39;s start point.
Definition: qline.h:112
QDebug & space()
Writes a space character to the debug stream and returns a reference to the stream.
Definition: qdebug.h:91
static qreal dot(const QPointF &a, const QPointF &b)
TransformationType inline_type() const
Definition: qtransform.h:193
bool operator==(const QTransform &) const
Returns true if this matrix is equal to the given matrix, otherwise returns false.
Definition: qtransform.cpp:783
qreal qCos(qreal v)
Definition: qmath.h:109
QTransform adjoint() const
Returns the adjoint of this matrix.
Definition: qtransform.cpp:321
qreal qSqrt(qreal v)
Definition: qmath.h:205
Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion &region)
Definition: qregion.cpp:1160
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
Private * d
Definition: qtransform.h:187
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
qreal m11() const
Returns the horizontal scaling factor.
Definition: qtransform.h:237
qreal m33() const
Returns the division factor.
Definition: qtransform.h:269
QMatrix inverted(bool *invertible=0) const
Returns an inverted copy of this matrix.
Definition: qmatrix.cpp:1066
QScopedPointer< QPainterPathPrivate, QPainterPathPrivateDeleter > d_ptr
Definition: qpainterpath.h:211
QMatrix affine
Definition: qtransform.h:179
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
static bool needsPerspectiveClipping(const QRectF &rect, const QTransform &transform)
QTransform & rotateRadians(qreal a, Qt::Axis axis=Qt::ZAxis)
Rotates the coordinate system counterclockwise by the given angle about the specified axis and return...
Definition: qtransform.cpp:711