Update spec to build Qt 5.0
[profile/ivi/qtbase.git] / src / gui / painting / qtransform.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include "qtransform.h"
42
43 #include "qdatastream.h"
44 #include "qdebug.h"
45 #include "qmatrix.h"
46 #include "qregion.h"
47 #include "qpainterpath.h"
48 #include "qpainterpath_p.h"
49 #include "qvariant.h"
50 #include <qmath.h>
51 #include <qnumeric.h>
52
53 #include <private/qbezier_p.h>
54
55 QT_BEGIN_NAMESPACE
56
57 #define Q_NEAR_CLIP (sizeof(qreal) == sizeof(double) ? 0.000001 : 0.0001)
58
59 #ifdef MAP
60 #  undef MAP
61 #endif
62 #define MAP(x, y, nx, ny) \
63     do { \
64         qreal FX_ = x; \
65         qreal FY_ = y; \
66         switch(t) {   \
67         case TxNone:  \
68             nx = FX_;   \
69             ny = FY_;   \
70             break;    \
71         case TxTranslate:    \
72             nx = FX_ + affine._dx;                \
73             ny = FY_ + affine._dy;                \
74             break;                              \
75         case TxScale:                           \
76             nx = affine._m11 * FX_ + affine._dx;  \
77             ny = affine._m22 * FY_ + affine._dy;  \
78             break;                              \
79         case TxRotate:                          \
80         case TxShear:                           \
81         case TxProject:                                      \
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);     \
87                 w = 1./w;                                               \
88                 nx *= w;                                                \
89                 ny *= w;                                                \
90             }                                                           \
91         }                                                               \
92     } while (0)
93
94 /*!
95     \class QTransform
96     \brief The QTransform class specifies 2D transformations of a coordinate system.
97     \since 4.3
98     \ingroup painting
99     \inmodule QtGui
100
101     A transformation specifies how to translate, scale, shear, rotate
102     or project the coordinate system, and is typically used when
103     rendering graphics.
104
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.
110
111     QTransform is the recommended transformation class in Qt.
112
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.
119
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.
127
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.
136
137     Finally, the QTransform class supports matrix multiplication, addition
138     and subtraction, and objects of the class can be streamed as well
139     as compared.
140
141     \tableofcontents
142
143     \section1 Rendering Graphics
144
145     When rendering graphics, the matrix defines the transformations
146     but the actual transformation is performed by the drawing routines
147     in QPainter.
148
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.
155
156     QPainter has functions to translate, scale, shear and rotate the
157     coordinate system without using a QTransform. For example:
158
159     \table 100%
160     \row
161     \li \inlineimage qtransform-simpletransformation.png
162     \li
163     \snippet transform/main.cpp 0
164     \endtable
165
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
169     example:
170
171     \table 100%
172     \row
173     \li \inlineimage qtransform-combinedtransformation.png
174     \li
175     \snippet transform/main.cpp 1
176     \endtable
177
178     \section1 Basic Matrix Operations
179
180     \image qtransform-representation.png
181
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.
188
189     QTransform transforms a point in the plane to another point using the
190     following formulas:
191
192     \snippet code/src_gui_painting_qtransform.cpp 0
193
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.
197
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.
204
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
216     the scaling factors.
217
218     Here's the combined transformations example using basic matrix
219     operations:
220
221     \table 100%
222     \row
223     \li \inlineimage qtransform-combinedtransformation2.png
224     \li
225     \snippet transform/main.cpp 2
226     \endtable
227
228     \sa QPainter, {Coordinate System}, {painting/affine}{Affine
229     Transformations Example}, {Transformations Example}
230 */
231
232 /*!
233     \enum QTransform::TransformationType
234
235     \value TxNone
236     \value TxTranslate
237     \value TxScale
238     \value TxRotate
239     \value TxShear
240     \value TxProject
241 */
242
243 /*!
244     \fn QTransform::QTransform(Qt::Initialization)
245     \internal
246 */
247
248 /*!
249     Constructs an identity matrix.
250
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.
253
254     \sa reset()
255 */
256 QTransform::QTransform()
257     : affine(true)
258     , m_13(0), m_23(0), m_33(1)
259     , m_type(TxNone)
260     , m_dirty(TxNone)
261 {
262 }
263
264 /*!
265     \fn QTransform::QTransform(qreal m11, qreal m12, qreal m13, qreal m21, qreal m22, qreal m23, qreal m31, qreal m32, qreal m33)
266
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.
269
270     \sa setMatrix()
271 */
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)
277     , m_type(TxNone)
278     , m_dirty(TxProject)
279 {
280 }
281
282 /*!
283     \fn QTransform::QTransform(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy)
284
285     Constructs a matrix with the elements, \a m11, \a m12, \a m21, \a m22, \a dx and \a dy.
286
287     \sa setMatrix()
288 */
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)
293     , m_type(TxNone)
294     , m_dirty(TxShear)
295 {
296 }
297
298 /*!
299     \fn QTransform::QTransform(const QMatrix &matrix)
300
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,
303     and 1 respectively.
304  */
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)
308     , m_type(TxNone)
309     , m_dirty(TxShear)
310 {
311 }
312
313 /*!
314     Returns the adjoint of this matrix.
315 */
316 QTransform QTransform::adjoint() const
317 {
318     qreal h11, h12, h13,
319         h21, h22, h23,
320         h31, h32, h33;
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;
330
331     return QTransform(h11, h12, h13,
332                       h21, h22, h23,
333                       h31, h32, h33, true);
334 }
335
336 /*!
337     Returns the transpose of this matrix.
338 */
339 QTransform QTransform::transposed() const
340 {
341     QTransform t(affine._m11, affine._m21, affine._dx,
342                  affine._m12, affine._m22, affine._dy,
343                  m_13, m_23, m_33, true);
344     t.m_type = m_type;
345     t.m_dirty = m_dirty;
346     return t;
347 }
348
349 /*!
350     Returns an inverted copy of this matrix.
351
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
355     set to false.
356
357     \sa isInvertible()
358 */
359 QTransform QTransform::inverted(bool *invertible) const
360 {
361     QTransform invert(true);
362     bool inv = true;
363
364     switch(inline_type()) {
365     case TxNone:
366         break;
367     case TxTranslate:
368         invert.affine._dx = -affine._dx;
369         invert.affine._dy = -affine._dy;
370         break;
371     case TxScale:
372         inv = !qFuzzyIsNull(affine._m11);
373         inv &= !qFuzzyIsNull(affine._m22);
374         if (inv) {
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;
379         }
380         break;
381     case TxRotate:
382     case TxShear:
383         invert.affine = affine.inverted(&inv);
384         break;
385     default:
386         // general case
387         qreal det = determinant();
388         inv = !qFuzzyIsNull(det);
389         if (inv)
390             invert = adjoint() / det;
391         break;
392     }
393
394     if (invertible)
395         *invertible = inv;
396
397     if (inv) {
398         // inverting doesn't change the type
399         invert.m_type = m_type;
400         invert.m_dirty = m_dirty;
401     }
402
403     return invert;
404 }
405
406 /*!
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.
409
410     \sa setMatrix()
411 */
412 QTransform &QTransform::translate(qreal dx, qreal dy)
413 {
414     if (dx == 0 && dy == 0)
415         return *this;
416 #ifndef QT_NO_DEBUG
417     if (qIsNaN(dx) | qIsNaN(dy)) {
418         qWarning() << "QTransform::translate with NaN called";
419         return *this;
420     }
421 #endif
422
423     switch(inline_type()) {
424     case TxNone:
425         affine._dx = dx;
426         affine._dy = dy;
427         break;
428     case TxTranslate:
429         affine._dx += dx;
430         affine._dy += dy;
431         break;
432     case TxScale:
433         affine._dx += dx*affine._m11;
434         affine._dy += dy*affine._m22;
435         break;
436     case TxProject:
437         m_33 += dx*m_13 + dy*m_23;
438         // Fall through
439     case TxShear:
440     case TxRotate:
441         affine._dx += dx*affine._m11 + dy*affine._m21;
442         affine._dy += dy*affine._m22 + dx*affine._m12;
443         break;
444     }
445     if (m_dirty < TxTranslate)
446         m_dirty = TxTranslate;
447     return *this;
448 }
449
450 /*!
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.
454
455     \since 4.5
456 */
457 QTransform QTransform::fromTranslate(qreal dx, qreal dy)
458 {
459 #ifndef QT_NO_DEBUG
460     if (qIsNaN(dx) | qIsNaN(dy)) {
461         qWarning() << "QTransform::fromTranslate with NaN called";
462         return QTransform();
463 }
464 #endif
465     QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1, true);
466     if (dx == 0 && dy == 0)
467         transform.m_type = TxNone;
468     else
469         transform.m_type = TxTranslate;
470     transform.m_dirty = TxNone;
471     return transform;
472 }
473
474 /*!
475     Scales the coordinate system by \a sx horizontally and \a sy
476     vertically, and returns a reference to the matrix.
477
478     \sa setMatrix()
479 */
480 QTransform & QTransform::scale(qreal sx, qreal sy)
481 {
482     if (sx == 1 && sy == 1)
483         return *this;
484 #ifndef QT_NO_DEBUG
485     if (qIsNaN(sx) | qIsNaN(sy)) {
486         qWarning() << "QTransform::scale with NaN called";
487         return *this;
488     }
489 #endif
490
491     switch(inline_type()) {
492     case TxNone:
493     case TxTranslate:
494         affine._m11 = sx;
495         affine._m22 = sy;
496         break;
497     case TxProject:
498         m_13 *= sx;
499         m_23 *= sy;
500         // fall through
501     case TxRotate:
502     case TxShear:
503         affine._m12 *= sx;
504         affine._m21 *= sy;
505         // fall through
506     case TxScale:
507         affine._m11 *= sx;
508         affine._m22 *= sy;
509         break;
510     }
511     if (m_dirty < TxScale)
512         m_dirty = TxScale;
513     return *this;
514 }
515
516 /*!
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.
520
521     \since 4.5
522 */
523 QTransform QTransform::fromScale(qreal sx, qreal sy)
524 {
525 #ifndef QT_NO_DEBUG
526     if (qIsNaN(sx) | qIsNaN(sy)) {
527         qWarning() << "QTransform::fromScale with NaN called";
528         return QTransform();
529 }
530 #endif
531     QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1, true);
532     if (sx == 1. && sy == 1.)
533         transform.m_type = TxNone;
534     else
535         transform.m_type = TxScale;
536     transform.m_dirty = TxNone;
537     return transform;
538 }
539
540 /*!
541     Shears the coordinate system by \a sh horizontally and \a sv
542     vertically, and returns a reference to the matrix.
543
544     \sa setMatrix()
545 */
546 QTransform & QTransform::shear(qreal sh, qreal sv)
547 {
548     if (sh == 0 && sv == 0)
549         return *this;
550 #ifndef QT_NO_DEBUG
551     if (qIsNaN(sh) | qIsNaN(sv)) {
552         qWarning() << "QTransform::shear with NaN called";
553         return *this;
554     }
555 #endif
556
557     switch(inline_type()) {
558     case TxNone:
559     case TxTranslate:
560         affine._m12 = sv;
561         affine._m21 = sh;
562         break;
563     case TxScale:
564         affine._m12 = sv*affine._m22;
565         affine._m21 = sh*affine._m11;
566         break;
567     case TxProject: {
568         qreal tm13 = sv*m_23;
569         qreal tm23 = sh*m_13;
570         m_13 += tm13;
571         m_23 += tm23;
572     }
573         // fall through
574     case TxRotate:
575     case TxShear: {
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;
582         break;
583     }
584     }
585     if (m_dirty < TxShear)
586         m_dirty = TxShear;
587     return *this;
588 }
589
590 const qreal deg2rad = qreal(0.017453292519943295769);        // pi/180
591 const qreal inv_dist_to_plane = 1. / 1024.;
592
593 /*!
594     \fn QTransform &QTransform::rotate(qreal angle, Qt::Axis axis)
595
596     Rotates the coordinate system counterclockwise by the given \a angle
597     about the specified \a axis and returns a reference to the matrix.
598
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.
602
603     The angle is specified in degrees.
604
605     \sa setMatrix()
606 */
607 QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
608 {
609     if (a == 0)
610         return *this;
611 #ifndef QT_NO_DEBUG
612     if (qIsNaN(a)) {
613         qWarning() << "QTransform::rotate with NaN called";
614         return *this;
615     }
616 #endif
617
618     qreal sina = 0;
619     qreal cosa = 0;
620     if (a == 90. || a == -270.)
621         sina = 1.;
622     else if (a == 270. || a == -90.)
623         sina = -1.;
624     else if (a == 180.)
625         cosa = -1.;
626     else{
627         qreal b = deg2rad*a;          // convert to radians
628         sina = qSin(b);               // fast and convenient
629         cosa = qCos(b);
630     }
631
632     if (axis == Qt::ZAxis) {
633         switch(inline_type()) {
634         case TxNone:
635         case TxTranslate:
636             affine._m11 = cosa;
637             affine._m12 = sina;
638             affine._m21 = -sina;
639             affine._m22 = cosa;
640             break;
641         case TxScale: {
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;
648             break;
649         }
650         case TxProject: {
651             qreal tm13 = cosa*m_13 + sina*m_23;
652             qreal tm23 = -sina*m_13 + cosa*m_23;
653             m_13 = tm13;
654             m_23 = tm23;
655             // fall through
656         }
657         case TxRotate:
658         case TxShear: {
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;
665             break;
666         }
667         }
668         if (m_dirty < TxRotate)
669             m_dirty = TxRotate;
670     } else {
671         QTransform result;
672         if (axis == Qt::YAxis) {
673             result.affine._m11 = cosa;
674             result.m_13 = -sina * inv_dist_to_plane;
675         } else {
676             result.affine._m22 = cosa;
677             result.m_23 = -sina * inv_dist_to_plane;
678         }
679         result.m_type = TxProject;
680         *this = result * *this;
681     }
682
683     return *this;
684 }
685
686 /*!
687     \fn QTransform & QTransform::rotateRadians(qreal angle, Qt::Axis axis)
688
689     Rotates the coordinate system counterclockwise by the given \a angle
690     about the specified \a axis and returns a reference to the matrix.
691
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.
695
696     The angle is specified in radians.
697
698     \sa setMatrix()
699 */
700 QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
701 {
702 #ifndef QT_NO_DEBUG
703     if (qIsNaN(a)) {
704         qWarning() << "QTransform::rotateRadians with NaN called";
705         return *this;
706     }
707 #endif
708     qreal sina = qSin(a);
709     qreal cosa = qCos(a);
710
711     if (axis == Qt::ZAxis) {
712         switch(inline_type()) {
713         case TxNone:
714         case TxTranslate:
715             affine._m11 = cosa;
716             affine._m12 = sina;
717             affine._m21 = -sina;
718             affine._m22 = cosa;
719             break;
720         case TxScale: {
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;
727             break;
728         }
729         case TxProject: {
730             qreal tm13 = cosa*m_13 + sina*m_23;
731             qreal tm23 = -sina*m_13 + cosa*m_23;
732             m_13 = tm13;
733             m_23 = tm23;
734             // fall through
735         }
736         case TxRotate:
737         case TxShear: {
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;
744             break;
745         }
746         }
747         if (m_dirty < TxRotate)
748             m_dirty = TxRotate;
749     } else {
750         QTransform result;
751         if (axis == Qt::YAxis) {
752             result.affine._m11 = cosa;
753             result.m_13 = -sina * inv_dist_to_plane;
754         } else {
755             result.affine._m22 = cosa;
756             result.m_23 = -sina * inv_dist_to_plane;
757         }
758         result.m_type = TxProject;
759         *this = result * *this;
760     }
761     return *this;
762 }
763
764 /*!
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.
768 */
769 bool QTransform::operator==(const QTransform &o) const
770 {
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 &&
777            m_13 == o.m_13 &&
778            m_23 == o.m_23 &&
779            m_33 == o.m_33;
780 }
781
782 /*!
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.
786 */
787 bool QTransform::operator!=(const QTransform &o) const
788 {
789     return !operator==(o);
790 }
791
792 /*!
793     \fn QTransform & QTransform::operator*=(const QTransform &matrix)
794     \overload
795
796     Returns the result of multiplying this matrix by the given \a
797     matrix.
798 */
799 QTransform & QTransform::operator*=(const QTransform &o)
800 {
801     const TransformationType otherType = o.inline_type();
802     if (otherType == TxNone)
803         return *this;
804
805     const TransformationType thisType = inline_type();
806     if (thisType == TxNone)
807         return operator=(o);
808
809     TransformationType t = qMax(thisType, otherType);
810     switch(t) {
811     case TxNone:
812         break;
813     case TxTranslate:
814         affine._dx += o.affine._dx;
815         affine._dy += o.affine._dy;
816         break;
817     case TxScale:
818     {
819         qreal m11 = affine._m11*o.affine._m11;
820         qreal m22 = affine._m22*o.affine._m22;
821
822         qreal m31 = affine._dx*o.affine._m11 + o.affine._dx;
823         qreal m32 = affine._dy*o.affine._m22 + o.affine._dy;
824
825         affine._m11 = m11;
826         affine._m22 = m22;
827         affine._dx = m31; affine._dy = m32;
828         break;
829     }
830     case TxRotate:
831     case TxShear:
832     {
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;
835
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;
838
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;
841
842         affine._m11 = m11; affine._m12 = m12;
843         affine._m21 = m21; affine._m22 = m22;
844         affine._dx = m31; affine._dy = m32;
845         break;
846     }
847     case TxProject:
848     {
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;
852
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;
856
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;
860
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;
864     }
865     }
866
867     m_dirty = t;
868     m_type = t;
869
870     return *this;
871 }
872
873 /*!
874     \fn QTransform QTransform::operator*(const QTransform &matrix) const
875     Returns the result of multiplying this matrix by the given \a
876     matrix.
877
878     Note that matrix multiplication is not commutative, i.e. a*b !=
879     b*a.
880 */
881 QTransform QTransform::operator*(const QTransform &m) const
882 {
883     const TransformationType otherType = m.inline_type();
884     if (otherType == TxNone)
885         return *this;
886
887     const TransformationType thisType = inline_type();
888     if (thisType == TxNone)
889         return m;
890
891     QTransform t(true);
892     TransformationType type = qMax(thisType, otherType);
893     switch(type) {
894     case TxNone:
895         break;
896     case TxTranslate:
897         t.affine._dx = affine._dx + m.affine._dx;
898         t.affine._dy += affine._dy + m.affine._dy;
899         break;
900     case TxScale:
901     {
902         qreal m11 = affine._m11*m.affine._m11;
903         qreal m22 = affine._m22*m.affine._m22;
904
905         qreal m31 = affine._dx*m.affine._m11 + m.affine._dx;
906         qreal m32 = affine._dy*m.affine._m22 + m.affine._dy;
907
908         t.affine._m11 = m11;
909         t.affine._m22 = m22;
910         t.affine._dx = m31; t.affine._dy = m32;
911         break;
912     }
913     case TxRotate:
914     case TxShear:
915     {
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;
918
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;
921
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;
924
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;
928         break;
929     }
930     case TxProject:
931     {
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;
935
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;
939
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;
943
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;
947     }
948     }
949
950     t.m_dirty = type;
951     t.m_type = type;
952
953     return t;
954 }
955
956 /*!
957     \fn QTransform & QTransform::operator*=(qreal scalar)
958     \overload
959
960     Returns the result of performing an element-wise multiplication of this
961     matrix with the given \a scalar.
962 */
963
964 /*!
965     \fn QTransform & QTransform::operator/=(qreal scalar)
966     \overload
967
968     Returns the result of performing an element-wise division of this
969     matrix by the given \a scalar.
970 */
971
972 /*!
973     \fn QTransform & QTransform::operator+=(qreal scalar)
974     \overload
975
976     Returns the matrix obtained by adding the given \a scalar to each
977     element of this matrix.
978 */
979
980 /*!
981     \fn QTransform & QTransform::operator-=(qreal scalar)
982     \overload
983
984     Returns the matrix obtained by subtracting the given \a scalar from each
985     element of this matrix.
986 */
987
988 /*!
989     Assigns the given \a matrix's values to this matrix.
990 */
991 QTransform & QTransform::operator=(const QTransform &matrix)
992 {
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;
999     m_13 = matrix.m_13;
1000     m_23 = matrix.m_23;
1001     m_33 = matrix.m_33;
1002     m_type = matrix.m_type;
1003     m_dirty = matrix.m_dirty;
1004
1005     return *this;
1006 }
1007
1008 /*!
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
1011     which are set to 1.
1012
1013     \sa QTransform(), isIdentity(), {QTransform#Basic Matrix
1014     Operations}{Basic Matrix Operations}
1015 */
1016 void QTransform::reset()
1017 {
1018     affine._m11 = affine._m22 = m_33 = 1.0;
1019     affine._m12 = m_13 = affine._m21 = m_23 = affine._dx = affine._dy = 0;
1020     m_type = TxNone;
1021     m_dirty = TxNone;
1022 }
1023
1024 #ifndef QT_NO_DATASTREAM
1025 /*!
1026     \fn QDataStream &operator<<(QDataStream &stream, const QTransform &matrix)
1027     \since 4.3
1028     \relates QTransform
1029
1030     Writes the given \a matrix to the given \a stream and returns a
1031     reference to the stream.
1032
1033     \sa {Serializing Qt Data Types}
1034 */
1035 QDataStream & operator<<(QDataStream &s, const QTransform &m)
1036 {
1037     s << double(m.m11())
1038       << double(m.m12())
1039       << double(m.m13())
1040       << double(m.m21())
1041       << double(m.m22())
1042       << double(m.m23())
1043       << double(m.m31())
1044       << double(m.m32())
1045       << double(m.m33());
1046     return s;
1047 }
1048
1049 /*!
1050     \fn QDataStream &operator>>(QDataStream &stream, QTransform &matrix)
1051     \since 4.3
1052     \relates QTransform
1053
1054     Reads the given \a matrix from the given \a stream and returns a
1055     reference to the stream.
1056
1057     \sa {Serializing Qt Data Types}
1058 */
1059 QDataStream & operator>>(QDataStream &s, QTransform &t)
1060 {
1061      double m11, m12, m13,
1062          m21, m22, m23,
1063          m31, m32, m33;
1064
1065      s >> m11;
1066      s >> m12;
1067      s >> m13;
1068      s >> m21;
1069      s >> m22;
1070      s >> m23;
1071      s >> m31;
1072      s >> m32;
1073      s >> m33;
1074      t.setMatrix(m11, m12, m13,
1075                  m21, m22, m23,
1076                  m31, m32, m33);
1077      return s;
1078 }
1079
1080 #endif // QT_NO_DATASTREAM
1081
1082 #ifndef QT_NO_DEBUG_STREAM
1083 QDebug operator<<(QDebug dbg, const QTransform &m)
1084 {
1085     static const char *typeStr[] =
1086     {
1087         "TxNone",
1088         "TxTranslate",
1089         "TxScale",
1090         0,
1091         "TxRotate",
1092         0, 0, 0,
1093         "TxShear",
1094         0, 0, 0, 0, 0, 0, 0,
1095         "TxProject"
1096     };
1097
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()
1108                   << ')';
1109
1110     return dbg.space();
1111 }
1112 #endif
1113
1114 /*!
1115     \fn QPoint operator*(const QPoint &point, const QTransform &matrix)
1116     \relates QTransform
1117
1118     This is the same as \a{matrix}.map(\a{point}).
1119
1120     \sa QTransform::map()
1121 */
1122 QPoint QTransform::map(const QPoint &p) const
1123 {
1124     qreal fx = p.x();
1125     qreal fy = p.y();
1126
1127     qreal x = 0, y = 0;
1128
1129     TransformationType t = inline_type();
1130     switch(t) {
1131     case TxNone:
1132         x = fx;
1133         y = fy;
1134         break;
1135     case TxTranslate:
1136         x = fx + affine._dx;
1137         y = fy + affine._dy;
1138         break;
1139     case TxScale:
1140         x = affine._m11 * fx + affine._dx;
1141         y = affine._m22 * fy + affine._dy;
1142         break;
1143     case TxRotate:
1144     case TxShear:
1145     case TxProject:
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);
1150             x *= w;
1151             y *= w;
1152         }
1153     }
1154     return QPoint(qRound(x), qRound(y));
1155 }
1156
1157
1158 /*!
1159     \fn QPointF operator*(const QPointF &point, const QTransform &matrix)
1160     \relates QTransform
1161
1162     Same as \a{matrix}.map(\a{point}).
1163
1164     \sa QTransform::map()
1165 */
1166
1167 /*!
1168     \overload
1169
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.
1172 */
1173 QPointF QTransform::map(const QPointF &p) const
1174 {
1175     qreal fx = p.x();
1176     qreal fy = p.y();
1177
1178     qreal x = 0, y = 0;
1179
1180     TransformationType t = inline_type();
1181     switch(t) {
1182     case TxNone:
1183         x = fx;
1184         y = fy;
1185         break;
1186     case TxTranslate:
1187         x = fx + affine._dx;
1188         y = fy + affine._dy;
1189         break;
1190     case TxScale:
1191         x = affine._m11 * fx + affine._dx;
1192         y = affine._m22 * fy + affine._dy;
1193         break;
1194     case TxRotate:
1195     case TxShear:
1196     case TxProject:
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);
1201             x *= w;
1202             y *= w;
1203         }
1204     }
1205     return QPointF(x, y);
1206 }
1207
1208 /*!
1209     \fn QPoint QTransform::map(const QPoint &point) const
1210     \overload
1211
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
1215     nearest integer.
1216 */
1217
1218 /*!
1219     \fn QLineF operator*(const QLineF &line, const QTransform &matrix)
1220     \relates QTransform
1221
1222     This is the same as \a{matrix}.map(\a{line}).
1223
1224     \sa QTransform::map()
1225 */
1226
1227 /*!
1228     \fn QLine operator*(const QLine &line, const QTransform &matrix)
1229     \relates QTransform
1230
1231     This is the same as \a{matrix}.map(\a{line}).
1232
1233     \sa QTransform::map()
1234 */
1235
1236 /*!
1237     \overload
1238
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.
1241 */
1242 QLine QTransform::map(const QLine &l) const
1243 {
1244     qreal fx1 = l.x1();
1245     qreal fy1 = l.y1();
1246     qreal fx2 = l.x2();
1247     qreal fy2 = l.y2();
1248
1249     qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1250
1251     TransformationType t = inline_type();
1252     switch(t) {
1253     case TxNone:
1254         x1 = fx1;
1255         y1 = fy1;
1256         x2 = fx2;
1257         y2 = fy2;
1258         break;
1259     case TxTranslate:
1260         x1 = fx1 + affine._dx;
1261         y1 = fy1 + affine._dy;
1262         x2 = fx2 + affine._dx;
1263         y2 = fy2 + affine._dy;
1264         break;
1265     case TxScale:
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;
1270         break;
1271     case TxRotate:
1272     case TxShear:
1273     case TxProject:
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);
1280             x1 *= w;
1281             y1 *= w;
1282             w = 1./(m_13 * fx2 + m_23 * fy2 + m_33);
1283             x2 *= w;
1284             y2 *= w;
1285         }
1286     }
1287     return QLine(qRound(x1), qRound(y1), qRound(x2), qRound(y2));
1288 }
1289
1290 /*!
1291     \overload
1292
1293     \fn QLineF QTransform::map(const QLineF &line) const
1294
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
1298     integer.
1299 */
1300
1301 QLineF QTransform::map(const QLineF &l) const
1302 {
1303     qreal fx1 = l.x1();
1304     qreal fy1 = l.y1();
1305     qreal fx2 = l.x2();
1306     qreal fy2 = l.y2();
1307
1308     qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1309
1310     TransformationType t = inline_type();
1311     switch(t) {
1312     case TxNone:
1313         x1 = fx1;
1314         y1 = fy1;
1315         x2 = fx2;
1316         y2 = fy2;
1317         break;
1318     case TxTranslate:
1319         x1 = fx1 + affine._dx;
1320         y1 = fy1 + affine._dy;
1321         x2 = fx2 + affine._dx;
1322         y2 = fy2 + affine._dy;
1323         break;
1324     case TxScale:
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;
1329         break;
1330     case TxRotate:
1331     case TxShear:
1332     case TxProject:
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);
1339             x1 *= w;
1340             y1 *= w;
1341             w = 1./(m_13 * fx2 + m_23 * fy2 + m_33);
1342             x2 *= w;
1343             y2 *= w;
1344         }
1345     }
1346     return QLineF(x1, y1, x2, y2);
1347 }
1348
1349 static QPolygonF mapProjective(const QTransform &transform, const QPolygonF &poly)
1350 {
1351     if (poly.size() == 0)
1352         return poly;
1353
1354     if (poly.size() == 1)
1355         return QPolygonF() << transform.map(poly.at(0));
1356
1357     QPainterPath path;
1358     path.addPolygon(poly);
1359
1360     path = transform.map(path);
1361
1362     QPolygonF result;
1363     for (int i = 0; i < path.elementCount(); ++i)
1364         result << path.elementAt(i);
1365     return result;
1366 }
1367
1368
1369 /*!
1370     \fn QPolygonF operator *(const QPolygonF &polygon, const QTransform &matrix)
1371     \since 4.3
1372     \relates QTransform
1373
1374     This is the same as \a{matrix}.map(\a{polygon}).
1375
1376     \sa QTransform::map()
1377 */
1378
1379 /*!
1380     \fn QPolygon operator*(const QPolygon &polygon, const QTransform &matrix)
1381     \relates QTransform
1382
1383     This is the same as \a{matrix}.map(\a{polygon}).
1384
1385     \sa QTransform::map()
1386 */
1387
1388 /*!
1389     \fn QPolygonF QTransform::map(const QPolygonF &polygon) const
1390     \overload
1391
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
1394     matrix.
1395 */
1396 QPolygonF QTransform::map(const QPolygonF &a) const
1397 {
1398     TransformationType t = inline_type();
1399     if (t <= TxTranslate)
1400         return a.translated(affine._dx, affine._dy);
1401
1402     if (t >= QTransform::TxProject)
1403         return mapProjective(*this, a);
1404
1405     int size = a.size();
1406     int i;
1407     QPolygonF p(size);
1408     const QPointF *da = a.constData();
1409     QPointF *dp = p.data();
1410
1411     for(i = 0; i < size; ++i) {
1412         MAP(da[i].xp, da[i].yp, dp[i].xp, dp[i].yp);
1413     }
1414     return p;
1415 }
1416
1417 /*!
1418     \fn QPolygon QTransform::map(const QPolygon &polygon) const
1419     \overload
1420
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
1424     nearest integer.
1425 */
1426 QPolygon QTransform::map(const QPolygon &a) const
1427 {
1428     TransformationType t = inline_type();
1429     if (t <= TxTranslate)
1430         return a.translated(qRound(affine._dx), qRound(affine._dy));
1431
1432     if (t >= QTransform::TxProject)
1433         return mapProjective(*this, QPolygonF(a)).toPolygon();
1434
1435     int size = a.size();
1436     int i;
1437     QPolygon p(size);
1438     const QPoint *da = a.constData();
1439     QPoint *dp = p.data();
1440
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);
1446     }
1447     return p;
1448 }
1449
1450 /*!
1451     \fn QRegion operator*(const QRegion &region, const QTransform &matrix)
1452     \relates QTransform
1453
1454     This is the same as \a{matrix}.map(\a{region}).
1455
1456     \sa QTransform::map()
1457 */
1458
1459 extern QPainterPath qt_regionToPath(const QRegion &region);
1460
1461 /*!
1462     \fn QRegion QTransform::map(const QRegion &region) const
1463     \overload
1464
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.
1467
1468     Calling this method can be rather expensive if rotations or
1469     shearing are used.
1470 */
1471 QRegion QTransform::map(const QRegion &r) const
1472 {
1473     TransformationType t = inline_type();
1474     if (t == TxNone)
1475         return r;
1476
1477     if (t == TxTranslate) {
1478         QRegion copy(r);
1479         copy.translate(qRound(affine._dx), qRound(affine._dy));
1480         return copy;
1481     }
1482
1483     if (t == TxScale && r.rectCount() == 1)
1484         return QRegion(mapRect(r.boundingRect()));
1485
1486     QPainterPath p = map(qt_regionToPath(r));
1487     return p.toFillPolygon(QTransform()).toPolygon();
1488 }
1489
1490 struct QHomogeneousCoordinate
1491 {
1492     qreal x;
1493     qreal y;
1494     qreal w;
1495
1496     QHomogeneousCoordinate() {}
1497     QHomogeneousCoordinate(qreal x_, qreal y_, qreal w_) : x(x_), y(y_), w(w_) {}
1498
1499     const QPointF toPoint() const {
1500         qreal iw = 1. / w;
1501         return QPointF(x * iw, y * iw);
1502     }
1503 };
1504
1505 static inline QHomogeneousCoordinate mapHomogeneous(const QTransform &transform, const QPointF &p)
1506 {
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();
1511     return c;
1512 }
1513
1514 static inline bool lineTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b,
1515                                   bool needsMoveTo, bool needsLineTo = true)
1516 {
1517     QHomogeneousCoordinate ha = mapHomogeneous(transform, a);
1518     QHomogeneousCoordinate hb = mapHomogeneous(transform, b);
1519
1520     if (ha.w < Q_NEAR_CLIP && hb.w < Q_NEAR_CLIP)
1521         return false;
1522
1523     if (hb.w < Q_NEAR_CLIP) {
1524         const qreal t = (Q_NEAR_CLIP - hb.w) / (ha.w - hb.w);
1525
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);
1531
1532         ha.x += (hb.x - ha.x) * t;
1533         ha.y += (hb.y - ha.y) * t;
1534         ha.w = qreal(Q_NEAR_CLIP);
1535
1536         const QPointF p = ha.toPoint();
1537         if (needsMoveTo) {
1538             path.moveTo(p);
1539             needsMoveTo = false;
1540         } else {
1541             path.lineTo(p);
1542         }
1543     }
1544
1545     if (needsMoveTo)
1546         path.moveTo(ha.toPoint());
1547
1548     if (needsLineTo)
1549         path.lineTo(hb.toPoint());
1550
1551     return true;
1552 }
1553 Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
1554
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)
1556 {
1557     // Convert projective xformed curves to line
1558     // segments so they can be transformed more accurately
1559
1560     qreal scale;
1561     qt_scaleForTransform(transform, &scale);
1562
1563     qreal curveThreshold = scale == 0 ? qreal(0.25) : (qreal(0.25) / scale);
1564
1565     QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(curveThreshold);
1566
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;
1570
1571     return !needsMoveTo;
1572 }
1573
1574 static QPainterPath mapProjective(const QTransform &transform, const QPainterPath &path)
1575 {
1576     QPainterPath result;
1577
1578     QPointF last;
1579     QPointF lastMoveTo;
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);
1586
1587             lastMoveTo = path.elementAt(i);
1588             last = path.elementAt(i);
1589             needsMoveTo = true;
1590             break;
1591         case QPainterPath::LineToElement:
1592             if (lineTo_clipped(result, transform, last, path.elementAt(i), needsMoveTo))
1593                 needsMoveTo = false;
1594             last = path.elementAt(i);
1595             break;
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;
1599             i += 2;
1600             last = path.elementAt(i);
1601             break;
1602         default:
1603             Q_ASSERT(false);
1604         }
1605     }
1606
1607     if (path.elementCount() > 0 && lastMoveTo != last)
1608         lineTo_clipped(result, transform, last, lastMoveTo, needsMoveTo, false);
1609
1610     result.setFillRule(path.fillRule());
1611     return result;
1612 }
1613
1614 /*!
1615     \fn QPainterPath operator *(const QPainterPath &path, const QTransform &matrix)
1616     \since 4.3
1617     \relates QTransform
1618
1619     This is the same as \a{matrix}.map(\a{path}).
1620
1621     \sa QTransform::map()
1622 */
1623
1624 /*!
1625     \overload
1626
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
1629     matrix.
1630 */
1631 QPainterPath QTransform::map(const QPainterPath &path) const
1632 {
1633     TransformationType t = inline_type();
1634     if (t == TxNone || path.elementCount() == 0)
1635         return path;
1636
1637     if (t >= TxProject)
1638         return mapProjective(*this, path);
1639
1640     QPainterPath copy = path;
1641
1642     if (t == TxTranslate) {
1643         copy.translate(affine._dx, affine._dy);
1644     } else {
1645         copy.detach();
1646         // Full xform
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);
1650         }
1651     }
1652
1653     return copy;
1654 }
1655
1656 /*!
1657     \fn QPolygon QTransform::mapToPolygon(const QRect &rectangle) const
1658
1659     Creates and returns a QPolygon representation of the given \a
1660     rectangle, mapped into the coordinate system defined by this
1661     matrix.
1662
1663     The rectangle's coordinates are transformed using the following
1664     formulas:
1665
1666     \snippet code/src_gui_painting_qtransform.cpp 1
1667
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)}.
1672
1673     \sa mapRect(), {QTransform#Basic Matrix Operations}{Basic Matrix
1674     Operations}
1675 */
1676 QPolygon QTransform::mapToPolygon(const QRect &rect) const
1677 {
1678     TransformationType t = inline_type();
1679
1680     QPolygon a(4);
1681     qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 };
1682     if (t <= TxScale) {
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();
1687         if (w < 0) {
1688             w = -w;
1689             x[0] -= w;
1690         }
1691         if (h < 0) {
1692             h = -h;
1693             y[0] -= h;
1694         }
1695         x[1] = x[0]+w;
1696         x[2] = x[1];
1697         x[3] = x[0];
1698         y[1] = y[0];
1699         y[2] = y[0]+h;
1700         y[3] = y[2];
1701     } else {
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]);
1708     }
1709
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]));
1716     return a;
1717 }
1718
1719 /*!
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.
1723
1724     \sa quadToSquare(), quadToQuad()
1725 */
1726 bool QTransform::squareToQuad(const QPolygonF &quad, QTransform &trans)
1727 {
1728     if (quad.count() != 4)
1729         return false;
1730
1731     qreal dx0 = quad[0].x();
1732     qreal dx1 = quad[1].x();
1733     qreal dx2 = quad[2].x();
1734     qreal dx3 = quad[3].x();
1735
1736     qreal dy0 = quad[0].y();
1737     qreal dy1 = quad[1].y();
1738     qreal dy2 = quad[2].y();
1739     qreal dy3 = quad[3].y();
1740
1741     double ax  = dx0 - dx1 + dx2 - dx3;
1742     double ay  = dy0 - dy1 + dy2 - dy3;
1743
1744     if (!ax && !ay) { //afine transform
1745         trans.setMatrix(dx1 - dx0, dy1 - dy0,  0,
1746                         dx2 - dx1, dy2 - dy1,  0,
1747                         dx0,       dy0,  1);
1748     } else {
1749         double ax1 = dx1 - dx2;
1750         double ax2 = dx3 - dx2;
1751         double ay1 = dy1 - dy2;
1752         double ay2 = dy3 - dy2;
1753
1754         /*determinants */
1755         double gtop    =  ax  * ay2 - ax2 * ay;
1756         double htop    =  ax1 * ay  - ax  * ay1;
1757         double bottom  =  ax1 * ay2 - ax2 * ay1;
1758
1759         double a, b, c, d, e, f, g, h;  /*i is always 1*/
1760
1761         if (!bottom)
1762             return false;
1763
1764         g = gtop/bottom;
1765         h = htop/bottom;
1766
1767         a = dx1 - dx0 + g * dx1;
1768         b = dx3 - dx0 + h * dx3;
1769         c = dx0;
1770         d = dy1 - dy0 + g * dy1;
1771         e = dy3 - dy0 + h * dy3;
1772         f = dy0;
1773
1774         trans.setMatrix(a, d, g,
1775                         b, e, h,
1776                         c, f, 1.0);
1777     }
1778
1779     return true;
1780 }
1781
1782 /*!
1783     \fn bool QTransform::quadToSquare(const QPolygonF &quad, QTransform &trans)
1784
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.
1788
1789     \sa squareToQuad(), quadToQuad()
1790 */
1791 bool QTransform::quadToSquare(const QPolygonF &quad, QTransform &trans)
1792 {
1793     if (!squareToQuad(quad, trans))
1794         return false;
1795
1796     bool invertible = false;
1797     trans = trans.inverted(&invertible);
1798
1799     return invertible;
1800 }
1801
1802 /*!
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
1806     false.
1807
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.
1811
1812     \sa squareToQuad(), quadToSquare()
1813 */
1814 bool QTransform::quadToQuad(const QPolygonF &one,
1815                             const QPolygonF &two,
1816                             QTransform &trans)
1817 {
1818     QTransform stq;
1819     if (!quadToSquare(one, trans))
1820         return false;
1821     if (!squareToQuad(two, stq))
1822         return false;
1823     trans *= stq;
1824     //qDebug()<<"Final = "<<trans;
1825     return true;
1826 }
1827
1828 /*!
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.
1835
1836     \sa QTransform()
1837 */
1838
1839 void QTransform::setMatrix(qreal m11, qreal m12, qreal m13,
1840                            qreal m21, qreal m22, qreal m23,
1841                            qreal m31, qreal m32, qreal m33)
1842 {
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;
1846     m_type = TxNone;
1847     m_dirty = TxProject;
1848 }
1849
1850 static inline bool needsPerspectiveClipping(const QRectF &rect, const QTransform &transform)
1851 {
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());
1854
1855     return wx + wy + transform.m33() < Q_NEAR_CLIP;
1856 }
1857
1858 QRect QTransform::mapRect(const QRect &rect) const
1859 {
1860     TransformationType t = inline_type();
1861     if (t <= TxTranslate)
1862         return rect.translated(qRound(affine._dx), qRound(affine._dy));
1863
1864     if (t <= TxScale) {
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());
1869         if (w < 0) {
1870             w = -w;
1871             x -= w;
1872         }
1873         if (h < 0) {
1874             h = -h;
1875             y -= h;
1876         }
1877         return QRect(x, y, w, h);
1878     } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
1879         // see mapToPolygon for explanations of the algorithm.
1880         qreal x = 0, y = 0;
1881         MAP(rect.left(), rect.top(), x, y);
1882         qreal xmin = x;
1883         qreal ymin = y;
1884         qreal xmax = x;
1885         qreal ymax = 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));
1902     } else {
1903         QPainterPath path;
1904         path.addRect(rect);
1905         return map(path).boundingRect().toRect();
1906     }
1907 }
1908
1909 /*!
1910     \fn QRectF QTransform::mapRect(const QRectF &rectangle) const
1911
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
1914     matrix.
1915
1916     The rectangle's coordinates are transformed using the following
1917     formulas:
1918
1919     \snippet code/src_gui_painting_qtransform.cpp 2
1920
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.
1924
1925     \sa mapToPolygon(), {QTransform#Basic Matrix Operations}{Basic Matrix
1926     Operations}
1927 */
1928 QRectF QTransform::mapRect(const QRectF &rect) const
1929 {
1930     TransformationType t = inline_type();
1931     if (t <= TxTranslate)
1932         return rect.translated(affine._dx, affine._dy);
1933
1934     if (t <= TxScale) {
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();
1939         if (w < 0) {
1940             w = -w;
1941             x -= w;
1942         }
1943         if (h < 0) {
1944             h = -h;
1945             y -= h;
1946         }
1947         return QRectF(x, y, w, h);
1948     } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
1949         qreal x = 0, y = 0;
1950         MAP(rect.x(), rect.y(), x, y);
1951         qreal xmin = x;
1952         qreal ymin = y;
1953         qreal xmax = x;
1954         qreal ymax = 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);
1971     } else {
1972         QPainterPath path;
1973         path.addRect(rect);
1974         return map(path).boundingRect();
1975     }
1976 }
1977
1978 /*!
1979     \fn QRect QTransform::mapRect(const QRect &rectangle) const
1980     \overload
1981
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
1985     nearest integer.
1986 */
1987
1988 /*!
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.
1992
1993     The coordinates are transformed using the following formulas:
1994
1995     \snippet code/src_gui_painting_qtransform.cpp 3
1996
1997     The point (x, y) is the original point, and (x', y') is the
1998     transformed point.
1999
2000     \sa {QTransform#Basic Matrix Operations}{Basic Matrix Operations}
2001 */
2002 void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty) const
2003 {
2004     TransformationType t = inline_type();
2005     MAP(x, y, *tx, *ty);
2006 }
2007
2008 /*!
2009     \overload
2010
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.
2015 */
2016 void QTransform::map(int x, int y, int *tx, int *ty) const
2017 {
2018     TransformationType t = inline_type();
2019     qreal fx = 0, fy = 0;
2020     MAP(x, y, fx, fy);
2021     *tx = qRound(fx);
2022     *ty = qRound(fy);
2023 }
2024
2025 /*!
2026   Returns the QTransform as an affine matrix.
2027
2028   \warning If a perspective transformation has been specified,
2029   then the conversion will cause loss of data.
2030 */
2031 const QMatrix &QTransform::toAffine() const
2032 {
2033     return affine;
2034 }
2035
2036 /*!
2037   Returns the transformation type of this matrix.
2038
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.
2043
2044   Knowing the transformation type of a matrix is useful for optimization:
2045   you can often handle specific types more optimally than handling
2046   the generic case.
2047   */
2048 QTransform::TransformationType QTransform::type() const
2049 {
2050     if(m_dirty == TxNone || m_dirty < m_type)
2051         return static_cast<TransformationType>(m_type);
2052
2053     switch (static_cast<TransformationType>(m_dirty)) {
2054     case TxProject:
2055         if (!qFuzzyIsNull(m_13) || !qFuzzyIsNull(m_23) || !qFuzzyIsNull(m_33 - 1)) {
2056              m_type = TxProject;
2057              break;
2058          }
2059     case TxShear:
2060     case TxRotate:
2061         if (!qFuzzyIsNull(affine._m12) || !qFuzzyIsNull(affine._m21)) {
2062             const qreal dot = affine._m11 * affine._m12 + affine._m21 * affine._m22;
2063             if (qFuzzyIsNull(dot))
2064                 m_type = TxRotate;
2065             else
2066                 m_type = TxShear;
2067             break;
2068         }
2069     case TxScale:
2070         if (!qFuzzyIsNull(affine._m11 - 1) || !qFuzzyIsNull(affine._m22 - 1)) {
2071             m_type = TxScale;
2072             break;
2073         }
2074     case TxTranslate:
2075         if (!qFuzzyIsNull(affine._dx) || !qFuzzyIsNull(affine._dy)) {
2076             m_type = TxTranslate;
2077             break;
2078         }
2079     case TxNone:
2080         m_type = TxNone;
2081         break;
2082     }
2083
2084     m_dirty = TxNone;
2085     return static_cast<TransformationType>(m_type);
2086 }
2087
2088 /*!
2089
2090     Returns the transform as a QVariant.
2091 */
2092 QTransform::operator QVariant() const
2093 {
2094     return QVariant(QVariant::Transform, this);
2095 }
2096
2097
2098 /*!
2099     \fn bool QTransform::isInvertible() const
2100
2101     Returns true if the matrix is invertible, otherwise returns false.
2102
2103     \sa inverted()
2104 */
2105
2106 /*!
2107     \fn qreal QTransform::det() const
2108     \obsolete
2109
2110     Returns the matrix's determinant. Use determinant() instead.
2111 */
2112
2113
2114 /*!
2115     \fn qreal QTransform::m11() const
2116
2117     Returns the horizontal scaling factor.
2118
2119     \sa scale(), {QTransform#Basic Matrix Operations}{Basic Matrix
2120     Operations}
2121 */
2122
2123 /*!
2124     \fn qreal QTransform::m12() const
2125
2126     Returns the vertical shearing factor.
2127
2128     \sa shear(), {QTransform#Basic Matrix Operations}{Basic Matrix
2129     Operations}
2130 */
2131
2132 /*!
2133     \fn qreal QTransform::m21() const
2134
2135     Returns the horizontal shearing factor.
2136
2137     \sa shear(), {QTransform#Basic Matrix Operations}{Basic Matrix
2138     Operations}
2139 */
2140
2141 /*!
2142     \fn qreal QTransform::m22() const
2143
2144     Returns the vertical scaling factor.
2145
2146     \sa scale(), {QTransform#Basic Matrix Operations}{Basic Matrix
2147     Operations}
2148 */
2149
2150 /*!
2151     \fn qreal QTransform::dx() const
2152
2153     Returns the horizontal translation factor.
2154
2155     \sa m31(), translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2156     Operations}
2157 */
2158
2159 /*!
2160     \fn qreal QTransform::dy() const
2161
2162     Returns the vertical translation factor.
2163
2164     \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2165     Operations}
2166 */
2167
2168
2169 /*!
2170     \fn qreal QTransform::m13() const
2171
2172     Returns the horizontal projection factor.
2173
2174     \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2175     Operations}
2176 */
2177
2178
2179 /*!
2180     \fn qreal QTransform::m23() const
2181
2182     Returns the vertical projection factor.
2183
2184     \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2185     Operations}
2186 */
2187
2188 /*!
2189     \fn qreal QTransform::m31() const
2190
2191     Returns the horizontal translation factor.
2192
2193     \sa dx(), translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2194     Operations}
2195 */
2196
2197 /*!
2198     \fn qreal QTransform::m32() const
2199
2200     Returns the vertical translation factor.
2201
2202     \sa dy(), translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2203     Operations}
2204 */
2205
2206 /*!
2207     \fn qreal QTransform::m33() const
2208
2209     Returns the division factor.
2210
2211     \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2212     Operations}
2213 */
2214
2215 /*!
2216     \fn qreal QTransform::determinant() const
2217
2218     Returns the matrix's determinant.
2219 */
2220
2221 /*!
2222     \fn bool QTransform::isIdentity() const
2223
2224     Returns true if the matrix is the identity matrix, otherwise
2225     returns false.
2226
2227     \sa reset()
2228 */
2229
2230 /*!
2231     \fn bool QTransform::isAffine() const
2232
2233     Returns true if the matrix represent an affine transformation,
2234     otherwise returns false.
2235 */
2236
2237 /*!
2238     \fn bool QTransform::isScaling() const
2239
2240     Returns true if the matrix represents a scaling
2241     transformation, otherwise returns false.
2242
2243     \sa reset()
2244 */
2245
2246 /*!
2247     \fn bool QTransform::isRotating() const
2248
2249     Returns true if the matrix represents some kind of a
2250     rotating transformation, otherwise returns false.
2251
2252     \note A rotation transformation of 180 degrees and/or 360 degrees is treated as a scaling transformation.
2253
2254     \sa reset()
2255 */
2256
2257 /*!
2258     \fn bool QTransform::isTranslating() const
2259
2260     Returns true if the matrix represents a translating
2261     transformation, otherwise returns false.
2262
2263     \sa reset()
2264 */
2265
2266 /*!
2267     \fn bool qFuzzyCompare(const QTransform& t1, const QTransform& t2)
2268
2269     \relates QTransform
2270     \since 4.6
2271
2272     Returns true if \a t1 and \a t2 are equal, allowing for a small
2273     fuzziness factor for floating-point comparisons; false otherwise.
2274 */
2275
2276
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
2280 Q_GUI_EXPORT
2281 bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
2282 {
2283     const QTransform::TransformationType type = transform.type();
2284     if (type <= QTransform::TxTranslate) {
2285         if (scale)
2286             *scale = 1;
2287         return true;
2288     } else if (type == QTransform::TxScale) {
2289         const qreal xScale = qAbs(transform.m11());
2290         const qreal yScale = qAbs(transform.m22());
2291         if (scale)
2292             *scale = qMax(xScale, yScale);
2293         return qFuzzyCompare(xScale, yScale);
2294     }
2295
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();
2300     if (scale)
2301         *scale = qSqrt(qMax(xScale, yScale));
2302     return type == QTransform::TxRotate && qFuzzyCompare(xScale, yScale);
2303 }
2304
2305 QT_END_NAMESPACE