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