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 
40 #ifndef QMATRIX4X4_H
41 #define QMATRIX4X4_H
42 
43 #include <QtGui/qtguiglobal.h>
44 #include <QtGui/qvector3d.h>
45 #include <QtGui/qvector4d.h>
46 #include <QtGui/qquaternion.h>
47 #include <QtGui/qgenericmatrix.h>
48 #include <QtCore/qrect.h>
49 
50 QT_BEGIN_NAMESPACE
51 
52 
53 #ifndef QT_NO_MATRIX4X4
54 
55 class QMatrix;
56 class QTransform;
57 class QVariant;
58 
59 class Q_GUI_EXPORT QMatrix4x4
60 {
61 public:
QMatrix4x4()62     inline QMatrix4x4() { setToIdentity(); }
QMatrix4x4(Qt::Initialization)63     explicit QMatrix4x4(Qt::Initialization) : flagBits(General) {}
64     explicit QMatrix4x4(const float *values);
65     inline QMatrix4x4(float m11, float m12, float m13, float m14,
66                       float m21, float m22, float m23, float m24,
67                       float m31, float m32, float m33, float m34,
68                       float m41, float m42, float m43, float m44);
69 
70     template <int N, int M>
71     explicit QMatrix4x4(const QGenericMatrix<N, M, float>& matrix);
72 
73     QMatrix4x4(const float *values, int cols, int rows);
74     QMatrix4x4(const QTransform& transform);
75 #if QT_DEPRECATED_SINCE(5, 15)
76     QMatrix4x4(const QMatrix& matrix);
77 #endif // QT_DEPRECATED_SINCE(5, 15)
78 
79     inline const float& operator()(int row, int column) const;
80     inline float& operator()(int row, int column);
81 
82 #ifndef QT_NO_VECTOR4D
83     inline QVector4D column(int index) const;
84     inline void setColumn(int index, const QVector4D& value);
85 
86     inline QVector4D row(int index) const;
87     inline void setRow(int index, const QVector4D& value);
88 #endif
89 
90     inline bool isAffine() const;
91 
92     inline bool isIdentity() const;
93     inline void setToIdentity();
94 
95     inline void fill(float value);
96 
97     double determinant() const;
98     QMatrix4x4 inverted(bool *invertible = nullptr) const;
99     QMatrix4x4 transposed() const;
100     QMatrix3x3 normalMatrix() const;
101 
102     inline QMatrix4x4& operator+=(const QMatrix4x4& other);
103     inline QMatrix4x4& operator-=(const QMatrix4x4& other);
104     inline QMatrix4x4& operator*=(const QMatrix4x4& other);
105     inline QMatrix4x4& operator*=(float factor);
106     QMatrix4x4& operator/=(float divisor);
107     inline bool operator==(const QMatrix4x4& other) const;
108     inline bool operator!=(const QMatrix4x4& other) const;
109 
110     friend QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2);
111     friend QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2);
112     friend QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2);
113 #ifndef QT_NO_VECTOR3D
114     friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector);
115     friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix);
116 #endif
117 #ifndef QT_NO_VECTOR4D
118     friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix);
119     friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector);
120 #endif
121     friend QPoint operator*(const QPoint& point, const QMatrix4x4& matrix);
122     friend QPointF operator*(const QPointF& point, const QMatrix4x4& matrix);
123     friend QMatrix4x4 operator-(const QMatrix4x4& matrix);
124     friend QPoint operator*(const QMatrix4x4& matrix, const QPoint& point);
125     friend QPointF operator*(const QMatrix4x4& matrix, const QPointF& point);
126     friend QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix);
127     friend QMatrix4x4 operator*(const QMatrix4x4& matrix, float factor);
128     friend Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, float divisor);
129 
130     friend inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2);
131 
132 #ifndef QT_NO_VECTOR3D
133     void scale(const QVector3D& vector);
134     void translate(const QVector3D& vector);
135     void rotate(float angle, const QVector3D& vector);
136 #endif
137     void scale(float x, float y);
138     void scale(float x, float y, float z);
139     void scale(float factor);
140     void translate(float x, float y);
141     void translate(float x, float y, float z);
142     void rotate(float angle, float x, float y, float z = 0.0f);
143 #ifndef QT_NO_QUATERNION
144     void rotate(const QQuaternion& quaternion);
145 #endif
146 
147     void ortho(const QRect& rect);
148     void ortho(const QRectF& rect);
149     void ortho(float left, float right, float bottom, float top, float nearPlane, float farPlane);
150     void frustum(float left, float right, float bottom, float top, float nearPlane, float farPlane);
151     void perspective(float verticalAngle, float aspectRatio, float nearPlane, float farPlane);
152 #ifndef QT_NO_VECTOR3D
153     void lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up);
154 #endif
155     void viewport(const QRectF &rect);
156     void viewport(float left, float bottom, float width, float height, float nearPlane = 0.0f, float farPlane = 1.0f);
157     void flipCoordinates();
158 
159     void copyDataTo(float *values) const;
160 
161 #if QT_DEPRECATED_SINCE(5, 15)
162     QT_DEPRECATED_X("Use toTransform()") QMatrix toAffine() const;
163 #endif // QT_DEPRECATED_SINCE(5, 15)
164     QTransform toTransform() const;
165     QTransform toTransform(float distanceToPlane) const;
166 
167     QPoint map(const QPoint& point) const;
168     QPointF map(const QPointF& point) const;
169 #ifndef QT_NO_VECTOR3D
170     QVector3D map(const QVector3D& point) const;
171     QVector3D mapVector(const QVector3D& vector) const;
172 #endif
173 #ifndef QT_NO_VECTOR4D
174     QVector4D map(const QVector4D& point) const;
175 #endif
176     QRect mapRect(const QRect& rect) const;
177     QRectF mapRect(const QRectF& rect) const;
178 
179     template <int N, int M>
180     QGenericMatrix<N, M, float> toGenericMatrix() const;
181 
182     inline float *data();
data()183     inline const float *data() const { return *m; }
constData()184     inline const float *constData() const { return *m; }
185 
186     void optimize();
187 
188     operator QVariant() const;
189 
190 #ifndef QT_NO_DEBUG_STREAM
191     friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
192 #endif
193 
194 private:
195     float m[4][4];          // Column-major order to match OpenGL.
196     int flagBits;           // Flag bits from the enum below.
197 
198     // When matrices are multiplied, the flag bits are or-ed together.
199     enum {
200         Identity        = 0x0000, // Identity matrix
201         Translation     = 0x0001, // Contains a translation
202         Scale           = 0x0002, // Contains a scale
203         Rotation2D      = 0x0004, // Contains a rotation about the Z axis
204         Rotation        = 0x0008, // Contains an arbitrary rotation
205         Perspective     = 0x0010, // Last row is different from (0, 0, 0, 1)
206         General         = 0x001f  // General matrix, unknown contents
207     };
208 
209     // Construct without initializing identity matrix.
QMatrix4x4(int)210     explicit QMatrix4x4(int) { }
211 
212     QMatrix4x4 orthonormalInverse() const;
213 
214     void projectedRotate(float angle, float x, float y, float z);
215 
216     friend class QGraphicsRotation;
217 };
218 
219 QT_WARNING_PUSH
220 QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
221 QT_WARNING_DISABLE_GCC("-Wfloat-equal")
222 QT_WARNING_DISABLE_INTEL(1572)
223 Q_DECLARE_TYPEINFO(QMatrix4x4, Q_MOVABLE_TYPE);
224 
QMatrix4x4(float m11,float m12,float m13,float m14,float m21,float m22,float m23,float m24,float m31,float m32,float m33,float m34,float m41,float m42,float m43,float m44)225 inline QMatrix4x4::QMatrix4x4
226         (float m11, float m12, float m13, float m14,
227          float m21, float m22, float m23, float m24,
228          float m31, float m32, float m33, float m34,
229          float m41, float m42, float m43, float m44)
230 {
231     m[0][0] = m11; m[0][1] = m21; m[0][2] = m31; m[0][3] = m41;
232     m[1][0] = m12; m[1][1] = m22; m[1][2] = m32; m[1][3] = m42;
233     m[2][0] = m13; m[2][1] = m23; m[2][2] = m33; m[2][3] = m43;
234     m[3][0] = m14; m[3][1] = m24; m[3][2] = m34; m[3][3] = m44;
235     flagBits = General;
236 }
237 
238 template <int N, int M>
QMatrix4x4(const QGenericMatrix<N,M,float> & matrix)239 Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4
240     (const QGenericMatrix<N, M, float>& matrix)
241 {
242     const float *values = matrix.constData();
243     for (int matrixCol = 0; matrixCol < 4; ++matrixCol) {
244         for (int matrixRow = 0; matrixRow < 4; ++matrixRow) {
245             if (matrixCol < N && matrixRow < M)
246                 m[matrixCol][matrixRow] = values[matrixCol * M + matrixRow];
247             else if (matrixCol == matrixRow)
248                 m[matrixCol][matrixRow] = 1.0f;
249             else
250                 m[matrixCol][matrixRow] = 0.0f;
251         }
252     }
253     flagBits = General;
254 }
255 
256 template <int N, int M>
toGenericMatrix()257 QGenericMatrix<N, M, float> QMatrix4x4::toGenericMatrix() const
258 {
259     QGenericMatrix<N, M, float> result;
260     float *values = result.data();
261     for (int matrixCol = 0; matrixCol < N; ++matrixCol) {
262         for (int matrixRow = 0; matrixRow < M; ++matrixRow) {
263             if (matrixCol < 4 && matrixRow < 4)
264                 values[matrixCol * M + matrixRow] = m[matrixCol][matrixRow];
265             else if (matrixCol == matrixRow)
266                 values[matrixCol * M + matrixRow] = 1.0f;
267             else
268                 values[matrixCol * M + matrixRow] = 0.0f;
269         }
270     }
271     return result;
272 }
273 
operator()274 inline const float& QMatrix4x4::operator()(int aRow, int aColumn) const
275 {
276     Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
277     return m[aColumn][aRow];
278 }
279 
operator()280 inline float& QMatrix4x4::operator()(int aRow, int aColumn)
281 {
282     Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
283     flagBits = General;
284     return m[aColumn][aRow];
285 }
286 
287 #ifndef QT_NO_VECTOR4D
column(int index)288 inline QVector4D QMatrix4x4::column(int index) const
289 {
290     Q_ASSERT(index >= 0 && index < 4);
291     return QVector4D(m[index][0], m[index][1], m[index][2], m[index][3]);
292 }
293 
setColumn(int index,const QVector4D & value)294 inline void QMatrix4x4::setColumn(int index, const QVector4D& value)
295 {
296     Q_ASSERT(index >= 0 && index < 4);
297     m[index][0] = value.x();
298     m[index][1] = value.y();
299     m[index][2] = value.z();
300     m[index][3] = value.w();
301     flagBits = General;
302 }
303 
row(int index)304 inline QVector4D QMatrix4x4::row(int index) const
305 {
306     Q_ASSERT(index >= 0 && index < 4);
307     return QVector4D(m[0][index], m[1][index], m[2][index], m[3][index]);
308 }
309 
setRow(int index,const QVector4D & value)310 inline void QMatrix4x4::setRow(int index, const QVector4D& value)
311 {
312     Q_ASSERT(index >= 0 && index < 4);
313     m[0][index] = value.x();
314     m[1][index] = value.y();
315     m[2][index] = value.z();
316     m[3][index] = value.w();
317     flagBits = General;
318 }
319 #endif
320 
321 Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, float divisor);
322 
isAffine()323 inline bool QMatrix4x4::isAffine() const
324 {
325     return m[0][3] == 0.0f && m[1][3] == 0.0f && m[2][3] == 0.0f && m[3][3] == 1.0f;
326 }
327 
isIdentity()328 inline bool QMatrix4x4::isIdentity() const
329 {
330     if (flagBits == Identity)
331         return true;
332     if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f)
333         return false;
334     if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f)
335         return false;
336     if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f)
337         return false;
338     if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f)
339         return false;
340     if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f)
341         return false;
342     return (m[3][3] == 1.0f);
343 }
344 
setToIdentity()345 inline void QMatrix4x4::setToIdentity()
346 {
347     m[0][0] = 1.0f;
348     m[0][1] = 0.0f;
349     m[0][2] = 0.0f;
350     m[0][3] = 0.0f;
351     m[1][0] = 0.0f;
352     m[1][1] = 1.0f;
353     m[1][2] = 0.0f;
354     m[1][3] = 0.0f;
355     m[2][0] = 0.0f;
356     m[2][1] = 0.0f;
357     m[2][2] = 1.0f;
358     m[2][3] = 0.0f;
359     m[3][0] = 0.0f;
360     m[3][1] = 0.0f;
361     m[3][2] = 0.0f;
362     m[3][3] = 1.0f;
363     flagBits = Identity;
364 }
365 
fill(float value)366 inline void QMatrix4x4::fill(float value)
367 {
368     m[0][0] = value;
369     m[0][1] = value;
370     m[0][2] = value;
371     m[0][3] = value;
372     m[1][0] = value;
373     m[1][1] = value;
374     m[1][2] = value;
375     m[1][3] = value;
376     m[2][0] = value;
377     m[2][1] = value;
378     m[2][2] = value;
379     m[2][3] = value;
380     m[3][0] = value;
381     m[3][1] = value;
382     m[3][2] = value;
383     m[3][3] = value;
384     flagBits = General;
385 }
386 
387 inline QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
388 {
389     m[0][0] += other.m[0][0];
390     m[0][1] += other.m[0][1];
391     m[0][2] += other.m[0][2];
392     m[0][3] += other.m[0][3];
393     m[1][0] += other.m[1][0];
394     m[1][1] += other.m[1][1];
395     m[1][2] += other.m[1][2];
396     m[1][3] += other.m[1][3];
397     m[2][0] += other.m[2][0];
398     m[2][1] += other.m[2][1];
399     m[2][2] += other.m[2][2];
400     m[2][3] += other.m[2][3];
401     m[3][0] += other.m[3][0];
402     m[3][1] += other.m[3][1];
403     m[3][2] += other.m[3][2];
404     m[3][3] += other.m[3][3];
405     flagBits = General;
406     return *this;
407 }
408 
409 inline QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
410 {
411     m[0][0] -= other.m[0][0];
412     m[0][1] -= other.m[0][1];
413     m[0][2] -= other.m[0][2];
414     m[0][3] -= other.m[0][3];
415     m[1][0] -= other.m[1][0];
416     m[1][1] -= other.m[1][1];
417     m[1][2] -= other.m[1][2];
418     m[1][3] -= other.m[1][3];
419     m[2][0] -= other.m[2][0];
420     m[2][1] -= other.m[2][1];
421     m[2][2] -= other.m[2][2];
422     m[2][3] -= other.m[2][3];
423     m[3][0] -= other.m[3][0];
424     m[3][1] -= other.m[3][1];
425     m[3][2] -= other.m[3][2];
426     m[3][3] -= other.m[3][3];
427     flagBits = General;
428     return *this;
429 }
430 
431 inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& o)
432 {
433     const QMatrix4x4 other = o; // prevent aliasing when &o == this ### Qt 6: take o by value
434     flagBits |= other.flagBits;
435 
436     if (flagBits < Rotation2D) {
437         m[3][0] += m[0][0] * other.m[3][0];
438         m[3][1] += m[1][1] * other.m[3][1];
439         m[3][2] += m[2][2] * other.m[3][2];
440 
441         m[0][0] *= other.m[0][0];
442         m[1][1] *= other.m[1][1];
443         m[2][2] *= other.m[2][2];
444         return *this;
445     }
446 
447     float m0, m1, m2;
448     m0 = m[0][0] * other.m[0][0]
449             + m[1][0] * other.m[0][1]
450             + m[2][0] * other.m[0][2]
451             + m[3][0] * other.m[0][3];
452     m1 = m[0][0] * other.m[1][0]
453             + m[1][0] * other.m[1][1]
454             + m[2][0] * other.m[1][2]
455             + m[3][0] * other.m[1][3];
456     m2 = m[0][0] * other.m[2][0]
457             + m[1][0] * other.m[2][1]
458             + m[2][0] * other.m[2][2]
459             + m[3][0] * other.m[2][3];
460     m[3][0] = m[0][0] * other.m[3][0]
461             + m[1][0] * other.m[3][1]
462             + m[2][0] * other.m[3][2]
463             + m[3][0] * other.m[3][3];
464     m[0][0] = m0;
465     m[1][0] = m1;
466     m[2][0] = m2;
467 
468     m0 = m[0][1] * other.m[0][0]
469             + m[1][1] * other.m[0][1]
470             + m[2][1] * other.m[0][2]
471             + m[3][1] * other.m[0][3];
472     m1 = m[0][1] * other.m[1][0]
473             + m[1][1] * other.m[1][1]
474             + m[2][1] * other.m[1][2]
475             + m[3][1] * other.m[1][3];
476     m2 = m[0][1] * other.m[2][0]
477             + m[1][1] * other.m[2][1]
478             + m[2][1] * other.m[2][2]
479             + m[3][1] * other.m[2][3];
480     m[3][1] = m[0][1] * other.m[3][0]
481             + m[1][1] * other.m[3][1]
482             + m[2][1] * other.m[3][2]
483             + m[3][1] * other.m[3][3];
484     m[0][1] = m0;
485     m[1][1] = m1;
486     m[2][1] = m2;
487 
488     m0 = m[0][2] * other.m[0][0]
489             + m[1][2] * other.m[0][1]
490             + m[2][2] * other.m[0][2]
491             + m[3][2] * other.m[0][3];
492     m1 = m[0][2] * other.m[1][0]
493             + m[1][2] * other.m[1][1]
494             + m[2][2] * other.m[1][2]
495             + m[3][2] * other.m[1][3];
496     m2 = m[0][2] * other.m[2][0]
497             + m[1][2] * other.m[2][1]
498             + m[2][2] * other.m[2][2]
499             + m[3][2] * other.m[2][3];
500     m[3][2] = m[0][2] * other.m[3][0]
501             + m[1][2] * other.m[3][1]
502             + m[2][2] * other.m[3][2]
503             + m[3][2] * other.m[3][3];
504     m[0][2] = m0;
505     m[1][2] = m1;
506     m[2][2] = m2;
507 
508     m0 = m[0][3] * other.m[0][0]
509             + m[1][3] * other.m[0][1]
510             + m[2][3] * other.m[0][2]
511             + m[3][3] * other.m[0][3];
512     m1 = m[0][3] * other.m[1][0]
513             + m[1][3] * other.m[1][1]
514             + m[2][3] * other.m[1][2]
515             + m[3][3] * other.m[1][3];
516     m2 = m[0][3] * other.m[2][0]
517             + m[1][3] * other.m[2][1]
518             + m[2][3] * other.m[2][2]
519             + m[3][3] * other.m[2][3];
520     m[3][3] = m[0][3] * other.m[3][0]
521             + m[1][3] * other.m[3][1]
522             + m[2][3] * other.m[3][2]
523             + m[3][3] * other.m[3][3];
524     m[0][3] = m0;
525     m[1][3] = m1;
526     m[2][3] = m2;
527     return *this;
528 }
529 
530 inline QMatrix4x4& QMatrix4x4::operator*=(float factor)
531 {
532     m[0][0] *= factor;
533     m[0][1] *= factor;
534     m[0][2] *= factor;
535     m[0][3] *= factor;
536     m[1][0] *= factor;
537     m[1][1] *= factor;
538     m[1][2] *= factor;
539     m[1][3] *= factor;
540     m[2][0] *= factor;
541     m[2][1] *= factor;
542     m[2][2] *= factor;
543     m[2][3] *= factor;
544     m[3][0] *= factor;
545     m[3][1] *= factor;
546     m[3][2] *= factor;
547     m[3][3] *= factor;
548     flagBits = General;
549     return *this;
550 }
551 
552 inline bool QMatrix4x4::operator==(const QMatrix4x4& other) const
553 {
554     return m[0][0] == other.m[0][0] &&
555            m[0][1] == other.m[0][1] &&
556            m[0][2] == other.m[0][2] &&
557            m[0][3] == other.m[0][3] &&
558            m[1][0] == other.m[1][0] &&
559            m[1][1] == other.m[1][1] &&
560            m[1][2] == other.m[1][2] &&
561            m[1][3] == other.m[1][3] &&
562            m[2][0] == other.m[2][0] &&
563            m[2][1] == other.m[2][1] &&
564            m[2][2] == other.m[2][2] &&
565            m[2][3] == other.m[2][3] &&
566            m[3][0] == other.m[3][0] &&
567            m[3][1] == other.m[3][1] &&
568            m[3][2] == other.m[3][2] &&
569            m[3][3] == other.m[3][3];
570 }
571 
572 inline bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
573 {
574     return m[0][0] != other.m[0][0] ||
575            m[0][1] != other.m[0][1] ||
576            m[0][2] != other.m[0][2] ||
577            m[0][3] != other.m[0][3] ||
578            m[1][0] != other.m[1][0] ||
579            m[1][1] != other.m[1][1] ||
580            m[1][2] != other.m[1][2] ||
581            m[1][3] != other.m[1][3] ||
582            m[2][0] != other.m[2][0] ||
583            m[2][1] != other.m[2][1] ||
584            m[2][2] != other.m[2][2] ||
585            m[2][3] != other.m[2][3] ||
586            m[3][0] != other.m[3][0] ||
587            m[3][1] != other.m[3][1] ||
588            m[3][2] != other.m[3][2] ||
589            m[3][3] != other.m[3][3];
590 }
591 
592 inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
593 {
594     QMatrix4x4 m(1);
595     m.m[0][0] = m1.m[0][0] + m2.m[0][0];
596     m.m[0][1] = m1.m[0][1] + m2.m[0][1];
597     m.m[0][2] = m1.m[0][2] + m2.m[0][2];
598     m.m[0][3] = m1.m[0][3] + m2.m[0][3];
599     m.m[1][0] = m1.m[1][0] + m2.m[1][0];
600     m.m[1][1] = m1.m[1][1] + m2.m[1][1];
601     m.m[1][2] = m1.m[1][2] + m2.m[1][2];
602     m.m[1][3] = m1.m[1][3] + m2.m[1][3];
603     m.m[2][0] = m1.m[2][0] + m2.m[2][0];
604     m.m[2][1] = m1.m[2][1] + m2.m[2][1];
605     m.m[2][2] = m1.m[2][2] + m2.m[2][2];
606     m.m[2][3] = m1.m[2][3] + m2.m[2][3];
607     m.m[3][0] = m1.m[3][0] + m2.m[3][0];
608     m.m[3][1] = m1.m[3][1] + m2.m[3][1];
609     m.m[3][2] = m1.m[3][2] + m2.m[3][2];
610     m.m[3][3] = m1.m[3][3] + m2.m[3][3];
611     m.flagBits = QMatrix4x4::General;
612     return m;
613 }
614 
615 inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
616 {
617     QMatrix4x4 m(1);
618     m.m[0][0] = m1.m[0][0] - m2.m[0][0];
619     m.m[0][1] = m1.m[0][1] - m2.m[0][1];
620     m.m[0][2] = m1.m[0][2] - m2.m[0][2];
621     m.m[0][3] = m1.m[0][3] - m2.m[0][3];
622     m.m[1][0] = m1.m[1][0] - m2.m[1][0];
623     m.m[1][1] = m1.m[1][1] - m2.m[1][1];
624     m.m[1][2] = m1.m[1][2] - m2.m[1][2];
625     m.m[1][3] = m1.m[1][3] - m2.m[1][3];
626     m.m[2][0] = m1.m[2][0] - m2.m[2][0];
627     m.m[2][1] = m1.m[2][1] - m2.m[2][1];
628     m.m[2][2] = m1.m[2][2] - m2.m[2][2];
629     m.m[2][3] = m1.m[2][3] - m2.m[2][3];
630     m.m[3][0] = m1.m[3][0] - m2.m[3][0];
631     m.m[3][1] = m1.m[3][1] - m2.m[3][1];
632     m.m[3][2] = m1.m[3][2] - m2.m[3][2];
633     m.m[3][3] = m1.m[3][3] - m2.m[3][3];
634     m.flagBits = QMatrix4x4::General;
635     return m;
636 }
637 
638 inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
639 {
640     int flagBits = m1.flagBits | m2.flagBits;
641     if (flagBits < QMatrix4x4::Rotation2D) {
642         QMatrix4x4 m = m1;
643         m.m[3][0] += m.m[0][0] * m2.m[3][0];
644         m.m[3][1] += m.m[1][1] * m2.m[3][1];
645         m.m[3][2] += m.m[2][2] * m2.m[3][2];
646 
647         m.m[0][0] *= m2.m[0][0];
648         m.m[1][1] *= m2.m[1][1];
649         m.m[2][2] *= m2.m[2][2];
650         m.flagBits = flagBits;
651         return m;
652     }
653 
654     QMatrix4x4 m(1);
655     m.m[0][0] = m1.m[0][0] * m2.m[0][0]
656               + m1.m[1][0] * m2.m[0][1]
657               + m1.m[2][0] * m2.m[0][2]
658               + m1.m[3][0] * m2.m[0][3];
659     m.m[0][1] = m1.m[0][1] * m2.m[0][0]
660               + m1.m[1][1] * m2.m[0][1]
661               + m1.m[2][1] * m2.m[0][2]
662               + m1.m[3][1] * m2.m[0][3];
663     m.m[0][2] = m1.m[0][2] * m2.m[0][0]
664               + m1.m[1][2] * m2.m[0][1]
665               + m1.m[2][2] * m2.m[0][2]
666               + m1.m[3][2] * m2.m[0][3];
667     m.m[0][3] = m1.m[0][3] * m2.m[0][0]
668               + m1.m[1][3] * m2.m[0][1]
669               + m1.m[2][3] * m2.m[0][2]
670               + m1.m[3][3] * m2.m[0][3];
671 
672     m.m[1][0] = m1.m[0][0] * m2.m[1][0]
673               + m1.m[1][0] * m2.m[1][1]
674               + m1.m[2][0] * m2.m[1][2]
675               + m1.m[3][0] * m2.m[1][3];
676     m.m[1][1] = m1.m[0][1] * m2.m[1][0]
677               + m1.m[1][1] * m2.m[1][1]
678               + m1.m[2][1] * m2.m[1][2]
679               + m1.m[3][1] * m2.m[1][3];
680     m.m[1][2] = m1.m[0][2] * m2.m[1][0]
681               + m1.m[1][2] * m2.m[1][1]
682               + m1.m[2][2] * m2.m[1][2]
683               + m1.m[3][2] * m2.m[1][3];
684     m.m[1][3] = m1.m[0][3] * m2.m[1][0]
685               + m1.m[1][3] * m2.m[1][1]
686               + m1.m[2][3] * m2.m[1][2]
687               + m1.m[3][3] * m2.m[1][3];
688 
689     m.m[2][0] = m1.m[0][0] * m2.m[2][0]
690               + m1.m[1][0] * m2.m[2][1]
691               + m1.m[2][0] * m2.m[2][2]
692               + m1.m[3][0] * m2.m[2][3];
693     m.m[2][1] = m1.m[0][1] * m2.m[2][0]
694               + m1.m[1][1] * m2.m[2][1]
695               + m1.m[2][1] * m2.m[2][2]
696               + m1.m[3][1] * m2.m[2][3];
697     m.m[2][2] = m1.m[0][2] * m2.m[2][0]
698               + m1.m[1][2] * m2.m[2][1]
699               + m1.m[2][2] * m2.m[2][2]
700               + m1.m[3][2] * m2.m[2][3];
701     m.m[2][3] = m1.m[0][3] * m2.m[2][0]
702               + m1.m[1][3] * m2.m[2][1]
703               + m1.m[2][3] * m2.m[2][2]
704               + m1.m[3][3] * m2.m[2][3];
705 
706     m.m[3][0] = m1.m[0][0] * m2.m[3][0]
707               + m1.m[1][0] * m2.m[3][1]
708               + m1.m[2][0] * m2.m[3][2]
709               + m1.m[3][0] * m2.m[3][3];
710     m.m[3][1] = m1.m[0][1] * m2.m[3][0]
711               + m1.m[1][1] * m2.m[3][1]
712               + m1.m[2][1] * m2.m[3][2]
713               + m1.m[3][1] * m2.m[3][3];
714     m.m[3][2] = m1.m[0][2] * m2.m[3][0]
715               + m1.m[1][2] * m2.m[3][1]
716               + m1.m[2][2] * m2.m[3][2]
717               + m1.m[3][2] * m2.m[3][3];
718     m.m[3][3] = m1.m[0][3] * m2.m[3][0]
719               + m1.m[1][3] * m2.m[3][1]
720               + m1.m[2][3] * m2.m[3][2]
721               + m1.m[3][3] * m2.m[3][3];
722     m.flagBits = flagBits;
723     return m;
724 }
725 
726 #ifndef QT_NO_VECTOR3D
727 
728 inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
729 {
730     float x, y, z, w;
731     x = vector.x() * matrix.m[0][0] +
732         vector.y() * matrix.m[0][1] +
733         vector.z() * matrix.m[0][2] +
734         matrix.m[0][3];
735     y = vector.x() * matrix.m[1][0] +
736         vector.y() * matrix.m[1][1] +
737         vector.z() * matrix.m[1][2] +
738         matrix.m[1][3];
739     z = vector.x() * matrix.m[2][0] +
740         vector.y() * matrix.m[2][1] +
741         vector.z() * matrix.m[2][2] +
742         matrix.m[2][3];
743     w = vector.x() * matrix.m[3][0] +
744         vector.y() * matrix.m[3][1] +
745         vector.z() * matrix.m[3][2] +
746         matrix.m[3][3];
747     if (w == 1.0f)
748         return QVector3D(x, y, z);
749     else
750         return QVector3D(x / w, y / w, z / w);
751 }
752 
753 inline QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
754 {
755     float x, y, z, w;
756     if (matrix.flagBits == QMatrix4x4::Identity) {
757         return vector;
758     } else if (matrix.flagBits < QMatrix4x4::Rotation2D) {
759         // Translation | Scale
760         return QVector3D(vector.x() * matrix.m[0][0] + matrix.m[3][0],
761                          vector.y() * matrix.m[1][1] + matrix.m[3][1],
762                          vector.z() * matrix.m[2][2] + matrix.m[3][2]);
763     } else if (matrix.flagBits < QMatrix4x4::Rotation) {
764         // Translation | Scale | Rotation2D
765         return QVector3D(vector.x() * matrix.m[0][0] + vector.y() * matrix.m[1][0] + matrix.m[3][0],
766                          vector.x() * matrix.m[0][1] + vector.y() * matrix.m[1][1] + matrix.m[3][1],
767                          vector.z() * matrix.m[2][2] + matrix.m[3][2]);
768     } else {
769         x = vector.x() * matrix.m[0][0] +
770             vector.y() * matrix.m[1][0] +
771             vector.z() * matrix.m[2][0] +
772             matrix.m[3][0];
773         y = vector.x() * matrix.m[0][1] +
774             vector.y() * matrix.m[1][1] +
775             vector.z() * matrix.m[2][1] +
776             matrix.m[3][1];
777         z = vector.x() * matrix.m[0][2] +
778             vector.y() * matrix.m[1][2] +
779             vector.z() * matrix.m[2][2] +
780             matrix.m[3][2];
781         w = vector.x() * matrix.m[0][3] +
782             vector.y() * matrix.m[1][3] +
783             vector.z() * matrix.m[2][3] +
784             matrix.m[3][3];
785         if (w == 1.0f)
786             return QVector3D(x, y, z);
787         else
788             return QVector3D(x / w, y / w, z / w);
789     }
790 }
791 
792 #endif
793 
794 #ifndef QT_NO_VECTOR4D
795 
796 inline QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
797 {
798     float x, y, z, w;
799     x = vector.x() * matrix.m[0][0] +
800         vector.y() * matrix.m[0][1] +
801         vector.z() * matrix.m[0][2] +
802         vector.w() * matrix.m[0][3];
803     y = vector.x() * matrix.m[1][0] +
804         vector.y() * matrix.m[1][1] +
805         vector.z() * matrix.m[1][2] +
806         vector.w() * matrix.m[1][3];
807     z = vector.x() * matrix.m[2][0] +
808         vector.y() * matrix.m[2][1] +
809         vector.z() * matrix.m[2][2] +
810         vector.w() * matrix.m[2][3];
811     w = vector.x() * matrix.m[3][0] +
812         vector.y() * matrix.m[3][1] +
813         vector.z() * matrix.m[3][2] +
814         vector.w() * matrix.m[3][3];
815     return QVector4D(x, y, z, w);
816 }
817 
818 inline QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
819 {
820     float x, y, z, w;
821     x = vector.x() * matrix.m[0][0] +
822         vector.y() * matrix.m[1][0] +
823         vector.z() * matrix.m[2][0] +
824         vector.w() * matrix.m[3][0];
825     y = vector.x() * matrix.m[0][1] +
826         vector.y() * matrix.m[1][1] +
827         vector.z() * matrix.m[2][1] +
828         vector.w() * matrix.m[3][1];
829     z = vector.x() * matrix.m[0][2] +
830         vector.y() * matrix.m[1][2] +
831         vector.z() * matrix.m[2][2] +
832         vector.w() * matrix.m[3][2];
833     w = vector.x() * matrix.m[0][3] +
834         vector.y() * matrix.m[1][3] +
835         vector.z() * matrix.m[2][3] +
836         vector.w() * matrix.m[3][3];
837     return QVector4D(x, y, z, w);
838 }
839 
840 #endif
841 
842 inline QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
843 {
844     float xin, yin;
845     float x, y, w;
846     xin = point.x();
847     yin = point.y();
848     x = xin * matrix.m[0][0] +
849         yin * matrix.m[0][1] +
850         matrix.m[0][3];
851     y = xin * matrix.m[1][0] +
852         yin * matrix.m[1][1] +
853         matrix.m[1][3];
854     w = xin * matrix.m[3][0] +
855         yin * matrix.m[3][1] +
856         matrix.m[3][3];
857     if (w == 1.0f)
858         return QPoint(qRound(x), qRound(y));
859     else
860         return QPoint(qRound(x / w), qRound(y / w));
861 }
862 
863 inline QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
864 {
865     float xin, yin;
866     float x, y, w;
867     xin = float(point.x());
868     yin = float(point.y());
869     x = xin * matrix.m[0][0] +
870         yin * matrix.m[0][1] +
871         matrix.m[0][3];
872     y = xin * matrix.m[1][0] +
873         yin * matrix.m[1][1] +
874         matrix.m[1][3];
875     w = xin * matrix.m[3][0] +
876         yin * matrix.m[3][1] +
877         matrix.m[3][3];
878     if (w == 1.0f) {
879         return QPointF(qreal(x), qreal(y));
880     } else {
881         return QPointF(qreal(x / w), qreal(y / w));
882     }
883 }
884 
885 inline QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
886 {
887     float xin, yin;
888     float x, y, w;
889     xin = point.x();
890     yin = point.y();
891     if (matrix.flagBits == QMatrix4x4::Identity) {
892         return point;
893     } else if (matrix.flagBits < QMatrix4x4::Rotation2D) {
894         // Translation | Scale
895         return QPoint(qRound(xin * matrix.m[0][0] + matrix.m[3][0]),
896                       qRound(yin * matrix.m[1][1] + matrix.m[3][1]));
897     } else if (matrix.flagBits < QMatrix4x4::Perspective) {
898         return QPoint(qRound(xin * matrix.m[0][0] + yin * matrix.m[1][0] + matrix.m[3][0]),
899                       qRound(xin * matrix.m[0][1] + yin * matrix.m[1][1] + matrix.m[3][1]));
900     } else {
901         x = xin * matrix.m[0][0] +
902             yin * matrix.m[1][0] +
903             matrix.m[3][0];
904         y = xin * matrix.m[0][1] +
905             yin * matrix.m[1][1] +
906             matrix.m[3][1];
907         w = xin * matrix.m[0][3] +
908             yin * matrix.m[1][3] +
909             matrix.m[3][3];
910         if (w == 1.0f)
911             return QPoint(qRound(x), qRound(y));
912         else
913             return QPoint(qRound(x / w), qRound(y / w));
914     }
915 }
916 
917 inline QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
918 {
919     qreal xin, yin;
920     qreal x, y, w;
921     xin = point.x();
922     yin = point.y();
923     if (matrix.flagBits == QMatrix4x4::Identity) {
924         return point;
925     } else if (matrix.flagBits < QMatrix4x4::Rotation2D) {
926         // Translation | Scale
927         return QPointF(xin * qreal(matrix.m[0][0]) + qreal(matrix.m[3][0]),
928                        yin * qreal(matrix.m[1][1]) + qreal(matrix.m[3][1]));
929     } else if (matrix.flagBits < QMatrix4x4::Perspective) {
930         return QPointF(xin * qreal(matrix.m[0][0]) + yin * qreal(matrix.m[1][0]) +
931                        qreal(matrix.m[3][0]),
932                        xin * qreal(matrix.m[0][1]) + yin * qreal(matrix.m[1][1]) +
933                        qreal(matrix.m[3][1]));
934     } else {
935         x = xin * qreal(matrix.m[0][0]) +
936             yin * qreal(matrix.m[1][0]) +
937             qreal(matrix.m[3][0]);
938         y = xin * qreal(matrix.m[0][1]) +
939             yin * qreal(matrix.m[1][1]) +
940             qreal(matrix.m[3][1]);
941         w = xin * qreal(matrix.m[0][3]) +
942             yin * qreal(matrix.m[1][3]) +
943             qreal(matrix.m[3][3]);
944         if (w == 1.0) {
945             return QPointF(qreal(x), qreal(y));
946         } else {
947             return QPointF(qreal(x / w), qreal(y / w));
948         }
949     }
950 }
951 
952 inline QMatrix4x4 operator-(const QMatrix4x4& matrix)
953 {
954     QMatrix4x4 m(1);
955     m.m[0][0] = -matrix.m[0][0];
956     m.m[0][1] = -matrix.m[0][1];
957     m.m[0][2] = -matrix.m[0][2];
958     m.m[0][3] = -matrix.m[0][3];
959     m.m[1][0] = -matrix.m[1][0];
960     m.m[1][1] = -matrix.m[1][1];
961     m.m[1][2] = -matrix.m[1][2];
962     m.m[1][3] = -matrix.m[1][3];
963     m.m[2][0] = -matrix.m[2][0];
964     m.m[2][1] = -matrix.m[2][1];
965     m.m[2][2] = -matrix.m[2][2];
966     m.m[2][3] = -matrix.m[2][3];
967     m.m[3][0] = -matrix.m[3][0];
968     m.m[3][1] = -matrix.m[3][1];
969     m.m[3][2] = -matrix.m[3][2];
970     m.m[3][3] = -matrix.m[3][3];
971     m.flagBits = QMatrix4x4::General;
972     return m;
973 }
974 
975 inline QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix)
976 {
977     QMatrix4x4 m(1);
978     m.m[0][0] = matrix.m[0][0] * factor;
979     m.m[0][1] = matrix.m[0][1] * factor;
980     m.m[0][2] = matrix.m[0][2] * factor;
981     m.m[0][3] = matrix.m[0][3] * factor;
982     m.m[1][0] = matrix.m[1][0] * factor;
983     m.m[1][1] = matrix.m[1][1] * factor;
984     m.m[1][2] = matrix.m[1][2] * factor;
985     m.m[1][3] = matrix.m[1][3] * factor;
986     m.m[2][0] = matrix.m[2][0] * factor;
987     m.m[2][1] = matrix.m[2][1] * factor;
988     m.m[2][2] = matrix.m[2][2] * factor;
989     m.m[2][3] = matrix.m[2][3] * factor;
990     m.m[3][0] = matrix.m[3][0] * factor;
991     m.m[3][1] = matrix.m[3][1] * factor;
992     m.m[3][2] = matrix.m[3][2] * factor;
993     m.m[3][3] = matrix.m[3][3] * factor;
994     m.flagBits = QMatrix4x4::General;
995     return m;
996 }
997 
998 inline QMatrix4x4 operator*(const QMatrix4x4& matrix, float factor)
999 {
1000     QMatrix4x4 m(1);
1001     m.m[0][0] = matrix.m[0][0] * factor;
1002     m.m[0][1] = matrix.m[0][1] * factor;
1003     m.m[0][2] = matrix.m[0][2] * factor;
1004     m.m[0][3] = matrix.m[0][3] * factor;
1005     m.m[1][0] = matrix.m[1][0] * factor;
1006     m.m[1][1] = matrix.m[1][1] * factor;
1007     m.m[1][2] = matrix.m[1][2] * factor;
1008     m.m[1][3] = matrix.m[1][3] * factor;
1009     m.m[2][0] = matrix.m[2][0] * factor;
1010     m.m[2][1] = matrix.m[2][1] * factor;
1011     m.m[2][2] = matrix.m[2][2] * factor;
1012     m.m[2][3] = matrix.m[2][3] * factor;
1013     m.m[3][0] = matrix.m[3][0] * factor;
1014     m.m[3][1] = matrix.m[3][1] * factor;
1015     m.m[3][2] = matrix.m[3][2] * factor;
1016     m.m[3][3] = matrix.m[3][3] * factor;
1017     m.flagBits = QMatrix4x4::General;
1018     return m;
1019 }
1020 
qFuzzyCompare(const QMatrix4x4 & m1,const QMatrix4x4 & m2)1021 inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
1022 {
1023     return qFuzzyCompare(m1.m[0][0], m2.m[0][0]) &&
1024            qFuzzyCompare(m1.m[0][1], m2.m[0][1]) &&
1025            qFuzzyCompare(m1.m[0][2], m2.m[0][2]) &&
1026            qFuzzyCompare(m1.m[0][3], m2.m[0][3]) &&
1027            qFuzzyCompare(m1.m[1][0], m2.m[1][0]) &&
1028            qFuzzyCompare(m1.m[1][1], m2.m[1][1]) &&
1029            qFuzzyCompare(m1.m[1][2], m2.m[1][2]) &&
1030            qFuzzyCompare(m1.m[1][3], m2.m[1][3]) &&
1031            qFuzzyCompare(m1.m[2][0], m2.m[2][0]) &&
1032            qFuzzyCompare(m1.m[2][1], m2.m[2][1]) &&
1033            qFuzzyCompare(m1.m[2][2], m2.m[2][2]) &&
1034            qFuzzyCompare(m1.m[2][3], m2.m[2][3]) &&
1035            qFuzzyCompare(m1.m[3][0], m2.m[3][0]) &&
1036            qFuzzyCompare(m1.m[3][1], m2.m[3][1]) &&
1037            qFuzzyCompare(m1.m[3][2], m2.m[3][2]) &&
1038            qFuzzyCompare(m1.m[3][3], m2.m[3][3]);
1039 }
1040 
map(const QPoint & point)1041 inline QPoint QMatrix4x4::map(const QPoint& point) const
1042 {
1043     return *this * point;
1044 }
1045 
map(const QPointF & point)1046 inline QPointF QMatrix4x4::map(const QPointF& point) const
1047 {
1048     return *this * point;
1049 }
1050 
1051 #ifndef QT_NO_VECTOR3D
1052 
map(const QVector3D & point)1053 inline QVector3D QMatrix4x4::map(const QVector3D& point) const
1054 {
1055     return *this * point;
1056 }
1057 
mapVector(const QVector3D & vector)1058 inline QVector3D QMatrix4x4::mapVector(const QVector3D& vector) const
1059 {
1060     if (flagBits < Scale) {
1061         // Translation
1062         return vector;
1063     } else if (flagBits < Rotation2D) {
1064         // Translation | Scale
1065         return QVector3D(vector.x() * m[0][0],
1066                          vector.y() * m[1][1],
1067                          vector.z() * m[2][2]);
1068     } else {
1069         return QVector3D(vector.x() * m[0][0] +
1070                          vector.y() * m[1][0] +
1071                          vector.z() * m[2][0],
1072                          vector.x() * m[0][1] +
1073                          vector.y() * m[1][1] +
1074                          vector.z() * m[2][1],
1075                          vector.x() * m[0][2] +
1076                          vector.y() * m[1][2] +
1077                          vector.z() * m[2][2]);
1078     }
1079 }
1080 
1081 #endif
1082 
1083 #ifndef QT_NO_VECTOR4D
1084 
map(const QVector4D & point)1085 inline QVector4D QMatrix4x4::map(const QVector4D& point) const
1086 {
1087     return *this * point;
1088 }
1089 
1090 #endif
1091 
data()1092 inline float *QMatrix4x4::data()
1093 {
1094     // We have to assume that the caller will modify the matrix elements,
1095     // so we flip it over to "General" mode.
1096     flagBits = General;
1097     return *m;
1098 }
1099 
viewport(const QRectF & rect)1100 inline void QMatrix4x4::viewport(const QRectF &rect)
1101 {
1102     viewport(float(rect.x()), float(rect.y()), float(rect.width()), float(rect.height()));
1103 }
1104 
1105 QT_WARNING_POP
1106 
1107 #ifndef QT_NO_DEBUG_STREAM
1108 Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
1109 #endif
1110 
1111 #ifndef QT_NO_DATASTREAM
1112 Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &);
1113 Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &);
1114 #endif
1115 
1116 #if QT_DEPRECATED_SINCE(5, 0)
1117 template <int N, int M>
qGenericMatrixToMatrix4x4(const QGenericMatrix<N,M,float> & matrix)1118 QT_DEPRECATED QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, float>& matrix)
1119 {
1120     return QMatrix4x4(matrix.constData(), N, M);
1121 }
1122 
1123 template <int N, int M>
qGenericMatrixFromMatrix4x4(const QMatrix4x4 & matrix)1124 QT_DEPRECATED QGenericMatrix<N, M, float> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
1125 {
1126     QGenericMatrix<N, M, float> result;
1127     const float *m = matrix.constData();
1128     float *values = result.data();
1129     for (int col = 0; col < N; ++col) {
1130         for (int row = 0; row < M; ++row) {
1131             if (col < 4 && row < 4)
1132                 values[col * M + row] = m[col * 4 + row];
1133             else if (col == row)
1134                 values[col * M + row] = 1.0f;
1135             else
1136                 values[col * M + row] = 0.0f;
1137         }
1138     }
1139     return result;
1140 }
1141 #endif
1142 
1143 #endif
1144 
1145 QT_END_NAMESPACE
1146 
1147 #endif
1148