1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
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.
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.
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.
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.
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.
101 A transformation specifies how to translate, scale, shear, rotate
102 or project the coordinate system, and is typically used when
105 QTransform differs from QMatrix in that it is a true 3x3 matrix,
106 allowing perspective transformations. QTransform's toAffine()
107 method allows casting QTransform to QMatrix. If a perspective
108 transformation has been specified on the matrix, then the
109 conversion will cause loss of data.
111 QTransform is the recommended transformation class in Qt.
113 A QTransform object can be built using the setMatrix(), scale(),
114 rotate(), translate() and shear() functions. Alternatively, it
115 can be built by applying \l {QTransform#Basic Matrix
116 Operations}{basic matrix operations}. The matrix can also be
117 defined when constructed, and it can be reset to the identity
118 matrix (the default) using the reset() function.
120 The QTransform class supports mapping of graphic primitives: A given
121 point, line, polygon, region, or painter path can be mapped to the
122 coordinate system defined by \e this matrix using the map()
123 function. In case of a rectangle, its coordinates can be
124 transformed using the mapRect() function. A rectangle can also be
125 transformed into a \e polygon (mapped to the coordinate system
126 defined by \e this matrix), using the mapToPolygon() function.
128 QTransform provides the isIdentity() function which returns true if
129 the matrix is the identity matrix, and the isInvertible() function
130 which returns true if the matrix is non-singular (i.e. AB = BA =
131 I). The inverted() function returns an inverted copy of \e this
132 matrix if it is invertible (otherwise it returns the identity
133 matrix), and adjoint() returns the matrix's classical adjoint.
134 In addition, QTransform provides the determinant() function which
135 returns the matrix's determinant.
137 Finally, the QTransform class supports matrix multiplication, addition
138 and subtraction, and objects of the class can be streamed as well
143 \section1 Rendering Graphics
145 When rendering graphics, the matrix defines the transformations
146 but the actual transformation is performed by the drawing routines
149 By default, QPainter operates on the associated device's own
150 coordinate system. The standard coordinate system of a
151 QPaintDevice has its origin located at the top-left position. The
152 \e x values increase to the right; \e y values increase
153 downward. For a complete description, see the \l {Coordinate
154 System} {coordinate system} documentation.
156 QPainter has functions to translate, scale, shear and rotate the
157 coordinate system without using a QTransform. For example:
161 \li \inlineimage qtransform-simpletransformation.png
163 \snippet transform/main.cpp 0
166 Although these functions are very convenient, it can be more
167 efficient to build a QTransform and call QPainter::setTransform() if you
168 want to perform more than a single transform operation. For
173 \li \inlineimage qtransform-combinedtransformation.png
175 \snippet transform/main.cpp 1
178 \section1 Basic Matrix Operations
180 \image qtransform-representation.png
182 A QTransform object contains a 3 x 3 matrix. The \c m31 (\c dx) and
183 \c m32 (\c dy) elements specify horizontal and vertical translation.
184 The \c m11 and \c m22 elements specify horizontal and vertical scaling.
185 The \c m21 and \c m12 elements specify horizontal and vertical \e shearing.
186 And finally, the \c m13 and \c m23 elements specify horizontal and vertical
187 projection, with \c m33 as an additional projection factor.
189 QTransform transforms a point in the plane to another point using the
192 \snippet code/src_gui_painting_qtransform.cpp 0
194 The point \e (x, y) is the original point, and \e (x', y') is the
195 transformed point. \e (x', y') can be transformed back to \e (x,
196 y) by performing the same operation on the inverted() matrix.
198 The various matrix elements can be set when constructing the
199 matrix, or by using the setMatrix() function later on. They can also
200 be manipulated using the translate(), rotate(), scale() and
201 shear() convenience functions. The currently set values can be
202 retrieved using the m11(), m12(), m13(), m21(), m22(), m23(),
203 m31(), m32(), m33(), dx() and dy() functions.
205 Translation is the simplest transformation. Setting \c dx and \c
206 dy will move the coordinate system \c dx units along the X axis
207 and \c dy units along the Y axis. Scaling can be done by setting
208 \c m11 and \c m22. For example, setting \c m11 to 2 and \c m22 to
209 1.5 will double the height and increase the width by 50%. The
210 identity matrix has \c m11, \c m22, and \c m33 set to 1 (all others are set
211 to 0) mapping a point to itself. Shearing is controlled by \c m12
212 and \c m21. Setting these elements to values different from zero
213 will twist the coordinate system. Rotation is achieved by
214 setting both the shearing factors and the scaling factors. Perspective
215 transformation is achieved by setting both the projection factors and
218 Here's the combined transformations example using basic matrix
223 \li \inlineimage qtransform-combinedtransformation2.png
225 \snippet transform/main.cpp 2
228 \sa QPainter, {Coordinate System}, {painting/affine}{Affine
229 Transformations Example}, {Transformations Example}
233 \enum QTransform::TransformationType
244 \fn QTransform::QTransform(Qt::Initialization)
249 Constructs an identity matrix.
251 All elements are set to zero except \c m11 and \c m22 (specifying
252 the scale) and \c m33 which are set to 1.
256 QTransform::QTransform()
258 , m_13(0), m_23(0), m_33(1)
265 \fn QTransform::QTransform(qreal m11, qreal m12, qreal m13, qreal m21, qreal m22, qreal m23, qreal m31, qreal m32, qreal m33)
267 Constructs a matrix with the elements, \a m11, \a m12, \a m13,
268 \a m21, \a m22, \a m23, \a m31, \a m32, \a m33.
272 QTransform::QTransform(qreal h11, qreal h12, qreal h13,
273 qreal h21, qreal h22, qreal h23,
274 qreal h31, qreal h32, qreal h33)
275 : affine(h11, h12, h21, h22, h31, h32, true)
276 , m_13(h13), m_23(h23), m_33(h33)
283 \fn QTransform::QTransform(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy)
285 Constructs a matrix with the elements, \a m11, \a m12, \a m21, \a m22, \a dx and \a dy.
289 QTransform::QTransform(qreal h11, qreal h12, qreal h21,
290 qreal h22, qreal dx, qreal dy)
291 : affine(h11, h12, h21, h22, dx, dy, true)
292 , m_13(0), m_23(0), m_33(1)
299 \fn QTransform::QTransform(const QMatrix &matrix)
301 Constructs a matrix that is a copy of the given \a matrix.
302 Note that the \c m13, \c m23, and \c m33 elements are set to 0, 0,
305 QTransform::QTransform(const QMatrix &mtx)
306 : affine(mtx._m11, mtx._m12, mtx._m21, mtx._m22, mtx._dx, mtx._dy, true),
307 m_13(0), m_23(0), m_33(1)
314 Returns the adjoint of this matrix.
316 QTransform QTransform::adjoint() const
321 h11 = affine._m22*m_33 - m_23*affine._dy;
322 h21 = m_23*affine._dx - affine._m21*m_33;
323 h31 = affine._m21*affine._dy - affine._m22*affine._dx;
324 h12 = m_13*affine._dy - affine._m12*m_33;
325 h22 = affine._m11*m_33 - m_13*affine._dx;
326 h32 = affine._m12*affine._dx - affine._m11*affine._dy;
327 h13 = affine._m12*m_23 - m_13*affine._m22;
328 h23 = m_13*affine._m21 - affine._m11*m_23;
329 h33 = affine._m11*affine._m22 - affine._m12*affine._m21;
331 return QTransform(h11, h12, h13,
333 h31, h32, h33, true);
337 Returns the transpose of this matrix.
339 QTransform QTransform::transposed() const
341 QTransform t(affine._m11, affine._m21, affine._dx,
342 affine._m12, affine._m22, affine._dy,
343 m_13, m_23, m_33, true);
350 Returns an inverted copy of this matrix.
352 If the matrix is singular (not invertible), the returned matrix is
353 the identity matrix. If \a invertible is valid (i.e. not 0), its
354 value is set to true if the matrix is invertible, otherwise it is
359 QTransform QTransform::inverted(bool *invertible) const
361 QTransform invert(true);
364 switch(inline_type()) {
368 invert.affine._dx = -affine._dx;
369 invert.affine._dy = -affine._dy;
372 inv = !qFuzzyIsNull(affine._m11);
373 inv &= !qFuzzyIsNull(affine._m22);
375 invert.affine._m11 = 1. / affine._m11;
376 invert.affine._m22 = 1. / affine._m22;
377 invert.affine._dx = -affine._dx * invert.affine._m11;
378 invert.affine._dy = -affine._dy * invert.affine._m22;
383 invert.affine = affine.inverted(&inv);
387 qreal det = determinant();
388 inv = !qFuzzyIsNull(det);
390 invert = adjoint() / det;
398 // inverting doesn't change the type
399 invert.m_type = m_type;
400 invert.m_dirty = m_dirty;
407 Moves the coordinate system \a dx along the x axis and \a dy along
408 the y axis, and returns a reference to the matrix.
412 QTransform &QTransform::translate(qreal dx, qreal dy)
414 if (dx == 0 && dy == 0)
417 if (qIsNaN(dx) | qIsNaN(dy)) {
418 qWarning() << "QTransform::translate with NaN called";
423 switch(inline_type()) {
433 affine._dx += dx*affine._m11;
434 affine._dy += dy*affine._m22;
437 m_33 += dx*m_13 + dy*m_23;
441 affine._dx += dx*affine._m11 + dy*affine._m21;
442 affine._dy += dy*affine._m22 + dx*affine._m12;
445 if (m_dirty < TxTranslate)
446 m_dirty = TxTranslate;
451 Creates a matrix which corresponds to a translation of \a dx along
452 the x axis and \a dy along the y axis. This is the same as
453 QTransform().translate(dx, dy) but slightly faster.
457 QTransform QTransform::fromTranslate(qreal dx, qreal dy)
460 if (qIsNaN(dx) | qIsNaN(dy)) {
461 qWarning() << "QTransform::fromTranslate with NaN called";
465 QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1, true);
466 if (dx == 0 && dy == 0)
467 transform.m_type = TxNone;
469 transform.m_type = TxTranslate;
470 transform.m_dirty = TxNone;
475 Scales the coordinate system by \a sx horizontally and \a sy
476 vertically, and returns a reference to the matrix.
480 QTransform & QTransform::scale(qreal sx, qreal sy)
482 if (sx == 1 && sy == 1)
485 if (qIsNaN(sx) | qIsNaN(sy)) {
486 qWarning() << "QTransform::scale with NaN called";
491 switch(inline_type()) {
511 if (m_dirty < TxScale)
517 Creates a matrix which corresponds to a scaling of
518 \a sx horizontally and \a sy vertically.
519 This is the same as QTransform().scale(sx, sy) but slightly faster.
523 QTransform QTransform::fromScale(qreal sx, qreal sy)
526 if (qIsNaN(sx) | qIsNaN(sy)) {
527 qWarning() << "QTransform::fromScale with NaN called";
531 QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1, true);
532 if (sx == 1. && sy == 1.)
533 transform.m_type = TxNone;
535 transform.m_type = TxScale;
536 transform.m_dirty = TxNone;
541 Shears the coordinate system by \a sh horizontally and \a sv
542 vertically, and returns a reference to the matrix.
546 QTransform & QTransform::shear(qreal sh, qreal sv)
548 if (sh == 0 && sv == 0)
551 if (qIsNaN(sh) | qIsNaN(sv)) {
552 qWarning() << "QTransform::shear with NaN called";
557 switch(inline_type()) {
564 affine._m12 = sv*affine._m22;
565 affine._m21 = sh*affine._m11;
568 qreal tm13 = sv*m_23;
569 qreal tm23 = sh*m_13;
576 qreal tm11 = sv*affine._m21;
577 qreal tm22 = sh*affine._m12;
578 qreal tm12 = sv*affine._m22;
579 qreal tm21 = sh*affine._m11;
580 affine._m11 += tm11; affine._m12 += tm12;
581 affine._m21 += tm21; affine._m22 += tm22;
585 if (m_dirty < TxShear)
590 const qreal deg2rad = qreal(0.017453292519943295769); // pi/180
591 const qreal inv_dist_to_plane = 1. / 1024.;
594 \fn QTransform &QTransform::rotate(qreal angle, Qt::Axis axis)
596 Rotates the coordinate system counterclockwise by the given \a angle
597 about the specified \a axis and returns a reference to the matrix.
599 Note that if you apply a QTransform to a point defined in widget
600 coordinates, the direction of the rotation will be clockwise
601 because the y-axis points downwards.
603 The angle is specified in degrees.
607 QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
613 qWarning() << "QTransform::rotate with NaN called";
620 if (a == 90. || a == -270.)
622 else if (a == 270. || a == -90.)
627 qreal b = deg2rad*a; // convert to radians
628 sina = qSin(b); // fast and convenient
632 if (axis == Qt::ZAxis) {
633 switch(inline_type()) {
642 qreal tm11 = cosa*affine._m11;
643 qreal tm12 = sina*affine._m22;
644 qreal tm21 = -sina*affine._m11;
645 qreal tm22 = cosa*affine._m22;
646 affine._m11 = tm11; affine._m12 = tm12;
647 affine._m21 = tm21; affine._m22 = tm22;
651 qreal tm13 = cosa*m_13 + sina*m_23;
652 qreal tm23 = -sina*m_13 + cosa*m_23;
659 qreal tm11 = cosa*affine._m11 + sina*affine._m21;
660 qreal tm12 = cosa*affine._m12 + sina*affine._m22;
661 qreal tm21 = -sina*affine._m11 + cosa*affine._m21;
662 qreal tm22 = -sina*affine._m12 + cosa*affine._m22;
663 affine._m11 = tm11; affine._m12 = tm12;
664 affine._m21 = tm21; affine._m22 = tm22;
668 if (m_dirty < TxRotate)
672 if (axis == Qt::YAxis) {
673 result.affine._m11 = cosa;
674 result.m_13 = -sina * inv_dist_to_plane;
676 result.affine._m22 = cosa;
677 result.m_23 = -sina * inv_dist_to_plane;
679 result.m_type = TxProject;
680 *this = result * *this;
687 \fn QTransform & QTransform::rotateRadians(qreal angle, Qt::Axis axis)
689 Rotates the coordinate system counterclockwise by the given \a angle
690 about the specified \a axis and returns a reference to the matrix.
692 Note that if you apply a QTransform to a point defined in widget
693 coordinates, the direction of the rotation will be clockwise
694 because the y-axis points downwards.
696 The angle is specified in radians.
700 QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
704 qWarning() << "QTransform::rotateRadians with NaN called";
708 qreal sina = qSin(a);
709 qreal cosa = qCos(a);
711 if (axis == Qt::ZAxis) {
712 switch(inline_type()) {
721 qreal tm11 = cosa*affine._m11;
722 qreal tm12 = sina*affine._m22;
723 qreal tm21 = -sina*affine._m11;
724 qreal tm22 = cosa*affine._m22;
725 affine._m11 = tm11; affine._m12 = tm12;
726 affine._m21 = tm21; affine._m22 = tm22;
730 qreal tm13 = cosa*m_13 + sina*m_23;
731 qreal tm23 = -sina*m_13 + cosa*m_23;
738 qreal tm11 = cosa*affine._m11 + sina*affine._m21;
739 qreal tm12 = cosa*affine._m12 + sina*affine._m22;
740 qreal tm21 = -sina*affine._m11 + cosa*affine._m21;
741 qreal tm22 = -sina*affine._m12 + cosa*affine._m22;
742 affine._m11 = tm11; affine._m12 = tm12;
743 affine._m21 = tm21; affine._m22 = tm22;
747 if (m_dirty < TxRotate)
751 if (axis == Qt::YAxis) {
752 result.affine._m11 = cosa;
753 result.m_13 = -sina * inv_dist_to_plane;
755 result.affine._m22 = cosa;
756 result.m_23 = -sina * inv_dist_to_plane;
758 result.m_type = TxProject;
759 *this = result * *this;
765 \fn bool QTransform::operator==(const QTransform &matrix) const
766 Returns true if this matrix is equal to the given \a matrix,
767 otherwise returns false.
769 bool QTransform::operator==(const QTransform &o) const
771 return affine._m11 == o.affine._m11 &&
772 affine._m12 == o.affine._m12 &&
773 affine._m21 == o.affine._m21 &&
774 affine._m22 == o.affine._m22 &&
775 affine._dx == o.affine._dx &&
776 affine._dy == o.affine._dy &&
783 \fn bool QTransform::operator!=(const QTransform &matrix) const
784 Returns true if this matrix is not equal to the given \a matrix,
785 otherwise returns false.
787 bool QTransform::operator!=(const QTransform &o) const
789 return !operator==(o);
793 \fn QTransform & QTransform::operator*=(const QTransform &matrix)
796 Returns the result of multiplying this matrix by the given \a
799 QTransform & QTransform::operator*=(const QTransform &o)
801 const TransformationType otherType = o.inline_type();
802 if (otherType == TxNone)
805 const TransformationType thisType = inline_type();
806 if (thisType == TxNone)
809 TransformationType t = qMax(thisType, otherType);
814 affine._dx += o.affine._dx;
815 affine._dy += o.affine._dy;
819 qreal m11 = affine._m11*o.affine._m11;
820 qreal m22 = affine._m22*o.affine._m22;
822 qreal m31 = affine._dx*o.affine._m11 + o.affine._dx;
823 qreal m32 = affine._dy*o.affine._m22 + o.affine._dy;
827 affine._dx = m31; affine._dy = m32;
833 qreal m11 = affine._m11*o.affine._m11 + affine._m12*o.affine._m21;
834 qreal m12 = affine._m11*o.affine._m12 + affine._m12*o.affine._m22;
836 qreal m21 = affine._m21*o.affine._m11 + affine._m22*o.affine._m21;
837 qreal m22 = affine._m21*o.affine._m12 + affine._m22*o.affine._m22;
839 qreal m31 = affine._dx*o.affine._m11 + affine._dy*o.affine._m21 + o.affine._dx;
840 qreal m32 = affine._dx*o.affine._m12 + affine._dy*o.affine._m22 + o.affine._dy;
842 affine._m11 = m11; affine._m12 = m12;
843 affine._m21 = m21; affine._m22 = m22;
844 affine._dx = m31; affine._dy = m32;
849 qreal m11 = affine._m11*o.affine._m11 + affine._m12*o.affine._m21 + m_13*o.affine._dx;
850 qreal m12 = affine._m11*o.affine._m12 + affine._m12*o.affine._m22 + m_13*o.affine._dy;
851 qreal m13 = affine._m11*o.m_13 + affine._m12*o.m_23 + m_13*o.m_33;
853 qreal m21 = affine._m21*o.affine._m11 + affine._m22*o.affine._m21 + m_23*o.affine._dx;
854 qreal m22 = affine._m21*o.affine._m12 + affine._m22*o.affine._m22 + m_23*o.affine._dy;
855 qreal m23 = affine._m21*o.m_13 + affine._m22*o.m_23 + m_23*o.m_33;
857 qreal m31 = affine._dx*o.affine._m11 + affine._dy*o.affine._m21 + m_33*o.affine._dx;
858 qreal m32 = affine._dx*o.affine._m12 + affine._dy*o.affine._m22 + m_33*o.affine._dy;
859 qreal m33 = affine._dx*o.m_13 + affine._dy*o.m_23 + m_33*o.m_33;
861 affine._m11 = m11; affine._m12 = m12; m_13 = m13;
862 affine._m21 = m21; affine._m22 = m22; m_23 = m23;
863 affine._dx = m31; affine._dy = m32; m_33 = m33;
874 \fn QTransform QTransform::operator*(const QTransform &matrix) const
875 Returns the result of multiplying this matrix by the given \a
878 Note that matrix multiplication is not commutative, i.e. a*b !=
881 QTransform QTransform::operator*(const QTransform &m) const
883 const TransformationType otherType = m.inline_type();
884 if (otherType == TxNone)
887 const TransformationType thisType = inline_type();
888 if (thisType == TxNone)
892 TransformationType type = qMax(thisType, otherType);
897 t.affine._dx = affine._dx + m.affine._dx;
898 t.affine._dy += affine._dy + m.affine._dy;
902 qreal m11 = affine._m11*m.affine._m11;
903 qreal m22 = affine._m22*m.affine._m22;
905 qreal m31 = affine._dx*m.affine._m11 + m.affine._dx;
906 qreal m32 = affine._dy*m.affine._m22 + m.affine._dy;
910 t.affine._dx = m31; t.affine._dy = m32;
916 qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21;
917 qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22;
919 qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21;
920 qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22;
922 qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m.affine._dx;
923 qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m.affine._dy;
925 t.affine._m11 = m11; t.affine._m12 = m12;
926 t.affine._m21 = m21; t.affine._m22 = m22;
927 t.affine._dx = m31; t.affine._dy = m32;
932 qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21 + m_13*m.affine._dx;
933 qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22 + m_13*m.affine._dy;
934 qreal m13 = affine._m11*m.m_13 + affine._m12*m.m_23 + m_13*m.m_33;
936 qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21 + m_23*m.affine._dx;
937 qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22 + m_23*m.affine._dy;
938 qreal m23 = affine._m21*m.m_13 + affine._m22*m.m_23 + m_23*m.m_33;
940 qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m_33*m.affine._dx;
941 qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m_33*m.affine._dy;
942 qreal m33 = affine._dx*m.m_13 + affine._dy*m.m_23 + m_33*m.m_33;
944 t.affine._m11 = m11; t.affine._m12 = m12; t.m_13 = m13;
945 t.affine._m21 = m21; t.affine._m22 = m22; t.m_23 = m23;
946 t.affine._dx = m31; t.affine._dy = m32; t.m_33 = m33;
957 \fn QTransform & QTransform::operator*=(qreal scalar)
960 Returns the result of performing an element-wise multiplication of this
961 matrix with the given \a scalar.
965 \fn QTransform & QTransform::operator/=(qreal scalar)
968 Returns the result of performing an element-wise division of this
969 matrix by the given \a scalar.
973 \fn QTransform & QTransform::operator+=(qreal scalar)
976 Returns the matrix obtained by adding the given \a scalar to each
977 element of this matrix.
981 \fn QTransform & QTransform::operator-=(qreal scalar)
984 Returns the matrix obtained by subtracting the given \a scalar from each
985 element of this matrix.
989 Assigns the given \a matrix's values to this matrix.
991 QTransform & QTransform::operator=(const QTransform &matrix)
993 affine._m11 = matrix.affine._m11;
994 affine._m12 = matrix.affine._m12;
995 affine._m21 = matrix.affine._m21;
996 affine._m22 = matrix.affine._m22;
997 affine._dx = matrix.affine._dx;
998 affine._dy = matrix.affine._dy;
1002 m_type = matrix.m_type;
1003 m_dirty = matrix.m_dirty;
1009 Resets the matrix to an identity matrix, i.e. all elements are set
1010 to zero, except \c m11 and \c m22 (specifying the scale) and \c m33
1013 \sa QTransform(), isIdentity(), {QTransform#Basic Matrix
1014 Operations}{Basic Matrix Operations}
1016 void QTransform::reset()
1018 affine._m11 = affine._m22 = m_33 = 1.0;
1019 affine._m12 = m_13 = affine._m21 = m_23 = affine._dx = affine._dy = 0;
1024 #ifndef QT_NO_DATASTREAM
1026 \fn QDataStream &operator<<(QDataStream &stream, const QTransform &matrix)
1030 Writes the given \a matrix to the given \a stream and returns a
1031 reference to the stream.
1033 \sa {Serializing Qt Data Types}
1035 QDataStream & operator<<(QDataStream &s, const QTransform &m)
1037 s << double(m.m11())
1050 \fn QDataStream &operator>>(QDataStream &stream, QTransform &matrix)
1054 Reads the given \a matrix from the given \a stream and returns a
1055 reference to the stream.
1057 \sa {Serializing Qt Data Types}
1059 QDataStream & operator>>(QDataStream &s, QTransform &t)
1061 double m11, m12, m13,
1074 t.setMatrix(m11, m12, m13,
1080 #endif // QT_NO_DATASTREAM
1082 #ifndef QT_NO_DEBUG_STREAM
1083 QDebug operator<<(QDebug dbg, const QTransform &m)
1085 static const char *typeStr[] =
1094 0, 0, 0, 0, 0, 0, 0,
1098 dbg.nospace() << "QTransform(type=" << typeStr[m.type()] << ','
1099 << " 11=" << m.m11()
1100 << " 12=" << m.m12()
1101 << " 13=" << m.m13()
1102 << " 21=" << m.m21()
1103 << " 22=" << m.m22()
1104 << " 23=" << m.m23()
1105 << " 31=" << m.m31()
1106 << " 32=" << m.m32()
1107 << " 33=" << m.m33()
1115 \fn QPoint operator*(const QPoint &point, const QTransform &matrix)
1118 This is the same as \a{matrix}.map(\a{point}).
1120 \sa QTransform::map()
1122 QPoint QTransform::map(const QPoint &p) const
1129 TransformationType t = inline_type();
1136 x = fx + affine._dx;
1137 y = fy + affine._dy;
1140 x = affine._m11 * fx + affine._dx;
1141 y = affine._m22 * fy + affine._dy;
1146 x = affine._m11 * fx + affine._m21 * fy + affine._dx;
1147 y = affine._m12 * fx + affine._m22 * fy + affine._dy;
1148 if (t == TxProject) {
1149 qreal w = 1./(m_13 * fx + m_23 * fy + m_33);
1154 return QPoint(qRound(x), qRound(y));
1159 \fn QPointF operator*(const QPointF &point, const QTransform &matrix)
1162 Same as \a{matrix}.map(\a{point}).
1164 \sa QTransform::map()
1170 Creates and returns a QPointF object that is a copy of the given point,
1171 \a p, mapped into the coordinate system defined by this matrix.
1173 QPointF QTransform::map(const QPointF &p) const
1180 TransformationType t = inline_type();
1187 x = fx + affine._dx;
1188 y = fy + affine._dy;
1191 x = affine._m11 * fx + affine._dx;
1192 y = affine._m22 * fy + affine._dy;
1197 x = affine._m11 * fx + affine._m21 * fy + affine._dx;
1198 y = affine._m12 * fx + affine._m22 * fy + affine._dy;
1199 if (t == TxProject) {
1200 qreal w = 1./(m_13 * fx + m_23 * fy + m_33);
1205 return QPointF(x, y);
1209 \fn QPoint QTransform::map(const QPoint &point) const
1212 Creates and returns a QPoint object that is a copy of the given \a
1213 point, mapped into the coordinate system defined by this
1214 matrix. Note that the transformed coordinates are rounded to the
1219 \fn QLineF operator*(const QLineF &line, const QTransform &matrix)
1222 This is the same as \a{matrix}.map(\a{line}).
1224 \sa QTransform::map()
1228 \fn QLine operator*(const QLine &line, const QTransform &matrix)
1231 This is the same as \a{matrix}.map(\a{line}).
1233 \sa QTransform::map()
1239 Creates and returns a QLineF object that is a copy of the given line,
1240 \a l, mapped into the coordinate system defined by this matrix.
1242 QLine QTransform::map(const QLine &l) const
1249 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1251 TransformationType t = inline_type();
1260 x1 = fx1 + affine._dx;
1261 y1 = fy1 + affine._dy;
1262 x2 = fx2 + affine._dx;
1263 y2 = fy2 + affine._dy;
1266 x1 = affine._m11 * fx1 + affine._dx;
1267 y1 = affine._m22 * fy1 + affine._dy;
1268 x2 = affine._m11 * fx2 + affine._dx;
1269 y2 = affine._m22 * fy2 + affine._dy;
1274 x1 = affine._m11 * fx1 + affine._m21 * fy1 + affine._dx;
1275 y1 = affine._m12 * fx1 + affine._m22 * fy1 + affine._dy;
1276 x2 = affine._m11 * fx2 + affine._m21 * fy2 + affine._dx;
1277 y2 = affine._m12 * fx2 + affine._m22 * fy2 + affine._dy;
1278 if (t == TxProject) {
1279 qreal w = 1./(m_13 * fx1 + m_23 * fy1 + m_33);
1282 w = 1./(m_13 * fx2 + m_23 * fy2 + m_33);
1287 return QLine(qRound(x1), qRound(y1), qRound(x2), qRound(y2));
1293 \fn QLineF QTransform::map(const QLineF &line) const
1295 Creates and returns a QLine object that is a copy of the given \a
1296 line, mapped into the coordinate system defined by this matrix.
1297 Note that the transformed coordinates are rounded to the nearest
1301 QLineF QTransform::map(const QLineF &l) const
1308 qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1310 TransformationType t = inline_type();
1319 x1 = fx1 + affine._dx;
1320 y1 = fy1 + affine._dy;
1321 x2 = fx2 + affine._dx;
1322 y2 = fy2 + affine._dy;
1325 x1 = affine._m11 * fx1 + affine._dx;
1326 y1 = affine._m22 * fy1 + affine._dy;
1327 x2 = affine._m11 * fx2 + affine._dx;
1328 y2 = affine._m22 * fy2 + affine._dy;
1333 x1 = affine._m11 * fx1 + affine._m21 * fy1 + affine._dx;
1334 y1 = affine._m12 * fx1 + affine._m22 * fy1 + affine._dy;
1335 x2 = affine._m11 * fx2 + affine._m21 * fy2 + affine._dx;
1336 y2 = affine._m12 * fx2 + affine._m22 * fy2 + affine._dy;
1337 if (t == TxProject) {
1338 qreal w = 1./(m_13 * fx1 + m_23 * fy1 + m_33);
1341 w = 1./(m_13 * fx2 + m_23 * fy2 + m_33);
1346 return QLineF(x1, y1, x2, y2);
1349 static QPolygonF mapProjective(const QTransform &transform, const QPolygonF &poly)
1351 if (poly.size() == 0)
1354 if (poly.size() == 1)
1355 return QPolygonF() << transform.map(poly.at(0));
1358 path.addPolygon(poly);
1360 path = transform.map(path);
1363 for (int i = 0; i < path.elementCount(); ++i)
1364 result << path.elementAt(i);
1370 \fn QPolygonF operator *(const QPolygonF &polygon, const QTransform &matrix)
1374 This is the same as \a{matrix}.map(\a{polygon}).
1376 \sa QTransform::map()
1380 \fn QPolygon operator*(const QPolygon &polygon, const QTransform &matrix)
1383 This is the same as \a{matrix}.map(\a{polygon}).
1385 \sa QTransform::map()
1389 \fn QPolygonF QTransform::map(const QPolygonF &polygon) const
1392 Creates and returns a QPolygonF object that is a copy of the given
1393 \a polygon, mapped into the coordinate system defined by this
1396 QPolygonF QTransform::map(const QPolygonF &a) const
1398 TransformationType t = inline_type();
1399 if (t <= TxTranslate)
1400 return a.translated(affine._dx, affine._dy);
1402 if (t >= QTransform::TxProject)
1403 return mapProjective(*this, a);
1405 int size = a.size();
1408 const QPointF *da = a.constData();
1409 QPointF *dp = p.data();
1411 for(i = 0; i < size; ++i) {
1412 MAP(da[i].xp, da[i].yp, dp[i].xp, dp[i].yp);
1418 \fn QPolygon QTransform::map(const QPolygon &polygon) const
1421 Creates and returns a QPolygon object that is a copy of the given
1422 \a polygon, mapped into the coordinate system defined by this
1423 matrix. Note that the transformed coordinates are rounded to the
1426 QPolygon QTransform::map(const QPolygon &a) const
1428 TransformationType t = inline_type();
1429 if (t <= TxTranslate)
1430 return a.translated(qRound(affine._dx), qRound(affine._dy));
1432 if (t >= QTransform::TxProject)
1433 return mapProjective(*this, QPolygonF(a)).toPolygon();
1435 int size = a.size();
1438 const QPoint *da = a.constData();
1439 QPoint *dp = p.data();
1441 for(i = 0; i < size; ++i) {
1442 qreal nx = 0, ny = 0;
1443 MAP(da[i].xp, da[i].yp, nx, ny);
1444 dp[i].xp = qRound(nx);
1445 dp[i].yp = qRound(ny);
1451 \fn QRegion operator*(const QRegion ®ion, const QTransform &matrix)
1454 This is the same as \a{matrix}.map(\a{region}).
1456 \sa QTransform::map()
1459 extern QPainterPath qt_regionToPath(const QRegion ®ion);
1462 \fn QRegion QTransform::map(const QRegion ®ion) const
1465 Creates and returns a QRegion object that is a copy of the given
1466 \a region, mapped into the coordinate system defined by this matrix.
1468 Calling this method can be rather expensive if rotations or
1471 QRegion QTransform::map(const QRegion &r) const
1473 TransformationType t = inline_type();
1477 if (t == TxTranslate) {
1479 copy.translate(qRound(affine._dx), qRound(affine._dy));
1483 if (t == TxScale && r.rectCount() == 1)
1484 return QRegion(mapRect(r.boundingRect()));
1486 QPainterPath p = map(qt_regionToPath(r));
1487 return p.toFillPolygon(QTransform()).toPolygon();
1490 struct QHomogeneousCoordinate
1496 QHomogeneousCoordinate() {}
1497 QHomogeneousCoordinate(qreal x_, qreal y_, qreal w_) : x(x_), y(y_), w(w_) {}
1499 const QPointF toPoint() const {
1501 return QPointF(x * iw, y * iw);
1505 static inline QHomogeneousCoordinate mapHomogeneous(const QTransform &transform, const QPointF &p)
1507 QHomogeneousCoordinate c;
1508 c.x = transform.m11() * p.x() + transform.m21() * p.y() + transform.m31();
1509 c.y = transform.m12() * p.x() + transform.m22() * p.y() + transform.m32();
1510 c.w = transform.m13() * p.x() + transform.m23() * p.y() + transform.m33();
1514 static inline bool lineTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b,
1515 bool needsMoveTo, bool needsLineTo = true)
1517 QHomogeneousCoordinate ha = mapHomogeneous(transform, a);
1518 QHomogeneousCoordinate hb = mapHomogeneous(transform, b);
1520 if (ha.w < Q_NEAR_CLIP && hb.w < Q_NEAR_CLIP)
1523 if (hb.w < Q_NEAR_CLIP) {
1524 const qreal t = (Q_NEAR_CLIP - hb.w) / (ha.w - hb.w);
1526 hb.x += (ha.x - hb.x) * t;
1527 hb.y += (ha.y - hb.y) * t;
1528 hb.w = qreal(Q_NEAR_CLIP);
1529 } else if (ha.w < Q_NEAR_CLIP) {
1530 const qreal t = (Q_NEAR_CLIP - ha.w) / (hb.w - ha.w);
1532 ha.x += (hb.x - ha.x) * t;
1533 ha.y += (hb.y - ha.y) * t;
1534 ha.w = qreal(Q_NEAR_CLIP);
1536 const QPointF p = ha.toPoint();
1539 needsMoveTo = false;
1546 path.moveTo(ha.toPoint());
1549 path.lineTo(hb.toPoint());
1553 Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
1555 static inline bool cubicTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, bool needsMoveTo)
1557 // Convert projective xformed curves to line
1558 // segments so they can be transformed more accurately
1561 qt_scaleForTransform(transform, &scale);
1563 qreal curveThreshold = scale == 0 ? qreal(0.25) : (qreal(0.25) / scale);
1565 QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(curveThreshold);
1567 for (int i = 0; i < segment.size() - 1; ++i)
1568 if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo))
1569 needsMoveTo = false;
1571 return !needsMoveTo;
1574 static QPainterPath mapProjective(const QTransform &transform, const QPainterPath &path)
1576 QPainterPath result;
1580 bool needsMoveTo = true;
1581 for (int i = 0; i < path.elementCount(); ++i) {
1582 switch (path.elementAt(i).type) {
1583 case QPainterPath::MoveToElement:
1584 if (i > 0 && lastMoveTo != last)
1585 lineTo_clipped(result, transform, last, lastMoveTo, needsMoveTo);
1587 lastMoveTo = path.elementAt(i);
1588 last = path.elementAt(i);
1591 case QPainterPath::LineToElement:
1592 if (lineTo_clipped(result, transform, last, path.elementAt(i), needsMoveTo))
1593 needsMoveTo = false;
1594 last = path.elementAt(i);
1596 case QPainterPath::CurveToElement:
1597 if (cubicTo_clipped(result, transform, last, path.elementAt(i), path.elementAt(i+1), path.elementAt(i+2), needsMoveTo))
1598 needsMoveTo = false;
1600 last = path.elementAt(i);
1607 if (path.elementCount() > 0 && lastMoveTo != last)
1608 lineTo_clipped(result, transform, last, lastMoveTo, needsMoveTo, false);
1610 result.setFillRule(path.fillRule());
1615 \fn QPainterPath operator *(const QPainterPath &path, const QTransform &matrix)
1619 This is the same as \a{matrix}.map(\a{path}).
1621 \sa QTransform::map()
1627 Creates and returns a QPainterPath object that is a copy of the
1628 given \a path, mapped into the coordinate system defined by this
1631 QPainterPath QTransform::map(const QPainterPath &path) const
1633 TransformationType t = inline_type();
1634 if (t == TxNone || path.elementCount() == 0)
1638 return mapProjective(*this, path);
1640 QPainterPath copy = path;
1642 if (t == TxTranslate) {
1643 copy.translate(affine._dx, affine._dy);
1647 for (int i=0; i<path.elementCount(); ++i) {
1648 QPainterPath::Element &e = copy.d_ptr->elements[i];
1649 MAP(e.x, e.y, e.x, e.y);
1657 \fn QPolygon QTransform::mapToPolygon(const QRect &rectangle) const
1659 Creates and returns a QPolygon representation of the given \a
1660 rectangle, mapped into the coordinate system defined by this
1663 The rectangle's coordinates are transformed using the following
1666 \snippet code/src_gui_painting_qtransform.cpp 1
1668 Polygons and rectangles behave slightly differently when
1669 transformed (due to integer rounding), so
1670 \c{matrix.map(QPolygon(rectangle))} is not always the same as
1671 \c{matrix.mapToPolygon(rectangle)}.
1673 \sa mapRect(), {QTransform#Basic Matrix Operations}{Basic Matrix
1676 QPolygon QTransform::mapToPolygon(const QRect &rect) const
1678 TransformationType t = inline_type();
1681 qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 };
1683 x[0] = affine._m11*rect.x() + affine._dx;
1684 y[0] = affine._m22*rect.y() + affine._dy;
1685 qreal w = affine._m11*rect.width();
1686 qreal h = affine._m22*rect.height();
1702 qreal right = rect.x() + rect.width();
1703 qreal bottom = rect.y() + rect.height();
1704 MAP(rect.x(), rect.y(), x[0], y[0]);
1705 MAP(right, rect.y(), x[1], y[1]);
1706 MAP(right, bottom, x[2], y[2]);
1707 MAP(rect.x(), bottom, x[3], y[3]);
1710 // all coordinates are correctly, tranform to a pointarray
1711 // (rounding to the next integer)
1712 a.setPoints(4, qRound(x[0]), qRound(y[0]),
1713 qRound(x[1]), qRound(y[1]),
1714 qRound(x[2]), qRound(y[2]),
1715 qRound(x[3]), qRound(y[3]));
1720 Creates a transformation matrix, \a trans, that maps a unit square
1721 to a four-sided polygon, \a quad. Returns true if the transformation
1722 is constructed or false if such a transformation does not exist.
1724 \sa quadToSquare(), quadToQuad()
1726 bool QTransform::squareToQuad(const QPolygonF &quad, QTransform &trans)
1728 if (quad.count() != 4)
1731 qreal dx0 = quad[0].x();
1732 qreal dx1 = quad[1].x();
1733 qreal dx2 = quad[2].x();
1734 qreal dx3 = quad[3].x();
1736 qreal dy0 = quad[0].y();
1737 qreal dy1 = quad[1].y();
1738 qreal dy2 = quad[2].y();
1739 qreal dy3 = quad[3].y();
1741 double ax = dx0 - dx1 + dx2 - dx3;
1742 double ay = dy0 - dy1 + dy2 - dy3;
1744 if (!ax && !ay) { //afine transform
1745 trans.setMatrix(dx1 - dx0, dy1 - dy0, 0,
1746 dx2 - dx1, dy2 - dy1, 0,
1749 double ax1 = dx1 - dx2;
1750 double ax2 = dx3 - dx2;
1751 double ay1 = dy1 - dy2;
1752 double ay2 = dy3 - dy2;
1755 double gtop = ax * ay2 - ax2 * ay;
1756 double htop = ax1 * ay - ax * ay1;
1757 double bottom = ax1 * ay2 - ax2 * ay1;
1759 double a, b, c, d, e, f, g, h; /*i is always 1*/
1767 a = dx1 - dx0 + g * dx1;
1768 b = dx3 - dx0 + h * dx3;
1770 d = dy1 - dy0 + g * dy1;
1771 e = dy3 - dy0 + h * dy3;
1774 trans.setMatrix(a, d, g,
1783 \fn bool QTransform::quadToSquare(const QPolygonF &quad, QTransform &trans)
1785 Creates a transformation matrix, \a trans, that maps a four-sided polygon,
1786 \a quad, to a unit square. Returns true if the transformation is constructed
1787 or false if such a transformation does not exist.
1789 \sa squareToQuad(), quadToQuad()
1791 bool QTransform::quadToSquare(const QPolygonF &quad, QTransform &trans)
1793 if (!squareToQuad(quad, trans))
1796 bool invertible = false;
1797 trans = trans.inverted(&invertible);
1803 Creates a transformation matrix, \a trans, that maps a four-sided
1804 polygon, \a one, to another four-sided polygon, \a two.
1805 Returns true if the transformation is possible; otherwise returns
1808 This is a convenience method combining quadToSquare() and
1809 squareToQuad() methods. It allows the input quad to be
1810 transformed into any other quad.
1812 \sa squareToQuad(), quadToSquare()
1814 bool QTransform::quadToQuad(const QPolygonF &one,
1815 const QPolygonF &two,
1819 if (!quadToSquare(one, trans))
1821 if (!squareToQuad(two, stq))
1824 //qDebug()<<"Final = "<<trans;
1829 Sets the matrix elements to the specified values, \a m11,
1830 \a m12, \a m13 \a m21, \a m22, \a m23 \a m31, \a m32 and
1831 \a m33. Note that this function replaces the previous values.
1832 QTransform provides the translate(), rotate(), scale() and shear()
1833 convenience functions to manipulate the various matrix elements
1834 based on the currently defined coordinate system.
1839 void QTransform::setMatrix(qreal m11, qreal m12, qreal m13,
1840 qreal m21, qreal m22, qreal m23,
1841 qreal m31, qreal m32, qreal m33)
1843 affine._m11 = m11; affine._m12 = m12; m_13 = m13;
1844 affine._m21 = m21; affine._m22 = m22; m_23 = m23;
1845 affine._dx = m31; affine._dy = m32; m_33 = m33;
1847 m_dirty = TxProject;
1850 static inline bool needsPerspectiveClipping(const QRectF &rect, const QTransform &transform)
1852 const qreal wx = qMin(transform.m13() * rect.left(), transform.m13() * rect.right());
1853 const qreal wy = qMin(transform.m23() * rect.top(), transform.m23() * rect.bottom());
1855 return wx + wy + transform.m33() < Q_NEAR_CLIP;
1858 QRect QTransform::mapRect(const QRect &rect) const
1860 TransformationType t = inline_type();
1861 if (t <= TxTranslate)
1862 return rect.translated(qRound(affine._dx), qRound(affine._dy));
1865 int x = qRound(affine._m11*rect.x() + affine._dx);
1866 int y = qRound(affine._m22*rect.y() + affine._dy);
1867 int w = qRound(affine._m11*rect.width());
1868 int h = qRound(affine._m22*rect.height());
1877 return QRect(x, y, w, h);
1878 } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
1879 // see mapToPolygon for explanations of the algorithm.
1881 MAP(rect.left(), rect.top(), x, y);
1886 MAP(rect.right() + 1, rect.top(), x, y);
1887 xmin = qMin(xmin, x);
1888 ymin = qMin(ymin, y);
1889 xmax = qMax(xmax, x);
1890 ymax = qMax(ymax, y);
1891 MAP(rect.right() + 1, rect.bottom() + 1, x, y);
1892 xmin = qMin(xmin, x);
1893 ymin = qMin(ymin, y);
1894 xmax = qMax(xmax, x);
1895 ymax = qMax(ymax, y);
1896 MAP(rect.left(), rect.bottom() + 1, x, y);
1897 xmin = qMin(xmin, x);
1898 ymin = qMin(ymin, y);
1899 xmax = qMax(xmax, x);
1900 ymax = qMax(ymax, y);
1901 return QRect(qRound(xmin), qRound(ymin), qRound(xmax)-qRound(xmin), qRound(ymax)-qRound(ymin));
1905 return map(path).boundingRect().toRect();
1910 \fn QRectF QTransform::mapRect(const QRectF &rectangle) const
1912 Creates and returns a QRectF object that is a copy of the given \a
1913 rectangle, mapped into the coordinate system defined by this
1916 The rectangle's coordinates are transformed using the following
1919 \snippet code/src_gui_painting_qtransform.cpp 2
1921 If rotation or shearing has been specified, this function returns
1922 the \e bounding rectangle. To retrieve the exact region the given
1923 \a rectangle maps to, use the mapToPolygon() function instead.
1925 \sa mapToPolygon(), {QTransform#Basic Matrix Operations}{Basic Matrix
1928 QRectF QTransform::mapRect(const QRectF &rect) const
1930 TransformationType t = inline_type();
1931 if (t <= TxTranslate)
1932 return rect.translated(affine._dx, affine._dy);
1935 qreal x = affine._m11*rect.x() + affine._dx;
1936 qreal y = affine._m22*rect.y() + affine._dy;
1937 qreal w = affine._m11*rect.width();
1938 qreal h = affine._m22*rect.height();
1947 return QRectF(x, y, w, h);
1948 } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
1950 MAP(rect.x(), rect.y(), x, y);
1955 MAP(rect.x() + rect.width(), rect.y(), x, y);
1956 xmin = qMin(xmin, x);
1957 ymin = qMin(ymin, y);
1958 xmax = qMax(xmax, x);
1959 ymax = qMax(ymax, y);
1960 MAP(rect.x() + rect.width(), rect.y() + rect.height(), x, y);
1961 xmin = qMin(xmin, x);
1962 ymin = qMin(ymin, y);
1963 xmax = qMax(xmax, x);
1964 ymax = qMax(ymax, y);
1965 MAP(rect.x(), rect.y() + rect.height(), x, y);
1966 xmin = qMin(xmin, x);
1967 ymin = qMin(ymin, y);
1968 xmax = qMax(xmax, x);
1969 ymax = qMax(ymax, y);
1970 return QRectF(xmin, ymin, xmax-xmin, ymax - ymin);
1974 return map(path).boundingRect();
1979 \fn QRect QTransform::mapRect(const QRect &rectangle) const
1982 Creates and returns a QRect object that is a copy of the given \a
1983 rectangle, mapped into the coordinate system defined by this
1984 matrix. Note that the transformed coordinates are rounded to the
1989 Maps the given coordinates \a x and \a y into the coordinate
1990 system defined by this matrix. The resulting values are put in *\a
1991 tx and *\a ty, respectively.
1993 The coordinates are transformed using the following formulas:
1995 \snippet code/src_gui_painting_qtransform.cpp 3
1997 The point (x, y) is the original point, and (x', y') is the
2000 \sa {QTransform#Basic Matrix Operations}{Basic Matrix Operations}
2002 void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty) const
2004 TransformationType t = inline_type();
2005 MAP(x, y, *tx, *ty);
2011 Maps the given coordinates \a x and \a y into the coordinate
2012 system defined by this matrix. The resulting values are put in *\a
2013 tx and *\a ty, respectively. Note that the transformed coordinates
2014 are rounded to the nearest integer.
2016 void QTransform::map(int x, int y, int *tx, int *ty) const
2018 TransformationType t = inline_type();
2019 qreal fx = 0, fy = 0;
2026 Returns the QTransform as an affine matrix.
2028 \warning If a perspective transformation has been specified,
2029 then the conversion will cause loss of data.
2031 const QMatrix &QTransform::toAffine() const
2037 Returns the transformation type of this matrix.
2039 The transformation type is the highest enumeration value
2040 capturing all of the matrix's transformations. For example,
2041 if the matrix both scales and shears, the type would be \c TxShear,
2042 because \c TxShear has a higher enumeration value than \c TxScale.
2044 Knowing the transformation type of a matrix is useful for optimization:
2045 you can often handle specific types more optimally than handling
2048 QTransform::TransformationType QTransform::type() const
2050 if(m_dirty == TxNone || m_dirty < m_type)
2051 return static_cast<TransformationType>(m_type);
2053 switch (static_cast<TransformationType>(m_dirty)) {
2055 if (!qFuzzyIsNull(m_13) || !qFuzzyIsNull(m_23) || !qFuzzyIsNull(m_33 - 1)) {
2061 if (!qFuzzyIsNull(affine._m12) || !qFuzzyIsNull(affine._m21)) {
2062 const qreal dot = affine._m11 * affine._m12 + affine._m21 * affine._m22;
2063 if (qFuzzyIsNull(dot))
2070 if (!qFuzzyIsNull(affine._m11 - 1) || !qFuzzyIsNull(affine._m22 - 1)) {
2075 if (!qFuzzyIsNull(affine._dx) || !qFuzzyIsNull(affine._dy)) {
2076 m_type = TxTranslate;
2085 return static_cast<TransformationType>(m_type);
2090 Returns the transform as a QVariant.
2092 QTransform::operator QVariant() const
2094 return QVariant(QVariant::Transform, this);
2099 \fn bool QTransform::isInvertible() const
2101 Returns true if the matrix is invertible, otherwise returns false.
2107 \fn qreal QTransform::det() const
2110 Returns the matrix's determinant. Use determinant() instead.
2115 \fn qreal QTransform::m11() const
2117 Returns the horizontal scaling factor.
2119 \sa scale(), {QTransform#Basic Matrix Operations}{Basic Matrix
2124 \fn qreal QTransform::m12() const
2126 Returns the vertical shearing factor.
2128 \sa shear(), {QTransform#Basic Matrix Operations}{Basic Matrix
2133 \fn qreal QTransform::m21() const
2135 Returns the horizontal shearing factor.
2137 \sa shear(), {QTransform#Basic Matrix Operations}{Basic Matrix
2142 \fn qreal QTransform::m22() const
2144 Returns the vertical scaling factor.
2146 \sa scale(), {QTransform#Basic Matrix Operations}{Basic Matrix
2151 \fn qreal QTransform::dx() const
2153 Returns the horizontal translation factor.
2155 \sa m31(), translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2160 \fn qreal QTransform::dy() const
2162 Returns the vertical translation factor.
2164 \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2170 \fn qreal QTransform::m13() const
2172 Returns the horizontal projection factor.
2174 \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2180 \fn qreal QTransform::m23() const
2182 Returns the vertical projection factor.
2184 \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2189 \fn qreal QTransform::m31() const
2191 Returns the horizontal translation factor.
2193 \sa dx(), translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2198 \fn qreal QTransform::m32() const
2200 Returns the vertical translation factor.
2202 \sa dy(), translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2207 \fn qreal QTransform::m33() const
2209 Returns the division factor.
2211 \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2216 \fn qreal QTransform::determinant() const
2218 Returns the matrix's determinant.
2222 \fn bool QTransform::isIdentity() const
2224 Returns true if the matrix is the identity matrix, otherwise
2231 \fn bool QTransform::isAffine() const
2233 Returns true if the matrix represent an affine transformation,
2234 otherwise returns false.
2238 \fn bool QTransform::isScaling() const
2240 Returns true if the matrix represents a scaling
2241 transformation, otherwise returns false.
2247 \fn bool QTransform::isRotating() const
2249 Returns true if the matrix represents some kind of a
2250 rotating transformation, otherwise returns false.
2252 \note A rotation transformation of 180 degrees and/or 360 degrees is treated as a scaling transformation.
2258 \fn bool QTransform::isTranslating() const
2260 Returns true if the matrix represents a translating
2261 transformation, otherwise returns false.
2267 \fn bool qFuzzyCompare(const QTransform& t1, const QTransform& t2)
2272 Returns true if \a t1 and \a t2 are equal, allowing for a small
2273 fuzziness factor for floating-point comparisons; false otherwise.
2277 // returns true if the transform is uniformly scaling
2278 // (same scale in x and y direction)
2279 // scale is set to the max of x and y scaling factors
2281 bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
2283 const QTransform::TransformationType type = transform.type();
2284 if (type <= QTransform::TxTranslate) {
2288 } else if (type == QTransform::TxScale) {
2289 const qreal xScale = qAbs(transform.m11());
2290 const qreal yScale = qAbs(transform.m22());
2292 *scale = qMax(xScale, yScale);
2293 return qFuzzyCompare(xScale, yScale);
2296 const qreal xScale = transform.m11() * transform.m11()
2297 + transform.m21() * transform.m21();
2298 const qreal yScale = transform.m12() * transform.m12()
2299 + transform.m22() * transform.m22();
2301 *scale = qSqrt(qMax(xScale, yScale));
2302 return type == QTransform::TxRotate && qFuzzyCompare(xScale, yScale);