1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include "qmatrix.h"
41 
42 #include "qdatastream.h"
43 #include "qdebug.h"
44 #include "qhashfunctions.h"
45 #include "qregion.h"
46 #include "qpainterpath.h"
47 #include "qpainterpath_p.h"
48 #include "qtransform.h"
49 #include "qvariant.h"
50 #include <qmath.h>
51 
52 #include <limits.h>
53 
54 QT_BEGIN_NAMESPACE
55 
56 /*!
57     \class QMatrix
58     \brief The QMatrix class specifies 2D transformations of a
59     coordinate system.
60     \obsolete
61 
62     \ingroup painting
63     \inmodule QtGui
64 
65     A matrix specifies how to translate, scale, shear or rotate the
66     coordinate system, and is typically used when rendering graphics.
67     QMatrix, in contrast to QTransform, does not allow perspective
68     transformations. QTransform is the recommended transformation
69     class in Qt.
70 
71     A QMatrix object can be built using the setMatrix(), scale(),
72     rotate(), translate() and shear() functions.  Alternatively, it
73     can be built by applying \l {QMatrix#Basic Matrix
74     Operations}{basic matrix operations}. The matrix can also be
75     defined when constructed, and it can be reset to the identity
76     matrix (the default) using the reset() function.
77 
78     The QMatrix class supports mapping of graphic primitives: A given
79     point, line, polygon, region, or painter path can be mapped to the
80     coordinate system defined by \e this matrix using the map()
81     function. In case of a rectangle, its coordinates can be
82     transformed using the mapRect() function. A rectangle can also be
83     transformed into a \e polygon (mapped to the coordinate system
84     defined by \e this matrix), using the mapToPolygon() function.
85 
86     QMatrix provides the isIdentity() function which returns \c true if
87     the matrix is the identity matrix, and the isInvertible() function
88     which returns \c true if the matrix is non-singular (i.e. AB = BA =
89     I). The inverted() function returns an inverted copy of \e this
90     matrix if it is invertible (otherwise it returns the identity
91     matrix). In addition, QMatrix provides the determinant() function
92     returning the matrix's determinant.
93 
94     Finally, the QMatrix class supports matrix multiplication, and
95     objects of the class can be streamed as well as compared.
96 
97     \tableofcontents
98 
99     \section1 Rendering Graphics
100 
101     When rendering graphics, the matrix defines the transformations
102     but the actual transformation is performed by the drawing routines
103     in QPainter.
104 
105     By default, QPainter operates on the associated device's own
106     coordinate system.  The standard coordinate system of a
107     QPaintDevice has its origin located at the top-left position. The
108     \e x values increase to the right; \e y values increase
109     downward. For a complete description, see the \l {Coordinate
110     System}{coordinate system} documentation.
111 
112     QPainter has functions to translate, scale, shear and rotate the
113     coordinate system without using a QMatrix. For example:
114 
115     \table 100%
116     \row
117     \li \inlineimage qmatrix-simpletransformation.png
118     \li
119     \snippet matrix/matrix.cpp 0
120     \endtable
121 
122     Although these functions are very convenient, it can be more
123     efficient to build a QMatrix and call QPainter::setMatrix() if you
124     want to perform more than a single transform operation. For
125     example:
126 
127     \table 100%
128     \row
129     \li \inlineimage qmatrix-combinedtransformation.png
130     \li
131     \snippet matrix/matrix.cpp 1
132     \endtable
133 
134     \section1 Basic Matrix Operations
135 
136     \image qmatrix-representation.png
137 
138     A QMatrix object contains a 3 x 3 matrix.  The \c dx and \c dy
139     elements specify horizontal and vertical translation. The \c m11
140     and \c m22 elements specify horizontal and vertical scaling. And
141     finally, the \c m21 and \c m12 elements specify horizontal and
142     vertical \e shearing.
143 
144     QMatrix transforms a point in the plane to another point using the
145     following formulas:
146 
147     \snippet code/src_gui_painting_qmatrix.cpp 0
148 
149     The point \e (x, y) is the original point, and \e (x', y') is the
150     transformed point. \e (x', y') can be transformed back to \e (x,
151     y) by performing the same operation on the inverted() matrix.
152 
153     The various matrix elements can be set when constructing the
154     matrix, or by using the setMatrix() function later on. They can also
155     be manipulated using the translate(), rotate(), scale() and
156     shear() convenience functions, The currently set values can be
157     retrieved using the m11(), m12(), m21(), m22(), dx() and dy()
158     functions.
159 
160     Translation is the simplest transformation. Setting \c dx and \c
161     dy will move the coordinate system \c dx units along the X axis
162     and \c dy units along the Y axis.  Scaling can be done by setting
163     \c m11 and \c m22. For example, setting \c m11 to 2 and \c m22 to
164     1.5 will double the height and increase the width by 50%.  The
165     identity matrix has \c m11 and \c m22 set to 1 (all others are set
166     to 0) mapping a point to itself. Shearing is controlled by \c m12
167     and \c m21. Setting these elements to values different from zero
168     will twist the coordinate system. Rotation is achieved by
169     carefully setting both the shearing factors and the scaling
170     factors.
171 
172     Here's the combined transformations example using basic matrix
173     operations:
174 
175     \table 100%
176     \row
177     \li \inlineimage qmatrix-combinedtransformation.png
178     \li
179     \snippet matrix/matrix.cpp 2
180     \endtable
181 
182     \sa QPainter, QTransform, {Coordinate System},
183         {painting/affine}{Affine Transformations Example}, {Transformations Example}
184 */
185 
186 
187 // some defines to inline some code
188 #define MAPDOUBLE(x, y, nx, ny) \
189 { \
190     qreal fx = x; \
191     qreal fy = y; \
192     nx = _m11*fx + _m21*fy + _dx; \
193     ny = _m12*fx + _m22*fy + _dy; \
194 }
195 
196 #define MAPINT(x, y, nx, ny) \
197 { \
198     qreal fx = x; \
199     qreal fy = y; \
200     nx = qRound(_m11*fx + _m21*fy + _dx); \
201     ny = qRound(_m12*fx + _m22*fy + _dy); \
202 }
203 
204 /*****************************************************************************
205   QMatrix member functions
206  *****************************************************************************/
207 /*!
208     \fn QMatrix::QMatrix(Qt::Initialization)
209     \internal
210 */
211 
212 /*!
213     Constructs an identity matrix.
214 
215     All elements are set to zero except \c m11 and \c m22 (specifying
216     the scale), which are set to 1.
217 
218     \sa reset()
219 */
220 
QMatrix()221 QMatrix::QMatrix()
222     : _m11(1.)
223     , _m12(0.)
224     , _m21(0.)
225     , _m22(1.)
226     , _dx(0.)
227     , _dy(0.)
228 {
229 }
230 
231 /*!
232     Constructs a matrix with the elements, \a m11, \a m12, \a m21, \a
233     m22, \a dx and \a dy.
234 
235     \sa setMatrix()
236 */
237 
QMatrix(qreal m11,qreal m12,qreal m21,qreal m22,qreal dx,qreal dy)238 QMatrix::QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy)
239     : _m11(m11)
240     , _m12(m12)
241     , _m21(m21)
242     , _m22(m22)
243     , _dx(dx)
244     , _dy(dy)
245 {
246 }
247 
248 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
249 /*!
250      Constructs a matrix that is a copy of the given \a matrix.
251  */
QMatrix(const QMatrix & matrix)252 QMatrix::QMatrix(const QMatrix &matrix) noexcept
253     : _m11(matrix._m11)
254     , _m12(matrix._m12)
255     , _m21(matrix._m21)
256     , _m22(matrix._m22)
257     , _dx(matrix._dx)
258     , _dy(matrix._dy)
259 {
260 }
261 #endif
262 
263 /*!
264     Sets the matrix elements to the specified values, \a m11, \a m12,
265     \a m21, \a m22, \a dx and \a dy.
266 
267     Note that this function replaces the previous values. QMatrix
268     provide the translate(), rotate(), scale() and shear() convenience
269     functions to manipulate the various matrix elements based on the
270     currently defined coordinate system.
271 
272     \sa QMatrix()
273 */
274 
setMatrix(qreal m11,qreal m12,qreal m21,qreal m22,qreal dx,qreal dy)275 void QMatrix::setMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy)
276 {
277     _m11 = m11;
278     _m12 = m12;
279     _m21 = m21;
280     _m22 = m22;
281     _dx  = dx;
282     _dy  = dy;
283 }
284 
285 
286 /*!
287     \fn qreal QMatrix::m11() const
288 
289     Returns the horizontal scaling factor.
290 
291     \sa scale(), {QMatrix#Basic Matrix Operations}{Basic Matrix
292     Operations}
293 */
294 
295 /*!
296     \fn qreal QMatrix::m12() const
297 
298     Returns the vertical shearing factor.
299 
300     \sa shear(), {QMatrix#Basic Matrix Operations}{Basic Matrix
301     Operations}
302 */
303 
304 /*!
305     \fn qreal QMatrix::m21() const
306 
307     Returns the horizontal shearing factor.
308 
309     \sa shear(), {QMatrix#Basic Matrix Operations}{Basic Matrix
310     Operations}
311 */
312 
313 /*!
314     \fn qreal QMatrix::m22() const
315 
316     Returns the vertical scaling factor.
317 
318     \sa scale(), {QMatrix#Basic Matrix Operations}{Basic Matrix
319     Operations}
320 */
321 
322 /*!
323     \fn qreal QMatrix::dx() const
324 
325     Returns the horizontal translation factor.
326 
327     \sa translate(), {QMatrix#Basic Matrix Operations}{Basic Matrix
328     Operations}
329 */
330 
331 /*!
332     \fn qreal QMatrix::dy() const
333 
334     Returns the vertical translation factor.
335 
336     \sa translate(), {QMatrix#Basic Matrix Operations}{Basic Matrix
337     Operations}
338 */
339 
340 
341 /*!
342     Maps the given coordinates \a x and \a y into the coordinate
343     system defined by this matrix. The resulting values are put in *\a
344     tx and *\a ty, respectively.
345 
346     The coordinates are transformed using the following formulas:
347 
348     \snippet code/src_gui_painting_qmatrix.cpp 1
349 
350     The point (x, y) is the original point, and (x', y') is the
351     transformed point.
352 
353     \sa {QMatrix#Basic Matrix Operations}{Basic Matrix Operations}
354 */
355 
map(qreal x,qreal y,qreal * tx,qreal * ty) const356 void QMatrix::map(qreal x, qreal y, qreal *tx, qreal *ty) const
357 {
358     MAPDOUBLE(x, y, *tx, *ty);
359 }
360 
361 
362 
363 /*!
364     \overload
365 
366     Maps the given coordinates \a x and \a y into the coordinate
367     system defined by this matrix. The resulting values are put in *\a
368     tx and *\a ty, respectively. Note that the transformed coordinates
369     are rounded to the nearest integer.
370 */
371 
map(int x,int y,int * tx,int * ty) const372 void QMatrix::map(int x, int y, int *tx, int *ty) const
373 {
374     MAPINT(x, y, *tx, *ty);
375 }
376 
mapRect(const QRect & rect) const377 QRect QMatrix::mapRect(const QRect &rect) const
378 {
379     QRect result;
380     if (_m12 == 0.0F && _m21 == 0.0F) {
381         int x = qRound(_m11*rect.x() + _dx);
382         int y = qRound(_m22*rect.y() + _dy);
383         int w = qRound(_m11*rect.width());
384         int h = qRound(_m22*rect.height());
385         if (w < 0) {
386             w = -w;
387             x -= w;
388         }
389         if (h < 0) {
390             h = -h;
391             y -= h;
392         }
393         result = QRect(x, y, w, h);
394     } else {
395         // see mapToPolygon for explanations of the algorithm.
396         qreal x0, y0;
397         qreal x, y;
398         MAPDOUBLE(rect.left(), rect.top(), x0, y0);
399         qreal xmin = x0;
400         qreal ymin = y0;
401         qreal xmax = x0;
402         qreal ymax = y0;
403         MAPDOUBLE(rect.right() + 1, rect.top(), x, y);
404         xmin = qMin(xmin, x);
405         ymin = qMin(ymin, y);
406         xmax = qMax(xmax, x);
407         ymax = qMax(ymax, y);
408         MAPDOUBLE(rect.right() + 1, rect.bottom() + 1, x, y);
409         xmin = qMin(xmin, x);
410         ymin = qMin(ymin, y);
411         xmax = qMax(xmax, x);
412         ymax = qMax(ymax, y);
413         MAPDOUBLE(rect.left(), rect.bottom() + 1, x, y);
414         xmin = qMin(xmin, x);
415         ymin = qMin(ymin, y);
416         xmax = qMax(xmax, x);
417         ymax = qMax(ymax, y);
418         result = QRect(qRound(xmin), qRound(ymin), qRound(xmax)-qRound(xmin), qRound(ymax)-qRound(ymin));
419     }
420     return result;
421 }
422 
423 /*!
424     \fn QRectF QMatrix::mapRect(const QRectF &rectangle) const
425 
426     Creates and returns a QRectF object that is a copy of the given \a
427     rectangle, mapped into the coordinate system defined by this
428     matrix.
429 
430     The rectangle's coordinates are transformed using the following
431     formulas:
432 
433     \snippet code/src_gui_painting_qmatrix.cpp 2
434 
435     If rotation or shearing has been specified, this function returns
436     the \e bounding rectangle. To retrieve the exact region the given
437     \a rectangle maps to, use the mapToPolygon() function instead.
438 
439     \sa mapToPolygon(), {QMatrix#Basic Matrix Operations}{Basic Matrix
440     Operations}
441 */
mapRect(const QRectF & rect) const442 QRectF QMatrix::mapRect(const QRectF &rect) const
443 {
444     QRectF result;
445     if (_m12 == 0.0F && _m21 == 0.0F) {
446         qreal x = _m11*rect.x() + _dx;
447         qreal y = _m22*rect.y() + _dy;
448         qreal w = _m11*rect.width();
449         qreal h = _m22*rect.height();
450         if (w < 0) {
451             w = -w;
452             x -= w;
453         }
454         if (h < 0) {
455             h = -h;
456             y -= h;
457         }
458         result = QRectF(x, y, w, h);
459     } else {
460         qreal x0, y0;
461         qreal x, y;
462         MAPDOUBLE(rect.x(), rect.y(), x0, y0);
463         qreal xmin = x0;
464         qreal ymin = y0;
465         qreal xmax = x0;
466         qreal ymax = y0;
467         MAPDOUBLE(rect.x() + rect.width(), rect.y(), x, y);
468         xmin = qMin(xmin, x);
469         ymin = qMin(ymin, y);
470         xmax = qMax(xmax, x);
471         ymax = qMax(ymax, y);
472         MAPDOUBLE(rect.x() + rect.width(), rect.y() + rect.height(), x, y);
473         xmin = qMin(xmin, x);
474         ymin = qMin(ymin, y);
475         xmax = qMax(xmax, x);
476         ymax = qMax(ymax, y);
477         MAPDOUBLE(rect.x(), rect.y() + rect.height(), x, y);
478         xmin = qMin(xmin, x);
479         ymin = qMin(ymin, y);
480         xmax = qMax(xmax, x);
481         ymax = qMax(ymax, y);
482         result = QRectF(xmin, ymin, xmax-xmin, ymax - ymin);
483     }
484     return result;
485 }
486 
487 /*!
488     \fn QRect QMatrix::mapRect(const QRect &rectangle) const
489     \overload
490 
491     Creates and returns a QRect object that is a copy of the given \a
492     rectangle, mapped into the coordinate system defined by this
493     matrix. Note that the transformed coordinates are rounded to the
494     nearest integer.
495 */
496 
497 
498 /*!
499     \fn QPoint operator*(const QPoint &point, const QMatrix &matrix)
500     \relates QMatrix
501 
502     This is the same as \a{matrix}.map(\a{point}).
503 
504     \sa QMatrix::map()
505 */
506 
map(const QPoint & p) const507 QPoint QMatrix::map(const QPoint &p) const
508 {
509     qreal fx = p.x();
510     qreal fy = p.y();
511     return QPoint(qRound(_m11*fx + _m21*fy + _dx),
512                    qRound(_m12*fx + _m22*fy + _dy));
513 }
514 
515 /*!
516     \fn QPointF operator*(const QPointF &point, const QMatrix &matrix)
517     \relates QMatrix
518 
519     Same as \a{matrix}.map(\a{point}).
520 
521     \sa QMatrix::map()
522 */
523 
524 /*!
525     \overload
526 
527     Creates and returns a QPointF object that is a copy of the given
528     \a point, mapped into the coordinate system defined by this
529     matrix.
530 */
map(const QPointF & point) const531 QPointF QMatrix::map(const QPointF &point) const
532 {
533     qreal fx = point.x();
534     qreal fy = point.y();
535     return QPointF(_m11*fx + _m21*fy + _dx, _m12*fx + _m22*fy + _dy);
536 }
537 
538 /*!
539     \fn QPoint QMatrix::map(const QPoint &point) const
540     \overload
541 
542     Creates and returns a QPoint object that is a copy of the given \a
543     point, mapped into the coordinate system defined by this
544     matrix. Note that the transformed coordinates are rounded to the
545     nearest integer.
546 */
547 
548 /*!
549     \fn QLineF operator*(const QLineF &line, const QMatrix &matrix)
550     \relates QMatrix
551 
552     This is the same as \a{matrix}.map(\a{line}).
553 
554     \sa QMatrix::map()
555 */
556 
557 /*!
558     \fn QLine operator*(const QLine &line, const QMatrix &matrix)
559     \relates QMatrix
560 
561     This is the same as \a{matrix}.map(\a{line}).
562 
563     \sa QMatrix::map()
564 */
565 
566 /*!
567     \overload
568 
569     Creates and returns a QLineF object that is a copy of the given \a
570     line, mapped into the coordinate system defined by this matrix.
571 */
map(const QLineF & line) const572 QLineF QMatrix::map(const QLineF &line) const
573 {
574     return QLineF(map(line.p1()), map(line.p2()));
575 }
576 
577 /*!
578     \overload
579 
580     Creates and returns a QLine object that is a copy of the given \a
581     line, mapped into the coordinate system defined by this matrix.
582     Note that the transformed coordinates are rounded to the nearest
583     integer.
584 */
map(const QLine & line) const585 QLine QMatrix::map(const QLine &line) const
586 {
587     return QLine(map(line.p1()), map(line.p2()));
588 }
589 
590 /*!
591     \fn QPolygonF operator *(const QPolygonF &polygon, const QMatrix &matrix)
592     \relates QMatrix
593 
594     This is the same as \a{matrix}.map(\a{polygon}).
595 
596     \sa QMatrix::map()
597 */
598 
599 /*!
600     \fn QPolygon operator*(const QPolygon &polygon, const QMatrix &matrix)
601     \relates QMatrix
602 
603     This is the same as \a{matrix}.map(\a{polygon}).
604 
605     \sa QMatrix::map()
606 */
607 
map(const QPolygon & a) const608 QPolygon QMatrix::map(const QPolygon &a) const
609 {
610     int size = a.size();
611     int i;
612     QPolygon p(size);
613     const QPoint *da = a.constData();
614     QPoint *dp = p.data();
615     for(i = 0; i < size; i++) {
616         MAPINT(da[i].x(), da[i].y(), dp[i].rx(), dp[i].ry());
617     }
618     return p;
619 }
620 
621 /*!
622     \fn QPolygonF QMatrix::map(const QPolygonF &polygon) const
623     \overload
624 
625     Creates and returns a QPolygonF object that is a copy of the given
626     \a polygon, mapped into the coordinate system defined by this
627     matrix.
628 */
map(const QPolygonF & a) const629 QPolygonF QMatrix::map(const QPolygonF &a) const
630 {
631     int size = a.size();
632     int i;
633     QPolygonF p(size);
634     const QPointF *da = a.constData();
635     QPointF *dp = p.data();
636     for(i = 0; i < size; i++) {
637         MAPDOUBLE(da[i].xp, da[i].yp, dp[i].xp, dp[i].yp);
638     }
639     return p;
640 }
641 
642 /*!
643     \fn QPolygon QMatrix::map(const QPolygon &polygon) const
644     \overload
645 
646     Creates and returns a QPolygon object that is a copy of the given
647     \a polygon, mapped into the coordinate system defined by this
648     matrix. Note that the transformed coordinates are rounded to the
649     nearest integer.
650 */
651 
652 /*!
653     \fn QRegion operator*(const QRegion &region, const QMatrix &matrix)
654     \relates QMatrix
655 
656     This is the same as \a{matrix}.map(\a{region}).
657 
658     \sa QMatrix::map()
659 */
660 
661 extern QPainterPath qt_regionToPath(const QRegion &region);
662 
663 /*!
664     \fn QRegion QMatrix::map(const QRegion &region) const
665     \overload
666 
667     Creates and returns a QRegion object that is a copy of the given
668     \a region, mapped into the coordinate system defined by this matrix.
669 
670     Calling this method can be rather expensive if rotations or
671     shearing are used.
672 */
map(const QRegion & r) const673 QRegion QMatrix::map(const QRegion &r) const
674 {
675     if (_m11 == 1.0 && _m22 == 1.0 && _m12 == 0.0 && _m21 == 0.0) { // translate or identity
676         if (_dx == 0.0 && _dy == 0.0) // Identity
677             return r;
678         QRegion copy(r);
679         copy.translate(qRound(_dx), qRound(_dy));
680         return copy;
681     }
682 
683     QPainterPath p = map(qt_regionToPath(r));
684     return p.toFillPolygon(QTransform()).toPolygon();
685 }
686 
687 /*!
688     \fn QPainterPath operator *(const QPainterPath &path, const QMatrix &matrix)
689     \relates QMatrix
690 
691     This is the same as \a{matrix}.map(\a{path}).
692 
693     \sa QMatrix::map()
694 */
695 
696 /*!
697     \overload
698 
699     Creates and returns a QPainterPath object that is a copy of the
700     given \a path, mapped into the coordinate system defined by this
701     matrix.
702 */
map(const QPainterPath & path) const703 QPainterPath QMatrix::map(const QPainterPath &path) const
704 {
705     if (path.isEmpty())
706         return QPainterPath();
707 
708     QPainterPath copy = path;
709 
710     // Translate or identity
711     if (_m11 == 1.0 && _m22 == 1.0 && _m12 == 0.0 && _m21 == 0.0) {
712 
713         // Translate
714         if (_dx != 0.0 || _dy != 0.0) {
715             copy.detach();
716             for (int i=0; i<path.elementCount(); ++i) {
717                 QPainterPath::Element &e = copy.d_ptr->elements[i];
718                 e.x += _dx;
719                 e.y += _dy;
720             }
721         }
722 
723     // Full xform
724     } else {
725         copy.detach();
726         for (int i=0; i<path.elementCount(); ++i) {
727             QPainterPath::Element &e = copy.d_ptr->elements[i];
728             qreal fx = e.x, fy = e.y;
729             e.x = _m11*fx + _m21*fy + _dx;
730             e.y =  _m12*fx + _m22*fy + _dy;
731         }
732     }
733 
734     return copy;
735 }
736 
737 /*!
738     \fn QPolygon QMatrix::mapToPolygon(const QRect &rectangle) const
739 
740     Creates and returns a QPolygon representation of the given \a
741     rectangle, mapped into the coordinate system defined by this
742     matrix.
743 
744     The rectangle's coordinates are transformed using the following
745     formulas:
746 
747     \snippet code/src_gui_painting_qmatrix.cpp 3
748 
749     Polygons and rectangles behave slightly differently when
750     transformed (due to integer rounding), so
751     \c{matrix.map(QPolygon(rectangle))} is not always the same as
752     \c{matrix.mapToPolygon(rectangle)}.
753 
754     \sa mapRect(), {QMatrix#Basic Matrix Operations}{Basic Matrix
755     Operations}
756 */
mapToPolygon(const QRect & rect) const757 QPolygon QMatrix::mapToPolygon(const QRect &rect) const
758 {
759     QPolygon a(4);
760     qreal x[4], y[4];
761     if (_m12 == 0.0F && _m21 == 0.0F) {
762         x[0] = _m11*rect.x() + _dx;
763         y[0] = _m22*rect.y() + _dy;
764         qreal w = _m11*rect.width();
765         qreal h = _m22*rect.height();
766         if (w < 0) {
767             w = -w;
768             x[0] -= w;
769         }
770         if (h < 0) {
771             h = -h;
772             y[0] -= h;
773         }
774         x[1] = x[0]+w;
775         x[2] = x[1];
776         x[3] = x[0];
777         y[1] = y[0];
778         y[2] = y[0]+h;
779         y[3] = y[2];
780     } else {
781         qreal right = rect.x() + rect.width();
782         qreal bottom = rect.y() + rect.height();
783         MAPDOUBLE(rect.x(), rect.y(), x[0], y[0]);
784         MAPDOUBLE(right, rect.y(), x[1], y[1]);
785         MAPDOUBLE(right, bottom, x[2], y[2]);
786         MAPDOUBLE(rect.x(), bottom, x[3], y[3]);
787     }
788 #if 0
789     int i;
790     for(i = 0; i< 4; i++)
791         qDebug("coords(%d) = (%f/%f) (%d/%d)", i, x[i], y[i], qRound(x[i]), qRound(y[i]));
792     qDebug("width=%f, height=%f", qSqrt((x[1]-x[0])*(x[1]-x[0]) + (y[1]-y[0])*(y[1]-y[0])),
793             qSqrt((x[0]-x[3])*(x[0]-x[3]) + (y[0]-y[3])*(y[0]-y[3])));
794 #endif
795     // all coordinates are correctly, tranform to a pointarray
796     // (rounding to the next integer)
797     a.setPoints(4, qRound(x[0]), qRound(y[0]),
798                  qRound(x[1]), qRound(y[1]),
799                  qRound(x[2]), qRound(y[2]),
800                  qRound(x[3]), qRound(y[3]));
801     return a;
802 }
803 
804 /*!
805     Resets the matrix to an identity matrix, i.e. all elements are set
806     to zero, except \c m11 and \c m22 (specifying the scale) which are
807     set to 1.
808 
809     \sa QMatrix(), isIdentity(), {QMatrix#Basic Matrix
810     Operations}{Basic Matrix Operations}
811 */
812 
reset()813 void QMatrix::reset()
814 {
815     _m11 = _m22 = 1.0;
816     _m12 = _m21 = _dx = _dy = 0.0;
817 }
818 
819 /*!
820     \fn bool QMatrix::isIdentity() const
821 
822     Returns \c true if the matrix is the identity matrix, otherwise
823     returns \c false.
824 
825     \sa reset()
826 */
827 
828 /*!
829     Moves the coordinate system \a dx along the x axis and \a dy along
830     the y axis, and returns a reference to the matrix.
831 
832     \sa setMatrix()
833 */
834 
translate(qreal dx,qreal dy)835 QMatrix &QMatrix::translate(qreal dx, qreal dy)
836 {
837     _dx += dx*_m11 + dy*_m21;
838     _dy += dy*_m22 + dx*_m12;
839     return *this;
840 }
841 
842 /*!
843     \fn QMatrix &QMatrix::scale(qreal sx, qreal sy)
844 
845     Scales the coordinate system by \a sx horizontally and \a sy
846     vertically, and returns a reference to the matrix.
847 
848     \sa setMatrix()
849 */
850 
scale(qreal sx,qreal sy)851 QMatrix &QMatrix::scale(qreal sx, qreal sy)
852 {
853     _m11 *= sx;
854     _m12 *= sx;
855     _m21 *= sy;
856     _m22 *= sy;
857     return *this;
858 }
859 
860 /*!
861     Shears the coordinate system by \a sh horizontally and \a sv
862     vertically, and returns a reference to the matrix.
863 
864     \sa setMatrix()
865 */
866 
shear(qreal sh,qreal sv)867 QMatrix &QMatrix::shear(qreal sh, qreal sv)
868 {
869     qreal tm11 = sv*_m21;
870     qreal tm12 = sv*_m22;
871     qreal tm21 = sh*_m11;
872     qreal tm22 = sh*_m12;
873     _m11 += tm11;
874     _m12 += tm12;
875     _m21 += tm21;
876     _m22 += tm22;
877     return *this;
878 }
879 
880 const qreal deg2rad = qreal(0.017453292519943295769);        // pi/180
881 
882 /*!
883     \fn QMatrix &QMatrix::rotate(qreal degrees)
884 
885     Rotates the coordinate system the given \a degrees
886     counterclockwise.
887 
888     Note that if you apply a QMatrix to a point defined in widget
889     coordinates, the direction of the rotation will be clockwise
890     because the y-axis points downwards.
891 
892     Returns a reference to the matrix.
893 
894     \sa setMatrix()
895 */
896 
rotate(qreal a)897 QMatrix &QMatrix::rotate(qreal a)
898 {
899     qreal sina = 0;
900     qreal cosa = 0;
901     if (a == 90. || a == -270.)
902         sina = 1.;
903     else if (a == 270. || a == -90.)
904         sina = -1.;
905     else if (a == 180.)
906         cosa = -1.;
907     else{
908         qreal b = deg2rad*a;                        // convert to radians
909         sina = qSin(b);               // fast and convenient
910         cosa = qCos(b);
911     }
912     qreal tm11 = cosa*_m11 + sina*_m21;
913     qreal tm12 = cosa*_m12 + sina*_m22;
914     qreal tm21 = -sina*_m11 + cosa*_m21;
915     qreal tm22 = -sina*_m12 + cosa*_m22;
916     _m11 = tm11; _m12 = tm12;
917     _m21 = tm21; _m22 = tm22;
918     return *this;
919 }
920 
921 /*!
922     \fn bool QMatrix::isInvertible() const
923 
924     Returns \c true if the matrix is invertible, otherwise returns \c false.
925 
926     \sa inverted()
927 */
928 
929 /*!
930     \since 4.6
931     \fn qreal QMatrix::determinant() const
932 
933     Returns the matrix's determinant.
934 */
935 
936 /*!
937     Returns an inverted copy of this matrix.
938 
939     If the matrix is singular (not invertible), the returned matrix is
940     the identity matrix. If \a invertible is valid (i.e. not 0), its
941     value is set to true if the matrix is invertible, otherwise it is
942     set to false.
943 
944     \sa isInvertible()
945 */
946 
inverted(bool * invertible) const947 QMatrix QMatrix::inverted(bool *invertible) const
948 {
949     qreal dtr = determinant();
950     if (dtr == 0.0) {
951         if (invertible)
952             *invertible = false;                // singular matrix
953         return QMatrix(true);
954     }
955     else {                                        // invertible matrix
956         if (invertible)
957             *invertible = true;
958         qreal dinv = 1.0/dtr;
959         return QMatrix((_m22*dinv),        (-_m12*dinv),
960                        (-_m21*dinv), (_m11*dinv),
961                        ((_m21*_dy - _m22*_dx)*dinv),
962                        ((_m12*_dx - _m11*_dy)*dinv),
963                        true);
964     }
965 }
966 
967 
968 /*!
969     \fn bool QMatrix::operator==(const QMatrix &matrix) const
970 
971     Returns \c true if this matrix is equal to the given \a matrix,
972     otherwise returns \c false.
973 */
974 
operator ==(const QMatrix & m) const975 bool QMatrix::operator==(const QMatrix &m) const
976 {
977     return _m11 == m._m11 &&
978            _m12 == m._m12 &&
979            _m21 == m._m21 &&
980            _m22 == m._m22 &&
981            _dx == m._dx &&
982            _dy == m._dy;
983 }
984 
985 
986 /*!
987     \since 5.6
988     \relates QMatrix
989 
990     Returns the hash value for \a key, using
991     \a seed to seed the calculation.
992 */
qHash(const QMatrix & key,uint seed)993 uint qHash(const QMatrix &key, uint seed) noexcept
994 {
995     QtPrivate::QHashCombine hash;
996     seed = hash(seed, key.m11());
997     seed = hash(seed, key.m12());
998     seed = hash(seed, key.m21());
999     seed = hash(seed, key.m22());
1000     seed = hash(seed, key.dx());
1001     seed = hash(seed, key.dy());
1002     return seed;
1003 }
1004 
1005 /*!
1006     \fn bool QMatrix::operator!=(const QMatrix &matrix) const
1007 
1008     Returns \c true if this matrix is not equal to the given \a matrix,
1009     otherwise returns \c false.
1010 */
1011 
operator !=(const QMatrix & m) const1012 bool QMatrix::operator!=(const QMatrix &m) const
1013 {
1014     return _m11 != m._m11 ||
1015            _m12 != m._m12 ||
1016            _m21 != m._m21 ||
1017            _m22 != m._m22 ||
1018            _dx != m._dx ||
1019            _dy != m._dy;
1020 }
1021 
1022 /*!
1023     \fn QMatrix &QMatrix::operator *=(const QMatrix &matrix)
1024     \overload
1025 
1026     Returns the result of multiplying this matrix by the given \a
1027     matrix.
1028 */
1029 
operator *=(const QMatrix & m)1030 QMatrix &QMatrix::operator *=(const QMatrix &m)
1031 {
1032     qreal tm11 = _m11*m._m11 + _m12*m._m21;
1033     qreal tm12 = _m11*m._m12 + _m12*m._m22;
1034     qreal tm21 = _m21*m._m11 + _m22*m._m21;
1035     qreal tm22 = _m21*m._m12 + _m22*m._m22;
1036 
1037     qreal tdx  = _dx*m._m11  + _dy*m._m21 + m._dx;
1038     qreal tdy =  _dx*m._m12  + _dy*m._m22 + m._dy;
1039 
1040     _m11 = tm11; _m12 = tm12;
1041     _m21 = tm21; _m22 = tm22;
1042     _dx = tdx; _dy = tdy;
1043     return *this;
1044 }
1045 
1046 /*!
1047     \fn QMatrix QMatrix::operator *(const QMatrix &matrix) const
1048 
1049     Returns the result of multiplying this matrix by the given \a
1050     matrix.
1051 
1052     Note that matrix multiplication is not commutative, i.e. a*b !=
1053     b*a.
1054 */
1055 
operator *(const QMatrix & m) const1056 QMatrix QMatrix::operator *(const QMatrix &m) const
1057 {
1058     qreal tm11 = _m11*m._m11 + _m12*m._m21;
1059     qreal tm12 = _m11*m._m12 + _m12*m._m22;
1060     qreal tm21 = _m21*m._m11 + _m22*m._m21;
1061     qreal tm22 = _m21*m._m12 + _m22*m._m22;
1062 
1063     qreal tdx  = _dx*m._m11  + _dy*m._m21 + m._dx;
1064     qreal tdy =  _dx*m._m12  + _dy*m._m22 + m._dy;
1065     return QMatrix(tm11, tm12, tm21, tm22, tdx, tdy, true);
1066 }
1067 
1068 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1069 /*!
1070     Assigns the given \a matrix's values to this matrix.
1071 */
operator =(const QMatrix & matrix)1072 QMatrix &QMatrix::operator=(const QMatrix &matrix) noexcept
1073 {
1074     _m11 = matrix._m11;
1075     _m12 = matrix._m12;
1076     _m21 = matrix._m21;
1077     _m22 = matrix._m22;
1078     _dx  = matrix._dx;
1079     _dy  = matrix._dy;
1080     return *this;
1081 }
1082 #endif
1083 
1084 /*!
1085     \since 4.2
1086 
1087     Returns the matrix as a QVariant.
1088 */
operator QVariant() const1089 QMatrix::operator QVariant() const
1090 {
1091     return QVariant(QMetaType::QMatrix, this);
1092 }
1093 
operator *(const QPainterPath & p,const QMatrix & m)1094 Q_GUI_EXPORT QPainterPath operator *(const QPainterPath &p, const QMatrix &m)
1095 {
1096     return m.map(p);
1097 }
1098 
1099 
1100 /*****************************************************************************
1101   QMatrix stream functions
1102  *****************************************************************************/
1103 #ifndef QT_NO_DATASTREAM
1104 /*!
1105     \fn QDataStream &operator<<(QDataStream &stream, const QMatrix &matrix)
1106     \relates QMatrix
1107 
1108     Writes the given \a matrix to the given \a stream and returns a
1109     reference to the stream.
1110 
1111     \sa {Serializing Qt Data Types}
1112 */
1113 
operator <<(QDataStream & s,const QMatrix & m)1114 QDataStream &operator<<(QDataStream &s, const QMatrix &m)
1115 {
1116     if (s.version() == 1) {
1117         s << (float)m.m11() << (float)m.m12() << (float)m.m21()
1118           << (float)m.m22() << (float)m.dx()  << (float)m.dy();
1119     } else {
1120         s << double(m.m11())
1121           << double(m.m12())
1122           << double(m.m21())
1123           << double(m.m22())
1124           << double(m.dx())
1125           << double(m.dy());
1126     }
1127     return s;
1128 }
1129 
1130 /*!
1131     \fn QDataStream &operator>>(QDataStream &stream, QMatrix &matrix)
1132     \relates QMatrix
1133 
1134     Reads the given \a matrix from the given \a stream and returns a
1135     reference to the stream.
1136 
1137     \sa {Serializing Qt Data Types}
1138 */
1139 
operator >>(QDataStream & s,QMatrix & m)1140 QDataStream &operator>>(QDataStream &s, QMatrix &m)
1141 {
1142     if (s.version() == 1) {
1143         float m11, m12, m21, m22, dx, dy;
1144         s >> m11;  s >> m12;  s >> m21;  s >> m22;
1145         s >> dx;   s >> dy;
1146         m.setMatrix(m11, m12, m21, m22, dx, dy);
1147     }
1148     else {
1149         double m11, m12, m21, m22, dx, dy;
1150         s >> m11;
1151         s >> m12;
1152         s >> m21;
1153         s >> m22;
1154         s >> dx;
1155         s >> dy;
1156         m.setMatrix(m11, m12, m21, m22, dx, dy);
1157     }
1158     return s;
1159 }
1160 #endif // QT_NO_DATASTREAM
1161 
1162 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug dbg,const QMatrix & m)1163 QDebug operator<<(QDebug dbg, const QMatrix &m)
1164 {
1165     QDebugStateSaver saver(dbg);
1166     dbg.nospace() << "QMatrix("
1167                   << "11=" << m.m11()
1168                   << " 12=" << m.m12()
1169                   << " 21=" << m.m21()
1170                   << " 22=" << m.m22()
1171                   << " dx=" << m.dx()
1172                   << " dy=" << m.dy()
1173                   << ')';
1174     return dbg;
1175 }
1176 #endif
1177 
1178 /*!
1179     \fn bool qFuzzyCompare(const QMatrix& m1, const QMatrix& m2)
1180 
1181     \relates QMatrix
1182     \since 4.6
1183 
1184     \brief The qFuzzyCompare function is for comparing two matrices
1185     using a fuzziness factor.
1186 
1187     Returns \c true if \a m1 and \a m2 are equal, allowing for a small
1188     fuzziness factor for floating-point comparisons; false otherwise.
1189 */
1190 
1191 QT_END_NAMESPACE
1192