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

Last change on this file since 348 was 2, checked in by Dmitry A. Kuminov, 17 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