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

Last change on this file since 477 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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