|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 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 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
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 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
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 |
|
52 QT_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 det() 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 {The 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, {The 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 |
|
218 QMatrix::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 |
|
235 QMatrix::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 */ |
|
249 QMatrix::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 |
|
271 void 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 |
|
352 void 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 |
|
368 void QMatrix::map(int x, int y, int *tx, int *ty) const |
|
369 { |
|
370 MAPINT(x, y, *tx, *ty); |
|
371 } |
|
372 |
|
373 QRect 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 */ |
|
438 QRectF 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 |
|
503 QPoint 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 */ |
|
527 QPointF 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 */ |
|
568 QLineF 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 */ |
|
581 QLine 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 |
|
604 QPolygon 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 */ |
|
625 QPolygonF 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 ®ion, 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 |
|
657 extern QPainterPath qt_regionToPath(const QRegion ®ion); |
|
658 |
|
659 /*! |
|
660 \fn QRegion QMatrix::map(const QRegion ®ion) 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 */ |
|
669 QRegion 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 */ |
|
699 QPainterPath 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 |
|
743 QRegion 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 */ |
|
789 QPolygon 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 |
|
845 void 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 |
|
867 QMatrix &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 |
|
883 QMatrix &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 |
|
899 QMatrix &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 |
|
912 const 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 |
|
929 QMatrix &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 \fn qreal QMatrix::det() const |
|
963 |
|
964 Returns the matrix's determinant. |
|
965 */ |
|
966 |
|
967 /*! |
|
968 \fn QMatrix QMatrix::invert(bool *invertible) const |
|
969 |
|
970 Returns an inverted copy of this matrix. |
|
971 |
|
972 Use the inverted() function instead. |
|
973 */ |
|
974 |
|
975 /*! |
|
976 Returns an inverted copy of this matrix. |
|
977 |
|
978 If the matrix is singular (not invertible), the returned matrix is |
|
979 the identity matrix. If \a invertible is valid (i.e. not 0), its |
|
980 value is set to true if the matrix is invertible, otherwise it is |
|
981 set to false. |
|
982 |
|
983 \sa isInvertible() |
|
984 */ |
|
985 |
|
986 QMatrix QMatrix::inverted(bool *invertible) const |
|
987 { |
|
988 qreal determinant = det(); |
|
989 if (determinant == 0.0) { |
|
990 if (invertible) |
|
991 *invertible = false; // singular matrix |
|
992 return QMatrix(true); |
|
993 } |
|
994 else { // invertible matrix |
|
995 if (invertible) |
|
996 *invertible = true; |
|
997 qreal dinv = 1.0/determinant; |
|
998 return QMatrix((_m22*dinv), (-_m12*dinv), |
|
999 (-_m21*dinv), (_m11*dinv), |
|
1000 ((_m21*_dy - _m22*_dx)*dinv), |
|
1001 ((_m12*_dx - _m11*_dy)*dinv), |
|
1002 true); |
|
1003 } |
|
1004 } |
|
1005 |
|
1006 |
|
1007 /*! |
|
1008 \fn bool QMatrix::operator==(const QMatrix &matrix) const |
|
1009 |
|
1010 Returns true if this matrix is equal to the given \a matrix, |
|
1011 otherwise returns false. |
|
1012 */ |
|
1013 |
|
1014 bool QMatrix::operator==(const QMatrix &m) const |
|
1015 { |
|
1016 return _m11 == m._m11 && |
|
1017 _m12 == m._m12 && |
|
1018 _m21 == m._m21 && |
|
1019 _m22 == m._m22 && |
|
1020 _dx == m._dx && |
|
1021 _dy == m._dy; |
|
1022 } |
|
1023 |
|
1024 /*! |
|
1025 \fn bool QMatrix::operator!=(const QMatrix &matrix) const |
|
1026 |
|
1027 Returns true if this matrix is not equal to the given \a matrix, |
|
1028 otherwise returns false. |
|
1029 */ |
|
1030 |
|
1031 bool QMatrix::operator!=(const QMatrix &m) const |
|
1032 { |
|
1033 return _m11 != m._m11 || |
|
1034 _m12 != m._m12 || |
|
1035 _m21 != m._m21 || |
|
1036 _m22 != m._m22 || |
|
1037 _dx != m._dx || |
|
1038 _dy != m._dy; |
|
1039 } |
|
1040 |
|
1041 /*! |
|
1042 \fn QMatrix &QMatrix::operator *=(const QMatrix &matrix) |
|
1043 \overload |
|
1044 |
|
1045 Returns the result of multiplying this matrix by the given \a |
|
1046 matrix. |
|
1047 */ |
|
1048 |
|
1049 QMatrix &QMatrix::operator *=(const QMatrix &m) |
|
1050 { |
|
1051 qreal tm11 = _m11*m._m11 + _m12*m._m21; |
|
1052 qreal tm12 = _m11*m._m12 + _m12*m._m22; |
|
1053 qreal tm21 = _m21*m._m11 + _m22*m._m21; |
|
1054 qreal tm22 = _m21*m._m12 + _m22*m._m22; |
|
1055 |
|
1056 qreal tdx = _dx*m._m11 + _dy*m._m21 + m._dx; |
|
1057 qreal tdy = _dx*m._m12 + _dy*m._m22 + m._dy; |
|
1058 |
|
1059 _m11 = tm11; _m12 = tm12; |
|
1060 _m21 = tm21; _m22 = tm22; |
|
1061 _dx = tdx; _dy = tdy; |
|
1062 return *this; |
|
1063 } |
|
1064 |
|
1065 /*! |
|
1066 \fn QMatrix QMatrix::operator *(const QMatrix &matrix) const |
|
1067 |
|
1068 Returns the result of multiplying this matrix by the given \a |
|
1069 matrix. |
|
1070 |
|
1071 Note that matrix multiplication is not commutative, i.e. a*b != |
|
1072 b*a. |
|
1073 */ |
|
1074 |
|
1075 QMatrix QMatrix::operator *(const QMatrix &m) const |
|
1076 { |
|
1077 qreal tm11 = _m11*m._m11 + _m12*m._m21; |
|
1078 qreal tm12 = _m11*m._m12 + _m12*m._m22; |
|
1079 qreal tm21 = _m21*m._m11 + _m22*m._m21; |
|
1080 qreal tm22 = _m21*m._m12 + _m22*m._m22; |
|
1081 |
|
1082 qreal tdx = _dx*m._m11 + _dy*m._m21 + m._dx; |
|
1083 qreal tdy = _dx*m._m12 + _dy*m._m22 + m._dy; |
|
1084 return QMatrix(tm11, tm12, tm21, tm22, tdx, tdy, true); |
|
1085 } |
|
1086 |
|
1087 /*! |
|
1088 Assigns the given \a matrix's values to this matrix. |
|
1089 */ |
|
1090 QMatrix &QMatrix::operator=(const QMatrix &matrix) |
|
1091 { |
|
1092 _m11 = matrix._m11; |
|
1093 _m12 = matrix._m12; |
|
1094 _m21 = matrix._m21; |
|
1095 _m22 = matrix._m22; |
|
1096 _dx = matrix._dx; |
|
1097 _dy = matrix._dy; |
|
1098 return *this; |
|
1099 } |
|
1100 |
|
1101 /*! |
|
1102 \since 4.2 |
|
1103 |
|
1104 Returns the matrix as a QVariant. |
|
1105 */ |
|
1106 QMatrix::operator QVariant() const |
|
1107 { |
|
1108 return QVariant(QVariant::Matrix, this); |
|
1109 } |
|
1110 |
|
1111 Q_GUI_EXPORT QPainterPath operator *(const QPainterPath &p, const QMatrix &m) |
|
1112 { |
|
1113 return m.map(p); |
|
1114 } |
|
1115 |
|
1116 |
|
1117 /***************************************************************************** |
|
1118 QMatrix stream functions |
|
1119 *****************************************************************************/ |
|
1120 #ifndef QT_NO_DATASTREAM |
|
1121 /*! |
|
1122 \fn QDataStream &operator<<(QDataStream &stream, const QMatrix &matrix) |
|
1123 \relates QMatrix |
|
1124 |
|
1125 Writes the given \a matrix to the given \a stream and returns a |
|
1126 reference to the stream. |
|
1127 |
|
1128 \sa {Format of the QDataStream Operators} |
|
1129 */ |
|
1130 |
|
1131 QDataStream &operator<<(QDataStream &s, const QMatrix &m) |
|
1132 { |
|
1133 if (s.version() == 1) { |
|
1134 s << (float)m.m11() << (float)m.m12() << (float)m.m21() |
|
1135 << (float)m.m22() << (float)m.dx() << (float)m.dy(); |
|
1136 } else { |
|
1137 s << double(m.m11()) |
|
1138 << double(m.m12()) |
|
1139 << double(m.m21()) |
|
1140 << double(m.m22()) |
|
1141 << double(m.dx()) |
|
1142 << double(m.dy()); |
|
1143 } |
|
1144 return s; |
|
1145 } |
|
1146 |
|
1147 /*! |
|
1148 \fn QDataStream &operator>>(QDataStream &stream, QMatrix &matrix) |
|
1149 \relates QMatrix |
|
1150 |
|
1151 Reads the given \a matrix from the given \a stream and returns a |
|
1152 reference to the stream. |
|
1153 |
|
1154 \sa {Format of the QDataStream Operators} |
|
1155 */ |
|
1156 |
|
1157 QDataStream &operator>>(QDataStream &s, QMatrix &m) |
|
1158 { |
|
1159 if (s.version() == 1) { |
|
1160 float m11, m12, m21, m22, dx, dy; |
|
1161 s >> m11; s >> m12; s >> m21; s >> m22; |
|
1162 s >> dx; s >> dy; |
|
1163 m.setMatrix(m11, m12, m21, m22, dx, dy); |
|
1164 } |
|
1165 else { |
|
1166 double m11, m12, m21, m22, dx, dy; |
|
1167 s >> m11; |
|
1168 s >> m12; |
|
1169 s >> m21; |
|
1170 s >> m22; |
|
1171 s >> dx; |
|
1172 s >> dy; |
|
1173 m.setMatrix(m11, m12, m21, m22, dx, dy); |
|
1174 } |
|
1175 return s; |
|
1176 } |
|
1177 #endif // QT_NO_DATASTREAM |
|
1178 |
|
1179 #ifndef QT_NO_DEBUG_STREAM |
|
1180 QDebug operator<<(QDebug dbg, const QMatrix &m) |
|
1181 { |
|
1182 dbg.nospace() << "QMatrix(" |
|
1183 << "11=" << m.m11() |
|
1184 << " 12=" << m.m12() |
|
1185 << " 21=" << m.m21() |
|
1186 << " 22=" << m.m22() |
|
1187 << " dx=" << m.dx() |
|
1188 << " dy=" << m.dy() |
|
1189 << ')'; |
|
1190 return dbg.space(); |
|
1191 } |
|
1192 #endif |
|
1193 |
|
1194 /*! |
|
1195 \fn QRect QMatrix::map(const QRect &rect) const |
|
1196 \compat |
|
1197 |
|
1198 Creates and returns a QRect object that is a copy of the given |
|
1199 rectangle, mapped into the coordinate system defined by this |
|
1200 matrix. |
|
1201 |
|
1202 Use the mapRect() function instead. |
|
1203 */ |
|
1204 |
|
1205 |
|
1206 /*! |
|
1207 \fn bool qFuzzyCompare(const QMatrix& m1, const QMatrix& m2) |
|
1208 |
|
1209 \relates QMatrix |
|
1210 \since 4.6 |
|
1211 |
|
1212 \brief The qFuzzyCompare function is for comparing two matrices |
|
1213 using a fuzziness factor. |
|
1214 |
|
1215 Returns true if \a m1 and \a m2 are equal, allowing for a small |
|
1216 fuzziness factor for floating-point comparisons; false otherwise. |
|
1217 */ |
|
1218 |
|
1219 QT_END_NAMESPACE |