1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtGui module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | #ifndef QTRANSFORM_H |
40 | #define QTRANSFORM_H |
41 | |
42 | #include <QtGui/qtguiglobal.h> |
43 | #include <QtGui/qmatrix.h> |
44 | #include <QtGui/qpolygon.h> |
45 | #include <QtGui/qregion.h> |
46 | #include <QtGui/qwindowdefs.h> |
47 | #include <QtCore/qline.h> |
48 | #include <QtCore/qpoint.h> |
49 | #include <QtCore/qrect.h> |
50 | |
51 | QT_BEGIN_NAMESPACE |
52 | |
53 | class QVariant; |
54 | class QPainterPath; |
55 | |
56 | class Q_GUI_EXPORT QTransform |
57 | { |
58 | public: |
59 | enum TransformationType { |
60 | TxNone = 0x00, |
61 | TxTranslate = 0x01, |
62 | TxScale = 0x02, |
63 | TxRotate = 0x04, |
64 | TxShear = 0x08, |
65 | TxProject = 0x10 |
66 | }; |
67 | |
68 | inline explicit QTransform(Qt::Initialization) : affine(Qt::Uninitialized) {} |
69 | QTransform(); |
70 | QTransform(qreal h11, qreal h12, qreal h13, |
71 | qreal h21, qreal h22, qreal h23, |
72 | qreal h31, qreal h32, qreal h33 = 1.0); |
73 | QTransform(qreal h11, qreal h12, qreal h21, |
74 | qreal h22, qreal dx, qreal dy); |
75 | #if QT_DEPRECATED_SINCE(5, 15) |
76 | explicit QTransform(const QMatrix &mtx); |
77 | #endif // QT_DEPRECATED_SINCE(5, 15) |
78 | |
79 | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
80 | // ### Qt 6: remove; the compiler-generated ones are fine! |
81 | QTransform &operator=(QTransform &&other) noexcept // = default |
82 | { memcpy(dest: static_cast<void *>(this), src: static_cast<void *>(&other), n: sizeof(QTransform)); return *this; } |
83 | QTransform &operator=(const QTransform &) noexcept; // = default |
84 | QTransform(QTransform &&other) noexcept // = default |
85 | : affine(Qt::Uninitialized) |
86 | { memcpy(dest: static_cast<void *>(this), src: static_cast<void *>(&other), n: sizeof(QTransform)); } |
87 | QTransform(const QTransform &other) noexcept // = default |
88 | : affine(Qt::Uninitialized) |
89 | { memcpy(dest: static_cast<void *>(this), src: static_cast<const void *>(&other), n: sizeof(QTransform)); } |
90 | #endif |
91 | |
92 | bool isAffine() const; |
93 | bool isIdentity() const; |
94 | bool isInvertible() const; |
95 | bool isScaling() const; |
96 | bool isRotating() const; |
97 | bool isTranslating() const; |
98 | |
99 | TransformationType type() const; |
100 | |
101 | inline qreal determinant() const; |
102 | #if QT_DEPRECATED_SINCE(5, 13) |
103 | QT_DEPRECATED_X("Use determinant() instead" ) |
104 | qreal det() const; |
105 | #endif |
106 | |
107 | qreal m11() const; |
108 | qreal m12() const; |
109 | qreal m13() const; |
110 | qreal m21() const; |
111 | qreal m22() const; |
112 | qreal m23() const; |
113 | qreal m31() const; |
114 | qreal m32() const; |
115 | qreal m33() const; |
116 | qreal dx() const; |
117 | qreal dy() const; |
118 | |
119 | void setMatrix(qreal m11, qreal m12, qreal m13, |
120 | qreal m21, qreal m22, qreal m23, |
121 | qreal m31, qreal m32, qreal m33); |
122 | |
123 | Q_REQUIRED_RESULT QTransform inverted(bool *invertible = nullptr) const; |
124 | Q_REQUIRED_RESULT QTransform adjoint() const; |
125 | Q_REQUIRED_RESULT QTransform transposed() const; |
126 | |
127 | QTransform &translate(qreal dx, qreal dy); |
128 | QTransform &scale(qreal sx, qreal sy); |
129 | QTransform &shear(qreal sh, qreal sv); |
130 | QTransform &rotate(qreal a, Qt::Axis axis = Qt::ZAxis); |
131 | QTransform &rotateRadians(qreal a, Qt::Axis axis = Qt::ZAxis); |
132 | |
133 | static bool squareToQuad(const QPolygonF &square, QTransform &result); |
134 | static bool quadToSquare(const QPolygonF &quad, QTransform &result); |
135 | static bool quadToQuad(const QPolygonF &one, |
136 | const QPolygonF &two, |
137 | QTransform &result); |
138 | |
139 | bool operator==(const QTransform &) const; |
140 | bool operator!=(const QTransform &) const; |
141 | |
142 | QTransform &operator*=(const QTransform &); |
143 | QTransform operator*(const QTransform &o) const; |
144 | |
145 | operator QVariant() const; |
146 | |
147 | void reset(); |
148 | QPoint map(const QPoint &p) const; |
149 | QPointF map(const QPointF &p) const; |
150 | QLine map(const QLine &l) const; |
151 | QLineF map(const QLineF &l) const; |
152 | QPolygonF map(const QPolygonF &a) const; |
153 | QPolygon map(const QPolygon &a) const; |
154 | QRegion map(const QRegion &r) const; |
155 | QPainterPath map(const QPainterPath &p) const; |
156 | QPolygon mapToPolygon(const QRect &r) const; |
157 | QRect mapRect(const QRect &) const; |
158 | QRectF mapRect(const QRectF &) const; |
159 | void map(int x, int y, int *tx, int *ty) const; |
160 | void map(qreal x, qreal y, qreal *tx, qreal *ty) const; |
161 | |
162 | #if QT_DEPRECATED_SINCE(5, 15) |
163 | const QMatrix &toAffine() const; |
164 | #endif // QT_DEPRECATED_SINCE(5, 15) |
165 | |
166 | QTransform &operator*=(qreal div); |
167 | QTransform &operator/=(qreal div); |
168 | QTransform &operator+=(qreal div); |
169 | QTransform &operator-=(qreal div); |
170 | |
171 | static QTransform fromTranslate(qreal dx, qreal dy); |
172 | static QTransform fromScale(qreal dx, qreal dy); |
173 | |
174 | private: |
175 | inline QTransform(qreal h11, qreal h12, qreal h13, |
176 | qreal h21, qreal h22, qreal h23, |
177 | qreal h31, qreal h32, qreal h33, bool) |
178 | : affine(h11, h12, h21, h22, h31, h32, true) |
179 | , m_13(h13), m_23(h23), m_33(h33) |
180 | , m_type(TxNone) |
181 | , m_dirty(TxProject) |
182 | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
183 | , d(nullptr) |
184 | #endif |
185 | { |
186 | } |
187 | inline QTransform(bool) |
188 | : affine(true) |
189 | , m_13(0), m_23(0), m_33(1) |
190 | , m_type(TxNone) |
191 | , m_dirty(TxNone) |
192 | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
193 | , d(nullptr) |
194 | #endif |
195 | { |
196 | } |
197 | inline TransformationType inline_type() const; |
198 | QMatrix affine; |
199 | qreal m_13; |
200 | qreal m_23; |
201 | qreal m_33; |
202 | |
203 | mutable uint m_type : 5; |
204 | mutable uint m_dirty : 5; |
205 | #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) |
206 | class Private; |
207 | Private *d; |
208 | #endif |
209 | }; |
210 | Q_DECLARE_TYPEINFO(QTransform, Q_MOVABLE_TYPE); |
211 | |
212 | Q_GUI_EXPORT Q_DECL_CONST_FUNCTION uint qHash(const QTransform &key, uint seed = 0) noexcept; |
213 | |
214 | /******* inlines *****/ |
215 | inline QTransform::TransformationType QTransform::inline_type() const |
216 | { |
217 | if (m_dirty == TxNone) |
218 | return static_cast<TransformationType>(m_type); |
219 | return type(); |
220 | } |
221 | |
222 | inline bool QTransform::isAffine() const |
223 | { |
224 | return inline_type() < TxProject; |
225 | } |
226 | inline bool QTransform::isIdentity() const |
227 | { |
228 | return inline_type() == TxNone; |
229 | } |
230 | |
231 | inline bool QTransform::isInvertible() const |
232 | { |
233 | return !qFuzzyIsNull(d: determinant()); |
234 | } |
235 | |
236 | inline bool QTransform::isScaling() const |
237 | { |
238 | return type() >= TxScale; |
239 | } |
240 | inline bool QTransform::isRotating() const |
241 | { |
242 | return inline_type() >= TxRotate; |
243 | } |
244 | |
245 | inline bool QTransform::isTranslating() const |
246 | { |
247 | return inline_type() >= TxTranslate; |
248 | } |
249 | |
250 | inline qreal QTransform::determinant() const |
251 | { |
252 | return affine._m11*(m_33*affine._m22-affine._dy*m_23) - |
253 | affine._m21*(m_33*affine._m12-affine._dy*m_13)+affine._dx*(m_23*affine._m12-affine._m22*m_13); |
254 | } |
255 | #if QT_DEPRECATED_SINCE(5, 13) |
256 | inline qreal QTransform::det() const |
257 | { |
258 | return determinant(); |
259 | } |
260 | #endif |
261 | inline qreal QTransform::m11() const |
262 | { |
263 | return affine._m11; |
264 | } |
265 | inline qreal QTransform::m12() const |
266 | { |
267 | return affine._m12; |
268 | } |
269 | inline qreal QTransform::m13() const |
270 | { |
271 | return m_13; |
272 | } |
273 | inline qreal QTransform::m21() const |
274 | { |
275 | return affine._m21; |
276 | } |
277 | inline qreal QTransform::m22() const |
278 | { |
279 | return affine._m22; |
280 | } |
281 | inline qreal QTransform::m23() const |
282 | { |
283 | return m_23; |
284 | } |
285 | inline qreal QTransform::m31() const |
286 | { |
287 | return affine._dx; |
288 | } |
289 | inline qreal QTransform::m32() const |
290 | { |
291 | return affine._dy; |
292 | } |
293 | inline qreal QTransform::m33() const |
294 | { |
295 | return m_33; |
296 | } |
297 | inline qreal QTransform::dx() const |
298 | { |
299 | return affine._dx; |
300 | } |
301 | inline qreal QTransform::dy() const |
302 | { |
303 | return affine._dy; |
304 | } |
305 | |
306 | QT_WARNING_PUSH |
307 | QT_WARNING_DISABLE_CLANG("-Wfloat-equal" ) |
308 | QT_WARNING_DISABLE_GCC("-Wfloat-equal" ) |
309 | QT_WARNING_DISABLE_INTEL(1572) |
310 | |
311 | inline QTransform &QTransform::operator*=(qreal num) |
312 | { |
313 | if (num == 1.) |
314 | return *this; |
315 | affine._m11 *= num; |
316 | affine._m12 *= num; |
317 | m_13 *= num; |
318 | affine._m21 *= num; |
319 | affine._m22 *= num; |
320 | m_23 *= num; |
321 | affine._dx *= num; |
322 | affine._dy *= num; |
323 | m_33 *= num; |
324 | if (m_dirty < TxScale) |
325 | m_dirty = TxScale; |
326 | return *this; |
327 | } |
328 | inline QTransform &QTransform::operator/=(qreal div) |
329 | { |
330 | if (div == 0) |
331 | return *this; |
332 | div = 1/div; |
333 | return operator*=(num: div); |
334 | } |
335 | inline QTransform &QTransform::operator+=(qreal num) |
336 | { |
337 | if (num == 0) |
338 | return *this; |
339 | affine._m11 += num; |
340 | affine._m12 += num; |
341 | m_13 += num; |
342 | affine._m21 += num; |
343 | affine._m22 += num; |
344 | m_23 += num; |
345 | affine._dx += num; |
346 | affine._dy += num; |
347 | m_33 += num; |
348 | m_dirty = TxProject; |
349 | return *this; |
350 | } |
351 | inline QTransform &QTransform::operator-=(qreal num) |
352 | { |
353 | if (num == 0) |
354 | return *this; |
355 | affine._m11 -= num; |
356 | affine._m12 -= num; |
357 | m_13 -= num; |
358 | affine._m21 -= num; |
359 | affine._m22 -= num; |
360 | m_23 -= num; |
361 | affine._dx -= num; |
362 | affine._dy -= num; |
363 | m_33 -= num; |
364 | m_dirty = TxProject; |
365 | return *this; |
366 | } |
367 | |
368 | QT_WARNING_POP |
369 | |
370 | inline bool qFuzzyCompare(const QTransform& t1, const QTransform& t2) |
371 | { |
372 | return qFuzzyCompare(p1: t1.m11(), p2: t2.m11()) |
373 | && qFuzzyCompare(p1: t1.m12(), p2: t2.m12()) |
374 | && qFuzzyCompare(p1: t1.m13(), p2: t2.m13()) |
375 | && qFuzzyCompare(p1: t1.m21(), p2: t2.m21()) |
376 | && qFuzzyCompare(p1: t1.m22(), p2: t2.m22()) |
377 | && qFuzzyCompare(p1: t1.m23(), p2: t2.m23()) |
378 | && qFuzzyCompare(p1: t1.m31(), p2: t2.m31()) |
379 | && qFuzzyCompare(p1: t1.m32(), p2: t2.m32()) |
380 | && qFuzzyCompare(p1: t1.m33(), p2: t2.m33()); |
381 | } |
382 | |
383 | |
384 | /****** stream functions *******************/ |
385 | #ifndef QT_NO_DATASTREAM |
386 | Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTransform &); |
387 | Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTransform &); |
388 | #endif |
389 | |
390 | #ifndef QT_NO_DEBUG_STREAM |
391 | Q_GUI_EXPORT QDebug operator<<(QDebug, const QTransform &); |
392 | #endif |
393 | /****** end stream functions *******************/ |
394 | |
395 | // mathematical semantics |
396 | inline QPoint operator*(const QPoint &p, const QTransform &m) |
397 | { return m.map(p); } |
398 | inline QPointF operator*(const QPointF &p, const QTransform &m) |
399 | { return m.map(p); } |
400 | inline QLineF operator*(const QLineF &l, const QTransform &m) |
401 | { return m.map(l); } |
402 | inline QLine operator*(const QLine &l, const QTransform &m) |
403 | { return m.map(l); } |
404 | inline QPolygon operator *(const QPolygon &a, const QTransform &m) |
405 | { return m.map(a); } |
406 | inline QPolygonF operator *(const QPolygonF &a, const QTransform &m) |
407 | { return m.map(a); } |
408 | inline QRegion operator *(const QRegion &r, const QTransform &m) |
409 | { return m.map(r); } |
410 | |
411 | inline QTransform operator *(const QTransform &a, qreal n) |
412 | { QTransform t(a); t *= n; return t; } |
413 | inline QTransform operator /(const QTransform &a, qreal n) |
414 | { QTransform t(a); t /= n; return t; } |
415 | inline QTransform operator +(const QTransform &a, qreal n) |
416 | { QTransform t(a); t += n; return t; } |
417 | inline QTransform operator -(const QTransform &a, qreal n) |
418 | { QTransform t(a); t -= n; return t; } |
419 | |
420 | QT_END_NAMESPACE |
421 | |
422 | #endif // QTRANSFORM_H |
423 | |