Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-19 09:32:49

0001 // Copyright (C) 2016 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 
0004 #ifndef QMATRIX4X4_H
0005 #define QMATRIX4X4_H
0006 
0007 #include <QtGui/qtguiglobal.h>
0008 #include <QtGui/qvector3d.h>
0009 #include <QtGui/qvector4d.h>
0010 #include <QtGui/qgenericmatrix.h>
0011 #include <QtCore/qrect.h>
0012 
0013 class tst_QMatrixNxN;
0014 
0015 QT_BEGIN_NAMESPACE
0016 
0017 #ifndef QT_NO_QUATERNION
0018 class QQuaternion;
0019 #endif
0020 
0021 #ifndef QT_NO_MATRIX4X4
0022 
0023 class QTransform;
0024 class QVariant;
0025 
0026 class Q_GUI_EXPORT QMatrix4x4
0027 {
0028 public:
0029     inline QMatrix4x4() { setToIdentity(); }
0030     explicit QMatrix4x4(Qt::Initialization) : flagBits(General) {}
0031     explicit QMatrix4x4(const float *values);
0032     inline QMatrix4x4(float m11, float m12, float m13, float m14,
0033                       float m21, float m22, float m23, float m24,
0034                       float m31, float m32, float m33, float m34,
0035                       float m41, float m42, float m43, float m44);
0036 
0037     template <int N, int M>
0038     explicit QMatrix4x4(const QGenericMatrix<N, M, float>& matrix);
0039 
0040     QMatrix4x4(const float *values, int cols, int rows);
0041     QMatrix4x4(const QTransform& transform);
0042 
0043     inline const float& operator()(int row, int column) const;
0044     inline float& operator()(int row, int column);
0045 
0046 #ifndef QT_NO_VECTOR4D
0047     inline QVector4D column(int index) const;
0048     inline void setColumn(int index, const QVector4D& value);
0049 
0050     inline QVector4D row(int index) const;
0051     inline void setRow(int index, const QVector4D& value);
0052 #endif
0053 
0054     inline bool isAffine() const;
0055 
0056     inline bool isIdentity() const;
0057     inline void setToIdentity();
0058 
0059     inline void fill(float value);
0060 
0061     double determinant() const;
0062     QMatrix4x4 inverted(bool *invertible = nullptr) const;
0063     QMatrix4x4 transposed() const;
0064     QMatrix3x3 normalMatrix() const;
0065 
0066     inline QMatrix4x4& operator+=(const QMatrix4x4& other);
0067     inline QMatrix4x4& operator-=(const QMatrix4x4& other);
0068     inline QMatrix4x4& operator*=(const QMatrix4x4& other);
0069     inline QMatrix4x4& operator*=(float factor);
0070     QMatrix4x4& operator/=(float divisor);
0071     inline bool operator==(const QMatrix4x4& other) const;
0072     inline bool operator!=(const QMatrix4x4& other) const;
0073 
0074     friend QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2);
0075     friend QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2);
0076     friend QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2);
0077 #ifndef QT_NO_VECTOR3D
0078 #if QT_DEPRECATED_SINCE(6, 1)
0079     friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector);
0080     friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix);
0081 #endif
0082 #endif
0083 #ifndef QT_NO_VECTOR4D
0084     friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix);
0085     friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector);
0086 #endif
0087     friend QPoint operator*(const QPoint& point, const QMatrix4x4& matrix);
0088     friend QPointF operator*(const QPointF& point, const QMatrix4x4& matrix);
0089     friend QMatrix4x4 operator-(const QMatrix4x4& matrix);
0090 #if QT_DEPRECATED_SINCE(6, 1)
0091     friend QPoint operator*(const QMatrix4x4& matrix, const QPoint& point);
0092     friend QPointF operator*(const QMatrix4x4& matrix, const QPointF& point);
0093 #endif
0094     friend QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix);
0095     friend QMatrix4x4 operator*(const QMatrix4x4& matrix, float factor);
0096     friend Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, float divisor);
0097 
0098     friend Q_GUI_EXPORT bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2) noexcept;
0099 
0100 #ifndef QT_NO_VECTOR3D
0101     void scale(const QVector3D& vector);
0102     void translate(const QVector3D& vector);
0103     void rotate(float angle, const QVector3D& vector);
0104 #endif
0105     void scale(float x, float y);
0106     void scale(float x, float y, float z);
0107     void scale(float factor);
0108     void translate(float x, float y);
0109     void translate(float x, float y, float z);
0110     void rotate(float angle, float x, float y, float z = 0.0f);
0111 #ifndef QT_NO_QUATERNION
0112     void rotate(const QQuaternion& quaternion);
0113 #endif
0114 
0115     void ortho(const QRect& rect);
0116     void ortho(const QRectF& rect);
0117     void ortho(float left, float right, float bottom, float top, float nearPlane, float farPlane);
0118     void frustum(float left, float right, float bottom, float top, float nearPlane, float farPlane);
0119     void perspective(float verticalAngle, float aspectRatio, float nearPlane, float farPlane);
0120 #ifndef QT_NO_VECTOR3D
0121     void lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up);
0122 #endif
0123     void viewport(const QRectF &rect);
0124     void viewport(float left, float bottom, float width, float height, float nearPlane = 0.0f, float farPlane = 1.0f);
0125     void flipCoordinates();
0126 
0127     void copyDataTo(float *values) const;
0128 
0129     QTransform toTransform() const;
0130     QTransform toTransform(float distanceToPlane) const;
0131 
0132     inline QPoint map(const QPoint& point) const;
0133     inline QPointF map(const QPointF& point) const;
0134 #ifndef QT_NO_VECTOR3D
0135     inline QVector3D map(const QVector3D& point) const;
0136     inline QVector3D mapVector(const QVector3D& vector) const;
0137 #endif
0138 #ifndef QT_NO_VECTOR4D
0139     inline QVector4D map(const QVector4D& point) const;
0140 #endif
0141     QRect mapRect(const QRect& rect) const;
0142     QRectF mapRect(const QRectF& rect) const;
0143 
0144     template <int N, int M>
0145     QGenericMatrix<N, M, float> toGenericMatrix() const;
0146 
0147     inline float *data();
0148     inline const float *data() const { return *m; }
0149     inline const float *constData() const { return *m; }
0150 
0151     void optimize();
0152 
0153     operator QVariant() const;
0154 
0155 #ifndef QT_NO_DEBUG_STREAM
0156     friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
0157 #endif
0158 
0159 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
0160     void projectedRotate(float angle, float x, float y, float z, float distanceToPlane);
0161     // ### Qt7: Remove
0162     void projectedRotate(float angle, float x, float y, float z);
0163 #else
0164     void projectedRotate(float angle, float x, float y, float z, float distanceToPlane = 1024.0);
0165 #endif
0166 
0167     // When matrices are multiplied, the flag bits are or-ed together.
0168     // Note that the ordering of the bit values matters. (ident < t < s < r2d < r < p)
0169     enum Flag {
0170         Identity        = 0x0000, // Identity matrix
0171         Translation     = 0x0001, // Contains a translation
0172         Scale           = 0x0002, // Contains a scale
0173         Rotation2D      = 0x0004, // Contains a rotation about the Z axis
0174         Rotation        = 0x0008, // Contains an arbitrary rotation
0175         Perspective     = 0x0010, // Last row is different from (0, 0, 0, 1)
0176         General         = 0x001f  // General matrix, unknown contents
0177     };
0178     Q_DECLARE_FLAGS(Flags, Flag)
0179 
0180     Flags flags() const { return flagBits; }
0181 
0182 private:
0183     float m[4][4];          // Column-major order to match OpenGL.
0184     Flags flagBits;
0185 
0186     QMatrix4x4 orthonormalInverse() const;
0187 
0188     friend class ::tst_QMatrixNxN; // for access to flagBits
0189 };
0190 
0191 Q_DECLARE_OPERATORS_FOR_FLAGS(QMatrix4x4::Flags)
0192 
0193 QT_WARNING_PUSH
0194 QT_WARNING_DISABLE_FLOAT_COMPARE
0195 
0196 Q_DECLARE_TYPEINFO(QMatrix4x4, Q_PRIMITIVE_TYPE);
0197 
0198 inline QMatrix4x4::QMatrix4x4
0199         (float m11, float m12, float m13, float m14,
0200          float m21, float m22, float m23, float m24,
0201          float m31, float m32, float m33, float m34,
0202          float m41, float m42, float m43, float m44)
0203 {
0204     m[0][0] = m11; m[0][1] = m21; m[0][2] = m31; m[0][3] = m41;
0205     m[1][0] = m12; m[1][1] = m22; m[1][2] = m32; m[1][3] = m42;
0206     m[2][0] = m13; m[2][1] = m23; m[2][2] = m33; m[2][3] = m43;
0207     m[3][0] = m14; m[3][1] = m24; m[3][2] = m34; m[3][3] = m44;
0208     flagBits = General;
0209 }
0210 
0211 template <int N, int M>
0212 Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4
0213     (const QGenericMatrix<N, M, float>& matrix)
0214 {
0215     const float *values = matrix.constData();
0216     for (int matrixCol = 0; matrixCol < 4; ++matrixCol) {
0217         for (int matrixRow = 0; matrixRow < 4; ++matrixRow) {
0218             if (matrixCol < N && matrixRow < M)
0219                 m[matrixCol][matrixRow] = values[matrixCol * M + matrixRow];
0220             else if (matrixCol == matrixRow)
0221                 m[matrixCol][matrixRow] = 1.0f;
0222             else
0223                 m[matrixCol][matrixRow] = 0.0f;
0224         }
0225     }
0226     flagBits = General;
0227 }
0228 
0229 template <int N, int M>
0230 QGenericMatrix<N, M, float> QMatrix4x4::toGenericMatrix() const
0231 {
0232     QGenericMatrix<N, M, float> result;
0233     float *values = result.data();
0234     for (int matrixCol = 0; matrixCol < N; ++matrixCol) {
0235         for (int matrixRow = 0; matrixRow < M; ++matrixRow) {
0236             if (matrixCol < 4 && matrixRow < 4)
0237                 values[matrixCol * M + matrixRow] = m[matrixCol][matrixRow];
0238             else if (matrixCol == matrixRow)
0239                 values[matrixCol * M + matrixRow] = 1.0f;
0240             else
0241                 values[matrixCol * M + matrixRow] = 0.0f;
0242         }
0243     }
0244     return result;
0245 }
0246 
0247 inline const float& QMatrix4x4::operator()(int aRow, int aColumn) const
0248 {
0249     Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
0250     return m[aColumn][aRow];
0251 }
0252 
0253 inline float& QMatrix4x4::operator()(int aRow, int aColumn)
0254 {
0255     Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
0256     flagBits = General;
0257     return m[aColumn][aRow];
0258 }
0259 
0260 #ifndef QT_NO_VECTOR4D
0261 inline QVector4D QMatrix4x4::column(int index) const
0262 {
0263     Q_ASSERT(index >= 0 && index < 4);
0264     return QVector4D(m[index][0], m[index][1], m[index][2], m[index][3]);
0265 }
0266 
0267 inline void QMatrix4x4::setColumn(int index, const QVector4D& value)
0268 {
0269     Q_ASSERT(index >= 0 && index < 4);
0270     m[index][0] = value.x();
0271     m[index][1] = value.y();
0272     m[index][2] = value.z();
0273     m[index][3] = value.w();
0274     flagBits = General;
0275 }
0276 
0277 inline QVector4D QMatrix4x4::row(int index) const
0278 {
0279     Q_ASSERT(index >= 0 && index < 4);
0280     return QVector4D(m[0][index], m[1][index], m[2][index], m[3][index]);
0281 }
0282 
0283 inline void QMatrix4x4::setRow(int index, const QVector4D& value)
0284 {
0285     Q_ASSERT(index >= 0 && index < 4);
0286     m[0][index] = value.x();
0287     m[1][index] = value.y();
0288     m[2][index] = value.z();
0289     m[3][index] = value.w();
0290     flagBits = General;
0291 }
0292 #endif
0293 
0294 Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, float divisor);
0295 
0296 inline bool QMatrix4x4::isAffine() const
0297 {
0298     return m[0][3] == 0.0f && m[1][3] == 0.0f && m[2][3] == 0.0f && m[3][3] == 1.0f;
0299 }
0300 
0301 inline bool QMatrix4x4::isIdentity() const
0302 {
0303     if (flagBits == Identity)
0304         return true;
0305     if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f)
0306         return false;
0307     if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f)
0308         return false;
0309     if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f)
0310         return false;
0311     if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f)
0312         return false;
0313     if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f)
0314         return false;
0315     return (m[3][3] == 1.0f);
0316 }
0317 
0318 inline void QMatrix4x4::setToIdentity()
0319 {
0320     m[0][0] = 1.0f;
0321     m[0][1] = 0.0f;
0322     m[0][2] = 0.0f;
0323     m[0][3] = 0.0f;
0324     m[1][0] = 0.0f;
0325     m[1][1] = 1.0f;
0326     m[1][2] = 0.0f;
0327     m[1][3] = 0.0f;
0328     m[2][0] = 0.0f;
0329     m[2][1] = 0.0f;
0330     m[2][2] = 1.0f;
0331     m[2][3] = 0.0f;
0332     m[3][0] = 0.0f;
0333     m[3][1] = 0.0f;
0334     m[3][2] = 0.0f;
0335     m[3][3] = 1.0f;
0336     flagBits = Identity;
0337 }
0338 
0339 inline void QMatrix4x4::fill(float value)
0340 {
0341     m[0][0] = value;
0342     m[0][1] = value;
0343     m[0][2] = value;
0344     m[0][3] = value;
0345     m[1][0] = value;
0346     m[1][1] = value;
0347     m[1][2] = value;
0348     m[1][3] = value;
0349     m[2][0] = value;
0350     m[2][1] = value;
0351     m[2][2] = value;
0352     m[2][3] = value;
0353     m[3][0] = value;
0354     m[3][1] = value;
0355     m[3][2] = value;
0356     m[3][3] = value;
0357     flagBits = General;
0358 }
0359 
0360 inline QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
0361 {
0362     m[0][0] += other.m[0][0];
0363     m[0][1] += other.m[0][1];
0364     m[0][2] += other.m[0][2];
0365     m[0][3] += other.m[0][3];
0366     m[1][0] += other.m[1][0];
0367     m[1][1] += other.m[1][1];
0368     m[1][2] += other.m[1][2];
0369     m[1][3] += other.m[1][3];
0370     m[2][0] += other.m[2][0];
0371     m[2][1] += other.m[2][1];
0372     m[2][2] += other.m[2][2];
0373     m[2][3] += other.m[2][3];
0374     m[3][0] += other.m[3][0];
0375     m[3][1] += other.m[3][1];
0376     m[3][2] += other.m[3][2];
0377     m[3][3] += other.m[3][3];
0378     flagBits = General;
0379     return *this;
0380 }
0381 
0382 inline QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
0383 {
0384     m[0][0] -= other.m[0][0];
0385     m[0][1] -= other.m[0][1];
0386     m[0][2] -= other.m[0][2];
0387     m[0][3] -= other.m[0][3];
0388     m[1][0] -= other.m[1][0];
0389     m[1][1] -= other.m[1][1];
0390     m[1][2] -= other.m[1][2];
0391     m[1][3] -= other.m[1][3];
0392     m[2][0] -= other.m[2][0];
0393     m[2][1] -= other.m[2][1];
0394     m[2][2] -= other.m[2][2];
0395     m[2][3] -= other.m[2][3];
0396     m[3][0] -= other.m[3][0];
0397     m[3][1] -= other.m[3][1];
0398     m[3][2] -= other.m[3][2];
0399     m[3][3] -= other.m[3][3];
0400     flagBits = General;
0401     return *this;
0402 }
0403 
0404 inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& o)
0405 {
0406     const QMatrix4x4 other = o; // prevent aliasing when &o == this ### Qt 6: take o by value
0407     flagBits |= other.flagBits;
0408 
0409     if (flagBits.toInt() < Rotation2D) {
0410         m[3][0] += m[0][0] * other.m[3][0];
0411         m[3][1] += m[1][1] * other.m[3][1];
0412         m[3][2] += m[2][2] * other.m[3][2];
0413 
0414         m[0][0] *= other.m[0][0];
0415         m[1][1] *= other.m[1][1];
0416         m[2][2] *= other.m[2][2];
0417         return *this;
0418     }
0419 
0420     float m0, m1, m2;
0421     m0 = m[0][0] * other.m[0][0]
0422             + m[1][0] * other.m[0][1]
0423             + m[2][0] * other.m[0][2]
0424             + m[3][0] * other.m[0][3];
0425     m1 = m[0][0] * other.m[1][0]
0426             + m[1][0] * other.m[1][1]
0427             + m[2][0] * other.m[1][2]
0428             + m[3][0] * other.m[1][3];
0429     m2 = m[0][0] * other.m[2][0]
0430             + m[1][0] * other.m[2][1]
0431             + m[2][0] * other.m[2][2]
0432             + m[3][0] * other.m[2][3];
0433     m[3][0] = m[0][0] * other.m[3][0]
0434             + m[1][0] * other.m[3][1]
0435             + m[2][0] * other.m[3][2]
0436             + m[3][0] * other.m[3][3];
0437     m[0][0] = m0;
0438     m[1][0] = m1;
0439     m[2][0] = m2;
0440 
0441     m0 = m[0][1] * other.m[0][0]
0442             + m[1][1] * other.m[0][1]
0443             + m[2][1] * other.m[0][2]
0444             + m[3][1] * other.m[0][3];
0445     m1 = m[0][1] * other.m[1][0]
0446             + m[1][1] * other.m[1][1]
0447             + m[2][1] * other.m[1][2]
0448             + m[3][1] * other.m[1][3];
0449     m2 = m[0][1] * other.m[2][0]
0450             + m[1][1] * other.m[2][1]
0451             + m[2][1] * other.m[2][2]
0452             + m[3][1] * other.m[2][3];
0453     m[3][1] = m[0][1] * other.m[3][0]
0454             + m[1][1] * other.m[3][1]
0455             + m[2][1] * other.m[3][2]
0456             + m[3][1] * other.m[3][3];
0457     m[0][1] = m0;
0458     m[1][1] = m1;
0459     m[2][1] = m2;
0460 
0461     m0 = m[0][2] * other.m[0][0]
0462             + m[1][2] * other.m[0][1]
0463             + m[2][2] * other.m[0][2]
0464             + m[3][2] * other.m[0][3];
0465     m1 = m[0][2] * other.m[1][0]
0466             + m[1][2] * other.m[1][1]
0467             + m[2][2] * other.m[1][2]
0468             + m[3][2] * other.m[1][3];
0469     m2 = m[0][2] * other.m[2][0]
0470             + m[1][2] * other.m[2][1]
0471             + m[2][2] * other.m[2][2]
0472             + m[3][2] * other.m[2][3];
0473     m[3][2] = m[0][2] * other.m[3][0]
0474             + m[1][2] * other.m[3][1]
0475             + m[2][2] * other.m[3][2]
0476             + m[3][2] * other.m[3][3];
0477     m[0][2] = m0;
0478     m[1][2] = m1;
0479     m[2][2] = m2;
0480 
0481     m0 = m[0][3] * other.m[0][0]
0482             + m[1][3] * other.m[0][1]
0483             + m[2][3] * other.m[0][2]
0484             + m[3][3] * other.m[0][3];
0485     m1 = m[0][3] * other.m[1][0]
0486             + m[1][3] * other.m[1][1]
0487             + m[2][3] * other.m[1][2]
0488             + m[3][3] * other.m[1][3];
0489     m2 = m[0][3] * other.m[2][0]
0490             + m[1][3] * other.m[2][1]
0491             + m[2][3] * other.m[2][2]
0492             + m[3][3] * other.m[2][3];
0493     m[3][3] = m[0][3] * other.m[3][0]
0494             + m[1][3] * other.m[3][1]
0495             + m[2][3] * other.m[3][2]
0496             + m[3][3] * other.m[3][3];
0497     m[0][3] = m0;
0498     m[1][3] = m1;
0499     m[2][3] = m2;
0500     return *this;
0501 }
0502 
0503 inline QMatrix4x4& QMatrix4x4::operator*=(float factor)
0504 {
0505     m[0][0] *= factor;
0506     m[0][1] *= factor;
0507     m[0][2] *= factor;
0508     m[0][3] *= factor;
0509     m[1][0] *= factor;
0510     m[1][1] *= factor;
0511     m[1][2] *= factor;
0512     m[1][3] *= factor;
0513     m[2][0] *= factor;
0514     m[2][1] *= factor;
0515     m[2][2] *= factor;
0516     m[2][3] *= factor;
0517     m[3][0] *= factor;
0518     m[3][1] *= factor;
0519     m[3][2] *= factor;
0520     m[3][3] *= factor;
0521     flagBits = General;
0522     return *this;
0523 }
0524 
0525 inline bool QMatrix4x4::operator==(const QMatrix4x4& other) const
0526 {
0527     return m[0][0] == other.m[0][0] &&
0528            m[0][1] == other.m[0][1] &&
0529            m[0][2] == other.m[0][2] &&
0530            m[0][3] == other.m[0][3] &&
0531            m[1][0] == other.m[1][0] &&
0532            m[1][1] == other.m[1][1] &&
0533            m[1][2] == other.m[1][2] &&
0534            m[1][3] == other.m[1][3] &&
0535            m[2][0] == other.m[2][0] &&
0536            m[2][1] == other.m[2][1] &&
0537            m[2][2] == other.m[2][2] &&
0538            m[2][3] == other.m[2][3] &&
0539            m[3][0] == other.m[3][0] &&
0540            m[3][1] == other.m[3][1] &&
0541            m[3][2] == other.m[3][2] &&
0542            m[3][3] == other.m[3][3];
0543 }
0544 
0545 inline bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
0546 {
0547     return m[0][0] != other.m[0][0] ||
0548            m[0][1] != other.m[0][1] ||
0549            m[0][2] != other.m[0][2] ||
0550            m[0][3] != other.m[0][3] ||
0551            m[1][0] != other.m[1][0] ||
0552            m[1][1] != other.m[1][1] ||
0553            m[1][2] != other.m[1][2] ||
0554            m[1][3] != other.m[1][3] ||
0555            m[2][0] != other.m[2][0] ||
0556            m[2][1] != other.m[2][1] ||
0557            m[2][2] != other.m[2][2] ||
0558            m[2][3] != other.m[2][3] ||
0559            m[3][0] != other.m[3][0] ||
0560            m[3][1] != other.m[3][1] ||
0561            m[3][2] != other.m[3][2] ||
0562            m[3][3] != other.m[3][3];
0563 }
0564 
0565 inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
0566 {
0567     Q_DECL_UNINITIALIZED
0568     QMatrix4x4 m(Qt::Uninitialized);
0569     m.m[0][0] = m1.m[0][0] + m2.m[0][0];
0570     m.m[0][1] = m1.m[0][1] + m2.m[0][1];
0571     m.m[0][2] = m1.m[0][2] + m2.m[0][2];
0572     m.m[0][3] = m1.m[0][3] + m2.m[0][3];
0573     m.m[1][0] = m1.m[1][0] + m2.m[1][0];
0574     m.m[1][1] = m1.m[1][1] + m2.m[1][1];
0575     m.m[1][2] = m1.m[1][2] + m2.m[1][2];
0576     m.m[1][3] = m1.m[1][3] + m2.m[1][3];
0577     m.m[2][0] = m1.m[2][0] + m2.m[2][0];
0578     m.m[2][1] = m1.m[2][1] + m2.m[2][1];
0579     m.m[2][2] = m1.m[2][2] + m2.m[2][2];
0580     m.m[2][3] = m1.m[2][3] + m2.m[2][3];
0581     m.m[3][0] = m1.m[3][0] + m2.m[3][0];
0582     m.m[3][1] = m1.m[3][1] + m2.m[3][1];
0583     m.m[3][2] = m1.m[3][2] + m2.m[3][2];
0584     m.m[3][3] = m1.m[3][3] + m2.m[3][3];
0585     return m;
0586 }
0587 
0588 inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
0589 {
0590     Q_DECL_UNINITIALIZED
0591     QMatrix4x4 m(Qt::Uninitialized);
0592     m.m[0][0] = m1.m[0][0] - m2.m[0][0];
0593     m.m[0][1] = m1.m[0][1] - m2.m[0][1];
0594     m.m[0][2] = m1.m[0][2] - m2.m[0][2];
0595     m.m[0][3] = m1.m[0][3] - m2.m[0][3];
0596     m.m[1][0] = m1.m[1][0] - m2.m[1][0];
0597     m.m[1][1] = m1.m[1][1] - m2.m[1][1];
0598     m.m[1][2] = m1.m[1][2] - m2.m[1][2];
0599     m.m[1][3] = m1.m[1][3] - m2.m[1][3];
0600     m.m[2][0] = m1.m[2][0] - m2.m[2][0];
0601     m.m[2][1] = m1.m[2][1] - m2.m[2][1];
0602     m.m[2][2] = m1.m[2][2] - m2.m[2][2];
0603     m.m[2][3] = m1.m[2][3] - m2.m[2][3];
0604     m.m[3][0] = m1.m[3][0] - m2.m[3][0];
0605     m.m[3][1] = m1.m[3][1] - m2.m[3][1];
0606     m.m[3][2] = m1.m[3][2] - m2.m[3][2];
0607     m.m[3][3] = m1.m[3][3] - m2.m[3][3];
0608     return m;
0609 }
0610 
0611 inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
0612 {
0613     Q_DECL_UNINITIALIZED
0614     QMatrix4x4 m(Qt::Uninitialized);
0615     QMatrix4x4::Flags flagBits = m1.flagBits | m2.flagBits;
0616     if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
0617         // Scale | Translation
0618         m.m[0][0] = m1.m[0][0] * m2.m[0][0];
0619         m.m[0][1] = 0.0f;
0620         m.m[0][2] = 0.0f;
0621         m.m[0][3] = 0.0f;
0622 
0623         m.m[1][0] = 0.0f;
0624         m.m[1][1] = m1.m[1][1] * m2.m[1][1];
0625         m.m[1][2] = 0.0f;
0626         m.m[1][3] = 0.0f;
0627 
0628         m.m[2][0] = 0.0f;
0629         m.m[2][1] = 0.0f;
0630         m.m[2][2] = m1.m[2][2] * m2.m[2][2];
0631         m.m[2][3] = 0.0f;
0632 
0633         m.m[3][0] = m1.m[3][0] + m1.m[0][0] * m2.m[3][0];
0634         m.m[3][1] = m1.m[3][1] + m1.m[1][1] * m2.m[3][1];
0635         m.m[3][2] = m1.m[3][2] + m1.m[2][2] * m2.m[3][2];
0636         m.m[3][3] = 1.0f;
0637         m.flagBits = flagBits;
0638         return m;
0639     }
0640 
0641     m.m[0][0] = m1.m[0][0] * m2.m[0][0]
0642               + m1.m[1][0] * m2.m[0][1]
0643               + m1.m[2][0] * m2.m[0][2]
0644               + m1.m[3][0] * m2.m[0][3];
0645     m.m[0][1] = m1.m[0][1] * m2.m[0][0]
0646               + m1.m[1][1] * m2.m[0][1]
0647               + m1.m[2][1] * m2.m[0][2]
0648               + m1.m[3][1] * m2.m[0][3];
0649     m.m[0][2] = m1.m[0][2] * m2.m[0][0]
0650               + m1.m[1][2] * m2.m[0][1]
0651               + m1.m[2][2] * m2.m[0][2]
0652               + m1.m[3][2] * m2.m[0][3];
0653     m.m[0][3] = m1.m[0][3] * m2.m[0][0]
0654               + m1.m[1][3] * m2.m[0][1]
0655               + m1.m[2][3] * m2.m[0][2]
0656               + m1.m[3][3] * m2.m[0][3];
0657 
0658     m.m[1][0] = m1.m[0][0] * m2.m[1][0]
0659               + m1.m[1][0] * m2.m[1][1]
0660               + m1.m[2][0] * m2.m[1][2]
0661               + m1.m[3][0] * m2.m[1][3];
0662     m.m[1][1] = m1.m[0][1] * m2.m[1][0]
0663               + m1.m[1][1] * m2.m[1][1]
0664               + m1.m[2][1] * m2.m[1][2]
0665               + m1.m[3][1] * m2.m[1][3];
0666     m.m[1][2] = m1.m[0][2] * m2.m[1][0]
0667               + m1.m[1][2] * m2.m[1][1]
0668               + m1.m[2][2] * m2.m[1][2]
0669               + m1.m[3][2] * m2.m[1][3];
0670     m.m[1][3] = m1.m[0][3] * m2.m[1][0]
0671               + m1.m[1][3] * m2.m[1][1]
0672               + m1.m[2][3] * m2.m[1][2]
0673               + m1.m[3][3] * m2.m[1][3];
0674 
0675     m.m[2][0] = m1.m[0][0] * m2.m[2][0]
0676               + m1.m[1][0] * m2.m[2][1]
0677               + m1.m[2][0] * m2.m[2][2]
0678               + m1.m[3][0] * m2.m[2][3];
0679     m.m[2][1] = m1.m[0][1] * m2.m[2][0]
0680               + m1.m[1][1] * m2.m[2][1]
0681               + m1.m[2][1] * m2.m[2][2]
0682               + m1.m[3][1] * m2.m[2][3];
0683     m.m[2][2] = m1.m[0][2] * m2.m[2][0]
0684               + m1.m[1][2] * m2.m[2][1]
0685               + m1.m[2][2] * m2.m[2][2]
0686               + m1.m[3][2] * m2.m[2][3];
0687     m.m[2][3] = m1.m[0][3] * m2.m[2][0]
0688               + m1.m[1][3] * m2.m[2][1]
0689               + m1.m[2][3] * m2.m[2][2]
0690               + m1.m[3][3] * m2.m[2][3];
0691 
0692     m.m[3][0] = m1.m[0][0] * m2.m[3][0]
0693               + m1.m[1][0] * m2.m[3][1]
0694               + m1.m[2][0] * m2.m[3][2]
0695               + m1.m[3][0] * m2.m[3][3];
0696     m.m[3][1] = m1.m[0][1] * m2.m[3][0]
0697               + m1.m[1][1] * m2.m[3][1]
0698               + m1.m[2][1] * m2.m[3][2]
0699               + m1.m[3][1] * m2.m[3][3];
0700     m.m[3][2] = m1.m[0][2] * m2.m[3][0]
0701               + m1.m[1][2] * m2.m[3][1]
0702               + m1.m[2][2] * m2.m[3][2]
0703               + m1.m[3][2] * m2.m[3][3];
0704     m.m[3][3] = m1.m[0][3] * m2.m[3][0]
0705               + m1.m[1][3] * m2.m[3][1]
0706               + m1.m[2][3] * m2.m[3][2]
0707               + m1.m[3][3] * m2.m[3][3];
0708     m.flagBits = flagBits;
0709     return m;
0710 }
0711 
0712 #ifndef QT_NO_VECTOR3D
0713 
0714 #if QT_DEPRECATED_SINCE(6, 1)
0715 
0716 QT_DEPRECATED_VERSION_X_6_1("Extend the QVector3D to a QVector4D with 1.0 as the w coordinate before multiplying")
0717 inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
0718 {
0719     float x, y, z, w;
0720     x = vector.x() * matrix.m[0][0] +
0721         vector.y() * matrix.m[0][1] +
0722         vector.z() * matrix.m[0][2] +
0723         matrix.m[0][3];
0724     y = vector.x() * matrix.m[1][0] +
0725         vector.y() * matrix.m[1][1] +
0726         vector.z() * matrix.m[1][2] +
0727         matrix.m[1][3];
0728     z = vector.x() * matrix.m[2][0] +
0729         vector.y() * matrix.m[2][1] +
0730         vector.z() * matrix.m[2][2] +
0731         matrix.m[2][3];
0732     w = vector.x() * matrix.m[3][0] +
0733         vector.y() * matrix.m[3][1] +
0734         vector.z() * matrix.m[3][2] +
0735         matrix.m[3][3];
0736     if (w == 1.0f)
0737         return QVector3D(x, y, z);
0738     else
0739         return QVector3D(x / w, y / w, z / w);
0740 }
0741 
0742 QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(vector) instead")
0743 inline QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
0744 {
0745     return matrix.map(vector);
0746 }
0747 
0748 #endif
0749 
0750 #endif
0751 
0752 #ifndef QT_NO_VECTOR4D
0753 
0754 inline QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
0755 {
0756     float x, y, z, w;
0757     x = vector.x() * matrix.m[0][0] +
0758         vector.y() * matrix.m[0][1] +
0759         vector.z() * matrix.m[0][2] +
0760         vector.w() * matrix.m[0][3];
0761     y = vector.x() * matrix.m[1][0] +
0762         vector.y() * matrix.m[1][1] +
0763         vector.z() * matrix.m[1][2] +
0764         vector.w() * matrix.m[1][3];
0765     z = vector.x() * matrix.m[2][0] +
0766         vector.y() * matrix.m[2][1] +
0767         vector.z() * matrix.m[2][2] +
0768         vector.w() * matrix.m[2][3];
0769     w = vector.x() * matrix.m[3][0] +
0770         vector.y() * matrix.m[3][1] +
0771         vector.z() * matrix.m[3][2] +
0772         vector.w() * matrix.m[3][3];
0773     return QVector4D(x, y, z, w);
0774 }
0775 
0776 inline QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
0777 {
0778     float x, y, z, w;
0779     x = vector.x() * matrix.m[0][0] +
0780         vector.y() * matrix.m[1][0] +
0781         vector.z() * matrix.m[2][0] +
0782         vector.w() * matrix.m[3][0];
0783     y = vector.x() * matrix.m[0][1] +
0784         vector.y() * matrix.m[1][1] +
0785         vector.z() * matrix.m[2][1] +
0786         vector.w() * matrix.m[3][1];
0787     z = vector.x() * matrix.m[0][2] +
0788         vector.y() * matrix.m[1][2] +
0789         vector.z() * matrix.m[2][2] +
0790         vector.w() * matrix.m[3][2];
0791     w = vector.x() * matrix.m[0][3] +
0792         vector.y() * matrix.m[1][3] +
0793         vector.z() * matrix.m[2][3] +
0794         vector.w() * matrix.m[3][3];
0795     return QVector4D(x, y, z, w);
0796 }
0797 
0798 #endif
0799 
0800 inline QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
0801 {
0802     float xin, yin;
0803     float x, y, w;
0804     xin = point.x();
0805     yin = point.y();
0806     x = xin * matrix.m[0][0] +
0807         yin * matrix.m[0][1] +
0808         matrix.m[0][3];
0809     y = xin * matrix.m[1][0] +
0810         yin * matrix.m[1][1] +
0811         matrix.m[1][3];
0812     w = xin * matrix.m[3][0] +
0813         yin * matrix.m[3][1] +
0814         matrix.m[3][3];
0815     if (w == 1.0f)
0816         return QPoint(qRound(x), qRound(y));
0817     else
0818         return QPoint(qRound(x / w), qRound(y / w));
0819 }
0820 
0821 inline QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
0822 {
0823     float xin, yin;
0824     float x, y, w;
0825     xin = float(point.x());
0826     yin = float(point.y());
0827     x = xin * matrix.m[0][0] +
0828         yin * matrix.m[0][1] +
0829         matrix.m[0][3];
0830     y = xin * matrix.m[1][0] +
0831         yin * matrix.m[1][1] +
0832         matrix.m[1][3];
0833     w = xin * matrix.m[3][0] +
0834         yin * matrix.m[3][1] +
0835         matrix.m[3][3];
0836     if (w == 1.0f) {
0837         return QPointF(qreal(x), qreal(y));
0838     } else {
0839         return QPointF(qreal(x / w), qreal(y / w));
0840     }
0841 }
0842 
0843 #if QT_DEPRECATED_SINCE(6, 1)
0844 
0845 QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(point) instead")
0846 inline QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
0847 {
0848     return matrix.map(point);
0849 }
0850 
0851 QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(point) instead")
0852 inline QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
0853 {
0854     return matrix.map(point);
0855 }
0856 
0857 #endif
0858 
0859 inline QMatrix4x4 operator-(const QMatrix4x4& matrix)
0860 {
0861     Q_DECL_UNINITIALIZED
0862     QMatrix4x4 m(Qt::Uninitialized);
0863     m.m[0][0] = -matrix.m[0][0];
0864     m.m[0][1] = -matrix.m[0][1];
0865     m.m[0][2] = -matrix.m[0][2];
0866     m.m[0][3] = -matrix.m[0][3];
0867     m.m[1][0] = -matrix.m[1][0];
0868     m.m[1][1] = -matrix.m[1][1];
0869     m.m[1][2] = -matrix.m[1][2];
0870     m.m[1][3] = -matrix.m[1][3];
0871     m.m[2][0] = -matrix.m[2][0];
0872     m.m[2][1] = -matrix.m[2][1];
0873     m.m[2][2] = -matrix.m[2][2];
0874     m.m[2][3] = -matrix.m[2][3];
0875     m.m[3][0] = -matrix.m[3][0];
0876     m.m[3][1] = -matrix.m[3][1];
0877     m.m[3][2] = -matrix.m[3][2];
0878     m.m[3][3] = -matrix.m[3][3];
0879     return m;
0880 }
0881 
0882 inline QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix)
0883 {
0884     Q_DECL_UNINITIALIZED
0885     QMatrix4x4 m(Qt::Uninitialized);
0886     m.m[0][0] = matrix.m[0][0] * factor;
0887     m.m[0][1] = matrix.m[0][1] * factor;
0888     m.m[0][2] = matrix.m[0][2] * factor;
0889     m.m[0][3] = matrix.m[0][3] * factor;
0890     m.m[1][0] = matrix.m[1][0] * factor;
0891     m.m[1][1] = matrix.m[1][1] * factor;
0892     m.m[1][2] = matrix.m[1][2] * factor;
0893     m.m[1][3] = matrix.m[1][3] * factor;
0894     m.m[2][0] = matrix.m[2][0] * factor;
0895     m.m[2][1] = matrix.m[2][1] * factor;
0896     m.m[2][2] = matrix.m[2][2] * factor;
0897     m.m[2][3] = matrix.m[2][3] * factor;
0898     m.m[3][0] = matrix.m[3][0] * factor;
0899     m.m[3][1] = matrix.m[3][1] * factor;
0900     m.m[3][2] = matrix.m[3][2] * factor;
0901     m.m[3][3] = matrix.m[3][3] * factor;
0902     return m;
0903 }
0904 
0905 inline QMatrix4x4 operator*(const QMatrix4x4& matrix, float factor)
0906 {
0907     Q_DECL_UNINITIALIZED
0908     QMatrix4x4 m(Qt::Uninitialized);
0909     m.m[0][0] = matrix.m[0][0] * factor;
0910     m.m[0][1] = matrix.m[0][1] * factor;
0911     m.m[0][2] = matrix.m[0][2] * factor;
0912     m.m[0][3] = matrix.m[0][3] * factor;
0913     m.m[1][0] = matrix.m[1][0] * factor;
0914     m.m[1][1] = matrix.m[1][1] * factor;
0915     m.m[1][2] = matrix.m[1][2] * factor;
0916     m.m[1][3] = matrix.m[1][3] * factor;
0917     m.m[2][0] = matrix.m[2][0] * factor;
0918     m.m[2][1] = matrix.m[2][1] * factor;
0919     m.m[2][2] = matrix.m[2][2] * factor;
0920     m.m[2][3] = matrix.m[2][3] * factor;
0921     m.m[3][0] = matrix.m[3][0] * factor;
0922     m.m[3][1] = matrix.m[3][1] * factor;
0923     m.m[3][2] = matrix.m[3][2] * factor;
0924     m.m[3][3] = matrix.m[3][3] * factor;
0925     return m;
0926 }
0927 
0928 inline QPoint QMatrix4x4::map(const QPoint& point) const
0929 {
0930     float xin, yin;
0931     float x, y, w;
0932     xin = point.x();
0933     yin = point.y();
0934     if (flagBits == QMatrix4x4::Identity) {
0935         return point;
0936     } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
0937         // Translation | Scale
0938         return QPoint(qRound(xin * m[0][0] + m[3][0]),
0939                       qRound(yin * m[1][1] + m[3][1]));
0940     } else if (flagBits.toInt() < QMatrix4x4::Perspective) {
0941         return QPoint(qRound(xin * m[0][0] + yin * m[1][0] + m[3][0]),
0942                       qRound(xin * m[0][1] + yin * m[1][1] + m[3][1]));
0943     } else {
0944         x = xin * m[0][0] +
0945             yin * m[1][0] +
0946             m[3][0];
0947         y = xin * m[0][1] +
0948             yin * m[1][1] +
0949             m[3][1];
0950         w = xin * m[0][3] +
0951             yin * m[1][3] +
0952             m[3][3];
0953         if (w == 1.0f)
0954             return QPoint(qRound(x), qRound(y));
0955         else
0956             return QPoint(qRound(x / w), qRound(y / w));
0957     }
0958 }
0959 
0960 inline QPointF QMatrix4x4::map(const QPointF& point) const
0961 {
0962     qreal xin, yin;
0963     qreal x, y, w;
0964     xin = point.x();
0965     yin = point.y();
0966     if (flagBits == QMatrix4x4::Identity) {
0967         return point;
0968     } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
0969         // Translation | Scale
0970         return QPointF(xin * qreal(m[0][0]) + qreal(m[3][0]),
0971                        yin * qreal(m[1][1]) + qreal(m[3][1]));
0972     } else if (flagBits.toInt() < QMatrix4x4::Perspective) {
0973         return QPointF(xin * qreal(m[0][0]) + yin * qreal(m[1][0]) +
0974                        qreal(m[3][0]),
0975                        xin * qreal(m[0][1]) + yin * qreal(m[1][1]) +
0976                        qreal(m[3][1]));
0977     } else {
0978         x = xin * qreal(m[0][0]) +
0979             yin * qreal(m[1][0]) +
0980             qreal(m[3][0]);
0981         y = xin * qreal(m[0][1]) +
0982             yin * qreal(m[1][1]) +
0983             qreal(m[3][1]);
0984         w = xin * qreal(m[0][3]) +
0985             yin * qreal(m[1][3]) +
0986             qreal(m[3][3]);
0987         if (w == 1.0) {
0988             return QPointF(qreal(x), qreal(y));
0989         } else {
0990             return QPointF(qreal(x / w), qreal(y / w));
0991         }
0992     }
0993 }
0994 
0995 #ifndef QT_NO_VECTOR3D
0996 
0997 inline QVector3D QMatrix4x4::map(const QVector3D& point) const
0998 {
0999     float x, y, z, w;
1000     if (flagBits == QMatrix4x4::Identity) {
1001         return point;
1002     } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
1003         // Translation | Scale
1004         return QVector3D(point.x() * m[0][0] + m[3][0],
1005                          point.y() * m[1][1] + m[3][1],
1006                          point.z() * m[2][2] + m[3][2]);
1007     } else if (flagBits.toInt() < QMatrix4x4::Rotation) {
1008         // Translation | Scale | Rotation2D
1009         return QVector3D(point.x() * m[0][0] + point.y() * m[1][0] + m[3][0],
1010                          point.x() * m[0][1] + point.y() * m[1][1] + m[3][1],
1011                          point.z() * m[2][2] + m[3][2]);
1012     } else {
1013         x = point.x() * m[0][0] +
1014             point.y() * m[1][0] +
1015             point.z() * m[2][0] +
1016             m[3][0];
1017         y = point.x() * m[0][1] +
1018             point.y() * m[1][1] +
1019             point.z() * m[2][1] +
1020             m[3][1];
1021         z = point.x() * m[0][2] +
1022             point.y() * m[1][2] +
1023             point.z() * m[2][2] +
1024             m[3][2];
1025         w = point.x() * m[0][3] +
1026             point.y() * m[1][3] +
1027             point.z() * m[2][3] +
1028             m[3][3];
1029         if (w == 1.0f)
1030             return QVector3D(x, y, z);
1031         else
1032             return QVector3D(x / w, y / w, z / w);
1033     }
1034 }
1035 
1036 inline QVector3D QMatrix4x4::mapVector(const QVector3D& vector) const
1037 {
1038     if (flagBits.toInt() < Scale) {
1039         // Translation
1040         return vector;
1041     } else if (flagBits.toInt() < Rotation2D) {
1042         // Translation | Scale
1043         return QVector3D(vector.x() * m[0][0],
1044                          vector.y() * m[1][1],
1045                          vector.z() * m[2][2]);
1046     } else {
1047         return QVector3D(vector.x() * m[0][0] +
1048                          vector.y() * m[1][0] +
1049                          vector.z() * m[2][0],
1050                          vector.x() * m[0][1] +
1051                          vector.y() * m[1][1] +
1052                          vector.z() * m[2][1],
1053                          vector.x() * m[0][2] +
1054                          vector.y() * m[1][2] +
1055                          vector.z() * m[2][2]);
1056     }
1057 }
1058 
1059 #endif
1060 
1061 #ifndef QT_NO_VECTOR4D
1062 
1063 inline QVector4D QMatrix4x4::map(const QVector4D& point) const
1064 {
1065     return *this * point;
1066 }
1067 
1068 #endif
1069 
1070 inline float *QMatrix4x4::data()
1071 {
1072     // We have to assume that the caller will modify the matrix elements,
1073     // so we flip it over to "General" mode.
1074     flagBits = General;
1075     return *m;
1076 }
1077 
1078 inline void QMatrix4x4::viewport(const QRectF &rect)
1079 {
1080     viewport(float(rect.x()), float(rect.y()), float(rect.width()), float(rect.height()));
1081 }
1082 
1083 QT_WARNING_POP
1084 
1085 #ifndef QT_NO_DEBUG_STREAM
1086 Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
1087 #endif
1088 
1089 #ifndef QT_NO_DATASTREAM
1090 Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &);
1091 Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &);
1092 #endif
1093 
1094 #endif
1095 
1096 QT_END_NAMESPACE
1097 
1098 #endif