source: trunk/src/gui/painting/qmatrix.cpp@ 846

Last change on this file since 846 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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