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