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/qpainterpath.h>
45#include <QtGui/qpolygon.h>
46#include <QtGui/qregion.h>
47#include <QtGui/qwindowdefs.h>
48#include <QtCore/qline.h>
49#include <QtCore/qpoint.h>
50#include <QtCore/qrect.h>
51
52QT_BEGIN_NAMESPACE
53
54
55class QVariant;
56
57class Q_GUI_EXPORT QTransform
58{
59public:
60 enum TransformationType {
61 TxNone = 0x00,
62 TxTranslate = 0x01,
63 TxScale = 0x02,
64 TxRotate = 0x04,
65 TxShear = 0x08,
66 TxProject = 0x10
67 };
68
69 inline explicit QTransform(Qt::Initialization) : affine(Qt::Uninitialized) {}
70 QTransform();
71 QTransform(qreal h11, qreal h12, qreal h13,
72 qreal h21, qreal h22, qreal h23,
73 qreal h31, qreal h32, qreal h33 = 1.0);
74 QTransform(qreal h11, qreal h12, qreal h21,
75 qreal h22, qreal dx, qreal dy);
76 explicit QTransform(const QMatrix &mtx);
77
78#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
79 // ### Qt 6: remove; the compiler-generated ones are fine!
80 QTransform &operator=(QTransform &&other) Q_DECL_NOTHROW // = default
81 { memcpy(static_cast<void *>(this), static_cast<void *>(&other), sizeof(QTransform)); return *this; }
82 QTransform &operator=(const QTransform &) Q_DECL_NOTHROW; // = default
83 QTransform(QTransform &&other) Q_DECL_NOTHROW // = default
84 : affine(Qt::Uninitialized)
85 { memcpy(static_cast<void *>(this), static_cast<void *>(&other), sizeof(QTransform)); }
86 QTransform(const QTransform &other) Q_DECL_NOTHROW // = default
87 : affine(Qt::Uninitialized)
88 { memcpy(static_cast<void *>(this), static_cast<const void *>(&other), sizeof(QTransform)); }
89#endif
90
91 bool isAffine() const;
92 bool isIdentity() const;
93 bool isInvertible() const;
94 bool isScaling() const;
95 bool isRotating() const;
96 bool isTranslating() const;
97
98 TransformationType type() const;
99
100 inline qreal determinant() const;
101 qreal det() const;
102
103 qreal m11() const;
104 qreal m12() const;
105 qreal m13() const;
106 qreal m21() const;
107 qreal m22() const;
108 qreal m23() const;
109 qreal m31() const;
110 qreal m32() const;
111 qreal m33() const;
112 qreal dx() const;
113 qreal dy() const;
114
115 void setMatrix(qreal m11, qreal m12, qreal m13,
116 qreal m21, qreal m22, qreal m23,
117 qreal m31, qreal m32, qreal m33);
118
119 Q_REQUIRED_RESULT QTransform inverted(bool *invertible = nullptr) const;
120 Q_REQUIRED_RESULT QTransform adjoint() const;
121 Q_REQUIRED_RESULT QTransform transposed() const;
122
123 QTransform &translate(qreal dx, qreal dy);
124 QTransform &scale(qreal sx, qreal sy);
125 QTransform &shear(qreal sh, qreal sv);
126 QTransform &rotate(qreal a, Qt::Axis axis = Qt::ZAxis);
127 QTransform &rotateRadians(qreal a, Qt::Axis axis = Qt::ZAxis);
128
129 static bool squareToQuad(const QPolygonF &square, QTransform &result);
130 static bool quadToSquare(const QPolygonF &quad, QTransform &result);
131 static bool quadToQuad(const QPolygonF &one,
132 const QPolygonF &two,
133 QTransform &result);
134
135 bool operator==(const QTransform &) const;
136 bool operator!=(const QTransform &) const;
137
138 QTransform &operator*=(const QTransform &);
139 QTransform operator*(const QTransform &o) const;
140
141 operator QVariant() const;
142
143 void reset();
144 QPoint map(const QPoint &p) const;
145 QPointF map(const QPointF &p) const;
146 QLine map(const QLine &l) const;
147 QLineF map(const QLineF &l) const;
148 QPolygonF map(const QPolygonF &a) const;
149 QPolygon map(const QPolygon &a) const;
150 QRegion map(const QRegion &r) const;
151 QPainterPath map(const QPainterPath &p) const;
152 QPolygon mapToPolygon(const QRect &r) const;
153 QRect mapRect(const QRect &) const;
154 QRectF mapRect(const QRectF &) const;
155 void map(int x, int y, int *tx, int *ty) const;
156 void map(qreal x, qreal y, qreal *tx, qreal *ty) const;
157
158 const QMatrix &toAffine() const;
159
160 QTransform &operator*=(qreal div);
161 QTransform &operator/=(qreal div);
162 QTransform &operator+=(qreal div);
163 QTransform &operator-=(qreal div);
164
165 static QTransform fromTranslate(qreal dx, qreal dy);
166 static QTransform fromScale(qreal dx, qreal dy);
167
168private:
169 inline QTransform(qreal h11, qreal h12, qreal h13,
170 qreal h21, qreal h22, qreal h23,
171 qreal h31, qreal h32, qreal h33, bool)
172 : affine(h11, h12, h21, h22, h31, h32, true)
173 , m_13(h13), m_23(h23), m_33(h33)
174 , m_type(TxNone)
175 , m_dirty(TxProject)
176 , d(nullptr)
177 {
178 }
179 inline QTransform(bool)
180 : affine(true)
181 , m_13(0), m_23(0), m_33(1)
182 , m_type(TxNone)
183 , m_dirty(TxNone)
184 , d(nullptr)
185 {
186 }
187 inline TransformationType inline_type() const;
188 QMatrix affine;
189 qreal m_13;
190 qreal m_23;
191 qreal m_33;
192
193 mutable uint m_type : 5;
194 mutable uint m_dirty : 5;
195#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
196 class Private;
197 Private *d;
198#endif
199};
200Q_DECLARE_TYPEINFO(QTransform, Q_MOVABLE_TYPE);
201
202Q_GUI_EXPORT Q_DECL_CONST_FUNCTION uint qHash(const QTransform &key, uint seed = 0) Q_DECL_NOTHROW;
203
204/******* inlines *****/
205inline QTransform::TransformationType QTransform::inline_type() const
206{
207 if (m_dirty == TxNone)
208 return static_cast<TransformationType>(m_type);
209 return type();
210}
211
212inline bool QTransform::isAffine() const
213{
214 return inline_type() < TxProject;
215}
216inline bool QTransform::isIdentity() const
217{
218 return inline_type() == TxNone;
219}
220
221inline bool QTransform::isInvertible() const
222{
223 return !qFuzzyIsNull(determinant());
224}
225
226inline bool QTransform::isScaling() const
227{
228 return type() >= TxScale;
229}
230inline bool QTransform::isRotating() const
231{
232 return inline_type() >= TxRotate;
233}
234
235inline bool QTransform::isTranslating() const
236{
237 return inline_type() >= TxTranslate;
238}
239
240inline qreal QTransform::determinant() const
241{
242 return affine._m11*(m_33*affine._m22-affine._dy*m_23) -
243 affine._m21*(m_33*affine._m12-affine._dy*m_13)+affine._dx*(m_23*affine._m12-affine._m22*m_13);
244}
245inline qreal QTransform::det() const
246{
247 return determinant();
248}
249inline qreal QTransform::m11() const
250{
251 return affine._m11;
252}
253inline qreal QTransform::m12() const
254{
255 return affine._m12;
256}
257inline qreal QTransform::m13() const
258{
259 return m_13;
260}
261inline qreal QTransform::m21() const
262{
263 return affine._m21;
264}
265inline qreal QTransform::m22() const
266{
267 return affine._m22;
268}
269inline qreal QTransform::m23() const
270{
271 return m_23;
272}
273inline qreal QTransform::m31() const
274{
275 return affine._dx;
276}
277inline qreal QTransform::m32() const
278{
279 return affine._dy;
280}
281inline qreal QTransform::m33() const
282{
283 return m_33;
284}
285inline qreal QTransform::dx() const
286{
287 return affine._dx;
288}
289inline qreal QTransform::dy() const
290{
291 return affine._dy;
292}
293
294QT_WARNING_PUSH
295QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
296QT_WARNING_DISABLE_GCC("-Wfloat-equal")
297
298inline QTransform &QTransform::operator*=(qreal num)
299{
300 if (num == 1.)
301 return *this;
302 affine._m11 *= num;
303 affine._m12 *= num;
304 m_13 *= num;
305 affine._m21 *= num;
306 affine._m22 *= num;
307 m_23 *= num;
308 affine._dx *= num;
309 affine._dy *= num;
310 m_33 *= num;
311 if (m_dirty < TxScale)
312 m_dirty = TxScale;
313 return *this;
314}
315inline QTransform &QTransform::operator/=(qreal div)
316{
317 if (div == 0)
318 return *this;
319 div = 1/div;
320 return operator*=(div);
321}
322inline QTransform &QTransform::operator+=(qreal num)
323{
324 if (num == 0)
325 return *this;
326 affine._m11 += num;
327 affine._m12 += num;
328 m_13 += num;
329 affine._m21 += num;
330 affine._m22 += num;
331 m_23 += num;
332 affine._dx += num;
333 affine._dy += num;
334 m_33 += num;
335 m_dirty = TxProject;
336 return *this;
337}
338inline QTransform &QTransform::operator-=(qreal num)
339{
340 if (num == 0)
341 return *this;
342 affine._m11 -= num;
343 affine._m12 -= num;
344 m_13 -= num;
345 affine._m21 -= num;
346 affine._m22 -= num;
347 m_23 -= num;
348 affine._dx -= num;
349 affine._dy -= num;
350 m_33 -= num;
351 m_dirty = TxProject;
352 return *this;
353}
354
355QT_WARNING_POP
356
357inline bool qFuzzyCompare(const QTransform& t1, const QTransform& t2)
358{
359 return qFuzzyCompare(t1.m11(), t2.m11())
360 && qFuzzyCompare(t1.m12(), t2.m12())
361 && qFuzzyCompare(t1.m13(), t2.m13())
362 && qFuzzyCompare(t1.m21(), t2.m21())
363 && qFuzzyCompare(t1.m22(), t2.m22())
364 && qFuzzyCompare(t1.m23(), t2.m23())
365 && qFuzzyCompare(t1.m31(), t2.m31())
366 && qFuzzyCompare(t1.m32(), t2.m32())
367 && qFuzzyCompare(t1.m33(), t2.m33());
368}
369
370
371/****** stream functions *******************/
372#ifndef QT_NO_DATASTREAM
373Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTransform &);
374Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTransform &);
375#endif
376
377#ifndef QT_NO_DEBUG_STREAM
378Q_GUI_EXPORT QDebug operator<<(QDebug, const QTransform &);
379#endif
380/****** end stream functions *******************/
381
382// mathematical semantics
383inline QPoint operator*(const QPoint &p, const QTransform &m)
384{ return m.map(p); }
385inline QPointF operator*(const QPointF &p, const QTransform &m)
386{ return m.map(p); }
387inline QLineF operator*(const QLineF &l, const QTransform &m)
388{ return m.map(l); }
389inline QLine operator*(const QLine &l, const QTransform &m)
390{ return m.map(l); }
391inline QPolygon operator *(const QPolygon &a, const QTransform &m)
392{ return m.map(a); }
393inline QPolygonF operator *(const QPolygonF &a, const QTransform &m)
394{ return m.map(a); }
395inline QRegion operator *(const QRegion &r, const QTransform &m)
396{ return m.map(r); }
397inline QPainterPath operator *(const QPainterPath &p, const QTransform &m)
398{ return m.map(p); }
399
400inline QTransform operator *(const QTransform &a, qreal n)
401{ QTransform t(a); t *= n; return t; }
402inline QTransform operator /(const QTransform &a, qreal n)
403{ QTransform t(a); t /= n; return t; }
404inline QTransform operator +(const QTransform &a, qreal n)
405{ QTransform t(a); t += n; return t; }
406inline QTransform operator -(const QTransform &a, qreal n)
407{ QTransform t(a); t -= n; return t; }
408
409QT_END_NAMESPACE
410
411#endif // QTRANSFORM_H
412