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
54QT_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
221QMatrix::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
238QMatrix::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 */
252QMatrix::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
275void 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
356void 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
372void QMatrix::map(int x, int y, int *tx, int *ty) const
373{
374 MAPINT(x, y, *tx, *ty);
375}
376
377QRect QMatrix::mapRect(const QRect &rect) const
378{
379 QRect result;
380 if (_m12 == 0.0F && _m21 == 0.0F) {
381 int x = qRound(d: _m11*rect.x() + _dx);
382 int y = qRound(d: _m22*rect.y() + _dy);
383 int w = qRound(d: _m11*rect.width());
384 int h = qRound(d: _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(a: xmin, b: x);
405 ymin = qMin(a: ymin, b: y);
406 xmax = qMax(a: xmax, b: x);
407 ymax = qMax(a: ymax, b: y);
408 MAPDOUBLE(rect.right() + 1, rect.bottom() + 1, x, y);
409 xmin = qMin(a: xmin, b: x);
410 ymin = qMin(a: ymin, b: y);
411 xmax = qMax(a: xmax, b: x);
412 ymax = qMax(a: ymax, b: y);
413 MAPDOUBLE(rect.left(), rect.bottom() + 1, x, y);
414 xmin = qMin(a: xmin, b: x);
415 ymin = qMin(a: ymin, b: y);
416 xmax = qMax(a: xmax, b: x);
417 ymax = qMax(a: ymax, b: y);
418 result = QRect(qRound(d: xmin), qRound(d: ymin), qRound(d: xmax)-qRound(d: xmin), qRound(d: ymax)-qRound(d: 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*/
442QRectF 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(a: xmin, b: x);
469 ymin = qMin(a: ymin, b: y);
470 xmax = qMax(a: xmax, b: x);
471 ymax = qMax(a: ymax, b: y);
472 MAPDOUBLE(rect.x() + rect.width(), rect.y() + rect.height(), x, y);
473 xmin = qMin(a: xmin, b: x);
474 ymin = qMin(a: ymin, b: y);
475 xmax = qMax(a: xmax, b: x);
476 ymax = qMax(a: ymax, b: y);
477 MAPDOUBLE(rect.x(), rect.y() + rect.height(), x, y);
478 xmin = qMin(a: xmin, b: x);
479 ymin = qMin(a: ymin, b: y);
480 xmax = qMax(a: xmax, b: x);
481 ymax = qMax(a: ymax, b: 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
507QPoint QMatrix::map(const QPoint &p) const
508{
509 qreal fx = p.x();
510 qreal fy = p.y();
511 return QPoint(qRound(d: _m11*fx + _m21*fy + _dx),
512 qRound(d: _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*/
531QPointF 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*/
572QLineF QMatrix::map(const QLineF &line) const
573{
574 return QLineF(map(point: line.p1()), map(point: 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*/
585QLine QMatrix::map(const QLine &line) const
586{
587 return QLine(map(p: line.p1()), map(p: 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
608QPolygon 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*/
629QPolygonF 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
661extern 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*/
673QRegion 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(dx: qRound(d: _dx), dy: qRound(d: _dy));
680 return copy;
681 }
682
683 QPainterPath p = map(p: qt_regionToPath(region: r));
684 return p.toFillPolygon(matrix: 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*/
703QPainterPath 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*/
757QPolygon 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(nPoints: 4, firstx: qRound(d: x[0]), firsty: qRound(d: y[0]),
798 qRound(d: x[1]), qRound(d: y[1]),
799 qRound(d: x[2]), qRound(d: y[2]),
800 qRound(d: x[3]), qRound(d: 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
813void 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
835QMatrix &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
851QMatrix &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
867QMatrix &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
880const 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
897QMatrix &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(v: b); // fast and convenient
910 cosa = qCos(v: 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
947QMatrix 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
975bool 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*/
993uint 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
1012bool 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
1030QMatrix &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
1056QMatrix 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*/
1072QMatrix &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*/
1089QMatrix::operator QVariant() const
1090{
1091 return QVariant(QMetaType::QMatrix, this);
1092}
1093
1094Q_GUI_EXPORT QPainterPath operator *(const QPainterPath &p, const QMatrix &m)
1095{
1096 return m.map(path: 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
1114QDataStream &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
1140QDataStream &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
1163QDebug 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
1191QT_END_NAMESPACE
1192

source code of qtbase/src/gui/painting/qmatrix.cpp