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 QDOUBLEMATRIX4X4_H
41 #define QDOUBLEMATRIX4X4_H
42 
43 //
44 //  W A R N I N G
45 //  -------------
46 //
47 // This file is not part of the Qt API.  It exists purely as an
48 // implementation detail.  This header file may change from version to
49 // version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include <QtPositioning/private/qpositioningglobal_p.h>
55 #include <QtPositioning/private/qdoublevector3d_p.h>
56 #include <QtCore/QDebug>
57 #include <QtCore/qmetatype.h>
58 #include <QtCore/QRectF>
59 
60 QT_BEGIN_NAMESPACE
61 
62 /*
63  * This class is a copy/paste/replace of QMatrix4x4
64  * No algorithm has been changed.
65  * Some methods have been removed.
66  */
67 
68 class Q_POSITIONING_PRIVATE_EXPORT QDoubleMatrix4x4
69 {
70 public:
QDoubleMatrix4x4()71     inline QDoubleMatrix4x4() { setToIdentity(); }
QDoubleMatrix4x4(Qt::Initialization)72     explicit QDoubleMatrix4x4(Qt::Initialization) : flagBits(General) {}
73     explicit QDoubleMatrix4x4(const double *values);
74     inline QDoubleMatrix4x4(double m11, double m12, double m13, double m14,
75                       double m21, double m22, double m23, double m24,
76                       double m31, double m32, double m33, double m34,
77                       double m41, double m42, double m43, double m44);
78 
79     QDoubleMatrix4x4(const double *values, int cols, int rows);
80 
81     inline const double& operator()(int row, int column) const;
82     inline double& operator()(int row, int column);
83 
84     inline bool isAffine() const;
85 
86     inline bool isIdentity() const;
87     inline void setToIdentity();
88 
89     inline void fill(double value);
90 
91     double determinant() const;
92     QDoubleMatrix4x4 inverted(bool *invertible = nullptr) const;
93     QDoubleMatrix4x4 transposed() const;
94 
95     inline QDoubleMatrix4x4& operator+=(const QDoubleMatrix4x4& other);
96     inline QDoubleMatrix4x4& operator-=(const QDoubleMatrix4x4& other);
97     inline QDoubleMatrix4x4& operator*=(const QDoubleMatrix4x4& other);
98     inline QDoubleMatrix4x4& operator*=(double factor);
99     QDoubleMatrix4x4& operator/=(double divisor);
100     inline bool operator==(const QDoubleMatrix4x4& other) const;
101     inline bool operator!=(const QDoubleMatrix4x4& other) const;
102 
103     friend QDoubleMatrix4x4 operator+(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2);
104     friend QDoubleMatrix4x4 operator-(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2);
105     friend QDoubleMatrix4x4 operator*(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2);
106 
107     friend QDoubleVector3D operator*(const QDoubleMatrix4x4& matrix, const QDoubleVector3D& vector);
108     friend QDoubleVector3D operator*(const QDoubleVector3D& vector, const QDoubleMatrix4x4& matrix);
109 
110     friend QPoint operator*(const QPoint& point, const QDoubleMatrix4x4& matrix);
111     friend QPointF operator*(const QPointF& point, const QDoubleMatrix4x4& matrix);
112     friend QDoubleMatrix4x4 operator-(const QDoubleMatrix4x4& matrix);
113     friend QPoint operator*(const QDoubleMatrix4x4& matrix, const QPoint& point);
114     friend QPointF operator*(const QDoubleMatrix4x4& matrix, const QPointF& point);
115     friend QDoubleMatrix4x4 operator*(double factor, const QDoubleMatrix4x4& matrix);
116     friend QDoubleMatrix4x4 operator*(const QDoubleMatrix4x4& matrix, double factor);
117     friend Q_POSITIONING_PRIVATE_EXPORT QDoubleMatrix4x4 operator/(const QDoubleMatrix4x4& matrix, double divisor);
118 
119     friend inline bool qFuzzyCompare(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2);
120 
121 
122     void scale(const QDoubleVector3D& vector);
123     void translate(const QDoubleVector3D& vector);
124     void rotate(double angle, const QDoubleVector3D& vector);
125 
126     void scale(double x, double y);
127     void scale(double x, double y, double z);
128     void scale(double factor);
129     void translate(double x, double y);
130     void translate(double x, double y, double z);
131     void rotate(double angle, double x, double y, double z = 0.0f);
132 
133     void ortho(const QRect& rect);
134     void ortho(const QRectF& rect);
135     void ortho(double left, double right, double bottom, double top, double nearPlane, double farPlane);
136     void frustum(double left, double right, double bottom, double top, double nearPlane, double farPlane);
137     void perspective(double verticalAngle, double aspectRatio, double nearPlane, double farPlane);
138 
139     void lookAt(const QDoubleVector3D& eye, const QDoubleVector3D& center, const QDoubleVector3D& up);
140 
141     void viewport(const QRectF &rect);
142     void viewport(double left, double bottom, double width, double height, double nearPlane = 0.0f, double farPlane = 1.0f);
143     void flipCoordinates();
144 
145     void copyDataTo(double *values) const;
146 
147     QPoint map(const QPoint& point) const;
148     QPointF map(const QPointF& point) const;
149 
150     QDoubleVector3D map(const QDoubleVector3D& point) const;
151     QDoubleVector3D mapVector(const QDoubleVector3D& vector) const;
152 
153     QRect mapRect(const QRect& rect) const;
154     QRectF mapRect(const QRectF& rect) const;
155 
156     inline double *data();
data()157     inline const double *data() const { return *m; }
constData()158     inline const double *constData() const { return *m; }
159 
160     void optimize();
161 
162 #ifndef QT_NO_DEBUG_STREAM
163     friend Q_POSITIONING_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QDoubleMatrix4x4 &m);
164 #endif
165 
166 private:
167     double m[4][4];          // Column-major order to match OpenGL.
168     int flagBits;           // Flag bits from the enum below.
169 
170     // When matrices are multiplied, the flag bits are or-ed together.
171     enum {
172         Identity        = 0x0000, // Identity matrix
173         Translation     = 0x0001, // Contains a translation
174         Scale           = 0x0002, // Contains a scale
175         Rotation2D      = 0x0004, // Contains a rotation about the Z axis
176         Rotation        = 0x0008, // Contains an arbitrary rotation
177         Perspective     = 0x0010, // Last row is different from (0, 0, 0, 1)
178         General         = 0x001f  // General matrix, unknown contents
179     };
180 
181     // Construct without initializing identity matrix.
QDoubleMatrix4x4(int)182     explicit QDoubleMatrix4x4(int) { }
183 
184     QDoubleMatrix4x4 orthonormalInverse() const;
185 
186     void projectedRotate(double angle, double x, double y, double z);
187 };
188 
189 Q_DECLARE_TYPEINFO(QDoubleMatrix4x4, Q_MOVABLE_TYPE);
190 
QDoubleMatrix4x4(double m11,double m12,double m13,double m14,double m21,double m22,double m23,double m24,double m31,double m32,double m33,double m34,double m41,double m42,double m43,double m44)191 inline QDoubleMatrix4x4::QDoubleMatrix4x4
192         (double m11, double m12, double m13, double m14,
193          double m21, double m22, double m23, double m24,
194          double m31, double m32, double m33, double m34,
195          double m41, double m42, double m43, double m44)
196 {
197     m[0][0] = m11; m[0][1] = m21; m[0][2] = m31; m[0][3] = m41;
198     m[1][0] = m12; m[1][1] = m22; m[1][2] = m32; m[1][3] = m42;
199     m[2][0] = m13; m[2][1] = m23; m[2][2] = m33; m[2][3] = m43;
200     m[3][0] = m14; m[3][1] = m24; m[3][2] = m34; m[3][3] = m44;
201     flagBits = General;
202 }
203 
operator()204 inline const double& QDoubleMatrix4x4::operator()(int aRow, int aColumn) const
205 {
206     Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
207     return m[aColumn][aRow];
208 }
209 
operator()210 inline double& QDoubleMatrix4x4::operator()(int aRow, int aColumn)
211 {
212     Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
213     flagBits = General;
214     return m[aColumn][aRow];
215 }
216 
217 Q_POSITIONING_PRIVATE_EXPORT QDoubleMatrix4x4 operator/(const QDoubleMatrix4x4& matrix, double divisor);
218 
isAffine()219 inline bool QDoubleMatrix4x4::isAffine() const
220 {
221     return m[0][3] == 0.0f && m[1][3] == 0.0f && m[2][3] == 0.0f && m[3][3] == 1.0f;
222 }
223 
isIdentity()224 inline bool QDoubleMatrix4x4::isIdentity() const
225 {
226     if (flagBits == Identity)
227         return true;
228     if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f)
229         return false;
230     if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f)
231         return false;
232     if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f)
233         return false;
234     if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f)
235         return false;
236     if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f)
237         return false;
238     return (m[3][3] == 1.0f);
239 }
240 
setToIdentity()241 inline void QDoubleMatrix4x4::setToIdentity()
242 {
243     m[0][0] = 1.0f;
244     m[0][1] = 0.0f;
245     m[0][2] = 0.0f;
246     m[0][3] = 0.0f;
247     m[1][0] = 0.0f;
248     m[1][1] = 1.0f;
249     m[1][2] = 0.0f;
250     m[1][3] = 0.0f;
251     m[2][0] = 0.0f;
252     m[2][1] = 0.0f;
253     m[2][2] = 1.0f;
254     m[2][3] = 0.0f;
255     m[3][0] = 0.0f;
256     m[3][1] = 0.0f;
257     m[3][2] = 0.0f;
258     m[3][3] = 1.0f;
259     flagBits = Identity;
260 }
261 
fill(double value)262 inline void QDoubleMatrix4x4::fill(double value)
263 {
264     m[0][0] = value;
265     m[0][1] = value;
266     m[0][2] = value;
267     m[0][3] = value;
268     m[1][0] = value;
269     m[1][1] = value;
270     m[1][2] = value;
271     m[1][3] = value;
272     m[2][0] = value;
273     m[2][1] = value;
274     m[2][2] = value;
275     m[2][3] = value;
276     m[3][0] = value;
277     m[3][1] = value;
278     m[3][2] = value;
279     m[3][3] = value;
280     flagBits = General;
281 }
282 
283 inline QDoubleMatrix4x4& QDoubleMatrix4x4::operator+=(const QDoubleMatrix4x4& other)
284 {
285     m[0][0] += other.m[0][0];
286     m[0][1] += other.m[0][1];
287     m[0][2] += other.m[0][2];
288     m[0][3] += other.m[0][3];
289     m[1][0] += other.m[1][0];
290     m[1][1] += other.m[1][1];
291     m[1][2] += other.m[1][2];
292     m[1][3] += other.m[1][3];
293     m[2][0] += other.m[2][0];
294     m[2][1] += other.m[2][1];
295     m[2][2] += other.m[2][2];
296     m[2][3] += other.m[2][3];
297     m[3][0] += other.m[3][0];
298     m[3][1] += other.m[3][1];
299     m[3][2] += other.m[3][2];
300     m[3][3] += other.m[3][3];
301     flagBits = General;
302     return *this;
303 }
304 
305 inline QDoubleMatrix4x4& QDoubleMatrix4x4::operator-=(const QDoubleMatrix4x4& other)
306 {
307     m[0][0] -= other.m[0][0];
308     m[0][1] -= other.m[0][1];
309     m[0][2] -= other.m[0][2];
310     m[0][3] -= other.m[0][3];
311     m[1][0] -= other.m[1][0];
312     m[1][1] -= other.m[1][1];
313     m[1][2] -= other.m[1][2];
314     m[1][3] -= other.m[1][3];
315     m[2][0] -= other.m[2][0];
316     m[2][1] -= other.m[2][1];
317     m[2][2] -= other.m[2][2];
318     m[2][3] -= other.m[2][3];
319     m[3][0] -= other.m[3][0];
320     m[3][1] -= other.m[3][1];
321     m[3][2] -= other.m[3][2];
322     m[3][3] -= other.m[3][3];
323     flagBits = General;
324     return *this;
325 }
326 
327 inline QDoubleMatrix4x4& QDoubleMatrix4x4::operator*=(const QDoubleMatrix4x4& other)
328 {
329     flagBits |= other.flagBits;
330 
331     if (flagBits < Rotation2D) {
332         m[3][0] += m[0][0] * other.m[3][0];
333         m[3][1] += m[1][1] * other.m[3][1];
334         m[3][2] += m[2][2] * other.m[3][2];
335 
336         m[0][0] *= other.m[0][0];
337         m[1][1] *= other.m[1][1];
338         m[2][2] *= other.m[2][2];
339         return *this;
340     }
341 
342     double m0, m1, m2;
343     m0 = m[0][0] * other.m[0][0]
344             + m[1][0] * other.m[0][1]
345             + m[2][0] * other.m[0][2]
346             + m[3][0] * other.m[0][3];
347     m1 = m[0][0] * other.m[1][0]
348             + m[1][0] * other.m[1][1]
349             + m[2][0] * other.m[1][2]
350             + m[3][0] * other.m[1][3];
351     m2 = m[0][0] * other.m[2][0]
352             + m[1][0] * other.m[2][1]
353             + m[2][0] * other.m[2][2]
354             + m[3][0] * other.m[2][3];
355     m[3][0] = m[0][0] * other.m[3][0]
356             + m[1][0] * other.m[3][1]
357             + m[2][0] * other.m[3][2]
358             + m[3][0] * other.m[3][3];
359     m[0][0] = m0;
360     m[1][0] = m1;
361     m[2][0] = m2;
362 
363     m0 = m[0][1] * other.m[0][0]
364             + m[1][1] * other.m[0][1]
365             + m[2][1] * other.m[0][2]
366             + m[3][1] * other.m[0][3];
367     m1 = m[0][1] * other.m[1][0]
368             + m[1][1] * other.m[1][1]
369             + m[2][1] * other.m[1][2]
370             + m[3][1] * other.m[1][3];
371     m2 = m[0][1] * other.m[2][0]
372             + m[1][1] * other.m[2][1]
373             + m[2][1] * other.m[2][2]
374             + m[3][1] * other.m[2][3];
375     m[3][1] = m[0][1] * other.m[3][0]
376             + m[1][1] * other.m[3][1]
377             + m[2][1] * other.m[3][2]
378             + m[3][1] * other.m[3][3];
379     m[0][1] = m0;
380     m[1][1] = m1;
381     m[2][1] = m2;
382 
383     m0 = m[0][2] * other.m[0][0]
384             + m[1][2] * other.m[0][1]
385             + m[2][2] * other.m[0][2]
386             + m[3][2] * other.m[0][3];
387     m1 = m[0][2] * other.m[1][0]
388             + m[1][2] * other.m[1][1]
389             + m[2][2] * other.m[1][2]
390             + m[3][2] * other.m[1][3];
391     m2 = m[0][2] * other.m[2][0]
392             + m[1][2] * other.m[2][1]
393             + m[2][2] * other.m[2][2]
394             + m[3][2] * other.m[2][3];
395     m[3][2] = m[0][2] * other.m[3][0]
396             + m[1][2] * other.m[3][1]
397             + m[2][2] * other.m[3][2]
398             + m[3][2] * other.m[3][3];
399     m[0][2] = m0;
400     m[1][2] = m1;
401     m[2][2] = m2;
402 
403     m0 = m[0][3] * other.m[0][0]
404             + m[1][3] * other.m[0][1]
405             + m[2][3] * other.m[0][2]
406             + m[3][3] * other.m[0][3];
407     m1 = m[0][3] * other.m[1][0]
408             + m[1][3] * other.m[1][1]
409             + m[2][3] * other.m[1][2]
410             + m[3][3] * other.m[1][3];
411     m2 = m[0][3] * other.m[2][0]
412             + m[1][3] * other.m[2][1]
413             + m[2][3] * other.m[2][2]
414             + m[3][3] * other.m[2][3];
415     m[3][3] = m[0][3] * other.m[3][0]
416             + m[1][3] * other.m[3][1]
417             + m[2][3] * other.m[3][2]
418             + m[3][3] * other.m[3][3];
419     m[0][3] = m0;
420     m[1][3] = m1;
421     m[2][3] = m2;
422     return *this;
423 }
424 
425 inline QDoubleMatrix4x4& QDoubleMatrix4x4::operator*=(double factor)
426 {
427     m[0][0] *= factor;
428     m[0][1] *= factor;
429     m[0][2] *= factor;
430     m[0][3] *= factor;
431     m[1][0] *= factor;
432     m[1][1] *= factor;
433     m[1][2] *= factor;
434     m[1][3] *= factor;
435     m[2][0] *= factor;
436     m[2][1] *= factor;
437     m[2][2] *= factor;
438     m[2][3] *= factor;
439     m[3][0] *= factor;
440     m[3][1] *= factor;
441     m[3][2] *= factor;
442     m[3][3] *= factor;
443     flagBits = General;
444     return *this;
445 }
446 
447 inline bool QDoubleMatrix4x4::operator==(const QDoubleMatrix4x4& other) const
448 {
449     return m[0][0] == other.m[0][0] &&
450            m[0][1] == other.m[0][1] &&
451            m[0][2] == other.m[0][2] &&
452            m[0][3] == other.m[0][3] &&
453            m[1][0] == other.m[1][0] &&
454            m[1][1] == other.m[1][1] &&
455            m[1][2] == other.m[1][2] &&
456            m[1][3] == other.m[1][3] &&
457            m[2][0] == other.m[2][0] &&
458            m[2][1] == other.m[2][1] &&
459            m[2][2] == other.m[2][2] &&
460            m[2][3] == other.m[2][3] &&
461            m[3][0] == other.m[3][0] &&
462            m[3][1] == other.m[3][1] &&
463            m[3][2] == other.m[3][2] &&
464            m[3][3] == other.m[3][3];
465 }
466 
467 inline bool QDoubleMatrix4x4::operator!=(const QDoubleMatrix4x4& other) const
468 {
469     return m[0][0] != other.m[0][0] ||
470            m[0][1] != other.m[0][1] ||
471            m[0][2] != other.m[0][2] ||
472            m[0][3] != other.m[0][3] ||
473            m[1][0] != other.m[1][0] ||
474            m[1][1] != other.m[1][1] ||
475            m[1][2] != other.m[1][2] ||
476            m[1][3] != other.m[1][3] ||
477            m[2][0] != other.m[2][0] ||
478            m[2][1] != other.m[2][1] ||
479            m[2][2] != other.m[2][2] ||
480            m[2][3] != other.m[2][3] ||
481            m[3][0] != other.m[3][0] ||
482            m[3][1] != other.m[3][1] ||
483            m[3][2] != other.m[3][2] ||
484            m[3][3] != other.m[3][3];
485 }
486 
487 inline QDoubleMatrix4x4 operator+(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2)
488 {
489     QDoubleMatrix4x4 m(1);
490     m.m[0][0] = m1.m[0][0] + m2.m[0][0];
491     m.m[0][1] = m1.m[0][1] + m2.m[0][1];
492     m.m[0][2] = m1.m[0][2] + m2.m[0][2];
493     m.m[0][3] = m1.m[0][3] + m2.m[0][3];
494     m.m[1][0] = m1.m[1][0] + m2.m[1][0];
495     m.m[1][1] = m1.m[1][1] + m2.m[1][1];
496     m.m[1][2] = m1.m[1][2] + m2.m[1][2];
497     m.m[1][3] = m1.m[1][3] + m2.m[1][3];
498     m.m[2][0] = m1.m[2][0] + m2.m[2][0];
499     m.m[2][1] = m1.m[2][1] + m2.m[2][1];
500     m.m[2][2] = m1.m[2][2] + m2.m[2][2];
501     m.m[2][3] = m1.m[2][3] + m2.m[2][3];
502     m.m[3][0] = m1.m[3][0] + m2.m[3][0];
503     m.m[3][1] = m1.m[3][1] + m2.m[3][1];
504     m.m[3][2] = m1.m[3][2] + m2.m[3][2];
505     m.m[3][3] = m1.m[3][3] + m2.m[3][3];
506     m.flagBits = QDoubleMatrix4x4::General;
507     return m;
508 }
509 
510 inline QDoubleMatrix4x4 operator-(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2)
511 {
512     QDoubleMatrix4x4 m(1);
513     m.m[0][0] = m1.m[0][0] - m2.m[0][0];
514     m.m[0][1] = m1.m[0][1] - m2.m[0][1];
515     m.m[0][2] = m1.m[0][2] - m2.m[0][2];
516     m.m[0][3] = m1.m[0][3] - m2.m[0][3];
517     m.m[1][0] = m1.m[1][0] - m2.m[1][0];
518     m.m[1][1] = m1.m[1][1] - m2.m[1][1];
519     m.m[1][2] = m1.m[1][2] - m2.m[1][2];
520     m.m[1][3] = m1.m[1][3] - m2.m[1][3];
521     m.m[2][0] = m1.m[2][0] - m2.m[2][0];
522     m.m[2][1] = m1.m[2][1] - m2.m[2][1];
523     m.m[2][2] = m1.m[2][2] - m2.m[2][2];
524     m.m[2][3] = m1.m[2][3] - m2.m[2][3];
525     m.m[3][0] = m1.m[3][0] - m2.m[3][0];
526     m.m[3][1] = m1.m[3][1] - m2.m[3][1];
527     m.m[3][2] = m1.m[3][2] - m2.m[3][2];
528     m.m[3][3] = m1.m[3][3] - m2.m[3][3];
529     m.flagBits = QDoubleMatrix4x4::General;
530     return m;
531 }
532 
533 inline QDoubleMatrix4x4 operator*(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2)
534 {
535     int flagBits = m1.flagBits | m2.flagBits;
536     if (flagBits < QDoubleMatrix4x4::Rotation2D) {
537         QDoubleMatrix4x4 m = m1;
538         m.m[3][0] += m.m[0][0] * m2.m[3][0];
539         m.m[3][1] += m.m[1][1] * m2.m[3][1];
540         m.m[3][2] += m.m[2][2] * m2.m[3][2];
541 
542         m.m[0][0] *= m2.m[0][0];
543         m.m[1][1] *= m2.m[1][1];
544         m.m[2][2] *= m2.m[2][2];
545         m.flagBits = flagBits;
546         return m;
547     }
548 
549     QDoubleMatrix4x4 m(1);
550     m.m[0][0] = m1.m[0][0] * m2.m[0][0]
551               + m1.m[1][0] * m2.m[0][1]
552               + m1.m[2][0] * m2.m[0][2]
553               + m1.m[3][0] * m2.m[0][3];
554     m.m[0][1] = m1.m[0][1] * m2.m[0][0]
555               + m1.m[1][1] * m2.m[0][1]
556               + m1.m[2][1] * m2.m[0][2]
557               + m1.m[3][1] * m2.m[0][3];
558     m.m[0][2] = m1.m[0][2] * m2.m[0][0]
559               + m1.m[1][2] * m2.m[0][1]
560               + m1.m[2][2] * m2.m[0][2]
561               + m1.m[3][2] * m2.m[0][3];
562     m.m[0][3] = m1.m[0][3] * m2.m[0][0]
563               + m1.m[1][3] * m2.m[0][1]
564               + m1.m[2][3] * m2.m[0][2]
565               + m1.m[3][3] * m2.m[0][3];
566 
567     m.m[1][0] = m1.m[0][0] * m2.m[1][0]
568               + m1.m[1][0] * m2.m[1][1]
569               + m1.m[2][0] * m2.m[1][2]
570               + m1.m[3][0] * m2.m[1][3];
571     m.m[1][1] = m1.m[0][1] * m2.m[1][0]
572               + m1.m[1][1] * m2.m[1][1]
573               + m1.m[2][1] * m2.m[1][2]
574               + m1.m[3][1] * m2.m[1][3];
575     m.m[1][2] = m1.m[0][2] * m2.m[1][0]
576               + m1.m[1][2] * m2.m[1][1]
577               + m1.m[2][2] * m2.m[1][2]
578               + m1.m[3][2] * m2.m[1][3];
579     m.m[1][3] = m1.m[0][3] * m2.m[1][0]
580               + m1.m[1][3] * m2.m[1][1]
581               + m1.m[2][3] * m2.m[1][2]
582               + m1.m[3][3] * m2.m[1][3];
583 
584     m.m[2][0] = m1.m[0][0] * m2.m[2][0]
585               + m1.m[1][0] * m2.m[2][1]
586               + m1.m[2][0] * m2.m[2][2]
587               + m1.m[3][0] * m2.m[2][3];
588     m.m[2][1] = m1.m[0][1] * m2.m[2][0]
589               + m1.m[1][1] * m2.m[2][1]
590               + m1.m[2][1] * m2.m[2][2]
591               + m1.m[3][1] * m2.m[2][3];
592     m.m[2][2] = m1.m[0][2] * m2.m[2][0]
593               + m1.m[1][2] * m2.m[2][1]
594               + m1.m[2][2] * m2.m[2][2]
595               + m1.m[3][2] * m2.m[2][3];
596     m.m[2][3] = m1.m[0][3] * m2.m[2][0]
597               + m1.m[1][3] * m2.m[2][1]
598               + m1.m[2][3] * m2.m[2][2]
599               + m1.m[3][3] * m2.m[2][3];
600 
601     m.m[3][0] = m1.m[0][0] * m2.m[3][0]
602               + m1.m[1][0] * m2.m[3][1]
603               + m1.m[2][0] * m2.m[3][2]
604               + m1.m[3][0] * m2.m[3][3];
605     m.m[3][1] = m1.m[0][1] * m2.m[3][0]
606               + m1.m[1][1] * m2.m[3][1]
607               + m1.m[2][1] * m2.m[3][2]
608               + m1.m[3][1] * m2.m[3][3];
609     m.m[3][2] = m1.m[0][2] * m2.m[3][0]
610               + m1.m[1][2] * m2.m[3][1]
611               + m1.m[2][2] * m2.m[3][2]
612               + m1.m[3][2] * m2.m[3][3];
613     m.m[3][3] = m1.m[0][3] * m2.m[3][0]
614               + m1.m[1][3] * m2.m[3][1]
615               + m1.m[2][3] * m2.m[3][2]
616               + m1.m[3][3] * m2.m[3][3];
617     m.flagBits = flagBits;
618     return m;
619 }
620 
621 inline QDoubleVector3D operator*(const QDoubleVector3D& vector, const QDoubleMatrix4x4& matrix)
622 {
623     double x, y, z, w;
624     x = vector.x() * matrix.m[0][0] +
625         vector.y() * matrix.m[0][1] +
626         vector.z() * matrix.m[0][2] +
627         matrix.m[0][3];
628     y = vector.x() * matrix.m[1][0] +
629         vector.y() * matrix.m[1][1] +
630         vector.z() * matrix.m[1][2] +
631         matrix.m[1][3];
632     z = vector.x() * matrix.m[2][0] +
633         vector.y() * matrix.m[2][1] +
634         vector.z() * matrix.m[2][2] +
635         matrix.m[2][3];
636     w = vector.x() * matrix.m[3][0] +
637         vector.y() * matrix.m[3][1] +
638         vector.z() * matrix.m[3][2] +
639         matrix.m[3][3];
640     if (w == 1.0f)
641         return QDoubleVector3D(x, y, z);
642     else
643         return QDoubleVector3D(x / w, y / w, z / w);
644 }
645 
646 inline QDoubleVector3D operator*(const QDoubleMatrix4x4& matrix, const QDoubleVector3D& vector)
647 {
648     double x, y, z, w;
649     if (matrix.flagBits == QDoubleMatrix4x4::Identity) {
650         return vector;
651     } else if (matrix.flagBits < QDoubleMatrix4x4::Rotation2D) {
652         // Translation | Scale
653         return QDoubleVector3D(vector.x() * matrix.m[0][0] + matrix.m[3][0],
654                          vector.y() * matrix.m[1][1] + matrix.m[3][1],
655                          vector.z() * matrix.m[2][2] + matrix.m[3][2]);
656     } else if (matrix.flagBits < QDoubleMatrix4x4::Rotation) {
657         // Translation | Scale | Rotation2D
658         return QDoubleVector3D(vector.x() * matrix.m[0][0] + vector.y() * matrix.m[1][0] + matrix.m[3][0],
659                          vector.x() * matrix.m[0][1] + vector.y() * matrix.m[1][1] + matrix.m[3][1],
660                          vector.z() * matrix.m[2][2] + matrix.m[3][2]);
661     } else {
662         x = vector.x() * matrix.m[0][0] +
663             vector.y() * matrix.m[1][0] +
664             vector.z() * matrix.m[2][0] +
665             matrix.m[3][0];
666         y = vector.x() * matrix.m[0][1] +
667             vector.y() * matrix.m[1][1] +
668             vector.z() * matrix.m[2][1] +
669             matrix.m[3][1];
670         z = vector.x() * matrix.m[0][2] +
671             vector.y() * matrix.m[1][2] +
672             vector.z() * matrix.m[2][2] +
673             matrix.m[3][2];
674         w = vector.x() * matrix.m[0][3] +
675             vector.y() * matrix.m[1][3] +
676             vector.z() * matrix.m[2][3] +
677             matrix.m[3][3];
678         if (w == 1.0f)
679             return QDoubleVector3D(x, y, z);
680         else
681             return QDoubleVector3D(x / w, y / w, z / w);
682     }
683 }
684 
685 inline QPoint operator*(const QPoint& point, const QDoubleMatrix4x4& matrix)
686 {
687     double xin, yin;
688     double x, y, w;
689     xin = point.x();
690     yin = point.y();
691     x = xin * matrix.m[0][0] +
692         yin * matrix.m[0][1] +
693         matrix.m[0][3];
694     y = xin * matrix.m[1][0] +
695         yin * matrix.m[1][1] +
696         matrix.m[1][3];
697     w = xin * matrix.m[3][0] +
698         yin * matrix.m[3][1] +
699         matrix.m[3][3];
700     if (w == 1.0f)
701         return QPoint(qRound(x), qRound(y));
702     else
703         return QPoint(qRound(x / w), qRound(y / w));
704 }
705 
706 inline QPointF operator*(const QPointF& point, const QDoubleMatrix4x4& matrix)
707 {
708     double xin, yin;
709     double x, y, w;
710     xin = point.x();
711     yin = point.y();
712     x = xin * matrix.m[0][0] +
713         yin * matrix.m[0][1] +
714         matrix.m[0][3];
715     y = xin * matrix.m[1][0] +
716         yin * matrix.m[1][1] +
717         matrix.m[1][3];
718     w = xin * matrix.m[3][0] +
719         yin * matrix.m[3][1] +
720         matrix.m[3][3];
721     if (w == 1.0f) {
722         return QPointF(double(x), double(y));
723     } else {
724         return QPointF(double(x / w), double(y / w));
725     }
726 }
727 
728 inline QPoint operator*(const QDoubleMatrix4x4& matrix, const QPoint& point)
729 {
730     double xin, yin;
731     double x, y, w;
732     xin = point.x();
733     yin = point.y();
734     if (matrix.flagBits == QDoubleMatrix4x4::Identity) {
735         return point;
736     } else if (matrix.flagBits < QDoubleMatrix4x4::Rotation2D) {
737         // Translation | Scale
738         return QPoint(qRound(xin * matrix.m[0][0] + matrix.m[3][0]),
739                       qRound(yin * matrix.m[1][1] + matrix.m[3][1]));
740     } else if (matrix.flagBits < QDoubleMatrix4x4::Perspective) {
741         return QPoint(qRound(xin * matrix.m[0][0] + yin * matrix.m[1][0] + matrix.m[3][0]),
742                       qRound(xin * matrix.m[0][1] + yin * matrix.m[1][1] + matrix.m[3][1]));
743     } else {
744         x = xin * matrix.m[0][0] +
745             yin * matrix.m[1][0] +
746             matrix.m[3][0];
747         y = xin * matrix.m[0][1] +
748             yin * matrix.m[1][1] +
749             matrix.m[3][1];
750         w = xin * matrix.m[0][3] +
751             yin * matrix.m[1][3] +
752             matrix.m[3][3];
753         if (w == 1.0f)
754             return QPoint(qRound(x), qRound(y));
755         else
756             return QPoint(qRound(x / w), qRound(y / w));
757     }
758 }
759 
760 inline QPointF operator*(const QDoubleMatrix4x4& matrix, const QPointF& point)
761 {
762     double xin, yin;
763     double x, y, w;
764     xin = point.x();
765     yin = point.y();
766     if (matrix.flagBits == QDoubleMatrix4x4::Identity) {
767         return point;
768     } else if (matrix.flagBits < QDoubleMatrix4x4::Rotation2D) {
769         // Translation | Scale
770         return QPointF(xin * matrix.m[0][0] + matrix.m[3][0],
771                        yin * matrix.m[1][1] + matrix.m[3][1]);
772     } else if (matrix.flagBits < QDoubleMatrix4x4::Perspective) {
773         return QPointF(xin * matrix.m[0][0] + yin * matrix.m[1][0] + matrix.m[3][0],
774                        xin * matrix.m[0][1] + yin * matrix.m[1][1] + matrix.m[3][1]);
775     } else {
776         x = xin * matrix.m[0][0] +
777             yin * matrix.m[1][0] +
778             matrix.m[3][0];
779         y = xin * matrix.m[0][1] +
780             yin * matrix.m[1][1] +
781             matrix.m[3][1];
782         w = xin * matrix.m[0][3] +
783             yin * matrix.m[1][3] +
784             matrix.m[3][3];
785         if (w == 1.0f) {
786             return QPointF(double(x), double(y));
787         } else {
788             return QPointF(double(x / w), double(y / w));
789         }
790     }
791 }
792 
793 inline QDoubleMatrix4x4 operator-(const QDoubleMatrix4x4& matrix)
794 {
795     QDoubleMatrix4x4 m(1);
796     m.m[0][0] = -matrix.m[0][0];
797     m.m[0][1] = -matrix.m[0][1];
798     m.m[0][2] = -matrix.m[0][2];
799     m.m[0][3] = -matrix.m[0][3];
800     m.m[1][0] = -matrix.m[1][0];
801     m.m[1][1] = -matrix.m[1][1];
802     m.m[1][2] = -matrix.m[1][2];
803     m.m[1][3] = -matrix.m[1][3];
804     m.m[2][0] = -matrix.m[2][0];
805     m.m[2][1] = -matrix.m[2][1];
806     m.m[2][2] = -matrix.m[2][2];
807     m.m[2][3] = -matrix.m[2][3];
808     m.m[3][0] = -matrix.m[3][0];
809     m.m[3][1] = -matrix.m[3][1];
810     m.m[3][2] = -matrix.m[3][2];
811     m.m[3][3] = -matrix.m[3][3];
812     m.flagBits = QDoubleMatrix4x4::General;
813     return m;
814 }
815 
816 inline QDoubleMatrix4x4 operator*(double factor, const QDoubleMatrix4x4& matrix)
817 {
818     QDoubleMatrix4x4 m(1);
819     m.m[0][0] = matrix.m[0][0] * factor;
820     m.m[0][1] = matrix.m[0][1] * factor;
821     m.m[0][2] = matrix.m[0][2] * factor;
822     m.m[0][3] = matrix.m[0][3] * factor;
823     m.m[1][0] = matrix.m[1][0] * factor;
824     m.m[1][1] = matrix.m[1][1] * factor;
825     m.m[1][2] = matrix.m[1][2] * factor;
826     m.m[1][3] = matrix.m[1][3] * factor;
827     m.m[2][0] = matrix.m[2][0] * factor;
828     m.m[2][1] = matrix.m[2][1] * factor;
829     m.m[2][2] = matrix.m[2][2] * factor;
830     m.m[2][3] = matrix.m[2][3] * factor;
831     m.m[3][0] = matrix.m[3][0] * factor;
832     m.m[3][1] = matrix.m[3][1] * factor;
833     m.m[3][2] = matrix.m[3][2] * factor;
834     m.m[3][3] = matrix.m[3][3] * factor;
835     m.flagBits = QDoubleMatrix4x4::General;
836     return m;
837 }
838 
839 inline QDoubleMatrix4x4 operator*(const QDoubleMatrix4x4& matrix, double factor)
840 {
841     QDoubleMatrix4x4 m(1);
842     m.m[0][0] = matrix.m[0][0] * factor;
843     m.m[0][1] = matrix.m[0][1] * factor;
844     m.m[0][2] = matrix.m[0][2] * factor;
845     m.m[0][3] = matrix.m[0][3] * factor;
846     m.m[1][0] = matrix.m[1][0] * factor;
847     m.m[1][1] = matrix.m[1][1] * factor;
848     m.m[1][2] = matrix.m[1][2] * factor;
849     m.m[1][3] = matrix.m[1][3] * factor;
850     m.m[2][0] = matrix.m[2][0] * factor;
851     m.m[2][1] = matrix.m[2][1] * factor;
852     m.m[2][2] = matrix.m[2][2] * factor;
853     m.m[2][3] = matrix.m[2][3] * factor;
854     m.m[3][0] = matrix.m[3][0] * factor;
855     m.m[3][1] = matrix.m[3][1] * factor;
856     m.m[3][2] = matrix.m[3][2] * factor;
857     m.m[3][3] = matrix.m[3][3] * factor;
858     m.flagBits = QDoubleMatrix4x4::General;
859     return m;
860 }
861 
qFuzzyCompare(const QDoubleMatrix4x4 & m1,const QDoubleMatrix4x4 & m2)862 inline bool qFuzzyCompare(const QDoubleMatrix4x4& m1, const QDoubleMatrix4x4& m2)
863 {
864     return qFuzzyCompare(m1.m[0][0], m2.m[0][0]) &&
865            qFuzzyCompare(m1.m[0][1], m2.m[0][1]) &&
866            qFuzzyCompare(m1.m[0][2], m2.m[0][2]) &&
867            qFuzzyCompare(m1.m[0][3], m2.m[0][3]) &&
868            qFuzzyCompare(m1.m[1][0], m2.m[1][0]) &&
869            qFuzzyCompare(m1.m[1][1], m2.m[1][1]) &&
870            qFuzzyCompare(m1.m[1][2], m2.m[1][2]) &&
871            qFuzzyCompare(m1.m[1][3], m2.m[1][3]) &&
872            qFuzzyCompare(m1.m[2][0], m2.m[2][0]) &&
873            qFuzzyCompare(m1.m[2][1], m2.m[2][1]) &&
874            qFuzzyCompare(m1.m[2][2], m2.m[2][2]) &&
875            qFuzzyCompare(m1.m[2][3], m2.m[2][3]) &&
876            qFuzzyCompare(m1.m[3][0], m2.m[3][0]) &&
877            qFuzzyCompare(m1.m[3][1], m2.m[3][1]) &&
878            qFuzzyCompare(m1.m[3][2], m2.m[3][2]) &&
879            qFuzzyCompare(m1.m[3][3], m2.m[3][3]);
880 }
881 
map(const QPoint & point)882 inline QPoint QDoubleMatrix4x4::map(const QPoint& point) const
883 {
884     return *this * point;
885 }
886 
map(const QPointF & point)887 inline QPointF QDoubleMatrix4x4::map(const QPointF& point) const
888 {
889     return *this * point;
890 }
891 
map(const QDoubleVector3D & point)892 inline QDoubleVector3D QDoubleMatrix4x4::map(const QDoubleVector3D& point) const
893 {
894     return *this * point;
895 }
896 
mapVector(const QDoubleVector3D & vector)897 inline QDoubleVector3D QDoubleMatrix4x4::mapVector(const QDoubleVector3D& vector) const
898 {
899     if (flagBits < Scale) {
900         // Translation
901         return vector;
902     } else if (flagBits < Rotation2D) {
903         // Translation | Scale
904         return QDoubleVector3D(vector.x() * m[0][0],
905                          vector.y() * m[1][1],
906                          vector.z() * m[2][2]);
907     } else {
908         return QDoubleVector3D(vector.x() * m[0][0] +
909                          vector.y() * m[1][0] +
910                          vector.z() * m[2][0],
911                          vector.x() * m[0][1] +
912                          vector.y() * m[1][1] +
913                          vector.z() * m[2][1],
914                          vector.x() * m[0][2] +
915                          vector.y() * m[1][2] +
916                          vector.z() * m[2][2]);
917     }
918 }
919 
data()920 inline double *QDoubleMatrix4x4::data()
921 {
922     // We have to assume that the caller will modify the matrix elements,
923     // so we flip it over to "General" mode.
924     flagBits = General;
925     return *m;
926 }
927 
viewport(const QRectF & rect)928 inline void QDoubleMatrix4x4::viewport(const QRectF &rect)
929 {
930     viewport(rect.x(), rect.y(), rect.width(), rect.height());
931 }
932 
933 #ifndef QT_NO_DEBUG_STREAM
934 Q_POSITIONING_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QDoubleMatrix4x4 &m);
935 #endif
936 
937 #ifndef QT_NO_DATASTREAM
938 Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDoubleMatrix4x4 &);
939 Q_POSITIONING_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDoubleMatrix4x4 &);
940 #endif
941 
942 
943 QT_END_NAMESPACE
944 
945 
946 #endif // QDOUBLEMATRIX4X4_H
947