| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the QtQuick module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qopenvgmatrix.h" |
| |
| QT_BEGIN_NAMESPACE |
| |
| // QOpenVGMatrix: Because Qt will never have enough matrix classes |
| // Internally the data is stored as column-major format |
| // So this is a 3x3 version of QMatrix4x4 for optimal |
| // OpenVG usage. |
| |
| QOpenVGMatrix::QOpenVGMatrix() |
| { |
| setToIdentity(); |
| } |
| |
| QOpenVGMatrix::QOpenVGMatrix(const float *values) |
| { |
| for (int col = 0; col < 3; ++col) |
| for (int row = 0; row < 3; ++row) |
| m[col][row] = values[col * 3 + row]; |
| } |
| |
| const float &QOpenVGMatrix::operator()(int row, int column) const |
| { |
| Q_ASSERT(row >= 0 && row < 4 && column >= 0 && column < 4); |
| return m[column][row]; |
| } |
| |
| float &QOpenVGMatrix::operator()(int row, int column) |
| { |
| Q_ASSERT(row >= 0 && row < 4 && column >= 0 && column < 4); |
| return m[column][row]; |
| } |
| |
| bool QOpenVGMatrix::isIdentity() const |
| { |
| if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f) |
| return false; |
| if ( m[1][0] != 0.0f || m[1][1] != 1.0f) |
| return false; |
| if (m[1][2] != 0.0f || m[2][0] != 0.0f) |
| return false; |
| if (m[2][1] != 0.0f || m[2][2] != 1.0f) |
| return false; |
| |
| return true; |
| } |
| |
| void QOpenVGMatrix::setToIdentity() |
| { |
| m[0][0] = 1.0f; |
| m[0][1] = 0.0f; |
| m[0][2] = 0.0f; |
| m[1][0] = 0.0f; |
| m[1][1] = 1.0f; |
| m[1][2] = 0.0f; |
| m[2][0] = 0.0f; |
| m[2][1] = 0.0f; |
| m[2][2] = 1.0f; |
| } |
| |
| bool QOpenVGMatrix::isAffine() const |
| { |
| if (m[0][2] == 0.0f && m[1][2] == 0.0f && m[2][2] == 1.0f) |
| return true; |
| |
| return false; |
| } |
| |
| QPointF QOpenVGMatrix::map(const QPointF &point) const |
| { |
| return *this * point; |
| } |
| |
| void QOpenVGMatrix::fill(float value) |
| { |
| m[0][0] = value; |
| m[0][1] = value; |
| m[0][2] = value; |
| m[1][0] = value; |
| m[1][1] = value; |
| m[1][2] = value; |
| m[2][0] = value; |
| m[2][1] = value; |
| m[2][2] = value; |
| } |
| |
| QOpenVGMatrix QOpenVGMatrix::transposed() const |
| { |
| QOpenVGMatrix result; |
| for (int row = 0; row < 3; ++row) { |
| for (int col = 0; col < 3; ++col) |
| result.m[col][row] = m[row][col]; |
| } |
| return result; |
| } |
| |
| QOpenVGMatrix &QOpenVGMatrix::operator+=(const QOpenVGMatrix &other) |
| { |
| m[0][0] += other.m[0][0]; |
| m[0][1] += other.m[0][1]; |
| m[0][2] += other.m[0][2]; |
| m[1][0] += other.m[1][0]; |
| m[1][1] += other.m[1][1]; |
| m[1][2] += other.m[1][2]; |
| m[2][0] += other.m[2][0]; |
| m[2][1] += other.m[2][1]; |
| m[2][2] += other.m[2][2]; |
| return *this; |
| } |
| |
| QOpenVGMatrix &QOpenVGMatrix::operator-=(const QOpenVGMatrix &other) |
| { |
| m[0][0] -= other.m[0][0]; |
| m[0][1] -= other.m[0][1]; |
| m[0][2] -= other.m[0][2]; |
| m[1][0] -= other.m[1][0]; |
| m[1][1] -= other.m[1][1]; |
| m[1][2] -= other.m[1][2]; |
| m[2][0] -= other.m[2][0]; |
| m[2][1] -= other.m[2][1]; |
| m[2][2] -= other.m[2][2]; |
| return *this; |
| } |
| |
| QOpenVGMatrix &QOpenVGMatrix::operator*=(const QOpenVGMatrix &other) |
| { |
| float m0, m1; |
| m0 = m[0][0] * other.m[0][0] |
| + m[1][0] * other.m[0][1] |
| + m[2][0] * other.m[0][2]; |
| m1 = m[0][0] * other.m[1][0] |
| + m[1][0] * other.m[1][1] |
| + m[2][0] * other.m[1][2]; |
| m[2][0] = m[0][0] * other.m[2][0] |
| + m[1][0] * other.m[2][1] |
| + m[2][0] * other.m[2][2]; |
| m[0][0] = m0; |
| m[1][0] = m1; |
| |
| m0 = m[0][1] * other.m[0][0] |
| + m[1][1] * other.m[0][1] |
| + m[2][1] * other.m[0][2]; |
| m1 = m[0][1] * other.m[1][0] |
| + m[1][1] * other.m[1][1] |
| + m[2][1] * other.m[1][2]; |
| m[2][1] = m[0][1] * other.m[2][0] |
| + m[1][1] * other.m[2][1] |
| + m[2][1] * other.m[2][2]; |
| m[0][1] = m0; |
| m[1][1] = m1; |
| |
| m0 = m[0][2] * other.m[0][0] |
| + m[1][2] * other.m[0][1] |
| + m[2][2] * other.m[0][2]; |
| m1 = m[0][2] * other.m[1][0] |
| + m[1][2] * other.m[1][1] |
| + m[2][2] * other.m[1][2]; |
| m[2][2] = m[0][2] * other.m[2][0] |
| + m[1][2] * other.m[2][1] |
| + m[2][2] * other.m[2][2]; |
| m[0][2] = m0; |
| m[1][2] = m1; |
| return *this; |
| } |
| |
| QOpenVGMatrix &QOpenVGMatrix::operator*=(float factor) |
| { |
| m[0][0] *= factor; |
| m[0][1] *= factor; |
| m[0][2] *= factor; |
| m[1][0] *= factor; |
| m[1][1] *= factor; |
| m[1][2] *= factor; |
| m[2][0] *= factor; |
| m[2][1] *= factor; |
| m[2][2] *= factor; |
| return *this; |
| } |
| |
| QOpenVGMatrix &QOpenVGMatrix::operator/=(float divisor) |
| { |
| m[0][0] /= divisor; |
| m[0][1] /= divisor; |
| m[0][2] /= divisor; |
| m[1][0] /= divisor; |
| m[1][1] /= divisor; |
| m[1][2] /= divisor; |
| m[2][0] /= divisor; |
| m[2][1] /= divisor; |
| m[2][2] /= divisor; |
| return *this; |
| } |
| |
| bool QOpenVGMatrix::operator==(const QOpenVGMatrix &other) const |
| { |
| return m[0][0] == other.m[0][0] && |
| m[0][1] == other.m[0][1] && |
| m[0][2] == other.m[0][2] && |
| m[1][0] == other.m[1][0] && |
| m[1][1] == other.m[1][1] && |
| m[1][2] == other.m[1][2] && |
| m[2][0] == other.m[2][0] && |
| m[2][1] == other.m[2][1] && |
| m[2][2] == other.m[2][2]; |
| } |
| |
| bool QOpenVGMatrix::operator!=(const QOpenVGMatrix &other) const |
| { |
| return m[0][0] != other.m[0][0] || |
| m[0][1] != other.m[0][1] || |
| m[0][2] != other.m[0][2] || |
| m[1][0] != other.m[1][0] || |
| m[1][1] != other.m[1][1] || |
| m[1][2] != other.m[1][2] || |
| m[2][0] != other.m[2][0] || |
| m[2][1] != other.m[2][1] || |
| m[2][2] != other.m[2][2]; |
| } |
| |
| void QOpenVGMatrix::copyDataTo(float *values) const |
| { |
| // Row-Major? |
| for (int row = 0; row < 3; ++row) { |
| for (int col = 0; col < 3; ++col) |
| values[row * 3 + col] = float(m[col][row]); |
| } |
| } |
| |
| QOpenVGMatrix operator*(const QOpenVGMatrix &m1, const QOpenVGMatrix &m2) |
| { |
| QOpenVGMatrix matrix; |
| matrix.m[0][0] = m1.m[0][0] * m2.m[0][0] |
| + m1.m[1][0] * m2.m[0][1] |
| + m1.m[2][0] * m2.m[0][2]; |
| matrix.m[0][1] = m1.m[0][1] * m2.m[0][0] |
| + m1.m[1][1] * m2.m[0][1] |
| + m1.m[2][1] * m2.m[0][2]; |
| matrix.m[0][2] = m1.m[0][2] * m2.m[0][0] |
| + m1.m[1][2] * m2.m[0][1] |
| + m1.m[2][2] * m2.m[0][2]; |
| |
| matrix.m[1][0] = m1.m[0][0] * m2.m[1][0] |
| + m1.m[1][0] * m2.m[1][1] |
| + m1.m[2][0] * m2.m[1][2]; |
| matrix.m[1][1] = m1.m[0][1] * m2.m[1][0] |
| + m1.m[1][1] * m2.m[1][1] |
| + m1.m[2][1] * m2.m[1][2]; |
| matrix.m[1][2] = m1.m[0][2] * m2.m[1][0] |
| + m1.m[1][2] * m2.m[1][1] |
| + m1.m[2][2] * m2.m[1][2]; |
| |
| matrix.m[2][0] = m1.m[0][0] * m2.m[2][0] |
| + m1.m[1][0] * m2.m[2][1] |
| + m1.m[2][0] * m2.m[2][2]; |
| matrix.m[2][1] = m1.m[0][1] * m2.m[2][0] |
| + m1.m[1][1] * m2.m[2][1] |
| + m1.m[2][1] * m2.m[2][2]; |
| matrix.m[2][2] = m1.m[0][2] * m2.m[2][0] |
| + m1.m[1][2] * m2.m[2][1] |
| + m1.m[2][2] * m2.m[2][2]; |
| return matrix; |
| } |
| |
| QPointF operator*(const QPointF& point, const QOpenVGMatrix& matrix) |
| { |
| float xin = point.x(); |
| float yin = point.y(); |
| float x = xin * matrix.m[0][0] + |
| yin * matrix.m[0][1] + |
| matrix.m[0][2]; |
| float y = xin * matrix.m[1][0] + |
| yin * matrix.m[1][1] + |
| matrix.m[1][2]; |
| float w = xin * matrix.m[2][0] + |
| yin * matrix.m[2][1] + |
| matrix.m[2][2]; |
| if (w == 1.0f) { |
| return QPointF(float(x), float(y)); |
| } else { |
| return QPointF(float(x / w), float(y / w)); |
| } |
| } |
| |
| QPointF operator*(const QOpenVGMatrix& matrix, const QPointF& point) |
| { |
| float xin = point.x(); |
| float yin = point.y(); |
| float x = xin * matrix.m[0][0] + |
| yin * matrix.m[1][0] + |
| matrix.m[2][0]; |
| float y = xin * matrix.m[0][1] + |
| yin * matrix.m[1][1] + |
| matrix.m[2][1]; |
| float w = xin * matrix.m[0][2] + |
| yin * matrix.m[1][2] + |
| matrix.m[2][2]; |
| if (w == 1.0f) { |
| return QPointF(float(x), float(y)); |
| } else { |
| return QPointF(float(x / w), float(y / w)); |
| } |
| } |
| |
| QDebug operator<<(QDebug dbg, const QOpenVGMatrix &m) |
| { |
| QDebugStateSaver saver(dbg); |
| // Output in row-major order because it is more human-readable. |
| dbg.nospace() << "QOpenVGMatrix:(" << endl |
| << qSetFieldWidth(10) |
| << m(0, 0) << m(0, 1) << m(0, 2) << endl |
| << m(1, 0) << m(1, 1) << m(1, 2) << endl |
| << m(2, 0) << m(2, 1) << m(2, 2) << endl |
| << qSetFieldWidth(0) << ')'; |
| return dbg; |
| } |
| |
| QDataStream &operator<<(QDataStream &stream, const QOpenVGMatrix &matrix) |
| { |
| for (int row = 0; row < 3; ++row) |
| for (int col = 0; col < 3; ++col) |
| stream << matrix(row, col); |
| return stream; |
| } |
| |
| |
| QDataStream &operator>>(QDataStream &stream, QOpenVGMatrix &matrix) |
| { |
| float x; |
| for (int row = 0; row < 4; ++row) { |
| for (int col = 0; col < 4; ++col) { |
| stream >> x; |
| matrix(row, col) = x; |
| } |
| } |
| return stream; |
| } |
| |
| |
| QT_END_NAMESPACE |