Make QRegion not need to be friends with QVector
[profile/ivi/qtbase.git] / src / gui / painting / qtransform.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
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
100     A transformation specifies how to translate, scale, shear, rotate
101     or project the coordinate system, and is typically used when
102     rendering graphics.
103
104     QTransform differs from QMatrix in that it is a true 3x3 matrix,
105     allowing perspective transformations. QTransform's toAffine()
106     method allows casting QTransform to QMatrix. If a perspective
107     transformation has been specified on the matrix, then the
108     conversion will cause loss of data.
109
110     QTransform is the recommended transformation class in Qt.
111
112     A QTransform object can be built using the setMatrix(), scale(),
113     rotate(), translate() and shear() functions.  Alternatively, it
114     can be built by applying \l {QTransform#Basic Matrix
115     Operations}{basic matrix operations}. The matrix can also be
116     defined when constructed, and it can be reset to the identity
117     matrix (the default) using the reset() function.
118
119     The QTransform class supports mapping of graphic primitives: A given
120     point, line, polygon, region, or painter path can be mapped to the
121     coordinate system defined by \e this matrix using the map()
122     function. In case of a rectangle, its coordinates can be
123     transformed using the mapRect() function. A rectangle can also be
124     transformed into a \e polygon (mapped to the coordinate system
125     defined by \e this matrix), using the mapToPolygon() function.
126
127     QTransform provides the isIdentity() function which returns true if
128     the matrix is the identity matrix, and the isInvertible() function
129     which returns true if the matrix is non-singular (i.e. AB = BA =
130     I). The inverted() function returns an inverted copy of \e this
131     matrix if it is invertible (otherwise it returns the identity
132     matrix), and adjoint() returns the matrix's classical adjoint.
133     In addition, QTransform provides the determinant() function which
134     returns the matrix's determinant.
135
136     Finally, the QTransform class supports matrix multiplication, addition
137     and subtraction, and objects of the class can be streamed as well
138     as compared.
139
140     \tableofcontents
141
142     \section1 Rendering Graphics
143
144     When rendering graphics, the matrix defines the transformations
145     but the actual transformation is performed by the drawing routines
146     in QPainter.
147
148     By default, QPainter operates on the associated device's own
149     coordinate system.  The standard coordinate system of a
150     QPaintDevice has its origin located at the top-left position. The
151     \e x values increase to the right; \e y values increase
152     downward. For a complete description, see the \l {Coordinate
153     System} {coordinate system} documentation.
154
155     QPainter has functions to translate, scale, shear and rotate the
156     coordinate system without using a QTransform. For example:
157
158     \table 100%
159     \row
160     \li \inlineimage qtransform-simpletransformation.png
161     \li
162     \snippet transform/main.cpp 0
163     \endtable
164
165     Although these functions are very convenient, it can be more
166     efficient to build a QTransform and call QPainter::setTransform() if you
167     want to perform more than a single transform operation. For
168     example:
169
170     \table 100%
171     \row
172     \li \inlineimage qtransform-combinedtransformation.png
173     \li
174     \snippet transform/main.cpp 1
175     \endtable
176
177     \section1 Basic Matrix Operations
178
179     \image qtransform-representation.png
180
181     A QTransform object contains a 3 x 3 matrix.  The \c m31 (\c dx) and
182     \c m32 (\c dy) elements specify horizontal and vertical translation.
183     The \c m11 and \c m22 elements specify horizontal and vertical scaling.
184     The \c m21 and \c m12 elements specify horizontal and vertical \e shearing.
185     And finally, the \c m13 and \c m23 elements specify horizontal and vertical
186     projection, with \c m33 as an additional projection factor.
187
188     QTransform transforms a point in the plane to another point using the
189     following formulas:
190
191     \snippet code/src_gui_painting_qtransform.cpp 0
192
193     The point \e (x, y) is the original point, and \e (x', y') is the
194     transformed point. \e (x', y') can be transformed back to \e (x,
195     y) by performing the same operation on the inverted() matrix.
196
197     The various matrix elements can be set when constructing the
198     matrix, or by using the setMatrix() function later on. They can also
199     be manipulated using the translate(), rotate(), scale() and
200     shear() convenience functions. The currently set values can be
201     retrieved using the m11(), m12(), m13(), m21(), m22(), m23(),
202     m31(), m32(), m33(), dx() and dy() functions.
203
204     Translation is the simplest transformation. Setting \c dx and \c
205     dy will move the coordinate system \c dx units along the X axis
206     and \c dy units along the Y axis.  Scaling can be done by setting
207     \c m11 and \c m22. For example, setting \c m11 to 2 and \c m22 to
208     1.5 will double the height and increase the width by 50%.  The
209     identity matrix has \c m11, \c m22, and \c m33 set to 1 (all others are set
210     to 0) mapping a point to itself. Shearing is controlled by \c m12
211     and \c m21. Setting these elements to values different from zero
212     will twist the coordinate system. Rotation is achieved by
213     setting both the shearing factors and the scaling factors. Perspective
214     transformation is achieved by setting both the projection factors and
215     the scaling factors.
216
217     Here's the combined transformations example using basic matrix
218     operations:
219
220     \table 100%
221     \row
222     \li \inlineimage qtransform-combinedtransformation2.png
223     \li
224     \snippet transform/main.cpp 2
225     \endtable
226
227     \sa QPainter, {Coordinate System}, {painting/affine}{Affine
228     Transformations Example}, {Transformations Example}
229 */
230
231 /*!
232     \enum QTransform::TransformationType
233
234     \value TxNone
235     \value TxTranslate
236     \value TxScale
237     \value TxRotate
238     \value TxShear
239     \value TxProject
240 */
241
242 /*!
243     \fn QTransform::QTransform(Qt::Initialization)
244     \internal
245 */
246
247 /*!
248     Constructs an identity matrix.
249
250     All elements are set to zero except \c m11 and \c m22 (specifying
251     the scale) and \c m13 which are set to 1.
252
253     \sa reset()
254 */
255 QTransform::QTransform()
256     : affine(true)
257     , m_13(0), m_23(0), m_33(1)
258     , m_type(TxNone)
259     , m_dirty(TxNone)
260 {
261 }
262
263 /*!
264     \fn QTransform::QTransform(qreal m11, qreal m12, qreal m13, qreal m21, qreal m22, qreal m23, qreal m31, qreal m32, qreal m33)
265
266     Constructs a matrix with the elements, \a m11, \a m12, \a m13,
267     \a m21, \a m22, \a m23, \a m31, \a m32, \a m33.
268
269     \sa setMatrix()
270 */
271 QTransform::QTransform(qreal h11, qreal h12, qreal h13,
272                        qreal h21, qreal h22, qreal h23,
273                        qreal h31, qreal h32, qreal h33)
274     : affine(h11, h12, h21, h22, h31, h32, true)
275     , m_13(h13), m_23(h23), m_33(h33)
276     , m_type(TxNone)
277     , m_dirty(TxProject)
278 {
279 }
280
281 /*!
282     \fn QTransform::QTransform(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy)
283
284     Constructs a matrix with the elements, \a m11, \a m12, \a m21, \a m22, \a dx and \a dy.
285
286     \sa setMatrix()
287 */
288 QTransform::QTransform(qreal h11, qreal h12, qreal h21,
289                        qreal h22, qreal dx, qreal dy)
290     : affine(h11, h12, h21, h22, dx, dy, true)
291     , m_13(0), m_23(0), m_33(1)
292     , m_type(TxNone)
293     , m_dirty(TxShear)
294 {
295 }
296
297 /*!
298     \fn QTransform::QTransform(const QMatrix &matrix)
299
300     Constructs a matrix that is a copy of the given \a matrix.
301     Note that the \c m13, \c m23, and \c m33 elements are set to 0, 0,
302     and 1 respectively.
303  */
304 QTransform::QTransform(const QMatrix &mtx)
305     : affine(mtx._m11, mtx._m12, mtx._m21, mtx._m22, mtx._dx, mtx._dy, true),
306       m_13(0), m_23(0), m_33(1)
307     , m_type(TxNone)
308     , m_dirty(TxShear)
309 {
310 }
311
312 /*!
313     Returns the adjoint of this matrix.
314 */
315 QTransform QTransform::adjoint() const
316 {
317     qreal h11, h12, h13,
318         h21, h22, h23,
319         h31, h32, h33;
320     h11 = affine._m22*m_33 - m_23*affine._dy;
321     h21 = m_23*affine._dx - affine._m21*m_33;
322     h31 = affine._m21*affine._dy - affine._m22*affine._dx;
323     h12 = m_13*affine._dy - affine._m12*m_33;
324     h22 = affine._m11*m_33 - m_13*affine._dx;
325     h32 = affine._m12*affine._dx - affine._m11*affine._dy;
326     h13 = affine._m12*m_23 - m_13*affine._m22;
327     h23 = m_13*affine._m21 - affine._m11*m_23;
328     h33 = affine._m11*affine._m22 - affine._m12*affine._m21;
329
330     return QTransform(h11, h12, h13,
331                       h21, h22, h23,
332                       h31, h32, h33, true);
333 }
334
335 /*!
336     Returns the transpose of this matrix.
337 */
338 QTransform QTransform::transposed() const
339 {
340     QTransform t(affine._m11, affine._m21, affine._dx,
341                  affine._m12, affine._m22, affine._dy,
342                  m_13, m_23, m_33, true);
343     t.m_type = m_type;
344     t.m_dirty = m_dirty;
345     return t;
346 }
347
348 /*!
349     Returns an inverted copy of this matrix.
350
351     If the matrix is singular (not invertible), the returned matrix is
352     the identity matrix. If \a invertible is valid (i.e. not 0), its
353     value is set to true if the matrix is invertible, otherwise it is
354     set to false.
355
356     \sa isInvertible()
357 */
358 QTransform QTransform::inverted(bool *invertible) const
359 {
360     QTransform invert(true);
361     bool inv = true;
362
363     switch(inline_type()) {
364     case TxNone:
365         break;
366     case TxTranslate:
367         invert.affine._dx = -affine._dx;
368         invert.affine._dy = -affine._dy;
369         break;
370     case TxScale:
371         inv = !qFuzzyIsNull(affine._m11);
372         inv &= !qFuzzyIsNull(affine._m22);
373         if (inv) {
374             invert.affine._m11 = 1. / affine._m11;
375             invert.affine._m22 = 1. / affine._m22;
376             invert.affine._dx = -affine._dx * invert.affine._m11;
377             invert.affine._dy = -affine._dy * invert.affine._m22;
378         }
379         break;
380     case TxRotate:
381     case TxShear:
382         invert.affine = affine.inverted(&inv);
383         break;
384     default:
385         // general case
386         qreal det = determinant();
387         inv = !qFuzzyIsNull(det);
388         if (inv)
389             invert = adjoint() / det;
390         break;
391     }
392
393     if (invertible)
394         *invertible = inv;
395
396     if (inv) {
397         // inverting doesn't change the type
398         invert.m_type = m_type;
399         invert.m_dirty = m_dirty;
400     }
401
402     return invert;
403 }
404
405 /*!
406     Moves the coordinate system \a dx along the x axis and \a dy along
407     the y axis, and returns a reference to the matrix.
408
409     \sa setMatrix()
410 */
411 QTransform &QTransform::translate(qreal dx, qreal dy)
412 {
413     if (dx == 0 && dy == 0)
414         return *this;
415 #ifndef QT_NO_DEBUG
416     if (qIsNaN(dx) | qIsNaN(dy)) {
417         qWarning() << "QTransform::translate with NaN called";
418         return *this;
419     }
420 #endif
421
422     switch(inline_type()) {
423     case TxNone:
424         affine._dx = dx;
425         affine._dy = dy;
426         break;
427     case TxTranslate:
428         affine._dx += dx;
429         affine._dy += dy;
430         break;
431     case TxScale:
432         affine._dx += dx*affine._m11;
433         affine._dy += dy*affine._m22;
434         break;
435     case TxProject:
436         m_33 += dx*m_13 + dy*m_23;
437         // Fall through
438     case TxShear:
439     case TxRotate:
440         affine._dx += dx*affine._m11 + dy*affine._m21;
441         affine._dy += dy*affine._m22 + dx*affine._m12;
442         break;
443     }
444     if (m_dirty < TxTranslate)
445         m_dirty = TxTranslate;
446     return *this;
447 }
448
449 /*!
450     Creates a matrix which corresponds to a translation of \a dx along
451     the x axis and \a dy along the y axis. This is the same as
452     QTransform().translate(dx, dy) but slightly faster.
453
454     \since 4.5
455 */
456 QTransform QTransform::fromTranslate(qreal dx, qreal dy)
457 {
458 #ifndef QT_NO_DEBUG
459     if (qIsNaN(dx) | qIsNaN(dy)) {
460         qWarning() << "QTransform::fromTranslate with NaN called";
461         return QTransform();
462 }
463 #endif
464     QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1, true);
465     if (dx == 0 && dy == 0)
466         transform.m_type = TxNone;
467     else
468         transform.m_type = TxTranslate;
469     transform.m_dirty = TxNone;
470     return transform;
471 }
472
473 /*!
474     Scales the coordinate system by \a sx horizontally and \a sy
475     vertically, and returns a reference to the matrix.
476
477     \sa setMatrix()
478 */
479 QTransform & QTransform::scale(qreal sx, qreal sy)
480 {
481     if (sx == 1 && sy == 1)
482         return *this;
483 #ifndef QT_NO_DEBUG
484     if (qIsNaN(sx) | qIsNaN(sy)) {
485         qWarning() << "QTransform::scale with NaN called";
486         return *this;
487     }
488 #endif
489
490     switch(inline_type()) {
491     case TxNone:
492     case TxTranslate:
493         affine._m11 = sx;
494         affine._m22 = sy;
495         break;
496     case TxProject:
497         m_13 *= sx;
498         m_23 *= sy;
499         // fall through
500     case TxRotate:
501     case TxShear:
502         affine._m12 *= sx;
503         affine._m21 *= sy;
504         // fall through
505     case TxScale:
506         affine._m11 *= sx;
507         affine._m22 *= sy;
508         break;
509     }
510     if (m_dirty < TxScale)
511         m_dirty = TxScale;
512     return *this;
513 }
514
515 /*!
516     Creates a matrix which corresponds to a scaling of
517     \a sx horizontally and \a sy vertically.
518     This is the same as QTransform().scale(sx, sy) but slightly faster.
519
520     \since 4.5
521 */
522 QTransform QTransform::fromScale(qreal sx, qreal sy)
523 {
524 #ifndef QT_NO_DEBUG
525     if (qIsNaN(sx) | qIsNaN(sy)) {
526         qWarning() << "QTransform::fromScale with NaN called";
527         return QTransform();
528 }
529 #endif
530     QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1, true);
531     if (sx == 1. && sy == 1.)
532         transform.m_type = TxNone;
533     else
534         transform.m_type = TxScale;
535     transform.m_dirty = TxNone;
536     return transform;
537 }
538
539 /*!
540     Shears the coordinate system by \a sh horizontally and \a sv
541     vertically, and returns a reference to the matrix.
542
543     \sa setMatrix()
544 */
545 QTransform & QTransform::shear(qreal sh, qreal sv)
546 {
547     if (sh == 0 && sv == 0)
548         return *this;
549 #ifndef QT_NO_DEBUG
550     if (qIsNaN(sh) | qIsNaN(sv)) {
551         qWarning() << "QTransform::shear with NaN called";
552         return *this;
553     }
554 #endif
555
556     switch(inline_type()) {
557     case TxNone:
558     case TxTranslate:
559         affine._m12 = sv;
560         affine._m21 = sh;
561         break;
562     case TxScale:
563         affine._m12 = sv*affine._m22;
564         affine._m21 = sh*affine._m11;
565         break;
566     case TxProject: {
567         qreal tm13 = sv*m_23;
568         qreal tm23 = sh*m_13;
569         m_13 += tm13;
570         m_23 += tm23;
571     }
572         // fall through
573     case TxRotate:
574     case TxShear: {
575         qreal tm11 = sv*affine._m21;
576         qreal tm22 = sh*affine._m12;
577         qreal tm12 = sv*affine._m22;
578         qreal tm21 = sh*affine._m11;
579         affine._m11 += tm11; affine._m12 += tm12;
580         affine._m21 += tm21; affine._m22 += tm22;
581         break;
582     }
583     }
584     if (m_dirty < TxShear)
585         m_dirty = TxShear;
586     return *this;
587 }
588
589 const qreal deg2rad = qreal(0.017453292519943295769);        // pi/180
590 const qreal inv_dist_to_plane = 1. / 1024.;
591
592 /*!
593     \fn QTransform &QTransform::rotate(qreal angle, Qt::Axis axis)
594
595     Rotates the coordinate system counterclockwise by the given \a angle
596     about the specified \a axis and returns a reference to the matrix.
597
598     Note that if you apply a QTransform to a point defined in widget
599     coordinates, the direction of the rotation will be clockwise
600     because the y-axis points downwards.
601
602     The angle is specified in degrees.
603
604     \sa setMatrix()
605 */
606 QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
607 {
608     if (a == 0)
609         return *this;
610 #ifndef QT_NO_DEBUG
611     if (qIsNaN(a)) {
612         qWarning() << "QTransform::rotate with NaN called";
613         return *this;
614     }
615 #endif
616
617     qreal sina = 0;
618     qreal cosa = 0;
619     if (a == 90. || a == -270.)
620         sina = 1.;
621     else if (a == 270. || a == -90.)
622         sina = -1.;
623     else if (a == 180.)
624         cosa = -1.;
625     else{
626         qreal b = deg2rad*a;          // convert to radians
627         sina = qSin(b);               // fast and convenient
628         cosa = qCos(b);
629     }
630
631     if (axis == Qt::ZAxis) {
632         switch(inline_type()) {
633         case TxNone:
634         case TxTranslate:
635             affine._m11 = cosa;
636             affine._m12 = sina;
637             affine._m21 = -sina;
638             affine._m22 = cosa;
639             break;
640         case TxScale: {
641             qreal tm11 = cosa*affine._m11;
642             qreal tm12 = sina*affine._m22;
643             qreal tm21 = -sina*affine._m11;
644             qreal tm22 = cosa*affine._m22;
645             affine._m11 = tm11; affine._m12 = tm12;
646             affine._m21 = tm21; affine._m22 = tm22;
647             break;
648         }
649         case TxProject: {
650             qreal tm13 = cosa*m_13 + sina*m_23;
651             qreal tm23 = -sina*m_13 + cosa*m_23;
652             m_13 = tm13;
653             m_23 = tm23;
654             // fall through
655         }
656         case TxRotate:
657         case TxShear: {
658             qreal tm11 = cosa*affine._m11 + sina*affine._m21;
659             qreal tm12 = cosa*affine._m12 + sina*affine._m22;
660             qreal tm21 = -sina*affine._m11 + cosa*affine._m21;
661             qreal tm22 = -sina*affine._m12 + cosa*affine._m22;
662             affine._m11 = tm11; affine._m12 = tm12;
663             affine._m21 = tm21; affine._m22 = tm22;
664             break;
665         }
666         }
667         if (m_dirty < TxRotate)
668             m_dirty = TxRotate;
669     } else {
670         QTransform result;
671         if (axis == Qt::YAxis) {
672             result.affine._m11 = cosa;
673             result.m_13 = -sina * inv_dist_to_plane;
674         } else {
675             result.affine._m22 = cosa;
676             result.m_23 = -sina * inv_dist_to_plane;
677         }
678         result.m_type = TxProject;
679         *this = result * *this;
680     }
681
682     return *this;
683 }
684
685 /*!
686     \fn QTransform & QTransform::rotateRadians(qreal angle, Qt::Axis axis)
687
688     Rotates the coordinate system counterclockwise by the given \a angle
689     about the specified \a axis and returns a reference to the matrix.
690
691     Note that if you apply a QTransform to a point defined in widget
692     coordinates, the direction of the rotation will be clockwise
693     because the y-axis points downwards.
694
695     The angle is specified in radians.
696
697     \sa setMatrix()
698 */
699 QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
700 {
701 #ifndef QT_NO_DEBUG
702     if (qIsNaN(a)) {
703         qWarning() << "QTransform::rotateRadians with NaN called";
704         return *this;
705     }
706 #endif
707     qreal sina = qSin(a);
708     qreal cosa = qCos(a);
709
710     if (axis == Qt::ZAxis) {
711         switch(inline_type()) {
712         case TxNone:
713         case TxTranslate:
714             affine._m11 = cosa;
715             affine._m12 = sina;
716             affine._m21 = -sina;
717             affine._m22 = cosa;
718             break;
719         case TxScale: {
720             qreal tm11 = cosa*affine._m11;
721             qreal tm12 = sina*affine._m22;
722             qreal tm21 = -sina*affine._m11;
723             qreal tm22 = cosa*affine._m22;
724             affine._m11 = tm11; affine._m12 = tm12;
725             affine._m21 = tm21; affine._m22 = tm22;
726             break;
727         }
728         case TxProject: {
729             qreal tm13 = cosa*m_13 + sina*m_23;
730             qreal tm23 = -sina*m_13 + cosa*m_23;
731             m_13 = tm13;
732             m_23 = tm23;
733             // fall through
734         }
735         case TxRotate:
736         case TxShear: {
737             qreal tm11 = cosa*affine._m11 + sina*affine._m21;
738             qreal tm12 = cosa*affine._m12 + sina*affine._m22;
739             qreal tm21 = -sina*affine._m11 + cosa*affine._m21;
740             qreal tm22 = -sina*affine._m12 + cosa*affine._m22;
741             affine._m11 = tm11; affine._m12 = tm12;
742             affine._m21 = tm21; affine._m22 = tm22;
743             break;
744         }
745         }
746         if (m_dirty < TxRotate)
747             m_dirty = TxRotate;
748     } else {
749         QTransform result;
750         if (axis == Qt::YAxis) {
751             result.affine._m11 = cosa;
752             result.m_13 = -sina * inv_dist_to_plane;
753         } else {
754             result.affine._m22 = cosa;
755             result.m_23 = -sina * inv_dist_to_plane;
756         }
757         result.m_type = TxProject;
758         *this = result * *this;
759     }
760     return *this;
761 }
762
763 /*!
764     \fn bool QTransform::operator==(const QTransform &matrix) const
765     Returns true if this matrix is equal to the given \a matrix,
766     otherwise returns false.
767 */
768 bool QTransform::operator==(const QTransform &o) const
769 {
770     return affine._m11 == o.affine._m11 &&
771            affine._m12 == o.affine._m12 &&
772            affine._m21 == o.affine._m21 &&
773            affine._m22 == o.affine._m22 &&
774            affine._dx == o.affine._dx &&
775            affine._dy == o.affine._dy &&
776            m_13 == o.m_13 &&
777            m_23 == o.m_23 &&
778            m_33 == o.m_33;
779 }
780
781 /*!
782     \fn bool QTransform::operator!=(const QTransform &matrix) const
783     Returns true if this matrix is not equal to the given \a matrix,
784     otherwise returns false.
785 */
786 bool QTransform::operator!=(const QTransform &o) const
787 {
788     return !operator==(o);
789 }
790
791 /*!
792     \fn QTransform & QTransform::operator*=(const QTransform &matrix)
793     \overload
794
795     Returns the result of multiplying this matrix by the given \a
796     matrix.
797 */
798 QTransform & QTransform::operator*=(const QTransform &o)
799 {
800     const TransformationType otherType = o.inline_type();
801     if (otherType == TxNone)
802         return *this;
803
804     const TransformationType thisType = inline_type();
805     if (thisType == TxNone)
806         return operator=(o);
807
808     TransformationType t = qMax(thisType, otherType);
809     switch(t) {
810     case TxNone:
811         break;
812     case TxTranslate:
813         affine._dx += o.affine._dx;
814         affine._dy += o.affine._dy;
815         break;
816     case TxScale:
817     {
818         qreal m11 = affine._m11*o.affine._m11;
819         qreal m22 = affine._m22*o.affine._m22;
820
821         qreal m31 = affine._dx*o.affine._m11 + o.affine._dx;
822         qreal m32 = affine._dy*o.affine._m22 + o.affine._dy;
823
824         affine._m11 = m11;
825         affine._m22 = m22;
826         affine._dx = m31; affine._dy = m32;
827         break;
828     }
829     case TxRotate:
830     case TxShear:
831     {
832         qreal m11 = affine._m11*o.affine._m11 + affine._m12*o.affine._m21;
833         qreal m12 = affine._m11*o.affine._m12 + affine._m12*o.affine._m22;
834
835         qreal m21 = affine._m21*o.affine._m11 + affine._m22*o.affine._m21;
836         qreal m22 = affine._m21*o.affine._m12 + affine._m22*o.affine._m22;
837
838         qreal m31 = affine._dx*o.affine._m11 + affine._dy*o.affine._m21 + o.affine._dx;
839         qreal m32 = affine._dx*o.affine._m12 + affine._dy*o.affine._m22 + o.affine._dy;
840
841         affine._m11 = m11; affine._m12 = m12;
842         affine._m21 = m21; affine._m22 = m22;
843         affine._dx = m31; affine._dy = m32;
844         break;
845     }
846     case TxProject:
847     {
848         qreal m11 = affine._m11*o.affine._m11 + affine._m12*o.affine._m21 + m_13*o.affine._dx;
849         qreal m12 = affine._m11*o.affine._m12 + affine._m12*o.affine._m22 + m_13*o.affine._dy;
850         qreal m13 = affine._m11*o.m_13 + affine._m12*o.m_23 + m_13*o.m_33;
851
852         qreal m21 = affine._m21*o.affine._m11 + affine._m22*o.affine._m21 + m_23*o.affine._dx;
853         qreal m22 = affine._m21*o.affine._m12 + affine._m22*o.affine._m22 + m_23*o.affine._dy;
854         qreal m23 = affine._m21*o.m_13 + affine._m22*o.m_23 + m_23*o.m_33;
855
856         qreal m31 = affine._dx*o.affine._m11 + affine._dy*o.affine._m21 + m_33*o.affine._dx;
857         qreal m32 = affine._dx*o.affine._m12 + affine._dy*o.affine._m22 + m_33*o.affine._dy;
858         qreal m33 = affine._dx*o.m_13 + affine._dy*o.m_23 + m_33*o.m_33;
859
860         affine._m11 = m11; affine._m12 = m12; m_13 = m13;
861         affine._m21 = m21; affine._m22 = m22; m_23 = m23;
862         affine._dx = m31; affine._dy = m32; m_33 = m33;
863     }
864     }
865
866     m_dirty = t;
867     m_type = t;
868
869     return *this;
870 }
871
872 /*!
873     \fn QTransform QTransform::operator*(const QTransform &matrix) const
874     Returns the result of multiplying this matrix by the given \a
875     matrix.
876
877     Note that matrix multiplication is not commutative, i.e. a*b !=
878     b*a.
879 */
880 QTransform QTransform::operator*(const QTransform &m) const
881 {
882     const TransformationType otherType = m.inline_type();
883     if (otherType == TxNone)
884         return *this;
885
886     const TransformationType thisType = inline_type();
887     if (thisType == TxNone)
888         return m;
889
890     QTransform t(true);
891     TransformationType type = qMax(thisType, otherType);
892     switch(type) {
893     case TxNone:
894         break;
895     case TxTranslate:
896         t.affine._dx = affine._dx + m.affine._dx;
897         t.affine._dy += affine._dy + m.affine._dy;
898         break;
899     case TxScale:
900     {
901         qreal m11 = affine._m11*m.affine._m11;
902         qreal m22 = affine._m22*m.affine._m22;
903
904         qreal m31 = affine._dx*m.affine._m11 + m.affine._dx;
905         qreal m32 = affine._dy*m.affine._m22 + m.affine._dy;
906
907         t.affine._m11 = m11;
908         t.affine._m22 = m22;
909         t.affine._dx = m31; t.affine._dy = m32;
910         break;
911     }
912     case TxRotate:
913     case TxShear:
914     {
915         qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21;
916         qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22;
917
918         qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21;
919         qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22;
920
921         qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m.affine._dx;
922         qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m.affine._dy;
923
924         t.affine._m11 = m11; t.affine._m12 = m12;
925         t.affine._m21 = m21; t.affine._m22 = m22;
926         t.affine._dx = m31; t.affine._dy = m32;
927         break;
928     }
929     case TxProject:
930     {
931         qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21 + m_13*m.affine._dx;
932         qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22 + m_13*m.affine._dy;
933         qreal m13 = affine._m11*m.m_13 + affine._m12*m.m_23 + m_13*m.m_33;
934
935         qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21 + m_23*m.affine._dx;
936         qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22 + m_23*m.affine._dy;
937         qreal m23 = affine._m21*m.m_13 + affine._m22*m.m_23 + m_23*m.m_33;
938
939         qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m_33*m.affine._dx;
940         qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m_33*m.affine._dy;
941         qreal m33 = affine._dx*m.m_13 + affine._dy*m.m_23 + m_33*m.m_33;
942
943         t.affine._m11 = m11; t.affine._m12 = m12; t.m_13 = m13;
944         t.affine._m21 = m21; t.affine._m22 = m22; t.m_23 = m23;
945         t.affine._dx = m31; t.affine._dy = m32; t.m_33 = m33;
946     }
947     }
948
949     t.m_dirty = type;
950     t.m_type = type;
951
952     return t;
953 }
954
955 /*!
956     \fn QTransform & QTransform::operator*=(qreal scalar)
957     \overload
958
959     Returns the result of performing an element-wise multiplication of this
960     matrix with the given \a scalar.
961 */
962
963 /*!
964     \fn QTransform & QTransform::operator/=(qreal scalar)
965     \overload
966
967     Returns the result of performing an element-wise division of this
968     matrix by the given \a scalar.
969 */
970
971 /*!
972     \fn QTransform & QTransform::operator+=(qreal scalar)
973     \overload
974
975     Returns the matrix obtained by adding the given \a scalar to each
976     element of this matrix.
977 */
978
979 /*!
980     \fn QTransform & QTransform::operator-=(qreal scalar)
981     \overload
982
983     Returns the matrix obtained by subtracting the given \a scalar from each
984     element of this matrix.
985 */
986
987 /*!
988     Assigns the given \a matrix's values to this matrix.
989 */
990 QTransform & QTransform::operator=(const QTransform &matrix)
991 {
992     affine._m11 = matrix.affine._m11;
993     affine._m12 = matrix.affine._m12;
994     affine._m21 = matrix.affine._m21;
995     affine._m22 = matrix.affine._m22;
996     affine._dx = matrix.affine._dx;
997     affine._dy = matrix.affine._dy;
998     m_13 = matrix.m_13;
999     m_23 = matrix.m_23;
1000     m_33 = matrix.m_33;
1001     m_type = matrix.m_type;
1002     m_dirty = matrix.m_dirty;
1003
1004     return *this;
1005 }
1006
1007 /*!
1008     Resets the matrix to an identity matrix, i.e. all elements are set
1009     to zero, except \c m11 and \c m22 (specifying the scale) and \c m33
1010     which are set to 1.
1011
1012     \sa QTransform(), isIdentity(), {QTransform#Basic Matrix
1013     Operations}{Basic Matrix Operations}
1014 */
1015 void QTransform::reset()
1016 {
1017     affine._m11 = affine._m22 = m_33 = 1.0;
1018     affine._m12 = m_13 = affine._m21 = m_23 = affine._dx = affine._dy = 0;
1019     m_type = TxNone;
1020     m_dirty = TxNone;
1021 }
1022
1023 #ifndef QT_NO_DATASTREAM
1024 /*!
1025     \fn QDataStream &operator<<(QDataStream &stream, const QTransform &matrix)
1026     \since 4.3
1027     \relates QTransform
1028
1029     Writes the given \a matrix to the given \a stream and returns a
1030     reference to the stream.
1031
1032     \sa {Serializing Qt Data Types}
1033 */
1034 QDataStream & operator<<(QDataStream &s, const QTransform &m)
1035 {
1036     s << double(m.m11())
1037       << double(m.m12())
1038       << double(m.m13())
1039       << double(m.m21())
1040       << double(m.m22())
1041       << double(m.m23())
1042       << double(m.m31())
1043       << double(m.m32())
1044       << double(m.m33());
1045     return s;
1046 }
1047
1048 /*!
1049     \fn QDataStream &operator>>(QDataStream &stream, QTransform &matrix)
1050     \since 4.3
1051     \relates QTransform
1052
1053     Reads the given \a matrix from the given \a stream and returns a
1054     reference to the stream.
1055
1056     \sa {Serializing Qt Data Types}
1057 */
1058 QDataStream & operator>>(QDataStream &s, QTransform &t)
1059 {
1060      double m11, m12, m13,
1061          m21, m22, m23,
1062          m31, m32, m33;
1063
1064      s >> m11;
1065      s >> m12;
1066      s >> m13;
1067      s >> m21;
1068      s >> m22;
1069      s >> m23;
1070      s >> m31;
1071      s >> m32;
1072      s >> m33;
1073      t.setMatrix(m11, m12, m13,
1074                  m21, m22, m23,
1075                  m31, m32, m33);
1076      return s;
1077 }
1078
1079 #endif // QT_NO_DATASTREAM
1080
1081 #ifndef QT_NO_DEBUG_STREAM
1082 QDebug operator<<(QDebug dbg, const QTransform &m)
1083 {
1084     static const char *typeStr[] =
1085     {
1086         "TxNone",
1087         "TxTranslate",
1088         "TxScale",
1089         0,
1090         "TxRotate",
1091         0, 0, 0,
1092         "TxShear",
1093         0, 0, 0, 0, 0, 0, 0,
1094         "TxProject"
1095     };
1096
1097     dbg.nospace() << "QTransform(type=" << typeStr[m.type()] << ','
1098                   << " 11=" << m.m11()
1099                   << " 12=" << m.m12()
1100                   << " 13=" << m.m13()
1101                   << " 21=" << m.m21()
1102                   << " 22=" << m.m22()
1103                   << " 23=" << m.m23()
1104                   << " 31=" << m.m31()
1105                   << " 32=" << m.m32()
1106                   << " 33=" << m.m33()
1107                   << ')';
1108
1109     return dbg.space();
1110 }
1111 #endif
1112
1113 /*!
1114     \fn QPoint operator*(const QPoint &point, const QTransform &matrix)
1115     \relates QTransform
1116
1117     This is the same as \a{matrix}.map(\a{point}).
1118
1119     \sa QTransform::map()
1120 */
1121 QPoint QTransform::map(const QPoint &p) const
1122 {
1123     qreal fx = p.x();
1124     qreal fy = p.y();
1125
1126     qreal x = 0, y = 0;
1127
1128     TransformationType t = inline_type();
1129     switch(t) {
1130     case TxNone:
1131         x = fx;
1132         y = fy;
1133         break;
1134     case TxTranslate:
1135         x = fx + affine._dx;
1136         y = fy + affine._dy;
1137         break;
1138     case TxScale:
1139         x = affine._m11 * fx + affine._dx;
1140         y = affine._m22 * fy + affine._dy;
1141         break;
1142     case TxRotate:
1143     case TxShear:
1144     case TxProject:
1145         x = affine._m11 * fx + affine._m21 * fy + affine._dx;
1146         y = affine._m12 * fx + affine._m22 * fy + affine._dy;
1147         if (t == TxProject) {
1148             qreal w = 1./(m_13 * fx + m_23 * fy + m_33);
1149             x *= w;
1150             y *= w;
1151         }
1152     }
1153     return QPoint(qRound(x), qRound(y));
1154 }
1155
1156
1157 /*!
1158     \fn QPointF operator*(const QPointF &point, const QTransform &matrix)
1159     \relates QTransform
1160
1161     Same as \a{matrix}.map(\a{point}).
1162
1163     \sa QTransform::map()
1164 */
1165
1166 /*!
1167     \overload
1168
1169     Creates and returns a QPointF object that is a copy of the given point,
1170     \a p, mapped into the coordinate system defined by this matrix.
1171 */
1172 QPointF QTransform::map(const QPointF &p) const
1173 {
1174     qreal fx = p.x();
1175     qreal fy = p.y();
1176
1177     qreal x = 0, y = 0;
1178
1179     TransformationType t = inline_type();
1180     switch(t) {
1181     case TxNone:
1182         x = fx;
1183         y = fy;
1184         break;
1185     case TxTranslate:
1186         x = fx + affine._dx;
1187         y = fy + affine._dy;
1188         break;
1189     case TxScale:
1190         x = affine._m11 * fx + affine._dx;
1191         y = affine._m22 * fy + affine._dy;
1192         break;
1193     case TxRotate:
1194     case TxShear:
1195     case TxProject:
1196         x = affine._m11 * fx + affine._m21 * fy + affine._dx;
1197         y = affine._m12 * fx + affine._m22 * fy + affine._dy;
1198         if (t == TxProject) {
1199             qreal w = 1./(m_13 * fx + m_23 * fy + m_33);
1200             x *= w;
1201             y *= w;
1202         }
1203     }
1204     return QPointF(x, y);
1205 }
1206
1207 /*!
1208     \fn QPoint QTransform::map(const QPoint &point) const
1209     \overload
1210
1211     Creates and returns a QPoint object that is a copy of the given \a
1212     point, mapped into the coordinate system defined by this
1213     matrix. Note that the transformed coordinates are rounded to the
1214     nearest integer.
1215 */
1216
1217 /*!
1218     \fn QLineF operator*(const QLineF &line, const QTransform &matrix)
1219     \relates QTransform
1220
1221     This is the same as \a{matrix}.map(\a{line}).
1222
1223     \sa QTransform::map()
1224 */
1225
1226 /*!
1227     \fn QLine operator*(const QLine &line, const QTransform &matrix)
1228     \relates QTransform
1229
1230     This is the same as \a{matrix}.map(\a{line}).
1231
1232     \sa QTransform::map()
1233 */
1234
1235 /*!
1236     \overload
1237
1238     Creates and returns a QLineF object that is a copy of the given line,
1239     \a l, mapped into the coordinate system defined by this matrix.
1240 */
1241 QLine QTransform::map(const QLine &l) const
1242 {
1243     qreal fx1 = l.x1();
1244     qreal fy1 = l.y1();
1245     qreal fx2 = l.x2();
1246     qreal fy2 = l.y2();
1247
1248     qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1249
1250     TransformationType t = inline_type();
1251     switch(t) {
1252     case TxNone:
1253         x1 = fx1;
1254         y1 = fy1;
1255         x2 = fx2;
1256         y2 = fy2;
1257         break;
1258     case TxTranslate:
1259         x1 = fx1 + affine._dx;
1260         y1 = fy1 + affine._dy;
1261         x2 = fx2 + affine._dx;
1262         y2 = fy2 + affine._dy;
1263         break;
1264     case TxScale:
1265         x1 = affine._m11 * fx1 + affine._dx;
1266         y1 = affine._m22 * fy1 + affine._dy;
1267         x2 = affine._m11 * fx2 + affine._dx;
1268         y2 = affine._m22 * fy2 + affine._dy;
1269         break;
1270     case TxRotate:
1271     case TxShear:
1272     case TxProject:
1273         x1 = affine._m11 * fx1 + affine._m21 * fy1 + affine._dx;
1274         y1 = affine._m12 * fx1 + affine._m22 * fy1 + affine._dy;
1275         x2 = affine._m11 * fx2 + affine._m21 * fy2 + affine._dx;
1276         y2 = affine._m12 * fx2 + affine._m22 * fy2 + affine._dy;
1277         if (t == TxProject) {
1278             qreal w = 1./(m_13 * fx1 + m_23 * fy1 + m_33);
1279             x1 *= w;
1280             y1 *= w;
1281             w = 1./(m_13 * fx2 + m_23 * fy2 + m_33);
1282             x2 *= w;
1283             y2 *= w;
1284         }
1285     }
1286     return QLine(qRound(x1), qRound(y1), qRound(x2), qRound(y2));
1287 }
1288
1289 /*!
1290     \overload
1291
1292     \fn QLineF QTransform::map(const QLineF &line) const
1293
1294     Creates and returns a QLine object that is a copy of the given \a
1295     line, mapped into the coordinate system defined by this matrix.
1296     Note that the transformed coordinates are rounded to the nearest
1297     integer.
1298 */
1299
1300 QLineF QTransform::map(const QLineF &l) const
1301 {
1302     qreal fx1 = l.x1();
1303     qreal fy1 = l.y1();
1304     qreal fx2 = l.x2();
1305     qreal fy2 = l.y2();
1306
1307     qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
1308
1309     TransformationType t = inline_type();
1310     switch(t) {
1311     case TxNone:
1312         x1 = fx1;
1313         y1 = fy1;
1314         x2 = fx2;
1315         y2 = fy2;
1316         break;
1317     case TxTranslate:
1318         x1 = fx1 + affine._dx;
1319         y1 = fy1 + affine._dy;
1320         x2 = fx2 + affine._dx;
1321         y2 = fy2 + affine._dy;
1322         break;
1323     case TxScale:
1324         x1 = affine._m11 * fx1 + affine._dx;
1325         y1 = affine._m22 * fy1 + affine._dy;
1326         x2 = affine._m11 * fx2 + affine._dx;
1327         y2 = affine._m22 * fy2 + affine._dy;
1328         break;
1329     case TxRotate:
1330     case TxShear:
1331     case TxProject:
1332         x1 = affine._m11 * fx1 + affine._m21 * fy1 + affine._dx;
1333         y1 = affine._m12 * fx1 + affine._m22 * fy1 + affine._dy;
1334         x2 = affine._m11 * fx2 + affine._m21 * fy2 + affine._dx;
1335         y2 = affine._m12 * fx2 + affine._m22 * fy2 + affine._dy;
1336         if (t == TxProject) {
1337             qreal w = 1./(m_13 * fx1 + m_23 * fy1 + m_33);
1338             x1 *= w;
1339             y1 *= w;
1340             w = 1./(m_13 * fx2 + m_23 * fy2 + m_33);
1341             x2 *= w;
1342             y2 *= w;
1343         }
1344     }
1345     return QLineF(x1, y1, x2, y2);
1346 }
1347
1348 static QPolygonF mapProjective(const QTransform &transform, const QPolygonF &poly)
1349 {
1350     if (poly.size() == 0)
1351         return poly;
1352
1353     if (poly.size() == 1)
1354         return QPolygonF() << transform.map(poly.at(0));
1355
1356     QPainterPath path;
1357     path.addPolygon(poly);
1358
1359     path = transform.map(path);
1360
1361     QPolygonF result;
1362     for (int i = 0; i < path.elementCount(); ++i)
1363         result << path.elementAt(i);
1364     return result;
1365 }
1366
1367
1368 /*!
1369     \fn QPolygonF operator *(const QPolygonF &polygon, const QTransform &matrix)
1370     \since 4.3
1371     \relates QTransform
1372
1373     This is the same as \a{matrix}.map(\a{polygon}).
1374
1375     \sa QTransform::map()
1376 */
1377
1378 /*!
1379     \fn QPolygon operator*(const QPolygon &polygon, const QTransform &matrix)
1380     \relates QTransform
1381
1382     This is the same as \a{matrix}.map(\a{polygon}).
1383
1384     \sa QTransform::map()
1385 */
1386
1387 /*!
1388     \fn QPolygonF QTransform::map(const QPolygonF &polygon) const
1389     \overload
1390
1391     Creates and returns a QPolygonF object that is a copy of the given
1392     \a polygon, mapped into the coordinate system defined by this
1393     matrix.
1394 */
1395 QPolygonF QTransform::map(const QPolygonF &a) const
1396 {
1397     TransformationType t = inline_type();
1398     if (t <= TxTranslate)
1399         return a.translated(affine._dx, affine._dy);
1400
1401     if (t >= QTransform::TxProject)
1402         return mapProjective(*this, a);
1403
1404     int size = a.size();
1405     int i;
1406     QPolygonF p(size);
1407     const QPointF *da = a.constData();
1408     QPointF *dp = p.data();
1409
1410     for(i = 0; i < size; ++i) {
1411         MAP(da[i].xp, da[i].yp, dp[i].xp, dp[i].yp);
1412     }
1413     return p;
1414 }
1415
1416 /*!
1417     \fn QPolygon QTransform::map(const QPolygon &polygon) const
1418     \overload
1419
1420     Creates and returns a QPolygon object that is a copy of the given
1421     \a polygon, mapped into the coordinate system defined by this
1422     matrix. Note that the transformed coordinates are rounded to the
1423     nearest integer.
1424 */
1425 QPolygon QTransform::map(const QPolygon &a) const
1426 {
1427     TransformationType t = inline_type();
1428     if (t <= TxTranslate)
1429         return a.translated(qRound(affine._dx), qRound(affine._dy));
1430
1431     if (t >= QTransform::TxProject)
1432         return mapProjective(*this, QPolygonF(a)).toPolygon();
1433
1434     int size = a.size();
1435     int i;
1436     QPolygon p(size);
1437     const QPoint *da = a.constData();
1438     QPoint *dp = p.data();
1439
1440     for(i = 0; i < size; ++i) {
1441         qreal nx = 0, ny = 0;
1442         MAP(da[i].xp, da[i].yp, nx, ny);
1443         dp[i].xp = qRound(nx);
1444         dp[i].yp = qRound(ny);
1445     }
1446     return p;
1447 }
1448
1449 /*!
1450     \fn QRegion operator*(const QRegion &region, const QTransform &matrix)
1451     \relates QTransform
1452
1453     This is the same as \a{matrix}.map(\a{region}).
1454
1455     \sa QTransform::map()
1456 */
1457
1458 extern QPainterPath qt_regionToPath(const QRegion &region);
1459
1460 /*!
1461     \fn QRegion QTransform::map(const QRegion &region) const
1462     \overload
1463
1464     Creates and returns a QRegion object that is a copy of the given
1465     \a region, mapped into the coordinate system defined by this matrix.
1466
1467     Calling this method can be rather expensive if rotations or
1468     shearing are used.
1469 */
1470 QRegion QTransform::map(const QRegion &r) const
1471 {
1472     TransformationType t = inline_type();
1473     if (t == TxNone)
1474         return r;
1475
1476     if (t == TxTranslate) {
1477         QRegion copy(r);
1478         copy.translate(qRound(affine._dx), qRound(affine._dy));
1479         return copy;
1480     }
1481
1482     if (t == TxScale && r.rectCount() == 1)
1483         return QRegion(mapRect(r.boundingRect()));
1484
1485     QPainterPath p = map(qt_regionToPath(r));
1486     return p.toFillPolygon(QTransform()).toPolygon();
1487 }
1488
1489 struct QHomogeneousCoordinate
1490 {
1491     qreal x;
1492     qreal y;
1493     qreal w;
1494
1495     QHomogeneousCoordinate() {}
1496     QHomogeneousCoordinate(qreal x_, qreal y_, qreal w_) : x(x_), y(y_), w(w_) {}
1497
1498     const QPointF toPoint() const {
1499         qreal iw = 1. / w;
1500         return QPointF(x * iw, y * iw);
1501     }
1502 };
1503
1504 static inline QHomogeneousCoordinate mapHomogeneous(const QTransform &transform, const QPointF &p)
1505 {
1506     QHomogeneousCoordinate c;
1507     c.x = transform.m11() * p.x() + transform.m21() * p.y() + transform.m31();
1508     c.y = transform.m12() * p.x() + transform.m22() * p.y() + transform.m32();
1509     c.w = transform.m13() * p.x() + transform.m23() * p.y() + transform.m33();
1510     return c;
1511 }
1512
1513 static inline bool lineTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b,
1514                                   bool needsMoveTo, bool needsLineTo = true)
1515 {
1516     QHomogeneousCoordinate ha = mapHomogeneous(transform, a);
1517     QHomogeneousCoordinate hb = mapHomogeneous(transform, b);
1518
1519     if (ha.w < Q_NEAR_CLIP && hb.w < Q_NEAR_CLIP)
1520         return false;
1521
1522     if (hb.w < Q_NEAR_CLIP) {
1523         const qreal t = (Q_NEAR_CLIP - hb.w) / (ha.w - hb.w);
1524
1525         hb.x += (ha.x - hb.x) * t;
1526         hb.y += (ha.y - hb.y) * t;
1527         hb.w = qreal(Q_NEAR_CLIP);
1528     } else if (ha.w < Q_NEAR_CLIP) {
1529         const qreal t = (Q_NEAR_CLIP - ha.w) / (hb.w - ha.w);
1530
1531         ha.x += (hb.x - ha.x) * t;
1532         ha.y += (hb.y - ha.y) * t;
1533         ha.w = qreal(Q_NEAR_CLIP);
1534
1535         const QPointF p = ha.toPoint();
1536         if (needsMoveTo) {
1537             path.moveTo(p);
1538             needsMoveTo = false;
1539         } else {
1540             path.lineTo(p);
1541         }
1542     }
1543
1544     if (needsMoveTo)
1545         path.moveTo(ha.toPoint());
1546
1547     if (needsLineTo)
1548         path.lineTo(hb.toPoint());
1549
1550     return true;
1551 }
1552 Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
1553
1554 static inline bool cubicTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, bool needsMoveTo)
1555 {
1556     // Convert projective xformed curves to line
1557     // segments so they can be transformed more accurately
1558
1559     qreal scale;
1560     qt_scaleForTransform(transform, &scale);
1561
1562     qreal curveThreshold = scale == 0 ? qreal(0.25) : (qreal(0.25) / scale);
1563
1564     QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(curveThreshold);
1565
1566     for (int i = 0; i < segment.size() - 1; ++i)
1567         if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo))
1568             needsMoveTo = false;
1569
1570     return !needsMoveTo;
1571 }
1572
1573 static QPainterPath mapProjective(const QTransform &transform, const QPainterPath &path)
1574 {
1575     QPainterPath result;
1576
1577     QPointF last;
1578     QPointF lastMoveTo;
1579     bool needsMoveTo = true;
1580     for (int i = 0; i < path.elementCount(); ++i) {
1581         switch (path.elementAt(i).type) {
1582         case QPainterPath::MoveToElement:
1583             if (i > 0 && lastMoveTo != last)
1584                 lineTo_clipped(result, transform, last, lastMoveTo, needsMoveTo);
1585
1586             lastMoveTo = path.elementAt(i);
1587             last = path.elementAt(i);
1588             needsMoveTo = true;
1589             break;
1590         case QPainterPath::LineToElement:
1591             if (lineTo_clipped(result, transform, last, path.elementAt(i), needsMoveTo))
1592                 needsMoveTo = false;
1593             last = path.elementAt(i);
1594             break;
1595         case QPainterPath::CurveToElement:
1596             if (cubicTo_clipped(result, transform, last, path.elementAt(i), path.elementAt(i+1), path.elementAt(i+2), needsMoveTo))
1597                 needsMoveTo = false;
1598             i += 2;
1599             last = path.elementAt(i);
1600             break;
1601         default:
1602             Q_ASSERT(false);
1603         }
1604     }
1605
1606     if (path.elementCount() > 0 && lastMoveTo != last)
1607         lineTo_clipped(result, transform, last, lastMoveTo, needsMoveTo, false);
1608
1609     result.setFillRule(path.fillRule());
1610     return result;
1611 }
1612
1613 /*!
1614     \fn QPainterPath operator *(const QPainterPath &path, const QTransform &matrix)
1615     \since 4.3
1616     \relates QTransform
1617
1618     This is the same as \a{matrix}.map(\a{path}).
1619
1620     \sa QTransform::map()
1621 */
1622
1623 /*!
1624     \overload
1625
1626     Creates and returns a QPainterPath object that is a copy of the
1627     given \a path, mapped into the coordinate system defined by this
1628     matrix.
1629 */
1630 QPainterPath QTransform::map(const QPainterPath &path) const
1631 {
1632     TransformationType t = inline_type();
1633     if (t == TxNone || path.elementCount() == 0)
1634         return path;
1635
1636     if (t >= TxProject)
1637         return mapProjective(*this, path);
1638
1639     QPainterPath copy = path;
1640
1641     if (t == TxTranslate) {
1642         copy.translate(affine._dx, affine._dy);
1643     } else {
1644         copy.detach();
1645         // Full xform
1646         for (int i=0; i<path.elementCount(); ++i) {
1647             QPainterPath::Element &e = copy.d_ptr->elements[i];
1648             MAP(e.x, e.y, e.x, e.y);
1649         }
1650     }
1651
1652     return copy;
1653 }
1654
1655 /*!
1656     \fn QPolygon QTransform::mapToPolygon(const QRect &rectangle) const
1657
1658     Creates and returns a QPolygon representation of the given \a
1659     rectangle, mapped into the coordinate system defined by this
1660     matrix.
1661
1662     The rectangle's coordinates are transformed using the following
1663     formulas:
1664
1665     \snippet code/src_gui_painting_qtransform.cpp 1
1666
1667     Polygons and rectangles behave slightly differently when
1668     transformed (due to integer rounding), so
1669     \c{matrix.map(QPolygon(rectangle))} is not always the same as
1670     \c{matrix.mapToPolygon(rectangle)}.
1671
1672     \sa mapRect(), {QTransform#Basic Matrix Operations}{Basic Matrix
1673     Operations}
1674 */
1675 QPolygon QTransform::mapToPolygon(const QRect &rect) const
1676 {
1677     TransformationType t = inline_type();
1678
1679     QPolygon a(4);
1680     qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 };
1681     if (t <= TxScale) {
1682         x[0] = affine._m11*rect.x() + affine._dx;
1683         y[0] = affine._m22*rect.y() + affine._dy;
1684         qreal w = affine._m11*rect.width();
1685         qreal h = affine._m22*rect.height();
1686         if (w < 0) {
1687             w = -w;
1688             x[0] -= w;
1689         }
1690         if (h < 0) {
1691             h = -h;
1692             y[0] -= h;
1693         }
1694         x[1] = x[0]+w;
1695         x[2] = x[1];
1696         x[3] = x[0];
1697         y[1] = y[0];
1698         y[2] = y[0]+h;
1699         y[3] = y[2];
1700     } else {
1701         qreal right = rect.x() + rect.width();
1702         qreal bottom = rect.y() + rect.height();
1703         MAP(rect.x(), rect.y(), x[0], y[0]);
1704         MAP(right, rect.y(), x[1], y[1]);
1705         MAP(right, bottom, x[2], y[2]);
1706         MAP(rect.x(), bottom, x[3], y[3]);
1707     }
1708
1709     // all coordinates are correctly, tranform to a pointarray
1710     // (rounding to the next integer)
1711     a.setPoints(4, qRound(x[0]), qRound(y[0]),
1712                 qRound(x[1]), qRound(y[1]),
1713                 qRound(x[2]), qRound(y[2]),
1714                 qRound(x[3]), qRound(y[3]));
1715     return a;
1716 }
1717
1718 /*!
1719     Creates a transformation matrix, \a trans, that maps a unit square
1720     to a four-sided polygon, \a quad. Returns true if the transformation
1721     is constructed or false if such a transformation does not exist.
1722
1723     \sa quadToSquare(), quadToQuad()
1724 */
1725 bool QTransform::squareToQuad(const QPolygonF &quad, QTransform &trans)
1726 {
1727     if (quad.count() != 4)
1728         return false;
1729
1730     qreal dx0 = quad[0].x();
1731     qreal dx1 = quad[1].x();
1732     qreal dx2 = quad[2].x();
1733     qreal dx3 = quad[3].x();
1734
1735     qreal dy0 = quad[0].y();
1736     qreal dy1 = quad[1].y();
1737     qreal dy2 = quad[2].y();
1738     qreal dy3 = quad[3].y();
1739
1740     double ax  = dx0 - dx1 + dx2 - dx3;
1741     double ay  = dy0 - dy1 + dy2 - dy3;
1742
1743     if (!ax && !ay) { //afine transform
1744         trans.setMatrix(dx1 - dx0, dy1 - dy0,  0,
1745                         dx2 - dx1, dy2 - dy1,  0,
1746                         dx0,       dy0,  1);
1747     } else {
1748         double ax1 = dx1 - dx2;
1749         double ax2 = dx3 - dx2;
1750         double ay1 = dy1 - dy2;
1751         double ay2 = dy3 - dy2;
1752
1753         /*determinants */
1754         double gtop    =  ax  * ay2 - ax2 * ay;
1755         double htop    =  ax1 * ay  - ax  * ay1;
1756         double bottom  =  ax1 * ay2 - ax2 * ay1;
1757
1758         double a, b, c, d, e, f, g, h;  /*i is always 1*/
1759
1760         if (!bottom)
1761             return false;
1762
1763         g = gtop/bottom;
1764         h = htop/bottom;
1765
1766         a = dx1 - dx0 + g * dx1;
1767         b = dx3 - dx0 + h * dx3;
1768         c = dx0;
1769         d = dy1 - dy0 + g * dy1;
1770         e = dy3 - dy0 + h * dy3;
1771         f = dy0;
1772
1773         trans.setMatrix(a, d, g,
1774                         b, e, h,
1775                         c, f, 1.0);
1776     }
1777
1778     return true;
1779 }
1780
1781 /*!
1782     \fn bool QTransform::quadToSquare(const QPolygonF &quad, QTransform &trans)
1783
1784     Creates a transformation matrix, \a trans, that maps a four-sided polygon,
1785     \a quad, to a unit square. Returns true if the transformation is constructed
1786     or false if such a transformation does not exist.
1787
1788     \sa squareToQuad(), quadToQuad()
1789 */
1790 bool QTransform::quadToSquare(const QPolygonF &quad, QTransform &trans)
1791 {
1792     if (!squareToQuad(quad, trans))
1793         return false;
1794
1795     bool invertible = false;
1796     trans = trans.inverted(&invertible);
1797
1798     return invertible;
1799 }
1800
1801 /*!
1802     Creates a transformation matrix, \a trans, that maps a four-sided
1803     polygon, \a one, to another four-sided polygon, \a two.
1804     Returns true if the transformation is possible; otherwise returns
1805     false.
1806
1807     This is a convenience method combining quadToSquare() and
1808     squareToQuad() methods. It allows the input quad to be
1809     transformed into any other quad.
1810
1811     \sa squareToQuad(), quadToSquare()
1812 */
1813 bool QTransform::quadToQuad(const QPolygonF &one,
1814                             const QPolygonF &two,
1815                             QTransform &trans)
1816 {
1817     QTransform stq;
1818     if (!quadToSquare(one, trans))
1819         return false;
1820     if (!squareToQuad(two, stq))
1821         return false;
1822     trans *= stq;
1823     //qDebug()<<"Final = "<<trans;
1824     return true;
1825 }
1826
1827 /*!
1828     Sets the matrix elements to the specified values, \a m11,
1829     \a m12, \a m13 \a m21, \a m22, \a m23 \a m31, \a m32 and
1830     \a m33. Note that this function replaces the previous values.
1831     QTransform provides the translate(), rotate(), scale() and shear()
1832     convenience functions to manipulate the various matrix elements
1833     based on the currently defined coordinate system.
1834
1835     \sa QTransform()
1836 */
1837
1838 void QTransform::setMatrix(qreal m11, qreal m12, qreal m13,
1839                            qreal m21, qreal m22, qreal m23,
1840                            qreal m31, qreal m32, qreal m33)
1841 {
1842     affine._m11 = m11; affine._m12 = m12; m_13 = m13;
1843     affine._m21 = m21; affine._m22 = m22; m_23 = m23;
1844     affine._dx = m31; affine._dy = m32; m_33 = m33;
1845     m_type = TxNone;
1846     m_dirty = TxProject;
1847 }
1848
1849 static inline bool needsPerspectiveClipping(const QRectF &rect, const QTransform &transform)
1850 {
1851     const qreal wx = qMin(transform.m13() * rect.left(), transform.m13() * rect.right());
1852     const qreal wy = qMin(transform.m23() * rect.top(), transform.m23() * rect.bottom());
1853
1854     return wx + wy + transform.m33() < Q_NEAR_CLIP;
1855 }
1856
1857 QRect QTransform::mapRect(const QRect &rect) const
1858 {
1859     TransformationType t = inline_type();
1860     if (t <= TxTranslate)
1861         return rect.translated(qRound(affine._dx), qRound(affine._dy));
1862
1863     if (t <= TxScale) {
1864         int x = qRound(affine._m11*rect.x() + affine._dx);
1865         int y = qRound(affine._m22*rect.y() + affine._dy);
1866         int w = qRound(affine._m11*rect.width());
1867         int h = qRound(affine._m22*rect.height());
1868         if (w < 0) {
1869             w = -w;
1870             x -= w;
1871         }
1872         if (h < 0) {
1873             h = -h;
1874             y -= h;
1875         }
1876         return QRect(x, y, w, h);
1877     } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
1878         // see mapToPolygon for explanations of the algorithm.
1879         qreal x = 0, y = 0;
1880         MAP(rect.left(), rect.top(), x, y);
1881         qreal xmin = x;
1882         qreal ymin = y;
1883         qreal xmax = x;
1884         qreal ymax = y;
1885         MAP(rect.right() + 1, rect.top(), x, y);
1886         xmin = qMin(xmin, x);
1887         ymin = qMin(ymin, y);
1888         xmax = qMax(xmax, x);
1889         ymax = qMax(ymax, y);
1890         MAP(rect.right() + 1, rect.bottom() + 1, x, y);
1891         xmin = qMin(xmin, x);
1892         ymin = qMin(ymin, y);
1893         xmax = qMax(xmax, x);
1894         ymax = qMax(ymax, y);
1895         MAP(rect.left(), rect.bottom() + 1, x, y);
1896         xmin = qMin(xmin, x);
1897         ymin = qMin(ymin, y);
1898         xmax = qMax(xmax, x);
1899         ymax = qMax(ymax, y);
1900         return QRect(qRound(xmin), qRound(ymin), qRound(xmax)-qRound(xmin), qRound(ymax)-qRound(ymin));
1901     } else {
1902         QPainterPath path;
1903         path.addRect(rect);
1904         return map(path).boundingRect().toRect();
1905     }
1906 }
1907
1908 /*!
1909     \fn QRectF QTransform::mapRect(const QRectF &rectangle) const
1910
1911     Creates and returns a QRectF object that is a copy of the given \a
1912     rectangle, mapped into the coordinate system defined by this
1913     matrix.
1914
1915     The rectangle's coordinates are transformed using the following
1916     formulas:
1917
1918     \snippet code/src_gui_painting_qtransform.cpp 2
1919
1920     If rotation or shearing has been specified, this function returns
1921     the \e bounding rectangle. To retrieve the exact region the given
1922     \a rectangle maps to, use the mapToPolygon() function instead.
1923
1924     \sa mapToPolygon(), {QTransform#Basic Matrix Operations}{Basic Matrix
1925     Operations}
1926 */
1927 QRectF QTransform::mapRect(const QRectF &rect) const
1928 {
1929     TransformationType t = inline_type();
1930     if (t <= TxTranslate)
1931         return rect.translated(affine._dx, affine._dy);
1932
1933     if (t <= TxScale) {
1934         qreal x = affine._m11*rect.x() + affine._dx;
1935         qreal y = affine._m22*rect.y() + affine._dy;
1936         qreal w = affine._m11*rect.width();
1937         qreal h = affine._m22*rect.height();
1938         if (w < 0) {
1939             w = -w;
1940             x -= w;
1941         }
1942         if (h < 0) {
1943             h = -h;
1944             y -= h;
1945         }
1946         return QRectF(x, y, w, h);
1947     } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
1948         qreal x = 0, y = 0;
1949         MAP(rect.x(), rect.y(), x, y);
1950         qreal xmin = x;
1951         qreal ymin = y;
1952         qreal xmax = x;
1953         qreal ymax = y;
1954         MAP(rect.x() + rect.width(), rect.y(), x, y);
1955         xmin = qMin(xmin, x);
1956         ymin = qMin(ymin, y);
1957         xmax = qMax(xmax, x);
1958         ymax = qMax(ymax, y);
1959         MAP(rect.x() + rect.width(), rect.y() + rect.height(), x, y);
1960         xmin = qMin(xmin, x);
1961         ymin = qMin(ymin, y);
1962         xmax = qMax(xmax, x);
1963         ymax = qMax(ymax, y);
1964         MAP(rect.x(), rect.y() + rect.height(), x, y);
1965         xmin = qMin(xmin, x);
1966         ymin = qMin(ymin, y);
1967         xmax = qMax(xmax, x);
1968         ymax = qMax(ymax, y);
1969         return QRectF(xmin, ymin, xmax-xmin, ymax - ymin);
1970     } else {
1971         QPainterPath path;
1972         path.addRect(rect);
1973         return map(path).boundingRect();
1974     }
1975 }
1976
1977 /*!
1978     \fn QRect QTransform::mapRect(const QRect &rectangle) const
1979     \overload
1980
1981     Creates and returns a QRect object that is a copy of the given \a
1982     rectangle, mapped into the coordinate system defined by this
1983     matrix. Note that the transformed coordinates are rounded to the
1984     nearest integer.
1985 */
1986
1987 /*!
1988     Maps the given coordinates \a x and \a y into the coordinate
1989     system defined by this matrix. The resulting values are put in *\a
1990     tx and *\a ty, respectively.
1991
1992     The coordinates are transformed using the following formulas:
1993
1994     \snippet code/src_gui_painting_qtransform.cpp 3
1995
1996     The point (x, y) is the original point, and (x', y') is the
1997     transformed point.
1998
1999     \sa {QTransform#Basic Matrix Operations}{Basic Matrix Operations}
2000 */
2001 void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty) const
2002 {
2003     TransformationType t = inline_type();
2004     MAP(x, y, *tx, *ty);
2005 }
2006
2007 /*!
2008     \overload
2009
2010     Maps the given coordinates \a x and \a y into the coordinate
2011     system defined by this matrix. The resulting values are put in *\a
2012     tx and *\a ty, respectively. Note that the transformed coordinates
2013     are rounded to the nearest integer.
2014 */
2015 void QTransform::map(int x, int y, int *tx, int *ty) const
2016 {
2017     TransformationType t = inline_type();
2018     qreal fx = 0, fy = 0;
2019     MAP(x, y, fx, fy);
2020     *tx = qRound(fx);
2021     *ty = qRound(fy);
2022 }
2023
2024 /*!
2025   Returns the QTransform as an affine matrix.
2026
2027   \warning If a perspective transformation has been specified,
2028   then the conversion will cause loss of data.
2029 */
2030 const QMatrix &QTransform::toAffine() const
2031 {
2032     return affine;
2033 }
2034
2035 /*!
2036   Returns the transformation type of this matrix.
2037
2038   The transformation type is the highest enumeration value
2039   capturing all of the matrix's transformations. For example,
2040   if the matrix both scales and shears, the type would be \c TxShear,
2041   because \c TxShear has a higher enumeration value than \c TxScale.
2042
2043   Knowing the transformation type of a matrix is useful for optimization:
2044   you can often handle specific types more optimally than handling
2045   the generic case.
2046   */
2047 QTransform::TransformationType QTransform::type() const
2048 {
2049     if(m_dirty == TxNone || m_dirty < m_type)
2050         return static_cast<TransformationType>(m_type);
2051
2052     switch (static_cast<TransformationType>(m_dirty)) {
2053     case TxProject:
2054         if (!qFuzzyIsNull(m_13) || !qFuzzyIsNull(m_23) || !qFuzzyIsNull(m_33 - 1)) {
2055              m_type = TxProject;
2056              break;
2057          }
2058     case TxShear:
2059     case TxRotate:
2060         if (!qFuzzyIsNull(affine._m12) || !qFuzzyIsNull(affine._m21)) {
2061             const qreal dot = affine._m11 * affine._m12 + affine._m21 * affine._m22;
2062             if (qFuzzyIsNull(dot))
2063                 m_type = TxRotate;
2064             else
2065                 m_type = TxShear;
2066             break;
2067         }
2068     case TxScale:
2069         if (!qFuzzyIsNull(affine._m11 - 1) || !qFuzzyIsNull(affine._m22 - 1)) {
2070             m_type = TxScale;
2071             break;
2072         }
2073     case TxTranslate:
2074         if (!qFuzzyIsNull(affine._dx) || !qFuzzyIsNull(affine._dy)) {
2075             m_type = TxTranslate;
2076             break;
2077         }
2078     case TxNone:
2079         m_type = TxNone;
2080         break;
2081     }
2082
2083     m_dirty = TxNone;
2084     return static_cast<TransformationType>(m_type);
2085 }
2086
2087 /*!
2088
2089     Returns the transform as a QVariant.
2090 */
2091 QTransform::operator QVariant() const
2092 {
2093     return QVariant(QVariant::Transform, this);
2094 }
2095
2096
2097 /*!
2098     \fn bool QTransform::isInvertible() const
2099
2100     Returns true if the matrix is invertible, otherwise returns false.
2101
2102     \sa inverted()
2103 */
2104
2105 /*!
2106     \fn qreal QTransform::det() const
2107     \obsolete
2108
2109     Returns the matrix's determinant. Use determinant() instead.
2110 */
2111
2112
2113 /*!
2114     \fn qreal QTransform::m11() const
2115
2116     Returns the horizontal scaling factor.
2117
2118     \sa scale(), {QTransform#Basic Matrix Operations}{Basic Matrix
2119     Operations}
2120 */
2121
2122 /*!
2123     \fn qreal QTransform::m12() const
2124
2125     Returns the vertical shearing factor.
2126
2127     \sa shear(), {QTransform#Basic Matrix Operations}{Basic Matrix
2128     Operations}
2129 */
2130
2131 /*!
2132     \fn qreal QTransform::m21() const
2133
2134     Returns the horizontal shearing factor.
2135
2136     \sa shear(), {QTransform#Basic Matrix Operations}{Basic Matrix
2137     Operations}
2138 */
2139
2140 /*!
2141     \fn qreal QTransform::m22() const
2142
2143     Returns the vertical scaling factor.
2144
2145     \sa scale(), {QTransform#Basic Matrix Operations}{Basic Matrix
2146     Operations}
2147 */
2148
2149 /*!
2150     \fn qreal QTransform::dx() const
2151
2152     Returns the horizontal translation factor.
2153
2154     \sa m31(), translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2155     Operations}
2156 */
2157
2158 /*!
2159     \fn qreal QTransform::dy() const
2160
2161     Returns the vertical translation factor.
2162
2163     \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2164     Operations}
2165 */
2166
2167
2168 /*!
2169     \fn qreal QTransform::m13() const
2170
2171     Returns the horizontal projection factor.
2172
2173     \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2174     Operations}
2175 */
2176
2177
2178 /*!
2179     \fn qreal QTransform::m23() const
2180
2181     Returns the vertical projection factor.
2182
2183     \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2184     Operations}
2185 */
2186
2187 /*!
2188     \fn qreal QTransform::m31() const
2189
2190     Returns the horizontal translation factor.
2191
2192     \sa dx(), translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2193     Operations}
2194 */
2195
2196 /*!
2197     \fn qreal QTransform::m32() const
2198
2199     Returns the vertical translation factor.
2200
2201     \sa dy(), translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2202     Operations}
2203 */
2204
2205 /*!
2206     \fn qreal QTransform::m33() const
2207
2208     Returns the division factor.
2209
2210     \sa translate(), {QTransform#Basic Matrix Operations}{Basic Matrix
2211     Operations}
2212 */
2213
2214 /*!
2215     \fn qreal QTransform::determinant() const
2216
2217     Returns the matrix's determinant.
2218 */
2219
2220 /*!
2221     \fn bool QTransform::isIdentity() const
2222
2223     Returns true if the matrix is the identity matrix, otherwise
2224     returns false.
2225
2226     \sa reset()
2227 */
2228
2229 /*!
2230     \fn bool QTransform::isAffine() const
2231
2232     Returns true if the matrix represent an affine transformation,
2233     otherwise returns false.
2234 */
2235
2236 /*!
2237     \fn bool QTransform::isScaling() const
2238
2239     Returns true if the matrix represents a scaling
2240     transformation, otherwise returns false.
2241
2242     \sa reset()
2243 */
2244
2245 /*!
2246     \fn bool QTransform::isRotating() const
2247
2248     Returns true if the matrix represents some kind of a
2249     rotating transformation, otherwise returns false.
2250
2251     \sa reset()
2252 */
2253
2254 /*!
2255     \fn bool QTransform::isTranslating() const
2256
2257     Returns true if the matrix represents a translating
2258     transformation, otherwise returns false.
2259
2260     \sa reset()
2261 */
2262
2263 /*!
2264     \fn bool qFuzzyCompare(const QTransform& t1, const QTransform& t2)
2265
2266     \relates QTransform
2267     \since 4.6
2268
2269     Returns true if \a t1 and \a t2 are equal, allowing for a small
2270     fuzziness factor for floating-point comparisons; false otherwise.
2271 */
2272
2273
2274 // returns true if the transform is uniformly scaling
2275 // (same scale in x and y direction)
2276 // scale is set to the max of x and y scaling factors
2277 Q_GUI_EXPORT
2278 bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
2279 {
2280     const QTransform::TransformationType type = transform.type();
2281     if (type <= QTransform::TxTranslate) {
2282         if (scale)
2283             *scale = 1;
2284         return true;
2285     } else if (type == QTransform::TxScale) {
2286         const qreal xScale = qAbs(transform.m11());
2287         const qreal yScale = qAbs(transform.m22());
2288         if (scale)
2289             *scale = qMax(xScale, yScale);
2290         return qFuzzyCompare(xScale, yScale);
2291     }
2292
2293     const qreal xScale = transform.m11() * transform.m11()
2294                          + transform.m21() * transform.m21();
2295     const qreal yScale = transform.m12() * transform.m12()
2296                          + transform.m22() * transform.m22();
2297     if (scale)
2298         *scale = qSqrt(qMax(xScale, yScale));
2299     return type == QTransform::TxRotate && qFuzzyCompare(xScale, yScale);
2300 }
2301
2302 QT_END_NAMESPACE