1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
41 #include "qtransform.h"
43 #include "qdatastream.h"
47 #include "qpainterpath.h"
48 #include "qpainterpath_p.h"
53 #include <private/qbezier_p.h>
57 #define Q_NEAR_CLIP (sizeof(qreal) == sizeof(double) ? 0.000001 : 0.0001)
62 #define MAP(x, y, nx, ny) \
72 nx = FX_ + affine._dx; \
73 ny = FY_ + affine._dy; \
76 nx = affine._m11 * FX_ + affine._dx; \
77 ny = affine._m22 * FY_ + affine._dy; \
82 nx = affine._m11 * FX_ + affine._m21 * FY_ + affine._dx; \
83 ny = affine._m12 * FX_ + affine._m22 * FY_ + affine._dy; \
84 if (t == TxProject) { \
85 qreal w = (m_13 * FX_ + m_23 * FY_ + m_33); \
86 if (w < qreal(Q_NEAR_CLIP)) w = qreal(Q_NEAR_CLIP); \
96 \brief The QTransform class specifies 2D transformations of a coordinate system.
100 A transformation specifies how to translate, scale, shear, rotate
101 or project the coordinate system, and is typically used when
104 QTransform differs from QMatrix in that it is a true 3x3 matrix,
105 allowing perspective transformations. QTransform's toAffine()
106 method allows casting QTransform to QMatrix. If a perspective
107 transformation has been specified on the matrix, then the
108 conversion will cause loss of data.
110 QTransform is the recommended transformation class in Qt.
112 A QTransform object can be built using the setMatrix(), scale(),
113 rotate(), translate() and shear() functions. Alternatively, it
114 can be built by applying \l {QTransform#Basic Matrix
115 Operations}{basic matrix operations}. The matrix can also be
116 defined when constructed, and it can be reset to the identity
117 matrix (the default) using the reset() function.
119 The QTransform class supports mapping of graphic primitives: A given
120 point, line, polygon, region, or painter path can be mapped to the
121 coordinate system defined by \e this matrix using the map()
122 function. In case of a rectangle, its coordinates can be
123 transformed using the mapRect() function. A rectangle can also be
124 transformed into a \e polygon (mapped to the coordinate system
125 defined by \e this matrix), using the mapToPolygon() function.
127 QTransform provides the isIdentity() function which returns true if
128 the matrix is the identity matrix, and the isInvertible() function
129 which returns true if the matrix is non-singular (i.e. AB = BA =
130 I). The inverted() function returns an inverted copy of \e this
131 matrix if it is invertible (otherwise it returns the identity
132 matrix), and adjoint() returns the matrix's classical adjoint.
133 In addition, QTransform provides the determinant() function which
134 returns the matrix's determinant.
136 Finally, the QTransform class supports matrix multiplication, addition
137 and subtraction, and objects of the class can be streamed as well
142 \section1 Rendering Graphics
144 When rendering graphics, the matrix defines the transformations
145 but the actual transformation is performed by the drawing routines
148 By default, QPainter operates on the associated device's own
149 coordinate system. The standard coordinate system of a
150 QPaintDevice has its origin located at the top-left position. The
151 \e x values increase to the right; \e y values increase
152 downward. For a complete description, see the \l {Coordinate
153 System} {coordinate system} documentation.
155 QPainter has functions to translate, scale, shear and rotate the
156 coordinate system without using a QTransform. For example:
160 \li \inlineimage qtransform-simpletransformation.png
162 \snippet transform/main.cpp 0
165 Although these functions are very convenient, it can be more
166 efficient to build a QTransform and call QPainter::setTransform() if you
167 want to perform more than a single transform operation. For
172 \li \inlineimage qtransform-combinedtransformation.png
174 \snippet transform/main.cpp 1
177 \section1 Basic Matrix Operations
179 \image qtransform-representation.png
181 A QTransform object contains a 3 x 3 matrix. The \c m31 (\c dx) and
182 \c m32 (\c dy) elements specify horizontal and vertical translation.
183 The \c m11 and \c m22 elements specify horizontal and vertical scaling.
184 The \c m21 and \c m12 elements specify horizontal and vertical \e shearing.
185 And finally, the \c m13 and \c m23 elements specify horizontal and vertical
186 projection, with \c m33 as an additional projection factor.
188 QTransform transforms a point in the plane to another point using the
191 \snippet code/src_gui_painting_qtransform.cpp 0
193 The point \e (x, y) is the original point, and \e (x', y') is the
194 transformed point. \e (x', y') can be transformed back to \e (x,
195 y) by performing the same operation on the inverted() matrix.
197 The various matrix elements can be set when constructing the
198 matrix, or by using the setMatrix() function later on. They can also
199 be manipulated using the translate(), rotate(), scale() and
200 shear() convenience functions. The currently set values can be
201 retrieved using the m11(), m12(), m13(), m21(), m22(), m23(),
202 m31(), m32(), m33(), dx() and dy() functions.
204 Translation is the simplest transformation. Setting \c dx and \c
205 dy will move the coordinate system \c dx units along the X axis
206 and \c dy units along the Y axis. Scaling can be done by setting
207 \c m11 and \c m22. For example, setting \c m11 to 2 and \c m22 to
208 1.5 will double the height and increase the width by 50%. The
209 identity matrix has \c m11, \c m22, and \c m33 set to 1 (all others are set
210 to 0) mapping a point to itself. Shearing is controlled by \c m12
211 and \c m21. Setting these elements to values different from zero
212 will twist the coordinate system. Rotation is achieved by
213 setting both the shearing factors and the scaling factors. Perspective
214 transformation is achieved by setting both the projection factors and
217 Here's the combined transformations example using basic matrix
222 \li \inlineimage qtransform-combinedtransformation2.png
224 \snippet transform/main.cpp 2
227 \sa QPainter, {Coordinate System}, {painting/affine}{Affine
228 Transformations Example}, {Transformations Example}
232 \enum QTransform::TransformationType
243 \fn QTransform::QTransform(Qt::Initialization)
248 Constructs an identity matrix.
250 All elements are set to zero except \c m11 and \c m22 (specifying
251 the scale) and \c m13 which are set to 1.
255 QTransform::QTransform()
257 , m_13(0), m_23(0), m_33(1)
264 \fn QTransform::QTransform(qreal m11, qreal m12, qreal m13, qreal m21, qreal m22, qreal m23, qreal m31, qreal m32, qreal m33)
266 Constructs a matrix with the elements, \a m11, \a m12, \a m13,
267 \a m21, \a m22, \a m23, \a m31, \a m32, \a m33.
271 QTransform::QTransform(qreal h11, qreal h12, qreal h13,
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)
282 \fn QTransform::QTransform(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy)
284 Constructs a matrix with the elements, \a m11, \a m12, \a m21, \a m22, \a dx and \a dy.
288 QTransform::QTransform(qreal h11, qreal h12, qreal h21,
289 qreal h22, qreal dx, qreal dy)
290 : affine(h11, h12, h21, h22, dx, dy, true)
291 , m_13(0), m_23(0), m_33(1)
298 \fn QTransform::QTransform(const QMatrix &matrix)
300 Constructs a matrix that is a copy of the given \a matrix.
301 Note that the \c m13, \c m23, and \c m33 elements are set to 0, 0,
304 QTransform::QTransform(const QMatrix &mtx)
305 : affine(mtx._m11, mtx._m12, mtx._m21, mtx._m22, mtx._dx, mtx._dy, true),
306 m_13(0), m_23(0), m_33(1)
313 Returns the adjoint of this matrix.
315 QTransform QTransform::adjoint() const
320 h11 = affine._m22*m_33 - m_23*affine._dy;
321 h21 = m_23*affine._dx - affine._m21*m_33;
322 h31 = affine._m21*affine._dy - affine._m22*affine._dx;
323 h12 = m_13*affine._dy - affine._m12*m_33;
324 h22 = affine._m11*m_33 - m_13*affine._dx;
325 h32 = affine._m12*affine._dx - affine._m11*affine._dy;
326 h13 = affine._m12*m_23 - m_13*affine._m22;
327 h23 = m_13*affine._m21 - affine._m11*m_23;
328 h33 = affine._m11*affine._m22 - affine._m12*affine._m21;
330 return QTransform(h11, h12, h13,
332 h31, h32, h33, true);
336 Returns the transpose of this matrix.
338 QTransform QTransform::transposed() const
340 QTransform t(affine._m11, affine._m21, affine._dx,
341 affine._m12, affine._m22, affine._dy,
342 m_13, m_23, m_33, true);
349 Returns an inverted copy of this matrix.
351 If the matrix is singular (not invertible), the returned matrix is
352 the identity matrix. If \a invertible is valid (i.e. not 0), its
353 value is set to true if the matrix is invertible, otherwise it is
358 QTransform QTransform::inverted(bool *invertible) const
360 QTransform invert(true);
363 switch(inline_type()) {
367 invert.affine._dx = -affine._dx;
368 invert.affine._dy = -affine._dy;
371 inv = !qFuzzyIsNull(affine._m11);
372 inv &= !qFuzzyIsNull(affine._m22);
374 invert.affine._m11 = 1. / affine._m11;
375 invert.affine._m22 = 1. / affine._m22;
376 invert.affine._dx = -affine._dx * invert.affine._m11;
377 invert.affine._dy = -affine._dy * invert.affine._m22;
382 invert.affine = affine.inverted(&inv);
386 qreal det = determinant();
387 inv = !qFuzzyIsNull(det);
389 invert = adjoint() / det;
397 // inverting doesn't change the type
398 invert.m_type = m_type;
399 invert.m_dirty = m_dirty;
406 Moves the coordinate system \a dx along the x axis and \a dy along
407 the y axis, and returns a reference to the matrix.
411 QTransform &QTransform::translate(qreal dx, qreal dy)
413 if (dx == 0 && dy == 0)
416 if (qIsNaN(dx) | qIsNaN(dy)) {
417 qWarning() << "QTransform::translate with NaN called";
422 switch(inline_type()) {
432 affine._dx += dx*affine._m11;
433 affine._dy += dy*affine._m22;
436 m_33 += dx*m_13 + dy*m_23;
440 affine._dx += dx*affine._m11 + dy*affine._m21;
441 affine._dy += dy*affine._m22 + dx*affine._m12;
444 if (m_dirty < TxTranslate)
445 m_dirty = TxTranslate;
450 Creates a matrix which corresponds to a translation of \a dx along
451 the x axis and \a dy along the y axis. This is the same as
452 QTransform().translate(dx, dy) but slightly faster.
456 QTransform QTransform::fromTranslate(qreal dx, qreal dy)
459 if (qIsNaN(dx) | qIsNaN(dy)) {
460 qWarning() << "QTransform::fromTranslate with NaN called";
464 QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1, true);
465 if (dx == 0 && dy == 0)
466 transform.m_type = TxNone;
468 transform.m_type = TxTranslate;
469 transform.m_dirty = TxNone;
474 Scales the coordinate system by \a sx horizontally and \a sy
475 vertically, and returns a reference to the matrix.
479 QTransform & QTransform::scale(qreal sx, qreal sy)
481 if (sx == 1 && sy == 1)
484 if (qIsNaN(sx) | qIsNaN(sy)) {
485 qWarning() << "QTransform::scale with NaN called";
490 switch(inline_type()) {
510 if (m_dirty < TxScale)
516 Creates a matrix which corresponds to a scaling of
517 \a sx horizontally and \a sy vertically.
518 This is the same as QTransform().scale(sx, sy) but slightly faster.
522 QTransform QTransform::fromScale(qreal sx, qreal sy)
525 if (qIsNaN(sx) | qIsNaN(sy)) {
526 qWarning() << "QTransform::fromScale with NaN called";
530 QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1, true);
531 if (sx == 1. && sy == 1.)
532 transform.m_type = TxNone;
534 transform.m_type = TxScale;
535 transform.m_dirty = TxNone;
540 Shears the coordinate system by \a sh horizontally and \a sv
541 vertically, and returns a reference to the matrix.
545 QTransform & QTransform::shear(qreal sh, qreal sv)
547 if (sh == 0 && sv == 0)
550 if (qIsNaN(sh) | qIsNaN(sv)) {
551 qWarning() << "QTransform::shear with NaN called";
556 switch(inline_type()) {
563 affine._m12 = sv*affine._m22;
564 affine._m21 = sh*affine._m11;
567 qreal tm13 = sv*m_23;
568 qreal tm23 = sh*m_13;
575 qreal tm11 = sv*affine._m21;
576 qreal tm22 = sh*affine._m12;
577 qreal tm12 = sv*affine._m22;
578 qreal tm21 = sh*affine._m11;
579 affine._m11 += tm11; affine._m12 += tm12;
580 affine._m21 += tm21; affine._m22 += tm22;
584 if (m_dirty < TxShear)
589 const qreal deg2rad = qreal(0.017453292519943295769); // pi/180
590 const qreal inv_dist_to_plane = 1. / 1024.;
593 \fn QTransform &QTransform::rotate(qreal angle, Qt::Axis axis)
595 Rotates the coordinate system counterclockwise by the given \a angle
596 about the specified \a axis and returns a reference to the matrix.
598 Note that if you apply a QTransform to a point defined in widget
599 coordinates, the direction of the rotation will be clockwise
600 because the y-axis points downwards.
602 The angle is specified in degrees.
606 QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
612 qWarning() << "QTransform::rotate with NaN called";
619 if (a == 90. || a == -270.)
621 else if (a == 270. || a == -90.)
626 qreal b = deg2rad*a; // convert to radians
627 sina = qSin(b); // fast and convenient
631 if (axis == Qt::ZAxis) {
632 switch(inline_type()) {
641 qreal tm11 = cosa*affine._m11;
642 qreal tm12 = sina*affine._m22;
643 qreal tm21 = -sina*affine._m11;
644 qreal tm22 = cosa*affine._m22;
645 affine._m11 = tm11; affine._m12 = tm12;
646 affine._m21 = tm21; affine._m22 = tm22;
650 qreal tm13 = cosa*m_13 + sina*m_23;
651 qreal tm23 = -sina*m_13 + cosa*m_23;
658 qreal tm11 = cosa*affine._m11 + sina*affine._m21;
659 qreal tm12 = cosa*affine._m12 + sina*affine._m22;
660 qreal tm21 = -sina*affine._m11 + cosa*affine._m21;
661 qreal tm22 = -sina*affine._m12 + cosa*affine._m22;
662 affine._m11 = tm11; affine._m12 = tm12;
663 affine._m21 = tm21; affine._m22 = tm22;
667 if (m_dirty < TxRotate)
671 if (axis == Qt::YAxis) {
672 result.affine._m11 = cosa;
673 result.m_13 = -sina * inv_dist_to_plane;
675 result.affine._m22 = cosa;
676 result.m_23 = -sina * inv_dist_to_plane;
678 result.m_type = TxProject;
679 *this = result * *this;
686 \fn QTransform & QTransform::rotateRadians(qreal angle, Qt::Axis axis)
688 Rotates the coordinate system counterclockwise by the given \a angle
689 about the specified \a axis and returns a reference to the matrix.
691 Note that if you apply a QTransform to a point defined in widget
692 coordinates, the direction of the rotation will be clockwise
693 because the y-axis points downwards.
695 The angle is specified in radians.
699 QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
703 qWarning() << "QTransform::rotateRadians with NaN called";
707 qreal sina = qSin(a);
708 qreal cosa = qCos(a);
710 if (axis == Qt::ZAxis) {
711 switch(inline_type()) {
720 qreal tm11 = cosa*affine._m11;
721 qreal tm12 = sina*affine._m22;
722 qreal tm21 = -sina*affine._m11;
723 qreal tm22 = cosa*affine._m22;
724 affine._m11 = tm11; affine._m12 = tm12;
725 affine._m21 = tm21; affine._m22 = tm22;
729 qreal tm13 = cosa*m_13 + sina*m_23;
730 qreal tm23 = -sina*m_13 + cosa*m_23;
737 qreal tm11 = cosa*affine._m11 + sina*affine._m21;
738 qreal tm12 = cosa*affine._m12 + sina*affine._m22;
739 qreal tm21 = -sina*affine._m11 + cosa*affine._m21;
740 qreal tm22 = -sina*affine._m12 + cosa*affine._m22;
741 affine._m11 = tm11; affine._m12 = tm12;
742 affine._m21 = tm21; affine._m22 = tm22;
746 if (m_dirty < TxRotate)
750 if (axis == Qt::YAxis) {
751 result.affine._m11 = cosa;
752 result.m_13 = -sina * inv_dist_to_plane;
754 result.affine._m22 = cosa;
755 result.m_23 = -sina * inv_dist_to_plane;
757 result.m_type = TxProject;
758 *this = result * *this;
764 \fn bool QTransform::operator==(const QTransform &matrix) const
765 Returns true if this matrix is equal to the given \a matrix,
766 otherwise returns false.
768 bool QTransform::operator==(const QTransform &o) const
770 return affine._m11 == o.affine._m11 &&
771 affine._m12 == o.affine._m12 &&
772 affine._m21 == o.affine._m21 &&
773 affine._m22 == o.affine._m22 &&
774 affine._dx == o.affine._dx &&
775 affine._dy == o.affine._dy &&
782 \fn bool QTransform::operator!=(const QTransform &matrix) const
783 Returns true if this matrix is not equal to the given \a matrix,
784 otherwise returns false.
786 bool QTransform::operator!=(const QTransform &o) const
788 return !operator==(o);
792 \fn QTransform & QTransform::operator*=(const QTransform &matrix)
795 Returns the result of multiplying this matrix by the given \a
798 QTransform & QTransform::operator*=(const QTransform &o)
800 const TransformationType otherType = o.inline_type();
801 if (otherType == TxNone)
804 const TransformationType thisType = inline_type();
805 if (thisType == TxNone)
808 TransformationType t = qMax(thisType, otherType);
813 affine._dx += o.affine._dx;
814 affine._dy += o.affine._dy;
818 qreal m11 = affine._m11*o.affine._m11;
819 qreal m22 = affine._m22*o.affine._m22;
821 qreal m31 = affine._dx*o.affine._m11 + o.affine._dx;
822 qreal m32 = affine._dy*o.affine._m22 + o.affine._dy;
826 affine._dx = m31; affine._dy = m32;
832 qreal m11 = affine._m11*o.affine._m11 + affine._m12*o.affine._m21;
833 qreal m12 = affine._m11*o.affine._m12 + affine._m12*o.affine._m22;
835 qreal m21 = affine._m21*o.affine._m11 + affine._m22*o.affine._m21;
836 qreal m22 = affine._m21*o.affine._m12 + affine._m22*o.affine._m22;
838 qreal m31 = affine._dx*o.affine._m11 + affine._dy*o.affine._m21 + o.affine._dx;
839 qreal m32 = affine._dx*o.affine._m12 + affine._dy*o.affine._m22 + o.affine._dy;
841 affine._m11 = m11; affine._m12 = m12;
842 affine._m21 = m21; affine._m22 = m22;
843 affine._dx = m31; affine._dy = m32;
848 qreal m11 = affine._m11*o.affine._m11 + affine._m12*o.affine._m21 + m_13*o.affine._dx;
849 qreal m12 = affine._m11*o.affine._m12 + affine._m12*o.affine._m22 + m_13*o.affine._dy;
850 qreal m13 = affine._m11*o.m_13 + affine._m12*o.m_23 + m_13*o.m_33;
852 qreal m21 = affine._m21*o.affine._m11 + affine._m22*o.affine._m21 + m_23*o.affine._dx;
853 qreal m22 = affine._m21*o.affine._m12 + affine._m22*o.affine._m22 + m_23*o.affine._dy;
854 qreal m23 = affine._m21*o.m_13 + affine._m22*o.m_23 + m_23*o.m_33;
856 qreal m31 = affine._dx*o.affine._m11 + affine._dy*o.affine._m21 + m_33*o.affine._dx;
857 qreal m32 = affine._dx*o.affine._m12 + affine._dy*o.affine._m22 + m_33*o.affine._dy;
858 qreal m33 = affine._dx*o.m_13 + affine._dy*o.m_23 + m_33*o.m_33;
860 affine._m11 = m11; affine._m12 = m12; m_13 = m13;
861 affine._m21 = m21; affine._m22 = m22; m_23 = m23;
862 affine._dx = m31; affine._dy = m32; m_33 = m33;
873 \fn QTransform QTransform::operator*(const QTransform &matrix) const
874 Returns the result of multiplying this matrix by the given \a
877 Note that matrix multiplication is not commutative, i.e. a*b !=
880 QTransform QTransform::operator*(const QTransform &m) const
882 const TransformationType otherType = m.inline_type();
883 if (otherType == TxNone)
886 const TransformationType thisType = inline_type();
887 if (thisType == TxNone)
891 TransformationType type = qMax(thisType, otherType);
896 t.affine._dx = affine._dx + m.affine._dx;
897 t.affine._dy += affine._dy + m.affine._dy;
901 qreal m11 = affine._m11*m.affine._m11;
902 qreal m22 = affine._m22*m.affine._m22;
904 qreal m31 = affine._dx*m.affine._m11 + m.affine._dx;
905 qreal m32 = affine._dy*m.affine._m22 + m.affine._dy;
909 t.affine._dx = m31; t.affine._dy = m32;
915 qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21;
916 qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22;
918 qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21;
919 qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22;
921 qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m.affine._dx;
922 qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m.affine._dy;
924 t.affine._m11 = m11; t.affine._m12 = m12;
925 t.affine._m21 = m21; t.affine._m22 = m22;
926 t.affine._dx = m31; t.affine._dy = m32;
931 qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21 + m_13*m.affine._dx;
932 qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22 + m_13*m.affine._dy;
933 qreal m13 = affine._m11*m.m_13 + affine._m12*m.m_23 + m_13*m.m_33;
935 qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21 + m_23*m.affine._dx;
936 qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22 + m_23*m.affine._dy;
937 qreal m23 = affine._m21*m.m_13 + affine._m22*m.m_23 + m_23*m.m_33;
939 qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m_33*m.affine._dx;
940 qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m_33*m.affine._dy;
941 qreal m33 = affine._dx*m.m_13 + affine._dy*m.m_23 + m_33*m.m_33;
943 t.affine._m11 = m11; t.affine._m12 = m12; t.m_13 = m13;
944 t.affine._m21 = m21; t.affine._m22 = m22; t.m_23 = m23;
945 t.affine._dx = m31; t.affine._dy = m32; t.m_33 = m33;
956 \fn QTransform & QTransform::operator*=(qreal scalar)
959 Returns the result of performing an element-wise multiplication of this
960 matrix with the given \a scalar.
964 \fn QTransform & QTransform::operator/=(qreal scalar)
967 Returns the result of performing an element-wise division of this
968 matrix by the given \a scalar.
972 \fn QTransform & QTransform::operator+=(qreal scalar)
975 Returns the matrix obtained by adding the given \a scalar to each
976 element of this matrix.
980 \fn QTransform & QTransform::operator-=(qreal scalar)
983 Returns the matrix obtained by subtracting the given \a scalar from each
984 element of this matrix.
988 Assigns the given \a matrix's values to this matrix.
990 QTransform & QTransform::operator=(const QTransform &matrix)
992 affine._m11 = matrix.affine._m11;
993 affine._m12 = matrix.affine._m12;
994 affine._m21 = matrix.affine._m21;
995 affine._m22 = matrix.affine._m22;
996 affine._dx = matrix.affine._dx;
997 affine._dy = matrix.affine._dy;
1001 m_type = matrix.m_type;
1002 m_dirty = matrix.m_dirty;
1008 Resets the matrix to an identity matrix, i.e. all elements are set
1009 to zero, except \c m11 and \c m22 (specifying the scale) and \c m33
1012 \sa QTransform(), isIdentity(), {QTransform#Basic Matrix
1013 Operations}{Basic Matrix Operations}
1015 void QTransform::reset()
1017 affine._m11 = affine._m22 = m_33 = 1.0;
1018 affine._m12 = m_13 = affine._m21 = m_23 = affine._dx = affine._dy = 0;
1023 #ifndef QT_NO_DATASTREAM
1025 \fn QDataStream &operator<<(QDataStream &stream, const QTransform &matrix)
1029 Writes the given \a matrix to the given \a stream and returns a
1030 reference to the stream.
1032 \sa {Serializing Qt Data Types}
1034 QDataStream & operator<<(QDataStream &s, const QTransform &m)
1036 s << double(m.m11())
1049 \fn QDataStream &operator>>(QDataStream &stream, QTransform &matrix)
1053 Reads the given \a matrix from the given \a stream and returns a
1054 reference to the stream.
1056 \sa {Serializing Qt Data Types}
1058 QDataStream & operator>>(QDataStream &s, QTransform &t)
1060 double m11, m12, m13,
1073 t.setMatrix(m11, m12, m13,
1079 #endif // QT_NO_DATASTREAM
1081 #ifndef QT_NO_DEBUG_STREAM
1082 QDebug operator<<(QDebug dbg, const QTransform &m)
1084 static const char *typeStr[] =
1093 0, 0, 0, 0, 0, 0, 0,
1097 dbg.nospace() << "QTransform(type=" << typeStr[m.type()] << ','
1098 << " 11=" << m.m11()
1099 << " 12=" << m.m12()
1100 << " 13=" << m.m13()
1101 << " 21=" << m.m21()
1102 << " 22=" << m.m22()
1103 << " 23=" << m.m23()
1104 << " 31=" << m.m31()
1105 << " 32=" << m.m32()
1106 << " 33=" << m.m33()
1114 \fn QPoint operator*(const QPoint &point, const QTransform &matrix)
1117 This is the same as \a{matrix}.map(\a{point}).
1119 \sa QTransform::map()
1121 QPoint QTransform::map(const QPoint &p) const
1128 TransformationType t = inline_type();
1135 x = fx + affine._dx;
1136 y = fy + affine._dy;
1139 x = affine._m11 * fx + affine._dx;
1140 y = affine._m22 * fy + affine._dy;
1145 x = affine._m11 * fx + affine._m21 * fy + affine._dx;
1146 y = affine._m12 * fx + affine._m22 * fy + affine._dy;
1147 if (t == TxProject) {
1148 qreal w = 1./(m_13 * fx + m_23 * fy + m_33);
1153 return QPoint(qRound(x), qRound(y));
1158 \fn QPointF operator*(const QPointF &point, const QTransform &matrix)
1161 Same as \a{matrix}.map(\a{point}).
1163 \sa QTransform::map()
1169 Creates and returns a QPointF object that is a copy of the given point,
1170 \a p, mapped into the coordinate system defined by this matrix.
1172 QPointF QTransform::map(const QPointF &p) const
1179 TransformationType t = inline_type();
1186 x = fx + affine._dx;
1187 y = fy + affine._dy;
1190 x = affine._m11 * fx + affine._dx;
1191 y = affine._m22 * fy + affine._dy;
1196 x = affine._m11 * fx + affine._m21 * fy + affine._dx;
1197 y = affine._m12 * fx + affine._m22 * fy + affine._dy;
1198 if (t == TxProject) {
1199 qreal w = 1./(m_13 * fx + m_23 * fy + m_33);
1204 return QPointF(x, y);
1208 \fn QPoint QTransform::map(const QPoint &point) const
1211 Creates and returns a QPoint object that is a copy of the given \a
1212 point, mapped into the coordinate system defined by this
1213 matrix. Note that the transformed coordinates are rounded to the
1218 \fn QLineF operator*(const QLineF &line, const QTransform &matrix)
1221 This is the same as \a{matrix}.map(\a{line}).
1223 \sa QTransform::map()
1227 \fn QLine operator*(const QLine &line, const QTransform &matrix)
1230 This is the same as \a{matrix}.map(\a{line}).
1232 \sa QTransform::map()
1238 Creates and returns a QLineF object that is a copy of the given line,
1239 \a l, mapped into the coordinate system defined by this matrix.
1241 QLine QTransform::map(const QLine &l) const
1248 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1250 TransformationType t = inline_type();
1259 x1 = fx1 + affine._dx;
1260 y1 = fy1 + affine._dy;
1261 x2 = fx2 + affine._dx;
1262 y2 = fy2 + affine._dy;
1265 x1 = affine._m11 * fx1 + affine._dx;
1266 y1 = affine._m22 * fy1 + affine._dy;
1267 x2 = affine._m11 * fx2 + affine._dx;
1268 y2 = affine._m22 * fy2 + affine._dy;
1273 x1 = affine._m11 * fx1 + affine._m21 * fy1 + affine._dx;
1274 y1 = affine._m12 * fx1 + affine._m22 * fy1 + affine._dy;
1275 x2 = affine._m11 * fx2 + affine._m21 * fy2 + affine._dx;
1276 y2 = affine._m12 * fx2 + affine._m22 * fy2 + affine._dy;
1277 if (t == TxProject) {
1278 qreal w = 1./(m_13 * fx1 + m_23 * fy1 + m_33);
1281 w = 1./(m_13 * fx2 + m_23 * fy2 + m_33);
1286 return QLine(qRound(x1), qRound(y1), qRound(x2), qRound(y2));
1292 \fn QLineF QTransform::map(const QLineF &line) const
1294 Creates and returns a QLine object that is a copy of the given \a
1295 line, mapped into the coordinate system defined by this matrix.
1296 Note that the transformed coordinates are rounded to the nearest
1300 QLineF QTransform::map(const QLineF &l) const
1307 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1309 TransformationType t = inline_type();
1318 x1 = fx1 + affine._dx;
1319 y1 = fy1 + affine._dy;
1320 x2 = fx2 + affine._dx;
1321 y2 = fy2 + affine._dy;
1324 x1 = affine._m11 * fx1 + affine._dx;
1325 y1 = affine._m22 * fy1 + affine._dy;
1326 x2 = affine._m11 * fx2 + affine._dx;
1327 y2 = affine._m22 * fy2 + affine._dy;
1332 x1 = affine._m11 * fx1 + affine._m21 * fy1 + affine._dx;
1333 y1 = affine._m12 * fx1 + affine._m22 * fy1 + affine._dy;
1334 x2 = affine._m11 * fx2 + affine._m21 * fy2 + affine._dx;
1335 y2 = affine._m12 * fx2 + affine._m22 * fy2 + affine._dy;
1336 if (t == TxProject) {
1337 qreal w = 1./(m_13 * fx1 + m_23 * fy1 + m_33);
1340 w = 1./(m_13 * fx2 + m_23 * fy2 + m_33);
1345 return QLineF(x1, y1, x2, y2);
1348 static QPolygonF mapProjective(const QTransform &transform, const QPolygonF &poly)
1350 if (poly.size() == 0)
1353 if (poly.size() == 1)
1354 return QPolygonF() << transform.map(poly.at(0));
1357 path.addPolygon(poly);
1359 path = transform.map(path);
1362 for (int i = 0; i < path.elementCount(); ++i)
1363 result << path.elementAt(i);
1369 \fn QPolygonF operator *(const QPolygonF &polygon, const QTransform &matrix)
1373 This is the same as \a{matrix}.map(\a{polygon}).
1375 \sa QTransform::map()
1379 \fn QPolygon operator*(const QPolygon &polygon, const QTransform &matrix)
1382 This is the same as \a{matrix}.map(\a{polygon}).
1384 \sa QTransform::map()
1388 \fn QPolygonF QTransform::map(const QPolygonF &polygon) const
1391 Creates and returns a QPolygonF object that is a copy of the given
1392 \a polygon, mapped into the coordinate system defined by this
1395 QPolygonF QTransform::map(const QPolygonF &a) const
1397 TransformationType t = inline_type();
1398 if (t <= TxTranslate)
1399 return a.translated(affine._dx, affine._dy);
1401 if (t >= QTransform::TxProject)
1402 return mapProjective(*this, a);
1404 int size = a.size();
1407 const QPointF *da = a.constData();
1408 QPointF *dp = p.data();
1410 for(i = 0; i < size; ++i) {
1411 MAP(da[i].xp, da[i].yp, dp[i].xp, dp[i].yp);
1417 \fn QPolygon QTransform::map(const QPolygon &polygon) const
1420 Creates and returns a QPolygon object that is a copy of the given
1421 \a polygon, mapped into the coordinate system defined by this
1422 matrix. Note that the transformed coordinates are rounded to the
1425 QPolygon QTransform::map(const QPolygon &a) const
1427 TransformationType t = inline_type();
1428 if (t <= TxTranslate)
1429 return a.translated(qRound(affine._dx), qRound(affine._dy));
1431 if (t >= QTransform::TxProject)
1432 return mapProjective(*this, QPolygonF(a)).toPolygon();
1434 int size = a.size();
1437 const QPoint *da = a.constData();
1438 QPoint *dp = p.data();
1440 for(i = 0; i < size; ++i) {
1441 qreal nx = 0, ny = 0;
1442 MAP(da[i].xp, da[i].yp, nx, ny);
1443 dp[i].xp = qRound(nx);
1444 dp[i].yp = qRound(ny);
1450 \fn QRegion operator*(const QRegion ®ion, const QTransform &matrix)
1453 This is the same as \a{matrix}.map(\a{region}).
1455 \sa QTransform::map()
1458 extern QPainterPath qt_regionToPath(const QRegion ®ion);
1461 \fn QRegion QTransform::map(const QRegion ®ion) const
1464 Creates and returns a QRegion object that is a copy of the given
1465 \a region, mapped into the coordinate system defined by this matrix.
1467 Calling this method can be rather expensive if rotations or
1470 QRegion QTransform::map(const QRegion &r) const
1472 TransformationType t = inline_type();
1476 if (t == TxTranslate) {
1478 copy.translate(qRound(affine._dx), qRound(affine._dy));
1482 if (t == TxScale && r.rectCount() == 1)
1483 return QRegion(mapRect(r.boundingRect()));
1485 QPainterPath p = map(qt_regionToPath(r));
1486 return p.toFillPolygon(QTransform()).toPolygon();
1489 struct QHomogeneousCoordinate
1495 QHomogeneousCoordinate() {}
1496 QHomogeneousCoordinate(qreal x_, qreal y_, qreal w_) : x(x_), y(y_), w(w_) {}
1498 const QPointF toPoint() const {
1500 return QPointF(x * iw, y * iw);
1504 static inline QHomogeneousCoordinate mapHomogeneous(const QTransform &transform, const QPointF &p)
1506 QHomogeneousCoordinate c;
1507 c.x = transform.m11() * p.x() + transform.m21() * p.y() + transform.m31();
1508 c.y = transform.m12() * p.x() + transform.m22() * p.y() + transform.m32();
1509 c.w = transform.m13() * p.x() + transform.m23() * p.y() + transform.m33();
1513 static inline bool lineTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b,
1514 bool needsMoveTo, bool needsLineTo = true)
1516 QHomogeneousCoordinate ha = mapHomogeneous(transform, a);
1517 QHomogeneousCoordinate hb = mapHomogeneous(transform, b);
1519 if (ha.w < Q_NEAR_CLIP && hb.w < Q_NEAR_CLIP)
1522 if (hb.w < Q_NEAR_CLIP) {
1523 const qreal t = (Q_NEAR_CLIP - hb.w) / (ha.w - hb.w);
1525 hb.x += (ha.x - hb.x) * t;
1526 hb.y += (ha.y - hb.y) * t;
1527 hb.w = qreal(Q_NEAR_CLIP);
1528 } else if (ha.w < Q_NEAR_CLIP) {
1529 const qreal t = (Q_NEAR_CLIP - ha.w) / (hb.w - ha.w);
1531 ha.x += (hb.x - ha.x) * t;
1532 ha.y += (hb.y - ha.y) * t;
1533 ha.w = qreal(Q_NEAR_CLIP);
1535 const QPointF p = ha.toPoint();
1538 needsMoveTo = false;
1545 path.moveTo(ha.toPoint());
1548 path.lineTo(hb.toPoint());
1552 Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
1554 static inline bool cubicTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, bool needsMoveTo)
1556 // Convert projective xformed curves to line
1557 // segments so they can be transformed more accurately
1560 qt_scaleForTransform(transform, &scale);
1562 qreal curveThreshold = scale == 0 ? qreal(0.25) : (qreal(0.25) / scale);
1564 QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(curveThreshold);
1566 for (int i = 0; i < segment.size() - 1; ++i)
1567 if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo))
1568 needsMoveTo = false;
1570 return !needsMoveTo;
1573 static QPainterPath mapProjective(const QTransform &transform, const QPainterPath &path)
1575 QPainterPath result;
1579 bool needsMoveTo = true;
1580 for (int i = 0; i < path.elementCount(); ++i) {
1581 switch (path.elementAt(i).type) {
1582 case QPainterPath::MoveToElement:
1583 if (i > 0 && lastMoveTo != last)
1584 lineTo_clipped(result, transform, last, lastMoveTo, needsMoveTo);
1586 lastMoveTo = path.elementAt(i);
1587 last = path.elementAt(i);
1590 case QPainterPath::LineToElement:
1591 if (lineTo_clipped(result, transform, last, path.elementAt(i), needsMoveTo))
1592 needsMoveTo = false;
1593 last = path.elementAt(i);
1595 case QPainterPath::CurveToElement:
1596 if (cubicTo_clipped(result, transform, last, path.elementAt(i), path.elementAt(i+1), path.elementAt(i+2), needsMoveTo))
1597 needsMoveTo = false;
1599 last = path.elementAt(i);
1606 if (path.elementCount() > 0 && lastMoveTo != last)
1607 lineTo_clipped(result, transform, last, lastMoveTo, needsMoveTo, false);
1609 result.setFillRule(path.fillRule());
1614 \fn QPainterPath operator *(const QPainterPath &path, const QTransform &matrix)
1618 This is the same as \a{matrix}.map(\a{path}).
1620 \sa QTransform::map()
1626 Creates and returns a QPainterPath object that is a copy of the
1627 given \a path, mapped into the coordinate system defined by this
1630 QPainterPath QTransform::map(const QPainterPath &path) const
1632 TransformationType t = inline_type();
1633 if (t == TxNone || path.elementCount() == 0)
1637 return mapProjective(*this, path);
1639 QPainterPath copy = path;
1641 if (t == TxTranslate) {
1642 copy.translate(affine._dx, affine._dy);
1646 for (int i=0; i<path.elementCount(); ++i) {
1647 QPainterPath::Element &e = copy.d_ptr->elements[i];
1648 MAP(e.x, e.y, e.x, e.y);
1656 \fn QPolygon QTransform::mapToPolygon(const QRect &rectangle) const
1658 Creates and returns a QPolygon representation of the given \a
1659 rectangle, mapped into the coordinate system defined by this
1662 The rectangle's coordinates are transformed using the following
1665 \snippet code/src_gui_painting_qtransform.cpp 1
1667 Polygons and rectangles behave slightly differently when
1668 transformed (due to integer rounding), so
1669 \c{matrix.map(QPolygon(rectangle))} is not always the same as
1670 \c{matrix.mapToPolygon(rectangle)}.
1672 \sa mapRect(), {QTransform#Basic Matrix Operations}{Basic Matrix
1675 QPolygon QTransform::mapToPolygon(const QRect &rect) const
1677 TransformationType t = inline_type();
1680 qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 };
1682 x[0] = affine._m11*rect.x() + affine._dx;
1683 y[0] = affine._m22*rect.y() + affine._dy;
1684 qreal w = affine._m11*rect.width();
1685 qreal h = affine._m22*rect.height();
1701 qreal right = rect.x() + rect.width();
1702 qreal bottom = rect.y() + rect.height();
1703 MAP(rect.x(), rect.y(), x[0], y[0]);
1704 MAP(right, rect.y(), x[1], y[1]);
1705 MAP(right, bottom, x[2], y[2]);
1706 MAP(rect.x(), bottom, x[3], y[3]);
1709 // all coordinates are correctly, tranform to a pointarray
1710 // (rounding to the next integer)
1711 a.setPoints(4, qRound(x[0]), qRound(y[0]),
1712 qRound(x[1]), qRound(y[1]),
1713 qRound(x[2]), qRound(y[2]),
1714 qRound(x[3]), qRound(y[3]));
1719 Creates a transformation matrix, \a trans, that maps a unit square
1720 to a four-sided polygon, \a quad. Returns true if the transformation
1721 is constructed or false if such a transformation does not exist.
1723 \sa quadToSquare(), quadToQuad()
1725 bool QTransform::squareToQuad(const QPolygonF &quad, QTransform &trans)
1727 if (quad.count() != 4)
1730 qreal dx0 = quad[0].x();
1731 qreal dx1 = quad[1].x();
1732 qreal dx2 = quad[2].x();
1733 qreal dx3 = quad[3].x();
1735 qreal dy0 = quad[0].y();
1736 qreal dy1 = quad[1].y();
1737 qreal dy2 = quad[2].y();
1738 qreal dy3 = quad[3].y();
1740 double ax = dx0 - dx1 + dx2 - dx3;
1741 double ay = dy0 - dy1 + dy2 - dy3;
1743 if (!ax && !ay) { //afine transform
1744 trans.setMatrix(dx1 - dx0, dy1 - dy0, 0,
1745 dx2 - dx1, dy2 - dy1, 0,
1748 double ax1 = dx1 - dx2;
1749 double ax2 = dx3 - dx2;
1750 double ay1 = dy1 - dy2;
1751 double ay2 = dy3 - dy2;
1754 double gtop = ax * ay2 - ax2 * ay;
1755 double htop = ax1 * ay - ax * ay1;
1756 double bottom = ax1 * ay2 - ax2 * ay1;
1758 double a, b, c, d, e, f, g, h; /*i is always 1*/
1766 a = dx1 - dx0 + g * dx1;
1767 b = dx3 - dx0 + h * dx3;
1769 d = dy1 - dy0 + g * dy1;
1770 e = dy3 - dy0 + h * dy3;
1773 trans.setMatrix(a, d, g,
1782 \fn bool QTransform::quadToSquare(const QPolygonF &quad, QTransform &trans)
1784 Creates a transformation matrix, \a trans, that maps a four-sided polygon,
1785 \a quad, to a unit square. Returns true if the transformation is constructed
1786 or false if such a transformation does not exist.
1788 \sa squareToQuad(), quadToQuad()
1790 bool QTransform::quadToSquare(const QPolygonF &quad, QTransform &trans)
1792 if (!squareToQuad(quad, trans))
1795 bool invertible = false;
1796 trans = trans.inverted(&invertible);
1802 Creates a transformation matrix, \a trans, that maps a four-sided
1803 polygon, \a one, to another four-sided polygon, \a two.
1804 Returns true if the transformation is possible; otherwise returns
1807 This is a convenience method combining quadToSquare() and
1808 squareToQuad() methods. It allows the input quad to be
1809 transformed into any other quad.
1811 \sa squareToQuad(), quadToSquare()
1813 bool QTransform::quadToQuad(const QPolygonF &one,
1814 const QPolygonF &two,
1818 if (!quadToSquare(one, trans))
1820 if (!squareToQuad(two, stq))
1823 //qDebug()<<"Final = "<<trans;
1828 Sets the matrix elements to the specified values, \a m11,
1829 \a m12, \a m13 \a m21, \a m22, \a m23 \a m31, \a m32 and
1830 \a m33. Note that this function replaces the previous values.
1831 QTransform provides the translate(), rotate(), scale() and shear()
1832 convenience functions to manipulate the various matrix elements
1833 based on the currently defined coordinate system.
1838 void QTransform::setMatrix(qreal m11, qreal m12, qreal m13,
1839 qreal m21, qreal m22, qreal m23,
1840 qreal m31, qreal m32, qreal m33)
1842 affine._m11 = m11; affine._m12 = m12; m_13 = m13;
1843 affine._m21 = m21; affine._m22 = m22; m_23 = m23;
1844 affine._dx = m31; affine._dy = m32; m_33 = m33;
1846 m_dirty = TxProject;
1849 static inline bool needsPerspectiveClipping(const QRectF &rect, const QTransform &transform)
1851 const qreal wx = qMin(transform.m13() * rect.left(), transform.m13() * rect.right());
1852 const qreal wy = qMin(transform.m23() * rect.top(), transform.m23() * rect.bottom());
1854 return wx + wy + transform.m33() < Q_NEAR_CLIP;
1857 QRect QTransform::mapRect(const QRect &rect) const
1859 TransformationType t = inline_type();
1860 if (t <= TxTranslate)
1861 return rect.translated(qRound(affine._dx), qRound(affine._dy));
1864 int x = qRound(affine._m11*rect.x() + affine._dx);
1865 int y = qRound(affine._m22*rect.y() + affine._dy);
1866 int w = qRound(affine._m11*rect.width());
1867 int h = qRound(affine._m22*rect.height());
1876 return QRect(x, y, w, h);
1877 } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
1878 // see mapToPolygon for explanations of the algorithm.
1880 MAP(rect.left(), rect.top(), x, y);
1885 MAP(rect.right() + 1, rect.top(), x, y);
1886 xmin = qMin(xmin, x);
1887 ymin = qMin(ymin, y);
1888 xmax = qMax(xmax, x);
1889 ymax = qMax(ymax, y);
1890 MAP(rect.right() + 1, rect.bottom() + 1, x, y);
1891 xmin = qMin(xmin, x);
1892 ymin = qMin(ymin, y);
1893 xmax = qMax(xmax, x);
1894 ymax = qMax(ymax, y);
1895 MAP(rect.left(), rect.bottom() + 1, x, y);
1896 xmin = qMin(xmin, x);
1897 ymin = qMin(ymin, y);
1898 xmax = qMax(xmax, x);
1899 ymax = qMax(ymax, y);
1900 return QRect(qRound(xmin), qRound(ymin), qRound(xmax)-qRound(xmin), qRound(ymax)-qRound(ymin));
1904 return map(path).boundingRect().toRect();
1909 \fn QRectF QTransform::mapRect(const QRectF &rectangle) const
1911 Creates and returns a QRectF object that is a copy of the given \a
1912 rectangle, mapped into the coordinate system defined by this
1915 The rectangle's coordinates are transformed using the following
1918 \snippet code/src_gui_painting_qtransform.cpp 2
1920 If rotation or shearing has been specified, this function returns
1921 the \e bounding rectangle. To retrieve the exact region the given
1922 \a rectangle maps to, use the mapToPolygon() function instead.
1924 \sa mapToPolygon(), {QTransform#Basic Matrix Operations}{Basic Matrix
1927 QRectF QTransform::mapRect(const QRectF &rect) const
1929 TransformationType t = inline_type();
1930 if (t <= TxTranslate)
1931 return rect.translated(affine._dx, affine._dy);
1934 qreal x = affine._m11*rect.x() + affine._dx;
1935 qreal y = affine._m22*rect.y() + affine._dy;
1936 qreal w = affine._m11*rect.width();
1937 qreal h = affine._m22*rect.height();
1946 return QRectF(x, y, w, h);
1947 } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
1949 MAP(rect.x(), rect.y(), x, y);
1954 MAP(rect.x() + rect.width(), rect.y(), x, y);
1955 xmin = qMin(xmin, x);
1956 ymin = qMin(ymin, y);
1957 xmax = qMax(xmax, x);
1958 ymax = qMax(ymax, y);
1959 MAP(rect.x() + rect.width(), rect.y() + rect.height(), x, y);
1960 xmin = qMin(xmin, x);
1961 ymin = qMin(ymin, y);
1962 xmax = qMax(xmax, x);
1963 ymax = qMax(ymax, y);
1964 MAP(rect.x(), rect.y() + rect.height(), x, y);
1965 xmin = qMin(xmin, x);
1966 ymin = qMin(ymin, y);
1967 xmax = qMax(xmax, x);
1968 ymax = qMax(ymax, y);
1969 return QRectF(xmin, ymin, xmax-xmin, ymax - ymin);
1973 return map(path).boundingRect();
1978 \fn QRect QTransform::mapRect(const QRect &rectangle) const
1981 Creates and returns a QRect object that is a copy of the given \a
1982 rectangle, mapped into the coordinate system defined by this
1983 matrix. Note that the transformed coordinates are rounded to the
1988 Maps the given coordinates \a x and \a y into the coordinate
1989 system defined by this matrix. The resulting values are put in *\a
1990 tx and *\a ty, respectively.
1992 The coordinates are transformed using the following formulas:
1994 \snippet code/src_gui_painting_qtransform.cpp 3
1996 The point (x, y) is the original point, and (x', y') is the
1999 \sa {QTransform#Basic Matrix Operations}{Basic Matrix Operations}
2001 void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty) const
2003 TransformationType t = inline_type();
2004 MAP(x, y, *tx, *ty);
2010 Maps the given coordinates \a x and \a y into the coordinate
2011 system defined by this matrix. The resulting values are put in *\a
2012 tx and *\a ty, respectively. Note that the transformed coordinates
2013 are rounded to the nearest integer.
2015 void QTransform::map(int x, int y, int *tx, int *ty) const
2017 TransformationType t = inline_type();
2018 qreal fx = 0, fy = 0;
2025 Returns the QTransform as an affine matrix.
2027 \warning If a perspective transformation has been specified,
2028 then the conversion will cause loss of data.
2030 const QMatrix &QTransform::toAffine() const
2036 Returns the transformation type of this matrix.
2038 The transformation type is the highest enumeration value
2039 capturing all of the matrix's transformations. For example,
2040 if the matrix both scales and shears, the type would be \c TxShear,
2041 because \c TxShear has a higher enumeration value than \c TxScale.
2043 Knowing the transformation type of a matrix is useful for optimization:
2044 you can often handle specific types more optimally than handling
2047 QTransform::TransformationType QTransform::type() const
2049 if(m_dirty == TxNone || m_dirty < m_type)
2050 return static_cast<TransformationType>(m_type);
2052 switch (static_cast<TransformationType>(m_dirty)) {
2054 if (!qFuzzyIsNull(m_13) || !qFuzzyIsNull(m_23) || !qFuzzyIsNull(m_33 - 1)) {
2060 if (!qFuzzyIsNull(affine._m12) || !qFuzzyIsNull(affine._m21)) {
2061 const qreal dot = affine._m11 * affine._m12 + affine._m21 * affine._m22;
2062 if (qFuzzyIsNull(dot))
2069 if (!qFuzzyIsNull(affine._m11 - 1) || !qFuzzyIsNull(affine._m22 - 1)) {
2074 if (!qFuzzyIsNull(affine._dx) || !qFuzzyIsNull(affine._dy)) {
2075 m_type = TxTranslate;
2084 return static_cast<TransformationType>(m_type);
2089 Returns the transform as a QVariant.
2091 QTransform::operator QVariant() const
2093 return QVariant(QVariant::Transform, this);
2098 \fn bool QTransform::isInvertible() const
2100 Returns true if the matrix is invertible, otherwise returns false.
2106 \fn qreal QTransform::det() const
2109 Returns the matrix's determinant. Use determinant() instead.
2114 \fn qreal QTransform::m11() const
2116 Returns the horizontal scaling factor.
2118 \sa scale(), {QTransform#Basic Matrix Operations}{Basic Matrix
2123 \fn qreal QTransform::m12() const
2125 Returns the vertical shearing factor.
2127 \sa shear(), {QTransform#Basic Matrix Operations}{Basic Matrix
2132 \fn qreal QTransform::m21() const
2134 Returns the horizontal shearing factor.
2136 \sa shear(), {QTransform#Basic Matrix Operations}{Basic Matrix
2141 \fn qreal QTransform::m22() const
2143 Returns the vertical scaling factor.
2145 \sa scale(), {QTransform#Basic Matrix Operations}{Basic Matrix
2150 \fn qreal QTransform::dx() const
2152 Returns the horizontal translation factor.
2154 \sa m31(), translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2159 \fn qreal QTransform::dy() const
2161 Returns the vertical translation factor.
2163 \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2169 \fn qreal QTransform::m13() const
2171 Returns the horizontal projection factor.
2173 \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2179 \fn qreal QTransform::m23() const
2181 Returns the vertical projection factor.
2183 \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2188 \fn qreal QTransform::m31() const
2190 Returns the horizontal translation factor.
2192 \sa dx(), translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2197 \fn qreal QTransform::m32() const
2199 Returns the vertical translation factor.
2201 \sa dy(), translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2206 \fn qreal QTransform::m33() const
2208 Returns the division factor.
2210 \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2215 \fn qreal QTransform::determinant() const
2217 Returns the matrix's determinant.
2221 \fn bool QTransform::isIdentity() const
2223 Returns true if the matrix is the identity matrix, otherwise
2230 \fn bool QTransform::isAffine() const
2232 Returns true if the matrix represent an affine transformation,
2233 otherwise returns false.
2237 \fn bool QTransform::isScaling() const
2239 Returns true if the matrix represents a scaling
2240 transformation, otherwise returns false.
2246 \fn bool QTransform::isRotating() const
2248 Returns true if the matrix represents some kind of a
2249 rotating transformation, otherwise returns false.
2255 \fn bool QTransform::isTranslating() const
2257 Returns true if the matrix represents a translating
2258 transformation, otherwise returns false.
2264 \fn bool qFuzzyCompare(const QTransform& t1, const QTransform& t2)
2269 Returns true if \a t1 and \a t2 are equal, allowing for a small
2270 fuzziness factor for floating-point comparisons; false otherwise.
2274 // returns true if the transform is uniformly scaling
2275 // (same scale in x and y direction)
2276 // scale is set to the max of x and y scaling factors
2278 bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
2280 const QTransform::TransformationType type = transform.type();
2281 if (type <= QTransform::TxTranslate) {
2285 } else if (type == QTransform::TxScale) {
2286 const qreal xScale = qAbs(transform.m11());
2287 const qreal yScale = qAbs(transform.m22());
2289 *scale = qMax(xScale, yScale);
2290 return qFuzzyCompare(xScale, yScale);
2293 const qreal xScale = transform.m11() * transform.m11()
2294 + transform.m21() * transform.m21();
2295 const qreal yScale = transform.m12() * transform.m12()
2296 + transform.m22() * transform.m22();
2298 *scale = qSqrt(qMax(xScale, yScale));
2299 return type == QTransform::TxRotate && qFuzzyCompare(xScale, yScale);